From c158862fe7b892d8b8a702b2bb5730b7282944dd Mon Sep 17 00:00:00 2001 From: Robert Tari Date: Thu, 18 Jul 2024 03:05:26 +0200 Subject: [PATCH] Never crash when getting system layouts fixes https://github.com/AyatanaIndicators/ayatana-indicator-keyboard/issues/66 --- src/keyboard-lomiri.c | 289 +++++++++++++++++++++------------------- src/keyboard-x11.c | 299 ++++++++++++++++++++++-------------------- 2 files changed, 309 insertions(+), 279 deletions(-) diff --git a/src/keyboard-lomiri.c b/src/keyboard-lomiri.c index 6666c7b8..c7bc9dc1 100644 --- a/src/keyboard-lomiri.c +++ b/src/keyboard-lomiri.c @@ -370,9 +370,155 @@ static void onSourcesChanged (GSettings *pSettings, const gchar *sKey, gpointer } } +static void getSystemLayouts (gchar *sLocation, Keyboard *self) +{ + gboolean bExists = g_file_test (sLocation, G_FILE_TEST_EXISTS); + + if (!bExists) + { + return; + } + + gchar *sFile = NULL; + GError *pError = NULL; + g_file_get_contents (sLocation, &sFile, NULL, &pError); + + if (pError) + { + g_error_free (pError); + + return; + } + + GRegex *pRegex = NULL; + gboolean bDefaultLocation = g_str_equal (sLocation, "/etc/default/keyboard"); + + if (bDefaultLocation) + { + #if GLIB_CHECK_VERSION(2, 73, 0) + pRegex = g_regex_new (" *XKBLAYOUT *= *\"*([,a-zA-Z0-9]*)\"*", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, &pError); + #else + pRegex = g_regex_new (" *XKBLAYOUT *= *\"*([,a-zA-Z0-9]*)\"*", (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, &pError); + #endif + } + else + { + #if GLIB_CHECK_VERSION(2, 73, 0) + pRegex = g_regex_new (" *Option +\"*XkbLayout\"* +\"*([,a-zA-Z0-9]*)\"*", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, &pError); + #else + pRegex = g_regex_new (" *Option +\"*XkbLayout\"* +\"*([,a-zA-Z0-9]*)\"*", (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, &pError); + #endif + } + + if (pError) + { + g_warning ("Panic: Failed to compile regex: %s", pError->message); + g_error_free (pError); + g_free(sFile); + + return; + } + + GMatchInfo *pMatchInfo = NULL; + + #if GLIB_CHECK_VERSION(2, 73, 0) + gboolean bMatch = g_regex_match (pRegex, sFile, G_REGEX_MATCH_DEFAULT, &pMatchInfo); + #else + gboolean bMatch = g_regex_match (pRegex, sFile, (GRegexMatchFlags) 0, &pMatchInfo); + #endif + + if (!bMatch) + { + g_regex_unref (pRegex); + g_free(sFile); + + return; + } + + gchar *sLayouts = g_match_info_fetch (pMatchInfo, 1); + GStrv lLayouts = g_strsplit (sLayouts, ",", -1); + g_free (sLayouts); + g_match_info_free (pMatchInfo); + g_regex_unref (pRegex); + + if (bDefaultLocation) + { + #if GLIB_CHECK_VERSION(2, 73, 0) + pRegex = g_regex_new (" *XKBVARIANT *= *\"*([,a-zA-Z0-9]*)\"*", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, &pError); + #else + pRegex = g_regex_new (" *XKBVARIANT *= *\"*([,a-zA-Z0-9]*)\"*", (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, &pError); + #endif + } + else + { + #if GLIB_CHECK_VERSION(2, 73, 0) + pRegex = g_regex_new (" *Option +\"*XkbVariant\"* +\"*([,a-zA-Z0-9]*)\"*", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, &pError); + #else + pRegex = g_regex_new (" *Option +\"*XkbVariant\"* +\"*([,a-zA-Z0-9]*)\"*", (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, &pError); + #endif + } + + if (pError) + { + g_warning ("Panic: Failed to compile regex: %s", pError->message); + g_error_free (pError); + g_free(sFile); + + return; + } + + #if GLIB_CHECK_VERSION(2, 73, 0) + bMatch = g_regex_match (pRegex, sFile, G_REGEX_MATCH_DEFAULT, &pMatchInfo); + #else + bMatch = g_regex_match (pRegex, sFile, (GRegexMatchFlags) 0, &pMatchInfo); + #endif + + if (!bMatch) + { + g_regex_unref (pRegex); + g_free(sFile); + + return; + } + + gchar *sVariants = g_match_info_fetch (pMatchInfo, 1); + GStrv lVariants = g_strsplit (sVariants, ",", -1); + g_free (sVariants); + g_match_info_free (pMatchInfo); + g_regex_unref (pRegex); + g_free(sFile); + guint nLayouts = g_strv_length (lLayouts); + + for (guint nLayout = 0; nLayout < nLayouts; nLayout++) + { + gchar *sId = NULL; + guint nVariantLength = 0; + + if (lVariants && lVariants[nLayout]) + { + nVariantLength = strlen (lVariants[nLayout]); + } + + if (nVariantLength) + { + sId = g_strconcat (lLayouts[nLayout], "+", lVariants[nLayout], NULL); + } + else + { + sId = g_strdup (lLayouts[nLayout]); + } + + self->pPrivate->lLayoutRec = g_slist_append (self->pPrivate->lLayoutRec, sId); + } + + g_strfreev (lLayouts); + g_strfreev (lVariants); +} + static void keyboard_init(Keyboard *self) { self->pPrivate = keyboard_get_instance_private(self); + self->pPrivate->lLayoutRec = NULL; self->pPrivate->lLayouts = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, freeLayout); // Read all available layouts @@ -446,152 +592,19 @@ static void keyboard_init(Keyboard *self) else { // Get system layouts - gboolean bDefaultLocation = g_file_test ("/etc/default/keyboard", G_FILE_TEST_EXISTS); - gchar *sLocation = NULL; + getSystemLayouts ("/etc/default/keyboard", self); - if (bDefaultLocation) - { - sLocation = "/etc/default/keyboard"; - } - else + if (!self->pPrivate->lLayoutRec) { - sLocation = "/etc/X11/xorg.conf.d/00-keyboard.conf"; + getSystemLayouts ("/etc/X11/xorg.conf.d/00-keyboard.conf", self); } - gchar *sFile = NULL; - GError *pError = NULL; - g_file_get_contents (sLocation, &sFile, NULL, &pError); - GStrv lLayouts = NULL; - GStrv lVariants = NULL; - - if (!pError) + if (!self->pPrivate->lLayoutRec) { - GRegex *pRegex = NULL; - - if (bDefaultLocation) - { - #if GLIB_CHECK_VERSION(2, 73, 0) - pRegex = g_regex_new (" *XKBLAYOUT *= *\"*([,a-zA-Z0-9]*)\"*", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, &pError); - #else - pRegex = g_regex_new (" *XKBLAYOUT *= *\"*([,a-zA-Z0-9]*)\"*", (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, &pError); - #endif - } - else - { - #if GLIB_CHECK_VERSION(2, 73, 0) - pRegex = g_regex_new (" *Option +\"*XkbLayout\"* +\"*([,a-zA-Z0-9]*)\"*", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, &pError); - #else - pRegex = g_regex_new (" *Option +\"*XkbLayout\"* +\"*([,a-zA-Z0-9]*)\"*", (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, &pError); - #endif - } - - if (!pError) - { - GMatchInfo *pMatchInfo = NULL; - - #if GLIB_CHECK_VERSION(2, 73, 0) - gboolean bMatch = g_regex_match (pRegex, sFile, G_REGEX_MATCH_DEFAULT, &pMatchInfo); - #else - gboolean bMatch = g_regex_match (pRegex, sFile, (GRegexMatchFlags) 0, &pMatchInfo); - #endif - - if (bMatch) - { - gchar *sLayouts = g_match_info_fetch (pMatchInfo, 1); - lLayouts = g_strsplit (sLayouts, ",", -1); - g_free (sLayouts); - } - else - { - g_error ("PANIC: No system XkbLayout found"); - } - - g_match_info_free (pMatchInfo); - g_regex_unref (pRegex); - } - else - { - g_error ("PANIC: Failed to compile regex: %s", pError->message); - g_error_free (pError); - } - - if (bDefaultLocation) - { - #if GLIB_CHECK_VERSION(2, 73, 0) - pRegex = g_regex_new (" *XKBVARIANT *= *\"*([,a-zA-Z0-9]*)\"*", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, &pError); - #else - pRegex = g_regex_new (" *XKBVARIANT *= *\"*([,a-zA-Z0-9]*)\"*", (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, &pError); - #endif - } - else - { - #if GLIB_CHECK_VERSION(2, 73, 0) - pRegex = g_regex_new (" *Option +\"*XkbVariant\"* +\"*([,a-zA-Z0-9]*)\"*", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, &pError); - #else - pRegex = g_regex_new (" *Option +\"*XkbVariant\"* +\"*([,a-zA-Z0-9]*)\"*", (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, &pError); - #endif - } - - if (!pError) - { - GMatchInfo *pMatchInfo = NULL; - - #if GLIB_CHECK_VERSION(2, 73, 0) - gboolean bMatch = g_regex_match (pRegex, sFile, G_REGEX_MATCH_DEFAULT, &pMatchInfo); - #else - gboolean bMatch = g_regex_match (pRegex, sFile, (GRegexMatchFlags) 0, &pMatchInfo); - #endif - - if (bMatch) - { - gchar *sVariants = g_match_info_fetch (pMatchInfo, 1); - lVariants = g_strsplit (sVariants, ",", -1); - g_free (sVariants); - } - - g_match_info_free (pMatchInfo); - g_regex_unref (pRegex); - } - else - { - g_error ("PANIC: Failed to compile regex: %s", pError->message); - g_error_free (pError); - } - - g_free(sFile); - } - else - { - g_error ("PANIC: Failed to get %s contents: %s", sLocation, pError->message); - g_error_free (pError); - } - - guint nLayouts = g_strv_length (lLayouts); - - for (guint nLayout = 0; nLayout < nLayouts; nLayout++) - { - gchar *sId = NULL; - guint nVariantLength = 0; - - if (lVariants && lVariants[nLayout]) - { - nVariantLength = strlen (lVariants[nLayout]); - } - - if (nVariantLength) - { - sId = g_strconcat (lLayouts[nLayout], "+", lVariants[nLayout], NULL); - } - else - { - sId = g_strdup (lLayouts[nLayout]); - } - + gchar *sId = g_strdup ("us"); self->pPrivate->lLayoutRec = g_slist_append (self->pPrivate->lLayoutRec, sId); } - g_strfreev (lLayouts); - g_strfreev (lVariants); self->pPrivate->nLayout = 0; //~ Get system layouts diff --git a/src/keyboard-x11.c b/src/keyboard-x11.c index 83811521..efa9ec57 100644 --- a/src/keyboard-x11.c +++ b/src/keyboard-x11.c @@ -564,9 +564,159 @@ static void onUserChanged (GDBusConnection *pConnection, const gchar *sSender, c } } +static void getSystemLayouts (gchar *sLocation, Keyboard *self) +{ + gboolean bExists = g_file_test (sLocation, G_FILE_TEST_EXISTS); + + if (!bExists) + { + return; + } + + gchar *sFile = NULL; + GError *pError = NULL; + g_file_get_contents (sLocation, &sFile, NULL, &pError); + + if (pError) + { + g_error_free (pError); + + return; + } + + GRegex *pRegex = NULL; + gboolean bDefaultLocation = g_str_equal (sLocation, "/etc/default/keyboard"); + + if (bDefaultLocation) + { + #if GLIB_CHECK_VERSION(2, 73, 0) + pRegex = g_regex_new (" *XKBLAYOUT *= *\"*([,a-zA-Z0-9]*)\"*", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, &pError); + #else + pRegex = g_regex_new (" *XKBLAYOUT *= *\"*([,a-zA-Z0-9]*)\"*", (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, &pError); + #endif + } + else + { + #if GLIB_CHECK_VERSION(2, 73, 0) + pRegex = g_regex_new (" *Option +\"*XkbLayout\"* +\"*([,a-zA-Z0-9]*)\"*", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, &pError); + #else + pRegex = g_regex_new (" *Option +\"*XkbLayout\"* +\"*([,a-zA-Z0-9]*)\"*", (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, &pError); + #endif + } + + if (pError) + { + g_warning ("Panic: Failed to compile regex: %s", pError->message); + g_error_free (pError); + g_free(sFile); + + return; + } + + GMatchInfo *pMatchInfo = NULL; + + #if GLIB_CHECK_VERSION(2, 73, 0) + gboolean bMatch = g_regex_match (pRegex, sFile, G_REGEX_MATCH_DEFAULT, &pMatchInfo); + #else + gboolean bMatch = g_regex_match (pRegex, sFile, (GRegexMatchFlags) 0, &pMatchInfo); + #endif + + if (!bMatch) + { + g_regex_unref (pRegex); + g_free(sFile); + + return; + } + + gchar *sLayouts = g_match_info_fetch (pMatchInfo, 1); + GStrv lLayouts = g_strsplit (sLayouts, ",", -1); + g_free (sLayouts); + g_match_info_free (pMatchInfo); + g_regex_unref (pRegex); + + if (bDefaultLocation) + { + #if GLIB_CHECK_VERSION(2, 73, 0) + pRegex = g_regex_new (" *XKBVARIANT *= *\"*([,a-zA-Z0-9]*)\"*", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, &pError); + #else + pRegex = g_regex_new (" *XKBVARIANT *= *\"*([,a-zA-Z0-9]*)\"*", (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, &pError); + #endif + } + else + { + #if GLIB_CHECK_VERSION(2, 73, 0) + pRegex = g_regex_new (" *Option +\"*XkbVariant\"* +\"*([,a-zA-Z0-9]*)\"*", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, &pError); + #else + pRegex = g_regex_new (" *Option +\"*XkbVariant\"* +\"*([,a-zA-Z0-9]*)\"*", (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, &pError); + #endif + } + + if (pError) + { + g_warning ("Panic: Failed to compile regex: %s", pError->message); + g_error_free (pError); + g_free(sFile); + + return; + } + + #if GLIB_CHECK_VERSION(2, 73, 0) + bMatch = g_regex_match (pRegex, sFile, G_REGEX_MATCH_DEFAULT, &pMatchInfo); + #else + bMatch = g_regex_match (pRegex, sFile, (GRegexMatchFlags) 0, &pMatchInfo); + #endif + + if (!bMatch) + { + g_regex_unref (pRegex); + g_free(sFile); + + return; + } + + gchar *sVariants = g_match_info_fetch (pMatchInfo, 1); + GStrv lVariants = g_strsplit (sVariants, ",", -1); + g_free (sVariants); + g_match_info_free (pMatchInfo); + g_regex_unref (pRegex); + g_free(sFile); + guint nLayouts = g_strv_length (lLayouts); + GStrvBuilder *pBuilder = g_strv_builder_new (); + + for (guint nLayout = 0; nLayout < nLayouts; nLayout++) + { + gchar *sId = NULL; + guint nVariantLength = 0; + + if (lVariants && lVariants[nLayout]) + { + nVariantLength = strlen (lVariants[nLayout]); + } + + if (nVariantLength) + { + sId = g_strconcat (lLayouts[nLayout], "+", lVariants[nLayout], NULL); + } + else + { + sId = g_strdup (lLayouts[nLayout]); + } + + self->pPrivate->lLayoutRec = g_slist_append (self->pPrivate->lLayoutRec, sId); + g_strv_builder_add (pBuilder, sId); + } + + self->pPrivate->lSystemLayouts = g_strv_builder_end (pBuilder); + g_strv_builder_unref (pBuilder); + g_strfreev (lLayouts); + g_strfreev (lVariants); +} + static void keyboard_init(Keyboard *self) { self->pPrivate = keyboard_get_instance_private(self); + self->pPrivate->lLayoutRec = NULL; self->pPrivate->lLayouts = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, freeLayout); // Read all available layouts @@ -657,156 +807,23 @@ static void keyboard_init(Keyboard *self) self->pPrivate->nSubscription = g_dbus_connection_signal_subscribe (self->pPrivate->pConnection, NULL, GREETER_BUS_NAME, "UserChanged", GREETER_BUS_PATH, NULL, G_DBUS_SIGNAL_FLAGS_NONE, onUserChanged, self, NULL); // Get system layouts - gboolean bDefaultLocation = g_file_test ("/etc/default/keyboard", G_FILE_TEST_EXISTS); - gchar *sLocation = NULL; - - if (bDefaultLocation) - { - sLocation = "/etc/default/keyboard"; - } - else - { - sLocation = "/etc/X11/xorg.conf.d/00-keyboard.conf"; - } - - gchar *sFile = NULL; - GError *pError = NULL; - g_file_get_contents (sLocation, &sFile, NULL, &pError); - GStrv lLayouts = NULL; - GStrv lVariants = NULL; - - if (!pError) - { - GRegex *pRegex = NULL; - - if (bDefaultLocation) - { - #if GLIB_CHECK_VERSION(2, 73, 0) - pRegex = g_regex_new (" *XKBLAYOUT *= *\"*([,a-zA-Z0-9]*)\"*", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, &pError); - #else - pRegex = g_regex_new (" *XKBLAYOUT *= *\"*([,a-zA-Z0-9]*)\"*", (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, &pError); - #endif - } - else - { - #if GLIB_CHECK_VERSION(2, 73, 0) - pRegex = g_regex_new (" *Option +\"*XkbLayout\"* +\"*([,a-zA-Z0-9]*)\"*", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, &pError); - #else - pRegex = g_regex_new (" *Option +\"*XkbLayout\"* +\"*([,a-zA-Z0-9]*)\"*", (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, &pError); - #endif - } - - if (!pError) - { - GMatchInfo *pMatchInfo = NULL; - - #if GLIB_CHECK_VERSION(2, 73, 0) - gboolean bMatch = g_regex_match (pRegex, sFile, G_REGEX_MATCH_DEFAULT, &pMatchInfo); - #else - gboolean bMatch = g_regex_match (pRegex, sFile, (GRegexMatchFlags) 0, &pMatchInfo); - #endif - - if (bMatch) - { - gchar *sLayouts = g_match_info_fetch (pMatchInfo, 1); - lLayouts = g_strsplit (sLayouts, ",", -1); - g_free (sLayouts); - } - else - { - g_error ("PANIC: No system XkbLayout found"); - } - - g_match_info_free (pMatchInfo); - g_regex_unref (pRegex); - } - else - { - g_error ("PANIC: Failed to compile regex: %s", pError->message); - g_error_free (pError); - } - - if (bDefaultLocation) - { - #if GLIB_CHECK_VERSION(2, 73, 0) - pRegex = g_regex_new (" *XKBVARIANT *= *\"*([,a-zA-Z0-9]*)\"*", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, &pError); - #else - pRegex = g_regex_new (" *XKBVARIANT *= *\"*([,a-zA-Z0-9]*)\"*", (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, &pError); - #endif - } - else - { - #if GLIB_CHECK_VERSION(2, 73, 0) - pRegex = g_regex_new (" *Option +\"*XkbVariant\"* +\"*([,a-zA-Z0-9]*)\"*", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, &pError); - #else - pRegex = g_regex_new (" *Option +\"*XkbVariant\"* +\"*([,a-zA-Z0-9]*)\"*", (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, &pError); - #endif - } - - if (!pError) - { - GMatchInfo *pMatchInfo = NULL; - - #if GLIB_CHECK_VERSION(2, 73, 0) - gboolean bMatch = g_regex_match (pRegex, sFile, G_REGEX_MATCH_DEFAULT, &pMatchInfo); - #else - gboolean bMatch = g_regex_match (pRegex, sFile, (GRegexMatchFlags) 0, &pMatchInfo); - #endif - - if (bMatch) - { - gchar *sVariants = g_match_info_fetch (pMatchInfo, 1); - lVariants = g_strsplit (sVariants, ",", -1); - g_free (sVariants); - } - - g_match_info_free (pMatchInfo); - g_regex_unref (pRegex); - } - else - { - g_error ("PANIC: Failed to compile regex: %s", pError->message); - g_error_free (pError); - } + getSystemLayouts ("/etc/default/keyboard", self); - g_free(sFile); - } - else + if (!self->pPrivate->lLayoutRec) { - g_error ("PANIC: Failed to get %s contents: %s", sLocation, pError->message); - g_error_free (pError); + getSystemLayouts ("/etc/X11/xorg.conf.d/00-keyboard.conf", self); } - guint nLayouts = g_strv_length (lLayouts); - GStrvBuilder *pBuilder = g_strv_builder_new (); - - for (guint nLayout = 0; nLayout < nLayouts; nLayout++) + if (!self->pPrivate->lLayoutRec) { - gchar *sId = NULL; - guint nVariantLength = 0; - - if (lVariants && lVariants[nLayout]) - { - nVariantLength = strlen (lVariants[nLayout]); - } - - if (nVariantLength) - { - sId = g_strconcat (lLayouts[nLayout], "+", lVariants[nLayout], NULL); - } - else - { - sId = g_strdup (lLayouts[nLayout]); - } - + GStrvBuilder *pBuilder = g_strv_builder_new (); + gchar *sId = g_strdup ("us"); self->pPrivate->lLayoutRec = g_slist_append (self->pPrivate->lLayoutRec, sId); g_strv_builder_add (pBuilder, sId); + self->pPrivate->lSystemLayouts = g_strv_builder_end (pBuilder); + g_strv_builder_unref (pBuilder); } - self->pPrivate->lSystemLayouts = g_strv_builder_end (pBuilder); - g_strv_builder_unref (pBuilder); - g_strfreev (lLayouts); - g_strfreev (lVariants); self->pPrivate->nLayout = 0; //~ Get system layouts