[glib-networking/mcatanzaro/proxies] wip




commit 9e2828843e90458d57d042c2d1b6e71b1c9afc07
Author: Michael Catanzaro <mcatanzaro redhat com>
Date:   Fri Jul 2 15:43:01 2021 -0500

    wip

 meson.build                                   |  19 +-
 proxy/environment/environmentproxy-module.c   |  65 +++++++
 proxy/environment/genvironmentproxyresolver.c | 262 ++++++++++++++++++++++++++
 proxy/environment/genvironmentproxyresolver.h |  35 ++++
 proxy/environment/meson.build                 |  38 ++++
 proxy/gnome/meson.build                       |   2 +-
 proxy/libproxy/meson.build                    |   2 +-
 proxy/tests/{libproxy.c => environment.c}     |   0
 proxy/tests/meson.build                       |  15 +-
 9 files changed, 421 insertions(+), 17 deletions(-)
---
diff --git a/meson.build b/meson.build
index bf5f845c..83f926d9 100644
--- a/meson.build
+++ b/meson.build
@@ -169,20 +169,19 @@ if ['darwin', 'ios'].contains(host_system)
   module_suffix = 'so'
 endif
 
-if libproxy_dep.found() or gsettings_desktop_schemas_dep.found()
-  proxy_test_programs = []
+proxy_test_programs = []
 
-  if libproxy_dep.found()
-    subdir('proxy/libproxy')
-  endif
-
-  if gsettings_desktop_schemas_dep.found()
-    subdir('proxy/gnome')
-  endif
+if libproxy_dep.found()
+subdir('proxy/libproxy')
+endif
 
-  subdir('proxy/tests')
+if gsettings_desktop_schemas_dep.found()
+subdir('proxy/gnome')
 endif
 
+subdir('proxy/environment')
+subdir('proxy/tests')
+
 subdir('tls/base')
 
 if gnutls_dep.found()
diff --git a/proxy/environment/environmentproxy-module.c b/proxy/environment/environmentproxy-module.c
new file mode 100644
index 00000000..0361849f
--- /dev/null
+++ b/proxy/environment/environmentproxy-module.c
@@ -0,0 +1,65 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright 2021 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+
+#include "genvironmentproxyresolver.h"
+
+
+void
+g_io_environmentproxy_load (GIOModule *module)
+{
+  gchar *locale_dir;
+#ifdef G_OS_WIN32
+  gchar *base_dir;
+#endif
+
+  g_environment_proxy_resolver_register (module);
+
+#ifdef G_OS_WIN32
+  base_dir = g_win32_get_package_installation_directory_of_module (NULL);
+  locale_dir = g_build_filename (base_dir, "share", "locale", NULL);
+  g_free (base_dir);
+#else
+  locale_dir = g_strdup (LOCALE_DIR);
+#endif
+
+  bindtextdomain (GETTEXT_PACKAGE, locale_dir);
+  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+  g_free (locale_dir);
+}
+
+void
+g_io_environmentproxy_unload (GIOModule *module)
+{
+}
+
+gchar **
+g_io_environmentproxy_query (void)
+{
+  gchar *eps[] = {
+    G_PROXY_RESOLVER_EXTENSION_POINT_NAME,
+    NULL
+  };
+  return g_strdupv (eps);
+}
diff --git a/proxy/environment/genvironmentproxyresolver.c b/proxy/environment/genvironmentproxyresolver.c
new file mode 100644
index 00000000..b0afeb4e
--- /dev/null
+++ b/proxy/environment/genvironmentproxyresolver.c
@@ -0,0 +1,262 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright 2021 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "genvironmentproxyresolver.h"
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+
+struct _GEnvironmentProxyResolver {
+  GObject parent_instance;
+};
+
+static void g_environment_proxy_resolver_iface_init (GProxyResolverInterface *iface);
+
+#ifdef GENVIRONMENTPROXY_MODULE
+static void
+g_environment_proxy_resolver_class_finalize (GEnvironmentProxyResolverClass *klass)
+{
+}
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (GEnvironmentProxyResolver,
+                                g_environment_proxy_resolver,
+                                G_TYPE_OBJECT, 0,
+                                G_IMPLEMENT_INTERFACE_DYNAMIC (G_TYPE_PROXY_RESOLVER,
+                                                               g_environment_proxy_resolver_iface_init))
+#else
+G_DEFINE_TYPE_EXTENDED (GEnvironmentProxyResolver,
+                        g_environment_proxy_resolver,
+                        G_TYPE_OBJECT, 0,
+                        G_IMPLEMENT_INTERFACE (G_TYPE_PROXY_RESOLVER,
+                                               g_environment_proxy_resolver_iface_init))
+#endif
+
+static void
+g_environment_proxy_resolver_init (GEnvironmentProxyResolver *resolver)
+{
+}
+
+static gboolean
+g_environment_proxy_resolver_is_supported (GProxyResolver *object)
+{
+  return g_getenv ("ftp_proxy") || g_getenv ("FTP_PROXY") ||
+         g_getenv ("https_proxy") || g_getenv ("HTTPS_PROXY") ||
+         g_getenv ("http_proxy") || g_getenv ("HTTP_PROXY") ||
+         g_getenv ("no_proxy") || g_getenv ("NO_PROXY");
+}
+
+static gchar **
+proxy_results (const gchar *uri)
+{
+  gchar **proxies = g_new0 (gchar *, 2);
+  proxies[0] = g_strdup (uri);
+  return proxies;
+}
+
+static gboolean
+is_uri_ignored (const gchar *uri,
+                const gchar *ignore_pattern)
+{
+  GUri *guri = NULL;
+  GUri *ignore_guri = NULL;
+  const char *host;
+  const char *ignore_host;
+  int port;
+  int ignore_port;
+  gboolean ignored = FALSE;
+  GError *error = NULL;
+
+  guri = g_uri_parse (uri, G_URI_FLAGS_NONE, &error);
+  if (!guri)
+    {
+      g_warning ("Failed to parse URI %s: %s", uri, error->message);
+      g_error_free (error);
+      goto out;
+    }
+  host = g_uri_get_host (guri);
+  if (!host)
+    goto out;
+  port = g_uri_get_port (guri);
+
+  ignore_guri = g_uri_parse (ignore_pattern, G_URI_FLAGS_NONE, &error);
+  if (!ignore_guri)
+    {
+      g_warning ("Failed to parse URI %s: %s", ignore_pattern, error->message);
+      g_error_free (error);
+      goto out;
+    }
+  ignore_host = g_uri_get_host (ignore_guri);
+  if (!ignore_host)
+    goto out;
+  ignore_port = g_uri_get_port (ignore_guri);
+
+  /* libproxy's no_proxy config is implement in its ignore_domain.cpp,
+   * ignore_hostname.cpp, and ignore_ip.cpp. It's smarter than ours. I've just
+   * copied the basic domain checks from libproxy's ignore_domain.cpp. (Note the
+   * glob check is *really* strict.)
+   */
+
+       /* Hostname match (domain.com or domain.com:80) */
+       if (strcmp (host, ignore_host) == 0)
+               return (ignore_port == 0 || port == ignore_port);
+
+       /* Endswith (.domain.com or .domain.com:80) */
+       if (ignore_host[0] == '.' && g_str_has_suffix (host, ignore_host))
+               return (ignore_port == 0 || port == ignore_port);
+
+       /* Glob (*.domain.com or *.domain.com:80). */
+       if (ignore_host[0] == '*' && g_str_has_suffix (host, ignore_host + 1))
+               return (ignore_port == 0 || port == ignore_port);
+
+out:
+  if (guri)
+    g_uri_unref (guri);
+  if (ignore_guri)
+    g_uri_unref (ignore_guri);
+  return ignored;
+}
+
+static gchar **
+g_environment_proxy_resolver_lookup (GProxyResolver  *resolver,
+                                     const gchar     *uri,
+                                     GCancellable    *cancellable,
+                                     GError         **error)
+{
+  gchar *scheme = g_uri_parse_scheme (uri);
+  gchar **no_proxy = NULL;
+
+  if (g_getenv ("no_proxy"))
+    no_proxy = g_strsplit (g_getenv ("no_proxy"), ",", -1);
+  else if (g_getenv ("NO_PROXY"))
+    no_proxy = g_strsplit (g_getenv ("NO_PROXY"), ",", -1);
+
+  if (no_proxy)
+    {
+      int len = g_strv_length (no_proxy);
+      gboolean ignored = FALSE;
+
+      for (int i = 0; i < len; i++)
+        {
+          if (is_uri_ignored (uri, no_proxy[i]))
+            {
+              ignored = TRUE;
+              break;
+            }
+        }
+      g_strfreev (no_proxy);
+
+      if (ignored)
+        return proxy_results ("direct://");
+    }
+
+  /* The order of precedence of the environment variables is copied from
+   * libproxy's config_envvar.cpp. We match it carefully. Note that the
+   * HTTP proxy is used for all schemes, not just HTTP.
+   */
+  if (g_ascii_strcasecmp (scheme, "ftp") == 0)
+    {
+      if (g_getenv ("ftp_proxy"))
+        return proxy_results (g_getenv ("ftp_proxy"));
+      if (g_getenv ("FTP_proxy"))
+        return proxy_results (g_getenv ("FTP_PROXY"));
+    }
+
+  if (g_ascii_strcasecmp (scheme, "https") == 0)
+    {
+      if (g_getenv ("https_proxy"))
+        return proxy_results (g_getenv ("https_proxy"));
+      if (g_getenv ("HTTPS_proxy"))
+        return proxy_results (g_getenv ("HTTPS_PROXY"));
+    }
+
+  if (g_getenv ("http_proxy"))
+    return proxy_results (g_getenv ("http_proxy"));
+
+  if (g_getenv ("HTTP_PROXY"))
+    return proxy_results (g_getenv ("HTTP_PROXY"));
+
+  return g_new0 (gchar *, 1);
+}
+
+static void
+g_environment_proxy_resolver_lookup_async (GProxyResolver      *resolver,
+                                           const gchar         *uri,
+                                           GCancellable        *cancellable,
+                                           GAsyncReadyCallback  callback,
+                                           gpointer             user_data)
+{
+  GTask *task;
+  gchar **proxies;
+
+  proxies = g_environment_proxy_resolver_lookup (resolver, uri, cancellable, NULL);
+
+  task = g_task_new (resolver, cancellable, callback, user_data);
+  g_task_set_source_tag (task, g_environment_proxy_resolver_lookup_async);
+  g_task_set_name (task, "[glib-networking] g_environment_proxy_resolver_lookup_async");
+  g_task_set_task_data (task, g_strdup (uri), g_free);
+  g_task_set_return_on_cancel (task, TRUE);
+  g_task_return_pointer (task, proxies, (GDestroyNotify)g_strfreev);
+  g_object_unref (task);
+}
+
+static gchar **
+g_environment_proxy_resolver_lookup_finish (GProxyResolver     *resolver,
+                                            GAsyncResult       *result,
+                                            GError            **error)
+{
+  g_return_val_if_fail (g_task_is_valid (result, resolver), NULL);
+  g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == 
g_environment_proxy_resolver_lookup_async, NULL);
+
+  return g_task_propagate_pointer (G_TASK (result), error);
+}
+
+static void
+g_environment_proxy_resolver_class_init (GEnvironmentProxyResolverClass *resolver_class)
+{
+}
+
+static void
+g_environment_proxy_resolver_iface_init (GProxyResolverInterface *iface)
+{
+  iface->is_supported = g_environment_proxy_resolver_is_supported;
+  iface->lookup = g_environment_proxy_resolver_lookup;
+  iface->lookup_async = g_environment_proxy_resolver_lookup_async;
+  iface->lookup_finish = g_environment_proxy_resolver_lookup_finish;
+}
+
+#ifdef GENVIRONMENTPROXY_MODULE
+void
+g_environment_proxy_resolver_register (GIOModule *module)
+{
+  g_environment_proxy_resolver_register_type (G_TYPE_MODULE (module));
+  if (!module)
+    g_io_extension_point_register (G_PROXY_RESOLVER_EXTENSION_POINT_NAME);
+  g_io_extension_point_implement (G_PROXY_RESOLVER_EXTENSION_POINT_NAME,
+                                  g_environment_proxy_resolver_get_type(),
+                                  "environment",
+                                  100);
+}
+#endif
diff --git a/proxy/environment/genvironmentproxyresolver.h b/proxy/environment/genvironmentproxyresolver.h
new file mode 100644
index 00000000..faf5b6f3
--- /dev/null
+++ b/proxy/environment/genvironmentproxyresolver.h
@@ -0,0 +1,35 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright 2021 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_ENVIRONMENT_PROXY_RESOLVER         (g_environment_proxy_resolver_get_type ())
+
+G_DECLARE_FINAL_TYPE (GEnvironmentProxyResolver, g_environment_proxy_resolver, G, 
ENVIRONMENT_PROXY_RESOLVER, GObject)
+
+void g_environment_proxy_resolver_register (GIOModule *module);
+
+G_END_DECLS
diff --git a/proxy/environment/meson.build b/proxy/environment/meson.build
new file mode 100644
index 00000000..9f8a4133
--- /dev/null
+++ b/proxy/environment/meson.build
@@ -0,0 +1,38 @@
+service_conf = configuration_data()
+service_conf.set('libexecdir', libexecdir)
+
+sources = files(
+  'genvironmentproxyresolver.c',
+  'environmentproxy-module.c'
+)
+
+deps = [
+  gio_dep,
+  glib_dep,
+  gmodule_dep,
+  gobject_dep
+]
+
+module = shared_module(
+  'gioenvironmentproxy',
+  sources: sources,
+  include_directories: top_inc,
+  dependencies: deps,
+  c_args: '-DGENVIRONMENTPROXY_MODULE',
+  link_args: module_ldflags,
+  link_depends: symbol_map,
+  name_suffix: module_suffix,
+  install: true,
+  install_dir: gio_module_dir
+)
+
+if get_option('static_modules')
+  static_library('gioenvironmentproxy',
+    objects: module.extract_all_objects(),
+    install: true,
+    install_dir: gio_module_dir
+  )
+  pkg.generate(module)
+endif
+
+proxy_test_programs += [['environment', 'environment', deps]]
diff --git a/proxy/gnome/meson.build b/proxy/gnome/meson.build
index 278ca328..dd4bc5be 100644
--- a/proxy/gnome/meson.build
+++ b/proxy/gnome/meson.build
@@ -32,4 +32,4 @@ if get_option('static_modules')
   pkg.generate(module)
 endif
 
-proxy_test_programs += [['gnome', deps]]
+proxy_test_programs += [['gnome', 'gnome', deps]]
diff --git a/proxy/libproxy/meson.build b/proxy/libproxy/meson.build
index 038bfa1e..7a766b3d 100644
--- a/proxy/libproxy/meson.build
+++ b/proxy/libproxy/meson.build
@@ -70,4 +70,4 @@ executable(
   install_dir: libexecdir
 )
 
-proxy_test_programs += [['libproxy', deps]]
+proxy_test_programs += [['environment', 'libproxy', deps]]
diff --git a/proxy/tests/libproxy.c b/proxy/tests/environment.c
similarity index 100%
rename from proxy/tests/libproxy.c
rename to proxy/tests/environment.c
diff --git a/proxy/tests/meson.build b/proxy/tests/meson.build
index 4e0079f0..fd385876 100644
--- a/proxy/tests/meson.build
+++ b/proxy/tests/meson.build
@@ -8,20 +8,25 @@ foreach program: proxy_test_programs
   test_conf.set('installed_tests_dir', installed_tests_execdir)
   test_conf.set('program', program[0])
 
+  test_name = program[0]
+  if program[0] != program[1]
+    test_name = program[0] + '-' + program[1]
+  endif
+
   if enable_installed_tests
     configure_file(
       input: test_template,
-      output: program[0] + '.test',
+      output: test_name + '.test',
       install_dir: installed_tests_metadir,
       configuration: test_conf
     )
   endif
 
   exe = executable(
-    program[0],
+    test_name,
     program[0] + '.c',
     include_directories: top_inc,
-    dependencies: program[1],
+    dependencies: program[2],
     c_args: cflags,
     install: enable_installed_tests,
     install_dir: installed_tests_execdir
@@ -30,11 +35,11 @@ foreach program: proxy_test_programs
   envs = [
     'G_TEST_SRCDIR=' + meson.current_source_dir(),
     'G_TEST_BUILDDIR=' + meson.current_build_dir(),
-    'GIO_MODULE_DIR=' + join_paths(meson.build_root(), 'proxy', program[0])
+    'GIO_MODULE_DIR=' + join_paths(meson.build_root(), 'proxy', program[1])
   ]
 
   test(
-    program[0],
+    test_name,
     exe,
     env: envs
   )


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]