From 05a8e0d352affa5999cf906249aa40c7c44fc4f0 Mon Sep 17 00:00:00 2001 From: Rob Norris Date: Sun, 16 Oct 2016 11:26:41 +0100 Subject: [PATCH] Embed GtkHTML 4.10.0 URI functions https://git.gnome.org/browse/gtkhtml --- src/Makefile.am | 3 +- src/misc/gtkhtml-private.h | 32 ++++++ src/misc/gtkhtml.c | 193 +++++++++++++++++++++++++++++++++++++ 3 files changed, 227 insertions(+), 1 deletion(-) create mode 100644 src/misc/gtkhtml-private.h create mode 100644 src/misc/gtkhtml.c diff --git a/src/Makefile.am b/src/Makefile.am index 7c580905..d3093a6d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -158,7 +158,8 @@ libviking_a_SOURCES = \ preferences.c preferences.h \ misc/fpconv.c misc/fpconv.h misc/powers.h \ misc/strtod.c misc/strtod.h \ - misc/kdtree.c misc/kdtree.h + misc/kdtree.c misc/kdtree.h \ + misc/gtkhtml.c misc/gtkhtml-private.h if BING libviking_a_SOURCES += \ diff --git a/src/misc/gtkhtml-private.h b/src/misc/gtkhtml-private.h new file mode 100644 index 00000000..5fe1dcaf --- /dev/null +++ b/src/misc/gtkhtml-private.h @@ -0,0 +1,32 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* This file is part of the GtkHTML library. + * + * Copyright 1999, 2000 Helix Code, Inc. + * + * 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; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ +/* + * Viking note: This is an extract from GtkHTML 4.10.0 for URI functions + */ +#ifndef _GTKHTML_PRIVATE_H +#define _GTKHTML_PRIVATE_H + +#include + +gchar *gtk_html_filename_to_uri (const gchar *filename); +gchar *gtk_html_filename_from_uri (const gchar *uri); + +#endif /* _GTKHTML_PRIVATE_H */ diff --git a/src/misc/gtkhtml.c b/src/misc/gtkhtml.c new file mode 100644 index 00000000..5565cf11 --- /dev/null +++ b/src/misc/gtkhtml.c @@ -0,0 +1,193 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* This file is part of the GtkHTML library. + * + * Copyright 1999, 2000 Helix Code, Inc. + * + * 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; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ +/* + * Viking note: This is an extract from GtkHTML 4.10.0 for URI functions + */ +#include "gtkhtml-private.h" +#include + +gchar * +gtk_html_filename_from_uri (const gchar *uri) +{ + const gchar *relative_fpath; + gchar *temp_uri, *temp_filename; + gchar *retval; + + if (!uri || !*uri) + return NULL; + + if (g_ascii_strncasecmp (uri, "file://", 7) == 0) + return g_filename_from_uri (uri, NULL, NULL); + + if (g_ascii_strncasecmp (uri, "file:", 5) == 0) { + /* Relative (file or other) URIs shouldn't contain the + * scheme prefix at all. But accept such broken URIs + * anyway. Whether they are URI-encoded or not is + * anybody's guess, assume they are. + */ + relative_fpath = uri + 5; + } else { + /* A proper relative file URI. Just do the URI-decoding. */ + relative_fpath = uri; + } + + if (g_path_is_absolute (relative_fpath)) { + /* The totally broken case of "file:" followed + * directly by an absolute pathname. + */ + /* file:/foo/bar.zap or file:c:/foo/bar.zap */ +#ifdef G_OS_WIN32 + if (g_ascii_isalpha (relative_fpath[0]) && relative_fpath[1] == ':') + temp_uri = g_strconcat ("file:///", relative_fpath, NULL); + else + temp_uri = g_strconcat ("file://", relative_fpath, NULL); +#else + temp_uri = g_strconcat ("file://", relative_fpath, NULL); +#endif + retval = g_filename_from_uri (temp_uri, NULL, NULL); + g_free (temp_uri); + + return retval; + } + + /* Create a dummy absolute file: URI and call + * g_filename_from_uri(), then strip off the dummy + * prefix. + */ +#ifdef G_OS_WIN32 + if (g_ascii_isalpha (relative_fpath[0]) && relative_fpath[1] == ':') { + /* file:c:relative/path/foo.bar */ + gchar drive_letter = relative_fpath[0]; + + temp_uri = g_strconcat ("file:///dummy/", relative_fpath + 2, NULL); + temp_filename = g_filename_from_uri (temp_uri, NULL, NULL); + g_free (temp_uri); + + if (temp_filename == NULL) + return NULL; + + g_assert (strncmp (temp_filename, G_DIR_SEPARATOR_S "dummy" G_DIR_SEPARATOR_S, 7) == 0); + + retval = g_strdup_printf ("%c:%s", drive_letter, temp_filename + 7); + g_free (temp_filename); + + return retval; + } +#endif + temp_uri = g_strconcat ("file:///dummy/", relative_fpath, NULL); + temp_filename = g_filename_from_uri (temp_uri, NULL, NULL); + g_free (temp_uri); + + if (temp_filename == NULL) + return NULL; + + g_assert (strncmp (temp_filename, G_DIR_SEPARATOR_S "dummy" G_DIR_SEPARATOR_S, 7) == 0); + + retval = g_strdup (temp_filename + 7); + g_free (temp_filename); + + return retval; +} + +gchar * +gtk_html_filename_to_uri (const gchar *filename) +{ + gchar *fake_filename, *fake_uri, *retval; + const gchar dummy_prefix[] = "file:///dummy/"; + const gint dummy_prefix_len = sizeof (dummy_prefix) - 1; +#ifdef G_OS_WIN32 + gchar drive_letter = 0; +#else + gchar *first_end, *colon; +#endif + + if (!filename || !*filename) + return NULL; + + if (g_path_is_absolute (filename)) + return g_filename_to_uri (filename, NULL, NULL); + + /* filename is a relative path, and the corresponding URI is + * filename as such but URI-escaped. Instead of yet again + * copy-pasteing the URI-escape code from gconvert.c (or + * somewhere else), prefix a fake top-level directory to make + * it into an absolute path, call g_filename_to_uri() to turn it + * into a full file: URI, and then strip away the file:/// and + * the fake top-level directory. + */ + +#ifdef G_OS_WIN32 + if (g_ascii_isalpha (*filename) && filename[1] == ':') { + /* A non-absolute path, but with a drive letter. Ugh. */ + drive_letter = *filename; + filename += 2; + } +#endif + fake_filename = g_build_filename ("/dummy", filename, NULL); + fake_uri = g_filename_to_uri (fake_filename, NULL, NULL); + g_free (fake_filename); + + if (fake_uri == NULL) + return NULL; + + g_assert (strncmp (fake_uri, dummy_prefix, dummy_prefix_len) == 0); + +#ifdef G_OS_WIN32 + /* Re-insert the drive letter if we had one. Double ugh. + * URI-encode the colon so the drive letter isn't taken for a + * URI scheme! + */ + if (drive_letter) + retval = g_strdup_printf ("%c%%3a%s", + drive_letter, + fake_uri + dummy_prefix_len); + else + retval = g_strdup (fake_uri + dummy_prefix_len); +#else + retval = g_strdup (fake_uri + dummy_prefix_len); +#endif + g_free (fake_uri); + +#ifdef G_OS_UNIX + /* Check if there are colons in the first component of the + * pathname, and URI-encode them so that the part up to the + * colon isn't taken for a URI scheme name! This isn't + * necessary on Win32 as there can't be colons in a file name + * in the first place. + */ + first_end = strchr (retval, '/'); + if (first_end == NULL) + first_end = retval + strlen (retval); + + while ((colon = strchr (retval, ':')) != NULL && colon < first_end) { + gchar *new_retval = g_malloc (strlen (retval) + 3); + + strncpy (new_retval, retval, colon - retval); + strcpy (new_retval + (colon - retval), "%3a"); + strcpy (new_retval + (colon - retval) + 3, colon + 1); + + g_free (retval); + retval = new_retval; + } +#endif + + return retval; +} -- 2.39.5