Diff for /loncom/publisher/lonpublisher.pm between versions 1.97 and 1.303

version 1.97, 2002/09/18 15:43:06 version 1.303, 2023/07/14 22:19:22
Line 25 Line 25
 #  #
 # http://www.lon-capa.org/  # http://www.lon-capa.org/
 #  #
 #   
 # (TeX Content Handler  
 #  
 # 05/29/00,05/30,10/11 Gerd Kortemeyer)  
 #  
 # 11/28,11/29,11/30,12/01,12/02,12/04,12/23 Gerd Kortemeyer  
 # 03/23 Guy Albertelli  
 # 03/24,03/29,04/03 Gerd Kortemeyer  
 # 04/16/2001 Scott Harrison  
 # 05/03,05/05,05/07 Gerd Kortemeyer  
 # 05/28/2001 Scott Harrison  
 # 06/23,08/07,08/11,8/13,8/17,8/18,8/24,9/26,10/16 Gerd Kortemeyer  
 # 12/04,12/05 Guy Albertelli  
 # 12/05 Gerd Kortemeyer  
 # 12/05 Guy Albertelli  
 # 12/06,12/07 Gerd Kortemeyer  
 # 12/15,12/16 Scott Harrison  
 # 12/25 Gerd Kortemeyer  
 # YEAR=2002  
 # 1/16,1/17 Scott Harrison  
 # 1/17 Gerd Kortemeyer  
 #  
 ###  ###
   
 ###############################################################################  ###############################################################################
Line 86  invocation by F<loncapa_apache.conf>: Line 64  invocation by F<loncapa_apache.conf>:
   ErrorDocument     500 /adm/errorhandler    ErrorDocument     500 /adm/errorhandler
   </Location>    </Location>
   
   =head1 OVERVIEW
   
   Authors can only write-access the C</priv/domain/authorname/> space. 
   They can copy resources into the resource area through the 
   publication step, and move them back through a recover step. 
   Authors do not have direct write-access to their resource space.
   
   During the publication step, several events will be
   triggered. Metadata is gathered, where a wizard manages default
   entries on a hierarchical per-directory base: The wizard imports the
   metadata (including access privileges and royalty information) from
   the most recent published resource in the current directory, and if
   that is not available, from the next directory above, etc. The Network
   keeps all previous versions of a resource and makes them available by
   an explicit version number, which is inserted between the file name
   and extension, for example C<foo.2.html>, while the most recent
   version does not carry a version number (C<foo.html>). Servers
   subscribing to a changed resource are notified that a new version is
   available.
   
 =head1 DESCRIPTION  =head1 DESCRIPTION
   
 B<lonpublisher> takes the proper steps to add resources to the LON-CAPA  B<lonpublisher> takes the proper steps to add resources to the LON-CAPA
Line 104  to publication space. Line 102  to publication space.
 Many of the undocumented subroutines implement various magical  Many of the undocumented subroutines implement various magical
 parsing shortcuts.  parsing shortcuts.
   
 =over 4  
   
 =cut  =cut
   
 ######################################################################  ######################################################################
Line 120  use Apache::File; Line 116  use Apache::File;
 use File::Copy;  use File::Copy;
 use Apache::Constants qw(:common :http :methods);  use Apache::Constants qw(:common :http :methods);
 use HTML::LCParser;  use HTML::LCParser;
   use HTML::Entities;
   use Encode::Encoder;
 use Apache::lonxml;  use Apache::lonxml;
 use Apache::lonhomework;  
 use Apache::loncacc;  
 use DBI;  use DBI;
 use Apache::lonnet();  use Apache::lonnet;
 use Apache::loncommon();  use Apache::loncommon();
   use Apache::lonhtmlcommon;
 use Apache::lonmysql;  use Apache::lonmysql;
   use Apache::lonlocal;
 my %addid;  use Apache::loncfile;
 my %nokey;  use LONCAPA::lonmetadata;
   use Apache::lonmsg;
 my %metadatafields;  use vars qw(%metadatafields %metadatakeys %addid $readit);
 my %metadatakeys;  use LONCAPA qw(:DEFAULT :match);
    
 my $docroot;  my $docroot;
   
 my $cuname;  my $cuname;
 my $cudom;  my $cudom;
   
 #########################################  my $registered_cleanup;
 #########################################  my $modified_urls;
   
   my $lock;
   
 =pod  =pod
   
   =over 4
   
 =item B<metaeval>  =item B<metaeval>
   
 Evaluates a string that contains metadata.  This subroutine  Evaluates a string that contains metadata.  This subroutine
Line 169  nothing Line 170  nothing
   
 #########################################  #########################################
 #########################################  #########################################
   #
   # Modifies global %metadatafields %metadatakeys 
   #
   
 sub metaeval {  sub metaeval {
     my $metastring=shift;      my ($metastring,$prefix)=@_;
         
         my $parser=HTML::LCParser->new(\$metastring);      my $parser=HTML::LCParser->new(\$metastring);
         my $token;      my $token;
         while ($token=$parser->get_token) {      while ($token=$parser->get_token) {
            if ($token->[0] eq 'S') {   if ($token->[0] eq 'S') {
       my $entry=$token->[1];      my $entry=$token->[1];
               my $unikey=$entry;      my $unikey=$entry;
               if (defined($token->[2]->{'package'})) {       next if ($entry =~ m/^(?:parameter|stores)_/);
                   $unikey.='_package_'.$token->[2]->{'package'};      if (defined($token->[2]->{'package'})) { 
               }    $unikey.="\0package\0".$token->[2]->{'package'};
               if (defined($token->[2]->{'part'})) {       } 
                  $unikey.='_'.$token->[2]->{'part'};       if (defined($token->[2]->{'part'})) { 
       }   $unikey.="\0".$token->[2]->{'part'}; 
               if (defined($token->[2]->{'id'})) {       }
                   $unikey.='_'.$token->[2]->{'id'};      if (defined($token->[2]->{'id'})) { 
               }    $unikey.="\0".$token->[2]->{'id'};
               if (defined($token->[2]->{'name'})) {       } 
                  $unikey.='_'.$token->[2]->{'name'};       if (defined($token->[2]->{'name'})) { 
       }   $unikey.="\0".$token->[2]->{'name'}; 
               foreach (@{$token->[3]}) {      }
   $metadatafields{$unikey.'.'.$_}=$token->[2]->{$_};      foreach my $item (@{$token->[3]}) {
                   if ($metadatakeys{$unikey}) {   $metadatafields{$unikey.'.'.$item}=$token->[2]->{$item};
       $metadatakeys{$unikey}.=','.$_;   if ($metadatakeys{$unikey}) {
                   } else {      $metadatakeys{$unikey}.=','.$item;
                       $metadatakeys{$unikey}=$_;   } else {
                   }      $metadatakeys{$unikey}=$item;
               }   }
               if ($metadatafields{$unikey}) {      }
   my $newentry=$parser->get_text('/'.$entry);      my $newentry=$parser->get_text('/'.$entry);
                   unless (($metadatafields{$unikey}=~/$newentry/) ||      if (($entry eq 'customdistributionfile') ||
                           ($newentry eq '')) {   ($entry eq 'sourcerights')) {
                      $metadatafields{$unikey}.=', '.$newentry;   $newentry=~s/^\s*//;
   }   if ($newentry !~m|^/res|) { $newentry=$prefix.$newentry; }
       } else {      }
                  $metadatafields{$unikey}=$parser->get_text('/'.$entry);  # actually store
               }      if ( $entry eq 'rule' && exists($metadatafields{$unikey})) {
           }   $metadatafields{$unikey}.=','.$newentry;
        }      } else {
    $metadatafields{$unikey}=$newentry;
       }
    }
       }
 }  }
   
 #########################################  #########################################
Line 249  XHTML text that indicates successful rea Line 258  XHTML text that indicates successful rea
 #########################################  #########################################
 #########################################  #########################################
 sub metaread {  sub metaread {
     my ($logfile,$fn)=@_;      my ($logfile,$fn,$prefix)=@_;
     unless (-e $fn) {      unless (-e $fn) {
  print($logfile 'No file '.$fn."\n");   print($logfile 'No file '.$fn."\n");
         return '<br><b>No file:</b> <tt>'.$fn.'</tt>';          return '<p class="LC_warning">'
                 .&mt('No file: [_1]',&Apache::loncfile::display($fn))
                 .'</p>';
     }      }
     print($logfile 'Processing '.$fn."\n");      print($logfile 'Processing '.$fn."\n");
     my $metastring;      my $metastring;
     {      {
      my $metafh=Apache::File->new($fn);   my $metafh=Apache::File->new($fn);
      $metastring=join('',<$metafh>);   $metastring=join('',<$metafh>);
     }      }
     &metaeval($metastring);      &metaeval($metastring,$prefix);
     return '<br><b>Processed file:</b> <tt>'.$fn.'</tt>';      return '<p class="LC_info">'
             .&mt('Processed file: [_1]',&Apache::loncfile::display($fn))
             .'</p>';
 }  }
   
 #########################################  #########################################
 #########################################  #########################################
   
 =pod  sub coursedependencies {
       my $url=&Apache::lonnet::declutter(shift);
 =item B<sqltime>      $url=~s/\.meta$//;
       my ($adomain,$aauthor)=($url=~ m{^($match_domain)/($match_username)/});
 Convert 'time' format into a datetime sql format      my $regexp=quotemeta($url);
       $regexp='___'.$regexp.'___course';
 Parameters:      my %evaldata=&Apache::lonnet::dump('nohist_resevaldata',$adomain,
          $aauthor,$regexp);
 =over 4      my %courses=();
       foreach my $item (keys(%evaldata)) {
 =item I<$timef>   if ($item=~/^([a-zA-Z0-9]+_[a-zA-Z0-9]+)___.+___course$/) {
       $courses{$1}=1;
 Seconds since 00:00:00 UTC, January 1, 1970.          }
       }
 =back      return %courses;
   
 Returns:  
   
 =over 4  
   
 =item Scalar string  
   
 MySQL-compatible datetime string.  
   
 =back  
   
 =cut  
   
 #########################################  
 #########################################  
 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";  
 }  }
   
   
 #########################################  #########################################
 #########################################  #########################################
   
   
 =pod  =pod
   
 =item Form-field-generating subroutines.  =item Form-field-generating subroutines.
Line 323  string which presents the form field (fo Line 314  string which presents the form field (fo
   
 =item B<textfield>  =item B<textfield>
   
   =item B<text_with_browse_field>
   
 =item B<hiddenfield>  =item B<hiddenfield>
   
   =item B<checkbox>
   
 =item B<selectbox>  =item B<selectbox>
   
 =back  =back
Line 334  string which presents the form field (fo Line 329  string which presents the form field (fo
 #########################################  #########################################
 #########################################  #########################################
 sub textfield {  sub textfield {
     my ($title,$name,$value)=@_;      my ($title,$name,$value,$noline,$readonly)=@_;
     return "\n<p><b>$title:</b><br>".      $value=~s/^\s+//gs;
            '<input type="text" name="'.$name.'" size=80 value="'.$value.'" />';      $value=~s/\s+$//gs;
       $value=~s/\s+/ /gs;
       $title=&mt($title);
       $env{'form.'.$name}=$value;
       return "\n".&Apache::lonhtmlcommon::row_title($title)
              .'<input type="text" name="'.$name.'" size="80" value="'.$value.'" />'
              .&Apache::lonhtmlcommon::row_closure($noline);
   }
   
   sub text_with_browse_field {
       my ($title,$name,$value,$restriction,$noline,$readonly)=@_;
       $value=~s/^\s+//gs;
       $value=~s/\s+$//gs;
       $value=~s/\s+/ /gs;
       $title=&mt($title);
       $env{'form.'.$name}=$value;
       my $disabled;
       if ($readonly) {
           $disabled = ' disabled="disabled"';
       }
       my $output =
             "\n".&Apache::lonhtmlcommon::row_title($title)
             .'<input type="text" name="'.$name.'" size="80" value="'.$value.'"'.$disabled.' />';
       unless ($readonly) {
           $output .=
             '<br />'
     .'<a href="javascript:openbrowser(\'pubform\',\''.$name.'\',\''.$restriction.'\');">'
             .&mt('Select')
             .'</a>&nbsp;'
     .'<a href="javascript:opensearcher(\'pubform\',\''.$name.'\');">'
             .&mt('Search')
             .'</a>';
       }
       $output .= &Apache::lonhtmlcommon::row_closure($noline);
       return $output;
 }  }
   
 sub hiddenfield {  sub hiddenfield {
     my ($name,$value)=@_;      my ($name,$value)=@_;
       $env{'form.'.$name}=$value;
     return "\n".'<input type="hidden" name="'.$name.'" value="'.$value.'" />';      return "\n".'<input type="hidden" name="'.$name.'" value="'.$value.'" />';
 }  }
   
   sub checkbox {
       my ($name,$text)=@_;
       return "\n<label><input type='checkbox' name='$name' /> ".
    &mt($text)."</label>";
   }
   
 sub selectbox {  sub selectbox {
     my ($title,$name,$value,$functionref,@idlist)=@_;      my ($title,$name,$value,$readonly,$functionref,@idlist)=@_;
     my $uctitle=uc($title);      $title=&mt($title);
     my $selout="\n<p><font color=\"#800000\" face=\"helvetica\"><b>$uctitle:".      $value=(split(/\s*,\s*/,$value))[-1];
  "</b></font><br />".'<select name="'.$name.'">';      if (defined($value)) {
     foreach (@idlist) {   $env{'form.'.$name}=$value;
         $selout.='<option value=\''.$_.'\'';      } else {
         if ($_ eq $value) {   $env{'form.'.$name}=$idlist[0];
     $selout.=' selected>'.&{$functionref}($_).'</option>';      }
  }      my $selout="\n".&Apache::lonhtmlcommon::row_title($title)
         else {$selout.='>'.&{$functionref}($_).'</option>';}                .'<select name="'.$name.'">';
       foreach my $id (@idlist) {
           $selout.='<option value="'.$id.'"';
           if ($id eq $value) {
       $selout.=' selected="selected"';
           }
           if ($readonly) {
               $selout .= ' disabled="disabled"';
           }
           $selout.='>'.&{$functionref}($id).'</option>';
     }      }
     return $selout.'</select>';      $selout.='</select>'.&Apache::lonhtmlcommon::row_closure();
       return $selout;
   }
   
   sub select_level_form {
       my ($value,$name)=@_;
       $env{'form.'.$name}=$value;
       if (!defined($value)) { $env{'form.'.$name}=0; }
       return  &Apache::loncommon::select_level_form($value,$name);
   }
   
   sub common_access {
       my ($name,$text,$options)=@_;
       return unless (ref($options) eq 'ARRAY');
       my $formname = 'pubdirpref';
       my $chkname = 'common'.$name;
       my $chkid = 'LC_'.$chkname;
       my $divid = $chkid.'div';
       my $customdivid = 'LC_customfile'; 
       my $selname = $chkname.'select';
       my $selid = $chkid.'select';
       my $selonchange;
       if ($name eq 'dist') {
           $selonchange = ' onchange="showHideCustom(this,'."'$customdivid'".');"';
       }
       my %lt = &Apache::lonlocal::texthash(
                                               'default' => 'System wide - can be used for any courses system wide',
                                               'domain'  => 'Domain only - use limited to courses in the domai',
                                               'custom'  => 'Customized right of use ...',
                                               'public'  => 'Public - no authentication or authorization required for use',
                                               'closed'  => 'Closed - XML source is closed to everyone',
                                               'open'    => 'Open - XML source is open to people who want to use it',
                                               'sel'     => 'Select',
                                           );
       my $output = <<"END";
   <span class="LC_nobreak">
   <label>
   <input type="checkbox" name="commonaccess" value="$name" id="$chkid"  
   onclick="showHideAccess(this,'$divid');" />
   $text</label></span>
   <div id="$divid" style="padding:0;clear:both;margin:0;border:0;display:none">
   <select name="$selname" id="$selid" $selonchange>
   <option value="" selected="selected">$lt{'sel'}</option>
   END
       foreach my $val (@{$options}) {
           $output .= '<option value="'.$val.'">'.$lt{$val}.'</option>'."\n";
       }
       $output .= '
   </select>';
       if ($name eq 'dist') {
           $output .= <<"END";
   <div id="$customdivid" style="padding:0;clear:both;margin:0;border:0;display:none">
   <input type="text" name="commoncustomrights" size="60" value="" />
   <a href="javascript:openbrowser('$formname','commoncustomrights','rights');">
   $lt{'sel'}</a></div>
   END
       }
       $output .= '
   </div>
   ';
 }  }
   
 #########################################  #########################################
Line 380  sub urlfixup { Line 484  sub urlfixup {
     if ($url =~ /^mailto:/i) { return $url; }      if ($url =~ /^mailto:/i) { return $url; }
     #internal document links need no fixing      #internal document links need no fixing
     if ($url =~ /^\#/) { return $url; }       if ($url =~ /^\#/) { return $url; } 
     my ($host)=($url=~/(?:http\:\/\/)*([^\/]+)/);      my ($host)=($url=~m{(?:(?:http|https|ftp)://)*([^/]+)});
     foreach (values %Apache::lonnet::hostname) {      my @lonids = &Apache::lonnet::machine_ids($host);
  if ($_ eq $host) {      if (@lonids) {
     $url=~s/^http\:\/\///;   $url=~s{^(?:http|https|ftp)://}{};
             $url=~s/^$host//;   $url=~s/^\Q$host\E//;
         }  
     }      }
     if ($url=~/^http\:\/\//) { return $url; }      if ($url=~m{^(?:http|https|ftp)://}) { return $url; }
     $url=~s/\~$cuname/res\/$cudom\/$cuname/;      $url=~s{\Q~$cuname\E}{res/$cudom/$cuname};
     return $url;      return $url;
 }  }
   
Line 429  Currently undocumented Line 532  Currently undocumented
 #########################################  #########################################
 #########################################  #########################################
 sub set_allow {  sub set_allow {
     my ($allow,$logfile,$target,$tag,$oldurl)=@_;      my ($allow,$logfile,$target,$tag,$oldurl,$type)=@_;
     my $newurl=&urlfixup($oldurl,$target);      my $newurl=&urlfixup($oldurl,$target);
     my $return_url=$oldurl;      my $return_url=$oldurl;
     print $logfile 'GUYURL: '.$tag.':'.$oldurl.' - '.$newurl."\n";      print $logfile 'GUYURL: '.$tag.':'.$oldurl.' - '.$newurl."\n";
Line 439  sub set_allow { Line 542  sub set_allow {
     }      }
     if (($newurl !~ /^javascript:/i) &&      if (($newurl !~ /^javascript:/i) &&
  ($newurl !~ /^mailto:/i) &&   ($newurl !~ /^mailto:/i) &&
  ($newurl !~ /^http:/i) &&   ($newurl !~ /^(?:http|https|ftp):/i) &&
  ($newurl !~ /^\#/)) {   ($newurl !~ /^\#/)) {
           if (($type eq 'src') || ($type eq 'href')) {
               if ($newurl =~ /^([^?]+)\?[^?]*$/) {
                   $newurl = $1;
               }
           }
  $$allow{&absoluteurl($newurl,$target)}=1;   $$allow{&absoluteurl($newurl,$target)}=1;
     }      }
     return $return_url      return $return_url;
 }  }
   
 #########################################  #########################################
Line 466  sub get_subscribed_hosts { Line 574  sub get_subscribed_hosts {
     $target=~/(.*)\/([^\/]+)$/;      $target=~/(.*)\/([^\/]+)$/;
     my $srcf=$2;      my $srcf=$2;
     opendir(DIR,$1);      opendir(DIR,$1);
       # cycle through listed files, subscriptions used to exist
       # as "filename.lonid"
     while ($filename=readdir(DIR)) {      while ($filename=readdir(DIR)) {
  if ($filename=~/$srcf\.(\w+)$/) {   if ($filename=~/\Q$srcf\E\.($match_lonid)$/) {
     my $subhost=$1;      my $subhost=$1;
     if ($subhost ne 'meta' && $subhost ne 'subscription') {      if (($subhost ne 'meta' 
    && $subhost ne 'subscription' 
    && $subhost ne 'meta.subscription'
    && $subhost ne 'tmp') &&
                   ($subhost ne $Apache::lonnet::perlvar{'lonHostID'})) {
  push(@subscribed,$subhost);   push(@subscribed,$subhost);
     }      }
  }   }
Line 477  sub get_subscribed_hosts { Line 591  sub get_subscribed_hosts {
     closedir(DIR);      closedir(DIR);
     my $sh;      my $sh;
     if ( $sh=Apache::File->new("$target.subscription") ) {      if ( $sh=Apache::File->new("$target.subscription") ) {
  &Apache::lonnet::logthis("opened $target.subscription");  
  while (my $subline=<$sh>) {   while (my $subline=<$sh>) {
     &Apache::lonnet::logthis("Trying $subline");      if ($subline =~ /^($match_lonid):/) { 
     if ($subline =~ /(^\w+):/) { push(@subscribed,$1); } else {                  if ($1 ne $Apache::lonnet::perlvar{'lonHostID'}) { 
  &Apache::lonnet::logthis("No Match for $subline");                     push(@subscribed,$1);
           }
     }      }
  }   }
     } else {  
  &Apache::lonnet::logthis("Unable to open $target.subscription");  
     }      }
     &Apache::lonnet::logthis("Got list of ".join(':',@subscribed));  
     return @subscribed;      return @subscribed;
 }  }
   
Line 510  sub get_max_ids_indices { Line 621  sub get_max_ids_indices {
     my $maxindex=10;      my $maxindex=10;
     my $maxid=10;      my $maxid=10;
     my $needsfixup=0;      my $needsfixup=0;
       my $duplicateids=0;
   
       my %allids;
       my %duplicatedids;
   
     my $parser=HTML::LCParser->new($content);      my $parser=HTML::LCParser->new($content);
       $parser->xml_mode(1);
     my $token;      my $token;
     while ($token=$parser->get_token) {      while ($token=$parser->get_token) {
  if ($token->[0] eq 'S') {   if ($token->[0] eq 'S') {
     my $counter;      my $counter;
     if ($counter=$addid{$token->[1]}) {      if ($counter=$addid{$token->[1]}) {
  if ($counter eq 'id') {   if ($counter eq 'id') {
     if (defined($token->[2]->{'id'})) {      if (defined($token->[2]->{'id'}) &&
    $token->[2]->{'id'} !~ /^\s*$/) {
  $maxid=($token->[2]->{'id'}>$maxid)?$token->[2]->{'id'}:$maxid;   $maxid=($token->[2]->{'id'}>$maxid)?$token->[2]->{'id'}:$maxid;
    if (exists($allids{$token->[2]->{'id'}})) {
       $duplicateids=1;
       $duplicatedids{$token->[2]->{'id'}}=1;
    } else {
       $allids{$token->[2]->{'id'}}=1;
    }
     } else {      } else {
  $needsfixup=1;   $needsfixup=1;
     }      }
  } else {   } else {
     if (defined($token->[2]->{'index'})) {      if (defined($token->[2]->{'index'}) &&
    $token->[2]->{'index'} !~ /^\s*$/) {
  $maxindex=($token->[2]->{'index'}>$maxindex)?$token->[2]->{'index'}:$maxindex;   $maxindex=($token->[2]->{'index'}>$maxindex)?$token->[2]->{'index'}:$maxindex;
     } else {      } else {
  $needsfixup=1;   $needsfixup=1;
Line 533  sub get_max_ids_indices { Line 657  sub get_max_ids_indices {
     }      }
  }   }
     }      }
     return ($needsfixup,$maxid,$maxindex);      return ($needsfixup,$maxid,$maxindex,$duplicateids,
       (keys(%duplicatedids)));
 }  }
   
 #########################################  #########################################
Line 565  sub get_all_text_unbalanced { Line 690  sub get_all_text_unbalanced {
  } elsif ($token->[0] eq 'E')  {   } elsif ($token->[0] eq 'E')  {
     $result.=$token->[2];      $result.=$token->[2];
  }   }
  if ($result =~ /(.*)$tag(.*)/) {   if ($result =~ /\Q$tag\E/s) {
       ($result,my $redo)=$result =~ /(.*)\Q$tag\E(.*)/is;
     #&Apache::lonnet::logthis('Got a winner with leftovers ::'.$2);      #&Apache::lonnet::logthis('Got a winner with leftovers ::'.$2);
     #&Apache::lonnet::logthis('Result is :'.$1);      #&Apache::lonnet::logthis('Result is :'.$1);
     $result=$1;      $redo=$tag.$redo;
     my $redo=$tag.$2;  
     push (@$pars,HTML::LCParser->new(\$redo));      push (@$pars,HTML::LCParser->new(\$redo));
     $$pars[-1]->xml_mode('1');      $$pars[-1]->xml_mode('1');
     last;      last;
Line 602  sub fix_ids_and_indices { Line 727  sub fix_ids_and_indices {
  $content=join('',<$org>);   $content=join('',<$org>);
     }      }
   
     my ($needsfixup,$maxid,$maxindex)=&get_max_ids_indices(\$content);      my ($needsfixup,$maxid,$maxindex,$duplicateids,@duplicatedids)=
    &get_max_ids_indices(\$content);
   
       print $logfile ("Got $needsfixup,$maxid,$maxindex,$duplicateids--".
      join(', ',@duplicatedids));
       if ($duplicateids) {
    print $logfile "Duplicate ID(s) exist, ".join(', ',@duplicatedids)."\n";
    my $outstring='<span class="LC_error">'.&mt('Unable to publish file, it contains duplicated ID(s), ID(s) need to be unique. The duplicated ID(s) are').': '.join(', ',@duplicatedids).'</span>';
    return ($outstring,1);
       }
     if ($needsfixup) {      if ($needsfixup) {
  print $logfile "Needs ID and/or index fixup\n".   print $logfile "Needs ID and/or index fixup\n".
     "Max ID   : $maxid (min 10)\n".      "Max ID   : $maxid (min 10)\n".
                 "Max Index: $maxindex (min 10)\n";                  "Max Index: $maxindex (min 10)\n";
     }      }
     my $outstring='';      my $outstring='';
       my $responsecounter=1;
     my @parser;      my @parser;
     $parser[0]=HTML::LCParser->new(\$content);      $parser[0]=HTML::LCParser->new(\$content);
     $parser[-1]->xml_mode(1);      $parser[-1]->xml_mode(1);
Line 624  sub fix_ids_and_indices { Line 758  sub fix_ids_and_indices {
     $allow{$token->[2]->{'src'}}=1;      $allow{$token->[2]->{'src'}}=1;
     next;      next;
  }   }
    if ($lctag eq 'base') { next; }
                   if (($lctag eq 'part') || ($lctag eq 'problem')) {
                       $responsecounter=0;
                   }
                   if ($lctag=~/response$/) { $responsecounter++; }
                   if ($lctag eq 'import') { $responsecounter++; }
  my %parms=%{$token->[2]};   my %parms=%{$token->[2]};
  $counter=$addid{$tag};   $counter=$addid{$tag};
  if (!$counter) { $counter=$addid{$lctag}; }   if (!$counter) { $counter=$addid{$lctag}; }
  if ($counter) {   if ($counter) {
     if ($counter eq 'id') {      if ($counter eq 'id') {
  unless (defined($parms{'id'})) {   unless (defined($parms{'id'}) &&
    $parms{'id'}!~/^\s*$/) {
     $maxid++;      $maxid++;
     $parms{'id'}=$maxid;      $parms{'id'}=$maxid;
     print $logfile 'ID: '.$tag.':'.$maxid."\n";      print $logfile 'ID(new) : '.$tag.':'.$maxid."\n";
    } else {
       print $logfile 'ID(kept): '.$tag.':'.$parms{'id'}."\n";
  }   }
     } elsif ($counter eq 'index') {      } elsif ($counter eq 'index') {
  unless (defined($parms{'index'})) {   unless (defined($parms{'index'}) &&
    $parms{'index'}!~/^\s*$/) {
     $maxindex++;      $maxindex++;
     $parms{'index'}=$maxindex;      $parms{'index'}=$maxindex;
     print $logfile 'Index: '.$tag.':'.$maxindex."\n";      print $logfile 'Index: '.$tag.':'.$maxindex."\n";
  }   }
     }      }
  }   }
  foreach my $type ('src','href','background','bgimg') {                  unless ($parms{'type'} eq 'zombie') {
     foreach my $key (keys(%parms)) {      foreach my $type ('src','href','background','bgimg') {
  if ($key =~ /^$type$/i) {   foreach my $key (keys(%parms)) {
     $parms{$key}=&set_allow(\%allow,$logfile,      if ($key =~ /^$type$/i) {
     $target,$tag,                                  next if (($lctag eq 'img') && ($type eq 'src') && 
     $parms{$key});                                           ($parms{$key} =~ m{^data\:image/gif;base64,}));
    $parms{$key}=&set_allow(\%allow,$logfile,
    $target,$tag,
    $parms{$key},$type);
       }
  }   }
     }      }
  }   }
  # probably a <randomlabel> image type <label>   # probably a <randomlabel> image type <label>
  if ($lctag eq 'label' && defined($parms{'description'})) {   # or a <image> tag inside <imageresponse>
    if (($lctag eq 'label' && defined($parms{'description'}))
       ||
       ($lctag eq 'image')) {
     my $next_token=$parser[-1]->get_token();      my $next_token=$parser[-1]->get_token();
     if ($next_token->[0] eq 'T') {      if ($next_token->[0] eq 'T') {
                           $next_token->[1] =~ s/[\n\r\f]+//g;
  $next_token->[1]=&set_allow(\%allow,$logfile,   $next_token->[1]=&set_allow(\%allow,$logfile,
     $target,$tag,      $target,$tag,
     $next_token->[1]);      $next_token->[1]);
Line 663  sub fix_ids_and_indices { Line 815  sub fix_ids_and_indices {
  }   }
  if ($lctag eq 'applet') {   if ($lctag eq 'applet') {
     my $codebase='';      my $codebase='';
     if (defined($parms{'codebase'})) {      my $havecodebase=0;
  my $oldcodebase=$parms{'codebase'};      foreach my $key (keys(%parms)) {
    if (lc($key) eq 'codebase') { 
       $codebase=$parms{$key};
       $havecodebase=1; 
    }
       }
       if ($havecodebase) {
    my $oldcodebase=$codebase;
  unless ($oldcodebase=~/\/$/) {   unless ($oldcodebase=~/\/$/) {
     $oldcodebase.='/';      $oldcodebase.='/';
  }   }
Line 678  sub fix_ids_and_indices { Line 837  sub fix_ids_and_indices {
  }   }
  $allow{&absoluteurl($codebase,$target).'/*'}=1;   $allow{&absoluteurl($codebase,$target).'/*'}=1;
     } else {      } else {
  foreach ('archive','code','object') {   foreach my $key (keys(%parms)) {
     if (defined($parms{$_})) {      if ($key =~ /(archive|code|object)/i) {
  my $oldurl=$parms{$_};   my $oldurl=$parms{$key};
  my $newurl=&urlfixup($oldurl,$target);   my $newurl=&urlfixup($oldurl,$target);
  $newurl=~s/\/[^\/]+$/\/\*/;   $newurl=~s/\/[^\/]+$/\/\*/;
  print $logfile 'Allow: applet '.$_.':'.   print $logfile 'Allow: applet '.lc($key).':'.
     $oldurl.' allows '.      $oldurl.' allows '.$newurl."\n";
  $newurl."\n";  
  $allow{&absoluteurl($newurl,$target)}=1;   $allow{&absoluteurl($newurl,$target)}=1;
     }      }
  }   }
Line 693  sub fix_ids_and_indices { Line 851  sub fix_ids_and_indices {
  }   }
  my $newparmstring='';   my $newparmstring='';
  my $endtag='';   my $endtag='';
  foreach (keys %parms) {   foreach my $parkey (keys(%parms)) {
     if ($_ eq '/') {      if ($parkey eq '/') {
  $endtag=' /';   $endtag=' /';
     } else {       } else { 
  my $quote=($parms{$_}=~/\"/?"'":'"');   my $quote=($parms{$parkey}=~/\"/?"'":'"');
  $newparmstring.=' '.$_.'='.$quote.$parms{$_}.$quote;   $newparmstring.=' '.$parkey.'='.$quote.$parms{$parkey}.$quote;
     }      }
  }   }
  if (!$endtag) { if ($token->[4]=~m:/>$:) { $endtag=' /'; }; }   if (!$endtag) { if ($token->[4]=~m:/>$:) { $endtag=' /'; }; }
  $outstring.='<'.$tag.$newparmstring.$endtag.'>';   $outstring.='<'.$tag.$newparmstring.$endtag.'>';
  if ($lctag eq 'm') {   if ($lctag eq 'm' || $lctag eq 'answer' || $lctag eq 'display' ||
     $outstring.=&get_all_text_unbalanced('/m',\@parser);                      $lctag eq 'tex') {
  }      $outstring.=&get_all_text_unbalanced('/'.$lctag,\@parser);
                   } elsif ($lctag eq 'script') {
                       if ($parms{'type'} eq 'loncapa/perl') {
                           $outstring.=&get_all_text_unbalanced('/'.$lctag,\@parser);
                       } else {
                           my $script = &get_all_text_unbalanced('/'.$lctag,\@parser);
                           if ($script =~ m{\.set\w+(Src|Swf)\(["']}i) {
                               my @srcs = split(/\.set/i,$script);
                               if (scalar(@srcs) > 1) {
                                   foreach my $item (@srcs) {
                                       if ($item =~ m{^(FlashPlayerSwf|MediaSrc|XMPSrc|ConfigurationSrc|PosterImageSrc)\((['"])(?:(?!\2).)+\2\)}is) {
                                           my $srctype = $1;
                                           my $quote = $2;
                                           my ($url) = ($item =~ m{^\Q$srctype($quote\E([^$quote]+)\Q$quote)\E});
                                           $url = &urlfixup($url);
                                           unless ($url=~m{^(?:http|https|ftp)://}) {
                                               $allow{&absoluteurl($url,$target)}=1;
                                               if ($srctype eq 'ConfigurationSrc') {
                                                   if ($url =~ m{^(.+/)configuration_express\.xml$}) {
   #
   # Camtasia 8.1: express_show/spritesheet.png needed, and included in zip archive.
   # Not referenced directly in <main>.html or <main>_player.html files,
   # so add this file to %allow (where <main> is name user gave to file/archive).
   #
                                                       my $spritesheet = $1.'express_show/spritesheet.png';
                                                       $allow{&absoluteurl($spritesheet,$target)}=1;
   
   #
   # Camtasia 8.4: skins/express_show/spritesheet.min.css needed, and included in zip archive.
   # Not referenced directly in <main>.html or <main>_player.html files,
   # so add this file to %allow (where <main> is name user gave to file/archive).
   #
                                                       my $spritecss = $1.'express_show/spritesheet.min.css';
                                                       $allow{&absoluteurl($spritecss,$target)}=1;
                                                   }
                                               } elsif ($srctype eq 'PosterImageSrc') {
                                                   if ($url =~ m{^(.+)_First_Frame\.png$}) {
                                                       my $prefix = $1;
   #
   # Camtasia 8.1: <main>_Thumbnails.png needed, and included in zip archive.
   # Not referenced directly in <main>.html or <main>_player.html files,
   # so add this file to %allow (where <main> is name user gave to file/archive).
   #
                                                       my $thumbnail = $prefix.'_Thumbnails.png';
                                                       $allow{&absoluteurl($thumbnail,$target)}=1;
                                                   }
                                               }
                                           }
                                       }
                                   }
                               }
                           }
                           if ($script =~ m{\.addMediaSrc\((["'])((?!\1).+)\1\);}) {
                               my $src = $2;
                               if ($src) {
                                   my $url = &urlfixup($src);
                                   unless ($url=~m{^(?:http|https|ftp)://}) {
                                       $allow{&absoluteurl($url,$target)}=1;
                                   }
                               }
                           }
                           if ($script =~ /\(document,\s*(['"])script\1,\s*\[([^\]]+)\]\);/s) {
                               my $scriptslist = $2;
                               my @srcs = split(/\s*,\s*/,$scriptslist);
                               foreach my $src (@srcs) {
                                   if ($src =~ /(["'])(?:(?!\1).)+\.js\1/) {
                                       my $quote = $1;
                                       my ($url) = ($src =~ m/\Q$quote\E([^$quote]+)\Q$quote\E/);
                                       $url = &urlfixup($url);
                                       unless ($url=~m{^(?:http|https|ftp)://}) {
                                           $allow{&absoluteurl($url,$target)}=1;
                                       }
                                   }
                               }
                           }
                           if ($script =~ m{loadScript\(\s*(['"])((?:(?!\1).)+\.js)\1,\s*function}is) {
                               my $src = $2;
                               if ($src) {
                                   my $url = &urlfixup($src);
                                   unless ($url=~m{^(?:http|https|ftp)://}) {
                                       $allow{&absoluteurl($url,$target)}=1;
                                   }
                               }
                           }
                           $outstring .= $script;
                       }
                   }
     } elsif ($token->[0] eq 'E') {      } elsif ($token->[0] eq 'E') {
  if ($token->[2]) {   if ($token->[2]) {
     unless ($token->[1] eq 'allow') {      unless ($token->[1] eq 'allow') {
  $outstring.='</'.$token->[1].'>';   $outstring.='</'.$token->[1].'>';
     }      }
  }                  }
                   if ((($token->[1] eq 'part') || ($token->[1] eq 'problem'))
                       && (!$responsecounter)) {
                       my $outstring='<span class="LC_error">'.&mt('Found [_1] without responses. This resource cannot be published.',$token->[1]).'</span>';
                       return ($outstring,1);
                   }
     } else {      } else {
  $outstring.=$token->[1];   $outstring.=$token->[1];
     }      }
Line 727  sub fix_ids_and_indices { Line 976  sub fix_ids_and_indices {
  print $logfile "Does not need ID and/or index fixup\n";   print $logfile "Does not need ID and/or index fixup\n";
     }      }
   
     return ($outstring,%allow);      return ($outstring,0,%allow);
 }  }
   
 #########################################  #########################################
Line 749  Returns: (error,status).  error is undef Line 998  Returns: (error,status).  error is undef
 #########################################  #########################################
 #########################################  #########################################
 sub store_metadata {  sub store_metadata {
     my %metadata = %{shift()};      my %metadata = @_;
     my $error;      my $error;
     # Determine if the table exists      # Determine if the table exists
     my $status = &Apache::lonmysql::check_table('metadata');      my $status = &Apache::lonmysql::check_table('metadata');
     if (! defined($status)) {      if (! defined($status)) {
         $error='<font color="red">WARNING: Cannot connect to '.          $error='<span class="LC_error">'
             'database!</font>';                .&mt('WARNING: Cannot connect to database!')
                 .'</span>';
         &Apache::lonnet::logthis($error);          &Apache::lonnet::logthis($error);
         return ($error,undef);          return ($error,undef);
     }      }
     if ($status == 0) {      if ($status == 0) {
         # It would be nice to actually create the table....          # It would be nice to actually create the table....
         $error ='<font color="red">WARNING: The metadata table does not '.          $error ='<span class="LC_error">'
             'exist in the LON-CAPA database.</font>';                 .&mt('WARNING: The metadata table does not exist in the LON-CAPA database!')
                  .'</span>';
         &Apache::lonnet::logthis($error);          &Apache::lonnet::logthis($error);
         return ($error,undef);          return ($error,undef);
     }      }
     # Remove old value from table      my $dbh = &Apache::lonmysql::get_dbh();
     $status = &Apache::lonmysql::remove_from_table      if (($metadata{'obsolete'}) || ($metadata{'copyright'} eq 'priv')) {
         ('metadata','url',$metadata{'url'});          # remove this entry
     if (! defined($status)) {   my $delitem = 'url = '.$dbh->quote($metadata{'url'});
         $error = '<font color="red">Error when removing old values from '.   $status = &LONCAPA::lonmetadata::delete_metadata($dbh,undef,$delitem);
             'metadata table in LON-CAPA database.</font>';                                                         
         &Apache::lonnet::logthis($error);      } else {
         return ($error,undef);          $status = &LONCAPA::lonmetadata::update_metadata($dbh,undef,undef,
                                                            \%metadata);
     }      }
     # Store data in table.      if (defined($status) && $status ne '') {
     $status = &Apache::lonmysql::store_row('metadata',\%metadata);          $error='<span class="LC_error">'
     if (! defined($status)) {                .&mt('Error occurred saving new values in metadata table in LON-CAPA database!')
         $error='<font color="red">Error occured storing new values in '.                .'</span>';
             'metadata table in LON-CAPA database</font>';  
         &Apache::lonnet::logthis($error);          &Apache::lonnet::logthis($error);
           &Apache::lonnet::logthis($status);
         return ($error,undef);          return ($error,undef);
     }      }
     return (undef,$status);      return (undef,'success');
   }
   
   
   # ========================================== Parse file for errors and warnings
   
   sub checkonthis {
       my ($r,$source)=@_;
       my $uri=&Apache::lonnet::hreflocation($source);
       $uri=~s/\/$//;
       my $result=&Apache::lonnet::ssi_body($uri,
    ('grade_target'=>'web',
     'return_only_error_and_warning_counts' => 1));
       my ($errorcount,$warningcount)=split(':',$result);
       if (($errorcount) || ($warningcount)) {
           $r->print('<h3>'.&mt('Warnings and Errors').'</h3>');
           $r->print('<tt>'.$uri.'</tt>:');
           $r->print('<ul>');
           if ($warningcount) {
               $r->print('<li><div class="LC_warning">'
                        .&mt('[quant,_1,warning]',$warningcount)
                        .'</div></li>');
           }
           if ($errorcount) {
               $r->print('<li><div class="LC_error">'
                        .&mt('[quant,_1,error]',$errorcount)
                        .' <img src="/adm/lonMisc/bomb.gif" />'
                        .'</div></li>');
           }
           $r->print('</ul>');
       } else {
    #$r->print('<font color="green">'.&mt('ok').'</font>');
       }
       $r->rflush();
       return ($warningcount,$errorcount);
   }
   
   # ============================================== Parse file itself for metadata
   #
   # parses a file with target meta, sets global %metadatafields %metadatakeys 
   
   sub parseformeta {
       my ($source,$style)=@_;
       my $allmeta='';
       if (($style eq 'ssi') || ($style eq 'prv')) {
    my $dir=$source;
    $dir=~s-/[^/]*$--;
    my $file=$source;
    $file=(split('/',$file))[-1];
           $source=&Apache::lonnet::hreflocation($dir,$file);
    $allmeta=&Apache::lonnet::ssi_body($source,('grade_target' => 'meta'));
           &metaeval($allmeta);
       }
       return $allmeta;
 }  }
   
 #########################################  #########################################
Line 797  This is the workhorse function of this m Line 1102  This is the workhorse function of this m
 backup copies, performs any automatic processing (prior to publication,  backup copies, performs any automatic processing (prior to publication,
 especially for rat and ssi files),  especially for rat and ssi files),
   
   Returns a 2 element array, the first is the string to be shown to the
   user, the second is an error code, either 1 (an error occurred) or 0
   (no error occurred)
   
 I<Additional documentation needed.>  I<Additional documentation needed.>
   
 =cut  =cut
Line 805  I<Additional documentation needed.> Line 1114  I<Additional documentation needed.>
 #########################################  #########################################
 sub publish {  sub publish {
   
     my ($source,$target,$style,$batch)=@_;      my ($source,$target,$style,$batch,$nokeyref)=@_;
     my $logfile;      my $logfile;
     my $scrout='';      my $scrout='';
     my $allmeta='';      my $allmeta='';
Line 813  sub publish { Line 1122  sub publish {
     my %allow=();      my %allow=();
   
     unless ($logfile=Apache::File->new('>>'.$source.'.log')) {      unless ($logfile=Apache::File->new('>>'.$source.'.log')) {
  return    return ('<span class="LC_error">'.&mt('No write permission to user directory, FAIL').'</span>',1);
          '<font color=red>No write permission to user directory, FAIL</font>';  
     }      }
     print $logfile       print $logfile 
 "\n\n================= Publish ".localtime()." Phase One  ================\n";  "\n\n================= Publish ".localtime()." Phase One  ================\n".$env{'user.name'}.':'.$env{'user.domain'}."\n";
   
     if (($style eq 'ssi') || ($style eq 'rat')) {      if (($style eq 'ssi') || ($style eq 'rat') || ($style eq 'prv')) {
 # ------------------------------------------------------- This needs processing  # ------------------------------------------------------- This needs processing
   
 # ----------------------------------------------------------------- Backup Copy  # ----------------------------------------------------------------- Backup Copy
Line 828  sub publish { Line 1136  sub publish {
     print $logfile "Copied original file to ".$copyfile."\n";      print $logfile "Copied original file to ".$copyfile."\n";
         } else {          } else {
     print $logfile "Unable to write backup ".$copyfile.':'.$!."\n";      print $logfile "Unable to write backup ".$copyfile.':'.$!."\n";
           return "<font color=red>Failed to write backup copy, $!,FAIL</font>";      return ("<span class=\"LC_error\">".&mt("Failed to write backup copy, [_1], FAIL",$1)."</span>",1);
         }          }
 # ------------------------------------------------------------- IDs and indices  # ------------------------------------------------------------- IDs and indices
   
  my $outstring;   my ($outstring,$error);
  ($outstring,%allow)=&fix_ids_and_indices($logfile,$source,$target);   ($outstring,$error,%allow)=&fix_ids_and_indices($logfile,$source,
    $target);
    if ($error) { return ($outstring,$error); }
 # ------------------------------------------------------------ Construct Allows  # ------------------------------------------------------------ Construct Allows
           
  $scrout.='<h3>Dependencies</h3>';          my $outdep=''; # Collect dependencies output data
         my $allowstr='';          my $allowstr='';
         foreach (sort(keys(%allow))) {          foreach my $thisdep (sort(keys(%allow))) {
    my $thisdep=$_;  
    if ($thisdep !~ /[^\s]/) { next; }     if ($thisdep !~ /[^\s]/) { next; }
              if ($thisdep =~/\$/) {
                 $outdep.='<div class="LC_warning">'
                          .&mt('The resource depends on another resource with variable filename, i.e., [_1].','<tt>'.$thisdep.'</tt>').'<br />'
                          .&mt('You likely need to explicitly allow access to all possible dependencies using the [_1]-tag.','<tt>&lt;allow&gt;</tt>')
                          ."</div>\n";
              }
            unless ($style eq 'rat') {              unless ($style eq 'rat') { 
               $allowstr.="\n".'<allow src="'.$thisdep.'" />';                $allowstr.="\n".'<allow src="'.$thisdep.'" />';
    }     }
            $scrout.='<br>';            $outdep.='<div>';
            unless ($thisdep=~/\*/) {             if ($thisdep!~/[\*\$]/ && $thisdep!~m|^/adm/|) {
        $scrout.='<a href="'.$thisdep.'">';         $outdep.='<a href="'.$thisdep.'">';
            }             }
            $scrout.='<tt>'.$thisdep.'</tt>';             $outdep.='<tt>'.$thisdep.'</tt>';
            unless ($thisdep=~/\*/) {             if ($thisdep!~/[\*\$]/ && $thisdep!~m|^/adm/|) {
        $scrout.='</a>';         $outdep.='</a>';
                if (                 if (
        &Apache::lonnet::getfile($Apache::lonnet::perlvar{'lonDocRoot'}.'/'.         &Apache::lonnet::getfile($Apache::lonnet::perlvar{'lonDocRoot'}.'/'.
                                             $thisdep.'.meta') eq '-1') {                                              $thisdep.'.meta') eq '-1') {
    $scrout.= ' - <font color="red">Currently not available'.     $outdep.= ' - <span class="LC_error">'.&mt('Currently not available').
        '</font>';         '</span>';
                } else {                 } else {
   #
   # Store the fact that the dependency has been used by the target file
   # Unfortunately, usage is erroneously named sequsage in lonmeta.pm
   # The translation happens in lonmetadata.pm
   #
                    my %temphash=(&Apache::lonnet::declutter($target).'___'.                     my %temphash=(&Apache::lonnet::declutter($target).'___'.
                              &Apache::lonnet::declutter($thisdep).'___usage'                               &Apache::lonnet::declutter($thisdep).'___usage'
                                  => time);                                   => time);
                    $thisdep=~/^\/res\/(\w+)\/(\w+)\//;                     $thisdep=~m{^/res/($match_domain)/($match_username)/};
                    if ((defined($1)) && (defined($2))) {                     if ((defined($1)) && (defined($2))) {
                       &Apache::lonnet::put('nohist_resevaldata',\%temphash,                        &Apache::lonnet::put('nohist_resevaldata',\%temphash,
    $1,$2);     $1,$2);
    }     }
        }         }
            }             }
              $outdep.='</div><br />';
         }          }
         $outstring=~s/\n*(\<\/[^\>]+\>)\s*$/$allowstr\n$1\n/s;  
   
  #Encode any High ASCII characters          if ($outdep) {
  $outstring=&HTML::Entities::encode($outstring,"\200-\377");              $scrout.='<h3>'.&mt('Dependencies').'</h3>'
                       .$outdep
           }
           $outstring=~s/\n*(\<\/[^\>]+\>[^<]*)$/$allowstr\n$1\n/s;
   
 # ------------------------------------------------------------- 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 ('<span class="LC_error">'.&mt('No write permission to').
  '<font color="red">No write permission to '.$source.       ' '.$source.
  ', FAIL</font>';       ', '.&mt('FAIL').'</span>',1);
   }    }
           print($org $outstring);            print($org $outstring);
         }          }
   $content=$outstring;    $content=$outstring;
   
     }      }
   
   # ----------------------------------------------------- Course Authoring Space.
       my ($courseauthor,$crsaurights,$readonly);
       if ($env{'request.course.id'}) {
           my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
           my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
           my $docroot = $Apache::lonnet::perlvar{'lonDocRoot'};
           if ($source =~ m{^\Q$docroot/priv/$cdom/$cnum/\E}) {
               $courseauthor = $cnum.':'.$cdom;
               $crsaurights = "/res/$cdom/$cnum/default.rights";
               $readonly = 1;
           }
       }
   
 # -------------------------------------------- Initial step done, now metadata.  # -------------------------------------------- Initial step done, now metadata.
   
 # --------------------------------------- Storage for metadata keys and fields.  # --------------------------------------- Storage for metadata keys and fields.
   # these are globals
   #
      %metadatafields=();       %metadatafields=();
      %metadatakeys=();       %metadatakeys=();
             
      my %oldparmstores=();       my %oldparmstores=();
             
     unless ($batch) {      unless ($batch) {
      $scrout.='<h3>Metadata Information ' .       $scrout.='<h3>'.&mt('Metadata').' ' .
        Apache::loncommon::help_open_topic("Metadata_Description")         &Apache::loncommon::help_open_topic("Metadata_Description")
        . '</h3>';         . '</h3>';
     }      }
   
 # ------------------------------------------------ First, check out environment  # ------------------------------------------------ First, check out environment
      unless (-e $source.'.meta') {       if ((!(-e $source.'.meta')) || ($env{'form.forceoverride'})) {
         $metadatafields{'author'}=$ENV{'environment.firstname'}.' '.          $metadatafields{'author'}=$env{'environment.firstname'}.' '.
                           $ENV{'environment.middlename'}.' '.                            $env{'environment.middlename'}.' '.
                   $ENV{'environment.lastname'}.' '.                    $env{'environment.lastname'}.' '.
                   $ENV{'environment.generation'};                    $env{'environment.generation'};
         $metadatafields{'author'}=~s/\s+/ /g;          $metadatafields{'author'}=~s/\s+/ /g;
         $metadatafields{'author'}=~s/\s+$//;          $metadatafields{'author'}=~s/\s+$//;
         $metadatafields{'owner'}=$cuname.'@'.$cudom;          $metadatafields{'owner'}=$cuname.':'.$cudom;
   
 # ------------------------------------------------ Check out directory hierachy  # ------------------------------------------------ Check out directory hierachy
   
         my $thisdisfn=$source;          my $thisdisfn=$source;
         $thisdisfn=~s/^\/home\/$cuname\///;  
   
         my @urlparts=split(/\//,$thisdisfn);          $thisdisfn=~s/^\Q$docroot\E\/priv\/\Q$cudom\E\/\Q$cuname\E\///;
           my @urlparts=('.',split(/\//,$thisdisfn));
         $#urlparts--;          $#urlparts--;
   
         my $currentpath='/home/'.$cuname.'/';          my $currentpath=$docroot.'/priv/'.$cudom.'/'.$cuname.'/';
   
         foreach (@urlparts) {   my $prefix='../'x($#urlparts);
     $currentpath.=$_.'/';          foreach my $subdir (@urlparts) {
             $scrout.=&metaread($logfile,$currentpath.'default.meta');      $currentpath.=$subdir.'/';
               $scrout.=&metaread($logfile,$currentpath.'default.meta',$prefix);
       $prefix=~s|^\.\./||;
         }          }
   
   # ----------------------------------------------------------- Parse file itself
   # read %metadatafields from file itself
    
    $allmeta=&parseformeta($source,$style);
   
 # ------------------- Clear out parameters and stores (there should not be any)  # ------------------- Clear out parameters and stores (there should not be any)
   
         foreach (keys %metadatafields) {          foreach my $field (keys(%metadatafields)) {
     if (($_=~/^parameter/) || ($_=~/^stores/)) {      if (($field=~/^parameter/) || ($field=~/^stores/)) {
  delete $metadatafields{$_};   delete $metadatafields{$field};
             }              }
         }          }
   
Line 940  sub publish { Line 1286  sub publish {
   
         $scrout.=&metaread($logfile,$source.'.meta');          $scrout.=&metaread($logfile,$source.'.meta');
   
         foreach (keys %metadatafields) {          foreach my $field (keys(%metadatafields)) {
     if (($_=~/^parameter/) || ($_=~/^stores/)) {      if (($field=~/^parameter/) || ($field=~/^stores/)) {
                 $oldparmstores{$_}=1;                  $oldparmstores{$field}=1;
  delete $metadatafields{$_};   delete $metadatafields{$field};
             }              }
         }          }
           # ------------------------------------------------------------- Save some stuff
     }          my %savemeta=();
           if ($metadatafields{'title'}) { $savemeta{'title'}=$metadatafields{'title'}; }
 # -------------------------------------------------- Parse content for metadata  # ------------------------------------------ See if anything new in file itself
     if ($style eq 'ssi') {   
         my $oldenv=$ENV{'request.uri'};   $allmeta=&parseformeta($source,$style);
   # ----------------------------------------------------------- Restore the stuff
         $ENV{'request.uri'}=$target;          foreach my $item (keys(%savemeta)) {
         $allmeta=Apache::lonxml::xmlparse(undef,'meta',$content);      $metadatafields{$item}=$savemeta{$item};
         $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='';
         foreach (sort keys %metadatafields) {      foreach my $field (sort(keys(%metadatafields))) {
     if (($_=~/^parameter/) || ($_=~/^stores/)) {   if (($field=~/^parameter/) || ($field=~/^stores/)) {
                 unless ($_=~/\.\w+$/) {       unless ($field=~/\.\w+$/) {
                    unless ($oldparmstores{$_}) {   unless ($oldparmstores{$field}) {
       print $logfile 'New: '.$_."\n";      my $disp_key = $field;
                       $chparms.=$_.' ';      $disp_key =~ tr/\0/_/;
                    }      print $logfile ('New: '.$disp_key."\n");
         }      $chparms .= $disp_key.' ';
             }   }
         }      }
         if ($chparms) {   }
     $scrout.='<p><b>New parameters or stored values:</b> '.      }
                      $chparms;      if ($chparms) {
         }   $scrout.='<p><b>'.&mt('New parameters or saved values').
       ':</b> '.$chparms.'</p>';
       }
   
         $chparms='';      $chparms='';
         foreach (sort keys %oldparmstores) {      foreach my $olditem (sort(keys(%oldparmstores))) {
     if (($_=~/^parameter/) || ($_=~/^stores/)) {   if (($olditem=~/^parameter/) || ($olditem=~/^stores/)) {
                 unless (($metadatafields{$_.'.name'}) ||      unless (($metadatafields{$olditem.'.name'}) ||
                         ($metadatafields{$_.'.package'}) || ($_=~/\.\w+$/)) {      ($metadatafields{$olditem.'.package'}) || ($olditem=~/\.\w+$/)) {
     print $logfile 'Obsolete: '.$_."\n";   my $disp_key = $olditem;
                     $chparms.=$_.' ';   $disp_key =~ tr/\0/_/;
                 }   print $logfile ('Obsolete: '.$disp_key."\n");
             }   $chparms.=$disp_key.' ';
         }      }
         if ($chparms) {   }
     $scrout.='<p><b>Obsolete parameters or stored values:</b> '.      }
                      $chparms;      if ($chparms) {
         }          $scrout.='<p><b>'.&mt('Obsolete parameters or saved values').':</b> '
           .$chparms.'</p>'
                   .'<p class="LC_warning"><b>'.&mt('Warning!').'</b><br />'
                   .&mt('If this resource is in active use, student performance data from the previous version may become inaccessible.')
                   .'</p><hr />';
       }
       if ($metadatafields{'copyright'} eq 'priv') {
           $scrout.='<p class="LC_warning"><b>'.&mt('Warning!').'</b><br />'
                   .&mt('Copyright/distribution option "Private" is no longer supported. Select another option from below. Consider "Custom Rights" for maximum control over the usage of your resource.')
                   .'</p><hr />';
       }
   
 # ------------------------------------------------------- Now have all metadata  # ------------------------------------------------------- Now have all metadata
   
         my %keywords=();      my %keywords=();
                   
  if (length($content)<500000) {      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;
             $textonly=~s/\<[^\>]*\>//g;   $textonly=~s/\<[^\>]*\>//g;
             $textonly=~tr/A-Z/a-z/;  
             $textonly=~s/[\$\&][a-z]\w*//g;          #this is a work simplification for german authors for present
             $textonly=~s/[^a-z\s]//g;          $textonly=HTML::Entities::decode($textonly);           #decode HTML-character
           $textonly=Encode::Encoder::encode('utf8', $textonly);  #encode to perl internal unicode
             foreach ($textonly=~m/(\w+)/g) {          $textonly=~tr/A-ZÜÄÖ/a-züäö/;      #add lowercase rule for german "Umlaute"
  unless ($nokey{$_}) {          $textonly=~s/[\$\&][a-z]\w*//g;
                    $keywords{$_}=1;          $textonly=~s/[^a-z^ü^ä^ö^ß\s]//g;  #dont delete german "Umlaute"
                 }   
           foreach ($textonly=~m/[^\s]+/g) {  #match all but whitespaces
               unless ($nokeyref->{$_}) {
                   $keywords{$_}=1;
             }              }
         }          }
   
   
       }
                           
             foreach (split(/\W+/,$metadatafields{'keywords'})) {      foreach my $addkey (split(/[\"\'\,\;]/,$metadatafields{'keywords'})) {
  $keywords{$_}=1;   $addkey=~s/\s+/ /g;
             }   $addkey=~s/^\s//;
    $addkey=~s/\s$//;
    if ($addkey=~/\w/) {
       $keywords{$addkey}=1;
    }
       }
 # --------------------------------------------------- Now we also have keywords  # --------------------------------------------------- Now we also have keywords
 # =============================================================================  # =============================================================================
 # INTERACTIVE MODE  # interactive mode html goes into $intr_scrout
 #  # batch mode throws away this HTML
    unless ($batch) {  # additionally all of the field functions have a by product of setting
         $scrout.=  #   $env{'from.'..} so that it can be used by the phase two handler in
      '<form name="pubform" action="/adm/publish" method="post">'.  #    batch mode
        '<p><input type="submit" value="Finalize Publication" /></p>'.  
           &hiddenfield('phase','two').      my $intr_scrout.='<br />'
           &hiddenfield('filename',$ENV{'form.filename'}).                      .'<form name="pubform" action="/adm/publish" method="post">';
   &hiddenfield('allmeta',&Apache::lonnet::escape($allmeta)).      unless ($env{'form.makeobsolete'}) {
           &hiddenfield('dependencies',join(',',keys %allow)).         $intr_scrout.='<p class="LC_warning">'
           &textfield('Title','title',$metadatafields{'title'}).                      .&mt('Searching for your resource will be based on the following metadata. Please provide as much data as possible.')
           &textfield('Author(s)','author',$metadatafields{'author'}).                      .'</p>'
   &textfield('Subject','subject',$metadatafields{'subject'});                      .'<p><input type="submit" value="'
                       .&mt('Finalize Publication')
 # --------------------------------------------------- Scan content for keywords                      .'" /> <a href="'.&Apache::loncfile::url($source).'">'.&mt('Cancel').'</a></p>';
       }
       $intr_scrout.=&Apache::lonhtmlcommon::start_pick_box();
       $intr_scrout.=
    &hiddenfield('phase','two').
    &hiddenfield('filename',$env{'form.filename'}).
    &hiddenfield('allmeta',&escape($allmeta)).
    &hiddenfield('dependencies',join(',',keys(%allow)));
       unless ($env{'form.makeobsolete'}) {
          $intr_scrout.=
    &textfield('Title','title',$metadatafields{'title'}).
    &textfield('Author(s)','author',$metadatafields{'author'}).
    &textfield('Subject','subject',$metadatafields{'subject'});
    # --------------------------------------------------- Scan content for keywords
   
         my $keywords_help = Apache::loncommon::help_open_topic("Publishing_Keywords");      my $keywords_help = &Apache::loncommon::help_open_topic("Publishing_Keywords");
  my $keywordout=<<"END";      my $keywordout=<<"END";
 <script>  <script>
 function checkAll(field)  function checkAll(field) {
 {  
     for (i = 0; i < field.length; i++)      for (i = 0; i < field.length; i++)
         field[i].checked = true ;          field[i].checked = true ;
 }  }
   
 function uncheckAll(field)  function uncheckAll(field) {
 {  
     for (i = 0; i < field.length; i++)      for (i = 0; i < field.length; i++)
         field[i].checked = false ;          field[i].checked = false ;
 }  }
 </script>  </script>
 <p><b>Keywords: $keywords_help</b>   
 <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  END
         $keywordout.='<table border=2><tr>';      $keywordout.="\n".&Apache::lonhtmlcommon::row_title(&mt('Keywords'))
         my $colcount=0;                  .$keywords_help
                   .'<input type="button" value="'.&mt('check all').'" onclick="javascript:checkAll(document.pubform.keywords)" />'
             foreach (sort keys %keywords) {                  .'<input type="button" value="'.&mt('uncheck all').'" onclick="javascript:uncheckAll(document.pubform.keywords)" />'
                 $keywordout.='<td><input type=checkbox name="keywords" value="'.$_.'"';                  .'</p><br />'
                 if ($metadatafields{'keywords'}) {                  .&Apache::loncommon::start_data_table();
                    if ($metadatafields{'keywords'}=~/$_/) {       my $cols_per_row = 10;
                       $keywordout.=' checked';       my $colcount=0;
                    }      my $wordcount=0;
         } elsif (&Apache::loncommon::keyword($_)) {      my $numkeywords = scalar(keys(%keywords));
             $keywordout.=' checked';  
                 }       foreach my $word (sort(keys(%keywords))) {
                 $keywordout.='>'.$_.'</td>';          if ($colcount == 0) {
                 if ($colcount>10) {              $keywordout .= &Apache::loncommon::start_data_table_row();
     $keywordout.="</tr><tr>\n";          }
                     $colcount=0;          $colcount++;
                 }          $wordcount++;
                 $colcount++;          if (($wordcount == $numkeywords) && ($colcount < $cols_per_row)) {
               my $colspan = 1+$cols_per_row-$colcount;
               $keywordout .= '<td colspan="'.$colspan.'">';
           } else {
               $keywordout .= '<td>';
           }
           $keywordout.='<label><input type="checkbox" name="keywords" value="'.$word.'"';
           if ($metadatafields{'keywords'}) {
               if ($metadatafields{'keywords'}=~/\Q$word\E/) {
                   $keywordout.=' checked="checked"';
                   $env{'form.keywords'}.=$word.',';
             }              }
                   } elsif (&Apache::loncommon::keyword($word)) {
  $keywordout.='</tr></table>';              $keywordout.=' checked="checked"';
               $env{'form.keywords'}.=$word.',';
           }
           $keywordout.=' />'.$word.'</label></td>';
           if ($colcount == $cols_per_row) {
               $keywordout.=&Apache::loncommon::end_data_table_row();
               $colcount=0;
           }
       }
       if ($colcount > 0) {
           $keywordout .= &Apache::loncommon::end_data_table_row();
       }
   
         $scrout.=$keywordout;      $env{'form.keywords'}=~s/\,$//;
   
         $scrout.=&textfield('Additional Keywords','addkey','');      $keywordout.=&Apache::loncommon::end_data_table_row()
                    .&Apache::loncommon::end_data_table()
                    .&Apache::lonhtmlcommon::row_closure();
   
         $scrout.=&textfield('Notes','notes',$metadatafields{'notes'});      $intr_scrout.=$keywordout;
   
         $scrout.=      $intr_scrout.=&textfield('Additional Keywords','addkey','');
              '<p><b>Abstract:</b><br><textarea cols=80 rows=5 name=abstract>'.  
               $metadatafields{'abstract'}.'</textarea>';  
   
  $source=~/\.(\w+)$/;      $intr_scrout.=&textfield('Notes','notes',$metadatafields{'notes'});
   
  $scrout.=&hiddenfield('mime',$1);      $intr_scrout.="\n".&Apache::lonhtmlcommon::row_title(&mt('Abstract'))
                    .'<textarea cols="80" rows="5" name="abstract">'
                    .$metadatafields{'abstract'}
                    .'</textarea>'
                    .&Apache::lonhtmlcommon::row_closure();
   
         $scrout.=&selectbox('Language','language',      $source=~/\.(\w+)$/;
                             $metadatafields{'language'},  
     \&Apache::loncommon::languagedescription,  
     (&Apache::loncommon::languageids),  
      );  
   
         unless ($metadatafields{'creationdate'}) {      $intr_scrout.="\n".&Apache::lonhtmlcommon::row_title(&mt('Grade Levels'))
     $metadatafields{'creationdate'}=time;                   .&mt('Lowest Grade Level:').'&nbsp;'
         }                   .&select_level_form($metadatafields{'lowestgradelevel'},'lowestgradelevel')
         $scrout.=&hiddenfield('creationdate',$metadatafields{'creationdate'});  #                .&Apache::lonhtmlcommon::row_closure();
   #   $intr_scrout.="\n".&Apache::lonhtmlcommon::row_title(&mt('Highest Grade Level'))
                    .' '.&mt('Highest Grade Level:').'&nbsp;'
                    .&select_level_form($metadatafields{'highestgradelevel'},'highestgradelevel')
                    .&Apache::lonhtmlcommon::row_closure();
   
       $intr_scrout.=&textfield('Standards','standards',$metadatafields{'standards'});
   
       $intr_scrout.=&hiddenfield('mime',$1);
   
         $scrout.=&hiddenfield('lastrevisiondate',time);      my $defaultlanguage=$metadatafields{'language'};
       $defaultlanguage =~ s/\s*notset\s*//g;
       $defaultlanguage =~ s/^,\s*//g;
       $defaultlanguage =~ s/,\s*$//g;
   
          $intr_scrout.=&selectbox('Language','language',
  $scrout.=&textfield('Publisher/Owner','owner',       $defaultlanguage,'',
                             $metadatafields{'owner'});       \&Apache::loncommon::languagedescription,
        (&Apache::loncommon::languageids),
        );
   
       unless ($metadatafields{'creationdate'}) {
    $metadatafields{'creationdate'}=time;
       }
       $intr_scrout.=&hiddenfield('creationdate',
          &Apache::lonmysql::unsqltime($metadatafields{'creationdate'}));
   
       $intr_scrout.=&hiddenfield('lastrevisiondate',time);
   
       my $pubowner_last;
       if ($style eq 'prv') {
           $pubowner_last = 1;
       }
       if ($courseauthor) {
           $metadatafields{'owner'} = $courseauthor;
       }
       $intr_scrout.=&textfield('Publisher/Owner','owner',
        $metadatafields{'owner'},$pubowner_last,$readonly);
   
   # ---------------------------------------------- Retrofix for unused copyright
       if ($metadatafields{'copyright'} eq 'free') {
    $metadatafields{'copyright'}='default';
    $metadatafields{'sourceavail'}='open';
       }
       if ($metadatafields{'copyright'} eq 'priv') {
           $metadatafields{'copyright'}='domain';
       }
   # ------------------------------------------------ Dial in reasonable defaults
       my $defaultoption=$metadatafields{'copyright'};
       unless ($defaultoption) { $defaultoption='default'; }
       if ($courseauthor) {
           $defaultoption='custom';
           $metadatafields{'customdistributionfile'}=$crsaurights;
       }
       my $defaultsourceoption=$metadatafields{'sourceavail'};
       unless ($defaultsourceoption) { $defaultsourceoption='closed'; }
       unless ($style eq 'prv') {
 # -------------------------------------------------- Correct copyright for rat.  # -------------------------------------------------- Correct copyright for rat.
     if ($style eq 'rat') {   if ($style eq 'rat') {
  if ($metadatafields{'copyright'} eq 'public') {   # -------------------------------------- Retrofix for non-applicable copyright
     delete $metadatafields{'copyright'};      if ($metadatafields{'copyright'} eq 'public') { 
  }   delete $metadatafields{'copyright'};
         $scrout.=&selectbox('Copyright/Distribution','copyright',   $defaultoption='default';
                             $metadatafields{'copyright'},      }
     \&Apache::loncommon::copyrightdescription,      $intr_scrout.=&selectbox('Copyright/Distribution','copyright',
      (grep !/^public$/,(&Apache::loncommon::copyrightids)));       $defaultoption,$readonly,
     }       \&Apache::loncommon::copyrightdescription,
     else {      (grep !/^(public|priv)$/,(&Apache::loncommon::copyrightids)));
         $scrout.=&selectbox('Copyright/Distribution','copyright',   } else {
                             $metadatafields{'copyright'},      $intr_scrout.=&selectbox('Copyright/Distribution','copyright',
     \&Apache::loncommon::copyrightdescription,       $defaultoption,$readonly,
      (&Apache::loncommon::copyrightids));       \&Apache::loncommon::copyrightdescription,
     }       (grep !/^priv$/,(&Apache::loncommon::copyrightids)));
    }
     my $copyright_help =   my $copyright_help =
         Apache::loncommon::help_open_topic('Publishing_Copyright');      &Apache::loncommon::help_open_topic('Publishing_Copyright');
     $scrout =~ s/DISTRIBUTION:/'DISTRIBUTION: ' . $copyright_help/ge;          my $replace=&mt('Copyright/Distribution:');
     return $scrout.   $intr_scrout =~ s/$replace/$replace.' '.$copyright_help/ge;
         '<p><input type="submit" value="Finalize Publication" /></p></form>';  
 # =============================================================================   $intr_scrout.=&text_with_browse_field('Custom Distribution File','customdistributionfile',$metadatafields{'customdistributionfile'},'rights','',$readonly);
 # BATCH MODE   $intr_scrout.=&selectbox('Source Distribution','sourceavail',
 #   $defaultsourceoption,'',
   } else {   \&Apache::loncommon::source_copyrightdescription,
 # Transfer metadata directly to environment for stage 2   (&Apache::loncommon::source_copyrightids));
     foreach (keys %metadatafields) {  # $intr_scrout.=&text_with_browse_field('Source Custom Distribution File','sourcerights',$metadatafields{'sourcerights'},'rights');
  $ENV{'form.'.$_}=$metadatafields{$_};   my $uctitle=&mt('Obsolete');
     }          my $obsolete_checked=($metadatafields{'obsolete'})?' checked="checked"':'';
     $ENV{'form.addkey'}='';          $intr_scrout.="\n".&Apache::lonhtmlcommon::row_title($uctitle)
     $ENV{'form.keywords'}='';                       .'<input type="checkbox" name="obsolete"'.$obsolete_checked.' />'
     foreach (keys %keywords) {                       .&Apache::lonhtmlcommon::row_closure(1);
         if ($metadatafields{'keywords'}) {          $intr_scrout.=&text_with_browse_field('Suggested Replacement for Obsolete File',
            if ($metadatafields{'keywords'}=~/$_/) {       'obsoletereplacement',
               $ENV{'form.keywords'}.=$_.',';       $metadatafields{'obsoletereplacement'},'',1);
            }      } else {
  } elsif (&Apache::loncommon::keyword($_)) {   $intr_scrout.=&hiddenfield('copyright','private');
     $ENV{'form.keywords'}.=$_.',';      }
         }      } else {
     }         $intr_scrout.=
     $ENV{'form.keywords'}=~s/\,$//;   &hiddenfield('title',$metadatafields{'title'}).
     unless ($ENV{'form.creationdate'}) { $ENV{'form.creationdate'}=time; }   &hiddenfield('author',$metadatafields{'author'}).
     $ENV{'form.lastrevisiondate'}=time;   &hiddenfield('subject',$metadatafields{'subject'}).
     if ((($style eq 'rat') && ($ENV{'form.copyright'} eq 'public')) ||   &hiddenfield('keywords',$metadatafields{'keywords'}).
         (!$ENV{'form.copyright'})) {    &hiddenfield('abstract',$metadatafields{'abstract'}).
  $ENV{'form.copyright'}='default';   &hiddenfield('notes',$metadatafields{'notes'}).
     }    &hiddenfield('mime',$metadatafields{'mime'}).
     $ENV{'form.allmeta'}=&Apache::lonnet::escape($allmeta);   &hiddenfield('creationdate',$metadatafields{'creationdate'}).
     return $scrout;   &hiddenfield('lastrevisiondate',time).
   }   &hiddenfield('owner',$metadatafields{'owner'}).
    &hiddenfield('lowestgradelevel',$metadatafields{'lowestgradelevel'}).
    &hiddenfield('standards',$metadatafields{'standards'}).
    &hiddenfield('highestgradelevel',$metadatafields{'highestgradelevel'}).
    &hiddenfield('language',$metadatafields{'language'}).
    &hiddenfield('copyright',$metadatafields{'copyright'}).
    &hiddenfield('sourceavail',$metadatafields{'sourceavail'}).
    &hiddenfield('customdistributionfile',$metadatafields{'customdistributionfile'}).
    &hiddenfield('obsolete',1).
    &text_with_browse_field('Suggested Replacement for Obsolete File',
       'obsoletereplacement',
       $metadatafields{'obsoletereplacement'},'',1);
      }
       if (!$batch) {
    $scrout.=$intr_scrout
               .&Apache::lonhtmlcommon::end_pick_box()
               .'<p><input type="submit" value="'
       .&mt($env{'form.makeobsolete'}?'Make Obsolete':'Finalize Publication')
               .'" /></p>'
               .'</form>';
       }
       return($scrout,0);
   }
   
   sub getnokey {
       my ($includedir) = @_;
       my $nokey={};
       my $fh=Apache::File->new($includedir.'/un_keyword.tab');
       while (<$fh>) {
           my $word=$_;
           chomp($word);
           $nokey->{$word}=1;
       }
       return $nokey;
 }  }
   
 #########################################  #########################################
Line 1182  Parameters: Line 1660  Parameters:
   
 =item I<$distarget>  =item I<$distarget>
   
   =item I<$batch>
   
   =item I<$usebuffer>
   
 =back  =back
   
 Returns:  Returns:
   
 =over 4  =over 4
   
 =item Scalar string  =item integer or array
   
 String contains status (errors and warnings) and information associated with  if $userbuffer arg is true, and if caller wants an array
 the server's attempts at publication.  then the array ($output,$rtncode) will be returned, otherwise
   just the $rtncode will be returned.  $rtncode is an integer:
   
   0: fail
   1: success
   
   =back
   
 =cut  =cut
   
   #'stupid emacs
 #########################################  #########################################
 #########################################  #########################################
 sub phasetwo {  sub phasetwo {
   
     my ($source,$target,$style,$distarget,$batch)=@_;      my ($r,$source,$target,$style,$distarget,$batch,$usebuffer)=@_;
       $source=~s/\/+/\//g;
       $target=~s/\/+/\//g;
   #
   # Unless trying to get rid of something, check name validity
   #
       my $output;
       unless ($env{'form.obsolete'}) {
    if ($target=~/(\_\_\_|\&\&\&|\:\:\:)/) {
       $output = '<span class="LC_error">'.
         &mt('Unsupported character combination [_1] in filename, FAIL.',"<tt>'.$1.'</tt>").
         '</span>';
               if ($usebuffer) {
                   if (wantarray) { 
                       return ($output,0);
                   } else {
                       return 0;
                   }
               } else {
                   $r->print($output);
           return 0;
               }
    }
    unless ($target=~/\.(\w+)$/) {
               $output = '<span class="LC_error">'.&mt('No valid extension found in filename, FAIL').'</span>'; 
               if ($usebuffer) {
                   if (wantarray) {
                       return ($output,0);
                   } else {
                       return 0;
                   }
               } else {
           $r->print($output);
           return 0;
               }
    }
    if ($target=~/\.(\d+)\.(\w+)$/) {
       $output = '<span class="LC_error">'.&mt('Filename of resource contains internal version number. Cannot publish such resources, FAIL').'</span>';
               if ($usebuffer) {
                   if (wantarray) {
                       return ($output,0);
                   } else {
                       return 0;
                   }
               } else { 
                   $r->print($output);
           return 0;
               }
    }
       }
   
   #
   # End name check
   #
       $distarget=~s/\/+/\//g;
     my $logfile;      my $logfile;
     my $scrout='';  
     unless ($logfile=Apache::File->new('>>'.$source.'.log')) {      unless ($logfile=Apache::File->new('>>'.$source.'.log')) {
  return           $output = '<span class="LC_error">'.
          '<font color=red>No write permission to user directory, FAIL</font>';    &mt('No write permission to user directory, FAIL').'</span>';
           if ($usebuffer) {
               if (wantarray) {
                   return ($output,0);
               } else {
                   return 0;
               }
           } else {
               return 0;
           }
     }      }
       
       if ($source =~ /\.rights$/) {
    $output = '<p><span class="LC_warning">'.&mt('Warning: It can take up to 1 hour for rights changes to fully propagate.').'</span></p>';
           unless ($usebuffer) {
               $r->print($output);
               $output = ''; 
           }
       }
   
     print $logfile       print $logfile 
 "\n================= Publish ".localtime()." Phase Two  ================\n";          "\n================= Publish ".localtime()." Phase Two  ================\n".$env{'user.name'}.':'.$env{'user.domain'}."\n";
       
       %metadatafields=();
       %metadatakeys=();
   
      %metadatafields=();      &metaeval(&unescape($env{'form.allmeta'}));
      %metadatakeys=();  
   
      &metaeval(&Apache::lonnet::unescape($ENV{'form.allmeta'}));      if ($batch) {
           my %commonaccess;
           map { $commonaccess{$_} = 1; } &Apache::loncommon::get_env_multiple('form.commonaccess');
           if ($commonaccess{'dist'}) {
               unless ($style eq 'prv') { 
                   if ($env{'form.commondistselect'} eq 'custom') {
                       unless ($source =~ /\.rights$/) {
                           if ($env{'form.commoncustomrights'} =~ m{^/res/.+\.rights$}) { 
                               $env{'form.customdistributionfile'} = $env{'form.commoncustomrights'}; 
                               $env{'form.copyright'} = $env{'form.commondistselect'};
                           }
                       }
                   } elsif ($env{'form.commondistselect'} =~ /^default|domain|public$/) {
                       $env{'form.copyright'} = $env{'form.commondistselect'};
                   }
               }
           }
           unless ($style eq 'prv') {
               if ($commonaccess{'source'}) {
                   if (($env{'form.commonsourceselect'} eq 'open') || ($env{'form.commonsourceselect'} eq 'closed')) {
                       $env{'form.sourceavail'} = $env{'form.commonsourceselect'};
                   }
               }
           }
       }
   
      $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{'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'};
      $metadatafields{'language'}=$ENV{'form.language'};      $metadatafields{'language'}=$env{'form.language'};
      $metadatafields{'creationdate'}=      $metadatafields{'creationdate'}=$env{'form.creationdate'};
          &sqltime($ENV{'form.creationdate'});      $metadatafields{'lastrevisiondate'}=$env{'form.lastrevisiondate'};
      $metadatafields{'lastrevisiondate'}=      $metadatafields{'owner'}=$env{'form.owner'};
          &sqltime($ENV{'form.lastrevisiondate'});      $metadatafields{'copyright'}=$env{'form.copyright'};
      $metadatafields{'owner'}=$ENV{'form.owner'};      $metadatafields{'standards'}=$env{'form.standards'};
      $metadatafields{'copyright'}=$ENV{'form.copyright'};      $metadatafields{'lowestgradelevel'}=$env{'form.lowestgradelevel'};
      $metadatafields{'dependencies'}=$ENV{'form.dependencies'};      $metadatafields{'highestgradelevel'}=$env{'form.highestgradelevel'};
       $metadatafields{'customdistributionfile'}=
      my $allkeywords=$ENV{'form.addkey'};                                   $env{'form.customdistributionfile'};
      if (exists($ENV{'form.keywords'})) {      $metadatafields{'sourceavail'}=$env{'form.sourceavail'};
          if (ref($ENV{'form.keywords'})) {      $metadatafields{'obsolete'}=$env{'form.obsolete'};
              $allkeywords .= ','.join(',',@{$ENV{'form.keywords'}});      $metadatafields{'obsoletereplacement'}=
          } else {                          $env{'form.obsoletereplacement'};
              $allkeywords .= ','.$ENV{'form.keywords'};      $metadatafields{'dependencies'}=$env{'form.dependencies'};
          }      $metadatafields{'modifyinguser'}=$env{'user.name'}.':'.
      }                                   $env{'user.domain'};
      $allkeywords=~s/\W+/\,/;      $metadatafields{'authorspace'}=$cuname.':'.$cudom;
      $allkeywords=~s/^\,//;      $metadatafields{'domain'}=$cudom;
      $metadatafields{'keywords'}=$allkeywords;  
        my $crsauthor;
      {      if ($env{'request.course.id'}) {
        print $logfile "\nWrite metadata file for ".$source;          my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
        my $mfh;          my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
        unless ($mfh=Apache::File->new('>'.$source.'.meta')) {          if ($distarget =~ m{^/res/$cdom/$cnum}) {
  return               $crsauthor = 1;
          '<font color=red>Could not write metadata, FAIL</font>';              my $default_rights = "/res/$cdom/$cnum/default.rights";
        }              unless ($distarget eq $default_rights) {
        foreach (sort keys %metadatafields) {                  $metadatafields{'copyright'} = 'custom';
  unless ($_=~/\./) {                  $metadatafields{'customdistributionfile'} = $default_rights;
            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";  
      }  
   
       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/[\"\']//g;
       $allkeywords=~s/\s*[\;\,]\s*/\,/g;
       $allkeywords=~s/\s+/ /g;
       $allkeywords=~s/^[ \,]//;
       $allkeywords=~s/[ \,]$//;
       $metadatafields{'keywords'}=$allkeywords;
       
   # check if custom distribution file is specified
       if ($metadatafields{'copyright'} eq 'custom') {
    my $file=$metadatafields{'customdistributionfile'};
    unless ($file=~/\.rights$/) {
               $output .= '<span class="LC_error">'.&mt('No valid custom distribution rights file specified, FAIL').
          '</span>';
               if ($usebuffer) {
                   if (wantarray) {
                       return ($output,0);
                   } else {
                       return 0;
                   }
               } else {
                   $r->print($output);
           return 0;
               }
           }
       }
       {
           print $logfile "\nWrite metadata file for ".$source;
           my $mfh;
           unless ($mfh=Apache::File->new('>'.$source.'.meta')) {
               $output .= '<span class="LC_error">'.&mt('Could not write metadata, FAIL').
          '</span>';
               if ($usebuffer) {
                   if (wantarray) {
                       return ($output,0);
                   } else {
                       return 0;
                   }
               } else {
                   $r->print($output);
           return 0;
               }
           }
           foreach my $field (sort(keys(%metadatafields))) {
               unless ($field=~/\./) {
                   my $unikey=$field;
                   $unikey=~/^([A-Za-z]+)/;
                   my $tag=$1;
                   $tag=~tr/A-Z/a-z/;
                   print $mfh "\n\<$tag";
                   foreach my $item (split(/\,/,$metadatakeys{$unikey})) {
                       my $value=$metadatafields{$unikey.'.'.$item};
                       $value=~s/\"/\'\'/g;
                       print $mfh ' '.$item.'="'.$value.'"';
                   }
                   print $mfh '>'.
                       &HTML::Entities::encode($metadatafields{$unikey},'<>&"')
                           .'</'.$tag.'>';
               }
           }
   
           $output  .= '<p>'.&mt('Wrote Metadata').'</p>';
           unless ($usebuffer) {
               $r->print($output);
               $output = '';
           }
           print $logfile "\nWrote metadata";
       }
       
 # -------------------------------- Synchronize entry with SQL metadata database  # -------------------------------- Synchronize entry with SQL metadata database
     my $warning;  
     $metadatafields{'url'} = $distarget;      $metadatafields{'url'} = $distarget;
     $metadatafields{'version'} = 'current';      $metadatafields{'version'} = 'current';
     unless ($metadatafields{'copyright'} eq 'priv') {  
         my ($error,$success) = &store_metadata(\%metadatafields);      unless ($crsauthor) {
           my ($error,$success) = &store_metadata(%metadatafields);
         if ($success) {          if ($success) {
             $scrout.='<p>Synchronized SQL metadata database';      $output .= '<p>'.&mt('Synchronized SQL metadata database').'</p>';
             print $logfile "\nSynchronized SQL metadata database";      print $logfile "\nSynchronized SQL metadata database";
         } else {          } else {
             $warning.=$error;      $output .= $error;
             print $logfile "\n".$error;      print $logfile "\n".$error;
           }
           unless ($usebuffer) {
               $r->print($output);
               $output = '';
         }          }
     } else {  
         $scrout.='<p>Private Publication - did not synchronize database';  
         print $logfile "\nPrivate: Did not synchronize data into ".  
             "SQL metadata database";  
     }      }
   # --------------------------------------------- Delete author resource messages
       my $delresult=&Apache::lonmsg::del_url_author_res_msg($target); 
       $output .= '<p>'.&mt('Removing error messages:').' '.$delresult.'</p>';
       unless ($usebuffer) {
           $r->print($output);
           $output = '';
       }
       print $logfile "\nRemoving error messages: $delresult";
 # ----------------------------------------------------------- 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/) {          my $docroot = $Apache::lonnet::perlvar{'lonDocRoot'};
  print $logfile "\nPANIC: Target dir is ".$srcd;          unless ($srcd=~/^\Q$docroot\E\/res/) {
         return "<font color=red>Invalid target directory, FAIL</font>";              print $logfile "\nPANIC: Target dir is ".$srcd;
     }              $output .= 
     opendir(DIR,$srcd);   "<span class=\"LC_error\">".&mt('Invalid target directory, FAIL')."</span>";
     while ($filename=readdir(DIR)) {              if ($usebuffer) {
        if ($filename=~/$srcf\.(\d+)\.$srct$/) {                  if (wantarray) {
    $maxversion=($1>$maxversion)?$1:$maxversion;                      return ($output,0);
        }                  } else {
     }                      return 0;
     closedir(DIR);                  }
     $maxversion++;              } else {
     $scrout.='<p>Creating old version '.$maxversion;                  $r->print($output);
     print $logfile "\nCreating old version ".$maxversion;          return 0;
               }
     my $copyfile=$srcd.'/'.$srcf.'.'.$maxversion.'.'.$srct;          }
           opendir(DIR,$srcd);
           while ($filename=readdir(DIR)) {
               if (-l $srcd.'/'.$filename) {
                   unlink($srcd.'/'.$filename);
                   unlink($srcd.'/'.$filename.'.meta');
               } else {
                   if ($filename=~/^\Q$srcf\E\.(\d+)\.\Q$srct\E$/) {
                       $maxversion=($1>$maxversion)?$1:$maxversion;
                   }
               }
           }
           closedir(DIR);
           $maxversion++;
           $output .= '<p>'.&mt('Creating old version [_1]',$maxversion).'</p>';
           unless ($usebuffer) {
               $r->print($output);
               $output = '';
           }
           print $logfile "\nCreating old version ".$maxversion."\n";
           
           my $copyfile=$srcd.'/'.$srcf.'.'.$maxversion.'.'.$srct;
           
         if (copy($target,$copyfile)) {          if (copy($target,$copyfile)) {
     print $logfile "Copied old target to ".$copyfile."\n";      print $logfile "Copied old target to ".$copyfile."\n";
             $scrout.='<p>Copied old target file';              $output .= &Apache::lonhtmlcommon::confirm_success(&mt('Copied old target file'));
               unless ($usebuffer) {
                   $r->print($output);
                   $output = '';
               }
         } 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>";              $output .= &Apache::lonhtmlcommon::confirm_success(&mt('Failed to copy old target').", $!",1);
               if ($usebuffer) {
                   if (wantarray) {
                       return ($output,0);
                   } else {
                       return 0;
                   }
               } else {
                   $r->print($output); 
           return 0;
               }
         }          }
           
 # --------------------------------------------------------------- Copy Metadata  # --------------------------------------------------------------- Copy Metadata
   
  $copyfile=$copyfile.'.meta';   $copyfile=$copyfile.'.meta';
           
         if (copy($target.'.meta',$copyfile)) {          if (copy($target.'.meta',$copyfile)) {
     print $logfile "Copied old target metadata to ".$copyfile."\n";      print $logfile "Copied old target metadata to ".$copyfile."\n";
             $scrout.='<p>Copied old metadata';              $output .= &Apache::lonhtmlcommon::confirm_success(&mt('Copied old metadata'));
               unless ($usebuffer) {
                   $r->print($output);
                   $output = '';
               }
         } 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                   $output .= &Apache::lonhtmlcommon::confirm_success(
        "<font color=red>Failed to write old metadata copy, $!, FAIL</font>";                                 &mt('Failed to write old metadata copy').", $!",1);
                   if ($usebuffer) {
                       if (wantarray) {
                           return ($output,0);
                       } else {
                           return 0;
                       }
                   } else {
                       $r->print($output);
                       return 0;
                   }
     }      }
         }          }
       } else {
           $output .= '<p>'.&mt('Initial version').'</p>';
 } else {          unless ($usebuffer) {
     $scrout.='<p>Initial version';              $r->print($output);
     print $logfile "\nInitial version";              $output = '';
 }          }
           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];              mkdir($path,0777);
    mkdir($path,0777);              $output .= '<p>'
                }                        .&mt('Created directory [_1]'
            }                             ,'<span class="LC_filename">'.$parts[$count].'</span>')
                         .'</p>';
         if (copy($source,$copyfile)) {              unless ($usebuffer) {
     print $logfile "\nCopied original source to ".$copyfile."\n";                  $r->print($output);
             $scrout.='<p>Copied source file';                  $output = '';
               }
           }
       }
       
       if (copy($source,$copyfile)) {
           print $logfile "\nCopied original source to ".$copyfile."\n";
           $output .= &Apache::lonhtmlcommon::confirm_success(&mt('Copied source file'));
           unless ($usebuffer) {
               $r->print($output);
               $output = '';
           }
       } else {
           print $logfile "\nUnable to write ".$copyfile.':'.$!."\n";
           $output .= &Apache::lonhtmlcommon::confirm_success(
       &mt('Failed to copy source').", $!",1);
           if ($usebuffer) {
               if (wantarray) {
                   return ($output,0);
               } else {
                   return 0;
               }
         } else {          } else {
     print $logfile "\nUnable to write ".$copyfile.':'.$!."\n";              $r->print($output);
             return "<font color=red>Failed to copy source, $!, FAIL</font>";              return 0;
         }          }
       }
       
   # ---------------------------------------------- Delete local tmp-preview files
       unlink($copyfile.'.tmp');
 # --------------------------------------------------------------- Copy Metadata  # --------------------------------------------------------------- Copy Metadata
   
         $copyfile=$copyfile.'.meta';      $copyfile=$copyfile.'.meta';
       
         if (copy($source.'.meta',$copyfile)) {      if (copy($source.'.meta',$copyfile)) {
     print $logfile "\nCopied original metadata to ".$copyfile."\n";          print $logfile "\nCopied original metadata to ".$copyfile."\n";
             $scrout.='<p>Copied metadata';          $output .= &Apache::lonhtmlcommon::confirm_success(&mt('Copied metadata'));
           unless ($usebuffer) {
               $r->print($output);
               $output = '';
           }
       } else {
           print $logfile "\nUnable to write metadata ".$copyfile.':'.$!."\n";
           $output .= &Apache::lonhtmlcommon::confirm_success(
                        &mt('Failed to write metadata copy').", $!",1);
           if ($usebuffer) {
               if (wantarray) {
                   return ($output,0);
               } else {
                   return 0;
               }
         } else {          } else {
     print $logfile "\nUnable to write metadata ".$copyfile.':'.$!."\n";              $r->print($output);
             return               return 0;
           "<font color=red>Failed to write metadata copy, $!, FAIL</font>";  
         }          }
       }
 # --------------------------------------------------- Send update notifications      unless ($usebuffer) {
           $r->rflush;
     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  # ------------------------------------------------------------- Trigger updates
       push(@{$modified_urls},[$target,$source]);
     my @subscribedmeta=&get_subscribed_hosts("$target.meta");      unless ($registered_cleanup) {
     foreach my $subhost (@subscribedmeta) {          my $handlers = $r->get_handlers('PerlCleanupHandler');
  $scrout.='<p>Notifying host for metadata only '.$subhost.':';          $r->set_handlers('PerlCleanupHandler' => [\&notify,@{$handlers}]);
  print $logfile "\nNotifying host for metadata only ".$subhost.':';   $registered_cleanup=1;
  my $reply=&Apache::lonnet::critical('update:'.$target.'.meta',  
     $subhost);  
  $scrout.=$reply;  
  print $logfile $reply;  
     }      }
   
 # ------------------------------------------------ Provide link to new resource  # ---------------------------------------------------------- Clear local caches
   unless ($batch) {  
     my $thisdistarget=$target;      my $thisdistarget=$target;
     $thisdistarget=~s/^$docroot//;      $thisdistarget=~s/^\Q$docroot\E//;
       &Apache::lonnet::devalidate_cache_new('resversion',$target);
     my $thissrc=$source;      &Apache::lonnet::devalidate_cache_new('meta',
     $thissrc=~s/^\/home\/(\w+)\/public_html/\/priv\/$1/;   &Apache::lonnet::declutter($thisdistarget));
   
   # ------------------------------------------------------------- Everything done
       $logfile->close();
       $output .= '<p class="LC_success">'.&mt('Done').'</p>';
       unless ($usebuffer) {
           $r->print($output);
           $output = '';
       }
   
     my $thissrcdir=$thissrc;  # ------------------------------------------------ Provide link to new resource
     $thissrcdir=~s/\/[^\/]+$/\//;      unless ($batch) {
           
           my $thissrc=&Apache::loncfile::url($source);
           my $thissrcdir=$thissrc;
           $thissrcdir=~s/\/[^\/]+$/\//;
           
           $output .= 
               &Apache::lonhtmlcommon::actionbox([
                   '<a href="'.$thisdistarget.'">'.
                   &mt('View Published Version').
                   '</a>',
                   '<a href="'.$thissrc.'">'.
                   &mt('Back to Source').
                   '</a>',
                   '<a href="'.$thissrcdir.'">'.
                   &mt('Back to Source Directory').
                   '</a>']);
           unless ($usebuffer) {
               $r->print($output);
               $output = '';
           }
       }
   
       if ($usebuffer) {
           if (wantarray) {
               return ($output,1);
           } else {
               return 1;
           }
       } else {
           if (wantarray) {
               return ('',1);
           } else {
               return 1;
           }
       }
   }
   
     return $warning.$scrout.  # =============================================================== Notifications
       '<hr><a href="'.$thisdistarget.'"><font size="+2">'.  sub notify {  
       'View Published Version</font></a>'.  # --------------------------------------------------- Send update notifications
       '<p><a href="'.$thissrc.'"><font size=+2>Back to Source</font></a>'.      foreach my $targetsource (@{$modified_urls}){
       '<p><a href="'.$thissrcdir.   my ($target,$source)=@{$targetsource};
       '"><font size="+2">Back to Source Directory</font></a>';   my $logfile=Apache::File->new('>>'.$source.'.log');
   } else {   print $logfile "\nCleanup phase: Notifications\n";
     return $warning.$scrout;   my @subscribed=&get_subscribed_hosts($target);
   }   foreach my $subhost (@subscribed) {
       print $logfile "\nNotifying host ".$subhost.':';
       my $reply=&Apache::lonnet::critical('update:'.$target,$subhost);
       print $logfile $reply;
    }
   # ---------------------------------------- Send update notifications, meta only
    my @subscribedmeta=&get_subscribed_hosts("$target.meta");
    foreach my $subhost (@subscribedmeta) {
       print $logfile "\nNotifying host for metadata only ".$subhost.':';
       my $reply=&Apache::lonnet::critical('update:'.$target.'.meta',
    $subhost);
       print $logfile $reply;
    } 
   # --------------------------------------------------- Notify subscribed courses
    my %courses=&coursedependencies($target);
    my $now=time;
    foreach my $course (keys(%courses)) {
       print $logfile "\nNotifying course ".$course.':';
       my ($cdom,$cname)=split(/\_/,$course);
       my $reply=&Apache::lonnet::cput
    ('versionupdate',{$target => $now},$cdom,$cname);
       print $logfile $reply;
    }
    print $logfile "\n============ Done ============\n";
    $logfile->close();
       }
       if ($lock) { &Apache::lonnet::remove_lock($lock); }
       return OK;
 }  }
   
 #########################################  #########################################
   
 sub batchpublish {  sub batchpublish {
     my ($r,$srcfile,$targetfile)=@_;      my ($r,$srcfile,$targetfile,$nokeyref,$usebuffer)=@_;
     my $thisdisfn=$srcfile;      #publication pollutes %env with form.* values
     $thisdisfn=~s/\/home\/korte\/public_html\///;      my %oldenv=%env;
     $srcfile=~s/\/+/\//g;      $srcfile=~s/\/+/\//g;
       $targetfile=~s/\/+/\//g;
   
     my $docroot=$r->dir_config('lonDocRoot');      my $docroot=$r->dir_config('lonDocRoot');
     my $thisdistarget=$targetfile;      my $thisdistarget=$targetfile;
     $thisdistarget=~s/^$docroot//;      $thisdistarget=~s/^\Q$docroot\E//;
   
   
     undef %metadatafields;      %metadatafields=();
     undef %metadatakeys;      %metadatakeys=();
      %metadatafields=();      $srcfile=~/\.(\w+)$/;
      %metadatakeys=();      my $thistype=$1;
       $srcfile=~/\.(\w+)$/;  
       my $thistype=$1;  
   
   
       my $thisembstyle=&Apache::loncommon::fileembstyle($thistype);      my $thisembstyle=&Apache::loncommon::fileembstyle($thistype);
             
     $r->print('<h2>Publishing <tt>'.$thisdisfn.'</tt></h2>');      my $output = '<h2>'
                .&mt('Publishing [_1]',&Apache::loncfile::display($srcfile))
                .'</h2>';
       unless ($usebuffer) {
           $r->print($output);
           $output = '';
       }
   
 # phase one takes  # phase one takes
 #  my ($source,$target,$style,$batch)=@_;  #  my ($source,$target,$style,$batch)=@_;
     $r->print('<p>'.&publish($srcfile,$targetfile,$thisembstyle,1).'</p>');      my ($outstring,$error)=&publish($srcfile,$targetfile,$thisembstyle,1,$nokeyref);
       
       if ($usebuffer) {
           $output .= '<p>'.$outstring.'</p>';
       } else {
           $r->print('<p>'.$outstring.'</p>');
       }
 # phase two takes  # phase two takes
 # my ($source,$target,$style,$distarget,batch)=@_;  # my ($source,$target,$style,$distarget,batch)=@_;
 # $ENV{'form.allmeta'},$ENV{'form.title'},$ENV{'form.author'},...  # $env{'form.allmeta'},$env{'form.title'},$env{'form.author'},...
     $r->print(      if (!$error) {
 '<p>'.&phasetwo($srcfile,$targetfile,$thisembstyle,$thisdistarget,1).'</p>');          if ($usebuffer) {
     return '';      my ($result,$error) = &phasetwo($r,$srcfile,$targetfile,$thisembstyle,$thisdistarget,1,$usebuffer);
       $output .= '<p>'.$result.'</p>';
           } else {
               &phasetwo($r,$srcfile,$targetfile,$thisembstyle,$thisdistarget,1);
           }
       }
       %env=%oldenv;
       if ($usebuffer) {
           return $output;
       } else {
           return '';
       } 
 }  }
   
 #########################################  #########################################
   
 sub publishdirectory {  sub publishdirectory {
     my ($r,$fn,$thisdisfn)=@_;      my ($r,$fn,$thisdisfn,$nokeyref,$crsauthor)=@_;
     my $resdir=      $fn=~s/\/+/\//g;
     $Apache::lonnet::perlvar{'lonDocRoot'}.'/res/'.$cudom.'/'.$cuname.      $thisdisfn=~s/\/+/\//g;
       $thisdisfn;      my $thisdisresdir=$thisdisfn;
       $r->print('<h1>Directory <tt>'.$thisdisfn.'/</tt></h1>'.      $thisdisresdir=~s/^\/priv\//\/res\//;
                 'Target: <tt>'.$resdir.'</tt><br />');      my $resdir = $r->dir_config('lonDocRoot').$thisdisresdir;
       $r->print('<form name="pubdirpref" method="post" action="">'
       my $dirptr=16384; # Mask indicating a directory in stat.cmode.               .&Apache::lonhtmlcommon::start_pick_box()
                .&Apache::lonhtmlcommon::row_title(&mt('Directory'))
       opendir(DIR,$fn);              .'<span class="LC_filename">'.$thisdisfn.'</span>'
       my @files=sort(readdir(DIR));              .&Apache::lonhtmlcommon::row_closure()
       foreach my $filename (@files) {              .&Apache::lonhtmlcommon::row_title(&mt('Target'))
          my ($cdev,$cino,$cmode,$cnlink,              .'<span class="LC_filename">'.$thisdisresdir.'</span>'
             $cuid,$cgid,$crdev,$csize,      );
             $catime,$cmtime,$cctime,      my %reasons = &Apache::lonlocal::texthash(
             $cblksize,$cblocks)=stat($fn.'/'.$filename);                        mod => 'Authoring Space file postdates published file', 
                         modmeta => 'Authoring Space metadata file postdates published file',
          my $extension='';                        unpub => 'Resource is unpublished',
          if ($filename=~/\.(\w+)$/) { $extension=$1; }      );
          if ($cmode&$dirptr) {  
    if (($filename!~/^\./) && ($ENV{'form.pubrec'})) {      my $dirptr=16384; # Mask indicating a directory in stat.cmode.
       &publishdirectory($r,$fn.'/'.$filename,$thisdisfn.'/'.$filename);      unless ($env{'form.phase'} eq 'two') {
    }  # ask user what they want
          } elsif ((&Apache::loncommon::fileembstyle($extension) ne 'hdn') &&          $r->print(&Apache::lonhtmlcommon::row_closure()
                   ($filename!~/^[\#\.]/) && ($filename!~/\~$/)) {                   .&Apache::lonhtmlcommon::row_title(&mt('Options')
 # find out publication status and/or exiting metadata                   .&Apache::loncommon::help_open_topic('Publishing_Directory_Options')));
      my $publishthis=0;          $r->print(&hiddenfield('phase','two').
              if (-e $resdir.'/'.$filename) {    &hiddenfield('filename',$env{'form.filename'}).
         my ($rdev,$rino,$rmode,$rnlink,                    '<fieldset><legend>'.&mt('Recurse').'</legend>'.
         $ruid,$rgid,$rrdev,$rsize,                    &checkbox('pubrec','include subdirectories').
         $ratime,$rmtime,$rctime,                    '</fieldset>'.
         $rblksize,$rblocks)=stat($resdir.'/'.$filename);                    '<fieldset><legend>'.&mt('Force').'</legend>'.
         if ($rmtime<$cmtime) {                    &checkbox('forcerepub','force republication of previously published files').'<br />'.
                     &checkbox('forceoverride','force directory level metadata over existing').
                     '</fieldset>'.
                     '<fieldset><legend>'.&mt('Exclude').'</legend>'.
                     &checkbox('excludeunpub','exclude currently unpublished files').'<br />'.
                     &checkbox('excludemod','exclude modified files').'<br />'.
                     &checkbox('excludemodmeta','exclude files with modified metadata').
                     '</fieldset>'.
                     '<fieldset><legend>'.&mt('Actions').'</legend>'.
                     &checkbox('obsolete','make file(s) obsolete').'<br />');
           unless ($crsauthor) {
               $r->print(&common_access('dist',&mt('apply common copyright/distribution'),
                                        ['default','domain','public','custom']).'<br />');
           }
           $r->print(&common_access('source',&mt('apply common source availability'),
                                    ['closed','open']).
                     '</fieldset>'
           );
           $r->print(&Apache::lonhtmlcommon::row_closure(1)
                    .&Apache::lonhtmlcommon::end_pick_box()
                    .'<br /><input type="submit" value="'.&mt('Publish Directory').'" /></form>'
           );
           $lock=0;
       } else {
           $r->print(&Apache::lonhtmlcommon::row_closure(1)
                    .&Apache::lonhtmlcommon::end_pick_box()
           );
           my %commonaccess;
           map { $commonaccess{$_} = 1; } &Apache::loncommon::get_env_multiple('form.commonaccess');
           unless ($lock) { $lock=&Apache::lonnet::set_lock(&mt('Publishing [_1]',$fn)); }
   # actually publish things
    opendir(DIR,$fn);
    my @files=sort(readdir(DIR));
    foreach my $filename (@files) {
       my ($cdev,$cino,$cmode,$cnlink,
    $cuid,$cgid,$crdev,$csize,
    $catime,$cmtime,$cctime,
    $cblksize,$cblocks)=stat($fn.'/'.$filename);
       
       my $extension='';
       if ($filename=~/\.(\w+)$/) { $extension=$1; }
       if ($cmode&$dirptr) {
    if (($filename!~/^\./) && ($env{'form.pubrec'})) {
       &publishdirectory($r,$fn.'/'.$filename,$thisdisfn.'/'.$filename,$nokeyref,$crsauthor);
    }
       } elsif ((&Apache::loncommon::fileembstyle($extension) ne 'hdn') &&
        ($filename!~/^[\#\.]/) && ($filename!~/\~$/)) {
   # find out publication status and/or existing metadata
    my $publishthis=0;
                   my $skipthis;
    if (-e $resdir.'/'.$filename) {
       my ($rdev,$rino,$rmode,$rnlink,
    $ruid,$rgid,$rrdev,$rsize,
    $ratime,$rmtime,$rctime,
    $rblksize,$rblocks)=stat($resdir.'/'.$filename);
       if (($rmtime<$cmtime) || ($env{'form.forcerepub'})) {
 # previously published, modified now  # previously published, modified now
     $publishthis=1;                          if ($env{'form.excludemod'}) {
                 }                              $skipthis='mod';
      } else {                          } else {
                               $publishthis=1;
                           }
       }
                       unless ($skipthis) {
                           my $meta_cmtime = (stat($fn.'/'.$filename.'.meta'))[9];
                           my $meta_rmtime = (stat($resdir.'/'.$filename.'.meta'))[9];
                           if ( $meta_rmtime<$meta_cmtime ) {
                               if ($env{'form.excludemodmeta'}) {
                                   $skipthis='modmeta';
                                   $publishthis=0; 
                               } else {
                                   $publishthis=1;
                               }
                           } else {
                               unless (&Apache::loncommon::fileembstyle($extension) eq 'prv') {
                                   if ($commonaccess{'dist'}) {
                                       my ($currdist,$currdistfile,$currsourceavail);
                                       my $currdist =  &Apache::lonnet::metadata($thisdisresdir.'/'.$filename,'copyright');
                                       if ($currdist eq 'custom') {
                                           $currdistfile =  &Apache::lonnet::metadata($thisdisresdir.'/'.$filename,'customdistributionfile');
                                       }
                                       if ($env{'form.commondistselect'} eq 'custom') {
                                           if ($env{'form.commoncustomrights'} =~ m{^/res/.+\.rights$}) {
                                               if ($currdist eq 'custom') {
                                                   unless ($env{'form.commoncustomrights'} eq $currdistfile) {
                                                       $publishthis=1;
                                                   }
                                               } else {
                                                   $publishthis=1;
                                               }
                                           }
                                       } elsif ($env{'form.commondistselect'} =~ /^default|domain|public$/) {
                                           unless ($currdist eq $env{'form.commondistselect'}) {
                                               $publishthis=1;
                                           }
                                       }
                                   }
                               }
                           }
                       }
    } else {
 # never published  # never published
  $publishthis=1;                      if ($env{'form.excludeunpub'}) {
      }                          $skipthis='unpub';
              if ($publishthis) {                      } else {
                 &batchpublish($r,$fn.'/'.$filename,$resdir.'/'.$filename);                          $publishthis=1;
      } else {                      }
                  $r->print('<br />Skipping '.$filename.'<br />');   }
              }  
              $r->rflush();   if ($publishthis) {
          }      &batchpublish($r,$fn.'/'.$filename,$resdir.'/'.$filename,$nokeyref);
       }   } else {
       closedir(DIR);                      my $reason;
                       if ($skipthis) {
                           $reason = $reasons{$skipthis};
                       } else {
                           $reason = &mt('No changes needed to published resource or metadata');
                       }
                       $r->print('<br />'.&mt('Skipping').' '.$filename);
                       if ($reason) {
                           $r->print(' ('.$reason.')');
                       }
                       $r->print('<br />');
    }
    $r->rflush();
       }
    }
    closedir(DIR);
       }
   }
   
   #########################################
   # publish a default.meta file
   
   sub defaultmetapublish {
       my ($r,$fn,$cuname,$cudom)=@_;
       unless (-e $fn) {
          return HTTP_NOT_FOUND;
       }
       my $target=$fn;
       $target=~s/^\Q$Apache::lonnet::perlvar{'lonDocRoot'}\E\/priv\//\Q$Apache::lonnet::perlvar{'lonDocRoot'}\E\/res\//;
   
   
       &Apache::loncommon::content_type($r,'text/html');
       $r->send_http_header;
   
       $r->print(&Apache::loncommon::start_page('Metadata Publication'));
   
   # ---------------------------------------------------------------- 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) {
               mkdir($path,0777);
               $r->print('<p>'
                        .&mt('Created directory [_1]'
                            ,'<span class="LC_filename">'.$parts[$count].'</span>')
                        .'</p>'
               );
           }
       }
       
       if (copy($fn,$copyfile)) {
           $r->print('<p>'.&mt('Copied source file').'</p>');
       } else {
           return "<span class=\"LC_error\">".
       &mt('Failed to copy source').", $!, ".&mt('FAIL')."</span>";
       }
   
   # --------------------------------------------------- Send update notifications
   
       my @subscribed=&get_subscribed_hosts($target);
       foreach my $subhost (@subscribed) {
    $r->print('<p>'.&mt('Notifying host').' '.$subhost.':');$r->rflush;
    my $reply=&Apache::lonnet::critical('update:'.$target,$subhost);
    $r->print($reply.'</p><br />');$r->rflush;
       }
   # ------------------------------------------------------------------- Link back
       $r->print("<a href='".&Apache::loncfile::display($fn)."'>".&mt('Back to Metadata').'</a>');
       $r->print(&Apache::loncommon::end_page());
       return OK;
 }  }
 #########################################  #########################################
   
Line 1555  Publishing from $thisfn to $thistarget w Line 2548  Publishing from $thisfn to $thistarget w
 #########################################  #########################################
 #########################################  #########################################
 sub handler {  sub handler {
   my $r=shift;      my $r=shift;
   
   if ($r->header_only) {      if ($r->header_only) {
      $r->content_type('text/html');   &Apache::loncommon::content_type($r,'text/html');
      $r->send_http_header;   $r->send_http_header;
      return OK;   return OK;
   }      }
   
 # Get query string for limited number of parameters  # Get query string for limited number of parameters
   
     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},      &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
                                             ['filename']);                                              ['filename']);
   
   # -------------------------------------- Flag and buffer for registered cleanup
       $registered_cleanup=0;
       @{$modified_urls}=();
 # -------------------------------------------------------------- Check filename  # -------------------------------------------------------------- Check filename
   
   my $fn=$ENV{'form.filename'};      my $fn=&unescape($env{'form.filename'});
       ($cuname,$cudom)=&Apache::lonnet::constructaccess($fn);
     # ----------------------------------------------------- Do we have permissions?
   unless ($fn) {        unless (($cuname) && ($cudom)) {
      $r->log_reason($cuname.' at '.$cudom.         $r->log_reason($env{'user.name'}.' at '.$env{'user.domain'}.
          ' trying to publish empty filename', $r->filename);                         ' trying to publish file '.$env{'form.filename'}.
      return HTTP_NOT_FOUND;                        ' - not authorized', 
   }                         $r->filename); 
          return HTTP_NOT_ACCEPTABLE;
   ($cuname,$cudom)=       }
     &Apache::loncacc::constructaccess($fn,$r->dir_config('lonDefDomain'));  # ----------------------------------------------------------------- Get docroot
   unless (($cuname) && ($cudom)) {      $docroot=$r->dir_config('lonDocRoot');
      $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'}.  
          ' ('.$fn.') - not homeserver ('.  
          &Apache::lonnet::homeserver($cuname,$cudom).')',   
          $r->filename);   
      return HTTP_NOT_ACCEPTABLE;  
   }  
   
   $fn=~s/^http\:\/\/[^\/]+//;  
   $fn=~s/^\/\~(\w+)/\/home\/$1\/public_html/;  
   
   my $targetdir='';  
   $docroot=$r->dir_config('lonDocRoot');   
   if ($1 ne $cuname) {  
      $r->log_reason($cuname.' at '.$cudom.  
          ' trying to publish unowned file '.$ENV{'form.filename'}.  
          ' ('.$fn.')',   
          $r->filename);   
      return HTTP_NOT_ACCEPTABLE;  
   } else {  
       $targetdir=$docroot.'/res/'.$cudom;  
   }  
                                    
     
   unless (-e $fn) {   
      $r->log_reason($cuname.' at '.$cudom.  
          ' trying to publish non-existing file '.$ENV{'form.filename'}.  
          ' ('.$fn.')',   
          $r->filename);   
      return HTTP_NOT_FOUND;  
   }   
   
 unless ($ENV{'form.phase'} eq 'two') {  
   
 # -------------------------------- File is there and owned, init lookup tables.  # special publication: default.meta file
       if ($fn=~/\/default.meta$/) {
    return &defaultmetapublish($r,$fn,$cuname,$cudom); 
       }
       $fn=~s/\.meta$//;
   
   %addid=();  # sanity test on the filename 
    
       unless ($fn) { 
    $r->log_reason($cuname.' at '.$cudom.
          ' trying to publish empty filename', $r->filename); 
    return HTTP_NOT_FOUND;
       } 
   
   {      unless (-e $docroot.$fn) { 
       my $fh=Apache::File->new($r->dir_config('lonTabDir').'/addid.tab');   $r->log_reason($cuname.' at '.$cudom.
       while (<$fh>=~/(\w+)\s+(\w+)/) {         ' trying to publish non-existing file '.
           $addid{$1}=$2;         $env{'form.filename'}.' ('.$fn.')', 
       }         $r->filename); 
   }   return HTTP_NOT_FOUND;
       } 
   
   %nokey=();  # --------------------------------- File is there and owned, start page output
   
   {      &Apache::loncommon::content_type($r,'text/html');
      my $fh=Apache::File->new($r->dir_config('lonIncludes').'/un_keyword.tab');      $r->send_http_header;
       while (<$fh>) {  
           my $word=$_;  
           chomp($word);  
           $nokey{$word}=1;  
       }  
   }  
   
       # Breadcrumbs
       &Apache::lonhtmlcommon::clear_breadcrumbs();
       my $crumbtext = 'Authoring Space';
       my $crumbhref = &Apache::loncommon::authorspace($fn);
       my $crsauthor;
       if ($env{'request.course.id'}) {
           my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
           my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
           if ($crumbhref eq "/priv/$cdom/$cnum/") {
               $crumbtext = 'Course Authoring Space';
               $crsauthor = 1;
           }
       }
       &Apache::lonhtmlcommon::add_breadcrumb({
           'text'  => $crumbtext,
           'href'  => $crumbhref,
       });
       &Apache::lonhtmlcommon::add_breadcrumb({
           'text'  => 'Resource Publication',
           'href'  => '',
       });
   
       my $js='<script type="text/javascript">'.
    &Apache::loncommon::browser_and_searcher_javascript().
    '</script>';
       my $startargs = {};
       if ($fn=~/\/$/) {
           unless ($env{'form.phase'} eq 'two') {
               $startargs->{'add_entries'} = { onload => 'javascript:setDefaultAccess();' };
               $js .= <<"END";
   <script type="text/javascript">
   // <![CDATA[
   function showHideAccess(caller,div) {
       if (document.getElementById(div)) {
           if (caller.checked) {
               document.getElementById(div).style.display='inline-block';
           } else {
               document.getElementById(div).style.display='none';
           }
       }
 }  }
   
 # ---------------------------------------------------------- Start page output.  function showHideCustom(caller,divid) {
       if (document.getElementById(divid)) {
   $r->content_type('text/html');          if (caller.options[caller.selectedIndex].value == 'custom') {
   $r->send_http_header;              document.getElementById(divid).style.display="inline-block";
           } else {
   $r->print('<html><head><title>LON-CAPA Publishing</title></head>');              document.getElementById(divid).style.display="none";
   $r->print(&Apache::loncommon::bodytag('Resource Publication'));          }
   my $thisfn=$fn;      }
   }
   my $thistarget=$thisfn;  function setDefaultAccess() {
             var chkids = Array('LC_commondist','LC_commonsource');
   $thistarget=~s/^\/home/$targetdir/;      for (var i=0; i<chkids.length; i++) {
   $thistarget=~s/\/public\_html//;          if (document.getElementById(chkids[i])) {
               document.getElementById(chkids[i]).checked = false;
   my $thisdistarget=$thistarget;          }
   $thisdistarget=~s/^$docroot//;          if (document.getElementById(chkids[i]+'select')) {
              document.getElementById(chkids[i]+'select').selectedIndex = 0; 
           }
           if (document.getElementById(chkids[i]+'div')) {
               document.getElementById(chkids[i]+'div').style.display = 'none';
           }
       }
   }
   // ]]>
   </script>
   
   my $thisdisfn=$thisfn;  END
   $thisdisfn=~s/^\/home\/$cuname\/public_html\///;          }
       }
       $r->print(&Apache::loncommon::start_page('Resource Publication',$js,$startargs)
                .&Apache::lonhtmlcommon::breadcrumbs()
                .&Apache::loncommon::head_subbox(
                     &Apache::loncommon::CSTR_pageheader($docroot.$fn))
       );
   
       my $thisdisfn=&HTML::Entities::encode($fn,'<>&"');
       my $thistarget=$fn;
       $thistarget=~s/^\/priv\//\/res\//;
       my $thisdistarget=&HTML::Entities::encode($thistarget,'<>&"');
       my $nokeyref = &getnokey($r->dir_config('lonIncludes'));
   
   if ($fn=~/\/$/) {      if ($fn=~/\/$/) {
 # -------------------------------------------------------- This is a directory  # -------------------------------------------------------- This is a directory
       &publishdirectory($r,$fn,$thisdisfn);   &publishdirectory($r,$docroot.$fn,$thisdisfn,$nokeyref,$crsauthor);
           $r->print(
   } else {              '<br /><br />'.
               &Apache::lonhtmlcommon::actionbox([
                   '<a href="'.$thisdisfn.'">'.&mt('Return to Directory').'</a>']));
       } else {
 # ---------------------- Evaluate individual file, and then output information.  # ---------------------- Evaluate individual file, and then output information.
       $thisfn=~/\.(\w+)$/;   $fn=~/\.(\w+)$/;
       my $thistype=$1;   my $thistype=$1;
       my $thisembstyle=&Apache::loncommon::fileembstyle($thistype);   my $thisembstyle=&Apache::loncommon::fileembstyle($thistype);
           if ($thistype eq 'page') {  $thisembstyle = 'rat'; }
       $r->print('<h2>Publishing '.  
         &Apache::loncommon::filedescription($thistype).' <tt>'.          $r->print('<h2>'
         '<a href="/~'.$cuname.'/'.$thisdisfn.'" target="cat">'.$thisdisfn.                   .&mt('Publishing [_1]'
         '</a></tt></h2><b>Target:</b> <tt>'.$thisdistarget.'</tt><p>');                       ,'<span class="LC_filename">'.$thisdisfn.'</span>')
                       .'</h2>'
       if (($cuname ne $ENV{'user.name'}) || ($cudom ne $ENV{'user.domain'})) {          );
           $r->print('<h3><font color="red">Co-Author: '.$cuname.' at '.$cudom.  
     '</font></h3>');          $r->print('<h3>'.&mt('Resource Details').'</h3>');
       }  
           $r->print(&Apache::lonhtmlcommon::start_pick_box());
       if (&Apache::loncommon::fileembstyle($thistype) eq 'ssi') {  
           $r->print('<br /><a href="/adm/diff?filename=/~'.$cuname.'/'.          $r->print(&Apache::lonhtmlcommon::row_title(&mt('Type'))
                     $thisdisfn.                   .&Apache::loncommon::filedescription($thistype)
    '&versionone=priv" target="cat">Diffs with Current Version</a><p>');                   .&Apache::lonhtmlcommon::row_closure()
       }                   );
   
           $r->print(&Apache::lonhtmlcommon::row_title(&mt('Link to Resource'))
                    .'<tt>'
                    );
    $r->print(<<ENDCAPTION);
   <a href='javascript:void(window.open("$thisdisfn","cat","height=300,width=500,scrollbars=1,resizable=1,menubar=0,location=1"))'>
   $thisdisfn</a>
   ENDCAPTION
           $r->print('</tt>'
                    .&Apache::lonhtmlcommon::row_closure()
                    );
   
           $r->print(&Apache::lonhtmlcommon::row_title(&mt('Target'))
                    .'<tt>'.$thisdistarget.'</tt>'
                    );
    if (($cuname ne $env{'user.name'})||($cudom ne $env{'user.domain'})) {
               $r->print(&Apache::lonhtmlcommon::row_closure()
                        .&Apache::lonhtmlcommon::row_title(&mt('Co-Author'))
                        .'<span class="LC_warning">'
        .&Apache::loncommon::plainname($cuname,$cudom) .' ('.$cuname.':'.$cudom.')'
                        .'</span>'
                        );
    }
   
    if (&Apache::loncommon::fileembstyle($thistype) eq 'ssi') {
               $r->print(&Apache::lonhtmlcommon::row_closure()
                        .&Apache::lonhtmlcommon::row_title(&mt('Diffs')));
       $r->print(<<ENDDIFF);
   <a href='javascript:void(window.open("/adm/diff?filename=$thisdisfn&amp;versiontwo=priv","cat","height=300,width=500,scrollbars=1,resizable=1,menubar=0,location=1"))'>
   ENDDIFF
               $r->print(&mt('Diffs with Current Version').'</a>');
    }
           
           $r->print(&Apache::lonhtmlcommon::row_closure(1)
                    .&Apache::lonhtmlcommon::end_pick_box()
                    );
       
 # ------------------ Publishing from $thisfn to $thistarget with $thisembstyle.  # ---------------------- Publishing from $fn to $thistarget with $thisembstyle.
   
    unless ($env{'form.phase'} eq 'two') {
   # ---------------------------------------------------------- Parse for problems
       my ($warningcount,$errorcount);
       if ($thisembstyle eq 'ssi') {
    ($warningcount,$errorcount)=&checkonthis($r,$fn);
       }
       unless ($errorcount) {
    my ($outstring,$error)=
       &publish($docroot.$fn,$docroot.$thistarget,$thisembstyle,undef,$nokeyref);
    $r->print($outstring);
       } else {
    $r->print('<h3 class="LC_error">'.
     &mt('The document contains errors and cannot be published.').
     '</h3>');
       }
    } else {
       my ($output,$error) = &phasetwo($r,$docroot.$fn,$docroot.$thistarget,
                                               $thisembstyle,$thisdistarget);
               $r->print($output);
    }
       }
       $r->print(&Apache::loncommon::end_page());
   
        unless ($ENV{'form.phase'} eq 'two') {      return OK;
          $r->print(  }
           '<hr />'.&publish($thisfn,$thistarget,$thisembstyle));  
        } else {  BEGIN {
          $r->print(  
           '<hr />'.&phasetwo($thisfn,$thistarget,  
      $thisembstyle,$thisdistarget));   
        }    
   
   }  # ----------------------------------- Read addid.tab
   $r->print('</body></html>');      unless ($readit) {
           %addid=();
   
   return OK;          {
               my $tabdir = $Apache::lonnet::perlvar{'lonTabDir'};
               my $fh=Apache::File->new($tabdir.'/addid.tab');
               while (<$fh>=~/(\w+)\s+(\w+)/) {
                   $addid{$1}=$2;
               }
           }
       }
       $readit=1;
 }  }
   
   
 1;  1;
 __END__  __END__
   

Removed from v.1.97  
changed lines
  Added in v.1.303


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