• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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