Welcome to mirror list, hosted at ThFree Co, Russian Federation.

dev.gajim.org/gajim/python-nbxmpp.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Hörist <philipp@hoerist.com>2023-02-05 17:23:34 +0300
committerPhilipp Hörist <philipp@hoerist.com>2023-02-05 17:54:38 +0300
commit83f0dd1de8ef8a5c2ce1a087c4e7e38856b5cb1c (patch)
tree26f2eb6f6719f4c684dfb0d2dbf8d21a5e979c12
parent8883336f27cff82dc847acf1fc2f266a69475b1c (diff)
imprv: Add SASLprep profile
-rw-r--r--nbxmpp/stringprep.py48
-rw-r--r--test/unit/test_stringprep.py54
2 files changed, 102 insertions, 0 deletions
diff --git a/nbxmpp/stringprep.py b/nbxmpp/stringprep.py
index 84943e4..9f3a43e 100644
--- a/nbxmpp/stringprep.py
+++ b/nbxmpp/stringprep.py
@@ -241,3 +241,51 @@ def nameprep(string: str, allow_unassigned: bool = False) -> str:
)
return ''.join(chars)
+
+
+def _saslprep_do_mapping(chars: list[str]) -> None:
+ i = 0
+ while i < len(chars):
+ c = chars[i]
+ if stringprep.in_table_b1(c):
+ del chars[i]
+
+ elif stringprep.in_table_c12(c):
+ chars[i] = ' '
+
+ i += 1
+
+
+def saslprep(string: str, allow_unassigned: bool = False) -> str:
+ '''
+ Process the given `string` using the SASLprep (`RFC 4013`_) profile.
+ '''
+
+ chars = list(string)
+ _saslprep_do_mapping(chars)
+ do_normalization(chars)
+ check_against_tables(
+ chars,
+ (
+ stringprep.in_table_c12,
+ stringprep.in_table_c21,
+ stringprep.in_table_c22,
+ stringprep.in_table_c3,
+ stringprep.in_table_c4,
+ stringprep.in_table_c5,
+ stringprep.in_table_c6,
+ stringprep.in_table_c7,
+ stringprep.in_table_c8,
+ stringprep.in_table_c9,
+ ))
+ check_bidi(chars)
+
+ if not allow_unassigned:
+ check_against_tables(
+ chars,
+ (
+ stringprep.in_table_a1,
+ )
+ )
+
+ return ''.join(chars)
diff --git a/test/unit/test_stringprep.py b/test/unit/test_stringprep.py
index 06cb769..5817a29 100644
--- a/test/unit/test_stringprep.py
+++ b/test/unit/test_stringprep.py
@@ -1,6 +1,7 @@
import unittest
from nbxmpp.stringprep import nodeprep
+from nbxmpp.stringprep import saslprep
from nbxmpp.stringprep import resourceprep
from nbxmpp.stringprep import nameprep
from nbxmpp.stringprep import check_bidi
@@ -201,3 +202,56 @@ class TestResourceprep(unittest.TestCase):
self.assertEqual(
'\u0221',
resourceprep('\u0221', allow_unassigned=True))
+
+
+class TestSASLprep(unittest.TestCase):
+ def test_map_to_nothing(self):
+ self.assertEqual(
+ 'IX',
+ saslprep('I\u00ADX'),
+ 'SASLprep requirement: map SOFT HYPHEN to nothing')
+
+ def test_nfkc(self):
+ self.assertEqual(
+ 'a',
+ saslprep('\u00AA'),
+ 'SASLprep requirement: NFKC')
+ self.assertEqual(
+ 'IX',
+ saslprep('\u2168'),
+ 'SASLprep requirement: NFKC')
+
+ def test_case_fold(self):
+ self.assertNotEqual(
+ 'user',
+ saslprep('USER'),
+ 'SASLprep requirement: No CaseFold')
+
+ def test_prohibited_character(self):
+ with self.assertRaisesRegex(
+ ValueError,
+ r'U\+0007',
+ msg='SASLprep requirement: '
+ 'prohibited character (C.2.1)'):
+ saslprep('\u0007')
+
+ def test_bidi_check(self):
+ with self.assertRaises(
+ ValueError,
+ msg='SASLprep requirement: bidi check'):
+ saslprep('\u0627\u0031')
+
+ def test_unassigned(self):
+ with self.assertRaises(
+ ValueError,
+ msg='SASLprep requirement: unassigned'):
+ saslprep('\u0221', allow_unassigned=False)
+
+ with self.assertRaises(
+ ValueError,
+ msg='enforce no unassigned by default'):
+ saslprep('\u0221')
+
+ self.assertEqual(
+ '\u0221',
+ saslprep('\u0221', allow_unassigned=True))