[patch] move eel-vfs-extensions into gnome-vfs
- From: James Willcox <jwillcox gnome org>
- To: gnome-vfs-list gnome org
- Subject: [patch] move eel-vfs-extensions into gnome-vfs
- Date: 18 Sep 2002 22:19:28 -0500
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]