[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Validating an Image file is an image file

John Joyce

7/18/2007 2:26:00 PM

I know how to validate a file based only on the file name dot
extension, but this seems wholly insecure to me.
I feel that just testing for .jpg, .png, .jpeg, .gif, etc... is not
enough.
Clearly renaming a file to anything at all is easy to do.
How can I read into the file and check to see if it is is actually a
file of a given image type? Is there file header info to look for ?
Such as a particular byte sequence at a particular location in the file?


John Joyce

17 Answers

Xavier Noria

7/18/2007 2:30:00 PM

0

El Jul 18, 2007, a las 4:25 PM, John Joyce escribió:

> I know how to validate a file based only on the file name dot
> extension, but this seems wholly insecure to me.
> I feel that just testing for .jpg, .png, .jpeg, .gif, etc... is not
> enough.
> Clearly renaming a file to anything at all is easy to do.
> How can I read into the file and check to see if it is is actually
> a file of a given image type? Is there file header info to look for ?

The canonical solution is to delegate to this library:

http://grub.ath.cx/...

-- fxn


John Joyce

7/18/2007 4:21:00 PM

0


On Jul 18, 2007, at 9:33 AM, Wayne E. Seguin wrote:

> On Jul 18, 2007, at 10:25 , John Joyce wrote:
>> I know how to validate a file based only on the file name dot
>> extension, but this seems wholly insecure to me.
>> I feel that just testing for .jpg, .png, .jpeg, .gif, etc... is
>> not enough.
>> Clearly renaming a file to anything at all is easy to do.
>> How can I read into the file and check to see if it is is actually
>> a file of a given image type? Is there file header info to look for ?
>> Such as a particular byte sequence at a particular location in the
>> file?
>>
>>
>> John Joyce
>
> Use the unix file command `file #{file_name}`
>
> example:
>
> > file the.gif
> the.gif: GIF image data, version 89a, 91 x 91
>
> --
> Wayne E. Seguin
> Sr. Systems Architect & Systems Admin
> wayneseguin@gmail.com
>
>
>
The file command and bindings to it are OK, but results are not
consistent across common image file types. What's worse is that the
code would be unportable. Ideally, the solution would rely simply on
the file format internally and thus be portable.

Alex Young

7/18/2007 4:42:00 PM

0

John Joyce wrote:
>
> On Jul 18, 2007, at 9:33 AM, Wayne E. Seguin wrote:
>
>> On Jul 18, 2007, at 10:25 , John Joyce wrote:
>>> I know how to validate a file based only on the file name dot
>>> extension, but this seems wholly insecure to me.
>>> I feel that just testing for .jpg, .png, .jpeg, .gif, etc... is not
>>> enough.
>>> Clearly renaming a file to anything at all is easy to do.
>>> How can I read into the file and check to see if it is is actually a
>>> file of a given image type? Is there file header info to look for ?
>>> Such as a particular byte sequence at a particular location in the file?
>>>
>>>
>>> John Joyce
>>
>> Use the unix file command `file #{file_name}`
>>
>> example:
>>
>> > file the.gif
>> the.gif: GIF image data, version 89a, 91 x 91
>>
>> --
>> Wayne E. Seguin
>> Sr. Systems Architect & Systems Admin
>> wayneseguin@gmail.com
>>
>>
>>
> The file command and bindings to it are OK, but results are not
> consistent across common image file types. What's worse is that the
> code would be unportable. Ideally, the solution would rely simply on the
> file format internally and thus be portable.
>
If you know it's an image file, then ImageMagick's identify command will
probably do what you need, especially with the --verbose switch. I
think you get the same info from Magick::Image#inspect, if RMagick's an
option for you.

--
Alex

John Joyce

7/18/2007 4:48:00 PM

0

Well, looks like RMagick can do this for me.
For a minute I was starting to fear reading specs on formats, but
perhaps not.

John Joyce

Daniel Berger

7/18/2007 9:14:00 PM

0

On Jul 18, 10:20 am, John Joyce <dangerwillrobinsondan...@gmail.com>
wrote:

<snip>

> The file command and bindings to it are OK, but results are not
> consistent across common image file types. What's worse is that the
> code would be unportable. Ideally, the solution would rely simply on
> the file format internally and thus be portable.

How's this for a portable version? I based this on a 5 minute overview
of the Wikipedia content at http://en.wikipedia.org/wiki/Mag...(programming),
combined with some trial and error.

class File
def self.image?(file)
bmp?(file) || jpg?(file) || png?(file) || gif?(file)
end

def self.bmp?(file)
IO.read(file, 3) == "BM6" && File.extname(file).downcase ==
'.bmp'
end

def self.jpg?(file)
IO.read(file, 10) == "\377\330\377\340\000\020JFIF" &&
File.extname(file).downcase == '.jpg'
end

def self.png?(file)
IO.read(file, 4) == "\211PNG" && File.extname(file).downcase ==
'.png'
end

def self.gif?(file)
['GIF89a', 'GIF97a'].include?(IO.read(file, 6)) &&
File.extname(file).downcase == '.gif'
end
end

Regards,

Dan


John Joyce

7/18/2007 11:37:00 PM

0


On Jul 18, 2007, at 4:13 PM, Daniel Berger wrote:

> On Jul 18, 10:20 am, John Joyce <dangerwillrobinsondan...@gmail.com>
> wrote:
>
> <snip>
>
>> The file command and bindings to it are OK, but results are not
>> consistent across common image file types. What's worse is that the
>> code would be unportable. Ideally, the solution would rely simply on
>> the file format internally and thus be portable.
>
> How's this for a portable version? I based this on a 5 minute overview
> of the Wikipedia content at http://en.wikipedia...
> Magic_number_(programming),
> combined with some trial and error.
>
> class File
> def self.image?(file)
> bmp?(file) || jpg?(file) || png?(file) || gif?(file)
> end
>
> def self.bmp?(file)
> IO.read(file, 3) == "BM6" && File.extname(file).downcase ==
> '.bmp'
> end
>
> def self.jpg?(file)
> IO.read(file, 10) == "\377\330\377\340\000\020JFIF" &&
> File.extname(file).downcase == '.jpg'
> end
>
> def self.png?(file)
> IO.read(file, 4) == "\211PNG" && File.extname(file).downcase ==
> '.png'
> end
>
> def self.gif?(file)
> ['GIF89a', 'GIF97a'].include?(IO.read(file, 6)) &&
> File.extname(file).downcase == '.gif'
> end
> end
>
> Regards,
>
> Dan
>
>
Cool, Dan, that looks pretty slick. I certainly couldn't have done
that so quickly, but I knew what basically was needed. That looks
like about what I was thinking of conceptually. Very nice and clean
code! Nice touch with downcasing file extensions too! I hate that
cameras all like to upcase filenames... (> <)!
That will probably run a lot lighter than RMagick methods, I'll try
it out later. I've been fiddling with the RMagick API all afternoon.
There's a lot of documentation but some of it is lacking in clear
examples.
At this point I know how to scale images and keep the aspect ratio
within a maximum new size, but I'd like to have the final output be
square with matting on the sides for portrait orientation, matting on
the top and bottom for landscape orientation, either one with the
scaled image centered.
Will this require subsequent compositing after scaling? Or did I miss
a method somewhere in the docs that does all of this at once?

John Joyce

Tim Hunter

7/19/2007 12:29:00 AM

0

John Joyce wrote:
> Cool, Dan, that looks pretty slick. I certainly couldn't have done
> that so quickly, but I knew what basically was needed. That looks like
> about what I was thinking of conceptually. Very nice and clean code!
> Nice touch with downcasing file extensions too! I hate that cameras
> all like to upcase filenames... (> <)!
> That will probably run a lot lighter than RMagick methods, I'll try it
> out later. I've been fiddling with the RMagick API all afternoon.
> There's a lot of documentation but some of it is lacking in clear
> examples.
> At this point I know how to scale images and keep the aspect ratio
> within a maximum new size, but I'd like to have the final output be
> square with matting on the sides for portrait orientation, matting on
> the top and bottom for landscape orientation, either one with the
> scaled image centered.
> Will this require subsequent compositing after scaling? Or did I miss
> a method somewhere in the docs that does all of this at once?
>
> John Joyce
>
Yes, you'll need to composite the scaled image on top of the background
of your desired size. See my article "Alpha Compositing - Part 1"
[http://rmagick.rubyforge.org/src...]. If you're making a lot of
thumbnails you might also be interested in "Making Thumbnails with
RMagick" [http://rmagick.rubyforge.org/resizing-me...], which
compares the performance of all the RMagick resizing methods.

Also if you'll tell me which parts of the documentation are lacking in
clear examples I'll see what I can do to fix it. You can always open a
documentation bug in the RMagick bug tracker on RubyForge.

--
RMagick OS X Installer [http://rubyforge.org/project...]
RMagick Hints & Tips [http://rubyforge.org/forum/forum.php?for...]
RMagick Installation FAQ [http://rmagick.rubyforge.org/instal...]


John Joyce

7/19/2007 1:47:00 AM

0


On Jul 18, 2007, at 7:28 PM, Tim Hunter wrote:

> John Joyce wrote:
>> Cool, Dan, that looks pretty slick. I certainly couldn't have done
>> that so quickly, but I knew what basically was needed. That looks
>> like about what I was thinking of conceptually. Very nice and
>> clean code! Nice touch with downcasing file extensions too! I hate
>> that cameras all like to upcase filenames... (> <)!
>> That will probably run a lot lighter than RMagick methods, I'll
>> try it out later. I've been fiddling with the RMagick API all
>> afternoon. There's a lot of documentation but some of it is
>> lacking in clear examples.
>> At this point I know how to scale images and keep the aspect ratio
>> within a maximum new size, but I'd like to have the final output
>> be square with matting on the sides for portrait orientation,
>> matting on the top and bottom for landscape orientation, either
>> one with the scaled image centered.
>> Will this require subsequent compositing after scaling? Or did I
>> miss a method somewhere in the docs that does all of this at once?
>>
>> John Joyce
>>
> Yes, you'll need to composite the scaled image on top of the
> background of your desired size. See my article "Alpha Compositing
> - Part 1" [http://rmagick.rubyforge.org/src...]. If you're
> making a lot of thumbnails you might also be interested in "Making
> Thumbnails with RMagick" [http://rmagick.rubyforge.org...
> methods.html], which compares the performance of all the RMagick
> resizing methods.
>
> Also if you'll tell me which parts of the documentation are lacking
> in clear examples I'll see what I can do to fix it. You can always
> open a documentation bug in the RMagick bug tracker on RubyForge.
>
>
Also very cool. Thanks.
I will check that stuff out.
I guess it's just a bit much the first time looking at the API.
The main thing I found a bit vague was creating a new Image or
ImageList instance.
ImageList responds basically as I would expect, but Image doesn't .
Initially I was trying:
img = Image.read('redzigzag.jpg')
Which apparently creates something similar to ImageList.
But when trying to use Image methods, I kept getting an error
about ...private method ... called for ....[...]:array
(the elipses are just leaving out specifics)
What I didn't realize I was missing was the [0] in:
img = Image.read('redzigzag.jpg')[0]
I'm still not quite sure how that is working as part of that
statement really, but I know how to get it going anyway.
I can certainly see the convenience of using ImageList to batch a
bunch of images, but I figured that Image was fine for working out
the logic and flow of what I want to do first.

The only other truly confusing thing was lack of examples in many
method definitions. This is just me, I can "get it" faster when I
have a method definition and example with dummy data plugged in.

BTW, the RVG stuff looks pretty interesting. I didn't have time to
really dig deep into that so much, just skimming.

Overall, I especially like the simplicity of reading and writing
files with RMagick. I'm just glad I can do it with Ruby instead of
PHP, because Ruby is much easier for me to get a clear picture in my
mind of what I'm looking at.

Daniel Berger

7/19/2007 1:07:00 PM

0



On Jul 19, 5:05 am, "Raf Coremans" <rra...@gmail.com> wrote:
> 2007/7/18, Daniel Berger <djber...@gmail.com>:
> <snip>
>
> > def self.jpg?(file)
> > IO.read(file, 10) == "\377\330\377\340\000\020JFIF" &&
> > File.extname(file).downcase == '.jpg'
> > end
>
> Ack! The proper abbreviation, and thus also the filename extension, is
> 'jpeg'. 'jpg' is an abomination introduced by the same people who introduced
> the *shudder* '.htm' filename extension.

Be that as it may, you will see both extensions in practice. So, the
code should probably be refactored to be:

def self.jpeg?(file)
IO.read(file, 10) == "\377\330\377\340\000\020JFIF" && ['.jpg',
'.jpeg'].include?(File.extname(file).downcase)
end

alias jpg? jpeg?

Regards,

Dan


Daniel Berger

7/19/2007 2:11:00 PM

0



On Jul 19, 7:06 am, Daniel Berger <djber...@gmail.com> wrote:
> On Jul 19, 5:05 am, "Raf Coremans" <rra...@gmail.com> wrote:
>
> > 2007/7/18, Daniel Berger <djber...@gmail.com>:
> > <snip>
>
> > > def self.jpg?(file)
> > > IO.read(file, 10) == "\377\330\377\340\000\020JFIF" &&
> > > File.extname(file).downcase == '.jpg'
> > > end
>
> > Ack! The proper abbreviation, and thus also the filename extension, is
> > 'jpeg'. 'jpg' is an abomination introduced by the same people who introduced
> > the *shudder* '.htm' filename extension.
>
> Be that as it may, you will see both extensions in practice. So, the
> code should probably be refactored to be:
>
> def self.jpeg?(file)
> IO.read(file, 10) == "\377\330\377\340\000\020JFIF" && ['.jpg',
> '.jpeg'].include?(File.extname(file).downcase)
> end
>
> alias jpg? jpeg?

Whoops, that should be:

class << self
alias jpg? jpeg?
end

Regards,

Dan