[gnome-control-center] Move username related utilities to um-utils.[hc]
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-control-center] Move username related utilities to um-utils.[hc]
- Date: Thu, 19 May 2011 01:21:28 +0000 (UTC)
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]