mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-25 09:30:16 +01:00
all: merge branch 'th/sanitize-non-utf8-rh1443114'
https://bugzilla.redhat.com/show_bug.cgi?id=1443114 https://bugzilla.redhat.com/show_bug.cgi?id=1451160 https://bugzilla.redhat.com/show_bug.cgi?id=1451286
This commit is contained in:
commit
dfd72a623e
7 changed files with 446 additions and 137 deletions
|
|
@ -21,6 +21,9 @@
|
|||
each device in your application, use the object path. If you're looking
|
||||
for a way to track a specific piece of hardware across reboot or hotplug,
|
||||
use a MAC address or USB serial number.
|
||||
|
||||
Note that non-UTF-8 characters are backslash escaped. Use g_strcompress()
|
||||
to obtain the true (non-UTF-8) string.
|
||||
-->
|
||||
<property name="Udi" type="s" access="read"/>
|
||||
|
||||
|
|
@ -28,6 +31,9 @@
|
|||
Interface:
|
||||
|
||||
The name of the device's control (and often data) interface.
|
||||
Note that non UTF-8 characters are backslash escaped, so the
|
||||
resulting name may be longer then 15 characters. Use g_strcompress()
|
||||
to revert the escaping.
|
||||
-->
|
||||
<property name="Interface" type="s" access="read"/>
|
||||
|
||||
|
|
@ -38,6 +44,9 @@
|
|||
not refer to the actual data interface until the device has successfully
|
||||
established a data connection, indicated by the device's State becoming
|
||||
ACTIVATED.
|
||||
Note that non UTF-8 characters are backslash escaped, so the
|
||||
resulting name may be longer then 15 characters. Use g_strcompress()
|
||||
to revert the escaping.
|
||||
-->
|
||||
<property name="IpInterface" type="s" access="read"/>
|
||||
|
||||
|
|
@ -45,6 +54,8 @@
|
|||
Driver:
|
||||
|
||||
The driver handling the device.
|
||||
Non-UTF-8 sequences are backslash escaped. Use g_strcompress()
|
||||
to revert.
|
||||
-->
|
||||
<property name="Driver" type="s" access="read"/>
|
||||
|
||||
|
|
@ -52,6 +63,8 @@
|
|||
DriverVersion:
|
||||
|
||||
The version of the driver handling the device.
|
||||
Non-UTF-8 sequences are backslash escaped. Use g_strcompress()
|
||||
to revert.
|
||||
-->
|
||||
<property name="DriverVersion" type="s" access="read"/>
|
||||
|
||||
|
|
@ -59,6 +72,8 @@
|
|||
FirmwareVersion:
|
||||
|
||||
The firmware version for the device.
|
||||
Non-UTF-8 sequences are backslash escaped. Use g_strcompress()
|
||||
to revert.
|
||||
-->
|
||||
<property name="FirmwareVersion" type="s" access="read"/>
|
||||
|
||||
|
|
|
|||
|
|
@ -5323,6 +5323,100 @@ static void test_nm_utils_enum (void)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
do_test_utils_str_utf8safe (const char *str, const char *expected, NMUtilsStrUtf8SafeFlags flags)
|
||||
{
|
||||
const char *str_safe, *s;
|
||||
gs_free char *str2 = NULL;
|
||||
gs_free char *str3 = NULL;
|
||||
|
||||
str_safe = nm_utils_str_utf8safe_escape (str, flags, &str2);
|
||||
|
||||
str3 = nm_utils_str_utf8safe_escape_cp (str, flags);
|
||||
g_assert_cmpstr (str3, ==, str_safe);
|
||||
g_assert ((!str && !str3) || (str != str3));
|
||||
g_clear_pointer (&str3, g_free);
|
||||
|
||||
if (expected == NULL) {
|
||||
g_assert (str_safe == str);
|
||||
g_assert (!str2);
|
||||
if (str) {
|
||||
g_assert (!strchr (str, '\\'));
|
||||
g_assert (g_utf8_validate (str, -1, NULL));
|
||||
}
|
||||
|
||||
g_assert (str == nm_utils_str_utf8safe_unescape (str_safe, &str3));
|
||||
g_assert (!str3);
|
||||
|
||||
str3 = nm_utils_str_utf8safe_unescape_cp (str_safe);
|
||||
if (str) {
|
||||
g_assert (str3 != str);
|
||||
g_assert_cmpstr (str3, ==, str);
|
||||
} else
|
||||
g_assert (!str3);
|
||||
g_clear_pointer (&str3, g_free);
|
||||
return;
|
||||
}
|
||||
|
||||
g_assert (str);
|
||||
g_assert (str_safe != str);
|
||||
g_assert (str_safe == str2);
|
||||
g_assert ( strchr (str, '\\')
|
||||
|| !g_utf8_validate (str, -1, NULL)
|
||||
|| ( NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII)
|
||||
&& NM_STRCHAR_ANY (str, ch, (guchar) ch >= 127))
|
||||
|| ( NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL)
|
||||
&& NM_STRCHAR_ANY (str, ch, (guchar) ch < ' ')));
|
||||
g_assert (g_utf8_validate (str_safe, -1, NULL));
|
||||
|
||||
str3 = g_strcompress (str_safe);
|
||||
g_assert_cmpstr (str, ==, str3);
|
||||
g_clear_pointer (&str3, g_free);
|
||||
|
||||
str3 = nm_utils_str_utf8safe_unescape_cp (str_safe);
|
||||
g_assert (str3 != str);
|
||||
g_assert_cmpstr (str3, ==, str);
|
||||
g_clear_pointer (&str3, g_free);
|
||||
|
||||
s = nm_utils_str_utf8safe_unescape (str_safe, &str3);
|
||||
g_assert (str3 != str);
|
||||
g_assert (s == str3);
|
||||
g_assert_cmpstr (str3, ==, str);
|
||||
g_clear_pointer (&str3, g_free);
|
||||
|
||||
g_assert_cmpstr (str_safe, ==, expected);
|
||||
}
|
||||
|
||||
static void
|
||||
test_utils_str_utf8safe (void)
|
||||
{
|
||||
do_test_utils_str_utf8safe (NULL, NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
||||
do_test_utils_str_utf8safe ("", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
||||
do_test_utils_str_utf8safe ("\314", "\\314", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
||||
do_test_utils_str_utf8safe ("\314\315x\315\315x", "\\314\\315x\\315\\315x", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
||||
do_test_utils_str_utf8safe ("\314\315xx", "\\314\\315xx", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
||||
do_test_utils_str_utf8safe ("\314xx", "\\314xx", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
||||
do_test_utils_str_utf8safe ("\xa0", "\\240", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
||||
do_test_utils_str_utf8safe ("\xe2\x91\xa0", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
||||
do_test_utils_str_utf8safe ("\xe2\xe2\x91\xa0", "\\342\xe2\x91\xa0", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
||||
do_test_utils_str_utf8safe ("\xe2\xe2\x91\xa0\xa0", "\\342\xe2\x91\xa0\\240", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
||||
do_test_utils_str_utf8safe ("a", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
||||
do_test_utils_str_utf8safe ("ab", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
||||
do_test_utils_str_utf8safe ("ab\314", "ab\\314", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
||||
do_test_utils_str_utf8safe ("ab\314adsf", "ab\\314adsf", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
||||
do_test_utils_str_utf8safe ("abadsf", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
||||
do_test_utils_str_utf8safe ("abäb", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
||||
do_test_utils_str_utf8safe ("x\xa0", "x\\240", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
||||
do_test_utils_str_utf8safe ("Ä\304ab\\äb", "Ä\\304ab\\\\äb", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
||||
do_test_utils_str_utf8safe ("Äab\\äb", "Äab\\\\äb", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
||||
do_test_utils_str_utf8safe ("ÄÄab\\äb", "ÄÄab\\\\äb", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
||||
do_test_utils_str_utf8safe ("㈞abä㈞b", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
||||
do_test_utils_str_utf8safe ("abäb", "ab\\303\\244b", NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII);
|
||||
do_test_utils_str_utf8safe ("ab\ab", "ab\\007b", NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static int
|
||||
_test_nm_in_set_get (int *call_counter, gboolean allow_called, int value)
|
||||
{
|
||||
|
|
@ -5680,6 +5774,7 @@ int main (int argc, char **argv)
|
|||
nmtst_init (&argc, &argv, TRUE);
|
||||
|
||||
/* The tests */
|
||||
g_test_add_func ("/core/general/test_utils_str_utf8safe", test_utils_str_utf8safe);
|
||||
g_test_add_func ("/core/general/test_nm_in_set", test_nm_in_set);
|
||||
g_test_add_func ("/core/general/test_nm_in_strset", test_nm_in_strset);
|
||||
g_test_add_func ("/core/general/test_setting_vpn_items", test_setting_vpn_items);
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ typedef struct {
|
|||
GPtrArray *available_connections;
|
||||
|
||||
struct udev *udev;
|
||||
char *product, *short_product;
|
||||
char *product;
|
||||
char *vendor, *short_vendor;
|
||||
char *description, *bus_name;
|
||||
|
||||
|
|
@ -320,7 +320,6 @@ finalize (GObject *object)
|
|||
g_free (priv->driver_version);
|
||||
g_free (priv->firmware_version);
|
||||
g_free (priv->product);
|
||||
g_free (priv->short_product);
|
||||
g_free (priv->vendor);
|
||||
g_free (priv->short_vendor);
|
||||
g_free (priv->description);
|
||||
|
|
@ -1357,6 +1356,17 @@ _get_udev_property (NMDevice *device,
|
|||
return db_value;
|
||||
}
|
||||
|
||||
static char *
|
||||
_get_udev_property_utf8safe (NMDevice *device,
|
||||
const char *enc_prop, /* ID_XXX_ENC */
|
||||
const char *db_prop) /* ID_XXX_FROM_DATABASE */
|
||||
{
|
||||
return nm_utils_str_utf8safe_escape_take (_get_udev_property (device,
|
||||
enc_prop,
|
||||
db_prop),
|
||||
NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL);
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_device_get_product:
|
||||
* @device: a #NMDevice
|
||||
|
|
@ -1365,6 +1375,9 @@ _get_udev_property (NMDevice *device,
|
|||
*
|
||||
* Returns: the product name of the device. This is the internal string used by the
|
||||
* device, and must not be modified.
|
||||
*
|
||||
* The string is backslash escaped (C escaping) for invalid characters. The escaping
|
||||
* can be reverted with g_strcompress(), however the result may not be valid UTF-8.
|
||||
**/
|
||||
const char *
|
||||
nm_device_get_product (NMDevice *device)
|
||||
|
|
@ -1374,15 +1387,16 @@ nm_device_get_product (NMDevice *device)
|
|||
g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
|
||||
|
||||
priv = NM_DEVICE_GET_PRIVATE (device);
|
||||
if (!priv->product)
|
||||
priv->product = _get_udev_property (device, "ID_MODEL_ENC", "ID_MODEL_FROM_DATABASE");
|
||||
if (!priv->product) {
|
||||
priv->product = _get_udev_property_utf8safe (device, "ID_MODEL_ENC", "ID_MODEL_FROM_DATABASE");
|
||||
|
||||
/* Sometimes ID_PRODUCT_FROM_DATABASE is used? */
|
||||
if (!priv->product)
|
||||
priv->product = _get_udev_property (device, "ID_MODEL_ENC", "ID_PRODUCT_FROM_DATABASE");
|
||||
/* Sometimes ID_PRODUCT_FROM_DATABASE is used? */
|
||||
if (!priv->product)
|
||||
priv->product = _get_udev_property_utf8safe (device, "ID_MODEL_ENC", "ID_PRODUCT_FROM_DATABASE");
|
||||
|
||||
if (!priv->product)
|
||||
priv->product = g_strdup ("");
|
||||
if (!priv->product)
|
||||
priv->product = g_strdup ("");
|
||||
}
|
||||
|
||||
return priv->product;
|
||||
}
|
||||
|
|
@ -1395,6 +1409,9 @@ nm_device_get_product (NMDevice *device)
|
|||
*
|
||||
* Returns: the vendor name of the device. This is the internal string used by the
|
||||
* device, and must not be modified.
|
||||
*
|
||||
* The string is backslash escaped (C escaping) for invalid characters. The escaping
|
||||
* can be reverted with g_strcompress(), however the result may not be valid UTF-8.
|
||||
**/
|
||||
const char *
|
||||
nm_device_get_vendor (NMDevice *device)
|
||||
|
|
@ -1406,7 +1423,7 @@ nm_device_get_vendor (NMDevice *device)
|
|||
priv = NM_DEVICE_GET_PRIVATE (device);
|
||||
|
||||
if (!priv->vendor)
|
||||
priv->vendor = _get_udev_property (device, "ID_VENDOR_ENC", "ID_VENDOR_FROM_DATABASE");
|
||||
priv->vendor = _get_udev_property_utf8safe (device, "ID_VENDOR_ENC", "ID_VENDOR_FROM_DATABASE");
|
||||
|
||||
if (!priv->vendor)
|
||||
priv->vendor = g_strdup ("");
|
||||
|
|
@ -1414,128 +1431,146 @@ nm_device_get_vendor (NMDevice *device)
|
|||
return priv->vendor;
|
||||
}
|
||||
|
||||
static const char * const ignored_words[] = {
|
||||
"Semiconductor",
|
||||
"Components",
|
||||
"Corporation",
|
||||
"Communications",
|
||||
"Company",
|
||||
"Corp.",
|
||||
"Corp",
|
||||
"Co.",
|
||||
"Inc.",
|
||||
"Inc",
|
||||
"Incorporated",
|
||||
"Ltd.",
|
||||
"Limited.",
|
||||
"Intel?",
|
||||
"chipset",
|
||||
"adapter",
|
||||
"[hex]",
|
||||
"NDIS",
|
||||
"Module",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char * const ignored_phrases[] = {
|
||||
"Multiprotocol MAC/baseband processor",
|
||||
"Wireless LAN Controller",
|
||||
"Wireless LAN Adapter",
|
||||
"Wireless Adapter",
|
||||
"Network Connection",
|
||||
"Wireless Cardbus Adapter",
|
||||
"Wireless CardBus Adapter",
|
||||
"54 Mbps Wireless PC Card",
|
||||
"Wireless PC Card",
|
||||
"Wireless PC",
|
||||
"PC Card with XJACK(r) Antenna",
|
||||
"Wireless cardbus",
|
||||
"Wireless LAN PC Card",
|
||||
"Technology Group Ltd.",
|
||||
"Communication S.p.A.",
|
||||
"Business Mobile Networks BV",
|
||||
"Mobile Broadband Minicard Composite Device",
|
||||
"Mobile Communications AB",
|
||||
"(PC-Suite Mode)",
|
||||
NULL
|
||||
};
|
||||
|
||||
static char *
|
||||
fixup_desc_string (const char *desc)
|
||||
{
|
||||
char *p, *temp;
|
||||
char **words, **item;
|
||||
GString *str;
|
||||
static const char *const IGNORED_PHRASES[] = {
|
||||
"Multiprotocol MAC/baseband processor",
|
||||
"Wireless LAN Controller",
|
||||
"Wireless LAN Adapter",
|
||||
"Wireless Adapter",
|
||||
"Network Connection",
|
||||
"Wireless Cardbus Adapter",
|
||||
"Wireless CardBus Adapter",
|
||||
"54 Mbps Wireless PC Card",
|
||||
"Wireless PC Card",
|
||||
"Wireless PC",
|
||||
"PC Card with XJACK(r) Antenna",
|
||||
"Wireless cardbus",
|
||||
"Wireless LAN PC Card",
|
||||
"Technology Group Ltd.",
|
||||
"Communication S.p.A.",
|
||||
"Business Mobile Networks BV",
|
||||
"Mobile Broadband Minicard Composite Device",
|
||||
"Mobile Communications AB",
|
||||
"(PC-Suite Mode)",
|
||||
};
|
||||
static const char *const IGNORED_WORDS[] = {
|
||||
"Semiconductor",
|
||||
"Components",
|
||||
"Corporation",
|
||||
"Communications",
|
||||
"Company",
|
||||
"Corp.",
|
||||
"Corp",
|
||||
"Co.",
|
||||
"Inc.",
|
||||
"Inc",
|
||||
"Incorporated",
|
||||
"Ltd.",
|
||||
"Limited.",
|
||||
"Intel?",
|
||||
"chipset",
|
||||
"adapter",
|
||||
"[hex]",
|
||||
"NDIS",
|
||||
"Module",
|
||||
};
|
||||
char *desc_full;
|
||||
char *p, *q;
|
||||
int i;
|
||||
|
||||
if (!desc)
|
||||
if (!desc || !desc[0])
|
||||
return NULL;
|
||||
|
||||
p = temp = g_strdup (desc);
|
||||
while (*p) {
|
||||
if (*p == '_' || *p == ',')
|
||||
/* restore original non-UTF-8-safe text. */
|
||||
desc_full = nm_utils_str_utf8safe_unescape_cp (desc);
|
||||
|
||||
/* replace all invalid UTF-8 bytes with space. */
|
||||
p = desc_full;
|
||||
while (!g_utf8_validate (p, -1, (const char **) &q)) {
|
||||
/* the byte is invalid UTF-8. Replace it with space and proceed. */
|
||||
*q = ' ';
|
||||
p = q + 1;
|
||||
}
|
||||
|
||||
/* replace '_', ',', and ASCII controll characters with space. */
|
||||
for (p = desc_full; p[0]; p++) {
|
||||
if ( NM_IN_SET (*p, '_', ',')
|
||||
|| *p < ' ')
|
||||
*p = ' ';
|
||||
p++;
|
||||
}
|
||||
|
||||
/* Attempt to shorten ID by ignoring certain phrases */
|
||||
for (i = 0; ignored_phrases[i]; i++) {
|
||||
p = strstr (temp, ignored_phrases[i]);
|
||||
for (i = 0; i < G_N_ELEMENTS (IGNORED_PHRASES); i++) {
|
||||
p = strstr (desc_full, IGNORED_PHRASES[i]);
|
||||
if (p) {
|
||||
guint32 ignored_len = strlen (ignored_phrases[i]);
|
||||
const char *eow = &p[strlen (IGNORED_PHRASES[i])];
|
||||
|
||||
memmove (p, p + ignored_len, strlen (p + ignored_len) + 1); /* +1 for the \0 */
|
||||
memmove (p, eow, strlen (eow) + 1); /* +1 for the \0 */
|
||||
}
|
||||
}
|
||||
|
||||
/* Attempt to shorten ID by ignoring certain individual words */
|
||||
words = g_strsplit (temp, " ", 0);
|
||||
str = g_string_new_len (NULL, strlen (temp));
|
||||
g_free (temp);
|
||||
/* Attempt to shorten ID by ignoring certain individual words.
|
||||
* - word-split the description at spaces
|
||||
* - coalesce multiple spaces
|
||||
* - skip over IGNORED_WORDS */
|
||||
p = desc_full;
|
||||
q = desc_full;
|
||||
for (;;) {
|
||||
char *eow;
|
||||
gsize l;
|
||||
|
||||
for (item = words; *item; item++) {
|
||||
gboolean ignore = FALSE;
|
||||
/* skip leading spaces. */
|
||||
while (p[0] == ' ')
|
||||
p++;
|
||||
|
||||
if (**item == '\0')
|
||||
continue;
|
||||
if (!p[0])
|
||||
break;
|
||||
|
||||
for (i = 0; ignored_words[i]; i++) {
|
||||
if (!strcmp (*item, ignored_words[i])) {
|
||||
ignore = TRUE;
|
||||
break;
|
||||
}
|
||||
/* split leading word on first space */
|
||||
eow = strchr (p, ' ');
|
||||
if (eow)
|
||||
*eow = '\0';
|
||||
|
||||
if (nm_utils_strv_find_first ((char **) IGNORED_WORDS,
|
||||
G_N_ELEMENTS (IGNORED_WORDS),
|
||||
p) < 0)
|
||||
goto next;
|
||||
|
||||
l = strlen (p);
|
||||
if (q != p) {
|
||||
if (q != desc_full)
|
||||
*q++ = ' ';
|
||||
memmove (q, p, l);
|
||||
}
|
||||
q += l;
|
||||
|
||||
if (!ignore) {
|
||||
if (str->len)
|
||||
g_string_append_c (str, ' ');
|
||||
g_string_append (str, *item);
|
||||
}
|
||||
next:
|
||||
if (!eow)
|
||||
break;
|
||||
p = eow + 1;
|
||||
}
|
||||
g_strfreev (words);
|
||||
|
||||
temp = str->str;
|
||||
g_string_free (str, FALSE);
|
||||
*q++ = '\0';
|
||||
|
||||
return temp;
|
||||
if (!desc_full[0]) {
|
||||
g_free (desc_full);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nm_assert (g_utf8_validate (desc_full, -1, NULL));
|
||||
return desc_full;
|
||||
}
|
||||
|
||||
static void
|
||||
get_description (NMDevice *device)
|
||||
ensure_description (NMDevice *device)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
|
||||
const char *dev_product;
|
||||
const char *dev_vendor;
|
||||
char *pdown;
|
||||
char *vdown;
|
||||
GString *str;
|
||||
GParamSpec *name_prop;
|
||||
gs_free char *short_product = NULL;
|
||||
|
||||
dev_product = nm_device_get_product (device);
|
||||
priv->short_product = fixup_desc_string (dev_product);
|
||||
|
||||
dev_vendor = nm_device_get_vendor (device);
|
||||
priv->short_vendor = fixup_desc_string (dev_vendor);
|
||||
priv->short_vendor = nm_str_realloc (fixup_desc_string (nm_device_get_vendor (device)));
|
||||
|
||||
/* Grab device's preferred name, if any */
|
||||
name_prop = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (device)), "name");
|
||||
|
|
@ -1546,28 +1581,24 @@ get_description (NMDevice *device)
|
|||
g_clear_pointer (&priv->description, g_free);
|
||||
}
|
||||
|
||||
if (!dev_product || !dev_vendor) {
|
||||
priv->description = g_strdup (nm_device_get_iface (device));
|
||||
if ( !priv->short_vendor
|
||||
|| !(short_product = fixup_desc_string (nm_device_get_product (device)))) {
|
||||
priv->description = g_strdup (nm_device_get_iface (device) ?: "");
|
||||
return;
|
||||
}
|
||||
|
||||
str = g_string_new_len (NULL, strlen (priv->short_vendor) + strlen (priv->short_product) + 1);
|
||||
|
||||
/* Another quick hack; if all of the fixed up vendor string
|
||||
* is found in product, ignore the vendor.
|
||||
*/
|
||||
pdown = g_ascii_strdown (priv->short_product, -1);
|
||||
vdown = g_ascii_strdown (priv->short_vendor, -1);
|
||||
if (!strstr (pdown, vdown)) {
|
||||
g_string_append (str, priv->short_vendor);
|
||||
g_string_append_c (str, ' ');
|
||||
{
|
||||
gs_free char *pdown = g_ascii_strdown (short_product, -1);
|
||||
gs_free char *vdown = g_ascii_strdown (priv->short_vendor, -1);
|
||||
|
||||
if (!strstr (pdown, vdown))
|
||||
priv->description = g_strconcat (priv->short_vendor, " ", short_product, NULL);
|
||||
else
|
||||
priv->description = g_steal_pointer (&short_product);
|
||||
}
|
||||
g_free (pdown);
|
||||
g_free (vdown);
|
||||
|
||||
g_string_append (str, priv->short_product);
|
||||
|
||||
priv->description = g_string_free (str, FALSE);
|
||||
}
|
||||
|
||||
static const char *
|
||||
|
|
@ -1580,7 +1611,7 @@ get_short_vendor (NMDevice *device)
|
|||
priv = NM_DEVICE_GET_PRIVATE (device);
|
||||
|
||||
if (!priv->description)
|
||||
get_description (device);
|
||||
ensure_description (device);
|
||||
|
||||
return priv->short_vendor;
|
||||
}
|
||||
|
|
@ -1604,7 +1635,7 @@ nm_device_get_description (NMDevice *device)
|
|||
priv = NM_DEVICE_GET_PRIVATE (device);
|
||||
|
||||
if (!priv->description)
|
||||
get_description (device);
|
||||
ensure_description (device);
|
||||
|
||||
return priv->description;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -397,3 +397,141 @@ nm_g_object_set_property (GObject *object,
|
|||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
_str_append_escape (GString *s, char ch)
|
||||
{
|
||||
g_string_append_c (s, '\\');
|
||||
g_string_append_c (s, '0' + ((((guchar) ch) >> 6) & 07));
|
||||
g_string_append_c (s, '0' + ((((guchar) ch) >> 3) & 07));
|
||||
g_string_append_c (s, '0' + ( ((guchar) ch) & 07));
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_utils_str_utf8safe_escape:
|
||||
* @str: NUL terminated input string, possibly in utf-8 encoding
|
||||
* @flags: #NMUtilsStrUtf8SafeFlags flags
|
||||
* @to_free: (out): return the pointer location of the string
|
||||
* if a copying was necessary.
|
||||
*
|
||||
* Returns the possible non-UTF-8 NUL terminated string @str
|
||||
* and uses backslash escaping (C escaping, like g_strescape())
|
||||
* to sanitize non UTF-8 characters. The result is valid
|
||||
* UTF-8.
|
||||
*
|
||||
* The operation can be reverted with g_strcompress() or
|
||||
* nm_utils_str_utf8safe_unescape().
|
||||
*
|
||||
* Depending on @flags, valid UTF-8 characters are not escaped at all
|
||||
* (except the escape character '\\'). This is the difference to g_strescape(),
|
||||
* which escapes all non-ASCII characters. This allows to pass on
|
||||
* valid UTF-8 characters as-is and can be directly shown to the user
|
||||
* as UTF-8 -- with exception of the backslash escape character,
|
||||
* invalid UTF-8 sequences, and other (depending on @flags).
|
||||
*
|
||||
* Returns: the escaped input string, as valid UTF-8. If no escaping
|
||||
* is necessary, it returns the input @str. Otherwise, an allocated
|
||||
* string @to_free is returned which must be freed by the caller
|
||||
* with g_free. The escaping can be reverted by g_strcompress().
|
||||
**/
|
||||
const char *
|
||||
nm_utils_str_utf8safe_escape (const char *str, NMUtilsStrUtf8SafeFlags flags, char **to_free)
|
||||
{
|
||||
const char *p = NULL;
|
||||
GString *s;
|
||||
|
||||
g_return_val_if_fail (to_free, NULL);
|
||||
|
||||
*to_free = NULL;
|
||||
if (!str || !str[0])
|
||||
return str;
|
||||
|
||||
if ( g_utf8_validate (str, -1, &p)
|
||||
&& !NM_STRCHAR_ANY (str, ch,
|
||||
( ch == '\\' \
|
||||
|| ( NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL) \
|
||||
&& ch < ' ') \
|
||||
|| ( NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII) \
|
||||
&& ((guchar) ch) >= 127))))
|
||||
return str;
|
||||
|
||||
s = g_string_sized_new ((p - str) + strlen (p) + 5);
|
||||
|
||||
do {
|
||||
for (; str < p; str++) {
|
||||
char ch = str[0];
|
||||
|
||||
if (ch == '\\')
|
||||
g_string_append (s, "\\\\");
|
||||
else if ( ( NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL) \
|
||||
&& ch < ' ') \
|
||||
|| ( NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII) \
|
||||
&& ((guchar) ch) >= 127))
|
||||
_str_append_escape (s, ch);
|
||||
else
|
||||
g_string_append_c (s, ch);
|
||||
}
|
||||
|
||||
if (p[0] == '\0')
|
||||
break;
|
||||
_str_append_escape (s, p[0]);
|
||||
|
||||
str = &p[1];
|
||||
g_utf8_validate (str, -1, &p);
|
||||
} while (TRUE);
|
||||
|
||||
*to_free = g_string_free (s, FALSE);
|
||||
return *to_free;
|
||||
}
|
||||
|
||||
const char *
|
||||
nm_utils_str_utf8safe_unescape (const char *str, char **to_free)
|
||||
{
|
||||
g_return_val_if_fail (to_free, NULL);
|
||||
|
||||
if (!str || !strchr (str, '\\')) {
|
||||
*to_free = NULL;
|
||||
return str;
|
||||
}
|
||||
return (*to_free = g_strcompress (str));
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_utils_str_utf8safe_escape_cp:
|
||||
* @str: NUL terminated input string, possibly in utf-8 encoding
|
||||
* @flags: #NMUtilsStrUtf8SafeFlags flags
|
||||
*
|
||||
* Like nm_utils_str_utf8safe_escape(), except the returned value
|
||||
* is always a copy of the input and must be freed by the caller.
|
||||
*
|
||||
* Returns: the escaped input string in UTF-8 encoding. The returned
|
||||
* value should be freed with g_free().
|
||||
* The escaping can be reverted by g_strcompress().
|
||||
**/
|
||||
char *
|
||||
nm_utils_str_utf8safe_escape_cp (const char *str, NMUtilsStrUtf8SafeFlags flags)
|
||||
{
|
||||
char *s;
|
||||
|
||||
nm_utils_str_utf8safe_escape (str, flags, &s);
|
||||
return s ?: g_strdup (str);
|
||||
}
|
||||
|
||||
char *
|
||||
nm_utils_str_utf8safe_unescape_cp (const char *str)
|
||||
{
|
||||
return str ? g_strcompress (str) : NULL;
|
||||
}
|
||||
|
||||
char *
|
||||
nm_utils_str_utf8safe_escape_take (char *str, NMUtilsStrUtf8SafeFlags flags)
|
||||
{
|
||||
char *str_to_free;
|
||||
|
||||
nm_utils_str_utf8safe_escape (str, flags, &str_to_free);
|
||||
if (str_to_free) {
|
||||
g_free (str);
|
||||
return str_to_free;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,4 +97,20 @@ gboolean nm_g_object_set_property (GObject *object,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef enum {
|
||||
NM_UTILS_STR_UTF8_SAFE_FLAG_NONE = 0,
|
||||
NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL = 0x0001,
|
||||
NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII = 0x0002,
|
||||
} NMUtilsStrUtf8SafeFlags;
|
||||
|
||||
const char *nm_utils_str_utf8safe_escape (const char *str, NMUtilsStrUtf8SafeFlags flags, char **to_free);
|
||||
const char *nm_utils_str_utf8safe_unescape (const char *str, char **to_free);
|
||||
|
||||
char *nm_utils_str_utf8safe_escape_cp (const char *str, NMUtilsStrUtf8SafeFlags flags);
|
||||
char *nm_utils_str_utf8safe_unescape_cp (const char *str);
|
||||
|
||||
char *nm_utils_str_utf8safe_escape_take (char *str, NMUtilsStrUtf8SafeFlags flags);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif /* __NM_SHARED_UTILS_H__ */
|
||||
|
|
|
|||
|
|
@ -67,8 +67,9 @@ nm_udev_utils_property_decode (const char *uproperty, char **to_free)
|
|||
if ( p[0] == '\\'
|
||||
&& p[1] == 'x'
|
||||
&& (a = g_ascii_xdigit_value (p[2])) >= 0
|
||||
&& (b = g_ascii_xdigit_value (p[3])) >= 0) {
|
||||
if (!unescaped) {
|
||||
&& (b = g_ascii_xdigit_value (p[3])) >= 0
|
||||
&& (a || b)) {
|
||||
if (!n) {
|
||||
gssize l = p - uproperty;
|
||||
|
||||
unescaped = g_malloc (l + strlen (p) + 1 - 3);
|
||||
|
|
@ -84,11 +85,12 @@ nm_udev_utils_property_decode (const char *uproperty, char **to_free)
|
|||
}
|
||||
}
|
||||
|
||||
if (!unescaped) {
|
||||
if (!n) {
|
||||
*to_free = NULL;
|
||||
return uproperty;
|
||||
}
|
||||
|
||||
*n++ = '\0';
|
||||
return (*to_free = unescaped);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2463,7 +2463,7 @@ device_link_changed (NMDevice *self)
|
|||
info = *pllink;
|
||||
|
||||
udi = nm_platform_link_get_udi (nm_device_get_platform (self), info.ifindex);
|
||||
if (udi && g_strcmp0 (udi, priv->udi)) {
|
||||
if (udi && !nm_streq0 (udi, priv->udi)) {
|
||||
/* Update UDI to what udev gives us */
|
||||
g_free (priv->udi);
|
||||
priv->udi = g_strdup (udi);
|
||||
|
|
@ -2844,7 +2844,7 @@ update_device_from_platform_link (NMDevice *self, const NMPlatformLink *plink)
|
|||
g_return_if_fail (plink != NULL);
|
||||
|
||||
udi = nm_platform_link_get_udi (nm_device_get_platform (self), plink->ifindex);
|
||||
if (udi && !g_strcmp0 (udi, priv->udi)) {
|
||||
if (udi && !nm_streq0 (udi, priv->udi)) {
|
||||
g_free (priv->udi);
|
||||
priv->udi = g_strdup (udi);
|
||||
_notify (self, PROP_UDI);
|
||||
|
|
@ -13839,14 +13839,11 @@ set_property (GObject *object, guint prop_id,
|
|||
|
||||
switch (prop_id) {
|
||||
case PROP_UDI:
|
||||
if (g_value_get_string (value)) {
|
||||
g_free (priv->udi);
|
||||
priv->udi = g_value_dup_string (value);
|
||||
}
|
||||
/* construct-only */
|
||||
priv->udi = g_value_dup_string (value);
|
||||
break;
|
||||
case PROP_IFACE:
|
||||
/* construct-only */
|
||||
g_return_if_fail (!priv->iface);
|
||||
priv->iface = g_value_dup_string (value);
|
||||
break;
|
||||
case PROP_DRIVER:
|
||||
|
|
@ -13941,28 +13938,43 @@ get_property (GObject *object, guint prop_id,
|
|||
|
||||
switch (prop_id) {
|
||||
case PROP_UDI:
|
||||
g_value_set_string (value, priv->udi);
|
||||
/* UDI is (depending on the device type) a path to sysfs and can contain
|
||||
* non-UTF-8.
|
||||
* ip link add name $'d\xccf\\c' type dummy */
|
||||
g_value_take_string (value,
|
||||
nm_utils_str_utf8safe_escape_cp (priv->udi,
|
||||
NM_UTILS_STR_UTF8_SAFE_FLAG_NONE));
|
||||
break;
|
||||
case PROP_IFACE:
|
||||
g_value_set_string (value, priv->iface);
|
||||
g_value_take_string (value,
|
||||
nm_utils_str_utf8safe_escape_cp (priv->iface,
|
||||
NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL));
|
||||
break;
|
||||
case PROP_IP_IFACE:
|
||||
if (ip_config_valid (priv->state))
|
||||
g_value_set_string (value, nm_device_get_ip_iface (self));
|
||||
else
|
||||
if (ip_config_valid (priv->state)) {
|
||||
g_value_take_string (value,
|
||||
nm_utils_str_utf8safe_escape_cp (nm_device_get_ip_iface (self),
|
||||
NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL));
|
||||
} else
|
||||
g_value_set_string (value, NULL);
|
||||
break;
|
||||
case PROP_IFINDEX:
|
||||
g_value_set_int (value, priv->ifindex);
|
||||
break;
|
||||
case PROP_DRIVER:
|
||||
g_value_set_string (value, priv->driver);
|
||||
g_value_take_string (value,
|
||||
nm_utils_str_utf8safe_escape_cp (priv->driver,
|
||||
NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL));
|
||||
break;
|
||||
case PROP_DRIVER_VERSION:
|
||||
g_value_set_string (value, priv->driver_version);
|
||||
g_value_take_string (value,
|
||||
nm_utils_str_utf8safe_escape_cp (priv->driver_version,
|
||||
NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL));
|
||||
break;
|
||||
case PROP_FIRMWARE_VERSION:
|
||||
g_value_set_string (value, priv->firmware_version);
|
||||
g_value_take_string (value,
|
||||
nm_utils_str_utf8safe_escape_cp (priv->firmware_version,
|
||||
NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL));
|
||||
break;
|
||||
case PROP_CAPABILITIES:
|
||||
g_value_set_uint (value, (priv->capabilities & ~NM_DEVICE_CAP_INTERNAL_MASK));
|
||||
|
|
@ -14159,7 +14171,7 @@ nm_device_class_init (NMDeviceClass *klass)
|
|||
obj_properties[PROP_UDI] =
|
||||
g_param_spec_string (NM_DEVICE_UDI, "", "",
|
||||
NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
obj_properties[PROP_IFACE] =
|
||||
g_param_spec_string (NM_DEVICE_IFACE, "", "",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue