Commit eb7fea92 authored by Michael K. Fleming's avatar Michael K. Fleming Committed by Michael Fleming
Browse files

reviewed by: <sullivan@eazel.com>

2001-02-11  Michael K. Fleming  <mfleming@eazel.com>

	reviewed by: <sullivan@eazel.com>

	Bug 5961: Starting nautilus with path to local HTML file
	causes images not to load.

	The problem here was that any argument specified on the commandline
	was being passed directly into Nautilus and its components as a
	valid URI.  Added pre-processing to commandline arguments, including
	ability to handle relative file pathnames. (so you can do "nautilus ."
	to open a window on the current directory)

	* libnautilus-extensions/nautilus-file-utilities.c:
	(file_uri_from_local_relative_path),
	(nautilus_make_uri_from_shell_arg), (is_uri_partial),
	(remove_internal_relative_components),
	(nautilus_uri_make_full_from_relative),
	(nautilus_self_check_file_utilities):
	* libnautilus-extensions/nautilus-file-utilities.h:
	* src/nautilus-application.c:
	(nautilus_make_uri_list_from_shell_strv),
	(nautilus_application_startup):
parent 34cb3598
2001-02-11 Michael K. Fleming <mfleming@eazel.com>
reviewed by: <sullivan@eazel.com>
Bug 5961: Starting nautilus with path to local HTML file
causes images not to load.
The problem here was that any argument specified on the commandline
was being passed directly into Nautilus and its components as a
valid URI. Added pre-processing to commandline arguments, including
ability to handle relative file pathnames. (so you can do "nautilus ."
to open a window on the current directory)
* libnautilus-extensions/nautilus-file-utilities.c:
(file_uri_from_local_relative_path),
(nautilus_make_uri_from_shell_arg), (is_uri_partial),
(remove_internal_relative_components),
(nautilus_uri_make_full_from_relative),
(nautilus_self_check_file_utilities):
* libnautilus-extensions/nautilus-file-utilities.h:
* src/nautilus-application.c:
(nautilus_make_uri_list_from_shell_strv),
(nautilus_application_startup):
2001-02-12 Rebecca Schulman <rebecka@eazel.com>
Fix bugzilla.eazel.com bug 4962 that open with
mpg123 fails. The problem was a check for
......
......@@ -170,6 +170,73 @@ nautilus_make_uri_from_input (const char *location)
return 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 = nautilus_uri_make_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;
}
/**
* nautilus_make_uri_from_shell_arg:
*
* Similar to nautilus_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 *
nautilus_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;
}
char *
nautilus_uri_get_basename (const char *uri)
{
......@@ -205,6 +272,253 @@ nautilus_uri_get_scheme (const char *uri)
return g_strndup (uri, colon - 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);
}
/*
* Remove "./" segments
* Compact "../" segments inside the URI
* Remove "." at the end of the URL
* Leave any ".."'s at the beginning of the URI
*/
/*
* 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;
}
}
/**
* nautilus_uri_make_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 nautilus-mozilla-content-view
* because nautilus-mozilla-content-view cannot link with libnautilus-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 *
nautilus_uri_make_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;
}
gboolean
nautilus_uri_is_trash (const char *uri)
{
......@@ -1504,6 +1818,49 @@ nautilus_self_check_file_utilities (void)
NAUTILUS_CHECK_STRING_RESULT (nautilus_make_uri_canonical ("gnome-trash:xxx"), NAUTILUS_TRASH_URI);
NAUTILUS_CHECK_STRING_RESULT (nautilus_make_uri_canonical ("pipe:gnome-info2html2 as"), "pipe:gnome-info2html2 as");
/*
* Most of these test cases are from rfc 2396 (except for the NULL checks)
*/
#define BASE_URI "http://a/b/c/d;p?q"
#define TEST_PARTIAL(partial, result) NAUTILUS_CHECK_STRING_RESULT (nautilus_uri_make_full_from_relative (BASE_URI, partial), result)
NAUTILUS_CHECK_STRING_RESULT (nautilus_uri_make_full_from_relative (NULL, NULL), NULL);
NAUTILUS_CHECK_STRING_RESULT (nautilus_uri_make_full_from_relative (BASE_URI, NULL), BASE_URI);
NAUTILUS_CHECK_STRING_RESULT (nautilus_uri_make_full_from_relative (NULL, BASE_URI), BASE_URI);
TEST_PARTIAL ("g", "http://a/b/c/g");
TEST_PARTIAL ("./g", "http://a/b/c/g");
TEST_PARTIAL ("g/", "http://a/b/c/g/");
TEST_PARTIAL ("/g", "http://a/g");
TEST_PARTIAL ("//g", "http://g");
TEST_PARTIAL ("?y", "http://a/b/c/?y");
TEST_PARTIAL ("g?y", "http://a/b/c/g?y");
TEST_PARTIAL ("#s", "http://a/b/c/d;p#s");
TEST_PARTIAL ("g#s", "http://a/b/c/g#s");
TEST_PARTIAL ("g?y#s", "http://a/b/c/g?y#s");
TEST_PARTIAL (";x", "http://a/b/c/;x");
TEST_PARTIAL ("g;x", "http://a/b/c/g;x");
TEST_PARTIAL ("g;x?y#s", "http://a/b/c/g;x?y#s");
TEST_PARTIAL (".", "http://a/b/c/");
TEST_PARTIAL ("./", "http://a/b/c/");
TEST_PARTIAL ("..", "http://a/b/");
TEST_PARTIAL ("../g", "http://a/b/g");
TEST_PARTIAL ("../..", "http://a/");
TEST_PARTIAL ("../../", "http://a/");
TEST_PARTIAL ("../../g", "http://a/g");
/* Others */
TEST_PARTIAL ("g/..", "http://a/b/c/");
TEST_PARTIAL ("g/../", "http://a/b/c/");
TEST_PARTIAL ("g/../g", "http://a/b/c/g");
}
#endif /* !NAUTILUS_OMIT_SELF_CHECK */
......@@ -40,6 +40,8 @@ typedef struct NautilusReadFileHandle NautilusReadFileHandle;
char * nautilus_format_uri_for_display (const char *uri);
char * nautilus_make_uri_from_input (const char *location);
char * nautilus_make_uri_from_shell_arg (const char *location);
gboolean nautilus_uri_is_trash (const char *uri);
gboolean nautilus_uri_is_trash_folder (const char *uri);
gboolean nautilus_uri_is_in_trash (const char *uri);
......@@ -49,6 +51,10 @@ gboolean nautilus_uris_match (const char
char * nautilus_uri_get_basename (const char *uri);
char * nautilus_uri_get_scheme (const char *uri);
char * nautilus_uri_make_full_from_relative (const char *base_uri,
const char *uri);
/* FIXME bugzilla.eazel.com 2424:
* This is the same as gnome-libs g_concat_dir_and_file except
* for handling path == NULL.
......
......@@ -170,6 +170,73 @@ nautilus_make_uri_from_input (const char *location)
return 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 = nautilus_uri_make_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;
}
/**
* nautilus_make_uri_from_shell_arg:
*
* Similar to nautilus_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 *
nautilus_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;
}
char *
nautilus_uri_get_basename (const char *uri)
{
......@@ -205,6 +272,253 @@ nautilus_uri_get_scheme (const char *uri)
return g_strndup (uri, colon - 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);
}
/*
* Remove "./" segments
* Compact "../" segments inside the URI
* Remove "." at the end of the URL
* Leave any ".."'s at the beginning of the URI
*/
/*
* 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;
}
}