diff --git a/Lib/ldap/filter.py b/Lib/ldap/filter.py index 782737aa..e95b5559 100644 --- a/Lib/ldap/filter.py +++ b/Lib/ldap/filter.py @@ -87,3 +87,21 @@ def time_span_filter( until_timestr=strf_secs(until_timestamp), ) # end of time_span_filter() + + +def is_filter(ldap_filter): + """ + Returns True if `ldap_filter' can be parsed as a valid LDAP filter, otherwise False is returned. + """ + import ldap + lo = ldap.initialize('') + try: + lo.search_ext_s('', ldap.SCOPE_BASE, ldap_filter) + except (ldap.FILTER_ERROR, TypeError, ValueError): + return False + except ldap.SERVER_DOWN: + # the filter syntax is valid, as the connection is not bound we expect SERVER_DOWN here + return True + finally: + lo.unbind() + raise RuntimeError('Could not check filter syntax.') # can not happen diff --git a/Tests/t_ldap_filter.py b/Tests/t_ldap_filter.py index 313b3733..972d9bf0 100644 --- a/Tests/t_ldap_filter.py +++ b/Tests/t_ldap_filter.py @@ -10,7 +10,7 @@ # Switch off processing .ldaprc or ldap.conf before importing _ldap os.environ['LDAPNOINIT'] = '1' -from ldap.filter import escape_filter_chars +from ldap.filter import escape_filter_chars, is_filter, filter_format class TestDN(unittest.TestCase): @@ -18,6 +18,27 @@ class TestDN(unittest.TestCase): test ldap.functions """ + def test_is_filter(self): + """ + test function is_filter() + """ + self.assertEqual(is_filter(''), True) + self.assertEqual(is_filter('foo='), True) + self.assertEqual(is_filter('foo=bar'), True) + self.assertEqual(is_filter('foo=*'), True) + self.assertEqual(is_filter(filter_format('foo=%s', ['*'])), True) + self.assertEqual(is_filter('(foo=bar)'), True) + self.assertEqual(is_filter('(&(foo=bar))'), True) + self.assertEqual(is_filter('(|(foo=bar))'), True) + self.assertEqual(is_filter('foo>='), True) + self.assertEqual(is_filter('(foo>=)'), True) + self.assertEqual(is_filter('foo==bar'), True) + self.assertEqual(is_filter('foobar'), False) + self.assertEqual(is_filter('(foo='), False) + self.assertEqual(is_filter('foo=)'), False) + self.assertEqual(is_filter('=bar'), False) + self.assertEqual(is_filter('foo=\x00'), False) + def test_escape_filter_chars_mode0(self): """ test function escape_filter_chars() with escape_mode=0