[LON-CAPA-cvs] cvs: doc /loncapafiles loncapafiles.lpml loncom loncapa_apache.conf loncom/interface loncommon.pm loncom/publisher lonpubdisplay.pm lonpublisher.pm

raeburn raeburn at source.lon-capa.org
Thu Jul 31 11:15:38 EDT 2025


raeburn		Thu Jul 31 15:15:38 2025 EDT

  Added files:                 
    /loncom/publisher	lonpubdisplay.pm 

  Modified files:              
    /loncom/publisher	lonpublisher.pm 
    /loncom/interface	loncommon.pm 
    /loncom	loncapa_apache.conf 
    /doc/loncapafiles	loncapafiles.lpml 
  Log:
  - Move handler and some routines in lonpublisher.pm to lonpubdisplay.pm
    so lonpublisher.pm no longer needs Apache::Constants to facilitate calling
    lonpublisher::batchpublish() outside of Apache context.
    - Replace use of Apache::File with standard open()
    - Copies of &url() and &display() in loncfile.pm added as &cfile_url()
      and &cfile_display() in loncommon.pm, so lonpublisher.pm no longer needs
      loncfile.pm (which needs Apache::Constants).
  
  
-------------- next part --------------
Index: loncom/publisher/lonpublisher.pm
diff -u loncom/publisher/lonpublisher.pm:1.309 loncom/publisher/lonpublisher.pm:1.310
--- loncom/publisher/lonpublisher.pm:1.309	Wed Jul 30 05:00:06 2025
+++ loncom/publisher/lonpublisher.pm	Thu Jul 31 15:15:36 2025
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Publication Handler
 #
-# $Id: lonpublisher.pm,v 1.309 2025/07/30 05:00:06 raeburn Exp $
+# $Id: lonpublisher.pm,v 1.310 2025/07/31 15:15:36 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -47,22 +47,12 @@
 
 =head1 NAME
 
-lonpublisher - LON-CAPA publishing handler
+Apache::lonpublisher
 
 =head1 SYNOPSIS
 
-B<lonpublisher> is used by B<mod_perl> inside B<Apache>.  This is the
-invocation by F<loncapa_apache.conf>:
-
-  <Location /adm/publish>
-  PerlAccessHandler       Apache::lonacc
-  SetHandler perl-script
-  PerlHandler Apache::lonpublisher
-  ErrorDocument     403 /adm/login
-  ErrorDocument     404 /adm/notfound.html
-  ErrorDocument     406 /adm/unauthorized.html
-  ErrorDocument     500 /adm/errorhandler
-  </Location>
+    Utilities for publishing resources
+    Provides subroutines called by lonpubdisplay.pm
 
 =head1 OVERVIEW
 
@@ -112,34 +102,21 @@
 
 # ------------------------------------------------- modules used by this module
 use strict;
-use Apache::File;
 use File::Copy;
-use Apache::Constants qw(:common :http :methods);
 use HTML::LCParser;
 use HTML::Entities;
 use Encode::Encoder;
-use Apache::lonxml;
 use DBI;
 use Apache::lonnet;
 use Apache::loncommon();
 use Apache::lonhtmlcommon;
 use Apache::lonmysql;
 use Apache::lonlocal;
-use Apache::loncfile;
 use LONCAPA::lonmetadata;
 use Apache::lonmsg;
-use vars qw(%metadatafields %metadatakeys %addid $readit);
 use LONCAPA qw(:DEFAULT :match);
- 
-my $docroot;
-
-my $cuname;
-my $cudom;
 
-my $registered_cleanup;
-my $modified_urls;
-
-my $lock;
+use vars qw(%metadatafields %metadatakeys %addid $readit $cuname $cudom $modified_urls $lock);
 
 =pod
 
@@ -262,44 +239,28 @@
     unless (-e $fn) {
 	print($logfile 'No file '.$fn."\n");
         return '<p class="LC_warning">'
-              .&mt('No file: [_1]',&Apache::loncfile::display($fn))
+              .&mt('No file: [_1]',
+		   &Apache::loncommon::cfile_display($fn))
               .'</p>';
     }
     print($logfile 'Processing '.$fn."\n");
     my $metastring;
     {
-	my $metafh=Apache::File->new($fn);
-	$metastring=join('',<$metafh>);
+        if (open(my $metafh,'<',$fn)) {
+            $metastring=join('',<$metafh>);
+            close($metafh);
+        }
     }
     &metaeval($metastring,$prefix);
     return '<p class="LC_info">'
-          .&mt('Processed file: [_1]',&Apache::loncfile::display($fn))
+          .&mt('Processed file: [_1]',
+               &Apache::loncommon::cfile_display($fn))
           .'</p>';
 }
 
 #########################################
 #########################################
 
-sub coursedependencies {
-    my $url=&Apache::lonnet::declutter(shift);
-    $url=~s/\.meta$//;
-    my ($adomain,$aauthor)=($url=~ m{^($match_domain)/($match_username)/});
-    my $regexp=quotemeta($url);
-    $regexp='___'.$regexp.'___course';
-    my %evaldata=&Apache::lonnet::dump('nohist_resevaldata',$adomain,
-				       $aauthor,$regexp);
-    my %courses=();
-    foreach my $item (keys(%evaldata)) {
-	if ($item=~/^([a-zA-Z0-9]+_[a-zA-Z0-9]+)___.+___course$/) {
-	    $courses{$1}=1;
-        }
-    }
-    return %courses;
-}
-#########################################
-#########################################
-
-
 =pod
 
 =item Form-field-generating subroutines.
@@ -589,8 +550,7 @@
 	}
     }
     closedir(DIR);
-    my $sh;
-    if ( $sh=Apache::File->new("$target.subscription") ) {
+    if (open(my $sh,'<',"$target.subscription")) {
 	while (my $subline=<$sh>) {
 	    if ($subline =~ /^($match_lonid):/) { 
                 if ($1 ne $Apache::lonnet::perlvar{'lonHostID'}) { 
@@ -598,6 +558,7 @@
 	        }
 	    }
 	}
+        close($sh);
     }
     return @subscribed;
 }
@@ -723,8 +684,10 @@
     my %allow;
     my $content;
     {
-	my $org=Apache::File->new($source);
-	$content=join('',<$org>);
+        if (open(my $org,'<',$source)) {
+            $content=join('',<$org>);
+            close($org);
+        }
     }
 
     my ($needsfixup,$maxid,$maxindex,$duplicateids, at duplicatedids)=
@@ -1120,8 +1083,9 @@
     my $allmeta='';
     my $content='';
     my %allow=();
+    my $docroot = $Apache::lonnet::perlvar{'lonDocRoot'};
 
-    unless ($logfile=Apache::File->new('>>'.$source.'.log')) {
+    unless (open($logfile,'>>',$source.'.log')) {
 	return ('<span class="LC_error">'.&mt('No write permission to user directory, FAIL').'</span>',1);
     }
     print $logfile 
@@ -1136,6 +1100,7 @@
 	    print $logfile "Copied original file to ".$copyfile."\n";
         } else {
 	    print $logfile "Unable to write backup ".$copyfile.':'.$!."\n";
+            close($logfile);
 	    return ("<span class=\"LC_error\">".&mt("Failed to write backup copy, [_1], FAIL",$1)."</span>",1);
         }
 # ------------------------------------------------------------- IDs and indices
@@ -1143,7 +1108,7 @@
 	my ($outstring,$error);
 	($outstring,$error,%allow)=&fix_ids_and_indices($logfile,$source,
 							$target);
-	if ($error) { return ($outstring,$error); }
+	if ($error) { close($logfile); return ($outstring,$error); }
 # ------------------------------------------------------------ Construct Allows
     
         my $outdep=''; # Collect dependencies output data
@@ -1200,13 +1165,15 @@
 
         {
           my $org;
-          unless ($org=Apache::File->new('>'.$source)) {
+          unless (open($org,'>',$source)) {
              print $logfile "No write permit to $source\n";
+             close($logfile);
              return ('<span class="LC_error">'.&mt('No write permission to').
 		     ' '.$source.
 		     ', '.&mt('FAIL').'</span>',1);
 	  }
           print($org $outstring);
+          close($org);
         }
 	  $content=$outstring;
 
@@ -1217,7 +1184,6 @@
     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";
@@ -1400,7 +1366,8 @@
                     .'</p>'
                     .'<p><input type="submit" value="'
                     .&mt('Finalize Publication')
-                    .'" /> <a href="'.&Apache::loncfile::url($source).'">'.&mt('Cancel').'</a></p>';
+                    .'" /> <a href="'.&Apache::loncommon::cfile_url($source).'">'
+                    .&mt('Cancel').'</a></p>';
     }
     $intr_scrout.=&Apache::lonhtmlcommon::start_pick_box();
     $intr_scrout.=
@@ -1623,17 +1590,20 @@
             .'" /></p>'
             .'</form>';
     }
+    close($logfile);
     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;
+    if (open(my $fh,'<',$includedir.'/un_keyword.tab')) {
+        while (<$fh>) {
+            my $word=$_;
+            chomp($word);
+            $nokey->{$word}=1;
+        }
+        close($fh);
     }
     return $nokey;
 }
@@ -1691,6 +1661,8 @@
     my ($r,$source,$target,$style,$distarget,$batch,$usebuffer)=@_;
     $source=~s/\/+/\//g;
     $target=~s/\/+/\//g;
+
+    my $docroot = $Apache::lonnet::perlvar{'lonDocRoot'};
 #
 # Unless trying to get rid of something, check name validity
 #
@@ -1744,7 +1716,7 @@
 #
     $distarget=~s/\/+/\//g;
     my $logfile;
-    unless ($logfile=Apache::File->new('>>'.$source.'.log')) {
+    unless (open($logfile,'>>',$source.'.log')) {
         $output = '<span class="LC_error">'.
 		  &mt('No write permission to user directory, FAIL').'</span>';
         if ($usebuffer) {
@@ -1861,6 +1833,7 @@
 	unless ($file=~/\.rights$/) {
             $output .= '<span class="LC_error">'.&mt('No valid custom distribution rights file specified, FAIL').
 		       '</span>';
+            close($logfile);
             if ($usebuffer) {
                 if (wantarray) {
                     return ($output,0);
@@ -1876,9 +1849,10 @@
     {
         print $logfile "\nWrite metadata file for ".$source;
         my $mfh;
-        unless ($mfh=Apache::File->new('>'.$source.'.meta')) {
+        unless (open($mfh,'>',$source.'.meta')) {
             $output .= '<span class="LC_error">'.&mt('Could not write metadata, FAIL').
 		       '</span>';
+            close($logfile);
             if ($usebuffer) {
                 if (wantarray) {
                     return ($output,0);
@@ -1908,6 +1882,7 @@
             }
         }
 
+        close($mfh);
         $output  .= '<p>'.&mt('Wrote Metadata').'</p>';
         unless ($usebuffer) {
             $r->print($output);
@@ -1952,9 +1927,9 @@
         my $srcf=$2;
         my $srct=$3;
         my $srcd=$1;
-        my $docroot = $Apache::lonnet::perlvar{'lonDocRoot'};
         unless ($srcd=~/^\Q$docroot\E\/res/) {
             print $logfile "\nPANIC: Target dir is ".$srcd;
+            close($logfile);
             $output .= 
 	 "<span class=\"LC_error\">".&mt('Invalid target directory, FAIL')."</span>";
             if ($usebuffer) {
@@ -1999,6 +1974,7 @@
             }
         } else {
 	    print $logfile "Unable to write ".$copyfile.':'.$!."\n";
+            close($logfile);
             $output .= &Apache::lonhtmlcommon::confirm_success(&mt('Failed to copy old target').", $!",1);
             if ($usebuffer) {
                 if (wantarray) {
@@ -2026,6 +2002,7 @@
         } else {
 	    print $logfile "Unable to write metadata ".$copyfile.':'.$!."\n";
             if (-e $target.'.meta') {
+                close($logfile);
                 $output .= &Apache::lonhtmlcommon::confirm_success(
                                &mt('Failed to write old metadata copy').", $!",1);
                 if ($usebuffer) {
@@ -2081,6 +2058,7 @@
         }
     } else {
         print $logfile "\nUnable to write ".$copyfile.':'.$!."\n";
+        close($logfile);
         $output .= &Apache::lonhtmlcommon::confirm_success(
 	    &mt('Failed to copy source').", $!",1);
         if ($usebuffer) {
@@ -2110,6 +2088,7 @@
         }
     } else {
         print $logfile "\nUnable to write metadata ".$copyfile.':'.$!."\n";
+        close($logfile);
         $output .= &Apache::lonhtmlcommon::confirm_success(
                      &mt('Failed to write metadata copy').", $!",1);
         if ($usebuffer) {
@@ -2129,7 +2108,6 @@
 
 # ------------------------------------------------------------- Trigger updates
     push(@{$modified_urls},[$target,$source]);
-    &notify_in_cleanup($r);
 
 # ---------------------------------------------------------- Clear local caches
     my $thisdistarget=$target;
@@ -2139,7 +2117,7 @@
 			 &Apache::lonnet::declutter($thisdistarget));
 
 # ------------------------------------------------------------- Everything done
-    $logfile->close();
+    close($logfile);
     $output .= '<p class="LC_success">'.&mt('Done').'</p>';
     unless ($usebuffer) {
         $r->print($output);
@@ -2149,7 +2127,7 @@
 # ------------------------------------------------ Provide link to new resource
     unless ($batch) {
         
-        my $thissrc=&Apache::loncfile::url($source);
+        my $thissrc=&Apache::loncommon::cfile_url($source);
         my $thissrcdir=$thissrc;
         $thissrcdir=~s/\/[^\/]+$/\//;
         
@@ -2185,56 +2163,6 @@
     }
 }
 
-sub notify_in_cleanup {
-    my ($r) = @_;
-    unless ($registered_cleanup) {
-        my $handlers = $r->get_handlers('PerlCleanupHandler');
-        $r->set_handlers('PerlCleanupHandler' => [\&notify,@{$handlers}]);
-        $registered_cleanup=1;
-    }
-}
-
-# =============================================================== Notifications
-sub notify {  
-# --------------------------------------------------- Send update notifications
-    if (ref($modified_urls) eq 'ARRAY') {
-        foreach my $targetsource (@{$modified_urls}){
-	    my ($target,$source)=@{$targetsource};
-	    my $logfile=Apache::File->new('>>'.$source.'.log');
-	    print $logfile "\nCleanup phase: Notifications\n";
-	    my @subscribed=&get_subscribed_hosts($target);
-	    foreach my $subhost (@subscribed) {
-	        print $logfile "\nNotifying host ".$subhost.':';
-	        my $reply=&Apache::lonnet::critical('update:'.$target,$subhost);
-	        print $logfile $reply;
-	    }
-# ---------------------------------------- Send update notifications, meta only
-	    my @subscribedmeta=&get_subscribed_hosts("$target.meta");
-	    foreach my $subhost (@subscribedmeta) {
-	        print $logfile "\nNotifying host for metadata only ".$subhost.':';
-	        my $reply=&Apache::lonnet::critical('update:'.$target.'.meta',
-		    				    $subhost);
-	        print $logfile $reply;
-	    }
-# --------------------------------------------------- Notify subscribed courses
-	    my %courses=&coursedependencies($target);
-	    my $now=time;
-	    foreach 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();
-        }
-        $modified_urls = [];
-    }
-    if ($lock) { &Apache::lonnet::remove_lock($lock); }
-    return OK;
-}
-
 #########################################
 
 sub batchpublish {
@@ -2244,7 +2172,12 @@
     $srcfile=~s/\/+/\//g;
     $targetfile=~s/\/+/\//g;
 
-    my $docroot=$r->dir_config('lonDocRoot');
+    my $docroot;
+    if ($usebuffer) {
+        $docroot=$Apache::lonnet::perlvar{'lonDocRoot'};
+    } else {
+        $docroot=$r->dir_config('lonDocRoot');
+    }
     my $thisdistarget=$targetfile;
     $thisdistarget=~s/^\Q$docroot\E//;
 
@@ -2270,7 +2203,8 @@
     my $thisembstyle=&Apache::loncommon::fileembstyle($thistype);
      
     my $output = '<h2>'
-             .&mt('Publishing [_1]',&Apache::loncfile::display($srcfile))
+             .&mt('Publishing [_1]',
+                  &Apache::loncommon::cfile_display($srcfile))
              .'</h2>';
     unless ($usebuffer) {
         $r->print($output);
@@ -2374,9 +2308,6 @@
         my %commonaccess;
         map { $commonaccess{$_} = 1; } &Apache::loncommon::get_env_multiple('form.commonaccess');
         unless ($lock) { $lock=&Apache::lonnet::set_lock(&mt('Publishing [_1]',$fn)); }
-        if ($lock) {
-            &notify_in_cleanup($r);
-        }
 # actually publish things
 	opendir(DIR,$fn);
 	my @files=sort(readdir(DIR));
@@ -2478,341 +2409,6 @@
     }
 }
 
-#########################################
-# 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/}{$Apache::lonnet::perlvar{'lonDocRoot'}/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 {
-        $r->print('<span class="LC_error">'.
-                  &mt('Failed to copy source').", $!, ".&mt('FAIL').
-                  '</span>');
-        $r->print(&Apache::loncommon::end_page());
-        return OK;
-    }
-
-# --------------------------------------------------- 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::url($fn).'">'.&mt('Back to Metadata').'</a>');
-    $r->print(&Apache::loncommon::end_page());
-    return OK;
-}
-#########################################
-
-=pod
-
-=item B<handler>
-
-A basic outline of the handler subroutine follows.
-
-=over 4
-
-=item *
-
-Get query string for limited number of parameters.
-
-=item *
-
-Check filename.
-
-=item *
-
-File is there and owned, init lookup tables.
-
-=item *
-
-Start page output.
-
-=item *
-
-Evaluate individual file, and then output information.
-
-=item *
-
-Publishing from $thisfn to $thistarget with $thisembstyle.
-
-=back
-
-=cut
-
-#########################################
-#########################################
-sub handler {
-    my $r=shift;
-
-    if ($r->header_only) {
-	&Apache::loncommon::content_type($r,'text/html');
-	$r->send_http_header;
-	return OK;
-    }
-
-# Get query string for limited number of parameters
-
-    &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
-                                            ['filename']);
-
-# -------------------------------------- Flag and buffer for registered cleanup
-    $registered_cleanup=0;
-    @{$modified_urls}=();
-# -------------------------------------------------------------- Check filename
-
-    my $fn=&unescape($env{'form.filename'});
-    ($cuname,$cudom)=&Apache::lonnet::constructaccess($fn);
-# ----------------------------------------------------- Do we have permissions?
-     unless (($cuname) && ($cudom)) {
-       $r->log_reason($env{'user.name'}.' at '.$env{'user.domain'}.
-                      ' trying to publish file '.$env{'form.filename'}.
-                      ' - not authorized', 
-                      $r->filename); 
-       return HTTP_NOT_ACCEPTABLE;
-     }
-# ----------------------------------------------------------------- Get docroot
-    $docroot=$r->dir_config('lonDocRoot');
-
-
-# special publication: default.meta file
-    if ($fn=~/\/default.meta$/) {
-	return &defaultmetapublish($r,$docroot.$fn,$cuname,$cudom); 
-    }
-    $fn=~s/\.meta$//;
-
-# 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) { 
-	$r->log_reason($cuname.' at '.$cudom.
-		       ' trying to publish non-existing file '.
-		       $env{'form.filename'}.' ('.$fn.')', 
-		       $r->filename); 
-	return HTTP_NOT_FOUND;
-    } 
-
-# --------------------------------- File is there and owned, start page output
-
-    &Apache::loncommon::content_type($r,'text/html');
-    $r->send_http_header;
-
-    # 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';
-        }
-    }
-}
-
-function showHideCustom(caller,divid) {
-    if (document.getElementById(divid)) {
-        if (caller.options[caller.selectedIndex].value == 'custom') {
-            document.getElementById(divid).style.display="inline-block";
-        } else {
-            document.getElementById(divid).style.display="none";
-        }
-    }
-}
-function setDefaultAccess() {
-    var chkids = Array('LC_commondist','LC_commonsource');
-    for (var i=0; i<chkids.length; i++) {
-        if (document.getElementById(chkids[i])) {
-            document.getElementById(chkids[i]).checked = false;
-        }
-        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>
-
-END
-        }
-    }
-    $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=~/\/$/) {
-# -------------------------------------------------------- This is a directory
-	&publishdirectory($r,$docroot.$fn,$thisdisfn,$nokeyref,$crsauthor);
-        $r->print(
-            '<br /><br />'.
-            &Apache::lonhtmlcommon::actionbox([
-                '<a href="'.$thisdisfn.'">'.&mt('Return to Directory').'</a>']));
-    } else {
-# ---------------------- Evaluate individual file, and then output information.
-	$fn=~/\.(\w+)$/;
-	my $thistype=$1;
-	my $thisembstyle=&Apache::loncommon::fileembstyle($thistype);
-        if ($thistype eq 'page') {  $thisembstyle = 'rat'; }
-
-        $r->print('<h2>'
-                 .&mt('Publishing [_1]'
-                     ,'<span class="LC_filename">'.$thisdisfn.'</span>')
-                 .'</h2>'
-        );
-
-        $r->print('<h3>'.&mt('Resource Details').'</h3>');
-
-        $r->print(&Apache::lonhtmlcommon::start_pick_box());
-
-        $r->print(&Apache::lonhtmlcommon::row_title(&mt('Type'))
-                 .&Apache::loncommon::filedescription($thistype)
-                 .&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&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 $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());
-
-    return OK;
-}
-
 BEGIN {
 
 # ----------------------------------- Read addid.tab
@@ -2821,9 +2417,10 @@
 
         {
             my $tabdir = $Apache::lonnet::perlvar{'lonTabDir'};
-            my $fh=Apache::File->new($tabdir.'/addid.tab');
-            while (<$fh>=~/(\w+)\s+(\w+)/) {
-                $addid{$1}=$2;
+            if (open(my $fh,'<',$tabdir.'/addid.tab')) {
+                while (<$fh>=~/(\w+)\s+(\w+)/) {
+                    $addid{$1}=$2;
+                }
             }
         }
     }
Index: loncom/interface/loncommon.pm
diff -u loncom/interface/loncommon.pm:1.1478 loncom/interface/loncommon.pm:1.1479
--- loncom/interface/loncommon.pm:1.1478	Sat Jun 28 14:34:46 2025
+++ loncom/interface/loncommon.pm	Thu Jul 31 15:15:37 2025
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # a pile of common routines
 #
-# $Id: loncommon.pm,v 1.1478 2025/06/28 14:34:46 raeburn Exp $
+# $Id: loncommon.pm,v 1.1479 2025/07/31 15:15:37 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -6817,6 +6817,27 @@
     return %editors;
 }
 
+sub cfile_url {
+    my ($fn,$context) = @_;
+    my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'};
+    $fn=~ s/^\Q$londocroot\E//;
+    $fn=~s{/\./}{/}g;
+    if ($context eq 'js') {
+        &js_escape(\$fn);
+    } else {
+        $fn=&HTML::Entities::encode($fn,'\'<>"&');
+    }
+    return $fn;
+}
+
+sub cfile_display {
+    my $fn=shift;
+    my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'};
+    $fn=~s/^\Q$londocroot\E//;
+    $fn=~s{/\./}{/}g;
+    return '<span class="LC_filename">'.$fn.'</span>';
+}
+
 ###############################################
 ###############################################
 
Index: loncom/loncapa_apache.conf
diff -u loncom/loncapa_apache.conf:1.286 loncom/loncapa_apache.conf:1.287
--- loncom/loncapa_apache.conf:1.286	Mon Jan  8 02:23:45 2024
+++ loncom/loncapa_apache.conf	Thu Jul 31 15:15:37 2025
@@ -2,7 +2,7 @@
 ## loncapa_apache.conf -- Apache HTTP LON-CAPA configuration file
 ##
 
-# $Id: loncapa_apache.conf,v 1.286 2024/01/08 02:23:45 raeburn Exp $
+# $Id: loncapa_apache.conf,v 1.287 2025/07/31 15:15:37 raeburn Exp $
 
 #
 # LON-CAPA Section (extensions to httpd.conf daemon configuration)
@@ -1149,7 +1149,7 @@
 Require valid-user
 PerlAuthzHandler       Apache::lonacc
 SetHandler perl-script
-PerlHandler Apache::lonpublisher
+PerlHandler Apache::lonpubdisplay
 ErrorDocument     403 /adm/login
 ErrorDocument     404 /adm/notfound.html
 ErrorDocument     406 /adm/unauthorized
Index: doc/loncapafiles/loncapafiles.lpml
diff -u doc/loncapafiles/loncapafiles.lpml:1.1077 doc/loncapafiles/loncapafiles.lpml:1.1078
--- doc/loncapafiles/loncapafiles.lpml:1.1077	Sun Jun 15 23:49:47 2025
+++ doc/loncapafiles/loncapafiles.lpml	Thu Jul 31 15:15:38 2025
@@ -2,7 +2,7 @@
  "http://lpml.sourceforge.net/DTD/lpml.dtd">
 <!-- loncapafiles.lpml -->
 
-<!-- $Id: loncapafiles.lpml,v 1.1077 2025/06/15 23:49:47 raeburn Exp $ -->
+<!-- $Id: loncapafiles.lpml,v 1.1078 2025/07/31 15:15:38 raeburn Exp $ -->
 
 <!--
 
@@ -6028,11 +6028,23 @@
 </dependencies>
 </file>
 <file>
+<source>loncom/publisher/lonpubdisplay.pm</source>
+<target dist='default'>home/httpd/lib/perl/Apache/lonpubdisplay.pm</target>
+<categoryname>handler</categoryname>
+<description>
+Handler for publishing a LON-CAPA educational resource complete with metadata
+(authorship, language, copyright, creation date, etc). Uses subroutines and
+package variables in lonpublisher.pm
+</description>
+<status>works/unverified</status>
+</file>
+<file>
 <source>loncom/publisher/lonpublisher.pm</source>
 <target dist='default'>home/httpd/lib/perl/Apache/lonpublisher.pm</target>
 <categoryname>handler</categoryname>
 <description>
-Publishes an LON-CAPA educational resource complete with metadata
+Subroutines and package variables used by lonpubdisplay.pm to publish 
+a LON-CAPA educational resource complete with metadata
 (authorship, language, copyright, creation date, etc).
 </description>
 <status>works/unverified</status>

Index: loncom/publisher/lonpubdisplay.pm
+++ loncom/publisher/lonpubdisplay.pm
# The LearningOnline Network with CAPA
# Publication Handler
#
# $Id: lonpubdisplay.pm,v 1.1 2025/07/31 15:15:36 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
#
# LON-CAPA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# LON-CAPA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LON-CAPA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# /home/httpd/html/adm/gpl.txt
#
# http://www.lon-capa.org/
#
###

=pod

=head1 NAME

lonpubdisplay - LON-CAPA publishing handler

=head1 SYNOPSIS

B<lonpubdisplay> is used by B<mod_perl> inside B<Apache>.  This is the
invocation by F<loncapa_apache.conf>:

  <Location /adm/publish>
  PerlAccessHandler       Apache::lonacc
  SetHandler perl-script
  PerlHandler Apache::lonpubdisplay
  ErrorDocument     403 /adm/login
  ErrorDocument     404 /adm/notfound.html
  ErrorDocument     406 /adm/unauthorized.html
  ErrorDocument     500 /adm/errorhandler
  </Location>

=head1 OVERVIEW

Authors can only write-access the C</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.

=head1 DESCRIPTION

B<lonpubdisplay>

=head2 SUBROUTINES

=cut

######################################################################
######################################################################

package Apache::lonpubdisplay;

# ------------------------------------------------- modules used by this module
use strict;
use File::Copy;
use HTML::Entities;
use Apache::Constants qw(:common :http :methods);
use Apache::lonnet;
use Apache::loncommon();
use Apache::lonhtmlcommon;
use Apache::lonpublisher;
use Apache::loncfile;
use Apache::lonlocal;
use LONCAPA qw(:DEFAULT :match);

my $registered_cleanup;

#########################################

=pod

=item B<handler>

A basic outline of the handler subroutine follows.

=over 4

=item *

Get query string for limited number of parameters.

=item *

Check filename.

=item *

File is there and owned, init lookup tables.

=item *

Start page output.

=item *

Evaluate individual file, and then output information.

=item *

Publishing from $thisfn to $thistarget with $thisembstyle.

=back

=cut


#########################################
#########################################

sub coursedependencies {
    my $url=&Apache::lonnet::declutter(shift);
    $url=~s/\.meta$//;
    my ($adomain,$aauthor)=($url=~ m{^($match_domain)/($match_username)/});
    my $regexp=quotemeta($url);
    $regexp='___'.$regexp.'___course';
    my %evaldata=&Apache::lonnet::dump('nohist_resevaldata',$adomain,
                                       $aauthor,$regexp);
    my %courses=();
    foreach my $item (keys(%evaldata)) {
        if ($item=~/^([a-zA-Z0-9]+_[a-zA-Z0-9]+)___.+___course$/) {
            $courses{$1}=1;
        }
    }
    return %courses;
}

sub notify_in_cleanup {
    my ($r) = @_;
    unless ($registered_cleanup) {
        my $handlers = $r->get_handlers('PerlCleanupHandler');
        $r->set_handlers('PerlCleanupHandler' => [\&notify,@{$handlers}]);
        $registered_cleanup=1;
    }
}

# =============================================================== Notifications
sub notify {
# --------------------------------------------------- Send update notifications
    if (ref($Apache::lonpublisher::modified_urls) eq 'ARRAY') {
        foreach my $targetsource (@{$Apache::lonpublisher::modified_urls}){
            my ($target,$source)=@{$targetsource};
            my ($logfile,$canlog);
            if (open($logfile,'>>',$source.'.log')) {
                $canlog = 1;
            }
            print $logfile "\nCleanup phase: Notifications\n" if ($canlog);
            my @subscribed=&Apache::lonpublisher::get_subscribed_hosts($target);
            foreach my $subhost (@subscribed) { 
                print $logfile "\nNotifying host ".$subhost.':' if ($canlog);
                my $reply=&Apache::lonnet::critical('update:'.$target,$subhost);
                print $logfile $reply if ($canlog);
            }
# ---------------------------------------- Send update notifications, meta only
            my @subscribedmeta=&Apache::lonpublisher::get_subscribed_hosts("$target.meta");
            foreach my $subhost (@subscribedmeta) {
                print $logfile "\nNotifying host for metadata only ".$subhost.':' if ($canlog);
                my $reply=&Apache::lonnet::critical('update:'.$target.'.meta',
                                                    $subhost);
                print $logfile $reply if ($canlog);
            }
# --------------------------------------------------- Notify subscribed courses
            my %courses=&coursedependencies($target);
            my $now=time;
            foreach my $course (keys(%courses)) {
                print $logfile "\nNotifying course ".$course.':' if ($canlog);
                my ($cdom,$cname)=split(/\_/,$course);
                my $reply=&Apache::lonnet::cput
                    ('versionupdate',{$target => $now},$cdom,$cname);
                print $logfile $reply if ($canlog);
            }
            if ($canlog) {
                print $logfile "\n============ Done ============\n";
                close($logfile);
            }
        }
        $Apache::lonpublisher::modified_urls = [];
    }
    if ($Apache::lonpublisher::lock) { &Apache::lonnet::remove_lock($Apache::lonpublisher::lock); }
    return OK;
}

#########################################
# 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 {
        $r->print("<span class=\"LC_error\">".
                  &mt('Failed to copy source').", $!, ".&mt('FAIL').
		  "</span>");
        $r->print(&Apache::loncommon::end_page());
        return OK;        
    }

# --------------------------------------------------- Send update notifications

    my @subscribed=&Apache::lonpublisher::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;
}

sub reset_globals {
    $Apache::lonpublisher::cuname = '';
    $Apache::lonpublisher::cudom = '';
    %Apache::lonpublisher::metadatafields = ();
    %Apache::lonpublisher::metadatakeys = ();
    @{$Apache::lonpublisher::modified_urls} = ();
}

#########################################
#########################################
sub handler {
    my $r=shift;

    if ($r->header_only) {
        &Apache::loncommon::content_type($r,'text/html');
        $r->send_http_header;
        return OK;
    }

# Initialize globals in Apache::lonpublisher
    &reset_globals();  

# Get query string for limited number of parameters

    &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
                                            ['filename']);

# -------------------------------------- Flag and buffer for registered cleanup
    $registered_cleanup=0;
    @{$Apache::lonpublisher::modified_urls}=();
# -------------------------------------------------------------- Check filename

    my $fn=&unescape($env{'form.filename'});
    my ($cuname,$cudom) = 
        &Apache::lonnet::constructaccess($fn);
# ----------------------------------------------------- Do we have permissions?
     unless (($cuname) && ($cudom)) {
       $r->log_reason($env{'user.name'}.' at '.$env{'user.domain'}.
                      ' trying to publish file '.$env{'form.filename'}.
                      ' - not authorized',
                      $r->filename);
       return HTTP_NOT_ACCEPTABLE;
     }
# ----------------------------------------------------------------- Get docroot
    my $docroot=$r->dir_config('lonDocRoot');

# special publication: default.meta file
    if ($fn=~/\/default.meta$/) {
        return &defaultmetapublish($r,$fn,$cuname,$cudom);
    }

# set values for cuname and cudom globals in Apache::lonpublisher
    $Apache::lonpublisher::cuname = $cuname;
    $Apache::lonpublisher::cudom = $cudom;

    $fn=~s/\.meta$//;

# sanity test on the filename 

    unless ($fn) {
        $r->log_reason($cuname.' at '.$cudom.
                       ' trying to publish empty filename', $r->filename);
        &reset_globals();
        return HTTP_NOT_FOUND;
    }

    unless (-e $docroot.$fn) {
        $r->log_reason($cuname.' at '.$cudom.
                       ' trying to publish non-existing file '.
                       $env{'form.filename'}.' ('.$fn.')',
                       $r->filename);
        &reset_globals();
        return HTTP_NOT_FOUND;
    }

# --------------------------------- File is there and owned, start page output

    &Apache::loncommon::content_type($r,'text/html');
    $r->send_http_header;

    # 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';
        }
    }
}

function showHideCustom(caller,divid) {
    if (document.getElementById(divid)) {
        if (caller.options[caller.selectedIndex].value == 'custom') {
            document.getElementById(divid).style.display="inline-block";
        } else {
            document.getElementById(divid).style.display="none";
        }
    }
}
function setDefaultAccess() {
    var chkids = Array('LC_commondist','LC_commonsource');
    for (var i=0; i<chkids.length; i++) {
        if (document.getElementById(chkids[i])) {
            document.getElementById(chkids[i]).checked = false;
        }
        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>

END
        }
    }
    $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 = &Apache::lonpublisher::getnokey($r->dir_config('lonIncludes'));

    if ($fn=~/\/$/) {
# -------------------------------------------------------- This is a directory
        &Apache::lonpublisher::publishdirectory($r,$docroot.$fn,$thisdisfn,$nokeyref,$crsauthor);
        if ($Apache::lonpublisher::lock) {
            &notify_in_cleanup($r);
        }
        $r->print(
            '<br /><br />'.
            &Apache::lonhtmlcommon::actionbox([
                '<a href="'.$thisdisfn.'">'.&mt('Return to Directory').'</a>']));
    } else {
# ---------------------- Evaluate individual file, and then output information.
        $fn=~/\.(\w+)$/;
        my $thistype=$1;
        my $thisembstyle=&Apache::loncommon::fileembstyle($thistype);
        if ($thistype eq 'page') {  $thisembstyle = 'rat'; }

        $r->print('<h2>'
                 .&mt('Publishing [_1]'
                     ,'<span class="LC_filename">'.$thisdisfn.'</span>')
                 .'</h2>'
        );
         
        $r->print('<h3>'.&mt('Resource Details').'</h3>');
         
        $r->print(&Apache::lonhtmlcommon::start_pick_box());

        $r->print(&Apache::lonhtmlcommon::row_title(&mt('Type'))
                 .&Apache::loncommon::filedescription($thistype)
                 .&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&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 $fn to $thistarget with $thisembstyle.

        unless ($env{'form.phase'} eq 'two') {
# ---------------------------------------------------------- Parse for problems
            my ($warningcount,$errorcount);
            if ($thisembstyle eq 'ssi') {
                ($warningcount,$errorcount)=&Apache::lonpublisher::checkonthis($r,$fn);
            } 
            unless ($errorcount) {
                my ($outstring,$error)=
                    &Apache::lonpublisher::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) =
	        &Apache::lonpublisher::phasetwo($r,$docroot.$fn,$docroot.$thistarget,
                                                $thisembstyle,$thisdistarget);
            $r->print($output);
# ------------------------------------------------------------- Trigger updates
            if (@{$Apache::lonpublisher::modified_urls}) {
                &notify_in_cleanup($r);
            }
        }
    }
    $r->print(&Apache::loncommon::end_page());
    &reset_globals();
    return OK;
}

BEGIN {

# ----------------------------------- Read addid.tab
    unless ($Apache::lonpublisher::readit) {
        %Apache::lonpublisher::addid=();

        {
            my $tabdir = $Apache::lonnet::perlvar{'lonTabDir'};
            if (open(my $fh,'<',$tabdir.'/addid.tab')) {
                while (<$fh>=~/(\w+)\s+(\w+)/) {
                    $Apache::lonpublisher::addid{$1}=$2;
                }
                close($fh);
            }
        }
    }
    $Apache::lonpublisher::readit=1;
}

1;


More information about the LON-CAPA-cvs mailing list