2  * Copyright (c) 2000-2004,2006,2011-2012,2014 Apple Inc. All Rights Reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. Please obtain a copy of the License at 
  10  * http://www.opensource.apple.com/apsl/ and read it before using this 
  13  * The Original Code and all software distributed under the License are 
  14  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  15  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  16  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  17  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  18  * Please see the License for the specific language governing rights and 
  19  * limitations under the License. 
  21  * @APPLE_LICENSE_HEADER_END@ 
  26 // Manage the Tower of Babel of CSSM dates and times 
  28 #include <security_cdsa_utilities/cssmdates.h> 
  29 #include <security_cdsa_utilities/cssmerrors.h> 
  30 #include <Security/cssm.h> 
  35 // A (private) PODwrapper for CFGregorianDate 
  37 struct Gregorian 
: public PodWrapper
<Gregorian
, CFGregorianDate
> { 
  40     Gregorian(int y
, int m
, int d
, int h 
= 0, int min 
= 0, double sec 
= 0) 
  42         year 
= y
; month 
= m
; day 
= d
; 
  43         hour 
= h
; minute 
= min
; second 
= sec
; 
  46     Gregorian(CFAbsoluteTime ref
) 
  47     { static_cast<CFGregorianDate 
&>(*this) = CFAbsoluteTimeGetGregorianDate(ref
, NULL
); } 
  49     operator CFAbsoluteTime () const 
  50     { return CFGregorianDateGetAbsoluteTime(*this, NULL
); } 
  55 // The CssmDate PODwrapper 
  57 CssmDate::CssmDate(const char *y
, const char *m
, const char *d
) 
  59     assign(years(), 4, y
); 
  60     assign(months(), 2, m
); 
  64 CssmDate::CssmDate(int y
, int m
, int d
) 
  66     // internal format is "yyyymmdd" (no null termination) 
  68     if (8 != snprintf(str
, 9, "%4.4d%2.2d%2.2d", y
, m
, d
)) 
  69         CssmError::throwMe(CSSM_ERRCODE_UNKNOWN_FORMAT
); 
  73 int CssmDate::year() const 
  74 { return atoi(string(years(), 4).c_str()); } 
  76 int CssmDate::month() const 
  77 { return atoi(string(months(), 2).c_str()); } 
  79 int CssmDate::day() const 
  80 { return atoi(string(days(), 2).c_str()); } 
  83 void CssmDate::assign(char *dest
, int width
, const char *src
) 
  85     // pick last width characters of src at most 
  86     size_t len 
= strlen(src
); 
  88         CssmError::throwMe(CSSM_ERRCODE_UNKNOWN_FORMAT
); 
  89     memset(dest
, '0', width 
- len
); 
  90     memcpy(dest 
+ width 
- len
, src
, len
); 
  95 // CssmUniformDate core functions 
 100 // Uniform conversions with CFDateRef 
 102 CssmUniformDate::CssmUniformDate(CFDateRef ref
) 
 104     mTime 
= CFDateGetAbsoluteTime(ref
); 
 107 CssmUniformDate::operator CFDateRef() const 
 109     return CFDateCreate(NULL
, mTime
); 
 114 // Uniform conversions with CssmDates 
 116 CssmUniformDate::CssmUniformDate(const CssmDate 
&date
) 
 118     mTime 
= CFGregorianDateGetAbsoluteTime(Gregorian(date
.year(), date
.month(), date
.day()), 
 122 CssmUniformDate::operator CssmDate () const 
 124     Gregorian 
greg(mTime
); 
 125     return CssmDate(greg
.year
, greg
.month
, greg
.day
); 
 130 // Uniform conversions with CssmData (1999-06-30_15:05:39 form) 
 132 CssmUniformDate::CssmUniformDate(const CSSM_DATA 
&inData
) 
 134     const CssmData 
&data 
= CssmData::overlay(inData
); 
 135     if (data
.length() != 19) 
 136         CssmError::throwMe(CSSM_ERRCODE_UNKNOWN_FORMAT
); 
 137     setFromString(reinterpret_cast<const char *>(inData
.Data
), "%ld-%d-%d_%d:%d:%lf", 19); 
 140 void CssmUniformDate::convertTo(CssmOwnedData 
&data
) const 
 142     Gregorian 
greg(mTime
); 
 144     if (19 != snprintf(str
, 20, "%4.4d-%2.2d-%2.2d_%2.2d:%2.2d:%2.2d", 
 145         int(greg
.year
), greg
.month
, greg
.day
, greg
.hour
, greg
.minute
, int(greg
.second
))) 
 146         CssmError::throwMe(CSSM_ERRCODE_UNKNOWN_FORMAT
); 
 147     data 
= CssmData(str
, 19); 
 152 // Uniform conversions with CSSM_TIMESTRING (19990630150539 form) 
 154 CssmUniformDate::CssmUniformDate(const char *src
) 
 156     setFromString(src
, "%4ld%2d%2d%2d%2d%2lf", 14); 
 159 void CssmUniformDate::convertTo(char *dst
, size_t length
) const 
 162         CssmError::throwMe(CSSMERR_CSSM_BUFFER_TOO_SMALL
); 
 163     Gregorian 
greg(mTime
); 
 165     if (14 != snprintf(str
, 15, "%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d", 
 166         int(greg
.year
), greg
.month
, greg
.day
, greg
.hour
, greg
.minute
, int(greg
.second
))) 
 167         CssmError::throwMe(CSSM_ERRCODE_UNKNOWN_FORMAT
); 
 168     memcpy(dst
, str
, length 
== 14 ? 14 : 15);   // null terminate if there's room 
 173 // Generalized parse-from-string setup 
 175 void CssmUniformDate::setFromString(const char *src
, const char *format
, size_t fieldWidth
) 
 177     // use a stack buffer 
 179     assert(fieldWidth 
< sizeof(str
)); 
 181     // make a copy with proper null terminator 
 182     memcpy(str
, src
, fieldWidth
); 
 183     str
[fieldWidth
] = '\0'; 
 185     // parse (with limited checks for bad field formats) 
 187     int month
, day
, hour
, minute
; 
 189     if (6 != sscanf(str
, format
, 
 190         &year
, &month
, &day
, &hour
, &minute
, &second
)) 
 191         CssmError::throwMe(CSSM_ERRCODE_UNKNOWN_FORMAT
); 
 194     mTime 
= Gregorian((int)year
, month
, day
, hour
, minute
, second
);