Re: ImageMagick for SVG and other image types?: Pseudo Code
John Gaffney <jgaffney-W1WbbPd4oPN/W2okNb46yti2O/[email protected]>
| Newsgroups | gmane.comp.web.dillo.devel |
|---|---|
| Message-ID | <[email protected]> |
I was going to attempt a sort of proof-of-concept patch, and still
include a mix of code and pseudo-code below, but see that a change
would be required in the way a_Misc_get_content_type_from_data() (in
src/misc.[hc]) is called from elsewhere in Dillo -- but this would not
require much change, since, as far as I can see,
a_Misc_get_content_type_from_data() is called from only two places in
the rest of the source code. The problem is that the data being
parsed is from a Dstr, but only the str and the value of the len
members of this Dstr are passed to
a_Misc_get_content_type_from_data(), so that the Dstr is not
modifiable. If a pointer to the Dstr were passed instead, it would be
modifiable, which would then allow for conversion of image types other
than GIF, PNG, and JPG to be converted to PNG for the purposes of
display by replacing the original Dstr data with the data for the
converted image. (This would mean that Dillo would be using and
caching the PNG into which the original image was converted, rather
than the original, but this is only proposed as an interim means of at
least displaying other, currently unsupported, image types.)
In a mix of code and pseudo-code:
Along with the configure.ac block to use the Magick++-config utility to test for
the Magick++ library and its version and to set the corresponding compiler and
linker flags, and a call in main() to Magick::InitializeMagick(NULL),
replace the current src/misc.c block starting at line 161
} else if (Size >= 2 && !strncmp(p, "\xff\xd8", 2)) {
/* JPEG has the first 2 bytes set to 0xffd8 in BigEndian - looking
* at the character representation should be machine independent. */
Type = DT_IMAGE_JPG;
st = 0;
/* Text */
} else {
/* Heuristic for "text/plain"
... */
with something like
} else if (Size >= 2 && !strncmp(p, "\xff\xd8", 2)) {
/* JPEG has the first 2 bytes set to 0xffd8 in BigEndian - looking
* at the character representation should be machine independent. */
Type = DT_IMAGE_JPG;
st = 0;
} else if (ConvertImage(ModifiablePtrToData, & DataLen)) {
Type = DT_IMAGE_PNG;
st = 0;
/* Text */
} else {
/* Heuristic for "text/plain"
... */
and adding to src/misc.h
#include "miscconv.hh"
with two new files: a header miscconv.hh with
#ifndef __MISCCONV_HH__
#define __MISCCONV_HH__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdlib.h>
int ConvertImage (void *, size_t *);
#ifdef __cplusplus
}
#endif
#endif
and, for the source file miscconv.cc, something like
#include "miscconv.hh"
#include <Magick++.h>
extern "C" int ConvertImage ( char * Data, size_t * Size ) {
try {
Magick :: Blob blob ( Data, Size ), PngBlob;
// This ctor will throw an exception if Data is not image data:
Magick :: Image image ( blob );
// From the magic used by the `file' command, it seems that identifying SVG
// data by its magic would be pretty involved, and as far as I can tell
// there is no way in Magick++ to check the type of the image data
// (including whether it is image data to begin with) without constructing
// an Image -- which, if the data is any kind of image recognized by
// ImageMagick, seems automatically to convert the image to some internal
// format. And in consequence it seems that any security policies, such as
// limits on image sizes or types, would have to be set via the local
// ImageMagick policy (in the ImageMagick policy.xml in /etc or the like).
// Now that the Image has been constructed, if desired its native type can be
// determined by, e.g., Image::format(). Otherwise, one can
// just proceed with the conversion of images of any format.
// The following call could also throw an exception:
image . write ( & PngBlob, "PNG");
// And now we just need to rewire things for the converted image:
Code here to deallocate Data, allocate a new pointer according to PngBlob.length(),
replace Data with the new pointer, and copy PngBlob.data() to it.
}
catch ( Magick :: Exception & e ) {
// The ImageMagick docs cover the rather wide array of possible warnings and
// errors, and a MSG could be crafted from these, but for the present purposes
// any exception means the failure to return a displayable PNG.
Code to do whatever with e.what() ...
return 0;
}
return 1;
}
John Gaffney <[email protected]> writes:
> At this point Dillo supports the display of GIF, PNG, and JPG, but SVG
> is used heavily by sites like, for example, Wikipedia. Has the
> Magick++ library in ImageMagick been considered for supporting these
> other image formats? The FLTK people seem enthusiastic about the
> Imago library in spite of its alpha state of development; librsvg,
> which looks, at least to my untutored eye, like it requires a fair
> amount of voodoo to use, is apparently no longer actively supported
> and would at any rate only provide SVG support; but ImageMagick is
> pretty standard with Linux distributions, and the Magick++ interface
> makes conversions from any format to PNG for the purposes of display
> extremely easy. In src/misc.c, at the end of the image part of the
> else-if ladder in a_Misc_get_content_type_from_data(), one could add
> another "rung" that uses Data and Size to create a Magick::Blob, and
> from this a Magick::Image, then use Magick::Image.write() to write
> this to another Magick::Blob of type PNG, and then replace Data and
> Size with those of the resulting Magick::Blob. A try-catch block
> would catch the cases where Data is not an image. Altogether this
> sort of "cheat" would require very few lines of code to implement.
> And the Magick++-config utility could supply the needed -D..., -I...,
> -l... flags to the configure script.
>
> I'm not suggesting this is an ideal long-term solution, but in the
> interim would at least allow the display of other image types.
>
> The most recent mention of this on the mailing list seems to be
> Jorge's indication on 22 April 2016 that
>
> No, there's no SVG image support in dillo yet.
>
> It should not be hard to implement though, but it needs an effort
> similar to GIF or PNG or JPEG code. Patch welcomed! ;)
>
> But surely someone has thought of ImageMagick before. Are there
> objections to using it? And if so, maybe a flag could be set by the
> configure script to conditionally compile this in for those who want
> it? (If this is pursued, the configure script should probably also
> check that the version of ImageMagick is recent enough to have been
> patched against that serious exploit in just this sort of conversion
> code.)
>
> A test program shows that the invocation of ImageMagick and
> conversions really are as simple as the steps outlined above. But I
> would be happy to make an attempt at a patch, if you don't mind this
> being undertaken by an amateur.
>
>
> _______________________________________________
> Dillo-dev mailing list
> [email protected]
> http://lists.dillo.org/cgi-bin/mailman/listinfo/dillo-dev
_______________________________________________
Dillo-dev mailing list
[email protected]
http://lists.dillo.org/cgi-bin/mailman/listinfo/dillo-dev