db-move: moved linux-zen from [testing] to [extra] (x86_64)
[arch-packages.git] / feh / trunk / 0001-libmagic.patch
blobb7d9e3cad3813cd1a076f868c3abace3bec5f3c1
1 From 4affafe91579799efd83f4c8e05c291eeb684c9c Mon Sep 17 00:00:00 2001
2 From: Christian Hesse <mail@eworm.de>
3 Date: Wed, 5 Jan 2022 14:35:15 +0100
4 Subject: [PATCH 1/3] use libmagic to detect valid file formats
6 Writing our own magic bytes detection is prone to errors and an
7 everlasting catch-up-game. Let's use libmagic to get things right,
8 this is less code and makes things more reliable.
10 Building without libmagic is still possible. That will make the code
11 act like specifying FEH_SKIP_MAGIC=1, effectively passing everything
12 to imlib2.
13 ---
14 README.md | 2 +
15 config.mk | 6 +++
16 src/imlib.c | 134 ++++++++++++++++++++--------------------------------
17 3 files changed, 59 insertions(+), 83 deletions(-)
19 diff --git a/README.md b/README.md
20 index 4401af2..c4cb7ef 100644
21 --- a/README.md
22 +++ b/README.md
23 @@ -22,6 +22,7 @@ Dependencies
25 * Imlib2
26 * libcurl (disable with make curl=0)
27 + * libmagic (disable with make magic=0)
28 * libpng
29 * libX11
30 * libXinerama (disable with make xinerama=0)
31 @@ -91,6 +92,7 @@ indicates that the corresponding feature is enabled by default.
32 | help | 0 | include help text (refers to the manpage otherwise) |
33 | inotify | 0 | enable inotify, needed for `--auto-reload` |
34 | stat64 | 0 | Support CIFS shares from 64bit hosts on 32bit machines |
35 +| magic | 1 | Build against libmagic to filter unsupported file formats |
36 | mkstemps | 1 | Whether your libc provides `mkstemps()`. If set to 0, feh will be unable to load gif images via libcurl |
37 | verscmp | 1 | Whether your libc provides `strvercmp()`. If set to 0, feh will use an internal implementation. |
38 | xinerama | 1 | Support Xinerama/XRandR multiscreen setups |
39 diff --git a/config.mk b/config.mk
40 index 2d63f72..910eac7 100644
41 --- a/config.mk
42 +++ b/config.mk
43 @@ -6,6 +6,7 @@ curl ?= 1
44 debug ?= 0
45 exif ?= 0
46 help ?= 0
47 +magic ?= 1
48 mkstemps ?= 1
49 verscmp ?= 1
50 xinerama ?= 1
51 @@ -68,6 +69,11 @@ ifeq (${mkstemps},1)
52 CFLAGS += -DHAVE_MKSTEMPS
53 endif
55 +ifeq (${magic},1)
56 + CFLAGS += -DHAVE_LIBMAGIC
57 + LDLIBS += -lmagic
58 +endif
60 ifeq (${verscmp},1)
61 CFLAGS += -DHAVE_STRVERSCMP
62 endif
63 diff --git a/src/imlib.c b/src/imlib.c
64 index 6d709a2..70d459f 100644
65 --- a/src/imlib.c
66 +++ b/src/imlib.c
67 @@ -44,6 +44,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
68 #include "exif.h"
69 #endif
71 +#ifdef HAVE_LIBMAGIC
72 +#include <magic.h>
73 +#endif
75 Display *disp = NULL;
76 Visual *vis = NULL;
77 Screen *scr = NULL;
78 @@ -242,98 +246,62 @@ void feh_print_load_error(char *file, winwidget w, Imlib_Load_Error err, enum fe
79 * avoid calling Imlib2 for files it probably cannot handle. See
80 * <https://phab.enlightenment.org/T8739> and
81 * <https://github.com/derf/feh/issues/505>.
82 - *
83 - * Note that this drops support for bz2-compressed files, unless
84 - * FEH_SKIP_MAGIC is set
86 int feh_is_image(feh_file * file)
88 - unsigned char buf[16];
89 - FILE *fh = fopen(file->filename, "r");
90 - if (!fh) {
91 - return 0;
92 - }
93 - // Files smaller than buf will be padded with zeroes
94 - memset(buf, 0, sizeof(buf));
95 - if (fread(buf, 1, 16, fh) <= 0) {
96 - fclose(fh);
97 - return 0;
98 - }
99 - fclose(fh);
100 +#ifdef HAVE_LIBMAGIC
101 + magic_t magic;
102 + const char * mime_type;
103 + int is_image = 0;
105 - if (buf[0] == 0xff && buf[1] == 0xd8) {
106 - // JPEG
107 - return 1;
109 - if (!memcmp(buf, "\x89PNG\x0d\x0a\x1a\x0a", 8)) {
110 - // PNG
111 - return 1;
113 - if (buf[0] == 'A' && buf[1] == 'R' && buf[2] == 'G' && buf[3] == 'B') {
114 - // ARGB
115 - return 1;
117 - if (buf[0] == 'B' && buf[1] == 'M') {
118 - // BMP
119 - return 1;
121 - if (!memcmp(buf, "farbfeld", 8)) {
122 - // farbfeld
123 - return 1;
125 - if (buf[0] == 'G' && buf[1] == 'I' && buf[2] == 'F') {
126 - // GIF
127 - return 1;
129 - if (buf[0] == 0x00 && buf[1] == 0x00 && buf[2] <= 0x02 && buf[3] == 0x00) {
130 - // ICO
131 - return 1;
133 - if (!memcmp(buf, "FORM", 4)) {
134 - // Amiga IFF ILBM
135 - return 1;
137 - if (buf[0] == 'P' && buf[1] >= '1' && buf[1] <= '7') {
138 - // PNM et al.
139 - return 1;
141 - if (strstr(file->filename, ".tga")) {
142 - // TGA
143 - return 1;
145 - if (!memcmp(buf, "II\x2a\x00", 4) || !memcmp(buf, "MM\x00\x2a", 4)) {
146 - // TIFF
147 - return 1;
149 - if (!memcmp(buf, "RIFF", 4)) {
150 - // might be webp
151 - return 1;
153 - if (!memcmp(buf + 4, "ftyphei", 7) || !memcmp(buf + 4, "ftypmif1", 8)) {
154 - // HEIC/HEIF - note that this is only supported in imlib2-heic. Ordinary
155 - // imlib2 releases do not support heic/heif images as of 2021-01.
156 - return 1;
158 - if ((buf[0] == 0xff && buf[1] == 0x0a) || !memcmp(buf, "\x00\x00\x00\x0cJXL \x0d\x0a\x87\x0a", 12)) {
159 - // JXL - note that this is only supported in imlib2-jxl. Ordinary
160 - // imlib2 releases do not support JXL images as of 2021-06.
161 + if (getenv("FEH_SKIP_MAGIC")) {
162 return 1;
164 - buf[15] = 0;
165 - if (strstr((char *)buf, "XPM")) {
166 - // XPM
167 - return 1;
169 + if (!(magic = magic_open(MAGIC_MIME_TYPE | MAGIC_SYMLINK))) {
170 + weprintf("unable to initialize magic library\n");
171 + return 0;
173 - if (strstr(file->filename, ".bz2") || strstr(file->filename, ".gz")) {
174 - // Imlib2 supports compressed images. It relies on the filename to
175 - // determine the appropriate loader and does not use magic bytes here.
176 - return 1;
178 + if (magic_load(magic, NULL) != 0) {
179 + weprintf("cannot load magic database: %s\n", magic_error(magic));
180 + magic_close(magic);
181 + return 0;
183 - // moved to the end as this variable won't be set in most cases
184 - if (getenv("FEH_SKIP_MAGIC")) {
185 - return 1;
187 + mime_type = magic_file(magic, file->filename);
189 + if (mime_type) {
190 + D(("file %s has mime type: %s\n", file->filename, mime_type));
192 + if (strncmp(mime_type, "image/", 6) == 0) {
193 + is_image = 1;
196 + /* imlib2 supports loading compressed images, let's have a look inside */
197 + if (strcmp(mime_type, "application/gzip") == 0 ||
198 + strcmp(mime_type, "application/x-bzip2") == 0 ||
199 + strcmp(mime_type, "application/x-xz") == 0) {
200 + magic_setflags(magic, magic_getflags(magic) | MAGIC_COMPRESS);
201 + mime_type = magic_file(magic, file->filename);
203 + if (mime_type) {
204 + D(("uncompressed file %s has mime type: %s\n", file->filename, mime_type));
206 + if (strncmp(mime_type, "image/", 6) == 0) {
207 + is_image = 1;
212 - return 0;
214 + magic_close(magic);
216 + return is_image;
217 +#else
218 + (void)file;
219 + return 1;
220 +#endif
223 int feh_load_image(Imlib_Image * im, feh_file * file)
225 2.35.1
228 From facb67f8438aa8ef18ffacdccfd0a2d1c2730e5c Mon Sep 17 00:00:00 2001
229 From: Christian Hesse <mail@eworm.de>
230 Date: Wed, 12 Jan 2022 09:53:15 +0100
231 Subject: [PATCH 2/3] global initialization for libmagic
233 Add a global `magic_t magic` and initialize it just once.
235 Also `feh_is_image()` now calls itself to check compressed files, saving
236 some duplicate code.
238 src/feh.h | 4 +++
239 src/imlib.c | 94 ++++++++++++++++++++++++++++++-----------------------
240 src/main.c | 8 +++++
241 3 files changed, 66 insertions(+), 40 deletions(-)
243 diff --git a/src/feh.h b/src/feh.h
244 index 007c7c5..9afe238 100644
245 --- a/src/feh.h
246 +++ b/src/feh.h
247 @@ -145,6 +145,10 @@ void init_slideshow_mode(void);
248 void init_list_mode(void);
249 void init_loadables_mode(void);
250 void init_unloadables_mode(void);
251 +#ifdef HAVE_LIBMAGIC
252 +void uninit_magic(void);
253 +void init_magic(void);
254 +#endif
255 void feh_clean_exit(void);
256 int feh_should_ignore_image(Imlib_Image * im);
257 int feh_load_image(Imlib_Image * im, feh_file * file);
258 diff --git a/src/imlib.c b/src/imlib.c
259 index 70d459f..0accbdc 100644
260 --- a/src/imlib.c
261 +++ b/src/imlib.c
262 @@ -46,6 +46,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
264 #ifdef HAVE_LIBMAGIC
265 #include <magic.h>
267 +magic_t magic = NULL;
268 #endif
270 Display *disp = NULL;
271 @@ -239,6 +241,33 @@ void feh_print_load_error(char *file, winwidget w, Imlib_Load_Error err, enum fe
275 +#ifdef HAVE_LIBMAGIC
276 +void uninit_magic(void)
278 + if (!magic) {
279 + return;
282 + magic_close(magic);
283 + magic = NULL;
285 +void init_magic(void)
287 + if (getenv("FEH_SKIP_MAGIC")) {
288 + return;
291 + if (!(magic = magic_open(MAGIC_NONE))) {
292 + weprintf("unable to initialize magic library\n");
293 + return;
296 + if (magic_load(magic, NULL) != 0) {
297 + weprintf("cannot load magic database: %s\n", magic_error(magic));
298 + uninit_magic();
303 * This is a workaround for an Imlib2 regression, causing unloadable image
304 * detection to be excessively slow (and, thus, causing feh to hang for a while
305 @@ -247,62 +276,47 @@ void feh_print_load_error(char *file, winwidget w, Imlib_Load_Error err, enum fe
306 * <https://phab.enlightenment.org/T8739> and
307 * <https://github.com/derf/feh/issues/505>.
309 -int feh_is_image(feh_file * file)
310 +int feh_is_image(feh_file * file, int magic_flags)
312 -#ifdef HAVE_LIBMAGIC
313 - magic_t magic;
314 - const char * mime_type;
315 - int is_image = 0;
316 + const char * mime_type = NULL;
318 - if (getenv("FEH_SKIP_MAGIC")) {
319 + if (!magic) {
320 return 1;
323 - if (!(magic = magic_open(MAGIC_MIME_TYPE | MAGIC_SYMLINK))) {
324 - weprintf("unable to initialize magic library\n");
325 - return 0;
327 + magic_setflags(magic, MAGIC_MIME_TYPE | MAGIC_SYMLINK | magic_flags);
328 + mime_type = magic_file(magic, file->filename);
330 - if (magic_load(magic, NULL) != 0) {
331 - weprintf("cannot load magic database: %s\n", magic_error(magic));
332 - magic_close(magic);
333 + if (!mime_type) {
334 return 0;
337 - mime_type = magic_file(magic, file->filename);
339 - if (mime_type) {
340 - D(("file %s has mime type: %s\n", file->filename, mime_type));
342 - if (strncmp(mime_type, "image/", 6) == 0) {
343 - is_image = 1;
346 - /* imlib2 supports loading compressed images, let's have a look inside */
347 - if (strcmp(mime_type, "application/gzip") == 0 ||
348 - strcmp(mime_type, "application/x-bzip2") == 0 ||
349 - strcmp(mime_type, "application/x-xz") == 0) {
350 - magic_setflags(magic, magic_getflags(magic) | MAGIC_COMPRESS);
351 - mime_type = magic_file(magic, file->filename);
352 + D(("file %s has mime type: %s\n", file->filename, mime_type));
354 - if (mime_type) {
355 - D(("uncompressed file %s has mime type: %s\n", file->filename, mime_type));
356 + if (strncmp(mime_type, "image/", 6) == 0) {
357 + return 1;
360 - if (strncmp(mime_type, "image/", 6) == 0) {
361 - is_image = 1;
365 + /* no infinite loop on compressed content, please */
366 + if (magic_flags) {
367 + return 0;
370 - magic_close(magic);
371 + /* imlib2 supports loading compressed images, let's have a look inside */
372 + if (strcmp(mime_type, "application/gzip") == 0 ||
373 + strcmp(mime_type, "application/x-bzip2") == 0 ||
374 + strcmp(mime_type, "application/x-xz") == 0) {
375 + return feh_is_image(file, MAGIC_COMPRESS);
378 - return is_image;
379 + return 0;
381 #else
382 - (void)file;
383 +int feh_is_image(__attribute__((unused)) feh_file * file, __attribute__((unused)) int magic_flags)
385 return 1;
386 -#endif
388 +#endif
390 int feh_load_image(Imlib_Image * im, feh_file * file)
392 @@ -326,7 +340,7 @@ int feh_load_image(Imlib_Image * im, feh_file * file)
395 else {
396 - if (feh_is_image(file)) {
397 + if (feh_is_image(file, 0)) {
398 *im = imlib_load_image_with_error_return(file->filename, &err);
399 } else {
400 feh_err = LOAD_ERROR_MAGICBYTES;
401 diff --git a/src/main.c b/src/main.c
402 index 3d124fd..34b667a 100644
403 --- a/src/main.c
404 +++ b/src/main.c
405 @@ -69,6 +69,10 @@ int main(int argc, char **argv)
406 #endif
409 +#ifdef HAVE_LIBMAGIC
410 + init_magic();
411 +#endif
413 feh_event_init();
415 if (opt.index)
416 @@ -262,6 +266,10 @@ void feh_clean_exit(void)
417 if(disp)
418 XCloseDisplay(disp);
420 +#ifdef HAVE_LIBMAGIC
421 + uninit_magic();
422 +#endif
425 * Only restore the old terminal settings if
426 * - we changed them in the first place
428 2.35.1
431 From 26cd770c8732a4467e57cf3e7a5d4c2518836275 Mon Sep 17 00:00:00 2001
432 From: Daniel Friesel <derf@finalrewind.org>
433 Date: Thu, 10 Feb 2022 21:41:35 +0100
434 Subject: [PATCH 3/3] Run init_magic before init_parse_options
436 init_parse_options calls feh_prepare_filelist, which in turn calls
437 feh_file_info_preload if opt.preload is set. This function will load all
438 images in the filelist to determine their attributes, so we need to initialize
439 libmagic before calling init_parse_options.
441 src/main.c | 9 +++++----
442 1 file changed, 5 insertions(+), 4 deletions(-)
444 diff --git a/src/main.c b/src/main.c
445 index 34b667a..85e0504 100644
446 --- a/src/main.c
447 +++ b/src/main.c
448 @@ -49,6 +49,11 @@ int main(int argc, char **argv)
449 srandom(getpid() * time(NULL) % ((unsigned int) -1));
451 setup_signal_handlers();
453 +#ifdef HAVE_LIBMAGIC
454 + init_magic();
455 +#endif
457 init_parse_options(argc, argv);
459 init_imlib_fonts();
460 @@ -69,10 +74,6 @@ int main(int argc, char **argv)
461 #endif
464 -#ifdef HAVE_LIBMAGIC
465 - init_magic();
466 -#endif
468 feh_event_init();
470 if (opt.index)