summaryrefslogtreecommitdiffstats
path: root/modules/text_server_adv/text_server_adv.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/text_server_adv/text_server_adv.cpp')
-rw-r--r--modules/text_server_adv/text_server_adv.cpp63
1 files changed, 63 insertions, 0 deletions
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index f8dbbc2e61..bb49fb5248 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -347,6 +347,7 @@ bool TextServerAdvanced::has_feature(Feature p_feature) const {
case FEATURE_CONTEXT_SENSITIVE_CASE_CONVERSION:
case FEATURE_USE_SUPPORT_DATA:
case FEATURE_UNICODE_IDENTIFIERS:
+ case FEATURE_UNICODE_SECURITY:
return true;
default: {
}
@@ -5640,6 +5641,68 @@ String TextServerAdvanced::percent_sign(const String &p_language) const {
return "%";
}
+int TextServerAdvanced::is_confusable(const String &p_string, const PackedStringArray &p_dict) const {
+ UErrorCode status = U_ZERO_ERROR;
+ int match_index = -1;
+
+ Char16String utf16 = p_string.utf16();
+ Vector<UChar *> skeletons;
+ skeletons.resize(p_dict.size());
+
+ USpoofChecker *sc = uspoof_open(&status);
+ uspoof_setChecks(sc, USPOOF_CONFUSABLE, &status);
+ for (int i = 0; i < p_dict.size(); i++) {
+ Char16String word = p_dict[i].utf16();
+ int32_t len = uspoof_getSkeleton(sc, 0, word.get_data(), -1, NULL, 0, &status);
+ skeletons.write[i] = (UChar *)memalloc(++len * sizeof(UChar));
+ status = U_ZERO_ERROR;
+ uspoof_getSkeleton(sc, 0, word.get_data(), -1, skeletons.write[i], len, &status);
+ }
+
+ int32_t len = uspoof_getSkeleton(sc, 0, utf16.get_data(), -1, NULL, 0, &status);
+ UChar *skel = (UChar *)memalloc(++len * sizeof(UChar));
+ status = U_ZERO_ERROR;
+ uspoof_getSkeleton(sc, 0, utf16.get_data(), -1, skel, len, &status);
+ for (int i = 0; i < skeletons.size(); i++) {
+ if (u_strcmp(skel, skeletons[i]) == 0) {
+ match_index = i;
+ break;
+ }
+ }
+ memfree(skel);
+
+ for (int i = 0; i < skeletons.size(); i++) {
+ memfree(skeletons.write[i]);
+ }
+ uspoof_close(sc);
+
+ ERR_FAIL_COND_V_MSG(U_FAILURE(status), -1, u_errorName(status));
+
+ return match_index;
+}
+
+bool TextServerAdvanced::spoof_check(const String &p_string) const {
+ UErrorCode status = U_ZERO_ERROR;
+ Char16String utf16 = p_string.utf16();
+
+ USet *allowed = uset_openEmpty();
+ uset_addAll(allowed, uspoof_getRecommendedSet(&status));
+ uset_addAll(allowed, uspoof_getInclusionSet(&status));
+
+ USpoofChecker *sc = uspoof_open(&status);
+ uspoof_setAllowedChars(sc, allowed, &status);
+ uspoof_setRestrictionLevel(sc, USPOOF_MODERATELY_RESTRICTIVE);
+
+ int32_t bitmask = uspoof_check(sc, utf16.get_data(), -1, NULL, &status);
+
+ uspoof_close(sc);
+ uset_close(allowed);
+
+ ERR_FAIL_COND_V_MSG(U_FAILURE(status), false, u_errorName(status));
+
+ return (bitmask != 0);
+}
+
String TextServerAdvanced::strip_diacritics(const String &p_string) const {
UErrorCode err = U_ZERO_ERROR;