Skip to content

Instantly share code, notes, and snippets.

@jsenin
Last active August 29, 2015 14:16
Show Gist options
  • Save jsenin/0d7bf185a54f09c3c793 to your computer and use it in GitHub Desktop.
Save jsenin/0d7bf185a54f09c3c793 to your computer and use it in GitHub Desktop.
mate-desktop pluma uri decode problem poc
/**
* compile gcc `pkg-config --cflags gtk+-3.0` -o pluma-uri-decode pluma-uri-decode.c `pkg-config --libs gtk+-3.0`
* execute:
* ./pluma-uri-decode file:///tmp/pluma/pluma-1.8.1+dfsg1/pluma/pluma-window.c
*
* running as user will enter at mount part and not show uri, only a mount_name
* running as root will not enter at mount
*/
#include <gtk/gtk.h>
int
main (int argc,
char *argv[])
{
GFile *location;
GMount *mount;
gchar *mount_name;
gchar *uri;
gtk_init (&argc, &argv);
location = g_file_new_for_uri ( argv[1] );
uri = g_file_get_parse_name (location);
mount = g_file_find_enclosing_mount (location, NULL, NULL);
if (mount != NULL)
{
mount_name = g_mount_get_name (mount);
g_message("is mount %s %s", mount_name, uri );
gchar *path;
/* obtain the "path" patrt of the uri */
if (pluma_utils_decode_uri (uri,
NULL, NULL,
NULL, NULL,
&path))
{
g_message("decode ok %s %s", uri , path );
}
}
g_message("end");
return 0;
}
static void
null_ptr (gchar **ptr)
{
if (ptr)
*ptr = NULL;
}
/**
* pluma_utils_decode_uri:
* @uri: the uri to decode
* @scheme: return value pointer for the uri's scheme (e.g. http, sftp, ...)
* @user: return value pointer for the uri user info
* @port: return value pointer for the uri port
* @host: return value pointer for the uri host
* @path: return value pointer for the uri path
*
* Parse and break an uri apart in its individual components like the uri
* scheme, user info, port, host and path. The return value pointer can be
* NULL to ignore certain parts of the uri. If the function returns TRUE, then
* all return value pointers should be freed using g_free
*
* Return value: TRUE if the uri could be properly decoded, FALSE otherwise.
*/
gboolean
pluma_utils_decode_uri (const gchar *uri,
gchar **scheme,
gchar **user,
gchar **host,
gchar **port,
gchar **path
)
{
/* Largely copied from glib/gio/gdummyfile.c:_g_decode_uri. This
* functionality should be in glib/gio, but for now we implement it
* ourselves (see bug #546182) */
const char *p, *in, *hier_part_start, *hier_part_end;
char *out;
char c;
/* From RFC 3986 Decodes:
* URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
*/
p = uri;
null_ptr (scheme);
null_ptr (user);
null_ptr (port);
null_ptr (host);
null_ptr (path);
/* Decode scheme:
* scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
*/
g_message("decoding1");
if (!g_ascii_isalpha (*p)){
g_message("byebye %s",p);
return FALSE;
}
while (1)
{
c = *p++;
if (c == ':')
break;
if (!(g_ascii_isalnum(c) ||
c == '+' ||
c == '-' ||
c == '.'))
return FALSE;
}
if (scheme)
{
*scheme = g_malloc (p - uri);
out = *scheme;
for (in = uri; in < p - 1; in++)
*out++ = g_ascii_tolower (*in);
*out = '\0';
}
hier_part_start = p;
hier_part_end = p + strlen (p);
if (hier_part_start[0] == '/' && hier_part_start[1] == '/')
{
const char *authority_start, *authority_end;
const char *userinfo_start, *userinfo_end;
const char *host_start, *host_end;
const char *port_start;
authority_start = hier_part_start + 2;
/* authority is always followed by / or nothing */
authority_end = memchr (authority_start, '/', hier_part_end - authority_start);
if (authority_end == NULL)
authority_end = hier_part_end;
/* 3.2:
* authority = [ userinfo "@" ] host [ ":" port ]
*/
userinfo_end = memchr (authority_start, '@', authority_end - authority_start);
if (userinfo_end)
{
userinfo_start = authority_start;
if (user)
*user = g_uri_unescape_segment (userinfo_start, userinfo_end, NULL);
if (user && *user == NULL)
{
if (scheme)
g_free (*scheme);
return FALSE;
}
host_start = userinfo_end + 1;
}
else
host_start = authority_start;
port_start = memchr (host_start, ':', authority_end - host_start);
if (port_start)
{
host_end = port_start++;
if (port)
*port = g_strndup (port_start, authority_end - port_start);
}
else
host_end = authority_end;
if (host)
*host = g_strndup (host_start, host_end - host_start);
hier_part_start = authority_end;
}
if (path)
*path = g_uri_unescape_segment (hier_part_start, hier_part_end, "/");
return TRUE;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment