mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-03-12 02:35:28 +01:00
New functions to convert between local pahtnames and file: uris.
2001-08-26 Alex Larsson <alexl@redhat.com> * glib/gconvert.[ch] (g_filename_from_uri, g_filename_to_uri): New functions to convert between local pahtnames and file: uris. * tests/Makefile.am: * tests/uri-test.c: Tests for the new functions.
This commit is contained in:
parent
a7a76cfac7
commit
4e11203c54
10
ChangeLog
10
ChangeLog
@ -1,3 +1,13 @@
|
|||||||
|
2001-08-26 Alex Larsson <alexl@redhat.com>
|
||||||
|
|
||||||
|
* glib/gconvert.[ch] (g_filename_from_uri,
|
||||||
|
g_filename_to_uri): New functions to convert
|
||||||
|
between local pahtnames and file: uris.
|
||||||
|
|
||||||
|
* tests/Makefile.am:
|
||||||
|
* tests/uri-test.c:
|
||||||
|
Tests for the new functions.
|
||||||
|
|
||||||
2001-08-25 Alexander Larsson <alla@lysator.liu.se>
|
2001-08-25 Alexander Larsson <alla@lysator.liu.se>
|
||||||
|
|
||||||
* glib/gstrfuncs.[ch]:
|
* glib/gstrfuncs.[ch]:
|
||||||
|
@ -1,3 +1,13 @@
|
|||||||
|
2001-08-26 Alex Larsson <alexl@redhat.com>
|
||||||
|
|
||||||
|
* glib/gconvert.[ch] (g_filename_from_uri,
|
||||||
|
g_filename_to_uri): New functions to convert
|
||||||
|
between local pahtnames and file: uris.
|
||||||
|
|
||||||
|
* tests/Makefile.am:
|
||||||
|
* tests/uri-test.c:
|
||||||
|
Tests for the new functions.
|
||||||
|
|
||||||
2001-08-25 Alexander Larsson <alla@lysator.liu.se>
|
2001-08-25 Alexander Larsson <alla@lysator.liu.se>
|
||||||
|
|
||||||
* glib/gstrfuncs.[ch]:
|
* glib/gstrfuncs.[ch]:
|
||||||
|
@ -1,3 +1,13 @@
|
|||||||
|
2001-08-26 Alex Larsson <alexl@redhat.com>
|
||||||
|
|
||||||
|
* glib/gconvert.[ch] (g_filename_from_uri,
|
||||||
|
g_filename_to_uri): New functions to convert
|
||||||
|
between local pahtnames and file: uris.
|
||||||
|
|
||||||
|
* tests/Makefile.am:
|
||||||
|
* tests/uri-test.c:
|
||||||
|
Tests for the new functions.
|
||||||
|
|
||||||
2001-08-25 Alexander Larsson <alla@lysator.liu.se>
|
2001-08-25 Alexander Larsson <alla@lysator.liu.se>
|
||||||
|
|
||||||
* glib/gstrfuncs.[ch]:
|
* glib/gstrfuncs.[ch]:
|
||||||
|
@ -1,3 +1,13 @@
|
|||||||
|
2001-08-26 Alex Larsson <alexl@redhat.com>
|
||||||
|
|
||||||
|
* glib/gconvert.[ch] (g_filename_from_uri,
|
||||||
|
g_filename_to_uri): New functions to convert
|
||||||
|
between local pahtnames and file: uris.
|
||||||
|
|
||||||
|
* tests/Makefile.am:
|
||||||
|
* tests/uri-test.c:
|
||||||
|
Tests for the new functions.
|
||||||
|
|
||||||
2001-08-25 Alexander Larsson <alla@lysator.liu.se>
|
2001-08-25 Alexander Larsson <alla@lysator.liu.se>
|
||||||
|
|
||||||
* glib/gstrfuncs.[ch]:
|
* glib/gstrfuncs.[ch]:
|
||||||
|
@ -1,3 +1,13 @@
|
|||||||
|
2001-08-26 Alex Larsson <alexl@redhat.com>
|
||||||
|
|
||||||
|
* glib/gconvert.[ch] (g_filename_from_uri,
|
||||||
|
g_filename_to_uri): New functions to convert
|
||||||
|
between local pahtnames and file: uris.
|
||||||
|
|
||||||
|
* tests/Makefile.am:
|
||||||
|
* tests/uri-test.c:
|
||||||
|
Tests for the new functions.
|
||||||
|
|
||||||
2001-08-25 Alexander Larsson <alla@lysator.liu.se>
|
2001-08-25 Alexander Larsson <alla@lysator.liu.se>
|
||||||
|
|
||||||
* glib/gstrfuncs.[ch]:
|
* glib/gstrfuncs.[ch]:
|
||||||
|
@ -1,3 +1,13 @@
|
|||||||
|
2001-08-26 Alex Larsson <alexl@redhat.com>
|
||||||
|
|
||||||
|
* glib/gconvert.[ch] (g_filename_from_uri,
|
||||||
|
g_filename_to_uri): New functions to convert
|
||||||
|
between local pahtnames and file: uris.
|
||||||
|
|
||||||
|
* tests/Makefile.am:
|
||||||
|
* tests/uri-test.c:
|
||||||
|
Tests for the new functions.
|
||||||
|
|
||||||
2001-08-25 Alexander Larsson <alla@lysator.liu.se>
|
2001-08-25 Alexander Larsson <alla@lysator.liu.se>
|
||||||
|
|
||||||
* glib/gstrfuncs.[ch]:
|
* glib/gstrfuncs.[ch]:
|
||||||
|
@ -1,3 +1,13 @@
|
|||||||
|
2001-08-26 Alex Larsson <alexl@redhat.com>
|
||||||
|
|
||||||
|
* glib/gconvert.[ch] (g_filename_from_uri,
|
||||||
|
g_filename_to_uri): New functions to convert
|
||||||
|
between local pahtnames and file: uris.
|
||||||
|
|
||||||
|
* tests/Makefile.am:
|
||||||
|
* tests/uri-test.c:
|
||||||
|
Tests for the new functions.
|
||||||
|
|
||||||
2001-08-25 Alexander Larsson <alla@lysator.liu.se>
|
2001-08-25 Alexander Larsson <alla@lysator.liu.se>
|
||||||
|
|
||||||
* glib/gstrfuncs.[ch]:
|
* glib/gstrfuncs.[ch]:
|
||||||
|
@ -1,3 +1,13 @@
|
|||||||
|
2001-08-26 Alex Larsson <alexl@redhat.com>
|
||||||
|
|
||||||
|
* glib/gconvert.[ch] (g_filename_from_uri,
|
||||||
|
g_filename_to_uri): New functions to convert
|
||||||
|
between local pahtnames and file: uris.
|
||||||
|
|
||||||
|
* tests/Makefile.am:
|
||||||
|
* tests/uri-test.c:
|
||||||
|
Tests for the new functions.
|
||||||
|
|
||||||
2001-08-25 Alexander Larsson <alla@lysator.liu.se>
|
2001-08-25 Alexander Larsson <alla@lysator.liu.se>
|
||||||
|
|
||||||
* glib/gstrfuncs.[ch]:
|
* glib/gstrfuncs.[ch]:
|
||||||
|
371
glib/gconvert.c
371
glib/gconvert.c
@ -563,11 +563,24 @@ static gchar *
|
|||||||
strdup_len (const gchar *string,
|
strdup_len (const gchar *string,
|
||||||
gssize len,
|
gssize len,
|
||||||
gsize *bytes_written,
|
gsize *bytes_written,
|
||||||
gsize *bytes_read)
|
gsize *bytes_read,
|
||||||
|
GError **error)
|
||||||
|
|
||||||
{
|
{
|
||||||
gsize real_len;
|
gsize real_len;
|
||||||
|
|
||||||
|
if (!g_utf8_validate (string, -1, NULL))
|
||||||
|
{
|
||||||
|
if (bytes_read)
|
||||||
|
*bytes_read = 0;
|
||||||
|
if (bytes_written)
|
||||||
|
*bytes_written = 0;
|
||||||
|
|
||||||
|
g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
|
||||||
|
_("Invalid byte sequence in conversion input"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
real_len = strlen (string);
|
real_len = strlen (string);
|
||||||
else
|
else
|
||||||
@ -718,7 +731,7 @@ g_locale_to_utf8 (const gchar *opsysstring,
|
|||||||
const char *charset;
|
const char *charset;
|
||||||
|
|
||||||
if (g_get_charset (&charset))
|
if (g_get_charset (&charset))
|
||||||
return strdup_len (opsysstring, len, bytes_read, bytes_written);
|
return strdup_len (opsysstring, len, bytes_read, bytes_written, error);
|
||||||
else
|
else
|
||||||
return g_convert (opsysstring, len,
|
return g_convert (opsysstring, len,
|
||||||
"UTF-8", charset, bytes_read, bytes_written, error);
|
"UTF-8", charset, bytes_read, bytes_written, error);
|
||||||
@ -864,7 +877,7 @@ g_locale_from_utf8 (const gchar *utf8string,
|
|||||||
const gchar *charset;
|
const gchar *charset;
|
||||||
|
|
||||||
if (g_get_charset (&charset))
|
if (g_get_charset (&charset))
|
||||||
return strdup_len (utf8string, len, bytes_read, bytes_written);
|
return strdup_len (utf8string, len, bytes_read, bytes_written, error);
|
||||||
else
|
else
|
||||||
return g_convert (utf8string, len,
|
return g_convert (utf8string, len,
|
||||||
charset, "UTF-8", bytes_read, bytes_written, error);
|
charset, "UTF-8", bytes_read, bytes_written, error);
|
||||||
@ -907,12 +920,13 @@ g_filename_to_utf8 (const gchar *opsysstring,
|
|||||||
bytes_read, bytes_written,
|
bytes_read, bytes_written,
|
||||||
error);
|
error);
|
||||||
#else /* !G_PLATFORM_WIN32 */
|
#else /* !G_PLATFORM_WIN32 */
|
||||||
|
|
||||||
if (getenv ("G_BROKEN_FILENAMES"))
|
if (getenv ("G_BROKEN_FILENAMES"))
|
||||||
return g_locale_to_utf8 (opsysstring, len,
|
return g_locale_to_utf8 (opsysstring, len,
|
||||||
bytes_read, bytes_written,
|
bytes_read, bytes_written,
|
||||||
error);
|
error);
|
||||||
else
|
else
|
||||||
return strdup_len (opsysstring, len, bytes_read, bytes_written);
|
return strdup_len (opsysstring, len, bytes_read, bytes_written, error);
|
||||||
#endif /* !G_PLATFORM_WIN32 */
|
#endif /* !G_PLATFORM_WIN32 */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -955,6 +969,353 @@ g_filename_from_utf8 (const gchar *utf8string,
|
|||||||
bytes_read, bytes_written,
|
bytes_read, bytes_written,
|
||||||
error);
|
error);
|
||||||
else
|
else
|
||||||
return strdup_len (utf8string, len, bytes_read, bytes_written);
|
return strdup_len (utf8string, len, bytes_read, bytes_written, error);
|
||||||
#endif /* !G_PLATFORM_WIN32 */
|
#endif /* !G_PLATFORM_WIN32 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Test of haystack has the needle prefix, comparing case
|
||||||
|
* insensitive. haystack may be UTF-8, but needle must
|
||||||
|
* contain only ascii. */
|
||||||
|
static gboolean
|
||||||
|
has_case_prefix (const gchar *haystack, const gchar *needle)
|
||||||
|
{
|
||||||
|
const gchar *h, *n;
|
||||||
|
|
||||||
|
/* Eat one character at a time. */
|
||||||
|
h = haystack;
|
||||||
|
n = needle;
|
||||||
|
|
||||||
|
while (*n && *h &&
|
||||||
|
g_ascii_tolower (*n) == g_ascii_tolower (*h))
|
||||||
|
{
|
||||||
|
n++;
|
||||||
|
h++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *n == '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
UNSAFE_ALL = 0x1, /* Escape all unsafe characters */
|
||||||
|
UNSAFE_ALLOW_PLUS = 0x2, /* Allows '+' */
|
||||||
|
UNSAFE_PATH = 0x4, /* Allows '/' and '?' and '&' and '=' */
|
||||||
|
UNSAFE_DOS_PATH = 0x8, /* Allows '/' and '?' and '&' and '=' and ':' */
|
||||||
|
UNSAFE_HOST = 0x10, /* Allows '/' and ':' and '@' */
|
||||||
|
UNSAFE_SLASHES = 0x20 /* Allows all characters except for '/' and '%' */
|
||||||
|
} UnsafeCharacterSet;
|
||||||
|
|
||||||
|
static const guchar acceptable[96] = {
|
||||||
|
/* X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 XA XB XC XD XE XF */
|
||||||
|
0x00,0x3F,0x20,0x20,0x20,0x00,0x2C,0x3F,0x3F,0x3F,0x3F,0x22,0x20,0x3F,0x3F,0x1C, /* 2X !"#$%&'()*+,-./ */
|
||||||
|
0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x38,0x20,0x20,0x2C,0x20,0x2C, /* 3X 0123456789:;<=>? */
|
||||||
|
0x30,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, /* 4X @ABCDEFGHIJKLMNO */
|
||||||
|
0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x20,0x20,0x20,0x20,0x3F, /* 5X PQRSTUVWXYZ[\]^_ */
|
||||||
|
0x20,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, /* 6X `abcdefghijklmno */
|
||||||
|
0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x20,0x20,0x20,0x3F,0x20 /* 7X pqrstuvwxyz{|}~DEL */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const gchar hex[16] = "0123456789ABCDEF";
|
||||||
|
|
||||||
|
/* Note: This escape function works on file: URIs, but if you want to
|
||||||
|
* escape something else, please read RFC-2396 */
|
||||||
|
static gchar *
|
||||||
|
g_escape_uri_string (const gchar *string,
|
||||||
|
UnsafeCharacterSet mask)
|
||||||
|
{
|
||||||
|
#define ACCEPTABLE(a) ((a)>=32 && (a)<128 && (acceptable[(a)-32] & use_mask))
|
||||||
|
|
||||||
|
const gchar *p;
|
||||||
|
gchar *q;
|
||||||
|
gchar *result;
|
||||||
|
int c;
|
||||||
|
gint unacceptable;
|
||||||
|
UnsafeCharacterSet use_mask;
|
||||||
|
|
||||||
|
g_return_val_if_fail (mask == UNSAFE_ALL
|
||||||
|
|| mask == UNSAFE_ALLOW_PLUS
|
||||||
|
|| mask == UNSAFE_PATH
|
||||||
|
|| mask == UNSAFE_DOS_PATH
|
||||||
|
|| mask == UNSAFE_HOST
|
||||||
|
|| mask == UNSAFE_SLASHES, NULL);
|
||||||
|
|
||||||
|
unacceptable = 0;
|
||||||
|
use_mask = mask;
|
||||||
|
for (p = string; *p != '\0'; p++)
|
||||||
|
{
|
||||||
|
c = *p;
|
||||||
|
if (!ACCEPTABLE (c))
|
||||||
|
unacceptable++;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = g_malloc (p - string + unacceptable * 2 + 1);
|
||||||
|
|
||||||
|
use_mask = mask;
|
||||||
|
for (q = result, p = string; *p != '\0'; p++)
|
||||||
|
{
|
||||||
|
c = (unsigned char)*p;
|
||||||
|
|
||||||
|
if (!ACCEPTABLE (c))
|
||||||
|
{
|
||||||
|
*q++ = '%'; /* means hex coming */
|
||||||
|
*q++ = hex[c >> 4];
|
||||||
|
*q++ = hex[c & 15];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*q++ = *p;
|
||||||
|
}
|
||||||
|
|
||||||
|
*q = '\0';
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gchar *
|
||||||
|
g_escape_file_uri (const gchar *hostname,
|
||||||
|
const gchar *pathname)
|
||||||
|
{
|
||||||
|
char *escaped_hostname = NULL;
|
||||||
|
char *escaped_path;
|
||||||
|
char *res;
|
||||||
|
|
||||||
|
if (hostname && *hostname != '\0')
|
||||||
|
{
|
||||||
|
escaped_hostname = g_escape_uri_string (hostname, UNSAFE_HOST);
|
||||||
|
}
|
||||||
|
|
||||||
|
escaped_path = g_escape_uri_string (pathname, UNSAFE_DOS_PATH);
|
||||||
|
|
||||||
|
res = g_strconcat ("file://",
|
||||||
|
(escaped_hostname) ? escaped_hostname : "",
|
||||||
|
(*escaped_path != '/') ? "/" : "",
|
||||||
|
escaped_path,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
g_free (escaped_hostname);
|
||||||
|
g_free (escaped_path);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
unescape_character (const char *scanner)
|
||||||
|
{
|
||||||
|
int first_digit;
|
||||||
|
int second_digit;
|
||||||
|
|
||||||
|
first_digit = g_ascii_xdigit_value (*scanner++);
|
||||||
|
|
||||||
|
if (first_digit < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
second_digit = g_ascii_xdigit_value (*scanner++);
|
||||||
|
if (second_digit < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return (first_digit << 4) | second_digit;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gchar *
|
||||||
|
g_unescape_uri_string (const gchar *escaped,
|
||||||
|
const gchar *illegal_characters,
|
||||||
|
int len)
|
||||||
|
{
|
||||||
|
const gchar *in, *in_end;
|
||||||
|
gchar *out, *result;
|
||||||
|
int character;
|
||||||
|
|
||||||
|
if (escaped == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (len < 0)
|
||||||
|
len = strlen (escaped);
|
||||||
|
|
||||||
|
result = g_malloc (len + 1);
|
||||||
|
|
||||||
|
out = result;
|
||||||
|
for (in = escaped, in_end = escaped + len; in < in_end && *in != '\0'; in++)
|
||||||
|
{
|
||||||
|
character = *in;
|
||||||
|
if (character == '%')
|
||||||
|
{
|
||||||
|
character = unescape_character (in + 1);
|
||||||
|
|
||||||
|
/* Check for an illegal character. We consider '\0' illegal here. */
|
||||||
|
if (character == 0
|
||||||
|
|| (illegal_characters != NULL
|
||||||
|
&& strchr (illegal_characters, (char)character) != NULL))
|
||||||
|
{
|
||||||
|
g_free (result);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
in += 2;
|
||||||
|
}
|
||||||
|
*out++ = character;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out = '\0';
|
||||||
|
|
||||||
|
g_assert (out - result <= strlen (escaped));
|
||||||
|
|
||||||
|
if (!g_utf8_validate (result, -1, NULL))
|
||||||
|
{
|
||||||
|
g_free (result);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_filename_from_uri:
|
||||||
|
* @uri: a uri describing a filename (escaped, encoded in UTF-8)
|
||||||
|
* @hostname: Location to store hostname for the URI, or %NULL.
|
||||||
|
* If there is no hostname in the URI, %NULL will be
|
||||||
|
* stored in this location.
|
||||||
|
* @error: location to store the error occuring, or %NULL to ignore
|
||||||
|
* errors. Any of the errors in #GConvertError may occur.
|
||||||
|
*
|
||||||
|
* Converts an escaped UTF-8 encoded URI to a local filename in the
|
||||||
|
* encoding used for filenames.
|
||||||
|
*
|
||||||
|
* Return value: a newly allocated string holding the resulting
|
||||||
|
* filename, or %NULL on an error.
|
||||||
|
**/
|
||||||
|
gchar *
|
||||||
|
g_filename_from_uri (const char *uri,
|
||||||
|
char **hostname,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
const char *path_part;
|
||||||
|
const char *host_part;
|
||||||
|
char *unescaped_hostname;
|
||||||
|
char *result;
|
||||||
|
char *filename;
|
||||||
|
int offs;
|
||||||
|
|
||||||
|
if (hostname)
|
||||||
|
*hostname = NULL;
|
||||||
|
|
||||||
|
if (!has_case_prefix (uri, "file:/"))
|
||||||
|
{
|
||||||
|
g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_NOT_LOCAL_FILE,
|
||||||
|
_("The URI `%s' does not specify a local file"),
|
||||||
|
uri);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
path_part = uri + strlen ("file:");
|
||||||
|
|
||||||
|
if (strchr (path_part, '#') != NULL)
|
||||||
|
{
|
||||||
|
g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_INVALID_URI,
|
||||||
|
_("The local file URI `%s' may not include a `#'"),
|
||||||
|
uri);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_case_prefix (path_part, "///"))
|
||||||
|
path_part += 2;
|
||||||
|
else if (has_case_prefix (path_part, "//"))
|
||||||
|
{
|
||||||
|
path_part += 2;
|
||||||
|
host_part = path_part;
|
||||||
|
|
||||||
|
path_part = strchr (path_part, '/');
|
||||||
|
|
||||||
|
if (path_part == NULL)
|
||||||
|
{
|
||||||
|
g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_INVALID_URI,
|
||||||
|
_("The URI `%s' is invalid"),
|
||||||
|
uri);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
unescaped_hostname = g_unescape_uri_string (host_part, "", path_part - host_part);
|
||||||
|
if (unescaped_hostname == NULL)
|
||||||
|
{
|
||||||
|
g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_INVALID_URI,
|
||||||
|
_("The hostname of the URI `%s' is contains invalidly escaped characters"),
|
||||||
|
uri);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hostname)
|
||||||
|
*hostname = unescaped_hostname;
|
||||||
|
else
|
||||||
|
g_free (unescaped_hostname);
|
||||||
|
}
|
||||||
|
|
||||||
|
filename = g_unescape_uri_string (path_part, "/", -1);
|
||||||
|
|
||||||
|
if (filename == NULL)
|
||||||
|
{
|
||||||
|
g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_INVALID_URI,
|
||||||
|
_("The URI `%s' is contains invalidly escaped characters"),
|
||||||
|
uri);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DOS uri's are like "file://host/c:\foo", so we need to check if we need to
|
||||||
|
* drop the initial slash */
|
||||||
|
offs = 0;
|
||||||
|
if (g_path_is_absolute (filename+1))
|
||||||
|
offs = 1;
|
||||||
|
|
||||||
|
result = g_filename_from_utf8 (filename + offs, -1, NULL, NULL, error);
|
||||||
|
g_free (filename);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_filename_to_uri:
|
||||||
|
* @filename: an absolute filename specified in the encoding
|
||||||
|
* used for filenames by the operating system.
|
||||||
|
* @hostname: A UTF-8 encoded hostname, or %NULL for none.
|
||||||
|
* @error: location to store the error occuring, or %NULL to ignore
|
||||||
|
* errors. Any of the errors in #GConvertError may occur.
|
||||||
|
*
|
||||||
|
* Converts an absolute filename to an escaped UTF-8 encoded URI.
|
||||||
|
*
|
||||||
|
* Return value: a newly allocated string holding the resulting
|
||||||
|
* URI, or %NULL on an error.
|
||||||
|
**/
|
||||||
|
gchar *
|
||||||
|
g_filename_to_uri (const char *filename,
|
||||||
|
char *hostname,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
char *escaped_uri;
|
||||||
|
char *utf8_filename;
|
||||||
|
|
||||||
|
g_return_val_if_fail (filename != NULL, NULL);
|
||||||
|
|
||||||
|
if (!g_path_is_absolute (filename))
|
||||||
|
{
|
||||||
|
g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_NOT_ABSOLUTE_PATH,
|
||||||
|
_("The pathname '%s' is not an absolute path"),
|
||||||
|
filename);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
utf8_filename = g_filename_to_utf8 (filename, -1, NULL, NULL, error);
|
||||||
|
if (utf8_filename == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (hostname &&
|
||||||
|
!g_utf8_validate (hostname, -1, NULL))
|
||||||
|
{
|
||||||
|
g_free (utf8_filename);
|
||||||
|
g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
|
||||||
|
_("Invalid byte sequence in hostname"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
escaped_uri = g_escape_file_uri (hostname,
|
||||||
|
utf8_filename);
|
||||||
|
g_free (utf8_filename);
|
||||||
|
|
||||||
|
return escaped_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,10 @@ typedef enum
|
|||||||
G_CONVERT_ERROR_NO_CONVERSION,
|
G_CONVERT_ERROR_NO_CONVERSION,
|
||||||
G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
|
G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
|
||||||
G_CONVERT_ERROR_FAILED,
|
G_CONVERT_ERROR_FAILED,
|
||||||
G_CONVERT_ERROR_PARTIAL_INPUT
|
G_CONVERT_ERROR_PARTIAL_INPUT,
|
||||||
|
G_CONVERT_ERROR_NOT_LOCAL_FILE,
|
||||||
|
G_CONVERT_ERROR_INVALID_URI,
|
||||||
|
G_CONVERT_ERROR_NOT_ABSOLUTE_PATH
|
||||||
} GConvertError;
|
} GConvertError;
|
||||||
|
|
||||||
#define G_CONVERT_ERROR g_convert_error_quark()
|
#define G_CONVERT_ERROR g_convert_error_quark()
|
||||||
@ -107,6 +110,15 @@ gchar* g_filename_from_utf8 (const gchar *utf8string,
|
|||||||
gsize *bytes_written,
|
gsize *bytes_written,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
gchar *g_filename_from_uri (const char *uri,
|
||||||
|
char **hostname,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
gchar *g_filename_to_uri (const char *filename,
|
||||||
|
char *hostname,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __G_CONVERT_H__ */
|
#endif /* __G_CONVERT_H__ */
|
||||||
|
@ -75,7 +75,8 @@ test_programs = \
|
|||||||
tree-test \
|
tree-test \
|
||||||
type-test \
|
type-test \
|
||||||
unicode-caseconv \
|
unicode-caseconv \
|
||||||
unicode-encoding
|
unicode-encoding \
|
||||||
|
uri-test
|
||||||
|
|
||||||
test_scripts = run-markup-tests.sh
|
test_scripts = run-markup-tests.sh
|
||||||
|
|
||||||
@ -117,6 +118,7 @@ tree_test_LDADD = $(progs_LDADD)
|
|||||||
type_test_LDADD = $(progs_LDADD)
|
type_test_LDADD = $(progs_LDADD)
|
||||||
unicode_encoding_LDADD = $(progs_LDADD)
|
unicode_encoding_LDADD = $(progs_LDADD)
|
||||||
unicode_caseconv_LDADD = $(progs_LDADD)
|
unicode_caseconv_LDADD = $(progs_LDADD)
|
||||||
|
uri_test_LDADD = $(progs_LDADD)
|
||||||
|
|
||||||
lib_LTLIBRARIES = libmoduletestplugin_a.la libmoduletestplugin_b.la
|
lib_LTLIBRARIES = libmoduletestplugin_a.la libmoduletestplugin_b.la
|
||||||
|
|
||||||
|
224
tests/uri-test.c
Normal file
224
tests/uri-test.c
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
/* GLIB - Library of useful routines for C programming
|
||||||
|
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||||
|
* file for a list of people on the GLib Team. See the ChangeLog
|
||||||
|
* files for a list of changes. These files are distributed with
|
||||||
|
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#undef G_DISABLE_ASSERT
|
||||||
|
#undef G_LOG_DOMAIN
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char *filename;
|
||||||
|
char *hostname;
|
||||||
|
char *expected_result;
|
||||||
|
GConvertError expected_error; /* If failed */
|
||||||
|
} ToUriTest;
|
||||||
|
|
||||||
|
ToUriTest
|
||||||
|
to_uri_tests[] = {
|
||||||
|
{ "/etc", NULL, "file:///etc"},
|
||||||
|
{ "/etc", "", "file:///etc"},
|
||||||
|
{ "/etc", "localhost", "file://localhost/etc"},
|
||||||
|
#ifdef G_OS_WIN32
|
||||||
|
{ "c:\\windows", NULL, "file:///c:\\windows"},
|
||||||
|
{ "c:\\windows", "localhost", "file://localhost/c:\\windows"},
|
||||||
|
#endif
|
||||||
|
{ "etc", "localhost", NULL, G_CONVERT_ERROR_NOT_ABSOLUTE_PATH},
|
||||||
|
{ "/etc/öäå", NULL, NULL, G_CONVERT_ERROR_ILLEGAL_SEQUENCE},
|
||||||
|
{ "/etc/öäå", NULL, "file:///etc/%C3%B6%C3%A4%C3%A5"},
|
||||||
|
{ "/etc", "öäå", "file://%C3%B6%C3%A4%C3%A5/etc"},
|
||||||
|
{ "/etc", "åäö", NULL, G_CONVERT_ERROR_ILLEGAL_SEQUENCE},
|
||||||
|
{ "/etc/file with #%", NULL, "file:///etc/file%20with%20%23%25"},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char *uri;
|
||||||
|
char *expected_filename;
|
||||||
|
char *expected_hostname;
|
||||||
|
GConvertError expected_error; /* If failed */
|
||||||
|
} FromUriTest;
|
||||||
|
|
||||||
|
FromUriTest
|
||||||
|
from_uri_tests[] = {
|
||||||
|
{ "file:///etc", "/etc", NULL},
|
||||||
|
{ "file:/etc", "/etc", NULL},
|
||||||
|
{ "file://localhost/etc", "/etc", "localhost", },
|
||||||
|
{ "file://localhost/etc/%23%25%20file", "/etc/#% file", "localhost", },
|
||||||
|
{ "file://%C3%B6%C3%A4%C3%A5/etc", "/etc", "öäå", },
|
||||||
|
{ "file:////etc/%C3%B6%C3%C3%C3%A5", NULL, NULL, G_CONVERT_ERROR_INVALID_URI},
|
||||||
|
{ "file://localhost/åäö", NULL, NULL, G_CONVERT_ERROR_INVALID_URI},
|
||||||
|
{ "file://åäö/etc", NULL, NULL, G_CONVERT_ERROR_INVALID_URI},
|
||||||
|
{ "file:///some/file#bad", NULL, NULL, G_CONVERT_ERROR_INVALID_URI},
|
||||||
|
{ "file://some", NULL, NULL, G_CONVERT_ERROR_INVALID_URI},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean any_failed = FALSE;
|
||||||
|
|
||||||
|
static void
|
||||||
|
run_to_uri_tests (void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
gchar *res;
|
||||||
|
GError *error;
|
||||||
|
|
||||||
|
for (i = 0; i < G_N_ELEMENTS (to_uri_tests); i++)
|
||||||
|
{
|
||||||
|
error = NULL;
|
||||||
|
res = g_filename_to_uri (to_uri_tests[i].filename,
|
||||||
|
to_uri_tests[i].hostname,
|
||||||
|
&error);
|
||||||
|
|
||||||
|
if (to_uri_tests[i].expected_result == NULL)
|
||||||
|
{
|
||||||
|
if (res != NULL)
|
||||||
|
{
|
||||||
|
g_print ("\ng_filename_to_uri() test %d failed, expected to return NULL, actual result: %s\n", i, res);
|
||||||
|
any_failed = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (error == NULL)
|
||||||
|
{
|
||||||
|
g_print ("\ng_filename_to_uri() test %d failed, returned NULL, but didn't set error\n", i);
|
||||||
|
any_failed = TRUE;
|
||||||
|
}
|
||||||
|
else if (error->domain != G_CONVERT_ERROR)
|
||||||
|
{
|
||||||
|
g_print ("\ng_filename_to_uri() test %d failed, returned NULL, set non G_CONVERT_ERROR error\n", i);
|
||||||
|
any_failed = TRUE;
|
||||||
|
}
|
||||||
|
else if (error->code != to_uri_tests[i].expected_error)
|
||||||
|
{
|
||||||
|
g_print ("\ng_filename_to_uri() test %d failed as expected, but set wrong errorcode %d instead of expected %d \n",
|
||||||
|
i, error->code, to_uri_tests[i].expected_error);
|
||||||
|
any_failed = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (res == NULL || strcmp (res, to_uri_tests[i].expected_result) != 0)
|
||||||
|
{
|
||||||
|
g_print ("\ng_filename_to_uri() test %d failed, expected result: %s, actual result: %s\n",
|
||||||
|
i, to_uri_tests[i].expected_result, (res) ? res : "NULL");
|
||||||
|
if (error)
|
||||||
|
g_print ("Error message: %s\n", error->message);
|
||||||
|
any_failed = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Give some output */
|
||||||
|
g_print (".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
run_from_uri_tests (void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
gchar *res;
|
||||||
|
gchar *hostname;
|
||||||
|
GError *error;
|
||||||
|
|
||||||
|
for (i = 0; i < G_N_ELEMENTS (from_uri_tests); i++)
|
||||||
|
{
|
||||||
|
error = NULL;
|
||||||
|
res = g_filename_from_uri (from_uri_tests[i].uri,
|
||||||
|
&hostname,
|
||||||
|
&error);
|
||||||
|
|
||||||
|
if (from_uri_tests[i].expected_filename == NULL)
|
||||||
|
{
|
||||||
|
if (res != NULL)
|
||||||
|
{
|
||||||
|
g_print ("\ng_filename_from_uri() test %d failed, expected to return NULL, actual result: %s\n", i, res);
|
||||||
|
any_failed = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (error == NULL)
|
||||||
|
{
|
||||||
|
g_print ("\ng_filename_from_uri() test %d failed, returned NULL, but didn't set error\n", i);
|
||||||
|
any_failed = TRUE;
|
||||||
|
}
|
||||||
|
else if (error->domain != G_CONVERT_ERROR)
|
||||||
|
{
|
||||||
|
g_print ("\ng_filename_from_uri() test %d failed, returned NULL, set non G_CONVERT_ERROR error\n", i);
|
||||||
|
any_failed = TRUE;
|
||||||
|
}
|
||||||
|
else if (error->code != from_uri_tests[i].expected_error)
|
||||||
|
{
|
||||||
|
g_print ("\ng_filename_from_uri() test %d failed as expected, but set wrong errorcode %d instead of expected %d \n",
|
||||||
|
i, error->code, from_uri_tests[i].expected_error);
|
||||||
|
any_failed = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (res == NULL || strcmp (res, from_uri_tests[i].expected_filename) != 0)
|
||||||
|
{
|
||||||
|
g_print ("\ng_filename_from_uri() test %d failed, expected result: %s, actual result: %s\n",
|
||||||
|
i, from_uri_tests[i].expected_filename, (res) ? res : "NULL");
|
||||||
|
any_failed = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (from_uri_tests[i].expected_hostname == NULL)
|
||||||
|
{
|
||||||
|
if (hostname != NULL)
|
||||||
|
{
|
||||||
|
g_print ("\ng_filename_from_uri() test %d failed, expected no hostname, got: %s\n",
|
||||||
|
i, hostname);
|
||||||
|
any_failed = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (hostname == NULL ||
|
||||||
|
strcmp (hostname, from_uri_tests[i].expected_hostname) != 0)
|
||||||
|
{
|
||||||
|
g_print ("\ng_filename_from_uri() test %d failed, expected hostname: %s, actual result: %s\n",
|
||||||
|
i, from_uri_tests[i].expected_hostname, (hostname) ? hostname : "NULL");
|
||||||
|
any_failed = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Give some output */
|
||||||
|
g_print (".");
|
||||||
|
}
|
||||||
|
g_print ("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc,
|
||||||
|
char *argv[])
|
||||||
|
{
|
||||||
|
run_to_uri_tests ();
|
||||||
|
run_from_uri_tests ();
|
||||||
|
|
||||||
|
return any_failed ? 1 : 0;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user