diff -Nru accountsservice-0.6.15/debian/accountsservice.postinst accountsservice-0.6.15/debian/accountsservice.postinst --- accountsservice-0.6.15/debian/accountsservice.postinst 2011-12-07 15:48:06.000000000 +0000 +++ accountsservice-0.6.15/debian/accountsservice.postinst 2012-02-02 10:02:39.000000000 +0000 @@ -20,4 +20,62 @@ [ -z "$pid" ] || /usr/lib/accountsservice/accounts-daemon & >/dev/null || true # will trigger through D-Bus activation fi +# +# Modify /etc/default/locale and /etc/environment due to a changed +# meaning in Ubuntu 12.04 of the LANG environment variable. LANG +# now represents the display language instead of regional formats. +# +LANG_definition_migration() { + unset LANG LC_MESSAGES + test -f /etc/default/locale && . /etc/default/locale + test -n "$LC_MESSAGES" || return 0 + + config_files='/etc/default/locale /etc/environment' + + update() { + # if that file doesn't define a locale, skip it + grep -q "^LANG=" $f || return 0 + + f=$1; var=$2; value=$3 + if grep -q "^$var=" $f; then + sed -i "s/^$var=.*/$var=\"$value\"/" $f + else + echo "$var=\"$value\"" >> $f + fi + } + + if [ -n "$LANG" ] && [ $LANG != ${LANG%.utf8*} ]; then + LANG=${LANG%.*}.UTF-8${LANG#*.utf8} + fi + if [ $LC_MESSAGES != ${LC_MESSAGES%.utf8*} ]; then + LC_MESSAGES=${LC_MESSAGES%.*}.UTF-8${LC_MESSAGES#*.utf8} + fi + + for f in $config_files; do + test -f "$f" || continue + update $f 'LANG' $LC_MESSAGES + done + + if [ -n "$LANG" ] && [ $LANG != $LC_MESSAGES ]; then + for f in $config_files; do + test -f "$f" || continue + for var in 'LC_NUMERIC' 'LC_TIME' 'LC_MONETARY' 'LC_PAPER' \ + 'LC_NAME' 'LC_ADDRESS' 'LC_TELEPHONE' 'LC_MEASUREMENT'; do + update $f $var $LANG + done + done + fi + + for f in $config_files; do + test -f "$f" || continue + for var in 'LC_MESSAGES' 'LC_CTYPE' 'LC_COLLATE'; do + sed -i "/^$var=\"[^[:space:]]*\"$/d" $f + done + done +} + +if dpkg --compare-versions "$2" lt-nl 0.6.15-2ubuntu3; then + LANG_definition_migration +fi + #DEBHELPER# diff -Nru accountsservice-0.6.15/debian/changelog accountsservice-0.6.15/debian/changelog --- accountsservice-0.6.15/debian/changelog 2012-01-31 13:48:56.000000000 +0000 +++ accountsservice-0.6.15/debian/changelog 2012-02-03 05:42:19.000000000 +0000 @@ -1,3 +1,39 @@ +accountsservice (0.6.15-2ubuntu3) precise; urgency=low + + [ Gunnar Hjalmarsson ] + * debian/patches/0001-formats-locale-property.patch and + debian/libaccountsservice0.symbols: + - Addition of FormatsLocale property and SetFormatsLocale method. + * debian/patches/0009-language-tools.patch: + - Make SetLanguage() and SetFormatsLocale() write to + ~/.pam_environment instead of ~/.profile (LP: #866062). + - Make the LANG variable, which up to now has represented regional + formats, denote the display language instead (LP: #877610). + * debian/patches/0010-set-language.patch: + - If the Language or FormatsLocale property is not yet set when + queried, respond with a sensible, dynamically generated fallback + value. + - Code added for migrating ~/.profile environment settings to + ~/.pam_environment. + - Don't alter any settings if SetLanguage is called from a language + chooser on the greeter and /home is encrypted or not yet mounted. + - Misc. code refactoring. + * debian/accountsservice.postinst: + - Modify /etc/default/locale and /etc/environment due to a changed + meaning of the LANG environment variable. + + [ Martin Pitt ] + * debian/accountsservice.postinst: Only run the LANG migration when + upgrading to this version. Also, slightly improve the call to grep. + * debian/libaccountsservice0.symbols: Fix versions of symbols from + 0001-formats-locale-property.patch. + * debian/libaccountsservice0.symbols: Add new symbols from 0.6.15-2ubuntu1. + * debian/accountsservice.postinst: In the LANG migration, do not add all the + variables to a file which doesn't define LANG, so that we don't repeat + them in /etc/environment when they are already in /etc/default/locale. + + -- Martin Pitt Fri, 03 Feb 2012 06:42:19 +0100 + accountsservice (0.6.15-2ubuntu2) precise; urgency=low * SECURITY UPDATE: file permissions bypass (LP: #904395) diff -Nru accountsservice-0.6.15/debian/libaccountsservice0.symbols accountsservice-0.6.15/debian/libaccountsservice0.symbols --- accountsservice-0.6.15/debian/libaccountsservice0.symbols 2011-12-07 15:48:06.000000000 +0000 +++ accountsservice-0.6.15/debian/libaccountsservice0.symbols 2012-02-02 09:30:17.000000000 +0000 @@ -3,7 +3,9 @@ act_user_collate@Base 0.6.8 act_user_get_account_type@Base 0.6.8 act_user_get_automatic_login@Base 0.6.8 + act_user_get_background_file@Base 0.6.15-2ubuntu1~ act_user_get_email@Base 0.6.8 + act_user_get_formats_locale@Base 0.6.15-2ubuntu3~ act_user_get_home_dir@Base 0.6.8 act_user_get_icon_file@Base 0.6.8 act_user_get_language@Base 0.6.8 @@ -37,7 +39,9 @@ act_user_password_mode_get_type@Base 0.6.8 act_user_set_account_type@Base 0.6.8 act_user_set_automatic_login@Base 0.6.8 + act_user_set_background_file@Base 0.6.15-2ubuntu1~ act_user_set_email@Base 0.6.8 + act_user_set_formats_locale@Base 0.6.15-2ubuntu3~ act_user_set_icon_file@Base 0.6.8 act_user_set_language@Base 0.6.8 act_user_set_location@Base 0.6.8 diff -Nru accountsservice-0.6.15/debian/patches/0001-formats-locale-property.patch accountsservice-0.6.15/debian/patches/0001-formats-locale-property.patch --- accountsservice-0.6.15/debian/patches/0001-formats-locale-property.patch 1970-01-01 00:00:00.000000000 +0000 +++ accountsservice-0.6.15/debian/patches/0001-formats-locale-property.patch 2012-02-02 09:02:38.000000000 +0000 @@ -0,0 +1,391 @@ +Description: Addition of FormatsLocale property and SetFormatsLocale method. +Forwarded: https://bugs.freedesktop.org/42857 +Author: Gunnar Hjalmarsson +Last-Update: 2011-11-12 + +--- accountsservice.orig/data/org.freedesktop.Accounts.User.xml 2011-10-17 21:56:32 +0200 ++++ accountsservice/data/org.freedesktop.Accounts.User.xml 2011-11-11 19:59:17 +0100 +@@ -150,6 +150,41 @@ + + + ++ ++ ++ ++ ++ ++ The new regional formats, as a locale specification like "de_DE.UTF-8". ++ ++ ++ ++ ++ ++ ++ Sets the users regional formats. ++ ++ ++ ++ The caller needs one of the following PolicyKit authorizations: ++ ++ ++ org.freedesktop.accounts.change-own-user-data ++ To change his own language ++ ++ ++ org.freedesktop.accounts.user-administration ++ To change the language of another user ++ ++ ++ ++ ++ if the caller lacks the appropriate PolicyKit authorization ++ if the operation failed ++ ++ ++ ++ + + + +@@ -621,6 +656,16 @@ + + + ++ ++ ++ ++ ++ ++ ++ The users regional formats, as a locale specification like "de_DE.UTF-8". ++ ++ ++ + + + + +--- accountsservice.orig/src/libaccountsservice/act-user.c 2011-10-17 21:56:32 +0200 ++++ accountsservice/src/libaccountsservice/act-user.c 2011-11-11 19:59:45 +0100 +@@ -59,6 +59,7 @@ + PROP_LOGIN_FREQUENCY, + PROP_ICON_FILE, + PROP_LANGUAGE, ++ PROP_FORMATS_LOCALE, + PROP_X_SESSION, + PROP_IS_LOADED + }; +@@ -88,6 +89,7 @@ + char *location; + char *icon_file; + char *language; ++ char *formats_locale; + char *x_session; + GList *sessions; + int login_frequency; +@@ -237,6 +239,9 @@ + case PROP_LANGUAGE: + g_value_set_string (value, user->language); + break; ++ case PROP_FORMATS_LOCALE: ++ g_value_set_string (value, user->formats_locale); ++ break; + case PROP_X_SESSION: + g_value_set_string (value, user->x_session); + break; +@@ -371,6 +376,13 @@ + NULL, + G_PARAM_READABLE)); + g_object_class_install_property (gobject_class, ++ PROP_FORMATS_LOCALE, ++ g_param_spec_string ("formats_locale", ++ "Regional Formats", ++ "User's regional formats.", ++ NULL, ++ G_PARAM_READABLE)); ++ g_object_class_install_property (gobject_class, + PROP_X_SESSION, + g_param_spec_string ("x-session", + "X session", +@@ -461,6 +473,7 @@ + g_free (user->email); + g_free (user->location); + g_free (user->language); ++ g_free (user->formats_locale); + + if (user->accounts_proxy != NULL) { + g_object_unref (user->accounts_proxy); +@@ -834,6 +847,22 @@ + } + + /** ++ * act_user_get_formats_locale: ++ * @user: a #ActUser ++ * ++ * Returns the path to the configured formats locale of @user. ++ * ++ * Returns: (transfer none): a path to an icon ++ */ ++const char * ++act_user_get_formats_locale (ActUser *user) ++{ ++ g_return_val_if_fail (ACT_IS_USER (user), NULL); ++ ++ return user->formats_locale; ++} ++ ++/** + * act_user_get_x_session: + * @user: a #ActUser + * +@@ -1033,6 +1062,17 @@ + user->language = g_value_dup_string (value); + g_object_notify (G_OBJECT (user), "language"); + } ++ ++ } else if (strcmp (key, "FormatsLocale") == 0) { ++ const char *new_formats_locale; ++ ++ new_formats_locale = g_value_get_string (value); ++ if (g_strcmp0 (user->formats_locale, new_formats_locale) != 0) { ++ g_free (user->formats_locale); ++ user->formats_locale = g_value_dup_string (value); ++ g_object_notify (G_OBJECT (user), "formats_locale"); ++ } ++ + } else if (strcmp (key, "XSession") == 0) { + const char *new_x_session; + +@@ -1255,6 +1295,37 @@ + g_error_free (error); + return; + } ++} ++ ++/** ++ * act_user_set_formats_locale: ++ * @user: the user object to alter. ++ * @formats_locale: a locale (e.g. en_US.utf8) ++ * ++ * Assigns a new formats locale for @user. ++ * ++ * Note this function is synchronous and ignores errors. ++ **/ ++void ++act_user_set_formats_locale (ActUser *user, ++ const char *formats_locale) ++{ ++ GError *error = NULL; ++ ++ g_return_if_fail (ACT_IS_USER (user)); ++ g_return_if_fail (formats_locale != NULL); ++ g_return_if_fail (DBUS_IS_G_PROXY (user->accounts_proxy)); ++ ++ if (!dbus_g_proxy_call (user->accounts_proxy, ++ "SetFormatsLocale", ++ &error, ++ G_TYPE_STRING, formats_locale, ++ G_TYPE_INVALID, ++ G_TYPE_INVALID)) { ++ g_warning ("SetFormatsLocale call failed: %s", error->message); ++ g_error_free (error); ++ return; ++ } + } + + /** + +--- accountsservice.orig/src/libaccountsservice/act-user.h 2011-10-17 21:56:32 +0200 ++++ accountsservice/src/libaccountsservice/act-user.h 2011-11-11 20:00:15 +0100 +@@ -71,6 +71,7 @@ + gboolean act_user_is_system_account (ActUser *user); + const char *act_user_get_icon_file (ActUser *user); + const char *act_user_get_language (ActUser *user); ++const char *act_user_get_formats_locale (ActUser *user); + const char *act_user_get_x_session (ActUser *user); + const char *act_user_get_primary_session_id (ActUser *user); + +@@ -82,6 +83,8 @@ + const char *email); + void act_user_set_language (ActUser *user, + const char *language); ++void act_user_set_formats_locale (ActUser *user, ++ const char *formats_locale); + void act_user_set_x_session (ActUser *user, + const char *x_session); + void act_user_set_location (ActUser *user, + +--- accountsservice.orig/src/user.c 2011-11-11 19:56:47 +0100 ++++ accountsservice/src/user.c 2011-11-11 19:57:36 +0100 +@@ -60,6 +60,7 @@ + PROP_ACCOUNT_TYPE, + PROP_EMAIL, + PROP_LANGUAGE, ++ PROP_FORMATS_LOCALE, + PROP_X_SESSION, + PROP_LOCATION, + PROP_PASSWORD_MODE, +@@ -97,6 +98,7 @@ + gchar *shell; + gchar *email; + gchar *language; ++ gchar *formats_locale; + gchar *x_session; + gchar *location; + guint64 login_frequency; +@@ -130,6 +132,9 @@ + case PROP_LANGUAGE: + user->language = g_value_dup_string (value); + break; ++ case PROP_FORMATS_LOCALE: ++ user->formats_locale = g_value_dup_string (value); ++ break; + case PROP_X_SESSION: + user->x_session = g_value_dup_string (value); + break; +@@ -190,6 +195,9 @@ + case PROP_LANGUAGE: + g_value_set_string (value, user->language); + break; ++ case PROP_FORMATS_LOCALE: ++ g_value_set_string (value, user->formats_locale); ++ break; + case PROP_X_SESSION: + g_value_set_string (value, user->x_session); + break; +@@ -326,6 +334,13 @@ + NULL, + G_PARAM_READABLE)); + g_object_class_install_property (gobject_class, ++ PROP_FORMATS_LOCALE, ++ g_param_spec_string ("formats_locale", ++ "Regional Formats", ++ "The regional formats for this user.", ++ NULL, ++ G_PARAM_READABLE)); ++ g_object_class_install_property (gobject_class, + PROP_X_SESSION, + g_param_spec_string ("x-session", + "X Session", +@@ -395,6 +410,7 @@ + user->icon_file = NULL; + user->email = NULL; + user->language = NULL; ++ user->formats_locale = NULL; + user->x_session = NULL; + user->location = NULL; + user->password_mode = PASSWORD_MODE_REGULAR; +@@ -419,6 +435,7 @@ + g_free (user->icon_file); + g_free (user->email); + g_free (user->language); ++ g_free (user->formats_locale); + g_free (user->x_session); + g_free (user->location); + g_free (user->password_hint); +@@ -624,6 +641,12 @@ + user->language = s; + } + ++ s = g_key_file_get_string (keyfile, "User", "FormatsLocale", NULL); ++ if (s != NULL) { ++ g_free (user->formats_locale); ++ user->formats_locale = s; ++ } ++ + s = g_key_file_get_string (keyfile, "User", "XSession", NULL); + if (s != NULL) { + g_free (user->x_session); +@@ -667,6 +690,9 @@ + if (user->language) + g_key_file_set_string (keyfile, "User", "Language", user->language); + ++ if (user->formats_locale) ++ g_key_file_set_string (keyfile, "User", "FormatsLocale", user->formats_locale); ++ + if (user->x_session) + g_key_file_set_string (keyfile, "User", "XSession", user->x_session); + +@@ -1112,6 +1138,68 @@ + + return TRUE; + } ++ ++static void ++user_change_formats_locale_authorized_cb (Daemon *daemon, ++ User *user, ++ DBusGMethodInvocation *context, ++ gpointer data) ++ ++{ ++ gchar *formats_locale = data; ++ ++ if (g_strcmp0 (user->formats_locale, formats_locale) != 0) { ++ g_free (user->formats_locale); ++ user->formats_locale = g_strdup (formats_locale); ++ ++ save_extra_data (user); ++ ++ g_signal_emit (user, signals[CHANGED], 0); ++ ++ g_object_notify (G_OBJECT (user), "formats_locale"); ++ } ++ ++ dbus_g_method_return (context); ++} ++ ++gboolean ++user_set_formats_locale (User *user, ++ const gchar *formats_locale, ++ DBusGMethodInvocation *context) ++{ ++ gchar *sender; ++ DBusConnection *connection; ++ DBusError dbus_error; ++ uid_t uid; ++ const gchar *action_id; ++ ++ connection = dbus_g_connection_get_connection (user->system_bus_connection); ++ sender = dbus_g_method_get_sender (context); ++ dbus_error_init (&dbus_error); ++ uid = dbus_bus_get_unix_user (connection, sender, &dbus_error); ++ if (dbus_error_is_set (&dbus_error)) { ++ throw_error (context, ERROR_FAILED, dbus_error.message); ++ dbus_error_free (&dbus_error); ++ ++ return TRUE; ++ } ++ ++ if (user->uid == uid) ++ action_id = "org.freedesktop.accounts.change-own-user-data"; ++ else ++ action_id = "org.freedesktop.accounts.user-administration"; ++ ++ daemon_local_check_auth (user->daemon, ++ user, ++ action_id, ++ TRUE, ++ user_change_formats_locale_authorized_cb, ++ context, ++ g_strdup (formats_locale), ++ (GDestroyNotify) g_free); ++ ++ return TRUE; ++} + + static void + user_change_x_session_authorized_cb (Daemon *daemon, + +--- accountsservice.orig/src/user.h 2011-10-17 21:56:32 +0200 ++++ accountsservice/src/user.h 2011-11-11 20:12:03 +0100 +@@ -80,6 +80,9 @@ + gboolean user_set_language (User *user, + const gchar *language, + DBusGMethodInvocation *context); ++gboolean user_set_formats_locale (User *user, ++ const gchar *formats_locale, ++ DBusGMethodInvocation *context); + gboolean user_set_x_session (User *user, + const gchar *x_session, + DBusGMethodInvocation *context); + diff -Nru accountsservice-0.6.15/debian/patches/0002-create-and-manage-groups-like-on-a-debian-system.patch accountsservice-0.6.15/debian/patches/0002-create-and-manage-groups-like-on-a-debian-system.patch --- accountsservice-0.6.15/debian/patches/0002-create-and-manage-groups-like-on-a-debian-system.patch 2011-12-07 15:48:06.000000000 +0000 +++ accountsservice-0.6.15/debian/patches/0002-create-and-manage-groups-like-on-a-debian-system.patch 2012-02-02 09:02:38.000000000 +0000 @@ -49,7 +49,7 @@ dbus_g_method_return (context, user_local_get_object_path (user)); --- accountsservice.orig/src/user.c +++ accountsservice/src/user.c -@@ -431,7 +431,7 @@ static gint +@@ -448,7 +448,7 @@ static gint account_type_from_pwent (struct passwd *pwent) { struct group *grp; @@ -58,7 +58,7 @@ gid_t *groups; gint ngroups; gint i; -@@ -441,17 +441,17 @@ account_type_from_pwent (struct passwd * +@@ -458,17 +458,17 @@ account_type_from_pwent (struct passwd * return ACCOUNT_TYPE_ADMINISTRATOR; } @@ -80,7 +80,7 @@ g_free (groups); return ACCOUNT_TYPE_ADMINISTRATOR; } -@@ -1630,7 +1630,7 @@ user_change_account_type_authorized_cb ( +@@ -1718,7 +1718,7 @@ user_change_account_type_authorized_cb ( gid_t *groups; gint ngroups; GString *str; @@ -89,7 +89,7 @@ struct group *grp; gint i; gchar *argv[6]; -@@ -1640,24 +1640,24 @@ user_change_account_type_authorized_cb ( +@@ -1728,24 +1728,24 @@ user_change_account_type_authorized_cb ( "change account type of user '%s' (%d) to %d", user->user_name, user->uid, account_type); diff -Nru accountsservice-0.6.15/debian/patches/0002-create-and-manage-groups-like-on-a-ubuntu-system.patch accountsservice-0.6.15/debian/patches/0002-create-and-manage-groups-like-on-a-ubuntu-system.patch --- accountsservice-0.6.15/debian/patches/0002-create-and-manage-groups-like-on-a-ubuntu-system.patch 2011-12-07 15:48:06.000000000 +0000 +++ accountsservice-0.6.15/debian/patches/0002-create-and-manage-groups-like-on-a-ubuntu-system.patch 2012-02-02 09:02:38.000000000 +0000 @@ -56,7 +56,7 @@ =================================================================== --- accountsservice.orig/src/user.c 2011-11-25 08:09:22.632988348 +0100 +++ accountsservice/src/user.c 2011-11-25 08:19:01.920961897 +0100 -@@ -431,7 +431,8 @@ +@@ -448,7 +448,8 @@ account_type_from_pwent (struct passwd *pwent) { struct group *grp; @@ -66,7 +66,7 @@ gid_t *groups; gint ngroups; gint i; -@@ -441,17 +442,26 @@ +@@ -458,17 +459,26 @@ return ACCOUNT_TYPE_ADMINISTRATOR; } @@ -97,7 +97,7 @@ g_free (groups); return ACCOUNT_TYPE_ADMINISTRATOR; } -@@ -1630,7 +1640,7 @@ +@@ -1718,7 +1728,7 @@ gid_t *groups; gint ngroups; GString *str; @@ -106,7 +106,7 @@ struct group *grp; gint i; gchar *argv[6]; -@@ -1640,24 +1650,24 @@ +@@ -1728,24 +1738,24 @@ "change account type of user '%s' (%d) to %d", user->user_name, user->uid, account_type); diff -Nru accountsservice-0.6.15/debian/patches/0008-nopasswdlogin-group.patch accountsservice-0.6.15/debian/patches/0008-nopasswdlogin-group.patch --- accountsservice-0.6.15/debian/patches/0008-nopasswdlogin-group.patch 2011-12-07 15:48:06.000000000 +0000 +++ accountsservice-0.6.15/debian/patches/0008-nopasswdlogin-group.patch 2012-02-02 09:02:38.000000000 +0000 @@ -4,7 +4,7 @@ --- accountsservice.orig/src/user.c +++ accountsservice/src/user.c -@@ -1748,6 +1748,21 @@ user_change_password_mode_authorized_cb +@@ -1846,6 +1846,21 @@ user_change_password_mode_authorized_cb return; } @@ -26,7 +26,7 @@ if (mode == PASSWORD_MODE_SET_AT_LOGIN) { argv[0] = "/usr/bin/chage"; argv[1] = "-d"; -@@ -1795,6 +1810,23 @@ user_change_password_mode_authorized_cb +@@ -1893,6 +1908,23 @@ user_change_password_mode_authorized_cb g_object_notify (G_OBJECT (user), "locked"); } @@ -50,7 +50,7 @@ user->password_mode = mode; g_object_notify (G_OBJECT (user), "password-mode"); -@@ -1876,6 +1908,20 @@ user_change_password_authorized_cb (Daem +@@ -1974,6 +2006,20 @@ user_change_password_authorized_cb (Daem error = NULL; if (!spawn_with_login_uid (context, argv, &error)) { diff -Nru accountsservice-0.6.15/debian/patches/0009-language-tools.patch accountsservice-0.6.15/debian/patches/0009-language-tools.patch --- accountsservice-0.6.15/debian/patches/0009-language-tools.patch 2012-01-31 13:44:58.000000000 +0000 +++ accountsservice-0.6.15/debian/patches/0009-language-tools.patch 2012-02-02 09:02:38.000000000 +0000 @@ -1,24 +1,9 @@ -Description: Help files for dealing with language settings. +Description: Help files for dealing with language/locale settings. Author: Gunnar Hjalmarsson ---- - configure.ac | 1 - data/Makefile.am | 1 - data/langtools/Makefile.am | 16 ++++++++ - data/langtools/language-options | 66 +++++++++++++++++++++++++++++++++ - data/langtools/language-validate | 73 +++++++++++++++++++++++++++++++++++++ - data/langtools/language2locale | 65 ++++++++++++++++++++++++++++++++ - data/langtools/main-countries | 28 ++++++++++++++ - data/langtools/save-to-profile | 54 +++++++++++++++++++++++++++ - data/langtools/set-language-helper | 25 ++++++++++++ - data/langtools/update-langlist | 61 ++++++++++++++++++++++++++++++ - 10 files changed, 390 insertions(+) - -Index: accountsservice-0.6.15/configure.ac -=================================================================== ---- accountsservice-0.6.15.orig/configure.ac 2012-01-31 08:44:05.064545115 -0500 -+++ accountsservice-0.6.15/configure.ac 2012-01-31 08:44:12.748545314 -0500 -@@ -178,6 +178,7 @@ +--- accountsservice.orig/configure.ac ++++ accountsservice/configure.ac +@@ -178,6 +178,7 @@ AC_CONFIG_FILES([ Makefile po/Makefile.in data/Makefile @@ -26,10 +11,24 @@ src/Makefile src/libaccountsservice/Makefile src/libaccountsservice/accountsservice.pc -Index: accountsservice-0.6.15/data/langtools/language2locale -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ accountsservice-0.6.15/data/langtools/language2locale 2012-01-31 08:44:12.748545314 -0500 +--- /dev/null ++++ accountsservice/data/langtools/del-profile-env-settings +@@ -0,0 +1,13 @@ ++#!/bin/sh -e ++ ++homedir=$1 ++ ++test -n "$homedir" || exit 1 ++ ++test -f "$homedir/.profile" && { ++ cd "$homedir" ++ for var in 'LANGUAGE' 'LANG' 'LC_MESSAGES' 'LC_CTYPE' 'LC_COLLATE'; do ++ sed -i "/^export $var=\"[^[:space:]]*\"$/d" .profile ++ done ++} ++ +--- /dev/null ++++ accountsservice/data/langtools/language2locale @@ -0,0 +1,65 @@ +#!/bin/sh -e +# @@ -39,7 +38,7 @@ +lang=$1 +locale_name= + -+test -n "$lang" || exit 0 ++test -n "$lang" || exit 1 + +langtoolsdir=/usr/share/language-tools + @@ -96,10 +95,8 @@ + +echo $locale_name + -Index: accountsservice-0.6.15/data/langtools/language-options -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ accountsservice-0.6.15/data/langtools/language-options 2012-01-31 08:44:12.748545314 -0500 +--- /dev/null ++++ accountsservice/data/langtools/language-options @@ -0,0 +1,66 @@ +#!/usr/bin/perl +use strict; @@ -167,21 +164,24 @@ +# print the resulting list of language options +print join("\n", sort keys %intersection) || 'en'; + -Index: accountsservice-0.6.15/data/langtools/language-validate -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ accountsservice-0.6.15/data/langtools/language-validate 2012-01-31 08:44:12.748545314 -0500 -@@ -0,0 +1,73 @@ +--- /dev/null ++++ accountsservice/data/langtools/language-validate +@@ -0,0 +1,78 @@ +#!/bin/sh -e + +lang=$1 +validated_language= + -+test -n "$lang" || exit 0 ++test -n "$lang" || exit 1 + +langtoolsdir=/usr/share/language-tools + +# ++# discard possible fallback languages ++# ++lang=${lang%%:*} ++ ++# +# remove possible encoding part +# +if [ $lang != ${lang%.utf8*} ]; then @@ -245,10 +245,8 @@ + +echo $validated_language + -Index: accountsservice-0.6.15/data/langtools/main-countries -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ accountsservice-0.6.15/data/langtools/main-countries 2012-01-31 08:44:12.748545314 -0500 +--- /dev/null ++++ accountsservice/data/langtools/main-countries @@ -0,0 +1,28 @@ +# If multiple country codes are present among the available locales for +# a language, we may want to map the language code to the language's @@ -278,11 +276,9 @@ +ti ti_ER +tr tr_TR + -Index: accountsservice-0.6.15/data/langtools/Makefile.am -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ accountsservice-0.6.15/data/langtools/Makefile.am 2012-01-31 08:44:12.748545314 -0500 -@@ -0,0 +1,16 @@ +--- /dev/null ++++ accountsservice/data/langtools/Makefile.am +@@ -0,0 +1,17 @@ +langtoolsdir = ${datadir}/language-tools + +install-data-hook: @@ -291,105 +287,85 @@ + chmod 755 $(DESTDIR)$(langtoolsdir); \ + fi + -+ $(INSTALL_SCRIPT) language-options $(DESTDIR)$(langtoolsdir)/language-options -+ $(INSTALL_SCRIPT) language-validate $(DESTDIR)$(langtoolsdir)/language-validate -+ $(INSTALL_SCRIPT) language2locale $(DESTDIR)$(langtoolsdir)/language2locale -+ $(INSTALL_DATA) main-countries $(DESTDIR)$(langtoolsdir)/main-countries -+ $(INSTALL_SCRIPT) save-to-profile $(DESTDIR)$(langtoolsdir)/save-to-profile -+ $(INSTALL_SCRIPT) set-language-helper $(DESTDIR)$(langtoolsdir)/set-language-helper -+ $(INSTALL_SCRIPT) update-langlist $(DESTDIR)$(langtoolsdir)/update-langlist -+ -Index: accountsservice-0.6.15/data/langtools/save-to-profile -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ accountsservice-0.6.15/data/langtools/save-to-profile 2012-01-31 08:44:54.604546384 -0500 -@@ -0,0 +1,51 @@ -+#!/bin/sh ++ $(INSTALL_SCRIPT) del-profile-env-settings $(DESTDIR)$(langtoolsdir)/del-profile-env-settings ++ $(INSTALL_SCRIPT) language-options $(DESTDIR)$(langtoolsdir)/language-options ++ $(INSTALL_SCRIPT) language-validate $(DESTDIR)$(langtoolsdir)/language-validate ++ $(INSTALL_SCRIPT) language2locale $(DESTDIR)$(langtoolsdir)/language2locale ++ $(INSTALL_DATA) main-countries $(DESTDIR)$(langtoolsdir)/main-countries ++ $(INSTALL_SCRIPT) save-to-pam-env $(DESTDIR)$(langtoolsdir)/save-to-pam-env ++ $(INSTALL_SCRIPT) set-language-helper $(DESTDIR)$(langtoolsdir)/set-language-helper ++ $(INSTALL_SCRIPT) update-langlist $(DESTDIR)$(langtoolsdir)/update-langlist ++ +--- /dev/null ++++ accountsservice/data/langtools/save-to-pam-env +@@ -0,0 +1,36 @@ ++#!/bin/sh -e +# -+# attempts to update the language settings in the user's ~/.profile config file ++# updates the ~/.pam_environment config file + -+user=$1 -+language_list=$2 -+locale_name=$3 -+ -+test -n "$user" || exit 0 -+ -+# look up the user's home directory first -+while read line; do -+ [ "${line%%:*}" = $user ] && break -+done < '/etc/passwd' -+if [ -n "$line" ]; then -+ OLDIFS=$IFS -+ IFS=':' -+ i=1 -+ for homedir in $line; do -+ if [ $i -ne 6 ]; then -+ i=$(( $i + 1 )) -+ continue -+ fi -+ break -+ done -+ IFS=$OLDIFS -+fi -+if [ "$( echo $homedir )" = '' -o ! -d "$homedir" ]; then -+ exit 0 -+fi ++homedir=$1 ++locale_name=$2 ++language_list=$3 + -+# create ~/.profile if it doesn't exist -+touch $homedir/.profile ++[ -n "$homedir" -a -n "$locale_name" ] || exit 1 + -+save_to_profile() { ++# create ~/.pam_environment if it doesn't exist ++touch "$homedir/.pam_environment" || exit 1 ++ ++save_to_pam_env() { + var=$1; value=$2 -+ if [ "$( grep "^[[:space:]]*export $var=" $homedir/.profile )" ]; then -+ sed -r -i "s/^[[:space:]]*(export $var=).*/\1\"$value\"/" $homedir/.profile ++ if [ "$( grep "^$var=" .pam_environment )" ]; then ++ sed -r -i "s/^($var=).*/\1$value/" .pam_environment + else -+ echo "export $var=\"$value\"" >> $homedir/.profile ++ echo "$var=$value" >> .pam_environment + fi +} -+test -n "$language_list" && save_to_profile 'LANGUAGE' $language_list -+test -n "$locale_name" && { -+ save_to_profile 'LC_MESSAGES' $locale_name -+ save_to_profile 'LC_CTYPE' $locale_name -+ save_to_profile 'LC_COLLATE' $locale_name -+} ++ ++cd "$homedir" ++if [ -n "$language_list" ]; then ++ save_to_pam_env 'LANGUAGE' $language_list ++ save_to_pam_env 'LANG' $locale_name ++else ++ for var in 'LC_NUMERIC' 'LC_TIME' 'LC_MONETARY' 'LC_PAPER' 'LC_NAME' \ ++ 'LC_ADDRESS' 'LC_TELEPHONE' 'LC_MEASUREMENT'; do ++ save_to_pam_env $var $locale_name ++ done ++ echo $locale_name ++fi + +exit 0 + -Index: accountsservice-0.6.15/data/langtools/set-language-helper -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ accountsservice-0.6.15/data/langtools/set-language-helper 2012-01-31 08:44:12.748545314 -0500 +--- /dev/null ++++ accountsservice/data/langtools/set-language-helper @@ -0,0 +1,25 @@ +#!/bin/sh -e + -+user=$1 ++homedir=$1 +language=$2 +validated_language= + -+[ -n "$user" -a -n "$language" ] || exit 0 ++[ -n "$language" -a -n "$homedir" ] || exit 1 + +langtoolsdir=/usr/share/language-tools + ++validated_language=$( $langtoolsdir/language-validate $language ) ++ +if [ $language = "${language%:*}" ]; then -+ validated_language=$( $langtoolsdir/language-validate $language ) -+ renewed_langlist=$( $langtoolsdir/update-langlist $validated_language $user ) ++ renewed_langlist=$( $langtoolsdir/update-langlist $validated_language "$homedir" ) +else + # $language contains a priority list -+ validated_language=$( $langtoolsdir/language-validate ${language%%:*} ) + renewed_langlist=$validated_language:${language#*:} +fi + +locale_name=$( $langtoolsdir/language2locale $validated_language ) + -+( $langtoolsdir/save-to-profile $user $renewed_langlist $locale_name ) ++( $langtoolsdir/save-to-pam-env "$homedir" $locale_name $renewed_langlist ) || exit 1 + +echo $validated_language + -Index: accountsservice-0.6.15/data/langtools/update-langlist -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ accountsservice-0.6.15/data/langtools/update-langlist 2012-01-31 08:44:12.748545314 -0500 -@@ -0,0 +1,61 @@ +--- /dev/null ++++ accountsservice/data/langtools/update-langlist +@@ -0,0 +1,48 @@ +#!/bin/sh -e +# +# update-langlist maintains the LANGUAGE priority list. It does so in @@ -397,32 +373,19 @@ +# language which provides full control. + +first_language=$1 -+user=$2 ++homedir=$2 +renewed_langlist= + -+[ -n "$first_language" -a -n "$user" ] || exit 0 ++[ -n "$first_language" -a -n "$homedir" ] || exit 1 + +get_old_langlist() { -+ while read line; do -+ [ "${line%%:*}" = $user ] && break -+ done < /etc/passwd -+ if [ -n "$line" ]; then -+ OLDIFS=$IFS -+ IFS=':' -+ i=1 -+ for homedir in $line; do -+ if [ $i -ne 6 ]; then -+ i=$(( $i + 1 )) -+ continue ++ if [ -r "$homedir/.pam_environment" ]; then ++ while read line; do ++ if [ "${line%=*}" = 'LANGUAGE' ]; then ++ old_langlist=${line#*=} ++ break + fi -+ break -+ done -+ IFS=$OLDIFS -+ fi -+ -+ if [ -r "$homedir/.profile" ]; then -+ old_langlist=$( grep "^[[:space:]]*export LANGUAGE=" \ -+ $homedir/.profile | cut -d '"' -f 2 ) ++ done < $homedir/.pam_environment + fi +} + @@ -451,10 +414,8 @@ + +echo $renewed_langlist + -Index: accountsservice-0.6.15/data/Makefile.am -=================================================================== ---- accountsservice-0.6.15.orig/data/Makefile.am 2012-01-31 08:44:04.976545113 -0500 -+++ accountsservice-0.6.15/data/Makefile.am 2012-01-31 08:44:12.748545314 -0500 +--- accountsservice.orig/data/Makefile.am ++++ accountsservice/data/Makefile.am @@ -1,3 +1,4 @@ +SUBDIRS = langtools diff -Nru accountsservice-0.6.15/debian/patches/0010-set-language.patch accountsservice-0.6.15/debian/patches/0010-set-language.patch --- accountsservice-0.6.15/debian/patches/0010-set-language.patch 2012-01-31 13:47:21.000000000 +0000 +++ accountsservice-0.6.15/debian/patches/0010-set-language.patch 2012-02-02 09:02:38.000000000 +0000 @@ -1,79 +1,545 @@ -Description: Save user language settings to ~/.profile. +Description: Save user language and regional formats settings to ~/.pam_environment. Author: Gunnar Hjalmarsson ---- - src/user.c | 40 +++++++++++++++++++++++++++++++++++++++- - 1 file changed, 39 insertions(+), 1 deletion(-) - -Index: accountsservice-0.6.15/src/user.c -=================================================================== ---- accountsservice-0.6.15.orig/src/user.c 2012-01-31 08:45:05.632546667 -0500 -+++ accountsservice-0.6.15/src/user.c 2012-01-31 08:47:16.808550028 -0500 -@@ -49,6 +49,7 @@ - #include "util.h" - - #define ICONDIR LOCALSTATEDIR "/lib/AccountsService/icons" -+#define LANGTOOLSDIR DATADIR "/language-tools" - - enum { - PROP_0, -@@ -1066,9 +1067,58 @@ - gpointer data) +--- accountsservice.orig/src/user.c ++++ accountsservice/src/user.c +@@ -114,6 +114,8 @@ + } UserClass; - { -- gchar *language = data; -+ gchar *language = data; + static void user_finalize (GObject *object); ++static gchar *user_get_fallback_value (User *user, ++ const gchar *property); + + G_DEFINE_TYPE (User, user, G_TYPE_OBJECT) + +@@ -193,10 +195,16 @@ + g_value_set_string (value, user->email); + break; + case PROP_LANGUAGE: +- g_value_set_string (value, user->language); ++ if (user->language) ++ g_value_set_string (value, user->language); ++ else ++ g_value_set_string (value, user_get_fallback_value (user, "Language")); + break; + case PROP_FORMATS_LOCALE: +- g_value_set_string (value, user->formats_locale); ++ if (user->formats_locale) ++ g_value_set_string (value, user->formats_locale); ++ else ++ g_value_set_string (value, user_get_fallback_value (user, "FormatsLocale")); + break; + case PROP_X_SESSION: + g_value_set_string (value, user->x_session); +@@ -1085,6 +1093,352 @@ + return TRUE; + } + ++static gboolean ++user_drop_privileges_to_user (User *user) ++{ ++ if (setresgid (user->gid, user->gid, -1) != 0) { ++ g_warning ("setresgid() failed"); ++ return FALSE; ++ } ++ if (setresuid (user->uid, user->uid, -1) != 0) { ++ g_warning ("setresuid() failed"); ++ return FALSE; ++ } ++ return TRUE; ++} ++ ++static void ++user_regain_privileges () ++{ ++ setresuid (0, 0, -1); ++ setresgid (0, 0, -1); ++} ++ ++static void ++user_get_profile_env (User *user, ++ gchar **language, ++ gchar **lang, ++ gchar **lcmess) ++{ ++ *language = NULL; ++ *lang = NULL; ++ *lcmess = NULL; ++ ++ FILE *fp; ++ gchar *profile_path = g_build_path ("/", user->home_dir, ".profile", NULL); ++ ++ if ((fp = fopen (profile_path, "r"))) { ++ gchar line[50]; ++ gchar **tokens; ++ while ((fgets (line, 50, fp)) != NULL) { ++ if (g_str_has_prefix (line, "export LANGUAGE=\"")) { ++ tokens = g_strsplit (line, "\"", 3); ++ *language = g_strdup (tokens[1]); ++ g_strfreev (tokens); ++ } ++ if (g_str_has_prefix (line, "export LANG=\"")) { ++ tokens = g_strsplit (line, "\"", 3); ++ *lang = g_strdup (tokens[1]); ++ g_strfreev (tokens); ++ } ++ if (g_str_has_prefix (line, "export LC_MESSAGES=\"")) { ++ tokens = g_strsplit (line, "\"", 3); ++ *lcmess = g_strdup (tokens[1]); ++ g_strfreev (tokens); ++ } ++ } ++ fclose (fp); ++ } ++ ++ g_free (profile_path); ++} ++ ++static gchar * ++user_locale_utf8_fix (const gchar *locale) ++{ ++ if (locale == NULL || !g_strrstr (locale, ".utf8")) ++ return g_strdup (locale); ++ ++ gchar **tokens = g_strsplit_set (locale, ".8", 3); ++ gchar *fixed_locale = g_strconcat (tokens[0], ".UTF-8", tokens[2], NULL); ++ g_strfreev (tokens); ++ ++ return fixed_locale; ++} ++ ++static gchar * ++user_language_validate (User *user, ++ const gchar *lang) ++{ ++ gboolean ret; ++ const gchar *program = "/usr/share/language-tools/language-validate"; ++ gchar *command = g_strconcat (program, " ", lang, NULL); ++ gchar *validated_language; ++ GError *error = NULL; ++ ++ if (!user_drop_privileges_to_user (user)) ++ return NULL; ++ ret = g_spawn_command_line_sync (command, &validated_language, NULL, NULL, &error); ++ user_regain_privileges (); ++ ++ g_free (command); ++ if (!ret) { ++ g_warning ("Couldn't get validated language: %s", error->message); ++ g_error_free (error); ++ return NULL; ++ } ++ return g_strchomp (validated_language); ++} ++ ++static gchar * ++user_locale_validate (const gchar *locale, ++ DBusGMethodInvocation *context) ++{ ++ gchar *validated_locale = NULL; ++ gchar *tmp_locale = NULL; ++ gchar *current = g_strdup (setlocale (LC_ALL, NULL)); ++ ++ if (locale == NULL || strlen (locale) < 2) ++ goto out; ++ tmp_locale = g_strdup (locale); ++ g_strchomp (tmp_locale); ++ ++ if (!setlocale (LC_ALL, tmp_locale)) { ++ throw_error (context, ERROR_FAILED, "'%s' is not a valid locale name", tmp_locale); ++ goto out; ++ } ++ validated_locale = user_locale_utf8_fix (tmp_locale); ++ ++out: ++ setlocale (LC_ALL, current); ++ g_free (tmp_locale); ++ g_free (current); ++ ++ return validated_locale; ++} ++ ++static gchar * ++user_get_fallback_value (User *user, ++ const gchar *property) ++{ ++ gchar *fallback_value = NULL; ++ gchar *system_language = NULL; ++ gchar *system_lang = NULL; ++ gchar *system_lctime = NULL; ++ ++ gchar *pam_env_path = g_build_path ("/", user->home_dir, ".pam_environment", NULL); ++ gchar *profile_language = NULL; ++ gchar *profile_lang = NULL; ++ gchar *profile_lcmess = NULL; ++ ++ /* take ~/.profile into account if not migrated */ ++ if (!g_file_test (pam_env_path, G_FILE_TEST_IS_REGULAR)) ++ user_get_profile_env (user, ++ &profile_language, ++ &profile_lang, ++ &profile_lcmess); ++ ++ FILE *fp; ++ if ((fp = fopen ("/etc/default/locale", "r"))) { ++ gchar line[50]; ++ gchar **tokens; ++ while ((fgets (line, 50, fp)) != NULL) { ++ if (g_str_has_prefix (line, "LANGUAGE=\"")) { ++ tokens = g_strsplit (line, "\"", 3); ++ system_language = g_strdup (tokens[1]); ++ g_strfreev (tokens); ++ } ++ if (g_str_has_prefix (line, "LANG=\"")) { ++ tokens = g_strsplit (line, "\"", 3); ++ system_lang = g_strdup (tokens[1]); ++ g_strfreev (tokens); ++ } ++ if (g_str_has_prefix (line, "LC_TIME=\"")) { ++ tokens = g_strsplit (line, "\"", 3); ++ system_lctime = g_strdup (tokens[1]); ++ g_strfreev (tokens); ++ } ++ } ++ fclose (fp); ++ } ++ ++ if (g_strcmp0 (property, "Language") == 0) { ++ gchar *tmp = NULL; ++ if (profile_language) ++ tmp = profile_language; ++ else if (system_language) ++ tmp = system_language; ++ else if (profile_lcmess) ++ tmp = profile_lcmess; ++ else if (profile_lang) ++ tmp = profile_lang; ++ else if (system_lang) ++ tmp = system_lang; ++ fallback_value = user_language_validate (user, tmp); ++ } ++ ++ if (g_strcmp0 (property, "FormatsLocale") == 0) { ++ gchar *tmp = NULL; ++ if (system_lctime) ++ tmp = system_lctime; ++ else if (profile_lang) ++ tmp = profile_lang; ++ else if (system_lang) ++ tmp = system_lang; ++ fallback_value = user_locale_utf8_fix (tmp); ++ } ++ ++ g_free (system_language); ++ g_free (system_lang); ++ g_free (system_lctime); ++ g_free (pam_env_path); ++ g_free (profile_language); ++ g_free (profile_lang); ++ g_free (profile_lcmess); ++ ++ return fallback_value; ++} ++ ++static gchar * ++user_update_environment (User *user, ++ gchar *data, ++ const gchar *script, ++ DBusGMethodInvocation *context) ++ ++/* This function updates ~/.pam_environment by means of the help files in /usr/share/language-tools. */ ++{ ++ gchar *program; ++ gchar *validated_data = NULL; + gint i; -+ gchar *command[] = { LANGTOOLSDIR "/set-language-helper", user->user_name, language, NULL }; -+ const gchar *allowed_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890._+-@:"; ++ const gchar *allowed_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890._+-:/ @"; + gboolean ret; -+ gchar *validated_language; + GError *error = NULL; ++ ++ program = g_build_path ("/", "/usr/share/language-tools", script, NULL); ++ gchar *command[] = { program, user->home_dir, data, NULL }; ++ ++ /* test for odd characters in arguments */ ++ for (i = 1; i <= 2; i++) { ++ if (strlen (command[i]) != strspn (command[i], allowed_chars)) { ++ throw_error (context, ERROR_FAILED, "non-permitted character(s) in argument"); ++ goto out; ++ } ++ } ++ ++ /* set applicable environment variables in ~/.pam_environment */ ++ if (!user_drop_privileges_to_user (user)) ++ goto out; ++ ret = g_spawn_sync ( NULL, ++ command, ++ NULL, ++ G_SPAWN_STDERR_TO_DEV_NULL, ++ NULL, ++ NULL, ++ &validated_data, ++ NULL, ++ NULL, ++ &error ); ++ user_regain_privileges (); ++ if (!ret) { ++ throw_error (context, ERROR_FAILED, "running '%s' failed: %s", program, error->message); ++ g_error_free (error); ++ validated_data = NULL; ++ goto out; ++ } ++ if (validated_data == NULL || strlen (validated_data) <= 1) { ++ throw_error (context, ERROR_FAILED, "running '%s' failed: no output", program); ++ validated_data = NULL; ++ goto out; ++ } ++ ++out: ++ g_free (program); ++ if (validated_data == NULL) ++ return NULL; ++ ++ return g_strchomp (validated_data); ++} ++ ++static gboolean ++user_migration_from_profile (User *user, ++ DBusGMethodInvocation *context, ++ gboolean *is_migrate, ++ gchar **profile_language, ++ gchar **profile_formats) ++{ ++ gchar *pam_env_path; ++ gchar *language = NULL; ++ gchar *lang = NULL; ++ gchar *lcmess = NULL; ++ gchar *tmp; ++ gchar *command = NULL; ++ GError *error = NULL; ++ gboolean ret = FALSE; ++ ++ *is_migrate = FALSE; ++ *profile_language = NULL; ++ *profile_formats = NULL; ++ ++ pam_env_path = g_build_path ("/", user->home_dir, ".pam_environment", NULL); ++ if (g_file_test (pam_env_path, G_FILE_TEST_IS_REGULAR)) ++ goto out; ++ else ++ *is_migrate = TRUE; ++ ++ user_get_profile_env (user, &language, &lang, &lcmess); ++ ++ tmp = NULL; ++ if (language) ++ tmp = language; ++ else if (lcmess) ++ tmp = lcmess; ++ if (tmp) { ++ *profile_language = user_update_environment (user, ++ tmp, ++ "set-language-helper", ++ context); ++ if (*profile_language == NULL) ++ goto out; ++ } ++ ++ tmp = NULL; ++ if (lang && lcmess && g_strcmp0 (lang, lcmess) != 0) ++ tmp = lang; ++ else if (lang && !lcmess) ++ tmp = lang; ++ if (tmp) { ++ *profile_formats = user_update_environment (user, ++ user_locale_validate (tmp, context), ++ "save-to-pam-env", ++ context); ++ if (*profile_formats == NULL) ++ goto out; ++ } ++ ++ const gchar *program = "/usr/share/language-tools/del-profile-env-settings"; ++ command = g_strconcat (program, " '", user->home_dir, "'", NULL); ++ if (!user_drop_privileges_to_user (user)) ++ goto out; ++ gboolean is_success = g_spawn_command_line_sync (command, NULL, NULL, NULL, &error); ++ user_regain_privileges (); ++ if (!is_success) { ++ throw_error (context, ERROR_FAILED, "couldn't edit ~/.profile: %s", error->message); ++ g_error_free (error); ++ goto out; ++ } ++ ++ ret = TRUE; ++ ++out: ++ g_free (pam_env_path); ++ g_free (language); ++ g_free (lang); ++ g_free (lcmess); ++ g_free (command); ++ ++ return ret; ++} ++ + static void + user_change_language_authorized_cb (Daemon *daemon, + User *user, +@@ -1092,12 +1446,94 @@ + gpointer data) + + { +- gchar *language = data; ++ const gchar *fallback_language = user_get_fallback_value (user, "Language"); ++ gboolean is_language_changed = (user->language && g_strcmp0 (user->language, data) != 0) ++ || (!user->language && g_strcmp0 (data, fallback_language) != 0); ++ ++ gboolean is_migrate; ++ gchar *dummy; ++ gchar *profile_formats; ++ ++ gchar *profile_path = g_build_path ("/", user->home_dir, ".profile", NULL); ++ if (!g_file_test (profile_path, G_FILE_TEST_IS_REGULAR)) { ++ ++ /* SetLanguage was probably called from a login greeter, ++ and HOME not mounted and/or not decrypted. ++ Hence don't save anything, or else accountsservice ++ and ~/.pam_environment would become out of sync. */ ++ throw_error (context, ERROR_FAILED, "not access to HOME yet so language not saved"); ++ goto out2; ++ } ++ ++ gboolean is_success = user_migration_from_profile (user, ++ context, ++ &is_migrate, ++ &dummy, ++ &profile_formats); ++ if (is_migrate && !is_success) ++ goto out2; ++ ++ if (is_language_changed || is_migrate) { ++ gchar *language = user_update_environment (user, ++ data, ++ "set-language-helper", ++ context); ++ if (language != NULL) { ++ g_free (user->language); ++ user->language = g_strdup (language); ++ } - if (g_strcmp0 (user->language, language) != 0) { +- if (g_strcmp0 (user->language, language) != 0) { +- g_free (user->language); +- user->language = g_strdup (language); ++ gchar *locale = NULL; ++ ++ if (profile_formats) ++ locale = profile_formats; ++ else if (!user->formats_locale && is_language_changed) { + -+ /* test for odd characters in arguments */ -+ for (i = 1; i <= 2; i++) { -+ if (strlen (command[i]) != strspn (command[i], allowed_chars)) { -+ throw_error (context, ERROR_FAILED, "non-permitted character(s) in argument"); -+ return; ++ /* set the user formats (certain LC_* variables) explicitly ++ in order to prevent surprises when LANG is changed */ ++ FILE *fp; ++ if ((fp = fopen ("/etc/default/locale", "r"))) { ++ gchar line[50]; ++ while ((fgets (line, 50, fp)) != NULL) { ++ if (g_str_has_prefix (line, "LC_TIME=\"")) { ++ gchar **tokens = g_strsplit (line, "\"", 3); ++ locale = g_strdup (tokens[1]); ++ g_strfreev (tokens); ++ break; ++ } ++ } ++ fclose (fp); ++ } ++ if (locale == NULL) { ++ GError *error = NULL; ++ const gchar *program = "/usr/share/language-tools/language2locale"; ++ if (!user_drop_privileges_to_user (user)) ++ goto out1; ++ gchar *command = g_strconcat (program, " ", fallback_language, NULL); ++ gboolean ret = g_spawn_command_line_sync (command, &locale, NULL, NULL, &error); ++ user_regain_privileges (); ++ if (!ret) { ++ throw_error (context, ERROR_FAILED, ++ "language-to-locale conversion failed: %s", error->message); ++ g_error_free (error); ++ locale = NULL; ++ } ++ g_free (command); + } + } + -+ /* set language related environment variables in ~/.profile */ -+ if (setresgid (user->gid, user->gid, -1) != 0) { -+ throw_error (context, ERROR_FAILED, "setresgid() failed, so language not set"); -+ return; -+ } -+ if (setresuid (user->uid, user->uid, -1) != 0) { -+ throw_error (context, ERROR_FAILED, "setresuid() failed, so language not set"); -+ return; -+ } -+ ret = g_spawn_sync ( NULL, -+ command, -+ NULL, -+ G_SPAWN_STDERR_TO_DEV_NULL, -+ NULL, -+ NULL, -+ &validated_language, -+ NULL, -+ NULL, -+ &error ); -+ setresuid (0, 0, -1); -+ setresgid (0, 0, -1); -+ if (!ret) { -+ throw_error (context, ERROR_FAILED, "running '%s' failed: %s", command[0], error->message); -+ g_error_free (error); -+ return; -+ } -+ if (validated_language != NULL && strlen (validated_language) > 1) { -+ language = g_strndup (validated_language, strspn (validated_language, allowed_chars)); -+ g_free (validated_language); -+ } else { -+ throw_error (context, ERROR_FAILED, "running '%s' failed: no output", command[0]); -+ return; ++ if (locale != NULL && strlen (locale) > 0) { ++ gchar *formats_locale = user_update_environment (user, ++ user_locale_validate (locale, context), ++ "save-to-pam-env", ++ context); ++ if (formats_locale != NULL) { ++ g_free (user->formats_locale); ++ user->formats_locale = g_strdup (formats_locale); ++ } + } + ++out1: + save_extra_data (user); + + g_signal_emit (user, signals[CHANGED], 0); +@@ -1105,6 +1541,8 @@ + g_object_notify (G_OBJECT (user), "language"); + } + ++out2: ++ g_free (profile_path); + dbus_g_method_return (context); + } + +@@ -1156,11 +1594,38 @@ + gpointer data) + + { +- gchar *formats_locale = data; ++ gboolean is_migrate; ++ gchar *profile_language; ++ gchar *dummy; ++ ++ gboolean is_success = user_migration_from_profile (user, ++ context, ++ &is_migrate, ++ &profile_language, ++ &dummy); ++ if (is_migrate && !is_success) ++ goto out; + - g_free (user->language); - user->language = g_strdup (language); ++ if (g_strcmp0 (user->formats_locale, data) != 0 || is_migrate) { ++ gchar *formats_locale = user_update_environment (user, ++ user_locale_validate (data, context), ++ "save-to-pam-env", ++ context); ++ if (formats_locale != NULL) { ++ g_free (user->formats_locale); ++ user->formats_locale = g_strdup (formats_locale); ++ } + +- if (g_strcmp0 (user->formats_locale, formats_locale) != 0) { +- g_free (user->formats_locale); +- user->formats_locale = g_strdup (formats_locale); ++ if (profile_language != NULL) { ++ gchar *language = user_update_environment (user, ++ profile_language, ++ "set-language-helper", ++ context); ++ if (language != NULL) { ++ g_free (user->language); ++ user->language = g_strdup (language); ++ } ++ } + + save_extra_data (user); + +@@ -1169,6 +1634,7 @@ + g_object_notify (G_OBJECT (user), "formats_locale"); + } + ++out: + dbus_g_method_return (context); + } diff -Nru accountsservice-0.6.15/debian/patches/0011-add-background-file-support.patch accountsservice-0.6.15/debian/patches/0011-add-background-file-support.patch --- accountsservice-0.6.15/debian/patches/0011-add-background-file-support.patch 2011-12-07 15:49:52.000000000 +0000 +++ accountsservice-0.6.15/debian/patches/0011-add-background-file-support.patch 2012-02-02 10:12:41.000000000 +0000 @@ -2,7 +2,7 @@ =================================================================== --- accountsservice-0.6.15.orig/data/org.freedesktop.Accounts.User.xml 2011-10-17 15:56:32.000000000 -0400 +++ accountsservice-0.6.15/data/org.freedesktop.Accounts.User.xml 2011-12-07 09:56:38.006039122 -0500 -@@ -296,6 +296,41 @@ +@@ -331,6 +331,41 @@ @@ -44,7 +44,7 @@ -@@ -651,6 +686,16 @@ +@@ -696,6 +731,16 @@ @@ -72,16 +72,16 @@ + PROP_BACKGROUND_FILE, PROP_ICON_FILE, PROP_LANGUAGE, - PROP_X_SESSION, -@@ -86,6 +87,7 @@ + PROP_FORMATS_LOCALE, +@@ -87,6 +88,7 @@ char *shell; char *email; char *location; + char *background_file; char *icon_file; char *language; - char *x_session; -@@ -231,6 +233,9 @@ + char *formats_locale; +@@ -233,6 +235,9 @@ case PROP_LOCATION: g_value_set_string (value, user->location); break; @@ -91,7 +91,7 @@ case PROP_ICON_FILE: g_value_set_string (value, user->icon_file); break; -@@ -357,6 +362,13 @@ +@@ -362,6 +367,13 @@ 0, G_PARAM_READABLE)); g_object_class_install_property (gobject_class, @@ -105,7 +105,7 @@ PROP_ICON_FILE, g_param_spec_string ("icon-file", "Icon File", -@@ -452,6 +464,7 @@ +@@ -464,6 +476,7 @@ g_free (user->user_name); g_free (user->real_name); @@ -113,7 +113,7 @@ g_free (user->icon_file); g_free (user->language); g_free (user->object_path); -@@ -802,6 +815,22 @@ +@@ -815,6 +828,22 @@ } /** @@ -136,7 +136,7 @@ * act_user_get_icon_file: * @user: a #ActUser * -@@ -1015,6 +1044,15 @@ +@@ -1044,6 +1073,15 @@ user->login_frequency = new_login_frequency; g_object_notify (G_OBJECT (user), "login-frequency"); } @@ -152,7 +152,7 @@ } else if (strcmp (key, "IconFile") == 0) { const char *new_icon_file; -@@ -1380,6 +1418,37 @@ +@@ -1451,6 +1489,37 @@ g_error_free (error); return; } @@ -202,7 +202,7 @@ PROP_ICON_FILE, PROP_LOCKED, PROP_AUTOMATIC_LOGIN, -@@ -101,6 +102,7 @@ +@@ -102,6 +103,7 @@ gchar *x_session; gchar *location; guint64 login_frequency; @@ -210,7 +210,7 @@ gchar *icon_file; gboolean locked; gboolean automatic_login; -@@ -197,6 +199,9 @@ +@@ -212,6 +214,9 @@ case PROP_LOCATION: g_value_set_string (value, user->location); break; @@ -220,7 +220,7 @@ case PROP_ICON_FILE: if (user->icon_file) g_value_set_string (value, user->icon_file); -@@ -350,6 +355,13 @@ +@@ -372,6 +377,13 @@ 0, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, @@ -234,7 +234,7 @@ PROP_ICON_FILE, g_param_spec_string ("icon-file", "Icon file", -@@ -393,6 +405,7 @@ +@@ -415,6 +427,7 @@ user->account_type = ACCOUNT_TYPE_STANDARD; user->home_dir = NULL; user->shell = NULL; @@ -242,7 +242,7 @@ user->icon_file = NULL; user->email = NULL; user->language = NULL; -@@ -417,6 +430,7 @@ +@@ -440,6 +453,7 @@ g_free (user->real_name); g_free (user->home_dir); g_free (user->shell); @@ -250,7 +250,7 @@ g_free (user->icon_file); g_free (user->email); g_free (user->language); -@@ -659,6 +673,12 @@ +@@ -689,6 +703,12 @@ user->password_hint = s; } @@ -263,7 +263,7 @@ s = g_key_file_get_string (keyfile, "User", "Icon", NULL); if (s != NULL) { g_free (user->icon_file); -@@ -687,6 +707,9 @@ +@@ -720,6 +740,9 @@ if (user->password_hint) g_key_file_set_string (keyfile, "User", "PasswordHint", user->password_hint); @@ -273,7 +273,7 @@ if (user->icon_file) g_key_file_set_string (keyfile, "User", "Icon", user->icon_file); } -@@ -1416,6 +1439,94 @@ +@@ -1906,6 +1929,94 @@ } static void @@ -372,7 +372,7 @@ =================================================================== --- accountsservice-0.6.15.orig/src/user.h 2011-10-17 15:56:32.000000000 -0400 +++ accountsservice-0.6.15/src/user.h 2011-12-07 10:23:06.910055939 -0500 -@@ -92,6 +92,9 @@ +@@ -95,6 +95,9 @@ gboolean user_set_shell (User *user, const gchar *shell, DBusGMethodInvocation *context); diff -Nru accountsservice-0.6.15/debian/patches/series accountsservice-0.6.15/debian/patches/series --- accountsservice-0.6.15/debian/patches/series 2011-12-07 15:48:06.000000000 +0000 +++ accountsservice-0.6.15/debian/patches/series 2012-02-02 09:02:38.000000000 +0000 @@ -1,3 +1,4 @@ +0001-formats-locale-property.patch 0002-create-and-manage-groups-like-on-a-debian-system.patch 0005-gdm_config_file_path.patch 0006-adduser_instead_of_useradd.patch diff -Nru accountsservice-0.6.15/debian/patches/ubuntu.series accountsservice-0.6.15/debian/patches/ubuntu.series --- accountsservice-0.6.15/debian/patches/ubuntu.series 2011-12-07 15:49:52.000000000 +0000 +++ accountsservice-0.6.15/debian/patches/ubuntu.series 2012-02-02 09:02:38.000000000 +0000 @@ -1,3 +1,4 @@ +0001-formats-locale-property.patch 0002-create-and-manage-groups-like-on-a-ubuntu-system.patch 0006-adduser_instead_of_useradd.patch 0007-add-lightdm-support.patch