Handle and cache Accept-Language in WebSettings

This commit is contained in:
Christian Dywan 2012-08-23 21:25:44 +02:00
parent 06341b8ecf
commit f6595ea15e
5 changed files with 137 additions and 120 deletions

View file

@ -900,49 +900,33 @@ midori_soup_session_settings_accept_language_cb (SoupSession* session,
SoupMessage* msg, SoupMessage* msg,
MidoriWebSettings* settings) MidoriWebSettings* settings)
{ {
gchar* languages = katze_object_get_string (settings, "preferred-languages"); const gchar* accept = midori_web_settings_get_accept_language (settings);
gchar* accpt; if (midori_debug ("soup"))
g_message ("Accept-Language set to '%s'", accept);
/* Empty, use the system locales */ soup_message_headers_append (msg->request_headers, "Accept-Language", accept);
if (!(languages && *languages))
accpt = sokoke_accept_languages (g_get_language_names ());
/* No =, no ., looks like a list of language names */
else if (!(strchr (languages, '=') && strchr (languages, '.')))
{
gchar ** lang_names = g_strsplit_set (languages, ",; ", -1);
accpt = sokoke_accept_languages ((const gchar* const *)lang_names);
g_strfreev (lang_names);
}
/* Presumably a well formatted list including priorities */
else
accpt = languages;
if (accpt != languages)
g_free (languages);
soup_message_headers_append (msg->request_headers, "Accept-Language", accpt);
g_free (accpt);
if (katze_object_get_boolean (settings, "strip-referer")) if (katze_object_get_boolean (settings, "strip-referer"))
{ {
const gchar* referer const gchar* referer
= soup_message_headers_get_one (msg->request_headers, "Referer"); = soup_message_headers_get_one (msg->request_headers, "Referer");
SoupURI* destination = soup_message_get_uri (msg); SoupURI* destination = soup_message_get_uri (msg);
if (referer && destination && !strstr (referer, destination->host)) SoupURI* stripped_uri;
{ if (referer && destination && !strstr (referer, destination->host)
SoupURI* stripped_uri = soup_uri_new (referer); && (stripped_uri = soup_uri_new (referer)))
if (stripped_uri != NULL)
{ {
gchar* stripped_referer; gchar* stripped_referer;
soup_uri_set_path (stripped_uri, ""); soup_uri_set_path (stripped_uri, "");
soup_uri_set_query (stripped_uri, NULL); soup_uri_set_query (stripped_uri, NULL);
stripped_referer = soup_uri_to_string (stripped_uri, FALSE); stripped_referer = soup_uri_to_string (stripped_uri, FALSE);
soup_uri_free (stripped_uri); soup_uri_free (stripped_uri);
if (strcmp (stripped_referer, referer))
{
if (midori_debug ("soup")) if (midori_debug ("soup"))
g_message ("Referer %s stripped to %s", referer, stripped_referer); g_message ("Referer '%s' stripped to '%s'", referer, stripped_referer);
soup_message_headers_replace (msg->request_headers, "Referer", soup_message_headers_replace (msg->request_headers, "Referer",
stripped_referer); stripped_referer);
g_free (stripped_referer);
} }
g_free (stripped_referer);
} }
} }
} }

View file

@ -87,6 +87,7 @@ struct _MidoriWebSettings
gint maximum_cache_size; gint maximum_cache_size;
#endif #endif
gchar* http_accept_language; gchar* http_accept_language;
gchar* accept;
gchar* ident_string; gchar* ident_string;
gint clear_private_data; gint clear_private_data;
@ -1281,6 +1282,8 @@ midori_web_settings_finalize (GObject* object)
katze_assign (web_settings->news_aggregator, NULL); katze_assign (web_settings->news_aggregator, NULL);
katze_assign (web_settings->location_entry_search, NULL); katze_assign (web_settings->location_entry_search, NULL);
katze_assign (web_settings->http_proxy, NULL); katze_assign (web_settings->http_proxy, NULL);
katze_assign (web_settings->http_accept_language, NULL);
katze_assign (web_settings->accept, NULL);
katze_assign (web_settings->ident_string, NULL); katze_assign (web_settings->ident_string, NULL);
katze_assign (web_settings->user_stylesheet_uri, NULL); katze_assign (web_settings->user_stylesheet_uri, NULL);
katze_assign (web_settings->user_stylesheet_uri_cached, NULL); katze_assign (web_settings->user_stylesheet_uri_cached, NULL);
@ -1481,6 +1484,121 @@ generate_ident_string (MidoriWebSettings* web_settings,
} }
} }
/* Provide a new way for SoupSession to assume an 'Accept-Language'
string automatically from the return value of g_get_language_names(),
properly formatted according to RFC2616.
Copyright (C) 2009 Mario Sanchez Prada <msanchez@igalia.com>
Copyright (C) 2009 Dan Winship <danw@gnome.org>
Mostly copied from libSoup 2.29, coding style adjusted */
/* Converts a language in POSIX format and to be RFC2616 compliant */
/* Based on code from epiphany-webkit (ephy_langs_append_languages()) */
static gchar *
sokoke_posix_lang_to_rfc2616 (const gchar *language)
{
if (!strchr (language, '.') && !strchr (language, '@') && language[0] != 'C')
/* change to lowercase and '_' to '-' */
return g_strdelimit (g_ascii_strdown (language, -1), "_", '-');
return NULL;
}
/* Adds a quality value to a string (any value between 0 and 1). */
static gchar *
sokoke_add_quality_value (const gchar *str,
float qvalue)
{
if ((qvalue >= 0.0) && (qvalue <= 1.0))
{
int qv_int = (qvalue * 1000 + 0.5);
return g_strdup_printf ("%s;q=%d.%d",
str, (int) (qv_int / 1000), qv_int % 1000);
}
return g_strdup (str);
}
/* Returns a RFC2616 compliant languages list from system locales */
static gchar *
sokoke_accept_languages (const gchar* const * lang_names)
{
GArray *langs_garray = NULL;
char *cur_lang = NULL;
char *prev_lang = NULL;
char **langs_array;
char *langs_str;
float delta;
int i, n_lang_names;
/* Calculate delta for setting the quality values */
n_lang_names = g_strv_length ((gchar **)lang_names);
delta = 0.999 / (n_lang_names - 1);
/* Build the array of languages */
langs_garray = g_array_new (TRUE, FALSE, sizeof (char*));
for (i = 0; lang_names[i] != NULL; i++)
{
cur_lang = sokoke_posix_lang_to_rfc2616 (lang_names[i]);
/* Apart from getting a valid RFC2616 compliant
language, also get rid of extra variants */
if (cur_lang && (!prev_lang ||
(!strcmp (prev_lang, cur_lang) || !strstr (prev_lang, cur_lang))))
{
gchar *qv_lang = NULL;
/* Save reference for further comparison */
prev_lang = cur_lang;
/* Add the quality value and append it */
qv_lang = sokoke_add_quality_value (cur_lang, 1 - i * delta);
g_array_append_val (langs_garray, qv_lang);
}
}
/* Fallback: add "en" if list is empty */
if (langs_garray->len == 0)
{
gchar* fallback = g_strdup ("en");
g_array_append_val (langs_garray, fallback);
}
langs_array = (char **) g_array_free (langs_garray, FALSE);
langs_str = g_strjoinv (", ", langs_array);
return langs_str;
}
static void
midori_web_settings_update_accept_language (MidoriWebSettings* settings)
{
gchar* languages = settings->http_accept_language;
/* Empty, use the system locales */
if (!(languages && *languages))
katze_assign (settings->accept, sokoke_accept_languages (g_get_language_names ()));
/* No =, no ., looks like a list of language names */
else if (!(strchr (languages, '=') && strchr (languages, '.')))
{
gchar ** lang_names = g_strsplit_set (languages, ",; ", -1);
katze_assign (settings->accept, sokoke_accept_languages ((const gchar* const *)lang_names));
g_strfreev (lang_names);
}
/* Presumably a well formatted list including priorities */
else
katze_assign (settings->accept, g_strdup (languages));
}
const gchar*
midori_web_settings_get_accept_language (MidoriWebSettings* settings)
{
if (!settings->accept)
midori_web_settings_update_accept_language (settings);
return settings->accept;
}
static void static void
midori_web_settings_process_stylesheets (MidoriWebSettings* settings, midori_web_settings_process_stylesheets (MidoriWebSettings* settings,
gint delta_len); gint delta_len);
@ -1724,6 +1842,7 @@ midori_web_settings_set_property (GObject* object,
katze_assign (web_settings->http_accept_language, g_value_dup_string (value)); katze_assign (web_settings->http_accept_language, g_value_dup_string (value));
g_object_set (web_settings, "spell-checking-languages", g_object_set (web_settings, "spell-checking-languages",
web_settings->http_accept_language, NULL); web_settings->http_accept_language, NULL);
midori_web_settings_update_accept_language (web_settings);
break; break;
case PROP_CLEAR_PRIVATE_DATA: case PROP_CLEAR_PRIVATE_DATA:
web_settings->clear_private_data = g_value_get_int (value); web_settings->clear_private_data = g_value_get_int (value);

View file

@ -190,6 +190,9 @@ MidoriSiteDataPolicy
midori_web_settings_get_site_data_policy (MidoriWebSettings* settings, midori_web_settings_get_site_data_policy (MidoriWebSettings* settings,
const gchar* uri); const gchar* uri);
const gchar*
midori_web_settings_get_accept_language (MidoriWebSettings* settings);
G_END_DECLS G_END_DECLS
#endif /* __MIDORI_WEB_SETTINGS_H__ */ #endif /* __MIDORI_WEB_SETTINGS_H__ */

View file

@ -1353,92 +1353,6 @@ sokoke_recursive_fork_protection (const gchar* uri,
return g_strcmp0 (fork_uri, uri) == 0 ? FALSE : TRUE; return g_strcmp0 (fork_uri, uri) == 0 ? FALSE : TRUE;
} }
/* Provide a new way for SoupSession to assume an 'Accept-Language'
string automatically from the return value of g_get_language_names(),
properly formatted according to RFC2616.
Copyright (C) 2009 Mario Sanchez Prada <msanchez@igalia.com>
Copyright (C) 2009 Dan Winship <danw@gnome.org>
Mostly copied from libSoup 2.29, coding style adjusted */
/* Converts a language in POSIX format and to be RFC2616 compliant */
/* Based on code from epiphany-webkit (ephy_langs_append_languages()) */
static gchar *
sokoke_posix_lang_to_rfc2616 (const gchar *language)
{
if (!strchr (language, '.') && !strchr (language, '@') && language[0] != 'C')
/* change to lowercase and '_' to '-' */
return g_strdelimit (g_ascii_strdown (language, -1), "_", '-');
return NULL;
}
/* Adds a quality value to a string (any value between 0 and 1). */
static gchar *
sokoke_add_quality_value (const gchar *str,
float qvalue)
{
if ((qvalue >= 0.0) && (qvalue <= 1.0))
{
int qv_int = (qvalue * 1000 + 0.5);
return g_strdup_printf ("%s;q=%d.%d",
str, (int) (qv_int / 1000), qv_int % 1000);
}
return g_strdup (str);
}
/* Returns a RFC2616 compliant languages list from system locales */
gchar *
sokoke_accept_languages (const gchar* const * lang_names)
{
GArray *langs_garray = NULL;
char *cur_lang = NULL;
char *prev_lang = NULL;
char **langs_array;
char *langs_str;
float delta;
int i, n_lang_names;
/* Calculate delta for setting the quality values */
n_lang_names = g_strv_length ((gchar **)lang_names);
delta = 0.999 / (n_lang_names - 1);
/* Build the array of languages */
langs_garray = g_array_new (TRUE, FALSE, sizeof (char*));
for (i = 0; lang_names[i] != NULL; i++)
{
cur_lang = sokoke_posix_lang_to_rfc2616 (lang_names[i]);
/* Apart from getting a valid RFC2616 compliant
language, also get rid of extra variants */
if (cur_lang && (!prev_lang ||
(!strcmp (prev_lang, cur_lang) || !strstr (prev_lang, cur_lang))))
{
gchar *qv_lang = NULL;
/* Save reference for further comparison */
prev_lang = cur_lang;
/* Add the quality value and append it */
qv_lang = sokoke_add_quality_value (cur_lang, 1 - i * delta);
g_array_append_val (langs_garray, qv_lang);
}
}
/* Fallback: add "en" if list is empty */
if (langs_garray->len == 0)
{
gchar* fallback = g_strdup ("en");
g_array_append_val (langs_garray, fallback);
}
langs_array = (char **) g_array_free (langs_garray, FALSE);
langs_str = g_strjoinv (", ", langs_array);
return langs_str;
}
/** /**
* sokoke_register_privacy_item: * sokoke_register_privacy_item:
* @name: the name of the privacy item * @name: the name of the privacy item

View file

@ -175,9 +175,6 @@ sokoke_prefetch_uri (MidoriWebSettings* settings,
gboolean gboolean
sokoke_resolve_hostname (const gchar* hostname); sokoke_resolve_hostname (const gchar* hostname);
gchar *
sokoke_accept_languages (const gchar* const * lang_names);
gboolean gboolean
sokoke_recursive_fork_protection (const gchar* uri, sokoke_recursive_fork_protection (const gchar* uri,
gboolean set_uri); gboolean set_uri);