GIO Extension for libproxy
authorNicolas Dufresne <nicolas.dufresne@collabora.co.uk>
Thu, 12 Aug 2010 19:41:21 +0000 (15:41 -0400)
committerNicolas Dufresne <nicolas.dufresne@collabora.co.uk>
Thu, 12 Aug 2010 19:41:21 +0000 (15:41 -0400)
Makefile.am
proxy/libproxy/Makefile.am [new file with mode: 0644]
proxy/libproxy/glibproxyresolver.c [new file with mode: 0644]
proxy/libproxy/glibproxyresolver.h [new file with mode: 0644]
proxy/libproxy/libproxy-module.c [new file with mode: 0644]

index 7d75347..866666b 100644 (file)
@@ -4,3 +4,7 @@ include $(top_srcdir)/Makefile.decl
 ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
 
 SUBDIRS =
+
+if HAVE_LIBPROXY
+SUBDIRS += proxy/libproxy
+endif
diff --git a/proxy/libproxy/Makefile.am b/proxy/libproxy/Makefile.am
new file mode 100644 (file)
index 0000000..dbd9ba0
--- /dev/null
@@ -0,0 +1,27 @@
+include $(top_srcdir)/Makefile.decl
+
+NULL =
+
+module_flags = -export_dynamic -avoid-version -module -no-undefined -export-symbols-regex '^g_io_module_(load|unload|query)'
+
+giomodule_LTLIBRARIES = libgiolibproxy.la
+giomoduledir = $(GIO_MODULE_DIR)
+
+libgiolibproxy_la_SOURCES =            \
+       glibproxyresolver.c             \
+       glibproxyresolver.h             \
+       libproxy-module.c               \
+       $(NULL)
+
+libgiolibproxy_la_CFLAGS = \
+       -DG_LOG_DOMAIN=\"GLib-Net\"     \
+       $(GIO_CFLAGS)                   \
+       $(LIBPROXY_CFLAGS)              \
+       -DGIO_MODULE_DIR=\"$(GIO_MODULE_DIR)\"  \
+       -DG_DISABLE_DEPRECATED
+
+libgiolibproxy_la_LDFLAGS = $(module_flags)
+libgiolibproxy_la_LIBADD = \
+               $(GIO_LIBS) \
+               $(LIBPROXY_LIBS) \
+               $(NULL)
diff --git a/proxy/libproxy/glibproxyresolver.c b/proxy/libproxy/glibproxyresolver.c
new file mode 100644 (file)
index 0000000..5ee5d9c
--- /dev/null
@@ -0,0 +1,267 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2010 Collabora, Ltd.
+ *
+ * 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 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
+ */
+
+#include "config.h"
+
+#include <proxy.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "glibproxyresolver.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+struct _GLibProxyResolver {
+  GObject parent_instance;
+  pxProxyFactory *factory;
+};
+
+static void g_libproxy_resolver_iface_init (GProxyResolverInterface *iface);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (GLibProxyResolver,
+                               g_libproxy_resolver,
+                               G_TYPE_OBJECT, 0,
+                               G_IMPLEMENT_INTERFACE_DYNAMIC (G_TYPE_PROXY_RESOLVER,
+                                                              g_libproxy_resolver_iface_init))
+
+static void  g_libproxy_resolver_class_finalize (GLibProxyResolverClass *klass)
+{
+}
+
+static void
+g_libproxy_resolver_finalize (GObject *object)
+{
+  GLibProxyResolver *resolver = G_LIBPROXY_RESOLVER (object);
+  
+  if (resolver->factory)
+    {
+      px_proxy_factory_free (resolver->factory);
+      resolver->factory = NULL;
+    }
+
+  /* must chain up */
+  G_OBJECT_CLASS (g_libproxy_resolver_parent_class)->finalize (object);
+}
+
+static void
+g_libproxy_resolver_init (GLibProxyResolver *resolver)
+{
+  resolver->factory = px_proxy_factory_new ();
+}
+
+static gboolean
+g_libproxy_resolver_is_supported (GProxyResolver *object)
+{
+  GLibProxyResolver *resolver = G_LIBPROXY_RESOLVER (object);
+  return resolver->factory != NULL;
+}
+
+static gchar **
+copy_proxies (gchar **proxies)
+{
+  gchar **copy;
+  int len = 0;
+  int i, j;
+
+  for (i = 0; proxies[i]; i++)
+    {
+      if (!strncmp ("socks://", proxies[i], 8))
+        len += 3;
+      else
+        len++;
+    }
+
+  copy = g_new (gchar *, len + 1);
+  for (i = j = 0; proxies[i]; i++, j++)
+    {
+      if (!strncmp ("socks://", proxies[i], 8))
+        {
+          copy[j++] = g_strdup_printf ("socks5://%s", proxies[i] + 8);
+          copy[j++] = g_strdup_printf ("socks4a://%s", proxies[i] + 8);
+          copy[j] = g_strdup_printf ("socks4://%s", proxies[i] + 8);
+        }
+      else
+        {
+          copy[j] = g_strdup (proxies[i]);
+        }
+    }
+  copy[j] = NULL;
+
+  return copy;
+}
+
+static void
+free_libproxy_proxies (gchar **proxies)
+{
+  int i;
+
+  for (i = 0; proxies[i]; i++)
+    free (proxies[i]);
+  free (proxies);
+}
+
+static gchar **
+get_libproxy_proxies (GLibProxyResolver  *resolver,
+                     const gchar        *uri,
+                     GCancellable       *cancellable,
+                     GError            **error)
+{
+  gchar **proxies;
+
+  /* FIXME: this is not really cancellable; to do it right we'd
+   * need to run this function in a thread pool like GThreadedResolver.
+   */
+
+  if (g_cancellable_set_error_if_cancelled (cancellable, error))
+    return NULL;
+
+  proxies = px_proxy_factory_get_proxies (resolver->factory, uri);
+  if (!proxies)
+    {
+      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                          _("Proxy resolver internal error."));
+    }
+
+  return proxies;
+}
+
+static gchar **
+g_libproxy_resolver_lookup (GProxyResolver  *iresolver,
+                           const gchar     *uri,
+                           GCancellable    *cancellable,
+                           GError         **error)
+{
+  GLibProxyResolver *resolver;
+  gchar **proxies;
+
+  g_return_val_if_fail (G_IS_LIBPROXY_RESOLVER (iresolver), NULL);
+  g_return_val_if_fail (uri != NULL, NULL);
+
+  resolver = G_LIBPROXY_RESOLVER (iresolver);
+
+  proxies = get_libproxy_proxies (resolver, uri, cancellable, error);
+
+  /* We always copy to be able to translate "socks" entry into
+   * three entries ("socks5", "socks4a", "socks4").
+   */
+  if (proxies)
+    {
+      gchar **copy;
+
+      copy = copy_proxies (proxies);
+      free_libproxy_proxies (proxies);
+      proxies = copy;
+    }
+
+  return proxies;
+}
+
+static void
+_lookup_async (GSimpleAsyncResult *simple,
+              GObject *object,
+              GCancellable *cancellable)
+{
+  GLibProxyResolver *resolver = G_LIBPROXY_RESOLVER (object);
+  GError *error = NULL;
+  gchar **proxies = NULL;
+  gchar *uri;
+
+  uri = g_simple_async_result_get_op_res_gpointer (simple);
+
+  proxies = get_libproxy_proxies (resolver, uri, cancellable, &error);
+
+  if (error)
+    {
+      g_simple_async_result_set_from_error (simple, error);
+      g_error_free (error);
+    }
+  else
+    g_simple_async_result_set_op_res_gpointer (simple, proxies, (GDestroyNotify)free_libproxy_proxies);
+}
+
+static void
+g_libproxy_resolver_lookup_async (GProxyResolver      *resolver,
+                                 const gchar         *uri,
+                                 GCancellable        *cancellable,
+                                 GAsyncReadyCallback  callback,
+                                 gpointer             user_data)
+{
+  GSimpleAsyncResult *simple;
+
+  simple = g_simple_async_result_new (G_OBJECT (resolver),
+                                     callback, user_data,
+                                     g_libproxy_resolver_lookup_async);
+  g_simple_async_result_set_op_res_gpointer (simple,
+                                            g_strdup (uri),
+                                            (GDestroyNotify) g_free);
+  g_simple_async_result_run_in_thread (simple, _lookup_async,
+                                      G_PRIORITY_DEFAULT, cancellable);
+  g_object_unref (simple);
+}
+
+static gchar **
+g_libproxy_resolver_lookup_finish (GProxyResolver     *resolver,
+                                  GAsyncResult       *result,
+                                  GError            **error)
+{
+  GSimpleAsyncResult *simple;
+  gchar **proxies;
+
+  g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (resolver), g_libproxy_resolver_lookup_async), NULL);
+
+  simple = G_SIMPLE_ASYNC_RESULT (result);
+
+  if (g_simple_async_result_propagate_error (simple, error))
+    return NULL;
+
+  proxies = g_simple_async_result_get_op_res_gpointer (simple);
+  return copy_proxies (proxies);
+}
+
+static void
+g_libproxy_resolver_class_init (GLibProxyResolverClass *resolver_class)
+{
+  GObjectClass *object_class;
+  
+  object_class = G_OBJECT_CLASS (resolver_class);
+  object_class->finalize = g_libproxy_resolver_finalize;
+}
+
+static void
+g_libproxy_resolver_iface_init (GProxyResolverInterface *iface)
+{
+  iface->is_supported = g_libproxy_resolver_is_supported;
+  iface->lookup = g_libproxy_resolver_lookup;
+  iface->lookup_async = g_libproxy_resolver_lookup_async;
+  iface->lookup_finish = g_libproxy_resolver_lookup_finish;
+}
+
+void
+g_libproxy_resolver_register (GIOModule *module)
+{
+  g_libproxy_resolver_register_type (G_TYPE_MODULE (module));
+  g_io_extension_point_implement (G_PROXY_RESOLVER_EXTENSION_POINT_NAME,
+                                 g_libproxy_resolver_get_type(),
+                                 "libproxy",
+                                 0);
+}
diff --git a/proxy/libproxy/glibproxyresolver.h b/proxy/libproxy/glibproxyresolver.h
new file mode 100644 (file)
index 0000000..19d2d13
--- /dev/null
@@ -0,0 +1,50 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2010 Collabora, Ltd.
+ *
+ * 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 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
+ */
+
+#ifndef __G_LIBPROXY_RESOLVER_H__
+#define __G_LIBPROXY_RESOLVER_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_LIBPROXY_RESOLVER         (g_libproxy_resolver_get_type ())
+#define G_LIBPROXY_RESOLVER(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_LIBPROXY_RESOLVER, GLibProxyResolver))
+#define G_LIBPROXY_RESOLVER_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_LIBPROXY_RESOLVER, GLibProxyResolverClass))
+#define G_IS_LIBPROXY_RESOLVER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_LIBPROXY_RESOLVER))
+#define G_IS_LIBPROXY_RESOLVER_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_LIBPROXY_RESOLVER))
+#define G_LIBPROXY_RESOLVER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_LIBPROXY_RESOLVER, GLibProxyResolverClass))
+
+typedef struct _GLibProxyResolver       GLibProxyResolver;
+typedef struct _GLibProxyResolverClass  GLibProxyResolverClass;
+
+struct _GLibProxyResolverClass {
+  GObjectClass parent_class;
+};
+
+GType g_libproxy_resolver_get_type (void);
+void  g_libproxy_resolver_register (GIOModule *module);
+
+G_END_DECLS
+
+#endif /* __G_LIBPROXY_RESOLVER_H__ */
diff --git a/proxy/libproxy/libproxy-module.c b/proxy/libproxy/libproxy-module.c
new file mode 100644 (file)
index 0000000..766840e
--- /dev/null
@@ -0,0 +1,47 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2010 Collabora, Ltd.
+ *
+ * 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 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
+ */
+
+#include "config.h"
+
+#include "glibproxyresolver.h"
+
+
+void
+g_io_module_load (GIOModule *module)
+{
+  g_libproxy_resolver_register (module);
+}
+
+void
+g_io_module_unload (GIOModule *module)
+{
+}
+
+gchar **
+g_io_module_query (void)
+{
+  gchar *eps[] = {
+    G_PROXY_RESOLVER_EXTENSION_POINT_NAME,
+    NULL
+  };
+  return g_strdupv (eps);
+}