/*
- * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2003, 2004, 2006-2008, 2011, 2012, 2015 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
- *
- * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
- *
+ *
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
- *
+ *
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
- *
+ *
* @APPLE_LICENSE_HEADER_END@
*/
typedef struct {
CFMutableArrayRef pInfo;
- regex_t *preg;
+ CFDataRef pRegex;
} addContext, *addContextRef;
}
-static void
-identifyKeyForPattern(const void *key, void *val, void *context)
+static Boolean
+keyMatchesPattern(CFStringRef key, CFDataRef pRegex)
{
- CFStringRef storeKey = (CFStringRef)key;
- CFDictionaryRef storeValue = (CFDictionaryRef)val;
- CFMutableArrayRef pInfo = ((addContextRef)context)->pInfo;
- regex_t * preg = ((addContextRef)context)->preg;
-
CFIndex len;
+ Boolean match = FALSE;
+ regex_t *preg;
int reError;
char str_q[256];
char * str = str_q;
- if (!CFDictionaryContainsKey(storeValue, kSCDData)) {
- /* if no data (yet) */
- return;
- }
-
/* convert store key to C string */
- len = CFStringGetLength(storeKey) + 1;
+ len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(key), kCFStringEncodingASCII) + 1;
if (len > (CFIndex)sizeof(str_q))
str = CFAllocatorAllocate(NULL, len, 0);
- if (_SC_cfstring_to_cstring(storeKey, str, len, kCFStringEncodingASCII) == NULL) {
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not convert store key to C string"));
+ if (_SC_cfstring_to_cstring(key, str, len, kCFStringEncodingASCII) == NULL) {
+ SC_log(LOG_INFO, "could not convert store key to C string");
goto done;
}
- /* compare store key to new notification keys regular expression pattern */
+ /* ALIGN: CF aligns to >8 byte boundries */
+ preg = (regex_t *)(void *)CFDataGetBytePtr(pRegex);
+
+ /* compare key to regular expression pattern */
reError = regexec(preg, str, 0, NULL, 0);
switch (reError) {
case 0 :
- /* we've got a match */
- CFArrayAppendValue(pInfo, storeKey);
+ match = TRUE;
break;
case REG_NOMATCH :
/* no match */
char reErrBuf[256];
(void)regerror(reError, preg, reErrBuf, sizeof(reErrBuf));
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf);
+ SC_log(LOG_INFO, "regexec() failed: %s", reErrBuf);
break;
}
}
done :
if (str != str_q) CFAllocatorDeallocate(NULL, str);
+ return match;
+}
+
+
+static void
+identifyKeyForPattern(const void *key, void *val, void *context)
+{
+ CFStringRef storeKey = (CFStringRef)key;
+ CFDictionaryRef storeValue = (CFDictionaryRef)val;
+ CFMutableArrayRef pInfo = ((addContextRef)context)->pInfo;
+ CFDataRef pRegex = ((addContextRef)context)->pRegex;
+
+ if (!CFDictionaryContainsKey(storeValue, kSCDData)) {
+ /* if no data (yet) */
+ return;
+ }
+
+ if (keyMatchesPattern(storeKey, pRegex)) {
+ /* if we've got a match */
+ CFArrayAppendValue(pInfo, storeKey);
+ }
+
return;
}
-__private_extern__ Boolean
-patternCompile(CFStringRef pattern, regex_t *preg, CFStringRef *error)
+static Boolean
+patternCompile(CFStringRef pattern, CFDataRef pRegex, CFStringRef *error)
{
Boolean append = FALSE;
Boolean insert = FALSE;
CFIndex len = 0;
+ CFIndex len_c;
Boolean ok;
char str_q[256];
char * str = str_q;
+ if (CFStringGetLength(pattern) == 0) {
+ SC_log(LOG_NOTICE, "empty regex pattern");
+ }
+
if (!CFStringHasPrefix(pattern, CFSTR("^"))) {
insert = TRUE;
}
append ? "$" : "");
}
- (void)CFStringGetBytes(pattern,
- CFRangeMake(0, CFStringGetLength(pattern)),
- kCFStringEncodingASCII,
- 0,
- FALSE,
- NULL,
- 0,
- &len);
+ len_c = CFStringGetBytes(pattern,
+ CFRangeMake(0, CFStringGetLength(pattern)),
+ kCFStringEncodingASCII,
+ 0,
+ FALSE,
+ NULL,
+ 0,
+ &len);
+ if (len_c <= 0) {
+ SC_log(LOG_NOTICE, "could not get buffer length for \"%@\"", pattern);
+ len = sizeof(str_q) - 1;
+ }
if (++len > (CFIndex)sizeof(str_q)) {
str = CFAllocatorAllocate(NULL, len, 0);
}
CFRelease(pattern);
}
if (ok) {
+ regex_t *preg;
int reError;
+ /* ALIGN: CF aligns to >8 byte boundries */
+ preg = (regex_t *)(void *)CFDataGetBytePtr(pRegex);
+
reError = regcomp(preg, str, REG_EXTENDED);
if (reError != 0) {
char reErrBuf[256];
(void)regerror(reError, preg, reErrBuf, sizeof(reErrBuf));
*error = CFStringCreateWithCString(NULL, reErrBuf, kCFStringEncodingASCII);
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regcomp(%s) failed: %s"), str, reErrBuf);
+#ifdef DEBUG
+ SC_log(LOG_DEBUG, "regcomp(%s) failed: %s", str, reErrBuf);
+#endif /* DEBUG */
ok = FALSE;
}
} else {
*error = CFRetain(CFSTR("could not convert pattern to regex string"));
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("%@"), *error);
+#ifdef DEBUG
+ SC_log(LOG_DEBUG, "%@", *error);
+#endif /* DEBUG */
}
if (str != str_q) CFAllocatorDeallocate(NULL, str);
}
-__private_extern__
-CFMutableArrayRef
+static void
+patternRelease(CFDataRef pRegex)
+{
+ regex_t *preg;
+
+ /* ALIGN: CF aligns to >8 byte boundries */
+ preg = (regex_t *)(void *)CFDataGetBytePtr(pRegex);
+ regfree(preg);
+
+ return;
+}
+
+
+static CF_RETURNS_RETAINED CFMutableArrayRef
patternCopy(CFStringRef pattern)
{
CFArrayRef pInfo;
pInfo = CFDictionaryGetValue(patternData, pattern);
- return pInfo ? CFArrayCreateMutableCopy(NULL, 0, pInfo) : NULL;
+ return (pInfo != NULL) ? CFArrayCreateMutableCopy(NULL, 0, pInfo) : NULL;
}
-__private_extern__
-CFMutableArrayRef
+static CF_RETURNS_RETAINED CFMutableArrayRef
patternNew(CFStringRef pattern)
{
addContext context;
- CFStringRef err;
+ CFStringRef err = NULL;
CFMutableArrayRef pInfo;
CFMutableDataRef pRegex;
CFArrayRef pSessions;
/* compile the regular expression from the pattern string. */
pRegex = CFDataCreateMutable(NULL, sizeof(regex_t));
CFDataSetLength(pRegex, sizeof(regex_t));
- if (!patternCompile(pattern, (regex_t *)CFDataGetBytePtr(pRegex), &err)) {
+ if (!patternCompile(pattern, pRegex, &err)) {
CFRelease(err);
CFRelease(pRegex);
CFRelease(pInfo);
CFRelease(pSessions);
/* identify/add all existing keys that match the specified pattern */
- context.pInfo = pInfo;
- context.preg = (regex_t *)CFDataGetBytePtr(pRegex);
+ context.pInfo = pInfo;
+ context.pRegex = pRegex;
my_CFDictionaryApplyFunction(storeData,
(CFDictionaryApplierFunction)identifyKeyForPattern,
&context);
}
+__private_extern__
+CFArrayRef
+patternCopyMatches(CFStringRef pattern)
+{
+ Boolean isNew = FALSE;
+ CFArrayRef keys;
+ CFMutableArrayRef pInfo;
+
+ /* find (or create new instance of) this pattern */
+ pInfo = patternCopy(pattern);
+ if (pInfo == NULL) {
+ /* if new pattern */
+ pInfo = patternNew(pattern);
+ if (pInfo == NULL) {
+ return NULL;
+ }
+
+ isNew = TRUE;
+ }
+
+ if (isNew) {
+ CFDataRef pRegex;
+
+ pRegex = CFArrayGetValueAtIndex(pInfo, 0);
+ patternRelease(pRegex);
+ }
+
+ CFArrayReplaceValues(pInfo, CFRangeMake(0, 2), NULL, 0);
+ keys = CFArrayCreateCopy(NULL, pInfo);
+ CFRelease(pInfo);
+
+ return keys;
+}
+
+
+__private_extern__
+Boolean
+patternKeyMatches(CFStringRef pattern, CFStringRef key)
+{
+ Boolean isNew = FALSE;
+ Boolean match = FALSE;
+ CFMutableArrayRef pInfo;
+ CFDataRef pRegex;
+
+ /* find (or create new instance of) this pattern */
+ pInfo = patternCopy(pattern);
+ if (pInfo != NULL) {
+ CFIndex n;
+
+ /* if existing pattern, check if known key */
+ n = CFArrayGetCount(pInfo);
+ match = (n > 2) &&
+ CFArrayContainsValue(pInfo, CFRangeMake(2, n - 2), key);
+ if (match) {
+ goto done;
+ }
+ } else {
+ /* if new pattern */
+ pInfo = patternNew(pattern);
+ if (pInfo == NULL) {
+ return FALSE;
+ }
+
+ isNew = TRUE;
+ }
+
+ pRegex = CFArrayGetValueAtIndex(pInfo, 0);
+ match = keyMatchesPattern(key, pRegex);
+
+ if (isNew) {
+ patternRelease(pRegex);
+ }
+
+ done :
+
+ CFRelease(pInfo);
+
+ return match;
+}
+
+
__private_extern__
Boolean
patternAddSession(CFStringRef pattern, CFNumberRef sessionNum)
/* find (or create new instance of) this pattern */
pInfo = patternCopy(pattern);
- if (!pInfo) {
+ if (pInfo == NULL) {
/* if new pattern */
pInfo = patternNew(pattern);
- if (!pInfo) {
+ if (pInfo == NULL) {
return FALSE;
}
}
/* find instance of this pattern */
pInfo = patternCopy(pattern);
+ assert(pInfo != NULL);
/* remove this session as a watcher from all matching keys */
n = CFArrayGetCount(pInfo);
/* if no other sessions are watching this pattern */
pRegex = CFArrayGetValueAtIndex(pInfo, 0);
- regfree((regex_t *)CFDataGetBytePtr(pRegex));
+ patternRelease(pRegex);
CFDictionaryRemoveValue(patternData, pattern);
}
char * str = str_q;
/* convert store key to C string */
- len = CFStringGetLength(storeKey) + 1;
+ len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(storeKey), kCFStringEncodingASCII) + 1;
if (len > (CFIndex)sizeof(str_q))
str = CFAllocatorAllocate(NULL, len, 0);
if (_SC_cfstring_to_cstring(storeKey, str, len, kCFStringEncodingASCII) == NULL) {
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not convert store key to C string"));
+ SC_log(LOG_INFO, "could not convert store key to C string");
goto done;
}
/* compare new store key to regular expression pattern */
- preg = (regex_t *)CFDataGetBytePtr(CFArrayGetValueAtIndex(pInfo, 0));
+ /* ALIGN: CF aligns to >8 byte boundries */
+ preg = (regex_t *)(void *)CFDataGetBytePtr(CFArrayGetValueAtIndex(pInfo, 0));
reError = regexec(preg, str, 0, NULL, 0);
switch (reError) {
case 0 : {
char reErrBuf[256];
(void)regerror(reError, preg, reErrBuf, sizeof(reErrBuf));
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf);
+ SC_log(LOG_INFO, "%s", reErrBuf);
break;
}
}
void
patternAddKey(CFStringRef key)
{
+ void *context = (void *)key;
+
my_CFDictionaryApplyFunction(patternData,
(CFDictionaryApplierFunction)addKeyForPattern,
- (void *)key);
+ context);
return;
}
}
i = CFArrayGetFirstIndexOfValue(pInfo, CFRangeMake(2, n-2), storeKey);
- if (i == -1) {
+ if (i == kCFNotFound) {
/* if this key wasn't matched by this pattern */
return;
}
void
patternRemoveKey(CFStringRef key)
{
+ void *context = (void *)key;
+
my_CFDictionaryApplyFunction(patternData,
(CFDictionaryApplierFunction)removeKeyFromPattern,
- (void *)key);
+ context);
return;
}