[empathy] Check format of some user names (#629261)



commit 054e1f0bf407756fa8380513d3b1d24930503cce
Author: Vitaly Minko <vitaly minko gmail com>
Date:   Thu Oct 14 11:55:25 2010 +0200

    Check format of some user names (#629261)

 libempathy-gtk/empathy-account-widget.c |  113 +++++++++++++++++++++++++++++++
 libempathy/empathy-account-settings.c   |  106 +++++++++++++++++++++++------
 libempathy/empathy-account-settings.h   |    8 ++
 3 files changed, 205 insertions(+), 22 deletions(-)
---
diff --git a/libempathy-gtk/empathy-account-widget.c b/libempathy-gtk/empathy-account-widget.c
index a326663..f595079 100644
--- a/libempathy-gtk/empathy-account-widget.c
+++ b/libempathy-gtk/empathy-account-widget.c
@@ -116,6 +116,49 @@ static guint signals[LAST_SIGNAL] = { 0 };
 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyAccountWidget)
 #define CHANGED_TIMEOUT 300
 
+#define DIGIT             "0-9"
+#define DIGITS            "(["DIGIT"]+)"
+#define ALPHA             "a-zA-Z"
+#define ALPHAS            "(["ALPHA"]+)"
+#define ALPHADIGIT        ALPHA DIGIT
+#define ALPHADIGITS       "(["ALPHADIGIT"]+)"
+#define ALPHADIGITDASH    ALPHA DIGIT "-"
+#define ALPHADIGITDASHS   "(["ALPHADIGITDASH"]*)"
+
+#define HOSTNUMBER        "("DIGITS"\\."DIGITS"\\."DIGITS"\\."DIGITS")"
+#define TOPLABEL          ALPHAS"|(["ALPHA"]" ALPHADIGITDASHS "["ALPHADIGIT"])"
+#define DOMAINLABEL       ALPHADIGITS"|(["ALPHADIGIT"]" ALPHADIGITDASHS \
+                                       "["ALPHADIGIT"])"
+#define HOSTNAME          "((" DOMAINLABEL "\\.)+" TOPLABEL ")"
+/* Based on http://www.ietf.org/rfc/rfc1738.txt (section 5) */
+#define HOST              "("HOSTNAME "|" HOSTNUMBER")"
+/* Based on http://www.ietf.org/rfc/rfc0822.txt (appendix D) */
+#define EMAIL_LOCALPART   "([^\\(\\)<>@,;:\\\\\"\\[\\]\\s]+)"
+
+/* UIN is digital according to the unofficial specification:
+ * http://iserverd.khstu.ru/docum_ext/icqv5.html#CTS
+ * 5 digits minimun according to http://en.wikipedia.org/wiki/ICQ#UIN */
+#define ICQ_USER_NAME     "(["DIGIT"]{5,})"
+/* Based on http://www.ietf.org/rfc/rfc2812.txt (section 2.3.1) */
+#define IRC_SPECIAL       "_\\[\\]{}\\\\|`^"
+#define IRC_USER_NAME     "(["ALPHA IRC_SPECIAL"]["ALPHADIGITDASH IRC_SPECIAL"]*)"
+/* Based on http://www.ietf.org/rfc/rfc4622.txt (section 2.2)
+ * We just exclude invalid characters to avoid ucschars and other redundant
+ * complexity */
+#define JABBER_USER_NAME  "([^@:'\"<>&\\s]+)"
+/* ID is an email according to the unofficial specification:
+ * http://www.hypothetic.org/docs/msn/general/names.php */
+#define MSN_USER_NAME     EMAIL_LOCALPART
+/* Based on the official help:
+ * http://help.yahoo.com/l/us/yahoo/edit/registration/edit-01.html */
+#define YAHOO_USER_NAME   "(["ALPHA"]["ALPHADIGIT"_\\.]{3,31})"
+
+#define ACCOUNT_REGEX_ICQ      "^"ICQ_USER_NAME"$"
+#define ACCOUNT_REGEX_IRC      "^"IRC_USER_NAME"$"
+#define ACCOUNT_REGEX_JABBER   "^"JABBER_USER_NAME"@"HOST"$"
+#define ACCOUNT_REGEX_MSN      "^"MSN_USER_NAME"@"HOST"$"
+#define ACCOUNT_REGEX_YAHOO    "^"YAHOO_USER_NAME"$"
+
 static void
 account_widget_set_control_buttons_sensitivity (EmpathyAccountWidget *self,
     gboolean sensitive)
@@ -136,6 +179,35 @@ account_widget_set_control_buttons_sensitivity (EmpathyAccountWidget *self,
 }
 
 static void
+account_widget_set_entry_highlighting (GtkEntry *entry, gboolean highlight)
+{
+  GdkColor color;
+  GtkStyle *style;
+
+  g_return_if_fail (GTK_IS_ENTRY (entry));
+
+  style = gtk_widget_get_style (GTK_WIDGET (entry));
+
+  if (highlight)
+    {
+      color = style->bg[GTK_STATE_SELECTED];
+
+      /* Here we take the current theme colour and add it to
+       * the colour for white and average the two. This
+       * gives a colour which is inline with the theme but
+       * slightly whiter.
+       */
+      color.red = (color.red + (style->white).red) / 2;
+      color.green = (color.green + (style->white).green) / 2;
+      color.blue = (color.blue + (style->white).blue) / 2;
+
+      gtk_widget_modify_base (GTK_WIDGET (entry), GTK_STATE_NORMAL, &color);
+    }
+  else
+    gtk_widget_modify_base (GTK_WIDGET (entry), GTK_STATE_NORMAL, NULL);
+}
+
+static void
 account_widget_handle_control_buttons_sensitivity (EmpathyAccountWidget *self)
 {
   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
@@ -156,9 +228,13 @@ account_widget_entry_changed_common (EmpathyAccountWidget *self,
   const gchar *str;
   const gchar *param_name;
   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
+  gboolean prev_status;
+  gboolean curr_status;
 
   str = gtk_entry_get_text (entry);
   param_name = g_object_get_data (G_OBJECT (entry), "param_name");
+  prev_status = empathy_account_settings_parameter_is_valid (priv->settings,
+                                                             param_name);
 
   if (EMP_STR_EMPTY (str))
     {
@@ -180,6 +256,11 @@ account_widget_entry_changed_common (EmpathyAccountWidget *self,
           tp_strdiff (param_name, "password") ? str : "***");
       empathy_account_settings_set_string (priv->settings, param_name, str);
     }
+
+  curr_status = empathy_account_settings_parameter_is_valid (priv->settings,
+                                                             param_name);
+  if (curr_status != prev_status)
+    account_widget_set_entry_highlighting (entry, !curr_status);
 }
 
 static void
@@ -191,6 +272,21 @@ account_widget_entry_changed_cb (GtkEditable *entry,
 }
 
 static void
+account_widget_entry_map_cb (GtkEntry *entry,
+    EmpathyAccountWidget *self)
+{
+  EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
+  const gchar *param_name;
+  gboolean is_valid;
+
+  /* need to initialize input highlighting */
+  param_name = g_object_get_data (G_OBJECT (entry), "param_name");
+  is_valid = empathy_account_settings_parameter_is_valid (priv->settings,
+                                                          param_name);
+  account_widget_set_entry_highlighting (entry, !is_valid);
+}
+
+static void
 account_widget_int_changed_cb (GtkWidget *widget,
     EmpathyAccountWidget *self)
 {
@@ -451,6 +547,8 @@ empathy_account_widget_setup_widget (EmpathyAccountWidget *self,
 
       g_signal_connect (widget, "changed",
           G_CALLBACK (account_widget_entry_changed_cb), self);
+      g_signal_connect (widget, "map",
+          G_CALLBACK (account_widget_entry_map_cb), self);
     }
   else if (GTK_IS_TOGGLE_BUTTON (widget))
     {
@@ -948,6 +1046,9 @@ account_widget_build_irc (EmpathyAccountWidget *self,
 {
   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
 
+  empathy_account_settings_set_regex (priv->settings, "account",
+      ACCOUNT_REGEX_IRC);
+
   if (priv->simple)
     {
       priv->irc_network_chooser = empathy_account_widget_irc_build_simple (self,
@@ -975,6 +1076,9 @@ account_widget_build_msn (EmpathyAccountWidget *self,
 {
   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
 
+  empathy_account_settings_set_regex (priv->settings, "account",
+      ACCOUNT_REGEX_MSN);
+
   if (priv->simple)
     {
       self->ui_details->gui = empathy_builder_get_file (filename,
@@ -1104,6 +1208,9 @@ account_widget_build_jabber (EmpathyAccountWidget *self,
   is_gtalk = account_widget_is_gtalk (self);
   is_facebook = account_widget_is_facebook (self);
 
+  empathy_account_settings_set_regex (priv->settings, "account",
+      ACCOUNT_REGEX_JABBER);
+
   if (priv->simple && !is_gtalk && !is_facebook)
     {
       /* Simple widget for XMPP */
@@ -1228,6 +1335,9 @@ account_widget_build_icq (EmpathyAccountWidget *self,
   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
   GtkWidget *spinbutton_port;
 
+  empathy_account_settings_set_regex (priv->settings, "account",
+      ACCOUNT_REGEX_ICQ);
+
   if (priv->simple)
     {
       self->ui_details->gui = empathy_builder_get_file (filename,
@@ -1306,6 +1416,9 @@ account_widget_build_yahoo (EmpathyAccountWidget *self,
 {
   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
 
+  empathy_account_settings_set_regex (priv->settings, "account",
+      ACCOUNT_REGEX_YAHOO);
+
   if (priv->simple)
     {
       self->ui_details->gui = empathy_builder_get_file (filename,
diff --git a/libempathy/empathy-account-settings.c b/libempathy/empathy-account-settings.c
index 29ff3f1..1e63aed 100644
--- a/libempathy/empathy-account-settings.c
+++ b/libempathy/empathy-account-settings.c
@@ -69,9 +69,15 @@ struct _EmpathyAccountSettingsPriv
   gboolean display_name_overridden;
   gboolean ready;
 
+  /* Parameter name (gchar *) -> parameter value (GValue) */
   GHashTable *parameters;
+  /* Keys are parameter names from the hash above (gchar *).
+   * Values are regular expresions that should match corresponding parameter
+   * values (GRegex *). Possible regexp patterns are defined in
+   * empathy-account-widget.c */
+  GHashTable *param_regexps;
   GArray *unset_parameters;
-  GArray *required_params;
+  GList *required_params;
 
   gulong managers_ready_id;
 
@@ -93,7 +99,12 @@ empathy_account_settings_init (EmpathyAccountSettings *obj)
   priv->parameters = g_hash_table_new_full (g_str_hash, g_str_equal,
     g_free, (GDestroyNotify) tp_g_value_slice_free);
 
+  priv->param_regexps = g_hash_table_new_full (g_str_hash, g_str_equal,
+    g_free, (GDestroyNotify) g_regex_unref);
+
   priv->unset_parameters = g_array_new (TRUE, FALSE, sizeof (gchar *));
+
+  priv->required_params = NULL;
 }
 
 static void empathy_account_settings_dispose (GObject *object);
@@ -343,6 +354,7 @@ empathy_account_settings_finalize (GObject *object)
 {
   EmpathyAccountSettings *self = EMPATHY_ACCOUNT_SETTINGS (object);
   EmpathyAccountSettingsPriv *priv = GET_PRIV (self);
+  GList *l;
 
   /* free any data held directly by the object here */
   g_free (priv->cm_name);
@@ -352,9 +364,14 @@ empathy_account_settings_finalize (GObject *object)
   g_free (priv->icon_name);
 
   if (priv->required_params != NULL)
-    g_array_free (priv->required_params, TRUE);
+    {
+      for (l = priv->required_params; l; l = l->next)
+        g_free (l->data);
+      g_list_free (priv->required_params);
+    }
 
   g_hash_table_destroy (priv->parameters);
+  g_hash_table_destroy (priv->param_regexps);
 
   empathy_account_settings_free_unset_parameters (self);
   g_array_free (priv->unset_parameters, TRUE);
@@ -407,16 +424,13 @@ empathy_account_settings_check_readyness (EmpathyAccountSettings *self)
   if (priv->required_params == NULL)
     {
       TpConnectionManagerParam *cur;
-      char *val;
-
-      priv->required_params = g_array_new (TRUE, FALSE, sizeof (gchar *));
 
       for (cur = tp_protocol->params; cur->name != NULL; cur++)
         {
           if (tp_connection_manager_param_is_required (cur))
             {
-              val = g_strdup (cur->name);
-              g_array_append_val (priv->required_params, val);
+              priv->required_params = g_list_append (priv->required_params,
+                                                     g_strdup (cur->name));
             }
         }
     }
@@ -1339,42 +1353,90 @@ empathy_account_settings_has_account (EmpathyAccountSettings *settings,
   return (!tp_strdiff (account_path, priv_account_path));
 }
 
+void
+empathy_account_settings_set_regex (EmpathyAccountSettings *settings,
+    const gchar *param,
+    const gchar *pattern)
+{
+  EmpathyAccountSettingsPriv *priv = GET_PRIV (settings);
+  GRegex *regex;
+
+  regex = g_regex_new (pattern, 0, 0, NULL);
+  g_hash_table_insert (priv->param_regexps, g_strdup (param), regex);
+}
+
 gboolean
-empathy_account_settings_is_valid (EmpathyAccountSettings *settings)
+empathy_account_settings_parameter_is_valid (
+    EmpathyAccountSettings *settings,
+    const gchar *param)
 {
   EmpathyAccountSettingsPriv *priv;
-  guint idx;
-  gchar *current;
-  gboolean missed = FALSE;
+  const GRegex *regex;
+  const gchar *value;
 
   g_return_val_if_fail (EMPATHY_IS_ACCOUNT_SETTINGS (settings), FALSE);
 
   priv = GET_PRIV (settings);
 
-  for (idx = 0; idx < priv->required_params->len; idx++)
+  if (g_list_find_custom (priv->required_params, param, (GCompareFunc) strcmp))
     {
-      current = g_array_index (priv->required_params, gchar *, idx);
-
       /* first, look if it's set in our own parameters */
-      if (tp_asv_lookup (priv->parameters, current))
-        continue;
+      if (tp_asv_lookup (priv->parameters, param))
+        goto test_regex;
 
       /* if we did not unset the parameter, look if it's in the account */
       if (priv->account != NULL &&
-          !empathy_account_settings_is_unset (settings, current))
+          !empathy_account_settings_is_unset (settings, param))
         {
           const GHashTable *account_params;
 
           account_params = tp_account_get_parameters (priv->account);
-          if (tp_asv_lookup (account_params, current))
-            continue;
+          if (tp_asv_lookup (account_params, param))
+            goto test_regex;
         }
 
-      missed = TRUE;
-      break;
+      return FALSE;
+    }
+
+test_regex:
+  /* test whether parameter value matches its regex */
+  regex = g_hash_table_lookup (priv->param_regexps, param);
+  if (regex)
+    {
+      value = empathy_account_settings_get_string (settings, param);
+      if (value != NULL && !g_regex_match (regex, value, 0, NULL))
+        return FALSE;
     }
 
-  return !missed;
+  return TRUE;
+}
+
+gboolean
+empathy_account_settings_is_valid (EmpathyAccountSettings *settings)
+{
+  EmpathyAccountSettingsPriv *priv;
+  const gchar *param;
+  GHashTableIter iter;
+  GList *l;
+
+  g_return_val_if_fail (EMPATHY_IS_ACCOUNT_SETTINGS (settings), FALSE);
+
+  priv = GET_PRIV (settings);
+
+  for (l = priv->required_params; l; l = l->next)
+    {
+      if (!empathy_account_settings_parameter_is_valid (settings, l->data))
+        return FALSE;
+    }
+
+  g_hash_table_iter_init (&iter, priv->param_regexps);
+  while (g_hash_table_iter_next (&iter, (gpointer *) &param, NULL))
+    {
+      if (!empathy_account_settings_parameter_is_valid (settings, param))
+        return FALSE;
+    }
+
+  return TRUE;
 }
 
 const TpConnectionManagerProtocol *
diff --git a/libempathy/empathy-account-settings.h b/libempathy/empathy-account-settings.h
index d3276e1..8f3634a 100644
--- a/libempathy/empathy-account-settings.h
+++ b/libempathy/empathy-account-settings.h
@@ -176,6 +176,14 @@ gboolean empathy_account_settings_apply_finish (
   GAsyncResult *result,
   GError **error);
 
+void empathy_account_settings_set_regex (EmpathyAccountSettings *settings,
+  const gchar *param,
+  const gchar *regex);
+
+gboolean empathy_account_settings_parameter_is_valid (
+    EmpathyAccountSettings *settings,
+    const gchar *param);
+
 gboolean empathy_account_settings_is_valid (EmpathyAccountSettings *settings);
 
 const TpConnectionManagerProtocol * empathy_account_settings_get_tp_protocol (



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