1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
3 * GIO - GLib Input, Output and Streaming Library
5 * Copyright 2010 Collabora, Ltd.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General
18 * Public License along with this library; if not, see
19 * <http://www.gnu.org/licenses/>.
21 * Author: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
30 #include "glibproxyresolver.h"
33 #include <glib/gi18n-lib.h>
35 struct _GLibproxyResolver {
36 GObject parent_instance;
37 pxProxyFactory *factory;
40 static void g_libproxy_resolver_iface_init (GProxyResolverInterface *iface);
42 #ifdef GLIBPROXY_MODULE
44 g_libproxy_resolver_class_finalize (GLibproxyResolverClass *klass)
48 G_DEFINE_DYNAMIC_TYPE_EXTENDED (GLibproxyResolver,
51 G_IMPLEMENT_INTERFACE_DYNAMIC (G_TYPE_PROXY_RESOLVER,
52 g_libproxy_resolver_iface_init))
54 G_DEFINE_TYPE_EXTENDED (GLibproxyResolver,
57 G_IMPLEMENT_INTERFACE (G_TYPE_PROXY_RESOLVER,
58 g_libproxy_resolver_iface_init))
62 g_libproxy_resolver_finalize (GObject *object)
64 GLibproxyResolver *resolver = G_LIBPROXY_RESOLVER (object);
66 if (resolver->factory)
68 px_proxy_factory_free (resolver->factory);
69 resolver->factory = NULL;
73 G_OBJECT_CLASS (g_libproxy_resolver_parent_class)->finalize (object);
77 g_libproxy_resolver_init (GLibproxyResolver *resolver)
79 resolver->factory = px_proxy_factory_new ();
83 g_libproxy_resolver_is_supported (GProxyResolver *object)
85 GLibproxyResolver *resolver = G_LIBPROXY_RESOLVER (object);
86 return resolver->factory != NULL;
90 copy_proxies (gchar **proxies)
96 for (i = 0; proxies[i]; i++)
98 if (!strncmp ("socks://", proxies[i], 8))
104 copy = g_new (gchar *, len + 1);
105 for (i = j = 0; proxies[i]; i++, j++)
107 if (!strncmp ("socks://", proxies[i], 8))
109 copy[j++] = g_strdup_printf ("socks5://%s", proxies[i] + 8);
110 copy[j++] = g_strdup_printf ("socks4a://%s", proxies[i] + 8);
111 copy[j] = g_strdup_printf ("socks4://%s", proxies[i] + 8);
115 copy[j] = g_strdup (proxies[i]);
123 /* FIXME: this function should be removed and replaced by a call to
124 * px_proxy_factory_free_proxies() once libproxy 0.4.16 is released.
125 * Sadly libproxy does not have any version check macros so it will
126 * have to be a hard dep.
129 free_libproxy_proxies (gchar **proxies)
133 for (i = 0; proxies[i]; i++)
139 get_libproxy_proxies (GTask *task,
140 gpointer source_object,
142 GCancellable *cancellable)
144 GLibproxyResolver *resolver = source_object;
145 const gchar *uri = task_data;
146 GError *error = NULL;
149 if (g_task_return_error_if_cancelled (task))
152 proxies = px_proxy_factory_get_proxies (resolver->factory, uri);
155 /* We always copy to be able to translate "socks" entry into
156 * three entries ("socks5", "socks4a", "socks4").
158 g_task_return_pointer (task, copy_proxies (proxies), (GDestroyNotify) g_strfreev);
159 free_libproxy_proxies (proxies);
163 g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
164 _("Proxy resolver internal error."));
165 g_task_return_error (task, error);
170 g_libproxy_resolver_lookup (GProxyResolver *iresolver,
172 GCancellable *cancellable,
175 GLibproxyResolver *resolver = G_LIBPROXY_RESOLVER (iresolver);
179 task = g_task_new (resolver, cancellable, NULL, NULL);
180 g_task_set_name (task, "[glib-networking] g_libproxy_resolver_lookup");
181 g_task_set_task_data (task, g_strdup (uri), g_free);
182 g_task_set_return_on_cancel (task, TRUE);
184 g_task_run_in_thread_sync (task, get_libproxy_proxies);
185 proxies = g_task_propagate_pointer (task, error);
186 g_object_unref (task);
192 g_libproxy_resolver_lookup_async (GProxyResolver *resolver,
194 GCancellable *cancellable,
195 GAsyncReadyCallback callback,
200 task = g_task_new (resolver, cancellable, callback, user_data);
201 g_task_set_source_tag (task, g_libproxy_resolver_lookup_async);
202 g_task_set_name (task, "[glib-networking] g_libproxy_resolver_lookup_async");
203 g_task_set_task_data (task, g_strdup (uri), g_free);
204 g_task_set_return_on_cancel (task, TRUE);
205 g_task_run_in_thread (task, get_libproxy_proxies);
206 g_object_unref (task);
210 g_libproxy_resolver_lookup_finish (GProxyResolver *resolver,
211 GAsyncResult *result,
214 g_return_val_if_fail (g_task_is_valid (result, resolver), NULL);
215 g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == g_libproxy_resolver_lookup_async, NULL);
217 return g_task_propagate_pointer (G_TASK (result), error);
221 g_libproxy_resolver_class_init (GLibproxyResolverClass *resolver_class)
223 GObjectClass *object_class;
225 object_class = G_OBJECT_CLASS (resolver_class);
226 object_class->finalize = g_libproxy_resolver_finalize;
230 g_libproxy_resolver_iface_init (GProxyResolverInterface *iface)
232 iface->is_supported = g_libproxy_resolver_is_supported;
233 iface->lookup = g_libproxy_resolver_lookup;
234 iface->lookup_async = g_libproxy_resolver_lookup_async;
235 iface->lookup_finish = g_libproxy_resolver_lookup_finish;
238 #ifdef GLIBPROXY_MODULE
240 g_libproxy_resolver_register (GIOModule *module)
242 g_libproxy_resolver_register_type (G_TYPE_MODULE (module));
244 g_io_extension_point_register (G_PROXY_RESOLVER_EXTENSION_POINT_NAME);
245 g_io_extension_point_implement (G_PROXY_RESOLVER_EXTENSION_POINT_NAME,
246 g_libproxy_resolver_get_type(),