From: Tony Cook Date: Mon, 4 Jun 2012 10:00:15 +0000 (+1000) Subject: added the check_file_limits() method to Imager X-Git-Tag: v0.91~3 X-Git-Url: http://git.imager.perl.org/imager.git/commitdiff_plain/e1558ffe47db4cddc09069968c457d3e3644430d?ds=inline added the check_file_limits() method to Imager This exposes the i_int_check_image_file_limits() API. Since I'd expected people to be able to write file handlers in perl, such authors need access to the file size limit checking mechanism. --- diff --git a/Imager.pm b/Imager.pm index 3fbfc7ee..7650a46e 100644 --- a/Imager.pm +++ b/Imager.pm @@ -3900,6 +3900,41 @@ sub get_file_limits { i_get_image_file_limits(); } +my @check_args = qw(width height channels sample_size); + +sub check_file_limits { + my $class = shift; + + my %opts = + ( + channels => 3, + sample_size => 1, + @_, + ); + + if ($opts{sample_size} && $opts{sample_size} eq 'float') { + $opts{sample_size} = length(pack("d", 0)); + } + + for my $name (@check_args) { + unless (defined $opts{$name}) { + $class->_set_error("check_file_limits: $name must be defined"); + return; + } + unless ($opts{$name} == int($opts{$name})) { + $class->_set_error("check_file_limits: $name must be a positive integer"); + return; + } + } + + my $result = i_int_check_image_file_limits(@opts{@check_args}); + unless ($result) { + $class->_set_error($class->_error_as_msg()); + } + + return $result; +} + # Shortcuts that can be exported sub newcolor { Imager::Color->new(@_); } @@ -4398,6 +4433,8 @@ image box() - L - draw a filled or outline box. +check_file_limits() - L + circle() - L - draw a filled circle close_log() - L - close the Imager diff --git a/Imager.xs b/Imager.xs index 95c6f8eb..c499da39 100644 --- a/Imager.xs +++ b/Imager.xs @@ -1059,6 +1059,14 @@ i_get_image_file_limits() PUSHs(sv_2mortal(newSVuv(bytes))); } +bool +i_int_check_image_file_limits(width, height, channels, sample_size) + i_img_dim width + i_img_dim height + int channels + size_t sample_size + PROTOTYPE: DISABLE + MODULE = Imager PACKAGE = Imager::IO PREFIX = io_ Imager::IO diff --git a/lib/Imager/Files.pod b/lib/Imager/Files.pod index 050b1986..b8884c30 100644 --- a/lib/Imager/Files.pod +++ b/lib/Imager/Files.pod @@ -488,6 +488,37 @@ You can get the current limits with the get_file_limits() method: my ($max_width, $max_height, $max_bytes) = Imager->get_file_limits(); +=item check_file_limits() +XX + +Intended for use by file handlers to check that the size of a file is +within the limits set by C. + +Parameters: + +=over + +=item * + +C, C - the width and height of the image in pixels. +Must be a positive integer. Required. + +=item * + +C - the number of channels in the image, including the alpha +channel if any. Must be a positive integer between 1 and 4 +inclusive. Default: 3. + +=item * + +C - the number of bytes stored per sample. Must be a +positive integer or C<"float">. Note that this should be the sample +size of the Imager image you will be creating, not the sample size in +the source, eg. if the source has 32-bit samples this should be +C<"float"> since Imager doesn't have 32-bit/sample images. + +=back + =back =head1 TYPE SPECIFIC INFORMATION diff --git a/limits.c b/limits.c index f7a74841..c0292549 100644 --- a/limits.c +++ b/limits.c @@ -157,7 +157,7 @@ i_int_check_image_file_limits(i_img_dim width, i_img_dim height, int channels, s } if (height <= 0) { - i_push_errorf(0, "file size limit - image height %" i_DF " is not positive", + i_push_errorf(0, "file size limit - image height of %" i_DF " is not positive", i_DFc(height)); return 0; } diff --git a/t/t1000files.t b/t/t1000files.t index cfad2c8e..22cbdf0a 100644 --- a/t/t1000files.t +++ b/t/t1000files.t @@ -4,7 +4,7 @@ # the file format use strict; -use Test::More tests => 67; +use Test::More tests => 85; use Imager; -d "testout" or mkdir "testout"; @@ -60,6 +60,37 @@ ok(Imager->set_file_limits(height=>150, bytes=>10000), "set height and bytes"); is_deeply([ Imager->get_file_limits() ], [ 100, 150, 10000 ], "check all values now set"); +ok(Imager->check_file_limits(width => 100, height => 30), + "check 100 x 30 (def channels, sample_size) ok") + or diag(Imager->errstr); +ok(Imager->check_file_limits(width => 100, height => 100, channels => 1), + "check 100 x 100 x 1 (def sample_size) ok") + or diag(Imager->errstr); +ok(Imager->check_file_limits(width => 100, height => 100, channels => 1), + "check 100 x 100 x 1 (def sample_size) ok") + or diag(Imager->errstr); +ok(!Imager->check_file_limits(width => 100, height => 100, channels => 1, sample_size => "float"), + "check 100 x 100 x 1 x float should fail"); +ok(!Imager->check_file_limits(width => 100, height => 100, channels => 0), + "0 channels should fail"); +is(Imager->errstr, "file size limit - channels 0 out of range", + "check error message"); +ok(!Imager->check_file_limits(width => 0, height => 100), + "0 width should fail"); +is(Imager->errstr, "file size limit - image width of 0 is not positive", + "check error message"); +ok(!Imager->check_file_limits(width => 100, height => 0), + "0 height should fail"); +is(Imager->errstr, "file size limit - image height of 0 is not positive", + "check error message"); +ok(!Imager->check_file_limits(width => 10, height => 10, sample_size => 0), + "0 sample_size should fail"); +is(Imager->errstr, "file size limit - sample_size 0 out of range", + "check error message"); +ok(!Imager->check_file_limits(width => 10, height => 10, sample_size => 1000), + "1000 sample_size should fail"); +is(Imager->errstr, "file size limit - sample_size 1000 out of range", + "check error message"); ok(Imager->set_file_limits(reset=>1, height => 99), "set height and reset"); is_deeply([ Imager->get_file_limits() ], [ 0, 99, 0x40000000 ], @@ -69,6 +100,16 @@ ok(Imager->set_file_limits(reset=>1), is_deeply([ Imager->get_file_limits() ], [ 0, 0, 0x40000000 ], "check all are reset"); +# bad parameters +is_deeply([ Imager->check_file_limits() ], [], + "missing size paramaters"); +is(Imager->errstr, "check_file_limits: width must be defined", + "check message"); +is_deeply([ Imager->check_file_limits(width => 100.5) ], [], + "non-integer parameter"); +is(Imager->errstr, "check_file_limits: width must be a positive integer", + "check message"); + # test error handling for loading file handers { # first, no module at all