mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 11:41:09 +00:00
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:
parent
bedb0bef2b
commit
970da8b0f9
2 changed files with 209 additions and 2 deletions
|
@ -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),
|
||||||
|
|
206
gst/gsturi.c
206
gst/gsturi.c
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue