diff options
| author | Michael Biebl <biebl@debian.org> | 2017-07-12 17:57:30 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2017-07-12 17:57:30 +0200 |
| commit | b9f0451fa35393ceedf6d9d20b78c43578ebea5d (patch) | |
| tree | 417afcdd717020ad44e25fadee4b89de23316e83 /shared | |
| parent | c333f062ddcba9b35330647bf6cbd0a07f2d786e (diff) | |
New upstream version 1.8.2 upstream/1.8.2
Diffstat (limited to 'shared')
| -rw-r--r-- | shared/nm-utils/nm-macros-internal.h | 13 | ||||
| -rw-r--r-- | shared/nm-utils/nm-shared-utils.c | 138 | ||||
| -rw-r--r-- | shared/nm-utils/nm-shared-utils.h | 16 | ||||
| -rw-r--r-- | shared/nm-utils/nm-test-utils.h | 9 | ||||
| -rw-r--r-- | shared/nm-utils/nm-udev-utils.c | 12 | ||||
| -rw-r--r-- | shared/nm-version-macros.h | 2 |
6 files changed, 175 insertions, 15 deletions
diff --git a/shared/nm-utils/nm-macros-internal.h b/shared/nm-utils/nm-macros-internal.h index 6ca66d29..5fe4bc50 100644 --- a/shared/nm-utils/nm-macros-internal.h +++ b/shared/nm-utils/nm-macros-internal.h @@ -609,18 +609,13 @@ nm_clear_g_cancellable (GCancellable **cancellable) /*****************************************************************************/ /* Determine whether @x is a power of two (@x being an integer type). - * For the special cases @x equals zero or one, it also returns true. - * In case @x being a signed type, for negative @x always return FALSE. */ + * Basically, this returns TRUE, if @x has exactly one bit set. + * For negative values and zero, this always returns FALSE. */ #define nm_utils_is_power_of_two(x) ({ \ typeof(x) __x = (x); \ \ - /* Check if the value is negative. In that case, return FALSE. - * The first expression is a compile time constant, depending on whether - * the type is signed. The second expression is a clumsy way for (__x >= 0), - * which otherwise causes a compiler warning for unsigned types. */ \ - ( (((typeof(__x)) -1) > ((typeof(__x)) 0)) \ - || (__x > 0 || __x == 0) ) \ - && ((__x & (__x - 1)) == 0); \ + ( (__x > ((typeof(__x)) 0)) \ + && ((__x & (__x - (((typeof(__x)) 1)))) == ((typeof(__x)) 0))); \ }) /*****************************************************************************/ diff --git a/shared/nm-utils/nm-shared-utils.c b/shared/nm-utils/nm-shared-utils.c index 413526dc..e7f31cbc 100644 --- a/shared/nm-utils/nm-shared-utils.c +++ b/shared/nm-utils/nm-shared-utils.c @@ -364,3 +364,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; +} diff --git a/shared/nm-utils/nm-shared-utils.h b/shared/nm-utils/nm-shared-utils.h index f1f9f518..69f9533d 100644 --- a/shared/nm-utils/nm-shared-utils.h +++ b/shared/nm-utils/nm-shared-utils.h @@ -86,4 +86,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__ */ diff --git a/shared/nm-utils/nm-test-utils.h b/shared/nm-utils/nm-test-utils.h index 0dfdfce6..bc521131 100644 --- a/shared/nm-utils/nm-test-utils.h +++ b/shared/nm-utils/nm-test-utils.h @@ -1183,6 +1183,15 @@ nmtst_file_get_contents (const char *filename) return contents; } +#define nmtst_file_set_contents(filename, content) \ + G_STMT_START { \ + GError *_error = NULL; \ + gboolean _success; \ + \ + _success = g_file_set_contents ((filename), (content), -1, &_error); \ + nmtst_assert_success (_success, _error); \ + } G_STMT_END + /*****************************************************************************/ static inline void diff --git a/shared/nm-utils/nm-udev-utils.c b/shared/nm-utils/nm-udev-utils.c index 5552d592..79d4426d 100644 --- a/shared/nm-utils/nm-udev-utils.c +++ b/shared/nm-utils/nm-udev-utils.c @@ -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); } @@ -144,7 +146,7 @@ nm_udev_utils_enumerate (struct udev *uclient, for (n = 0; subsystems[n]; n++) { const char *subsystem; const char *devtype; - gs_free char *to_free; + gs_free char *to_free = NULL; _subsystem_split (subsystems[n], &subsystem, &devtype, &to_free); @@ -240,7 +242,7 @@ nm_udev_client_new (const char *const*subsystems, /* install subsystem filters to only wake up for certain events */ for (n = 0; self->subsystems[n]; n++) { if (self->monitor) { - gs_free char *to_free; + gs_free char *to_free = NULL; const char *subsystem; const char *devtype; diff --git a/shared/nm-version-macros.h b/shared/nm-version-macros.h index a0b61c6f..e7a2f329 100644 --- a/shared/nm-version-macros.h +++ b/shared/nm-version-macros.h @@ -45,7 +45,7 @@ * Evaluates to the micro version number of NetworkManager which this source * compiled against. */ -#define NM_MICRO_VERSION (0) +#define NM_MICRO_VERSION (2) /** * NM_CHECK_VERSION: |