/** * Do the two texts share a Substring which is at least half the length of * the longer text? * This speedup can produce non-minimal diffs. * @param text1 First CFStringRef. * @param text2 Second CFStringRef. * @param diffTimeout Time limit for diff. * @return Five element String array, containing the prefix of text1, the * suffix of text1, the prefix of text2, the suffix of text2 and the * common middle. Or NULL if there was no match. */ CFArrayRef diff_halfMatchCreate(CFStringRef text1, CFStringRef text2, const float diffTimeout) { if (diffTimeout <= 0) { // Don't risk returning a non-optimal diff if we have unlimited time. return NULL; } CFStringRef longtext = CFStringGetLength(text1) > CFStringGetLength(text2) ? text1 : text2; CFStringRef shorttext = CFStringGetLength(text1) > CFStringGetLength(text2) ? text2 : text1; if (CFStringGetLength(longtext) < 4 || CFStringGetLength(shorttext) * 2 < CFStringGetLength(longtext)) { return NULL; // Pointless. } // First check if the second quarter is the seed for a half-match. CFArrayRef hm1 = diff_halfMatchICreate(longtext, shorttext, (CFStringGetLength(longtext) + 3) / 4); // Check again based on the third quarter. CFArrayRef hm2 = diff_halfMatchICreate(longtext, shorttext, (CFStringGetLength(longtext) + 1) / 2); CFArrayRef hm; if (hm1 == NULL && hm2 == NULL) { return NULL; } else if (hm2 == NULL) { hm = CFRetain(hm1); } else if (hm1 == NULL) { hm = CFRetain(hm2); } else { // Both matched. Select the longest. hm = CFStringGetLength(CFArrayGetValueAtIndex(hm1, 4)) > CFStringGetLength(CFArrayGetValueAtIndex(hm2, 4)) ? CFRetain(hm1) : CFRetain(hm2); } if (hm1 != NULL) { CFRelease(hm1); } if (hm2 != NULL) { CFRelease(hm2); } // A half-match was found, sort out the return data. if (CFStringGetLength(text1) > CFStringGetLength(text2)) { return hm; //return new CFStringRef[]{hm[0], hm[1], hm[2], hm[3], hm[4]}; } else { // { hm[0], hm[1], hm[2], hm[3], hm[4] } // => { hm[2], hm[3], hm[0], hm[1], hm[4] } CFMutableArrayRef hm_mutable = CFArrayCreateMutableCopy(kCFAllocatorDefault, CFArrayGetCount(hm), hm); CFRelease(hm); CFArrayExchangeValuesAtIndices(hm_mutable, 0, 2); CFArrayExchangeValuesAtIndices(hm_mutable, 1, 3); return hm_mutable; } }
/* * Obtain an array of the certificates in a timestamp response. Elements of the * returned array are SecCertificateRefs. The caller must CFRelease the returned * array. This timestamp is an authenticated timestamp provided by * a timestamping authority. * * Returns errSecParam if the CMS message was not signed or if signerIndex * is greater than the number of signers of the message minus one. It returns * errSecItemNotFound if no certificates were found. * * This cannot be called until after CMSDecoderFinalizeMessage() is called. */ OSStatus CMSDecoderCopySignerTimestampCertificates( CMSDecoderRef cmsDecoder, size_t signerIndex, /* usually 0 */ CFArrayRef *certificateRefs) /* RETURNED */ { OSStatus status = errSecParam; SecCmsMessageRef cmsg = NULL; SecCmsSignedDataRef signedData = NULL; int numContentInfos = 0; CFIndex tsn = 0; bool good = false; require(cmsDecoder && certificateRefs, xit); require_noerr(CMSDecoderGetCmsMessage(cmsDecoder, &cmsg), xit); numContentInfos = SecCmsMessageContentLevelCount(cmsg); for (int dex = 0; !signedData && dex < numContentInfos; dex++) { SecCmsContentInfoRef ci = SecCmsMessageContentLevel(cmsg, dex); SECOidTag tag = SecCmsContentInfoGetContentTypeTag(ci); if (tag == SEC_OID_PKCS7_SIGNED_DATA) if ((signedData = SecCmsSignedDataRef(SecCmsContentInfoGetContent(ci)))) if (SecCmsSignerInfoRef signerInfo = SecCmsSignedDataGetSignerInfo(signedData, (int)signerIndex)) { CFArrayRef certList = SecCmsSignerInfoGetTimestampCertList(signerInfo); require_action(certList, xit, status = errSecItemNotFound); CFMutableArrayRef certs = CFArrayCreateMutableCopy(kCFAllocatorDefault, CFArrayGetCount(certList), certList); if(certs){ //reorder certificates: tsn = CFArrayGetCount(certs); good = tsn > 0 && Security::CodeSigning::isAppleCA(SecCertificateRef(CFArrayGetValueAtIndex(certs, tsn-1))); if ( good == false ) { //change TS certificate ordering. for (CFIndex n = 0; n < tsn; n++) { if (SecCertificateRef tsRoot = SecCertificateRef(CFArrayGetValueAtIndex(certs, n))) if ((good = Security::CodeSigning::isAppleCA(tsRoot))) { CFArrayExchangeValuesAtIndices(certs, n, tsn-1); break; } } } *certificateRefs = CFArrayCreateCopy(kCFAllocatorDefault, certs); CFRelease(certs); status = errSecSuccess; } break; } } xit: return status; }
CF_INLINE void __CFZSort(CFMutableArrayRef array, CFRange range, CFComparatorFunction comparator, void *context) { CFIndex cnt = range.length; while (1 < cnt) { for (CFIndex idx = range.location; idx < range.location + cnt - 1; idx++) { const void *a = CFArrayGetValueAtIndex(array, idx); const void *b = CFArrayGetValueAtIndex(array, idx + 1); if ((CFComparisonResult)(INVOKE_CALLBACK3(comparator, b, a, context)) < 0) { CFArrayExchangeValuesAtIndices(array, idx, idx + 1); } } cnt--; } }