static gchar* _make_base_string(
                                GSignondSessionData *session_data, 
                                SoupURI* uri, gchar* nonce, gchar* timestamp)
{
    GString* base_string = g_string_new("POST&");
    
    gchar* base_uri;
    if (soup_uri_uses_default_port(uri))
        base_uri = g_strdup_printf("https://%s%s", soup_uri_get_host(uri),
                                                    soup_uri_get_path(uri));
    else
        base_uri = g_strdup_printf("https://%s:%u%s", soup_uri_get_host(uri),
                                                       soup_uri_get_port(uri),
                                                       soup_uri_get_path(uri));
    gchar* base_uri_e = _percent_encode(base_uri);
    g_string_append(base_string, base_uri_e);
    g_string_append(base_string, "&");
    g_free(base_uri);
    g_free(base_uri_e);
    
    GTree* parameters = g_tree_new((GCompareFunc)g_strcmp0);
    
    const gchar* query_s = soup_uri_get_query(uri);
    GHashTable* query;
    if (query_s != NULL)
        query = soup_form_decode(query_s);
    else    
        query = soup_form_decode("");
   
    g_hash_table_foreach(query, _insert_into_tree, parameters);
    
    const gchar* callback_uri = gsignond_dictionary_get_string(session_data, "Callback");
    if (callback_uri != NULL)
        g_tree_insert(parameters, "oauth_callback", (gchar*)callback_uri);
    const gchar* oauth_verifier = gsignond_dictionary_get_string(session_data, "_OauthVerifier");
    if (oauth_verifier != NULL)
        g_tree_insert(parameters, "oauth_verifier", (gchar*)oauth_verifier);
    g_tree_insert(parameters, "oauth_consumer_key", (gchar*)gsignond_dictionary_get_string(session_data, "ConsumerKey"));
    const gchar* oauth_temp_token = gsignond_dictionary_get_string(session_data, "_OauthTemporaryToken");
    if (oauth_temp_token != NULL)
        g_tree_insert(parameters, "oauth_token", (gchar*)oauth_temp_token);
    g_tree_insert(parameters, "oauth_signature_method", (gchar*)gsignond_dictionary_get_string(session_data, "SignatureMethod"));
    g_tree_insert(parameters, "oauth_nonce", nonce);
    g_tree_insert(parameters, "oauth_timestamp", timestamp);
    g_tree_insert(parameters, "oauth_version", "1.0");
    
    GString* parameters_string = g_string_new(NULL);
    g_tree_foreach(parameters, _make_parameters_string, parameters_string);
    gchar* parameters_s = g_string_free(parameters_string, FALSE);
    parameters_s[strlen(parameters_s)-1] = '\0'; //remove trailing '&'
    gchar* parameters_encoded = _percent_encode(parameters_s);
    g_string_append(base_string, parameters_encoded);
    
    g_free(parameters_encoded);
    g_free(parameters_s);
    g_tree_destroy(parameters);
    g_hash_table_destroy(query);
    
    return g_string_free(base_string, FALSE);
}
Esempio n. 2
0
char *
ephy_sync_utils_make_audience (const char *url)
{
  SoupURI *uri;
  const char *scheme;
  const char *host;
  char *audience;
  char *port;

  g_return_val_if_fail (url != NULL, NULL);

  uri = soup_uri_new (url);
  scheme = soup_uri_get_scheme (uri);
  host = soup_uri_get_host (uri);
  port = g_strdup_printf (":%u", soup_uri_get_port (uri));

  /* Even if the url doesn't contain the port, soup_uri_get_port() will return
   * the default port for the url's scheme so we need to check if the port was
   * really present in the url.
   */
  if (g_strstr_len (url, -1, port) != NULL)
    audience = g_strdup_printf ("%s://%s%s", scheme, host, port);
  else
    audience = g_strdup_printf ("%s://%s", scheme, host);

  g_free (port);
  soup_uri_free (uri);

  return audience;
}
Esempio n. 3
0
static gboolean
e_soup_ssl_trust_accept_certificate_cb (GTlsConnection *conn,
					GTlsCertificate *peer_cert,
					GTlsCertificateFlags errors,
					gpointer user_data)
{
	ESoupSslTrustData *handler = user_data;
	ETrustPromptResponse response;
	SoupURI *soup_uri;
	const gchar *host;
	gchar *auth_host = NULL;

	soup_uri = soup_message_get_uri (handler->soup_message);
	if (!soup_uri || !soup_uri_get_host (soup_uri))
		return FALSE;

	host = soup_uri_get_host (soup_uri);

	if (e_source_has_extension (handler->source, E_SOURCE_EXTENSION_AUTHENTICATION)) {
		ESourceAuthentication *extension_authentication;

		extension_authentication = e_source_get_extension (handler->source, E_SOURCE_EXTENSION_AUTHENTICATION);
		auth_host = e_source_authentication_dup_host (extension_authentication);

		if (auth_host && *auth_host) {
			/* Use the 'host' from the Authentication extension, because
			   it's the one used when storing the trust prompt result.
			   The SoupMessage can be redirected, thus it would not ever match. */
			host = auth_host;
		} else {
			g_free (auth_host);
			auth_host = NULL;
		}
	}

	response = e_source_webdav_verify_ssl_trust (
		e_source_get_extension (handler->source, E_SOURCE_EXTENSION_WEBDAV_BACKEND),
		host, peer_cert, errors);

	g_free (auth_host);

	return (response == E_TRUST_PROMPT_RESPONSE_ACCEPT ||
	        response == E_TRUST_PROMPT_RESPONSE_ACCEPT_TEMPORARILY);
}
ScLocalStorageManager* sc_local_storage_manager_new(const gchar *url) {
  ScLocalStorageManager *manager = g_new0(ScLocalStorageManager, 1);
  SoupURI *uri = soup_uri_new(url);
  GString *filename = g_string_new(NULL);
  const gchar *host = soup_uri_get_host(uri);
  const gchar *path = soup_uri_get_path(uri);
  const gchar *query = soup_uri_get_query(uri);
  const gchar *fragment = soup_uri_get_fragment(uri);
  GFile *parent = NULL;
  GError *error = NULL;

  g_string_append_printf(filename, "%s/%s", host, path);
			 
  if(url[strlen(url) - 1] == '/' || g_strcmp0("/", path) == 0)
    g_string_append(filename, "/index.html");
  
  if(query) g_string_append_printf(filename, "/%s\n", query);
  if(fragment) g_string_append_printf(filename, "#%s\n", fragment);
  manager->file = g_file_new_for_commandline_arg(filename->str);
  g_string_free(filename, TRUE);

  if(g_file_query_exists(manager->file, NULL)) {
    g_file_delete(manager->file, NULL, &error);
    if(error && !g_error_matches(error, G_IO_ERROR,G_IO_ERROR_EXISTS)) {
      g_critical(G_STRLOC ": %d : %s", error->code, error->message);
      g_error_free(error);
      g_object_unref(parent);
      g_object_unref(manager->file);
      g_free(manager);
      return NULL;
    }
  }

  parent = g_file_get_parent(manager->file);
  g_file_make_directory_with_parents(parent, NULL, &error);
  if(error && !g_error_matches(error, G_IO_ERROR,G_IO_ERROR_EXISTS)) {
    g_critical(G_STRLOC ": %d : %s", error->code, error->message);
    g_error_free(error);
    g_object_unref(parent);
    g_object_unref(manager->file);
    g_free(manager);
    return NULL;
  }

  error = NULL;
  manager->ostream = g_file_create(manager->file, G_FILE_CREATE_NONE, NULL, &error);
  if(error) {
    g_critical(G_STRLOC ": %d : %s", error->code, error->message);
    g_error_free(error);
    g_object_unref(parent);
    g_object_unref(manager->file);
    g_free(manager);
    return NULL;
  }
  return manager;
}
static void _request_access_token(GSignondOauthPlugin *self, 
                             GSignondSessionData *session_data,
                             GError** error
                                 )
{
    //GSignondPlugin* plugin = GSIGNOND_PLUGIN(self);

    const gchar* endpoint_url_s = gsignond_dictionary_get_string(session_data,
                                                               "TokenEndpoint");
    if (endpoint_url_s == NULL) {
        *error = g_error_new(GSIGNOND_ERROR,
                             GSIGNOND_ERROR_MISSING_DATA,
                             "Client did not supply TokenEndpoint");
        return;
    }
    SoupURI* endpoint_uri = soup_uri_new(endpoint_url_s);
    if (endpoint_uri == NULL) {
        *error = g_error_new(GSIGNOND_ERROR,
                             GSIGNOND_ERROR_MISSING_DATA,
                             "Client did not supply a valid TokenEndpoint");
        return;
    }
    
    if (g_strcmp0(soup_uri_get_scheme(endpoint_uri), "https") != 0) {
        soup_uri_free(endpoint_uri);
        *error = g_error_new(GSIGNOND_ERROR,
                             GSIGNOND_ERROR_MISSING_DATA,
                             "TokenEndpoint must use https");
        return;
    }
    gsignond_oauth_plugin_check_host(soup_uri_get_host(endpoint_uri),
        gsignond_session_data_get_allowed_realms (session_data), error);
    if (*error != NULL) {
        soup_uri_free(endpoint_uri);
        return;
    }
    
    gchar* authorization_header = _make_authorization_header(
                                                             session_data, 
                                                             endpoint_uri,
                                                             error
                                                            );
    if (*error == NULL) {
        SoupMessage *msg = soup_message_new_from_uri ("POST", endpoint_uri);
        soup_message_headers_append(msg->request_headers, "Authorization",
                                    authorization_header);
        g_free(authorization_header);
        soup_session_queue_message (self->soup_session, 
                                    msg, 
                                    _access_token_callback, 
                                    self);
    }
    soup_uri_free(endpoint_uri);
}
Esempio n. 6
0
/**
 * ephy_remove_tracking_from_uri:
 * @uri_string: a uri
 *
 * Sanitize @uri to make sure it does not contain analytics tracking
 * information. Inspired by the Firefox PureURL add-on:
 * https://addons.mozilla.org/fr/firefox/addon/pure-url/
 *
 * Returns: the sanitized uri, or %NULL on error or when the URI did
 * not change.
 */
char *
ephy_remove_tracking_from_uri (const char *uri_string)
{
  SoupURI *uri;
  GList *items, *new_items, *l;
  const char *query, *host;
  gboolean has_garbage = FALSE;
  char *ret = NULL;

  uri = soup_uri_new (uri_string);
  if (!uri)
    return ret;

  host = soup_uri_get_host (uri);
  query = soup_uri_get_query (uri);
  if (!query)
    goto bail;

  items = query_split (query);
  if (!items)
    goto bail;

  new_items = NULL;
  for (l = items; l != NULL; l = l->next) {
    QueryItem *item = l->data;

    if (!is_garbage (item->decoded_name, host))
      new_items = g_list_prepend (new_items, item);
    else
      has_garbage = TRUE;
  }

  if (has_garbage) {
    char *new_query;

    new_items = g_list_reverse (new_items);
    new_query = query_concat (new_items);

    soup_uri_set_query (uri, new_query);
    g_free (new_query);

    ret = soup_uri_to_string (uri, FALSE);
  }

  g_list_free_full (items, (GDestroyNotify) query_item_free);
  g_list_free (new_items);

bail:
  soup_uri_free (uri);
  return ret;
}
/* Add an URI to completion model for autocompletion */
static void _interface_tweaks_add_uri_to_completion_model(InterfaceTweaks *self, const gchar *inURI)
{
	g_return_if_fail(IS_INTERFACE_TWEAKS(self));
	g_return_if_fail(inURI!=NULL);

	InterfaceTweaksPrivate	*priv=self->priv;
	SoupURI					*soupURI;
	gchar					*modelURI;
	GtkTreeIter				iter;

	/* Create SoupURI from URI to retrieve host and/or scheme for completion */
	soupURI=soup_uri_new(inURI);
	g_return_if_fail(soupURI!=NULL);

	/* Add URI with scheme and host to completion */
	modelURI=g_strdup_printf("%s://%s", soup_uri_get_scheme(soupURI), soup_uri_get_host(soupURI));
	if(modelURI && g_hash_table_lookup(priv->completionModelDomains, modelURI)==NULL)
	{
		gtk_list_store_append(priv->completionModel, &iter);
		gtk_list_store_set(priv->completionModel, &iter, 0, modelURI, -1);
		g_hash_table_insert(priv->completionModelDomains, modelURI, GINT_TO_POINTER(TRUE));
	}
	if(modelURI) g_free(modelURI);

	/* Add URI without scheme - only host - to completion */
	modelURI=g_strdup(soup_uri_get_host(soupURI));
	if(modelURI && g_hash_table_lookup(priv->completionModelDomains, modelURI)==NULL)
	{
		gtk_list_store_append(priv->completionModel, &iter);
		gtk_list_store_set(priv->completionModel, &iter, 0, modelURI, -1);
		g_hash_table_insert(priv->completionModelDomains, modelURI, GINT_TO_POINTER(TRUE));
	}
	if(modelURI) g_free(modelURI);

	/* Release allocated resources */
	soup_uri_free(soupURI);
}
Esempio n. 8
0
static void
history_service_host_deleted_cb (EphyHistoryService *service,
                                 const char *deleted_url,
                                 EphyEmbedShell *shell)
{
  EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
  GList *l;
  SoupURI *deleted_uri;

  deleted_uri = soup_uri_new (deleted_url);

  for (l = priv->web_extensions; l; l = g_list_next (l)) {
    EphyWebExtensionProxy *web_extension = (EphyWebExtensionProxy *)l->data;

    ephy_web_extension_proxy_history_delete_host (web_extension, soup_uri_get_host (deleted_uri));
  }

  soup_uri_free (deleted_uri);
}
static char *
get_server_uri (SoupServer *server,
		const char *filename)
{
	GSList *uris;
	SoupURI *uri;
	char *ret;

	uris = soup_server_get_uris (server);
	g_assert (uris);

	uri = uris->data;
	ret = g_strdup_printf ("%s://%s:%d/%s",
			       soup_uri_get_scheme (uri),
			       soup_uri_get_host (uri),
			       soup_uri_get_port (uri),
			       filename);
	g_slist_free_full (uris, (GDestroyNotify) soup_uri_free);
	return ret;
}
static ProtectionSpace protectionSpaceFromSoupAuthAndMessage(SoupAuth* soupAuth, SoupMessage* message)
{
    const char* schemeName = soup_auth_get_scheme_name(soupAuth);
    ProtectionSpaceAuthenticationScheme scheme;
    if (!g_ascii_strcasecmp(schemeName, "basic"))
        scheme = ProtectionSpaceAuthenticationSchemeHTTPBasic;
    else if (!g_ascii_strcasecmp(schemeName, "digest"))
        scheme = ProtectionSpaceAuthenticationSchemeHTTPDigest;
    else if (!g_ascii_strcasecmp(schemeName, "ntlm"))
        scheme = ProtectionSpaceAuthenticationSchemeNTLM;
    else if (!g_ascii_strcasecmp(schemeName, "negotiate"))
        scheme = ProtectionSpaceAuthenticationSchemeNegotiate;
    else
        scheme = ProtectionSpaceAuthenticationSchemeUnknown;

    SoupURI* soupURI = soup_message_get_uri(message);
    return ProtectionSpace(String::fromUTF8(soup_uri_get_host(soupURI)), soup_uri_get_port(soupURI),
        protectionSpaceServerTypeFromURI(soupURI, soup_auth_is_for_proxy(soupAuth)),
        String::fromUTF8(soup_auth_get_realm(soupAuth)), scheme);
}
Esempio n. 11
0
GSList *
domain_get_cookie_domains(WebKitWebView *wv) 
{
    GSList *ret = NULL;
    WebKitWebFrame *frame = webkit_web_view_get_main_frame(wv);
    WebKitWebDataSource *data = webkit_web_frame_get_data_source(frame);
    if (data == NULL)
        return NULL;

    WebKitNetworkRequest *request = webkit_web_data_source_get_request(data);
    if (request == NULL)
        return NULL;

    SoupMessage *msg = webkit_network_request_get_message(request);
    if (msg == NULL)
        return NULL;

    SoupURI *uri = soup_message_get_uri(msg);
    if (uri == NULL)
        return NULL;

    const char *host = soup_uri_get_host(uri);
    char *base_host = g_strconcat(".", host, NULL);
    const char *base_domain = domain_get_base_for_host(base_host);

    char *cur = base_host;
    char *nextdot;

    while (cur != base_domain) 
    {
        nextdot = strchr(cur, '.');
        ret = g_slist_append(ret, nextdot);
        cur = nextdot+1;
        ret = g_slist_append(ret, cur);
    }
    return ret;
}
Esempio n. 12
0
static gchar *
trust_prompt_get_host_from_url (const gchar *url)
{
	SoupURI *suri;
	gchar *host;

	if (!url || !*url)
		return NULL;

	suri = soup_uri_new (url);
	if (!suri)
		return NULL;

	host = g_strdup (soup_uri_get_host (suri));

	if (!host || !*host) {
		g_free (host);
		host = NULL;
	}

	soup_uri_free (suri);

	return host;
}
Esempio n. 13
0
/**
 * e_webdav_discover_content_refresh:
 * @content: a WebDAV discovery content, created by e_webdav_discover_content_new()
 * @display_name: (allow-none): optional display name to use for scratch sources
 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
 *            is satisfied
 * @user_data: (closure): data to pass to the callback function
 *
 * Asynchronously starts refresh of the @content. This means to access the server
 * and search it for available sources. The @content shows a feedback and a Cancel
 * button during the operation.
 *
 * The @display_name is used only if the @content wasn't created with an #ESource and
 * it's shown in the password prompts, if there are required any.
 *
 * When the operation is finished, @callback will be called. You can then
 * call e_webdav_discover_content_refresh_finish() to get the result of the operation.
 *
 * Since: 3.18
 **/
void
e_webdav_discover_content_refresh (GtkWidget *content,
				   const gchar *display_name,
				   GCancellable *cancellable,
				   GAsyncReadyCallback callback,
				   gpointer user_data)
{
	EWebDAVDiscoverContentData *data;
	RefreshData *rd;
	ESource *source;
	SoupURI *soup_uri;
	GtkWidget *label;

	g_return_if_fail (GTK_IS_GRID (content));

	data = g_object_get_data (G_OBJECT (content), WEBDAV_DISCOVER_CONTENT_DATA_KEY);
	g_return_if_fail (data != NULL);
	g_return_if_fail (data->base_url != NULL);

	soup_uri = soup_uri_new (data->base_url);
	if (!soup_uri) {
		GSimpleAsyncResult *simple;

		simple = g_simple_async_result_new (G_OBJECT (content), callback, user_data, e_webdav_discover_content_refresh);
		g_simple_async_result_set_error (simple, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
			_("Invalid URL"));
		g_simple_async_result_complete_in_idle (simple);
		g_object_unref (simple);

		return;
	}

	if (!soup_uri_get_user (soup_uri)) {
		GSimpleAsyncResult *simple;

		soup_uri_free (soup_uri);

		simple = g_simple_async_result_new (G_OBJECT (content), callback, user_data, e_webdav_discover_content_refresh);
		g_simple_async_result_set_error (simple, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
			_("User name not filled"));
		g_simple_async_result_complete_in_idle (simple);
		g_object_unref (simple);

		return;
	}

	rd = g_new0 (RefreshData, 1);
	rd->content = g_object_ref (content);
	rd->cancellable = cancellable ? g_object_ref (cancellable) : g_cancellable_new ();
	rd->simple = g_simple_async_result_new (G_OBJECT (content), callback, user_data, e_webdav_discover_content_refresh);
	rd->base_url = g_strdup (data->base_url);
	rd->credentials = NULL;

	if (data->source) {
		source = g_object_ref (data->source);
	} else {
		ESourceWebdav *webdav_extension;
		ESourceAuthentication *auth_extension;

		source = e_source_new_with_uid (data->base_url, NULL, NULL);
		g_return_if_fail (source != NULL);

		webdav_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND);
		auth_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION);

		if (display_name && *display_name)
			e_source_set_display_name (source, display_name);
		e_source_webdav_set_soup_uri (webdav_extension, soup_uri);
		e_source_authentication_set_host (auth_extension, soup_uri_get_host (soup_uri));
		e_source_authentication_set_port (auth_extension, soup_uri_get_port (soup_uri));
		e_source_authentication_set_user (auth_extension, soup_uri_get_user (soup_uri));
	}

	gtk_list_store_clear (GTK_LIST_STORE (gtk_tree_view_get_model (data->sources_tree_view)));
	if (data->email_addresses_combo)
		gtk_combo_box_text_remove_all (GTK_COMBO_BOX_TEXT (data->email_addresses_combo));

	if (data->info_bar)
		gtk_widget_destroy (GTK_WIDGET (data->info_bar));

	data->info_bar = GTK_INFO_BAR (gtk_info_bar_new_with_buttons (_("Cancel"), GTK_RESPONSE_CANCEL, NULL));
	gtk_info_bar_set_message_type (data->info_bar, GTK_MESSAGE_INFO);
	gtk_info_bar_set_show_close_button (data->info_bar, FALSE);
	label = gtk_label_new (_("Searching server sources..."));
	gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (data->info_bar)), label);
	gtk_widget_show (label);
	gtk_widget_show (GTK_WIDGET (data->info_bar));

	g_signal_connect (data->info_bar, "response", G_CALLBACK (e_webdav_discover_info_bar_response_cb), rd);

	gtk_widget_set_sensitive (GTK_WIDGET (data->sources_tree_view), FALSE);
	if (data->email_addresses_combo)
		gtk_widget_set_sensitive (GTK_WIDGET (data->email_addresses_combo), FALSE);

	gtk_grid_attach (GTK_GRID (content), GTK_WIDGET (data->info_bar), 0, 2, 1, 1);

	e_webdav_discover_sources (source, rd->base_url, E_WEBDAV_DISCOVER_SUPPORTS_NONE, rd->credentials, rd->cancellable,
		e_webdav_discover_content_refresh_done_cb, rd);

	g_object_unref (source);
	soup_uri_free (soup_uri);
}
static void
do_soup_uri_null_tests (void)
{
	SoupURI *uri, *uri2;
	char *uri_string;

	debug_printf (1, "\nsoup_uri_new (NULL)\n");
	uri = soup_uri_new (NULL);
	if (SOUP_URI_IS_VALID (uri) || SOUP_URI_VALID_FOR_HTTP (uri)) {
		debug_printf (1, "  ERROR: soup_uri_new(NULL) returns valid URI?\n");
		errors++;
	}

	/* This implicitly also verifies that none of these methods g_warn */
	if (soup_uri_get_scheme (uri) ||
	    soup_uri_get_user (uri) ||
	    soup_uri_get_password (uri) ||
	    soup_uri_get_host (uri) ||
	    soup_uri_get_port (uri) ||
	    soup_uri_get_path (uri) ||
	    soup_uri_get_query (uri) ||
	    soup_uri_get_fragment (uri)) {
		debug_printf (1, "  ERROR: soup_uri_new(NULL) returns non-empty URI?\n");
		errors++;
	}

	expect_warning = TRUE;
	uri2 = soup_uri_new_with_base (uri, "/path");
	if (uri2 || expect_warning) {
		debug_printf (1, "  ERROR: soup_uri_new_with_base didn't fail on NULL URI?\n");
		errors++;
		expect_warning = FALSE;
	}

	expect_warning = TRUE;
	uri_string = soup_uri_to_string (uri, FALSE);
	if (expect_warning) {
		debug_printf (1, "  ERROR: soup_uri_to_string didn't fail on NULL URI?\n");
		errors++;
		expect_warning = FALSE;
	} else if (*uri_string) {
		debug_printf (1, "  ERROR: soup_uri_to_string on NULL URI returned '%s'\n",
			      uri_string);
		errors++;
	}
	g_free (uri_string);

	soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTP);
	if (SOUP_URI_IS_VALID (uri) || SOUP_URI_VALID_FOR_HTTP (uri)) {
		debug_printf (1, "  ERROR: setting scheme on NULL URI makes it valid?\n");
		errors++;
	}

	expect_warning = TRUE;
	uri_string = soup_uri_to_string (uri, FALSE);
	if (expect_warning) {
		debug_printf (1, "  ERROR: soup_uri_to_string didn't fail on scheme-only URI?\n");
		errors++;
		expect_warning = FALSE;
	} else if (strcmp (uri_string, "http:") != 0) {
		debug_printf (1, "  ERROR: soup_uri_to_string returned '%s' instead of 'http:'\n",
			      uri_string);
		errors++;
	}
	g_free (uri_string);

	soup_uri_set_host (uri, "localhost");
	if (SOUP_URI_IS_VALID (uri)) {
		debug_printf (1, "  ERROR: setting scheme+host on NULL URI makes it valid?\n");
		errors++;
	}
	if (SOUP_URI_VALID_FOR_HTTP (uri)) {
		debug_printf (1, "  ERROR: setting scheme+host on NULL URI makes it valid for http?\n");
		errors++;
	}

	expect_warning = TRUE;
	uri_string = soup_uri_to_string (uri, FALSE);
	if (expect_warning) {
		debug_printf (1, "  ERROR: soup_uri_to_string didn't fail on scheme+host URI?\n");
		errors++;
		expect_warning = FALSE;
	} else if (strcmp (uri_string, "http://localhost/") != 0) {
		debug_printf (1, "  ERROR: soup_uri_to_string with NULL path returned '%s' instead of 'http://localhost/'\n",
			      uri_string);
		errors++;
	}
	g_free (uri_string);

	expect_warning = TRUE;
	uri2 = soup_uri_new_with_base (uri, "/path");
	if (expect_warning) {
		debug_printf (1, "  ERROR: soup_uri_new_with_base didn't warn on NULL+scheme URI?\n");
		errors++;
		expect_warning = FALSE;
	} else if (!uri2) {
		debug_printf (1, "  ERROR: soup_uri_new_with_base didn't fix path on NULL+scheme URI\n");
		errors++;
	}

	if (uri2) {
		uri_string = soup_uri_to_string (uri2, FALSE);
		if (!uri_string) {
			debug_printf (1, "  ERROR: soup_uri_to_string failed on uri2?\n");
			errors++;
		} else if (strcmp (uri_string, "http://localhost/path") != 0) {
			debug_printf (1, "  ERROR: soup_uri_to_string returned '%s' instead of 'http://localhost/path'\n",
				      uri_string);
			errors++;
		}
		g_free (uri_string);
		soup_uri_free (uri2);
	}

	expect_warning = TRUE;
	soup_uri_set_path (uri, NULL);
	if (expect_warning) {
		debug_printf (1, "  ERROR: setting path to NULL doesn't warn\n");
		errors++;
		expect_warning = FALSE;
	}
	if (!uri->path || *uri->path) {
		debug_printf (1, "  ERROR: setting path to NULL != \"\"\n");
		errors++;
		soup_uri_set_path (uri, "");
	}

	uri_string = soup_uri_to_string (uri, FALSE);
	if (!uri_string) {
		debug_printf (1, "  ERROR: soup_uri_to_string failed on complete URI?\n");
		errors++;
	} else if (strcmp (uri_string, "http://localhost/") != 0) {
		debug_printf (1, "  ERROR: soup_uri_to_string with empty path returned '%s' instead of 'http://localhost/'\n",
			      uri_string);
		errors++;
	}
	g_free (uri_string);

	if (!SOUP_URI_IS_VALID (uri)) {
		debug_printf (1, "  ERROR: setting scheme+path on NULL URI doesn't make it valid?\n");
		errors++;
	}
	if (!SOUP_URI_VALID_FOR_HTTP (uri)) {
		debug_printf (1, "  ERROR: setting scheme+host+path on NULL URI doesn't make it valid for http?\n");
		errors++;
	}

	soup_uri_free (uri);
}
static void
_temporary_token_callback (SoupSession *session, SoupMessage *msg, gpointer user_data)
{
    GError* error = NULL;
    GSignondOauthPlugin *self = GSIGNOND_OAUTH_PLUGIN(user_data);

    if (msg->status_code != SOUP_STATUS_OK) {
        error = g_error_new(GSIGNOND_ERROR,
                                GSIGNOND_ERROR_NOT_AUTHORIZED,
                                "Temporary token endpoint returned an error: %d %s",
                                msg->status_code, msg->reason_phrase);
        goto out;
    }

    SoupBuffer* response_s = soup_message_body_flatten(msg->response_body);
    GHashTable* response = soup_form_decode(response_s->data);
    soup_buffer_free(response_s);

    const gchar* callback_confirmed = g_hash_table_lookup(response, "oauth_callback_confirmed");
    const gchar* token = g_hash_table_lookup(response, "oauth_token");
    const gchar* token_secret = g_hash_table_lookup(response, "oauth_token_secret");        

    if (token == NULL || token_secret == NULL || g_strcmp0(callback_confirmed, "true") != 0) {
        g_hash_table_destroy(response);
        error = g_error_new(GSIGNOND_ERROR,
                                GSIGNOND_ERROR_NOT_AUTHORIZED,
                                "Temporary token endpoint returned an invalid response");
        goto out;
    }

    const gchar* callback_url = gsignond_dictionary_get_string(self->oauth1_request, 
                                                               "Callback");
    if (callback_url == NULL) {                                                                    
        g_hash_table_destroy(response);
        error = g_error_new(GSIGNOND_ERROR,
                                GSIGNOND_ERROR_NOT_AUTHORIZED,
                                "Client did not supply Callback");
        goto out;
    }

    const gchar* authorization_url_s = gsignond_dictionary_get_string(self->oauth1_request, 
                                                                    "AuthorizationEndpoint");
    if (authorization_url_s == NULL) {                                                                    
        g_hash_table_destroy(response);
        error = g_error_new(GSIGNOND_ERROR,
                                GSIGNOND_ERROR_NOT_AUTHORIZED,
                                "Client did not supply AuthorizationEndpoint");
        goto out;
    }
    
    SoupURI* authorization_url = soup_uri_new(authorization_url_s);
    if (authorization_url == NULL) {
        g_hash_table_destroy(response);
        error = g_error_new(GSIGNOND_ERROR,
                                GSIGNOND_ERROR_NOT_AUTHORIZED,
                                "Client did not supply a valid AuthorizationEndpoint");
        goto out;
    }
    gsignond_oauth_plugin_check_host(soup_uri_get_host(authorization_url),
        gsignond_session_data_get_allowed_realms (self->oauth1_request), &error);
    if (error != NULL) {
        soup_uri_free(authorization_url);
        g_hash_table_destroy(response);
        return;
    }
    
    GHashTable* query = g_hash_table_new((GHashFunc)g_str_hash,
                                             (GEqualFunc)g_str_equal);
    const gchar* authorization_query_s = soup_uri_get_query(authorization_url);
    GHashTable *auth_query = NULL;
    if (authorization_query_s != NULL) {
        auth_query = soup_form_decode(authorization_query_s);
        g_hash_table_foreach(auth_query, _insert_key_value, query);
    }
    g_hash_table_insert(query, "oauth_token", (gchar*)token);
    soup_uri_set_query_from_form(authorization_url, query);
    if (auth_query)
        g_hash_table_destroy(auth_query);
    g_hash_table_destroy(query);
    
    gchar* open_url = soup_uri_to_string(authorization_url, FALSE);
    soup_uri_free(authorization_url);
    
    gsignond_dictionary_set_string(self->oauth1_request, "_OauthTemporaryToken", token);
    gsignond_dictionary_set_string(self->oauth1_request, "_OauthTemporaryTokenSecret", token_secret);
    
    GSignondSignonuiData* ui_request = gsignond_dictionary_new();
    gsignond_signonui_data_set_open_url(ui_request, open_url);
    g_free(open_url);
        
    if (g_strcmp0(callback_url, "oob") != 0)
        gsignond_signonui_data_set_final_url(ui_request, callback_url);
        
    /* add username and password, for fields initialization (the
     * decision on whether to actually use them is up to the signon UI */
    const gchar* username = gsignond_session_data_get_username(self->oauth1_request);
    if (username != NULL)
        gsignond_signonui_data_set_username(ui_request, username);
    const gchar* secret = gsignond_session_data_get_secret(self->oauth1_request);
    if (secret != NULL)
        gsignond_signonui_data_set_password(ui_request, secret);


     gsignond_plugin_user_action_required(GSIGNOND_PLUGIN(self), ui_request);
     gsignond_dictionary_unref(ui_request);    

    g_hash_table_destroy(response);

out:
   if (error != NULL) {
        _do_reset_oauth1(self);
        gsignond_plugin_error (GSIGNOND_PLUGIN(self), error);
        g_error_free(error);
   }
}