📄 slpd_predicate.c
字号:
/* returned through end. *//*--------------------------------------------------------------------------*/{ char *operator; /* Pointer to the operator substring. */ const char *cur; /* Current working character. */ const char *last_char; /* The last character in the working string. */ FilterResult err = FR_UNSET; /* The result of an evaluation. */ FilterResult stop_condition = FR_UNSET; if(recursion_depth <= 0) { return FR_PARSE_ERROR; } recursion_depth--; if(*start != BRACKET_OPEN) { return FR_PARSE_ERROR; } /***** Get the current expression. *****/ last_char = *end = find_bracket_end(start); if(*end == 0) { return FR_PARSE_ERROR; } (*end)++; /* Move the end pointer past the closing bracket. */ /**** * Check for the three legal characters that can follow an expression, * if the following character isn't one of those, the following character * is trash. ****/ if(!(**end == BRACKET_OPEN || **end == BRACKET_CLOSE || **end == '\0')) { return FR_PARSE_ERROR; } /***** check for boolean op. *****/ cur = start; cur++; switch(*cur) { case('&'): /***** And. *****/ case('|'): /***** Or. *****/ { if(*cur == '&') { stop_condition = FR_EVAL_FALSE; } else if(*cur == '|') { stop_condition = FR_EVAL_TRUE; } cur++; /* Move past operator. */ /*** Ensure that we have at least one operator. ***/ if(*cur != BRACKET_OPEN || cur >= last_char) { return FR_PARSE_ERROR; } /*** Evaluate each operand. ***/ /* NOTE: Due to the condition on the above "if", we are guarenteed that the first iteration of the loop is valid. */ do { err = filter(cur, &cur, slp_attr, recursion_depth); /*** Propagate errors. ***/ if(err != FR_EVAL_TRUE && err != FR_EVAL_FALSE) { return err; } /*** Short circuit. ***/ if(err == stop_condition) { return stop_condition; } } while(*cur == BRACKET_OPEN && cur < last_char); /*** If we ever get here, it means we've evaluated every operand without short circuiting -- meaning that the operation failed. ***/ return(stop_condition == FR_EVAL_TRUE ? FR_EVAL_FALSE : FR_EVAL_TRUE); } case('!'): /***** Not. *****/ /**** Child. ****/ cur++; err = filter(cur, &cur, slp_attr, recursion_depth); /*** Return errors. ***/ if(err != FR_EVAL_TRUE && err != FR_EVAL_FALSE) { return err; } /*** Perform "not". ***/ return(err == FR_EVAL_TRUE ? FR_EVAL_FALSE : FR_EVAL_TRUE); default: /***** Unknown operator. *****/ ; /* We don't do anything here because this will catch the first character of every leaf predicate. */ } /***** Check for leaf operator. *****/ if(IS_VALID_TAG_CHAR(*cur)) { Operation op; char *lhs, *rhs; /* The two operands. */ char *val_start; /* The character after the operator. ie, the start of the rhs. */ int lhs_len, rhs_len; /* Length of the lhs/rhs. */ SLPType type; SLPError slp_err; /**** Demux leaf op. ****/ /* Since all search operators contain a "=", we look for the equals * sign, and then poke around on either side of that for the real * value. */ operator = (char *)memchr(cur, '=', last_char - cur); if(operator == 0) { /**** No search operator. ****/ return FR_PARSE_ERROR; } /* The rhs always follows the operator. (This doesn't really make sense for PRESENT ops, but ignore that). */ val_start = operator + 1; /* Check for APPROX, GREATER, or LESS. Note that we shuffle the operator pointer back to point at the start of the op. */ if(operator == cur) {/* Check that we can poke back one char. */ return FR_PARSE_ERROR; } switch(*(operator - 1)) { case('~'): op = EQUAL; /* See Assumptions. */ operator--; break; case('>'): op = GREATER; operator--; break; case('<'): op = LESS; operator--; break; default: /* No prefix to the '='. */ /**** Check for PRESENT. ****/ if((operator == last_char - 2) && (*(operator+1) == '*')) { op = PRESENT; } /**** It's none of the above: therefore it's EQUAL. ****/ else { op = EQUAL; } } /***** Get operands. *****/ /**** Left. ****/ lhs_len = operator - cur; lhs = (char *)cur; /**** Right ****/ rhs_len = last_char - val_start; rhs = val_start; /***** Do leaf operation. *****/ /**** Check that tag exists. ****/ slp_err = SLPAttrGetType_len(slp_attr, lhs, lhs_len, &type); if(slp_err == SLP_TAG_ERROR) { /* Tag doesn't exist. */ return FR_EVAL_FALSE; } else if(slp_err == SLP_OK) { /* Tag exists. */ /**** Do operation. *****/ if(op == PRESENT) { /*** Since the PRESENT operation is the same for all types, do that now. ***/ return FR_EVAL_TRUE; } else { /*** A type-specific operation. ***/ switch(type) { case(SLP_BOOLEAN): err = bool_op(slp_attr, lhs, lhs_len, rhs, rhs_len, op); break; case(SLP_INTEGER): err = int_op(slp_attr, lhs, lhs_len, rhs, op); break; case(SLP_KEYWORD): err = keyw_op(slp_attr, lhs, rhs, op); break; case(SLP_STRING): err = str_op(slp_attr, lhs, lhs_len, rhs, rhs_len, op); break; case(SLP_OPAQUE): assert(0); /* Opaque is not yet supported. */ } } } else { /* Some other tag-related error. */ err = FR_INTERNAL_SYSTEM_ERROR; } assert(err != FR_UNSET); return err; } /***** No operator. *****/ return FR_PARSE_ERROR;}/*=========================================================================*/int SLPDPredicateTest(int version, int attrlistlen, const char* attrlist, int predicatelen, const char* predicate)/* Determine whether the specified attribute list satisfies *//* the specified predicate *//* *//* version (IN) SLP version of the predicate string (should always be *//* 2 since we don't handle SLPv1 predicates yet) *//* *//* attrlistlen (IN) length of attrlist *//* *//* attr (IN) attribute list to test *//* *//* predicatelen (IN) length of the predicate string *//* *//* predicate (IN) the predicate string *//* *//* Returns: Boolean value. Zero of test fails. Non-zero if test fails *//* or if there is a parse error in the predicate string *//*=========================================================================*/{ SLPAttributes attr; const char *end; /* Pointer to the end of the parsed attribute string. */ FilterResult err; char attrnull; char prednull; int result = 0; /* An NULL or empty string is always true. */ if(predicate == 0 || *(char *)predicate == 0) { return 1; } /* Attempt v1 too. */ if(version != 2 #if defined(ENABLE_SLPv1) && version != 1#endif ) { return 1; } /* TRICKY: Temporarily NULL terminate the attribute list */ /* and the predicate string. We can do this because */ /* there is room in the corresponding SLPv2 SRVREG */ /* and SRVRQST messages. Basically we are squashing */ /* the authcount and the spi string length. Don't */ /* worry, we fix things up later and it is MUCH */ /* faster than a malloc() for a new buffer 1 byte */ /* longer! */ prednull = predicate[predicatelen]; ((char*)predicate)[predicatelen] = 0; attrnull = attrlist[attrlistlen]; ((char*)attrlist)[attrlistlen] = 0; /* Generate an SLPAttr from the comma delimited list */ if(SLPAttrAlloc("en", NULL, SLP_FALSE, &attr) == 0) { if(SLPAttrFreshen(attr, attrlist) == 0) { switch(version) {#if defined(ENABLE_SLPv1) case 1: err=filterv1(predicate, &end, attr, SLPD_ATTR_RECURSION_DEPTH); break;#endif default: err=filter(predicate, &end, attr, SLPD_ATTR_RECURSION_DEPTH); break; } /* Check for trailing trash data. */ if((err == FR_EVAL_TRUE || err == FR_EVAL_FALSE) && *end != 0) { result = 0; } else if(err == FR_EVAL_TRUE) { result = 1; } } SLPAttrFree(attr); } /* Un null terminate */ ((char*)predicate)[predicatelen] = prednull; ((char*)attrlist)[attrlistlen] = attrnull; return result;}/*=========================================================================*/int SLPDFilterAttributes(int attrlistlen, const char* attrlist, int taglistlen, const char* taglist, int* resultlen, char** result)/* Copies attributes from the specified attribute list to a result string *//* according to the taglist as described by section 10.4. of RFC 2608 *//* *//* version (IN) SLP version of the predicate string (should always be *//* 2 since we don't handle SLPv1 predicates yet) *//* *//* attrlistlen (IN) length of attrlist *//* *//* attr (IN) attribute list to test *//* *//* predicatelen (IN) length of the predicate string *//* *//* predicate (IN) the predicate string *//* *//* Returns: Zero on success. Nonzero on failure *//*=========================================================================*/{ SLPAttributes attr; FilterResult err; char attrnull; char tagnull; *result = 0; *resultlen = 0; /* TRICKY: Temporarily NULL terminate the attribute list */ /* and the tag string. We can do this because */ /* there is room in the corresponding SLPv2 SRVREG */ /* and ATTRRQST messages. Basically we are squashing */ /* the authcount and the spi string length. Don't */ /* worry, we fix things up later and it is MUCH */ /* faster than a malloc() for a new buffer 1 byte */ /* longer! */ tagnull = taglist[taglistlen]; ((char*)taglist)[taglistlen] = 0; attrnull = attrlist[attrlistlen]; ((char*)attrlist)[attrlistlen] = 0; /* Generate an SLPAttr from the comma delimited list */ err = 1; if(SLPAttrAlloc("en", NULL, SLP_FALSE, &attr) == 0) { if(SLPAttrFreshen(attr, attrlist) == 0) { err = SLPAttrSerialize(attr, taglist, result, *resultlen, resultlen, SLP_FALSE); } SLPAttrFree(attr); } /* SLPAttrSerialize counts the NULL terminator which we don't care about*/ if(*resultlen) { *resultlen -= 1; } /* Un null terminate */ ((char*)taglist)[taglistlen] = tagnull; ((char*)attrlist)[attrlistlen] = attrnull; return(*resultlen == 0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -