Coverage Report

Created: 2025-06-13 06:55

/src/glib/gio/gproxyresolver.c
Line
Count
Source (jump to first uncovered line)
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
0
{
70
0
}
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
0
{
87
0
  if (g_once_init_enter (&proxy_resolver_default_singleton))
88
0
    {
89
0
      GProxyResolver *singleton;
90
91
0
      singleton = _g_io_module_get_default (G_PROXY_RESOLVER_EXTENSION_POINT_NAME,
92
0
                                            "GIO_USE_PROXY_RESOLVER",
93
0
                                            (GIOModuleVerifyFunc) g_proxy_resolver_is_supported);
94
95
0
      g_once_init_leave (&proxy_resolver_default_singleton, singleton);
96
0
    }
97
98
0
  return proxy_resolver_default_singleton;
99
0
}
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
0
{
116
0
  GProxyResolverInterface *iface;
117
118
0
  g_return_val_if_fail (G_IS_PROXY_RESOLVER (resolver), FALSE);
119
120
0
  iface = G_PROXY_RESOLVER_GET_IFACE (resolver);
121
122
0
  return (* iface->is_supported) (resolver);
123
0
}
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
0
{
160
0
  GProxyResolverInterface *iface;
161
0
  gchar **proxy_uris;
162
163
0
  g_return_val_if_fail (G_IS_PROXY_RESOLVER (resolver), NULL);
164
0
  g_return_val_if_fail (uri != NULL, NULL);
165
166
0
  if (!g_uri_is_valid (uri, G_URI_FLAGS_NONE, NULL))
167
0
    {
168
0
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
169
0
                   "Invalid URI ā€˜%s’", uri);
170
0
      return NULL;
171
0
    }
172
173
0
  iface = G_PROXY_RESOLVER_GET_IFACE (resolver);
174
175
0
  proxy_uris = (* iface->lookup) (resolver, uri, cancellable, error);
176
0
  if (proxy_uris == NULL && error != NULL)
177
0
    g_assert (*error != NULL);
178
0
  return proxy_uris;
179
0
}
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
0
{
201
0
  GProxyResolverInterface *iface;
202
0
  GError *error = NULL;
203
204
0
  g_return_if_fail (G_IS_PROXY_RESOLVER (resolver));
205
0
  g_return_if_fail (uri != NULL);
206
207
0
  if (!g_uri_is_valid (uri, G_URI_FLAGS_NONE, NULL))
208
0
    {
209
0
      g_set_error (&error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
210
0
                   "Invalid URI ā€˜%s’", uri);
211
0
      g_task_report_error (resolver, callback, user_data,
212
0
                           g_proxy_resolver_lookup_async,
213
0
                           g_steal_pointer (&error));
214
0
      return;
215
0
    }
216
217
0
  iface = G_PROXY_RESOLVER_GET_IFACE (resolver);
218
219
0
  (* iface->lookup_async) (resolver, uri, cancellable, callback, user_data);
220
0
}
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
0
{
243
0
  GProxyResolverInterface *iface;
244
0
  gchar **proxy_uris;
245
246
0
  g_return_val_if_fail (G_IS_PROXY_RESOLVER (resolver), NULL);
247
248
0
  if (g_async_result_is_tagged (result, g_proxy_resolver_lookup_async))
249
0
    return g_task_propagate_pointer (G_TASK (result), error);
250
251
0
  iface = G_PROXY_RESOLVER_GET_IFACE (resolver);
252
253
0
  proxy_uris = (* iface->lookup_finish) (resolver, result, error);
254
0
  if (proxy_uris == NULL && error != NULL)
255
0
    g_assert (*error != NULL);
256
0
  return proxy_uris;
257
0
}