class ConfigRegexChecker(ConfigChecker): """ :param str regexString: """ def __init__(self, regexString): super(ConfigRegexChecker, self).__init__() self._regex = NdnRegexTopMatcher(regexString) def checkNames(self, packetName, keyLocatorName, state): """ :param Name packetName: :param Name keyLocatorName: :param ValidationState state: :rtype: bool """ result = self._regex.match(keyLocatorName) if not result: state.fail( ValidationError( ValidationError.POLICY_ERROR, "KeyLocator check failed: regex " + self._regex.getExpr() + " for packet " + packetName.toUri() + " is invalid (KeyLocator=" + keyLocatorName.toUri() + ")")) return result
def __init__(self, packetNameRegexString, packetNameExpansion, keyNameRegexString, keyNameExpansion, hyperRelation): super(ConfigHyperRelationChecker, self).__init__() self._packetNameRegex = NdnRegexTopMatcher(packetNameRegexString) self._packetNameExpansion = packetNameExpansion self._keyNameRegex = NdnRegexTopMatcher(keyNameRegexString) self._keyNameExpansion = keyNameExpansion self._hyperRelation = hyperRelation
class ConfigRegexNameFilter(ConfigFilter): """ ConfigRegexNameFilter extends ConfigFilter to check that the packet name matches the specified regular expression. The configuration {@code "filter { type name regex ^[^<KEY>]*<KEY><>*<ksk-.*>$ }"} creates {@code ConfigRegexNameFilter("^[^<KEY>]*<KEY><>*<ksk-.*>$") }. :param str regexString: The regex string. """ def __init__(self, regexString): super(ConfigRegexNameFilter, self).__init__() self._regex = NdnRegexTopMatcher(regexString) def matchName(self, packetName): """ Implementation of the check for match. :param Name packetName: The packet name, which is already stripped of signature components if this is a signed Interest name. :return: True for a match. :rtype: bool """ return self._regex.match(packetName)
class ConfigRegexChecker(ConfigChecker): """ :param str regexString: """ def __init__(self, regexString): super(ConfigRegexChecker, self).__init__() self._regex = NdnRegexTopMatcher(regexString) def checkNames(self, packetName, keyLocatorName, state): """ :param Name packetName: :param Name keyLocatorName: :param ValidationState state: :rtype: bool """ result = self._regex.match(keyLocatorName) if not result: state.fail(ValidationError(ValidationError.POLICY_ERROR, "KeyLocator check failed: regex " + self._regex.getExpr() + " for packet " + packetName.toUri() + " is invalid (KeyLocator=" + keyLocatorName.toUri() + ")")) return result
class ConfigHyperRelationChecker(ConfigChecker): """ :param str packetNameRegexString: :param str packetNameExpansion: :param str keyNameRegexString: :param str keyNameExpansion: :param int hyperRelation: The value for the ConfigNameRelation.Relation enum. """ def __init__(self, packetNameRegexString, packetNameExpansion, keyNameRegexString, keyNameExpansion, hyperRelation): super(ConfigHyperRelationChecker, self).__init__() self._packetNameRegex = NdnRegexTopMatcher(packetNameRegexString) self._packetNameExpansion = packetNameExpansion self._keyNameRegex = NdnRegexTopMatcher(keyNameRegexString) self._keyNameExpansion = keyNameExpansion self._hyperRelation = hyperRelation def checkNames(self, packetName, keyLocatorName, state): """ :param Name packetName: :param Name keyLocatorName: :param ValidationState state: :rtype: bool """ if not self._packetNameRegex.match(packetName): state.fail(ValidationError(ValidationError.POLICY_ERROR, "The packet " + packetName.toUri() + " (KeyLocator=" + keyLocatorName.toUri() + ") does not match the hyper relation packet name regex " + self._packetNameRegex.getExpr())) return False if not self._keyNameRegex.match(keyLocatorName): state.fail(ValidationError(ValidationError.POLICY_ERROR, "The packet " + packetName.toUri() + " (KeyLocator=" + keyLocatorName.toUri() + ") does not match the hyper relation key name regex " + self._keyNameRegex.getExpr())) return False keyNameMatchExpansion = self._keyNameRegex.expand(self._keyNameExpansion) packetNameMatchExpansion = self._packetNameRegex.expand( self._packetNameExpansion) result = ConfigNameRelation.checkNameRelation( self._hyperRelation, keyNameMatchExpansion, packetNameMatchExpansion) if not result: state.fail(ValidationError(ValidationError.POLICY_ERROR, "KeyLocator check failed: hyper relation " + ConfigNameRelation.toString(self._hyperRelation) + " packet name match=" + packetNameMatchExpansion.toUri() + ", key name match=" + keyNameMatchExpansion.toUri() + " of packet " + packetName.toUri() + " (KeyLocator=" + keyLocatorName.toUri() + ") is invalid")) return result
def _findMatchingRule(self, objName, matchType): """ Search the configuration file for the first rule that matches the data or signed interest name. In the case of interests, the name to match should exclude the timestamp, nonce, and signature components. :param Name objName: The name to be matched. :param string matchType: The rule type to match, "data" or "interest". """ rules = self.config["validator/rule"] for r in rules: if r['for'][0].getValue() == matchType: passed = True try: filters = r['filter'] except KeyError: # no filters means we pass! return r else: for f in filters: # don't check the type - it can only be name for now # we need to see if this is a regex or a relation regexPattern = f.getFirstValue("regex") if regexPattern == None: matchRelation = f.getFirstValue("relation") matchUri = f.getFirstValue("name") matchName = Name(matchUri) passed = self._matchesRelation( objName, matchName, matchRelation) else: passed = NdnRegexTopMatcher(regexPattern).match( objName) if not passed: break if passed: return r return None
def doesMatch(self, name): """ Check if the given name matches this filter. Match if name starts with this filter's prefix. If this filter has the optional regexFilter then the remaining components match the regexFilter regular expression. For example, the following InterestFilter: InterestFilter("/hello", "<world><>+") will match all Interests, whose name has the prefix `/hello` which is followed by a component `world` and has at least one more component after it. Examples: /hello/world/! /hello/world/x/y/z Note that the regular expression will need to match all remaining components (e.g., there are implicit heading `^` and trailing `$` symbols in the regular expression). :param Name name: The name to check against this filter. :return: True if name matches this filter, otherwise False. :rtype: bool """ if len(name) < len(self._prefix): return False if self.hasRegexFilter(): # Perform a prefix match and regular expression match for the # remaining components. if not self._prefix.match(name): return False return NdnRegexTopMatcher(self._regexFilterPattern).match( name.getSubName(len(self._prefix))) else: # Just perform a prefix match. return self._prefix.match(name)
def test_top_matcher_advanced(self): cm = NdnRegexTopMatcher("^(<.*>*)<.*>") res = cm.match(Name("/n/a/b/c")) self.assertEqual(True, res) self.assertEqual(4, len(cm.getMatchResult())) self.assertEqual(Name("/n/a/b/"), cm.expand("\\1")) cm = NdnRegexTopMatcher("^(<.*>*)<.*><c>(<.*>)<.*>") res = cm.match(Name("/n/a/b/c/d/e/")) self.assertEqual(True, res) self.assertEqual(6, len(cm.getMatchResult())) self.assertEqual(Name("/n/a/d/"), cm.expand("\\1\\2")) cm = NdnRegexTopMatcher("(<.*>*)<.*>$") res = cm.match(Name("/n/a/b/c/")) self.assertEqual(True, res) self.assertEqual(4, len(cm.getMatchResult())) self.assertEqual(Name("/n/a/b/"), cm.expand("\\1")) cm = NdnRegexTopMatcher("<.*>(<.*>*)<.*>$") res = cm.match(Name("/n/a/b/c/")) self.assertEqual(True, res) self.assertEqual(4, len(cm.getMatchResult())) self.assertEqual(Name("/a/b/"), cm.expand("\\1")) cm = NdnRegexTopMatcher("<a>(<>*)<>$") res = cm.match(Name("/n/a/b/c/")) self.assertEqual(True, res) self.assertEqual(4, len(cm.getMatchResult())) self.assertEqual(Name("/b/"), cm.expand("\\1")) cm = NdnRegexTopMatcher("^<ndn><(.*)\\.(.*)><DNS>(<>*)<>") res = cm.match(Name("/ndn/ucla.edu/DNS/yingdi/mac/ksk-1/")) self.assertEqual(True, res) self.assertEqual(6, len(cm.getMatchResult())) self.assertEqual(Name("/ndn/edu/ucla/yingdi/mac/"), cm.expand("<ndn>\\2\\1\\3")) cm = NdnRegexTopMatcher( "^<ndn><(.*)\\.(.*)><DNS>(<>*)<>", "<ndn>\\2\\1\\3") res = cm.match(Name("/ndn/ucla.edu/DNS/yingdi/mac/ksk-1/")) self.assertEqual(True, res) self.assertEqual(6, len(cm.getMatchResult())) self.assertEqual(Name("/ndn/edu/ucla/yingdi/mac/"), cm.expand())
def test_top_matcher(self): cm = NdnRegexTopMatcher("^<a><b><c>") res = cm.match(Name("/a/b/c/d")) self.assertEqual(True, res) self.assertEqual(4, len(cm.getMatchResult())) self.assertEqual("a", cm.getMatchResult()[0].toEscapedString()) self.assertEqual("b", cm.getMatchResult()[1].toEscapedString()) self.assertEqual("c", cm.getMatchResult()[2].toEscapedString()) self.assertEqual("d", cm.getMatchResult()[3].toEscapedString()) cm = NdnRegexTopMatcher("<b><c><d>$") res = cm.match(Name("/a/b/c/d")) self.assertEqual(True, res) self.assertEqual(4, len(cm.getMatchResult())) self.assertEqual("a", cm.getMatchResult()[0].toEscapedString()) self.assertEqual("b", cm.getMatchResult()[1].toEscapedString()) self.assertEqual("c", cm.getMatchResult()[2].toEscapedString()) self.assertEqual("d", cm.getMatchResult()[3].toEscapedString()) cm = NdnRegexTopMatcher("^<a><b><c><d>$") res = cm.match(Name("/a/b/c/d")) self.assertEqual(True, res) self.assertEqual(4, len(cm.getMatchResult())) self.assertEqual("a", cm.getMatchResult()[0].toEscapedString()) self.assertEqual("b", cm.getMatchResult()[1].toEscapedString()) self.assertEqual("c", cm.getMatchResult()[2].toEscapedString()) self.assertEqual("d", cm.getMatchResult()[3].toEscapedString()) res = cm.match(Name("/a/b/c/d/e")) self.assertEqual(False, res) self.assertEqual(0, len(cm.getMatchResult())) cm = NdnRegexTopMatcher("<a><b><c><d>") res = cm.match(Name("/a/b/c/d")) self.assertEqual(True, res) self.assertEqual(4, len(cm.getMatchResult())) self.assertEqual("a", cm.getMatchResult()[0].toEscapedString()) self.assertEqual("b", cm.getMatchResult()[1].toEscapedString()) self.assertEqual("c", cm.getMatchResult()[2].toEscapedString()) self.assertEqual("d", cm.getMatchResult()[3].toEscapedString()) cm = NdnRegexTopMatcher("<b><c>") res = cm.match(Name("/a/b/c/d")) self.assertEqual(True, res) self.assertEqual(4, len(cm.getMatchResult())) self.assertEqual("a", cm.getMatchResult()[0].toEscapedString()) self.assertEqual("b", cm.getMatchResult()[1].toEscapedString()) self.assertEqual("c", cm.getMatchResult()[2].toEscapedString()) self.assertEqual("d", cm.getMatchResult()[3].toEscapedString())
def __init__(self, regexString): super(ConfigRegexNameFilter, self).__init__() self._regex = NdnRegexTopMatcher(regexString)
class ConfigHyperRelationChecker(ConfigChecker): """ :param str packetNameRegexString: :param str packetNameExpansion: :param str keyNameRegexString: :param str keyNameExpansion: :param int hyperRelation: The value for the ConfigNameRelation.Relation enum. """ def __init__(self, packetNameRegexString, packetNameExpansion, keyNameRegexString, keyNameExpansion, hyperRelation): super(ConfigHyperRelationChecker, self).__init__() self._packetNameRegex = NdnRegexTopMatcher(packetNameRegexString) self._packetNameExpansion = packetNameExpansion self._keyNameRegex = NdnRegexTopMatcher(keyNameRegexString) self._keyNameExpansion = keyNameExpansion self._hyperRelation = hyperRelation def checkNames(self, packetName, keyLocatorName, state): """ :param Name packetName: :param Name keyLocatorName: :param ValidationState state: :rtype: bool """ if not self._packetNameRegex.match(packetName): state.fail( ValidationError( ValidationError.POLICY_ERROR, "The packet " + packetName.toUri() + " (KeyLocator=" + keyLocatorName.toUri() + ") does not match the hyper relation packet name regex " + self._packetNameRegex.getExpr())) return False if not self._keyNameRegex.match(keyLocatorName): state.fail( ValidationError( ValidationError.POLICY_ERROR, "The packet " + packetName.toUri() + " (KeyLocator=" + keyLocatorName.toUri() + ") does not match the hyper relation key name regex " + self._keyNameRegex.getExpr())) return False keyNameMatchExpansion = self._keyNameRegex.expand( self._keyNameExpansion) packetNameMatchExpansion = self._packetNameRegex.expand( self._packetNameExpansion) result = ConfigNameRelation.checkNameRelation( self._hyperRelation, keyNameMatchExpansion, packetNameMatchExpansion) if not result: state.fail( ValidationError( ValidationError.POLICY_ERROR, "KeyLocator check failed: hyper relation " + ConfigNameRelation.toString(self._hyperRelation) + " packet name match=" + packetNameMatchExpansion.toUri() + ", key name match=" + keyNameMatchExpansion.toUri() + " of packet " + packetName.toUri() + " (KeyLocator=" + keyLocatorName.toUri() + ") is invalid")) return result
def _checkSignatureMatch(self, signatureName, objectName, rule, failureReason): """ Once a rule is found to match data or a signed interest, the name in the KeyLocator must satisfy the condition in the 'checker' section of the rule, else the data or interest is rejected. :param Name signatureName: The certificate name from the KeyLocator . :param Name objectName: The name of the data packet or interest. In the case of signed interests, this excludes the timestamp, nonce and signature components. :param BoostInfoTree rule: The rule from the configuration file that matches the data or interest. :param Array<str> failureReason: If verification fails, set failureReason[0] to the failure reason string. :return: True if matches. :rtype: bool """ checker = rule['checker'][0] checkerType = checker['type'][0].getValue() if checkerType == 'fixed-signer': signerInfo = checker['signer'][0] signerType = signerInfo['type'][0].getValue() if signerType == 'file': if self._isSecurityV1: cert = self._lookupCertificate( signerInfo['file-name'][0].getValue(), True) if cert is None: failureReason[0] = ( "Can't find fixed-signer certificate file: " + signerInfo['file-name'][0].getValue()) return False else: cert = self._lookupCertificateV2( signerInfo['file-name'][0].getValue(), True) if cert is None: failureReason[0] = ( "Can't find fixed-signer certificate file: " + signerInfo['file-name'][0].getValue()) return False elif signerType == 'base64': if self._isSecurityV1: cert = self._lookupCertificate( signerInfo['base64-string'][0].getValue(), False) if cert is None: failureReason[0] = ( "Can't find fixed-signer certificate base64: " + signerInfo['base64-string'][0].getValue()) return False else: cert = self._lookupCertificateV2( signerInfo['base64-string'][0].getValue(), False) if cert is None: failureReason[0] = ( "Can't find fixed-signer certificate base64: " + signerInfo['base64-string'][0].getValue()) return False else: failureReason[0] = ("Unrecognized fixed-signer signerType: " + signerType) return False if cert.getName().equals(signatureName): return True else: failureReason[0] = ("fixed-signer cert name \"" + cert.getName().toUri() + "\" does not equal signatureName \"" + signatureName.toUri() + "\"") return False elif checkerType == 'hierarchical': # this just means the data/interest name has the signing identity as a prefix # that means everything before 'ksk-?' in the key name identityRegex = '^([^<KEY>]*)<KEY>(<>*)<ksk-.+><ID-CERT>' identityMatch = NdnRegexTopMatcher(identityRegex) if identityMatch.match(signatureName): identityPrefix = identityMatch.expand("\\1").append( identityMatch.expand("\\2")) if self._matchesRelation(objectName, identityPrefix, 'is-prefix-of'): return True else: failureReason[0] = ("The hierarchical objectName \"" + objectName.toUri() + "\" is not a prefix of \"" + identityPrefix.toUri() + "\"") return False if not self._isSecurityV1: # Check for a security v2 key name. identityRegex2 = "^(<>*)<KEY><>$" identityMatch2 = NdnRegexTopMatcher(identityRegex2) if identityMatch2.match(signatureName): identityPrefix = identityMatch2.expand("\\1") if self._matchesRelation(objectName, identityPrefix, 'is-prefix-of'): return True else: failureReason[0] = ("The hierarchical objectName \"" + objectName.toUri() + "\" is not a prefix of \"" + identityPrefix.toUri() + "\"") return False failureReason[0] = ("The hierarchical identityRegex \"" + identityRegex + "\" does not match signatureName \"" + signatureName.toUri() + "\"") return False elif checkerType == 'customized': keyLocatorInfo = checker['key-locator'][0] # not checking type - only name is supported # is this a simple relation? relationType = keyLocatorInfo.getFirstValue("relation") if relationType != None: matchName = Name(keyLocatorInfo['name'][0].getValue()) if self._matchesRelation(signatureName, matchName, relationType): return True else: failureReason[0] = ("The custom signatureName \"" + signatureName.toUri() + "\" does not match matchName \"" + matchName.toUri() + "\" using relation " + relationType) return False # Is this a simple regex? simpleKeyRegex = keyLocatorInfo.getFirstValue("regex") if simpleKeyRegex != None: if NdnRegexTopMatcher(simpleKeyRegex).match(signatureName): return True else: failureReason[0] = ( "The custom signatureName \"" + signatureName.toUri() + "\" does not regex match simpleKeyRegex \"" + simpleKeyRegex + "\"") return False # is this a hyper-relation? hyperRelationList = keyLocatorInfo["hyper-relation"] if len(hyperRelationList) >= 1: hyperRelation = hyperRelationList[0] keyRegex = hyperRelation.getFirstValue('k-regex') keyExpansion = hyperRelation.getFirstValue('k-expand') nameRegex = hyperRelation.getFirstValue('p-regex') nameExpansion = hyperRelation.getFirstValue('p-expand') relationType = hyperRelation.getFirstValue('h-relation') if (keyRegex != None and keyExpansion != None and nameRegex != None and nameExpansion != None and relationType != None): keyMatch = NdnRegexTopMatcher(keyRegex) if not keyMatch.match(signatureName): failureReason[0] = ( "The custom hyper-relation signatureName \"" + signatureName.toUri() + "\" does not match the keyRegex \"" + keyRegex + "\"") return False keyMatchPrefix = keyMatch.expand(keyExpansion) nameMatch = NdnRegexTopMatcher(nameRegex) if not nameMatch.match(objectName): failureReason[0] = ( "The custom hyper-relation objectName \"" + objectName.toUri() + "\" does not match the nameRegex \"" + nameRegex + "\"") return False nameMatchExpansion = nameMatch.expand(nameExpansion) if self._matchesRelation(nameMatchExpansion, keyMatchPrefix, relationType): return True else: failureReason[0] = ( "The custom hyper-relation nameMatch \"" + nameMatchExpansion.toUri() + "\" does not match the keyMatchPrefix \"" + keyMatchPrefix.toUri() + "\" using relation " + relationType) return False failureReason[0] = "Unrecognized checkerType: " + checkerType return False
def _checkSignatureMatch(self, signatureName, objectName, rule, failureReason): """ Once a rule is found to match data or a signed interest, the name in the KeyLocator must satisfy the condition in the 'checker' section of the rule, else the data or interest is rejected. :param Name signatureName: The certificate name from the KeyLocator . :param Name objectName: The name of the data packet or interest. In the case of signed interests, this excludes the timestamp, nonce and signature components. :param BoostInfoTree rule: The rule from the configuration file that matches the data or interest. :param Array<str> failureReason: If verification fails, set failureReason[0] to the failure reason string. :return: True if matches. :rtype: bool """ checker = rule['checker'][0] checkerType = checker['type'][0].getValue() if checkerType == 'fixed-signer': signerInfo = checker['signer'][0] signerType = signerInfo['type'][0].getValue() if signerType == 'file': if self._isSecurityV1: cert = self._lookupCertificate( signerInfo['file-name'][0].getValue(), True) if cert is None: failureReason[0] = ( "Can't find fixed-signer certificate file: " + signerInfo['file-name'][0].getValue()) return False else: cert = self._lookupCertificateV2( signerInfo['file-name'][0].getValue(), True) if cert is None: failureReason[0] = ( "Can't find fixed-signer certificate file: " + signerInfo['file-name'][0].getValue()) return False elif signerType == 'base64': if self._isSecurityV1: cert = self._lookupCertificate( signerInfo['base64-string'][0].getValue(), False) if cert is None: failureReason[0] = ( "Can't find fixed-signer certificate base64: " + signerInfo['base64-string'][0].getValue()) return False else: cert = self._lookupCertificateV2( signerInfo['base64-string'][0].getValue(), False) if cert is None: failureReason[0] = ( "Can't find fixed-signer certificate base64: " + signerInfo['base64-string'][0].getValue()) return False else: failureReason[0] = ("Unrecognized fixed-signer signerType: " + signerType) return False if cert.getName().equals(signatureName): return True else: failureReason[0] = ("fixed-signer cert name \"" + cert.getName().toUri() + "\" does not equal signatureName \"" + signatureName.toUri() + "\"") return False elif checkerType == 'hierarchical': # this just means the data/interest name has the signing identity as a prefix # that means everything before 'ksk-?' in the key name identityRegex = '^([^<KEY>]*)<KEY>(<>*)<ksk-.+><ID-CERT>' identityMatch = NdnRegexTopMatcher(identityRegex) if identityMatch.match(signatureName): identityPrefix = identityMatch.expand("\\1").append( identityMatch.expand("\\2")) if self._matchesRelation(objectName, identityPrefix, 'is-prefix-of'): return True else: failureReason[0] = ("The hierarchical objectName \"" + objectName.toUri() + "\" is not a prefix of \"" + identityPrefix.toUri() + "\"") return False if not self._isSecurityV1: # Check for a security v2 key name. identityRegex2 = "^(<>*)<KEY><>$" identityMatch2 = NdnRegexTopMatcher(identityRegex2) if identityMatch2.match(signatureName): identityPrefix = identityMatch2.expand("\\1") if self._matchesRelation(objectName, identityPrefix, 'is-prefix-of'): return True else: failureReason[0] = ("The hierarchical objectName \"" + objectName.toUri() + "\" is not a prefix of \"" + identityPrefix.toUri() + "\"") return False failureReason[0] = ("The hierarchical identityRegex \"" + identityRegex + "\" does not match signatureName \"" + signatureName.toUri() + "\"") return False elif checkerType == 'customized': keyLocatorInfo = checker['key-locator'][0] # not checking type - only name is supported # is this a simple relation? relationType = keyLocatorInfo.getFirstValue("relation") if relationType != None: matchName = Name(keyLocatorInfo['name'][0].getValue()) if self._matchesRelation(signatureName, matchName, relationType): return True else: failureReason[0] = ("The custom signatureName \"" + signatureName.toUri() + "\" does not match matchName \"" + matchName.toUri() + "\" using relation " + relationType) return False # Is this a simple regex? simpleKeyRegex = keyLocatorInfo.getFirstValue("regex") if simpleKeyRegex != None: if NdnRegexTopMatcher(simpleKeyRegex).match(signatureName): return True else: failureReason[0] = ("The custom signatureName \"" + signatureName.toUri() + "\" does not regex match simpleKeyRegex \"" + simpleKeyRegex + "\"") return False # is this a hyper-relation? hyperRelationList = keyLocatorInfo["hyper-relation"] if len(hyperRelationList) >= 1: hyperRelation = hyperRelationList[0] keyRegex = hyperRelation.getFirstValue('k-regex') keyExpansion = hyperRelation.getFirstValue('k-expand') nameRegex = hyperRelation.getFirstValue('p-regex') nameExpansion = hyperRelation.getFirstValue('p-expand') relationType = hyperRelation.getFirstValue('h-relation') if (keyRegex != None and keyExpansion != None and nameRegex != None and nameExpansion != None and relationType != None): keyMatch = NdnRegexTopMatcher(keyRegex) if not keyMatch.match(signatureName): failureReason[0] = ( "The custom hyper-relation signatureName \"" + signatureName.toUri() + "\" does not match the keyRegex \"" + keyRegex + "\"") return False keyMatchPrefix = keyMatch.expand(keyExpansion) nameMatch = NdnRegexTopMatcher(nameRegex) if not nameMatch.match(objectName): failureReason[0] = ( "The custom hyper-relation objectName \"" + objectName.toUri() + "\" does not match the nameRegex \"" + nameRegex + "\"") return False nameMatchExpansion = nameMatch.expand(nameExpansion) if self._matchesRelation( nameMatchExpansion, keyMatchPrefix, relationType): return True else: failureReason[0] = ( "The custom hyper-relation nameMatch \"" + nameMatchExpansion.toUri() + "\" does not match the keyMatchPrefix \"" + keyMatchPrefix.toUri() + "\" using relation " + relationType) return False failureReason[0] = "Unrecognized checkerType: " + checkerType return False