1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * soup-misc.c: Miscellaneous functions
4
5 * Copyright (C) 2000-2003, Ximian, Inc.
6 */
7
8 #ifdef HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11
12 #include <string.h>
13
14 #include "soup-misc.h"
15 #include "soup-misc-private.h"
16
17 /**
18 * SECTION:soup-misc
19 * @short_description: Miscellaneous functions
20 *
21 **/
22
23 const gboolean soup_ssl_supported = TRUE;
24
25 /**
26 * soup_str_case_hash:
27 * @key: ASCII string to hash
28 *
29 * Hashes @key in a case-insensitive manner.
30 *
31 * Return value: the hash code.
32 **/
33 guint
soup_str_case_hash(gconstpointer key)34 soup_str_case_hash (gconstpointer key)
35 {
36 const char *p = key;
37 guint h = g_ascii_toupper(*p);
38
39 if (h)
40 for (p += 1; *p != '\0'; p++)
41 h = (h << 5) - h + g_ascii_toupper(*p);
42
43 return h;
44 }
45
46 /**
47 * soup_str_case_equal:
48 * @v1: an ASCII string
49 * @v2: another ASCII string
50 *
51 * Compares @v1 and @v2 in a case-insensitive manner
52 *
53 * Return value: %TRUE if they are equal (modulo case)
54 **/
55 gboolean
soup_str_case_equal(gconstpointer v1,gconstpointer v2)56 soup_str_case_equal (gconstpointer v1,
57 gconstpointer v2)
58 {
59 const char *string1 = v1;
60 const char *string2 = v2;
61
62 return g_ascii_strcasecmp (string1, string2) == 0;
63 }
64
65 /**
66 * soup_add_io_watch: (skip)
67 * @async_context: (allow-none): the #GMainContext to dispatch the I/O
68 * watch in, or %NULL for the default context
69 * @chan: the #GIOChannel to watch
70 * @condition: the condition to watch for
71 * @function: the callback to invoke when @condition occurs
72 * @data: user data to pass to @function
73 *
74 * Adds an I/O watch as with g_io_add_watch(), but using the given
75 * @async_context.
76 *
77 * Return value: a #GSource, which can be removed from @async_context
78 * with g_source_destroy().
79 **/
80 GSource *
soup_add_io_watch(GMainContext * async_context,GIOChannel * chan,GIOCondition condition,GIOFunc function,gpointer data)81 soup_add_io_watch (GMainContext *async_context,
82 GIOChannel *chan, GIOCondition condition,
83 GIOFunc function, gpointer data)
84 {
85 GSource *watch = g_io_create_watch (chan, condition);
86 g_source_set_callback (watch, (GSourceFunc) function, data, NULL);
87 g_source_attach (watch, async_context);
88 g_source_unref (watch);
89 return watch;
90 }
91
92 /**
93 * soup_add_idle: (skip)
94 * @async_context: (allow-none): the #GMainContext to dispatch the I/O
95 * watch in, or %NULL for the default context
96 * @function: the callback to invoke at idle time
97 * @data: user data to pass to @function
98 *
99 * Adds an idle event as with g_idle_add(), but using the given
100 * @async_context.
101 *
102 * If you want @function to run "right away", use
103 * soup_add_completion(), since that sets a higher priority on the
104 * #GSource than soup_add_idle() does.
105 *
106 * Return value: a #GSource, which can be removed from @async_context
107 * with g_source_destroy().
108 **/
109 GSource *
soup_add_idle(GMainContext * async_context,GSourceFunc function,gpointer data)110 soup_add_idle (GMainContext *async_context,
111 GSourceFunc function, gpointer data)
112 {
113 GSource *source = g_idle_source_new ();
114 g_source_set_callback (source, function, data, NULL);
115 g_source_attach (source, async_context);
116 g_source_unref (source);
117 return source;
118 }
119
120 GSource *
soup_add_completion_reffed(GMainContext * async_context,GSourceFunc function,gpointer data,GDestroyNotify dnotify)121 soup_add_completion_reffed (GMainContext *async_context,
122 GSourceFunc function,
123 gpointer data,
124 GDestroyNotify dnotify)
125 {
126 GSource *source = g_idle_source_new ();
127
128 g_source_set_priority (source, G_PRIORITY_DEFAULT);
129 g_source_set_callback (source, function, data, dnotify);
130 g_source_attach (source, async_context);
131 return source;
132 }
133
134 /**
135 * soup_add_completion: (skip)
136 * @async_context: (allow-none): the #GMainContext to dispatch the I/O
137 * watch in, or %NULL for the default context
138 * @function: the callback to invoke
139 * @data: user data to pass to @function
140 *
141 * Adds @function to be executed from inside @async_context with the
142 * default priority. Use this when you want to complete an action in
143 * @async_context's main loop, as soon as possible.
144 *
145 * Return value: a #GSource, which can be removed from @async_context
146 * with g_source_destroy().
147 *
148 * Since: 2.24
149 **/
150 GSource *
soup_add_completion(GMainContext * async_context,GSourceFunc function,gpointer data)151 soup_add_completion (GMainContext *async_context,
152 GSourceFunc function, gpointer data)
153 {
154 GSource *source;
155
156 source = soup_add_completion_reffed (async_context, function, data, NULL);
157 g_source_unref (source);
158 return source;
159 }
160
161 /**
162 * soup_add_timeout: (skip)
163 * @async_context: (allow-none): the #GMainContext to dispatch the I/O
164 * watch in, or %NULL for the default context
165 * @interval: the timeout interval, in milliseconds
166 * @function: the callback to invoke at timeout time
167 * @data: user data to pass to @function
168 *
169 * Adds a timeout as with g_timeout_add(), but using the given
170 * @async_context.
171 *
172 * Return value: a #GSource, which can be removed from @async_context
173 * with g_source_destroy().
174 **/
175 GSource *
soup_add_timeout(GMainContext * async_context,guint interval,GSourceFunc function,gpointer data)176 soup_add_timeout (GMainContext *async_context,
177 guint interval,
178 GSourceFunc function, gpointer data)
179 {
180 GSource *source = g_timeout_source_new (interval);
181 g_source_set_callback (source, function, data, NULL);
182 g_source_attach (source, async_context);
183 g_source_unref (source);
184 return source;
185 }
186
187 /* 00 URI_UNRESERVED
188 * 01 URI_PCT_ENCODED
189 * 02 URI_GEN_DELIMS
190 * 04 URI_SUB_DELIMS
191 * 08 HTTP_SEPARATOR
192 * 10 HTTP_CTL
193 */
194 const char soup_char_attributes[] = {
195 /* 0x00 - 0x07 */
196 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
197 /* 0x08 - 0x0f */
198 0x11, 0x19, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
199 /* 0x10 - 0x17 */
200 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
201 /* 0x18 - 0x1f */
202 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
203 /* !"#$%&' */
204 0x09, 0x04, 0x09, 0x02, 0x04, 0x01, 0x04, 0x04,
205 /* ()*+,-./ */
206 0x0c, 0x0c, 0x04, 0x04, 0x0c, 0x00, 0x00, 0x0a,
207 /* 01234567 */
208 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
209 /* 89:;<=>? */
210 0x00, 0x00, 0x0a, 0x0c, 0x09, 0x0a, 0x09, 0x0a,
211 /* @ABCDEFG */
212 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
213 /* HIJKLMNO */
214 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
215 /* PQRSTUVW */
216 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
217 /* XYZ[\]^_ */
218 0x00, 0x00, 0x00, 0x0a, 0x09, 0x0a, 0x01, 0x00,
219 /* `abcdefg */
220 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
221 /* hijklmno */
222 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
223 /* pqrstuvw */
224 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
225 /* xyz{|}~ */
226 0x00, 0x00, 0x00, 0x09, 0x01, 0x09, 0x00, 0x11,
227 /* 0x80 - 0xFF */
228 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
229 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
230 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
231 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
232 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
233 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
234 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
235 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
236 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
237 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
238 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
239 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
240 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
241 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
242 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
243 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
244 };
245
246 /**
247 * soup_host_matches_host
248 * @host: a URI
249 * @compare_with: a URI
250 *
251 * Checks if the @host and @compare_with exactly match or prefixed with a dot.
252 *
253 * Return value: %TRUE if the hosts match, %FALSE otherwise
254 *
255 * Since: 2.54
256 **/
257 gboolean
soup_host_matches_host(const gchar * host,const gchar * compare_with)258 soup_host_matches_host (const gchar *host, const gchar *compare_with)
259 {
260 g_return_val_if_fail (host != NULL, FALSE);
261 g_return_val_if_fail (compare_with != NULL, FALSE);
262
263 if (!g_ascii_strcasecmp (host, compare_with))
264 return TRUE;
265 if (*host != '.')
266 return FALSE;
267 if (!g_ascii_strcasecmp (host + 1, compare_with))
268 return TRUE;
269 return g_str_has_suffix (compare_with, host);
270 }
271