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

version 1.11, 2000/12/02 20:55:16 version 1.87, 2002/08/07 19:50:22
Line 1 Line 1
 # The LearningOnline Network with CAPA  # The LearningOnline Network with CAPA
 # Publication Handler  # Publication Handler
   #
   # $Id$
   #
   # Copyright Michigan State University Board of Trustees
   #
   # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
   #
   # LON-CAPA is free software; you can redistribute it and/or modify
   # it under the terms of the GNU General Public License as published by
   # the Free Software Foundation; either version 2 of the License, or
   # (at your option) any later version.
   #
   # LON-CAPA is distributed in the hope that it will be useful,
   # but WITHOUT ANY WARRANTY; without even the implied warranty of
   # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   # GNU General Public License for more details.
   #
   # You should have received a copy of the GNU General Public License
   # along with LON-CAPA; if not, write to the Free Software
   # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   #
   # /home/httpd/html/adm/gpl.txt
   #
   # http://www.lon-capa.org/
   #
 #   # 
 # (TeX Content Handler  # (TeX Content Handler
 #  #
 # 05/29/00,05/30,10/11 Gerd Kortemeyer)  # 05/29/00,05/30,10/11 Gerd Kortemeyer)
 #  #
 # 11/28,11/29,11/30,12/01,12/02 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
   #
   ###
   
   ###############################################################################
   ##                                                                           ##
   ## ORGANIZATION OF THIS PERL MODULE                                          ##
   ##                                                                           ##
   ## 1. Modules used by this module                                            ##
   ## 2. Various subroutines                                                    ##
   ## 3. Publication Step One                                                   ##
   ## 4. Phase Two                                                              ##
   ## 5. Main Handler                                                           ##
   ##                                                                           ##
   ###############################################################################
   
 package Apache::lonpublisher;  package Apache::lonpublisher;
   
   # ------------------------------------------------- modules used by this module
 use strict;  use strict;
 use Apache::File;  use Apache::File;
   use File::Copy;
 use Apache::Constants qw(:common :http :methods);  use Apache::Constants qw(:common :http :methods);
 use HTML::TokeParser;  use HTML::LCParser;
 use Apache::lonxml;  use Apache::lonxml;
 use Apache::structuretags;  use Apache::lonhomework;
 use Apache::response;  use Apache::loncacc;
   use DBI;
   use Apache::lonnet();
   use Apache::loncommon();
   
 my %addid;  my %addid;
 my %nokey;  my %nokey;
 my %language;  
 my %cprtag;  
   
 my %metadatafields;  my %metadatafields;
 my %metadatakeys;  my %metadatakeys;
   
   my $docroot;
   
   my $cuname;
   my $cudom;
   
   # ----------------------------------------------- Evaluate string with metadata
 sub metaeval {  sub metaeval {
     my $metastring=shift;      my $metastring=shift;
         
         my $parser=HTML::TokeParser->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'})) { 
                     $unikey.='_package_'.$token->[2]->{'package'};
                 } 
               if (defined($token->[2]->{'part'})) {                 if (defined($token->[2]->{'part'})) { 
                  $unikey.='_'.$token->[2]->{'part'};                    $unikey.='_'.$token->[2]->{'part'}; 
       }        }
                 if (defined($token->[2]->{'id'})) { 
                     $unikey.='_'.$token->[2]->{'id'};
                 } 
               if (defined($token->[2]->{'name'})) {                 if (defined($token->[2]->{'name'})) { 
                  $unikey.='_'.$token->[2]->{'name'};                    $unikey.='_'.$token->[2]->{'name'}; 
       }        }
                map {                foreach (@{$token->[3]}) {
   $metadatafields{$unikey.'.'.$_}=$token->[2]->{$_};    $metadatafields{$unikey.'.'.$_}=$token->[2]->{$_};
                   if ($metadatakeys{$unikey}) {                    if ($metadatakeys{$unikey}) {
       $metadatakeys{$unikey}.=','.$_;        $metadatakeys{$unikey}.=','.$_;
                   } else {                    } else {
                       $metadatakeys{$unikey}=$_;                        $metadatakeys{$unikey}=$_;
                   }                    }
               } @{$token->[3]};                }
               if ($metadatafields{$unikey}) {                if ($metadatafields{$unikey}) {
   my $newentry=$parser->get_text('/'.$entry);    my $newentry=$parser->get_text('/'.$entry);
                   unless ($metadatafields{$unikey}=~/$newentry/) {                    unless (($metadatafields{$unikey}=~/$newentry/) ||
                             ($newentry eq '')) {
                      $metadatafields{$unikey}.=', '.$newentry;                       $metadatafields{$unikey}.=', '.$newentry;
   }    }
       } else {        } else {
Line 60  sub metaeval { Line 130  sub metaeval {
        }         }
 }  }
   
   # -------------------------------------------------------- Read a metadata file
 sub metaread {  sub metaread {
     my ($logfile,$fn)=@_;      my ($logfile,$fn)=@_;
     unless (-e $fn) {      unless (-e $fn) {
Line 76  sub metaread { Line 147  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) =
    localtime($timef);
       $mon++; $year+=1900;
       return "$year-$mon-$mday $hour:$min:$sec";
   }
   
   # --------------------------------------------------------- Various form fields
   
 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>".
Line 88  sub hiddenfield { Line 170  sub hiddenfield {
 }  }
   
 sub selectbox {  sub selectbox {
     my ($title,$name,$value,%options)=@_;      my ($title,$name,$value,$functionref,@idlist)=@_;
     my $selout="\n<p><b>$title:</b><br>".'<select name="'.$name.'">';      my $uctitle=uc($title);
     map {      my $selout="\n<p><font color=\"#800000\" face=\"helvetica\"><b>$uctitle:".
         $selout.='<option value="'.$_.'"';   "</b></font><br />".'<select name="'.$name.'">';
         if ($_ eq $value) { $selout.=' selected'; }      foreach (@idlist) {
         $selout.='>'.$options{$_}.'</option>';          $selout.='<option value=\''.$_.'\'';
     } sort keys %options;          if ($_ eq $value) {
       $selout.=' selected>'.&{$functionref}($_).'</option>';
    }
           else {$selout.='>'.&{$functionref}($_).'</option>';}
       }
     return $selout.'</select>';      return $selout.'</select>';
 }  }
   
   # -------------------------------------------------------- Publication Step One
   
   sub urlfixup {
       my ($url,$target)=@_;
       unless ($url) { return ''; }
       #javascript code needs no fixing
       if ($url =~ /^javascript:/i) { return $url; }
       if ($url =~ /^mailto:/i) { return $url; }
       #internal document links need no fixing
       if ($url =~ /^\#/) { return $url; } 
       my ($host)=($url=~/(?:http\:\/\/)*([^\/]+)/);
       foreach (values %Apache::lonnet::hostname) {
    if ($_ eq $host) {
       $url=~s/^http\:\/\///;
               $url=~s/^$host//;
           }
       }
       if ($url=~/^http\:\/\//) { return $url; }
       $url=~s/\~$cuname/res\/$cudom\/$cuname/;
       return $url;
   }
   
   
   sub absoluteurl {
       my ($url,$target)=@_;
       unless ($url) { return ''; }
       if ($target) {
    $target=~s/\/[^\/]+$//;
          $url=&Apache::lonnet::hreflocation($target,$url);
       }
       return $url;
   }
   
   sub set_allow {
       my ($allow,$logfile,$target,$tag,$oldurl)=@_;
       my $newurl=&urlfixup($oldurl,$target);
       my $return_url=$oldurl;
       print $logfile 'GUYURL: '.$tag.':'.$oldurl.' - '.$newurl."\n";
       if ($newurl ne $oldurl) {
    $return_url=$newurl;
    print $logfile 'URL: '.$tag.':'.$oldurl.' - '.$newurl."\n";
       }
       if (($newurl !~ /^javascript:/i) &&
    ($newurl !~ /^mailto:/i) &&
    ($newurl !~ /^http:/i) &&
    ($newurl !~ /^\#/)) {
    $$allow{&absoluteurl($newurl,$target)}=1;
       }
       return $return_url
   }
   
   sub get_subscribed_hosts {
       my ($target)=@_;
       my @subscribed;
       my $filename;
       $target=~/(.*)\/([^\/]+)$/;
       my $srcf=$2;
       opendir(DIR,$1);
       while ($filename=readdir(DIR)) {
    if ($filename=~/$srcf\.(\w+)$/) {
       my $subhost=$1;
       if ($subhost ne 'meta' && $subhost ne 'subscription') {
    push(@subscribed,$subhost);
       }
    }
       }
       closedir(DIR);
       my $sh;
       if ( $sh=Apache::File->new("$target.subscription") ) {
    &Apache::lonnet::logthis("opened $target.subscription");
    while (my $subline=<$sh>) {
       &Apache::lonnet::logthis("Trying $subline");
       if ($subline =~ /(^\w+):/) { push(@subscribed,$1); } else {
    &Apache::lonnet::logthis("No Match for $subline");
       }
    }
       } else {
    &Apache::lonnet::logthis("Un able to open $target.subscription");
       }
       &Apache::lonnet::logthis("Got list of ".join(':',@subscribed));
       return @subscribed;
   }
   
   
   sub get_max_ids_indices {
       my ($content)=@_;
       my $maxindex=10;
       my $maxid=10;
       my $needsfixup=0;
   
       my $parser=HTML::LCParser->new($content);
       my $token;
       while ($token=$parser->get_token) {
    if ($token->[0] eq 'S') {
       my $counter;
       if ($counter=$addid{$token->[1]}) {
    if ($counter eq 'id') {
       if (defined($token->[2]->{'id'})) {
    $maxid=($token->[2]->{'id'}>$maxid)?$token->[2]->{'id'}:$maxid;
       } else {
    $needsfixup=1;
       }
    } else {
       if (defined($token->[2]->{'index'})) {
    $maxindex=($token->[2]->{'index'}>$maxindex)?$token->[2]->{'index'}:$maxindex;
       } else {
    $needsfixup=1;
       }
    }
       }
    }
       }
       return ($needsfixup,$maxid,$maxindex);
   }
   
   sub get_all_text_unbalanced {
       #there is a copy of this in lonxml.pm
       my($tag,$pars)= @_;
       my $token;
       my $result='';
       $tag='<'.$tag.'>';
       while ($token = $$pars[-1]->get_token) {
    if (($token->[0] eq 'T')||($token->[0] eq 'C')||($token->[0] eq 'D')) {
       $result.=$token->[1];
    } elsif ($token->[0] eq 'PI') {
       $result.=$token->[2];
    } elsif ($token->[0] eq 'S') {
       $result.=$token->[4];
    } elsif ($token->[0] eq 'E')  {
       $result.=$token->[2];
    }
    if ($result =~ /(.*)$tag(.*)/) {
       &Apache::lonnet::logthis('Got a winner with leftovers ::'.$2);
       &Apache::lonnet::logthis('Result is :'.$1);
       $result=$1;
       my $redo=$tag.$2;
       push (@$pars,HTML::LCParser->new(\$redo));
       $$pars[-1]->xml_mode('1');
       last;
    }
       }
       return $result
   }
   
   #Arguably this should all be done as a lonnet::ssi instead
   sub fix_ids_and_indices {
       my ($logfile,$source,$target)=@_;
   
       my %allow;
       my $content;
       {
    my $org=Apache::File->new($source);
    $content=join('',<$org>);
       }
   
       my ($needsfixup,$maxid,$maxindex)=&get_max_ids_indices(\$content);
   
       if ($needsfixup) {
    print $logfile "Needs ID and/or index fixup\n".
       "Max ID   : $maxid (min 10)\n".
                   "Max Index: $maxindex (min 10)\n";
       }
       my $outstring='';
       my @parser;
       $parser[0]=HTML::LCParser->new(\$content);
       $parser[-1]->xml_mode(1);
       my $token;
       while (@parser) {
    while ($token=$parser[-1]->get_token) {
       if ($token->[0] eq 'S') {
    my $counter;
    my $tag=$token->[1];
    my $lctag=lc($tag);
    if ($lctag eq 'allow') {
       $allow{$token->[2]->{'src'}}=1;
       next;
    }
    my %parms=%{$token->[2]};
    $counter=$addid{$tag};
    if (!$counter) { $counter=$addid{$lctag}; }
    if ($counter) {
       if ($counter eq 'id') {
    unless (defined($parms{'id'})) {
       $maxid++;
       $parms{'id'}=$maxid;
       print $logfile 'ID: '.$tag.':'.$maxid."\n";
    }
       } elsif ($counter eq 'index') {
    unless (defined($parms{'index'})) {
       $maxindex++;
       $parms{'index'}=$maxindex;
       print $logfile 'Index: '.$tag.':'.$maxindex."\n";
    }
       }
    }
    foreach my $type ('src','href','background','bgimg') {
       foreach my $key (keys(%parms)) {
    print $logfile "for $type, and $key\n";
    if ($key =~ /^$type$/i) {
       print $logfile "calling set_allow\n";
       $parms{$key}=&set_allow(\%allow,$logfile,
       $target,$tag,
       $parms{$key});
    }
       }
    }
    # probably a <randomlabel> image type <label>
    if ($lctag eq 'label' && defined($parms{'description'})) {
       my $next_token=$parser[-1]->get_token();
       if ($next_token->[0] eq 'T') {
    $next_token->[1]=&set_allow(\%allow,$logfile,
       $target,$tag,
       $next_token->[1]);
       }
       $parser[-1]->unget_token($next_token);
    }
    if ($lctag eq 'applet') {
       my $codebase='';
       if (defined($parms{'codebase'})) {
    my $oldcodebase=$parms{'codebase'};
    unless ($oldcodebase=~/\/$/) {
       $oldcodebase.='/';
    }
    $codebase=&urlfixup($oldcodebase,$target);
    $codebase=~s/\/$//;    
    if ($codebase ne $oldcodebase) {
       $parms{'codebase'}=$codebase;
       print $logfile 'URL codebase: '.$tag.':'.
    $oldcodebase.' - '.
       $codebase."\n";
    }
    $allow{&absoluteurl($codebase,$target).'/*'}=1;
       } else {
    foreach ('archive','code','object') {
       if (defined($parms{$_})) {
    my $oldurl=$parms{$_};
    my $newurl=&urlfixup($oldurl,$target);
    $newurl=~s/\/[^\/]+$/\/\*/;
    print $logfile 'Allow: applet '.$_.':'.
       $oldurl.' allows '.
    $newurl."\n";
    $allow{&absoluteurl($newurl,$target)}=1;
       }
    }
       }
    }
    my $newparmstring='';
    my $endtag='';
    foreach (keys %parms) {
       if ($_ eq '/') {
    $endtag=' /';
       } else { 
    my $quote=($parms{$_}=~/\"/?"'":'"');
    $newparmstring.=' '.$_.'='.$quote.$parms{$_}.$quote;
       }
    }
    if (!$endtag) { if ($token->[4]=~m:/>$:) { $endtag=' /'; }; }
    $outstring.='<'.$tag.$newparmstring.$endtag.'>';
    if ($lctag eq 'm') {
       $outstring.=&get_all_text_unbalanced('/m',\@parser);
    }
       } elsif ($token->[0] eq 'E') {
    if ($token->[2]) {
       unless ($token->[1] eq 'allow') {
    $outstring.='</'.$token->[1].'>';
       }
    }
       } else {
    $outstring.=$token->[1];
       }
    }
    pop(@parser);
       }
   
       if ($needsfixup) {
    print $logfile "End of ID and/or index fixup\n".
       "Max ID   : $maxid (min 10)\n".
    "Max Index: $maxindex (min 10)\n";
       } else {
    print $logfile "Does not need ID and/or index fixup\n";
       }
   
       return ($outstring,%allow);
   }
   
 sub publish {  sub publish {
   
     my ($source,$target,$style)=@_;      my ($source,$target,$style)=@_;
     my $logfile;      my $logfile;
     my $scrout='';      my $scrout='';
       my $allmeta='';
       my $content='';
       my %allow=();
   
     unless ($logfile=Apache::File->new('>>'.$source.'.log')) {      unless ($logfile=Apache::File->new('>>'.$source.'.log')) {
  return    return 
Line 116  sub publish { Line 490  sub publish {
   
 # ----------------------------------------------------------------- Backup Copy  # ----------------------------------------------------------------- Backup Copy
  my $copyfile=$source.'.save';   my $copyfile=$source.'.save';
         {          if (copy($source,$copyfile)) {
     my $org=Apache::File->new($source);  
             my $cop=Apache::File->new('>'.$copyfile);  
             while (my $line=<$org>) { print $cop $line; }  
         }  
         if (-e $copyfile) {  
     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 "<font color=red>Failed to write backup copy, $!,FAIL</font>";
         }          }
 # ------------------------------------------------------------- IDs and indices  # ------------------------------------------------------------- IDs and indices
   
         my $maxindex=10;   my $outstring;
         my $maxid=10;   ($outstring,%allow)=&fix_ids_and_indices($logfile,$source,$target);
         my $content='';  # ------------------------------------------------------------ Construct Allows
         my $needsfixup=0;      
    $scrout.='<h3>Dependencies</h3>';
         {          my $allowstr='';
           my $org=Apache::File->new($source);          foreach (sort(keys(%allow))) {
           $content=join('',<$org>);     my $thisdep=$_;
      if ($thisdep !~ /[^\s]/) { next; }
              unless ($style eq 'rat') { 
                 $allowstr.="\n".'<allow src="'.$thisdep.'" />';
      }
              $scrout.='<br>';
              unless ($thisdep=~/\*/) {
          $scrout.='<a href="'.$thisdep.'">';
              }
              $scrout.='<tt>'.$thisdep.'</tt>';
              unless ($thisdep=~/\*/) {
          $scrout.='</a>';
                  if (
          &Apache::lonnet::getfile($Apache::lonnet::perlvar{'lonDocRoot'}.'/'.
                                               $thisdep.'.meta') eq '-1') {
      $scrout.=
                              ' - <font color=red>Currently not available</font>';
                  } else {
                      my %temphash=(&Apache::lonnet::declutter($target).'___'.
                                &Apache::lonnet::declutter($thisdep).'___usage'
                                    => time);
                      $thisdep=~/^\/res\/(\w+)\/(\w+)\//;
                      if ((defined($1)) && (defined($2))) {
                         &Apache::lonnet::put('resevaldata',\%temphash,$1,$2);
      }
          }
              }
         }          }
         {          $outstring=~s/\n*(\<\/[^\>]+\>)\s*$/$allowstr\n$1\n/s;
           my $parser=HTML::TokeParser->new(\$content);  
           my $token;   #Encode any High ASCII characters
           while ($token=$parser->get_token) {   $outstring=&HTML::Entities::encode($outstring,"\200-\377");
               if ($token->[0] eq 'S') {  # ------------------------------------------------------------- Write modified
                   my $counter;  
   if ($counter=$addid{$token->[1]}) {  
       if ($counter eq 'id') {  
   if (defined($token->[2]->{'id'})) {  
                              $maxid=  
        ($token->[2]->{'id'}>$maxid)?$token->[2]->{'id'}:$maxid;  
  } else {  
                              $needsfixup=1;  
                          }  
                       } else {  
    if (defined($token->[2]->{'index'})) {  
                              $maxindex=  
    ($token->[2]->{'index'}>$maxindex)?$token->[2]->{'index'}:$maxindex;  
   } else {  
                              $needsfixup=1;  
   }  
       }  
   }  
               }  
           }  
       }  
       if ($needsfixup) {  
           print $logfile "Needs ID and/or index fixup\n".  
         "Max ID   : $maxid (min 10)\n".  
                 "Max Index: $maxindex (min 10)\n";  
   
           my $outstring='';  
           my $parser=HTML::TokeParser->new(\$content);  
           my $token;  
           while ($token=$parser->get_token) {  
               if ($token->[0] eq 'S') {  
                   my $counter;  
   if ($counter=$addid{$token->[1]}) {  
       if ($counter eq 'id') {  
   if (defined($token->[2]->{'id'})) {  
       $outstring.=$token->[4];  
   } else {  
                               $maxid++;  
                               my $thisid=' id="'.$maxid.'"';  
       my $fixup=$token->[4];  
                               $fixup=~s/(\<\w+)/$1$thisid/;  
                               $outstring.=$fixup;  
                               print $logfile 'ID: '.$fixup."\n";  
                           }  
                       } else {  
    if (defined($token->[2]->{'index'})) {  
       $outstring.=$token->[4];  
   } else {  
                               $maxindex++;  
                               my $thisindex=' index="'.$maxindex.'"';  
       my $fixup=$token->[4];  
                               $fixup=~s/(\<\w+)/$1$thisindex/;  
                               $outstring.=$fixup;  
                               print $logfile 'Index: '.$fixup."\n";  
   }  
       }  
   } else {  
                       $outstring.=$token->[4];  
                   }  
               } elsif ($token->[0] eq 'E') {  
                   $outstring.=$token->[2];  
               } else {  
                   $outstring.=$token->[1];  
               }  
           }  
         {          {
           my $org;            my $org;
           unless ($org=Apache::File->new('>'.$source)) {            unless ($org=Apache::File->new('>'.$source)) {
Line 218  sub publish { Line 549  sub publish {
           print $org $outstring;            print $org $outstring;
         }          }
   $content=$outstring;    $content=$outstring;
           print $logfile "End of ID and/or index fixup\n".  
         "Max ID   : $maxid (min 10)\n".  
                 "Max Index: $maxindex (min 10)\n";  
       } else {  
   print $logfile "Does not need ID and/or index fixup\n";  
       }  
   
       }
 # --------------------------------------------- Initial step done, now metadata  # --------------------------------------------- Initial step done, now metadata
   
 # ---------------------------------------- Storage for metadata keys and fields  # ---------------------------------------- Storage for metadata keys and fields
Line 233  sub publish { Line 559  sub publish {
      %metadatakeys=();       %metadatakeys=();
             
      my %oldparmstores=();       my %oldparmstores=();
        
        
        $scrout.='<h3>Metadata Information ' .
          Apache::loncommon::help_open_topic("Metadata_Description")
          . '</h3>';
   
 # ------------------------------------------------ First, check out environment  # ------------------------------------------------ First, check out environment
      unless (-e $source.'.meta') {       unless (-e $source.'.meta') {
Line 242  sub publish { Line 573  sub publish {
                   $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'}=$ENV{'user.name'}.'@'.$ENV{'user.domain'};          $metadatafields{'owner'}=$cuname.'@'.$cudom;
   
 # ------------------------------------------------ Check out directory hierachy  # ------------------------------------------------ Check out directory hierachy
   
         my $thisdisfn=$source;          my $thisdisfn=$source;
         $thisdisfn=~s/^\/home\/$ENV{'user.name'}\///;          $thisdisfn=~s/^\/home\/$cuname\///;
   
         my @urlparts=split(/\//,$thisdisfn);          my @urlparts=split(/\//,$thisdisfn);
         $#urlparts--;          $#urlparts--;
   
         my $currentpath='/home/'.$ENV{'user.name'}.'/';          my $currentpath='/home/'.$cuname.'/';
   
         map {          foreach (@urlparts) {
     $currentpath.=$_.'/';      $currentpath.=$_.'/';
             $scrout.=&metaread($logfile,$currentpath.'default.meta');              $scrout.=&metaread($logfile,$currentpath.'default.meta');
         } @urlparts;          }
   
 # ------------------- Clear out parameters and stores (there should not be any)  # ------------------- Clear out parameters and stores (there should not be any)
   
         map {          foreach (keys %metadatafields) {
     if (($_=~/^parameter/) || ($_=~/^stores/)) {      if (($_=~/^parameter/) || ($_=~/^stores/)) {
  delete $metadatafields{$_};   delete $metadatafields{$_};
             }              }
         } keys %metadatafields;          }
   
     } else {      } else {
 # ---------------------- Read previous metafile, remember parameters and stores  # ---------------------- Read previous metafile, remember parameters and stores
   
         $scrout.=&metaread($logfile,$source.'.meta');          $scrout.=&metaread($logfile,$source.'.meta');
   
         map {          foreach (keys %metadatafields) {
     if (($_=~/^parameter/) || ($_=~/^stores/)) {      if (($_=~/^parameter/) || ($_=~/^stores/)) {
                 $oldparmstores{$_}=1;                  $oldparmstores{$_}=1;
  delete $metadatafields{$_};   delete $metadatafields{$_};
             }              }
         } keys %metadatafields;          }
                   
     }      }
   
 # -------------------------------------------------- Parse content for metadata  # -------------------------------------------------- Parse content for metadata
       if ($style eq 'ssi') {
           my $oldenv=$ENV{'request.uri'};
   
         my $allmeta=Apache::lonxml::xmlparse('meta',$content);          $ENV{'request.uri'}=$target;
         &metaeval($allmeta);          $allmeta=Apache::lonxml::xmlparse(undef,'meta',$content);
           $ENV{'request.uri'}=$oldenv;
   
           &metaeval($allmeta);
       }
 # ---------------- Find and document discrepancies in the parameters and stores  # ---------------- Find and document discrepancies in the parameters and stores
   
         my $chparms='';          my $chparms='';
         map {          foreach (sort keys %metadatafields) {
     if (($_=~/^parameter/) || ($_=~/^stores/)) {      if (($_=~/^parameter/) || ($_=~/^stores/)) {
                 unless ($_=~/\.\w+$/) {                   unless ($_=~/\.\w+$/) { 
                    unless ($oldparmstores{$_}) {                     unless ($oldparmstores{$_}) {
Line 298  sub publish { Line 634  sub publish {
                    }                     }
         }          }
             }              }
         } sort keys %metadatafields;          }
         if ($chparms) {          if ($chparms) {
     $scrout.='<p><b>New parameters or stored values:</b> '.      $scrout.='<p><b>New parameters or stored values:</b> '.
                      $chparms;                       $chparms;
         }          }
   
         my $chparms='';          $chparms='';
         map {          foreach (sort keys %oldparmstores) {
     if (($_=~/^parameter/) || ($_=~/^stores/)) {      if (($_=~/^parameter/) || ($_=~/^stores/)) {
                 unless (($metadatafields{$_}) || ($_=~/\.\w+$/)) {                  unless (($metadatafields{$_.'.name'}) ||
                           ($metadatafields{$_.'.package'}) || ($_=~/\.\w+$/)) {
     print $logfile 'Obsolete: '.$_."\n";      print $logfile 'Obsolete: '.$_."\n";
                     $chparms.=$_.' ';                      $chparms.=$_.' ';
                 }                  }
             }              }
         } sort keys %oldparmstores;          }
         if ($chparms) {          if ($chparms) {
     $scrout.='<p><b>Obsolete parameters or stored values:</b> '.      $scrout.='<p><b>Obsolete parameters or stored values:</b> '.
                      $chparms;                       $chparms;
Line 321  sub publish { Line 658  sub publish {
 # ------------------------------------------------------- Now have all metadata  # ------------------------------------------------------- Now have all metadata
   
         $scrout.=          $scrout.=
      '<form action="/adm/publish" method="post">'.       '<form name="pubform" action="/adm/publish" method="post">'.
          '<p><input type="submit" value="Finalize Publication" /></p>'.
           &hiddenfield('phase','two').            &hiddenfield('phase','two').
           &hiddenfield('filename',$ENV{'form.filename'}).            &hiddenfield('filename',$ENV{'form.filename'}).
   &hiddenfield('allmeta',&Apache::lonnet::escape($allmeta)).    &hiddenfield('allmeta',&Apache::lonnet::escape($allmeta)).
             &hiddenfield('dependencies',join(',',keys %allow)).
           &textfield('Title','title',$metadatafields{'title'}).            &textfield('Title','title',$metadatafields{'title'}).
           &textfield('Author(s)','author',$metadatafields{'author'}).            &textfield('Author(s)','author',$metadatafields{'author'}).
   &textfield('Subject','subject',$metadatafields{'subject'});    &textfield('Subject','subject',$metadatafields{'subject'});
   
 # --------------------------------------------------- Scan content for keywords  # --------------------------------------------------- Scan content for keywords
   
  my $keywordout='<p><b>Keywords:</b><br><table border=2><tr>';          my $keywords_help = Apache::loncommon::help_open_topic("Publishing_Keywords");
    my $keywordout=<<"END";
   <script>
   function checkAll(field)
   {
       for (i = 0; i < field.length; i++)
           field[i].checked = true ;
   }
   
   function uncheckAll(field)
   {
       for (i = 0; i < field.length; i++)
           field[i].checked = false ;
   }
   </script>
   <p><b>Keywords: $keywords_help</b> 
   <input type="button" value="check all" onclick="javascript:checkAll(document.pubform.keywords)"> 
   <input type="button" value="uncheck all" onclick="javascript:uncheckAll(document.pubform.keywords)"> 
   <br />
   END
           $keywordout.='<table border=2><tr>';
         my $colcount=0;          my $colcount=0;
           my %keywords=();
                   
  {   if (length($content)<500000) {
     my $textonly=$content;      my $textonly=$content;
             $textonly=~s/\<script[^\<]+\<\/script\>//g;              $textonly=~s/\<script[^\<]+\<\/script\>//g;
             $textonly=~s/\<m\>[^\<]+\<\/m\>//g;              $textonly=~s/\<m\>[^\<]+\<\/m\>//g;
Line 343  sub publish { Line 703  sub publish {
             $textonly=~s/[\$\&][a-z]\w*//g;              $textonly=~s/[\$\&][a-z]\w*//g;
             $textonly=~s/[^a-z\s]//g;              $textonly=~s/[^a-z\s]//g;
   
             my %keywords=();              foreach ($textonly=~m/(\w+)/g) {
             map {  
  unless ($nokey{$_}) {   unless ($nokey{$_}) {
                    $keywords{$_}=1;                     $keywords{$_}=1;
                 }                   } 
             } ($textonly=~m/(\w+)/g);              }
           }
   
               
               foreach (split(/\W+/,$metadatafields{'keywords'})) {
    $keywords{$_}=1;
               }
   
             map {              foreach (sort keys %keywords) {
                 $keywordout.='<td><input type=checkbox name="'.$_.'"';                  $keywordout.='<td><input type=checkbox name="keywords" value="'.$_.'"';
                 if ($metadatafields{'keywords'}=~/$_/) {                   if ($metadatafields{'keywords'}) {
                    $keywordout.=' checked';                      if ($metadatafields{'keywords'}=~/$_/) { 
                 }                        $keywordout.=' checked'; 
                      }
           } elsif (&Apache::loncommon::keyword($_)) {
               $keywordout.=' checked';
                   } 
                 $keywordout.='>'.$_.'</td>';                  $keywordout.='>'.$_.'</td>';
                 if ($colcount>10) {                  if ($colcount>10) {
     $keywordout.="</tr><tr>\n";      $keywordout.="</tr><tr>\n";
                     $colcount=0;                      $colcount=0;
                 }                  }
                 $colcount++;                  $colcount++;
             } sort keys %keywords;              }
             $keywordout.='</tr></table>';  
   
         }           
                   
  $scrout.=$keywordout;   $keywordout.='</tr></table>';
   
           $scrout.=$keywordout;
   
           $scrout.=&textfield('Additional Keywords','addkey','');
   
         $scrout.=&textfield('Notes','notes',$metadatafields{'notes'});          $scrout.=&textfield('Notes','notes',$metadatafields{'notes'});
   
Line 380  sub publish { Line 749  sub publish {
  $scrout.=&hiddenfield('mime',$1);   $scrout.=&hiddenfield('mime',$1);
   
         $scrout.=&selectbox('Language','language',          $scrout.=&selectbox('Language','language',
                             $metadatafields{'language'},%language);                              $metadatafields{'language'},
       \&Apache::loncommon::languagedescription,
       (&Apache::loncommon::languageids),
        );
   
         unless ($metadatafields{'creationdate'}) {          unless ($metadatafields{'creationdate'}) {
     $metadatafields{'creationdate'}=time;      $metadatafields{'creationdate'}=time;
Line 392  sub publish { Line 764  sub publish {
         
  $scrout.=&textfield('Publisher/Owner','owner',   $scrout.=&textfield('Publisher/Owner','owner',
                             $metadatafields{'owner'});                              $metadatafields{'owner'});
   # --------------------------------------------------- Correct copyright for rat        
   
       if ($style eq 'rat') {
    if ($metadatafields{'copyright'} eq 'public') { 
       delete $metadatafields{'copyright'};
    }
         $scrout.=&selectbox('Copyright/Distribution','copyright',          $scrout.=&selectbox('Copyright/Distribution','copyright',
                             $metadatafields{'copyright'},%cprtag);                              $metadatafields{'copyright'},
       \&Apache::loncommon::copyrightdescription,
        (grep !/^public$/,(&Apache::loncommon::copyrightids)));
     }      }
       else {
           $scrout.=&selectbox('Copyright/Distribution','copyright',
                               $metadatafields{'copyright'},
       \&Apache::loncommon::copyrightdescription,
        (&Apache::loncommon::copyrightids));
       }
   
       my $copyright_help = Apache::loncommon::help_open_topic("Publishing_Copyright");
       $scrout =~ s/DISTRIBUTION:/'DISTRIBUTION: ' . $copyright_help/ge;
     return $scrout.      return $scrout.
       '<p><input type="submit" value="Finalize Publication"></form>';        '<p><input type="submit" value="Finalize Publication" /></p></form>';
 }  }
   
   # -------------------------------------------------------- Publication Step Two
   
 sub phasetwo {  sub phasetwo {
   
     my ($source,$target,$style)=@_;      my ($source,$target,$style,$distarget)=@_;
     my $logfile;      my $logfile;
     my $scrout='';      my $scrout='';
   
     unless ($logfile=Apache::File->new('>>'.$source.'.log')) {      unless ($logfile=Apache::File->new('>>'.$source.'.log')) {
  return    return 
          '<font color=red>No write permission to user directory, FAIL</font>';           '<font color=red>No write permission to user directory, FAIL</font>';
Line 422  sub phasetwo { Line 810  sub phasetwo {
      $metadatafields{'title'}=$ENV{'form.title'};       $metadatafields{'title'}=$ENV{'form.title'};
      $metadatafields{'author'}=$ENV{'form.author'};       $metadatafields{'author'}=$ENV{'form.author'};
      $metadatafields{'subject'}=$ENV{'form.subject'};       $metadatafields{'subject'}=$ENV{'form.subject'};
      $metadatafields{'keywords'}=$ENV{'form.keywords'};  
      $metadatafields{'notes'}=$ENV{'form.notes'};       $metadatafields{'notes'}=$ENV{'form.notes'};
      $metadatafields{'abstract'}=$ENV{'form.abstract'};       $metadatafields{'abstract'}=$ENV{'form.abstract'};
      $metadatafields{'mime'}=$ENV{'form.mime'};       $metadatafields{'mime'}=$ENV{'form.mime'};
Line 431  sub phasetwo { Line 818  sub phasetwo {
      $metadatafields{'lastrevisiondate'}=$ENV{'form.lastrevisiondate'};       $metadatafields{'lastrevisiondate'}=$ENV{'form.lastrevisiondate'};
      $metadatafields{'owner'}=$ENV{'form.owner'};       $metadatafields{'owner'}=$ENV{'form.owner'};
      $metadatafields{'copyright'}=$ENV{'form.copyright'};       $metadatafields{'copyright'}=$ENV{'form.copyright'};
             $metadatafields{'dependencies'}=$ENV{'form.dependencies'};
      map {  
          print $logfile "\n".$_.': '.$metadatafields{$_}.  
            "\n".$_.'.keys: '.$metadatakeys{$_};  
      } sort keys %metadatafields;  
   
        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
     my $warning;
   
     unless ($metadatafields{'copyright'} eq 'priv') {
   
       my $dbh;
       {
    unless (
    $dbh = DBI->connect("DBI:mysql:loncapa","www",
       $Apache::lonnet::perlvar{'lonSqlAccess'},{ RaiseError =>0,PrintError=>0})
    ) { 
       $warning='<font color=red>WARNING: Cannot connect to '.
    'database!</font>';
    }
    else {
       my %sqldatafields;
       $sqldatafields{'url'}=$distarget;
       my $sth=$dbh->prepare(
     'delete from metadata where url like binary'.
     '"'.$sqldatafields{'url'}.'"');
       $sth->execute();
       foreach ('title','author','subject','keywords','notes','abstract',
        'mime','language','creationdate','lastrevisiondate','owner',
        'copyright') {
    my $field=$metadatafields{$_}; $field=~s/\"/\'\'/g; 
    $sqldatafields{$_}=$field;
       }
       
       $sth=$dbh->prepare('insert into metadata values ('.
          '"'.delete($sqldatafields{'title'}).'"'.','.
          '"'.delete($sqldatafields{'author'}).'"'.','.
          '"'.delete($sqldatafields{'subject'}).'"'.','.
          '"'.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";
    }
       }
   
   } else {
       $scrout.='<p>Private Publication - did not synchronize database';
       print $logfile "\nPrivate: Did not synchronize data into ".
    "SQL metadata database";
   }
   # ----------------------------------------------------------- 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;
           return "<font color=red>Invalid target directory, FAIL</font>";
       }
       opendir(DIR,$srcd);
       while ($filename=readdir(DIR)) {
          if ($filename=~/$srcf\.(\d+)\.$srct$/) {
      $maxversion=($1>$maxversion)?$1:$maxversion;
          }
       }
       closedir(DIR);
       $maxversion++;
       $scrout.='<p>Creating old version '.$maxversion;
       print $logfile "\nCreating old version ".$maxversion;
   
       my $copyfile=$srcd.'/'.$srcf.'.'.$maxversion.'.'.$srct;
   
           if (copy($target,$copyfile)) {
       print $logfile "Copied old target to ".$copyfile."\n";
               $scrout.='<p>Copied old target file';
           } else {
       print $logfile "Unable to write ".$copyfile.':'.$!."\n";
              return "<font color=red>Failed to copy old target, $!, FAIL</font>";
           }
   
   # --------------------------------------------------------------- Copy Metadata
   
    $copyfile=$copyfile.'.meta';
   
           if (copy($target.'.meta',$copyfile)) {
       print $logfile "Copied old target metadata to ".$copyfile."\n";
               $scrout.='<p>Copied old metadata';
           } else {
       print $logfile "Unable to write metadata ".$copyfile.':'.$!."\n";
               if (-e $target.'.meta') {
                  return 
          "<font color=red>Failed to write old metadata copy, $!, FAIL</font>";
       }
           }
   
   
   } else {
       $scrout.='<p>Initial version';
       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;
                      $scrout.='<p>Created directory '.$parts[$count];
      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>";
           }
   
   # --------------------------------------------------------------- Copy Metadata
   
           $copyfile=$copyfile.'.meta';
   
           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 @subscribed=&get_subscribed_hosts($target);
       foreach my $subhost (@subscribed) {
    $scrout.='<p>Notifying host '.$subhost.':';
    print $logfile "\nNotifying host ".$subhost.':';
    my $reply=&Apache::lonnet::critical('update:'.$target,$subhost);
    $scrout.=$reply;
    print $logfile $reply;
       }
   
   # ---------------------------------------- Send update notifications, meta only
   
       my @subscribedmeta=&get_subscribed_hosts("$target.meta");
       foreach my $subhost (@subscribedmeta) {
    $scrout.='<p>Notifying host for metadata only '.$subhost.':';
    print $logfile "\nNotifying host for metadata only ".$subhost.':';
    my $reply=&Apache::lonnet::critical('update:'.$target.'.meta',
       $subhost);
    $scrout.=$reply;
    print $logfile $reply;
       }
   
   # ------------------------------------------------ Provide link to new resource
   
       my $thisdistarget=$target;
       $thisdistarget=~s/^$docroot//;
   
       my $thissrc=$source;
       $thissrc=~s/^\/home\/(\w+)\/public_html/\/priv\/$1/;
   
       my $thissrcdir=$thissrc;
       $thissrcdir=~s/\/[^\/]+$/\//;
   
   
       return $warning.$scrout.
         '<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>';
   
 }  }
   
Line 451  sub handler { Line 1065  sub handler {
      return OK;       return OK;
   }    }
   
   # Get query string for limited number of parameters
   
       &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
                                               ['filename']);
   
 # -------------------------------------------------------------- Check filename  # -------------------------------------------------------------- Check filename
   
   my $fn=$ENV{'form.filename'};    my $fn=$ENV{'form.filename'};
   
     
   unless ($fn) {     unless ($fn) { 
      $r->log_reason($ENV{'user.name'}.' at '.$ENV{'user.domain'}.       $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;
   }     } 
   
   unless ($ENV{'user.home'} eq $r->dir_config('lonHostID')) {    ($cuname,$cudom)=
      $r->log_reason($ENV{'user.name'}.' at '.$ENV{'user.domain'}.      &Apache::loncacc::constructaccess($fn,$r->dir_config('lonDefDomain'));
     unless (($cuname) && ($cudom)) {
        $r->log_reason($cuname.' at '.$cudom.
            ' trying to publish file '.$ENV{'form.filename'}.
            ' ('.$fn.') - not authorized', 
            $r->filename); 
        return HTTP_NOT_ACCEPTABLE;
     }
   
     unless (&Apache::lonnet::homeserver($cuname,$cudom) 
             eq $r->dir_config('lonHostID')) {
        $r->log_reason($cuname.' at '.$cudom.
          ' trying to publish file '.$ENV{'form.filename'}.           ' trying to publish file '.$ENV{'form.filename'}.
          ' ('.$fn.') - not homeserver ('.$ENV{'user.home'}.')',            ' ('.$fn.') - not homeserver ('.
            &Apache::lonnet::homeserver($cuname,$cudom).')', 
          $r->filename);            $r->filename); 
      return HTTP_NOT_ACCEPTABLE;       return HTTP_NOT_ACCEPTABLE;
   }    }
   
   $fn=~s/^http\:\/\/[^\/]+\/\~(\w+)/\/home\/$1\/public_html/;    $fn=~s/^http\:\/\/[^\/]+//;
     $fn=~s/^\/\~(\w+)/\/home\/$1\/public_html/;
   
   my $targetdir='';    my $targetdir='';
   my $docroot=$r->dir_config('lonDocRoot');     $docroot=$r->dir_config('lonDocRoot'); 
   if ($1 ne $ENV{'user.name'}) {    if ($1 ne $cuname) {
      $r->log_reason($ENV{'user.name'}.' at '.$ENV{'user.domain'}.       $r->log_reason($cuname.' at '.$cudom.
          ' trying to publish unowned file '.$ENV{'form.filename'}.           ' trying to publish unowned file '.$ENV{'form.filename'}.
          ' ('.$fn.')',            ' ('.$fn.')', 
          $r->filename);            $r->filename); 
      return HTTP_NOT_ACCEPTABLE;       return HTTP_NOT_ACCEPTABLE;
   } else {    } else {
       $targetdir=$docroot.'/res/'.$ENV{'user.domain'};        $targetdir=$docroot.'/res/'.$cudom;
   }    }
                                                                     
       
   unless (-e $fn) {     unless (-e $fn) { 
      $r->log_reason($ENV{'user.name'}.' at '.$ENV{'user.domain'}.       $r->log_reason($cuname.' at '.$cudom.
          ' trying to publish non-existing file '.$ENV{'form.filename'}.           ' trying to publish non-existing file '.$ENV{'form.filename'}.
          ' ('.$fn.')',            ' ('.$fn.')', 
          $r->filename);            $r->filename); 
Line 509  unless ($ENV{'form.phase'} eq 'two') { Line 1142  unless ($ENV{'form.phase'} eq 'two') {
   
   {    {
      my $fh=Apache::File->new($r->dir_config('lonIncludes').'/un_keyword.tab');       my $fh=Apache::File->new($r->dir_config('lonIncludes').'/un_keyword.tab');
       map {        while (<$fh>) {
           my $word=$_;            my $word=$_;
           chomp($word);            chomp($word);
           $nokey{$word}=1;            $nokey{$word}=1;
       } <$fh>;        }
   }  
   
   %language=();  
   
   {  
      my $fh=Apache::File->new($r->dir_config('lonTabDir').'/language.tab');  
       map {  
           $_=~/(\w+)\s+([\w\s\-]+)/;  
           $language{$1}=$2;  
       } <$fh>;  
   }  
   
   %cprtag=();  
   
   {  
      my $fh=Apache::File->new($r->dir_config('lonIncludes').'/copyright.tab');  
       map {  
           $_=~/(\w+)\s+([\w\s\-]+)/;  
           $cprtag{$1}=$2;  
       } <$fh>;  
   }    }
   
 }  }
Line 544  unless ($ENV{'form.phase'} eq 'two') { Line 1157  unless ($ENV{'form.phase'} eq 'two') {
   $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('<body bgcolor="#FFFFFF">');    $r->print(
      '<body bgcolor="#FFFFFF"><img align=right src=/adm/lonIcons/lonlogos.gif>');
   my $thisfn=$fn;    my $thisfn=$fn;
         
 # ------------------------------------------------------------- Individual file  # ------------------------------------------------------------- Individual file
   {    {
       $thisfn=~/\.(\w+)$/;        $thisfn=~/\.(\w+)$/;
       my $thistype=$1;        my $thistype=$1;
       my $thisembstyle=&Apache::lonnet::fileembstyle($thistype);        my $thisembstyle=&Apache::loncommon::fileembstyle($thistype);
   
       my $thistarget=$thisfn;        my $thistarget=$thisfn;
               
Line 562  unless ($ENV{'form.phase'} eq 'two') { Line 1176  unless ($ENV{'form.phase'} eq 'two') {
       $thisdistarget=~s/^$docroot//;        $thisdistarget=~s/^$docroot//;
   
       my $thisdisfn=$thisfn;        my $thisdisfn=$thisfn;
       $thisdisfn=~s/^\/home\/$ENV{'user.name'}\/public_html\///;        $thisdisfn=~s/^\/home\/$cuname\/public_html\///;
   
       $r->print('<h2>Publishing '.        $r->print('<h2>Publishing '.
         &Apache::lonnet::filedescription($thistype).' <tt>'.          &Apache::loncommon::filedescription($thistype).' <tt>'.
         $thisdisfn.'</tt></h2><b>Target:</b> <tt>'.$thisdistarget.'</tt><p>');          $thisdisfn.'</tt></h2><b>Target:</b> <tt>'.$thisdistarget.'</tt><p>');
      
          if (($cuname ne $ENV{'user.name'}) || ($cudom ne $ENV{'user.domain'})) {
             $r->print('<h3><font color=red>Co-Author: '.$cuname.' 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  # ------------ We are publishing from $thisfn to $thistarget with $thisembstyle
   
        unless ($ENV{'form.phase'} eq 'two') {         unless ($ENV{'form.phase'} eq 'two') {
           $r->print('<hr>'.&publish($thisfn,$thistarget,$thisembstyle));           $r->print(
             '<hr>'.&publish($thisfn,$thistarget,$thisembstyle));
        } else {         } else {
           $r->print('<hr>'.&phasetwo($thisfn,$thistarget,$thisembstyle));                 $r->print(
             '<hr>'.&phasetwo($thisfn,$thistarget,$thisembstyle,$thisdistarget)); 
        }           }  
   
   }    }
Line 585  unless ($ENV{'form.phase'} eq 'two') { Line 1212  unless ($ENV{'form.phase'} eq 'two') {
 1;  1;
 __END__  __END__
   
   =head1 NAME
   
   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
   
   =cut

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


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