X-Git-Url: http://git.vanrenterghem.biz/git.ikiwiki.info.git/blobdiff_plain/b9efeba972c82da706756eee51a0682018663586..1d4ddbb9eb140b9bafe5091143473a52e03887c5:/IkiWiki/Plugin/filecheck.pm diff --git a/IkiWiki/Plugin/filecheck.pm b/IkiWiki/Plugin/filecheck.pm index 1855a8b48..6e6528398 100644 --- a/IkiWiki/Plugin/filecheck.pm +++ b/IkiWiki/Plugin/filecheck.pm @@ -3,9 +3,9 @@ package IkiWiki::Plugin::filecheck; use warnings; use strict; -use IkiWiki 2.00; +use IkiWiki 3.00; -my %units=( #{{{ # size in bytes +my %units=( # size in bytes B => 1, byte => 1, KB => 2 ** 10, @@ -37,9 +37,21 @@ my %units=( #{{{ # size in bytes # ikiwiki, if you find you need larger data quantities, either modify # yourself to add them, or travel back in time to 2008 and kill me. # -- Joey -); #}}} +); -sub parsesize ($) { #{{{ +sub import { + hook(type => "getsetup", id => "filecheck", call => \&getsetup); +} + +sub getsetup () { + return + plugin => { + safe => 1, + rebuild => undef, + }, +} + +sub parsesize ($) { my $size=shift; no warnings; @@ -51,10 +63,10 @@ sub parsesize ($) { #{{{ } } return $base; -} #}}} +} # This is provided for other plugins that want to convert back the other way. -sub humansize ($) { #{{{ +sub humansize ($) { my $size=shift; foreach my $unit (reverse sort { $units{$a} <=> $units{$b} || $b cmp $a } keys %units) { @@ -63,21 +75,21 @@ sub humansize ($) { #{{{ } } return $size; # near zero, or negative -} #}}} +} package IkiWiki::PageSpec; -sub match_maxsize ($$;@) { #{{{ +sub match_maxsize ($$;@) { my $page=shift; - my $maxsize=eval{IkiWiki::Plugin::attachment::parsesize(shift)}; + my $maxsize=eval{IkiWiki::Plugin::filecheck::parsesize(shift)}; if ($@) { - return IkiWiki::FailReason->new("unable to parse maxsize (or number too large)"); + return IkiWiki::ErrorReason->new("unable to parse maxsize (or number too large)"); } my %params=@_; - my $file=exists $params{file} ? $params{file} : $IkiWiki::pagesources{$page}; + my $file=exists $params{file} ? $params{file} : IkiWiki::srcfile($IkiWiki::pagesources{$page}); if (! defined $file) { - return IkiWiki::FailReason->new("no file specified"); + return IkiWiki::ErrorReason->new("file does not exist"); } if (-s $file > $maxsize) { @@ -86,19 +98,19 @@ sub match_maxsize ($$;@) { #{{{ else { return IkiWiki::SuccessReason->new("file not too large"); } -} #}}} +} -sub match_minsize ($$;@) { #{{{ +sub match_minsize ($$;@) { my $page=shift; - my $minsize=eval{IkiWiki::Plugin::attachment::parsesize(shift)}; + my $minsize=eval{IkiWiki::Plugin::filecheck::parsesize(shift)}; if ($@) { - return IkiWiki::FailReason->new("unable to parse minsize (or number too large)"); + return IkiWiki::ErrorReason->new("unable to parse minsize (or number too large)"); } my %params=@_; - my $file=exists $params{file} ? $params{file} : $IkiWiki::pagesources{$page}; + my $file=exists $params{file} ? $params{file} : IkiWiki::srcfile($IkiWiki::pagesources{$page}); if (! defined $file) { - return IkiWiki::FailReason->new("no file specified"); + return IkiWiki::ErrorReason->new("file does not exist"); } if (-s $file < $minsize) { @@ -107,51 +119,70 @@ sub match_minsize ($$;@) { #{{{ else { return IkiWiki::SuccessReason->new("file not too small"); } -} #}}} +} -sub match_mimetype ($$;@) { #{{{ +sub match_mimetype ($$;@) { my $page=shift; my $wanted=shift; my %params=@_; - my $file=exists $params{file} ? $params{file} : $IkiWiki::pagesources{$page}; + my $file=exists $params{file} ? $params{file} : IkiWiki::srcfile($IkiWiki::pagesources{$page}); if (! defined $file) { - return IkiWiki::FailReason->new("no file specified"); + return IkiWiki::ErrorReason->new("file does not exist"); } - # Use ::magic to get the mime type, the idea is to only trust - # data obtained by examining the actual file contents. + # Get the mime type. + # + # First, try File::Mimeinfo. This is fast, but doesn't recognise + # all files. eval q{use File::MimeInfo::Magic}; - if ($@) { - return IkiWiki::FailReason->new("failed to load File::MimeInfo::Magic ($@); cannot check MIME type"); + my $mimeinfo_ok=! $@; + my $mimetype; + if ($mimeinfo_ok) { + $mimetype=File::MimeInfo::Magic::magic($file); } - my $mimetype=File::MimeInfo::Magic::magic($file); + + # Fall back to using file, which has a more complete + # magic database. if (! defined $mimetype) { - $mimetype="unknown"; + open(my $file_h, "-|", "file", "-bi", $file); + $mimetype=<$file_h>; + chomp $mimetype; + close $file_h; + } + if (! defined $mimetype) { + # Fall back to default value. + $mimetype=File::MimeInfo::Magic::default($file) + if $mimeinfo_ok; + if (! defined $mimetype) { + $mimetype="unknown"; + } } + # Ignore any parameters, we only want the type itself + $mimetype =~ s/;.*//; my $regexp=IkiWiki::glob2re($wanted); - if ($mimetype!~/^$regexp$/i) { + if ($mimetype!~$regexp) { return IkiWiki::FailReason->new("file MIME type is $mimetype, not $wanted"); } else { return IkiWiki::SuccessReason->new("file MIME type is $mimetype"); } -} #}}} +} -sub match_virusfree ($$;@) { #{{{ +sub match_virusfree ($$;@) { my $page=shift; my $wanted=shift; my %params=@_; - my $file=exists $params{file} ? $params{file} : $IkiWiki::pagesources{$page}; + my $file=exists $params{file} ? $params{file} : IkiWiki::srcfile($IkiWiki::pagesources{$page}); if (! defined $file) { - return IkiWiki::FailReason->new("no file specified"); + return IkiWiki::ErrorReason->new("file does not exist"); } if (! exists $IkiWiki::config{virus_checker} || ! length $IkiWiki::config{virus_checker}) { - return IkiWiki::FailReason->new("no virus_checker configured"); + return IkiWiki::ErrorReason->new("no virus_checker configured"); } # The file needs to be fed into the virus checker on stdin, @@ -159,7 +190,7 @@ sub match_virusfree ($$;@) { #{{{ # used, clamd would fail to read it. eval q{use IPC::Open2}; error($@) if $@; - open (IN, "<", $file) || return IkiWiki::FailReason->new("failed to read file"); + open (IN, "<", $file) || return IkiWiki::ErrorReason->new("failed to read file"); binmode(IN); my $sigpipe=0; $SIG{PIPE} = sub { $sigpipe=1 }; @@ -179,9 +210,9 @@ sub match_virusfree ($$;@) { #{{{ else { return IkiWiki::SuccessReason->new("file seems virusfree ($reason)"); } -} #}}} +} -sub match_ispage ($$;@) { #{{{ +sub match_ispage ($$;@) { my $filename=shift; if (defined IkiWiki::pagetype($filename)) { @@ -190,4 +221,4 @@ sub match_ispage ($$;@) { #{{{ else { return IkiWiki::FailReason->new("file is not a wiki page"); } -} #}}} +}