Beispiel #1
0
static char *
msn_httpconn_proxy_auth(MsnHttpConn *httpconn)
{
	PurpleAccount *account;
	PurpleProxyInfo *gpi;
	const char *username, *password;
	char *auth = NULL;

	account = httpconn->session->account;

	gpi = purple_proxy_get_setup(account);

	if (gpi == NULL || !(purple_proxy_info_get_type(gpi) == PURPLE_PROXY_HTTP ||
						 purple_proxy_info_get_type(gpi) == PURPLE_PROXY_USE_ENVVAR))
		return NULL;

	username = purple_proxy_info_get_username(gpi);
	password = purple_proxy_info_get_password(gpi);

	if (username != NULL) {
		char *tmp;
		auth = g_strdup_printf("%s:%s", username, password ? password : "");
		tmp = purple_base64_encode((const guchar *)auth, strlen(auth));
		g_free(auth);
		auth = g_strdup_printf("Proxy-Authorization: Basic %s\r\n", tmp);
		g_free(tmp);
	}

	return auth;
}
/* TODO find a way to do this without libpurple */
static inline char *
get_auth(PnNode *conn)
{
    const char *username, *password;
    PurpleProxyInfo *gpi;
    char *tmp, *auth;

    gpi = purple_proxy_get_setup(msn_session_get_user_data(conn->session));
    if (!gpi)
        return NULL;

    if (purple_proxy_info_get_type(gpi) != PURPLE_PROXY_HTTP &&
        purple_proxy_info_get_type(gpi) != PURPLE_PROXY_USE_ENVVAR)
        return NULL;

    username = purple_proxy_info_get_username(gpi);
    password = purple_proxy_info_get_password(gpi);
    if (!username && !password)
        return NULL;

    auth = g_strdup_printf("%s:%s", username ? username : "", password ? password : "");
    tmp = purple_base64_encode((const guchar *) auth, strlen(auth));
    g_free(auth);
    auth = g_strdup_printf("Proxy-Authorization: Basic %s\r\n", tmp);
    g_free(tmp);

    return auth;
}
Beispiel #3
0
static gboolean
initiate_resolving(gpointer data)
{
	PurpleDnsQueryData *query_data;
	PurpleProxyType proxy_type;

	query_data = data;
	query_data->timeout = 0;

	if (resolve_ip(query_data))
		/* resolve_ip calls purple_dnsquery_resolved */
		return FALSE;

	proxy_type = purple_proxy_info_get_type(
		purple_proxy_get_setup(query_data->account));
	if (proxy_type == PURPLE_PROXY_TOR) {
		purple_dnsquery_failed(query_data,
			_("Aborting DNS lookup in Tor Proxy mode."));
		return FALSE;
	}

	if (purple_dnsquery_ui_resolve(query_data))
		/* The UI is handling the resolve; we're done */
		return FALSE;

	resolve_host(query_data);

	return FALSE;
}
Beispiel #4
0
static void server_list_create(PurpleAccount *account)
{
	PurpleConnection *gc;
	qq_data *qd;
	PurpleProxyInfo *gpi;
	const gchar *custom_server;

	gc = purple_account_get_connection(account);
	g_return_if_fail(gc != NULL  && gc->proto_data != NULL);
	qd = gc->proto_data;

	gpi = purple_proxy_get_setup(account);

	qd->use_tcp = purple_account_get_bool(account, "use_tcp", TRUE);

	custom_server = purple_account_get_string(account, "server", NULL);

	if (custom_server != NULL) {
		purple_debug_info("QQ", "Select server '%s'\n", custom_server);
		if (*custom_server != '\0' && g_ascii_strcasecmp(custom_server, "auto") != 0) {
			qd->servers = g_list_append(qd->servers, g_strdup(custom_server));
			return;
		}
	}

	if (qd->use_tcp) {
		qd->servers =	server_list_build('T');
		return;
	}

	qd->servers =	server_list_build('U');
}
void om_post_or_get(OmegleAccount *oma, OmegleMethod method,
		const gchar *host, const gchar *url, const gchar *postdata,
		OmegleProxyCallbackFunc callback_func, gpointer user_data,
		gboolean keepalive)
{
	GString *request;
	gchar *cookies;
	OmegleConnection *omconn;
	gchar *real_url;
	gboolean is_proxy = FALSE;
	const gchar *user_agent;
	const gchar* const *languages;
	gchar *language_names;
	PurpleProxyInfo *proxy_info = NULL;
	gchar *proxy_auth;
	gchar *proxy_auth_base64;

	/* TODO: Fix keepalive and use it as much as possible */
	keepalive = FALSE;

	if (host == NULL)
		host = purple_account_get_string(oma->account, "host", "bajor.omegle.com");

	if (oma && oma->account && !(method & OM_METHOD_SSL))
	{
		proxy_info = purple_proxy_get_setup(oma->account);
		if (purple_proxy_info_get_type(proxy_info) == PURPLE_PROXY_USE_GLOBAL)
			proxy_info = purple_global_proxy_get_info();
		if (purple_proxy_info_get_type(proxy_info) == PURPLE_PROXY_HTTP)
		{
			is_proxy = TRUE;
		}	
	}
	if (is_proxy == TRUE)
	{
		real_url = g_strdup_printf("http://%s%s", host, url);
	} else {
		real_url = g_strdup(url);
	}

	cookies = om_cookies_to_string(oma);
	user_agent = purple_account_get_string(oma->account, "user-agent", "Opera/9.50 (Windows NT 5.1; U; en-GB)");
	
	if (method & OM_METHOD_POST && !postdata)
		postdata = "";

	/* Build the request */
	request = g_string_new(NULL);
	g_string_append_printf(request, "%s %s HTTP/1.0\r\n",
			(method & OM_METHOD_POST) ? "POST" : "GET",
			real_url);
	if (is_proxy == FALSE)
		g_string_append_printf(request, "Host: %s\r\n", host);
	g_string_append_printf(request, "Connection: %s\r\n",
			(keepalive ? "Keep-Alive" : "close"));
	g_string_append_printf(request, "User-Agent: %s\r\n", user_agent);
	if (method & OM_METHOD_POST) {
		g_string_append_printf(request,
				"Content-Type: application/x-www-form-urlencoded\r\n");
		g_string_append_printf(request,
				"Content-length: %zu\r\n", strlen(postdata));
	}
	g_string_append_printf(request, "Accept: application/json, text/html, */*\r\n");
	g_string_append_printf(request, "Cookie: %s\r\n", cookies);
	g_string_append_printf(request, "Accept-Encoding: gzip\r\n");
	if (is_proxy == TRUE)
	{
		if (purple_proxy_info_get_username(proxy_info) &&
			purple_proxy_info_get_password(proxy_info))
		{
			proxy_auth = g_strdup_printf("%s:%s", purple_proxy_info_get_username(proxy_info), purple_proxy_info_get_password(proxy_info));
			proxy_auth_base64 = purple_base64_encode((guchar *)proxy_auth, strlen(proxy_auth));
			g_string_append_printf(request, "Proxy-Authorization: Basic %s\r\n", proxy_auth_base64);
			g_free(proxy_auth_base64);
			g_free(proxy_auth);
		}
	}

	/* Tell the server what language we accept, so that we get error messages in our language (rather than our IP's) */
	languages = g_get_language_names();
	language_names = g_strjoinv(", ", (gchar **)languages);
	purple_util_chrreplace(language_names, '_', '-');
	g_string_append_printf(request, "Accept-Language: %s\r\n", language_names);
	g_free(language_names);

	purple_debug_info("omegle", "getting url %s\n", url);

	g_string_append_printf(request, "\r\n");
	if (method & OM_METHOD_POST)
		g_string_append_printf(request, "%s", postdata);

	/* If it needs to go over a SSL connection, we probably shouldn't print
	 * it in the debug log.  Without this condition a user's password is
	 * printed in the debug log */
	if (method == OM_METHOD_POST)
		purple_debug_info("omegle", "sending request data:\n%s\n",
			postdata);

	g_free(cookies);

	/*
	 * Do a separate DNS lookup for the given host name and cache it
	 * for next time.
	 *
	 * TODO: It would be better if we did this before we call
	 *       purple_proxy_connect(), so we could re-use the result.
	 *       Or even better: Use persistent HTTP connections for servers
	 *       that we access continually.
	 *
	 * TODO: This cache of the hostname<-->IP address does not respect
	 *       the TTL returned by the DNS server.  We should expire things
	 *       from the cache after some amount of time.
	 */
	if (!is_proxy)
	{
		/* Don't do this for proxy connections, since proxies do the DNS lookup */
		gchar *host_ip;

		host_ip = g_hash_table_lookup(oma->hostname_ip_cache, host);
		if (host_ip != NULL) {
			host = host_ip;
		} else if (oma->account && !oma->account->disconnecting) {
			GSList *host_lookup_list = NULL;
			PurpleDnsQueryData *query;

			host_lookup_list = g_slist_prepend(
					host_lookup_list, g_strdup(host));
			host_lookup_list = g_slist_prepend(
					host_lookup_list, oma);

			query = purple_dnsquery_a(host, 80,
					om_host_lookup_cb, host_lookup_list);
			oma->dns_queries = g_slist_prepend(oma->dns_queries, query);
			host_lookup_list = g_slist_append(host_lookup_list, query);
		}
	}

	omconn = g_new0(OmegleConnection, 1);
	omconn->oma = oma;
	omconn->url = real_url;
	omconn->method = method;
	omconn->hostname = g_strdup(host);
	omconn->request = request;
	omconn->callback = callback_func;
	omconn->user_data = user_data;
	omconn->fd = -1;
	omconn->connection_keepalive = keepalive;
	omconn->request_time = time(NULL);
	oma->conns = g_slist_prepend(oma->conns, omconn);

	om_attempt_connection(omconn);
}
static void sevencup_attempt_connection(SevenCupConnection *scon)
{
	gboolean is_proxy = FALSE;
	SevenCupAccount *sa = scon->sa;
	PurpleProxyInfo *proxy_info = NULL;

	if (sa && sa->account && !(scon->method & STEAM_METHOD_SSL))
	{
		proxy_info = purple_proxy_get_setup(sa->account);
		if (purple_proxy_info_get_type(proxy_info) == PURPLE_PROXY_USE_GLOBAL)
			proxy_info = purple_global_proxy_get_info();
		if (purple_proxy_info_get_type(proxy_info) == PURPLE_PROXY_HTTP)
		{
			is_proxy = TRUE;
		}	
	}

#if 0
	/* Connection to attempt retries.  This code doesn't work perfectly, but
	 * remains here for future reference if needed */
	if (time(NULL) - scon->request_time > 5) {
		/* We've continuously tried to remake this connection for a 
		 * bit now.  It isn't happening, sadly.  Time to die. */
		purple_debug_error("7cups", "could not connect after retries\n");
		sevencup_fatal_connection_cb(scon);
		return;
	}

	purple_debug_info("7cups", "making connection attempt\n");

	/* TODO: If we're retrying the connection, consider clearing the cached
	 * DNS value.  This will require some juggling with the hostname param */
	/* TODO/FIXME: This retries almost instantenously, which in some cases
	 * runs at blinding speed.  Slow it down. */
	/* TODO/FIXME: this doesn't retry properly on non-ssl connections */
#endif
	
	sa->conns = g_slist_prepend(sa->conns, scon);

	/*
	 * Do a separate DNS lookup for the given host name and cache it
	 * for next time.
	 *
	 * TODO: It would be better if we did this before we call
	 *       purple_proxy_connect(), so we could re-use the result.
	 *       Or even better: Use persistent HTTP connections for servers
	 *       that we access continually.
	 *
	 * TODO: This cache of the hostname<-->IP address does not respect
	 *       the TTL returned by the DNS server.  We should expire things
	 *       from the cache after some amount of time.
	 */
	if (!is_proxy && !(scon->method & STEAM_METHOD_SSL) && !g_hostname_is_ip_address(scon->hostname))
	{
		/* Don't do this for proxy connections, since proxies do the DNS lookup */
		gchar *host_ip;

		host_ip = g_hash_table_lookup(sa->hostname_ip_cache, scon->hostname);
		if (host_ip != NULL) {
			g_free(scon->hostname);
			scon->hostname = g_strdup(host_ip);
		} else if (sa->account && !sa->account->disconnecting) {
			GSList *host_lookup_list = NULL;
			PurpleDnsQueryData *query;

			host_lookup_list = g_slist_prepend(
					host_lookup_list, g_strdup(scon->hostname));
			host_lookup_list = g_slist_prepend(
					host_lookup_list, sa);

			query = purple_dnsquery_a(
#if PURPLE_VERSION_CHECK(3, 0, 0)
					scon->sa->account,
#endif
					scon->hostname, 80,
					sevencup_host_lookup_cb, host_lookup_list);
			sa->dns_queries = g_slist_prepend(sa->dns_queries, query);
			host_lookup_list = g_slist_append(host_lookup_list, query);
		}
	}

	if (scon->method & STEAM_METHOD_SSL) {
		scon->ssl_conn = purple_ssl_connect(sa->account, scon->hostname,
				443, sevencup_post_or_get_ssl_connect_cb,
				sevencup_ssl_connection_error, scon);
	} else {
		scon->connect_data = purple_proxy_connect(NULL, sa->account,
				scon->hostname, 80, sevencup_post_or_get_connect_cb, scon);
	}
	
	scon->timeout_watcher = purple_timeout_add_seconds(120, sevencup_connection_timedout, scon);

	return;
}
SevenCupConnection *
sevencup_post_or_get(SevenCupAccount *sa, SteamMethod method,
		const gchar *host, const gchar *url, const gchar *postdata,
		SteamProxyCallbackFunc callback_func, gpointer user_data,
		gboolean keepalive)
{
	GString *request;
	gchar *cookies;
	SevenCupConnection *scon;
	gchar *real_url;
	gboolean is_proxy = FALSE;
	const gchar *user_agent;
	const gchar* const *languages;
	gchar *language_names;
	PurpleProxyInfo *proxy_info = NULL;
	gchar *proxy_auth;
	gchar *proxy_auth_base64;

	if (host == NULL)
		host = "www.7cupsoftea.com";

	if (sa && sa->account)
	{
		if (purple_account_get_bool(sa->account, "use-https", TRUE))
			method |= STEAM_METHOD_SSL;
	}

	if (sa && sa->account && !(method & STEAM_METHOD_SSL))
	{
		proxy_info = purple_proxy_get_setup(sa->account);
		if (purple_proxy_info_get_type(proxy_info) == PURPLE_PROXY_USE_GLOBAL)
			proxy_info = purple_global_proxy_get_info();
		if (purple_proxy_info_get_type(proxy_info) == PURPLE_PROXY_HTTP)
		{
			is_proxy = TRUE;
		}	
	}
	if (is_proxy == TRUE)
	{
		real_url = g_strdup_printf("http://%s%s", host, url);
	} else {
		real_url = g_strdup(url);
	}

	cookies = sevencup_cookies_to_string(sa);
	user_agent = purple_account_get_string(sa->account, "user-agent", "Steam 1.2.0 / iPhone");
	
	if (method & STEAM_METHOD_POST && !postdata)
		postdata = "";

	/* Build the request */
	request = g_string_new(NULL);
	g_string_append_printf(request, "%s %s HTTP/1.1\r\n",
			(method & STEAM_METHOD_POST) ? "POST" : "GET",
			real_url);
	if (is_proxy == FALSE)
		g_string_append_printf(request, "Host: %s\r\n", host);
	g_string_append_printf(request, "Connection: %s\r\n",
			(keepalive ? "Keep-Alive" : "close"));
	g_string_append_printf(request, "User-Agent: %s\r\n", user_agent);
	if (method & STEAM_METHOD_POST) {
		g_string_append_printf(request,
				"Content-Type: application/x-www-form-urlencoded\r\n");
		g_string_append_printf(request,
				"Content-length: %zu\r\n", strlen(postdata));
	}
	g_string_append_printf(request, "Accept: */*\r\n");
	g_string_append_printf(request, "Cookie: %s\r\n", cookies);
	g_string_append_printf(request, "Accept-Encoding: gzip\r\n");
	if (is_proxy == TRUE)
	{
		if (purple_proxy_info_get_username(proxy_info) &&
			purple_proxy_info_get_password(proxy_info))
		{
			proxy_auth = g_strdup_printf("%s:%s", purple_proxy_info_get_username(proxy_info), purple_proxy_info_get_password(proxy_info));
			proxy_auth_base64 = purple_base64_encode((guchar *)proxy_auth, strlen(proxy_auth));
			g_string_append_printf(request, "Proxy-Authorization: Basic %s\r\n", proxy_auth_base64);
			g_free(proxy_auth_base64);
			g_free(proxy_auth);
		}
	}

	/* Tell the server what language we accept, so that we get error messages in our language (rather than our IP's) */
	languages = g_get_language_names();
	language_names = g_strjoinv(", ", (gchar **)languages);
	purple_util_chrreplace(language_names, '_', '-');
	g_string_append_printf(request, "Accept-Language: %s\r\n", language_names);
	g_free(language_names);

	purple_debug_info("7cups", "getting url %s\n", url);

	g_string_append_printf(request, "\r\n");
	if (method & STEAM_METHOD_POST)
		g_string_append_printf(request, "%s", postdata);

	/* If it needs to go over a SSL connection, we probably shouldn't print
	 * it in the debug log.  Without this condition a user's password is
	 * printed in the debug log */
	if (method == STEAM_METHOD_POST)
		purple_debug_info("7cups", "sending request data:\n%s\n",
			postdata);

	g_free(cookies);

	scon = g_new0(SevenCupConnection, 1);
	scon->sa = sa;
	scon->url = real_url;
	scon->method = method;
	scon->hostname = g_strdup(host);
	scon->request = request;
	scon->callback = callback_func;
	scon->user_data = user_data;
	scon->fd = -1;
	scon->connection_keepalive = keepalive;
	scon->request_time = time(NULL);
	
	g_queue_push_head(sa->waiting_conns, scon);
	sevencup_next_connection(sa);
	
	return scon;
}
SkypeWebConnection *
skypeweb_post_or_get(SkypeWebAccount *sa, SkypeWebMethod method,
		const gchar *host, const gchar *url, const gchar *postdata,
		SkypeWebProxyCallbackFunc callback_func, gpointer user_data,
		gboolean keepalive)
{
	GString *request;
	gchar *cookies;
	SkypeWebConnection *skypewebcon;
	gchar *real_url;
	gboolean is_proxy = FALSE;
	//const gchar *user_agent;
	const gchar* const *languages;
	gchar *language_names;
	PurpleProxyInfo *proxy_info = NULL;
	gchar *proxy_auth;
	gchar *proxy_auth_base64;

	/* TODO: Fix keepalive and use it as much as possible */
	keepalive = FALSE;

	if (host == NULL)
		host = "api.skype.com";

	if (sa && sa->account)
	{
		if (purple_account_get_bool(sa->account, "use-https", TRUE))
			method |= SKYPEWEB_METHOD_SSL;
	}

	if (sa && sa->account && !(method & SKYPEWEB_METHOD_SSL))
	{
		proxy_info = purple_proxy_get_setup(sa->account);
		if (purple_proxy_info_get_type(proxy_info) == PURPLE_PROXY_USE_GLOBAL)
			proxy_info = purple_global_proxy_get_info();
		if (purple_proxy_info_get_type(proxy_info) == PURPLE_PROXY_HTTP)
		{
			is_proxy = TRUE;
		}	
	}
	if (is_proxy == TRUE)
	{
		real_url = g_strdup_printf("http://%s%s", host, url);
	} else {
		real_url = g_strdup(url);
	}

	cookies = skypeweb_cookies_to_string(sa);
	//user_agent = purple_account_get_string(sa->account, "user-agent", "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36");
	
	if ((method & (SKYPEWEB_METHOD_POST | SKYPEWEB_METHOD_PUT)) && !postdata)
		postdata = "";

	/* Build the request */
	request = g_string_new(NULL);
	g_string_append_printf(request, "%s %s HTTP/1.0\r\n",
			((method & SKYPEWEB_METHOD_POST) ? "POST" : ((method & SKYPEWEB_METHOD_PUT) ? "PUT" : ((method & SKYPEWEB_METHOD_DELETE) ? "DELETE" : "GET"))),
			real_url);
	if (is_proxy == FALSE)
		g_string_append_printf(request, "Host: %s\r\n", host);
	g_string_append_printf(request, "Connection: %s\r\n",
			(keepalive ? "Keep-Alive" : "close"));
	//g_string_append_printf(request, "User-Agent: %s\r\n", user_agent);
	if (method & (SKYPEWEB_METHOD_POST | SKYPEWEB_METHOD_PUT)) {		
		if (postdata && (postdata[0] == '[' || postdata[0] == '{')) {
			g_string_append(request, "Content-Type: application/json\r\n"); // hax
		} else {
			g_string_append_printf(request, "Content-Type: application/x-www-form-urlencoded\r\n");
		}
		g_string_append_printf(request, "Content-length: %zu\r\n", strlen(postdata));
	}
	
	if (g_str_equal(host, SKYPEWEB_CONTACTS_HOST) || g_str_equal(host, SKYPEWEB_VIDEOMAIL_HOST)) {
		g_string_append_printf(request, "X-Skypetoken: %s\r\n", sa->skype_token);
		g_string_append(request, "X-Stratus-Caller: " SKYPEWEB_CLIENTINFO_NAME "\r\n");
		g_string_append(request, "X-Stratus-Request: abcd1234\r\n");
		g_string_append(request, "Origin: https://web.skype.com\r\n");
		g_string_append(request, "Referer: https://web.skype.com/main\r\n");
		g_string_append(request, "Accept: application/json; ver=1.0;\r\n");
	} else if (g_str_equal(host, sa->messages_host)) {
		g_string_append_printf(request, "RegistrationToken: %s\r\n", sa->registration_token);
		g_string_append(request, "Referer: https://web.skype.com/main\r\n");
		g_string_append(request, "Accept: application/json; ver=1.0;\r\n");
		g_string_append(request, "ClientInfo: os=Windows; osVer=8.1; proc=Win32; lcid=en-us; deviceType=1; country=n/a; clientName=" SKYPEWEB_CLIENTINFO_NAME "; clientVer=" SKYPEWEB_CLIENTINFO_VERSION "\r\n");
	} else {
		g_string_append_printf(request, "Accept: */*\r\n");
		g_string_append_printf(request, "Cookie: %s\r\n", cookies);
	}
	
	g_string_append_printf(request, "Accept-Encoding: gzip\r\n");
	if (is_proxy == TRUE)
	{
		if (purple_proxy_info_get_username(proxy_info) &&
			purple_proxy_info_get_password(proxy_info))
		{
			proxy_auth = g_strdup_printf("%s:%s", purple_proxy_info_get_username(proxy_info), purple_proxy_info_get_password(proxy_info));
			proxy_auth_base64 = purple_base64_encode((guchar *)proxy_auth, strlen(proxy_auth));
			g_string_append_printf(request, "Proxy-Authorization: Basic %s\r\n", proxy_auth_base64);
			g_free(proxy_auth_base64);
			g_free(proxy_auth);
		}
	}

	/* Tell the server what language we accept, so that we get error messages in our language (rather than our IP's) */
	languages = g_get_language_names();
	language_names = g_strjoinv(", ", (gchar **)languages);
	purple_util_chrreplace(language_names, '_', '-');
	g_string_append_printf(request, "Accept-Language: %s\r\n", language_names);
	g_free(language_names);

	purple_debug_info("skypeweb", "getting url %s\n", url);

	g_string_append_printf(request, "\r\n");
	if (method & (SKYPEWEB_METHOD_POST | SKYPEWEB_METHOD_PUT))
		g_string_append_printf(request, "%s", postdata);

	/* If it needs to go over a SSL connection, we probably shouldn't print
	 * it in the debug log.  Without this condition a user's password is
	 * printed in the debug log */
	if (method == SKYPEWEB_METHOD_POST || method == SKYPEWEB_METHOD_PUT)
		purple_debug_info("skypeweb", "sending request data:\n%s\n", postdata);
	
	purple_debug_misc("skypeweb", "sending headers:\n%s\n", request->str);

	g_free(cookies);

	skypewebcon = g_new0(SkypeWebConnection, 1);
	skypewebcon->sa = sa;
	skypewebcon->url = real_url;
	skypewebcon->method = method;
	skypewebcon->hostname = g_strdup(host);
	skypewebcon->request = request;
	skypewebcon->callback = callback_func;
	skypewebcon->user_data = user_data;
	skypewebcon->fd = -1;
	skypewebcon->connection_keepalive = keepalive;
	skypewebcon->request_time = time(NULL);
	
	g_queue_push_head(sa->waiting_conns, skypewebcon);
	skypeweb_next_connection(sa);
	
	return skypewebcon;
}