[patch] move eel-vfs-extensions into gnome-vfs



Hi,

Ok, so here's a patch that moves pretty much all the string URI
manipulation stuff from eel-vfs-extensions into gnome-vfs-utils.  Is
this ok to commit?

Thanks,
James



? gnome-vfs.patch
? gob
? network.vfolder-info.in
? stamp-h1
? doc/tmpl/gnome-vfs-unused.sgml
? doc/tmpl/gnome-vfs.sgml
? libgnomevfs/.gnome-vfs-file-info.c.swp
? libgnomevfs/.gnome-vfs-file-info.h.swp
? libgnomevfs/gnome-vfs-extensions.c
? libgnomevfs/gnome-vfs-extensions.h
? libgnomevfs/gnome-vfs-self-checks.h
? libgnomevfs/gnome-vfs-string.c
? libgnomevfs/gnome-vfs-string.h
? modules/applications.vfolder-info
? modules/network.vfolder-info
? modules/network.vfolder-info.in
? modules/preferences.vfolder-info
? test/test-metadata
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gnome-vfs/ChangeLog,v
retrieving revision 1.1397
diff -u -5 -r1.1397 ChangeLog
--- ChangeLog	13 Sep 2002 13:41:41 -0000	1.1397
+++ ChangeLog	19 Sep 2002 03:11:54 -0000
@@ -1,5 +1,28 @@
+2002-09-18  James Willcox  <jwillcox gnome org>
+
+	Moved some of eel-vfs-extensions.c into gnome-vfs-utils.c
+
+	* libgnomevfs/gnome-vfs-utils.c:
+	(gnome_vfs_escape_string_internal),
+	(gnome_vfs_make_uri_canonical_old), (gnome_vfs_make_valid_utf8),
+	(gnome_vfs_format_uri_for_display_internal),
+	(gnome_vfs_format_uri_for_display), (is_valid_scheme_character),
+	(has_valid_scheme), (gnome_vfs_escape_high_chars),
+	(gnome_vfs_make_uri_from_input_internal),
+	(gnome_vfs_make_uri_from_input),
+	(gnome_vfs_make_uri_canonical_strip_fragment), (uris_match),
+	(gnome_vfs_uris_match), (gnome_vfs_str_has_prefix),
+	(gnome_vfs_uri_is_local_scheme),
+	(gnome_vfs_handle_trailing_slashes),
+	(gnome_vfs_make_uri_canonical), (gnome_vfs_get_uri_scheme),
+	(file_uri_from_local_relative_path),
+	(gnome_vfs_make_uri_from_shell_arg), (is_uri_partial),
+	(remove_internal_relative_components),
+	(gnome_vfs_make_uri_full_from_relative):
+	* libgnomevfs/gnome-vfs-utils.h:
+
 2002-09-13  Ghee Teo <ghee teo sun com>
 	* Fixes #92132 in modules/http-method.c which leaks file descriptor
 	  on a bad page, error 405.
 
 2002-09-09  Jody Goldberg <jody gnome org>
Index: libgnomevfs/gnome-vfs-utils.c
===================================================================
RCS file: /cvs/gnome/gnome-vfs/libgnomevfs/gnome-vfs-utils.c,v
retrieving revision 1.56
diff -u -5 -r1.56 gnome-vfs-utils.c
--- libgnomevfs/gnome-vfs-utils.c	17 Jun 2002 08:16:31 -0000	1.56
+++ libgnomevfs/gnome-vfs-utils.c	19 Sep 2002 03:11:54 -0000
@@ -228,10 +228,12 @@
 	}
 	
 	*q = '\0';
 	
 	return result;
+
+#undef ACCEPTABLE
 }
 
 /**
  * gnome_vfs_escape_string:
  * @string: string to be escaped
@@ -618,27 +620,13 @@
 		}
 	}
 	return GNOME_VFS_OK;
 }
 
-/**
- * gnome_vfs_make_uri_canonical:
- * @uri: URI to make canonical
- *
- * Converts @uri to the standard (i.e. "canonical") format. This makes
- * the URI more appropriate for string comparisons as equivalent URIs
- * will often have the same canonical form.
- *
- * Return value: newly allocated string containing the canonical form
- * of @uri
- **/
-char *
-gnome_vfs_make_uri_canonical (const char *original_uri_text)
+static char *
+gnome_vfs_make_uri_canonical_old (const char *original_uri_text)
 {
-	/* For now use a sub-optimal implementation involving a
-	 * conversion to GnomeVFSURI and back.
-	 */
 	GnomeVFSURI *uri;
 	char *result;
 
 	uri = gnome_vfs_uri_new_private (original_uri_text, TRUE, TRUE, FALSE);
 	if (uri == NULL) {
@@ -1063,5 +1051,847 @@
 	/* Return the file. */
 	*file_size = total_bytes_read;
 	*file_contents = g_realloc (buffer, total_bytes_read);
 	return GNOME_VFS_OK;
 }
+
+char *
+gnome_vfs_make_valid_utf8 (const char *name)
+{
+	GString *string;
+	const char *remainder, *invalid;
+	int remaining_bytes, valid_bytes;
+
+	string = NULL;
+	remainder = name;
+	remaining_bytes = strlen (name);
+
+	while (remaining_bytes != 0) {
+		if (g_utf8_validate (remainder, remaining_bytes, &invalid)) {
+			break;
+		}
+		valid_bytes = invalid - remainder;
+
+		if (string == NULL) {
+			string = g_string_sized_new (remaining_bytes);
+		}
+		g_string_append_len (string, remainder, valid_bytes);
+		g_string_append_c (string, '?');
+
+		remaining_bytes -= valid_bytes + 1;
+		remainder = invalid + 1;
+	}
+
+	if (string == NULL) {
+		return g_strdup (name);
+	}
+
+	g_string_append (string, remainder);
+	g_string_append (string, _(" (invalid Unicode)"));
+	g_assert (g_utf8_validate (string->str, -1, NULL));
+
+	return g_string_free (string, FALSE);
+}
+
+static char *
+gnome_vfs_format_uri_for_display_internal (const char *uri, gboolean filenames_are_locale_encoded)
+{
+	char *canonical_uri, *path, *utf8_path;
+
+	g_return_val_if_fail (uri != NULL, g_strdup (""));
+
+	canonical_uri = gnome_vfs_make_uri_canonical_old (uri);
+
+	/* If there's no fragment and it's a local path. */
+	path = gnome_vfs_get_local_path_from_uri (canonical_uri);
+	
+	if (path != NULL) {
+		if (filenames_are_locale_encoded) {
+			utf8_path = g_locale_to_utf8 (path, -1, NULL, NULL, NULL);
+			if (utf8_path) {
+				g_free (canonical_uri);
+				g_free (path);
+				return utf8_path;
+			} 
+		} else if (g_utf8_validate (path, -1, NULL)) {
+			g_free (canonical_uri);
+			return path;
+		}
+	}
+
+	if (canonical_uri && !g_utf8_validate (canonical_uri, -1, NULL)) {
+		utf8_path = gnome_vfs_make_valid_utf8 (canonical_uri);
+		g_free (canonical_uri);
+		canonical_uri = utf8_path;
+	}
+
+	g_free (path);
+	return canonical_uri;
+}
+
+
+/**
+ * gnome_vfs_format_uri_for_display:
+ *
+ * Filter, modify, unescape and change URIs to make them appropriate
+ * to display to users. The conversion is done such that the roundtrip
+ * to UTf8 is reversible.
+ * 
+ * Rules:
+ * 	file: URI's without fragments should appear as local paths
+ * 	file: URI's with fragments should appear as file: URI's
+ * 	All other URI's appear as expected
+ *
+ * @uri: a URI
+ *
+ * returns a g_malloc'd UTF8 string
+ **/
+char *
+gnome_vfs_format_uri_for_display (const char *uri) 
+{
+	static gboolean broken_filenames;
+	
+	broken_filenames = g_getenv ("G_BROKEN_FILENAMES") != NULL;
+
+	return gnome_vfs_format_uri_for_display_internal (uri, broken_filenames);
+}
+
+static gboolean
+is_valid_scheme_character (char c)
+{
+	return g_ascii_isalnum (c) || c == '+' || c == '-' || c == '.';
+}
+
+static gboolean
+has_valid_scheme (const char *uri)
+{
+	const char *p;
+
+	p = uri;
+
+	if (!is_valid_scheme_character (*p)) {
+		return FALSE;
+	}
+
+	do {
+		p++;
+	} while (is_valid_scheme_character (*p));
+
+	return *p == ':';
+}
+
+static char *
+gnome_vfs_escape_high_chars (const guchar *string)
+{
+	char *result;
+	const guchar *scanner;
+	guchar *result_scanner;
+	int escape_count;
+	static const gchar hex[16] = "0123456789ABCDEF";
+
+#define ACCEPTABLE(a) ((a)>=32 && (a)<128)
+	
+	escape_count = 0;
+
+	if (string == NULL) {
+		return NULL;
+	}
+
+	for (scanner = string; *scanner != '\0'; scanner++) {
+		if (!ACCEPTABLE(*scanner)) {
+			escape_count++;
+		}
+	}
+	
+	if (escape_count == 0) {
+		return g_strdup (string);
+	}
+
+	/* allocate two extra characters for every character that
+	 * needs escaping and space for a trailing zero
+	 */
+	result = g_malloc (scanner - string + escape_count * 2 + 1);
+	for (scanner = string, result_scanner = result; *scanner != '\0'; scanner++) {
+		if (!ACCEPTABLE(*scanner)) {
+			*result_scanner++ = '%';
+			*result_scanner++ = hex[*scanner >> 4];
+			*result_scanner++ = hex[*scanner & 15];
+			
+		} else {
+			*result_scanner++ = *scanner;
+		}
+	}
+
+	*result_scanner = '\0';
+
+#undef ACCEPTABLE
+
+	return result;
+}
+
+/* The strip_trailing_whitespace option is intended to make copy/paste of
+ * URIs less error-prone when it is known that trailing whitespace isn't
+ * part of the uri.
+ */
+static char *
+gnome_vfs_make_uri_from_input_internal (const char *text,
+				  gboolean filenames_are_locale_encoded,
+				  gboolean strip_trailing_whitespace)
+{
+	char *stripped, *path, *uri, *locale_path, *filesystem_path, *escaped;
+
+	g_return_val_if_fail (text != NULL, g_strdup (""));
+
+	/* Strip off leading whitespaces (since they can't be part of a valid
+	   uri).   Only strip off trailing whitespaces when requested since
+	   they might be part of a valid uri.
+	 */
+	if (strip_trailing_whitespace) {
+		stripped = g_strstrip (g_strdup (text));
+	} else {
+		stripped = g_strchug (g_strdup (text));
+	}
+
+	switch (stripped[0]) {
+	case '\0':
+		uri = g_strdup ("");
+		break;
+	case '/':
+		if (filenames_are_locale_encoded) {
+			GError *error = NULL;
+			locale_path = g_locale_from_utf8 (stripped, -1, NULL, NULL, &error);
+			if (locale_path != NULL) {
+				uri = gnome_vfs_get_uri_from_local_path (locale_path);
+				g_free (locale_path);
+			} else {
+				/* We couldn't convert to the locale. */
+				/* FIXME: We should probably give a user-visible error here. */
+				uri = g_strdup("");
+			}
+		} else {
+			uri = gnome_vfs_get_uri_from_local_path (stripped);
+		}
+		break;
+	case '~':
+		if (filenames_are_locale_encoded) {
+			filesystem_path = g_locale_from_utf8 (stripped, -1, NULL, NULL, NULL);
+		} else {
+			filesystem_path = g_strdup (stripped);
+		}
+                /* deliberately falling into default case on fail */
+		if (filesystem_path != NULL) {
+			path = gnome_vfs_expand_initial_tilde (filesystem_path);
+			g_free (filesystem_path);
+			if (*path == '/') {
+				uri = gnome_vfs_get_uri_from_local_path (path);
+				g_free (path);
+				break;
+			}
+			g_free (path);
+		}
+                /* don't insert break here, read above comment */
+	default:
+		if (has_valid_scheme (stripped)) {
+			uri = gnome_vfs_escape_high_chars (stripped);
+		} else {
+			escaped = gnome_vfs_escape_high_chars (stripped);
+			uri = g_strconcat ("http://";, escaped, NULL);
+			g_free (escaped);
+		}
+	}
+
+	g_free (stripped);
+
+	return uri;
+	
+}
+
+
+
+/**
+ * gnome_vfs_make_uri_from_input:
+ *
+ * Takes a user input path/URI and makes a valid URI
+ * out of it
+ *
+ * @location: a possibly mangled "uri", in UTF8
+ *
+ * returns a newly allocated uri.
+ *
+ * This function is the reverse of gnome_vfs_format_uri_for_display
+ * but it also handles the fact that the user could have typed
+ * arbitrary UTF8 in the entry showing the string.
+ *
+ **/
+char *
+gnome_vfs_make_uri_from_input (const char *location)
+{
+	static gboolean broken_filenames;
+
+	broken_filenames = g_getenv ("G_BROKEN_FILENAMES") != NULL;
+
+	return gnome_vfs_make_uri_from_input_internal (location, broken_filenames, TRUE);
+}
+
+char *
+gnome_vfs_make_uri_canonical_strip_fragment (const char *uri)
+{
+	const char *fragment;
+	char *without_fragment, *canonical;
+
+	fragment = strchr (uri, '#');
+	if (fragment == NULL) {
+		return gnome_vfs_make_uri_canonical (uri);
+	}
+
+	without_fragment = g_strndup (uri, fragment - uri);
+	canonical = gnome_vfs_make_uri_canonical (without_fragment);
+	g_free (without_fragment);
+	return canonical;
+}
+
+
+static gboolean
+uris_match (const char *uri_1, const char *uri_2, gboolean ignore_fragments)
+{
+	char *canonical_1, *canonical_2;
+	gboolean result;
+
+	if (ignore_fragments) {
+		canonical_1 = gnome_vfs_make_uri_canonical_strip_fragment (uri_1);
+		canonical_2 = gnome_vfs_make_uri_canonical_strip_fragment (uri_2);
+	} else {
+		canonical_1 = gnome_vfs_make_uri_canonical (uri_1);
+		canonical_2 = gnome_vfs_make_uri_canonical (uri_2);
+	}
+
+	result = strcmp (canonical_1, canonical_2) ? FALSE : TRUE;
+
+	g_free (canonical_1);
+	g_free (canonical_2);
+	
+	return result;
+}
+
+gboolean
+gnome_vfs_uris_match (const char *uri_1, const char *uri_2)
+{
+	return uris_match (uri_1, uri_2, FALSE);
+}
+
+static gboolean
+gnome_vfs_str_has_prefix (const char *haystack, const char *needle)
+{
+        const char *h, *n;
+
+        /* Eat one character at a time. */
+        h = haystack == NULL ? "" : haystack;
+        n = needle == NULL ? "" : needle;
+        do {
+                if (*n == '\0') {
+                        return TRUE;
+                }
+                if (*h == '\0') {
+                        return FALSE;
+                }
+        } while (*h++ == *n++);
+        return FALSE;
+}
+
+
+static gboolean
+gnome_vfs_uri_is_local_scheme (const char *uri)
+{
+	gboolean is_local_scheme;
+	char *temp_scheme;
+	int i;
+	char *local_schemes[] = {"file:", "help:", "ghelp:", "gnome-help:",
+				 "trash:", "man:", "info:", 
+				 "hardware:", "search:", "pipe:",
+				 "gnome-trash:", NULL};
+
+	is_local_scheme = FALSE;
+	for (temp_scheme = *local_schemes, i = 0; temp_scheme != NULL; i++, temp_scheme = local_schemes[i]) {
+		is_local_scheme = gnome_vfs_istr_has_prefix (uri, temp_scheme);
+		if (is_local_scheme) {
+			break;
+		}
+	}
+	
+
+	return is_local_scheme;
+}
+
+static char *
+gnome_vfs_handle_trailing_slashes (const char *uri)
+{
+	char *temp, *uri_copy;
+	gboolean previous_char_is_column, previous_chars_are_slashes_without_column;
+	gboolean previous_chars_are_slashes_with_column;
+	gboolean is_local_scheme;
+
+	g_assert (uri != NULL);
+
+	uri_copy = g_strdup (uri);
+	if (strlen (uri_copy) <= 2) {
+		return uri_copy;
+	}
+
+	is_local_scheme = gnome_vfs_uri_is_local_scheme (uri);
+
+	previous_char_is_column = FALSE;
+	previous_chars_are_slashes_without_column = FALSE;
+	previous_chars_are_slashes_with_column = FALSE;
+
+	/* remove multiple trailing slashes */
+	for (temp = uri_copy; *temp != '\0'; temp++) {
+		if (*temp == '/' && !previous_char_is_column) {
+			previous_chars_are_slashes_without_column = TRUE;
+		} else if (*temp == '/' && previous_char_is_column) {
+			previous_chars_are_slashes_without_column = FALSE;
+			previous_char_is_column = TRUE;
+			previous_chars_are_slashes_with_column = TRUE;
+		} else {
+			previous_chars_are_slashes_without_column = FALSE;
+			previous_char_is_column = FALSE;
+			previous_chars_are_slashes_with_column = FALSE;
+		}
+
+		if (*temp == ':') {
+			previous_char_is_column = TRUE;
+		}
+	}
+
+	if (*temp == '\0' && previous_chars_are_slashes_without_column) {
+		if (is_local_scheme) {
+			/* go back till you remove them all. */
+			for (temp--; *(temp) == '/'; temp--) {
+				*temp = '\0';
+			}
+		} else {
+			/* go back till you remove them all but one. */
+			for (temp--; *(temp - 1) == '/'; temp--) {
+				*temp = '\0';
+			}			
+		}
+	}
+
+	if (*temp == '\0' && previous_chars_are_slashes_with_column) {
+		/* go back till you remove them all but three. */
+		for (temp--; *(temp - 3) != ':' && *(temp - 2) != ':' && *(temp - 1) != ':'; temp--) {
+			*temp = '\0';
+		}
+	}
+
+
+	return uri_copy;
+}
+
+
+
+char *
+gnome_vfs_make_uri_canonical (const char *uri)
+{
+	char *canonical_uri, *old_uri, *p;
+	gboolean relative_uri;
+
+	relative_uri = FALSE;
+
+	if (uri == NULL) {
+		return NULL;
+	}
+
+	/* FIXME bugzilla.eazel.com 648: 
+	 * This currently ignores the issue of two uris that are not identical but point
+	 * to the same data except for the specific cases of trailing '/' characters,
+	 * file:/ and file:///, and "lack of file:".
+	 */
+
+	canonical_uri = gnome_vfs_handle_trailing_slashes (uri);
+
+	/* Note: In some cases, a trailing slash means nothing, and can
+	 * be considered equivalent to no trailing slash. But this is
+	 * not true in every case; specifically not for web addresses passed
+	 * to a web-browser. So we don't have the trailing-slash-equivalence
+	 * logic here, but we do use that logic in EelDirectory where
+	 * the rules are more strict.
+	 */
+
+	/* Add file: if there is no scheme. */
+	if (strchr (canonical_uri, ':') == NULL) {
+		old_uri = canonical_uri;
+
+		if (old_uri[0] != '/') {
+			/* FIXME bugzilla.eazel.com 5069: 
+			 *  bandaid alert. Is this really the right thing to do?
+			 * 
+			 * We got what really is a relative path. We do a little bit of
+			 * a stretch here and assume it was meant to be a cryptic absolute path,
+			 * and convert it to one. Since we can't call gnome_vfs_uri_new and
+			 * gnome_vfs_uri_to_string to do the right make-canonical conversion,
+			 * we have to do it ourselves.
+			 */
+			relative_uri = TRUE;
+			canonical_uri = gnome_vfs_make_path_name_canonical (old_uri);
+			g_free (old_uri);
+			old_uri = canonical_uri;
+			canonical_uri = g_strconcat ("file:///", old_uri, NULL);
+		} else {
+			canonical_uri = g_strconcat ("file:", old_uri, NULL);
+		}
+		g_free (old_uri);
+	}
+
+	/* Lower-case the scheme. */
+	for (p = canonical_uri; *p != ':'; p++) {
+		g_assert (*p != '\0');
+		*p = g_ascii_tolower (*p);
+	}
+
+	if (!relative_uri) {
+		old_uri = canonical_uri;
+		canonical_uri = gnome_vfs_make_uri_canonical_old (canonical_uri);
+		if (canonical_uri != NULL) {
+			g_free (old_uri);
+		} else {
+			canonical_uri = old_uri;
+		}
+	}
+	
+	/* FIXME bugzilla.eazel.com 2802:
+	 * Work around gnome-vfs's desire to convert file:foo into file://foo
+	 * by converting to file:///foo here. When you remove this, check that
+	 * typing "foo" into location bar does not crash and returns an error
+	 * rather than displaying the contents of /
+	 */
+	if (gnome_vfs_str_has_prefix (canonical_uri, "file://")
+	    && !gnome_vfs_str_has_prefix (canonical_uri, "file:///")) {
+		old_uri = canonical_uri;
+		canonical_uri = g_strconcat ("file:/", old_uri + 5, NULL);
+		g_free (old_uri);
+	}
+
+	return canonical_uri;
+}
+
+char *
+gnome_vfs_get_uri_scheme (const char *uri)
+{
+	char *colon;
+
+	g_return_val_if_fail (uri != NULL, NULL);
+
+	colon = strchr (uri, ':');
+	
+	if (colon == NULL) {
+		return NULL;
+	}
+	
+	return g_strndup (uri, colon - uri);
+}
+
+/* Note that NULL's and full paths are also handled by this function.
+ * A NULL location will return the current working directory
+ */
+static char *
+file_uri_from_local_relative_path (const char *location)
+{
+	char *current_dir;
+	char *base_uri, *base_uri_slash;
+	char *location_escaped;
+	char *uri;
+
+	current_dir = g_get_current_dir ();
+	base_uri = gnome_vfs_get_uri_from_local_path (current_dir);
+	/* g_get_current_dir returns w/o trailing / */
+	base_uri_slash = g_strconcat (base_uri, "/", NULL);
+
+	location_escaped = gnome_vfs_escape_path_string (location);
+
+	uri = gnome_vfs_make_uri_full_from_relative (base_uri_slash, location_escaped);
+
+	g_free (location_escaped);
+	g_free (base_uri_slash);
+	g_free (base_uri);
+	g_free (current_dir);
+
+	return uri;
+}
+
+/**
+ * gnome_vfs_make_uri_from_shell_arg:
+ *
+ * Similar to gnome_vfs_make_uri_from_input, except that:
+ * 
+ * 1) guesses relative paths instead of http domains
+ * 2) doesn't bother stripping leading/trailing white space
+ * 3) doesn't bother with ~ expansion--that's done by the shell
+ *
+ * @location: a possibly mangled "uri"
+ *
+ * returns a newly allocated uri
+ *
+ **/
+char *
+gnome_vfs_make_uri_from_shell_arg (const char *location)
+{
+	char *uri;
+
+	g_return_val_if_fail (location != NULL, g_strdup (""));
+
+	switch (location[0]) {
+	case '\0':
+		uri = g_strdup ("");
+		break;
+	case '/':
+		uri = gnome_vfs_get_uri_from_local_path (location);
+		break;
+	default:
+		if (has_valid_scheme (location)) {
+			uri = g_strdup (location);
+		} else {
+			uri = file_uri_from_local_relative_path (location);
+		}
+	}
+
+	return uri;
+}
+
+static gboolean
+is_uri_partial (const char *uri)
+{
+	const char *current;
+
+	/* RFC 2396 section 3.1 */
+	for (current = uri ; 
+		*current
+		&& 	((*current >= 'a' && *current <= 'z')
+			 || (*current >= 'A' && *current <= 'Z')
+			 || (*current >= '0' && *current <= '9')
+			 || ('-' == *current)
+			 || ('+' == *current)
+			 || ('.' == *current)) ;
+	     current++);
+
+	return  !(':' == *current);
+}
+
+/*
+ * FIXME this is not the simplest or most time-efficent way
+ * to do this.  Probably a far more clear way of doing this processing
+ * is to split the path into segments, rather than doing the processing
+ * in place.
+ */
+static void
+remove_internal_relative_components (char *uri_current)
+{
+	char *segment_prev, *segment_cur;
+	size_t len_prev, len_cur;
+
+	len_prev = len_cur = 0;
+	segment_prev = NULL;
+
+	g_return_if_fail (uri_current != NULL);
+
+	segment_cur = uri_current;
+
+	while (*segment_cur) {
+		len_cur = strcspn (segment_cur, "/");
+
+		if (len_cur == 1 && segment_cur[0] == '.') {
+			/* Remove "." 's */
+			if (segment_cur[1] == '\0') {
+				segment_cur[0] = '\0';
+				break;
+			} else {
+				memmove (segment_cur, segment_cur + 2, strlen (segment_cur + 2) + 1);
+				continue;
+			}
+		} else if (len_cur == 2 && segment_cur[0] == '.' && segment_cur[1] == '.' ) {
+			/* Remove ".."'s (and the component to the left of it) that aren't at the
+			 * beginning or to the right of other ..'s
+			 */
+			if (segment_prev) {
+				if (! (len_prev == 2
+				       && segment_prev[0] == '.'
+				       && segment_prev[1] == '.')) {
+				       	if (segment_cur[2] == '\0') {
+						segment_prev[0] = '\0';
+						break;
+				       	} else {
+						memmove (segment_prev, segment_cur + 3, strlen (segment_cur + 3) + 1);
+
+						segment_cur = segment_prev;
+						len_cur = len_prev;
+
+						/* now we find the previous segment_prev */
+						if (segment_prev == uri_current) {
+							segment_prev = NULL;
+						} else if (segment_prev - uri_current >= 2) {
+							segment_prev -= 2;
+							for ( ; segment_prev > uri_current && segment_prev[0] != '/' 
+							      ; segment_prev-- );
+							if (segment_prev[0] == '/') {
+								segment_prev++;
+							}
+						}
+						continue;
+					}
+				}
+			}
+		}
+
+		/*Forward to next segment */
+
+		if (segment_cur [len_cur] == '\0') {
+			break;
+		}
+		 
+		segment_prev = segment_cur;
+		len_prev = len_cur;
+		segment_cur += len_cur + 1;	
+	}	
+}
+
+
+
+/**
+ * gnome_vfs_make_uri_full_from_relative:
+ * 
+ * Returns a full URI given a full base URI, and a secondary URI which may
+ * be relative.
+ *
+ * Return value: the URI (NULL for some bad errors).
+ *
+ * FIXME: This code has been copied from gnome_vfs-mozilla-content-view
+ * because gnome_vfs-mozilla-content-view cannot link with libgnome_vfs-extensions
+ * due to lame license issues.  Really, this belongs in gnome-vfs, but was added
+ * after the Gnome 1.4 gnome-vfs API freeze
+ **/
+
+char *
+gnome_vfs_make_uri_full_from_relative (const char *base_uri, const char *relative_uri)
+{
+	char *result = NULL;
+
+	/* See section 5.2 in RFC 2396 */
+
+	if (base_uri == NULL && relative_uri == NULL) {
+		result = NULL;
+	} else if (base_uri == NULL) {
+		result = g_strdup (relative_uri);
+	} else if (relative_uri == NULL) {
+		result = g_strdup (base_uri);
+	} else if (!is_uri_partial (relative_uri)) {
+		result = g_strdup (relative_uri);
+	} else {
+		char *mutable_base_uri;
+		char *mutable_uri;
+
+		char *uri_current;
+		size_t base_uri_length;
+		char *separator;
+
+		mutable_base_uri = g_strdup (base_uri);
+		uri_current = mutable_uri = g_strdup (relative_uri);
+
+		/* Chew off Fragment and Query from the base_url */
+
+		separator = strrchr (mutable_base_uri, '#'); 
+
+		if (separator) {
+			*separator = '\0';
+		}
+
+		separator = strrchr (mutable_base_uri, '?');
+
+		if (separator) {
+			*separator = '\0';
+		}
+
+		if ('/' == uri_current[0] && '/' == uri_current [1]) {
+			/* Relative URI's beginning with the authority
+			 * component inherit only the scheme from their parents
+			 */
+
+			separator = strchr (mutable_base_uri, ':');
+
+			if (separator) {
+				separator[1] = '\0';
+			}			  
+		} else if ('/' == uri_current[0]) {
+			/* Relative URI's beginning with '/' absolute-path based
+			 * at the root of the base uri
+			 */
+
+			separator = strchr (mutable_base_uri, ':');
+
+			/* g_assert (separator), really */
+			if (separator) {
+				/* If we start with //, skip past the authority section */
+				if ('/' == separator[1] && '/' == separator[2]) {
+					separator = strchr (separator + 3, '/');
+					if (separator) {
+						separator[0] = '\0';
+					}
+				} else {
+				/* If there's no //, just assume the scheme is the root */
+					separator[1] = '\0';
+				}
+			}
+		} else if ('#' != uri_current[0]) {
+			/* Handle the ".." convention for relative uri's */
+
+			/* If there's a trailing '/' on base_url, treat base_url
+			 * as a directory path.
+			 * Otherwise, treat it as a file path, and chop off the filename
+			 */
+
+			base_uri_length = strlen (mutable_base_uri);
+			if ('/' == mutable_base_uri[base_uri_length-1]) {
+				/* Trim off '/' for the operation below */
+				mutable_base_uri[base_uri_length-1] = 0;
+			} else {
+				separator = strrchr (mutable_base_uri, '/');
+				if (separator) {
+					*separator = '\0';
+				}
+			}
+
+			remove_internal_relative_components (uri_current);
+
+			/* handle the "../"'s at the beginning of the relative URI */
+			while (0 == strncmp ("../", uri_current, 3)) {
+				uri_current += 3;
+				separator = strrchr (mutable_base_uri, '/');
+				if (separator) {
+					*separator = '\0';
+				} else {
+					/* <shrug> */
+					break;
+				}
+			}
+
+			/* handle a ".." at the end */
+			if (uri_current[0] == '.' && uri_current[1] == '.' 
+			    && uri_current[2] == '\0') {
+
+			    	uri_current += 2;
+				separator = strrchr (mutable_base_uri, '/');
+				if (separator) {
+					*separator = '\0';
+				}
+			}
+
+			/* Re-append the '/' */
+			mutable_base_uri [strlen(mutable_base_uri)+1] = '\0';
+			mutable_base_uri [strlen(mutable_base_uri)] = '/';
+		}
+
+		result = g_strconcat (mutable_base_uri, uri_current, NULL);
+		g_free (mutable_base_uri); 
+		g_free (mutable_uri); 
+	}
+	
+	return result;
+}
+
Index: libgnomevfs/gnome-vfs-utils.h
===================================================================
RCS file: /cvs/gnome/gnome-vfs/libgnomevfs/gnome-vfs-utils.h,v
retrieving revision 1.35
diff -u -5 -r1.35 gnome-vfs-utils.h
--- libgnomevfs/gnome-vfs-utils.h	17 Jun 2002 07:34:42 -0000	1.35
+++ libgnomevfs/gnome-vfs-utils.h	19 Sep 2002 03:11:55 -0000
@@ -135,8 +135,18 @@
 /* Reads the contents of an entire file into memory */
 GnomeVFSResult  gnome_vfs_read_entire_file (const char *uri,
 					    int *file_size,
 					    char **file_contents);
 
+char * gnome_vfs_make_valid_utf8 (const char *uri);
+char * gnome_vfs_format_uri_for_display (const char *uri);
+char * gnome_vfs_make_uri_from_input (const char *uri);
+char * gnome_vfs_make_uri_canonical_strip_fragment (const char *uri);
+gboolean gnome_vfs_uris_match (const char *uri_1, const char *uri_2);
+char * gnome_vfs_get_uri_scheme (const char *uri);
+char * gnome_vfs_make_uri_from_shell_arg (const char *uri);
+char * gnome_vfs_make_uri_full_from_relative (const char *base_uri,
+					      const char *relative_uri);
+
 G_END_DECLS
 
 #endif /* GNOME_VFS_UTILS_H */


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