diff options
author | Matthias Clasen <mclasen@redhat.com> | 2021-11-13 11:01:27 -0500 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2021-11-13 11:08:50 -0500 |
commit | e6b3cb4c7aae79d1b02cabcc3659fec145d0954e (patch) | |
tree | cebe6cbb00c8f8c42a3b0759b11da3c6924b696a /pango/css/gtkcssdataurl.c | |
parent | befadb396f3f48a1c2fe0ca07b00e783e0878e02 (diff) | |
download | pango-e6b3cb4c7aae79d1b02cabcc3659fec145d0954e.tar.gz |
Wedge the gtk css parser into pango
This is a brute-force job, just to see how far I get.
Diffstat (limited to 'pango/css/gtkcssdataurl.c')
-rw-r--r-- | pango/css/gtkcssdataurl.c | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/pango/css/gtkcssdataurl.c b/pango/css/gtkcssdataurl.c new file mode 100644 index 00000000..53b1ed93 --- /dev/null +++ b/pango/css/gtkcssdataurl.c @@ -0,0 +1,174 @@ +/* GStreamer data:// uri source element + * Copyright (C) 2009 Igalia S.L + * Copyright (C) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/*<private> + * # Data URLs + * + * These function allow encoding and decoding of data: URLs, see + * [RFC 2397](http://tools.ietf.org/html/rfc2397) for more information. + */ + +#include "config.h" + +#include "gtkcssdataurlprivate.h" + +#include <string.h> + +#define _(x) x + +/*<private> + * gtk_css_data_url_parse: + * @url: the URL to parse + * @out_mimetype: (out nullable optional): Return location to set the contained + * mime type to. If no mime type was specified, this value is set to %NULL. + * @error: error location + * + * Decodes a data URL according to RFC2397 and returns the decoded data. + * + * Returns: a new `GBytes` with the decoded data + */ +GBytes * +gtk_css_data_url_parse (const char *url, + char **out_mimetype, + GError **error) +{ + char *mimetype = NULL; + const char *parameters_start; + const char *data_start; + GBytes *bytes; + gboolean base64 = FALSE; + char *charset = NULL; + gpointer bdata; + gsize bsize; + + /* url must be an URI as defined in RFC 2397 + * data:[<mediatype>][;base64],<data> + */ + if (g_ascii_strncasecmp ("data:", url, 5) != 0) + { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_INVALID_FILENAME, + _("Not a data: URL")); + return NULL; + } + + url += 5; + + parameters_start = strchr (url, ';'); + data_start = strchr (url, ','); + if (data_start == NULL) + { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_INVALID_FILENAME, + _("Malformed data: URL")); + return NULL; + } + if (parameters_start > data_start) + parameters_start = NULL; + + if (data_start != url && parameters_start != url) + { + mimetype = g_strndup (url, + (parameters_start ? parameters_start + : data_start) - url); + } + else + { + mimetype = NULL; + } + + if (parameters_start != NULL) + { + char *parameters_str; + char **parameters; + guint i; + + parameters_str = g_strndup (parameters_start + 1, data_start - parameters_start - 1); + parameters = g_strsplit (parameters_str, ";", -1); + + for (i = 0; parameters[i] != NULL; i++) + { + if (g_ascii_strcasecmp ("base64", parameters[i]) == 0) + { + base64 = TRUE; + } + else if (g_ascii_strncasecmp ("charset=", parameters[i], 8) == 0) + { + g_free (charset); + charset = g_strdup (parameters[i] + 8); + } + } + g_free (parameters_str); + g_strfreev (parameters); + } + + /* Skip comma */ + data_start += 1; + if (base64) + { + bdata = g_base64_decode (data_start, &bsize); + } + else + { + /* URI encoded, i.e. "percent" encoding */ + /* XXX: This doesn't allow nul bytes */ + bdata = g_uri_unescape_string (data_start, NULL); + if (bdata == NULL) + { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_INVALID_FILENAME, + _("Could not unescape string")); + g_free (mimetype); + return NULL; + } + bsize = strlen (bdata); + } + + /* Convert to UTF8 */ + if ((mimetype == NULL || g_ascii_strcasecmp ("text/plain", mimetype) == 0) && + charset && g_ascii_strcasecmp ("US-ASCII", charset) != 0 + && g_ascii_strcasecmp ("UTF-8", charset) != 0) + { + gsize read; + gsize written; + gpointer data; + + data = g_convert_with_fallback (bdata, bsize, + "UTF-8", charset, + (char *) "*", + &read, &written, NULL); + g_free (bdata); + + bdata = data; + bsize = written; + } + bytes = g_bytes_new_take (bdata, bsize); + + g_free (charset); + if (out_mimetype) + *out_mimetype = mimetype; + else + g_free (mimetype); + + return bytes; +} |