]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 | 1 | /* |
d8f41ccd | 2 | * Copyright (c) 2000-2004,2006,2011-2012,2014 Apple Inc. All Rights Reserved. |
b1ab9ed8 A |
3 | * |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
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 | |
11 | * file. | |
12 | * | |
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. | |
20 | * | |
21 | * @APPLE_LICENSE_HEADER_END@ | |
22 | */ | |
23 | ||
24 | ||
25 | // | |
26 | // Manage the Tower of Babel of CSSM dates and times | |
27 | // | |
28 | #include <security_cdsa_utilities/cssmdates.h> | |
29 | #include <security_cdsa_utilities/cssmerrors.h> | |
30 | #include <Security/cssm.h> | |
31 | #include <string> | |
32 | ||
33 | ||
34 | // | |
35 | // A (private) PODwrapper for CFGregorianDate | |
36 | // | |
37 | struct Gregorian : public PodWrapper<Gregorian, CFGregorianDate> { | |
38 | Gregorian() { } | |
39 | ||
40 | Gregorian(int y, int m, int d, int h = 0, int min = 0, double sec = 0) | |
41 | { | |
42 | year = y; month = m; day = d; | |
43 | hour = h; minute = min; second = sec; | |
44 | } | |
45 | ||
46 | Gregorian(CFAbsoluteTime ref) | |
47 | { static_cast<CFGregorianDate &>(*this) = CFAbsoluteTimeGetGregorianDate(ref, NULL); } | |
48 | ||
49 | operator CFAbsoluteTime () const | |
50 | { return CFGregorianDateGetAbsoluteTime(*this, NULL); } | |
51 | }; | |
52 | ||
53 | ||
54 | // | |
55 | // The CssmDate PODwrapper | |
56 | // | |
57 | CssmDate::CssmDate(const char *y, const char *m, const char *d) | |
58 | { | |
59 | assign(years(), 4, y); | |
60 | assign(months(), 2, m); | |
61 | assign(days(), 2, d); | |
62 | } | |
63 | ||
64 | CssmDate::CssmDate(int y, int m, int d) | |
65 | { | |
66 | // internal format is "yyyymmdd" (no null termination) | |
67 | char str[9]; | |
68 | if (8 != snprintf(str, 9, "%4.4d%2.2d%2.2d", y, m, d)) | |
69 | CssmError::throwMe(CSSM_ERRCODE_UNKNOWN_FORMAT); | |
70 | memcpy(this, str, 8); | |
71 | } | |
72 | ||
73 | int CssmDate::year() const | |
74 | { return atoi(string(years(), 4).c_str()); } | |
75 | ||
76 | int CssmDate::month() const | |
77 | { return atoi(string(months(), 2).c_str()); } | |
78 | ||
79 | int CssmDate::day() const | |
80 | { return atoi(string(days(), 2).c_str()); } | |
81 | ||
82 | // right-adjust fill | |
83 | void CssmDate::assign(char *dest, int width, const char *src) | |
84 | { | |
85 | // pick last width characters of src at most | |
427c49bc | 86 | size_t len = strlen(src); |
b1ab9ed8 A |
87 | if (len > width) |
88 | CssmError::throwMe(CSSM_ERRCODE_UNKNOWN_FORMAT); | |
89 | memset(dest, '0', width - len); | |
90 | memcpy(dest + width - len, src, len); | |
91 | } | |
92 | ||
93 | ||
94 | // | |
95 | // CssmUniformDate core functions | |
96 | // | |
97 | ||
98 | ||
99 | // | |
100 | // Uniform conversions with CFDateRef | |
101 | // | |
102 | CssmUniformDate::CssmUniformDate(CFDateRef ref) | |
103 | { | |
104 | mTime = CFDateGetAbsoluteTime(ref); | |
105 | } | |
106 | ||
107 | CssmUniformDate::operator CFDateRef() const | |
108 | { | |
109 | return CFDateCreate(NULL, mTime); | |
110 | } | |
111 | ||
112 | ||
113 | // | |
114 | // Uniform conversions with CssmDates | |
115 | // | |
116 | CssmUniformDate::CssmUniformDate(const CssmDate &date) | |
117 | { | |
118 | mTime = CFGregorianDateGetAbsoluteTime(Gregorian(date.year(), date.month(), date.day()), | |
119 | NULL); | |
120 | } | |
121 | ||
122 | CssmUniformDate::operator CssmDate () const | |
123 | { | |
124 | Gregorian greg(mTime); | |
125 | return CssmDate(greg.year, greg.month, greg.day); | |
126 | } | |
127 | ||
128 | ||
129 | // | |
130 | // Uniform conversions with CssmData (1999-06-30_15:05:39 form) | |
131 | // | |
132 | CssmUniformDate::CssmUniformDate(const CSSM_DATA &inData) | |
133 | { | |
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); | |
138 | } | |
139 | ||
140 | void CssmUniformDate::convertTo(CssmOwnedData &data) const | |
141 | { | |
142 | Gregorian greg(mTime); | |
143 | char str[20]; | |
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); | |
148 | } | |
149 | ||
150 | ||
151 | // | |
152 | // Uniform conversions with CSSM_TIMESTRING (19990630150539 form) | |
153 | // | |
154 | CssmUniformDate::CssmUniformDate(const char *src) | |
155 | { | |
156 | setFromString(src, "%4ld%2d%2d%2d%2d%2lf", 14); | |
157 | } | |
158 | ||
159 | void CssmUniformDate::convertTo(char *dst, size_t length) const | |
160 | { | |
161 | if (length < 14) | |
162 | CssmError::throwMe(CSSMERR_CSSM_BUFFER_TOO_SMALL); | |
163 | Gregorian greg(mTime); | |
164 | char str[15]; | |
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 | |
169 | } | |
170 | ||
171 | ||
172 | // | |
173 | // Generalized parse-from-string setup | |
174 | // | |
175 | void CssmUniformDate::setFromString(const char *src, const char *format, size_t fieldWidth) | |
176 | { | |
177 | // use a stack buffer | |
178 | char str[20]; | |
179 | assert(fieldWidth < sizeof(str)); | |
180 | ||
181 | // make a copy with proper null terminator | |
182 | memcpy(str, src, fieldWidth); | |
183 | str[fieldWidth] = '\0'; | |
184 | ||
185 | // parse (with limited checks for bad field formats) | |
186 | long year; | |
187 | int month, day, hour, minute; | |
188 | double second; | |
189 | if (6 != sscanf(str, format, | |
190 | &year, &month, &day, &hour, &minute, &second)) | |
191 | CssmError::throwMe(CSSM_ERRCODE_UNKNOWN_FORMAT); | |
192 | ||
193 | // success | |
427c49bc | 194 | mTime = Gregorian((int)year, month, day, hour, minute, second); |
b1ab9ed8 | 195 | } |