--- loncom/publisher/lonpublisher.pm 2001/04/03 11:26:02 1.23 +++ loncom/publisher/lonpublisher.pm 2001/08/17 16:49:04 1.40 @@ -8,6 +8,10 @@ # 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 Gerd Kortemeyer package Apache::lonpublisher; @@ -18,6 +22,8 @@ use Apache::Constants qw(:common :http : use HTML::TokeParser; use Apache::lonxml; use Apache::lonhomework; +use Apache::loncacc; +use DBI; my %addid; my %nokey; @@ -29,6 +35,9 @@ my %metadatakeys; my $docroot; +my $cuname; +my $cudom; + # ----------------------------------------------- Evaluate string with metadata sub metaeval { @@ -40,9 +49,15 @@ sub metaeval { if ($token->[0] eq 'S') { my $entry=$token->[1]; my $unikey=$entry; + if (defined($token->[2]->{'package'})) { + $unikey.='_package_'.$token->[2]->{'package'}; + } if (defined($token->[2]->{'part'})) { $unikey.='_'.$token->[2]->{'part'}; } + if (defined($token->[2]->{'id'})) { + $unikey.='_'.$token->[2]->{'id'}; + } if (defined($token->[2]->{'name'})) { $unikey.='_'.$token->[2]->{'name'}; } @@ -84,6 +99,14 @@ sub metaread { return '
Processed file: '.$fn.''; } +# ---------------------------- convert 'time' format into a datetime sql format +sub sqltime { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = + localtime(@_[0]); + $mon++; $year+=1900; + return "$year-$mon-$mday $hour:$min:$sec"; +} + # --------------------------------------------------------- Various form fields sub textfield { @@ -110,6 +133,25 @@ sub selectbox { # -------------------------------------------------------- Publication Step One +sub urlfixup { + my ($url,$target)=@_; + unless ($url) { return ''; } + my ($host)=($url=~/(?:http\:\/\/)*([^\/]+)/); + map { + if ($_ eq $host) { + $url=~s/^http\:\/\///; + $url=~s/^$host//; + } + } values %Apache::lonnet::hostname; + if ($url=~/^http\:\/\//) { return $url; } + $url=~s/\~$cuname/res\/$cudom\/$cuname/; + if ($target) { + $target=~s/\/[^\/]+$//; + $url=&Apache::lonnet::hreflocation($target,$url); + } + return $url; +} + sub publish { my ($source,$target,$style)=@_; @@ -117,6 +159,8 @@ sub publish { my $scrout=''; my $allmeta=''; my $content=''; + my %allow=(); + undef %allow; unless ($logfile=Apache::File->new('>>'.$source.'.log')) { return @@ -177,46 +221,109 @@ sub publish { print $logfile "Needs ID and/or index fixup\n". "Max ID : $maxid (min 10)\n". "Max Index: $maxindex (min 10)\n"; - + } my $outstring=''; my $parser=HTML::TokeParser->new(\$content); my $token; while ($token=$parser->get_token) { if ($token->[0] eq 'S') { - my $counter; - if ($counter=$addid{$token->[1]}) { + my $counter; + my $tag=$token->[1]; + unless ($tag eq 'allow') { + my %parms=%{$token->[2]}; + if ($counter=$addid{$tag}) { if ($counter eq 'id') { - if (defined($token->[2]->{'id'})) { - $outstring.=$token->[4]; - } else { + unless (defined($parms{'id'})) { $maxid++; - my $thisid=' id="'.$maxid.'"'; - my $fixup=$token->[4]; - $fixup=~s/(\<\w+)/$1$thisid/; - $outstring.=$fixup; - print $logfile 'ID: '.$fixup."\n"; + $parms{'id'}=$maxid; + print $logfile 'ID: '.$tag.':'.$maxid."\n"; } - } else { - if (defined($token->[2]->{'index'})) { - $outstring.=$token->[4]; - } else { + } elsif ($counter eq 'index') { + unless (defined($parms{'index'})) { $maxindex++; - my $thisindex=' index="'.$maxindex.'"'; - my $fixup=$token->[4]; - $fixup=~s/(\<\w+)/$1$thisindex/; - $outstring.=$fixup; - print $logfile 'Index: '.$fixup."\n"; + $parms{'index'}=$maxindex; + print $logfile 'Index: '.$tag.':'.$maxindex."\n"; } } - } else { - $outstring.=$token->[4]; + } + + map { + if (defined($parms{$_})) { + my $oldurl=$parms{$_}; + my $newurl=&urlfixup($oldurl,$target); + if ($newurl ne $oldurl) { + $parms{$_}=$newurl; + print $logfile 'URL: '.$tag.':'.$oldurl.' - '. + $newurl."\n"; + } + $allow{$newurl}=1; + } + } ('src','href'); + + if ($tag eq 'applet') { + my $codebase=''; + if (defined($parms{'codebase'})) { + my $oldcodebase=$parms{'codebase'}; + unless ($oldcodebase=~/\/$/) { + $oldcodebase.='/'; + } + $codebase=&urlfixup($oldcodebase,$target); + $codebase=~s/\/$//; + if ($codebase ne $oldcodebase) { + $parms{'codebase'}=$codebase; + print $logfile 'URL codebase: '.$tag.':'. + $oldcodebase.' - '. + $codebase."\n"; + } + $allow{$codebase.'/*'}=1; + } else { + map { + if (defined($parms{$_})) { + my $oldurl=$parms{$_}; + my $newurl=&urlfixup($oldurl,$target); + $newurl=~s/\/[^\/]+$/\/\*/; + print $logfile 'Allow: applet '.$_.':'. + $oldurl.' allows '. + $newurl."\n"; + $allow{$newurl}=1; + } + } ('archive','code','object'); + } } + + my $newparmstring=''; + my $endtag=''; + map { + if ($_ eq '/') { + $endtag=' /'; + } else { + my $quote=($parms{$_}=~/\"/?"'":'"'); + $newparmstring.=' '.$_.'='.$quote.$parms{$_}.$quote; + } + } keys %parms; + + $outstring.='<'.$tag.$newparmstring.$endtag.'>'; + } else { + $allow{$token->[2]->{'src'}}=1; + } } elsif ($token->[0] eq 'E') { - $outstring.=$token->[2]; + unless ($token->[1] eq 'allow') { + $outstring.=$token->[2]; + } } else { $outstring.=$token->[1]; } } +# ------------------------------------------------------------ Construct Allows + unless ($style eq 'rat') { + my $allowstr="\n"; + map { + $allowstr.=''."\n"; + } keys %allow; + $outstring=~s/(\<\/[^\>]+\>\s*)$/$allowstr$1/s; + } +# ------------------------------------------------------------- Write modified + { my $org; unless ($org=Apache::File->new('>'.$source)) { @@ -227,13 +334,15 @@ sub publish { print $org $outstring; } $content=$outstring; + + if ($needsfixup) { print $logfile "End of ID and/or index fixup\n". "Max ID : $maxid (min 10)\n". "Max Index: $maxindex (min 10)\n"; } else { print $logfile "Does not need ID and/or index fixup\n"; } - + } # --------------------------------------------- Initial step done, now metadata # ---------------------------------------- Storage for metadata keys and fields @@ -251,17 +360,17 @@ sub publish { $ENV{'environment.generation'}; $metadatafields{'author'}=~s/\s+/ /g; $metadatafields{'author'}=~s/\s+$//; - $metadatafields{'owner'}=$ENV{'user.name'}.'@'.$ENV{'user.domain'}; + $metadatafields{'owner'}=$cuname.'@'.$cudom; # ------------------------------------------------ Check out directory hierachy my $thisdisfn=$source; - $thisdisfn=~s/^\/home\/$ENV{'user.name'}\///; + $thisdisfn=~s/^\/home\/$cuname\///; my @urlparts=split(/\//,$thisdisfn); $#urlparts--; - my $currentpath='/home/'.$ENV{'user.name'}.'/'; + my $currentpath='/home/'.$cuname.'/'; map { $currentpath.=$_.'/'; @@ -291,10 +400,11 @@ sub publish { } # -------------------------------------------------- Parse content for metadata - + if ($style eq 'ssi') { $allmeta=Apache::lonxml::xmlparse('meta',$content); - &metaeval($allmeta); + &metaeval($allmeta); + } # ---------------- Find and document discrepancies in the parameters and stores my $chparms=''; @@ -316,7 +426,8 @@ sub publish { my $chparms=''; map { if (($_=~/^parameter/) || ($_=~/^stores/)) { - unless (($metadatafields{$_.'.name'}) || ($_=~/\.\w+$/)) { + unless (($metadatafields{$_.'.name'}) || + ($metadatafields{$_.'.package'}) || ($_=~/\.\w+$/)) { print $logfile 'Obsolete: '.$_."\n"; $chparms.=$_.' '; } @@ -326,7 +437,7 @@ sub publish { $scrout.='

Obsolete parameters or stored values: '. $chparms; } - } + # ------------------------------------------------------- Now have all metadata $scrout.= @@ -418,7 +529,7 @@ sub publish { sub phasetwo { - my ($source,$target,$style)=@_; + my ($source,$target,$style,$distarget)=@_; my $logfile; my $scrout=''; @@ -482,6 +593,69 @@ sub phasetwo { print $logfile "\nWrote metadata"; } +# -------------------------------- Synchronize entry with SQL metadata database + my %perlvar; + open (CONFIG,"/etc/httpd/conf/access.conf") || die "Can't read access.conf"; + my $configline; + while ($configline=) { + if ($configline =~ /PerlSetVar/) { + my ($dummy,$varname,$varvalue)=split(/\s+/,$configline); + chomp($varvalue); + $perlvar{$varname}=$varvalue; + } + } + close(CONFIG); + + my $warning; + my $dbh; + { + unless ( + $dbh = DBI->connect("DBI:mysql:loncapa","www",$perlvar{'lonSqlAccess'},{ RaiseError =>0,PrintError=>0}) + ) { + $warning='WARNING: Cannot connect to '. + 'database!'; + } + else { + my %sqldatafields; + $sqldatafields{'url'}=$distarget; + my $sth=$dbh->prepare( + 'delete from metadata where url like binary'. + '"'.$sqldatafields{'url'}.'"'); + $sth->execute(); + map {my $field=$metadatafields{$_}; $field=~s/\"/\'\'/g; + $sqldatafields{$_}=$field;} + ('title','author','subject','keywords','notes','abstract', + 'mime','language','creationdate','lastrevisiondate','owner', + 'copyright'); + + $sth=$dbh->prepare('insert into metadata values ('. + '"'.delete($sqldatafields{'title'}).'"'.','. + '"'.delete($sqldatafields{'author'}).'"'.','. + '"'.delete($sqldatafields{'subject'}).'"'.','. + '"'.delete($sqldatafields{'url'}).'"'.','. + '"'.delete($sqldatafields{'keywords'}).'"'.','. + '"'.'current'.'"'.','. + '"'.delete($sqldatafields{'notes'}).'"'.','. + '"'.delete($sqldatafields{'abstract'}).'"'.','. + '"'.delete($sqldatafields{'mime'}).'"'.','. + '"'.delete($sqldatafields{'language'}).'"'.','. + '"'. + sqltime(delete($sqldatafields{'creationdate'})) + .'"'.','. + '"'. + sqltime(delete( + $sqldatafields{'lastrevisiondate'})).'"'.','. + '"'.delete($sqldatafields{'owner'}).'"'.','. + '"'.delete( + $sqldatafields{'copyright'}).'"'.')'); + $sth->execute(); + $dbh->disconnect; + $scrout.='

Synchronized SQL metadata database'; + print $logfile "\nSynchronized SQL metadata database"; + } + } + + # ----------------------------------------------------------- Copy old versions if (-e $target) { @@ -639,7 +813,7 @@ if (-e $target) { $thissrcdir=~s/\/[^\/]+$/\//; - return $scrout. + return $warning.$scrout. '


View Target'. '

Back to Source'. '

Diffs with Current Version

'); + } # ------------ We are publishing from $thisfn to $thistarget with $thisembstyle unless ($ENV{'form.phase'} eq 'two') { - $r->print('


'.&publish($thisfn,$thistarget,$thisembstyle)); + $r->print( + '
'.&publish($thisfn,$thistarget,$thisembstyle)); } else { - $r->print('
'.&phasetwo($thisfn,$thistarget,$thisembstyle)); + $r->print( + '
'.&phasetwo($thisfn,$thistarget,$thisembstyle,$thisdistarget)); } }