1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2009 Gustavo Noronha Silva <gns@gnome.org>.
4  */
5 
6 #include "test-utils.h"
7 
8 SoupSession *session;
9 SoupURI *base_uri;
10 SoupMessageBody *chunk_data;
11 
12 static void
server_callback(SoupServer * server,SoupMessage * msg,const char * path,GHashTable * query,SoupClientContext * context,gpointer data)13 server_callback (SoupServer *server, SoupMessage *msg,
14 		 const char *path, GHashTable *query,
15 		 SoupClientContext *context, gpointer data)
16 {
17 	GError *error = NULL;
18 	char *query_key;
19 	SoupBuffer *response = NULL;
20 	gsize offset;
21 	gboolean empty_response = FALSE;
22 
23 	if (msg->method != SOUP_METHOD_GET) {
24 		soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
25 		return;
26 	}
27 
28 	soup_message_set_status (msg, SOUP_STATUS_OK);
29 
30 	if (query) {
31 		query_key = g_hash_table_lookup (query, "chunked");
32 		if (query_key && g_str_equal (query_key, "yes")) {
33 			soup_message_headers_set_encoding (msg->response_headers,
34 							   SOUP_ENCODING_CHUNKED);
35 		}
36 
37 		query_key = g_hash_table_lookup (query, "empty_response");
38 		if (query_key && g_str_equal (query_key, "yes"))
39 			empty_response = TRUE;
40 	}
41 
42 	if (!strcmp (path, "/mbox")) {
43 		if (!empty_response) {
44 			response = soup_test_load_resource ("mbox", &error);
45 			g_assert_no_error (error);
46 		}
47 
48 		soup_message_headers_append (msg->response_headers,
49 					     "Content-Type", "text/plain");
50 	}
51 
52 	if (g_str_has_prefix (path, "/nosniff/")) {
53 		char *base_name = g_path_get_basename (path);
54 
55 		response = soup_test_load_resource (base_name, &error);
56 		g_assert_no_error (error);
57 		g_free (base_name);
58 
59 		soup_message_headers_append (msg->response_headers,
60 					     "X-Content-Type-Options", "nosniff");
61 
62 		soup_message_headers_append (msg->response_headers,
63 					     "Content-Type", "no/sniffing-allowed");
64 	}
65 
66 	if (g_str_has_prefix (path, "/text_or_binary/") || g_str_has_prefix (path, "/apache_bug/")) {
67 		char *base_name = g_path_get_basename (path);
68 
69 		response = soup_test_load_resource (base_name, &error);
70 		g_assert_no_error (error);
71 		g_free (base_name);
72 
73 		soup_message_headers_append (msg->response_headers,
74 					     "Content-Type", "text/plain");
75 	}
76 
77 	if (g_str_has_prefix (path, "/unknown/")) {
78 		char *base_name = g_path_get_basename (path);
79 
80 		response = soup_test_load_resource (base_name, &error);
81 		g_assert_no_error (error);
82 		g_free (base_name);
83 
84 		soup_message_headers_append (msg->response_headers,
85 					     "Content-Type", "UNKNOWN/unknown");
86 	}
87 
88 	if (g_str_has_prefix (path, "/type/")) {
89 		char **components = g_strsplit (path, "/", 4);
90 		char *ptr;
91 
92 		char *base_name = g_path_get_basename (path);
93 
94 		response = soup_test_load_resource (base_name, &error);
95 		g_assert_no_error (error);
96 		g_free (base_name);
97 
98 		/* Hack to allow passing type in the URI */
99 		ptr = g_strrstr (components[2], "_");
100 		*ptr = '/';
101 
102 		soup_message_headers_append (msg->response_headers,
103 					     "Content-Type", components[2]);
104 		g_strfreev (components);
105 	}
106 
107 	if (g_str_has_prefix (path, "/multiple_headers/")) {
108 		char *base_name = g_path_get_basename (path);
109 
110 		response = soup_test_load_resource (base_name, &error);
111 		g_assert_no_error (error);
112 		g_free (base_name);
113 
114 		soup_message_headers_append (msg->response_headers,
115 					     "Content-Type", "text/xml");
116 		soup_message_headers_append (msg->response_headers,
117 					     "Content-Type", "text/plain");
118 	}
119 
120 	if (response) {
121 		for (offset = 0; offset < response->length; offset += 500) {
122 			soup_message_body_append (msg->response_body,
123 						  SOUP_MEMORY_COPY,
124 						  response->data + offset,
125 						  MIN (500, response->length - offset));
126 		}
127 
128 		soup_buffer_free (response);
129 	}
130 
131 	soup_message_body_complete (msg->response_body);
132 }
133 
134 static gboolean
unpause_msg(gpointer data)135 unpause_msg (gpointer data)
136 {
137 	SoupMessage *msg = (SoupMessage*)data;
138 	debug_printf (2, "  unpause\n");
139 	soup_session_unpause_message (session, msg);
140 	return FALSE;
141 }
142 
143 
144 static void
content_sniffed(SoupMessage * msg,char * content_type,GHashTable * params,gpointer data)145 content_sniffed (SoupMessage *msg, char *content_type, GHashTable *params, gpointer data)
146 {
147 	gboolean should_pause = GPOINTER_TO_INT (data);
148 
149 	debug_printf (2, "  content-sniffed -> %s\n", content_type);
150 
151 	soup_test_assert (g_object_get_data (G_OBJECT (msg), "got-chunk") == NULL,
152 			  "got-chunk got emitted before content-sniffed");
153 
154 	g_object_set_data (G_OBJECT (msg), "content-sniffed", GINT_TO_POINTER (TRUE));
155 
156 	if (should_pause) {
157 		debug_printf (2, "  pause\n");
158 		soup_session_pause_message (session, msg);
159 		g_idle_add (unpause_msg, msg);
160 	}
161 }
162 
163 static void
got_headers(SoupMessage * msg,gpointer data)164 got_headers (SoupMessage *msg, gpointer data)
165 {
166 	gboolean should_pause = GPOINTER_TO_INT (data);
167 
168 	debug_printf (2, "  got-headers\n");
169 
170 	soup_test_assert (g_object_get_data (G_OBJECT (msg), "content-sniffed") == NULL,
171 			  "content-sniffed got emitted before got-headers");
172 
173 	g_object_set_data (G_OBJECT (msg), "got-headers", GINT_TO_POINTER (TRUE));
174 
175 	if (should_pause) {
176 		debug_printf (2, "  pause\n");
177 		soup_session_pause_message (session, msg);
178 		g_idle_add (unpause_msg, msg);
179 	}
180 }
181 
182 static void
got_chunk(SoupMessage * msg,SoupBuffer * chunk,gpointer data)183 got_chunk (SoupMessage *msg, SoupBuffer *chunk, gpointer data)
184 {
185 	gboolean should_accumulate = GPOINTER_TO_INT (data);
186 
187 	debug_printf (2, "  got-chunk\n");
188 
189 	g_object_set_data (G_OBJECT (msg), "got-chunk", GINT_TO_POINTER (TRUE));
190 
191 	if (!should_accumulate) {
192 		if (!chunk_data)
193 			chunk_data = soup_message_body_new ();
194 		soup_message_body_append_buffer (chunk_data, chunk);
195 	}
196 }
197 
198 static void
do_signals_test(gboolean should_content_sniff,gboolean should_pause,gboolean should_accumulate,gboolean chunked_encoding,gboolean empty_response)199 do_signals_test (gboolean should_content_sniff,
200 		 gboolean should_pause,
201 		 gboolean should_accumulate,
202 		 gboolean chunked_encoding,
203 		 gboolean empty_response)
204 {
205 	SoupURI *uri = soup_uri_new_with_base (base_uri, "/mbox");
206 	SoupMessage *msg = soup_message_new_from_uri ("GET", uri);
207 	SoupBuffer *expected;
208 	GError *error = NULL;
209 	SoupBuffer *body = NULL;
210 
211 	debug_printf (1, "do_signals_test(%ssniff, %spause, %saccumulate, %schunked, %sempty)\n",
212 		      should_content_sniff ? "" : "!",
213 		      should_pause ? "" : "!",
214 		      should_accumulate ? "" : "!",
215 		      chunked_encoding ? "" : "!",
216 		      empty_response ? "" : "!");
217 
218 	if (chunked_encoding)
219 		soup_uri_set_query (uri, "chunked=yes");
220 
221 	if (empty_response) {
222 		if (uri->query) {
223 			char *tmp = uri->query;
224 			uri->query = g_strdup_printf ("%s&empty_response=yes", tmp);
225 			g_free (tmp);
226 		} else
227 			soup_uri_set_query (uri, "empty_response=yes");
228 	}
229 
230 	soup_message_set_uri (msg, uri);
231 
232 	soup_message_body_set_accumulate (msg->response_body, should_accumulate);
233 
234 	g_object_connect (msg,
235 			  "signal::got-headers", got_headers, GINT_TO_POINTER (should_pause),
236 			  "signal::got-chunk", got_chunk, GINT_TO_POINTER (should_accumulate),
237 			  "signal::content_sniffed", content_sniffed, GINT_TO_POINTER (should_pause),
238 			  NULL);
239 
240 	soup_session_send_message (session, msg);
241 
242 	if (should_content_sniff) {
243 		soup_test_assert (g_object_get_data (G_OBJECT (msg), "content-sniffed") != NULL,
244 				  "content-sniffed did not get emitted");
245 	} else {
246 		soup_test_assert (g_object_get_data (G_OBJECT (msg), "content-sniffed") == NULL,
247 				  "content-sniffed got emitted without a sniffer");
248 	}
249 
250 	if (empty_response)
251 		expected = soup_buffer_new (SOUP_MEMORY_STATIC, "", 0);
252 	else {
253 		expected = soup_test_load_resource ("mbox", &error);
254 		g_assert_no_error (error);
255 	}
256 
257 	if (!should_accumulate && chunk_data)
258 		body = soup_message_body_flatten (chunk_data);
259 	else if (msg->response_body)
260 		body = soup_message_body_flatten (msg->response_body);
261 
262 	if (body) {
263 		soup_assert_cmpmem (body->data, body->length,
264 				    expected->data, expected->length);
265 	}
266 
267 	soup_buffer_free (expected);
268 	if (body)
269 		soup_buffer_free (body);
270 	if (chunk_data) {
271 		soup_message_body_free (chunk_data);
272 		chunk_data = NULL;
273 	}
274 
275 	soup_uri_free (uri);
276 	g_object_unref (msg);
277 }
278 
279 static void
do_signals_tests(gconstpointer data)280 do_signals_tests (gconstpointer data)
281 {
282 	gboolean should_content_sniff = GPOINTER_TO_INT (data);
283 
284 	if (!should_content_sniff)
285 		soup_session_remove_feature_by_type (session, SOUP_TYPE_CONTENT_SNIFFER);
286 
287 	do_signals_test (should_content_sniff,
288 			 FALSE, FALSE, FALSE, FALSE);
289 	do_signals_test (should_content_sniff,
290 			 FALSE, FALSE, TRUE, FALSE);
291 	do_signals_test (should_content_sniff,
292 			 FALSE, TRUE, FALSE, FALSE);
293 	do_signals_test (should_content_sniff,
294 			 FALSE, TRUE, TRUE, FALSE);
295 
296 	do_signals_test (should_content_sniff,
297 			 TRUE, TRUE, FALSE, FALSE);
298 	do_signals_test (should_content_sniff,
299 			 TRUE, TRUE, TRUE, FALSE);
300 	do_signals_test (should_content_sniff,
301 			 TRUE, FALSE, FALSE, FALSE);
302 	do_signals_test (should_content_sniff,
303 			 TRUE, FALSE, TRUE, FALSE);
304 
305 	/* FIXME g_test_bug ("587907") */
306 	do_signals_test (should_content_sniff,
307 			 TRUE, TRUE, FALSE, TRUE);
308 	do_signals_test (should_content_sniff,
309 			 TRUE, TRUE, TRUE, TRUE);
310 
311 	if (!should_content_sniff)
312 		soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_SNIFFER);
313 }
314 
315 static void
sniffing_content_sniffed(SoupMessage * msg,const char * content_type,GHashTable * params,gpointer data)316 sniffing_content_sniffed (SoupMessage *msg, const char *content_type,
317 			  GHashTable *params, gpointer data)
318 {
319 	char **sniffed_type = (char **)data;
320 	GString *full_header;
321 	GHashTableIter iter;
322 	gpointer key, value;
323 
324 	full_header = g_string_new (content_type);
325 
326 	g_hash_table_iter_init (&iter, params);
327 	while (g_hash_table_iter_next (&iter, &key, &value)) {
328 		if (full_header->len)
329 			g_string_append (full_header, "; ");
330 		soup_header_g_string_append_param (full_header,
331 						   (const char *) key,
332 						   (const char *) value);
333 	}
334 
335 	*sniffed_type = g_string_free (full_header, FALSE);
336 }
337 
338 static void
test_sniffing(const char * path,const char * expected_type)339 test_sniffing (const char *path, const char *expected_type)
340 {
341 	SoupURI *uri;
342 	SoupMessage *msg;
343 	SoupRequest *req;
344 	GInputStream *stream;
345 	char *sniffed_type = NULL;
346 	const char *req_sniffed_type;
347 	GError *error = NULL;
348 
349 	uri = soup_uri_new_with_base (base_uri, path);
350 	msg = soup_message_new_from_uri ("GET", uri);
351 
352 	g_signal_connect (msg, "content-sniffed",
353 			  G_CALLBACK (sniffing_content_sniffed), &sniffed_type);
354 
355 	soup_session_send_message (session, msg);
356 	g_assert_cmpstr (sniffed_type, ==, expected_type);
357 	g_free (sniffed_type);
358 	g_object_unref (msg);
359 
360 	req = soup_session_request_uri (session, uri, NULL);
361 	stream = soup_test_request_send (req, NULL, 0, &error);
362 	if (stream) {
363 		soup_test_request_close_stream (req, stream, NULL, &error);
364 		g_object_unref (stream);
365 	}
366 	g_assert_no_error (error);
367 	g_clear_error (&error);
368 
369 	req_sniffed_type = soup_request_get_content_type (req);
370 	g_assert_cmpstr (req_sniffed_type, ==, expected_type);
371 	g_object_unref (req);
372 
373 	soup_uri_free (uri);
374 }
375 
376 static void
do_sniffing_test(gconstpointer data)377 do_sniffing_test (gconstpointer data)
378 {
379 	const char *path_and_result = data;
380 	char **parts;
381 
382 	parts = g_strsplit (path_and_result, " => ", -1);
383 	g_assert (parts && parts[0] && parts[1] && !parts[2]);
384 
385 	test_sniffing (parts[0], parts[1]);
386 	g_strfreev (parts);
387 }
388 
389 static void
test_disabled(gconstpointer data)390 test_disabled (gconstpointer data)
391 {
392 	const char *path = data;
393 	SoupURI *uri;
394 	SoupMessage *msg;
395 	SoupRequest *req;
396 	GInputStream *stream;
397 	char *sniffed_type = NULL;
398 	const char *sniffed_content_type;
399 	GError *error = NULL;
400 
401 	g_test_bug ("574773");
402 
403 	uri = soup_uri_new_with_base (base_uri, path);
404 
405 	msg = soup_message_new_from_uri ("GET", uri);
406 	g_assert_false (soup_message_is_feature_disabled (msg, SOUP_TYPE_CONTENT_SNIFFER));
407 	soup_message_disable_feature (msg, SOUP_TYPE_CONTENT_SNIFFER);
408 	g_assert_true (soup_message_is_feature_disabled (msg, SOUP_TYPE_CONTENT_SNIFFER));
409 
410 	g_signal_connect (msg, "content-sniffed",
411 			  G_CALLBACK (sniffing_content_sniffed), &sniffed_type);
412 
413 	soup_session_send_message (session, msg);
414 
415 	g_assert_null (sniffed_type);
416 	g_object_unref (msg);
417 
418 	req = soup_session_request_uri (session, uri, NULL);
419 	msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
420 	g_assert_false (soup_message_is_feature_disabled (msg, SOUP_TYPE_CONTENT_SNIFFER));
421 	soup_message_disable_feature (msg, SOUP_TYPE_CONTENT_SNIFFER);
422 	g_assert_true (soup_message_is_feature_disabled (msg, SOUP_TYPE_CONTENT_SNIFFER));
423 	g_object_unref (msg);
424 	stream = soup_test_request_send (req, NULL, 0, &error);
425 	if (stream) {
426 		soup_test_request_close_stream (req, stream, NULL, &error);
427 		g_object_unref (stream);
428 	}
429 	g_assert_no_error (error);
430 
431 	sniffed_content_type = soup_request_get_content_type (req);
432 	g_assert_cmpstr (sniffed_content_type, ==, NULL);
433 
434 	g_object_unref (req);
435 
436 	soup_uri_free (uri);
437 }
438 
439 int
main(int argc,char ** argv)440 main (int argc, char **argv)
441 {
442 	SoupServer *server;
443 	int ret;
444 
445 	test_init (argc, argv, NULL);
446 
447 	server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
448 	soup_server_add_handler (server, NULL, server_callback, NULL, NULL);
449 	base_uri = soup_test_server_get_uri (server, "http", NULL);
450 
451 	session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
452 					 SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
453 					 NULL);
454 	soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_SNIFFER);
455 
456 	g_test_add_data_func ("/sniffing/signals/no-sniffer",
457 			      GINT_TO_POINTER (FALSE),
458 			      do_signals_tests);
459 	g_test_add_data_func ("/sniffing/signals/with-sniffer",
460 			      GINT_TO_POINTER (TRUE),
461 			      do_signals_tests);
462 
463 	/* Test the apache bug sniffing path */
464 	g_test_add_data_func ("/sniffing/apache-bug/binary",
465 			      "/apache_bug/text_binary.txt => application/octet-stream",
466 			      do_sniffing_test);
467 	g_test_add_data_func ("/sniffing/apache-bug/text",
468 			      "/apache_bug/text.txt => text/plain",
469 			      do_sniffing_test);
470 
471 	/* X-Content-Type-Options: nosniff */
472 	g_test_add_data_func ("/sniffing/nosniff",
473 			      "nosniff/home.gif => no/sniffing-allowed",
474 			      do_sniffing_test);
475 
476 	/* GIF is a 'safe' type */
477 	g_test_add_data_func ("/sniffing/type/gif",
478 			      "text_or_binary/home.gif => image/gif",
479 			      do_sniffing_test);
480 
481 	/* With our current code, no sniffing is done using GIO, so
482 	 * the mbox will be identified as text/plain; should we change
483 	 * this?
484 	 */
485 	g_test_add_data_func ("/sniffing/type/mbox",
486 			      "text_or_binary/mbox => text/plain",
487 			      do_sniffing_test);
488 
489 	/* HTML is considered unsafe for this algorithm, since it is
490 	 * scriptable, so going from text/plain to text/html is
491 	 * considered 'privilege escalation'
492 	 */
493 	g_test_add_data_func ("/sniffing/type/html-in-text-context",
494 			      "text_or_binary/test.html => text/plain",
495 			      do_sniffing_test);
496 
497 	/* text/plain with binary content and unknown pattern should be
498 	 * application/octet-stream
499 	 */
500 	g_test_add_data_func ("/sniffing/type/text-binary",
501 			      "text_or_binary/text_binary.txt => application/octet-stream",
502 			      do_sniffing_test);
503 
504 	/* text/html with binary content and scriptable pattern should be
505 	 * application/octet-stream to avoid 'privilege escalation'
506 	 */
507 	g_test_add_data_func ("/sniffing/type/html-binary",
508 			      "text_or_binary/html_binary.html => application/octet-stream",
509 			      do_sniffing_test);
510 
511 	/* text/plain with binary content and non scriptable known pattern should
512 	 * be the given type
513 	 */
514 	g_test_add_data_func ("/sniffing/type/ps",
515 			      "text_or_binary/ps_binary.ps => application/postscript",
516 			      do_sniffing_test);
517 
518 	/* Test the unknown sniffing path */
519 	g_test_add_data_func ("/sniffing/type/unknown-html",
520 			      "unknown/test.html => text/html",
521 			      do_sniffing_test);
522 	g_test_add_data_func ("/sniffing/type/unknown-gif",
523 			      "unknown/home.gif => image/gif",
524 			      do_sniffing_test);
525 	g_test_add_data_func ("/sniffing/type/unknown-mbox",
526 			      "unknown/mbox => text/plain",
527 			      do_sniffing_test);
528 	g_test_add_data_func ("/sniffing/type/unknown-binary",
529 			      "unknown/text_binary.txt => application/octet-stream",
530 			      do_sniffing_test);
531 	/* FIXME g_test_bug ("715126") */
532 	g_test_add_data_func ("/sniffing/type/unknown-leading-space",
533 			      "unknown/leading_space.html => text/html",
534 			      do_sniffing_test);
535 	/* https://bugs.webkit.org/show_bug.cgi?id=173923 */
536 	g_test_add_data_func ("/sniffing/type/unknown-xml",
537 			      "unknown/misc.xml => text/xml",
538 			      do_sniffing_test);
539 
540 	/* Test the XML sniffing path */
541 	g_test_add_data_func ("/sniffing/type/xml",
542 			      "type/text_xml/home.gif => text/xml",
543 			      do_sniffing_test);
544 	g_test_add_data_func ("/sniffing/type/xml+xml",
545 			      "type/anice_type+xml/home.gif => anice/type+xml",
546 			      do_sniffing_test);
547 	g_test_add_data_func ("/sniffing/type/application-xml",
548 			      "type/application_xml/home.gif => application/xml",
549 			      do_sniffing_test);
550 
551 	/* Test the feed or html path */
552 	g_test_add_data_func ("/sniffing/type/html/html",
553 			      "type/text_html/test.html => text/html",
554 			      do_sniffing_test);
555 	g_test_add_data_func ("/sniffing/type/html/rss",
556 			      "type/text_html/rss20.xml => application/rss+xml",
557 			      do_sniffing_test);
558 	g_test_add_data_func ("/sniffing/type/html/atom",
559 			      "type/text_html/atom.xml => application/atom+xml",
560 			      do_sniffing_test);
561 	g_test_add_data_func ("/sniffing/type/html/rdf",
562 			      "type/text_html/feed.rdf => application/rss+xml",
563 			      do_sniffing_test);
564 
565 	/* Test the image sniffing path */
566 	g_test_add_data_func ("/sniffing/type/image/gif",
567 			      "type/image_png/home.gif => image/gif",
568 			      do_sniffing_test);
569 	g_test_add_data_func ("/sniffing/type/image/png",
570 			      "type/image_gif/home.png => image/png",
571 			      do_sniffing_test);
572 	g_test_add_data_func ("/sniffing/type/image/jpeg",
573 			      "type/image_png/home.jpg => image/jpeg",
574 			      do_sniffing_test);
575 	g_test_add_data_func ("/sniffing/type/image/webp",
576 			      "type/image_png/tux.webp => image/webp",
577 			      do_sniffing_test);
578 
579 	/* Test audio and video sniffing path */
580 	g_test_add_data_func ("/sniffing/type/audio/wav",
581 			      "type/audio_mpeg/test.wav => audio/wave",
582 			      do_sniffing_test);
583 	g_test_add_data_func ("/sniffing/type/audio/aiff",
584 			      "type/audio_mpeg/test.aiff => audio/aiff",
585 			      do_sniffing_test);
586 	g_test_add_data_func ("/sniffing/type/audio/ogg",
587 			      "type/audio_mpeg/test.ogg => application/ogg",
588 			      do_sniffing_test);
589 	g_test_add_data_func ("/sniffing/type/video/webm",
590 			      "type/video_theora/test.webm => video/webm",
591 			      do_sniffing_test);
592 
593 	/* Test the MP4 sniffing path */
594 	g_test_add_data_func ("/sniffing/type/video/mp4",
595 			      "unknown/test.mp4 => video/mp4",
596 			      do_sniffing_test);
597 
598 	/* The spec tells us to only use the last Content-Type header */
599 	g_test_add_data_func ("/sniffing/multiple-headers",
600 			      "multiple_headers/home.gif => image/gif",
601 			      do_sniffing_test);
602 
603 	/* Test that we keep the parameters when sniffing */
604 	g_test_add_data_func ("/sniffing/parameters",
605 			      "type/text_html; charset=UTF-8/test.html => text/html; charset=UTF-8",
606 			      do_sniffing_test);
607 
608 	/* Test that disabling the sniffer works correctly */
609 	g_test_add_data_func ("/sniffing/disabled",
610 			      "/text_or_binary/home.gif",
611 			      test_disabled);
612 
613 	ret = g_test_run ();
614 
615 	soup_uri_free (base_uri);
616 
617 	soup_test_session_abort_unref (session);
618 	soup_test_server_quit_unref (server);
619 
620 	test_cleanup ();
621 	return ret;
622 }
623