diff -ur empathy-2.32.0.1/libempathy/empathy-account-settings.c empathy-2.32.0.1.patched//libempathy/empathy-account-settings.c --- empathy-2.32.0.1/libempathy/empathy-account-settings.c 2010-10-04 17:52:45.000000000 +0400 +++ empathy-2.32.0.1.patched//libempathy/empathy-account-settings.c 2010-10-13 00:07:05.000000000 +0400 @@ -67,9 +67,15 @@ 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; @@ -91,7 +97,12 @@ 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); @@ -325,6 +336,7 @@ { 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); @@ -333,9 +345,14 @@ 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); @@ -388,16 +405,13 @@ 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)); } } } @@ -1287,42 +1301,90 @@ 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 *) ¶m, NULL)) + { + if (!empathy_account_settings_parameter_is_valid (settings, param)) + return FALSE; + } + + return TRUE; } const TpConnectionManagerProtocol * diff -ur empathy-2.32.0.1/libempathy/empathy-account-settings.h empathy-2.32.0.1.patched//libempathy/empathy-account-settings.h --- empathy-2.32.0.1/libempathy/empathy-account-settings.h 2010-10-04 17:52:45.000000000 +0400 +++ empathy-2.32.0.1.patched//libempathy/empathy-account-settings.h 2010-10-12 18:22:34.000000000 +0400 @@ -172,6 +172,14 @@ 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 ( diff -ur empathy-2.32.0.1/libempathy-gtk/empathy-account-widget.c empathy-2.32.0.1.patched//libempathy-gtk/empathy-account-widget.c --- empathy-2.32.0.1/libempathy-gtk/empathy-account-widget.c 2010-10-04 13:19:26.000000000 +0400 +++ empathy-2.32.0.1.patched//libempathy-gtk/empathy-account-widget.c 2010-10-13 17:04:09.000000000 +0400 @@ -116,6 +116,49 @@ #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 @@ } 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 @@ 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 @@ 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 @@ } 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 @@ 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 @@ { 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 @@ { 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 @@ 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 @@ 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 @@ { 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,