#ifdef __MWERKS__
#define _CPP_CSSM_DATE_TIME_UTILS
#endif
#include "cssmdatetime.h"
#include <string.h>
#include <stdio.h>
#include <security_utilities/errors.h>
#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
#include <CoreFoundation/CFDate.h>
#include <CoreFoundation/CFTimeZone.h>
#include <ctype.h>
#include <stdlib.h>
namespace Security
{
namespace CSSMDateTimeUtils
{
#define UTC_TIME_NOSEC_LEN 11
#define UTC_TIME_STRLEN 13
#define GENERALIZED_TIME_STRLEN 15
#define LOCALIZED_UTC_TIME_STRLEN 17
#define LOCALIZED_TIME_STRLEN 19
#define MAX_TIME_STR_LEN 30
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);
}
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);
}
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);
}
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;
if(cssmDate[len - 1] == '\0')
len--;
switch(len) {
case UTC_TIME_NOSEC_LEN: isUtc = 1;
noSeconds = 1;
break;
case UTC_TIME_STRLEN: isUtc = 1;
break;
case GENERALIZED_TIME_STRLEN: break;
case LOCALIZED_UTC_TIME_STRLEN: isUtc = 1;
case LOCALIZED_TIME_STRLEN: isLocal = 1;
break;
default: return 1;
}
cp = (char *)cssmDate;
for(i=0; i<(len - 1); i++) {
if ( !(isdigit(cp[i])) )
if ( !isLocal || !(cp[i]=='+' || cp[i]=='-') )
return 1;
}
if(!isLocal && cp[len - 1] != 'Z' ) {
return 1;
}
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 += 2000;
}
else if(x < 70) {
return 1;
}
else {
x += 1900;
}
}
gd.year = x;
szTemp[0] = *cp++;
szTemp[1] = *cp++;
szTemp[2] = '\0';
x = atoi( szTemp );
if((x > 12) || (x <= 0)) {
return 1;
}
gd.month = x;
szTemp[0] = *cp++;
szTemp[1] = *cp++;
szTemp[2] = '\0';
x = atoi( szTemp );
if((x > 31) || (x <= 0)) {
return 1;
}
gd.day = x;
szTemp[0] = *cp++;
szTemp[1] = *cp++;
szTemp[2] = '\0';
x = atoi( szTemp );
if((x > 23) || (x < 0)) {
return 1;
}
gd.hour = x;
szTemp[0] = *cp++;
szTemp[1] = *cp++;
szTemp[2] = '\0';
x = atoi( szTemp );
if((x > 59) || (x < 0)) {
return 1;
}
gd.minute = x;
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) {
ti = (*cp++ == '+') ? 1 : -1;
szTemp[0] = *cp++;
szTemp[1] = *cp++;
szTemp[2] = '\0';
x = atoi( szTemp ) * 60 * 60;
ti *= x;
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;
}
};
}