diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/feh.h | 4 | ||||
| -rw-r--r-- | src/imlib.c | 146 | ||||
| -rw-r--r-- | src/main.c | 9 | 
3 files changed, 77 insertions, 82 deletions
| @@ -145,6 +145,10 @@ void init_slideshow_mode(void);  void init_list_mode(void);  void init_loadables_mode(void);  void init_unloadables_mode(void); +#ifdef HAVE_LIBMAGIC +void uninit_magic(void); +void init_magic(void); +#endif  void feh_clean_exit(void);  int feh_should_ignore_image(Imlib_Image * im);  int feh_load_image(Imlib_Image * im, feh_file * file); diff --git a/src/imlib.c b/src/imlib.c index 6d709a2..0accbdc 100644 --- a/src/imlib.c +++ b/src/imlib.c @@ -44,6 +44,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  #include "exif.h"  #endif +#ifdef HAVE_LIBMAGIC +#include <magic.h> + +magic_t magic = NULL; +#endif +  Display *disp = NULL;  Visual *vis = NULL;  Screen *scr = NULL; @@ -235,6 +241,33 @@ void feh_print_load_error(char *file, winwidget w, Imlib_Load_Error err, enum fe  	}  } +#ifdef HAVE_LIBMAGIC +void uninit_magic(void) +{ +	if (!magic) { +		return; +	} + +	magic_close(magic); +	magic = NULL; +} +void init_magic(void) +{ +	if (getenv("FEH_SKIP_MAGIC")) { +		return; +	} + +	if (!(magic = magic_open(MAGIC_NONE))) { +		weprintf("unable to initialize magic library\n"); +		return; +	} + +	if (magic_load(magic, NULL) != 0) { +		weprintf("cannot load magic database: %s\n", magic_error(magic)); +		uninit_magic(); +	} +} +  /*   * This is a workaround for an Imlib2 regression, causing unloadable image   * detection to be excessively slow (and, thus, causing feh to hang for a while @@ -242,99 +275,48 @@ void feh_print_load_error(char *file, winwidget w, Imlib_Load_Error err, enum fe   * avoid calling Imlib2 for files it probably cannot handle. See   * <https://phab.enlightenment.org/T8739> and   * <https://github.com/derf/feh/issues/505>. - * - * Note that this drops support for bz2-compressed files, unless - * FEH_SKIP_MAGIC is set   */ -int feh_is_image(feh_file * file) +int feh_is_image(feh_file * file, int magic_flags)  { -	unsigned char buf[16]; -	FILE *fh = fopen(file->filename, "r"); -	if (!fh) { -		return 0; -	} -	// Files smaller than buf will be padded with zeroes -	memset(buf, 0, sizeof(buf)); -	if (fread(buf, 1, 16, fh) <= 0) { -		fclose(fh); -		return 0; -	} -	fclose(fh); +	const char * mime_type = NULL; -	if (buf[0] == 0xff && buf[1] == 0xd8) { -		// JPEG -		return 1; -	} -	if (!memcmp(buf, "\x89PNG\x0d\x0a\x1a\x0a", 8)) { -		// PNG -		return 1; -	} -	if (buf[0] == 'A' && buf[1] == 'R' && buf[2] == 'G' && buf[3] == 'B') { -		// ARGB -		return 1; -	} -	if (buf[0] == 'B' && buf[1] == 'M') { -		// BMP -		return 1; -	} -	if (!memcmp(buf, "farbfeld", 8)) { -		// farbfeld -		return 1; -	} -	if (buf[0] == 'G' && buf[1] == 'I' && buf[2] == 'F') { -		// GIF -		return 1; -	} -	if (buf[0] == 0x00 && buf[1] == 0x00 && buf[2] <= 0x02 && buf[3] == 0x00) { -		// ICO -		return 1; -	} -	if (!memcmp(buf, "FORM", 4)) { -		// Amiga IFF ILBM -		return 1; -	} -	if (buf[0] == 'P' && buf[1] >= '1' && buf[1] <= '7') { -		// PNM et al. -		return 1; -	} -	if (strstr(file->filename, ".tga")) { -		// TGA -		return 1; -	} -	if (!memcmp(buf, "II\x2a\x00", 4) || !memcmp(buf, "MM\x00\x2a", 4)) { -		// TIFF -		return 1; -	} -	if (!memcmp(buf, "RIFF", 4)) { -		// might be webp -		return 1; -	} -	if (!memcmp(buf + 4, "ftyphei", 7) || !memcmp(buf + 4, "ftypmif1", 8)) { -		// HEIC/HEIF - note that this is only supported in imlib2-heic. Ordinary -		// imlib2 releases do not support heic/heif images as of 2021-01. +	if (!magic) {  		return 1;  	} -	if ((buf[0] == 0xff && buf[1] == 0x0a) || !memcmp(buf, "\x00\x00\x00\x0cJXL \x0d\x0a\x87\x0a", 12)) { -		// JXL - note that this is only supported in imlib2-jxl. Ordinary -		// imlib2 releases do not support JXL images as of 2021-06. -		return 1; + +	magic_setflags(magic, MAGIC_MIME_TYPE | MAGIC_SYMLINK | magic_flags); +	mime_type = magic_file(magic, file->filename); + +	if (!mime_type) { +		return 0;  	} -	buf[15] = 0; -	if (strstr((char *)buf, "XPM")) { -		// XPM + +	D(("file %s has mime type: %s\n", file->filename, mime_type)); + +	if (strncmp(mime_type, "image/", 6) == 0) {  		return 1;  	} -	if (strstr(file->filename, ".bz2") || strstr(file->filename, ".gz")) { -		// Imlib2 supports compressed images. It relies on the filename to -		// determine the appropriate loader and does not use magic bytes here. -		return 1; + +	/* no infinite loop on compressed content, please */ +	if (magic_flags) { +		return 0;  	} -	// moved to the end as this variable won't be set in most cases -	if (getenv("FEH_SKIP_MAGIC")) { -		return 1; + +	/* imlib2 supports loading compressed images, let's have a look inside */ +	if (strcmp(mime_type, "application/gzip") == 0 || +	    strcmp(mime_type, "application/x-bzip2") == 0 || +	    strcmp(mime_type, "application/x-xz") == 0) { +		return feh_is_image(file, MAGIC_COMPRESS);  	} +  	return 0;  } +#else +int feh_is_image(__attribute__((unused)) feh_file * file, __attribute__((unused)) int magic_flags) +{ +	return 1; +} +#endif  int feh_load_image(Imlib_Image * im, feh_file * file)  { @@ -358,7 +340,7 @@ int feh_load_image(Imlib_Image * im, feh_file * file)  		}  	}  	else { -		if (feh_is_image(file)) { +		if (feh_is_image(file, 0)) {  			*im = imlib_load_image_with_error_return(file->filename, &err);  		} else {  			feh_err = LOAD_ERROR_MAGICBYTES; @@ -49,6 +49,11 @@ int main(int argc, char **argv)  	srandom(getpid() * time(NULL) % ((unsigned int) -1));  	setup_signal_handlers(); + +#ifdef HAVE_LIBMAGIC +	init_magic(); +#endif +  	init_parse_options(argc, argv);  	init_imlib_fonts(); @@ -262,6 +267,10 @@ void feh_clean_exit(void)  	if(disp)  		XCloseDisplay(disp); +#ifdef HAVE_LIBMAGIC +	uninit_magic(); +#endif +  	/*  	 * Only restore the old terminal settings if  	 * - we changed them in the first place | 
