void MacLongDateTimeToTimeString(const sint64 &inMacDate, uint32 inLength, void *outData) { // @@@ this code is close, but on the fringe case of a daylight savings time it will be off for a little while CFAbsoluteTime absTime = inMacDate - kCFAbsoluteTimeIntervalSince1904; // Remove local timezone component from absTime CFTimeZoneRef timeZone = CFTimeZoneCopyDefault(); absTime -= CFTimeZoneGetSecondsFromGMT(timeZone, absTime); CFRelease(timeZone); timeZone = CFTimeZoneCreateWithTimeIntervalFromGMT(NULL, 0); CFGregorianDate date = CFAbsoluteTimeGetGregorianDate(absTime, timeZone); CFRelease(timeZone); if (inLength == 16) { sprintf((char *)(outData), "%04d%02d%02d%02d%02d%02dZ", int(date.year % 10000), date.month, date.day, date.hour, date.minute, int(date.second)); } else if (inLength == 14) { /* UTC - 2 year digits - code which parses this assumes that * (2-digit) years between 0 and 49 are in century 21 */ sprintf((char *)(outData), "%02d%02d%02d%02d%02d%02dZ", int(date.year % 100), date.month, date.day, date.hour, date.minute, int(date.second)); } else MacOSError::throwMe(paramErr); }
static OSStatus DER_UTCTimeToCFDate(const SecAsn1Item * utcTime, CFAbsoluteTime *date) { char *string = (char *)utcTime->Data; int year, month, mday, hour, minute, second, hourOff, minOff; /* Verify time is formatted properly and capture information */ second = 0; hourOff = 0; minOff = 0; CAPTURE(year,string+0,loser); if (year < 50) { /* ASSUME that year # is in the 2000's, not the 1900's */ year += 2000; } else { year += 1900; } CAPTURE(month,string+2,loser); if ((month == 0) || (month > 12)) goto loser; CAPTURE(mday,string+4,loser); if ((mday == 0) || (mday > 31)) goto loser; CAPTURE(hour,string+6,loser); if (hour > 23) goto loser; CAPTURE(minute,string+8,loser); if (minute > 59) goto loser; if (ISDIGIT(string[10])) { CAPTURE(second,string+10,loser); if (second > 59) goto loser; string += 2; } if (string[10] == '+') { CAPTURE(hourOff,string+11,loser); if (hourOff > 23) goto loser; CAPTURE(minOff,string+13,loser); if (minOff > 59) goto loser; } else if (string[10] == '-') { CAPTURE(hourOff,string+11,loser); if (hourOff > 23) goto loser; hourOff = -hourOff; CAPTURE(minOff,string+13,loser); if (minOff > 59) goto loser; minOff = -minOff; } else if (string[10] != 'Z') { goto loser; } if (hourOff == 0 && minOff == 0) { *date = CFAbsoluteTimeForGregorianZuluMoment(year, month, mday, hour, minute, second); } else { CFTimeZoneRef tz = CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorDefault, (hourOff * 60 + minOff) * 60); *date = CFAbsoluteTimeForGregorianMoment(tz, year, month, mday, hour, minute, second); CFReleaseSafe(tz); } return SECSuccess; loser: return SECFailure; }
void CFDateToCssmDate(CFDateRef date, char *outCssmDate) { CFTimeZoneRef timeZone = CFTimeZoneCreateWithTimeIntervalFromGMT(NULL, 0); CFGregorianDate gd = CFAbsoluteTimeGetGregorianDate(CFDateGetAbsoluteTime(date), timeZone); sprintf(outCssmDate, "%04d%02d%02d%02d%02d%02dZ", (int)gd.year, gd.month, gd.day, gd.hour, gd.minute, (unsigned int)gd.second); CFRelease(timeZone); }
CFGregorianDate SecCFAbsoluteTimeGetGregorianDate(CFAbsoluteTime at, CFTimeInterval timeZoneOffset, CFErrorRef *error) { CFTimeZoneRef tz = CFTimeZoneCreateWithTimeIntervalFromGMT(0, timeZoneOffset); if (!tz) { SecCFDERCreateError(-1000, CFSTR("timezone creation failed."), 0, error); CFGregorianDate g = {}; return g; } else { CFGregorianDate g = CFAbsoluteTimeGetGregorianDate(at, tz); CFRelease(tz); return g; } }
/* * Convert CFAbsoluteTime to generalized time string, GMT format (4 digit year, * trailing 'Z'). Caller allocated the output which is GENERAL_TIME_STRLEN+1 bytes. */ void cfAbsTimeToGgenTime( CFAbsoluteTime absTime, char *genTime) { /* time zone = GMT */ CFTimeZoneRef tz = CFTimeZoneCreateWithTimeIntervalFromGMT(NULL, 0.0); CFGregorianDate greg = CFAbsoluteTimeGetGregorianDate(absTime, tz); int seconds = (int)greg.second; sprintf(genTime, "%04d%02d%02d%02d%02d%02dZ", (int)greg.year, greg.month, greg.day, greg.hour, greg.minute, seconds); }
void CssmDateToCFDate(const char *cssmDate, CFDateRef *outCFDate) { CFTimeZoneRef timeZone = CFTimeZoneCreateWithTimeIntervalFromGMT(NULL, 0); CFGregorianDate gd; unsigned int year, month, day, hour, minute, second; sscanf(cssmDate, "%4d%2d%2d%2d%2d%2d", &year, &month, &day, &hour, &minute, &second); gd.year = year; gd.month = month; gd.day = day; gd.hour = hour; gd.minute = minute; gd.second = second; *outCFDate = CFDateCreate(NULL, CFGregorianDateGetAbsoluteTime(gd, timeZone)); CFRelease(timeZone); }
static void printPlist(CFArrayRef plist, CFIndex indent, CFIndex maxWidth) { CFIndex count = CFArrayGetCount(plist); CFIndex ix; for (ix = 0; ix < count ; ++ix) { CFDictionaryRef prop = (CFDictionaryRef)CFArrayGetValueAtIndex(plist, ix); CFStringRef pType = (CFStringRef)CFDictionaryGetValue(prop, kSecPropertyKeyType); CFStringRef label = (CFStringRef)CFDictionaryGetValue(prop, kSecPropertyKeyLabel); CFStringRef llabel = (CFStringRef)CFDictionaryGetValue(prop, kSecPropertyKeyLocalizedLabel); CFTypeRef value = (CFTypeRef)CFDictionaryGetValue(prop, kSecPropertyKeyValue); bool isSection = CFEqual(pType, kSecPropertyTypeSection); CFMutableStringRef line = CFStringCreateMutable(NULL, 0); CFIndex jx = 0; for (jx = 0; jx < indent; ++jx) { CFStringAppend(line, CFSTR(" ")); } if (llabel) { CFStringAppend(line, llabel); if (!isSection) { for (jx = CFStringGetLength(llabel) + indent * 4; jx < maxWidth; ++jx) { CFStringAppend(line, CFSTR(" ")); } CFStringAppend(line, CFSTR(" : ")); } } if (CFEqual(pType, kSecPropertyTypeWarning)) { CFStringAppend(line, CFSTR("*WARNING* ")); CFStringAppend(line, (CFStringRef)value); } else if (CFEqual(pType, kSecPropertyTypeError)) { CFStringAppend(line, CFSTR("*ERROR* ")); CFStringAppend(line, (CFStringRef)value); } else if (CFEqual(pType, kSecPropertyTypeSuccess)) { CFStringAppend(line, CFSTR("*OK* ")); CFStringAppend(line, (CFStringRef)value); } else if (CFEqual(pType, kSecPropertyTypeTitle)) { CFStringAppend(line, CFSTR("*")); CFStringAppend(line, (CFStringRef)value); CFStringAppend(line, CFSTR("*")); } else if (CFEqual(pType, kSecPropertyTypeSection)) { } else if (CFEqual(pType, kSecPropertyTypeData)) { CFDataRef data = (CFDataRef)value; CFIndex length = CFDataGetLength(data); if (length > 20) CFStringAppendFormat(line, NULL, CFSTR("[%d bytes] "), length); const UInt8 *bytes = CFDataGetBytePtr(data); for (jx = 0; jx < length; ++jx) { if (jx == 0) CFStringAppendFormat(line, NULL, CFSTR("%02X"), bytes[jx]); else if (jx < 15 || length <= 20) CFStringAppendFormat(line, NULL, CFSTR(" %02X"), bytes[jx]); else { CFStringAppend(line, CFSTR(" ...")); break; } } } else if (CFEqual(pType, kSecPropertyTypeString)) { CFStringAppend(line, (CFStringRef)value); } else if (CFEqual(pType, kSecPropertyTypeDate)) { CFDateRef date = (CFDateRef)value; CFLocaleRef lc = CFLocaleCopyCurrent(); CFDateFormatterRef df = CFDateFormatterCreate(NULL, lc, kCFDateFormatterMediumStyle, kCFDateFormatterLongStyle); CFStringRef ds; if (df) { CFTimeZoneRef tz = CFTimeZoneCreateWithTimeIntervalFromGMT(NULL, 0.0); CFDateFormatterSetProperty(df, kCFDateFormatterTimeZone, tz); CFRelease(tz); ds = CFDateFormatterCreateStringWithDate(NULL, df, date); CFRelease(df); } else { ds = CFStringCreateWithFormat(NULL, NULL, CFSTR("%g"), CFDateGetAbsoluteTime(date)); } CFStringAppend(line, ds); CFRelease(ds); CFRelease(lc); } else if (CFEqual(pType, kSecPropertyTypeURL)) { CFURLRef url = (CFURLRef)value; CFStringAppend(line, CFSTR("<")); CFStringAppend(line, CFURLGetString(url)); CFStringAppend(line, CFSTR(">")); } else { CFStringAppendFormat(line, NULL, CFSTR("*unknown type %@* = %@"), pType, value); } if (!isSection || label) print_line(line); CFRelease(line); if (isSection) { printPlist((CFArrayRef)value, indent + 1, maxWidth); } } }
static OSStatus DER_UTCTimeToCFDate(const CSSM_DATA_PTR utcTime, CFAbsoluteTime *date) { CFGregorianDate gdate; char *string = (char *)utcTime->Data; long year, month, mday, hour, minute, second, hourOff, minOff; CFTimeZoneRef timeZone; /* Verify time is formatted properly and capture information */ second = 0; hourOff = 0; minOff = 0; CAPTURE(year,string+0,loser); if (year < 50) { /* ASSUME that year # is in the 2000's, not the 1900's */ year += 100; } CAPTURE(month,string+2,loser); if ((month == 0) || (month > 12)) goto loser; CAPTURE(mday,string+4,loser); if ((mday == 0) || (mday > 31)) goto loser; CAPTURE(hour,string+6,loser); if (hour > 23) goto loser; CAPTURE(minute,string+8,loser); if (minute > 59) goto loser; if (ISDIGIT(string[10])) { CAPTURE(second,string+10,loser); if (second > 59) goto loser; string += 2; } if (string[10] == '+') { CAPTURE(hourOff,string+11,loser); if (hourOff > 23) goto loser; CAPTURE(minOff,string+13,loser); if (minOff > 59) goto loser; } else if (string[10] == '-') { CAPTURE(hourOff,string+11,loser); if (hourOff > 23) goto loser; hourOff = -hourOff; CAPTURE(minOff,string+13,loser); if (minOff > 59) goto loser; minOff = -minOff; } else if (string[10] != 'Z') { goto loser; } gdate.year = (SInt32)(year + 1900); gdate.month = month; gdate.day = mday; gdate.hour = hour; gdate.minute = minute; gdate.second = second; if (hourOff == 0 && minOff == 0) timeZone = NULL; /* GMT */ else { timeZone = CFTimeZoneCreateWithTimeIntervalFromGMT(NULL, (hourOff * 60 + minOff) * 60); } *date = CFGregorianDateGetAbsoluteTime(gdate, timeZone); if (timeZone) CFRelease(timeZone); return SECSuccess; loser: return SECFailure; }
/* * Given a CSSM_DATA containing either a UTC-style or "generalized time" * time string, convert to 32-bit Mac time in seconds. * Returns nonzero on error. */ void TimeStringToMacLongDateTime (const CSSM_DATA &inUTCTime, sint64 &outMacDate) { char szTemp[5]; unsigned len; int isUtc; sint32 x; sint32 i; char *cp; CFGregorianDate date; ::memset( &date, 0, sizeof(date) ); if ((inUTCTime.Data == NULL) || (inUTCTime.Length == 0)) { MacOSError::throwMe(paramErr); } /* tolerate NULL terminated or not */ len = inUTCTime.Length; if (inUTCTime.Data[len - 1] == '\0') len--; switch(len) { case UTC_TIME_STRLEN: // 2-digit year, not Y2K compliant isUtc = 1; break; case GENERALIZED_TIME_STRLEN: // 4-digit year isUtc = 0; break; default: // unknown format MacOSError::throwMe(paramErr); } cp = (char *)inUTCTime.Data; /* check that all characters except last are digits */ for(i=0; i<(sint32)(len - 1); i++) { if ( !(isdigit(cp[i])) ) { MacOSError::throwMe(paramErr); } } /* check last character is a 'Z' */ if(cp[len - 1] != 'Z' ) { MacOSError::throwMe(paramErr); } /* YEAR */ szTemp[0] = *cp++; szTemp[1] = *cp++; if(!isUtc) { /* two more digits */ szTemp[2] = *cp++; szTemp[3] = *cp++; szTemp[4] = '\0'; } else { szTemp[2] = '\0'; } x = atoi( szTemp ); if(isUtc) { /* * 2-digit year. * 0 <= year <= 50 : assume century 21 * 50 < year < 70 : illegal per PKIX * 70 < year <= 99 : assume century 20 */ if(x <= 50) { x += 100; } else if(x < 70) { MacOSError::throwMe(paramErr); } /* else century 20, OK */ /* bug fix... we need to end up with a 4-digit year! */ x += 1900; } /* by definition - tm_year is year - 1900 */ //tmp->tm_year = x - 1900; date.year = x; /* MONTH */ szTemp[0] = *cp++; szTemp[1] = *cp++; szTemp[2] = '\0'; x = atoi( szTemp ); /* in the string, months are from 1 to 12 */ if((x > 12) || (x <= 0)) { MacOSError::throwMe(paramErr); } /* in a tm, 0 to 11 */ //tmp->tm_mon = x - 1; date.month = x; /* DAY */ szTemp[0] = *cp++; szTemp[1] = *cp++; szTemp[2] = '\0'; x = atoi( szTemp ); /* 1..31 in both formats */ if((x > 31) || (x <= 0)) { MacOSError::throwMe(paramErr); } //tmp->tm_mday = x; date.day = x; /* HOUR */ szTemp[0] = *cp++; szTemp[1] = *cp++; szTemp[2] = '\0'; x = atoi( szTemp ); if((x > 23) || (x < 0)) { MacOSError::throwMe(paramErr); } //tmp->tm_hour = x; date.hour = x; /* MINUTE */ szTemp[0] = *cp++; szTemp[1] = *cp++; szTemp[2] = '\0'; x = atoi( szTemp ); if((x > 59) || (x < 0)) { MacOSError::throwMe(paramErr); } //tmp->tm_min = x; date.minute = x; /* SECOND */ szTemp[0] = *cp++; szTemp[1] = *cp++; szTemp[2] = '\0'; x = atoi( szTemp ); if((x > 59) || (x < 0)) { MacOSError::throwMe(paramErr); } //tmp->tm_sec = x; date.second = x; CFTimeZoneRef timeZone = CFTimeZoneCreateWithTimeIntervalFromGMT(NULL, 0); CFAbsoluteTime absTime = CFGregorianDateGetAbsoluteTime(date, timeZone); CFRelease(timeZone); // Adjust abstime to local timezone timeZone = CFTimeZoneCopyDefault(); absTime += CFTimeZoneGetSecondsFromGMT(timeZone, absTime); CFRelease(timeZone); outMacDate = sint64(double(absTime + kCFAbsoluteTimeIntervalSince1904)); }
int CssmDateStringToCFDate(const char *cssmDate, unsigned int len, CFDateRef *outCFDate) { CFTimeZoneRef timeZone; CFGregorianDate gd; CFTimeInterval ti=0; char szTemp[5]; unsigned isUtc=0, isLocal=0, x, i; unsigned noSeconds=0; char *cp; if((cssmDate == NULL) || (len == 0) || (outCFDate == NULL)) return 1; /* tolerate NULL terminated or not */ if(cssmDate[len - 1] == '\0') len--; switch(len) { case UTC_TIME_NOSEC_LEN: // 2-digit year, no seconds, not y2K compliant isUtc = 1; noSeconds = 1; break; case UTC_TIME_STRLEN: // 2-digit year, not Y2K compliant isUtc = 1; break; case GENERALIZED_TIME_STRLEN: // 4-digit year //isUtc = 0; break; case LOCALIZED_UTC_TIME_STRLEN: // "YYMMDDhhmmssThhmm" (where T=[+,-]) isUtc = 1; // deliberate fallthrough case LOCALIZED_TIME_STRLEN: // "YYYYMMDDhhmmssThhmm" (where T=[+,-]) isLocal = 1; break; default: // unknown format return 1; } cp = (char *)cssmDate; /* check that all characters except last (or timezone indicator, if localized) are digits */ for(i=0; i<(len - 1); i++) { if ( !(isdigit(cp[i])) ) if ( !isLocal || !(cp[i]=='+' || cp[i]=='-') ) return 1; } /* check last character is a 'Z', unless localized */ if(!isLocal && cp[len - 1] != 'Z' ) { return 1; } /* YEAR */ szTemp[0] = *cp++; szTemp[1] = *cp++; if(!isUtc) { /* two more digits */ szTemp[2] = *cp++; szTemp[3] = *cp++; szTemp[4] = '\0'; } else { szTemp[2] = '\0'; } x = atoi( szTemp ); if(isUtc) { /* * 2-digit year. * 0 <= year < 50 : assume century 21 * 50 <= year < 70 : illegal per PKIX * 70 < year <= 99 : assume century 20 */ if(x < 50) { x += 2000; } else if(x < 70) { return 1; } else { /* century 20 */ x += 1900; } } gd.year = x; /* MONTH */ szTemp[0] = *cp++; szTemp[1] = *cp++; szTemp[2] = '\0'; x = atoi( szTemp ); /* in the string, months are from 1 to 12 */ if((x > 12) || (x <= 0)) { return 1; } gd.month = x; /* DAY */ szTemp[0] = *cp++; szTemp[1] = *cp++; szTemp[2] = '\0'; x = atoi( szTemp ); /* 1..31 in both formats */ if((x > 31) || (x <= 0)) { return 1; } gd.day = x; /* HOUR */ szTemp[0] = *cp++; szTemp[1] = *cp++; szTemp[2] = '\0'; x = atoi( szTemp ); if((x > 23) || (x < 0)) { return 1; } gd.hour = x; /* MINUTE */ szTemp[0] = *cp++; szTemp[1] = *cp++; szTemp[2] = '\0'; x = atoi( szTemp ); if((x > 59) || (x < 0)) { return 1; } gd.minute = x; /* SECOND */ if(noSeconds) { gd.second = 0; } else { szTemp[0] = *cp++; szTemp[1] = *cp++; szTemp[2] = '\0'; x = atoi( szTemp ); if((x > 59) || (x < 0)) { return 1; } gd.second = x; } if (isLocal) { /* ZONE INDICATOR */ ti = (*cp++ == '+') ? 1 : -1; /* ZONE HH OFFSET */ szTemp[0] = *cp++; szTemp[1] = *cp++; szTemp[2] = '\0'; x = atoi( szTemp ) * 60 * 60; ti *= x; /* ZONE MM OFFSET */ szTemp[0] = *cp++; szTemp[1] = *cp++; szTemp[2] = '\0'; x = atoi( szTemp ) * 60; ti += ((ti < 0) ? (x*-1) : x); } timeZone = CFTimeZoneCreateWithTimeIntervalFromGMT(NULL, ti); if (!timeZone) return 1; *outCFDate = CFDateCreate(NULL, CFGregorianDateGetAbsoluteTime(gd, timeZone)); CFRelease(timeZone); return 0; }