--- loncom/publisher/lonpublisher.pm 2002/10/03 15:02:22 1.98 +++ loncom/publisher/lonpublisher.pm 2003/09/24 19:38:18 1.135 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Publication Handler # -# $Id: lonpublisher.pm,v 1.98 2002/10/03 15:02:22 www Exp $ +# $Id: lonpublisher.pm,v 1.135 2003/09/24 19:38:18 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -33,18 +33,14 @@ # 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 # ### @@ -86,6 +82,26 @@ invocation by F: ErrorDocument 500 /adm/errorhandler +=head1 OVERVIEW + +Authors can only write-access the C 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, while the most recent +version does not carry a version number (C). Servers +subscribing to a changed resource are notified that a new version is +available. + =head1 DESCRIPTION B takes the proper steps to add resources to the LON-CAPA @@ -121,27 +137,22 @@ use File::Copy; use Apache::Constants qw(:common :http :methods); use HTML::LCParser; use Apache::lonxml; -use Apache::lonhomework; use Apache::loncacc; use DBI; use Apache::lonnet(); use Apache::loncommon(); use Apache::lonmysql; +use Apache::lonlocal; +use vars qw(%metadatafields %metadatakeys); my %addid; my %nokey; -my %metadatafields; -my %metadatakeys; - my $docroot; my $cuname; my $cudom; -######################################### -######################################### - =pod =item B @@ -200,7 +211,7 @@ sub metaeval { } if ($metadatafields{$unikey}) { my $newentry=$parser->get_text('/'.$entry); - unless (($metadatafields{$unikey}=~/$newentry/) || + unless (($metadatafields{$unikey}=~/\Q$newentry\E/) || ($newentry eq '')) { $metadatafields{$unikey}.=', '.$newentry; } @@ -252,7 +263,7 @@ sub metaread { my ($logfile,$fn)=@_; unless (-e $fn) { print($logfile 'No file '.$fn."\n"); - return '
No file: '.$fn.''; + return '
No file: '.$fn.''; } print($logfile 'Processing '.$fn."\n"); my $metastring; @@ -261,54 +272,33 @@ sub metaread { $metastring=join('',<$metafh>); } &metaeval($metastring); - return '
Processed file: '.$fn.''; + return '
Processed file: '.$fn.''; } ######################################### ######################################### -=pod - -=item B - -Convert 'time' format into a datetime sql format - -Parameters: - -=over 4 - -=item I<$timef> - -Seconds since 00:00:00 UTC, January 1, 1970. - -=back - -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"; +sub coursedependencies { + my $url=&Apache::lonnet::declutter(shift); + $url=~s/\.meta$//; + my ($adomain,$aauthor)=($url=~/^(\w+)\/(\w+)\//); + my $regexp=$url; + $regexp=~s/(\W)/\\$1/g; + $regexp='___'.$regexp.'___course'; + my %evaldata=&Apache::lonnet::dump('nohist_resevaldata',$adomain, + $aauthor,$regexp); + my %courses=(); + foreach (keys %evaldata) { + if ($_=~/^([a-zA-Z0-9]+_[a-zA-Z0-9]+)___.+___course$/) { + $courses{$1}=1; + } + } + return %courses; } - - ######################################### ######################################### + =pod =item Form-field-generating subroutines. @@ -335,7 +325,10 @@ string which presents the form field (fo ######################################### sub textfield { my ($title,$name,$value)=@_; - return "\n

$title:
". + $title=&mt($title); + my $uctitle=uc($title); + return "\n

$uctitle:". + "


". ''; } @@ -346,9 +339,11 @@ sub hiddenfield { sub selectbox { my ($title,$name,$value,$functionref,@idlist)=@_; + $title=&mt($title); my $uctitle=uc($title); + $value=(split(/\s*,\s*/,$value))[-1]; my $selout="\n

$uctitle:". - "
".''; foreach (@idlist) { $selout.='

Dependencies

'; @@ -849,7 +871,7 @@ sub publish { unless ($style eq 'rat') { $allowstr.="\n".''; } - $scrout.='
'; + $scrout.='
'; unless ($thisdep=~/\*/) { $scrout.=''; } @@ -883,9 +905,8 @@ sub publish { my $org; unless ($org=Apache::File->new('>'.$source)) { print $logfile "No write permit to $source\n"; - return - 'No write permission to '.$source. - ', FAIL'; + return ('No write permission to '.$source. + ', FAIL',1); } print($org $outstring); } @@ -916,11 +937,14 @@ sub publish { $metadatafields{'author'}=~s/\s+/ /g; $metadatafields{'author'}=~s/\s+$//; $metadatafields{'owner'}=$cuname.'@'.$cudom; + $metadatafields{'modifyinguser'}=$ENV{'user.name'}.'@'. + $ENV{'user.domain'}; + $metadatafields{'authorspace'}=$cuname.'@'.$cudom; # ------------------------------------------------ Check out directory hierachy my $thisdisfn=$source; - $thisdisfn=~s/^\/home\/$cuname\///; + $thisdisfn=~s/^\/home\/\Q$cuname\E\///; my @urlparts=split(/\//,$thisdisfn); $#urlparts--; @@ -955,214 +979,230 @@ sub publish { } # -------------------------------------------------- Parse content for metadata - if ($style eq 'ssi') { - my $oldenv=$ENV{'request.uri'}; - - $ENV{'request.uri'}=$target; - $allmeta=Apache::lonxml::xmlparse(undef,'meta',$content); - $ENV{'request.uri'}=$oldenv; + 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); } # ---------------- Find and document discrepancies in the parameters and stores - my $chparms=''; - foreach (sort keys %metadatafields) { - if (($_=~/^parameter/) || ($_=~/^stores/)) { - unless ($_=~/\.\w+$/) { - unless ($oldparmstores{$_}) { - print $logfile 'New: '.$_."\n"; - $chparms.=$_.' '; - } - } - } - } - if ($chparms) { - $scrout.='

New parameters or stored values: '. - $chparms; - } + my $chparms=''; + foreach (sort keys %metadatafields) { + if (($_=~/^parameter/) || ($_=~/^stores/)) { + unless ($_=~/\.\w+$/) { + unless ($oldparmstores{$_}) { + print $logfile 'New: '.$_."\n"; + $chparms.=$_.' '; + } + } + } + } + if ($chparms) { + $scrout.='

New parameters or stored values: '.$chparms.'

'; + } - $chparms=''; - foreach (sort keys %oldparmstores) { - if (($_=~/^parameter/) || ($_=~/^stores/)) { - unless (($metadatafields{$_.'.name'}) || - ($metadatafields{$_.'.package'}) || ($_=~/\.\w+$/)) { - print $logfile 'Obsolete: '.$_."\n"; - $chparms.=$_.' '; - } - } - } - if ($chparms) { - $scrout.='

Obsolete parameters or stored values: '. - $chparms; - } + $chparms=''; + foreach (sort keys %oldparmstores) { + if (($_=~/^parameter/) || ($_=~/^stores/)) { + unless (($metadatafields{$_.'.name'}) || + ($metadatafields{$_.'.package'}) || ($_=~/\.\w+$/)) { + print $logfile 'Obsolete: '.$_."\n"; + $chparms.=$_.' '; + } + } + } + if ($chparms) { + $scrout.='

Obsolete parameters or stored values: '. + $chparms.'

'; + } # ------------------------------------------------------- Now have all metadata - my %keywords=(); + my %keywords=(); - if (length($content)<500000) { - my $textonly=$content; - $textonly=~s/\//g; - $textonly=~s/\[^\<]+\<\/m\>//g; - $textonly=~s/\<[^\>]*\>//g; - $textonly=~tr/A-Z/a-z/; - $textonly=~s/[\$\&][a-z]\w*//g; - $textonly=~s/[^a-z\s]//g; - - foreach ($textonly=~m/(\w+)/g) { - unless ($nokey{$_}) { - $keywords{$_}=1; - } - } - } + if (length($content)<500000) { + my $textonly=$content; + $textonly=~s/\//g; + $textonly=~s/\[^\<]+\<\/m\>//g; + $textonly=~s/\<[^\>]*\>//g; + $textonly=~tr/A-Z/a-z/; + $textonly=~s/[\$\&][a-z]\w*//g; + $textonly=~s/[^a-z\s]//g; + + foreach ($textonly=~m/(\w+)/g) { + unless ($nokey{$_}) { + $keywords{$_}=1; + } + } + } - foreach (split(/\W+/,$metadatafields{'keywords'})) { - $keywords{$_}=1; - } + foreach (split(/\W+/,$metadatafields{'keywords'})) { + $keywords{$_}=1; + } # --------------------------------------------------- Now we also have keywords # ============================================================================= # INTERACTIVE MODE # - unless ($batch) { + unless ($batch) { $scrout.= - '
'. - '

'. - &hiddenfield('phase','two'). - &hiddenfield('filename',$ENV{'form.filename'}). - &hiddenfield('allmeta',&Apache::lonnet::escape($allmeta)). - &hiddenfield('dependencies',join(',',keys %allow)). - &textfield('Title','title',$metadatafields{'title'}). - &textfield('Author(s)','author',$metadatafields{'author'}). - &textfield('Subject','subject',$metadatafields{'subject'}); + ''. + '

'. + &hiddenfield('phase','two'). + &hiddenfield('filename',$ENV{'form.filename'}). + &hiddenfield('allmeta',&Apache::lonnet::escape($allmeta)). + &hiddenfield('dependencies',join(',',keys %allow)). + &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 $keywordout=<<"END"; -

Keywords: $keywords_help - - +

KEYWORDS: + $keywords_help + + +


END - $keywordout.=''; - my $colcount=0; + $keywordout.='
'; + my $colcount=0; + + foreach (sort keys %keywords) { + $keywordout.='\n"; + $colcount=0; + } + $colcount++; + } - foreach (sort keys %keywords) { - $keywordout.='\n"; - $colcount=0; - } - $colcount++; - } - $keywordout.='
'; + if ($colcount>10) { + $keywordout.="
'; - if ($colcount>10) { - $keywordout.="
'; - $scrout.=$keywordout; + $scrout.=$keywordout; - $scrout.=&textfield('Additional Keywords','addkey',''); + $scrout.=&textfield('Additional Keywords','addkey',''); - $scrout.=&textfield('Notes','notes',$metadatafields{'notes'}); + $scrout.=&textfield('Notes','notes',$metadatafields{'notes'}); - $scrout.= - '

Abstract:
'; + $scrout.= + "\n

ABSTRACT:". + "


". + '

'; $source=~/\.(\w+)$/; $scrout.=&hiddenfield('mime',$1); - $scrout.=&selectbox('Language','language', - $metadatafields{'language'}, + my $defaultlanguage=$metadatafields{'language'}; + $defaultlanguage =~ s/\s*notset\s*//g; + $defaultlanguage =~ s/^,\s*//g; + $defaultlanguage =~ s/,\s*$//g; + + $scrout.=&selectbox('Language','language', + $defaultlanguage, \&Apache::loncommon::languagedescription, (&Apache::loncommon::languageids), - ); + ); - unless ($metadatafields{'creationdate'}) { + unless ($metadatafields{'creationdate'}) { $metadatafields{'creationdate'}=time; - } - $scrout.=&hiddenfield('creationdate',$metadatafields{'creationdate'}); + } + $scrout.=&hiddenfield('creationdate', + &Apache::loncommon::unsqltime($metadatafields{'creationdate'})); + + $scrout.=&hiddenfield('lastrevisiondate',time); - $scrout.=&hiddenfield('lastrevisiondate',time); - $scrout.=&textfield('Publisher/Owner','owner', - $metadatafields{'owner'}); + $metadatafields{'owner'}); # -------------------------------------------------- Correct copyright for rat. - if ($style eq 'rat') { - if ($metadatafields{'copyright'} eq 'public') { - delete $metadatafields{'copyright'}; + my $defaultoption=$metadatafields{'copyright'}; + unless ($defaultoption) { $defaultoption='default'; } + unless ($style eq 'prv') { + if ($style eq 'rat') { + if ($metadatafields{'copyright'} eq 'public') { + delete $metadatafields{'copyright'}; + $defaultoption='default'; + } + $scrout.=&selectbox('Copyright/Distribution','copyright', + $defaultoption, + \&Apache::loncommon::copyrightdescription, + (grep !/^public$/,(&Apache::loncommon::copyrightids))); + } else { + $scrout.=&selectbox('Copyright/Distribution','copyright', + $defaultoption, + \&Apache::loncommon::copyrightdescription, + (&Apache::loncommon::copyrightids)); + } + + my $copyright_help = + Apache::loncommon::help_open_topic('Publishing_Copyright'); + $scrout =~ s/DISTRIBUTION:/'DISTRIBUTION: ' . $copyright_help/ge; + $scrout.=&textfield('Custom Distribution File','customdistributionfile', + $metadatafields{'customdistributionfile'}). + $copyright_help; + } else { + $scrout.=&hiddenfield('copyright','private'); } - $scrout.=&selectbox('Copyright/Distribution','copyright', - $metadatafields{'copyright'}, - \&Apache::loncommon::copyrightdescription, - (grep !/^public$/,(&Apache::loncommon::copyrightids))); - } - else { - $scrout.=&selectbox('Copyright/Distribution','copyright', - $metadatafields{'copyright'}, - \&Apache::loncommon::copyrightdescription, - (&Apache::loncommon::copyrightids)); - } - - my $copyright_help = - Apache::loncommon::help_open_topic('Publishing_Copyright'); - $scrout =~ s/DISTRIBUTION:/'DISTRIBUTION: ' . $copyright_help/ge; - return $scrout. - '

'; + return ($scrout.'

',0); # ============================================================================= # BATCH MODE # - } else { + } else { # Transfer metadata directly to environment for stage 2 - foreach (keys %metadatafields) { - $ENV{'form.'.$_}=$metadatafields{$_}; + foreach (keys %metadatafields) { + $ENV{'form.'.$_}=$metadatafields{$_}; + } + $ENV{'form.addkey'}=''; + $ENV{'form.keywords'}=''; + foreach (keys %keywords) { + if ($metadatafields{'keywords'}) { + if ($metadatafields{'keywords'}=~/\Q$_\E/) { + $ENV{'form.keywords'}.=$_.','; + } + } elsif (&Apache::loncommon::keyword($_)) { + $ENV{'form.keywords'}.=$_.','; + } + } + $ENV{'form.keywords'}=~s/\,$//; + unless ($ENV{'form.creationdate'}) { $ENV{'form.creationdate'}=time; } + $ENV{'form.lastrevisiondate'}=time; + if ((($style eq 'rat') && ($ENV{'form.copyright'} eq 'public')) || + (!$ENV{'form.copyright'})) { + $ENV{'form.copyright'}='default'; + } + $ENV{'form.allmeta'}=&Apache::lonnet::escape($allmeta); + return ($scrout,0); } - $ENV{'form.addkey'}=''; - $ENV{'form.keywords'}=''; - foreach (keys %keywords) { - if ($metadatafields{'keywords'}) { - if ($metadatafields{'keywords'}=~/$_/) { - $ENV{'form.keywords'}.=$_.','; - } - } elsif (&Apache::loncommon::keyword($_)) { - $ENV{'form.keywords'}.=$_.','; - } - } - $ENV{'form.keywords'}=~s/\,$//; - unless ($ENV{'form.creationdate'}) { $ENV{'form.creationdate'}=time; } - $ENV{'form.lastrevisiondate'}=time; - if ((($style eq 'rat') && ($ENV{'form.copyright'} eq 'public')) || - (!$ENV{'form.copyright'})) { - $ENV{'form.copyright'}='default'; - } - $ENV{'form.allmeta'}=&Apache::lonnet::escape($allmeta); - return $scrout; - } } ######################################### @@ -1196,255 +1236,280 @@ Returns: =item Scalar string String contains status (errors and warnings) and information associated with -the server's attempts at publication. +the server's attempts at publication. =cut +#'stupid emacs ######################################### ######################################### sub phasetwo { - my ($source,$target,$style,$distarget,$batch)=@_; + my ($r,$source,$target,$style,$distarget,$batch)=@_; + $source=~s/\/+/\//g; + $target=~s/\/+/\//g; + + if ($target=~/\_\_\_/) { + $r->print( + 'Unsupported character combination "___" in filename, FAIL'); + return 0; + } + $distarget=~s/\/+/\//g; my $logfile; - my $scrout=''; unless ($logfile=Apache::File->new('>>'.$source.'.log')) { - return - 'No write permission to user directory, FAIL'; + $r->print( + 'No write permission to user directory, FAIL'); + return 0; } print $logfile -"\n================= Publish ".localtime()." Phase Two ================\n"; - - %metadatafields=(); - %metadatakeys=(); - - &metaeval(&Apache::lonnet::unescape($ENV{'form.allmeta'})); - - $metadatafields{'title'}=$ENV{'form.title'}; - $metadatafields{'author'}=$ENV{'form.author'}; - $metadatafields{'subject'}=$ENV{'form.subject'}; - $metadatafields{'notes'}=$ENV{'form.notes'}; - $metadatafields{'abstract'}=$ENV{'form.abstract'}; - $metadatafields{'mime'}=$ENV{'form.mime'}; - $metadatafields{'language'}=$ENV{'form.language'}; - $metadatafields{'creationdate'}= - &sqltime($ENV{'form.creationdate'}); - $metadatafields{'lastrevisiondate'}= - &sqltime($ENV{'form.lastrevisiondate'}); - $metadatafields{'owner'}=$ENV{'form.owner'}; - $metadatafields{'copyright'}=$ENV{'form.copyright'}; - $metadatafields{'dependencies'}=$ENV{'form.dependencies'}; - - my $allkeywords=$ENV{'form.addkey'}; - if (exists($ENV{'form.keywords'})) { - if (ref($ENV{'form.keywords'})) { - $allkeywords .= ','.join(',',@{$ENV{'form.keywords'}}); - } else { - $allkeywords .= ','.$ENV{'form.keywords'}; - } - } - $allkeywords=~s/\W+/\,/; - $allkeywords=~s/^\,//; - $metadatafields{'keywords'}=$allkeywords; - - { - print $logfile "\nWrite metadata file for ".$source; - my $mfh; - unless ($mfh=Apache::File->new('>'.$source.'.meta')) { - return - 'Could not write metadata, FAIL'; - } - foreach (sort keys %metadatafields) { - unless ($_=~/\./) { - my $unikey=$_; - $unikey=~/^([A-Za-z]+)/; - my $tag=$1; - $tag=~tr/A-Z/a-z/; - print $mfh "\n\<$tag"; - foreach (split(/\,/,$metadatakeys{$unikey})) { - my $value=$metadatafields{$unikey.'.'.$_}; - $value=~s/\"/\'\'/g; - print $mfh ' '.$_.'="'.$value.'"'; - } - print $mfh '>'. - &HTML::Entities::encode($metadatafields{$unikey}) - .''; - } - } - $scrout.='

Wrote Metadata'; - print $logfile "\nWrote metadata"; - } - + "\n================= Publish ".localtime()." Phase Two ================\n".$ENV{'user.name'}.'@'.$ENV{'user.domain'}."\n"; + + %metadatafields=(); + %metadatakeys=(); + + &metaeval(&Apache::lonnet::unescape($ENV{'form.allmeta'})); + + $metadatafields{'title'}=$ENV{'form.title'}; + $metadatafields{'author'}=$ENV{'form.author'}; + $metadatafields{'subject'}=$ENV{'form.subject'}; + $metadatafields{'notes'}=$ENV{'form.notes'}; + $metadatafields{'abstract'}=$ENV{'form.abstract'}; + $metadatafields{'mime'}=$ENV{'form.mime'}; + $metadatafields{'language'}=$ENV{'form.language'}; + $metadatafields{'creationdate'}=$ENV{'form.creationdate'}; + $metadatafields{'lastrevisiondate'}=$ENV{'form.lastrevisiondate'}; + $metadatafields{'owner'}=$ENV{'form.owner'}; + $metadatafields{'copyright'}=$ENV{'form.copyright'}; + $metadatafields{'customdistributionfile'}= + $ENV{'form.customdistributionfile'}; + $metadatafields{'dependencies'}=$ENV{'form.dependencies'}; + + my $allkeywords=$ENV{'form.addkey'}; + if (exists($ENV{'form.keywords'})) { + if (ref($ENV{'form.keywords'})) { + $allkeywords .= ','.join(',',@{$ENV{'form.keywords'}}); + } else { + $allkeywords .= ','.$ENV{'form.keywords'}; + } + } + $allkeywords=~s/\W+/\,/; + $allkeywords=~s/^\,//; + $metadatafields{'keywords'}=$allkeywords; + + { + print $logfile "\nWrite metadata file for ".$source; + my $mfh; + unless ($mfh=Apache::File->new('>'.$source.'.meta')) { + return + 'Could not write metadata, FAIL'; + } + foreach (sort keys %metadatafields) { + unless ($_=~/\./) { + my $unikey=$_; + $unikey=~/^([A-Za-z]+)/; + my $tag=$1; + $tag=~tr/A-Z/a-z/; + print $mfh "\n\<$tag"; + foreach (split(/\,/,$metadatakeys{$unikey})) { + my $value=$metadatafields{$unikey.'.'.$_}; + $value=~s/\"/\'\'/g; + print $mfh ' '.$_.'="'.$value.'"'; + } + print $mfh '>'. + &HTML::Entities::encode($metadatafields{$unikey}) + .''; + } + } + $r->print('

Wrote Metadata

'); + print $logfile "\nWrote metadata"; + } + # -------------------------------- Synchronize entry with SQL metadata database - my $warning; + $metadatafields{'url'} = $distarget; $metadatafields{'version'} = 'current'; unless ($metadatafields{'copyright'} eq 'priv') { my ($error,$success) = &store_metadata(\%metadatafields); if ($success) { - $scrout.='

Synchronized SQL metadata database'; + $r->print('

Synchronized SQL metadata database

'); print $logfile "\nSynchronized SQL metadata database"; } else { - $warning.=$error; + $r->print($error); print $logfile "\n".$error; } } else { - $scrout.='

Private Publication - did not synchronize database'; + $r->print('

Private Publication - did not synchronize database

'); print $logfile "\nPrivate: Did not synchronize data into ". "SQL metadata database"; } # ----------------------------------------------------------- Copy old versions -if (-e $target) { - my $filename; - my $maxversion=0; - $target=~/(.*)\/([^\/]+)\.(\w+)$/; - my $srcf=$2; - my $srct=$3; - my $srcd=$1; - unless ($srcd=~/^\/home\/httpd\/html\/res/) { - print $logfile "\nPANIC: Target dir is ".$srcd; - return "Invalid target directory, FAIL"; - } - opendir(DIR,$srcd); - while ($filename=readdir(DIR)) { - if (-l $srcd.'/'.$filename) { - unlink($srcd.'/'.$filename); - } else { - if ($filename=~/$srcf\.(\d+)\.$srct$/) { - $maxversion=($1>$maxversion)?$1:$maxversion; - } - } - } - closedir(DIR); - $maxversion++; - $scrout.='

Creating old version '.$maxversion; - print $logfile "\nCreating old version ".$maxversion; - - my $copyfile=$srcd.'/'.$srcf.'.'.$maxversion.'.'.$srct; - + if (-e $target) { + my $filename; + my $maxversion=0; + $target=~/(.*)\/([^\/]+)\.(\w+)$/; + my $srcf=$2; + my $srct=$3; + my $srcd=$1; + unless ($srcd=~/^\/home\/httpd\/html\/res/) { + print $logfile "\nPANIC: Target dir is ".$srcd; + return "Invalid target directory, FAIL"; + } + opendir(DIR,$srcd); + while ($filename=readdir(DIR)) { + if (-l $srcd.'/'.$filename) { + unlink($srcd.'/'.$filename); + unlink($srcd.'/'.$filename.'.meta'); + } else { + if ($filename=~/\Q$srcf\E\.(\d+)\.\Q$srct\E$/) { + $maxversion=($1>$maxversion)?$1:$maxversion; + } + } + } + closedir(DIR); + $maxversion++; + $r->print('

Creating old version '.$maxversion.'

'); + print $logfile "\nCreating old version ".$maxversion."\n"; + + my $copyfile=$srcd.'/'.$srcf.'.'.$maxversion.'.'.$srct; + if (copy($target,$copyfile)) { print $logfile "Copied old target to ".$copyfile."\n"; - $scrout.='

Copied old target file'; + $r->print('

Copied old target file

'); } else { print $logfile "Unable to write ".$copyfile.':'.$!."\n"; - return "Failed to copy old target, $!, FAIL"; + return "Failed to copy old target, $!, FAIL"; } - + # --------------------------------------------------------------- Copy Metadata $copyfile=$copyfile.'.meta'; - + if (copy($target.'.meta',$copyfile)) { print $logfile "Copied old target metadata to ".$copyfile."\n"; - $scrout.='

Copied old metadata'; + $r->print('

Copied old metadata

') } else { print $logfile "Unable to write metadata ".$copyfile.':'.$!."\n"; if (-e $target.'.meta') { - return - "Failed to write old metadata copy, $!, FAIL"; + return + "Failed to write old metadata copy, $!, FAIL"; } } - - -} else { - $scrout.='

Initial version'; - print $logfile "\nInitial version"; -} + + + } else { + $r->print('

Initial version

'); + print $logfile "\nInitial version"; + } # ---------------------------------------------------------------- Write Source - my $copyfile=$target; - - my @parts=split(/\//,$copyfile); - my $path="/$parts[1]/$parts[2]/$parts[3]/$parts[4]"; - - my $count; - for ($count=5;$count<$#parts;$count++) { - $path.="/$parts[$count]"; - if ((-e $path)!=1) { - print $logfile "\nCreating directory ".$path; - $scrout.='

Created directory '.$parts[$count]; - mkdir($path,0777); - } - } - - if (copy($source,$copyfile)) { - print $logfile "\nCopied original source to ".$copyfile."\n"; - $scrout.='

Copied source file'; - } else { - print $logfile "\nUnable to write ".$copyfile.':'.$!."\n"; - return "Failed to copy source, $!, FAIL"; + my $copyfile=$target; + + my @parts=split(/\//,$copyfile); + my $path="/$parts[1]/$parts[2]/$parts[3]/$parts[4]"; + + my $count; + for ($count=5;$count<$#parts;$count++) { + $path.="/$parts[$count]"; + if ((-e $path)!=1) { + print $logfile "\nCreating directory ".$path; + $r->print('

Created directory '.$parts[$count].'

'); + mkdir($path,0777); } - + } + + if (copy($source,$copyfile)) { + print $logfile "\nCopied original source to ".$copyfile."\n"; + $r->print('

Copied source file

'); + } else { + print $logfile "\nUnable to write ".$copyfile.':'.$!."\n"; + return "Failed to copy source, $!, FAIL"; + } + # --------------------------------------------------------------- Copy Metadata - $copyfile=$copyfile.'.meta'; - - if (copy($source.'.meta',$copyfile)) { - print $logfile "\nCopied original metadata to ".$copyfile."\n"; - $scrout.='

Copied metadata'; - } else { - print $logfile "\nUnable to write metadata ".$copyfile.':'.$!."\n"; - return - "Failed to write metadata copy, $!, FAIL"; - } - + $copyfile=$copyfile.'.meta'; + + if (copy($source.'.meta',$copyfile)) { + print $logfile "\nCopied original metadata to ".$copyfile."\n"; + $r->print('

Copied metadata

'); + } else { + print $logfile "\nUnable to write metadata ".$copyfile.':'.$!."\n"; + return + "Failed to write metadata copy, $!, FAIL"; + } + $r->rflush; # --------------------------------------------------- Send update notifications my @subscribed=&get_subscribed_hosts($target); foreach my $subhost (@subscribed) { - $scrout.='

Notifying host '.$subhost.':'; + $r->print('

Notifying host '.$subhost.':');$r->rflush; print $logfile "\nNotifying host ".$subhost.':'; my $reply=&Apache::lonnet::critical('update:'.$target,$subhost); - $scrout.=$reply; + $r->print($reply.'


');$r->rflush; print $logfile $reply; } - + # ---------------------------------------- Send update notifications, meta only my @subscribedmeta=&get_subscribed_hosts("$target.meta"); foreach my $subhost (@subscribedmeta) { - $scrout.='

Notifying host for metadata only '.$subhost.':'; + $r->print('

Notifying host for metadata only '.$subhost.':');$r->rflush; print $logfile "\nNotifying host for metadata only ".$subhost.':'; my $reply=&Apache::lonnet::critical('update:'.$target.'.meta', $subhost); - $scrout.=$reply; + $r->print($reply.'


');$r->rflush; + print $logfile $reply; + } + +# --------------------------------------------------- Notify subscribed courses + my %courses=&coursedependencies($target); + my $now=time; + foreach (keys %courses) { + $r->print('

Notifying course '.$_.':');$r->rflush; + print $logfile "\nNotifying host ".$_.':'; + my ($cdom,$cname)=split(/\_/,$_); + my $reply=&Apache::lonnet::cput + ('versionupdate',{$target => $now},$cdom,$cname); + $r->print($reply.'


');$r->rflush; print $logfile $reply; } - # ------------------------------------------------ Provide link to new resource - unless ($batch) { - my $thisdistarget=$target; - $thisdistarget=~s/^$docroot//; - - my $thissrc=$source; - $thissrc=~s/^\/home\/(\w+)\/public_html/\/priv\/$1/; - - my $thissrcdir=$thissrc; - $thissrcdir=~s/\/[^\/]+$/\//; - - - return $warning.$scrout. - '
'. - 'View Published Version'. - '

Back to Source'. - '

Back to Source Directory'; - } else { - return $warning.$scrout; - } + unless ($batch) { + my $thisdistarget=$target; + $thisdistarget=~s/^\Q$docroot\E//; + + my $thissrc=$source; + $thissrc=~s/^\/home\/(\w+)\/public_html/\/priv\/$1/; + + my $thissrcdir=$thissrc; + $thissrcdir=~s/\/[^\/]+$/\//; + + + $r->print( + '


'. + 'View Published Version'. + '

Back to Source

'. + '

Back to Source Directory

'); + } } ######################################### sub batchpublish { my ($r,$srcfile,$targetfile)=@_; + #publication pollutes %ENV with form.* values + my %oldENV=%ENV; + $srcfile=~s/\/+/\//g; + $targetfile=~s/\/+/\//g; my $thisdisfn=$srcfile; $thisdisfn=~s/\/home\/korte\/public_html\///; $srcfile=~s/\/+/\//g; my $docroot=$r->dir_config('lonDocRoot'); my $thisdistarget=$targetfile; - $thisdistarget=~s/^$docroot//; + $thisdistarget=~s/^\Q$docroot\E//; undef %metadatafields; @@ -1461,12 +1526,17 @@ sub batchpublish { # phase one takes # my ($source,$target,$style,$batch)=@_; - $r->print('

'.&publish($srcfile,$targetfile,$thisembstyle,1).'

'); + my ($outstring,$error)=&publish($srcfile,$targetfile,$thisembstyle,1); + $r->print('

'.$outstring.'

'); # phase two takes # my ($source,$target,$style,$distarget,batch)=@_; # $ENV{'form.allmeta'},$ENV{'form.title'},$ENV{'form.author'},... - $r->print( -'

'.&phasetwo($srcfile,$targetfile,$thisembstyle,$thisdistarget,1).'

'); + if (!$error) { + $r->print('

'); + &phasetwo($r,$srcfile,$targetfile,$thisembstyle,$thisdistarget,1); + $r->print('

'); + } + %ENV=%oldENV; return ''; } @@ -1474,10 +1544,12 @@ sub batchpublish { sub publishdirectory { my ($r,$fn,$thisdisfn)=@_; + $fn=~s/\/+/\//g; + $thisdisfn=~s/\/+/\//g; my $resdir= - $Apache::lonnet::perlvar{'lonDocRoot'}.'/res/'.$cudom.'/'.$cuname. + $Apache::lonnet::perlvar{'lonDocRoot'}.'/res/'.$cudom.'/'.$cuname.'/'. $thisdisfn; - $r->print('

Directory '.$thisdisfn.'/

'. + $r->print('

Directory '.$thisdisfn.'

'. 'Target: '.$resdir.'
'); my $dirptr=16384; # Mask indicating a directory in stat.cmode. @@ -1505,7 +1577,7 @@ sub publishdirectory { $ruid,$rgid,$rrdev,$rsize, $ratime,$rmtime,$rctime, $rblksize,$rblocks)=stat($resdir.'/'.$filename); - if ($rmtime<$cmtime) { + if (($rmtime<$cmtime) || ($ENV{'form.forcerepub'})) { # previously published, modified now $publishthis=1; } @@ -1579,7 +1651,7 @@ sub handler { # -------------------------------------------------------------- Check filename - my $fn=$ENV{'form.filename'}; + my $fn=&Apache::lonnet::unescape($ENV{'form.filename'}); unless ($fn) { @@ -1665,6 +1737,8 @@ unless ($ENV{'form.phase'} eq 'two') { $r->print('LON-CAPA Publishing'); $r->print(&Apache::loncommon::bodytag('Resource Publication')); + + my $thisfn=$fn; my $thistarget=$thisfn; @@ -1673,25 +1747,33 @@ unless ($ENV{'form.phase'} eq 'two') { $thistarget=~s/\/public\_html//; my $thisdistarget=$thistarget; - $thisdistarget=~s/^$docroot//; + $thisdistarget=~s/^\Q$docroot\E//; my $thisdisfn=$thisfn; - $thisdisfn=~s/^\/home\/$cuname\/public_html\///; + $thisdisfn=~s/^\/home\/\Q$cuname\E\/public_html\///; if ($fn=~/\/$/) { # -------------------------------------------------------- This is a directory &publishdirectory($r,$fn,$thisdisfn); + $r->print('
Done
Return to Directory'); + } else { # ---------------------- Evaluate individual file, and then output information. $thisfn=~/\.(\w+)$/; my $thistype=$1; my $thisembstyle=&Apache::loncommon::fileembstyle($thistype); - $r->print('

Publishing '. - &Apache::loncommon::filedescription($thistype).' '. - ''.$thisdisfn. - '

Target: '.$thisdistarget.'

'); + &Apache::loncommon::filedescription($thistype).' '); + + $r->print(< +$thisdisfn +ENDCAPTION + $r->print( + 'Target: '.$thisdistarget.'
'); if (($cuname ne $ENV{'user.name'}) || ($cudom ne $ENV{'user.domain'})) { $r->print('

Co-Author: '.$cuname.' at '.$cudom. @@ -1699,22 +1781,21 @@ unless ($ENV{'form.phase'} eq 'two') { } if (&Apache::loncommon::fileembstyle($thistype) eq 'ssi') { - $r->print('
Diffs with Current Version

'); + $r->print(< +Diffs with Current Version
+ENDDIFF } # ------------------ Publishing from $thisfn to $thistarget with $thisembstyle. unless ($ENV{'form.phase'} eq 'two') { - $r->print( - '


'.&publish($thisfn,$thistarget,$thisembstyle)); + my ($outstring,$error)=&publish($thisfn,$thistarget,$thisembstyle); + $r->print('
'.$outstring); } else { - $r->print( - '
'.&phasetwo($thisfn,$thistarget, - $thisembstyle,$thisdistarget)); - } - + $r->print('
'); + &phasetwo($r,$thisfn,$thistarget,$thisembstyle,$thisdistarget); + } } $r->print(''); @@ -1728,5 +1809,7 @@ __END__ =back +=back + =cut 500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.