[dia] vdx: use embedded image rather than temporary file for image



commit 1a5fac587bfa054c578b04ba09bc48662f3e5780
Author: Hans Breuer <hans breuer org>
Date:   Sun Jun 26 12:21:23 2011 +0200

    vdx: use embedded image rather than temporary file for image
    
    With embedded images supported by Dia it is not necessary anymore to
    convert Base64 to a temporary file. No more unsafe tempnam(), too.
    
    Don't try to g_free() a constant string for old_file="".

 objects/standard/image.c  |    4 +-
 plug-ins/vdx/vdx-import.c |  142 +++++++++++++++------------------------------
 plug-ins/vdx/vdx.h        |    3 -
 3 files changed, 50 insertions(+), 99 deletions(-)
---
diff --git a/objects/standard/image.c b/objects/standard/image.c
index 1591880..66fe7f5 100644
--- a/objects/standard/image.c
+++ b/objects/standard/image.c
@@ -191,7 +191,7 @@ image_set_props(Image *image, GPtrArray *props)
 {
   struct stat st;
   time_t mtime = 0;
-  char *old_file = image->file ? g_strdup(image->file) : "";
+  char *old_file = image->file ? g_strdup(image->file) : NULL;
   const GdkPixbuf *old_pixbuf = dia_image_pixbuf (image->image);
   gboolean was_inline = image->inline_data;
 
@@ -228,7 +228,7 @@ image_set_props(Image *image, GPtrArray *props)
     if (was_inline && !image->inline_data)
       /* if saving fails we keep it inline */
       image->inline_data = !dia_image_save (image->image, image->file);
-  } else if (image->file && (strcmp(image->file, old_file) != 0 || image->mtime != mtime)) {
+  } else if (image->file && ((old_file && strcmp(image->file, old_file) != 0) || image->mtime != mtime)) {
     Element *elem = &image->element;
     DiaImage *img = NULL;
 
diff --git a/plug-ins/vdx/vdx-import.c b/plug-ins/vdx/vdx-import.c
index d3c5a63..ad975b3 100644
--- a/plug-ins/vdx/vdx-import.c
+++ b/plug-ins/vdx/vdx-import.c
@@ -1967,53 +1967,47 @@ plot_nurbs(const struct vdx_Geom *Geom, const struct vdx_XForm *XForm,
     return newobj;
 }
 
-/** Converts Base64 data to binary and writes to file
- * @param filename file to write
+/** Convert Base64 to pixbuf
  * @param b64 Base64 encoded data
  */
-
-static void
-write_base64_file(const char *filename, const char *b64)
+static GdkPixbuf *
+pixbuf_create_from_base64 (const char *b64)
 {
-#define BUF_SIZE 4096
-    FILE *f;
-    const gchar *in = b64;
-    guchar buf[BUF_SIZE];
+  /* see lib/prop_pixbuf.c(data_pixbuf) for a very similiar implementation */
+  GdkPixbuf *pixbuf = NULL;
+  GdkPixbufLoader *loader;
+  GError *error = NULL;
+
+  loader = gdk_pixbuf_loader_new ();
+  if (loader) {
     gint state = 0;
     guint save = 0;
-    gssize len;
-
-    if (!filename || !b64)
-    {
-        g_debug("write_base64_file() called with null parameters");
-        return;
-    }
-
-    f = g_fopen(filename, "w+b");
-    if (!f)
-    {
-        message_error(_("Couldn't write file %s"), filename);
-        return;
-    }
-
-    len = strlen (b64);
-    do
-    {
-        gsize ret = g_base64_decode_step (in,
-					  len > BUF_SIZE ? BUF_SIZE : len,
-					  buf, &state, &save);
-	if (fwrite (buf, sizeof(guchar), ret, f) != ret)
-	{
-	    message_error(_("Couldn't write file %s"), filename); 
-	    break;
-	}
-	in += BUF_SIZE;
-	len -= BUF_SIZE;
-    }
-    while (len > 0);
-
-    fclose(f);
-#undef BUF_SIZE
+#   define BUF_SIZE 4096
+    guchar buf[BUF_SIZE];
+    gchar *in = (gchar *)b64; /* direct access, not involving another xmlStrDup/xmlFree */
+    gssize len = strlen (b64);
+	
+    do {
+      gsize step = g_base64_decode_step (in,
+					 len > BUF_SIZE ? BUF_SIZE : len,
+					 buf, &state, &save);
+      if (!gdk_pixbuf_loader_write (loader, buf, step, &error))
+	break;
+
+      in += BUF_SIZE;
+      len -= BUF_SIZE;
+    } while (len > 0);
+    if (gdk_pixbuf_loader_close (loader, error ? NULL : &error)) {
+      pixbuf = g_object_ref (gdk_pixbuf_loader_get_pixbuf (loader));
+    } else {
+      message_warning (_("Failed to load image form diagram:\n%s"), error->message);
+      g_error_free (error);
+    }
+
+    g_object_unref (loader);
+  }
+  return pixbuf;
+# undef BUF_SIZE
 }
 
 /** Plots a bitmap
@@ -2035,16 +2029,11 @@ plot_image(const struct vdx_Geom *Geom, const struct vdx_XForm *XForm,
 
     Point p;
     float h, w;
-    static char *image_dir = 0;
 
     GSList *item;
     struct vdx_any *Any;
     struct vdx_text *text;
     const char *base64_data = 0;
-    static unsigned int file_counter = 0;
-    char suffix[5];
-    int i;
-    char *filename;
 
     *more = 0;
     /* We can only take a few formats */
@@ -2053,7 +2042,7 @@ plot_image(const struct vdx_Geom *Geom, const struct vdx_XForm *XForm,
         if (ForeignData->ForeignType &&
             !strcmp(ForeignData->ForeignType, "Bitmap"))
         {
-            strcpy(suffix, "BMP");
+            /* BMP */
         }
         else
         {
@@ -2063,48 +2052,6 @@ plot_image(const struct vdx_Geom *Geom, const struct vdx_XForm *XForm,
             return 0;
         }
     }
-    else
-    {
-        if (strcmp(ForeignData->CompressionType, "GIF") &&
-            strcmp(ForeignData->CompressionType, "JPEG") &&
-            strcmp(ForeignData->CompressionType, "PNG") &&
-            strcmp(ForeignData->CompressionType, "TIFF"))
-        {
-            message_error(_("Couldn't handle foreign object type %s"),
-                          ForeignData->CompressionType);
-            return 0;
-        }
-        strcpy(suffix, ForeignData->CompressionType);
-    }
-
-    /* Create the filename for the embedded object */
-
-    file_counter++;
-    for (i=0; suffix[i]; i++)
-    {
-        suffix[i] = tolower(suffix[i]);
-    }
-
-    if (!image_dir)
-    {
-        /* Security: don't trust tempnam to be unique, but use it as a
-           directory name. If the mkdir succeeds, we can't be subject
-           to a symlink attack (assuming /tmp is sticky) */
-        /* Functional: Dia includes bitmaps by reference, and we're
-           putting these bitmaps in a temporary location, so they'll be lost
-           on reboot. We could write them to the directory the file came
-           from or the current directory - both are problematic */
-        image_dir = (char *)tempnam(0, "dia");
-        if (!image_dir) return 0;
-        if (g_mkdir(image_dir, 0700))
-        {
-            message_error(_("Couldn't make object directory %s"), image_dir);
-            return 0;
-        }
-    }
-    filename = g_new(char, strlen(image_dir) + strlen(suffix) + 10);
-    sprintf(filename, "%s/%d.%s", image_dir, file_counter, suffix);
-    g_debug("Writing file %s", filename);
 
     /* Find the data in Base64 encoding in the body of ForeignData */
     for (item = ForeignData->any.children; item; item = item->next)
@@ -2118,8 +2065,6 @@ plot_image(const struct vdx_Geom *Geom, const struct vdx_XForm *XForm,
         }
     }
 
-    write_base64_file(filename, base64_data);
-
     /* Positioning data */
     p.x = Foreign->ImgOffsetX;
     p.y = Foreign->ImgOffsetY;
@@ -2130,9 +2075,18 @@ plot_image(const struct vdx_Geom *Geom, const struct vdx_XForm *XForm,
     /* Visio supplies bottom left, but Dia needs top left */
     p.y -= h;
 
-    newobj = create_standard_image(p.x, p.y, w, h, filename);
+    newobj = create_standard_image(p.x, p.y, w, h, NULL);
+    {
+	GPtrArray *props = g_ptr_array_new ();
+	PixbufProperty *prop = (PixbufProperty *)make_new_prop ("pixbuf", PROP_TYPE_PIXBUF, PROP_FLAG_DONT_SAVE);
 
-    g_free(filename);
+	/* In error prop->pixbuf is NULL, aka. broken image */
+	prop->pixbuf = pixbuf_create_from_base64 (base64_data);
+	g_ptr_array_add (props, prop);
+
+	newobj->ops->set_props(newobj, props);
+	prop_list_free(props);
+    }
     return newobj;
 }
 
diff --git a/plug-ins/vdx/vdx.h b/plug-ins/vdx/vdx.h
index faac1a6..1cff131 100644
--- a/plug-ins/vdx/vdx.h
+++ b/plug-ins/vdx/vdx.h
@@ -92,7 +92,4 @@ vdx_write_object(FILE *file, unsigned int depth, const void *p);
 const char *
 vdx_convert_xml_string(const char *s);
 
-char *
-tempnam(const char *dir, const char *pfx);
-
 #endif



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]