[libgxps/wip/nacho/separator] parse-utils: instead of using GFile use paths and canonalize them



commit 5d570fe3fc9dddf147e292740eec4c4a00304c46
Author: Ignacio Casal Quinteiro <ignacio casal nice-software com>
Date:   Sun Jan 29 13:19:13 2017 +0100

    parse-utils: instead of using GFile use paths and canonalize them
    
    This takes the method from glib to canonalize the paths just
    that instead of using G_DIR_SEPARATOR it always uses / since
    we want / for all the platforms.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=777894

 libgxps/gxps-parse-utils.c |   99 ++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 92 insertions(+), 7 deletions(-)
---
diff --git a/libgxps/gxps-parse-utils.c b/libgxps/gxps-parse-utils.c
index 18dff53..311ebca 100644
--- a/libgxps/gxps-parse-utils.c
+++ b/libgxps/gxps-parse-utils.c
@@ -395,13 +395,100 @@ gxps_parse_skip_number (gchar      **iter,
         *iter = p;
 }
 
+/* NOTE: Taken from glocalfile. Because we always need to use / on all platforms */
+static char *
+canonicalize_filename (const char *filename)
+{
+       char *canon, *start, *p, *q;
+       char *cwd;
+       int i;
+
+       if (!g_path_is_absolute (filename)) {
+               cwd = g_get_current_dir ();
+               canon = g_build_path ("/", cwd, filename, NULL);
+               g_free (cwd);
+       } else
+               canon = g_strdup (filename);
+
+       start = (char *)g_path_skip_root (canon);
+
+       if (start == NULL) {
+               /* This shouldn't really happen, as g_get_current_dir() should
+                * return an absolute pathname, but bug 573843 shows this is
+                * not always happening
+                */
+               g_free (canon);
+               return g_build_path ("/", "/", filename, NULL);
+       }
+
+       /* POSIX allows double slashes at the start to
+        * mean something special (as does windows too).
+        * So, "//" != "/", but more than two slashes
+        * is treated as "/".
+        */
+       i = 0;
+       for (p = start - 1; (p >= canon) && G_IS_DIR_SEPARATOR (*p); p--)
+               i++;
+
+       if (i > 2) {
+               i -= 1;
+               start -= i;
+               memmove (start, start+i, strlen (start+i)+1);
+       }
+
+       /* Make sure we're using the canonical dir separator */
+       p++;
+       while (p < start && G_IS_DIR_SEPARATOR (*p))
+               *p++ = '/';
+
+       p = start;
+       while (*p != 0) {
+               if (p[0] == '.' && (p[1] == 0 || G_IS_DIR_SEPARATOR (p[1]))) {
+                       memmove (p, p+1, strlen (p+1)+1);
+               } else if (p[0] == '.' && p[1] == '.' && (p[2] == 0 || G_IS_DIR_SEPARATOR (p[2]))) {
+                       q = p + 2;
+                       /* Skip previous separator */
+                       p = p - 2;
+                       if (p < start)
+                               p = start;
+                       while (p > start && !G_IS_DIR_SEPARATOR (*p))
+                               p--;
+                       if (G_IS_DIR_SEPARATOR (*p))
+                               *p++ = '/';
+                       memmove (p, q, strlen (q)+1);
+               } else {
+                       /* Skip until next separator */
+                       while (*p != 0 && !G_IS_DIR_SEPARATOR (*p))
+                               p++;
+
+                       if (*p != 0) {
+                               /* Canonicalize one separator */
+                               *p++ = '/';
+                       }
+               }
+
+               /* Remove additional separators */
+               q = p;
+               while (*q && G_IS_DIR_SEPARATOR (*q))
+                       q++;
+
+               if (p != q)
+                       memmove (p, q, strlen (q)+1);
+       }
+
+       /* Remove trailing slashes */
+       if (p > start && G_IS_DIR_SEPARATOR (*(p-1)))
+               *(p-1) = 0;
+
+       return canon;
+}
+
 gchar *
 gxps_resolve_relative_path (const gchar *source,
                            const gchar *target)
 {
-       GFile *source_file;
-       GFile *abs_file;
        gchar *dirname;
+       gchar *abs_path;
        gchar *retval;
 
        if (target[0] == '/')
@@ -410,13 +497,11 @@ gxps_resolve_relative_path (const gchar *source,
        dirname = g_path_get_dirname (source);
        if (strlen (dirname) == 1 && dirname[0] == '.')
                dirname[0] = '/';
-       source_file = g_file_new_for_path (dirname);
+       abs_path = g_build_path ("/", dirname, target, NULL);
        g_free (dirname);
 
-       abs_file = g_file_resolve_relative_path (source_file, target);
-       retval = g_file_get_path (abs_file);
-       g_object_unref (abs_file);
-       g_object_unref (source_file);
+       retval = canonicalize_filename (abs_path);
+       g_free (abs_path);
 
        return retval;
 }


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