Add support for non-ASCII characters in the SSID

Signed-off-by: Mike Lockwood <lockwood@android.com>
diff --git a/Android.mk b/Android.mk
index b1d9313..55e3106 100644
--- a/Android.mk
+++ b/Android.mk
@@ -33,6 +33,9 @@
 # To ignore possible wrong network configurations
 L_CFLAGS += -DWPA_IGNORE_CONFIG_ERRORS
 
+# To allow non-ASCII characters in SSID
+L_CFLAGS += -DWPA_UNICODE_SSID
+
 INCLUDES = external/openssl/include frameworks/base/cmds/keystore
   
 OBJS = config.c common.c md5.c md4.c rc4.c sha1.c des.c
diff --git a/common.c b/common.c
index fce9254..c5b6f7d 100644
--- a/common.c
+++ b/common.c
@@ -616,8 +616,11 @@
 	os_memcpy(ssid_txt, ssid, ssid_len);
 	ssid_txt[ssid_len] = '\0';
 	for (pos = ssid_txt; *pos != '\0'; pos++) {
+#ifndef WPA_UNICODE_SSID
+		/* Don't do this, since it prevents us from using APs with non-ASCII SSIDs */
 		if ((u8) *pos < 32 || (u8) *pos >= 127)
 			*pos = '_';
+#endif
 	}
 	return ssid_txt;
 }
diff --git a/config.c b/config.c
index 6ea66de..e5aeac2 100644
--- a/config.c
+++ b/config.c
@@ -205,6 +205,25 @@
 	return wpa_config_write_string((const u8 *) *src, len);
 }
 
+#ifdef WPA_UNICODE_SSID
+static char * wpa_config_write_str_unicode(const struct parse_data *data,
+				   struct wpa_ssid *ssid)
+{
+	size_t len;
+	char **src;
+
+	src = (char **) (((u8 *) ssid) + (long) data->param1);
+	if (*src == NULL)
+		return NULL;
+
+	if (data->param2)
+		len = *((size_t *) (((u8 *) ssid) + (long) data->param2));
+	else
+		len = os_strlen(*src);
+
+	return wpa_config_write_string_ascii((const u8 *) *src, len);
+}
+#endif
 
 static int wpa_config_parse_int(const struct parse_data *data,
 				struct wpa_ssid *ssid,
@@ -1059,6 +1078,16 @@
 #define STR_RANGE(f, min, max) _STR_RANGE(f, min, max), 0
 #define STR_RANGE_KEY(f, min, max) _STR_RANGE(f, min, max), 1
 
+#ifdef WPA_UNICODE_SSID
+/* STR_* variants that do not force conversion to ASCII */
+#define _STR_UNICODE(f) #f, wpa_config_parse_str, wpa_config_write_str_unicode, OFFSET(f)
+#define STR_UNICODE(f) _STR_UNICODE(f), NULL, NULL, NULL, 0
+#define _STR_LEN_UNICODE(f) _STR_UNICODE(f), OFFSET(f ## _len)
+#define STR_LEN_UNICODE(f) _STR_LEN_UNICODE(f), NULL, NULL, 0
+#define _STR_RANGE_UNICODE(f, min, max) _STR_LEN_UNICODE(f), (void *) (min), (void *) (max)
+#define STR_RANGE_UNICODE(f, min, max) _STR_RANGE_UNICODE(f, min, max), 0
+#endif
+
 #define _INT(f) #f, wpa_config_parse_int, wpa_config_write_int, \
 	OFFSET(f), (void *) 0
 
@@ -1099,7 +1128,11 @@
  * functions.
  */
 static const struct parse_data ssid_fields[] = {
+#ifdef WPA_UNICODE_SSID
+	{ STR_RANGE_UNICODE(ssid, 0, MAX_SSID_LEN) },
+#else
 	{ STR_RANGE(ssid, 0, MAX_SSID_LEN) },
+#endif
 	{ INT_RANGE(scan_ssid, 0, 1) },
 	{ FUNC(bssid) },
 	{ FUNC_KEY(psk) },
@@ -1163,6 +1196,15 @@
 	{ INT_RANGE(frequency, 0, 10000) }
 };
 
+#ifdef WPA_UNICODE_SSID
+#undef _STR_UNICODE
+#undef STR_UNICODE
+#undef _STR_LEN_UNICODE
+#undef STR_LEN_UNICODE
+#undef _STR_RANGE_UNICODE
+#undef STR_RANGE_UNICODE
+#endif
+
 #undef OFFSET
 #undef _STR
 #undef STR