mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-09-27 17:52:58 +02:00
guri: new URI parsing and generating functions
Add a set of new URI parsing and generating functions, including a new parsed-URI type GUri. Move all the code from gurifuncs.c into guri.c, reimplementing some of those functions (and g_string_append_uri_encoded()) in terms of the new code.
This commit is contained in:
@@ -80,7 +80,7 @@
|
|||||||
<xi:include href="xml/timers.xml" />
|
<xi:include href="xml/timers.xml" />
|
||||||
<xi:include href="xml/spawn.xml" />
|
<xi:include href="xml/spawn.xml" />
|
||||||
<xi:include href="xml/fileutils.xml" />
|
<xi:include href="xml/fileutils.xml" />
|
||||||
<xi:include href="xml/gurifuncs.xml" />
|
<xi:include href="xml/guri.xml" />
|
||||||
<xi:include href="xml/ghostutils.xml" />
|
<xi:include href="xml/ghostutils.xml" />
|
||||||
<xi:include href="xml/shell.xml" />
|
<xi:include href="xml/shell.xml" />
|
||||||
<xi:include href="xml/option.xml" />
|
<xi:include href="xml/option.xml" />
|
||||||
|
@@ -2856,19 +2856,60 @@ g_base64_decode_inplace
|
|||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<TITLE>URI Functions</TITLE>
|
<TITLE>URI Functions</TITLE>
|
||||||
<FILE>gurifuncs</FILE>
|
<FILE>guri</FILE>
|
||||||
|
GUri
|
||||||
|
g_uri_ref
|
||||||
|
g_uri_unref
|
||||||
|
<SUBSECTION>
|
||||||
|
GUriFlags
|
||||||
|
g_uri_split
|
||||||
|
g_uri_split_with_user
|
||||||
|
g_uri_split_network
|
||||||
|
g_uri_is_valid
|
||||||
|
g_uri_join
|
||||||
|
g_uri_join_with_user
|
||||||
|
g_uri_parse
|
||||||
|
g_uri_parse_relative
|
||||||
|
g_uri_resolve_relative
|
||||||
|
g_uri_build
|
||||||
|
g_uri_build_with_user
|
||||||
|
g_uri_peek_scheme
|
||||||
|
g_uri_parse_scheme
|
||||||
|
<SUBSECTION>
|
||||||
|
GUriHideFlags;
|
||||||
|
g_uri_to_string
|
||||||
|
g_uri_to_string_partial
|
||||||
|
<SUBSECTION>
|
||||||
|
g_uri_get_scheme
|
||||||
|
g_uri_get_userinfo
|
||||||
|
g_uri_get_user
|
||||||
|
g_uri_get_password
|
||||||
|
g_uri_get_auth_params
|
||||||
|
g_uri_get_host
|
||||||
|
g_uri_get_port
|
||||||
|
g_uri_get_path
|
||||||
|
g_uri_get_query
|
||||||
|
g_uri_get_fragment
|
||||||
|
<SUBSECTION>
|
||||||
|
g_uri_parse_params
|
||||||
|
<SUBSECTION>
|
||||||
G_URI_RESERVED_CHARS_ALLOWED_IN_PATH
|
G_URI_RESERVED_CHARS_ALLOWED_IN_PATH
|
||||||
G_URI_RESERVED_CHARS_ALLOWED_IN_PATH_ELEMENT
|
G_URI_RESERVED_CHARS_ALLOWED_IN_PATH_ELEMENT
|
||||||
G_URI_RESERVED_CHARS_ALLOWED_IN_USERINFO
|
G_URI_RESERVED_CHARS_ALLOWED_IN_USERINFO
|
||||||
G_URI_RESERVED_CHARS_GENERIC_DELIMITERS
|
G_URI_RESERVED_CHARS_GENERIC_DELIMITERS
|
||||||
G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS
|
G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS
|
||||||
g_uri_parse_scheme
|
|
||||||
g_uri_escape_string
|
g_uri_escape_string
|
||||||
g_uri_unescape_string
|
g_uri_unescape_string
|
||||||
g_uri_unescape_segment
|
g_uri_unescape_segment
|
||||||
|
<SUBSECTION>
|
||||||
g_uri_list_extract_uris
|
g_uri_list_extract_uris
|
||||||
g_filename_from_uri
|
g_filename_from_uri
|
||||||
g_filename_to_uri
|
g_filename_to_uri
|
||||||
|
<SUBSECTION>
|
||||||
|
G_URI_ERROR
|
||||||
|
GUriError
|
||||||
|
<SUBSECTION Private>
|
||||||
|
g_uri_error_quark
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
|
@@ -390,6 +390,7 @@ G_TYPE_MARKUP_PARSE_CONTEXT
|
|||||||
G_TYPE_SOURCE
|
G_TYPE_SOURCE
|
||||||
G_TYPE_POLLFD
|
G_TYPE_POLLFD
|
||||||
G_TYPE_THREAD
|
G_TYPE_THREAD
|
||||||
|
G_TYPE_URI
|
||||||
GStrv
|
GStrv
|
||||||
|
|
||||||
<SUBSECTION Standard>
|
<SUBSECTION Standard>
|
||||||
|
@@ -184,7 +184,7 @@ libglib_2_0_la_SOURCES = \
|
|||||||
gunidecomp.h \
|
gunidecomp.h \
|
||||||
gunidecomp.c \
|
gunidecomp.c \
|
||||||
gunicodeprivate.h \
|
gunicodeprivate.h \
|
||||||
gurifuncs.c \
|
guri.c \
|
||||||
gutils.c \
|
gutils.c \
|
||||||
gvariant.h \
|
gvariant.h \
|
||||||
gvariant.c \
|
gvariant.c \
|
||||||
@@ -304,7 +304,7 @@ glibsubinclude_HEADERS = \
|
|||||||
gtree.h \
|
gtree.h \
|
||||||
gtypes.h \
|
gtypes.h \
|
||||||
gunicode.h \
|
gunicode.h \
|
||||||
gurifuncs.h \
|
guri.h \
|
||||||
gutils.h \
|
gutils.h \
|
||||||
gvarianttype.h \
|
gvarianttype.h \
|
||||||
gvariant.h \
|
gvariant.h \
|
||||||
|
@@ -88,7 +88,7 @@
|
|||||||
#include <glib/gtree.h>
|
#include <glib/gtree.h>
|
||||||
#include <glib/gtypes.h>
|
#include <glib/gtypes.h>
|
||||||
#include <glib/gunicode.h>
|
#include <glib/gunicode.h>
|
||||||
#include <glib/gurifuncs.h>
|
#include <glib/guri.h>
|
||||||
#include <glib/gutils.h>
|
#include <glib/gutils.h>
|
||||||
#include <glib/gvarianttype.h>
|
#include <glib/gvarianttype.h>
|
||||||
#include <glib/gvariant.h>
|
#include <glib/gvariant.h>
|
||||||
|
@@ -495,90 +495,6 @@ g_string_insert_len (GString *string,
|
|||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SUB_DELIM_CHARS "!$&'()*+,;="
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
is_valid (char c,
|
|
||||||
const char *reserved_chars_allowed)
|
|
||||||
{
|
|
||||||
if (g_ascii_isalnum (c) ||
|
|
||||||
c == '-' ||
|
|
||||||
c == '.' ||
|
|
||||||
c == '_' ||
|
|
||||||
c == '~')
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
if (reserved_chars_allowed &&
|
|
||||||
strchr (reserved_chars_allowed, c) != NULL)
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gunichar_ok (gunichar c)
|
|
||||||
{
|
|
||||||
return
|
|
||||||
(c != (gunichar) -2) &&
|
|
||||||
(c != (gunichar) -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* g_string_append_uri_escaped:
|
|
||||||
* @string: a #GString
|
|
||||||
* @unescaped: a string
|
|
||||||
* @reserved_chars_allowed: a string of reserved characters allowed
|
|
||||||
* to be used, or %NULL
|
|
||||||
* @allow_utf8: set %TRUE if the escaped string may include UTF8 characters
|
|
||||||
*
|
|
||||||
* Appends @unescaped to @string, escaped any characters that
|
|
||||||
* are reserved in URIs using URI-style escape sequences.
|
|
||||||
*
|
|
||||||
* Returns: @string
|
|
||||||
*
|
|
||||||
* Since: 2.16
|
|
||||||
*/
|
|
||||||
GString *
|
|
||||||
g_string_append_uri_escaped (GString *string,
|
|
||||||
const gchar *unescaped,
|
|
||||||
const gchar *reserved_chars_allowed,
|
|
||||||
gboolean allow_utf8)
|
|
||||||
{
|
|
||||||
unsigned char c;
|
|
||||||
const gchar *end;
|
|
||||||
static const gchar hex[16] = "0123456789ABCDEF";
|
|
||||||
|
|
||||||
g_return_val_if_fail (string != NULL, NULL);
|
|
||||||
g_return_val_if_fail (unescaped != NULL, NULL);
|
|
||||||
|
|
||||||
end = unescaped + strlen (unescaped);
|
|
||||||
|
|
||||||
while ((c = *unescaped) != 0)
|
|
||||||
{
|
|
||||||
if (c >= 0x80 && allow_utf8 &&
|
|
||||||
gunichar_ok (g_utf8_get_char_validated (unescaped, end - unescaped)))
|
|
||||||
{
|
|
||||||
int len = g_utf8_skip [c];
|
|
||||||
g_string_append_len (string, unescaped, len);
|
|
||||||
unescaped += len;
|
|
||||||
}
|
|
||||||
else if (is_valid (c, reserved_chars_allowed))
|
|
||||||
{
|
|
||||||
g_string_append_c (string, c);
|
|
||||||
unescaped++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_string_append_c (string, '%');
|
|
||||||
g_string_append_c (string, hex[((guchar)c) >> 4]);
|
|
||||||
g_string_append_c (string, hex[((guchar)c) & 0xf]);
|
|
||||||
unescaped++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_string_append:
|
* g_string_append:
|
||||||
* @string: a #GString
|
* @string: a #GString
|
||||||
|
220
glib/guri-notes.txt
Normal file
220
glib/guri-notes.txt
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
aaa/aaas (rfc3588):
|
||||||
|
aaa://host[:port][;transport=tcp][;protocol=diameter]
|
||||||
|
technically violates 3986, since ";" could appear in authority
|
||||||
|
|
||||||
|
acap (rfc2244):
|
||||||
|
acap://[user[;AUTH=mech]@]host[:port]/data
|
||||||
|
|
||||||
|
cap (rfc4324):
|
||||||
|
cap://host[:port][/data]
|
||||||
|
|
||||||
|
cid/mid (rfc2392):
|
||||||
|
cid:content-id-data
|
||||||
|
mid:message-id-data[/content-id-data]
|
||||||
|
|
||||||
|
crid (rfc4078):
|
||||||
|
crid://host/data
|
||||||
|
|
||||||
|
data (rfc2397):
|
||||||
|
data:[type/subtype][;attr=value]*[;base64],data
|
||||||
|
|
||||||
|
dav (rfc4918):
|
||||||
|
dav:data
|
||||||
|
opaquelocktoken:uuid[path]
|
||||||
|
|
||||||
|
dict (rfc2229):
|
||||||
|
dict://[user[;authmech]@]host[:port]/d:word[:database[:nth]]
|
||||||
|
dict://[user[;authmech]@]host[:port]/m:word[:database[:strategy[:nth]]]
|
||||||
|
|
||||||
|
dns (rfc4501):
|
||||||
|
dns:[//host[:port]/]name[?[attr=value[;attr=value]*]]
|
||||||
|
|
||||||
|
file (rfc1738):
|
||||||
|
file://[host]/path
|
||||||
|
|
||||||
|
ftp (rfc1738):
|
||||||
|
ftp://[user[:pass]@]host[:port][/path[;type=type]]
|
||||||
|
|
||||||
|
geo (draft...):
|
||||||
|
geo:data
|
||||||
|
|
||||||
|
go (rfc3368):
|
||||||
|
go:[//host[:port]?]data[;attr=[type,]value]*
|
||||||
|
|
||||||
|
gopher (rfc4266):
|
||||||
|
gopher://host[:port]/path
|
||||||
|
|
||||||
|
h323 (rfc3508):
|
||||||
|
h323:[user@]host[:port][;params]*
|
||||||
|
|
||||||
|
http (rfc 2616):
|
||||||
|
http://host[:port][/path[?query]]
|
||||||
|
|
||||||
|
https (rfc 2818):
|
||||||
|
https://host[:port][/path[?query]]
|
||||||
|
|
||||||
|
iax (rfc 5456):
|
||||||
|
iax:[user@]host[:port][/number[?context]]
|
||||||
|
|
||||||
|
icap (rfc3507):
|
||||||
|
icap://[userinfo@]host[:port]/path[?query]
|
||||||
|
|
||||||
|
im (rfc3860):
|
||||||
|
im:mailbox[?[header=value[;header=value]*]]
|
||||||
|
|
||||||
|
imap (rfc5092):
|
||||||
|
imap://[user[;AUTH=mech]@]host[:port][/[mailbox[validity]]]
|
||||||
|
imap://[user[;AUTH=mech]@]host[:port]/mailbox[validity]?search
|
||||||
|
imap://[user[;AUTH=mech]@]host[:port]/mailbox[validity]uid[sect][part][auth]
|
||||||
|
|
||||||
|
info (rfc4452):
|
||||||
|
info:namespace/identifier[#fragment]
|
||||||
|
|
||||||
|
ipp (rfc3510):
|
||||||
|
ipp://host[:port][/path[?query]]
|
||||||
|
|
||||||
|
iris (rfc3981, 3983, 4992, 4993):
|
||||||
|
iris[.transport]:urn/[method]/[userinfo@]host[:port][/class/name]
|
||||||
|
|
||||||
|
ldap (rfc4516):
|
||||||
|
ldap://[host[:port]][/dn[?[attrs][?[scope][?[filter][?exts]]]]]
|
||||||
|
|
||||||
|
mailto (rfc2368):
|
||||||
|
mailto:mailbox[?[header=value[;header=value]*]]
|
||||||
|
|
||||||
|
msrp (rfc4975):
|
||||||
|
msrp://authority[/id];tcp[;attr=value]*
|
||||||
|
msrps://authority[/id];tcp[;attr=value]*
|
||||||
|
technically violates 3986, since ";" could appear in authority
|
||||||
|
|
||||||
|
mtqp (rfc3887):
|
||||||
|
mtqp://authority/track/id/secret
|
||||||
|
|
||||||
|
mupdate (rfc3656):
|
||||||
|
based on imap
|
||||||
|
|
||||||
|
news/nntp (rfc5538):
|
||||||
|
news:[//authority/]article-or-groups
|
||||||
|
nntp://authority/group[/article]
|
||||||
|
|
||||||
|
nfs (rfc2224):
|
||||||
|
nfs://host[:port][path]
|
||||||
|
|
||||||
|
pop (rfc2384):
|
||||||
|
pop://[[user][;auth=mech]@]host[:port]
|
||||||
|
|
||||||
|
pres (rfc3859):
|
||||||
|
pres:mailbox[?[header=value[;header=value]*]]
|
||||||
|
|
||||||
|
rtsp (rfc2326):
|
||||||
|
rtsp://host[:port][path]
|
||||||
|
rtspu://host[:port][path]
|
||||||
|
|
||||||
|
service (rfc2609):
|
||||||
|
service:... (possibly including authority)
|
||||||
|
|
||||||
|
shttp (rfc2660):
|
||||||
|
http-ish
|
||||||
|
|
||||||
|
sieve (draft...):
|
||||||
|
sieve://authority[path]
|
||||||
|
|
||||||
|
sip (3261)
|
||||||
|
sip:[user[:pass]@]host[:port][;name=val]*[?hname=hval[&hname=hval]*]
|
||||||
|
sips:[user[:pass]@]host[:port][;name=val]*[?hname=hval[&hname=hval]*]
|
||||||
|
|
||||||
|
sms (5724)
|
||||||
|
sms:phone[,phone]*[?name=val[&name=val]*]
|
||||||
|
|
||||||
|
snmp (4088)
|
||||||
|
snmp://[userinfo@]host[:port][/context...]
|
||||||
|
|
||||||
|
soap.beep (4227)
|
||||||
|
standard
|
||||||
|
|
||||||
|
tag (4151)
|
||||||
|
tag:host-or-email,8601date:data[#fragment]
|
||||||
|
|
||||||
|
tel (3966)
|
||||||
|
tel:number[;attr=value]*
|
||||||
|
|
||||||
|
telnet (4248)
|
||||||
|
telnet://[user[:pass]@]host[:port][/]
|
||||||
|
|
||||||
|
tftp (3617)
|
||||||
|
tftp://host/file[;mode=type]
|
||||||
|
|
||||||
|
tip (2371)
|
||||||
|
tip://host[:port]/path?trans
|
||||||
|
|
||||||
|
tv (2838)
|
||||||
|
tv:dnsid
|
||||||
|
|
||||||
|
urn (2141)
|
||||||
|
urn:data
|
||||||
|
|
||||||
|
vemmi (2122)
|
||||||
|
vemmi://host[:port]/service[;attr=val]*
|
||||||
|
|
||||||
|
xmlrpc.beep (3529)
|
||||||
|
standard
|
||||||
|
|
||||||
|
xmpp (5122)
|
||||||
|
xmpp:[//node@host[/]][[node@]host[/resource]][?query[;attr=val]*][#fragment]
|
||||||
|
|
||||||
|
x39.50 (2056)
|
||||||
|
z39.50r://host[:port][/[database[?docid]][;esn=data][;rs=data]]
|
||||||
|
z39.50s://host[:port][/[database[?docid]][;esn=data][;rs=data]]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
HTML5 rules:
|
||||||
|
- strip leading and trailing spaces
|
||||||
|
- chars less than U+0020 or greater than U+007F in unreserved
|
||||||
|
- U+0022, U+003C, U+003E, U+005B..E, U+0060, U+007B..D in unreserved
|
||||||
|
( " < > [ \ ] ^ ` { | } ~ )
|
||||||
|
- Allow single % except in hostname
|
||||||
|
- Allow # in fragment
|
||||||
|
- if host has non-UTF8 %-encoded, fail
|
||||||
|
- if host fails IDNA ToASCII, fail
|
||||||
|
- forcibly %-encode all reserved/non-ASCII path chars
|
||||||
|
- re-encode query to the URL's encoding (from enclosing doc) and
|
||||||
|
%-encode. replace unencodable chars with '?'
|
||||||
|
- if fully-resolved URI uses authority, replace all \ with /
|
||||||
|
|
||||||
|
|
||||||
|
gvfs and EUri both allow '@' in username
|
||||||
|
EUri does "parameters", but seems unused
|
||||||
|
hide_password in to_string
|
||||||
|
CamelURL does hide_auth too
|
||||||
|
CamelURL does params and uses them
|
||||||
|
CamelURL special-cases file URLs on win32 (via g_filename_to/from_uri)
|
||||||
|
|
||||||
|
|
||||||
|
http://www.freedesktop.org/wiki/Specifications/file-uri-spec says:
|
||||||
|
non-ASCII chars are %-encoded
|
||||||
|
URIs are in filesystem encoding, NOT UTF-8
|
||||||
|
accept "file:/path" for compat
|
||||||
|
http://blogs.msdn.com/ie/archive/2006/12/06/file-uris-in-windows.aspx:
|
||||||
|
IE allows "file://" + windows path (eg, "file://D:\blah blah\bl%h")
|
||||||
|
file://// == file://
|
||||||
|
don't use %-encoding for non-ASCII, just use non-ASCII.
|
||||||
|
(http://en.wikipedia.org/wiki/File_URI_scheme contradicts this?)
|
||||||
|
IE allows "|" instead of ":" for drive separator, but very deprecated
|
||||||
|
MUST NOT use %-encoding where not required
|
||||||
|
|
||||||
|
Bug 489862 - Basic URI operations
|
||||||
|
https://bugzilla.gnome.org/show_bug.cgi?id=489862
|
||||||
|
|
||||||
|
Bug 620417 - g_uri_unescape_string cannot unescape %00
|
||||||
|
https://bugzilla.gnome.org/show_bug.cgi?id=620417
|
||||||
|
|
||||||
|
Bug 611687 - gconvert g_filename_to_uri doesn't do what the documentation says
|
||||||
|
https://bugzilla.gnome.org/show_bug.cgi?id=611687
|
||||||
|
|
||||||
|
Bug 550110 - RFC: g_uri_is_valid (from GStreamer gst_uri_is_valid)
|
||||||
|
https://bugzilla.gnome.org/show_bug.cgi?id=550110
|
||||||
|
|
||||||
|
Add fireball URI matcher
|
||||||
|
(make sure it does email addresses too)
|
||||||
|
|
2323
glib/guri.c
Normal file
2323
glib/guri.c
Normal file
File diff suppressed because it is too large
Load Diff
286
glib/guri.h
Normal file
286
glib/guri.h
Normal file
@@ -0,0 +1,286 @@
|
|||||||
|
/* GLIB - Library of useful routines for C programming
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Copyright 2010-2013 Red Hat, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||||
|
#error "Only <glib.h> can be included directly."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __G_URI_H__
|
||||||
|
#define __G_URI_H__
|
||||||
|
|
||||||
|
#include <glib/gtypes.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef struct _GUri GUri;
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
GUri * g_uri_ref (GUri *uri);
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
void g_uri_unref (GUri *uri);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
G_URI_PARSE_STRICT = 1 << 0,
|
||||||
|
G_URI_HAS_PASSWORD = 1 << 1,
|
||||||
|
G_URI_HAS_AUTH_PARAMS = 1 << 2,
|
||||||
|
G_URI_ENCODED = 1 << 3,
|
||||||
|
G_URI_NON_DNS = 1 << 4,
|
||||||
|
} GUriFlags;
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
gboolean g_uri_split (const gchar *uri_string,
|
||||||
|
GUriFlags flags,
|
||||||
|
gchar **scheme,
|
||||||
|
gchar **userinfo,
|
||||||
|
gchar **host,
|
||||||
|
gint *port,
|
||||||
|
gchar **path,
|
||||||
|
gchar **query,
|
||||||
|
gchar **fragment,
|
||||||
|
GError **error);
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
gboolean g_uri_split_with_user (const gchar *uri_string,
|
||||||
|
GUriFlags flags,
|
||||||
|
gchar **scheme,
|
||||||
|
gchar **user,
|
||||||
|
gchar **password,
|
||||||
|
gchar **auth_params,
|
||||||
|
gchar **host,
|
||||||
|
gint *port,
|
||||||
|
gchar **path,
|
||||||
|
gchar **query,
|
||||||
|
gchar **fragment,
|
||||||
|
GError **error);
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
gboolean g_uri_split_network (const gchar *uri_string,
|
||||||
|
GUriFlags flags,
|
||||||
|
gchar **scheme,
|
||||||
|
gchar **host,
|
||||||
|
gint *port,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
gboolean g_uri_is_valid (const gchar *uri_string,
|
||||||
|
GUriFlags flags,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
gchar * g_uri_join (GUriFlags flags,
|
||||||
|
const gchar *scheme,
|
||||||
|
const gchar *userinfo,
|
||||||
|
const gchar *host,
|
||||||
|
gint port,
|
||||||
|
const gchar *path,
|
||||||
|
const gchar *query,
|
||||||
|
const gchar *fragment);
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
gchar * g_uri_join_with_user (GUriFlags flags,
|
||||||
|
const gchar *scheme,
|
||||||
|
const gchar *user,
|
||||||
|
const gchar *password,
|
||||||
|
const gchar *auth_params,
|
||||||
|
const gchar *host,
|
||||||
|
gint port,
|
||||||
|
const gchar *path,
|
||||||
|
const gchar *query,
|
||||||
|
const gchar *fragment);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
GUri * g_uri_parse (const gchar *uri_string,
|
||||||
|
GUriFlags flags,
|
||||||
|
GError **error);
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
GUri * g_uri_parse_relative (GUri *base_uri,
|
||||||
|
const gchar *uri_string,
|
||||||
|
GUriFlags flags,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
gchar * g_uri_resolve_relative (const gchar *base_uri_string,
|
||||||
|
const gchar *uri_string,
|
||||||
|
GUriFlags flags,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
GUri * g_uri_build (GUriFlags flags,
|
||||||
|
const gchar *scheme,
|
||||||
|
const gchar *userinfo,
|
||||||
|
const gchar *host,
|
||||||
|
gint port,
|
||||||
|
const gchar *path,
|
||||||
|
const gchar *query,
|
||||||
|
const gchar *fragment);
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
GUri * g_uri_build_with_user (GUriFlags flags,
|
||||||
|
const gchar *scheme,
|
||||||
|
const gchar *user,
|
||||||
|
const gchar *password,
|
||||||
|
const gchar *auth_params,
|
||||||
|
const gchar *host,
|
||||||
|
gint port,
|
||||||
|
const gchar *path,
|
||||||
|
const gchar *query,
|
||||||
|
const gchar *fragment);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
G_URI_HIDE_USERINFO = 1 << 0,
|
||||||
|
G_URI_HIDE_PASSWORD = 1 << 1,
|
||||||
|
G_URI_HIDE_AUTH_PARAMS = 1 << 2,
|
||||||
|
G_URI_HIDE_FRAGMENT = 1 << 3,
|
||||||
|
} GUriHideFlags;
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
char * g_uri_to_string (GUri *uri);
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
char * g_uri_to_string_partial (GUri *uri,
|
||||||
|
GUriHideFlags flags);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
const gchar *g_uri_get_scheme (GUri *uri);
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
const gchar *g_uri_get_userinfo (GUri *uri);
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
const gchar *g_uri_get_user (GUri *uri);
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
const gchar *g_uri_get_password (GUri *uri);
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
const gchar *g_uri_get_auth_params (GUri *uri);
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
const gchar *g_uri_get_host (GUri *uri);
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
gint g_uri_get_port (GUri *uri);
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
const gchar *g_uri_get_path (GUri *uri);
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
const gchar *g_uri_get_query (GUri *uri);
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
const gchar *g_uri_get_fragment (GUri *uri);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
GHashTable * g_uri_parse_params (const gchar *params,
|
||||||
|
gssize length,
|
||||||
|
gchar separator,
|
||||||
|
gboolean case_insensitive);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* G_URI_ERROR:
|
||||||
|
*
|
||||||
|
* Error domain for URI methods. Errors in this domain will be from
|
||||||
|
* the #GUriError enumeration. See #GError for information on error
|
||||||
|
* domains.
|
||||||
|
*/
|
||||||
|
#define G_URI_ERROR (g_uri_error_quark ())
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
GQuark g_uri_error_quark (void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GUriError:
|
||||||
|
* @G_URI_ERROR_MISC: miscellaneous error
|
||||||
|
* @G_URI_ERROR_BAD_SCHEME: the scheme of a URI could not be parsed.
|
||||||
|
* @G_URI_ERROR_BAD_USER: the user/userinfo of a URI could not be parsed.
|
||||||
|
* @G_URI_ERROR_BAD_PASSWORD: the password of a URI could not be parsed.
|
||||||
|
* @G_URI_ERROR_BAD_AUTH_PARAMS: the authentication parameters of a URI could not be parsed.
|
||||||
|
* @G_URI_ERROR_BAD_HOST: the host of a URI could not be parsed.
|
||||||
|
* @G_URI_ERROR_BAD_PORT: the port of a URI could not be parsed.
|
||||||
|
* @G_URI_ERROR_BAD_PATH: the path of a URI could not be parsed.
|
||||||
|
* @G_URI_ERROR_BAD_QUERY: the query of a URI could not be parsed.
|
||||||
|
* @G_URI_ERROR_BAD_FRAGMENT: the fragment of a URI could not be parsed.
|
||||||
|
*
|
||||||
|
* Error codes returned by #GUri methods.
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
G_URI_ERROR_MISC,
|
||||||
|
G_URI_ERROR_BAD_SCHEME,
|
||||||
|
G_URI_ERROR_BAD_USER,
|
||||||
|
G_URI_ERROR_BAD_PASSWORD,
|
||||||
|
G_URI_ERROR_BAD_AUTH_PARAMS,
|
||||||
|
G_URI_ERROR_BAD_HOST,
|
||||||
|
G_URI_ERROR_BAD_PORT,
|
||||||
|
G_URI_ERROR_BAD_PATH,
|
||||||
|
G_URI_ERROR_BAD_QUERY,
|
||||||
|
G_URI_ERROR_BAD_FRAGMENT
|
||||||
|
} GUriError;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* G_URI_RESERVED_CHARS_GENERIC_DELIMITERS:
|
||||||
|
*
|
||||||
|
* Generic delimiters characters as defined in RFC 3986. Includes ":/?#[]@".
|
||||||
|
**/
|
||||||
|
#define G_URI_RESERVED_CHARS_GENERIC_DELIMITERS ":/?#[]@"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS:
|
||||||
|
*
|
||||||
|
* Subcomponent delimiter characters as defined in RFC 3986. Includes "!$&'()*+,;=".
|
||||||
|
**/
|
||||||
|
#define G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS "!$&'()*+,;="
|
||||||
|
|
||||||
|
/**
|
||||||
|
* G_URI_RESERVED_CHARS_ALLOWED_IN_PATH_ELEMENT:
|
||||||
|
*
|
||||||
|
* Allowed characters in path elements. Includes "!$&'()*+,;=:@".
|
||||||
|
**/
|
||||||
|
#define G_URI_RESERVED_CHARS_ALLOWED_IN_PATH_ELEMENT G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS ":@"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* G_URI_RESERVED_CHARS_ALLOWED_IN_PATH:
|
||||||
|
*
|
||||||
|
* Allowed characters in a path. Includes "!$&'()*+,;=:@/".
|
||||||
|
**/
|
||||||
|
#define G_URI_RESERVED_CHARS_ALLOWED_IN_PATH G_URI_RESERVED_CHARS_ALLOWED_IN_PATH_ELEMENT "/"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* G_URI_RESERVED_CHARS_ALLOWED_IN_USERINFO:
|
||||||
|
*
|
||||||
|
* Allowed characters in userinfo as defined in RFC 3986. Includes "!$&'()*+,;=:".
|
||||||
|
**/
|
||||||
|
#define G_URI_RESERVED_CHARS_ALLOWED_IN_USERINFO G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS ":"
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_ALL
|
||||||
|
char * g_uri_unescape_string (const char *escaped_string,
|
||||||
|
const char *illegal_characters);
|
||||||
|
GLIB_AVAILABLE_IN_ALL
|
||||||
|
char * g_uri_unescape_segment (const char *escaped_string,
|
||||||
|
const char *escaped_string_end,
|
||||||
|
const char *illegal_characters);
|
||||||
|
|
||||||
|
GLIB_DEPRECATED_IN_2_44_FOR(g_uri_peek_scheme)
|
||||||
|
char * g_uri_parse_scheme (const char *uri);
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
const char *g_uri_peek_scheme (const char *uri);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_ALL
|
||||||
|
char * g_uri_escape_string (const char *unescaped,
|
||||||
|
const char *reserved_chars_allowed,
|
||||||
|
gboolean allow_utf8);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
GBytes * g_uri_unescape_bytes (const char *escaped_string,
|
||||||
|
gssize length,
|
||||||
|
const char *illegal_characters);
|
||||||
|
GLIB_AVAILABLE_IN_2_44
|
||||||
|
char * g_uri_escape_bytes (const guchar *unescaped,
|
||||||
|
gsize length,
|
||||||
|
const char *reserved_chars_allowed);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __G_URI_H__ */
|
252
glib/gurifuncs.c
252
glib/gurifuncs.c
@@ -1,252 +0,0 @@
|
|||||||
/* GIO - GLib Input, Output and Streaming Library
|
|
||||||
*
|
|
||||||
* Copyright (C) 2006-2007 Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* 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, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Author: Alexander Larsson <alexl@redhat.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include "gurifuncs.h"
|
|
||||||
|
|
||||||
#include <glib/gstrfuncs.h>
|
|
||||||
#include <glib/gmessages.h>
|
|
||||||
#include <glib/gstring.h>
|
|
||||||
#include <glib/gmem.h>
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SECTION:gurifuncs
|
|
||||||
* @title: URI Functions
|
|
||||||
* @short_description: manipulating URIs
|
|
||||||
*
|
|
||||||
* Functions for manipulating Universal Resource Identifiers (URIs) as
|
|
||||||
* defined by
|
|
||||||
* [RFC 3986](http://www.ietf.org/rfc/rfc3986.txt).
|
|
||||||
* It is highly recommended that you have read and
|
|
||||||
* understand RFC 3986 for understanding this API.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* g_uri_unescape_segment:
|
|
||||||
* @escaped_string: (allow-none): A string, may be %NULL
|
|
||||||
* @escaped_string_end: (allow-none): Pointer to end of @escaped_string, may be %NULL
|
|
||||||
* @illegal_characters: (allow-none): An optional string of illegal characters not to be allowed, may be %NULL
|
|
||||||
*
|
|
||||||
* Unescapes a segment of an escaped string.
|
|
||||||
*
|
|
||||||
* If any of the characters in @illegal_characters or the character zero appears
|
|
||||||
* as an escaped character in @escaped_string then that is an error and %NULL
|
|
||||||
* will be returned. This is useful it you want to avoid for instance having a
|
|
||||||
* slash being expanded in an escaped path element, which might confuse pathname
|
|
||||||
* handling.
|
|
||||||
*
|
|
||||||
* Returns: an unescaped version of @escaped_string or %NULL on error.
|
|
||||||
* The returned string should be freed when no longer needed. As a
|
|
||||||
* special case if %NULL is given for @escaped_string, this function
|
|
||||||
* will return %NULL.
|
|
||||||
*
|
|
||||||
* Since: 2.16
|
|
||||||
**/
|
|
||||||
char *
|
|
||||||
g_uri_unescape_segment (const char *escaped_string,
|
|
||||||
const char *escaped_string_end,
|
|
||||||
const char *illegal_characters)
|
|
||||||
{
|
|
||||||
const char *in;
|
|
||||||
char *out, *result;
|
|
||||||
gint character;
|
|
||||||
|
|
||||||
if (escaped_string == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (escaped_string_end == NULL)
|
|
||||||
escaped_string_end = escaped_string + strlen (escaped_string);
|
|
||||||
|
|
||||||
result = g_malloc (escaped_string_end - escaped_string + 1);
|
|
||||||
|
|
||||||
out = result;
|
|
||||||
for (in = escaped_string; in < escaped_string_end; in++)
|
|
||||||
{
|
|
||||||
character = *in;
|
|
||||||
|
|
||||||
if (*in == '%')
|
|
||||||
{
|
|
||||||
in++;
|
|
||||||
|
|
||||||
if (escaped_string_end - in < 2)
|
|
||||||
{
|
|
||||||
/* Invalid escaped char (to short) */
|
|
||||||
g_free (result);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
character = unescape_character (in);
|
|
||||||
|
|
||||||
/* 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++; /* The other char will be eaten in the loop header */
|
|
||||||
}
|
|
||||||
*out++ = (char)character;
|
|
||||||
}
|
|
||||||
|
|
||||||
*out = '\0';
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* g_uri_unescape_string:
|
|
||||||
* @escaped_string: an escaped string to be unescaped.
|
|
||||||
* @illegal_characters: (allow-none): a string of illegal characters not to be
|
|
||||||
* allowed, or %NULL.
|
|
||||||
*
|
|
||||||
* Unescapes a whole escaped string.
|
|
||||||
*
|
|
||||||
* If any of the characters in @illegal_characters or the character zero appears
|
|
||||||
* as an escaped character in @escaped_string then that is an error and %NULL
|
|
||||||
* will be returned. This is useful it you want to avoid for instance having a
|
|
||||||
* slash being expanded in an escaped path element, which might confuse pathname
|
|
||||||
* handling.
|
|
||||||
*
|
|
||||||
* Returns: an unescaped version of @escaped_string. The returned string
|
|
||||||
* should be freed when no longer needed.
|
|
||||||
*
|
|
||||||
* Since: 2.16
|
|
||||||
**/
|
|
||||||
char *
|
|
||||||
g_uri_unescape_string (const char *escaped_string,
|
|
||||||
const char *illegal_characters)
|
|
||||||
{
|
|
||||||
return g_uri_unescape_segment (escaped_string, NULL, illegal_characters);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* g_uri_parse_scheme:
|
|
||||||
* @uri: a valid URI.
|
|
||||||
*
|
|
||||||
* Gets the scheme portion of a URI string. RFC 3986 decodes the scheme as:
|
|
||||||
* |[
|
|
||||||
* URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
|
|
||||||
* ]|
|
|
||||||
* Common schemes include "file", "http", "svn+ssh", etc.
|
|
||||||
*
|
|
||||||
* Returns: The "Scheme" component of the URI, or %NULL on error.
|
|
||||||
* The returned string should be freed when no longer needed.
|
|
||||||
*
|
|
||||||
* Since: 2.16
|
|
||||||
**/
|
|
||||||
char *
|
|
||||||
g_uri_parse_scheme (const char *uri)
|
|
||||||
{
|
|
||||||
const char *p;
|
|
||||||
char c;
|
|
||||||
|
|
||||||
g_return_val_if_fail (uri != NULL, NULL);
|
|
||||||
|
|
||||||
/* From RFC 3986 Decodes:
|
|
||||||
* URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
|
|
||||||
*/
|
|
||||||
|
|
||||||
p = uri;
|
|
||||||
|
|
||||||
/* Decode scheme:
|
|
||||||
scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!g_ascii_isalpha (*p))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
c = *p++;
|
|
||||||
|
|
||||||
if (c == ':')
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!(g_ascii_isalnum(c) ||
|
|
||||||
c == '+' ||
|
|
||||||
c == '-' ||
|
|
||||||
c == '.'))
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return g_strndup (uri, p - uri - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* g_uri_escape_string:
|
|
||||||
* @unescaped: the unescaped input string.
|
|
||||||
* @reserved_chars_allowed: (allow-none): a string of reserved characters that
|
|
||||||
* are allowed to be used, or %NULL.
|
|
||||||
* @allow_utf8: %TRUE if the result can include UTF-8 characters.
|
|
||||||
*
|
|
||||||
* Escapes a string for use in a URI.
|
|
||||||
*
|
|
||||||
* Normally all characters that are not "unreserved" (i.e. ASCII alphanumerical
|
|
||||||
* characters plus dash, dot, underscore and tilde) are escaped.
|
|
||||||
* But if you specify characters in @reserved_chars_allowed they are not
|
|
||||||
* escaped. This is useful for the "reserved" characters in the URI
|
|
||||||
* specification, since those are allowed unescaped in some portions of
|
|
||||||
* a URI.
|
|
||||||
*
|
|
||||||
* Returns: an escaped version of @unescaped. The returned string should be
|
|
||||||
* freed when no longer needed.
|
|
||||||
*
|
|
||||||
* Since: 2.16
|
|
||||||
**/
|
|
||||||
char *
|
|
||||||
g_uri_escape_string (const char *unescaped,
|
|
||||||
const char *reserved_chars_allowed,
|
|
||||||
gboolean allow_utf8)
|
|
||||||
{
|
|
||||||
GString *s;
|
|
||||||
|
|
||||||
g_return_val_if_fail (unescaped != NULL, NULL);
|
|
||||||
|
|
||||||
s = g_string_sized_new (strlen (unescaped) + 10);
|
|
||||||
|
|
||||||
g_string_append_uri_escaped (s, unescaped, reserved_chars_allowed, allow_utf8);
|
|
||||||
|
|
||||||
return g_string_free (s, FALSE);
|
|
||||||
}
|
|
@@ -1,83 +0,0 @@
|
|||||||
/* GIO - GLib Input, Output and Streaming Library
|
|
||||||
*
|
|
||||||
* Copyright (C) 2006-2007 Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* 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, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Author: Alexander Larsson <alexl@redhat.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __G_URI_FUNCS_H__
|
|
||||||
#define __G_URI_FUNCS_H__
|
|
||||||
|
|
||||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
|
||||||
#error "Only <glib.h> can be included directly."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <glib/gtypes.h>
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
|
||||||
|
|
||||||
/**
|
|
||||||
* G_URI_RESERVED_CHARS_GENERIC_DELIMITERS:
|
|
||||||
*
|
|
||||||
* Generic delimiters characters as defined in RFC 3986. Includes ":/?#[]@".
|
|
||||||
**/
|
|
||||||
#define G_URI_RESERVED_CHARS_GENERIC_DELIMITERS ":/?#[]@"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS:
|
|
||||||
*
|
|
||||||
* Subcomponent delimiter characters as defined in RFC 3986. Includes "!$&'()*+,;=".
|
|
||||||
**/
|
|
||||||
#define G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS "!$&'()*+,;="
|
|
||||||
|
|
||||||
/**
|
|
||||||
* G_URI_RESERVED_CHARS_ALLOWED_IN_PATH_ELEMENT:
|
|
||||||
*
|
|
||||||
* Allowed characters in path elements. Includes "!$&'()*+,;=:@".
|
|
||||||
**/
|
|
||||||
#define G_URI_RESERVED_CHARS_ALLOWED_IN_PATH_ELEMENT G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS ":@"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* G_URI_RESERVED_CHARS_ALLOWED_IN_PATH:
|
|
||||||
*
|
|
||||||
* Allowed characters in a path. Includes "!$&'()*+,;=:@/".
|
|
||||||
**/
|
|
||||||
#define G_URI_RESERVED_CHARS_ALLOWED_IN_PATH G_URI_RESERVED_CHARS_ALLOWED_IN_PATH_ELEMENT "/"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* G_URI_RESERVED_CHARS_ALLOWED_IN_USERINFO:
|
|
||||||
*
|
|
||||||
* Allowed characters in userinfo as defined in RFC 3986. Includes "!$&'()*+,;=:".
|
|
||||||
**/
|
|
||||||
#define G_URI_RESERVED_CHARS_ALLOWED_IN_USERINFO G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS ":"
|
|
||||||
|
|
||||||
GLIB_AVAILABLE_IN_ALL
|
|
||||||
char * g_uri_unescape_string (const char *escaped_string,
|
|
||||||
const char *illegal_characters);
|
|
||||||
GLIB_AVAILABLE_IN_ALL
|
|
||||||
char * g_uri_unescape_segment (const char *escaped_string,
|
|
||||||
const char *escaped_string_end,
|
|
||||||
const char *illegal_characters);
|
|
||||||
GLIB_AVAILABLE_IN_ALL
|
|
||||||
char * g_uri_parse_scheme (const char *uri);
|
|
||||||
GLIB_AVAILABLE_IN_ALL
|
|
||||||
char * g_uri_escape_string (const char *unescaped,
|
|
||||||
const char *reserved_chars_allowed,
|
|
||||||
gboolean allow_utf8);
|
|
||||||
|
|
||||||
G_END_DECLS
|
|
||||||
|
|
||||||
#endif /* __G_URI_FUNCS_H__ */
|
|
443
glib/tests/uri.c
443
glib/tests/uri.c
@@ -33,10 +33,10 @@ typedef struct
|
|||||||
char *hostname;
|
char *hostname;
|
||||||
char *expected_result;
|
char *expected_result;
|
||||||
GConvertError expected_error; /* If failed */
|
GConvertError expected_error; /* If failed */
|
||||||
} ToUriTest;
|
} FileToUriTest;
|
||||||
|
|
||||||
ToUriTest
|
FileToUriTest
|
||||||
to_uri_tests[] = {
|
file_to_uri_tests[] = {
|
||||||
{ "/etc", NULL, "file:///etc"},
|
{ "/etc", NULL, "file:///etc"},
|
||||||
{ "/etc", "", "file:///etc"},
|
{ "/etc", "", "file:///etc"},
|
||||||
{ "/etc", "otherhost", "file://otherhost/etc"},
|
{ "/etc", "otherhost", "file://otherhost/etc"},
|
||||||
@@ -101,10 +101,10 @@ typedef struct
|
|||||||
char *expected_filename;
|
char *expected_filename;
|
||||||
char *expected_hostname;
|
char *expected_hostname;
|
||||||
GConvertError expected_error; /* If failed */
|
GConvertError expected_error; /* If failed */
|
||||||
} FromUriTest;
|
} FileFromUriTest;
|
||||||
|
|
||||||
FromUriTest
|
FileFromUriTest
|
||||||
from_uri_tests[] = {
|
file_from_uri_tests[] = {
|
||||||
{ "file:///etc", "/etc"},
|
{ "file:///etc", "/etc"},
|
||||||
{ "file:/etc", "/etc"},
|
{ "file:/etc", "/etc"},
|
||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
@@ -163,23 +163,23 @@ from_uri_tests[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
run_to_uri_tests (void)
|
run_file_to_uri_tests (void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
gchar *res;
|
gchar *res;
|
||||||
GError *error;
|
GError *error;
|
||||||
|
|
||||||
for (i = 0; i < G_N_ELEMENTS (to_uri_tests); i++)
|
for (i = 0; i < G_N_ELEMENTS (file_to_uri_tests); i++)
|
||||||
{
|
{
|
||||||
error = NULL;
|
error = NULL;
|
||||||
res = g_filename_to_uri (to_uri_tests[i].filename,
|
res = g_filename_to_uri (file_to_uri_tests[i].filename,
|
||||||
to_uri_tests[i].hostname,
|
file_to_uri_tests[i].hostname,
|
||||||
&error);
|
&error);
|
||||||
|
|
||||||
if (res)
|
if (res)
|
||||||
g_assert_cmpstr (res, ==, to_uri_tests[i].expected_result);
|
g_assert_cmpstr (res, ==, file_to_uri_tests[i].expected_result);
|
||||||
else
|
else
|
||||||
g_assert_error (error, G_CONVERT_ERROR, to_uri_tests[i].expected_error);
|
g_assert_error (error, G_CONVERT_ERROR, file_to_uri_tests[i].expected_error);
|
||||||
|
|
||||||
g_free (res);
|
g_free (res);
|
||||||
g_clear_error (&error);
|
g_clear_error (&error);
|
||||||
@@ -187,25 +187,26 @@ run_to_uri_tests (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
run_from_uri_tests (void)
|
run_file_from_uri_tests (void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
gchar *res;
|
gchar *res;
|
||||||
gchar *hostname;
|
gchar *hostname;
|
||||||
GError *error;
|
GError *error;
|
||||||
|
|
||||||
for (i = 0; i < G_N_ELEMENTS (from_uri_tests); i++)
|
for (i = 0; i < G_N_ELEMENTS (file_from_uri_tests); i++)
|
||||||
{
|
{
|
||||||
error = NULL;
|
error = NULL;
|
||||||
res = g_filename_from_uri (from_uri_tests[i].uri,
|
res = g_filename_from_uri (file_from_uri_tests[i].uri,
|
||||||
&hostname,
|
&hostname,
|
||||||
&error);
|
&error);
|
||||||
|
|
||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
if (from_uri_tests[i].expected_filename)
|
if (file_from_uri_tests[i].expected_filename)
|
||||||
{
|
{
|
||||||
gchar *p, *slash;
|
gchar *p, *slash;
|
||||||
p = from_uri_tests[i].expected_filename = g_strdup (from_uri_tests[i].expected_filename);
|
p = file_from_uri_tests[i].expected_filename =
|
||||||
|
g_strdup (file_from_uri_tests[i].expected_filename);
|
||||||
while ((slash = strchr (p, '/')) != NULL)
|
while ((slash = strchr (p, '/')) != NULL)
|
||||||
{
|
{
|
||||||
*slash = '\\';
|
*slash = '\\';
|
||||||
@@ -214,10 +215,10 @@ run_from_uri_tests (void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (res)
|
if (res)
|
||||||
g_assert_cmpstr (res, ==, from_uri_tests[i].expected_filename);
|
g_assert_cmpstr (res, ==, file_from_uri_tests[i].expected_filename);
|
||||||
else
|
else
|
||||||
g_assert_error (error, G_CONVERT_ERROR, from_uri_tests[i].expected_error);
|
g_assert_error (error, G_CONVERT_ERROR, file_from_uri_tests[i].expected_error);
|
||||||
g_assert_cmpstr (hostname, ==, from_uri_tests[i].expected_hostname);
|
g_assert_cmpstr (hostname, ==, file_from_uri_tests[i].expected_hostname);
|
||||||
|
|
||||||
g_free (res);
|
g_free (res);
|
||||||
g_free (hostname);
|
g_free (hostname);
|
||||||
@@ -266,20 +267,20 @@ safe_strcmp_hostname (const gchar *a, const gchar *b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
run_roundtrip_tests (void)
|
run_file_roundtrip_tests (void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
gchar *uri, *hostname, *res;
|
gchar *uri, *hostname, *res;
|
||||||
GError *error;
|
GError *error;
|
||||||
|
|
||||||
for (i = 0; i < G_N_ELEMENTS (to_uri_tests); i++)
|
for (i = 0; i < G_N_ELEMENTS (file_to_uri_tests); i++)
|
||||||
{
|
{
|
||||||
if (to_uri_tests[i].expected_error != 0)
|
if (file_to_uri_tests[i].expected_error != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
error = NULL;
|
error = NULL;
|
||||||
uri = g_filename_to_uri (to_uri_tests[i].filename,
|
uri = g_filename_to_uri (file_to_uri_tests[i].filename,
|
||||||
to_uri_tests[i].hostname,
|
file_to_uri_tests[i].hostname,
|
||||||
&error);
|
&error);
|
||||||
g_assert_no_error (error);
|
g_assert_no_error (error);
|
||||||
|
|
||||||
@@ -287,8 +288,8 @@ run_roundtrip_tests (void)
|
|||||||
res = g_filename_from_uri (uri, &hostname, &error);
|
res = g_filename_from_uri (uri, &hostname, &error);
|
||||||
g_assert_no_error (error);
|
g_assert_no_error (error);
|
||||||
|
|
||||||
g_assert (safe_strcmp_filename (to_uri_tests[i].filename, res) == 0);
|
g_assert (safe_strcmp_filename (file_to_uri_tests[i].filename, res) == 0);
|
||||||
g_assert (safe_strcmp_hostname (to_uri_tests[i].hostname, hostname) == 0);
|
g_assert (safe_strcmp_hostname (file_to_uri_tests[i].hostname, hostname) == 0);
|
||||||
g_free (res);
|
g_free (res);
|
||||||
g_free (uri);
|
g_free (uri);
|
||||||
g_free (hostname);
|
g_free (hostname);
|
||||||
@@ -364,15 +365,391 @@ test_uri_escape (void)
|
|||||||
static void
|
static void
|
||||||
test_uri_scheme (void)
|
test_uri_scheme (void)
|
||||||
{
|
{
|
||||||
|
const gchar *s1, *s2;
|
||||||
gchar *s;
|
gchar *s;
|
||||||
|
|
||||||
|
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
||||||
s = g_uri_parse_scheme ("ftp://ftp.gtk.org");
|
s = g_uri_parse_scheme ("ftp://ftp.gtk.org");
|
||||||
g_assert_cmpstr (s, ==, "ftp");
|
g_assert_cmpstr (s, ==, "ftp");
|
||||||
g_free (s);
|
g_free (s);
|
||||||
s = g_uri_parse_scheme ("1bad:");
|
s = g_uri_parse_scheme ("1bad:");
|
||||||
g_assert (s == NULL);
|
g_assert_cmpstr (s, ==, NULL);
|
||||||
s = g_uri_parse_scheme ("bad");
|
s = g_uri_parse_scheme ("bad");
|
||||||
g_assert (s == NULL);
|
g_assert_cmpstr (s, ==, NULL);
|
||||||
|
G_GNUC_END_IGNORE_DEPRECATIONS;
|
||||||
|
|
||||||
|
s1 = g_uri_peek_scheme ("ftp://ftp.gtk.org");
|
||||||
|
g_assert_cmpstr (s1, ==, "ftp");
|
||||||
|
s2 = g_uri_peek_scheme ("FTP://ftp.gtk.org");
|
||||||
|
g_assert_cmpstr (s2, ==, "ftp");
|
||||||
|
g_assert_true (s1 == s2);
|
||||||
|
s1 = g_uri_peek_scheme ("1bad:");
|
||||||
|
g_assert_cmpstr (s, ==, NULL);
|
||||||
|
s1 = g_uri_peek_scheme ("bad");
|
||||||
|
g_assert_cmpstr (s, ==, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const gchar *scheme;
|
||||||
|
const gchar *userinfo;
|
||||||
|
const gchar *host;
|
||||||
|
gint port;
|
||||||
|
const gchar *path;
|
||||||
|
const gchar *query;
|
||||||
|
const gchar *fragment;
|
||||||
|
} UriParts;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const gchar *orig;
|
||||||
|
const UriParts parts;
|
||||||
|
} UriAbsoluteTest;
|
||||||
|
|
||||||
|
static const UriAbsoluteTest absolute_tests[] = {
|
||||||
|
{ "foo:",
|
||||||
|
{ "foo", NULL, NULL, -1, "", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "file:/dev/null",
|
||||||
|
{ "file", NULL, NULL, -1, "/dev/null", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "file:///dev/null",
|
||||||
|
{ "file", NULL, "", -1, "/dev/null", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "ftp://user@host/path",
|
||||||
|
{ "ftp", "user", "host", -1, "/path", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "ftp://user@host:9999/path",
|
||||||
|
{ "ftp", "user", "host", 9999, "/path", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "ftp://user:password@host/path",
|
||||||
|
{ "ftp", "user:password", "host", -1, "/path", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "ftp://user:password@host:9999/path",
|
||||||
|
{ "ftp", "user:password", "host", 9999, "/path", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "ftp://user:password@host",
|
||||||
|
{ "ftp", "user:password", "host", -1, "", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "http://us%65r@host",
|
||||||
|
{ "http", "user", "host", -1, "", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "http://us%40r@host",
|
||||||
|
{ "http", "us@r", "host", -1, "", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "http://us%3ar@host",
|
||||||
|
{ "http", "us:r", "host", -1, "", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "http://us%2fr@host",
|
||||||
|
{ "http", "us/r", "host", -1, "", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "http://us%3fr@host",
|
||||||
|
{ "http", "us?r", "host", -1, "", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "http://host?query",
|
||||||
|
{ "http", NULL, "host", -1, "", "query", NULL }
|
||||||
|
},
|
||||||
|
{ "http://host/path?query=http%3A%2F%2Fhost%2Fpath%3Fchildparam%3Dchildvalue¶m=value",
|
||||||
|
{ "http", NULL, "host", -1, "/path", "query=http://host/path?childparam=childvalue¶m=value", NULL }
|
||||||
|
},
|
||||||
|
{ "http://control-chars/%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F",
|
||||||
|
{ "http", NULL, "control-chars", -1, "/\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x7F", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "http://space/%20",
|
||||||
|
{ "http", NULL, "space", -1, "/ ", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "http://delims/%3C%3E%23%25%22",
|
||||||
|
{ "http", NULL, "delims", -1, "/<>#%\"", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "http://unwise-chars/%7B%7D%7C%5C%5E%5B%5D%60",
|
||||||
|
{ "http", NULL, "unwise-chars", -1, "/{}|\\^[]`", NULL, NULL }
|
||||||
|
},
|
||||||
|
|
||||||
|
/* From RFC 2732 */
|
||||||
|
{ "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html",
|
||||||
|
{ "http", NULL, "FEDC:BA98:7654:3210:FEDC:BA98:7654:3210", 80, "/index.html", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "http://[1080:0:0:0:8:800:200C:417A]/index.html",
|
||||||
|
{ "http", NULL, "1080:0:0:0:8:800:200C:417A", -1, "/index.html", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "http://[3ffe:2a00:100:7031::1]",
|
||||||
|
{ "http", NULL, "3ffe:2a00:100:7031::1", -1, "", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "http://[1080::8:800:200C:417A]/foo",
|
||||||
|
{ "http", NULL, "1080::8:800:200C:417A", -1, "/foo", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "http://[::192.9.5.5]/ipng",
|
||||||
|
{ "http", NULL, "::192.9.5.5", -1, "/ipng", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "http://[::FFFF:129.144.52.38]:80/index.html",
|
||||||
|
{ "http", NULL, "::FFFF:129.144.52.38", 80, "/index.html", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "http://[2010:836B:4179::836B:4179]",
|
||||||
|
{ "http", NULL, "2010:836B:4179::836B:4179", -1, "", NULL, NULL }
|
||||||
|
},
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* Try to recover certain kinds of invalid URIs */
|
||||||
|
{ "http://host/path with spaces",
|
||||||
|
{ "http", NULL, "host", -1, "/path%20with%20spaces", NULL, NULL }
|
||||||
|
"http://host/path%20with%20spaces",
|
||||||
|
},
|
||||||
|
{ " http://host/path",
|
||||||
|
{ "http", NULL, "host", -1, "/path", NULL, NULL }
|
||||||
|
"http://host/path"
|
||||||
|
},
|
||||||
|
{ "http://host/path ",
|
||||||
|
{ "http", NULL, "host", -1, "/path", NULL, NULL }
|
||||||
|
"http://host/path"
|
||||||
|
},
|
||||||
|
{ "http://host ",
|
||||||
|
{ "http", NULL, "host", -1, "", NULL, NULL }
|
||||||
|
"http://host"
|
||||||
|
},
|
||||||
|
{ "http://host:999 ",
|
||||||
|
{ "http", NULL, "host", 999, "", NULL, NULL }
|
||||||
|
"http://host:999"
|
||||||
|
},
|
||||||
|
{ "http://host/pa\nth",
|
||||||
|
{ "http", NULL, "host", -1, "/path", NULL, NULL }
|
||||||
|
"http://host/path"
|
||||||
|
},
|
||||||
|
{ "http:\r\n//host/path",
|
||||||
|
{ "http", NULL, "host", -1, "/path", NULL, NULL }
|
||||||
|
"http://host/path"
|
||||||
|
},
|
||||||
|
{ "http://\thost/path",
|
||||||
|
{ "http", NULL, "host", -1, "/path", NULL, NULL }
|
||||||
|
"http://host/path"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Bug 594405; 0-length is different from not-present */
|
||||||
|
{ "http://host/path?",
|
||||||
|
{ "http", NULL, "host", -1, "/path", "", NULL }
|
||||||
|
},
|
||||||
|
{ "http://host/path#",
|
||||||
|
{ "http", NULL, "host", -1, "/path", NULL, "" },
|
||||||
|
},
|
||||||
|
|
||||||
|
/* Bug 590524; ignore bad %-encoding */
|
||||||
|
{ "http://host/path%",
|
||||||
|
{ "http", NULL, "host", -1, "/path%", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "http://h%ost/path",
|
||||||
|
{ "http", NULL, "h%ost", -1, "/path", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "http://host/path%%",
|
||||||
|
{ "http", NULL, "host", -1, "/path%%", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "http://host/path%%%",
|
||||||
|
{ "http", NULL, "host", -1, "/path%%%", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "http://host/path%/x/",
|
||||||
|
{ "http", NULL, "host", -1, "/path%/x/", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "http://host/path%0x/",
|
||||||
|
{ "http", NULL, "host", -1, "/path%0x/", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "http://host/path%ax",
|
||||||
|
{ "http", NULL, "host", -1, "/path%ax", NULL, NULL }
|
||||||
|
},
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* Bug 662806; %-encode non-ASCII characters */
|
||||||
|
{ "http://host/p\xc3\xa4th/",
|
||||||
|
{ "http", NULL, "host", -1, "/p%C3%A4th/", NULL, NULL }
|
||||||
|
{ "http", NULL, "host", -1, "/p%C3%A4th/", NULL, NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
|
||||||
|
{ "HTTP:////////////////",
|
||||||
|
{ "http", NULL, "", -1, "//////////////", NULL, NULL }
|
||||||
|
},
|
||||||
|
|
||||||
|
{ "http://@host",
|
||||||
|
{ "http", "", "host", -1, "", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "http://:@host",
|
||||||
|
{ "http", ":", "host", -1, "", NULL, NULL }
|
||||||
|
},
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
{ "http://host/keep%00nuls",
|
||||||
|
{ "http", NULL, "host", -1, "/keep%00nuls", NULL, NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* IPv6 scope ID parsing (both correct and incorrect) */
|
||||||
|
{ "http://[fe80::dead:beef%em1]/",
|
||||||
|
{ "http", NULL, "fe80::dead:beef%em1", -1, "/", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "http://[fe80::dead:beef%25em1]/",
|
||||||
|
{ "http", NULL, "fe80::dead:beef%em1", -1, "/", NULL, NULL }
|
||||||
|
},
|
||||||
|
{ "http://[fe80::dead:beef%10]/",
|
||||||
|
{ "http", NULL, "fe80::dead:beef%10", -1, "/", NULL, NULL }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static int num_absolute_tests = G_N_ELEMENTS (absolute_tests);
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_uri_parsing_absolute (void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < num_absolute_tests; i++)
|
||||||
|
{
|
||||||
|
const UriAbsoluteTest *test = &absolute_tests[i];
|
||||||
|
GError *error = NULL;
|
||||||
|
GUri *uri;
|
||||||
|
|
||||||
|
uri = g_uri_parse (test->orig, 0, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
g_assert_cmpstr (g_uri_get_scheme (uri), ==, test->parts.scheme);
|
||||||
|
g_assert_cmpstr (g_uri_get_userinfo (uri), ==, test->parts.userinfo);
|
||||||
|
g_assert_cmpstr (g_uri_get_host (uri), ==, test->parts.host);
|
||||||
|
g_assert_cmpint (g_uri_get_port (uri), ==, test->parts.port);
|
||||||
|
g_assert_cmpstr (g_uri_get_path (uri), ==, test->parts.path);
|
||||||
|
g_assert_cmpstr (g_uri_get_query (uri), ==, test->parts.query);
|
||||||
|
g_assert_cmpstr (g_uri_get_fragment (uri), ==, test->parts.fragment);
|
||||||
|
|
||||||
|
g_uri_unref (uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const gchar *orig, *resolved;
|
||||||
|
UriParts parts;
|
||||||
|
} UriRelativeTest;
|
||||||
|
|
||||||
|
/* This all comes from RFC 3986 */
|
||||||
|
static const char *relative_test_base = "http://a/b/c/d;p?q";
|
||||||
|
static const UriRelativeTest relative_tests[] = {
|
||||||
|
{ "g:h", "g:h",
|
||||||
|
{ "g", NULL, NULL, -1, "h", NULL, NULL } },
|
||||||
|
{ "g", "http://a/b/c/g",
|
||||||
|
{ "http", NULL, "a", -1, "/b/c/g", NULL, NULL } },
|
||||||
|
{ "./g", "http://a/b/c/g",
|
||||||
|
{ "http", NULL, "a", -1, "/b/c/g", NULL, NULL } },
|
||||||
|
{ "g/", "http://a/b/c/g/",
|
||||||
|
{ "http", NULL, "a", -1, "/b/c/g/", NULL, NULL } },
|
||||||
|
{ "/g", "http://a/g",
|
||||||
|
{ "http", NULL, "a", -1, "/g", NULL, NULL } },
|
||||||
|
{ "//g", "http://g",
|
||||||
|
{ "http", NULL, "g", -1, "", NULL, NULL } },
|
||||||
|
{ "?y", "http://a/b/c/d;p?y",
|
||||||
|
{ "http", NULL, "a", -1, "/b/c/d;p", "y", NULL } },
|
||||||
|
{ "g?y", "http://a/b/c/g?y",
|
||||||
|
{ "http", NULL, "a", -1, "/b/c/g", "y", NULL } },
|
||||||
|
{ "#s", "http://a/b/c/d;p?q#s",
|
||||||
|
{ "http", NULL, "a", -1, "/b/c/d;p", "q", "s" } },
|
||||||
|
{ "g#s", "http://a/b/c/g#s",
|
||||||
|
{ "http", NULL, "a", -1, "/b/c/g", NULL, "s" } },
|
||||||
|
{ "g?y#s", "http://a/b/c/g?y#s",
|
||||||
|
{ "http", NULL, "a", -1, "/b/c/g", "y", "s" } },
|
||||||
|
{ ";x", "http://a/b/c/;x",
|
||||||
|
{ "http", NULL, "a", -1, "/b/c/;x", NULL, NULL } },
|
||||||
|
{ "g;x", "http://a/b/c/g;x",
|
||||||
|
{ "http", NULL, "a", -1, "/b/c/g;x", NULL, NULL } },
|
||||||
|
{ "g;x?y#s", "http://a/b/c/g;x?y#s",
|
||||||
|
{ "http", NULL, "a", -1, "/b/c/g;x", "y", "s" } },
|
||||||
|
{ ".", "http://a/b/c/",
|
||||||
|
{ "http", NULL, "a", -1, "/b/c/", NULL, NULL } },
|
||||||
|
{ "./", "http://a/b/c/",
|
||||||
|
{ "http", NULL, "a", -1, "/b/c/", NULL, NULL } },
|
||||||
|
{ "..", "http://a/b/",
|
||||||
|
{ "http", NULL, "a", -1, "/b/", NULL, NULL } },
|
||||||
|
{ "../", "http://a/b/",
|
||||||
|
{ "http", NULL, "a", -1, "/b/", NULL, NULL } },
|
||||||
|
{ "../g", "http://a/b/g",
|
||||||
|
{ "http", NULL, "a", -1, "/b/g", NULL, NULL } },
|
||||||
|
{ "../..", "http://a/",
|
||||||
|
{ "http", NULL, "a", -1, "/", NULL, NULL } },
|
||||||
|
{ "../../", "http://a/",
|
||||||
|
{ "http", NULL, "a", -1, "/", NULL, NULL } },
|
||||||
|
{ "../../g", "http://a/g",
|
||||||
|
{ "http", NULL, "a", -1, "/g", NULL, NULL } },
|
||||||
|
{ "", "http://a/b/c/d;p?q",
|
||||||
|
{ "http", NULL, "a", -1, "/b/c/d;p", "q", NULL } },
|
||||||
|
{ "../../../g", "http://a/g",
|
||||||
|
{ "http", NULL, "a", -1, "/g", NULL, NULL } },
|
||||||
|
{ "../../../../g", "http://a/g",
|
||||||
|
{ "http", NULL, "a", -1, "/g", NULL, NULL } },
|
||||||
|
{ "/./g", "http://a/g",
|
||||||
|
{ "http", NULL, "a", -1, "/g", NULL, NULL } },
|
||||||
|
{ "/../g", "http://a/g",
|
||||||
|
{ "http", NULL, "a", -1, "/g", NULL, NULL } },
|
||||||
|
{ "g.", "http://a/b/c/g.",
|
||||||
|
{ "http", NULL, "a", -1, "/b/c/g.", NULL, NULL } },
|
||||||
|
{ ".g", "http://a/b/c/.g",
|
||||||
|
{ "http", NULL, "a", -1, "/b/c/.g", NULL, NULL } },
|
||||||
|
{ "g..", "http://a/b/c/g..",
|
||||||
|
{ "http", NULL, "a", -1, "/b/c/g..", NULL, NULL } },
|
||||||
|
{ "..g", "http://a/b/c/..g",
|
||||||
|
{ "http", NULL, "a", -1, "/b/c/..g", NULL, NULL } },
|
||||||
|
{ "./../g", "http://a/b/g",
|
||||||
|
{ "http", NULL, "a", -1, "/b/g", NULL, NULL } },
|
||||||
|
{ "./g/.", "http://a/b/c/g/",
|
||||||
|
{ "http", NULL, "a", -1, "/b/c/g/", NULL, NULL } },
|
||||||
|
{ "g/./h", "http://a/b/c/g/h",
|
||||||
|
{ "http", NULL, "a", -1, "/b/c/g/h", NULL, NULL } },
|
||||||
|
{ "g/../h", "http://a/b/c/h",
|
||||||
|
{ "http", NULL, "a", -1, "/b/c/h", NULL, NULL } },
|
||||||
|
{ "g;x=1/./y", "http://a/b/c/g;x=1/y",
|
||||||
|
{ "http", NULL, "a", -1, "/b/c/g;x=1/y", NULL, NULL } },
|
||||||
|
{ "g;x=1/../y", "http://a/b/c/y",
|
||||||
|
{ "http", NULL, "a", -1, "/b/c/y", NULL, NULL } },
|
||||||
|
{ "g?y/./x", "http://a/b/c/g?y/./x",
|
||||||
|
{ "http", NULL, "a", -1, "/b/c/g", "y/./x", NULL } },
|
||||||
|
{ "g?y/../x", "http://a/b/c/g?y/../x",
|
||||||
|
{ "http", NULL, "a", -1, "/b/c/g", "y/../x", NULL } },
|
||||||
|
{ "g#s/./x", "http://a/b/c/g#s/./x",
|
||||||
|
{ "http", NULL, "a", -1, "/b/c/g", NULL, "s/./x" } },
|
||||||
|
{ "g#s/../x", "http://a/b/c/g#s/../x",
|
||||||
|
{ "http", NULL, "a", -1, "/b/c/g", NULL, "s/../x" } },
|
||||||
|
{ "http:g", "http:g",
|
||||||
|
{ "http", NULL, NULL, -1, "g", NULL, NULL } }
|
||||||
|
};
|
||||||
|
static int num_relative_tests = G_N_ELEMENTS (relative_tests);
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_uri_parsing_relative (void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
GUri *base;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
base = g_uri_parse (relative_test_base, 0, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
for (i = 0; i < num_relative_tests; i++)
|
||||||
|
{
|
||||||
|
const UriRelativeTest *test = &relative_tests[i];
|
||||||
|
gchar *tostring, *resolved;
|
||||||
|
GUri *uri;
|
||||||
|
|
||||||
|
uri = g_uri_parse_relative (base, test->orig, 0, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
g_assert_cmpstr (g_uri_get_scheme (uri), ==, test->parts.scheme);
|
||||||
|
g_assert_cmpstr (g_uri_get_userinfo (uri), ==, test->parts.userinfo);
|
||||||
|
g_assert_cmpstr (g_uri_get_host (uri), ==, test->parts.host);
|
||||||
|
g_assert_cmpint (g_uri_get_port (uri), ==, test->parts.port);
|
||||||
|
g_assert_cmpstr (g_uri_get_path (uri), ==, test->parts.path);
|
||||||
|
g_assert_cmpstr (g_uri_get_query (uri), ==, test->parts.query);
|
||||||
|
g_assert_cmpstr (g_uri_get_fragment (uri), ==, test->parts.fragment);
|
||||||
|
|
||||||
|
tostring = g_uri_to_string (uri);
|
||||||
|
g_assert_cmpstr (tostring, ==, test->resolved);
|
||||||
|
g_free (tostring);
|
||||||
|
|
||||||
|
g_uri_unref (uri);
|
||||||
|
|
||||||
|
resolved = g_uri_resolve_relative (relative_test_base, test->orig, 0, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert_cmpstr (resolved, ==, test->resolved);
|
||||||
|
g_free (resolved);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -381,13 +758,15 @@ main (int argc,
|
|||||||
{
|
{
|
||||||
g_test_init (&argc, &argv, NULL);
|
g_test_init (&argc, &argv, NULL);
|
||||||
|
|
||||||
g_test_add_func ("/uri/to-uri", run_to_uri_tests);
|
g_test_add_func ("/uri/file-to-uri", run_file_to_uri_tests);
|
||||||
g_test_add_func ("/uri/from-uri", run_from_uri_tests);
|
g_test_add_func ("/uri/file-from-uri", run_file_from_uri_tests);
|
||||||
g_test_add_func ("/uri/roundtrip", run_roundtrip_tests);
|
g_test_add_func ("/uri/file-roundtrip", run_file_roundtrip_tests);
|
||||||
g_test_add_func ("/uri/list", run_uri_list_tests);
|
g_test_add_func ("/uri/list", run_uri_list_tests);
|
||||||
g_test_add_func ("/uri/unescape", test_uri_unescape);
|
g_test_add_func ("/uri/unescape", test_uri_unescape);
|
||||||
g_test_add_func ("/uri/escape", test_uri_escape);
|
g_test_add_func ("/uri/escape", test_uri_escape);
|
||||||
g_test_add_func ("/uri/scheme", test_uri_scheme);
|
g_test_add_func ("/uri/scheme", test_uri_scheme);
|
||||||
|
g_test_add_func ("/uri/parsing/absolute", test_uri_parsing_absolute);
|
||||||
|
g_test_add_func ("/uri/parsing/relative", test_uri_parsing_relative);
|
||||||
|
|
||||||
return g_test_run ();
|
return g_test_run ();
|
||||||
}
|
}
|
||||||
|
@@ -164,6 +164,7 @@ G_DEFINE_BOXED_TYPE (GMarkupParseContext, g_markup_parse_context, g_markup_parse
|
|||||||
|
|
||||||
G_DEFINE_BOXED_TYPE (GThread, g_thread, g_thread_ref, g_thread_unref)
|
G_DEFINE_BOXED_TYPE (GThread, g_thread, g_thread_ref, g_thread_unref)
|
||||||
G_DEFINE_BOXED_TYPE (GChecksum, g_checksum, g_checksum_copy, g_checksum_free)
|
G_DEFINE_BOXED_TYPE (GChecksum, g_checksum, g_checksum_copy, g_checksum_free)
|
||||||
|
G_DEFINE_BOXED_TYPE (GUri, g_uri, g_uri_ref, g_uri_unref)
|
||||||
|
|
||||||
/* This one can't use G_DEFINE_BOXED_TYPE (GStrv, g_strv, g_strdupv, g_strfreev) */
|
/* This one can't use G_DEFINE_BOXED_TYPE (GStrv, g_strv, g_strdupv, g_strfreev) */
|
||||||
GType
|
GType
|
||||||
|
@@ -342,6 +342,8 @@ GLIB_AVAILABLE_IN_2_36
|
|||||||
GType g_markup_parse_context_get_type (void) G_GNUC_CONST;
|
GType g_markup_parse_context_get_type (void) G_GNUC_CONST;
|
||||||
GLIB_AVAILABLE_IN_2_40
|
GLIB_AVAILABLE_IN_2_40
|
||||||
GType g_mapped_file_get_type (void) G_GNUC_CONST;
|
GType g_mapped_file_get_type (void) G_GNUC_CONST;
|
||||||
|
GLIB_AVAILABLE_IN_2_40
|
||||||
|
GType g_uri_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
GLIB_DEPRECATED_FOR('G_TYPE_VARIANT')
|
GLIB_DEPRECATED_FOR('G_TYPE_VARIANT')
|
||||||
GType g_variant_get_gtype (void) G_GNUC_CONST;
|
GType g_variant_get_gtype (void) G_GNUC_CONST;
|
||||||
|
Reference in New Issue
Block a user