Diff for /loncom/publisher/lonpublisher.pm between versions 1.93 and 1.232

version 1.93, 2002/08/12 14:48:32 version 1.232, 2008/03/18 23:31:31
Line 25 Line 25
 #  #
 # http://www.lon-capa.org/  # http://www.lon-capa.org/
 #  #
 #   
 # (TeX Content Handler  
 #  
 # 05/29/00,05/30,10/11 Gerd Kortemeyer)  
 #  
 # 11/28,11/29,11/30,12/01,12/02,12/04,12/23 Gerd Kortemeyer  
 # 03/23 Guy Albertelli  
 # 03/24,03/29,04/03 Gerd Kortemeyer  
 # 04/16/2001 Scott Harrison  
 # 05/03,05/05,05/07 Gerd Kortemeyer  
 # 05/28/2001 Scott Harrison  
 # 06/23,08/07,08/11,8/13,8/17,8/18,8/24,9/26,10/16 Gerd Kortemeyer  
 # 12/04,12/05 Guy Albertelli  
 # 12/05 Gerd Kortemeyer  
 # 12/05 Guy Albertelli  
 # 12/06,12/07 Gerd Kortemeyer  
 # 12/15,12/16 Scott Harrison  
 # 12/25 Gerd Kortemeyer  
 # YEAR=2002  
 # 1/16,1/17 Scott Harrison  
 # 1/17 Gerd Kortemeyer  
 #  
 ###  ###
   
 ###############################################################################  ###############################################################################
Line 67 Line 45
   
 =pod   =pod 
   
 =head1 Name  =head1 NAME
   
 lonpublisher - LON-CAPA publishing handler  lonpublisher - LON-CAPA publishing handler
   
 =head1 Synopsis  =head1 SYNOPSIS
   
   B<lonpublisher> is used by B<mod_perl> inside B<Apache>.  This is the
   invocation by F<loncapa_apache.conf>:
   
     <Location /adm/publish>
     PerlAccessHandler       Apache::lonacc
     SetHandler perl-script
     PerlHandler Apache::lonpublisher
     ErrorDocument     403 /adm/login
     ErrorDocument     404 /adm/notfound.html
     ErrorDocument     406 /adm/unauthorized.html
     ErrorDocument     500 /adm/errorhandler
     </Location>
   
   =head1 OVERVIEW
   
   Authors can only write-access the C</~authorname/> space. They can
   copy resources into the resource area through the publication step,
   and move them back through a recover step. Authors do not have direct
   write-access to their resource space.
   
   During the publication step, several events will be
   triggered. Metadata is gathered, where a wizard manages default
   entries on a hierarchical per-directory base: The wizard imports the
   metadata (including access privileges and royalty information) from
   the most recent published resource in the current directory, and if
   that is not available, from the next directory above, etc. The Network
   keeps all previous versions of a resource and makes them available by
   an explicit version number, which is inserted between the file name
   and extension, for example C<foo.2.html>, while the most recent
   version does not carry a version number (C<foo.html>). Servers
   subscribing to a changed resource are notified that a new version is
   available.
   
   =head1 DESCRIPTION
   
 lonpublisher takes the proper steps to add resources to the LON-CAPA  B<lonpublisher> takes the proper steps to add resources to the LON-CAPA
 digital library.  This includes updating the metadata table in the  digital library.  This includes updating the metadata table in the
 LON-CAPA database.  LON-CAPA database.
   
 =head1 Description  B<lonpublisher> is many things to many people.  
   
 lonpublisher is many things to many people.    
 To all people it is woefully documented.    
 This documentation conforms to this standard.  
   
 This module publishes a file.  This involves gathering metadata,  This module publishes a file.  This involves gathering metadata,
 versioning the file, copying file from construction space to  versioning the file, copying file from construction space to
 publication space, and copying metadata from construction space  publication space, and copying metadata from construction space
 to publication space.  to publication space.
   
 =head2 Internal Functions  =head2 SUBROUTINES
   
   Many of the undocumented subroutines implement various magical
   parsing shortcuts.
   
 =over 4  =over 4
   
Line 107  use File::Copy; Line 119  use File::Copy;
 use Apache::Constants qw(:common :http :methods);  use Apache::Constants qw(:common :http :methods);
 use HTML::LCParser;  use HTML::LCParser;
 use Apache::lonxml;  use Apache::lonxml;
 use Apache::lonhomework;  
 use Apache::loncacc;  use Apache::loncacc;
 use DBI;  use DBI;
 use Apache::lonnet();  use Apache::lonnet;
 use Apache::loncommon();  use Apache::loncommon();
 use Apache::lonmysql;  use Apache::lonmysql;
   use Apache::lonlocal;
   use Apache::loncfile;
   use LONCAPA::lonmetadata;
   use Apache::lonmsg;
   use vars qw(%metadatafields %metadatakeys);
   use LONCAPA qw(:DEFAULT :match);
    
   
 my %addid;  my %addid;
 my %nokey;  my %nokey;
   
 my %metadatafields;  
 my %metadatakeys;  
   
 my $docroot;  my $docroot;
   
 my $cuname;  my $cuname;
 my $cudom;  my $cudom;
   
 #########################################  my $registered_cleanup;
 #########################################  my $modified_urls;
   
 =pod  =pod
   
 =item metaeval  =item B<metaeval>
   
 Evaluate string with metadata  Evaluates a string that contains metadata.  This subroutine
   stores values inside I<%metadatafields> and I<%metadatakeys>.
   The hash key is a I<$unikey> corresponding to a unique id
   that is descriptive of the parser location inside the XML tree.
   
   Parameters:
   
   =over 4
   
   =item I<$metastring>
   
   A string that contains metadata.
   
   =back
   
   Returns:
   
   nothing
   
 =cut  =cut
   
 #########################################  #########################################
 #########################################  #########################################
   #
   # Modifies global %metadatafields %metadatakeys 
   #
   
 sub metaeval {  sub metaeval {
     my $metastring=shift;      my ($metastring,$prefix)=@_;
         
         my $parser=HTML::LCParser->new(\$metastring);      my $parser=HTML::LCParser->new(\$metastring);
         my $token;      my $token;
         while ($token=$parser->get_token) {      while ($token=$parser->get_token) {
            if ($token->[0] eq 'S') {   if ($token->[0] eq 'S') {
       my $entry=$token->[1];      my $entry=$token->[1];
               my $unikey=$entry;      my $unikey=$entry;
               if (defined($token->[2]->{'package'})) {       next if ($entry =~ m/^(?:parameter|stores)_/);
                   $unikey.='_package_'.$token->[2]->{'package'};      if (defined($token->[2]->{'package'})) { 
               }    $unikey.="\0package\0".$token->[2]->{'package'};
               if (defined($token->[2]->{'part'})) {       } 
                  $unikey.='_'.$token->[2]->{'part'};       if (defined($token->[2]->{'part'})) { 
       }   $unikey.="\0".$token->[2]->{'part'}; 
               if (defined($token->[2]->{'id'})) {       }
                   $unikey.='_'.$token->[2]->{'id'};      if (defined($token->[2]->{'id'})) { 
               }    $unikey.="\0".$token->[2]->{'id'};
               if (defined($token->[2]->{'name'})) {       } 
                  $unikey.='_'.$token->[2]->{'name'};       if (defined($token->[2]->{'name'})) { 
       }   $unikey.="\0".$token->[2]->{'name'}; 
               foreach (@{$token->[3]}) {      }
   $metadatafields{$unikey.'.'.$_}=$token->[2]->{$_};      foreach (@{$token->[3]}) {
                   if ($metadatakeys{$unikey}) {   $metadatafields{$unikey.'.'.$_}=$token->[2]->{$_};
       $metadatakeys{$unikey}.=','.$_;   if ($metadatakeys{$unikey}) {
                   } else {      $metadatakeys{$unikey}.=','.$_;
                       $metadatakeys{$unikey}=$_;   } else {
                   }      $metadatakeys{$unikey}=$_;
               }   }
               if ($metadatafields{$unikey}) {      }
   my $newentry=$parser->get_text('/'.$entry);      my $newentry=$parser->get_text('/'.$entry);
                   unless (($metadatafields{$unikey}=~/$newentry/) ||      if (($entry eq 'customdistributionfile') ||
                           ($newentry eq '')) {   ($entry eq 'sourcerights')) {
                      $metadatafields{$unikey}.=', '.$newentry;   $newentry=~s/^\s*//;
   }   if ($newentry !~m|^/res|) { $newentry=$prefix.$newentry; }
       } else {      }
                  $metadatafields{$unikey}=$parser->get_text('/'.$entry);  # actually store
               }      if ( $entry eq 'rule' && exists($metadatafields{$unikey})) {
           }   $metadatafields{$unikey}.=','.$newentry;
        }      } else {
    $metadatafields{$unikey}=$newentry;
       }
    }
       }
 }  }
   
 #########################################  #########################################
Line 185  sub metaeval { Line 225  sub metaeval {
   
 =pod  =pod
   
 =item metaread  =item B<metaread>
   
 Read a metadata file  Read a metadata file
   
   Parameters:
   
   =over
   
   =item I<$logfile>
   
   File output stream to output errors and warnings to.
   
   =item I<$fn>
   
   File name (including path).
   
   =back
   
   Returns:
   
   =over 4
   
   =item Scalar string (if successful)
   
   XHTML text that indicates successful reading of the metadata.
   
   =back
   
 =cut  =cut
   
 #########################################  #########################################
 #########################################  #########################################
 sub metaread {  sub metaread {
     my ($logfile,$fn)=@_;      my ($logfile,$fn,$prefix)=@_;
     unless (-e $fn) {      unless (-e $fn) {
  print $logfile 'No file '.$fn."\n";   print($logfile 'No file '.$fn."\n");
         return '<br><b>No file:</b> <tt>'.$fn.'</tt>';          return '<br /><b>'.&mt('No file').':</b> <tt>'.
       &Apache::loncfile::display($fn).'</tt>';
     }      }
     print $logfile 'Processing '.$fn."\n";      print($logfile 'Processing '.$fn."\n");
     my $metastring;      my $metastring;
     {      {
      my $metafh=Apache::File->new($fn);   my $metafh=Apache::File->new($fn);
      $metastring=join('',<$metafh>);   $metastring=join('',<$metafh>);
     }      }
     &metaeval($metastring);      &metaeval($metastring,$prefix);
     return '<br><b>Processed file:</b> <tt>'.$fn.'</tt>';      return '<br /><b>'.&mt('Processed file').':</b> <tt>'.
    &Apache::loncfile::display($fn).'</tt>';
 }  }
   
 #########################################  #########################################
 #########################################  #########################################
   
 =pod  sub coursedependencies {
       my $url=&Apache::lonnet::declutter(shift);
 =item sqltime      $url=~s/\.meta$//;
       my ($adomain,$aauthor)=($url=~ m{^($match_domain)/($match_username)/});
 Convert 'time' format into a datetime sql format      my $regexp=quotemeta($url);
       $regexp='___'.$regexp.'___course';
 =cut      my %evaldata=&Apache::lonnet::dump('nohist_resevaldata',$adomain,
          $aauthor,$regexp);
 #########################################      my %courses=();
 #########################################      foreach (keys %evaldata) {
 sub sqltime {   if ($_=~/^([a-zA-Z0-9]+_[a-zA-Z0-9]+)___.+___course$/) {
     my $timef=shift @_;      $courses{$1}=1;
     my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =          }
  localtime($timef);      }
     $mon++; $year+=1900;      return %courses;
     return "$year-$mon-$mday $hour:$min:$sec";  
 }  }
   
   
 #########################################  #########################################
 #########################################  #########################################
   
   
 =pod  =pod
   
 =item Form field generating functions  =item Form-field-generating subroutines.
   
   For input parameters, these subroutines take in values
   such as I<$name>, I<$value> and other form field metadata.
   The output (scalar string that is returned) is an XHTML
   string which presents the form field (foreseeably inside
   <form></form> tags).
   
 =over 4  =over 4
   
 =item textfield  =item B<textfield>
   
 =item hiddenfield  =item B<hiddenfield>
   
 =item selectbox  =item B<selectbox>
   
 =back  =back
   
Line 254  sub sqltime { Line 324  sub sqltime {
 #########################################  #########################################
 sub textfield {  sub textfield {
     my ($title,$name,$value)=@_;      my ($title,$name,$value)=@_;
     return "\n<p><b>$title:</b><br>".      $value=~s/^\s+//gs;
            '<input type=text name="'.$name.'" size=80 value="'.$value.'">';      $value=~s/\s+$//gs;
       $value=~s/\s+/ /gs;
       $title=&mt($title);
       $env{'form.'.$name}=$value;
       return "\n<p><font color=\"#800000\" face=\"helvetica\"><b>$title:".
              "</b></font></p><br />".
              '<input type="text" name="'.$name.'" size=80 value="'.$value.'" />';
   }
   
   sub text_with_browse_field {
       my ($title,$name,$value,$restriction)=@_;
       $value=~s/^\s+//gs;
       $value=~s/\s+$//gs;
       $value=~s/\s+/ /gs;
       $title=&mt($title);
       $env{'form.'.$name}=$value;
       return "\n<p><font color=\"#800000\" face=\"helvetica\"><b>$title:".
              "</b></font></p><br />".
              '<input type="text" name="'.$name.'" size=80 value="'.$value.'" />'.
      '<a href="javascript:openbrowser(\'pubform\',\''.$name.'\',\''.$restriction.'\');">'.&mt('Select').'</a>&nbsp;'.
      '<a href="javascript:opensearcher(\'pubform\',\''.$name.'\');">'.&mt('Search').'</a>';
      
 }  }
   
 sub hiddenfield {  sub hiddenfield {
     my ($name,$value)=@_;      my ($name,$value)=@_;
     return "\n".'<input type=hidden name="'.$name.'" value="'.$value.'">';      $env{'form.'.$name}=$value;
       return "\n".'<input type="hidden" name="'.$name.'" value="'.$value.'" />';
   }
   
   sub checkbox {
       my ($name,$text)=@_;
       return "\n<br /><label><input type='checkbox' name='$name' /> ".
    &mt($text)."</label>";
 }  }
   
 sub selectbox {  sub selectbox {
     my ($title,$name,$value,$functionref,@idlist)=@_;      my ($title,$name,$value,$functionref,@idlist)=@_;
     my $uctitle=uc($title);      $title=&mt($title);
     my $selout="\n<p><font color=\"#800000\" face=\"helvetica\"><b>$uctitle:".      $value=(split(/\s*,\s*/,$value))[-1];
  "</b></font><br />".'<select name="'.$name.'">';      if (defined($value)) {
    $env{'form.'.$name}=$value;
       } else {
    $env{'form.'.$name}=$idlist[0];
       }
       my $selout="\n<p><font color=\"#800000\" face=\"helvetica\"><b>$title:".
    '</b></font></p><br /><select name="'.$name.'">';
     foreach (@idlist) {      foreach (@idlist) {
         $selout.='<option value=\''.$_.'\'';          $selout.='<option value=\''.$_.'\'';
         if ($_ eq $value) {          if ($_ eq $value) {
Line 278  sub selectbox { Line 382  sub selectbox {
     return $selout.'</select>';      return $selout.'</select>';
 }  }
   
   sub select_level_form {
       my ($value,$name)=@_;
       $env{'form.'.$name}=$value;
       if (!defined($value)) { $env{'form.'.$name}=0; }
       return  &Apache::loncommon::select_level_form($value,$name);
   }
 #########################################  #########################################
 #########################################  #########################################
   
 =pod  =pod
   
 =item urlfixup  =item B<urlfixup>
   
 Fix up a url?  First step of publication  Fix up a url?  First step of publication
   
Line 299  sub urlfixup { Line 409  sub urlfixup {
     if ($url =~ /^mailto:/i) { return $url; }      if ($url =~ /^mailto:/i) { return $url; }
     #internal document links need no fixing      #internal document links need no fixing
     if ($url =~ /^\#/) { return $url; }       if ($url =~ /^\#/) { return $url; } 
     my ($host)=($url=~/(?:http\:\/\/)*([^\/]+)/);      my ($host)=($url=~m{(?:(?:http|https|ftp)://)*([^/]+)});
     foreach (values %Apache::lonnet::hostname) {      my @lonids = &Apache::lonnet::machine_ids($host);
  if ($_ eq $host) {      if (@lonids) {
     $url=~s/^http\:\/\///;   $url=~s{^(?:http|https|ftp)://}{};
             $url=~s/^$host//;   $url=~s/^\Q$host\E//;
         }  
     }      }
     if ($url=~/^http\:\/\//) { return $url; }      if ($url=~m{^(?:http|https|ftp)://}) { return $url; }
     $url=~s/\~$cuname/res\/$cudom\/$cuname/;      $url=~s{\Q~$cuname\E}{res/$cudom/$cuname};
     return $url;      return $url;
 }  }
   
Line 316  sub urlfixup { Line 425  sub urlfixup {
   
 =pod  =pod
   
 =item absoluteurl  =item B<absoluteurl>
   
 Currently undocumented      Currently undocumented.
   
 =cut  =cut
   
Line 339  sub absoluteurl { Line 448  sub absoluteurl {
   
 =pod  =pod
   
 =item set_allow  =item B<set_allow>
   
 Currently undocumented      Currently undocumented    
   
Line 358  sub set_allow { Line 467  sub set_allow {
     }      }
     if (($newurl !~ /^javascript:/i) &&      if (($newurl !~ /^javascript:/i) &&
  ($newurl !~ /^mailto:/i) &&   ($newurl !~ /^mailto:/i) &&
  ($newurl !~ /^http:/i) &&   ($newurl !~ /^(?:http|https|ftp):/i) &&
  ($newurl !~ /^\#/)) {   ($newurl !~ /^\#/)) {
  $$allow{&absoluteurl($newurl,$target)}=1;   $$allow{&absoluteurl($newurl,$target)}=1;
     }      }
     return $return_url      return $return_url;
 }  }
   
 #########################################  #########################################
Line 370  sub set_allow { Line 479  sub set_allow {
   
 =pod  =pod
   
 =item get_subscribed_hosts  =item B<get_subscribed_hosts>
   
 Currently undocumented      Currently undocumented    
   
Line 385  sub get_subscribed_hosts { Line 494  sub get_subscribed_hosts {
     $target=~/(.*)\/([^\/]+)$/;      $target=~/(.*)\/([^\/]+)$/;
     my $srcf=$2;      my $srcf=$2;
     opendir(DIR,$1);      opendir(DIR,$1);
       # cycle through listed files, subscriptions used to exist
       # as "filename.lonid"
     while ($filename=readdir(DIR)) {      while ($filename=readdir(DIR)) {
  if ($filename=~/$srcf\.(\w+)$/) {   if ($filename=~/\Q$srcf\E\.($match_lonid)$/) {
     my $subhost=$1;      my $subhost=$1;
     if ($subhost ne 'meta' && $subhost ne 'subscription') {      if (($subhost ne 'meta' 
    && $subhost ne 'subscription' 
    && $subhost ne 'meta.subscription'
    && $subhost ne 'tmp') &&
                   ($subhost ne $Apache::lonnet::perlvar{'lonHostID'})) {
  push(@subscribed,$subhost);   push(@subscribed,$subhost);
     }      }
  }   }
Line 396  sub get_subscribed_hosts { Line 511  sub get_subscribed_hosts {
     closedir(DIR);      closedir(DIR);
     my $sh;      my $sh;
     if ( $sh=Apache::File->new("$target.subscription") ) {      if ( $sh=Apache::File->new("$target.subscription") ) {
  &Apache::lonnet::logthis("opened $target.subscription");  
  while (my $subline=<$sh>) {   while (my $subline=<$sh>) {
     &Apache::lonnet::logthis("Trying $subline");      if ($subline =~ /^($match_lonid):/) { 
     if ($subline =~ /(^\w+):/) { push(@subscribed,$1); } else {                  if ($1 ne $Apache::lonnet::perlvar{'lonHostID'}) { 
  &Apache::lonnet::logthis("No Match for $subline");                     push(@subscribed,$1);
           }
     }      }
  }   }
     } else {  
  &Apache::lonnet::logthis("Un able to open $target.subscription");  
     }      }
     &Apache::lonnet::logthis("Got list of ".join(':',@subscribed));  
     return @subscribed;      return @subscribed;
 }  }
   
Line 416  sub get_subscribed_hosts { Line 528  sub get_subscribed_hosts {
   
 =pod  =pod
   
 =item get_max_ids_indices  =item B<get_max_ids_indices>
   
 Currently undocumented      Currently undocumented    
   
Line 429  sub get_max_ids_indices { Line 541  sub get_max_ids_indices {
     my $maxindex=10;      my $maxindex=10;
     my $maxid=10;      my $maxid=10;
     my $needsfixup=0;      my $needsfixup=0;
       my $duplicateids=0;
   
       my %allids;
       my %duplicatedids;
   
     my $parser=HTML::LCParser->new($content);      my $parser=HTML::LCParser->new($content);
       $parser->xml_mode(1);
     my $token;      my $token;
     while ($token=$parser->get_token) {      while ($token=$parser->get_token) {
  if ($token->[0] eq 'S') {   if ($token->[0] eq 'S') {
     my $counter;      my $counter;
     if ($counter=$addid{$token->[1]}) {      if ($counter=$addid{$token->[1]}) {
  if ($counter eq 'id') {   if ($counter eq 'id') {
     if (defined($token->[2]->{'id'})) {      if (defined($token->[2]->{'id'}) &&
    $token->[2]->{'id'} !~ /^\s*$/) {
  $maxid=($token->[2]->{'id'}>$maxid)?$token->[2]->{'id'}:$maxid;   $maxid=($token->[2]->{'id'}>$maxid)?$token->[2]->{'id'}:$maxid;
    if (exists($allids{$token->[2]->{'id'}})) {
       $duplicateids=1;
       $duplicatedids{$token->[2]->{'id'}}=1;
    } else {
       $allids{$token->[2]->{'id'}}=1;
    }
     } else {      } else {
  $needsfixup=1;   $needsfixup=1;
     }      }
  } else {   } else {
     if (defined($token->[2]->{'index'})) {      if (defined($token->[2]->{'index'}) &&
    $token->[2]->{'index'} !~ /^\s*$/) {
  $maxindex=($token->[2]->{'index'}>$maxindex)?$token->[2]->{'index'}:$maxindex;   $maxindex=($token->[2]->{'index'}>$maxindex)?$token->[2]->{'index'}:$maxindex;
     } else {      } else {
  $needsfixup=1;   $needsfixup=1;
Line 452  sub get_max_ids_indices { Line 577  sub get_max_ids_indices {
     }      }
  }   }
     }      }
     return ($needsfixup,$maxid,$maxindex);      return ($needsfixup,$maxid,$maxindex,$duplicateids,
       (keys(%duplicatedids)));
 }  }
   
 #########################################  #########################################
Line 460  sub get_max_ids_indices { Line 586  sub get_max_ids_indices {
   
 =pod  =pod
   
 =item get_all_text_unbalanced  =item B<get_all_text_unbalanced>
   
 Currently undocumented      Currently undocumented    
   
Line 484  sub get_all_text_unbalanced { Line 610  sub get_all_text_unbalanced {
  } elsif ($token->[0] eq 'E')  {   } elsif ($token->[0] eq 'E')  {
     $result.=$token->[2];      $result.=$token->[2];
  }   }
  if ($result =~ /(.*)$tag(.*)/) {   if ($result =~ /\Q$tag\E/s) {
       ($result,my $redo)=$result =~ /(.*)\Q$tag\E(.*)/is;
     #&Apache::lonnet::logthis('Got a winner with leftovers ::'.$2);      #&Apache::lonnet::logthis('Got a winner with leftovers ::'.$2);
     #&Apache::lonnet::logthis('Result is :'.$1);      #&Apache::lonnet::logthis('Result is :'.$1);
     $result=$1;      $redo=$tag.$redo;
     my $redo=$tag.$2;  
     push (@$pars,HTML::LCParser->new(\$redo));      push (@$pars,HTML::LCParser->new(\$redo));
     $$pars[-1]->xml_mode('1');      $$pars[-1]->xml_mode('1');
     last;      last;
Line 502  sub get_all_text_unbalanced { Line 628  sub get_all_text_unbalanced {
   
 =pod  =pod
   
 =item fix_ids_and_indices  =item B<fix_ids_and_indices>
   
 Currently undocumented      Currently undocumented    
   
Line 521  sub fix_ids_and_indices { Line 647  sub fix_ids_and_indices {
  $content=join('',<$org>);   $content=join('',<$org>);
     }      }
   
     my ($needsfixup,$maxid,$maxindex)=&get_max_ids_indices(\$content);      my ($needsfixup,$maxid,$maxindex,$duplicateids,@duplicatedids)=
    &get_max_ids_indices(\$content);
   
       print $logfile ("Got $needsfixup,$maxid,$maxindex,$duplicateids--".
      join(', ',@duplicatedids));
       if ($duplicateids) {
    print $logfile "Duplicate ID(s) exist, ".join(', ',@duplicatedids)."\n";
    my $outstring='<span class="LC_error">'.&mt('Unable to publish file, it contains duplicated ID(s), ID(s) need to be unique. The duplicated ID(s) are').': '.join(', ',@duplicatedids).'</span>';
    return ($outstring,1);
       }
     if ($needsfixup) {      if ($needsfixup) {
  print $logfile "Needs ID and/or index fixup\n".   print $logfile "Needs ID and/or index fixup\n".
     "Max ID   : $maxid (min 10)\n".      "Max ID   : $maxid (min 10)\n".
Line 543  sub fix_ids_and_indices { Line 677  sub fix_ids_and_indices {
     $allow{$token->[2]->{'src'}}=1;      $allow{$token->[2]->{'src'}}=1;
     next;      next;
  }   }
    if ($lctag eq 'base') { next; }
  my %parms=%{$token->[2]};   my %parms=%{$token->[2]};
  $counter=$addid{$tag};   $counter=$addid{$tag};
  if (!$counter) { $counter=$addid{$lctag}; }   if (!$counter) { $counter=$addid{$lctag}; }
  if ($counter) {   if ($counter) {
     if ($counter eq 'id') {      if ($counter eq 'id') {
  unless (defined($parms{'id'})) {   unless (defined($parms{'id'}) &&
    $parms{'id'}!~/^\s*$/) {
     $maxid++;      $maxid++;
     $parms{'id'}=$maxid;      $parms{'id'}=$maxid;
     print $logfile 'ID: '.$tag.':'.$maxid."\n";      print $logfile 'ID(new) : '.$tag.':'.$maxid."\n";
    } else {
       print $logfile 'ID(kept): '.$tag.':'.$parms{'id'}."\n";
  }   }
     } elsif ($counter eq 'index') {      } elsif ($counter eq 'index') {
  unless (defined($parms{'index'})) {   unless (defined($parms{'index'}) &&
    $parms{'index'}!~/^\s*$/) {
     $maxindex++;      $maxindex++;
     $parms{'index'}=$maxindex;      $parms{'index'}=$maxindex;
     print $logfile 'Index: '.$tag.':'.$maxindex."\n";      print $logfile 'Index: '.$tag.':'.$maxindex."\n";
  }   }
     }      }
  }   }
  foreach my $type ('src','href','background','bgimg') {                  unless ($parms{'type'} eq 'zombie') {
     foreach my $key (keys(%parms)) {      foreach my $type ('src','href','background','bgimg') {
  if ($key =~ /^$type$/i) {   foreach my $key (keys(%parms)) {
     $parms{$key}=&set_allow(\%allow,$logfile,      if ($key =~ /^$type$/i) {
     $target,$tag,   $parms{$key}=&set_allow(\%allow,$logfile,
     $parms{$key});   $target,$tag,
    $parms{$key});
       }
  }   }
     }      }
  }   }
  # probably a <randomlabel> image type <label>   # probably a <randomlabel> image type <label>
  if ($lctag eq 'label' && defined($parms{'description'})) {   # or a <image> tag inside <imageresponse>
    if (($lctag eq 'label' && defined($parms{'description'}))
       ||
       ($lctag eq 'image')) {
     my $next_token=$parser[-1]->get_token();      my $next_token=$parser[-1]->get_token();
     if ($next_token->[0] eq 'T') {      if ($next_token->[0] eq 'T') {
                           $next_token->[1] =~ s/[\n\r\f]+//g;
  $next_token->[1]=&set_allow(\%allow,$logfile,   $next_token->[1]=&set_allow(\%allow,$logfile,
     $target,$tag,      $target,$tag,
     $next_token->[1]);      $next_token->[1]);
Line 582  sub fix_ids_and_indices { Line 727  sub fix_ids_and_indices {
  }   }
  if ($lctag eq 'applet') {   if ($lctag eq 'applet') {
     my $codebase='';      my $codebase='';
     if (defined($parms{'codebase'})) {      my $havecodebase=0;
  my $oldcodebase=$parms{'codebase'};      foreach my $key (keys(%parms)) {
    if (lc($key) eq 'codebase') { 
       $codebase=$parms{$key};
       $havecodebase=1; 
    }
       }
       if ($havecodebase) {
    my $oldcodebase=$codebase;
  unless ($oldcodebase=~/\/$/) {   unless ($oldcodebase=~/\/$/) {
     $oldcodebase.='/';      $oldcodebase.='/';
  }   }
Line 597  sub fix_ids_and_indices { Line 749  sub fix_ids_and_indices {
  }   }
  $allow{&absoluteurl($codebase,$target).'/*'}=1;   $allow{&absoluteurl($codebase,$target).'/*'}=1;
     } else {      } else {
  foreach ('archive','code','object') {   foreach my $key (keys(%parms)) {
     if (defined($parms{$_})) {      if ($key =~ /(archive|code|object)/i) {
  my $oldurl=$parms{$_};   my $oldurl=$parms{$key};
  my $newurl=&urlfixup($oldurl,$target);   my $newurl=&urlfixup($oldurl,$target);
  $newurl=~s/\/[^\/]+$/\/\*/;   $newurl=~s/\/[^\/]+$/\/\*/;
  print $logfile 'Allow: applet '.$_.':'.   print $logfile 'Allow: applet '.lc($key).':'.
     $oldurl.' allows '.      $oldurl.' allows '.$newurl."\n";
  $newurl."\n";  
  $allow{&absoluteurl($newurl,$target)}=1;   $allow{&absoluteurl($newurl,$target)}=1;
     }      }
  }   }
Line 622  sub fix_ids_and_indices { Line 773  sub fix_ids_and_indices {
  }   }
  if (!$endtag) { if ($token->[4]=~m:/>$:) { $endtag=' /'; }; }   if (!$endtag) { if ($token->[4]=~m:/>$:) { $endtag=' /'; }; }
  $outstring.='<'.$tag.$newparmstring.$endtag.'>';   $outstring.='<'.$tag.$newparmstring.$endtag.'>';
  if ($lctag eq 'm') {   if ($lctag eq 'm' || $lctag eq 'script' 
     $outstring.=&get_all_text_unbalanced('/m',\@parser);                      || $lctag eq 'display' || $lctag eq 'tex') {
       $outstring.=&get_all_text_unbalanced('/'.$lctag,\@parser);
  }   }
     } elsif ($token->[0] eq 'E') {      } elsif ($token->[0] eq 'E') {
  if ($token->[2]) {   if ($token->[2]) {
Line 646  sub fix_ids_and_indices { Line 798  sub fix_ids_and_indices {
  print $logfile "Does not need ID and/or index fixup\n";   print $logfile "Does not need ID and/or index fixup\n";
     }      }
   
     return ($outstring,%allow);      return ($outstring,0,%allow);
 }  }
   
 #########################################  #########################################
Line 654  sub fix_ids_and_indices { Line 806  sub fix_ids_and_indices {
   
 =pod  =pod
   
 =item store_metadata  =item B<store_metadata>
   
 Store the metadata in the metadata table in the loncapa database.  Store the metadata in the metadata table in the loncapa database.
 Uses lonmysql to access the database.  Uses lonmysql to access the database.
Line 668  Returns: (error,status).  error is undef Line 820  Returns: (error,status).  error is undef
 #########################################  #########################################
 #########################################  #########################################
 sub store_metadata {  sub store_metadata {
     my %metadata = %{shift()};      my %metadata = @_;
     my $error;      my $error;
     # Determine if the table exists      # Determine if the table exists
     my $status = &Apache::lonmysql::check_table('metadata');      my $status = &Apache::lonmysql::check_table('metadata');
     if (! defined($status)) {      if (! defined($status)) {
         $error='<font color="red">WARNING: Cannot connect to '.          $error='<span class="LC_error">WARNING: Cannot connect to '.
             'database!</font>';              'database!</span>';
         &Apache::lonnet::logthis($error);          &Apache::lonnet::logthis($error);
         return ($error,undef);          return ($error,undef);
     }      }
     if ($status == 0) {      if ($status == 0) {
         # It would be nice to actually create the table....          # It would be nice to actually create the table....
         $error ='<font color="red">WARNING: The metadata table does not '.          $error ='<span class="LC_error">WARNING: The metadata table does not '.
             'exist in the LON-CAPA database.</font>';              'exist in the LON-CAPA database.</span>';
         &Apache::lonnet::logthis($error);          &Apache::lonnet::logthis($error);
         return ($error,undef);          return ($error,undef);
     }      }
     # Remove old value from table      my $dbh = &Apache::lonmysql::get_dbh();
     $status = &Apache::lonmysql::remove_from_table      if (($metadata{'obsolete'}) || ($metadata{'copyright'} eq 'priv') ||
         ('metadata','url',$metadata{'url'});   ($metadata{'copyright'} eq 'custom')) {
     if (! defined($status)) {          # remove this entry
         $error = '<font color="red">Error when removing old values from '.   my $delitem = 'url = '.$dbh->quote($metadata{'url'});
             'metadata table in LON-CAPA database.</font>';   $status = &LONCAPA::lonmetadata::delete_metadata($dbh,undef,$delitem);
         &Apache::lonnet::logthis($error);                                                         
         return ($error,undef);      } else {
           $status = &LONCAPA::lonmetadata::update_metadata($dbh,undef,undef,
                                                            \%metadata);
     }      }
     # Store data in table.      if (defined($status) && $status ne '') {
     $status = &Apache::lonmysql::store_row('metadata',\%metadata);          $error='<span class="LC_error">Error occured saving new values in '.
     if (! defined($status)) {              'metadata table in LON-CAPA database</span>';
         $error='<font color="red">Error occured storing new values in '.  
             'metadata table in LON-CAPA database</font>';  
         &Apache::lonnet::logthis($error);          &Apache::lonnet::logthis($error);
           &Apache::lonnet::logthis($status);
         return ($error,undef);          return ($error,undef);
     }      }
     return (undef,$status);      return (undef,'success');
   }
   
   
   # ========================================== Parse file for errors and warnings
   
   sub checkonthis {
       my ($r,$source)=@_;
       my $uri=&Apache::lonnet::hreflocation($source);
       $uri=~s/\/$//;
       my $result=&Apache::lonnet::ssi_body($uri,
    ('grade_target'=>'web',
     'return_only_error_and_warning_counts' => 1));
       my ($errorcount,$warningcount)=split(':',$result);
       if (($errorcount) || ($warningcount)) {
           $r->print('<br /><tt>'.$uri.'</tt>: ');
    if ($errorcount) {
       $r->print('<img src="/adm/lonMisc/bomb.gif" /><span class="LC_error"><b>'.
         $errorcount.' '.
         &mt('error(s)').'</b></span> ');
    }
    if ($warningcount) {
       $r->print('<font color="blue">'.
         $warningcount.' '.
         &mt('warning(s)').'</font>');
    }
       } else {
    #$r->print('<font color="green">'.&mt('ok').'</font>');
       }
       $r->rflush();
       return ($warningcount,$errorcount);
   }
   
   # ============================================== Parse file itself for metadata
   #
   # parses a file with target meta, sets global %metadatafields %metadatakeys 
   
   sub parseformeta {
       my ($source,$style)=@_;
       my $allmeta='';
       if (($style eq 'ssi') || ($style eq 'prv')) {
    my $dir=$source;
    $dir=~s-/[^/]*$--;
    my $file=$source;
    $file=(split('/',$file))[-1];
           $source=&Apache::lonnet::hreflocation($dir,$file);
    $allmeta=&Apache::lonnet::ssi_body($source,('grade_target' => 'meta'));
           &metaeval($allmeta);
       }
       return $allmeta;
 }  }
   
 #########################################  #########################################
Line 710  sub store_metadata { Line 912  sub store_metadata {
   
 =pod  =pod
   
 =item publish  =item B<publish>
   
   This is the workhorse function of this module.  This subroutine generates
   backup copies, performs any automatic processing (prior to publication,
   especially for rat and ssi files),
   
   Returns a 2 element array, the first is the string to be shown to the
   user, the second is an error code, either 1 (an error occured) or 0
   (no error occurred)
   
 Currently undocumented.  This is the workhorse function of this module.  I<Additional documentation needed.>
   
 =cut  =cut
   
Line 720  Currently undocumented.  This is the wor Line 930  Currently undocumented.  This is the wor
 #########################################  #########################################
 sub publish {  sub publish {
   
     my ($source,$target,$style)=@_;      my ($source,$target,$style,$batch)=@_;
     my $logfile;      my $logfile;
     my $scrout='';      my $scrout='';
     my $allmeta='';      my $allmeta='';
Line 728  sub publish { Line 938  sub publish {
     my %allow=();      my %allow=();
   
     unless ($logfile=Apache::File->new('>>'.$source.'.log')) {      unless ($logfile=Apache::File->new('>>'.$source.'.log')) {
  return    return ('<span class="LC_error">'.&mt('No write permission to user directory, FAIL').'</span>',1);
          '<font color=red>No write permission to user directory, FAIL</font>';  
     }      }
     print $logfile       print $logfile 
 "\n\n================= Publish ".localtime()." Phase One  ================\n";  "\n\n================= Publish ".localtime()." Phase One  ================\n".$env{'user.name'}.':'.$env{'user.domain'}."\n";
   
     if (($style eq 'ssi') || ($style eq 'rat')) {      if (($style eq 'ssi') || ($style eq 'rat') || ($style eq 'prv')) {
 # ------------------------------------------------------- This needs processing  # ------------------------------------------------------- This needs processing
   
 # ----------------------------------------------------------------- Backup Copy  # ----------------------------------------------------------------- Backup Copy
Line 743  sub publish { Line 952  sub publish {
     print $logfile "Copied original file to ".$copyfile."\n";      print $logfile "Copied original file to ".$copyfile."\n";
         } else {          } else {
     print $logfile "Unable to write backup ".$copyfile.':'.$!."\n";      print $logfile "Unable to write backup ".$copyfile.':'.$!."\n";
           return "<font color=red>Failed to write backup copy, $!,FAIL</font>";      return ("<span class=\"LC_error\">Failed to write backup copy, $!,FAIL</span>",1);
         }          }
 # ------------------------------------------------------------- IDs and indices  # ------------------------------------------------------------- IDs and indices
   
  my $outstring;   my ($outstring,$error);
  ($outstring,%allow)=&fix_ids_and_indices($logfile,$source,$target);   ($outstring,$error,%allow)=&fix_ids_and_indices($logfile,$source,
    $target);
    if ($error) { return ($outstring,$error); }
 # ------------------------------------------------------------ Construct Allows  # ------------------------------------------------------------ Construct Allows
           
  $scrout.='<h3>Dependencies</h3>';   $scrout.='<h3>'.&mt('Dependencies').'</h3>';
         my $allowstr='';          my $allowstr='';
         foreach (sort(keys(%allow))) {          foreach my $thisdep (sort(keys(%allow))) {
    my $thisdep=$_;  
    if ($thisdep !~ /[^\s]/) { next; }     if ($thisdep !~ /[^\s]/) { next; }
              if ($thisdep =~/\$/) {
                 $scrout.='<br /><span class="LC_warning">'
                          .&mt('The resource depends on another resource with variable filename, i.e., [_1].','<tt>'.$thisdep.'</tt>').'<br />'
                          .&mt('You likely need to explicitly allow access to all possible dependencies using the [_1]-tag.','<tt>&lt;allow&gt;</tt>')
                          .'</span><br />';
              }
            unless ($style eq 'rat') {              unless ($style eq 'rat') { 
               $allowstr.="\n".'<allow src="'.$thisdep.'" />';                $allowstr.="\n".'<allow src="'.$thisdep.'" />';
    }     }
            $scrout.='<br>';             $scrout.='<br />';
            unless ($thisdep=~/\*/) {             if ($thisdep!~/[\*\$]/ && $thisdep!~m|^/adm/|) {
        $scrout.='<a href="'.$thisdep.'">';         $scrout.='<a href="'.$thisdep.'">';
            }             }
            $scrout.='<tt>'.$thisdep.'</tt>';             $scrout.='<tt>'.$thisdep.'</tt>';
            unless ($thisdep=~/\*/) {             if ($thisdep!~/[\*\$]/ && $thisdep!~m|^/adm/|) {
        $scrout.='</a>';         $scrout.='</a>';
                if (                 if (
        &Apache::lonnet::getfile($Apache::lonnet::perlvar{'lonDocRoot'}.'/'.         &Apache::lonnet::getfile($Apache::lonnet::perlvar{'lonDocRoot'}.'/'.
                                             $thisdep.'.meta') eq '-1') {                                              $thisdep.'.meta') eq '-1') {
    $scrout.=     $scrout.= ' - <span class="LC_error">'.&mt('Currently not available').
                            ' - <font color=red>Currently not available</font>';         '</span>';
                } else {                 } else {
                    my %temphash=(&Apache::lonnet::declutter($target).'___'.                     my %temphash=(&Apache::lonnet::declutter($target).'___'.
                              &Apache::lonnet::declutter($thisdep).'___usage'                               &Apache::lonnet::declutter($thisdep).'___usage'
                                  => time);                                   => time);
                    $thisdep=~/^\/res\/(\w+)\/(\w+)\//;                     $thisdep=~m{^/res/($match_domain)/($match_username)/};
                    if ((defined($1)) && (defined($2))) {                     if ((defined($1)) && (defined($2))) {
                       &Apache::lonnet::put('nohist_resevaldata',\%temphash,                        &Apache::lonnet::put('nohist_resevaldata',\%temphash,
    $1,$2);     $1,$2);
Line 783  sub publish { Line 999  sub publish {
        }         }
            }             }
         }          }
         $outstring=~s/\n*(\<\/[^\>]+\>)\s*$/$allowstr\n$1\n/s;          $outstring=~s/\n*(\<\/[^\>]+\>[^<]*)$/$allowstr\n$1\n/s;
   
  #Encode any High ASCII characters  # ------------------------------------------------------------- Write modified.
  $outstring=&HTML::Entities::encode($outstring,"\200-\377");  
 # ------------------------------------------------------------- Write modified  
   
         {          {
           my $org;            my $org;
           unless ($org=Apache::File->new('>'.$source)) {            unless ($org=Apache::File->new('>'.$source)) {
              print $logfile "No write permit to $source\n";               print $logfile "No write permit to $source\n";
              return                return ('<span class="LC_error">'.&mt('No write permission to').
               "<font color=red>No write permission to $source, FAIL</font>";       ' '.$source.
        ', '.&mt('FAIL').'</span>',1);
   }    }
           print $org $outstring;            print($org $outstring);
         }          }
   $content=$outstring;    $content=$outstring;
   
     }      }
 # --------------------------------------------- Initial step done, now metadata  # -------------------------------------------- Initial step done, now metadata.
   
 # ---------------------------------------- Storage for metadata keys and fields  
   
   # --------------------------------------- Storage for metadata keys and fields.
   # these are globals
   #
      %metadatafields=();       %metadatafields=();
      %metadatakeys=();       %metadatakeys=();
             
      my %oldparmstores=();       my %oldparmstores=();
             
            unless ($batch) {
      $scrout.='<h3>Metadata Information ' .       $scrout.='<h3>'.&mt('Metadata Information').' ' .
        Apache::loncommon::help_open_topic("Metadata_Description")         Apache::loncommon::help_open_topic("Metadata_Description")
        . '</h3>';         . '</h3>';
       }
   
 # ------------------------------------------------ First, check out environment  # ------------------------------------------------ First, check out environment
      unless (-e $source.'.meta') {       if ((!(-e $source.'.meta')) || ($env{'form.forceoverride'})) {
         $metadatafields{'author'}=$ENV{'environment.firstname'}.' '.          $metadatafields{'author'}=$env{'environment.firstname'}.' '.
                           $ENV{'environment.middlename'}.' '.                            $env{'environment.middlename'}.' '.
                   $ENV{'environment.lastname'}.' '.                    $env{'environment.lastname'}.' '.
                   $ENV{'environment.generation'};                    $env{'environment.generation'};
         $metadatafields{'author'}=~s/\s+/ /g;          $metadatafields{'author'}=~s/\s+/ /g;
         $metadatafields{'author'}=~s/\s+$//;          $metadatafields{'author'}=~s/\s+$//;
         $metadatafields{'owner'}=$cuname.'@'.$cudom;          $metadatafields{'owner'}=$cuname.':'.$cudom;
   
 # ------------------------------------------------ Check out directory hierachy  # ------------------------------------------------ Check out directory hierachy
   
         my $thisdisfn=$source;          my $thisdisfn=$source;
         $thisdisfn=~s/^\/home\/$cuname\///;          $thisdisfn=~s/^\/home\/\Q$cuname\E\///;
   
         my @urlparts=split(/\//,$thisdisfn);          my @urlparts=split(/\//,$thisdisfn);
         $#urlparts--;          $#urlparts--;
   
         my $currentpath='/home/'.$cuname.'/';          my $currentpath='/home/'.$cuname.'/';
   
    my $prefix='../'x($#urlparts);
         foreach (@urlparts) {          foreach (@urlparts) {
     $currentpath.=$_.'/';      $currentpath.=$_.'/';
             $scrout.=&metaread($logfile,$currentpath.'default.meta');              $scrout.=&metaread($logfile,$currentpath.'default.meta',$prefix);
       $prefix=~s|^\.\./||;
         }          }
   
   # ----------------------------------------------------------- Parse file itself
   # read %metadatafields from file itself
    
    $allmeta=&parseformeta($source,$style);
   
 # ------------------- Clear out parameters and stores (there should not be any)  # ------------------- Clear out parameters and stores (there should not be any)
   
         foreach (keys %metadatafields) {          foreach (keys %metadatafields) {
Line 859  sub publish { Line 1083  sub publish {
  delete $metadatafields{$_};   delete $metadatafields{$_};
             }              }
         }          }
           # ------------------------------------------------------------- Save some stuff
     }          my %savemeta=();
           foreach ('title') {
 # -------------------------------------------------- Parse content for metadata              $savemeta{$_}=$metadatafields{$_};
     if ($style eq 'ssi') {   }
         my $oldenv=$ENV{'request.uri'};  # ------------------------------------------ See if anything new in file itself
    
         $ENV{'request.uri'}=$target;   $allmeta=&parseformeta($source,$style);
         $allmeta=Apache::lonxml::xmlparse(undef,'meta',$content);  # ----------------------------------------------------------- Restore the stuff
         $ENV{'request.uri'}=$oldenv;          foreach (keys %savemeta) {
       $metadatafields{$_}=$savemeta{$_};
    }
      }
   
         &metaeval($allmeta);         
     }  
 # ---------------- Find and document discrepancies in the parameters and stores  # ---------------- Find and document discrepancies in the parameters and stores
   
         my $chparms='';      my $chparms='';
         foreach (sort keys %metadatafields) {      foreach (sort keys %metadatafields) {
     if (($_=~/^parameter/) || ($_=~/^stores/)) {   if (($_=~/^parameter/) || ($_=~/^stores/)) {
                 unless ($_=~/\.\w+$/) {       unless ($_=~/\.\w+$/) { 
                    unless ($oldparmstores{$_}) {   unless ($oldparmstores{$_}) {
       print $logfile 'New: '.$_."\n";      my $disp_key = $_;
                       $chparms.=$_.' ';      $disp_key =~ tr/\0/_/;
                    }      print $logfile ('New: '.$disp_key."\n");
         }      $chparms .= $disp_key.' ';
             }   }
         }      }
         if ($chparms) {   }
     $scrout.='<p><b>New parameters or stored values:</b> '.      }
                      $chparms;      if ($chparms) {
         }   $scrout.='<p><b>'.&mt('New parameters or saved values').
       ':</b> '.$chparms.'</p>';
       }
   
         $chparms='';      $chparms='';
         foreach (sort keys %oldparmstores) {      foreach (sort keys %oldparmstores) {
     if (($_=~/^parameter/) || ($_=~/^stores/)) {   if (($_=~/^parameter/) || ($_=~/^stores/)) {
                 unless (($metadatafields{$_.'.name'}) ||      unless (($metadatafields{$_.'.name'}) ||
                         ($metadatafields{$_.'.package'}) || ($_=~/\.\w+$/)) {      ($metadatafields{$_.'.package'}) || ($_=~/\.\w+$/)) {
     print $logfile 'Obsolete: '.$_."\n";   my $disp_key = $_;
                     $chparms.=$_.' ';   $disp_key =~ tr/\0/_/;
                 }   print $logfile ('Obsolete: '.$disp_key."\n");
             }   $chparms.=$disp_key.' ';
         }      }
         if ($chparms) {   }
     $scrout.='<p><b>Obsolete parameters or stored values:</b> '.      }
                      $chparms;      if ($chparms) {
         }   $scrout.='<p><b>'.&mt('Obsolete parameters or saved values').':</b> '.
       $chparms.'</p><h1><span class="LC_warning">'.&mt('Warning!').
       '</span></h1><p><span class="LC_warning">'.
       &mt('If this resource is in active use, student performance data from the previous version may become inaccessible.').'</span></p><hr />';
       }
       if ($metadatafields{'copyright'} eq 'priv') {
           $scrout.='</p><h1><span class="LC_warning">'.&mt('Warning!').
               '</span></h1><p><span class="LC_warning">'.
               &mt('Copyright/distribution option "Private" is no longer supported. Select another option from below. Consider "Custom Rights" for maximum control over the usage of your resource.').'</span></p><hr />';
       }
   
 # ------------------------------------------------------- Now have all metadata  # ------------------------------------------------------- Now have all metadata
   
         $scrout.=      my %keywords=();
      '<form name="pubform" action="/adm/publish" method="post">'.          
        '<p><input type="submit" value="Finalize Publication" /></p>'.      if (length($content)<500000) {
           &hiddenfield('phase','two').   my $textonly=$content;
           &hiddenfield('filename',$ENV{'form.filename'}).   $textonly=~s/\<script[^\<]+\<\/script\>//g;
   &hiddenfield('allmeta',&Apache::lonnet::escape($allmeta)).   $textonly=~s/\<m\>[^\<]+\<\/m\>//g;
           &hiddenfield('dependencies',join(',',keys %allow)).   $textonly=~s/\<[^\>]*\>//g;
           &textfield('Title','title',$metadatafields{'title'}).   $textonly=~tr/A-Z/a-z/;
           &textfield('Author(s)','author',$metadatafields{'author'}).   $textonly=~s/[\$\&][a-z]\w*//g;
   &textfield('Subject','subject',$metadatafields{'subject'});   $textonly=~s/[^a-z\s]//g;
   
 # --------------------------------------------------- Scan content for keywords   foreach ($textonly=~m/(\w+)/g) {
       unless ($nokey{$_}) {
    $keywords{$_}=1;
       } 
    }
       }
   
         my $keywords_help = Apache::loncommon::help_open_topic("Publishing_Keywords");              
  my $keywordout=<<"END";      foreach my $addkey (split(/[\"\'\,\;]/,$metadatafields{'keywords'})) {
    $addkey=~s/\s+/ /g;
    $addkey=~s/^\s//;
    $addkey=~s/\s$//;
    if ($addkey=~/\w/) {
       $keywords{$addkey}=1;
    }
       }
   # --------------------------------------------------- Now we also have keywords
   # =============================================================================
   # interactive mode html goes into $intr_scrout
   # batch mode throws away this HTML
   # additionally all of the field functions have a by product of setting
   #   $env{'from.'..} so that it can be used by the phase two handler in
   #    batch mode
   
       my $intr_scrout.=
    '<form name="pubform" action="/adm/publish" method="post">'.
    '<p>'.($env{'form.makeobsolete'}?'':'<input type="submit" value="'.&mt('Finalize Publication').'" />').'</p>'.
    &hiddenfield('phase','two').
    &hiddenfield('filename',$env{'form.filename'}).
    &hiddenfield('allmeta',&escape($allmeta)).
    &hiddenfield('dependencies',join(',',keys %allow));
       unless ($env{'form.makeobsolete'}) {
          $intr_scrout.=
    &textfield('Title','title',$metadatafields{'title'}).
    &textfield('Author(s)','author',$metadatafields{'author'}).
    &textfield('Subject','subject',$metadatafields{'subject'});
    # --------------------------------------------------- Scan content for keywords
   
       my $keywords_help = Apache::loncommon::help_open_topic("Publishing_Keywords");
       my $KEYWORDS=&mt('Keywords');
       my $CheckAll=&mt('check all');
       my $UncheckAll=&mt('uncheck all');
       my $keywordout=<<"END";
 <script>  <script>
 function checkAll(field)  function checkAll(field) {
 {  
     for (i = 0; i < field.length; i++)      for (i = 0; i < field.length; i++)
         field[i].checked = true ;          field[i].checked = true ;
 }  }
   
 function uncheckAll(field)  function uncheckAll(field) {
 {  
     for (i = 0; i < field.length; i++)      for (i = 0; i < field.length; i++)
         field[i].checked = false ;          field[i].checked = false ;
 }  }
 </script>  </script>
 <p><b>Keywords: $keywords_help</b>   <p><font color="#800000" face="helvetica"><b>$KEYWORDS:</b></font>
 <input type="button" value="check all" onclick="javascript:checkAll(document.pubform.keywords)">    $keywords_help</b>
 <input type="button" value="uncheck all" onclick="javascript:uncheckAll(document.pubform.keywords)">   <input type="button" value="$CheckAll" onclick="javascript:checkAll(document.pubform.keywords)" /> 
   <input type="button" value="$UncheckAll" onclick="javascript:uncheckAll(document.pubform.keywords)" /> 
   </p>
 <br />  <br />
 END  END
         $keywordout.='<table border=2><tr>';      $keywordout.='<table border="2"><tr>';
         my $colcount=0;      my $colcount=0;
         my %keywords=();  
           
  if (length($content)<500000) {  
     my $textonly=$content;  
             $textonly=~s/\<script[^\<]+\<\/script\>//g;  
             $textonly=~s/\<m\>[^\<]+\<\/m\>//g;  
             $textonly=~s/\<[^\>]*\>//g;  
             $textonly=~tr/A-Z/a-z/;  
             $textonly=~s/[\$\&][a-z]\w*//g;  
             $textonly=~s/[^a-z\s]//g;  
   
             foreach ($textonly=~m/(\w+)/g) {  
  unless ($nokey{$_}) {  
                    $keywords{$_}=1;  
                 }   
             }  
         }  
   
                   foreach (sort keys %keywords) {
             foreach (split(/\W+/,$metadatafields{'keywords'})) {   $keywordout.='<td><label><input type="checkbox" name="keywords" value="'.$_.'"';
  $keywords{$_}=1;   if ($metadatafields{'keywords'}) {
             }      if ($metadatafields{'keywords'}=~/\Q$_\E/) {
    $keywordout.=' checked="on"';
    $env{'form.keywords'}.=$_.',';
       }
    } elsif (&Apache::loncommon::keyword($_)) {
       $keywordout.=' checked="on"';
       $env{'form.keywords'}.=$_.',';
    }
    $keywordout.=' />'.$_.'</label></td>';
    if ($colcount>10) {
       $keywordout.="</tr><tr>\n";
       $colcount=0;
    }
    $colcount++;
       }
       $env{'form.keywords'}=~s/\,$//;
   
             foreach (sort keys %keywords) {      $keywordout.='</tr></table>';
                 $keywordout.='<td><input type=checkbox name="keywords" value="'.$_.'"';  
                 if ($metadatafields{'keywords'}) {      $intr_scrout.=$keywordout;
                    if ($metadatafields{'keywords'}=~/$_/) {   
                       $keywordout.=' checked';   
                    }  
         } elsif (&Apache::loncommon::keyword($_)) {  
             $keywordout.=' checked';  
                 }   
                 $keywordout.='>'.$_.'</td>';  
                 if ($colcount>10) {  
     $keywordout.="</tr><tr>\n";  
                     $colcount=0;  
                 }  
                 $colcount++;  
             }  
           
  $keywordout.='</tr></table>';  
   
         $scrout.=$keywordout;      $intr_scrout.=&textfield('Additional Keywords','addkey','');
   
         $scrout.=&textfield('Additional Keywords','addkey','');      $intr_scrout.=&textfield('Notes','notes',$metadatafields{'notes'});
   
         $scrout.=&textfield('Notes','notes',$metadatafields{'notes'});      $intr_scrout.=
    "\n<p><font color=\"#800000\" face=\"helvetica\"><b>".&mt('Abstract').":".
    "</b></font></p><br />".
    '<textarea cols="80" rows="5" name="abstract">'.
    $metadatafields{'abstract'}.'</textarea></p>';
   
         $scrout.=      $source=~/\.(\w+)$/;
              '<p><b>Abstract:</b><br><textarea cols=80 rows=5 name=abstract>'.  
               $metadatafields{'abstract'}.'</textarea>';  
   
  $source=~/\.(\w+)$/;  
   
  $scrout.=&hiddenfield('mime',$1);      $intr_scrout.=
    "\n<p><font color=\"#800000\" face=\"helvetica\"><b>".
    &mt('Lowest Grade Level').':'.
    "</b></font></p><br />".
    &select_level_form($metadatafields{'lowestgradelevel'},'lowestgradelevel').
    "\n<p><font color=\"#800000\" face=\"helvetica\"><b>".
    &mt('Highest Grade Level').':'.
    "</b></font></p><br />".
    &select_level_form($metadatafields{'highestgradelevel'},'highestgradelevel').
    &textfield('Standards','standards',$metadatafields{'standards'});
   
         $scrout.=&selectbox('Language','language',  
                             $metadatafields{'language'},  
     \&Apache::loncommon::languagedescription,  
     (&Apache::loncommon::languageids),      $intr_scrout.=&hiddenfield('mime',$1);
   
       my $defaultlanguage=$metadatafields{'language'};
       $defaultlanguage =~ s/\s*notset\s*//g;
       $defaultlanguage =~ s/^,\s*//g;
       $defaultlanguage =~ s/,\s*$//g;
   
       $intr_scrout.=&selectbox('Language','language',
        $defaultlanguage,
        \&Apache::loncommon::languagedescription,
        (&Apache::loncommon::languageids),
      );       );
   
         unless ($metadatafields{'creationdate'}) {      unless ($metadatafields{'creationdate'}) {
     $metadatafields{'creationdate'}=time;   $metadatafields{'creationdate'}=time;
         }      }
         $scrout.=&hiddenfield('creationdate',$metadatafields{'creationdate'});      $intr_scrout.=&hiddenfield('creationdate',
          &Apache::lonmysql::unsqltime($metadatafields{'creationdate'}));
   
       $intr_scrout.=&hiddenfield('lastrevisiondate',time);
   
         $scrout.=&hiddenfield('lastrevisiondate',time);  
   
          $intr_scrout.=&textfield('Publisher/Owner','owner',
  $scrout.=&textfield('Publisher/Owner','owner',       $metadatafields{'owner'});
                             $metadatafields{'owner'});  
 # --------------------------------------------------- Correct copyright for rat          # ---------------------------------------------- Retrofix for unused copyright
       if ($metadatafields{'copyright'} eq 'free') {
     if ($style eq 'rat') {   $metadatafields{'copyright'}='default';
  if ($metadatafields{'copyright'} eq 'public') {    $metadatafields{'sourceavail'}='open';
     delete $metadatafields{'copyright'};      }
  }      if ($metadatafields{'copyright'} eq 'priv') {
         $scrout.=&selectbox('Copyright/Distribution','copyright',          $metadatafields{'copyright'}='domain';
                             $metadatafields{'copyright'},      }
     \&Apache::loncommon::copyrightdescription,  # ------------------------------------------------ Dial in reasonable defaults
      (grep !/^public$/,(&Apache::loncommon::copyrightids)));      my $defaultoption=$metadatafields{'copyright'};
     }      unless ($defaultoption) { $defaultoption='default'; }
     else {      my $defaultsourceoption=$metadatafields{'sourceavail'};
         $scrout.=&selectbox('Copyright/Distribution','copyright',      unless ($defaultsourceoption) { $defaultsourceoption='closed'; }
                             $metadatafields{'copyright'},      unless ($style eq 'prv') {
     \&Apache::loncommon::copyrightdescription,  # -------------------------------------------------- Correct copyright for rat.
      (&Apache::loncommon::copyrightids));   if ($style eq 'rat') {
     }  # -------------------------------------- Retrofix for non-applicable copyright
       if ($metadatafields{'copyright'} eq 'public') { 
     my $copyright_help = Apache::loncommon::help_open_topic("Publishing_Copyright");   delete $metadatafields{'copyright'};
     $scrout =~ s/DISTRIBUTION:/'DISTRIBUTION: ' . $copyright_help/ge;   $defaultoption='default';
     return $scrout.      }
       '<p><input type="submit" value="Finalize Publication" /></p></form>';      $intr_scrout.=&selectbox('Copyright/Distribution','copyright',
        $defaultoption,
        \&Apache::loncommon::copyrightdescription,
       (grep !/^(public|priv)$/,(&Apache::loncommon::copyrightids)));
    } else {
       $intr_scrout.=&selectbox('Copyright/Distribution','copyright',
        $defaultoption,
        \&Apache::loncommon::copyrightdescription,
        (grep !/^priv$/,(&Apache::loncommon::copyrightids)));
    }
    my $copyright_help =
       Apache::loncommon::help_open_topic('Publishing_Copyright');
    $intr_scrout =~ s/Distribution:/'Distribution: ' . $copyright_help/ge;
    $intr_scrout.=&text_with_browse_field('Custom Distribution File','customdistributionfile',$metadatafields{'customdistributionfile'},'rights').$copyright_help;
    $intr_scrout.=&selectbox('Source Distribution','sourceavail',
    $defaultsourceoption,
    \&Apache::loncommon::source_copyrightdescription,
    (&Apache::loncommon::source_copyrightids));
   # $intr_scrout.=&text_with_browse_field('Source Custom Distribution File','sourcerights',$metadatafields{'sourcerights'},'rights');
    my $uctitle=&mt('Obsolete');
    $intr_scrout.=
       "\n<p><label><font color=\"#800000\" face=\"helvetica\"><b>$uctitle:".
       '</b></font> <input type="checkbox" name="obsolete" ';
    if ($metadatafields{'obsolete'}) {
       $intr_scrout.=' checked="1" ';
    }
    $intr_scrout.='/ ></label></p>'.
       &text_with_browse_field('Suggested Replacement for Obsolete File',
       'obsoletereplacement',
       $metadatafields{'obsoletereplacement'});
       } else {
    $intr_scrout.=&hiddenfield('copyright','private');
       }
      } else {
          $intr_scrout.=
    &hiddenfield('title',$metadatafields{'title'}).
    &hiddenfield('author',$metadatafields{'author'}).
    &hiddenfield('subject',$metadatafields{'subject'}).
    &hiddenfield('keywords',$metadatafields{'keywords'}).
    &hiddenfield('abstract',$metadatafields{'abstract'}).
    &hiddenfield('notes',$metadatafields{'notes'}).
    &hiddenfield('mime',$metadatafields{'mime'}).
    &hiddenfield('creationdate',$metadatafields{'creationdate'}).
    &hiddenfield('lastrevisiondate',time).
    &hiddenfield('owner',$metadatafields{'owner'}).
    &hiddenfield('lowestgradelevel',$metadatafields{'lowestgradelevel'}).
    &hiddenfield('standards',$metadatafields{'standards'}).
    &hiddenfield('highestgradelevel',$metadatafields{'highestgradelevel'}).
    &hiddenfield('language',$metadatafields{'language'}).
    &hiddenfield('copyright',$metadatafields{'copyright'}).
    &hiddenfield('sourceavail',$metadatafields{'sourceavail'}).
    &hiddenfield('customdistributionfile',$metadatafields{'customdistributionfile'}).
    &hiddenfield('obsolete',1).
    &text_with_browse_field('Suggested Replacement for Obsolete File',
       'obsoletereplacement',
       $metadatafields{'obsoletereplacement'});
      }
       if (!$batch) {
    $scrout.=$intr_scrout.'<p><input type="submit" value="'.
       &mt($env{'form.makeobsolete'}?'Make Obsolete':'Finalize Publication').'" /></p></form>';
       }
       return($scrout,0);
 }  }
   
 #########################################  #########################################
Line 1043  END Line 1385  END
   
 =pod   =pod 
   
 =item phasetwo  =item B<phasetwo>
   
 Render second interface showing status of publication steps.  Render second interface showing status of publication steps.
 This is publication step two.  This is publication step two.
   
   Parameters:
   
   =over 4
   
   =item I<$source>
   
   =item I<$target>
   
   =item I<$style>
   
   =item I<$distarget>
   
   =back
   
   Returns:
   
   =over 4
   
   =item integer
   
   0: fail
   1: success
   
 =cut  =cut
   
   #'stupid emacs
 #########################################  #########################################
 #########################################  #########################################
 sub phasetwo {  sub phasetwo {
   
     my ($source,$target,$style,$distarget)=@_;      my ($r,$source,$target,$style,$distarget,$batch)=@_;
       $source=~s/\/+/\//g;
       $target=~s/\/+/\//g;
   #
   # Unless trying to get rid of something, check name validity
   #
       unless ($env{'form.obsolete'}) {
    if ($target=~/(\_\_\_|\&\&\&|\:\:\:)/) {
       $r->print('<span class="LC_error">'.
         &mt('Unsupported character combination [_1] in filename, FAIL.',"<tt>'.$1.'</tt>").
         '</span>');
       return 0;
    }
    unless ($target=~/\.(\w+)$/) {
       $r->print('<span class="LC_error">'.&mt('No valid extension found in filename, FAIL').'</span>');
       return 0;
    }
    if ($target=~/\.(\d+)\.(\w+)$/) {
       $r->print('<span class="LC_error">'.&mt('Cannot publish versioned resource, FAIL').'</span>');
       return 0;
    }
       }
   
   #
   # End name check
   #
       $distarget=~s/\/+/\//g;
     my $logfile;      my $logfile;
     my $scrout='';  
     unless ($logfile=Apache::File->new('>>'.$source.'.log')) {      unless ($logfile=Apache::File->new('>>'.$source.'.log')) {
  return    $r->print(
          '<font color=red>No write permission to user directory, FAIL</font>';          '<span class="LC_error">'.
    &mt('No write permission to user directory, FAIL').'</span>');
           return 0;
       }
       
       if ($source =~ /\.rights$/) {
    $r->print('<p><span class="LC_warning">'.&mt('Warning: It can take up to 1 hour for rights changes to fully propagate.').'</span></p>');
     }      }
     print $logfile   
 "\n================= Publish ".localtime()." Phase Two  ================\n";  
   
      %metadatafields=();  
      %metadatakeys=();  
   
      &metaeval(&Apache::lonnet::unescape($ENV{'form.allmeta'}));  
   
      $metadatafields{'title'}=$ENV{'form.title'};      print $logfile 
      $metadatafields{'author'}=$ENV{'form.author'};          "\n================= Publish ".localtime()." Phase Two  ================\n".$env{'user.name'}.':'.$env{'user.domain'}."\n";
      $metadatafields{'subject'}=$ENV{'form.subject'};      
      $metadatafields{'notes'}=$ENV{'form.notes'};      %metadatafields=();
      $metadatafields{'abstract'}=$ENV{'form.abstract'};      %metadatakeys=();
      $metadatafields{'mime'}=$ENV{'form.mime'};  
      $metadatafields{'language'}=$ENV{'form.language'};  
      $metadatafields{'creationdate'}=  
          &sqltime($ENV{'form.creationdate'});  
      $metadatafields{'lastrevisiondate'}=  
          &sqltime($ENV{'form.lastrevisiondate'});  
      $metadatafields{'owner'}=$ENV{'form.owner'};  
      $metadatafields{'copyright'}=$ENV{'form.copyright'};  
      $metadatafields{'dependencies'}=$ENV{'form.dependencies'};  
   
      my $allkeywords=$ENV{'form.addkey'};  
      if (exists($ENV{'form.keywords'})) {  
          if (ref($ENV{'form.keywords'})) {  
              $allkeywords .= ','.join(',',@{$ENV{'form.keywords'}});  
          } else {  
              $allkeywords .= ','.$ENV{'form.keywords'};  
          }  
      }  
      $allkeywords=~s/\W+/\,/;  
      $allkeywords=~s/^\,//;  
      $metadatafields{'keywords'}=$allkeywords;  
    
      {  
        print $logfile "\nWrite metadata file for ".$source;  
        my $mfh;  
        unless ($mfh=Apache::File->new('>'.$source.'.meta')) {  
  return   
          '<font color=red>Could not write metadata, FAIL</font>';  
        }  
        foreach (sort keys %metadatafields) {  
  unless ($_=~/\./) {  
            my $unikey=$_;  
            $unikey=~/^([A-Za-z]+)/;  
            my $tag=$1;  
            $tag=~tr/A-Z/a-z/;  
            print $mfh "\n\<$tag";  
            foreach (split(/\,/,$metadatakeys{$unikey})) {  
                my $value=$metadatafields{$unikey.'.'.$_};  
                $value=~s/\"/\'\'/g;  
                print $mfh ' '.$_.'="'.$value.'"';  
            }  
    print $mfh '>'.  
      &HTML::Entities::encode($metadatafields{$unikey})  
        .'</'.$tag.'>';  
          }  
        }  
        $scrout.='<p>Wrote Metadata';  
        print $logfile "\nWrote metadata";  
      }  
   
 # -------------------------------- Synchronize entry with SQL metadata database      &metaeval(&unescape($env{'form.allmeta'}));
     my $warning;      
     $metadatafields{'url'} = $distarget;      $metadatafields{'title'}=$env{'form.title'};
     $metadatafields{'version'} = 'current';      $metadatafields{'author'}=$env{'form.author'};
     unless ($metadatafields{'copyright'} eq 'priv') {      $metadatafields{'subject'}=$env{'form.subject'};
         my ($error,$success) = &store_metadata(\%metadatafields);      $metadatafields{'notes'}=$env{'form.notes'};
         if ($success) {      $metadatafields{'abstract'}=$env{'form.abstract'};
             $scrout.='<p>Synchronized SQL metadata database';      $metadatafields{'mime'}=$env{'form.mime'};
             print $logfile "\nSynchronized SQL metadata database";      $metadatafields{'language'}=$env{'form.language'};
       $metadatafields{'creationdate'}=$env{'form.creationdate'};
       $metadatafields{'lastrevisiondate'}=$env{'form.lastrevisiondate'};
       $metadatafields{'owner'}=$env{'form.owner'};
       $metadatafields{'copyright'}=$env{'form.copyright'};
       $metadatafields{'standards'}=$env{'form.standards'};
       $metadatafields{'lowestgradelevel'}=$env{'form.lowestgradelevel'};
       $metadatafields{'highestgradelevel'}=$env{'form.highestgradelevel'};
       $metadatafields{'customdistributionfile'}=
                                    $env{'form.customdistributionfile'};
       $metadatafields{'sourceavail'}=$env{'form.sourceavail'};
       $metadatafields{'obsolete'}=$env{'form.obsolete'};
       $metadatafields{'obsoletereplacement'}=
                           $env{'form.obsoletereplacement'};
       $metadatafields{'dependencies'}=$env{'form.dependencies'};
       $metadatafields{'modifyinguser'}=$env{'user.name'}.':'.
                                    $env{'user.domain'};
       $metadatafields{'authorspace'}=$cuname.':'.$cudom;
       $metadatafields{'domain'}=$cudom;
       
       my $allkeywords=$env{'form.addkey'};
       if (exists($env{'form.keywords'})) {
           if (ref($env{'form.keywords'})) {
               $allkeywords .= ','.join(',',@{$env{'form.keywords'}});
         } else {          } else {
             $warning.=$error;              $allkeywords .= ','.$env{'form.keywords'};
             print $logfile "\n".$error;  
         }          }
     } else {  
         $scrout.='<p>Private Publication - did not synchronize database';  
         print $logfile "\nPrivate: Did not synchronize data into ".  
             "SQL metadata database";  
     }      }
 # ----------------------------------------------------------- Copy old versions      $allkeywords=~s/[\"\']//g;
          $allkeywords=~s/\s*[\;\,]\s*/\,/g;
 if (-e $target) {      $allkeywords=~s/\s+/ /g;
     my $filename;      $allkeywords=~s/^[ \,]//;
     my $maxversion=0;      $allkeywords=~s/[ \,]$//;
     $target=~/(.*)\/([^\/]+)\.(\w+)$/;      $metadatafields{'keywords'}=$allkeywords;
     my $srcf=$2;      
     my $srct=$3;  # check if custom distribution file is specified
     my $srcd=$1;      if ($metadatafields{'copyright'} eq 'custom') {
     unless ($srcd=~/^\/home\/httpd\/html\/res/) {   my $file=$metadatafields{'customdistributionfile'};
  print $logfile "\nPANIC: Target dir is ".$srcd;   unless ($file=~/\.rights$/) {
         return "<font color=red>Invalid target directory, FAIL</font>";              $r->print(
                   '<span class="LC_error">'.&mt('No valid custom distribution rights file specified, FAIL').
    '</span>');
       return 0;
           }
     }      }
     opendir(DIR,$srcd);      {
     while ($filename=readdir(DIR)) {          print $logfile "\nWrite metadata file for ".$source;
        if ($filename=~/$srcf\.(\d+)\.$srct$/) {          my $mfh;
    $maxversion=($1>$maxversion)?$1:$maxversion;          unless ($mfh=Apache::File->new('>'.$source.'.meta')) {
        }              $r->print( 
                   '<span class="LC_error">'.&mt('Could not write metadata, FAIL').
    '</span>');
       return 0;
           }
           foreach (sort keys %metadatafields) {
               unless ($_=~/\./) {
                   my $unikey=$_;
                   $unikey=~/^([A-Za-z]+)/;
                   my $tag=$1;
                   $tag=~tr/A-Z/a-z/;
                   print $mfh "\n\<$tag";
                   foreach (split(/\,/,$metadatakeys{$unikey})) {
                       my $value=$metadatafields{$unikey.'.'.$_};
                       $value=~s/\"/\'\'/g;
                       print $mfh ' '.$_.'="'.$value.'"';
                   }
                   print $mfh '>'.
                       &HTML::Entities::encode($metadatafields{$unikey},'<>&"')
                           .'</'.$tag.'>';
               }
           }
           $r->print('<p>'.&mt('Wrote Metadata').'</p>');
           print $logfile "\nWrote metadata";
     }      }
     closedir(DIR);      
     $maxversion++;  # -------------------------------- Synchronize entry with SQL metadata database
     $scrout.='<p>Creating old version '.$maxversion;  
     print $logfile "\nCreating old version ".$maxversion;  
   
     my $copyfile=$srcd.'/'.$srcf.'.'.$maxversion.'.'.$srct;      $metadatafields{'url'} = $distarget;
       $metadatafields{'version'} = 'current';
   
       my ($error,$success) = &store_metadata(%metadatafields);
       if ($success) {
    $r->print('<p>'.&mt('Synchronized SQL metadata database').'</p>');
    print $logfile "\nSynchronized SQL metadata database";
       } else {
    $r->print($error);
    print $logfile "\n".$error;
       }
   # --------------------------------------------- Delete author resource messages
       my $delresult=&Apache::lonmsg::del_url_author_res_msg($target); 
       $r->print('<p>'.&mt('Removing error messages:').' '.$delresult.'</p>');
       print $logfile "\nRemoving error messages: $delresult";
   # ----------------------------------------------------------- Copy old versions
      
       if (-e $target) {
           my $filename;
           my $maxversion=0;
           $target=~/(.*)\/([^\/]+)\.(\w+)$/;
           my $srcf=$2;
           my $srct=$3;
           my $srcd=$1;
           unless ($srcd=~/^\/home\/httpd\/html\/res/) {
               print $logfile "\nPANIC: Target dir is ".$srcd;
               $r->print(
    "<span class=\"LC_error\">Invalid target directory, FAIL</span>");
       return 0;
           }
           opendir(DIR,$srcd);
           while ($filename=readdir(DIR)) {
               if (-l $srcd.'/'.$filename) {
                   unlink($srcd.'/'.$filename);
                   unlink($srcd.'/'.$filename.'.meta');
               } else {
                   if ($filename=~/\Q$srcf\E\.(\d+)\.\Q$srct\E$/) {
                       $maxversion=($1>$maxversion)?$1:$maxversion;
                   }
               }
           }
           closedir(DIR);
           $maxversion++;
           $r->print('<p>Creating old version '.$maxversion.'</p>');
           print $logfile "\nCreating old version ".$maxversion."\n";
           
           my $copyfile=$srcd.'/'.$srcf.'.'.$maxversion.'.'.$srct;
           
         if (copy($target,$copyfile)) {          if (copy($target,$copyfile)) {
     print $logfile "Copied old target to ".$copyfile."\n";      print $logfile "Copied old target to ".$copyfile."\n";
             $scrout.='<p>Copied old target file';              $r->print('<p>'.&mt('Copied old target file').'</p>');
         } else {          } else {
     print $logfile "Unable to write ".$copyfile.':'.$!."\n";      print $logfile "Unable to write ".$copyfile.':'.$!."\n";
            return "<font color=red>Failed to copy old target, $!, FAIL</font>";              $r->print("<span class=\"LC_error\">".&mt('Failed to copy old target').
    ", $!, ".&mt('FAIL')."</span>");
       return 0;
         }          }
           
 # --------------------------------------------------------------- Copy Metadata  # --------------------------------------------------------------- Copy Metadata
   
  $copyfile=$copyfile.'.meta';   $copyfile=$copyfile.'.meta';
           
         if (copy($target.'.meta',$copyfile)) {          if (copy($target.'.meta',$copyfile)) {
     print $logfile "Copied old target metadata to ".$copyfile."\n";      print $logfile "Copied old target metadata to ".$copyfile."\n";
             $scrout.='<p>Copied old metadata';              $r->print('<p>'.&mt('Copied old metadata').'</p>')
         } else {          } else {
     print $logfile "Unable to write metadata ".$copyfile.':'.$!."\n";      print $logfile "Unable to write metadata ".$copyfile.':'.$!."\n";
             if (-e $target.'.meta') {              if (-e $target.'.meta') {
                return                   $r->print( 
        "<font color=red>Failed to write old metadata copy, $!, FAIL</font>";                      "<span class=\"LC_error\">".
   &mt('Failed to write old metadata copy').", $!, ".&mt('FAIL')."</span>");
    return 0;
     }      }
         }          }
           
           
       } else {
           $r->print('<p>'.&mt('Initial version').'</p>');
           print $logfile "\nInitial version";
       }
   
   # ---------------------------------------------------------------- Write Source
       my $copyfile=$target;
       
       my @parts=split(/\//,$copyfile);
       my $path="/$parts[1]/$parts[2]/$parts[3]/$parts[4]";
       
       my $count;
       for ($count=5;$count<$#parts;$count++) {
           $path.="/$parts[$count]";
           if ((-e $path)!=1) {
               print $logfile "\nCreating directory ".$path;
               $r->print('<p>'.&mt('Created directory').' '.$parts[$count].'</p>');
               mkdir($path,0777);
           }
       }
       
       if (copy($source,$copyfile)) {
           print $logfile "\nCopied original source to ".$copyfile."\n";
           $r->print('<p>'.&mt('Copied source file').'</p>');
       } else {
           print $logfile "\nUnable to write ".$copyfile.':'.$!."\n";
           $r->print("<span class=\"LC_error\">".
       &mt('Failed to copy source').", $!, ".&mt('FAIL')."</span>");
    return 0;
       }
       
   # --------------------------------------------------------------- Copy Metadata
   
       $copyfile=$copyfile.'.meta';
       
       if (copy($source.'.meta',$copyfile)) {
           print $logfile "\nCopied original metadata to ".$copyfile."\n";
           $r->print('<p>'.&mt('Copied metadata').'</p>');
       } else {
           print $logfile "\nUnable to write metadata ".$copyfile.':'.$!."\n";
           $r->print(
               "<span class=\"LC_error\">".&mt('Failed to write metadata copy').", $!, ".&mt('FAIL')."</span>");
    return 0;
       }
       $r->rflush;
   
 } else {  # ------------------------------------------------------------- Trigger updates
     $scrout.='<p>Initial version';      push(@{$modified_urls},[$target,$source]);
     print $logfile "\nInitial version";      unless ($registered_cleanup) {
    $r->register_cleanup(\&notify);
    $registered_cleanup=1;
       }
   
   # ---------------------------------------------------------- Clear local caches
       my $thisdistarget=$target;
       $thisdistarget=~s/^\Q$docroot\E//;
       &Apache::lonnet::devalidate_cache_new('resversion',$target);
       &Apache::lonnet::devalidate_cache_new('meta',
    &Apache::lonnet::declutter($thisdistarget));
   
   # ------------------------------------------------ Provide link to new resource
       unless ($batch) {
           
           my $thissrc=$source;
           $thissrc=~s{^/home/($match_username)/public_html}{/priv/$1};
           
           my $thissrcdir=$thissrc;
           $thissrcdir=~s/\/[^\/]+$/\//;
           
           
           $r->print(
              '<hr /><a href="'.$thisdistarget.'"><font size="+2">'.
              &mt('View Published Version').'</font></a>'.
              '<p><a href="'.$thissrc.'"><font size=+2>'.
     &mt('Back to Source').'</font></a></p>'.
              '<p><a href="'.$thissrcdir.
                      '"><font size="+2">'.
     &mt('Back to Source Directory').'</font></a></p>');
       }
       $logfile->close();
       $r->print('<p><font color="green">'.&mt('Done').'</font></p>');
       return 1;
 }  }
   
 # ---------------------------------------------------------------- Write Source  # =============================================================== Notifications
  my $copyfile=$target;  sub notify {  
   # --------------------------------------------------- Send update notifications
       foreach my $targetsource (@{$modified_urls}){
    my ($target,$source)=@{$targetsource};
    my $logfile=Apache::File->new('>>'.$source.'.log');
    print $logfile "\nCleanup phase: Notifications\n";
    my @subscribed=&get_subscribed_hosts($target);
    foreach my $subhost (@subscribed) {
       print $logfile "\nNotifying host ".$subhost.':';
       my $reply=&Apache::lonnet::critical('update:'.$target,$subhost);
       print $logfile $reply;
    }
   # ---------------------------------------- Send update notifications, meta only
    my @subscribedmeta=&get_subscribed_hosts("$target.meta");
    foreach my $subhost (@subscribedmeta) {
       print $logfile "\nNotifying host for metadata only ".$subhost.':';
       my $reply=&Apache::lonnet::critical('update:'.$target.'.meta',
    $subhost);
       print $logfile $reply;
    } 
   # --------------------------------------------------- Notify subscribed courses
    my %courses=&coursedependencies($target);
    my $now=time;
    foreach (keys %courses) {
       print $logfile "\nNotifying course ".$_.':';
       my ($cdom,$cname)=split(/\_/,$_);
       my $reply=&Apache::lonnet::cput
    ('versionupdate',{$target => $now},$cdom,$cname);
       print $logfile $reply;
    }
    print $logfile "\n============ Done ============\n";
    $logfile->close();
       }
       return OK;
   }
   
            my @parts=split(/\//,$copyfile);  #########################################
            my $path="/$parts[1]/$parts[2]/$parts[3]/$parts[4]";  
   
            my $count;  sub batchpublish {
            for ($count=5;$count<$#parts;$count++) {      my ($r,$srcfile,$targetfile)=@_;
                $path.="/$parts[$count]";      #publication pollutes %env with form.* values
                if ((-e $path)!=1) {      my %oldenv=%env;
                    print $logfile "\nCreating directory ".$path;      $srcfile=~s/\/+/\//g;
                    $scrout.='<p>Created directory '.$parts[$count];      $targetfile=~s/\/+/\//g;
    mkdir($path,0777);      my $thisdisfn=$srcfile;
                }      $thisdisfn=~s/\/home\/korte\/public_html\///;
            }      $srcfile=~s/\/+/\//g;
   
         if (copy($source,$copyfile)) {      my $docroot=$r->dir_config('lonDocRoot');
     print $logfile "Copied original source to ".$copyfile."\n";      my $thisdistarget=$targetfile;
             $scrout.='<p>Copied source file';      $thisdistarget=~s/^\Q$docroot\E//;
         } else {  
     print $logfile "Unable to write ".$copyfile.':'.$!."\n";  
             return "<font color=red>Failed to copy source, $!, FAIL</font>";  
         }  
   
 # --------------------------------------------------------------- Copy Metadata  
   
         $copyfile=$copyfile.'.meta';      %metadatafields=();
       %metadatakeys=();
       $srcfile=~/\.(\w+)$/;
       my $thistype=$1;
   
         if (copy($source.'.meta',$copyfile)) {  
     print $logfile "Copied original metadata to ".$copyfile."\n";  
             $scrout.='<p>Copied metadata';  
         } else {  
     print $logfile "Unable to write metadata ".$copyfile.':'.$!."\n";  
             return   
           "<font color=red>Failed to write metadata copy, $!, FAIL</font>";  
         }  
   
 # --------------------------------------------------- Send update notifications      my $thisembstyle=&Apache::loncommon::fileembstyle($thistype);
        
       $r->print('<h2>'.&mt('Publishing').' <tt>'.$thisdisfn.'</tt></h2>');
   
     my @subscribed=&get_subscribed_hosts($target);  # phase one takes
     foreach my $subhost (@subscribed) {  #  my ($source,$target,$style,$batch)=@_;
  $scrout.='<p>Notifying host '.$subhost.':';      my ($outstring,$error)=&publish($srcfile,$targetfile,$thisembstyle,1);
  print $logfile "\nNotifying host ".$subhost.':';      $r->print('<p>'.$outstring.'</p>');
  my $reply=&Apache::lonnet::critical('update:'.$target,$subhost);  # phase two takes
  $scrout.=$reply;  # my ($source,$target,$style,$distarget,batch)=@_;
  print $logfile $reply;  # $env{'form.allmeta'},$env{'form.title'},$env{'form.author'},...
     }      if (!$error) {
    $r->print('<p>');
    &phasetwo($r,$srcfile,$targetfile,$thisembstyle,$thisdistarget,1);
    $r->print('</p>');
       }
       %env=%oldenv;
       return '';
   }
   
 # ---------------------------------------- Send update notifications, meta only  #########################################
   
     my @subscribedmeta=&get_subscribed_hosts("$target.meta");  sub publishdirectory {
     foreach my $subhost (@subscribedmeta) {      my ($r,$fn,$thisdisfn)=@_;
  $scrout.='<p>Notifying host for metadata only '.$subhost.':';      $fn=~s/\/+/\//g;
  print $logfile "\nNotifying host for metadata only ".$subhost.':';      $thisdisfn=~s/\/+/\//g;
  my $reply=&Apache::lonnet::critical('update:'.$target.'.meta',      my $resdir=
     $subhost);   $Apache::lonnet::perlvar{'lonDocRoot'}.'/res/'.$cudom.'/'.$cuname.'/'.
  $scrout.=$reply;   $thisdisfn;
  print $logfile $reply;      $r->print('<h1>'.&mt('Directory').' <tt>'.$thisdisfn.'</tt></h1>'.
         &mt('Target').': <tt>'.$resdir.'</tt><br />');
   
       my $dirptr=16384; # Mask indicating a directory in stat.cmode.
       unless ($env{'form.phase'} eq 'two') {
   # ask user what they want
           $r->print('<form name="pubdirpref" method="post">'.
     &hiddenfield('phase','two').
     &hiddenfield('filename',$env{'form.filename'}).
     &checkbox('pubrec','include subdirectories').
     &checkbox('forcerepub','force republication of previously published files').
                     &checkbox('obsolete','make file(s) obsolete').
     &checkbox('forceoverride','force directory level catalog information over existing').
     '<br /><input type="submit" value="'.&mt('Publish Directory').'" /></form>');
       } else {
   # actually publish things
    opendir(DIR,$fn);
    my @files=sort(readdir(DIR));
    foreach my $filename (@files) {
       my ($cdev,$cino,$cmode,$cnlink,
    $cuid,$cgid,$crdev,$csize,
    $catime,$cmtime,$cctime,
    $cblksize,$cblocks)=stat($fn.'/'.$filename);
       
       my $extension='';
       if ($filename=~/\.(\w+)$/) { $extension=$1; }
       if ($cmode&$dirptr) {
    if (($filename!~/^\./) && ($env{'form.pubrec'})) {
       &publishdirectory($r,$fn.'/'.$filename,$thisdisfn.'/'.$filename);
    }
       } elsif ((&Apache::loncommon::fileembstyle($extension) ne 'hdn') &&
        ($filename!~/^[\#\.]/) && ($filename!~/\~$/)) {
   # find out publication status and/or exiting metadata
    my $publishthis=0;
    if (-e $resdir.'/'.$filename) {
       my ($rdev,$rino,$rmode,$rnlink,
    $ruid,$rgid,$rrdev,$rsize,
    $ratime,$rmtime,$rctime,
    $rblksize,$rblocks)=stat($resdir.'/'.$filename);
       if (($rmtime<$cmtime) || ($env{'form.forcerepub'})) {
   # previously published, modified now
    $publishthis=1;
       }
       my $meta_cmtime = (stat($fn.'/'.$filename.'.meta'))[9];
       my $meta_rmtime = (stat($resdir.'/'.$filename.'.meta'))[9];
       if ( $meta_rmtime<$meta_cmtime ) {
    $publishthis=1;
       }
    } else {
   # never published
       $publishthis=1;
    }
   
    if ($publishthis) {
       &batchpublish($r,$fn.'/'.$filename,$resdir.'/'.$filename);
    } else {
       $r->print('<br />'.&mt('Skipping').' '.$filename.'<br />');
    }
    $r->rflush();
       }
    }
    closedir(DIR);
     }      }
   }
   
 # ------------------------------------------------ Provide link to new resource  #########################################
   # publish a default.meta file
     my $thisdistarget=$target;  
     $thisdistarget=~s/^$docroot//;  
   
     my $thissrc=$source;  sub defaultmetapublish {
     $thissrc=~s/^\/home\/(\w+)\/public_html/\/priv\/$1/;      my ($r,$fn,$cuname,$cudom)=@_;
       $fn=~s/^\/\~$cuname\//\/home\/$cuname\/public_html\//;
       unless (-e $fn) {
          return HTTP_NOT_FOUND;
       }
       my $target=$fn;
       $target=~s/^\/home\/$cuname\/public_html\//$Apache::lonnet::perlvar{'lonDocRoot'}\/res\/$cudom\/$cuname\//;
   
     my $thissrcdir=$thissrc;  
     $thissrcdir=~s/\/[^\/]+$/\//;  
   
       &Apache::loncommon::content_type($r,'text/html');
       $r->send_http_header;
   
     return $warning.$scrout.      $r->print(&Apache::loncommon::start_page('Catalog Information Publication'));
       '<hr><a href="'.$thisdistarget.'"><font size=+2>View Published Version</font></a>'.  
       '<p><a href="'.$thissrc.'"><font size=+2>Back to Source</font></a>'.  
       '<p><a href="'.$thissrcdir.  
       '"><font size=+2>Back to Source Directory</font></a>';  
   
 }  # ---------------------------------------------------------------- Write Source
       my $copyfile=$target;
       
       my @parts=split(/\//,$copyfile);
       my $path="/$parts[1]/$parts[2]/$parts[3]/$parts[4]";
       
       my $count;
       for ($count=5;$count<$#parts;$count++) {
           $path.="/$parts[$count]";
           if ((-e $path)!=1) {
               $r->print('<p>'.&mt('Created directory').' '.$parts[$count].'</p>');
               mkdir($path,0777);
           }
       }
       
       if (copy($fn,$copyfile)) {
           $r->print('<p>'.&mt('Copied source file').'</p>');
       } else {
           return "<span class=\"LC_error\">".
       &mt('Failed to copy source').", $!, ".&mt('FAIL')."</span>";
       }
   
   # --------------------------------------------------- Send update notifications
   
 #########################################      my @subscribed=&get_subscribed_hosts($target);
       foreach my $subhost (@subscribed) {
    $r->print('<p>'.&mt('Notifying host').' '.$subhost.':');$r->rflush;
    my $reply=&Apache::lonnet::critical('update:'.$target,$subhost);
    $r->print($reply.'</p><br />');$r->rflush;
       }
   # ------------------------------------------------------------------- Link back
       my $link=$fn;
       $link=~s/^\/home\/$cuname\/public_html\//\/priv\/$cuname\//;
       $r->print("<a href='$link'>".&mt('Back to Catalog Information').'</a>');
       $r->print(&Apache::loncommon::end_page());
       return OK;
   }
 #########################################  #########################################
   
 =pod  =pod
   
 =item handler  =item B<handler>
   
 A basic outline of the handler subroutine follows.  A basic outline of the handler subroutine follows.
   
 =over 4  =over 4
   
 =item Get query string for limited number of parameters  =item *
   
   Get query string for limited number of parameters.
   
   =item *
   
 =item Check filename  Check filename.
   
 =item File is there and owned, init lookup tables  =item *
   
 =item Start page output  File is there and owned, init lookup tables.
   
 =item Individual file  =item *
   
 =item publish from $thisfn to $thistarget with $thisembstyle  Start page output.
   
   =item *
   
   Evaluate individual file, and then output information.
   
   =item *
   
   Publishing from $thisfn to $thistarget with $thisembstyle.
   
 =back  =back
   
Line 1308  A basic outline of the handler subroutin Line 1960  A basic outline of the handler subroutin
 #########################################  #########################################
 #########################################  #########################################
 sub handler {  sub handler {
   my $r=shift;      my $r=shift;
   
   if ($r->header_only) {      if ($r->header_only) {
      $r->content_type('text/html');   &Apache::loncommon::content_type($r,'text/html');
      $r->send_http_header;   $r->send_http_header;
      return OK;   return OK;
   }      }
   
 # Get query string for limited number of parameters  # Get query string for limited number of parameters
   
     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},      &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
                                             ['filename']);                                              ['filename']);
   
   # -------------------------------------- Flag and buffer for registered cleanup
       $registered_cleanup=0;
       @{$modified_urls}=();
 # -------------------------------------------------------------- Check filename  # -------------------------------------------------------------- Check filename
   
   my $fn=$ENV{'form.filename'};      my $fn=&unescape($env{'form.filename'});
   
       ($cuname,$cudom)=
    &Apache::loncacc::constructaccess($fn,$r->dir_config('lonDefDomain'));
   
   # special publication: default.meta file
       if ($fn=~/\/default.meta$/) {
    return &defaultmetapublish($r,$fn,$cuname,$cudom); 
       }
       $fn=~s/\.meta$//;
       
   unless ($fn) {       unless ($fn) { 
      $r->log_reason($cuname.' at '.$cudom.   $r->log_reason($cuname.' at '.$cudom.
          ' trying to publish empty filename', $r->filename);          ' trying to publish empty filename', $r->filename); 
      return HTTP_NOT_FOUND;   return HTTP_NOT_FOUND;
   }       } 
   
   ($cuname,$cudom)=      unless (($cuname) && ($cudom)) {
     &Apache::loncacc::constructaccess($fn,$r->dir_config('lonDefDomain'));   $r->log_reason($cuname.' at '.$cudom.
   unless (($cuname) && ($cudom)) {         ' trying to publish file '.$env{'form.filename'}.
      $r->log_reason($cuname.' at '.$cudom.         ' ('.$fn.') - not authorized', 
          ' trying to publish file '.$ENV{'form.filename'}.         $r->filename); 
          ' ('.$fn.') - not authorized',    return HTTP_NOT_ACCEPTABLE;
          $r->filename);       }
      return HTTP_NOT_ACCEPTABLE;  
   }      my $home=&Apache::lonnet::homeserver($cuname,$cudom);
       my $allowed=0;
   unless (&Apache::lonnet::homeserver($cuname,$cudom)       my @ids=&Apache::lonnet::current_machine_ids();
           eq $r->dir_config('lonHostID')) {      foreach my $id (@ids) { if ($id eq $home) { $allowed = 1; }  }
      $r->log_reason($cuname.' at '.$cudom.      unless ($allowed) {
          ' trying to publish file '.$ENV{'form.filename'}.   $r->log_reason($cuname.' at '.$cudom.
          ' ('.$fn.') - not homeserver ('.         ' trying to publish file '.$env{'form.filename'}.
          &Apache::lonnet::homeserver($cuname,$cudom).')',          ' ('.$fn.') - not homeserver ('.$home.')', 
          $r->filename);          $r->filename); 
      return HTTP_NOT_ACCEPTABLE;   return HTTP_NOT_ACCEPTABLE;
   }      }
   
   $fn=~s/^http\:\/\/[^\/]+//;      $fn=~s{^http://[^/]+}{};
   $fn=~s/^\/\~(\w+)/\/home\/$1\/public_html/;      $fn=~s{^/~($match_username)}{/home/$1/public_html};
   
   my $targetdir='';      my $targetdir='';
   $docroot=$r->dir_config('lonDocRoot');       $docroot=$r->dir_config('lonDocRoot'); 
   if ($1 ne $cuname) {      if ($1 ne $cuname) {
      $r->log_reason($cuname.' at '.$cudom.   $r->log_reason($cuname.' at '.$cudom.
          ' trying to publish unowned file '.$ENV{'form.filename'}.         ' trying to publish unowned file '.
          ' ('.$fn.')',          $env{'form.filename'}.' ('.$fn.')', 
          $r->filename);          $r->filename); 
      return HTTP_NOT_ACCEPTABLE;   return HTTP_NOT_ACCEPTABLE;
   } else {      } else {
       $targetdir=$docroot.'/res/'.$cudom;   $targetdir=$docroot.'/res/'.$cudom;
   }      }
                                                                     
       
   unless (-e $fn) {       unless (-e $fn) { 
      $r->log_reason($cuname.' at '.$cudom.   $r->log_reason($cuname.' at '.$cudom.
          ' trying to publish non-existing file '.$ENV{'form.filename'}.         ' trying to publish non-existing file '.
          ' ('.$fn.')',          $env{'form.filename'}.' ('.$fn.')', 
          $r->filename);          $r->filename); 
      return HTTP_NOT_FOUND;   return HTTP_NOT_FOUND;
   }       } 
   
 unless ($ENV{'form.phase'} eq 'two') {  # -------------------------------- File is there and owned, init lookup tables.
   
 # --------------------------------- File is there and owned, init lookup tables      %addid=();
       
       {
    my $fh=Apache::File->new($r->dir_config('lonTabDir').'/addid.tab');
    while (<$fh>=~/(\w+)\s+(\w+)/) {
       $addid{$1}=$2;
    }
       }
   
   %addid=();      %nokey=();
   
   {      {
       my $fh=Apache::File->new($r->dir_config('lonTabDir').'/addid.tab');   my $fh=Apache::File->new($r->dir_config('lonIncludes').'/un_keyword.tab');
       while (<$fh>=~/(\w+)\s+(\w+)/) {   while (<$fh>) {
           $addid{$1}=$2;      my $word=$_;
       }      chomp($word);
   }      $nokey{$word}=1;
    }
       }
   
   %nokey=();  # ---------------------------------------------------------- Start page output.
   
   {      &Apache::loncommon::content_type($r,'text/html');
      my $fh=Apache::File->new($r->dir_config('lonIncludes').'/un_keyword.tab');      $r->send_http_header;
       while (<$fh>) {      
           my $word=$_;      my $js='<script type="text/javascript">'.
           chomp($word);   &Apache::loncommon::browser_and_searcher_javascript().
           $nokey{$word}=1;   '</script>';
       }      $r->print(&Apache::loncommon::start_page('Resource Publication',$js));
   }  
   
 }  
   
 # ----------------------------------------------------------- Start page output      my $thisfn=$fn;
   
   $r->content_type('text/html');      my $thistarget=$thisfn;
   $r->send_http_header;        
       $thistarget=~s/^\/home/$targetdir/;
       $thistarget=~s/\/public\_html//;
   
   $r->print('<html><head><title>LON-CAPA Publishing</title></head>');      my $thisdistarget=$thistarget;
   $r->print(      $thisdistarget=~s/^\Q$docroot\E//;
    '<body bgcolor="#FFFFFF"><img align=right src=/adm/lonIcons/lonlogos.gif>');  
   my $thisfn=$fn;  
      
 # ------------------------------------------------------------- Individual file  
   {  
       $thisfn=~/\.(\w+)$/;  
       my $thistype=$1;  
       my $thisembstyle=&Apache::loncommon::fileembstyle($thistype);  
   
       my $thistarget=$thisfn;      my $thisdisfn=$thisfn;
             $thisdisfn=~s/^\/home\/\Q$cuname\E\/public_html\///;
       $thistarget=~s/^\/home/$targetdir/;  
       $thistarget=~s/\/public\_html//;  
   
       my $thisdistarget=$thistarget;      if ($fn=~/\/$/) {
       $thisdistarget=~s/^$docroot//;  # -------------------------------------------------------- This is a directory
    &publishdirectory($r,$fn,$thisdisfn);
    $r->print('<hr /><a href="/priv/'
     .$cuname.'/'.$thisdisfn
     .'">'.&mt('Return to Directory').'</a>');
   
       my $thisdisfn=$thisfn;  
       $thisdisfn=~s/^\/home\/$cuname\/public_html\///;  
   
       $r->print('<h2>Publishing '.      } else {
         &Apache::loncommon::filedescription($thistype).' <tt>'.  # ---------------------- Evaluate individual file, and then output information.
         $thisdisfn.'</tt></h2><b>Target:</b> <tt>'.$thisdistarget.'</tt><p>');   $thisfn=~/\.(\w+)$/;
    my $thistype=$1;
    my $thisembstyle=&Apache::loncommon::fileembstyle($thistype);
           if ($thistype eq 'page') {  $thisembstyle = 'rat'; }
    $r->print('<h2>'.&mt('Publishing').' '.
     &Apache::loncommon::filedescription($thistype).' <tt>');
   
    $r->print(<<ENDCAPTION);
   <a href='javascript:void(window.open("/~$cuname/$thisdisfn","cat","height=300,width=500,scrollbars=1,resizable=1,menubar=0,location=1"))'>
   $thisdisfn</a>
   ENDCAPTION
           $r->print('</tt></h2><b>'.&mt('Target').':</b> <tt>'.
     $thisdistarget.'</tt><br />');
         
        if (($cuname ne $ENV{'user.name'}) || ($cudom ne $ENV{'user.domain'})) {   if (($cuname ne $env{'user.name'})||($cudom ne $env{'user.domain'})) {
           $r->print('<h3><font color=red>Co-Author: '.$cuname.' at '.$cudom.      $r->print('<h3><font color="red">'.&mt('Co-Author').': '.
                '</font></h3>');        $cuname.&mt(' at ').$cudom.'</font></h3>');
       }   }
   
       if (&Apache::loncommon::fileembstyle($thistype) eq 'ssi') {  
           $r->print('<br><a href="/adm/diff?filename=/~'.$cuname.'/'.  
                     $thisdisfn.  
    '&versionone=priv" target=cat>Diffs with Current Version</a><p>');  
       }  
     
 # ------------ We are publishing from $thisfn to $thistarget with $thisembstyle  
   
        unless ($ENV{'form.phase'} eq 'two') {   if (&Apache::loncommon::fileembstyle($thistype) eq 'ssi') {
          $r->print(      $r->print(<<ENDDIFF);
           '<hr>'.&publish($thisfn,$thistarget,$thisembstyle));  <br />
        } else {  <a href='javascript:void(window.open("/adm/diff?filename=/~$cuname/$thisdisfn&versiontwo=priv","cat","height=300,width=500,scrollbars=1,resizable=1,menubar=0,location=1"))'>
          $r->print(  ENDDIFF
           '<hr>'.&phasetwo($thisfn,$thistarget,$thisembstyle,$thisdistarget));               $r->print(&mt('Diffs with Current Version').'</a><br />');
        }     }
     
   # ------------------ Publishing from $thisfn to $thistarget with $thisembstyle.
   
   }   unless ($env{'form.phase'} eq 'two') {
   $r->print('</body></html>');  # ---------------------------------------------------------- Parse for problems
       my ($warningcount,$errorcount);
       if ($thisembstyle eq 'ssi') {
    ($warningcount,$errorcount)=&checkonthis($r,$thisfn);
       }
       unless ($errorcount) {
    my ($outstring,$error)=
       &publish($thisfn,$thistarget,$thisembstyle);
    $r->print('<hr />'.$outstring);
       } else {
    $r->print('<h3>'.
     &mt('The document contains errors and cannot be published.').
     '</h3>');
       }
    } else {
       &phasetwo($r,$thisfn,$thistarget,$thisembstyle,$thisdistarget); 
       $r->print('<hr />');
    }
       }
       $r->print(&Apache::loncommon::end_page());
   
   return OK;      return OK;
 }  }
   
 1;  1;
Line 1467  __END__ Line 2156  __END__
   
 =back  =back
   
   =back
   
 =cut  =cut
   

Removed from v.1.93  
changed lines
  Added in v.1.232


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