Change LGPL-2.1+ to LGPL-2.1-or-later
[platform/upstream/glib.git] / gio / gproxyresolver.c
1 /* GIO - GLib Input, Output and Streaming Library
2  *
3  * Copyright (C) 2010 Collabora, Ltd.
4  *
5  * SPDX-License-Identifier: LGPL-2.1-or-later
6  *
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.
11  *
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.
16  *
17  * You should have received a copy of the GNU Lesser General
18  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19  *
20  * Author: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
21  */
22
23 #include "config.h"
24
25 #include "gproxyresolver.h"
26
27 #include <glib.h>
28 #include "glibintl.h"
29
30 #include "gasyncresult.h"
31 #include "gcancellable.h"
32 #include "gtask.h"
33 #include "giomodule.h"
34 #include "gioerror.h"
35 #include "giomodule-priv.h"
36 #include "gnetworkingprivate.h"
37
38 /**
39  * SECTION:gproxyresolver
40  * @short_description: Asynchronous and cancellable network proxy resolver
41  * @include: gio/gio.h
42  *
43  * #GProxyResolver provides synchronous and asynchronous network proxy
44  * resolution. #GProxyResolver is used within #GSocketClient through
45  * the method g_socket_connectable_proxy_enumerate().
46  *
47  * Implementations of #GProxyResolver based on libproxy and GNOME settings can
48  * be found in glib-networking. GIO comes with an implementation for use inside
49  * Flatpak portals.
50  */
51
52 /**
53  * GProxyResolverInterface:
54  * @g_iface: The parent interface.
55  * @is_supported: the virtual function pointer for g_proxy_resolver_is_supported()
56  * @lookup: the virtual function pointer for g_proxy_resolver_lookup()
57  * @lookup_async: the virtual function pointer for
58  *  g_proxy_resolver_lookup_async()
59  * @lookup_finish: the virtual function pointer for
60  *  g_proxy_resolver_lookup_finish()
61  *
62  * The virtual function table for #GProxyResolver.
63  */
64
65 G_DEFINE_INTERFACE (GProxyResolver, g_proxy_resolver, G_TYPE_OBJECT)
66
67 static void
68 g_proxy_resolver_default_init (GProxyResolverInterface *iface)
69 {
70 }
71
72 static GProxyResolver *proxy_resolver_default_singleton = NULL;  /* (owned) (atomic) */
73
74 /**
75  * g_proxy_resolver_get_default:
76  *
77  * Gets the default #GProxyResolver for the system.
78  *
79  * Returns: (not nullable) (transfer none): the default #GProxyResolver, which
80  *     will be a dummy object if no proxy resolver is available
81  *
82  * Since: 2.26
83  */
84 GProxyResolver *
85 g_proxy_resolver_get_default (void)
86 {
87   if (g_once_init_enter (&proxy_resolver_default_singleton))
88     {
89       GProxyResolver *singleton;
90
91       singleton = _g_io_module_get_default (G_PROXY_RESOLVER_EXTENSION_POINT_NAME,
92                                             "GIO_USE_PROXY_RESOLVER",
93                                             (GIOModuleVerifyFunc) g_proxy_resolver_is_supported);
94
95       g_once_init_leave (&proxy_resolver_default_singleton, singleton);
96     }
97
98   return proxy_resolver_default_singleton;
99 }
100
101 /**
102  * g_proxy_resolver_is_supported:
103  * @resolver: a #GProxyResolver
104  *
105  * Checks if @resolver can be used on this system. (This is used
106  * internally; g_proxy_resolver_get_default() will only return a proxy
107  * resolver that returns %TRUE for this method.)
108  *
109  * Returns: %TRUE if @resolver is supported.
110  *
111  * Since: 2.26
112  */
113 gboolean
114 g_proxy_resolver_is_supported (GProxyResolver *resolver)
115 {
116   GProxyResolverInterface *iface;
117
118   g_return_val_if_fail (G_IS_PROXY_RESOLVER (resolver), FALSE);
119
120   iface = G_PROXY_RESOLVER_GET_IFACE (resolver);
121
122   return (* iface->is_supported) (resolver);
123 }
124
125 /**
126  * g_proxy_resolver_lookup:
127  * @resolver: a #GProxyResolver
128  * @uri: a URI representing the destination to connect to
129  * @cancellable: (nullable): a #GCancellable, or %NULL
130  * @error: return location for a #GError, or %NULL
131  *
132  * Looks into the system proxy configuration to determine what proxy,
133  * if any, to use to connect to @uri. The returned proxy URIs are of
134  * the form `<protocol>://[user[:password]@]host[:port]` or
135  * `direct://`, where <protocol> could be http, rtsp, socks
136  * or other proxying protocol.
137  *
138  * If you don't know what network protocol is being used on the
139  * socket, you should use `none` as the URI protocol.
140  * In this case, the resolver might still return a generic proxy type
141  * (such as SOCKS), but would not return protocol-specific proxy types
142  * (such as http).
143  *
144  * `direct://` is used when no proxy is needed.
145  * Direct connection should not be attempted unless it is part of the
146  * returned array of proxies.
147  *
148  * Returns: (transfer full) (array zero-terminated=1): A
149  *               NULL-terminated array of proxy URIs. Must be freed
150  *               with g_strfreev().
151  *
152  * Since: 2.26
153  */
154 gchar **
155 g_proxy_resolver_lookup (GProxyResolver  *resolver,
156                          const gchar     *uri,
157                          GCancellable    *cancellable,
158                          GError         **error)
159 {
160   GProxyResolverInterface *iface;
161   gchar **proxy_uris;
162
163   g_return_val_if_fail (G_IS_PROXY_RESOLVER (resolver), NULL);
164   g_return_val_if_fail (uri != NULL, NULL);
165
166   if (!g_uri_is_valid (uri, G_URI_FLAGS_NONE, NULL))
167     {
168       g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
169                    "Invalid URI ā€˜%sā€™", uri);
170       return NULL;
171     }
172
173   iface = G_PROXY_RESOLVER_GET_IFACE (resolver);
174
175   proxy_uris = (* iface->lookup) (resolver, uri, cancellable, error);
176   if (proxy_uris == NULL && error != NULL)
177     g_assert (*error != NULL);
178   return proxy_uris;
179 }
180
181 /**
182  * g_proxy_resolver_lookup_async:
183  * @resolver: a #GProxyResolver
184  * @uri: a URI representing the destination to connect to
185  * @cancellable: (nullable): a #GCancellable, or %NULL
186  * @callback: (scope async): callback to call after resolution completes
187  * @user_data: data for @callback
188  *
189  * Asynchronous lookup of proxy. See g_proxy_resolver_lookup() for more
190  * details.
191  *
192  * Since: 2.26
193  */
194 void
195 g_proxy_resolver_lookup_async (GProxyResolver      *resolver,
196                                const gchar         *uri,
197                                GCancellable        *cancellable,
198                                GAsyncReadyCallback  callback,
199                                gpointer             user_data)
200 {
201   GProxyResolverInterface *iface;
202   GError *error = NULL;
203
204   g_return_if_fail (G_IS_PROXY_RESOLVER (resolver));
205   g_return_if_fail (uri != NULL);
206
207   if (!g_uri_is_valid (uri, G_URI_FLAGS_NONE, NULL))
208     {
209       g_set_error (&error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
210                    "Invalid URI ā€˜%sā€™", uri);
211       g_task_report_error (resolver, callback, user_data,
212                            g_proxy_resolver_lookup_async,
213                            g_steal_pointer (&error));
214       return;
215     }
216
217   iface = G_PROXY_RESOLVER_GET_IFACE (resolver);
218
219   (* iface->lookup_async) (resolver, uri, cancellable, callback, user_data);
220 }
221
222 /**
223  * g_proxy_resolver_lookup_finish:
224  * @resolver: a #GProxyResolver
225  * @result: the result passed to your #GAsyncReadyCallback
226  * @error: return location for a #GError, or %NULL
227  *
228  * Call this function to obtain the array of proxy URIs when
229  * g_proxy_resolver_lookup_async() is complete. See
230  * g_proxy_resolver_lookup() for more details.
231  *
232  * Returns: (transfer full) (array zero-terminated=1): A
233  *               NULL-terminated array of proxy URIs. Must be freed
234  *               with g_strfreev().
235  *
236  * Since: 2.26
237  */
238 gchar **
239 g_proxy_resolver_lookup_finish (GProxyResolver     *resolver,
240                                 GAsyncResult       *result,
241                                 GError            **error)
242 {
243   GProxyResolverInterface *iface;
244   gchar **proxy_uris;
245
246   g_return_val_if_fail (G_IS_PROXY_RESOLVER (resolver), NULL);
247
248   if (g_async_result_is_tagged (result, g_proxy_resolver_lookup_async))
249     return g_task_propagate_pointer (G_TASK (result), error);
250
251   iface = G_PROXY_RESOLVER_GET_IFACE (resolver);
252
253   proxy_uris = (* iface->lookup_finish) (resolver, result, error);
254   if (proxy_uris == NULL && error != NULL)
255     g_assert (*error != NULL);
256   return proxy_uris;
257 }