Diff for /loncom/publisher/lonpublisher.pm between versions 1.87 and 1.109

version 1.87, 2002/08/07 19:50:22 version 1.109, 2003/02/18 13:20:13
Line 33 Line 33
 # 11/28,11/29,11/30,12/01,12/02,12/04,12/23 Gerd Kortemeyer  # 11/28,11/29,11/30,12/01,12/02,12/04,12/23 Gerd Kortemeyer
 # 03/23 Guy Albertelli  # 03/23 Guy Albertelli
 # 03/24,03/29,04/03 Gerd Kortemeyer  # 03/24,03/29,04/03 Gerd Kortemeyer
 # 04/16/2001 Scott Harrison  
 # 05/03,05/05,05/07 Gerd Kortemeyer  # 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  # 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/04,12/05 Guy Albertelli
 # 12/05 Gerd Kortemeyer  # 12/05 Gerd Kortemeyer
 # 12/05 Guy Albertelli  # 12/05 Guy Albertelli
 # 12/06,12/07 Gerd Kortemeyer  # 12/06,12/07 Gerd Kortemeyer
 # 12/15,12/16 Scott Harrison  
 # 12/25 Gerd Kortemeyer  # 12/25 Gerd Kortemeyer
 # YEAR=2002  # YEAR=2002
 # 1/16,1/17 Scott Harrison  
 # 1/17 Gerd Kortemeyer  # 1/17 Gerd Kortemeyer
 #  #
 ###  ###
Line 61 Line 57
 ##                                                                           ##  ##                                                                           ##
 ###############################################################################  ###############################################################################
   
   
   ######################################################################
   ######################################################################
   
   =pod 
   
   =head1 NAME
   
   lonpublisher - LON-CAPA publishing handler
   
   =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 DESCRIPTION
   
   B<lonpublisher> takes the proper steps to add resources to the LON-CAPA
   digital library.  This includes updating the metadata table in the
   LON-CAPA database.
   
   B<lonpublisher> is many things to many people.  
   
   This module publishes a file.  This involves gathering metadata,
   versioning the file, copying file from construction space to
   publication space, and copying metadata from construction space
   to publication space.
   
   =head2 SUBROUTINES
   
   Many of the undocumented subroutines implement various magical
   parsing shortcuts.
   
   =over 4
   
   =cut
   
   ######################################################################
   ######################################################################
   
   
 package Apache::lonpublisher;  package Apache::lonpublisher;
   
 # ------------------------------------------------- modules used by this module  # ------------------------------------------------- modules used by this module
Line 75  use Apache::loncacc; Line 122  use Apache::loncacc;
 use DBI;  use DBI;
 use Apache::lonnet();  use Apache::lonnet();
 use Apache::loncommon();  use Apache::loncommon();
   use Apache::lonmysql;
   use vars qw(%metadatafields %metadatakeys);
   
 my %addid;  my %addid;
 my %nokey;  my %nokey;
   
 my %metadatafields;  
 my %metadatakeys;  
   
 my $docroot;  my $docroot;
   
 my $cuname;  my $cuname;
 my $cudom;  my $cudom;
   
 # ----------------------------------------------- Evaluate string with metadata  =pod
   
   =item B<metaeval>
   
   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
   
   #########################################
   #########################################
 sub metaeval {  sub metaeval {
     my $metastring=shift;      my $metastring=shift;
         
Line 130  sub metaeval { Line 202  sub metaeval {
        }         }
 }  }
   
 # -------------------------------------------------------- Read a metadata file  #########################################
   #########################################
   
   =pod
   
   =item B<metaread>
   
   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
   
   #########################################
   #########################################
 sub metaread {  sub metaread {
     my ($logfile,$fn)=@_;      my ($logfile,$fn)=@_;
     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>No file:</b> <tt>'.$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);
Line 147  sub metaread { Line 255  sub metaread {
     return '<br><b>Processed file:</b> <tt>'.$fn.'</tt>';      return '<br><b>Processed file:</b> <tt>'.$fn.'</tt>';
 }  }
   
 # ---------------------------- convert 'time' format into a datetime sql format  #########################################
 sub sqltime {  #########################################
     my $timef=shift @_;  
     my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =  sub coursedependencies {
  localtime($timef);      my $url=&Apache::lonnet::declutter(shift);
     $mon++; $year+=1900;      $url=~s/\.meta$//;
     return "$year-$mon-$mday $hour:$min:$sec";      my ($adomain,$aauthor)=($url=~/^(\w+)\/(\w+)\//);
       my $regexp=$url;
       $regexp=~s/(\W)/\\$1/g;
       $regexp='___'.$regexp.'___course';
       my %evaldata=&Apache::lonnet::dump('nohist_resevaldata',$adomain,
          $aauthor,$regexp);
       my %courses=();
       foreach (keys %evaldata) {
    if ($_=~/^([a-zA-Z0-9]+_[a-zA-Z0-9]+)___.+___course$/) {
       $courses{$1}=1;
           }
       }
       return %courses;
 }  }
   #########################################
   #########################################
   
   
   =pod
   
 # --------------------------------------------------------- Various form fields  =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
   
   =item B<textfield>
   
   =item B<hiddenfield>
   
   =item B<selectbox>
   
   =back
   
   =cut
   
   #########################################
   #########################################
 sub textfield {  sub textfield {
     my ($title,$name,$value)=@_;      my ($title,$name,$value)=@_;
     return "\n<p><b>$title:</b><br>".      return "\n<p><b>$title:</b><br>".
            '<input type=text name="'.$name.'" size=80 value="'.$value.'">';             '<input type="text" name="'.$name.'" size=80 value="'.$value.'" />';
 }  }
   
 sub hiddenfield {  sub hiddenfield {
     my ($name,$value)=@_;      my ($name,$value)=@_;
     return "\n".'<input type=hidden name="'.$name.'" value="'.$value.'">';      return "\n".'<input type="hidden" name="'.$name.'" value="'.$value.'" />';
 }  }
   
 sub selectbox {  sub selectbox {
Line 184  sub selectbox { Line 329  sub selectbox {
     return $selout.'</select>';      return $selout.'</select>';
 }  }
   
 # -------------------------------------------------------- Publication Step One  #########################################
   #########################################
   
   =pod
   
   =item B<urlfixup>
   
   Fix up a url?  First step of publication
   
   =cut
   
   #########################################
   #########################################
 sub urlfixup {  sub urlfixup {
     my ($url,$target)=@_;      my ($url,$target)=@_;
     unless ($url) { return ''; }      unless ($url) { return ''; }
Line 206  sub urlfixup { Line 362  sub urlfixup {
     return $url;      return $url;
 }  }
   
   #########################################
   #########################################
   
   =pod
   
   =item B<absoluteurl>
   
   Currently undocumented.
   
   =cut
   
   #########################################
   #########################################
 sub absoluteurl {  sub absoluteurl {
     my ($url,$target)=@_;      my ($url,$target)=@_;
     unless ($url) { return ''; }      unless ($url) { return ''; }
Line 217  sub absoluteurl { Line 385  sub absoluteurl {
     return $url;      return $url;
 }  }
   
   #########################################
   #########################################
   
   =pod
   
   =item B<set_allow>
   
   Currently undocumented    
   
   =cut
   
   #########################################
   #########################################
 sub set_allow {  sub set_allow {
     my ($allow,$logfile,$target,$tag,$oldurl)=@_;      my ($allow,$logfile,$target,$tag,$oldurl)=@_;
     my $newurl=&urlfixup($oldurl,$target);      my $newurl=&urlfixup($oldurl,$target);
Line 235  sub set_allow { Line 416  sub set_allow {
     return $return_url      return $return_url
 }  }
   
   #########################################
   #########################################
   
   =pod
   
   =item B<get_subscribed_hosts>
   
   Currently undocumented    
   
   =cut
   
   #########################################
   #########################################
 sub get_subscribed_hosts {  sub get_subscribed_hosts {
     my ($target)=@_;      my ($target)=@_;
     my @subscribed;      my @subscribed;
Line 245  sub get_subscribed_hosts { Line 439  sub get_subscribed_hosts {
     while ($filename=readdir(DIR)) {      while ($filename=readdir(DIR)) {
  if ($filename=~/$srcf\.(\w+)$/) {   if ($filename=~/$srcf\.(\w+)$/) {
     my $subhost=$1;      my $subhost=$1;
     if ($subhost ne 'meta' && $subhost ne 'subscription') {      if (($subhost ne 'meta' && $subhost ne 'subscription') &&
                   ($subhost ne $Apache::lonnet::perlvar{'lonHostID'})) {
  push(@subscribed,$subhost);   push(@subscribed,$subhost);
     }      }
  }   }
Line 256  sub get_subscribed_hosts { Line 451  sub get_subscribed_hosts {
  &Apache::lonnet::logthis("opened $target.subscription");   &Apache::lonnet::logthis("opened $target.subscription");
  while (my $subline=<$sh>) {   while (my $subline=<$sh>) {
     &Apache::lonnet::logthis("Trying $subline");      &Apache::lonnet::logthis("Trying $subline");
     if ($subline =~ /(^\w+):/) { push(@subscribed,$1); } else {      if ($subline =~ /(^\w+):/) { 
                   if ($1 ne $Apache::lonnet::perlvar{'lonHostID'}) { 
                      push(@subscribed,$1);
           }
               } else {
  &Apache::lonnet::logthis("No Match for $subline");   &Apache::lonnet::logthis("No Match for $subline");
     }      }
  }   }
     } else {      } else {
  &Apache::lonnet::logthis("Un able to open $target.subscription");   &Apache::lonnet::logthis("Unable to open $target.subscription");
     }      }
     &Apache::lonnet::logthis("Got list of ".join(':',@subscribed));  
     return @subscribed;      return @subscribed;
 }  }
   
   
   #########################################
   #########################################
   
   =pod
   
   =item B<get_max_ids_indices>
   
   Currently undocumented    
   
   =cut
   
   #########################################
   #########################################
 sub get_max_ids_indices {  sub get_max_ids_indices {
     my ($content)=@_;      my ($content)=@_;
     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);
     my $token;      my $token;
Line 283  sub get_max_ids_indices { Line 498  sub get_max_ids_indices {
  if ($counter eq 'id') {   if ($counter eq 'id') {
     if (defined($token->[2]->{'id'})) {      if (defined($token->[2]->{'id'})) {
  $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;
     }      }
Line 296  sub get_max_ids_indices { Line 517  sub get_max_ids_indices {
     }      }
  }   }
     }      }
     return ($needsfixup,$maxid,$maxindex);      return ($needsfixup,$maxid,$maxindex,$duplicateids,
       (keys(%duplicatedids)));
 }  }
   
   #########################################
   #########################################
   
   =pod
   
   =item B<get_all_text_unbalanced>
   
   Currently undocumented    
   
   =cut
   
   #########################################
   #########################################
 sub get_all_text_unbalanced {  sub get_all_text_unbalanced {
     #there is a copy of this in lonxml.pm      #there is a copy of this in lonxml.pm
     my($tag,$pars)= @_;      my($tag,$pars)= @_;
Line 315  sub get_all_text_unbalanced { Line 550  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) {
     &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;      $result=$1;
     my $redo=$tag.$2;      my $redo=$tag.$2;
     push (@$pars,HTML::LCParser->new(\$redo));      push (@$pars,HTML::LCParser->new(\$redo));
Line 328  sub get_all_text_unbalanced { Line 563  sub get_all_text_unbalanced {
     return $result      return $result
 }  }
   
   #########################################
   #########################################
   
   =pod
   
   =item B<fix_ids_and_indices>
   
   Currently undocumented    
   
   =cut
   
   #########################################
   #########################################
 #Arguably this should all be done as a lonnet::ssi instead  #Arguably this should all be done as a lonnet::ssi instead
 sub fix_ids_and_indices {  sub fix_ids_and_indices {
     my ($logfile,$source,$target)=@_;      my ($logfile,$source,$target)=@_;
Line 339  sub fix_ids_and_indices { Line 587  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='<font color="red">Unable to publish file, it contains duplicated ID(s), ID(s) need to be unique. The duplicated ID(s) are: '.join(', ',@duplicatedids).'</font>';
    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 381  sub fix_ids_and_indices { Line 637  sub fix_ids_and_indices {
  }   }
  foreach my $type ('src','href','background','bgimg') {   foreach my $type ('src','href','background','bgimg') {
     foreach my $key (keys(%parms)) {      foreach my $key (keys(%parms)) {
  print $logfile "for $type, and $key\n";  
  if ($key =~ /^$type$/i) {   if ($key =~ /^$type$/i) {
     print $logfile "calling set_allow\n";  
     $parms{$key}=&set_allow(\%allow,$logfile,      $parms{$key}=&set_allow(\%allow,$logfile,
     $target,$tag,      $target,$tag,
     $parms{$key});      $parms{$key});
Line 466  sub fix_ids_and_indices { Line 720  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);
 }  }
   
   #########################################
   #########################################
   
   =pod
   
   =item B<store_metadata>
   
   Store the metadata in the metadata table in the loncapa database.
   Uses lonmysql to access the database.
   
   Inputs: \%metadata
   
   Returns: (error,status).  error is undef on success, status is undef on error.
   
   =cut
   
   #########################################
   #########################################
   sub store_metadata {
       my %metadata = %{shift()};
       my $error;
       # Determine if the table exists
       my $status = &Apache::lonmysql::check_table('metadata');
       if (! defined($status)) {
           $error='<font color="red">WARNING: Cannot connect to '.
               'database!</font>';
           &Apache::lonnet::logthis($error);
           return ($error,undef);
       }
       if ($status == 0) {
           # It would be nice to actually create the table....
           $error ='<font color="red">WARNING: The metadata table does not '.
               'exist in the LON-CAPA database.</font>';
           &Apache::lonnet::logthis($error);
           return ($error,undef);
       }
       # Remove old value from table
       $status = &Apache::lonmysql::remove_from_table
           ('metadata','url',$metadata{'url'});
       if (! defined($status)) {
           $error = '<font color="red">Error when removing old values from '.
               'metadata table in LON-CAPA database.</font>';
           &Apache::lonnet::logthis($error);
           return ($error,undef);
       }
       # Store data in table.
       $status = &Apache::lonmysql::store_row('metadata',\%metadata);
       if (! defined($status)) {
           $error='<font color="red">Error occured storing new values in '.
               'metadata table in LON-CAPA database</font>';
           &Apache::lonnet::logthis($error);
           return ($error,undef);
       }
       return (undef,$status);
   }
   
   #########################################
   #########################################
   
   =pod
   
   =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),
   
   I<Additional documentation needed.>
   
   =cut
   
   #########################################
   #########################################
 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 498  sub publish { Line 825  sub publish {
         }          }
 # ------------------------------------------------------------- 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; }
 # ------------------------------------------------------------ Construct Allows  # ------------------------------------------------------------ Construct Allows
           
  $scrout.='<h3>Dependencies</h3>';   $scrout.='<h3>Dependencies</h3>';
Line 520  sub publish { Line 849  sub publish {
                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.= ' - <font color="red">Currently not available'.
                            ' - <font color=red>Currently not available</font>';         '</font>';
                } 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=~/^\/res\/(\w+)\/(\w+)\//;
                    if ((defined($1)) && (defined($2))) {                     if ((defined($1)) && (defined($2))) {
                       &Apache::lonnet::put('resevaldata',\%temphash,$1,$2);                        &Apache::lonnet::put('nohist_resevaldata',\%temphash,
      $1,$2);
    }     }
        }         }
            }             }
Line 537  sub publish { Line 867  sub publish {
   
  #Encode any High ASCII characters   #Encode any High ASCII characters
  $outstring=&HTML::Entities::encode($outstring,"\200-\377");   $outstring=&HTML::Entities::encode($outstring,"\200-\377");
 # ------------------------------------------------------------- Write modified  # ------------------------------------------------------------- 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 
               "<font color=red>No write permission to $source, FAIL</font>";   '<font color="red">No write permission to '.$source.
    ', FAIL</font>';
   }    }
           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.
   
      %metadatafields=();       %metadatafields=();
      %metadatakeys=();       %metadatakeys=();
             
      my %oldparmstores=();       my %oldparmstores=();
             
            unless ($batch) {
      $scrout.='<h3>Metadata Information ' .       $scrout.='<h3>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') {       unless (-e $source.'.meta') {
Line 657  sub publish { Line 989  sub publish {
   
 # ------------------------------------------------------- Now have all metadata  # ------------------------------------------------------- Now have all metadata
   
           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 (split(/\W+/,$metadatafields{'keywords'})) {
    $keywords{$_}=1;
               }
   # --------------------------------------------------- Now we also have keywords
   # =============================================================================
   # INTERACTIVE MODE
   #
      unless ($batch) {
         $scrout.=          $scrout.=
      '<form name="pubform" action="/adm/publish" method="post">'.       '<form name="pubform" action="/adm/publish" method="post">'.
        '<p><input type="submit" value="Finalize Publication" /></p>'.         '<p><input type="submit" value="Finalize Publication" /></p>'.
Line 692  function uncheckAll(field) Line 1051  function uncheckAll(field)
 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 (split(/\W+/,$metadatafields{'keywords'})) {  
  $keywords{$_}=1;  
             }  
   
             foreach (sort keys %keywords) {              foreach (sort keys %keywords) {
                 $keywordout.='<td><input type=checkbox name="keywords" value="'.$_.'"';                  $keywordout.='<td><input type=checkbox name="keywords" value="'.$_.'"';
Line 757  END Line 1094  END
         unless ($metadatafields{'creationdate'}) {          unless ($metadatafields{'creationdate'}) {
     $metadatafields{'creationdate'}=time;      $metadatafields{'creationdate'}=time;
         }          }
         $scrout.=&hiddenfield('creationdate',$metadatafields{'creationdate'});          $scrout.=&hiddenfield('creationdate',
                 &Apache::loncommon::unsqltime($metadatafields{'creationdate'}));
   
         $scrout.=&hiddenfield('lastrevisiondate',time);          $scrout.=&hiddenfield('lastrevisiondate',time);
   
         
  $scrout.=&textfield('Publisher/Owner','owner',   $scrout.=&textfield('Publisher/Owner','owner',
                             $metadatafields{'owner'});                              $metadatafields{'owner'});
 # --------------------------------------------------- Correct copyright for rat          
   
   # -------------------------------------------------- Correct copyright for rat.
     if ($style eq 'rat') {      if ($style eq 'rat') {
  if ($metadatafields{'copyright'} eq 'public') {    if ($metadatafields{'copyright'} eq 'public') { 
     delete $metadatafields{'copyright'};      delete $metadatafields{'copyright'};
Line 782  END Line 1120  END
      (&Apache::loncommon::copyrightids));       (&Apache::loncommon::copyrightids));
     }      }
   
     my $copyright_help = Apache::loncommon::help_open_topic("Publishing_Copyright");      my $copyright_help =
           Apache::loncommon::help_open_topic('Publishing_Copyright');
     $scrout =~ s/DISTRIBUTION:/'DISTRIBUTION: ' . $copyright_help/ge;      $scrout =~ s/DISTRIBUTION:/'DISTRIBUTION: ' . $copyright_help/ge;
     return $scrout.      return $scrout.
       '<p><input type="submit" value="Finalize Publication" /></p></form>';          '<p><input type="submit" value="Finalize Publication" /></p></form>';
   # =============================================================================
   # BATCH MODE
   #
     } else {
   # Transfer metadata directly to environment for stage 2
       foreach (keys %metadatafields) {
    $ENV{'form.'.$_}=$metadatafields{$_};
       }
       $ENV{'form.addkey'}='';
       $ENV{'form.keywords'}='';
       foreach (keys %keywords) {
           if ($metadatafields{'keywords'}) {
              if ($metadatafields{'keywords'}=~/$_/) { 
                 $ENV{'form.keywords'}.=$_.','; 
              }
    } elsif (&Apache::loncommon::keyword($_)) {
       $ENV{'form.keywords'}.=$_.',';
           } 
       }
       $ENV{'form.keywords'}=~s/\,$//;
       unless ($ENV{'form.creationdate'}) { $ENV{'form.creationdate'}=time; }
       $ENV{'form.lastrevisiondate'}=time;
       if ((($style eq 'rat') && ($ENV{'form.copyright'} eq 'public')) ||
           (!$ENV{'form.copyright'})) { 
    $ENV{'form.copyright'}='default';
       } 
       $ENV{'form.allmeta'}=&Apache::lonnet::escape($allmeta);
       return $scrout;
     }
 }  }
   
 # -------------------------------------------------------- Publication Step Two  #########################################
   #########################################
   
 sub phasetwo {  =pod 
   
     my ($source,$target,$style,$distarget)=@_;  =item B<phasetwo>
     my $logfile;  
     my $scrout='';  
     unless ($logfile=Apache::File->new('>>'.$source.'.log')) {  
  return   
          '<font color=red>No write permission to user directory, FAIL</font>';  
     }  
     print $logfile   
 "\n================= Publish ".localtime()." Phase Two  ================\n";  
   
      %metadatafields=();  Render second interface showing status of publication steps.
      %metadatakeys=();  This is publication step two.
   
      &metaeval(&Apache::lonnet::unescape($ENV{'form.allmeta'}));  Parameters:
   
      $metadatafields{'title'}=$ENV{'form.title'};  =over 4
      $metadatafields{'author'}=$ENV{'form.author'};  
      $metadatafields{'subject'}=$ENV{'form.subject'};  
      $metadatafields{'notes'}=$ENV{'form.notes'};  
      $metadatafields{'abstract'}=$ENV{'form.abstract'};  
      $metadatafields{'mime'}=$ENV{'form.mime'};  
      $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{'dependencies'}=$ENV{'form.dependencies'};  
   
      my $allkeywords=$ENV{'form.addkey'};  
      if (exists($ENV{'form.keywords'}) && (ref($ENV{'form.keywords'}))) {  
          my @Keywords = @{$ENV{'form.keywords'}};  
          foreach (@Keywords) {  
              $allkeywords.=','.$_;  
          }  
      }  
      $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  =item I<$source>
   my $warning;  
   
   unless ($metadatafields{'copyright'} eq 'priv') {  =item I<$target>
   
   =item I<$style>
   
   =item I<$distarget>
   
   =back
   
   Returns:
   
   =over 4
   
   =item Scalar string
   
   String contains status (errors and warnings) and information associated with
   the server's attempts at publication.     
   
   =cut
   
   #'stupid emacs
   #########################################
   #########################################
   sub phasetwo {
   
     my $dbh;      my ($r,$source,$target,$style,$distarget,$batch)=@_;
       $source=~s/\/+/\//g;
       $target=~s/\/+/\//g;
   
       if ($target=~/\_\_\_/) {
    return 
    '<font color=red>Unsupported character combination "<tt>___</tt>" in filename, FAIL</font>';
       }
       $distarget=~s/\/+/\//g;
       my $logfile;
       unless ($logfile=Apache::File->new('>>'.$source.'.log')) {
    return 
               '<font color=red>No write permission to user directory, FAIL</font>';
       }
       print $logfile 
           "\n================= Publish ".localtime()." Phase Two  ================\n";
       
       %metadatafields=();
       %metadatakeys=();
       
       &metaeval(&Apache::lonnet::unescape($ENV{'form.allmeta'}));
       
       $metadatafields{'title'}=$ENV{'form.title'};
       $metadatafields{'author'}=$ENV{'form.author'};
       $metadatafields{'subject'}=$ENV{'form.subject'};
       $metadatafields{'notes'}=$ENV{'form.notes'};
       $metadatafields{'abstract'}=$ENV{'form.abstract'};
       $metadatafields{'mime'}=$ENV{'form.mime'};
       $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{'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;
       
     {      {
  unless (          print $logfile "\nWrite metadata file for ".$source;
  $dbh = DBI->connect("DBI:mysql:loncapa","www",          my $mfh;
     $Apache::lonnet::perlvar{'lonSqlAccess'},{ RaiseError =>0,PrintError=>0})          unless ($mfh=Apache::File->new('>'.$source.'.meta')) {
  ) {               return 
     $warning='<font color=red>WARNING: Cannot connect to '.                  '<font color=red>Could not write metadata, FAIL</font>';
  'database!</font>';          }
  }          foreach (sort keys %metadatafields) {
  else {              unless ($_=~/\./) {
     my %sqldatafields;                  my $unikey=$_;
     $sqldatafields{'url'}=$distarget;                  $unikey=~/^([A-Za-z]+)/;
     my $sth=$dbh->prepare(                  my $tag=$1;
   'delete from metadata where url like binary'.                  $tag=~tr/A-Z/a-z/;
   '"'.$sqldatafields{'url'}.'"');                  print $mfh "\n\<$tag";
     $sth->execute();                  foreach (split(/\,/,$metadatakeys{$unikey})) {
     foreach ('title','author','subject','keywords','notes','abstract',                      my $value=$metadatafields{$unikey.'.'.$_};
      'mime','language','creationdate','lastrevisiondate','owner',                      $value=~s/\"/\'\'/g;
      'copyright') {                      print $mfh ' '.$_.'="'.$value.'"';
  my $field=$metadatafields{$_}; $field=~s/\"/\'\'/g;                   }
  $sqldatafields{$_}=$field;                  print $mfh '>'.
     }                      &HTML::Entities::encode($metadatafields{$unikey})
                               .'</'.$tag.'>';
     $sth=$dbh->prepare('insert into metadata values ('.              }
        '"'.delete($sqldatafields{'title'}).'"'.','.          }
        '"'.delete($sqldatafields{'author'}).'"'.','.          $r->print('<p>Wrote Metadata');
        '"'.delete($sqldatafields{'subject'}).'"'.','.          print $logfile "\nWrote metadata";
        '"'.delete($sqldatafields{'url'}).'"'.','.  
        '"'.delete($sqldatafields{'keywords'}).'"'.','.  
        '"'.'current'.'"'.','.  
        '"'.delete($sqldatafields{'notes'}).'"'.','.  
        '"'.delete($sqldatafields{'abstract'}).'"'.','.  
        '"'.delete($sqldatafields{'mime'}).'"'.','.  
        '"'.delete($sqldatafields{'language'}).'"'.','.  
        '"'.  
        sqltime(delete($sqldatafields{'creationdate'}))  
        .'"'.','.  
        '"'.  
        sqltime(delete(  
        $sqldatafields{'lastrevisiondate'})).'"'.','.  
        '"'.delete($sqldatafields{'owner'}).'"'.','.  
        '"'.delete(  
        $sqldatafields{'copyright'}).'"'.')');  
     $sth->execute();  
     $dbh->disconnect;  
     $scrout.='<p>Synchronized SQL metadata database';  
     print $logfile "\nSynchronized SQL metadata database";  
  }  
     }      }
       
   # -------------------------------- Synchronize entry with SQL metadata database
   
 } else {      $metadatafields{'url'} = $distarget;
     $scrout.='<p>Private Publication - did not synchronize database';      $metadatafields{'version'} = 'current';
     print $logfile "\nPrivate: Did not synchronize data into ".      unless ($metadatafields{'copyright'} eq 'priv') {
  "SQL metadata database";          my ($error,$success) = &store_metadata(\%metadatafields);
 }          if ($success) {
               $r->print('<p>Synchronized SQL metadata database');
               print $logfile "\nSynchronized SQL metadata database";
           } else {
               $r->print($error);
               print $logfile "\n".$error;
           }
       } else {
           $r->print('<p>Private Publication - did not synchronize database');
           print $logfile "\nPrivate: Did not synchronize data into ".
               "SQL metadata database";
       }
 # ----------------------------------------------------------- Copy old versions  # ----------------------------------------------------------- Copy old versions
         
 if (-e $target) {      if (-e $target) {
     my $filename;          my $filename;
     my $maxversion=0;          my $maxversion=0;
     $target=~/(.*)\/([^\/]+)\.(\w+)$/;          $target=~/(.*)\/([^\/]+)\.(\w+)$/;
     my $srcf=$2;          my $srcf=$2;
     my $srct=$3;          my $srct=$3;
     my $srcd=$1;          my $srcd=$1;
     unless ($srcd=~/^\/home\/httpd\/html\/res/) {          unless ($srcd=~/^\/home\/httpd\/html\/res/) {
  print $logfile "\nPANIC: Target dir is ".$srcd;              print $logfile "\nPANIC: Target dir is ".$srcd;
         return "<font color=red>Invalid target directory, FAIL</font>";              return "<font color=red>Invalid target directory, FAIL</font>";
     }          }
     opendir(DIR,$srcd);          opendir(DIR,$srcd);
     while ($filename=readdir(DIR)) {          while ($filename=readdir(DIR)) {
        if ($filename=~/$srcf\.(\d+)\.$srct$/) {              if (-l $srcd.'/'.$filename) {
    $maxversion=($1>$maxversion)?$1:$maxversion;                  unlink($srcd.'/'.$filename);
        }                  unlink($srcd.'/'.$filename.'.meta');
     }              } else {
     closedir(DIR);                  if ($filename=~/$srcf\.(\d+)\.$srct$/) {
     $maxversion++;                      $maxversion=($1>$maxversion)?$1:$maxversion;
     $scrout.='<p>Creating old version '.$maxversion;                  }
     print $logfile "\nCreating old version ".$maxversion;              }
           }
     my $copyfile=$srcd.'/'.$srcf.'.'.$maxversion.'.'.$srct;          closedir(DIR);
           $maxversion++;
           $r->print('<p>Creating old version '.$maxversion);
           print $logfile "\nCreating old version ".$maxversion;
           
           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>Copied old target file');
         } 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>";              return "<font color=red>Failed to copy old target, $!, FAIL</font>";
         }          }
           
 # --------------------------------------------------------------- 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>Copied old metadata')
         } 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                   return 
        "<font color=red>Failed to write old metadata copy, $!, FAIL</font>";                      "<font color=red>Failed to write old metadata copy, $!, FAIL</font>";
     }      }
         }          }
           
           
 } else {      } else {
     $scrout.='<p>Initial version';          $r->print('<p>Initial version');
     print $logfile "\nInitial version";          print $logfile "\nInitial version";
 }      }
   
 # ---------------------------------------------------------------- Write Source  # ---------------------------------------------------------------- Write Source
  my $copyfile=$target;      my $copyfile=$target;
       
            my @parts=split(/\//,$copyfile);      my @parts=split(/\//,$copyfile);
            my $path="/$parts[1]/$parts[2]/$parts[3]/$parts[4]";      my $path="/$parts[1]/$parts[2]/$parts[3]/$parts[4]";
       
            my $count;      my $count;
            for ($count=5;$count<$#parts;$count++) {      for ($count=5;$count<$#parts;$count++) {
                $path.="/$parts[$count]";          $path.="/$parts[$count]";
                if ((-e $path)!=1) {          if ((-e $path)!=1) {
                    print $logfile "\nCreating directory ".$path;              print $logfile "\nCreating directory ".$path;
                    $scrout.='<p>Created directory '.$parts[$count];              $r->print('<p>Created directory '.$parts[$count]);
    mkdir($path,0777);              mkdir($path,0777);
                }  
            }  
   
         if (copy($source,$copyfile)) {  
     print $logfile "Copied original source to ".$copyfile."\n";  
             $scrout.='<p>Copied source file';  
         } else {  
     print $logfile "Unable to write ".$copyfile.':'.$!."\n";  
             return "<font color=red>Failed to copy source, $!, FAIL</font>";  
         }          }
       }
       
       if (copy($source,$copyfile)) {
           print $logfile "\nCopied original source to ".$copyfile."\n";
           $r->print('<p>Copied source file');
       } else {
           print $logfile "\nUnable to write ".$copyfile.':'.$!."\n";
           return "<font color=red>Failed to copy source, $!, FAIL</font>";
       }
       
 # --------------------------------------------------------------- Copy Metadata  # --------------------------------------------------------------- Copy Metadata
   
         $copyfile=$copyfile.'.meta';      $copyfile=$copyfile.'.meta';
       
         if (copy($source.'.meta',$copyfile)) {      if (copy($source.'.meta',$copyfile)) {
     print $logfile "Copied original metadata to ".$copyfile."\n";          print $logfile "\nCopied original metadata to ".$copyfile."\n";
             $scrout.='<p>Copied metadata';          $r->print('<p>Copied metadata');
         } else {      } else {
     print $logfile "Unable to write metadata ".$copyfile.':'.$!."\n";          print $logfile "\nUnable to write metadata ".$copyfile.':'.$!."\n";
             return           return 
           "<font color=red>Failed to write metadata copy, $!, FAIL</font>";              "<font color=red>Failed to write metadata copy, $!, FAIL</font>";
         }      }
       $r->rflush;
 # --------------------------------------------------- Send update notifications  # --------------------------------------------------- Send update notifications
   
     my @subscribed=&get_subscribed_hosts($target);      my @subscribed=&get_subscribed_hosts($target);
     foreach my $subhost (@subscribed) {      foreach my $subhost (@subscribed) {
  $scrout.='<p>Notifying host '.$subhost.':';   $r->print('<p>Notifying host '.$subhost.':');$r->rflush;
  print $logfile "\nNotifying host ".$subhost.':';   print $logfile "\nNotifying host ".$subhost.':';
  my $reply=&Apache::lonnet::critical('update:'.$target,$subhost);   my $reply=&Apache::lonnet::critical('update:'.$target,$subhost);
  $scrout.=$reply;   $r->print($reply.'<br />');$r->rflush;
  print $logfile $reply;   print $logfile $reply;
     }      }
       
 # ---------------------------------------- Send update notifications, meta only  # ---------------------------------------- Send update notifications, meta only
   
     my @subscribedmeta=&get_subscribed_hosts("$target.meta");      my @subscribedmeta=&get_subscribed_hosts("$target.meta");
     foreach my $subhost (@subscribedmeta) {      foreach my $subhost (@subscribedmeta) {
  $scrout.='<p>Notifying host for metadata only '.$subhost.':';   $r->print('<p>Notifying host for metadata only '.$subhost.':');$r->rflush;
  print $logfile "\nNotifying host for metadata only ".$subhost.':';   print $logfile "\nNotifying host for metadata only ".$subhost.':';
  my $reply=&Apache::lonnet::critical('update:'.$target.'.meta',   my $reply=&Apache::lonnet::critical('update:'.$target.'.meta',
     $subhost);      $subhost);
  $scrout.=$reply;   $r->print($reply.'<br />');$r->rflush;
    print $logfile $reply;
       }
       
   # --------------------------------------------------- Notify subscribed courses
       my %courses=&coursedependencies($target);
       my $now=time;
       foreach (keys %courses) {
    $r->print('<p>Notifying course '.$_.':');$r->rflush;
    print $logfile "\nNotifying host ".$_.':';
           my ($cdom,$cname)=split(/\_/,$_);
    my $reply=&Apache::lonnet::cput
                     ('versionupdate',{$target => $now},$cdom,$cname);
    $r->print($reply.'<br />');$r->rflush;
  print $logfile $reply;   print $logfile $reply;
     }      }
   
 # ------------------------------------------------ Provide link to new resource  # ------------------------------------------------ Provide link to new resource
       unless ($batch) {
           my $thisdistarget=$target;
           $thisdistarget=~s/^$docroot//;
           
           my $thissrc=$source;
           $thissrc=~s/^\/home\/(\w+)\/public_html/\/priv\/$1/;
           
           my $thissrcdir=$thissrc;
           $thissrcdir=~s/\/[^\/]+$/\//;
           
           
           $r->print(
              '<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>');
       }
   }
   
   #########################################
   
   sub batchpublish {
       my ($r,$srcfile,$targetfile)=@_;
       $srcfile=~s/\/+/\//g;
       $targetfile=~s/\/+/\//g;
       my $thisdisfn=$srcfile;
       $thisdisfn=~s/\/home\/korte\/public_html\///;
       $srcfile=~s/\/+/\//g;
   
     my $thisdistarget=$target;      my $docroot=$r->dir_config('lonDocRoot');
       my $thisdistarget=$targetfile;
     $thisdistarget=~s/^$docroot//;      $thisdistarget=~s/^$docroot//;
   
     my $thissrc=$source;  
     $thissrc=~s/^\/home\/(\w+)\/public_html/\/priv\/$1/;  
   
     my $thissrcdir=$thissrc;      undef %metadatafields;
     $thissrcdir=~s/\/[^\/]+$/\//;      undef %metadatakeys;
        %metadatafields=();
        %metadatakeys=();
         $srcfile=~/\.(\w+)$/;
         my $thistype=$1;
   
   
     return $warning.$scrout.        my $thisembstyle=&Apache::loncommon::fileembstyle($thistype);
       '<hr><a href="'.$thisdistarget.'"><font size=+2>View Published Version</font></a>'.       
       '<p><a href="'.$thissrc.'"><font size=+2>Back to Source</font></a>'.      $r->print('<h2>Publishing <tt>'.$thisdisfn.'</tt></h2>');
       '<p><a href="'.$thissrcdir.  
       '"><font size=+2>Back to Source Directory</font></a>';  
   
   # phase one takes
   #  my ($source,$target,$style,$batch)=@_;
       $r->print('<p>'.&publish($srcfile,$targetfile,$thisembstyle,1).'</p>');
   # phase two takes
   # my ($source,$target,$style,$distarget,batch)=@_;
   # $ENV{'form.allmeta'},$ENV{'form.title'},$ENV{'form.author'},...
       $r->print('<p>');
       &phasetwo($r,$srcfile,$targetfile,$thisembstyle,$thisdistarget,1);
       $r->print('</p>');
       return '';
   }
   
   #########################################
   
   sub publishdirectory {
       my ($r,$fn,$thisdisfn)=@_;
       $fn=~s/\/+/\//g;
       $thisdisfn=~s/\/+/\//g;
       my $resdir=
       $Apache::lonnet::perlvar{'lonDocRoot'}.'/res/'.$cudom.'/'.$cuname.'/'.
         $thisdisfn;
         $r->print('<h1>Directory <tt>'.$thisdisfn.'</tt></h1>'.
                   'Target: <tt>'.$resdir.'</tt><br />');
   
         my $dirptr=16384; # Mask indicating a directory in stat.cmode.
   
         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) {
   # previously published, modified now
       $publishthis=1;
                   }
        } else {
   # never published
    $publishthis=1;
        }
                if ($publishthis) {
                   &batchpublish($r,$fn.'/'.$filename,$resdir.'/'.$filename);
        } else {
                    $r->print('<br />Skipping '.$filename.'<br />');
                }
                $r->rflush();
            }
         }
         closedir(DIR);
 }  }
   #########################################
   
   =pod
   
   =item B<handler>
   
 # ================================================================ Main Handler  A basic outline of the handler subroutine follows.
   
   =over 4
   
   =item *
   
   Get query string for limited number of parameters.
   
   =item *
   
   Check filename.
   
   =item *
   
   File is there and owned, init lookup tables.
   
   =item *
   
   Start page output.
   
   =item *
   
   Evaluate individual file, and then output information.
   
   =item *
   
   Publishing from $thisfn to $thistarget with $thisembstyle.
   
   =back
   
   =cut
   
   #########################################
   #########################################
 sub handler {  sub handler {
   my $r=shift;    my $r=shift;
   
Line 1127  sub handler { Line 1647  sub handler {
   
 unless ($ENV{'form.phase'} eq 'two') {  unless ($ENV{'form.phase'} eq 'two') {
   
 # --------------------------------- File is there and owned, init lookup tables  # -------------------------------- File is there and owned, init lookup tables.
   
   %addid=();    %addid=();
   
Line 1151  unless ($ENV{'form.phase'} eq 'two') { Line 1671  unless ($ENV{'form.phase'} eq 'two') {
   
 }  }
   
 # ----------------------------------------------------------- Start page output  # ---------------------------------------------------------- Start page output.
   
   $r->content_type('text/html');    $r->content_type('text/html');
   $r->send_http_header;    $r->send_http_header;
   
   $r->print('<html><head><title>LON-CAPA Publishing</title></head>');    $r->print('<html><head><title>LON-CAPA Publishing</title></head>');
   $r->print(    $r->print(&Apache::loncommon::bodytag('Resource Publication'));
    '<body bgcolor="#FFFFFF"><img align=right src=/adm/lonIcons/lonlogos.gif>');  
   
   my $thisfn=$fn;    my $thisfn=$fn;
      
 # ------------------------------------------------------------- Individual file  
   {  
       $thisfn=~/\.(\w+)$/;  
       my $thistype=$1;  
       my $thisembstyle=&Apache::loncommon::fileembstyle($thistype);  
   
       my $thistarget=$thisfn;    my $thistarget=$thisfn;
               
       $thistarget=~s/^\/home/$targetdir/;    $thistarget=~s/^\/home/$targetdir/;
       $thistarget=~s/\/public\_html//;    $thistarget=~s/\/public\_html//;
   
       my $thisdistarget=$thistarget;    my $thisdistarget=$thistarget;
       $thisdistarget=~s/^$docroot//;    $thisdistarget=~s/^$docroot//;
   
       my $thisdisfn=$thisfn;    my $thisdisfn=$thisfn;
       $thisdisfn=~s/^\/home\/$cuname\/public_html\///;    $thisdisfn=~s/^\/home\/$cuname\/public_html\///;
   
     if ($fn=~/\/$/) {
   # -------------------------------------------------------- This is a directory
         &publishdirectory($r,$fn,$thisdisfn);
   
     } else {
   # ---------------------- Evaluate individual file, and then output information.
         $thisfn=~/\.(\w+)$/;
         my $thistype=$1;
         my $thisembstyle=&Apache::loncommon::fileembstyle($thistype);
   
       $r->print('<h2>Publishing '.        $r->print('<h2>Publishing '.
         &Apache::loncommon::filedescription($thistype).' <tt>'.          &Apache::loncommon::filedescription($thistype).' <tt>'.
         $thisdisfn.'</tt></h2><b>Target:</b> <tt>'.$thisdistarget.'</tt><p>');          '<a href="/~'.$cuname.'/'.$thisdisfn.'" target="cat">'.$thisdisfn.
           '</a></tt></h2><b>Target:</b> <tt>'.$thisdistarget.'</tt><p>');
         
        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">Co-Author: '.$cuname.' at '.$cudom.
                '</font></h3>');      '</font></h3>');
       }        }
   
       if (&Apache::loncommon::fileembstyle($thistype) eq 'ssi') {        if (&Apache::loncommon::fileembstyle($thistype) eq 'ssi') {
           $r->print('<br><a href="/adm/diff?filename=/~'.$cuname.'/'.            $r->print('<br /><a href="/adm/diff?filename=/~'.$cuname.'/'.
                     $thisdisfn.                      $thisdisfn.
    '&versionone=priv" target=cat>Diffs with Current Version</a><p>');     '&versiontwo=priv" target="cat">Diffs with Current Version</a><p>');
       }        }
       
 # ------------ We are publishing from $thisfn to $thistarget with $thisembstyle  # ------------------ Publishing from $thisfn to $thistarget with $thisembstyle.
   
        unless ($ENV{'form.phase'} eq 'two') {         unless ($ENV{'form.phase'} eq 'two') {
          $r->print(           $r->print(
           '<hr>'.&publish($thisfn,$thistarget,$thisembstyle));            '<hr />'.&publish($thisfn,$thistarget,$thisembstyle));
        } else {         } else {
          $r->print(             $r->print('<hr />');
           '<hr>'.&phasetwo($thisfn,$thistarget,$thisembstyle,$thisdistarget));              &phasetwo($r,$thisfn,$thistarget,$thisembstyle,$thisdistarget); 
        }           }  
   
   }    }
Line 1212  unless ($ENV{'form.phase'} eq 'two') { Line 1738  unless ($ENV{'form.phase'} eq 'two') {
 1;  1;
 __END__  __END__
   
 =head1 NAME  =pod
   
 Apache::lonpublisher - Publication Handler  
   
 =head1 SYNOPSIS  
   
 Invoked by /etc/httpd/conf/srm.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 INTRODUCTION  
   
 This module publishes a file.  This involves gathering metadata,  
 versioning the file, copying file from construction space to  
 publication space, and copying metadata from construction space  
 to publication space.  
   
 This is part of the LearningOnline Network with CAPA project  
 described at http://www.lon-capa.org.  
   
 =head1 HANDLER SUBROUTINE  
   
 This routine is called by Apache and mod_perl.  
   
 =over 4  
   
 =item *  
   
 Get query string for limited number of parameters  
   
 =item *  
   
 Check filename  
   
 =item *  
   
 File is there and owned, init lookup tables  
   
 =item *  
   
 Start page output  
   
 =item *  
   
 Individual file  
   
 =item *  
   
 publish from $thisfn to $thistarget with $thisembstyle  
   
 =back  
   
 =head1 OTHER SUBROUTINES  
   
 =over 4  
   
 =item *  
   
 metaeval() : Evaluate string with metadata  
   
 =item *  
   
 metaread() : Read a metadata file  
   
 =item *  
   
 sqltime() : convert 'time' format into a datetime sql format  
   
 =item *  
   
 textfield() : form field  
   
 =item *  
   
 hiddenfield() : form field  
   
 =item *  
   
 selectbox() : form field  
   
 =item *  
   
 urlfixup() : fixup URL (Publication Step One)  
   
 =item *  
   
 publish() : publish (Publication Step One)  
   
 =item *  
   
 phasetwo() : render second interface showing status of publication steps  
 (Publication Step Two)  
   
 =back  =back
   
 =cut  =cut
   

Removed from v.1.87  
changed lines
  Added in v.1.109


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