From ea449e9970004c5088452f1e847c7c4f6102936c Mon Sep 17 00:00:00 2001
From: Simeon Keske <git@n0emis.eu>
Date: Mon, 14 Sep 2020 02:20:21 +0200
Subject: [PATCH] initial commit

---
 .gitignore      |   3 +
 Makefile        |  51 +++++++++++++++++
 image.h         | 142 ++++++++++++++++++++++++++++++++++++++++++++++++
 imlib2_common.h | 128 +++++++++++++++++++++++++++++++++++++++++++
 loader.h        |  14 +++++
 loader_gpg.c    |  65 ++++++++++++++++++++++
 6 files changed, 403 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 Makefile
 create mode 100644 image.h
 create mode 100644 imlib2_common.h
 create mode 100644 loader.h
 create mode 100644 loader_gpg.c

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e3531ad
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+*.d
+*.o
+*.so
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..bdd97c3
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,51 @@
+TARGET = gpg.so
+MAJOR  = 1
+MINOR  = 1
+PATCH  = 1
+
+OPTS    := -O2
+CFLAGS  := -std=c99 $(OPTS) $(shell imlib2-config --cflags) -fPIC -Wall
+LDFLAGS := $(shell imlib2-config --libs)
+
+SRC = $(wildcard *.c)
+OBJ = $(foreach obj, $(SRC:.c=.o), $(notdir $(obj)))
+DEP = $(SRC:.c=.d)
+
+LIBDIR    ?= $(shell pkg-config --variable=libdir imlib2)
+LOADERDIR ?= $(LIBDIR)/imlib2/loaders/
+
+version = $(MAJOR).$(MINOR).$(PATCH)
+CFLAGS += -DVERSION="\"$(version)\""
+
+#commit = $(shell ./hash.sh)
+ifneq ($(commit), UNKNOWN)
+	CFLAGS += -DCOMMIT="\"$(commit)\""
+endif
+
+ifndef DISABLE_DEBUG
+	CFLAGS += -ggdb
+endif
+
+.PHONY: all clean install
+
+all: $(TARGET)
+
+$(TARGET): $(OBJ)
+	$(CC) -shared -o $@ $^ $(LDFLAGS)
+
+%.o: %.c
+	$(CC) -Wp,-MMD,$*.d -c $(CFLAGS) -o $@ $<
+
+clean:
+	rm $(DEP)
+	rm $(OBJ)
+	rm $(TARGET)
+
+install:
+	install -d $(DESTDIR)$(LOADERDIR)
+	install -s -m 444 gpg.so $(DESTDIR)$(LOADERDIR)
+
+uninstall:
+	rm $(LOADERDIR)/$(TARGET)
+
+-include $(DEP)
diff --git a/image.h b/image.h
new file mode 100644
index 0000000..5040db8
--- /dev/null
+++ b/image.h
@@ -0,0 +1,142 @@
+#ifndef __IMAGE
+#define __IMAGE 1
+
+#include "imlib2_common.h"
+#ifdef BUILD_X11
+#include <X11/Xlib.h>
+#else
+#ifndef X_DISPLAY_MISSING
+#define X_DISPLAY_MISSING
+#endif
+#endif
+
+typedef struct _imlibldctx ImlibLdCtx;
+
+#ifdef BUILD_X11
+typedef struct _imlibimagepixmap ImlibImagePixmap;
+#endif
+typedef struct _imlibloader ImlibLoader;
+typedef enum _imlib_load_error ImlibLoadError;
+
+typedef int         (*ImlibProgressFunction)(ImlibImage * im, char percent,
+                                             int update_x, int update_y,
+                                             int update_w, int update_h);
+typedef void        (*ImlibDataDestructorFunction)(ImlibImage * im, void *data);
+typedef void       *(*ImlibImageDataMemoryFunction)(void *, size_t size);
+
+#ifdef BUILD_X11
+struct _imlibimagepixmap {
+   int                 w, h;
+   Pixmap              pixmap, mask;
+   Display            *display;
+   Visual             *visual;
+   int                 depth;
+   int                 source_x, source_y, source_w, source_h;
+   Colormap            colormap;
+   char                antialias, hi_quality, dither_mask;
+   ImlibBorder         border;
+   ImlibImage         *image;
+   char               *file;
+   char                dirty;
+   int                 references;
+   DATABIG             modification_count;
+   ImlibImagePixmap   *next;
+};
+#endif
+
+void                __imlib_LoadAllLoaders(void);
+void                __imlib_RemoveAllLoaders(void);
+ImlibLoader       **__imlib_GetLoaderList(void);
+ImlibLoader        *__imlib_FindBestLoaderForFile(const char *file,
+                                                  int for_save);
+ImlibLoader        *__imlib_FindBestLoaderForFormat(const char *format,
+                                                    int for_save);
+ImlibLoader        *__imlib_FindBestLoaderForFileFormat(const char *file,
+                                                        const char *format,
+                                                        int for_save);
+void                __imlib_LoaderSetFormats(ImlibLoader * l,
+                                             const char *const *fmt,
+                                             unsigned int num);
+
+ImlibImage         *__imlib_CreateImage(int w, int h, DATA32 * data);
+ImlibImage         *__imlib_LoadImage(const char *file, FILE * fp,
+                                      ImlibProgressFunction progress,
+                                      char progress_granularity,
+                                      char immediate_load, char dont_cache,
+                                      ImlibLoadError * er);
+int                 __imlib_LoadEmbedded(ImlibLoader * l, ImlibImage * im,
+                                         const char *file, int load_data);
+int                 __imlib_LoadImageData(ImlibImage * im);
+void                __imlib_DirtyImage(ImlibImage * im);
+void                __imlib_FreeImage(ImlibImage * im);
+void                __imlib_SaveImage(ImlibImage * im, const char *file,
+                                      ImlibProgressFunction progress,
+                                      char progress_granularity,
+                                      ImlibLoadError * er);
+
+DATA32             *__imlib_AllocateData(ImlibImage * im);
+void                __imlib_FreeData(ImlibImage * im);
+void                __imlib_ReplaceData(ImlibImage * im, DATA32 * new_data);
+
+void                __imlib_LoadProgressSetPass(ImlibImage * im,
+                                                int pass, int n_pass);
+int                 __imlib_LoadProgress(ImlibImage * im,
+                                         int x, int y, int w, int h);
+int                 __imlib_LoadProgressRows(ImlibImage * im,
+                                             int row, int nrows);
+
+#ifdef BUILD_X11
+ImlibImagePixmap   *__imlib_ProduceImagePixmap(void);
+void                __imlib_ConsumeImagePixmap(ImlibImagePixmap * ip);
+ImlibImagePixmap   *__imlib_FindCachedImagePixmap(ImlibImage * im, int w, int h,
+                                                  Display * d, Visual * v,
+                                                  int depth, int sx, int sy,
+                                                  int sw, int sh, Colormap cm,
+                                                  char aa, char hiq, char dmask,
+                                                  DATABIG modification_count);
+ImlibImagePixmap   *__imlib_FindCachedImagePixmapByID(Display * d, Pixmap p);
+void                __imlib_AddImagePixmapToCache(ImlibImagePixmap * ip);
+void                __imlib_RemoveImagePixmapFromCache(ImlibImagePixmap * ip);
+void                __imlib_CleanupImagePixmapCache(void);
+
+ImlibImagePixmap   *__imlib_FindImlibImagePixmapByID(Display * d, Pixmap p);
+void                __imlib_FreePixmap(Display * d, Pixmap p);
+void                __imlib_DirtyPixmapsForImage(ImlibImage * im);
+#endif
+
+void                __imlib_AttachTag(ImlibImage * im, const char *key,
+                                      int val, void *data,
+                                      ImlibDataDestructorFunction destructor);
+void                __imlib_FreeTag(ImlibImage * im, ImlibImageTag * t);
+void                __imlib_FreeAllTags(ImlibImage * im);
+
+void                __imlib_SetCacheSize(int size);
+int                 __imlib_GetCacheSize(void);
+int                 __imlib_CurrentCacheSize(void);
+
+#define IMAGE_HAS_ALPHA(im) ((im)->flags & F_HAS_ALPHA)
+#define IMAGE_IS_UNLOADED(im) ((im)->flags & F_UNLOADED)
+#define IMAGE_IS_UNCACHEABLE(im) ((im)->flags & F_UNCACHEABLE)
+#define IMAGE_ALWAYS_CHECK_DISK(im) ((im)->flags & F_ALWAYS_CHECK_DISK)
+#define IMAGE_IS_VALID(im) (!((im)->flags & F_INVALID))
+#define IMAGE_FREE_DATA(im) (!((im)->flags & F_DONT_FREE_DATA))
+
+#define SET_FLAG(flags, f) ((flags) |= (f))
+#define UNSET_FLAG(flags, f) ((flags) &= (~f))
+
+#define LOAD_FAIL       0
+#define LOAD_SUCCESS    1
+#define LOAD_BREAK      2
+
+/* 32767 is the maximum pixmap dimension and ensures that
+ * (w * h * sizeof(DATA32)) won't exceed ULONG_MAX */
+#define X_MAX_DIM 32767
+/* NB! The image dimensions are sometimes used in (dim << 16) like expressions
+ * so great care must be taken if ever it is attempted to change this
+ * condition */
+
+#define IMAGE_DIMENSIONS_OK(w, h) \
+   ( ((w) > 0) && ((h) > 0) && ((w) <= X_MAX_DIM) && ((h) <= X_MAX_DIM) )
+
+#endif
+
diff --git a/imlib2_common.h b/imlib2_common.h
new file mode 100644
index 0000000..ea44e01
--- /dev/null
+++ b/imlib2_common.h
@@ -0,0 +1,128 @@
+#ifndef _IMLIB2_COMMON_H_
+#define _IMLIB2_COMMON_H_
+
+/* most of this file comes directly from imlib2 source code */
+
+#include <stdio.h>
+#include <Imlib2.h>
+
+#define UNSET_FLAGS(flags, f) ((flags) &= ~(f))
+#define SET_FLAGS(flags, f) ((flags) |= (f))
+
+typedef struct _imlibimage              ImlibImage;
+typedef struct _imlibldctx ImlibLdCtx;
+# ifdef BUILD_X11
+typedef struct _imlibimagepixmap        ImlibImagePixmap;
+# endif
+typedef struct _imlibborder             ImlibBorder;
+typedef struct _imlibloader             ImlibLoader;
+typedef struct _imlibimagetag           ImlibImageTag;
+
+typedef int (*ImlibProgressFunction)(ImlibImage *im, char percent,
+                                     int update_x, int update_y,
+                                     int update_w, int update_h);
+typedef void       *(*ImlibImageDataMemoryFunction)(void *, size_t size);
+typedef void (*ImlibDataDestructorFunction)(ImlibImage *im, void *data);
+
+enum _iflags
+{
+   F_NONE              = 0,
+   F_HAS_ALPHA         = (1 << 0),
+   F_UNLOADED          = (1 << 1),
+   F_UNCACHEABLE       = (1 << 2),
+   F_ALWAYS_CHECK_DISK = (1 << 3),
+   F_INVALID           = (1 << 4),
+   F_DONT_FREE_DATA    = (1 << 5),
+   F_FORMAT_IRRELEVANT = (1 << 6),
+   F_BORDER_IRRELEVANT = (1 << 7),
+   F_ALPHA_IRRELEVANT  = (1 << 8)
+};
+
+typedef enum   _iflags                  ImlibImageFlags;
+
+struct _imlibborder
+{
+   int left, right, top, bottom;
+};
+
+struct _imlibimagetag
+{
+   char           *key;
+   int             val;
+   void           *data;
+   void          (*destructor)(ImlibImage *im, void *data);
+   ImlibImageTag  *next;
+};
+
+struct _imlibimage {
+   char               *file;
+   int                 w, h;
+   DATA32             *data;
+   ImlibImageFlags     flags;
+   time_t              moddate;
+   ImlibBorder         border;
+   int                 references;
+   ImlibLoader        *loader;
+   char               *format;
+   ImlibImage         *next;
+   ImlibImageTag      *tags;
+   char               *real_file;
+   char               *key;
+   ImlibImageDataMemoryFunction data_memory_func;
+   ImlibLdCtx         *lc;
+   FILE               *fp;
+};
+
+# ifdef BUILD_X11
+struct _imlibimagepixmap
+{
+   int               w, h;
+   Pixmap            pixmap, mask;
+   Display          *display;
+   Visual           *visual;
+   int               depth;
+   int               source_x, source_y, source_w, source_h;
+   Colormap          colormap;
+   char              antialias, hi_quality, dither_mask;
+   ImlibBorder       border;
+   ImlibImage       *image;
+   char             *file;
+   char              dirty;
+   int               references;
+   DATABIG           modification_count;
+   ImlibImagePixmap *next;
+};
+# endif
+
+struct _imlibloader
+{
+   char         *file;
+   int           num_formats;
+   char        **formats;
+   void         *handle;
+   char        (*load)(ImlibImage *im,
+                       ImlibProgressFunction progress,
+                       char progress_granularity, char immediate_load);
+   char        (*save)(ImlibImage *im,
+                       ImlibProgressFunction progress,
+                       char progress_granularity);
+   ImlibLoader  *next;
+};
+
+# define IMAGE_HAS_ALPHA(im) ((im)->flags & F_HAS_ALPHA)
+# define IMAGE_IS_UNLOADED(im) ((im)->flags & F_UNLOADED)
+# define IMAGE_IS_UNCACHEABLE(im) ((im)->flags & F_UNCACHEABLE)
+# define IMAGE_ALWAYS_CHECK_DISK(im) ((im)->flags & F_ALWAYS_CHECK_DISK)
+# define IMAGE_IS_VALID(im) (!((im)->flags & F_INVALID))
+# define IMAGE_FREE_DATA(im) (!((im)->flags & F_DONT_FREE_DATA))
+
+# define SET_FLAG(flags, f) ((flags) |= (f))
+# define UNSET_FLAG(flags, f) ((flags) &= (~f))
+
+# define IMAGE_DIMENSIONS_OK(w, h) \
+   ( ((w) > 0) && ((h) > 0) && \
+     ((unsigned long long)(w) * (unsigned long long)(h) <= (1ULL << 29) - 1) )
+
+EAPI ImlibImageTag *__imlib_GetTag(ImlibImage *im, const char *key);
+
+#endif /* _IMLIB2_COMMON_H_ */
diff --git a/loader.h b/loader.h
new file mode 100644
index 0000000..7255aab
--- /dev/null
+++ b/loader.h
@@ -0,0 +1,14 @@
+#ifndef __LOADER_H
+#define __LOADER_H 1
+
+#include "imlib2_common.h"
+#include "image.h"
+
+EAPI char     load(ImlibImage * im, ImlibProgressFunction progress,
+                         char progress_granularity, char load_data);
+EAPI int      load2(ImlibImage * im, int load_data);
+EAPI char     save(ImlibImage * im, ImlibProgressFunction progress,
+                         char progress_granularity);
+EAPI void     formats(ImlibLoader * l);
+
+#endif /* __LOADER_H */
diff --git a/loader_gpg.c b/loader_gpg.c
new file mode 100644
index 0000000..fa64cf8
--- /dev/null
+++ b/loader_gpg.c
@@ -0,0 +1,65 @@
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <Imlib2.h>
+
+#include "imlib2_common.h"
+#include "loader.h"
+
+int
+load2(ImlibImage * im, int load_data)
+{
+   ImlibLoader        *loader;
+   int                 res;
+   const char         *s, *p, *q;
+   char                tmp[] = "/tmp/imlib2_loader_gpg-XXXXXX";
+   char               *real_ext, *dest;
+
+   /* make sure this file ends in ".pgp" and that there's another ext
+    * (e.g. "foo.png.pgp") */
+   for (p = s = im->real_file, q = NULL; *s; s++)
+     {
+        if (*s != '.' && *s != '/')
+           continue;
+        q = p;
+        p = s + 1;
+     }
+   if (!q || strcasecmp(p, "pgp"))
+      return 0;
+
+   if (!(real_ext = strndup(q, p - q - 1)))
+      return 0;
+
+   loader = __imlib_FindBestLoaderForFormat("jpg", 0);
+   if (!loader)
+      return 0;
+
+   dest = mkstemp(tmp);
+   close(dest);
+
+   char result[500]; 
+   strcpy(result, "gpg --decrypt --quiet ");
+   strcat(result, im->real_file);
+   strcat(result, " > ");
+   strcat(result, tmp);
+
+   system(result);
+
+   res = __imlib_LoadEmbedded(loader, im, tmp, load_data);
+
+ quit:
+   unlink(tmp);
+
+   return res;
+}
+
+void
+formats(ImlibLoader * l)
+{
+   static const char  *const list_formats[] = { "pgp" };
+   __imlib_LoaderSetFormats(l, list_formats,
+                            sizeof(list_formats) / sizeof(char *));
+}