ImageMagick for SVG and other image types?
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.
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 <jgaffney at lawrenceville.org> 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 Dillo-dev at dillo.org http://lists.dillo.org/cgi-bin/mailman/listinfo/dillo-dev
participants (1)
-
jgaffney@lawrenceville.org