#include "tpTime.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
#include <security_utilities/simulatecrash_assert.h>
int timeStringToCfDate(
const char *str,
unsigned len,
CFDateRef *cfDate)
{
char szTemp[5];
bool isUtc = false; bool isLocal = false; bool isCssmTime = false; bool noSeconds = false;
int x;
unsigned i;
char *cp;
CFGregorianDate gd;
CFTimeZoneRef timeZone;
CFTimeInterval gmtOff = 0;
if((str == NULL) || (len == 0) || (cfDate == NULL)) {
return 1;
}
if(str[len - 1] == '\0') {
len--;
}
switch(len) {
case UTC_TIME_NOSEC_LEN: isUtc = true;
noSeconds = true;
break;
case UTC_TIME_STRLEN: isUtc = true;
break;
case CSSM_TIME_STRLEN:
isCssmTime = true;
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 *)str;
for(i=0; i<(len - 1); i++) {
if ( !(isdigit(cp[i])) )
if ( !isLocal || !(cp[i]=='+' || cp[i]=='-') )
return 1;
}
if(isCssmTime || isLocal) {
if(!isdigit(cp[len - 1])) {
return 1;
}
}
else {
if(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 {
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) {
switch(*cp++) {
case '+':
gmtOff = 1;
break;
case '-':
gmtOff = -1;
break;
default:
return 1;
}
szTemp[0] = *cp++;
szTemp[1] = *cp++;
szTemp[2] = '\0';
x = atoi( szTemp ) * 60 * 60;
gmtOff *= x;
szTemp[0] = *cp++;
szTemp[1] = *cp++;
szTemp[2] = '\0';
x = atoi( szTemp ) * 60;
if(gmtOff < 0) {
gmtOff -= x;
}
else {
gmtOff += x;
}
}
timeZone = CFTimeZoneCreateWithTimeIntervalFromGMT(NULL, gmtOff);
if (!timeZone) {
return 1;
}
*cfDate = CFDateCreate(NULL, CFGregorianDateGetAbsoluteTime(gd, timeZone));
CFRelease(timeZone);
return 0;
}
int compareTimes(
CFDateRef t1,
CFDateRef t2)
{
switch(CFDateCompare(t1, t2, NULL)) {
case kCFCompareLessThan:
return -1;
case kCFCompareEqualTo:
return 0;
case kCFCompareGreaterThan:
return 1;
}
assert(0);
return 0;
}
void timeAtNowPlus(unsigned secFromNow,
TpTimeSpec timeSpec,
char *outStr)
{
struct tm utc;
time_t baseTime;
baseTime = time(NULL);
baseTime += (time_t)secFromNow;
utc = *gmtime(&baseTime);
switch(timeSpec) {
case TP_TIME_UTC:
if(utc.tm_year >= 100) {
utc.tm_year -= 100;
}
sprintf(outStr, "%02d%02d%02d%02d%02d%02dZ",
utc.tm_year , utc.tm_mon + 1,
utc.tm_mday, utc.tm_hour, utc.tm_min, utc.tm_sec);
break;
case TP_TIME_GEN:
sprintf(outStr, "%04d%02d%02d%02d%02d%02dZ",
utc.tm_year + 1900, utc.tm_mon + 1,
utc.tm_mday, utc.tm_hour, utc.tm_min, utc.tm_sec);
break;
case TP_TIME_CSSM:
sprintf(outStr, "%04d%02d%02d%02d%02d%02d",
utc.tm_year + 1900, utc.tm_mon + 1,
utc.tm_mday, utc.tm_hour, utc.tm_min, utc.tm_sec);
break;
}
}
int tpTimeToCssmTimestring(
const char *inStr, unsigned inStrLen, char *outTime)
{
if((inStrLen == 0) || (inStr == NULL)) {
return 1;
}
outTime[0] = '\0';
switch(inStrLen) {
case UTC_TIME_STRLEN:
{
char tmp[3];
int year;
tmp[0] = inStr[0];
tmp[1] = inStr[1];
tmp[2] = '\0';
year = atoi(tmp);
if(year < 50) {
strcpy(outTime, "20");
}
else if(year < 70) {
return 1;
}
else {
strcpy(outTime, "19");
}
memmove(outTime + 2, inStr, inStrLen - 1); break;
}
case CSSM_TIME_STRLEN:
memmove(outTime, inStr, inStrLen); break;
case GENERALIZED_TIME_STRLEN:
memmove(outTime, inStr, inStrLen - 1); break;
default:
return 1;
}
outTime[CSSM_TIME_STRLEN] = '\0';
return 0;
}