-}
-
-my %units=( # size in bytes
- B => 1,
- byte => 1,
- KB => 2 ** 10,
- kilobyte => 2 ** 10,
- K => 2 ** 10,
- KB => 2 ** 10,
- kilobyte => 2 ** 10,
- M => 2 ** 20,
- MB => 2 ** 20,
- megabyte => 2 ** 20,
- G => 2 ** 30,
- GB => 2 ** 30,
- gigabyte => 2 ** 30,
- T => 2 ** 40,
- TB => 2 ** 40,
- terabyte => 2 ** 40,
- P => 2 ** 50,
- PB => 2 ** 50,
- petabyte => 2 ** 50,
- E => 2 ** 60,
- EB => 2 ** 60,
- exabyte => 2 ** 60,
- Z => 2 ** 70,
- ZB => 2 ** 70,
- zettabyte => 2 ** 70,
- Y => 2 ** 80,
- YB => 2 ** 80,
- yottabyte => 2 ** 80,
- # 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 ($) { #{{{
- my $size=shift;
-
- no warnings;
- my $base=$size+0; # force to number
- use warnings;
- foreach my $unit (sort keys %units) {
- if ($size=~/[0-9\s]\Q$unit\E$/i) {
- return $base * $units{$unit};
- }
- }
- return $base;
-} #}}}
-
-sub humansize ($) { #{{{
- my $size=shift;
-
- foreach my $unit (reverse sort { $units{$a} <=> $units{$b} || $b cmp $a } keys %units) {
- if ($size / $units{$unit} > 0.25) {
- return (int($size / $units{$unit} * 10)/10).$unit;
- }
- }
- return $size; # near zero, or negative
-} #}}}
-
-package IkiWiki::PageSpec;
-
-sub match_maxsize ($$;@) { #{{{
- shift;
- my $maxsize=eval{IkiWiki::Plugin::attachment::parsesize(shift)};
- if ($@) {
- return IkiWiki::FailReason->new("unable to parse maxsize (or number too large)");
- }
-
- my %params=@_;
- if (! exists $params{file}) {
- return IkiWiki::FailReason->new("no file specified");
- }
-
- if (-s $params{file} > $maxsize) {
- return IkiWiki::FailReason->new("file too large (".(-s $params{file})." > $maxsize)");
- }
- else {
- return IkiWiki::SuccessReason->new("file not too large");
- }
-} #}}}
-
-sub match_minsize ($$;@) { #{{{
- shift;
- my $minsize=eval{IkiWiki::Plugin::attachment::parsesize(shift)};
- if ($@) {
- return IkiWiki::FailReason->new("unable to parse minsize (or number too large)");
- }
-
- my %params=@_;
- if (! exists $params{file}) {
- return IkiWiki::FailReason->new("no file specified");
- }
-
- if (-s $params{file} < $minsize) {
- return IkiWiki::FailReason->new("file too small");
- }
- else {
- return IkiWiki::SuccessReason->new("file not too small");
- }
-} #}}}
-
-sub match_mimetype ($$;@) { #{{{
- shift;
- my $wanted=shift;
-
- my %params=@_;
- if (! exists $params{file}) {
- return IkiWiki::FailReason->new("no file specified");
- }
-
- # Use ::magic to get the mime type, the idea is to only trust
- # data obtained by examining the actual file contents.
- eval q{use File::MimeInfo::Magic};
- if ($@) {
- return IkiWiki::FailReason->new("failed to load File::MimeInfo::Magic ($@); cannot check MIME type");
- }
- my $mimetype=File::MimeInfo::Magic::magic($params{file});
- if (! defined $mimetype) {
- $mimetype="unknown";
- }
-
- # turn glob into a safe regexp
- my $regexp=quotemeta($wanted);
- $regexp=~s/\\\*/.*/g;
- $regexp=~s/\\\?/./g;
-
- if ($mimetype!~/^$regexp$/i) {
- return IkiWiki::FailReason->new("file MIME type is $mimetype, not $wanted");
- }
- else {
- return IkiWiki::SuccessReason->new("file MIME type is $mimetype");
- }
-} #}}}
-
-sub match_ispage ($$;@) { #{{{
- my $filename=shift;
-
- if (defined IkiWiki::pagetype($filename)) {
- return IkiWiki::SuccessReason->new("file is a wiki page");
- }
- else {
- return IkiWiki::FailReason->new("file is not a wiki page");
- }
-} #}}}
-
-sub match_user ($$;@) { #{{{
- shift;
- my $user=shift;
- my %params=@_;
-
- if (! exists $params{user}) {
- return IkiWiki::FailReason->new("no user specified");
- }
-
- if (defined $params{user} && lc $params{user} eq lc $user) {
- return IkiWiki::SuccessReason->new("user is $user");
- }
- else {
- return IkiWiki::FailReason->new("user is $params{user}, not $user");
- }
-} #}}}
-
-sub match_ip ($$;@) { #{{{
- shift;
- my $ip=shift;
- my %params=@_;
-
- if (! exists $params{ip}) {
- return IkiWiki::FailReason->new("no IP specified");
- }
-
- if (defined $params{ip} && lc $params{ip} eq lc $ip) {
- return IkiWiki::SuccessReason->new("IP is $ip");
- }
- else {
- return IkiWiki::FailReason->new("IP is $params{ip}, not $ip");
- }