From 9eab79a76582e95965ed88085c83ef37651016b0 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 17 Dec 2009 11:24:41 +0100 Subject: [PATCH] Clean up accept-language-auto a bit Fix leaks, cross-reference the docs, use nicer qvalues, and don't bother cleaning up the g_get_language_names() return value; that's glib's fault (bug 604815). Also, use accept-language-auto in tests/get --- libsoup/soup-session.c | 111 +++++++++++++++++++++++-------------------------- tests/get.c | 4 +- 2 files changed, 55 insertions(+), 60 deletions(-) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 2dc6d1f..c6d8765 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -579,6 +579,10 @@ soup_session_class_init (SoupSessionClass *session_class) * If non-%NULL, the value to use for the "Accept-Language" header * on #SoupMessages sent from this session. * + * Setting this will disable + * #SoupSession:accept-language-auto. + * + * Since: 2.30 **/ /** * SOUP_SESSION_ACCEPT_LANGUAGE: @@ -600,6 +604,10 @@ soup_session_class_init (SoupSessionClass *session_class) * for the "Accept-Language" header on every #SoupMessage * sent, based on the return value of g_get_language_names(). * + * Setting this will override any previous value of + * #SoupSession:accept-language. + * + * Since: 2.30 **/ /** * SOUP_SESSION_ACCEPT_LANGUAGE_AUTO: @@ -703,40 +711,32 @@ safe_str_equal (const char *a, const char *b) static gchar * posix_lang_to_rfc2616 (const gchar *language) { - char *lang = NULL; - - if (strstr (language, ".") == 0 && - strstr (language, "@") == 0 && - strcmp (language, "C") != 0) - { - /* change to lowercase and '_' to '-' */ - lang = g_strdelimit (g_ascii_strdown - (language, -1), "_", '-'); - } + /* Don't include charset variants, etc */ + if (strchr (language, '.') || strchr (language, '@')) + return NULL; - return lang; + /* Ignore "C" locale, which g_get_language_names() always + * includes as a fallback. + */ + if (!strcmp (language, "C")) + return NULL; + + return g_strdelimit (g_ascii_strdown (language, -1), "_", '-'); } -/* Adds a quality value to a string (any value between 0 and 1). */ +/* Converts @quality from 0-100 to 0.0-1.0 and appends to @str */ static gchar * -add_quality_value (const gchar *str, float qvalue) +add_quality_value (const gchar *str, int quality) { - char *qv_str = NULL; - g_return_val_if_fail (str != NULL, NULL); - if ((qvalue >= 0.0) && (qvalue <= 1.0)) { - int qv_int = (qvalue * 1000 + 0.5); - qv_str = g_strdup_printf ("%s;q=%d.%d", - str, - (int) (qv_int / 1000), - qv_int % 1000); + if (quality > 0 && quality < 100) { + double qvalue = quality / 100.0; + return g_strdup_printf ("%s;q=%.2g", str, qvalue); } else { /* Just dup the string in this case */ - qv_str = g_strdup (str); + return g_strdup (str); } - - return qv_str; } /* Returns a RFC2616 compliant languages list from system locales */ @@ -744,54 +744,47 @@ static gchar * accept_languages_from_system (void) { const char * 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; + GPtrArray *langs = NULL; + char *lang, **langs_array, *langs_str; + int delta; + int i; lang_names = g_get_language_names (); g_return_val_if_fail (lang_names != NULL, NULL); - /* 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*)); + langs = g_ptr_array_new (); for (i = 0; lang_names[i] != NULL; i++) { - cur_lang = posix_lang_to_rfc2616 (lang_names[i]); - - /* Apart from getting a valid RFC2616 compliant - * language, also get rid of extra variants - */ - if ((cur_lang != NULL) && - (!prev_lang || - (!g_strcmp0 (prev_lang, cur_lang) || - !g_strstr_len (prev_lang, -1, cur_lang)))) { - - gchar *qv_lang = NULL; - - /* Save reference for further comparison */ - prev_lang = cur_lang; + lang = posix_lang_to_rfc2616 (lang_names[i]); + if (lang) + g_ptr_array_add (langs, lang); + } - /* Add the quality value and append it */ - qv_lang = add_quality_value (cur_lang, 1 - i * delta); - g_array_append_val (langs_garray, qv_lang); - } + /* Add quality values */ + if (langs->len < 10) + delta = 10; + else if (langs->len < 20) + delta = 5; + else + delta = 1; + + for (i = 0; i < langs->len; i++) { + lang = langs->pdata[i]; + langs->pdata[i] = add_quality_value (lang, 100 - i * delta); + g_free (lang); } /* Fallback: add "en" if list is empty */ - if (langs_garray->len == 0) { - char *default_lang = g_strdup ("en"); - g_array_append_val (langs_garray, default_lang); - } + if (langs->len == 0) + g_ptr_array_add (langs, g_strdup ("en")); - langs_array = (char **) g_array_free (langs_garray, FALSE); + g_ptr_array_add (langs, NULL); + langs_array = (char **)langs->pdata; langs_str = g_strjoinv (", ", langs_array); + g_strfreev (langs_array); + g_ptr_array_free (langs, FALSE); + return langs_str; } diff --git a/tests/get.c b/tests/get.c index 98f66f6..cc71946 100644 --- a/tests/get.c +++ b/tests/get.c @@ -46,7 +46,7 @@ get_url (const char *url) const char *hname, *value; char *path = soup_uri_to_string (soup_message_get_uri (msg), TRUE); - printf ("%s %s HTTP/1.%d\n\n", method, path, + printf ("%s %s HTTP/1.%d\n", method, path, soup_message_get_http_version (msg)); soup_message_headers_iter_init (&iter, msg->request_headers); while (soup_message_headers_iter_next (&iter, &hname, &value)) @@ -152,6 +152,7 @@ main (int argc, char **argv) #endif SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_DECODER, SOUP_SESSION_USER_AGENT, "get ", + SOUP_SESSION_ACCEPT_LANGUAGE_AUTO, TRUE, NULL); } else { session = soup_session_async_new_with_options ( @@ -161,6 +162,7 @@ main (int argc, char **argv) #endif SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_DECODER, SOUP_SESSION_USER_AGENT, "get ", + SOUP_SESSION_ACCEPT_LANGUAGE_AUTO, TRUE, NULL); } -- 2.7.4