diff --git a/lib/Foswiki/Plugins/UpdateAttachmentsPlugin.pm b/lib/Foswiki/Plugins/UpdateAttachmentsPlugin.pm index fd7345a..fa8333f 100644 --- a/lib/Foswiki/Plugins/UpdateAttachmentsPlugin.pm +++ b/lib/Foswiki/Plugins/UpdateAttachmentsPlugin.pm @@ -18,61 +18,72 @@ use strict; our $VERSION = '$Rev$'; our $RELEASE = 'Foswiki-1.0'; -our $SHORTDESCRIPTION = 'A batched alternative to AutoAttachments (adds and removes attachements)'; +our $SHORTDESCRIPTION = + 'A batched alternative to AutoAttachments (adds and removes attachements)'; our $NO_PREFS_IN_TOPIC = 1; my $debug = 0; sub initPlugin { - my( $topic, $web, $user, $installWeb ) = @_; + my ( $topic, $web, $user, $installWeb ) = @_; # check for Plugins.pm versions - if( $Foswiki::Plugins::VERSION < 2.1 ) { - Foswiki::Func::writeWarning( "Version mismatch between UpdateAttachmentsPlugin and Plugins.pm" ); + if ( $Foswiki::Plugins::VERSION < 2.1 ) { + Foswiki::Func::writeWarning( + "Version mismatch between UpdateAttachmentsPlugin and Plugins.pm"); return 0; } - + $debug = $Foswiki::cfg{Plugins}{UpdateAttachmentsPlugin}{Debug} || 0; - Foswiki::Func::registerRESTHandler('update', \&restUpdate); + Foswiki::Func::registerRESTHandler( 'update', \&restUpdate ); return 1; } - sub restUpdate { my $session = shift; - my $store = $session->{store}; - my $web = $session->{webName}; - + my $store = $session->{store}; + my $web = $session->{webName}; + print STDERR "update the attachments of $web\n" if $debug; - + #force autoattach off, as we need to know the real META my $cfgAutoAttach = $Foswiki::cfg{AutoAttachPubFiles}; $Foswiki::cfg{AutoAttachPubFiles} = 0; - - #TODO: consider the lighter weight aproach of scanning timestamps in the pub dir - # checking&updating only those topics that have newer timestamp pub files - # (it would only helps adding attachments, not removing them) - - my $topicsTested = 0; - my $topicsUpdated = 0; + +#TODO: consider the lighter weight aproach of scanning timestamps in the pub dir +# checking&updating only those topics that have newer timestamp pub files +# (it would only helps adding attachments, not removing them) + + my $topicsTested = 0; + my $topicsUpdated = 0; my $attachmentsIgnored = 0; my $attachmentsRemoved = 0; - my $attachmentsAdded = 0; + my $attachmentsAdded = 0; my $attachmentsUpdated = 0; + my $detailedReport = ''; #TODO: test user's access to web (rest already tests for web CHANGE access) - my @topicNames = Foswiki::Func::getTopicList( $web ); + my @topicNames = Foswiki::Func::getTopicList($web); foreach my $topic (@topicNames) { - # test user's permission on this topic (do this first, eventually this check may not read the topic.. for now it will populate the cache) - next if (!Foswiki::Func::checkAccessPermission( 'CHANGE', Foswiki::Func::getWikiName(), undef, $topic, $web )); - my $changed = 0; + my $topicObject = Foswiki::Meta->load( $session, $web, $topic ); + + if ( !$topicObject->haveAccess('CHANGE') ) { + $detailedReport .= + "bypassed $web.$topic - no permission to change
\n"; + $topicObject->finish(); + next; + } - my $topicObject = Foswiki::Meta->load($session, $web, $topic); my @knownAttachments = $topicObject->find('FILEATTACHMENT'); - my ($attachmentsFoundInPub, $attachmentsRemovedFromMeta, $attachmentsAddedToMeta, $attachmentsUpdatedInMeta) = - synchroniseAttachmentsList($topicObject, \@knownAttachments ); + my ( + $attachmentsFoundInPub, $attachmentsRemovedFromMeta, + $attachmentsAddedToMeta, $attachmentsUpdatedInMeta + ) = synchroniseAttachmentsList( $topicObject, \@knownAttachments ); + + # @validAttachmentsFound will contain the replacment attachment Metadata my @validAttachmentsFound; + foreach my $foundAttachment (@$attachmentsFoundInPub) { # test if the attachment filename is valid without having to @@ -83,7 +94,8 @@ sub restUpdate { && $validated eq $foundAttachment->{name} ) { - print STDERR 'AutoAttachPubFiles ignoring ' + $detailedReport .= + 'AutoAttachPubFiles ignoring ' . $foundAttachment->{name} . ' in ' . $topicObject->getPath() . ' - not a valid Foswiki Attachment filename'; @@ -96,31 +108,57 @@ sub restUpdate { $topicObject->putAll( 'FILEATTACHMENT', @validAttachmentsFound ) if @validAttachmentsFound; - #TODO: actually test that they are the same! (update size, date etc) - print STDERR "$web.$topic has ".scalar(@knownAttachments)." in meta, ".scalar(@$attachmentsFoundInPub)." in pub dir\n" if $debug; - - $changed = scalar(@$attachmentsRemovedFromMeta) + scalar(@$attachmentsAddedToMeta) + scalar(@$attachmentsUpdatedInMeta); + print STDERR "$web.$topic has " + . scalar(@knownAttachments) + . " in meta, " + . scalar(@$attachmentsFoundInPub) + . " in pub dir\n" + if $debug; + + $changed = + scalar(@$attachmentsRemovedFromMeta) + + scalar(@$attachmentsAddedToMeta) + + scalar(@$attachmentsUpdatedInMeta); if ($changed) { - $topicObject->save( comment => 'UpdateAttachments' ); + $topicObject->save( comment => 'UpdateAttachments' ); print STDERR "updating the attachments of $web.$topic\n" if $debug; $topicsUpdated++; $attachmentsRemoved += scalar(@$attachmentsRemovedFromMeta); - $attachmentsAdded += scalar(@$attachmentsAddedToMeta); + $attachmentsAdded += scalar(@$attachmentsAddedToMeta); $attachmentsUpdated += scalar(@$attachmentsUpdatedInMeta); + + $detailedReport .= "Updating $web.$topic
\n"; + foreach my $attach (@$attachmentsRemovedFromMeta) { + $detailedReport .= "Removed $attach
"; + } + foreach my $attach (@$attachmentsAddedToMeta) { + $detailedReport .= "Added $attach
"; + } + foreach my $attach (@$attachmentsUpdatedInMeta) { + $detailedReport .= "Updated $attach
"; + } } $topicsTested++; + $topicObject->finish(); + #TODO: $Foswiki::cfg{Plugins}{UpdateAttachmentsPlugin}{BatchLimit} } - print STDERR "UpdateAttachments checked $topicsTested, updated $topicsUpdated, removed $attachmentsRemoved attachments, $attachmentsIgnored ignored" if $debug; + print STDERR +"UpdateAttachments checked $topicsTested, updated $topicsUpdated, removed $attachmentsRemoved attachments, $attachmentsIgnored ignored" + if $debug; - # Restore auto-attach setting. (This *really* ought to be disabled if using this plugin - $Foswiki::cfg{AutoAttachPubFiles} = $cfgAutoAttach ; +# Restore auto-attach setting. (This *really* ought to be disabled if using this plugin + $Foswiki::cfg{AutoAttachPubFiles} = $cfgAutoAttach; - return "UpdateAttachments Topics checked $topicsTested, updated $topicsUpdated,
Attachments updated $attachmentsUpdated, added $attachmentsAdded, removed $attachmentsRemoved attachments, $attachmentsIgnored ignored"; + return < +Attachments updated $attachmentsUpdated, added $attachmentsAdded, removed $attachmentsRemoved, ignored $attachmentsIgnored

+$detailedReport +HERE } =begin TML @@ -141,12 +179,12 @@ put in the new tom. sub synchroniseAttachmentsList { my ( $topicObject, $attachmentsKnownInMeta ) = @_; - my %filesListedInPub = _getAttachmentStats($topicObject); - my %filesListedInMeta = (); - my %filesToAddToMeta = (); + my %filesListedInPub = _getAttachmentStats($topicObject); + my %filesListedInMeta = (); + my %filesToAddToMeta = (); my @filesRemovedFromMeta = (); - my @filesAddedToMeta = (); - my @filesUpdatedInMeta = (); + my @filesAddedToMeta = (); + my @filesUpdatedInMeta = (); # You need the following lines if you want metadata to supplement # the filesystem @@ -157,12 +195,16 @@ sub synchroniseAttachmentsList { foreach my $file ( keys %filesListedInPub ) { if ( $filesListedInMeta{$file} ) { - if ( $filesListedInMeta{$file}{size} ne $filesListedInPub{$file}{size} || - $filesListedInMeta{$file}{date} ne $filesListedInPub{$file}{date} ) { + if ( $filesListedInMeta{$file}{size} ne + $filesListedInPub{$file}{size} + || $filesListedInMeta{$file}{date} ne + $filesListedInPub{$file}{date} ) + { $filesListedInPub{$file}{autoattached} = "1"; push @filesUpdatedInMeta, $file; print STDERR "Updating $file \n"; } + # Bring forward any missing yet wanted attribute foreach my $field qw(comment attr user version autoattached) { if ( $filesListedInMeta{$file}{$field} ) { @@ -172,14 +214,26 @@ sub synchroniseAttachmentsList { } } else { + #default attachment owner to {AttachAsUser} push @filesAddedToMeta, $file; print STDERR "Adding $file \n"; $filesListedInPub{$file}{autoattached} = "1"; - if ((defined($Foswiki::cfg{Plugins}{UpdateAttachmentsPlugin}{AttachAsUser})) && - ($Foswiki::cfg{Plugins}{UpdateAttachmentsPlugin}{AttachAsUser} ne '')) { - $filesListedInPub{$file}{user} = $Foswiki::cfg{Plugins}{UpdateAttachmentsPlugin}{AttachAsUser}; - #TODO: needs testing for the generalised usermapping case - shoudl store cUID + if ( + ( + defined( + $Foswiki::cfg{Plugins}{UpdateAttachmentsPlugin} + {AttachAsUser} + ) + ) + && ( $Foswiki::cfg{Plugins}{UpdateAttachmentsPlugin} + {AttachAsUser} ne '' ) + ) + { + $filesListedInPub{$file}{user} = + $Foswiki::cfg{Plugins}{UpdateAttachmentsPlugin}{AttachAsUser}; + + #TODO: needs testing for the generalised usermapping case - shoudl store cUID } } } @@ -188,9 +242,17 @@ sub synchroniseAttachmentsList { # would show files that were in Meta but have disappeared from Pub. foreach my $file ( keys %filesListedInMeta ) { - if (! $filesListedInPub{$file} ) { - print STDERR "Removing $file \n"; - push @filesRemovedFromMeta, $file; + if ( !$filesListedInPub{$file} ) { + if ( + $Foswiki::cfg{Plugins}{UpdateAttachmentsPlugin}{RemoveMissing} ) + { + print STDERR "Removing $file \n" if $debug; + push @filesRemovedFromMeta, $file; + } + else { + $filesListedInPub{$file} = $filesListedInMeta{$file}; + print STDERR "Retained missing attachment $file\n" if $debug; + } } } @@ -198,7 +260,8 @@ sub synchroniseAttachmentsList { # proper attachment sequence my @deindexedBecauseMetaDoesnotIndexAttachments = values(%filesListedInPub); - return \@deindexedBecauseMetaDoesnotIndexAttachments, \@filesRemovedFromMeta, \@filesAddedToMeta, \@filesUpdatedInMeta; + return \@deindexedBecauseMetaDoesnotIndexAttachments, + \@filesRemovedFromMeta, \@filesAddedToMeta, \@filesUpdatedInMeta; } =begin TML @@ -211,7 +274,10 @@ Get list of attachment names actually stored for topic. sub getAttachmentList { my $topicObject = shift; - my $dir = "$Foswiki::cfg{PubDir}/" . $topicObject->web() . "/" . $topicObject->topic(); + my $dir = + "$Foswiki::cfg{PubDir}/" + . $topicObject->web() . "/" + . $topicObject->topic(); my $dh; opendir( $dh, $dir ) || return (); my @files = grep { !/^[.*_]/ && !/,v$/ } readdir($dh); @@ -222,9 +288,12 @@ sub getAttachmentList { # returns {} of filename => { key => value, key2 => value } # for any given web, topic sub _getAttachmentStats { - my $topicObject = shift; + my $topicObject = shift; my %attachmentList = (); - my $dir = "$Foswiki::cfg{PubDir}/" . $topicObject->web() . '/' . $topicObject->topic(); + my $dir = + "$Foswiki::cfg{PubDir}/" + . $topicObject->web() . '/' + . $topicObject->topic(); foreach my $attachment ( getAttachmentList($topicObject) ) { my @stat = stat( $dir . "/" . $attachment ); $attachmentList{$attachment} = @@ -246,8 +315,8 @@ sub _constructAttributesForAutoAttached { date => $stat->[9], # user => 'UnknownUser', #safer _not_ to default - Foswiki will fill it in when it needs to - comment => '', - attr => '', + comment => '', + attr => '', ); if ( $#$stat > 0 ) { diff --git a/lib/Foswiki/Plugins/UpdateAttachmentsPlugin/Config.spec b/lib/Foswiki/Plugins/UpdateAttachmentsPlugin/Config.spec index f69dd76..fcb59c7 100755 --- a/lib/Foswiki/Plugins/UpdateAttachmentsPlugin/Config.spec +++ b/lib/Foswiki/Plugins/UpdateAttachmentsPlugin/Config.spec @@ -1,14 +1,12 @@ -#---++ Extensions +#---+ Extensions #---++ Update Attachments Plugin # **STRING** # To attribute attachments to a known user, set this to their WikiName. This user should exist, -# and be mappable to a login. +# and be mappable to a login. If not set, the default UnknownUser will be used. $Foswiki::cfg{Plugins}{UpdateAttachmentsPlugin}{AttachAsUser} = ''; # **BOOLEAN** -# remove references to attachments that no longer exist in pub -$Foswiki::cfg{Plugins}{UpdateAttachmentsPlugin}{RemoveMissing} = $FALSE; +# Remove references to attachments that no longer exist in pub. +$Foswiki::cfg{Plugins}{UpdateAttachmentsPlugin}{RemoveMissing} = $TRUE; # **BOOLEAN** -# use the _internal_ _noHandlersSave - This option causes the topic update code to write directly into the -# Store, bypassing the API's and other Handlers. This is *Strongly* not recommended. This may break in -# future and is not recomended unless you know the code. -$Foswiki::cfg{Plugins}{UpdateAttachmentsPlugin}{UseDangerousNoHandlersSave} = $FALSE; +# Enable debugging messages - printed to STDERR (Apache error_log file) +$Foswiki::cfg{Plugins}{UpdateAttachmentsPlugin}{Debug} = $FALSE;