gst/gsturi.c (gst_uri_get_location): unescape string escape string.

Original commit message from CVS:
* gst/gsturi.c (gst_uri_get_location): unescape string
(gst_uri_construct): escape string.
This commit is contained in:
Johan Dahlin 2004-10-11 09:44:05 +00:00
parent bedb0bef2b
commit 970da8b0f9
2 changed files with 209 additions and 2 deletions

View file

@ -1,3 +1,8 @@
2004-10-11 Johan Dahlin <johan@gnome.org>
* gst/gsturi.c (gst_uri_get_location): unescape string
(gst_uri_construct): escape string.
2004-10-11 Benjamin Otte <otte@gnome.org> 2004-10-11 Benjamin Otte <otte@gnome.org>
* gst/gstpad.c: (gst_pad_renegotiate), (gst_pad_try_set_caps), * gst/gstpad.c: (gst_pad_renegotiate), (gst_pad_try_set_caps),

View file

@ -77,6 +77,195 @@ gst_uri_handler_base_init (gpointer g_class)
} }
} }
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 */
};
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;
#define HEX_ESCAPE '%'
/* Escape undesirable characters using %
* -------------------------------------
*
* This function takes a pointer to a string in which
* some characters may be unacceptable unescaped.
* It returns a string which has these characters
* represented by a '%' character followed by two hex digits.
*
* This routine returns a g_malloced string.
*/
static const gchar hex[16] = "0123456789ABCDEF";
static gchar *
escape_string_internal (const gchar * string, UnsafeCharacterSet mask)
{
#define ACCEPTABLE_CHAR(a) ((a)>=32 && (a)<128 && (acceptable[(a)-32] & use_mask))
const gchar *p;
gchar *q;
gchar *result;
guchar 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);
if (string == NULL) {
return NULL;
}
unacceptable = 0;
use_mask = mask;
for (p = string; *p != '\0'; p++) {
c = *p;
if (!ACCEPTABLE_CHAR (c)) {
unacceptable++;
}
if ((use_mask == UNSAFE_HOST) && (unacceptable || (c == '/'))) {
/* when escaping a host, if we hit something that needs to be escaped, or we finally
* hit a path separator, revert to path mode (the host segment of the url is over).
*/
use_mask = UNSAFE_PATH;
}
}
result = g_malloc (p - string + unacceptable * 2 + 1);
use_mask = mask;
for (q = result, p = string; *p != '\0'; p++) {
c = *p;
if (!ACCEPTABLE_CHAR (c)) {
*q++ = HEX_ESCAPE; /* means hex coming */
*q++ = hex[c >> 4];
*q++ = hex[c & 15];
} else {
*q++ = c;
}
if ((use_mask == UNSAFE_HOST) && (!ACCEPTABLE_CHAR (c) || (c == '/'))) {
use_mask = UNSAFE_PATH;
}
}
*q = '\0';
return result;
}
/**
* escape_string:
* @string: string to be escaped
*
* Escapes @string, replacing any and all special characters
* with equivalent escape sequences.
*
* Return value: a newly allocated string equivalent to @string
* but with all special characters escaped
**/
gchar *
escape_string (const gchar * string)
{
return escape_string_internal (string, UNSAFE_ALL);
}
static int
hex_to_int (gchar c)
{
return c >= '0' && c <= '9' ? c - '0'
: c >= 'A' && c <= 'F' ? c - 'A' + 10
: c >= 'a' && c <= 'f' ? c - 'a' + 10 : -1;
}
static int
unescape_character (const char *scanner)
{
int first_digit;
int second_digit;
first_digit = hex_to_int (*scanner++);
if (first_digit < 0) {
return -1;
}
second_digit = hex_to_int (*scanner++);
if (second_digit < 0) {
return -1;
}
return (first_digit << 4) | second_digit;
}
/**
* unescape_string:
* @escaped_string: an escaped URI, path, or other string
* @illegal_characters: a string containing a sequence of characters
* considered "illegal", '\0' is automatically in this list.
*
* Decodes escaped characters (i.e. PERCENTxx sequences) in @escaped_string.
* Characters are encoded in PERCENTxy form, where xy is the ASCII hex code
* for character 16x+y.
*
* Return value: a newly allocated string with the unescaped equivalents,
* or %NULL if @escaped_string contained one of the characters
* in @illegal_characters.
**/
static char *
unescape_string (const gchar * escaped_string, const gchar * illegal_characters)
{
const gchar *in;
gchar *out, *result;
gint character;
if (escaped_string == NULL) {
return NULL;
}
result = g_malloc (strlen (escaped_string) + 1);
out = result;
for (in = escaped_string; *in != '\0'; in++) {
character = *in;
if (*in == HEX_ESCAPE) {
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++ = (char) character;
}
*out = '\0';
g_assert (out - result <= strlen (escaped_string));
return result;
}
static void static void
gst_uri_protocol_check_internal (const gchar * uri, gchar ** endptr) gst_uri_protocol_check_internal (const gchar * uri, gchar ** endptr)
{ {
@ -172,13 +361,19 @@ gchar *
gst_uri_get_location (const gchar * uri) gst_uri_get_location (const gchar * uri)
{ {
gchar *colon; gchar *colon;
gchar *location, *unescaped;
g_return_val_if_fail (uri != NULL, NULL); g_return_val_if_fail (uri != NULL, NULL);
g_return_val_if_fail (gst_uri_is_valid (uri), NULL); g_return_val_if_fail (gst_uri_is_valid (uri), NULL);
colon = strstr (uri, "://"); colon = strstr (uri, "://");
return g_strdup (colon + 3); location = g_strdup (colon + 3);
unescaped = unescape_string (location, "/");
g_free (location);
return unescaped;
} }
/** /**
@ -193,10 +388,17 @@ gst_uri_get_location (const gchar * uri)
gchar * gchar *
gst_uri_construct (const gchar * protocol, const gchar * location) gst_uri_construct (const gchar * protocol, const gchar * location)
{ {
char *escaped;
char *retval;
g_return_val_if_fail (gst_uri_protocol_is_valid (protocol), NULL); g_return_val_if_fail (gst_uri_protocol_is_valid (protocol), NULL);
g_return_val_if_fail (location != NULL, NULL); g_return_val_if_fail (location != NULL, NULL);
return g_strdup_printf ("%s://%s", protocol, location); escaped = escape_string (location);
retval = g_strdup_printf ("%s://%s", protocol, escaped);
g_free (escaped);
return retval;
} }
typedef struct typedef struct