[dia] Fix relative path handling with Windows root directories



commit a9d2f0fa1a2af6ee2c9a6006b3af91517f6cb7b1
Author: Hans Breuer <hans breuer org>
Date:   Sun Dec 14 17:56:10 2014 +0100

    Fix relative path handling with Windows root directories
    
    We have do deal with the special meaning of Windows drives, where 'c:' is
    a reference to the current directory, but c:\ is the root path. For other
    directory names the trailing backslash is stripped by g_path_get_dirname().
    
    Bug reported on the mailing list:
    https://mail.gnome.org/archives/dia-list/2014-November/msg00045.html

 lib/dia_dirs.c                   |   11 +++-
 objects/Misc/diagram_as_object.c |    2 +-
 objects/standard/image.c         |  125 ++++++--------------------------------
 3 files changed, 30 insertions(+), 108 deletions(-)
---
diff --git a/lib/dia_dirs.c b/lib/dia_dirs.c
index c0672f7..99e8590 100644
--- a/lib/dia_dirs.c
+++ b/lib/dia_dirs.c
@@ -338,9 +338,16 @@ dia_relativize_filename (const gchar *master, const gchar *slave)
   bp1 = g_path_get_dirname (master);
   bp2 = g_path_get_dirname (slave);
 
-  if (g_str_has_prefix (bp1, bp2)) {
+  /* the slave path has to be included in master to become relative */
+  if (g_str_has_prefix (bp2, bp1)) {
     gchar *p;
-    rel = g_strdup (slave + strlen (bp1) + 1);
+    /* We have do deal with the special meaning of Windows drives, where 'c:' is
+     * a reference to the current directory, but c:\ is the root path. For other
+     * directory names the trailing backslash is stripped by g_path_get_dirname().
+     * So only advance (+1) in slave when there is no trailing backslash.
+     */
+    rel = g_strdup (slave + strlen (bp1)
+                         + (g_str_has_suffix (bp1, G_DIR_SEPARATOR_S) ? 0 : 1));
     /* flip backslashes */
     for (p = rel; *p != '\0'; p++)
       if (*p == '\\') *p = '/';    
diff --git a/objects/Misc/diagram_as_object.c b/objects/Misc/diagram_as_object.c
index 4516211..0a030ff 100644
--- a/objects/Misc/diagram_as_object.c
+++ b/objects/Misc/diagram_as_object.c
@@ -395,7 +395,7 @@ _dae_save (DiaObject *obj, ObjectNode obj_node, DiaContext *ctx)
     gchar *dirname = g_path_get_dirname (dia_context_get_filename (ctx));
     if (strstr (dae->filename, dirname) == dae->filename) {
       saved_path = dae->filename;
-      dae->filename += (strlen (dirname) + 1);
+      dae->filename += (strlen (dirname) + g_str_has_suffix (dirname, G_DIR_SEPARATOR_S) ? 0 : 1);
     }
     g_free (dirname);
   }
diff --git a/objects/standard/image.c b/objects/standard/image.c
index 843cf8a..a2d556f 100644
--- a/objects/standard/image.c
+++ b/objects/standard/image.c
@@ -37,6 +37,7 @@
 #include "dia_image.h"
 #include "message.h"
 #include "properties.h"
+#include "dia_dirs.h"
 
 #include "tool-icons.h"
 
@@ -689,41 +690,9 @@ image_copy(Image *image)
   return &newimage->element.object;
 }
 
-/* Gets the directory path of a filename.
-   Uses current working directory if filename is a relative pathname.
-   Examples:
-     /some/dir/file.gif => /some/dir
-     dir/file.gif => /cwd/dir
-   
-*/
-static char *
-get_directory(const char *filename) 
-{
-  char *cwd;
-  char *directory;
-  char *dirname;
-  
-  if (filename==NULL)
-    return NULL;
-
-  dirname = g_path_get_dirname(filename);
-  if (g_path_is_absolute(dirname)) {
-      directory = g_build_path(G_DIR_SEPARATOR_S, dirname, NULL);
-  } else {
-      cwd = g_get_current_dir();
-      directory = g_build_path(G_DIR_SEPARATOR_S, cwd, dirname, NULL);
-      g_free(cwd);
-  }
-  g_free(dirname);
-
-  return directory;
-}
-
 static void
 image_save(Image *image, ObjectNode obj_node, DiaContext *ctx)
 {
-  char *diafile_dir;
-  
   element_save(&image->element, obj_node, ctx);
 
   if (image->border_width != 0.1)
@@ -750,22 +719,14 @@ image_save(Image *image, ObjectNode obj_node, DiaContext *ctx)
     data_add_real(new_attribute(obj_node, "angle"), image->angle, ctx);
 
   if (image->file != NULL) {
-    if (g_path_is_absolute(image->file)) { /* Absolute pathname */
-      diafile_dir = get_directory(dia_context_get_filename (ctx));
-
-      if (diafile_dir && strncmp(diafile_dir, image->file, strlen(diafile_dir))==0) {
-       /* The image pathname has the dia file pathname in the begining */
-       /* Save the relative path: */
-       data_add_filename(new_attribute(obj_node, "file"),
-                         image->file + strlen(diafile_dir) + 1, ctx);
-      } else {
-       /* Save the absolute path: */
-       data_add_filename(new_attribute(obj_node, "file"), image->file, ctx);
-      }
-      g_free(diafile_dir);
+    gchar *relative = dia_relativize_filename (dia_context_get_filename (ctx), image->file);
+
+    if (relative) {
+      /* The image pathname has the diagram file pathname in the beginning */
+      data_add_filename(new_attribute(obj_node, "file"), relative, ctx);
+      g_free (relative);
     } else {
-      /* Relative path. Must be an erronuous filename...
-        Just save the filename. */
+      /* Save the absolute path: */
       data_add_filename(new_attribute(obj_node, "file"), image->file, ctx);
     }
   }
@@ -857,74 +818,28 @@ image_load(ObjectNode obj_node, int version, DiaContext *ctx)
   image->image = NULL;
   
   if (strcmp(image->file, "")!=0) {
-    diafile_dir = get_directory(dia_context_get_filename(ctx));
-
-    if (g_path_is_absolute(image->file)) { /* Absolute pathname */
+    if (   g_path_is_absolute (image->file)
+       && g_file_test (image->file, G_FILE_TEST_IS_REGULAR)) { /* Absolute pathname */
       image->image = dia_image_load(image->file);
-      if (image->image == NULL) {
-       /* Not found as abs path, try in same dir as diagram. */
-       char *temp_string;
-       const char *image_file_name = image->file;
-       const char *psep;
-
-       psep = strrchr(image->file, G_DIR_SEPARATOR);
-       /* try the other G_OS as well */
-       if (!psep)
-         psep =  strrchr(image->file, G_DIR_SEPARATOR == '/' ? '\\' : '/');
-       if (psep)
-         image_file_name = psep + 1;
-
-       temp_string = g_build_filename(diafile_dir, image_file_name, NULL);
-
-       image->image = dia_image_load(temp_string);
-
-       if (image->image != NULL) {
-         /* Found file in same dir as diagram. */
-         message_warning(_("The image file '%s' was not found in the specified directory.\n"
-                         "Using the file '%s' instead.\n"), image->file, temp_string);
-         g_free(image->file);
-         image->file = temp_string;
-       } else {
-         g_free(temp_string);
-         
-         image->image = dia_image_load((char *)image_file_name);
-         if (image->image != NULL) {
-           char *tmp;
-           /* Found file in current dir. */
-           message_warning(_("The image file '%s' was not found in the specified directory.\n"
-                           "Using the file '%s' instead.\n"), image->file, image_file_name);
-           tmp = image->file;
-           image->file = g_strdup(image_file_name);
-           g_free(tmp);
-         } else {
-           message_warning(_("The image file '%s' was not found.\n"),
-                           image_file_name);
-         }
-       }
-      }
-    } else { /* Relative pathname: */
-      char *temp_string;
-
-      temp_string = g_build_filename (diafile_dir, image->file, NULL);
-
-      image->image = dia_image_load(temp_string);
+    } else { /* build from relative pathname */
+      gchar *image_filename = dia_absolutize_filename (dia_context_get_filename (ctx), image->file);
 
+      image->image = dia_image_load(image_filename);
       if (image->image != NULL) {
-       /* Found file in same dir as diagram. */
+       /* Found file in same directory as diagram. */
        g_free(image->file);
-       image->file = temp_string;
+       image->file = image_filename;
       } else {
-       g_free(temp_string);
-         
+       /* not found as relative path, try literally */
+       g_free (image_filename);
+
        image->image = dia_image_load(image->file);
        if (image->image == NULL) {
-         /* Didn't find file in current dir. */
-         message_warning(_("The image file '%s' was not found.\n"),
-                         image->file);
+         /* Didn't find file in current directory. */
+         dia_context_add_message (ctx, _("The image file '%s' was not found.\n"), image->file);
        }
       }
     }
-    g_free(diafile_dir);
   }
   /* if we don't have an image yet try to recover it from inlined data */
   if (!image->image) {


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