Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 | // // QueryHelpers.h // CoreEntitlements // #pragma once /*! * @function CESelectIndex * Returns an operation that when executed will modify the context such that any subsequent operation is performed on the entitlement object at the specified index * * @param index * The index of the object within a container * * @discussion * Using an index that is past the container's size will result in an invalid context */ #define CESelectIndex(index) (CEQueryOperation_t){.opcode = kCEOpSelectIndex, .parameters = {.numericParameter = index}} /*! * @function CESelectKey * Returns an operation that when executed will modify the context such that any subsequent operation is performed on the key of the dictionary pair * @discussion * Selecting a key on a non-dictionary-pair object is undefined behavior (i..e. it is implementation defined) */ #define CESelectKey() CESelectIndex(0) /*! * @function CESelectValue * Returns an operation that when executed will modify the context such that any subsequent operation is performed on the value of the dictionary pair * @discussion * Selecting a value on a non-dictionary-pair object is undefined behavior (i..e. it is implementation defined) */ #define CESelectValue() CESelectIndex(1) /*! * @function CESelectDictValue * Returns an operation that when executed will modify the context such that any subsequent operation is performed on the object that corresponds * to the value pointed to by the specified key * * @param key * The key of the object within a container * * @discussion * Using a key that is not found in the container will result in an invalid context */ #define CESelectDictValue(key) (CEQueryOperation_t){.opcode = kCEOpSelectKey, .parameters = {.stringParameter = {.data = key, .length = sizeof(key) - 1}}} #define CESelectDictValueDynamic(key, len) (CEQueryOperation_t){.opcode = (CEQueryOpOpcode_t)(kCEOpSelectKey | kCEOpDynamic), .parameters = {.dynamicParameter = {.data = key, .length = len}}} /*! * @function CEMatchString * Returns an operation that will return a valid context if and only if the context corresponds to a valid string and matches the string exactly * * @param string * The string to match against (MUST BE A STRING LITERAL) * * @discussion * If a valid context is returned it will be in the same state as the execution context */ #define CEMatchString(string) (CEQueryOperation_t){.opcode = kCEOpMatchString, .parameters = {.stringParameter = {.data = string, .length = sizeof(string) - 1}}} #define CEMatchDynamicString(string, len) (CEQueryOperation_t){.opcode = kCEOpMatchString | kCEOpDynamic, .parameters = {.dynamicParameter = {.data = string, .length = len}}} /*! * @function CEMatchPrefix * Returns an operation that will return a valid context if and only if the context corresponds to a valid string and it's prefix matched the passed in prefix * * @param prefix * The prefix to match against (MUST BE A STRING LITERAL) * * @discussion * If a valid context is returned it will be in the same state as the execution context */ #define CEMatchPrefix(prefix) (CEQueryOperation_t){.opcode = kCEOpMatchStringPrefix, .parameters = {.stringParameter = {.data = prefix, .length = sizeof(prefix) - 1}}} #define CEMatchDynamicPrefix(prefix, len) (CEQueryOperation_t){.opcode = kCEOpMatchStringPrefix | kCEOpDynamic, .parameters = {.dynamicParameter = {.data = prefix, .length = len}}} /*! * @function CEMatchBool * Returns an operation that will return a valid context if and only if the context corresponds to a valid boolean and matches the boolean exactly * * @param val * The bool to match against * * @discussion * If a valid context is returned it will be in the same state as the execution context */ #define CEMatchBool(val) (CEQueryOperation_t){.opcode = kCEOpMatchBool, .parameters = {.numericParameter = !!val}} /*! * @function CEMatchInteger * Returns an operation that will return a valid context if and only if the context corresponds to a valid integer and matches the integer exactly * * @param val * The integer to match against * * @discussion * If a valid context is returned it will be in the same state as the execution context */ #define CEMatchInteger(val) (CEQueryOperation_t){.opcode = kCEOpMatchInteger, .parameters = {.numericParameter = val}} /*! * @function CEIsStringAllowed * Returns an operation that will return a valid context if 1) the current context is a string and allows the string via wildcard rules, or 2) the context is an array of strings that allows the string * * @param string * The string to match against (MUST BE A STRING LITERAL) * * @discussion * If a valid context is returned it will be in the same state as the execution context */ #define CEIsStringAllowed(string) (CEQueryOperation_t){.opcode = kCEOpStringValueAllowed, .parameters = {.stringParameter = {.data = string, .length = sizeof(string) - 1}}} #define CEIsDynamicStringAllowed(string, len) (CEQueryOperation_t){.opcode = kCEOpStringValueAllowed | kCEOpDynamic, .parameters = {.dynamicParameter = {.data = string, .length = len}}} /*! * @function CEIsStringPrefixAllowed * Returns an operation that will return a valid context if 1) the current context is a string and matches the prefix or 2) has an array that has the matches the prefix * * @param string * The string to match against (MUST BE A STRING LITERAL) * * @discussion * If a valid context is returned it will be in the same state as the execution context */ #define CEIsStringPrefixAllowed(string) (CEQueryOperation_t){.opcode = kCEOpStringPrefixValueAllowed, .parameters = {.stringParameter = {.data = string, .length = sizeof(string) - 1}}} #define CEIsDynamicStringPrefixAllowed(string, len) (CEQueryOperation_t){.opcode = kCEOpStringPrefixValueAllowed | kCEOpDynamic, .parameters = {.dynamicParameter = {.data = string, .length = len}}} #pragma mark Helpers /* Macro magic */ #define _SELECT_NTH_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, N, ...) N #define _mc_1(_call, x) _call(x), #define _mc_2(_call, x, ...) _call(x), _mc_1(_call, __VA_ARGS__) #define _mc_3(_call, x, ...) _call(x), _mc_2(_call, __VA_ARGS__) #define _mc_4(_call, x, ...) _call(x), _mc_3(_call, __VA_ARGS__) #define _mc_5(_call, x, ...) _call(x), _mc_4(_call, __VA_ARGS__) #define _mc_6(_call, x, ...) _call(x), _mc_5(_call, __VA_ARGS__) #define _mc_7(_call, x, ...) _call(x), _mc_6(_call, __VA_ARGS__) #define _mc_8(_call, x, ...) _call(x), _mc_7(_call, __VA_ARGS__) #define _mc_9(_call, x, ...) _call(x), _mc_8(_call, __VA_ARGS__) #define _mc_10(_call, x, ...) _call(x), _mc_9(_call, __VA_ARGS__) #define _MACRO_ITER(macro, ...) _SELECT_NTH_ARG(__VA_ARGS__, _mc_10, _mc_9, _mc_8 _mc_7, _mc_6, _mc_5, _mc_4, _mc_3, _mc_2, _mc_1)(macro, __VA_ARGS__) /*! Macro to automatically generate a query path from a list of string sub components So @code CE_SELECT_PATH("hello, "world") will select a key "hello" and then look up "world" in the dictionary stored in the value of "hello" @endcode */ #define CE_SELECT_PATH(...) _MACRO_ITER(CESelectDictValue, __VA_ARGS__) // Macro for string equals #define CE_STRING_EQUALS(str) CEMatchString(str) /* A macro that checks if the passed in context grants (via an explicit true boolean) the entitlement at the passed in path. */ #define CE_CONTEXT_GRANTS_ENTITLEMENT(ctx, ...) (CEContextQuery(ctx, (CEQuery_t){CE_SELECT_PATH(__VA_ARGS__) CEMatchBool(true)}, sizeof((CEQuery_t){CE_SELECT_PATH(__VA_ARGS__) CEMatchBool(true)}) / sizeof(CEQueryOperation_t)) == kCENoError) |