#ifdef __MWERKS__
#define _CPP_CSSM_DATE_TIME_UTILS
#endif
#include "cssmdatetime.h"
#include <string.h>
#include <stdio.h>
#include <Security/utilities.h>
#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
#include <CoreFoundation/CFDate.h>
#include <CoreFoundation/CFTimeZone.h>
#include <ctype.h>
namespace Security
{
namespace CSSMDateTimeUtils
{
#define MAX_TIME_STR_LEN 30
#define UTC_TIME_STRLEN 13
#define GENERALIZED_TIME_STRLEN 15
void
GetCurrentMacLongDateTime(SInt64 &outMacDate)
{
CFTimeZoneRef timeZone = CFTimeZoneCopyDefault();
CFAbsoluteTime absTime = CFAbsoluteTimeGetCurrent();
absTime += CFTimeZoneGetSecondsFromGMT(timeZone, absTime);
CFRelease(timeZone);
outMacDate = SInt64(double(absTime + kCFAbsoluteTimeIntervalSince1904));
}
void
TimeStringToMacSeconds (const CSSM_DATA &inUTCTime, UInt32 &ioMacDate)
{
SInt64 ldt;
TimeStringToMacLongDateTime(inUTCTime, ldt);
ioMacDate = UInt32(ldt);
}
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);
}
len = inUTCTime.Length;
if (inUTCTime.Data[len - 1] == '\0')
len--;
switch(len)
{
case UTC_TIME_STRLEN: isUtc = 1;
break;
case GENERALIZED_TIME_STRLEN: isUtc = 0;
break;
default: MacOSError::throwMe(paramErr);
}
cp = (char *)inUTCTime.Data;
for(i=0; i<(sint32)(len - 1); i++) {
if ( !(isdigit(cp[i])) ) {
MacOSError::throwMe(paramErr);
}
}
if(cp[len - 1] != 'Z' ) {
MacOSError::throwMe(paramErr);
}
szTemp[0] = *cp++;
szTemp[1] = *cp++;
if(!isUtc) {
szTemp[2] = *cp++;
szTemp[3] = *cp++;
szTemp[4] = '\0';
}
else {
szTemp[2] = '\0';
}
x = atoi( szTemp );
if(isUtc) {
if(x <= 50) {
x += 100;
}
else if(x < 70) {
MacOSError::throwMe(paramErr);
}
x += 1900;
}
date.year = x;
szTemp[0] = *cp++;
szTemp[1] = *cp++;
szTemp[2] = '\0';
x = atoi( szTemp );
if((x > 12) || (x <= 0)) {
MacOSError::throwMe(paramErr);
}
date.month = x;
szTemp[0] = *cp++;
szTemp[1] = *cp++;
szTemp[2] = '\0';
x = atoi( szTemp );
if((x > 31) || (x <= 0)) {
MacOSError::throwMe(paramErr);
}
date.day = x;
szTemp[0] = *cp++;
szTemp[1] = *cp++;
szTemp[2] = '\0';
x = atoi( szTemp );
if((x > 23) || (x < 0)) {
MacOSError::throwMe(paramErr);
}
date.hour = x;
szTemp[0] = *cp++;
szTemp[1] = *cp++;
szTemp[2] = '\0';
x = atoi( szTemp );
if((x > 59) || (x < 0)) {
MacOSError::throwMe(paramErr);
}
date.minute = x;
szTemp[0] = *cp++;
szTemp[1] = *cp++;
szTemp[2] = '\0';
x = atoi( szTemp );
if((x > 59) || (x < 0)) {
MacOSError::throwMe(paramErr);
}
date.second = x;
CFTimeZoneRef timeZone = CFTimeZoneCreateWithTimeIntervalFromGMT(NULL, 0);
CFAbsoluteTime absTime = CFGregorianDateGetAbsoluteTime(date, timeZone);
CFRelease(timeZone);
timeZone = CFTimeZoneCopyDefault();
absTime += CFTimeZoneGetSecondsFromGMT(timeZone, absTime);
CFRelease(timeZone);
outMacDate = SInt64(double(absTime + kCFAbsoluteTimeIntervalSince1904));
}
void MacSecondsToTimeString(UInt32 inMacDate, UInt32 inLength, void *outData)
{
SInt64 ldt = SInt64(UInt64(inMacDate));
MacLongDateTimeToTimeString(ldt, inLength, outData);
}
void MacLongDateTimeToTimeString(const SInt64 &inMacDate,
UInt32 inLength, void *outData)
{
CFAbsoluteTime absTime = inMacDate - kCFAbsoluteTimeIntervalSince1904;
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)
{
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);
}
};
}