Blame SOURCES/0008-utf8safe-fixes-rh1443114.patch

fc9aca
From 7f3d60df818fb2b1dd99b12f893a50fd2402968f Mon Sep 17 00:00:00 2001
fc9aca
From: Thomas Haller <thaller@redhat.com>
fc9aca
Date: Wed, 17 May 2017 16:45:46 +0200
fc9aca
Subject: [PATCH 01/13] libnm: fix unterminated NUL string when parsing UDev
fc9aca
 properties
fc9aca
fc9aca
This can result in trailing garbage (which fails UTF-8 validation
fc9aca
checks) or even worse, in read-out-of-bounds.
fc9aca
fc9aca
Fixes: 6808bf8195d427975638610781f8c5384228218d
fc9aca
fc9aca
https://bugzilla.redhat.com/show_bug.cgi?id=1443114
fc9aca
https://bugzilla.redhat.com/show_bug.cgi?id=1451160
fc9aca
https://bugzilla.redhat.com/show_bug.cgi?id=1451286
fc9aca
(cherry picked from commit 9594ee6e6921c3e37615a572de7e986274a68500)
fc9aca
(cherry picked from commit 5eb11aa8ec4e402b3e5795723519cdaab1cfb828)
fc9aca
---
fc9aca
 shared/nm-utils/nm-udev-utils.c | 1 +
fc9aca
 1 file changed, 1 insertion(+)
fc9aca
fc9aca
diff --git a/shared/nm-utils/nm-udev-utils.c b/shared/nm-utils/nm-udev-utils.c
fc9aca
index bf0ad5b..1f1811c 100644
fc9aca
--- a/shared/nm-utils/nm-udev-utils.c
fc9aca
+++ b/shared/nm-utils/nm-udev-utils.c
fc9aca
@@ -89,6 +89,7 @@ nm_udev_utils_property_decode (const char *uproperty, char **to_free)
fc9aca
 		return uproperty;
fc9aca
 	}
fc9aca
 
fc9aca
+	*n++ = '\0';
fc9aca
 	return (*to_free = unescaped);
fc9aca
 }
fc9aca
 
fc9aca
-- 
fc9aca
2.9.4
fc9aca
fc9aca
fc9aca
From be2a87e07f7a75e568d68afed1532b24edbee414 Mon Sep 17 00:00:00 2001
fc9aca
From: Thomas Haller <thaller@redhat.com>
fc9aca
Date: Wed, 17 May 2017 17:04:13 +0200
fc9aca
Subject: [PATCH 02/13] libnm: don't cunescape \x00 encoding in
fc9aca
 nm_udev_utils_property_decode()
fc9aca
fc9aca
UDev never creates such invalid escape sequences. Anyway,
fc9aca
we cannot accept a NUL character at this point. Just take
fc9aca
the ill escape verbatim -- it should never happen anyway.
fc9aca
fc9aca
(cherry picked from commit c15eae92c0c5fc12017dd84a66ee0bbb9638b270)
fc9aca
(cherry picked from commit 822282754d1653ac24f6e5a9bf616fc74f957050)
fc9aca
---
fc9aca
 shared/nm-utils/nm-udev-utils.c | 7 ++++---
fc9aca
 1 file changed, 4 insertions(+), 3 deletions(-)
fc9aca
fc9aca
diff --git a/shared/nm-utils/nm-udev-utils.c b/shared/nm-utils/nm-udev-utils.c
fc9aca
index 1f1811c..79d4426 100644
fc9aca
--- a/shared/nm-utils/nm-udev-utils.c
fc9aca
+++ b/shared/nm-utils/nm-udev-utils.c
fc9aca
@@ -67,8 +67,9 @@ nm_udev_utils_property_decode (const char *uproperty, char **to_free)
fc9aca
 		if (   p[0] == '\\'
fc9aca
 		    && p[1] == 'x'
fc9aca
 		    && (a = g_ascii_xdigit_value (p[2])) >= 0
fc9aca
-		    && (b = g_ascii_xdigit_value (p[3])) >= 0) {
fc9aca
-			if (!unescaped) {
fc9aca
+		    && (b = g_ascii_xdigit_value (p[3])) >= 0
fc9aca
+		    && (a || b)) {
fc9aca
+			if (!n) {
fc9aca
 				gssize l = p - uproperty;
fc9aca
 
fc9aca
 				unescaped = g_malloc (l + strlen (p) + 1 - 3);
fc9aca
@@ -84,7 +85,7 @@ nm_udev_utils_property_decode (const char *uproperty, char **to_free)
fc9aca
 		}
fc9aca
 	}
fc9aca
 
fc9aca
-	if (!unescaped) {
fc9aca
+	if (!n) {
fc9aca
 		*to_free = NULL;
fc9aca
 		return uproperty;
fc9aca
 	}
fc9aca
-- 
fc9aca
2.9.4
fc9aca
fc9aca
fc9aca
From e1679a6a48ba7367528927f3e7f0021be71e37d6 Mon Sep 17 00:00:00 2001
fc9aca
From: Thomas Haller <thaller@redhat.com>
fc9aca
Date: Wed, 17 May 2017 15:18:20 +0200
fc9aca
Subject: [PATCH 03/13] device: fix setting device's UDI property
fc9aca
fc9aca
Fixes: e8139f56c26ae3bcc5e14abdb29970ae07e93299
fc9aca
(cherry picked from commit 5eac18b58d2be9b5b611f4b4e356b2ac59e46bce)
fc9aca
(cherry picked from commit 4ae14d3677609ef3c702c1a7a706b6bc38030958)
fc9aca
---
fc9aca
 src/devices/nm-device.c | 4 ++--
fc9aca
 1 file changed, 2 insertions(+), 2 deletions(-)
fc9aca
fc9aca
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
fc9aca
index b14dc49..62cb5dd 100644
fc9aca
--- a/src/devices/nm-device.c
fc9aca
+++ b/src/devices/nm-device.c
fc9aca
@@ -2460,7 +2460,7 @@ device_link_changed (NMDevice *self)
fc9aca
 	info = *pllink;
fc9aca
 
fc9aca
 	udi = nm_platform_link_get_udi (nm_device_get_platform (self), info.ifindex);
fc9aca
-	if (udi && g_strcmp0 (udi, priv->udi)) {
fc9aca
+	if (udi && !nm_streq0 (udi, priv->udi)) {
fc9aca
 		/* Update UDI to what udev gives us */
fc9aca
 		g_free (priv->udi);
fc9aca
 		priv->udi = g_strdup (udi);
fc9aca
@@ -2841,7 +2841,7 @@ update_device_from_platform_link (NMDevice *self, const NMPlatformLink *plink)
fc9aca
 	g_return_if_fail (plink != NULL);
fc9aca
 
fc9aca
 	udi = nm_platform_link_get_udi (nm_device_get_platform (self), plink->ifindex);
fc9aca
-	if (udi && !g_strcmp0 (udi, priv->udi)) {
fc9aca
+	if (udi && !nm_streq0 (udi, priv->udi)) {
fc9aca
 		g_free (priv->udi);
fc9aca
 		priv->udi = g_strdup (udi);
fc9aca
 		_notify (self, PROP_UDI);
fc9aca
-- 
fc9aca
2.9.4
fc9aca
fc9aca
fc9aca
From 84b1c78c2474d9e579955fa0ebdfc6a8c0761548 Mon Sep 17 00:00:00 2001
fc9aca
From: Thomas Haller <thaller@redhat.com>
fc9aca
Date: Wed, 17 May 2017 15:01:10 +0200
fc9aca
Subject: [PATCH 04/13] device: make UDI property construct-only
fc9aca
fc9aca
(cherry picked from commit e216d5eac0768b5936f3415cde7808982c74f0ac)
fc9aca
(cherry picked from commit c3b180198fe10d1fe84fea8b9944834be4f4ad56)
fc9aca
---
fc9aca
 src/devices/nm-device.c | 9 +++------
fc9aca
 1 file changed, 3 insertions(+), 6 deletions(-)
fc9aca
fc9aca
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
fc9aca
index 62cb5dd..ed9bc49 100644
fc9aca
--- a/src/devices/nm-device.c
fc9aca
+++ b/src/devices/nm-device.c
fc9aca
@@ -13894,14 +13894,11 @@ set_property (GObject *object, guint prop_id,
fc9aca
 
fc9aca
 	switch (prop_id) {
fc9aca
 	case PROP_UDI:
fc9aca
-		if (g_value_get_string (value)) {
fc9aca
-			g_free (priv->udi);
fc9aca
-			priv->udi = g_value_dup_string (value);
fc9aca
-		}
fc9aca
+		/* construct-only */
fc9aca
+		priv->udi = g_value_dup_string (value);
fc9aca
 		break;
fc9aca
 	case PROP_IFACE:
fc9aca
 		/* construct-only */
fc9aca
-		g_return_if_fail (!priv->iface);
fc9aca
 		priv->iface = g_value_dup_string (value);
fc9aca
 		break;
fc9aca
 	case PROP_DRIVER:
fc9aca
@@ -14212,7 +14209,7 @@ nm_device_class_init (NMDeviceClass *klass)
fc9aca
 	obj_properties[PROP_UDI] =
fc9aca
 	    g_param_spec_string (NM_DEVICE_UDI, "", "",
fc9aca
 	                         NULL,
fc9aca
-	                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
fc9aca
+	                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
fc9aca
 	                         G_PARAM_STATIC_STRINGS);
fc9aca
 	obj_properties[PROP_IFACE] =
fc9aca
 	    g_param_spec_string (NM_DEVICE_IFACE, "", "",
fc9aca
-- 
fc9aca
2.9.4
fc9aca
fc9aca
fc9aca
From c63800b21cb46b7fbdc318205ed6af93aac9aeac Mon Sep 17 00:00:00 2001
fc9aca
From: Thomas Haller <thaller@redhat.com>
fc9aca
Date: Tue, 16 May 2017 18:50:21 +0200
fc9aca
Subject: [PATCH 05/13] shared: add nm_utils_str_utf8safe_*() API to sanitize
fc9aca
 UTF-8 strings
fc9aca
fc9aca
Use C-style backslash escaping to sanitize non-UTF-8 strings.
fc9aca
The functions are compatible with glib's g_strcompress() and
fc9aca
g_strescape().
fc9aca
fc9aca
The difference is only that g_strescape() escapes all non-printable,
fc9aca
non ASCII character as well, while nm_utils_str_utf8safe_escape()
fc9aca
-- depending on the flags -- preserves valid UTF-8 sequence except
fc9aca
backslash.
fc9aca
fc9aca
The flags allow to optionally escape ASCII control characters and
fc9aca
all non-ASCII (valid UTF-8) characters. But the option to preserve
fc9aca
valid UTF-8 (non-ASCII) characters verbatim, is what distinguishes
fc9aca
from g_strescape().
fc9aca
fc9aca
(cherry picked from commit df6d27b33a86e2ecdc5a8e1deff275d19b2cbde1)
fc9aca
(cherry picked from commit 52105f27df974715a8481fb240f98f73a6a8be08)
fc9aca
---
fc9aca
 libnm-core/tests/test-general.c   |  95 ++++++++++++++++++++++++++
fc9aca
 shared/nm-utils/nm-shared-utils.c | 138 ++++++++++++++++++++++++++++++++++++++
fc9aca
 shared/nm-utils/nm-shared-utils.h |  16 +++++
fc9aca
 3 files changed, 249 insertions(+)
fc9aca
fc9aca
diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c
fc9aca
index 7ecd681..fbcfa7d 100644
fc9aca
--- a/libnm-core/tests/test-general.c
fc9aca
+++ b/libnm-core/tests/test-general.c
fc9aca
@@ -5248,6 +5248,100 @@ static void test_nm_utils_enum (void)
fc9aca
 
fc9aca
 /*****************************************************************************/
fc9aca
 
fc9aca
+static void
fc9aca
+do_test_utils_str_utf8safe (const char *str, const char *expected, NMUtilsStrUtf8SafeFlags flags)
fc9aca
+{
fc9aca
+	const char *str_safe, *s;
fc9aca
+	gs_free char *str2 = NULL;
fc9aca
+	gs_free char *str3 = NULL;
fc9aca
+
fc9aca
+	str_safe = nm_utils_str_utf8safe_escape (str, flags, &str2;;
fc9aca
+
fc9aca
+	str3 = nm_utils_str_utf8safe_escape_cp (str, flags);
fc9aca
+	g_assert_cmpstr (str3, ==, str_safe);
fc9aca
+	g_assert ((!str && !str3) || (str != str3));
fc9aca
+	g_clear_pointer (&str3, g_free);
fc9aca
+
fc9aca
+	if (expected == NULL) {
fc9aca
+		g_assert (str_safe == str);
fc9aca
+		g_assert (!str2);
fc9aca
+		if (str) {
fc9aca
+			g_assert (!strchr (str, '\\'));
fc9aca
+			g_assert (g_utf8_validate (str, -1, NULL));
fc9aca
+		}
fc9aca
+
fc9aca
+		g_assert (str == nm_utils_str_utf8safe_unescape (str_safe, &str3));
fc9aca
+		g_assert (!str3);
fc9aca
+
fc9aca
+		str3 = nm_utils_str_utf8safe_unescape_cp (str_safe);
fc9aca
+		if (str) {
fc9aca
+			g_assert (str3 != str);
fc9aca
+			g_assert_cmpstr (str3, ==, str);
fc9aca
+		} else
fc9aca
+			g_assert (!str3);
fc9aca
+		g_clear_pointer (&str3, g_free);
fc9aca
+		return;
fc9aca
+	}
fc9aca
+
fc9aca
+	g_assert (str);
fc9aca
+	g_assert (str_safe != str);
fc9aca
+	g_assert (str_safe == str2);
fc9aca
+	g_assert (   strchr (str, '\\')
fc9aca
+	          || !g_utf8_validate (str, -1, NULL)
fc9aca
+	          || (   NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII)
fc9aca
+	              && NM_STRCHAR_ANY (str, ch, (guchar) ch >= 127))
fc9aca
+	          || (   NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL)
fc9aca
+	              && NM_STRCHAR_ANY (str, ch, (guchar) ch < ' ')));
fc9aca
+	g_assert (g_utf8_validate (str_safe, -1, NULL));
fc9aca
+
fc9aca
+	str3 = g_strcompress (str_safe);
fc9aca
+	g_assert_cmpstr (str, ==, str3);
fc9aca
+	g_clear_pointer (&str3, g_free);
fc9aca
+
fc9aca
+	str3 = nm_utils_str_utf8safe_unescape_cp (str_safe);
fc9aca
+	g_assert (str3 != str);
fc9aca
+	g_assert_cmpstr (str3, ==, str);
fc9aca
+	g_clear_pointer (&str3, g_free);
fc9aca
+
fc9aca
+	s = nm_utils_str_utf8safe_unescape (str_safe, &str3;;
fc9aca
+	g_assert (str3 != str);
fc9aca
+	g_assert (s == str3);
fc9aca
+	g_assert_cmpstr (str3, ==, str);
fc9aca
+	g_clear_pointer (&str3, g_free);
fc9aca
+
fc9aca
+	g_assert_cmpstr (str_safe, ==, expected);
fc9aca
+}
fc9aca
+
fc9aca
+static void
fc9aca
+test_utils_str_utf8safe (void)
fc9aca
+{
fc9aca
+	do_test_utils_str_utf8safe (NULL, NULL,                                       NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
fc9aca
+	do_test_utils_str_utf8safe ("", NULL,                                         NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
fc9aca
+	do_test_utils_str_utf8safe ("\314", "\\314",                                  NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
fc9aca
+	do_test_utils_str_utf8safe ("\314\315x\315\315x", "\\314\\315x\\315\\315x",   NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
fc9aca
+	do_test_utils_str_utf8safe ("\314\315xx", "\\314\\315xx",                     NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
fc9aca
+	do_test_utils_str_utf8safe ("\314xx", "\\314xx",                              NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
fc9aca
+	do_test_utils_str_utf8safe ("\xa0", "\\240",                                  NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
fc9aca
+	do_test_utils_str_utf8safe ("\xe2\x91\xa0", NULL,                             NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
fc9aca
+	do_test_utils_str_utf8safe ("\xe2\xe2\x91\xa0", "\\342\xe2\x91\xa0",          NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
fc9aca
+	do_test_utils_str_utf8safe ("\xe2\xe2\x91\xa0\xa0", "\\342\xe2\x91\xa0\\240", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
fc9aca
+	do_test_utils_str_utf8safe ("a", NULL,                                        NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
fc9aca
+	do_test_utils_str_utf8safe ("ab", NULL,                                       NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
fc9aca
+	do_test_utils_str_utf8safe ("ab\314", "ab\\314",                              NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
fc9aca
+	do_test_utils_str_utf8safe ("ab\314adsf", "ab\\314adsf",                      NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
fc9aca
+	do_test_utils_str_utf8safe ("abadsf", NULL,                                   NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
fc9aca
+	do_test_utils_str_utf8safe ("abäb", NULL,                                     NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
fc9aca
+	do_test_utils_str_utf8safe ("x\xa0", "x\\240",                                NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
fc9aca
+	do_test_utils_str_utf8safe ("Ä\304ab\\äb", "Ä\\304ab\\\\äb",                  NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
fc9aca
+	do_test_utils_str_utf8safe ("Äab\\äb", "Äab\\\\äb",                           NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
fc9aca
+	do_test_utils_str_utf8safe ("ÄÄab\\äb", "ÄÄab\\\\äb",                         NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
fc9aca
+	do_test_utils_str_utf8safe ("㈞abä㈞b", NULL,                                 NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
fc9aca
+	do_test_utils_str_utf8safe ("abäb", "ab\\303\\244b",                          NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII);
fc9aca
+	do_test_utils_str_utf8safe ("ab\ab", "ab\\007b",                              NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL);
fc9aca
+}
fc9aca
+
fc9aca
+/*****************************************************************************/
fc9aca
+
fc9aca
 static int
fc9aca
 _test_nm_in_set_get (int *call_counter, gboolean allow_called, int value)
fc9aca
 {
fc9aca
@@ -5605,6 +5699,7 @@ int main (int argc, char **argv)
fc9aca
 	nmtst_init (&argc, &argv, TRUE);
fc9aca
 
fc9aca
 	/* The tests */
fc9aca
+	g_test_add_func ("/core/general/test_utils_str_utf8safe", test_utils_str_utf8safe);
fc9aca
 	g_test_add_func ("/core/general/test_nm_in_set", test_nm_in_set);
fc9aca
 	g_test_add_func ("/core/general/test_nm_in_strset", test_nm_in_strset);
fc9aca
 	g_test_add_func ("/core/general/test_setting_vpn_items", test_setting_vpn_items);
fc9aca
diff --git a/shared/nm-utils/nm-shared-utils.c b/shared/nm-utils/nm-shared-utils.c
fc9aca
index 413526d..e7f31cb 100644
fc9aca
--- a/shared/nm-utils/nm-shared-utils.c
fc9aca
+++ b/shared/nm-utils/nm-shared-utils.c
fc9aca
@@ -364,3 +364,141 @@ nm_g_object_set_property (GObject *object,
fc9aca
 }
fc9aca
 
fc9aca
 /*****************************************************************************/
fc9aca
+
fc9aca
+static void
fc9aca
+_str_append_escape (GString *s, char ch)
fc9aca
+{
fc9aca
+	g_string_append_c (s, '\\');
fc9aca
+	g_string_append_c (s, '0' + ((((guchar) ch) >> 6) & 07));
fc9aca
+	g_string_append_c (s, '0' + ((((guchar) ch) >> 3) & 07));
fc9aca
+	g_string_append_c (s, '0' + ( ((guchar) ch)       & 07));
fc9aca
+}
fc9aca
+
fc9aca
+/**
fc9aca
+ * nm_utils_str_utf8safe_escape:
fc9aca
+ * @str: NUL terminated input string, possibly in utf-8 encoding
fc9aca
+ * @flags: #NMUtilsStrUtf8SafeFlags flags
fc9aca
+ * @to_free: (out): return the pointer location of the string
fc9aca
+ *   if a copying was necessary.
fc9aca
+ *
fc9aca
+ * Returns the possible non-UTF-8 NUL terminated string @str
fc9aca
+ * and uses backslash escaping (C escaping, like g_strescape())
fc9aca
+ * to sanitize non UTF-8 characters. The result is valid
fc9aca
+ * UTF-8.
fc9aca
+ *
fc9aca
+ * The operation can be reverted with g_strcompress() or
fc9aca
+ * nm_utils_str_utf8safe_unescape().
fc9aca
+ *
fc9aca
+ * Depending on @flags, valid UTF-8 characters are not escaped at all
fc9aca
+ * (except the escape character '\\'). This is the difference to g_strescape(),
fc9aca
+ * which escapes all non-ASCII characters. This allows to pass on
fc9aca
+ * valid UTF-8 characters as-is and can be directly shown to the user
fc9aca
+ * as UTF-8 -- with exception of the backslash escape character,
fc9aca
+ * invalid UTF-8 sequences, and other (depending on @flags).
fc9aca
+ *
fc9aca
+ * Returns: the escaped input string, as valid UTF-8. If no escaping
fc9aca
+ *   is necessary, it returns the input @str. Otherwise, an allocated
fc9aca
+ *   string @to_free is returned which must be freed by the caller
fc9aca
+ *   with g_free. The escaping can be reverted by g_strcompress().
fc9aca
+ **/
fc9aca
+const char *
fc9aca
+nm_utils_str_utf8safe_escape (const char *str, NMUtilsStrUtf8SafeFlags flags, char **to_free)
fc9aca
+{
fc9aca
+	const char *p = NULL;
fc9aca
+	GString *s;
fc9aca
+
fc9aca
+	g_return_val_if_fail (to_free, NULL);
fc9aca
+
fc9aca
+	*to_free = NULL;
fc9aca
+	if (!str || !str[0])
fc9aca
+		return str;
fc9aca
+
fc9aca
+	if (   g_utf8_validate (str, -1, &p)
fc9aca
+	    && !NM_STRCHAR_ANY (str, ch,
fc9aca
+	                        (   ch == '\\' \
fc9aca
+	                         || (   NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL) \
fc9aca
+	                             && ch < ' ') \
fc9aca
+	                         || (   NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII) \
fc9aca
+	                             && ((guchar) ch) >= 127))))
fc9aca
+		return str;
fc9aca
+
fc9aca
+	s = g_string_sized_new ((p - str) + strlen (p) + 5);
fc9aca
+
fc9aca
+	do {
fc9aca
+		for (; str < p; str++) {
fc9aca
+			char ch = str[0];
fc9aca
+
fc9aca
+			if (ch == '\\')
fc9aca
+				g_string_append (s, "\\\\");
fc9aca
+			else if (   (   NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL) \
fc9aca
+			             && ch < ' ') \
fc9aca
+			         || (   NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII) \
fc9aca
+			             && ((guchar) ch) >= 127))
fc9aca
+				_str_append_escape (s, ch);
fc9aca
+			else
fc9aca
+				g_string_append_c (s, ch);
fc9aca
+		}
fc9aca
+
fc9aca
+		if (p[0] == '\0')
fc9aca
+			break;
fc9aca
+		_str_append_escape (s, p[0]);
fc9aca
+
fc9aca
+		str = &p[1];
fc9aca
+		g_utf8_validate (str, -1, &p);
fc9aca
+	} while (TRUE);
fc9aca
+
fc9aca
+	*to_free = g_string_free (s, FALSE);
fc9aca
+	return *to_free;
fc9aca
+}
fc9aca
+
fc9aca
+const char *
fc9aca
+nm_utils_str_utf8safe_unescape (const char *str, char **to_free)
fc9aca
+{
fc9aca
+	g_return_val_if_fail (to_free, NULL);
fc9aca
+
fc9aca
+	if (!str || !strchr (str, '\\')) {
fc9aca
+		*to_free = NULL;
fc9aca
+		return str;
fc9aca
+	}
fc9aca
+	return (*to_free = g_strcompress (str));
fc9aca
+}
fc9aca
+
fc9aca
+/**
fc9aca
+ * nm_utils_str_utf8safe_escape_cp:
fc9aca
+ * @str: NUL terminated input string, possibly in utf-8 encoding
fc9aca
+ * @flags: #NMUtilsStrUtf8SafeFlags flags
fc9aca
+ *
fc9aca
+ * Like nm_utils_str_utf8safe_escape(), except the returned value
fc9aca
+ * is always a copy of the input and must be freed by the caller.
fc9aca
+ *
fc9aca
+ * Returns: the escaped input string in UTF-8 encoding. The returned
fc9aca
+ *   value should be freed with g_free().
fc9aca
+ *   The escaping can be reverted by g_strcompress().
fc9aca
+ **/
fc9aca
+char *
fc9aca
+nm_utils_str_utf8safe_escape_cp (const char *str, NMUtilsStrUtf8SafeFlags flags)
fc9aca
+{
fc9aca
+	char *s;
fc9aca
+
fc9aca
+	nm_utils_str_utf8safe_escape (str, flags, &s);
fc9aca
+	return s ?: g_strdup (str);
fc9aca
+}
fc9aca
+
fc9aca
+char *
fc9aca
+nm_utils_str_utf8safe_unescape_cp (const char *str)
fc9aca
+{
fc9aca
+	return str ? g_strcompress (str) : NULL;
fc9aca
+}
fc9aca
+
fc9aca
+char *
fc9aca
+nm_utils_str_utf8safe_escape_take (char *str, NMUtilsStrUtf8SafeFlags flags)
fc9aca
+{
fc9aca
+	char *str_to_free;
fc9aca
+
fc9aca
+	nm_utils_str_utf8safe_escape (str, flags, &str_to_free);
fc9aca
+	if (str_to_free) {
fc9aca
+		g_free (str);
fc9aca
+		return str_to_free;
fc9aca
+	}
fc9aca
+	return str;
fc9aca
+}
fc9aca
diff --git a/shared/nm-utils/nm-shared-utils.h b/shared/nm-utils/nm-shared-utils.h
fc9aca
index f1f9f51..69f9533 100644
fc9aca
--- a/shared/nm-utils/nm-shared-utils.h
fc9aca
+++ b/shared/nm-utils/nm-shared-utils.h
fc9aca
@@ -86,4 +86,20 @@ gboolean nm_g_object_set_property (GObject *object,
fc9aca
 
fc9aca
 /*****************************************************************************/
fc9aca
 
fc9aca
+typedef enum {
fc9aca
+	NM_UTILS_STR_UTF8_SAFE_FLAG_NONE                = 0,
fc9aca
+	NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL         = 0x0001,
fc9aca
+	NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII    = 0x0002,
fc9aca
+} NMUtilsStrUtf8SafeFlags;
fc9aca
+
fc9aca
+const char *nm_utils_str_utf8safe_escape   (const char *str, NMUtilsStrUtf8SafeFlags flags, char **to_free);
fc9aca
+const char *nm_utils_str_utf8safe_unescape (const char *str, char **to_free);
fc9aca
+
fc9aca
+char *nm_utils_str_utf8safe_escape_cp   (const char *str, NMUtilsStrUtf8SafeFlags flags);
fc9aca
+char *nm_utils_str_utf8safe_unescape_cp (const char *str);
fc9aca
+
fc9aca
+char *nm_utils_str_utf8safe_escape_take (char *str, NMUtilsStrUtf8SafeFlags flags);
fc9aca
+
fc9aca
+/*****************************************************************************/
fc9aca
+
fc9aca
 #endif /* __NM_SHARED_UTILS_H__ */
fc9aca
-- 
fc9aca
2.9.4
fc9aca
fc9aca
fc9aca
From e9eee9c65818e7dd85e79c1db6ad4c32b4c7fb52 Mon Sep 17 00:00:00 2001
fc9aca
From: Thomas Haller <thaller@redhat.com>
fc9aca
Date: Tue, 16 May 2017 14:11:07 +0200
fc9aca
Subject: [PATCH 06/13] device: sanitze UTF-8 values for D-Bus
fc9aca
fc9aca
  ip link add name $'d\xccf\\c' type dummy
fc9aca
fc9aca
Use nm_utils_str_utf8safe_escape() to sanitize non UTF-8 sequences
fc9aca
before exposing them on D-Bus. The operation can be reverted client
fc9aca
side via nm_utils_str_utf8safe_unescape() or simply g_strcompress().
fc9aca
fc9aca
Note that this preserves all valid UTF-8 sequences as-is, with exception
fc9aca
of the backslash escape character and ASCII control characters. Thus, this
fc9aca
is a change in behavior for strings that contain such characters.
fc9aca
fc9aca
Note that nmcli is not changed to somehow unescape the string before
fc9aca
printing. As the string is not valid UTF-8 (or contains ASCII characters
fc9aca
that need escaping), they are not printable as-is, so unescaping before
fc9aca
printing makes little sense.
fc9aca
fc9aca
(cherry picked from commit 0870906540506d0157f305df32b6b1f65b10ee85)
fc9aca
(cherry picked from commit 3a96772918a391ec8186183b5c14c9b165322d3a)
fc9aca
---
fc9aca
 .../org.freedesktop.NetworkManager.Device.xml      | 15 +++++++++++
fc9aca
 src/devices/nm-device.c                            | 31 ++++++++++++++++------
fc9aca
 2 files changed, 38 insertions(+), 8 deletions(-)
fc9aca
fc9aca
diff --git a/introspection/org.freedesktop.NetworkManager.Device.xml b/introspection/org.freedesktop.NetworkManager.Device.xml
fc9aca
index ee42410..be0a612 100644
fc9aca
--- a/introspection/org.freedesktop.NetworkManager.Device.xml
fc9aca
+++ b/introspection/org.freedesktop.NetworkManager.Device.xml
fc9aca
@@ -21,6 +21,9 @@
fc9aca
         each device in your application, use the object path. If you're looking
fc9aca
         for a way to track a specific piece of hardware across reboot or hotplug,
fc9aca
         use a MAC address or USB serial number.
fc9aca
+
fc9aca
+        Note that non-UTF-8 characters are backslash escaped. Use g_strcompress()
fc9aca
+        to obtain the true (non-UTF-8) string.
fc9aca
     -->
fc9aca
     <property name="Udi" type="s" access="read"/>
fc9aca
 
fc9aca
@@ -28,6 +31,9 @@
fc9aca
         Interface:
fc9aca
 
fc9aca
         The name of the device's control (and often data) interface.
fc9aca
+        Note that non UTF-8 characters are backslash escaped, so the
fc9aca
+        resulting name may be longer then 15 characters. Use g_strcompress()
fc9aca
+        to revert the escaping.
fc9aca
     -->
fc9aca
     <property name="Interface" type="s" access="read"/>
fc9aca
 
fc9aca
@@ -38,6 +44,9 @@
fc9aca
         not refer to the actual data interface until the device has successfully
fc9aca
         established a data connection, indicated by the device's State becoming
fc9aca
         ACTIVATED.
fc9aca
+        Note that non UTF-8 characters are backslash escaped, so the
fc9aca
+        resulting name may be longer then 15 characters. Use g_strcompress()
fc9aca
+        to revert the escaping.
fc9aca
     -->
fc9aca
     <property name="IpInterface" type="s" access="read"/>
fc9aca
 
fc9aca
@@ -45,6 +54,8 @@
fc9aca
         Driver:
fc9aca
 
fc9aca
         The driver handling the device.
fc9aca
+        Non-UTF-8 sequences are backslash escaped. Use g_strcompress()
fc9aca
+        to revert.
fc9aca
     -->
fc9aca
     <property name="Driver" type="s" access="read"/>
fc9aca
 
fc9aca
@@ -52,6 +63,8 @@
fc9aca
         DriverVersion:
fc9aca
 
fc9aca
         The version of the driver handling the device.
fc9aca
+        Non-UTF-8 sequences are backslash escaped. Use g_strcompress()
fc9aca
+        to revert.
fc9aca
     -->
fc9aca
     <property name="DriverVersion" type="s" access="read"/>
fc9aca
 
fc9aca
@@ -59,6 +72,8 @@
fc9aca
         FirmwareVersion:
fc9aca
 
fc9aca
         The firmware version for the device.
fc9aca
+        Non-UTF-8 sequences are backslash escaped. Use g_strcompress()
fc9aca
+        to revert.
fc9aca
     -->
fc9aca
     <property name="FirmwareVersion" type="s" access="read"/>
fc9aca
 
fc9aca
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
fc9aca
index ed9bc49..e61bde3 100644
fc9aca
--- a/src/devices/nm-device.c
fc9aca
+++ b/src/devices/nm-device.c
fc9aca
@@ -13993,28 +13993,43 @@ get_property (GObject *object, guint prop_id,
fc9aca
 
fc9aca
 	switch (prop_id) {
fc9aca
 	case PROP_UDI:
fc9aca
-		g_value_set_string (value, priv->udi);
fc9aca
+		/* UDI is (depending on the device type) a path to sysfs and can contain
fc9aca
+		 * non-UTF-8.
fc9aca
+		 *   ip link add name $'d\xccf\\c' type dummy  */
fc9aca
+		g_value_take_string (value,
fc9aca
+		                     nm_utils_str_utf8safe_escape_cp (priv->udi,
fc9aca
+		                                                      NM_UTILS_STR_UTF8_SAFE_FLAG_NONE));
fc9aca
 		break;
fc9aca
 	case PROP_IFACE:
fc9aca
-		g_value_set_string (value, priv->iface);
fc9aca
+		g_value_take_string (value,
fc9aca
+		                     nm_utils_str_utf8safe_escape_cp (priv->iface,
fc9aca
+		                                                      NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL));
fc9aca
 		break;
fc9aca
 	case PROP_IP_IFACE:
fc9aca
-		if (ip_config_valid (priv->state))
fc9aca
-			g_value_set_string (value, nm_device_get_ip_iface (self));
fc9aca
-		else
fc9aca
+		if (ip_config_valid (priv->state)) {
fc9aca
+			g_value_take_string (value,
fc9aca
+			                     nm_utils_str_utf8safe_escape_cp (nm_device_get_ip_iface (self),
fc9aca
+			                                                      NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL));
fc9aca
+		} else
fc9aca
 			g_value_set_string (value, NULL);
fc9aca
 		break;
fc9aca
 	case PROP_IFINDEX:
fc9aca
 		g_value_set_int (value, priv->ifindex);
fc9aca
 		break;
fc9aca
 	case PROP_DRIVER:
fc9aca
-		g_value_set_string (value, priv->driver);
fc9aca
+		g_value_take_string (value,
fc9aca
+		                     nm_utils_str_utf8safe_escape_cp (priv->driver,
fc9aca
+		                                                      NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL));
fc9aca
 		break;
fc9aca
 	case PROP_DRIVER_VERSION:
fc9aca
-		g_value_set_string (value, priv->driver_version);
fc9aca
+		g_value_take_string (value,
fc9aca
+		                     nm_utils_str_utf8safe_escape_cp (priv->driver_version,
fc9aca
+		                                                      NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL));
fc9aca
 		break;
fc9aca
 	case PROP_FIRMWARE_VERSION:
fc9aca
-		g_value_set_string (value, priv->firmware_version);
fc9aca
+		g_value_take_string (value,
fc9aca
+		                     nm_utils_str_utf8safe_escape_cp (priv->firmware_version,
fc9aca
+		                                                      NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL));
fc9aca
 		break;
fc9aca
 	case PROP_CAPABILITIES:
fc9aca
 		g_value_set_uint (value, (priv->capabilities & ~NM_DEVICE_CAP_INTERNAL_MASK));
fc9aca
-- 
fc9aca
2.9.4
fc9aca
fc9aca
fc9aca
From 0b8676b887f63a708e6444f6b3d19003a2f9b4c8 Mon Sep 17 00:00:00 2001
fc9aca
From: Thomas Haller <thaller@redhat.com>
fc9aca
Date: Wed, 17 May 2017 11:48:53 +0200
fc9aca
Subject: [PATCH 07/13] libnm: UTF-8 sanitize strings from UDev in NMDevice
fc9aca
fc9aca
(cherry picked from commit b9e9f7616556f693e2642ed433f3289f9c6da452)
fc9aca
(cherry picked from commit d7b184d99257a6e6e59b22709007675430ec308b)
fc9aca
---
fc9aca
 libnm/nm-device.c | 273 ++++++++++++++++++++++++++++++------------------------
fc9aca
 1 file changed, 152 insertions(+), 121 deletions(-)
fc9aca
fc9aca
diff --git a/libnm/nm-device.c b/libnm/nm-device.c
fc9aca
index 9cbdbd0..7e8feb1 100644
fc9aca
--- a/libnm/nm-device.c
fc9aca
+++ b/libnm/nm-device.c
fc9aca
@@ -81,7 +81,7 @@ typedef struct {
fc9aca
 	GPtrArray *available_connections;
fc9aca
 
fc9aca
 	struct udev *udev;
fc9aca
-	char *product, *short_product;
fc9aca
+	char *product;
fc9aca
 	char *vendor, *short_vendor;
fc9aca
 	char *description, *bus_name;
fc9aca
 
fc9aca
@@ -320,7 +320,6 @@ finalize (GObject *object)
fc9aca
 	g_free (priv->driver_version);
fc9aca
 	g_free (priv->firmware_version);
fc9aca
 	g_free (priv->product);
fc9aca
-	g_free (priv->short_product);
fc9aca
 	g_free (priv->vendor);
fc9aca
 	g_free (priv->short_vendor);
fc9aca
 	g_free (priv->description);
fc9aca
@@ -1357,6 +1356,17 @@ _get_udev_property (NMDevice *device,
fc9aca
 	return db_value;
fc9aca
 }
fc9aca
 
fc9aca
+static char *
fc9aca
+_get_udev_property_utf8safe (NMDevice *device,
fc9aca
+                             const char *enc_prop,  /* ID_XXX_ENC */
fc9aca
+                             const char *db_prop)   /* ID_XXX_FROM_DATABASE */
fc9aca
+{
fc9aca
+	return nm_utils_str_utf8safe_escape_take (_get_udev_property (device,
fc9aca
+	                                                              enc_prop,
fc9aca
+	                                                              db_prop),
fc9aca
+	                                          NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL);
fc9aca
+}
fc9aca
+
fc9aca
 /**
fc9aca
  * nm_device_get_product:
fc9aca
  * @device: a #NMDevice
fc9aca
@@ -1365,6 +1375,9 @@ _get_udev_property (NMDevice *device,
fc9aca
  *
fc9aca
  * Returns: the product name of the device. This is the internal string used by the
fc9aca
  * device, and must not be modified.
fc9aca
+ *
fc9aca
+ * The string is backslash escaped (C escaping) for invalid characters. The escaping
fc9aca
+ * can be reverted with g_strcompress(), however the result may not be valid UTF-8.
fc9aca
  **/
fc9aca
 const char *
fc9aca
 nm_device_get_product (NMDevice *device)
fc9aca
@@ -1374,15 +1387,16 @@ nm_device_get_product (NMDevice *device)
fc9aca
 	g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
fc9aca
 
fc9aca
 	priv = NM_DEVICE_GET_PRIVATE (device);
fc9aca
-	if (!priv->product)
fc9aca
-		priv->product = _get_udev_property (device, "ID_MODEL_ENC", "ID_MODEL_FROM_DATABASE");
fc9aca
+	if (!priv->product) {
fc9aca
+		priv->product = _get_udev_property_utf8safe (device, "ID_MODEL_ENC", "ID_MODEL_FROM_DATABASE");
fc9aca
 
fc9aca
-	/* Sometimes ID_PRODUCT_FROM_DATABASE is used? */
fc9aca
-	if (!priv->product)
fc9aca
-		priv->product = _get_udev_property (device, "ID_MODEL_ENC", "ID_PRODUCT_FROM_DATABASE");
fc9aca
+		/* Sometimes ID_PRODUCT_FROM_DATABASE is used? */
fc9aca
+		if (!priv->product)
fc9aca
+			priv->product = _get_udev_property_utf8safe (device, "ID_MODEL_ENC", "ID_PRODUCT_FROM_DATABASE");
fc9aca
 
fc9aca
-	if (!priv->product)
fc9aca
-		priv->product = g_strdup ("");
fc9aca
+		if (!priv->product)
fc9aca
+			priv->product = g_strdup ("");
fc9aca
+	}
fc9aca
 
fc9aca
 	return priv->product;
fc9aca
 }
fc9aca
@@ -1395,6 +1409,9 @@ nm_device_get_product (NMDevice *device)
fc9aca
  *
fc9aca
  * Returns: the vendor name of the device. This is the internal string used by the
fc9aca
  * device, and must not be modified.
fc9aca
+ *
fc9aca
+ * The string is backslash escaped (C escaping) for invalid characters. The escaping
fc9aca
+ * can be reverted with g_strcompress(), however the result may not be valid UTF-8.
fc9aca
  **/
fc9aca
 const char *
fc9aca
 nm_device_get_vendor (NMDevice *device)
fc9aca
@@ -1406,7 +1423,7 @@ nm_device_get_vendor (NMDevice *device)
fc9aca
 	priv = NM_DEVICE_GET_PRIVATE (device);
fc9aca
 
fc9aca
 	if (!priv->vendor)
fc9aca
-		priv->vendor = _get_udev_property (device, "ID_VENDOR_ENC", "ID_VENDOR_FROM_DATABASE");
fc9aca
+		priv->vendor = _get_udev_property_utf8safe (device, "ID_VENDOR_ENC", "ID_VENDOR_FROM_DATABASE");
fc9aca
 
fc9aca
 	if (!priv->vendor)
fc9aca
 		priv->vendor = g_strdup ("");
fc9aca
@@ -1414,128 +1431,146 @@ nm_device_get_vendor (NMDevice *device)
fc9aca
 	return priv->vendor;
fc9aca
 }
fc9aca
 
fc9aca
-static const char * const ignored_words[] = {
fc9aca
-	"Semiconductor",
fc9aca
-	"Components",
fc9aca
-	"Corporation",
fc9aca
-	"Communications",
fc9aca
-	"Company",
fc9aca
-	"Corp.",
fc9aca
-	"Corp",
fc9aca
-	"Co.",
fc9aca
-	"Inc.",
fc9aca
-	"Inc",
fc9aca
-	"Incorporated",
fc9aca
-	"Ltd.",
fc9aca
-	"Limited.",
fc9aca
-	"Intel?",
fc9aca
-	"chipset",
fc9aca
-	"adapter",
fc9aca
-	"[hex]",
fc9aca
-	"NDIS",
fc9aca
-	"Module",
fc9aca
-	NULL
fc9aca
-};
fc9aca
-
fc9aca
-static const char * const ignored_phrases[] = {
fc9aca
-	"Multiprotocol MAC/baseband processor",
fc9aca
-	"Wireless LAN Controller",
fc9aca
-	"Wireless LAN Adapter",
fc9aca
-	"Wireless Adapter",
fc9aca
-	"Network Connection",
fc9aca
-	"Wireless Cardbus Adapter",
fc9aca
-	"Wireless CardBus Adapter",
fc9aca
-	"54 Mbps Wireless PC Card",
fc9aca
-	"Wireless PC Card",
fc9aca
-	"Wireless PC",
fc9aca
-	"PC Card with XJACK(r) Antenna",
fc9aca
-	"Wireless cardbus",
fc9aca
-	"Wireless LAN PC Card",
fc9aca
-	"Technology Group Ltd.",
fc9aca
-	"Communication S.p.A.",
fc9aca
-	"Business Mobile Networks BV",
fc9aca
-	"Mobile Broadband Minicard Composite Device",
fc9aca
-	"Mobile Communications AB",
fc9aca
-	"(PC-Suite Mode)",
fc9aca
-	NULL
fc9aca
-};
fc9aca
-
fc9aca
 static char *
fc9aca
 fixup_desc_string (const char *desc)
fc9aca
 {
fc9aca
-	char *p, *temp;
fc9aca
-	char **words, **item;
fc9aca
-	GString *str;
fc9aca
+	static const char *const IGNORED_PHRASES[] = {
fc9aca
+		"Multiprotocol MAC/baseband processor",
fc9aca
+		"Wireless LAN Controller",
fc9aca
+		"Wireless LAN Adapter",
fc9aca
+		"Wireless Adapter",
fc9aca
+		"Network Connection",
fc9aca
+		"Wireless Cardbus Adapter",
fc9aca
+		"Wireless CardBus Adapter",
fc9aca
+		"54 Mbps Wireless PC Card",
fc9aca
+		"Wireless PC Card",
fc9aca
+		"Wireless PC",
fc9aca
+		"PC Card with XJACK(r) Antenna",
fc9aca
+		"Wireless cardbus",
fc9aca
+		"Wireless LAN PC Card",
fc9aca
+		"Technology Group Ltd.",
fc9aca
+		"Communication S.p.A.",
fc9aca
+		"Business Mobile Networks BV",
fc9aca
+		"Mobile Broadband Minicard Composite Device",
fc9aca
+		"Mobile Communications AB",
fc9aca
+		"(PC-Suite Mode)",
fc9aca
+	};
fc9aca
+	static const char *const IGNORED_WORDS[] = {
fc9aca
+		"Semiconductor",
fc9aca
+		"Components",
fc9aca
+		"Corporation",
fc9aca
+		"Communications",
fc9aca
+		"Company",
fc9aca
+		"Corp.",
fc9aca
+		"Corp",
fc9aca
+		"Co.",
fc9aca
+		"Inc.",
fc9aca
+		"Inc",
fc9aca
+		"Incorporated",
fc9aca
+		"Ltd.",
fc9aca
+		"Limited.",
fc9aca
+		"Intel?",
fc9aca
+		"chipset",
fc9aca
+		"adapter",
fc9aca
+		"[hex]",
fc9aca
+		"NDIS",
fc9aca
+		"Module",
fc9aca
+	};
fc9aca
+	char *desc_full;
fc9aca
+	char *p, *q;
fc9aca
 	int i;
fc9aca
 
fc9aca
-	if (!desc)
fc9aca
+	if (!desc || !desc[0])
fc9aca
 		return NULL;
fc9aca
 
fc9aca
-	p = temp = g_strdup (desc);
fc9aca
-	while (*p) {
fc9aca
-		if (*p == '_' || *p == ',')
fc9aca
+	/* restore original non-UTF-8-safe text. */
fc9aca
+	desc_full = nm_utils_str_utf8safe_unescape_cp (desc);
fc9aca
+
fc9aca
+	/* replace all invalid UTF-8 bytes with space. */
fc9aca
+	p = desc_full;
fc9aca
+	while (!g_utf8_validate (p, -1, (const char **) &q)) {
fc9aca
+		/* the byte is invalid UTF-8. Replace it with space and proceed. */
fc9aca
+		*q = ' ';
fc9aca
+		p = q + 1;
fc9aca
+	}
fc9aca
+
fc9aca
+	/* replace '_', ',', and ASCII controll characters with space. */
fc9aca
+	for (p = desc_full; p[0]; p++) {
fc9aca
+		if (   NM_IN_SET (*p, '_', ',')
fc9aca
+		    || *p < ' ')
fc9aca
 			*p = ' ';
fc9aca
-		p++;
fc9aca
 	}
fc9aca
 
fc9aca
 	/* Attempt to shorten ID by ignoring certain phrases */
fc9aca
-	for (i = 0; ignored_phrases[i]; i++) {
fc9aca
-		p = strstr (temp, ignored_phrases[i]);
fc9aca
+	for (i = 0; i < G_N_ELEMENTS (IGNORED_PHRASES); i++) {
fc9aca
+		p = strstr (desc_full, IGNORED_PHRASES[i]);
fc9aca
 		if (p) {
fc9aca
-			guint32 ignored_len = strlen (ignored_phrases[i]);
fc9aca
+			const char *eow = &p[strlen (IGNORED_PHRASES[i])];
fc9aca
 
fc9aca
-			memmove (p, p + ignored_len, strlen (p + ignored_len) + 1); /* +1 for the \0 */
fc9aca
+			memmove (p, eow, strlen (eow) + 1); /* +1 for the \0 */
fc9aca
 		}
fc9aca
 	}
fc9aca
 
fc9aca
-	/* Attempt to shorten ID by ignoring certain individual words */
fc9aca
-	words = g_strsplit (temp, " ", 0);
fc9aca
-	str = g_string_new_len (NULL, strlen (temp));
fc9aca
-	g_free (temp);
fc9aca
-
fc9aca
-	for (item = words; *item; item++) {
fc9aca
-		gboolean ignore = FALSE;
fc9aca
-
fc9aca
-		if (**item == '\0')
fc9aca
-			continue;
fc9aca
-
fc9aca
-		for (i = 0; ignored_words[i]; i++) {
fc9aca
-			if (!strcmp (*item, ignored_words[i])) {
fc9aca
-				ignore = TRUE;
fc9aca
-				break;
fc9aca
-			}
fc9aca
+	/* Attempt to shorten ID by ignoring certain individual words.
fc9aca
+	 * - word-split the description at spaces
fc9aca
+	 * - coalesce multiple spaces
fc9aca
+	 * - skip over IGNORED_WORDS */
fc9aca
+	p = desc_full;
fc9aca
+	q = desc_full;
fc9aca
+	for (;;) {
fc9aca
+		char *eow;
fc9aca
+		gsize l;
fc9aca
+
fc9aca
+		/* skip leading spaces. */
fc9aca
+		while (p[0] == ' ')
fc9aca
+			p++;
fc9aca
+
fc9aca
+		if (!p[0])
fc9aca
+			break;
fc9aca
+
fc9aca
+		/* split leading word on first space */
fc9aca
+		eow = strchr (p, ' ');
fc9aca
+		if (eow)
fc9aca
+			*eow = '\0';
fc9aca
+
fc9aca
+		if (nm_utils_strv_find_first ((char **) IGNORED_WORDS,
fc9aca
+		                              G_N_ELEMENTS (IGNORED_WORDS),
fc9aca
+		                              p) < 0)
fc9aca
+			goto next;
fc9aca
+
fc9aca
+		l = strlen (p);
fc9aca
+		if (q != p) {
fc9aca
+			if (q != desc_full)
fc9aca
+				*q++ = ' ';
fc9aca
+			memmove (q, p, l);
fc9aca
 		}
fc9aca
+		q += l;
fc9aca
 
fc9aca
-		if (!ignore) {
fc9aca
-			if (str->len)
fc9aca
-				g_string_append_c (str, ' ');
fc9aca
-			g_string_append (str, *item);
fc9aca
-		}
fc9aca
+next:
fc9aca
+		if (!eow)
fc9aca
+			break;
fc9aca
+		p = eow + 1;
fc9aca
 	}
fc9aca
-	g_strfreev (words);
fc9aca
 
fc9aca
-	temp = str->str;
fc9aca
-	g_string_free (str, FALSE);
fc9aca
+	*q++ = '\0';
fc9aca
 
fc9aca
-	return temp;
fc9aca
+	if (!desc_full[0]) {
fc9aca
+		g_free (desc_full);
fc9aca
+		return NULL;
fc9aca
+	}
fc9aca
+
fc9aca
+	nm_assert (g_utf8_validate (desc_full, -1, NULL));
fc9aca
+	return desc_full;
fc9aca
 }
fc9aca
 
fc9aca
 static void
fc9aca
-get_description (NMDevice *device)
fc9aca
+ensure_description (NMDevice *device)
fc9aca
 {
fc9aca
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
fc9aca
-	const char *dev_product;
fc9aca
-	const char *dev_vendor;
fc9aca
-	char *pdown;
fc9aca
-	char *vdown;
fc9aca
-	GString *str;
fc9aca
 	GParamSpec *name_prop;
fc9aca
+	gs_free char *short_product = NULL;
fc9aca
 
fc9aca
-	dev_product = nm_device_get_product (device);
fc9aca
-	priv->short_product = fixup_desc_string (dev_product);
fc9aca
-
fc9aca
-	dev_vendor = nm_device_get_vendor (device);
fc9aca
-	priv->short_vendor = fixup_desc_string (dev_vendor);
fc9aca
+	priv->short_vendor = nm_str_realloc (fixup_desc_string (nm_device_get_vendor (device)));
fc9aca
 
fc9aca
 	/* Grab device's preferred name, if any */
fc9aca
 	name_prop = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (device)), "name");
fc9aca
@@ -1546,28 +1581,24 @@ get_description (NMDevice *device)
fc9aca
 		g_clear_pointer (&priv->description, g_free);
fc9aca
 	}
fc9aca
 
fc9aca
-	if (!dev_product || !dev_vendor) {
fc9aca
-		priv->description = g_strdup (nm_device_get_iface (device));
fc9aca
+	if (   !priv->short_vendor
fc9aca
+	    || !(short_product = fixup_desc_string (nm_device_get_product (device)))) {
fc9aca
+		priv->description = g_strdup (nm_device_get_iface (device) ?: "");
fc9aca
 		return;
fc9aca
 	}
fc9aca
 
fc9aca
-	str = g_string_new_len (NULL, strlen (priv->short_vendor) + strlen (priv->short_product) + 1);
fc9aca
-
fc9aca
 	/* Another quick hack; if all of the fixed up vendor string
fc9aca
 	 * is found in product, ignore the vendor.
fc9aca
 	 */
fc9aca
-	pdown = g_ascii_strdown (priv->short_product, -1);
fc9aca
-	vdown = g_ascii_strdown (priv->short_vendor, -1);
fc9aca
-	if (!strstr (pdown, vdown)) {
fc9aca
-		g_string_append (str, priv->short_vendor);
fc9aca
-		g_string_append_c (str, ' ');
fc9aca
+	{
fc9aca
+		gs_free char *pdown = g_ascii_strdown (short_product, -1);
fc9aca
+		gs_free char *vdown = g_ascii_strdown (priv->short_vendor, -1);
fc9aca
+
fc9aca
+		if (!strstr (pdown, vdown))
fc9aca
+			priv->description = g_strconcat (priv->short_vendor, " ", short_product, NULL);
fc9aca
+		else
fc9aca
+			priv->description = g_steal_pointer (&short_product);
fc9aca
 	}
fc9aca
-	g_free (pdown);
fc9aca
-	g_free (vdown);
fc9aca
-
fc9aca
-	g_string_append (str, priv->short_product);
fc9aca
-
fc9aca
-	priv->description = g_string_free (str, FALSE);
fc9aca
 }
fc9aca
 
fc9aca
 static const char *
fc9aca
@@ -1580,7 +1611,7 @@ get_short_vendor (NMDevice *device)
fc9aca
 	priv = NM_DEVICE_GET_PRIVATE (device);
fc9aca
 
fc9aca
 	if (!priv->description)
fc9aca
-		get_description (device);
fc9aca
+		ensure_description (device);
fc9aca
 
fc9aca
 	return priv->short_vendor;
fc9aca
 }
fc9aca
@@ -1604,7 +1635,7 @@ nm_device_get_description (NMDevice *device)
fc9aca
 	priv = NM_DEVICE_GET_PRIVATE (device);
fc9aca
 
fc9aca
 	if (!priv->description)
fc9aca
-		get_description (device);
fc9aca
+		ensure_description (device);
fc9aca
 
fc9aca
 	return priv->description;
fc9aca
 }
fc9aca
-- 
fc9aca
2.9.4
fc9aca
fc9aca
fc9aca
From aee0c50ffa840e67642749189bd323620fff8d93 Mon Sep 17 00:00:00 2001
fc9aca
From: Thomas Haller <thaller@redhat.com>
fc9aca
Date: Fri, 19 May 2017 10:18:59 +0200
fc9aca
Subject: [PATCH 08/13] libnm: fix device description in fixup_desc_string()
fc9aca
fc9aca
Fixes: b9e9f7616556f693e2642ed433f3289f9c6da452
fc9aca
(cherry picked from commit 12c881ad40c4829eb430bd0148fa5dbbdfd0ec01)
fc9aca
(cherry picked from commit c22075dc98fc79021e9a4847b57188f09b489ddd)
fc9aca
---
fc9aca
 libnm/nm-device.c | 2 +-
fc9aca
 1 file changed, 1 insertion(+), 1 deletion(-)
fc9aca
fc9aca
diff --git a/libnm/nm-device.c b/libnm/nm-device.c
fc9aca
index 7e8feb1..6c27190 100644
fc9aca
--- a/libnm/nm-device.c
fc9aca
+++ b/libnm/nm-device.c
fc9aca
@@ -1535,7 +1535,7 @@ fixup_desc_string (const char *desc)
fc9aca
 
fc9aca
 		if (nm_utils_strv_find_first ((char **) IGNORED_WORDS,
fc9aca
 		                              G_N_ELEMENTS (IGNORED_WORDS),
fc9aca
-		                              p) < 0)
fc9aca
+		                              p) >= 0)
fc9aca
 			goto next;
fc9aca
 
fc9aca
 		l = strlen (p);
fc9aca
-- 
fc9aca
2.9.4
fc9aca
fc9aca
fc9aca
From 47527d343339cf0df13fa852ef73c5d0e4713890 Mon Sep 17 00:00:00 2001
fc9aca
From: Thomas Haller <thaller@redhat.com>
fc9aca
Date: Fri, 19 May 2017 11:01:23 +0200
fc9aca
Subject: [PATCH 09/13] libnm: ignore phrases in fixup device description only
fc9aca
 when delimited by space
fc9aca
fc9aca
(cherry picked from commit 72104ea10a26d4b4ff245ed60c5ccd5c043c5fe0)
fc9aca
(cherry picked from commit aa60b77146641db5f5d670356d8244f46dd90f81)
fc9aca
---
fc9aca
 libnm/nm-device.c | 6 +++++-
fc9aca
 1 file changed, 5 insertions(+), 1 deletion(-)
fc9aca
fc9aca
diff --git a/libnm/nm-device.c b/libnm/nm-device.c
fc9aca
index 6c27190..3a6052b 100644
fc9aca
--- a/libnm/nm-device.c
fc9aca
+++ b/libnm/nm-device.c
fc9aca
@@ -1507,7 +1507,11 @@ fixup_desc_string (const char *desc)
fc9aca
 		if (p) {
fc9aca
 			const char *eow = &p[strlen (IGNORED_PHRASES[i])];
fc9aca
 
fc9aca
-			memmove (p, eow, strlen (eow) + 1); /* +1 for the \0 */
fc9aca
+			/* require that the phrase is delimited by space, or
fc9aca
+			 * at the beginning or end of the description. */
fc9aca
+			if (   (p == desc_full || p[-1] == ' ')
fc9aca
+			    && NM_IN_SET (eow[0], '\0', ' '))
fc9aca
+				memmove (p, eow, strlen (eow) + 1); /* +1 for the \0 */
fc9aca
 		}
fc9aca
 	}
fc9aca
 
fc9aca
-- 
fc9aca
2.9.4
fc9aca
fc9aca
fc9aca
From 6bc607bd944e83eb4e1c668bba5f750ac98ea451 Mon Sep 17 00:00:00 2001
fc9aca
From: Thomas Haller <thaller@redhat.com>
fc9aca
Date: Fri, 19 May 2017 10:19:25 +0200
fc9aca
Subject: [PATCH 10/13] libnm: add testable libnm/nm-libnm-utils.c file
fc9aca
fc9aca
Previously, internal parts of libnm were not testable.
fc9aca
Instead, add "libnm/nm-libnm-utils.c" and "libnm/libnm-utils.la"
fc9aca
to contain code that can be statically linked with a new
fc9aca
test "libnm/tests/test-general".
fc9aca
fc9aca
(cherry picked from commit 8df944c7e495d18bfecaf9d8316ef7783039c94b)
fc9aca
(cherry picked from commit 1ebac60d2219dd29634e5d375f487d5ffa624266)
fc9aca
---
fc9aca
 Makefile.am                | 45 ++++++++++++++++++++++++++++++++++++++-------
fc9aca
 libnm/nm-libnm-utils.c     | 27 +++++++++++++++++++++++++++
fc9aca
 libnm/nm-libnm-utils.h     | 26 ++++++++++++++++++++++++++
fc9aca
 libnm/tests/test-general.c | 34 ++++++++++++++++++++++++++++++++++
fc9aca
 4 files changed, 125 insertions(+), 7 deletions(-)
fc9aca
 create mode 100644 libnm/nm-libnm-utils.c
fc9aca
 create mode 100644 libnm/nm-libnm-utils.h
fc9aca
 create mode 100644 libnm/tests/test-general.c
fc9aca
fc9aca
diff --git a/Makefile.am b/Makefile.am
fc9aca
index 709d79b..a6776e9 100644
fc9aca
--- a/Makefile.am
fc9aca
+++ b/Makefile.am
fc9aca
@@ -734,6 +734,7 @@ libnm_lib_h_pub_nointrospect = \
fc9aca
 libnm_lib_h_pub_mkenums = \
fc9aca
 	libnm/nm-enum-types.h
fc9aca
 libnm_lib_h_priv = \
fc9aca
+	libnm/nm-libnm-utils.h \
fc9aca
 	libnm/nm-dbus-helpers.h \
fc9aca
 	libnm/nm-device-private.h \
fc9aca
 	libnm/nm-dhcp4-config.h \
fc9aca
@@ -790,6 +791,14 @@ libnm_lib_c_real = \
fc9aca
 libnm_lib_c_mkenums = \
fc9aca
 	libnm/nm-enum-types.c
fc9aca
 
fc9aca
+libnm_lib_cppflags = \
fc9aca
+	$(dflt_cppflags_libnm_core) \
fc9aca
+	-I$(srcdir)/libnm \
fc9aca
+	-I$(builddir)/libnm \
fc9aca
+	-DG_LOG_DOMAIN=\""libnm"\" \
fc9aca
+	-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_LIB \
fc9aca
+	-DNMRUNDIR=\"$(nmrundir)\"
fc9aca
+
fc9aca
 libnminclude_HEADERS += \
fc9aca
 	$(libnm_lib_h_pub_real) \
fc9aca
 	$(libnm_lib_h_pub_nointrospect)
fc9aca
@@ -799,6 +808,23 @@ nodist_libnminclude_HEADERS += \
fc9aca
 
fc9aca
 ###############################################################################
fc9aca
 
fc9aca
+lib_LTLIBRARIES += libnm/libnm-utils.la
fc9aca
+
fc9aca
+libnm_libnm_utils_la_CPPFLAGS = \
fc9aca
+	$(libnm_lib_cppflags)
fc9aca
+
fc9aca
+libnm_libnm_utils_la_SOURCES = \
fc9aca
+	libnm/nm-libnm-utils.c
fc9aca
+
fc9aca
+libnm_libnm_utils_la_LIBADD = \
fc9aca
+	libnm-core/libnm-core.la \
fc9aca
+	introspection/libnmdbus.la \
fc9aca
+	$(GLIB_LIBS)
fc9aca
+
fc9aca
+$(libnm_libnm_utils_la_OBJECTS) : $(libnm_lib_h_pub_mkenums)
fc9aca
+
fc9aca
+###############################################################################
fc9aca
+
fc9aca
 lib_LTLIBRARIES += libnm/libnm.la
fc9aca
 
fc9aca
 GLIB_GENERATED += \
fc9aca
@@ -817,13 +843,8 @@ $(libnm_libnm_la_OBJECTS):                              $(libnm_lib_h_pub_mkenum
fc9aca
 $(libnm_tests_libnm_vpn_plugin_utils_test_la_OBJECTS):  $(libnm_core_lib_h_pub_mkenums)
fc9aca
 
fc9aca
 libnm_libnm_la_CPPFLAGS = \
fc9aca
-	$(dflt_cppflags_libnm_core) \
fc9aca
-	-I$(srcdir)/libnm \
fc9aca
-	-I$(builddir)/libnm \
fc9aca
-	$(LIBUDEV_CFLAGS) \
fc9aca
-	-DG_LOG_DOMAIN=\""libnm"\" \
fc9aca
-	-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_LIB \
fc9aca
-	-DNMRUNDIR=\"$(nmrundir)\"
fc9aca
+	$(libnm_lib_cppflags) \
fc9aca
+	$(LIBUDEV_CFLAGS)
fc9aca
 
fc9aca
 libnm_libnm_la_SOURCES = \
fc9aca
 	$(libnm_lib_h_pub_real) \
fc9aca
@@ -841,6 +862,7 @@ EXTRA_libnm_libnm_la_DEPENDENCIES = \
fc9aca
 libnm_libnm_la_LIBADD = \
fc9aca
 	libnm-core/libnm-core.la \
fc9aca
 	introspection/libnmdbus.la \
fc9aca
+	libnm/libnm-utils.la \
fc9aca
 	$(DL_LIBS) \
fc9aca
 	$(GLIB_LIBS) \
fc9aca
 	$(UUID_LIBS) \
fc9aca
@@ -947,6 +969,7 @@ EXTRA_DIST += \
fc9aca
 ###############################################################################
fc9aca
 
fc9aca
 libnm_tests_programs = \
fc9aca
+	libnm/tests/test-general \
fc9aca
 	libnm/tests/test-nm-client \
fc9aca
 	libnm/tests/test-remote-settings-client \
fc9aca
 	libnm/tests/test-secret-agent
fc9aca
@@ -964,10 +987,14 @@ libnm_tests_ldadd = \
fc9aca
 	libnm/libnm.la \
fc9aca
 	$(GLIB_LIBS)
fc9aca
 
fc9aca
+libnm_tests_test_general_CPPFLAGS = $(libnm_tests_cppflags)
fc9aca
 libnm_tests_test_nm_client_CPPFLAGS = $(libnm_tests_cppflags)
fc9aca
 libnm_tests_test_remote_settings_client_CPPFLAGS = $(libnm_tests_cppflags)
fc9aca
 libnm_tests_test_secret_agent_CPPFLAGS = $(libnm_tests_cppflags)
fc9aca
 
fc9aca
+libnm_tests_test_general_SOURCES = \
fc9aca
+	libnm/tests/test-general.c
fc9aca
+
fc9aca
 libnm_tests_test_nm_client_SOURCES = \
fc9aca
 	shared/nm-test-utils-impl.c \
fc9aca
 	shared/nm-test-libnm-utils.h \
fc9aca
@@ -983,10 +1010,14 @@ libnm_tests_test_secret_agent_SOURCES = \
fc9aca
 	shared/nm-test-libnm-utils.h \
fc9aca
 	libnm/tests/test-secret-agent.c
fc9aca
 
fc9aca
+libnm_tests_test_general_LDADD = \
fc9aca
+	libnm/libnm-utils.la \
fc9aca
+	$(libnm_tests_ldadd)
fc9aca
 libnm_tests_test_nm_client_LDADD = $(libnm_tests_ldadd)
fc9aca
 libnm_tests_test_remote_settings_client_LDADD = $(libnm_tests_ldadd)
fc9aca
 libnm_tests_test_secret_agent_LDADD = $(libnm_tests_ldadd)
fc9aca
 
fc9aca
+$(libnm_tests_test_general_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
fc9aca
 $(libnm_tests_test_nm_client_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
fc9aca
 $(libnm_tests_test_remote_settings_client_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
fc9aca
 $(libnm_tests_test_secret_agent_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
fc9aca
diff --git a/libnm/nm-libnm-utils.c b/libnm/nm-libnm-utils.c
fc9aca
new file mode 100644
fc9aca
index 0000000..8cea276
fc9aca
--- /dev/null
fc9aca
+++ b/libnm/nm-libnm-utils.c
fc9aca
@@ -0,0 +1,27 @@
fc9aca
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
fc9aca
+/*
fc9aca
+ * This library is free software; you can redistribute it and/or
fc9aca
+ * modify it under the terms of the GNU Lesser General Public
fc9aca
+ * License as published by the Free Software Foundation; either
fc9aca
+ * version 2 of the License, or (at your option) any later version.
fc9aca
+ *
fc9aca
+ * This library is distributed in the hope that it will be useful,
fc9aca
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
fc9aca
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
fc9aca
+ * Lesser General Public License for more details.
fc9aca
+ *
fc9aca
+ * You should have received a copy of the GNU Lesser General Public
fc9aca
+ * License along with this library; if not, write to the
fc9aca
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
fc9aca
+ * Boston, MA 02110-1301 USA.
fc9aca
+ *
fc9aca
+ * Copyright 2007 - 2008 Novell, Inc.
fc9aca
+ * Copyright 2007 - 2017 Red Hat, Inc.
fc9aca
+ */
fc9aca
+
fc9aca
+#include "nm-default.h"
fc9aca
+
fc9aca
+#include "nm-libnm-utils.h"
fc9aca
+
fc9aca
+/*****************************************************************************/
fc9aca
+
fc9aca
diff --git a/libnm/nm-libnm-utils.h b/libnm/nm-libnm-utils.h
fc9aca
new file mode 100644
fc9aca
index 0000000..356b2f9
fc9aca
--- /dev/null
fc9aca
+++ b/libnm/nm-libnm-utils.h
fc9aca
@@ -0,0 +1,26 @@
fc9aca
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
fc9aca
+/*
fc9aca
+ * This library is free software; you can redistribute it and/or
fc9aca
+ * modify it under the terms of the GNU Lesser General Public
fc9aca
+ * License as published by the Free Software Foundation; either
fc9aca
+ * version 2 of the License, or (at your option) any later version.
fc9aca
+ *
fc9aca
+ * This library is distributed in the hope that it will be useful,
fc9aca
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
fc9aca
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
fc9aca
+ * Lesser General Public License for more details.
fc9aca
+ *
fc9aca
+ * You should have received a copy of the GNU Lesser General Public
fc9aca
+ * License along with this library; if not, write to the
fc9aca
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
fc9aca
+ * Boston, MA 02110-1301 USA.
fc9aca
+ *
fc9aca
+ * Copyright 2017 Red Hat, Inc.
fc9aca
+ */
fc9aca
+
fc9aca
+#ifndef __NM_LIBNM_UTILS_H__
fc9aca
+#define __NM_LIBNM_UTILS_H__
fc9aca
+
fc9aca
+
fc9aca
+
fc9aca
+#endif /* __NM_LIBNM_UTILS_H__ */
fc9aca
diff --git a/libnm/tests/test-general.c b/libnm/tests/test-general.c
fc9aca
new file mode 100644
fc9aca
index 0000000..2653cb9
fc9aca
--- /dev/null
fc9aca
+++ b/libnm/tests/test-general.c
fc9aca
@@ -0,0 +1,34 @@
fc9aca
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
fc9aca
+/*
fc9aca
+ *
fc9aca
+ * This program is free software; you can redistribute it and/or modify
fc9aca
+ * it under the terms of the GNU General Public License as published by
fc9aca
+ * the Free Software Foundation; either version 2, or (at your option)
fc9aca
+ * any later version.
fc9aca
+ *
fc9aca
+ * This program is distributed in the hope that it will be useful,
fc9aca
+ * but WITHOUT SC WARRANTY; without even the implied warranty of
fc9aca
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
fc9aca
+ * GNU General Public License for more details.
fc9aca
+ *
fc9aca
+ * You should have received a copy of the GNU General Public License along
fc9aca
+ * with this program; if not, write to the Free Software Foundation, Inc.,
fc9aca
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
fc9aca
+ *
fc9aca
+ * Copyright 2017 Red Hat, Inc.
fc9aca
+ */
fc9aca
+
fc9aca
+#include "nm-default.h"
fc9aca
+
fc9aca
+#include "nm-utils/nm-test-utils.h"
fc9aca
+
fc9aca
+/*****************************************************************************/
fc9aca
+
fc9aca
+NMTST_DEFINE ();
fc9aca
+
fc9aca
+int main (int argc, char **argv)
fc9aca
+{
fc9aca
+	nmtst_init (&argc, &argv, TRUE);
fc9aca
+
fc9aca
+	return g_test_run ();
fc9aca
+}
fc9aca
-- 
fc9aca
2.9.4
fc9aca
fc9aca
fc9aca
From 3ac56f2ad81a4104f0bc3b95ebcc648fe8445c1d Mon Sep 17 00:00:00 2001
fc9aca
From: Thomas Haller <thaller@redhat.com>
fc9aca
Date: Fri, 19 May 2017 10:32:13 +0200
fc9aca
Subject: [PATCH 11/13] libnm: move fixup_desc_string() to nm-libnm-utils.c
fc9aca
fc9aca
(cherry picked from commit e255ad2a03c84f806f9606b420fa12757bbd883f)
fc9aca
(cherry picked from commit ea0fd21428bd3b287a6537d9238a53f174c8854c)
fc9aca
---
fc9aca
 libnm/nm-device.c          | 141 +--------------------------------------------
fc9aca
 libnm/nm-libnm-utils.c     | 135 +++++++++++++++++++++++++++++++++++++++++++
fc9aca
 libnm/nm-libnm-utils.h     |   2 +-
fc9aca
 libnm/tests/test-general.c |  35 +++++++++++
fc9aca
 4 files changed, 174 insertions(+), 139 deletions(-)
fc9aca
fc9aca
diff --git a/libnm/nm-device.c b/libnm/nm-device.c
fc9aca
index 3a6052b..969d08a 100644
fc9aca
--- a/libnm/nm-device.c
fc9aca
+++ b/libnm/nm-device.c
fc9aca
@@ -26,6 +26,7 @@
fc9aca
 #include <string.h>
fc9aca
 #include <libudev.h>
fc9aca
 
fc9aca
+#include "nm-libnm-utils.h"
fc9aca
 #include "nm-dbus-interface.h"
fc9aca
 #include "nm-active-connection.h"
fc9aca
 #include "nm-device-bt.h"
fc9aca
@@ -1431,142 +1432,6 @@ nm_device_get_vendor (NMDevice *device)
fc9aca
 	return priv->vendor;
fc9aca
 }
fc9aca
 
fc9aca
-static char *
fc9aca
-fixup_desc_string (const char *desc)
fc9aca
-{
fc9aca
-	static const char *const IGNORED_PHRASES[] = {
fc9aca
-		"Multiprotocol MAC/baseband processor",
fc9aca
-		"Wireless LAN Controller",
fc9aca
-		"Wireless LAN Adapter",
fc9aca
-		"Wireless Adapter",
fc9aca
-		"Network Connection",
fc9aca
-		"Wireless Cardbus Adapter",
fc9aca
-		"Wireless CardBus Adapter",
fc9aca
-		"54 Mbps Wireless PC Card",
fc9aca
-		"Wireless PC Card",
fc9aca
-		"Wireless PC",
fc9aca
-		"PC Card with XJACK(r) Antenna",
fc9aca
-		"Wireless cardbus",
fc9aca
-		"Wireless LAN PC Card",
fc9aca
-		"Technology Group Ltd.",
fc9aca
-		"Communication S.p.A.",
fc9aca
-		"Business Mobile Networks BV",
fc9aca
-		"Mobile Broadband Minicard Composite Device",
fc9aca
-		"Mobile Communications AB",
fc9aca
-		"(PC-Suite Mode)",
fc9aca
-	};
fc9aca
-	static const char *const IGNORED_WORDS[] = {
fc9aca
-		"Semiconductor",
fc9aca
-		"Components",
fc9aca
-		"Corporation",
fc9aca
-		"Communications",
fc9aca
-		"Company",
fc9aca
-		"Corp.",
fc9aca
-		"Corp",
fc9aca
-		"Co.",
fc9aca
-		"Inc.",
fc9aca
-		"Inc",
fc9aca
-		"Incorporated",
fc9aca
-		"Ltd.",
fc9aca
-		"Limited.",
fc9aca
-		"Intel?",
fc9aca
-		"chipset",
fc9aca
-		"adapter",
fc9aca
-		"[hex]",
fc9aca
-		"NDIS",
fc9aca
-		"Module",
fc9aca
-	};
fc9aca
-	char *desc_full;
fc9aca
-	char *p, *q;
fc9aca
-	int i;
fc9aca
-
fc9aca
-	if (!desc || !desc[0])
fc9aca
-		return NULL;
fc9aca
-
fc9aca
-	/* restore original non-UTF-8-safe text. */
fc9aca
-	desc_full = nm_utils_str_utf8safe_unescape_cp (desc);
fc9aca
-
fc9aca
-	/* replace all invalid UTF-8 bytes with space. */
fc9aca
-	p = desc_full;
fc9aca
-	while (!g_utf8_validate (p, -1, (const char **) &q)) {
fc9aca
-		/* the byte is invalid UTF-8. Replace it with space and proceed. */
fc9aca
-		*q = ' ';
fc9aca
-		p = q + 1;
fc9aca
-	}
fc9aca
-
fc9aca
-	/* replace '_', ',', and ASCII controll characters with space. */
fc9aca
-	for (p = desc_full; p[0]; p++) {
fc9aca
-		if (   NM_IN_SET (*p, '_', ',')
fc9aca
-		    || *p < ' ')
fc9aca
-			*p = ' ';
fc9aca
-	}
fc9aca
-
fc9aca
-	/* Attempt to shorten ID by ignoring certain phrases */
fc9aca
-	for (i = 0; i < G_N_ELEMENTS (IGNORED_PHRASES); i++) {
fc9aca
-		p = strstr (desc_full, IGNORED_PHRASES[i]);
fc9aca
-		if (p) {
fc9aca
-			const char *eow = &p[strlen (IGNORED_PHRASES[i])];
fc9aca
-
fc9aca
-			/* require that the phrase is delimited by space, or
fc9aca
-			 * at the beginning or end of the description. */
fc9aca
-			if (   (p == desc_full || p[-1] == ' ')
fc9aca
-			    && NM_IN_SET (eow[0], '\0', ' '))
fc9aca
-				memmove (p, eow, strlen (eow) + 1); /* +1 for the \0 */
fc9aca
-		}
fc9aca
-	}
fc9aca
-
fc9aca
-	/* Attempt to shorten ID by ignoring certain individual words.
fc9aca
-	 * - word-split the description at spaces
fc9aca
-	 * - coalesce multiple spaces
fc9aca
-	 * - skip over IGNORED_WORDS */
fc9aca
-	p = desc_full;
fc9aca
-	q = desc_full;
fc9aca
-	for (;;) {
fc9aca
-		char *eow;
fc9aca
-		gsize l;
fc9aca
-
fc9aca
-		/* skip leading spaces. */
fc9aca
-		while (p[0] == ' ')
fc9aca
-			p++;
fc9aca
-
fc9aca
-		if (!p[0])
fc9aca
-			break;
fc9aca
-
fc9aca
-		/* split leading word on first space */
fc9aca
-		eow = strchr (p, ' ');
fc9aca
-		if (eow)
fc9aca
-			*eow = '\0';
fc9aca
-
fc9aca
-		if (nm_utils_strv_find_first ((char **) IGNORED_WORDS,
fc9aca
-		                              G_N_ELEMENTS (IGNORED_WORDS),
fc9aca
-		                              p) >= 0)
fc9aca
-			goto next;
fc9aca
-
fc9aca
-		l = strlen (p);
fc9aca
-		if (q != p) {
fc9aca
-			if (q != desc_full)
fc9aca
-				*q++ = ' ';
fc9aca
-			memmove (q, p, l);
fc9aca
-		}
fc9aca
-		q += l;
fc9aca
-
fc9aca
-next:
fc9aca
-		if (!eow)
fc9aca
-			break;
fc9aca
-		p = eow + 1;
fc9aca
-	}
fc9aca
-
fc9aca
-	*q++ = '\0';
fc9aca
-
fc9aca
-	if (!desc_full[0]) {
fc9aca
-		g_free (desc_full);
fc9aca
-		return NULL;
fc9aca
-	}
fc9aca
-
fc9aca
-	nm_assert (g_utf8_validate (desc_full, -1, NULL));
fc9aca
-	return desc_full;
fc9aca
-}
fc9aca
-
fc9aca
 static void
fc9aca
 ensure_description (NMDevice *device)
fc9aca
 {
fc9aca
@@ -1574,7 +1439,7 @@ ensure_description (NMDevice *device)
fc9aca
 	GParamSpec *name_prop;
fc9aca
 	gs_free char *short_product = NULL;
fc9aca
 
fc9aca
-	priv->short_vendor = nm_str_realloc (fixup_desc_string (nm_device_get_vendor (device)));
fc9aca
+	priv->short_vendor = nm_str_realloc (nm_utils_fixup_desc_string (nm_device_get_vendor (device)));
fc9aca
 
fc9aca
 	/* Grab device's preferred name, if any */
fc9aca
 	name_prop = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (device)), "name");
fc9aca
@@ -1586,7 +1451,7 @@ ensure_description (NMDevice *device)
fc9aca
 	}
fc9aca
 
fc9aca
 	if (   !priv->short_vendor
fc9aca
-	    || !(short_product = fixup_desc_string (nm_device_get_product (device)))) {
fc9aca
+	    || !(short_product = nm_utils_fixup_desc_string (nm_device_get_product (device)))) {
fc9aca
 		priv->description = g_strdup (nm_device_get_iface (device) ?: "");
fc9aca
 		return;
fc9aca
 	}
fc9aca
diff --git a/libnm/nm-libnm-utils.c b/libnm/nm-libnm-utils.c
fc9aca
index 8cea276..fbbfe2c 100644
fc9aca
--- a/libnm/nm-libnm-utils.c
fc9aca
+++ b/libnm/nm-libnm-utils.c
fc9aca
@@ -25,3 +25,138 @@
fc9aca
 
fc9aca
 /*****************************************************************************/
fc9aca
 
fc9aca
+char *
fc9aca
+nm_utils_fixup_desc_string (const char *desc)
fc9aca
+{
fc9aca
+	static const char *const IGNORED_PHRASES[] = {
fc9aca
+		"Multiprotocol MAC/baseband processor",
fc9aca
+		"Wireless LAN Controller",
fc9aca
+		"Wireless LAN Adapter",
fc9aca
+		"Wireless Adapter",
fc9aca
+		"Network Connection",
fc9aca
+		"Wireless Cardbus Adapter",
fc9aca
+		"Wireless CardBus Adapter",
fc9aca
+		"54 Mbps Wireless PC Card",
fc9aca
+		"Wireless PC Card",
fc9aca
+		"Wireless PC",
fc9aca
+		"PC Card with XJACK(r) Antenna",
fc9aca
+		"Wireless cardbus",
fc9aca
+		"Wireless LAN PC Card",
fc9aca
+		"Technology Group Ltd.",
fc9aca
+		"Communication S.p.A.",
fc9aca
+		"Business Mobile Networks BV",
fc9aca
+		"Mobile Broadband Minicard Composite Device",
fc9aca
+		"Mobile Communications AB",
fc9aca
+		"(PC-Suite Mode)",
fc9aca
+	};
fc9aca
+	static const char *const IGNORED_WORDS[] = {
fc9aca
+		"Semiconductor",
fc9aca
+		"Components",
fc9aca
+		"Corporation",
fc9aca
+		"Communications",
fc9aca
+		"Company",
fc9aca
+		"Corp.",
fc9aca
+		"Corp",
fc9aca
+		"Co.",
fc9aca
+		"Inc.",
fc9aca
+		"Inc",
fc9aca
+		"Incorporated",
fc9aca
+		"Ltd.",
fc9aca
+		"Limited.",
fc9aca
+		"Intel?",
fc9aca
+		"chipset",
fc9aca
+		"adapter",
fc9aca
+		"[hex]",
fc9aca
+		"NDIS",
fc9aca
+		"Module",
fc9aca
+	};
fc9aca
+	char *desc_full;
fc9aca
+	char *p, *q;
fc9aca
+	int i;
fc9aca
+
fc9aca
+	if (!desc || !desc[0])
fc9aca
+		return NULL;
fc9aca
+
fc9aca
+	/* restore original non-UTF-8-safe text. */
fc9aca
+	desc_full = nm_utils_str_utf8safe_unescape_cp (desc);
fc9aca
+
fc9aca
+	/* replace all invalid UTF-8 bytes with space. */
fc9aca
+	p = desc_full;
fc9aca
+	while (!g_utf8_validate (p, -1, (const char **) &q)) {
fc9aca
+		/* the byte is invalid UTF-8. Replace it with space and proceed. */
fc9aca
+		*q = ' ';
fc9aca
+		p = q + 1;
fc9aca
+	}
fc9aca
+
fc9aca
+	/* replace '_', ',', and ASCII controll characters with space. */
fc9aca
+	for (p = desc_full; p[0]; p++) {
fc9aca
+		if (   NM_IN_SET (*p, '_', ',')
fc9aca
+		    || *p < ' ')
fc9aca
+			*p = ' ';
fc9aca
+	}
fc9aca
+
fc9aca
+	/* Attempt to shorten ID by ignoring certain phrases */
fc9aca
+	for (i = 0; i < G_N_ELEMENTS (IGNORED_PHRASES); i++) {
fc9aca
+		p = strstr (desc_full, IGNORED_PHRASES[i]);
fc9aca
+		if (p) {
fc9aca
+			const char *eow = &p[strlen (IGNORED_PHRASES[i])];
fc9aca
+
fc9aca
+			/* require that the phrase is delimited by space, or
fc9aca
+			 * at the beginning or end of the description. */
fc9aca
+			if (   (p == desc_full || p[-1] == ' ')
fc9aca
+			    && NM_IN_SET (eow[0], '\0', ' '))
fc9aca
+				memmove (p, eow, strlen (eow) + 1); /* +1 for the \0 */
fc9aca
+		}
fc9aca
+	}
fc9aca
+
fc9aca
+	/* Attempt to shorten ID by ignoring certain individual words.
fc9aca
+	 * - word-split the description at spaces
fc9aca
+	 * - coalesce multiple spaces
fc9aca
+	 * - skip over IGNORED_WORDS */
fc9aca
+	p = desc_full;
fc9aca
+	q = desc_full;
fc9aca
+	for (;;) {
fc9aca
+		char *eow;
fc9aca
+		gsize l;
fc9aca
+
fc9aca
+		/* skip leading spaces. */
fc9aca
+		while (p[0] == ' ')
fc9aca
+			p++;
fc9aca
+
fc9aca
+		if (!p[0])
fc9aca
+			break;
fc9aca
+
fc9aca
+		/* split leading word on first space */
fc9aca
+		eow = strchr (p, ' ');
fc9aca
+		if (eow)
fc9aca
+			*eow = '\0';
fc9aca
+
fc9aca
+		if (nm_utils_strv_find_first ((char **) IGNORED_WORDS,
fc9aca
+		                              G_N_ELEMENTS (IGNORED_WORDS),
fc9aca
+		                              p) >= 0)
fc9aca
+			goto next;
fc9aca
+
fc9aca
+		l = strlen (p);
fc9aca
+		if (q != p) {
fc9aca
+			if (q != desc_full)
fc9aca
+				*q++ = ' ';
fc9aca
+			memmove (q, p, l);
fc9aca
+		}
fc9aca
+		q += l;
fc9aca
+
fc9aca
+next:
fc9aca
+		if (!eow)
fc9aca
+			break;
fc9aca
+		p = eow + 1;
fc9aca
+	}
fc9aca
+
fc9aca
+	*q++ = '\0';
fc9aca
+
fc9aca
+	if (!desc_full[0]) {
fc9aca
+		g_free (desc_full);
fc9aca
+		return NULL;
fc9aca
+	}
fc9aca
+
fc9aca
+	nm_assert (g_utf8_validate (desc_full, -1, NULL));
fc9aca
+	return desc_full;
fc9aca
+}
fc9aca
diff --git a/libnm/nm-libnm-utils.h b/libnm/nm-libnm-utils.h
fc9aca
index 356b2f9..4a5a361 100644
fc9aca
--- a/libnm/nm-libnm-utils.h
fc9aca
+++ b/libnm/nm-libnm-utils.h
fc9aca
@@ -21,6 +21,6 @@
fc9aca
 #ifndef __NM_LIBNM_UTILS_H__
fc9aca
 #define __NM_LIBNM_UTILS_H__
fc9aca
 
fc9aca
-
fc9aca
+char *nm_utils_fixup_desc_string (const char *desc);
fc9aca
 
fc9aca
 #endif /* __NM_LIBNM_UTILS_H__ */
fc9aca
diff --git a/libnm/tests/test-general.c b/libnm/tests/test-general.c
fc9aca
index 2653cb9..7e0b7bb 100644
fc9aca
--- a/libnm/tests/test-general.c
fc9aca
+++ b/libnm/tests/test-general.c
fc9aca
@@ -20,15 +20,50 @@
fc9aca
 
fc9aca
 #include "nm-default.h"
fc9aca
 
fc9aca
+#include "nm-libnm-utils.h"
fc9aca
+
fc9aca
 #include "nm-utils/nm-test-utils.h"
fc9aca
 
fc9aca
 /*****************************************************************************/
fc9aca
 
fc9aca
+static void
fc9aca
+do_test_fixup_desc_string (const char *desc, const char *expected)
fc9aca
+{
fc9aca
+	gs_free char *result = NULL;
fc9aca
+
fc9aca
+	result = nm_utils_fixup_desc_string (desc);
fc9aca
+	g_assert_cmpstr (result, ==, expected);
fc9aca
+}
fc9aca
+
fc9aca
+#define do_test_fixup_desc_string_same(desc) (do_test_fixup_desc_string (""desc"", ""desc""))
fc9aca
+
fc9aca
+static void
fc9aca
+test_fixup_desc_string (void)
fc9aca
+{
fc9aca
+	do_test_fixup_desc_string (NULL, NULL);
fc9aca
+	do_test_fixup_desc_string ("", NULL);
fc9aca
+	do_test_fixup_desc_string_same ("a");
fc9aca
+	do_test_fixup_desc_string_same ("a b");
fc9aca
+	do_test_fixup_desc_string ("a b ", "a b");
fc9aca
+	do_test_fixup_desc_string ("  a   bbc ", "a bbc");
fc9aca
+	do_test_fixup_desc_string ("  a \xcc  bbc ", "a bbc");
fc9aca
+	do_test_fixup_desc_string ("  a\xcc  bbc ", "a bbc");
fc9aca
+	do_test_fixup_desc_string ("  a\xcc""bbc Wireless PC", "a bbc");
fc9aca
+	do_test_fixup_desc_string ("  a\xcc""bbc Wireless PC ", "a bbc");
fc9aca
+	do_test_fixup_desc_string ("  a\xcc""bbcWireless PC ", "a bbcWireless PC");
fc9aca
+	do_test_fixup_desc_string ("  a\xcc""bbc Wireless PCx", "a bbc Wireless PCx");
fc9aca
+	do_test_fixup_desc_string ("  a\xcc""bbc Inc Wireless PC ", "a bbc");
fc9aca
+}
fc9aca
+
fc9aca
+/*****************************************************************************/
fc9aca
+
fc9aca
 NMTST_DEFINE ();
fc9aca
 
fc9aca
 int main (int argc, char **argv)
fc9aca
 {
fc9aca
 	nmtst_init (&argc, &argv, TRUE);
fc9aca
 
fc9aca
+	g_test_add_func ("/libnm/general/fixup_desc_string", test_fixup_desc_string);
fc9aca
+
fc9aca
 	return g_test_run ();
fc9aca
 }
fc9aca
-- 
fc9aca
2.9.4
fc9aca
fc9aca
fc9aca
From 1e5a95c89c35fadbefd6db21c20fcc4a7750063a Mon Sep 17 00:00:00 2001
fc9aca
From: Thomas Haller <thaller@redhat.com>
fc9aca
Date: Fri, 19 May 2017 14:13:37 +0200
fc9aca
Subject: [PATCH 12/13] build: don't install intermediate library
fc9aca
 libnm/libnm-utils.la
fc9aca
fc9aca
Fixes: 8df944c7e495d18bfecaf9d8316ef7783039c94b
fc9aca
(cherry picked from commit 733160c862452721821c508465429ffbbda203ae)
fc9aca
(cherry picked from commit 23b5bdd8435bfaf729488e1d3d8821cce948e92e)
fc9aca
---
fc9aca
 Makefile.am | 2 +-
fc9aca
 1 file changed, 1 insertion(+), 1 deletion(-)
fc9aca
fc9aca
diff --git a/Makefile.am b/Makefile.am
fc9aca
index a6776e9..7ba3603 100644
fc9aca
--- a/Makefile.am
fc9aca
+++ b/Makefile.am
fc9aca
@@ -808,7 +808,7 @@ nodist_libnminclude_HEADERS += \
fc9aca
 
fc9aca
 ###############################################################################
fc9aca
 
fc9aca
-lib_LTLIBRARIES += libnm/libnm-utils.la
fc9aca
+noinst_LTLIBRARIES += libnm/libnm-utils.la
fc9aca
 
fc9aca
 libnm_libnm_utils_la_CPPFLAGS = \
fc9aca
 	$(libnm_lib_cppflags)
fc9aca
-- 
fc9aca
2.9.4
fc9aca
fc9aca
fc9aca
From 32ec4059fd17a30003571c6d97c9859e84de92ed Mon Sep 17 00:00:00 2001
fc9aca
From: Thomas Haller <thaller@redhat.com>
fc9aca
Date: Fri, 19 May 2017 14:24:14 +0200
fc9aca
Subject: [PATCH 13/13] build: don't link static libraries multiple times
fc9aca
fc9aca
libnm-core.a should only be linked once in libnm.so. Previously,
fc9aca
it was linked twice, once as part of libnm-utils.a and once
fc9aca
directly in libnm.so.
fc9aca
fc9aca
Fixes: 8df944c7e495d18bfecaf9d8316ef7783039c94b
fc9aca
(cherry picked from commit 5a67130e1548bd9314fbd007e131ef378d8b51c7)
fc9aca
(cherry picked from commit da2a02138dc7f0c5aff41019a0517854f379a44c)
fc9aca
---
fc9aca
 Makefile.am | 2 --
fc9aca
 1 file changed, 2 deletions(-)
fc9aca
fc9aca
diff --git a/Makefile.am b/Makefile.am
fc9aca
index 7ba3603..909847e 100644
fc9aca
--- a/Makefile.am
fc9aca
+++ b/Makefile.am
fc9aca
@@ -860,8 +860,6 @@ EXTRA_libnm_libnm_la_DEPENDENCIES = \
fc9aca
 	libnm/libnm.ver
fc9aca
 
fc9aca
 libnm_libnm_la_LIBADD = \
fc9aca
-	libnm-core/libnm-core.la \
fc9aca
-	introspection/libnmdbus.la \
fc9aca
 	libnm/libnm-utils.la \
fc9aca
 	$(DL_LIBS) \
fc9aca
 	$(GLIB_LIBS) \
fc9aca
-- 
fc9aca
2.9.4
fc9aca