Index: src/gconf-escape.h
===================================================================
--- src/gconf-escape.h	(revision 0)
+++ src/gconf-escape.h	(revision 0)
@@ -0,0 +1,30 @@
+/*
+ *  gconf_(un|)_escape_string - escape strings so they are
+ *  acceptable to gconf
+ *
+ *  Copyright (C) 2008 Thomas Thurman <tthurman@gnome.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#ifndef GCONF_ESCAPE
+#define GCONF_ESCAPE 1
+
+#include <glib.h>
+
+gchar *gconf_escape_string (const gchar *string);
+gchar *gconf_unescape_string (const gchar *string);
+
+#endif /* GCONF_ESCAPE */
Index: src/gam-slider.c
===================================================================
--- src/gam-slider.c	(revision 216)
+++ src/gam-slider.c	(working copy)
@@ -462,7 +462,20 @@
     priv = GAM_SLIDER_GET_PRIVATE (gam_slider);
 
     if (priv->name_config == NULL) {
-        priv->name_config = g_strdup (gam_slider_get_name (gam_slider));
+
+        /*
+	 * Call gconf_escape_string to make the string acceptable
+	 * to gconf; then perform another step to do much the same
+	 * using g_strdelimit, but only for a few characters.  You
+	 * may be wondering why we bother with the first step and
+	 * don't just add all disallowed characters to the list in
+	 * the second.  There are two reasons.  Firstly, the list
+	 * is a blacklist and gconf needs a whitelist.  Secondly, the
+	 * received string contains multibyte characters, so the
+	 * blacklist would be huge.
+	 */
+
+        priv->name_config = gconf_escape_string (gam_slider_get_name (gam_slider));
         priv->name_config = g_strdelimit (priv->name_config, GAM_CONFIG_DELIMITERS, '_');
     }
 
Index: src/gam-mixer.c
===================================================================
--- src/gam-mixer.c	(revision 216)
+++ src/gam-mixer.c	(working copy)
@@ -32,6 +32,7 @@
 #include "gam-slider-dual.h"
 #include "gam-toggle.h"
 #include "gam-props-dlg.h"
+#include "gconf-escape.h"
 
 enum {
     DISPLAY_NAME_CHANGED,
@@ -461,7 +462,20 @@
     priv = GAM_MIXER_GET_PRIVATE (gam_mixer);
 
     if (priv->mixer_name_config == NULL) {
-        priv->mixer_name_config = g_strdup (gam_mixer_get_mixer_name (gam_mixer));
+
+        /*
+	 * Call gconf_escape_string to make the string acceptable
+	 * to gconf; then perform another step to do much the same
+	 * using g_strdelimit, but only for a few characters.  You
+	 * may be wondering why we bother with the first step and
+	 * don't just add all disallowed characters to the list in
+	 * the second.  There are two reasons.  Firstly, the list
+	 * is a blacklist and gconf needs a whitelist.  Secondly, the
+	 * received string contains multibyte characters, so the
+	 * blacklist would be huge.
+	 */
+
+        priv->mixer_name_config = gconf_escape_string (gam_mixer_get_mixer_name (gam_mixer));
         priv->mixer_name_config = g_strdelimit (priv->mixer_name_config, GAM_CONFIG_DELIMITERS, '_');
     }
 
Index: src/Makefile.am
===================================================================
--- src/Makefile.am	(revision 216)
+++ src/Makefile.am	(working copy)
@@ -21,6 +21,7 @@
 	gam-slider-dual.c gam-slider-dual.h \
 	gam-toggle.c gam-toggle.h \
 	gam-prefs-dlg.c gam-prefs-dlg.h \
-	gam-props-dlg.c gam-props-dlg.h
+	gam-props-dlg.c gam-props-dlg.h \
+	gconf-escape.c gconf-escape.h
 
 gnome_alsamixer_LDADD = @PACKAGE_LIBS@
Index: src/gconf-escape.c
===================================================================
--- src/gconf-escape.c	(revision 0)
+++ src/gconf-escape.c	(revision 0)
@@ -0,0 +1,69 @@
+/*
+ *  gconf_(un|)_escape_string - escape strings so they are
+ *  acceptable to gconf
+ *
+ *  Copyright (C) 2008 Thomas Thurman <tthurman@gnome.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include "gconf-escape.h"
+#include <glib.h>
+
+static gboolean
+char_to_starred_hex (const GMatchInfo *match_info, GString *result, gpointer user_data)
+{
+  gchar *match_char = g_match_info_fetch (match_info, 0);
+
+  if (match_char && g_utf8_strlen (match_char, -1))
+    g_string_append_printf (result, "*%0lX*", g_utf8_get_char (match_char));
+  
+  g_free (match_char);
+
+  return FALSE;
+}
+
+static gboolean
+starred_hex_to_char (const GMatchInfo *match_info, GString *result, gpointer user_data)
+{
+  /* We KNOW this is a base-16 number */
+  gchar *hex_string = g_match_info_fetch (match_info, 1);
+
+  if (hex_string)
+    g_string_append_printf (result, "%lc", strtol(hex_string, NULL, 16));
+  
+  return FALSE;
+}
+
+gchar *
+gconf_escape_string (const gchar *string)
+{
+  GRegex *encode = g_regex_new ("[^A-Za-z 0-9_-]", 0, 0, NULL);
+  gchar *result = g_regex_replace_eval (encode, string, -1, 0, 0, char_to_starred_hex, NULL, NULL);
+
+  g_regex_unref (encode);
+  return result;
+}
+
+gchar *
+gconf_unescape_string (const gchar *string)
+{
+  /* Only uppercase matches. */
+  GRegex *decode = g_regex_new ("\\*([A-F0-9]+)\\*", 0, 0, NULL);
+  gchar *result = g_regex_replace_eval (decode, string, -1, 0, 0, starred_hex_to_char, NULL, NULL);
+
+  g_regex_unref (decode);
+  return result;
+}
