44e104c3619769fa907261ca166f3890f684c512
[platform/upstream/glib-networking.git] / proxy / gnome / gproxyresolvergnome.c
1 /* GIO - GLib Input, Output and Streaming Library
2  *
3  * Copyright 2010 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, see
17  * <http://www.gnu.org/licenses/>.
18  */
19
20 #include "config.h"
21
22 #include <stdlib.h>
23
24 #include "gproxyresolvergnome.h"
25
26 #include <glib/gi18n-lib.h>
27 #include <gdesktop-enums.h>
28
29 #define GNOME_PROXY_SETTINGS_SCHEMA       "org.gnome.system.proxy"
30 #define GNOME_PROXY_MODE_KEY              "mode"
31 #define GNOME_PROXY_AUTOCONFIG_URL_KEY    "autoconfig-url"
32 #define GNOME_PROXY_IGNORE_HOSTS_KEY      "ignore-hosts"
33 #define GNOME_PROXY_USE_SAME_PROXY_KEY    "use-same-proxy"
34
35 #define GNOME_PROXY_HTTP_CHILD_SCHEMA     "http"
36 #define GNOME_PROXY_HTTP_HOST_KEY         "host"
37 #define GNOME_PROXY_HTTP_PORT_KEY         "port"
38 #define GNOME_PROXY_HTTP_USE_AUTH_KEY     "use-authentication"
39 #define GNOME_PROXY_HTTP_USER_KEY         "authentication-user"
40 #define GNOME_PROXY_HTTP_PASSWORD_KEY     "authentication-password"
41
42 #define GNOME_PROXY_HTTPS_CHILD_SCHEMA    "https"
43 #define GNOME_PROXY_HTTPS_HOST_KEY        "host"
44 #define GNOME_PROXY_HTTPS_PORT_KEY        "port"
45
46 #define GNOME_PROXY_FTP_CHILD_SCHEMA      "ftp"
47 #define GNOME_PROXY_FTP_HOST_KEY          "host"
48 #define GNOME_PROXY_FTP_PORT_KEY          "port"
49
50 #define GNOME_PROXY_SOCKS_CHILD_SCHEMA    "socks"
51 #define GNOME_PROXY_SOCKS_HOST_KEY        "host"
52 #define GNOME_PROXY_SOCKS_PORT_KEY        "port"
53
54 typedef struct {
55   gchar        *name;
56   gint          length;
57   gushort       port;
58 } GProxyResolverGnomeDomain;
59
60 struct _GProxyResolverGnome {
61   GObject parent_instance;
62
63   GSettings *proxy_settings;
64   GSettings *http_settings;
65   GSettings *https_settings;
66   GSettings *ftp_settings;
67   GSettings *socks_settings;
68   gboolean need_update;
69
70   GDesktopProxyMode mode;
71   gchar *autoconfig_url;
72   gboolean use_same_proxy;
73
74   GPtrArray *ignore_ips;
75   GProxyResolverGnomeDomain *ignore_domains;
76
77   gchar *http_proxy, *https_proxy;
78   gchar *ftp_proxy, *socks_authority;
79
80   GDBusProxy *pacrunner;
81
82   GMutex lock;
83 };
84
85 static void g_proxy_resolver_gnome_iface_init (GProxyResolverInterface *iface);
86
87 G_DEFINE_DYNAMIC_TYPE_EXTENDED (GProxyResolverGnome,
88                                 g_proxy_resolver_gnome,
89                                 G_TYPE_OBJECT, 0,
90                                 G_IMPLEMENT_INTERFACE_DYNAMIC (G_TYPE_PROXY_RESOLVER,
91                                                                g_proxy_resolver_gnome_iface_init))
92
93 static void
94 g_proxy_resolver_gnome_class_finalize (GProxyResolverGnomeClass *klass)
95 {
96 }
97
98 static void
99 free_settings (GProxyResolverGnome *resolver)
100 {
101   int i;
102
103   if (resolver->ignore_ips)
104     g_ptr_array_free (resolver->ignore_ips, TRUE);
105   if (resolver->ignore_domains)
106     {
107       for (i = 0; resolver->ignore_domains[i].name; i++)
108         g_free (resolver->ignore_domains[i].name);
109       g_free (resolver->ignore_domains);
110     }
111
112   g_free (resolver->http_proxy);
113   g_free (resolver->https_proxy);
114   g_free (resolver->ftp_proxy);
115   g_free (resolver->socks_authority);
116   g_free (resolver->autoconfig_url);
117 }
118
119 static void
120 gsettings_changed (GSettings   *settings,
121                    const gchar *key,
122                    gpointer     user_data)
123 {
124   GProxyResolverGnome *resolver = user_data;
125
126   g_mutex_lock (&resolver->lock);
127   resolver->need_update = TRUE;
128   g_mutex_unlock (&resolver->lock);
129 }
130
131 static void
132 g_proxy_resolver_gnome_finalize (GObject *object)
133 {
134   GProxyResolverGnome *resolver = G_PROXY_RESOLVER_GNOME (object);
135
136   if (resolver->proxy_settings)
137     {
138       g_signal_handlers_disconnect_by_func (resolver->proxy_settings,
139                                             (gpointer)gsettings_changed,
140                                             resolver);
141       g_object_unref (resolver->proxy_settings);
142
143       g_signal_handlers_disconnect_by_func (resolver->http_settings,
144                                             (gpointer)gsettings_changed,
145                                             resolver);
146       g_object_unref (resolver->http_settings);
147
148       g_signal_handlers_disconnect_by_func (resolver->https_settings,
149                                             (gpointer)gsettings_changed,
150                                             resolver);
151       g_object_unref (resolver->https_settings);
152
153       g_signal_handlers_disconnect_by_func (resolver->ftp_settings,
154                                             (gpointer)gsettings_changed,
155                                             resolver);
156       g_object_unref (resolver->ftp_settings);
157
158       g_signal_handlers_disconnect_by_func (resolver->socks_settings,
159                                             (gpointer)gsettings_changed,
160                                             resolver);
161       g_object_unref (resolver->socks_settings);
162
163       free_settings (resolver);
164     }
165
166   if (resolver->pacrunner)
167     g_object_unref (resolver->pacrunner);
168
169   g_mutex_clear (&resolver->lock);
170
171   G_OBJECT_CLASS (g_proxy_resolver_gnome_parent_class)->finalize (object);
172 }
173
174 static void
175 g_proxy_resolver_gnome_init (GProxyResolverGnome *resolver)
176 {
177   g_mutex_init (&resolver->lock);
178
179   resolver->proxy_settings = g_settings_new (GNOME_PROXY_SETTINGS_SCHEMA);
180   g_signal_connect (resolver->proxy_settings, "changed",
181                     G_CALLBACK (gsettings_changed), resolver);
182   resolver->http_settings = g_settings_get_child (resolver->proxy_settings,
183                                                   GNOME_PROXY_HTTP_CHILD_SCHEMA);
184   g_signal_connect (resolver->http_settings, "changed",
185                     G_CALLBACK (gsettings_changed), resolver);
186   resolver->https_settings = g_settings_get_child (resolver->proxy_settings,
187                                                    GNOME_PROXY_HTTPS_CHILD_SCHEMA);
188   g_signal_connect (resolver->https_settings, "changed",
189                     G_CALLBACK (gsettings_changed), resolver);
190   resolver->ftp_settings = g_settings_get_child (resolver->proxy_settings,
191                                                  GNOME_PROXY_FTP_CHILD_SCHEMA);
192   g_signal_connect (resolver->ftp_settings, "changed",
193                     G_CALLBACK (gsettings_changed), resolver);
194   resolver->socks_settings = g_settings_get_child (resolver->proxy_settings,
195                                                    GNOME_PROXY_SOCKS_CHILD_SCHEMA);
196   g_signal_connect (resolver->socks_settings, "changed",
197                     G_CALLBACK (gsettings_changed), resolver);
198
199   resolver->need_update = TRUE;
200 }
201
202 /* called with lock held */
203 static void
204 update_settings (GProxyResolverGnome *resolver)
205 {
206   gchar **ignore_hosts;
207   gchar *host;
208   guint port;
209   int i;
210
211   resolver->need_update = FALSE;
212
213   free_settings (resolver);
214
215   resolver->mode =
216     g_settings_get_enum (resolver->proxy_settings, GNOME_PROXY_MODE_KEY);
217   resolver->autoconfig_url =
218     g_settings_get_string (resolver->proxy_settings, GNOME_PROXY_AUTOCONFIG_URL_KEY);
219   resolver->use_same_proxy =
220     g_settings_get_boolean (resolver->proxy_settings, GNOME_PROXY_USE_SAME_PROXY_KEY);
221
222   ignore_hosts =
223     g_settings_get_strv (resolver->proxy_settings, GNOME_PROXY_IGNORE_HOSTS_KEY);
224   if (ignore_hosts && ignore_hosts[0])
225     {
226       GPtrArray *ignore_ips;
227       GArray *ignore_domains;
228       gchar *host, *tmp, *colon, *bracket;
229       GInetAddress *iaddr;
230       GInetAddressMask *mask;
231       GProxyResolverGnomeDomain domain;
232       gushort port;
233
234       ignore_ips = g_ptr_array_new_with_free_func (g_object_unref);
235       ignore_domains = g_array_new (TRUE, FALSE, sizeof (GProxyResolverGnomeDomain));
236
237       for (i = 0; ignore_hosts[i]; i++)
238         {
239           host = g_strchomp (ignore_hosts[i]);
240
241           /* See if it's an IP address or IP/length mask */
242           mask = g_inet_address_mask_new_from_string (host, NULL);
243           if (mask)
244             {
245               g_ptr_array_add (ignore_ips, mask);
246               continue;
247             }
248
249           port = 0;
250
251           if (*host == '[')
252             {
253               /* [IPv6]:port */
254               host++;
255               bracket = strchr (host, ']');
256               if (!bracket || !bracket[1] || bracket[1] != ':')
257                 goto bad;
258
259               port = strtoul (bracket + 2, &tmp, 10);
260               if (*tmp)
261                 goto bad;
262
263               *bracket = '\0';
264             }
265           else
266             {
267               colon = strchr (host, ':');
268               if (colon && !strchr (colon + 1, ':'))
269                 {
270                   /* hostname:port or IPv4:port */
271                   port = strtoul (colon + 1, &tmp, 10);
272                   if (*tmp)
273                     goto bad;
274                   *colon = '\0';
275                 }
276             }
277
278           iaddr = g_inet_address_new_from_string (host);
279           if (iaddr)
280             g_object_unref (iaddr);
281           else
282             {
283               if (g_str_has_prefix (host, "*."))
284                 host += 2;
285               else if (*host == '.')
286                 host++;
287             }
288
289           memset (&domain, 0, sizeof (domain));
290           domain.name = g_strdup (host);
291           domain.length = strlen (domain.name);
292           domain.port = port;
293           g_array_append_val (ignore_domains, domain);
294           continue;
295
296         bad:
297           g_warning ("Ignoring invalid ignore_hosts value '%s'", host);
298         }
299
300       if (ignore_ips->len)
301         resolver->ignore_ips = ignore_ips;
302       else
303         {
304           g_ptr_array_free (ignore_ips, TRUE);
305           resolver->ignore_ips = NULL;
306         }
307
308       resolver->ignore_domains = (GProxyResolverGnomeDomain *)
309         g_array_free (ignore_domains, ignore_domains->len == 0);
310     }
311   else
312     {
313       resolver->ignore_ips = NULL;
314       resolver->ignore_domains = NULL;
315     }
316   g_strfreev (ignore_hosts);
317
318   host = g_settings_get_string (resolver->http_settings, GNOME_PROXY_HTTP_HOST_KEY);
319   port = g_settings_get_int (resolver->http_settings, GNOME_PROXY_HTTP_PORT_KEY);
320
321   if (host && *host)
322     {
323       if (g_settings_get_boolean (resolver->http_settings, GNOME_PROXY_HTTP_USE_AUTH_KEY))
324         {
325           gchar *user, *password;
326           gchar *enc_user, *enc_password;
327
328           user = g_settings_get_string (resolver->http_settings, GNOME_PROXY_HTTP_USER_KEY);
329           enc_user = g_uri_escape_string (user, NULL, TRUE);
330           g_free (user);
331           password = g_settings_get_string (resolver->http_settings, GNOME_PROXY_HTTP_PASSWORD_KEY);
332           enc_password = g_uri_escape_string (password, NULL, TRUE);
333           g_free (password);
334
335           resolver->http_proxy = g_strdup_printf ("http://%s:%s@%s:%u",
336                                                   enc_user, enc_password,
337                                                   host, port);
338           g_free (enc_user);
339           g_free (enc_password);
340         }
341       else
342         resolver->http_proxy = g_strdup_printf ("http://%s:%u", host, port);
343     }
344   g_free (host);
345
346   host = g_settings_get_string (resolver->https_settings, GNOME_PROXY_HTTPS_HOST_KEY);
347   port = g_settings_get_int (resolver->https_settings, GNOME_PROXY_HTTPS_PORT_KEY);
348   if (host && *host)
349     resolver->https_proxy = g_strdup_printf ("http://%s:%u", host, port);
350   g_free (host);
351
352   host = g_settings_get_string (resolver->ftp_settings, GNOME_PROXY_FTP_HOST_KEY);
353   port = g_settings_get_int (resolver->ftp_settings, GNOME_PROXY_FTP_PORT_KEY);
354   if (host && *host)
355     resolver->ftp_proxy = g_strdup_printf ("ftp://%s:%u", host, port);
356   g_free (host);
357
358   host = g_settings_get_string (resolver->socks_settings, GNOME_PROXY_SOCKS_HOST_KEY);
359   port = g_settings_get_int (resolver->socks_settings, GNOME_PROXY_SOCKS_PORT_KEY);
360   if (host && *host)
361     resolver->socks_authority = g_strdup_printf ("%s:%u", host, port);
362   g_free (host);
363
364   if (resolver->mode == G_DESKTOP_PROXY_MODE_AUTO && !resolver->pacrunner)
365     {
366       GError *error = NULL;
367       resolver->pacrunner =
368         g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
369                                        G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
370                                        G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
371                                        NULL,
372                                        "org.gtk.GLib.PACRunner",
373                                        "/org/gtk/GLib/PACRunner",
374                                        "org.gtk.GLib.PACRunner",
375                                        NULL, &error);
376       if (error)
377         {
378           g_warning ("Could not start proxy autoconfiguration helper:"
379                      "\n    %s\nProxy autoconfiguration will not work",
380                      error->message);
381         }
382     }
383   else if (resolver->mode != G_DESKTOP_PROXY_MODE_AUTO && resolver->pacrunner)
384     {
385       g_object_unref (resolver->pacrunner);
386       resolver->pacrunner = NULL;
387     }
388 }
389
390 static gboolean
391 g_proxy_resolver_gnome_is_supported (GProxyResolver *object)
392 {
393   return !g_strcmp0 (g_getenv ("DESKTOP_SESSION"), "gnome");
394 }
395
396 static gboolean
397 ignore_host (GProxyResolverGnome *resolver,
398              const gchar         *host,
399              gushort              port)
400 {
401   gchar *ascii_host = NULL;
402   gboolean ignore = FALSE;
403   gint i, length, offset;
404
405   if (resolver->ignore_ips)
406     {
407       GInetAddress *iaddr;
408
409       iaddr = g_inet_address_new_from_string (host);
410       if (iaddr)
411         {
412           for (i = 0; i < resolver->ignore_ips->len; i++)
413             {
414               GInetAddressMask *mask = resolver->ignore_ips->pdata[i];
415
416               if (g_inet_address_mask_matches (mask, iaddr))
417                 {
418                   ignore = TRUE;
419                   break;
420                 }
421             }
422
423           g_object_unref (iaddr);
424           if (ignore)
425             return TRUE;
426         }
427     }
428
429   if (g_hostname_is_non_ascii (host))
430     host = ascii_host = g_hostname_to_ascii (host);
431   length = strlen (host);
432
433   if (resolver->ignore_domains)
434     {
435       for (i = 0; resolver->ignore_domains[i].length; i++)
436         {
437           GProxyResolverGnomeDomain *domain = &resolver->ignore_domains[i];
438
439           offset = length - domain->length;
440           if ((domain->port == 0 || domain->port == port) &&
441               (offset == 0 || (offset > 0 && host[offset - 1] == '.')) &&
442               (g_ascii_strcasecmp (domain->name, host + offset) == 0))
443             {
444               ignore = TRUE;
445               break;
446             }
447         }
448     }
449
450   g_free (ascii_host);
451   return ignore;
452 }
453
454 static inline gchar **
455 make_proxies (const gchar *proxy)
456 {
457   gchar **proxies;
458
459   proxies = g_new (gchar *, 2);
460   proxies[0] = g_strdup (proxy);
461   proxies[1] = NULL;
462
463   return proxies;
464 }
465
466 /* Threadsafely determines what to do with @uri; returns %FALSE if an
467  * error occurs, %TRUE and an array of proxies if the mode is NONE or
468  * MANUAL, or if @uri is covered by ignore-hosts, or %TRUE and a
469  * (transfer-full) pacrunner and autoconfig url if the mode is AUTOMATIC.
470  */
471 static gboolean
472 g_proxy_resolver_gnome_lookup_internal (GProxyResolverGnome   *resolver,
473                                         const gchar           *uri,
474                                         gchar               ***out_proxies,
475                                         GDBusProxy           **out_pacrunner,
476                                         gchar                **out_autoconfig_url,
477                                         GCancellable          *cancellable,
478                                         GError               **error)
479 {
480   GSocketConnectable *addr = NULL;
481   const gchar *scheme = NULL, *host = NULL;
482   gushort port;
483
484   *out_proxies = NULL;
485   *out_pacrunner = NULL;
486   *out_autoconfig_url = NULL;
487
488   g_mutex_lock (&resolver->lock);
489   if (resolver->need_update)
490     update_settings (resolver);
491
492   if (resolver->mode == G_DESKTOP_PROXY_MODE_NONE)
493     {
494       *out_proxies = make_proxies ("direct://");
495       goto done;
496     }
497
498   /* FIXME: use guri when it lands... */
499   addr = g_network_address_parse_uri (uri, 0, error);
500   if (!addr)
501     goto done;
502   scheme = g_network_address_get_scheme (G_NETWORK_ADDRESS (addr));
503   host = g_network_address_get_hostname (G_NETWORK_ADDRESS (addr));
504   port = g_network_address_get_port (G_NETWORK_ADDRESS (addr));
505
506   if (ignore_host (resolver, host, port))
507     {
508       *out_proxies = make_proxies ("direct://");
509       goto done;
510     }
511
512   if (resolver->pacrunner)
513     {
514       *out_pacrunner = g_object_ref (resolver->pacrunner);
515       *out_autoconfig_url = g_strdup (resolver->autoconfig_url);
516       goto done;
517     }
518   else if (resolver->ftp_proxy &&
519            (!strcmp (scheme, "ftp") || !strcmp (scheme, "ftps")))
520     {
521       *out_proxies = make_proxies (resolver->ftp_proxy);
522     }
523   else if (resolver->https_proxy && !strcmp (scheme, "https"))
524     {
525       *out_proxies = make_proxies (resolver->https_proxy);
526     }
527   else if (resolver->http_proxy &&
528       (!strcmp (scheme, "http") || !strcmp (scheme, "https")))
529     {
530       *out_proxies = make_proxies (resolver->http_proxy);
531     }
532   else if (resolver->socks_authority)
533     {
534       *out_proxies = g_new (gchar *, 4);
535       *out_proxies[0] = g_strdup_printf ("socks5://%s", resolver->socks_authority);
536       *out_proxies[1] = g_strdup_printf ("socks4a://%s", resolver->socks_authority);
537       *out_proxies[2] = g_strdup_printf ("socks4://%s", resolver->socks_authority);
538       *out_proxies[3] = NULL;
539     }
540   else if (resolver->use_same_proxy && resolver->http_proxy)
541     {
542       *out_proxies = make_proxies (resolver->http_proxy);
543     }
544   else
545     *out_proxies = make_proxies ("direct://");
546
547 done:
548   if (addr)
549     g_object_unref (addr);
550   g_mutex_unlock (&resolver->lock);
551
552   if (*out_proxies || *out_pacrunner)
553     return TRUE;
554   else
555     return FALSE;
556 }
557
558 static gchar **
559 g_proxy_resolver_gnome_lookup (GProxyResolver  *proxy_resolver,
560                                const gchar     *uri,
561                                GCancellable    *cancellable,
562                                GError         **error)
563 {
564   GProxyResolverGnome *resolver = G_PROXY_RESOLVER_GNOME (proxy_resolver);
565   GDBusProxy *pacrunner;
566   gchar **proxies, *autoconfig_url;
567
568   if (!g_proxy_resolver_gnome_lookup_internal (resolver, uri,
569                                                &proxies, &pacrunner, &autoconfig_url,
570                                                cancellable, error))
571     return NULL;
572
573   if (pacrunner)
574     {
575       GVariant *vproxies;
576
577       vproxies = g_dbus_proxy_call_sync (pacrunner,
578                                          "Lookup",
579                                          g_variant_new ("(ss)",
580                                                         autoconfig_url,
581                                                         uri),
582                                          G_DBUS_CALL_FLAGS_NONE,
583                                          -1,
584                                          cancellable, error);
585       if (vproxies)
586         {
587           g_variant_get (vproxies, "(^as)", &proxies);
588           g_variant_unref (vproxies);
589         }
590       else
591         proxies = NULL;
592
593       g_object_unref (pacrunner);
594       g_free (autoconfig_url);
595     }
596
597   return proxies;
598 }
599
600 static void
601 got_autoconfig_proxies (GObject      *source,
602                         GAsyncResult *result,
603                         gpointer      user_data)
604 {
605   GTask *task = user_data;
606   GVariant *vproxies;
607   char **proxies;
608   GError *error = NULL;
609
610   vproxies = g_dbus_proxy_call_finish (G_DBUS_PROXY (source),
611                                        result, &error);
612   if (vproxies)
613     {
614       g_variant_get (vproxies, "(^as)", &proxies);
615       g_task_return_pointer (task, proxies, (GDestroyNotify)g_strfreev);
616       g_variant_unref (vproxies);
617     }
618   else
619     g_task_return_error (task, error);
620   g_object_unref (task);
621 }
622
623 static void
624 g_proxy_resolver_gnome_lookup_async (GProxyResolver      *proxy_resolver,
625                                      const gchar         *uri,
626                                      GCancellable        *cancellable,
627                                      GAsyncReadyCallback  callback,
628                                      gpointer             user_data)
629 {
630   GProxyResolverGnome *resolver = G_PROXY_RESOLVER_GNOME (proxy_resolver);
631   GTask *task;
632   char **proxies, *autoconfig_url;
633   GDBusProxy *pacrunner;
634   GError *error = NULL;
635
636   task = g_task_new (resolver, cancellable, callback, user_data);
637
638    if (!g_proxy_resolver_gnome_lookup_internal (resolver, uri,
639                                                 &proxies, &pacrunner, &autoconfig_url,
640                                                 cancellable, &error))
641      {
642        g_task_return_error (task, error);
643        g_object_unref (task);
644        return;
645      }
646    else if (proxies)
647      {
648        g_task_return_pointer (task, proxies, (GDestroyNotify)g_strfreev);
649        g_object_unref (task);
650        return;
651      }
652
653    g_dbus_proxy_call (pacrunner,
654                       "Lookup",
655                       g_variant_new ("(ss)",
656                                      autoconfig_url,
657                                      uri),
658                       G_DBUS_CALL_FLAGS_NONE,
659                       -1,
660                       cancellable,
661                       got_autoconfig_proxies,
662                       task);
663    g_object_unref (pacrunner);
664    g_free (autoconfig_url);
665 }
666
667 static gchar **
668 g_proxy_resolver_gnome_lookup_finish (GProxyResolver  *resolver,
669                                       GAsyncResult    *result,
670                                       GError         **error)
671 {
672   g_return_val_if_fail (g_task_is_valid (result, resolver), NULL);
673
674   return g_task_propagate_pointer (G_TASK (result), error);
675 }
676
677 static void
678 g_proxy_resolver_gnome_class_init (GProxyResolverGnomeClass *resolver_class)
679 {
680   GObjectClass *object_class;
681   
682   object_class = G_OBJECT_CLASS (resolver_class);
683   object_class->finalize = g_proxy_resolver_gnome_finalize;
684 }
685
686 static void
687 g_proxy_resolver_gnome_iface_init (GProxyResolverInterface *iface)
688 {
689   iface->is_supported = g_proxy_resolver_gnome_is_supported;
690   iface->lookup = g_proxy_resolver_gnome_lookup;
691   iface->lookup_async = g_proxy_resolver_gnome_lookup_async;
692   iface->lookup_finish = g_proxy_resolver_gnome_lookup_finish;
693 }
694
695 void
696 g_proxy_resolver_gnome_register (GIOModule *module)
697 {
698   g_proxy_resolver_gnome_register_type (G_TYPE_MODULE (module));
699   g_io_extension_point_implement (G_PROXY_RESOLVER_EXTENSION_POINT_NAME,
700                                   g_proxy_resolver_gnome_get_type(),
701                                   "gnome",
702                                   80);
703 }