[gnome-control-center] Move username related utilities to um-utils.[hc]



commit aef79bbf79541ed5b2063b6cf69374bd08173c12
Author: Matthias Clasen <mclasen redhat com>
Date:   Wed May 18 21:20:39 2011 -0400

    Move username related utilities to um-utils.[hc]
    
    This will make it easier to reuse them in gdm-initial-setup.

 panels/user-accounts/um-account-dialog.c |  268 +--------------------------
 panels/user-accounts/um-utils.c          |  302 ++++++++++++++++++++++++++++++
 panels/user-accounts/um-utils.h          |    7 +
 3 files changed, 314 insertions(+), 263 deletions(-)
---
diff --git a/panels/user-accounts/um-account-dialog.c b/panels/user-accounts/um-account-dialog.c
index 73803c0..e5caf49 100644
--- a/panels/user-accounts/um-account-dialog.c
+++ b/panels/user-accounts/um-account-dialog.c
@@ -21,11 +21,6 @@
 
 #include "config.h"
 
-#include <stdlib.h>
-#include <sys/types.h>
-#include <pwd.h>
-#include <utmp.h>
-
 #include <glib.h>
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
@@ -121,85 +116,23 @@ accept_account_dialog (GtkButton       *button,
         gtk_widget_hide (um->dialog);
 }
 
-static gboolean
-is_username_used (const gchar *username)
-{
-        struct passwd *pwent;
-
-        if (username == NULL || username[0] == '\0') {
-                return FALSE;
-        }
-
-        pwent = getpwnam (username);
-
-        return pwent != NULL;
-}
-
 static void
 username_changed (GtkComboBoxText *combo,
                   UmAccountDialog *um)
 {
-        gboolean in_use;
-        gboolean empty;
-        gboolean valid;
-        gboolean toolong;
         const gchar *username;
-        const gchar *c;
         gchar *tip;
         GtkWidget *entry;
 
         username = gtk_combo_box_text_get_active_text (combo);
 
-        if (username == NULL || username[0] == '\0') {
-                empty = TRUE;
-                in_use = FALSE;
-                toolong = FALSE;
-        } else {
-                empty = FALSE;
-                in_use = is_username_used (username);
-                toolong = strlen (username) > MAXNAMELEN;
-        }
-        valid = TRUE;
-
-        if (!in_use && !empty && !toolong) {
-                /* First char must be a letter, and it must only composed
-                 * of ASCII letters, digits, and a '.', '-', '_'
-                 */
-                for (c = username; *c; c++) {
-                        if (! ((*c >= 'a' && *c <= 'z') ||
-                               (*c >= 'A' && *c <= 'Z') ||
-                               (*c >= '0' && *c <= '9') ||
-                               (*c == '_') || (*c == '.') ||
-                               (*c == '-' && c != username)))
-                           valid = FALSE;
-                }
-        }
+        um->valid_username = is_valid_username (username, &tip);
 
-        um->valid_username = !empty && !in_use && !toolong && valid;
         gtk_widget_set_sensitive (um->ok_button, um->valid_name && um->valid_username);
-
         entry = gtk_bin_get_child (GTK_BIN (combo));
 
-        if (!empty && (in_use || toolong || !valid)) {
-                if (in_use) {
-                        tip = g_strdup_printf (_("A user with the username '%s' already exists"),
-                                               username);
-                }
-                else if (toolong) {
-                        tip = g_strdup_printf (_("The username is too long"));
-                }
-                else if (username[0] == '-') {
-                        tip = g_strdup (_("The username cannot start with a '-'"));
-                }
-                else {
-                        tip = g_strdup (_("The username must consist of:\n"
-                                          " \xe2\x9e\xa3 letters from the English alphabet\n"
-                                          " \xe2\x9e\xa3 digits\n"
-                                          " \xe2\x9e\xa3 any of the characters '.', '-' and '_'"));
-                }
-
+        if (tip) {
                 set_entry_validation_error (GTK_ENTRY (entry), tip);
-
                 g_free (tip);
         }
         else {
@@ -214,27 +147,16 @@ name_changed (GtkEntry        *name_entry,
 {
         GtkWidget *entry;
         GtkTreeModel *model;
-        gboolean in_use;
         const char *name;
-        char *lc_name, *ascii_name, *stripped_name;
-        char **words1;
-        char **words2 = NULL;
-        char **w1, **w2;
-        char *c;
-        char *unicode_fallback = "?";
-        GString *first_word, *last_word;
-        GString *item0, *item1, *item2, *item3, *item4;
-        int len;
-        int nwords1, nwords2, i;
-        GHashTable *items;
 
         entry = gtk_bin_get_child (GTK_BIN (um->username_combo));
+
         model = gtk_combo_box_get_model (GTK_COMBO_BOX (um->username_combo));
         gtk_list_store_clear (GTK_LIST_STORE (model));
 
         name = gtk_entry_get_text (GTK_ENTRY (name_entry));
 
-        um->valid_name = (strlen (name) > 0);
+        um->valid_name = is_valid_name (name);
         gtk_widget_set_sensitive (um->ok_button, um->valid_name && um->valid_username);
 
         if (!um->valid_name) {
@@ -242,189 +164,9 @@ name_changed (GtkEntry        *name_entry,
                 return;
         }
 
-        ascii_name = g_convert_with_fallback (name, -1, "ASCII//TRANSLIT", "UTF-8",
-                                              unicode_fallback, NULL, NULL, NULL);
-
-        lc_name = g_ascii_strdown (ascii_name, -1);
-
-        /* remove all non ASCII alphanumeric chars from the name,
-         * apart from the few allowed symbols
-         */
-        stripped_name = g_strnfill (strlen (lc_name) + 1, '\0');
-        i = 0;
-        for (c = lc_name; *c; c++) {
-                if (!(g_ascii_isdigit (*c) || g_ascii_islower (*c) ||
-                    *c == ' ' || *c == '-' || *c == '.' || *c == '_' ||
-                    /* used to track invalid words, removed below */
-                    *c == '?') )
-                        continue;
-
-                    stripped_name[i] = *c;
-                    i++;
-        }
-
-        if (strlen (stripped_name) == 0) {
-                g_free (ascii_name);
-                g_free (lc_name);
-                g_free (stripped_name);
-                return;
-        }
-
-        /* we split name on spaces, and then on dashes, so that we can treat
-         * words linked with dashes the same way, i.e. both fully shown, or
-         * both abbreviated
-         */
-        words1 = g_strsplit_set (stripped_name, " ", -1);
-        len = g_strv_length (words1);
-
-        /* The default item is a concatenation of all words without ? */
-        item0 = g_string_sized_new (strlen (stripped_name));
-
-        g_free (ascii_name);
-        g_free (lc_name);
-        g_free (stripped_name);
-
-        /* Concatenate the whole first word with the first letter of each
-         * word (item1), and the last word with the first letter of each
-         * word (item2). item3 and item4 are symmetrical respectively to
-         * item1 and item2.
-         *
-         * Constant 5 is the max reasonable number of words we may get when
-         * splitting on dashes, since we can't guess it at this point,
-         * and reallocating would be too bad.
-         */
-        item1 = g_string_sized_new (strlen (words1[0]) + len - 1 + 5);
-        item3 = g_string_sized_new (strlen (words1[0]) + len - 1 + 5);
-
-        item2 = g_string_sized_new (strlen (words1[len - 1]) + len - 1 + 5);
-        item4 = g_string_sized_new (strlen (words1[len - 1]) + len - 1 + 5);
-
-        /* again, guess at the max size of names */
-        first_word = g_string_sized_new (20);
-        last_word = g_string_sized_new (20);
-
-        nwords1 = 0;
-        nwords2 = 0;
-        for (w1 = words1; *w1; w1++) {
-                if (strlen (*w1) == 0)
-                        continue;
-
-                /* skip words with string '?', most likely resulting
-                 * from failed transliteration to ASCII
-                 */
-                if (strstr (*w1, unicode_fallback) != NULL)
-                        continue;
-
-                nwords1++; /* count real words, excluding empty string */
-
-                item0 = g_string_append (item0, *w1);
-
-                words2 = g_strsplit_set (*w1, "-", -1);
-                /* reset last word if a new non-empty word has been found */
-                if (strlen (*words2) > 0)
-                        last_word = g_string_set_size (last_word, 0);
-
-                for (w2 = words2; *w2; w2++) {
-                        if (strlen (*w2) == 0)
-                                continue;
-
-                        nwords2++;
-
-                        /* part of the first "toplevel" real word */
-                        if (nwords1 == 1) {
-                                item1 = g_string_append (item1, *w2);
-                                first_word = g_string_append (first_word, *w2);
-                        }
-                        else {
-                                item1 = g_string_append_unichar (item1,
-                                                                 g_utf8_get_char (*w2));
-                                item3 = g_string_append_unichar (item3,
-                                                                 g_utf8_get_char (*w2));
-                        }
-
-                        /* not part of the last "toplevel" word */
-                        if (w1 != words1 + len - 1) {
-                                item2 = g_string_append_unichar (item2,
-                                                                 g_utf8_get_char (*w2));
-                                item4 = g_string_append_unichar (item4,
-                                                                 g_utf8_get_char (*w2));
-                        }
-
-                        /* always save current word so that we have it if last one reveals empty */
-                        last_word = g_string_append (last_word, *w2);
-                }
-
-                g_strfreev (words2);
-        }
-        item2 = g_string_append (item2, last_word->str);
-        item3 = g_string_append (item3, first_word->str);
-        item4 = g_string_prepend (item4, last_word->str);
-
-        items = g_hash_table_new (g_str_hash, g_str_equal);
-
-        in_use = is_username_used (item0->str);
-        if (!in_use && !g_ascii_isdigit (item0->str[0])) {
-                gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (um->username_combo), item0->str);
-                g_hash_table_insert (items, item0->str, item0->str);
-        }
-
-        in_use = is_username_used (item1->str);
-        if (nwords2 > 0 && !in_use && !g_ascii_isdigit (item1->str[0])) {
-                gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (um->username_combo), item1->str);
-                g_hash_table_insert (items, item1->str, item1->str);
-        }
-
-        /* if there's only one word, would be the same as item1 */
-        if (nwords2 > 1) {
-                /* add other items */
-                in_use = is_username_used (item2->str);
-                if (!in_use && !g_ascii_isdigit (item2->str[0]) &&
-                    !g_hash_table_lookup (items, item2->str)) {
-                        gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (um->username_combo), item2->str);
-                        g_hash_table_insert (items, item2->str, item2->str);
-                }
-
-                in_use = is_username_used (item3->str);
-                if (!in_use && !g_ascii_isdigit (item3->str[0]) &&
-                    !g_hash_table_lookup (items, item3->str)) {
-                        gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (um->username_combo), item3->str);
-                        g_hash_table_insert (items, item3->str, item3->str);
-                }
-
-                in_use = is_username_used (item4->str);
-                if (!in_use && !g_ascii_isdigit (item4->str[0]) &&
-                    !g_hash_table_lookup (items, item4->str)) {
-                        gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (um->username_combo), item4->str);
-                        g_hash_table_insert (items, item4->str, item4->str);
-                }
-
-                /* add the last word */
-                in_use = is_username_used (last_word->str);
-                if (!in_use && !g_ascii_isdigit (last_word->str[0]) &&
-                    !g_hash_table_lookup (items, last_word->str)) {
-                        gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (um->username_combo), last_word->str);
-                        g_hash_table_insert (items, last_word->str, last_word->str);
-                }
-
-                /* ...and the first one */
-                in_use = is_username_used (first_word->str);
-                if (!in_use && !g_ascii_isdigit (first_word->str[0]) &&
-                    !g_hash_table_lookup (items, first_word->str)) {
-                        gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (um->username_combo), first_word->str);
-                        g_hash_table_insert (items, first_word->str, first_word->str);
-                }
-        }
+        generate_username_choices (name, GTK_LIST_STORE (model));
 
         gtk_combo_box_set_active (GTK_COMBO_BOX (um->username_combo), 0);
-        g_hash_table_destroy (items);
-        g_strfreev (words1);
-        g_string_free (first_word, TRUE);
-        g_string_free (last_word, TRUE);
-        g_string_free (item0, TRUE);
-        g_string_free (item1, TRUE);
-        g_string_free (item2, TRUE);
-        g_string_free (item3, TRUE);
-        g_string_free (item4, TRUE);
 }
 
 UmAccountDialog *
diff --git a/panels/user-accounts/um-utils.c b/panels/user-accounts/um-utils.c
index 4e4aa51..b874ff4 100644
--- a/panels/user-accounts/um-utils.c
+++ b/panels/user-accounts/um-utils.c
@@ -22,6 +22,10 @@
 #include "config.h"
 
 #include <math.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <utmp.h>
 
 #include <glib.h>
 #include <glib/gi18n.h>
@@ -440,3 +444,301 @@ down_arrow (GtkStyleContext *context,
         cairo_restore (cr);
 }
 
+
+#define MAXNAMELEN  (UT_NAMESIZE - 1)
+
+static gboolean
+is_username_used (const gchar *username)
+{
+        struct passwd *pwent;
+
+        if (username == NULL || username[0] == '\0') {
+                return FALSE;
+        }
+
+        pwent = getpwnam (username);
+
+        return pwent != NULL;
+}
+
+gboolean
+is_valid_name (const gchar *name)
+{
+        gboolean valid;
+
+        valid = (strlen (name) > 0);
+
+        return valid;
+}
+
+gboolean
+is_valid_username (const gchar *username, gchar **tip)
+{
+        gboolean empty;
+        gboolean in_use;
+        gboolean too_long;
+        gboolean valid;
+        const gchar *c;
+
+        if (username == NULL || username[0] == '\0') {
+                empty = TRUE;
+                in_use = FALSE;
+                too_long = FALSE;
+        } else {
+                empty = FALSE;
+                in_use = is_username_used (username);
+                too_long = strlen (username) > MAXNAMELEN;
+        }
+        valid = TRUE;
+
+        if (!in_use && !empty && !too_long) {
+                /* First char must be a letter, and it must only composed
+                 * of ASCII letters, digits, and a '.', '-', '_'
+                 */
+                for (c = username; *c; c++) {
+                        if (! ((*c >= 'a' && *c <= 'z') ||
+                               (*c >= 'A' && *c <= 'Z') ||
+                               (*c >= '0' && *c <= '9') ||
+                               (*c == '_') || (*c == '.') ||
+                               (*c == '-' && c != username)))
+                           valid = FALSE;
+                }
+        }
+
+        valid = !empty && !in_use && !too_long && valid;
+
+        if (!empty && (in_use || too_long || !valid)) {
+                if (in_use) {
+                        *tip = g_strdup_printf (_("A user with the username '%s' already exists"),
+                                               username);
+                }
+                else if (too_long) {
+                        *tip = g_strdup_printf (_("The username is too long"));
+                }
+                else if (username[0] == '-') {
+                        *tip = g_strdup (_("The username cannot start with a '-'"));
+                }
+                else {
+                        *tip = g_strdup (_("The username must consist of:\n"
+                                          " \xe2\x9e\xa3 letters from the English alphabet\n"
+                                          " \xe2\x9e\xa3 digits\n"
+                                          " \xe2\x9e\xa3 any of the characters '.', '-' and '_'"));
+                }
+        }
+        else {
+                *tip = NULL;
+        }
+
+        return valid;
+}
+
+void
+generate_username_choices (const gchar  *name,
+                           GtkListStore *store)
+{
+        gboolean in_use;
+        char *lc_name, *ascii_name, *stripped_name;
+        char **words1;
+        char **words2 = NULL;
+        char **w1, **w2;
+        char *c;
+        char *unicode_fallback = "?";
+        GString *first_word, *last_word;
+        GString *item0, *item1, *item2, *item3, *item4;
+        int len;
+        int nwords1, nwords2, i;
+        GHashTable *items;
+        GtkTreeIter iter;
+
+        gtk_list_store_clear (store);
+
+        ascii_name = g_convert_with_fallback (name, -1, "ASCII//TRANSLIT", "UTF-8",
+                                              unicode_fallback, NULL, NULL, NULL);
+
+        lc_name = g_ascii_strdown (ascii_name, -1);
+
+        /* remove all non ASCII alphanumeric chars from the name,
+         * apart from the few allowed symbols
+         */
+        stripped_name = g_strnfill (strlen (lc_name) + 1, '\0');
+        i = 0;
+        for (c = lc_name; *c; c++) {
+                if (!(g_ascii_isdigit (*c) || g_ascii_islower (*c) ||
+                    *c == ' ' || *c == '-' || *c == '.' || *c == '_' ||
+                    /* used to track invalid words, removed below */
+                    *c == '?') )
+                        continue;
+
+                    stripped_name[i] = *c;
+                    i++;
+        }
+
+        if (strlen (stripped_name) == 0) {
+                g_free (ascii_name);
+                g_free (lc_name);
+                g_free (stripped_name);
+                return;
+        }
+
+        /* we split name on spaces, and then on dashes, so that we can treat
+         * words linked with dashes the same way, i.e. both fully shown, or
+         * both abbreviated
+         */
+        words1 = g_strsplit_set (stripped_name, " ", -1);
+        len = g_strv_length (words1);
+
+        /* The default item is a concatenation of all words without ? */
+        item0 = g_string_sized_new (strlen (stripped_name));
+
+        g_free (ascii_name);
+        g_free (lc_name);
+        g_free (stripped_name);
+
+        /* Concatenate the whole first word with the first letter of each
+         * word (item1), and the last word with the first letter of each
+         * word (item2). item3 and item4 are symmetrical respectively to
+         * item1 and item2.
+         *
+         * Constant 5 is the max reasonable number of words we may get when
+         * splitting on dashes, since we can't guess it at this point,
+         * and reallocating would be too bad.
+         */
+        item1 = g_string_sized_new (strlen (words1[0]) + len - 1 + 5);
+        item3 = g_string_sized_new (strlen (words1[0]) + len - 1 + 5);
+
+        item2 = g_string_sized_new (strlen (words1[len - 1]) + len - 1 + 5);
+        item4 = g_string_sized_new (strlen (words1[len - 1]) + len - 1 + 5);
+
+        /* again, guess at the max size of names */
+        first_word = g_string_sized_new (20);
+        last_word = g_string_sized_new (20);
+
+        nwords1 = 0;
+        nwords2 = 0;
+        for (w1 = words1; *w1; w1++) {
+                if (strlen (*w1) == 0)
+                        continue;
+
+                /* skip words with string '?', most likely resulting
+                 * from failed transliteration to ASCII
+                 */
+                if (strstr (*w1, unicode_fallback) != NULL)
+                        continue;
+
+                nwords1++; /* count real words, excluding empty string */
+
+                item0 = g_string_append (item0, *w1);
+
+                words2 = g_strsplit_set (*w1, "-", -1);
+                /* reset last word if a new non-empty word has been found */
+                if (strlen (*words2) > 0)
+                        last_word = g_string_set_size (last_word, 0);
+
+                for (w2 = words2; *w2; w2++) {
+                        if (strlen (*w2) == 0)
+                                continue;
+
+                        nwords2++;
+
+                        /* part of the first "toplevel" real word */
+                        if (nwords1 == 1) {
+                                item1 = g_string_append (item1, *w2);
+                                first_word = g_string_append (first_word, *w2);
+                        }
+                        else {
+                                item1 = g_string_append_unichar (item1,
+                                                                 g_utf8_get_char (*w2));
+                                item3 = g_string_append_unichar (item3,
+                                                                 g_utf8_get_char (*w2));
+                        }
+
+                        /* not part of the last "toplevel" word */
+                        if (w1 != words1 + len - 1) {
+                                item2 = g_string_append_unichar (item2,
+                                                                 g_utf8_get_char (*w2));
+                                item4 = g_string_append_unichar (item4,
+                                                                 g_utf8_get_char (*w2));
+                        }
+
+                        /* always save current word so that we have it if last one reveals empty */
+                        last_word = g_string_append (last_word, *w2);
+                }
+
+                g_strfreev (words2);
+        }
+        item2 = g_string_append (item2, last_word->str);
+        item3 = g_string_append (item3, first_word->str);
+        item4 = g_string_prepend (item4, last_word->str);
+
+        items = g_hash_table_new (g_str_hash, g_str_equal);
+
+        in_use = is_username_used (item0->str);
+        if (!in_use && !g_ascii_isdigit (item0->str[0])) {
+                gtk_list_store_append (store, &iter);
+                gtk_list_store_set (store, &iter, 0, item0->str, -1);
+                g_hash_table_insert (items, item0->str, item0->str);
+        }
+
+        in_use = is_username_used (item1->str);
+        if (nwords2 > 0 && !in_use && !g_ascii_isdigit (item1->str[0])) {
+                gtk_list_store_append (store, &iter);
+                gtk_list_store_set (store, &iter, 0, item1->str, -1);
+                g_hash_table_insert (items, item1->str, item1->str);
+        }
+
+        /* if there's only one word, would be the same as item1 */
+        if (nwords2 > 1) {
+                /* add other items */
+                in_use = is_username_used (item2->str);
+                if (!in_use && !g_ascii_isdigit (item2->str[0]) &&
+                    !g_hash_table_lookup (items, item2->str)) {
+                        gtk_list_store_append (store, &iter);
+                        gtk_list_store_set (store, &iter, 0, item2->str, -1);
+                        g_hash_table_insert (items, item2->str, item2->str);
+                }
+
+                in_use = is_username_used (item3->str);
+                if (!in_use && !g_ascii_isdigit (item3->str[0]) &&
+                    !g_hash_table_lookup (items, item3->str)) {
+                        gtk_list_store_append (store, &iter);
+                        gtk_list_store_set (store, &iter, 0, item3->str, -1);
+                        g_hash_table_insert (items, item3->str, item3->str);
+                }
+
+                in_use = is_username_used (item4->str);
+                if (!in_use && !g_ascii_isdigit (item4->str[0]) &&
+                    !g_hash_table_lookup (items, item4->str)) {
+                        gtk_list_store_append (store, &iter);
+                        gtk_list_store_set (store, &iter, 0, item4->str, -1);
+                        g_hash_table_insert (items, item4->str, item4->str);
+                }
+
+                /* add the last word */
+                in_use = is_username_used (last_word->str);
+                if (!in_use && !g_ascii_isdigit (last_word->str[0]) &&
+                    !g_hash_table_lookup (items, last_word->str)) {
+                        gtk_list_store_append (store, &iter);
+                        gtk_list_store_set (store, &iter, 0, last_word->str, -1);
+                        g_hash_table_insert (items, last_word->str, last_word->str);
+                }
+
+                /* ...and the first one */
+                in_use = is_username_used (first_word->str);
+                if (!in_use && !g_ascii_isdigit (first_word->str[0]) &&
+                    !g_hash_table_lookup (items, first_word->str)) {
+                        gtk_list_store_append (store, &iter);
+                        gtk_list_store_set (store, &iter, 0, first_word->str, -1);
+                        g_hash_table_insert (items, first_word->str, first_word->str);
+                }
+        }
+
+        g_hash_table_destroy (items);
+        g_strfreev (words1);
+        g_string_free (first_word, TRUE);
+        g_string_free (last_word, TRUE);
+        g_string_free (item0, TRUE);
+        g_string_free (item1, TRUE);
+        g_string_free (item2, TRUE);
+        g_string_free (item3, TRUE);
+        g_string_free (item4, TRUE);
+}
diff --git a/panels/user-accounts/um-utils.h b/panels/user-accounts/um-utils.h
index d1c565d..54f57aa 100644
--- a/panels/user-accounts/um-utils.h
+++ b/panels/user-accounts/um-utils.h
@@ -58,6 +58,13 @@ void     down_arrow                       (GtkStyleContext *context,
                                            gint             width,
                                            gint             height);
 
+gboolean is_valid_name                    (const gchar     *name);
+gboolean is_valid_username                (const gchar     *name,
+                                           gchar          **tip);
+
+void     generate_username_choices        (const gchar     *name,
+                                           GtkListStore    *store);
+
 G_END_DECLS
 
 #endif



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]