2 * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
3 * Redistribution and modifications are permitted subject to BSD license.
5 #include <asn_internal.h>
7 #include <GeneralizedTime.h>
11 #include "/usr/include/time.h"
14 #endif /* __CYGWIN__ */
16 #ifndef ASN___INTERNAL_TEST_MODE
19 * UTCTime basic type description.
21 static const ber_tlv_tag_t asn_DEF_UTCTime_tags[] = {
22 (ASN_TAG_CLASS_UNIVERSAL | (23 << 2)), /* [UNIVERSAL 23] IMPLICIT ...*/
23 (ASN_TAG_CLASS_UNIVERSAL | (26 << 2)), /* [UNIVERSAL 26] IMPLICIT ...*/
24 (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
26 static asn_per_constraints_t asn_DEF_UTCTime_constraints = {
27 { APC_CONSTRAINED, 7, 7, 0x20, 0x7e }, /* Value */
28 { APC_SEMI_CONSTRAINED, -1, -1, 0, 0 }, /* Size */
31 asn_TYPE_operation_t asn_OP_UTCTime = {
35 OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */
36 OCTET_STRING_encode_der, /* Implemented in terms of OCTET STRING */
37 OCTET_STRING_decode_xer_utf8,
39 #ifdef ASN_DISABLE_OER_SUPPORT
43 OCTET_STRING_decode_oer,
44 OCTET_STRING_encode_oer,
45 #endif /* ASN_DISABLE_OER_SUPPORT */
46 #ifdef ASN_DISABLE_PER_SUPPORT
52 OCTET_STRING_decode_uper,
53 OCTET_STRING_encode_uper,
54 OCTET_STRING_decode_aper,
55 OCTET_STRING_encode_aper,
56 #endif /* ASN_DISABLE_PER_SUPPORT */
58 0 /* Use generic outmost tag fetcher */
60 asn_TYPE_descriptor_t asn_DEF_UTCTime = {
65 sizeof(asn_DEF_UTCTime_tags)
66 / sizeof(asn_DEF_UTCTime_tags[0]) - 2,
68 sizeof(asn_DEF_UTCTime_tags)
69 / sizeof(asn_DEF_UTCTime_tags[0]),
70 { 0, &asn_DEF_UTCTime_constraints, UTCTime_constraint },
71 0, 0, /* No members */
75 #endif /* ASN___INTERNAL_TEST_MODE */
78 * Check that the time looks like the time.
81 UTCTime_constraint(const asn_TYPE_descriptor_t *td, const void *sptr,
82 asn_app_constraint_failed_f *ctfailcb, void *app_key) {
83 const UTCTime_t *st = (const UTCTime_t *)sptr;
86 errno = EPERM; /* Just an unlikely error code */
87 tloc = asn_UT2time(st, 0, 0);
88 if(tloc == -1 && errno != EPERM) {
89 ASN__CTFAIL(app_key, td, sptr, "%s: Invalid time format: %s (%s:%d)",
90 td->name, strerror(errno), __FILE__, __LINE__);
97 #ifndef ASN___INTERNAL_TEST_MODE
100 UTCTime_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,
101 int ilevel, enum xer_encoder_flags_e flags,
102 asn_app_consume_bytes_f *cb, void *app_key) {
103 if(flags & XER_F_CANONICAL) {
109 if(asn_UT2time((const UTCTime_t *)sptr, &tm, 1) == -1
113 /* Fractions are not allowed in UTCTime */
114 ut = asn_time2UT(0, &tm, 1);
115 if(!ut) ASN__ENCODE_FAILED;
117 rv = OCTET_STRING_encode_xer_utf8(td, sptr, ilevel, flags,
119 OCTET_STRING_free(&asn_DEF_UTCTime, ut, 0);
122 return OCTET_STRING_encode_xer_utf8(td, sptr, ilevel, flags,
127 #endif /* ASN___INTERNAL_TEST_MODE */
130 UTCTime_print(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
131 asn_app_consume_bytes_f *cb, void *app_key) {
132 const UTCTime_t *st = (const UTCTime_t *)sptr;
134 (void)td; /* Unused argument */
135 (void)ilevel; /* Unused argument */
143 if(asn_UT2time(st, &tm, 1) == -1 && errno != EPERM)
144 return (cb("<bad-value>", 11, app_key) < 0) ? -1 : 0;
146 ret = snprintf(buf, sizeof(buf),
147 "%04d-%02d-%02d %02d:%02d:%02d (GMT)",
148 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
149 tm.tm_hour, tm.tm_min, tm.tm_sec);
150 assert(ret > 0 && ret < (int)sizeof(buf));
151 return (cb(buf, ret, app_key) < 0) ? -1 : 0;
153 return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
158 asn_UT2time(const UTCTime_t *st, struct tm *_tm, int as_gmt) {
159 char buf[24]; /* "AAMMJJhhmmss+hhmm" + cushion */
160 GeneralizedTime_t gt;
163 || st->size < 11 || st->size >= ((int)sizeof(buf) - 2)) {
168 gt.buf = (unsigned char *)buf;
169 gt.size = st->size + 2;
170 memcpy(gt.buf + 2, st->buf, st->size);
171 if(st->buf[0] > 0x35) {
181 return asn_GT2time(>, _tm, as_gmt);
185 asn_time2UT(UTCTime_t *opt_ut, const struct tm *tm, int force_gmt) {
186 GeneralizedTime_t *gt = (GeneralizedTime_t *)opt_ut;
188 gt = asn_time2GT(gt, tm, force_gmt);
189 if(gt == 0) return 0;
191 assert(gt->size >= 2);
193 memmove(gt->buf, gt->buf + 2, gt->size + 1);
195 return (UTCTime_t *)gt;
199 asn_random_fill_result_t
200 UTCTime_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
201 const asn_encoding_constraints_t *constraints,
203 asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
204 asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
205 asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
206 static const char *values[] = {
207 "700101000000", "700101000000-0000", "700101000000+0000",
208 "700101000000Z", "821106210623", "691106210827-0500",
211 size_t rnd = asn_random_between(0, sizeof(values)/sizeof(values[0])-1);
215 if(max_length < sizeof("yymmddhhmmss") && !*sptr) {
216 return result_skipped;
220 if(OCTET_STRING_fromBuf(*sptr, values[rnd], -1) != 0) {
221 if(!sptr) return result_failed;
224 *sptr = OCTET_STRING_new_fromBuf(td, values[rnd], -1);
225 if(!sptr) return result_failed;
232 UTCTime_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
234 const GeneralizedTime_t *a = aptr;
235 const GeneralizedTime_t *b = bptr;
244 at = asn_UT2time(a, 0, 0);
247 bt = asn_UT2time(b, 0, 0);
250 if(at == -1 && aerr != EPERM) {
251 if(bt == -1 && berr != EPERM) {
252 return OCTET_STRING_compare(td, aptr, bptr);
256 } else if(bt == -1 && berr != EPERM) {
259 /* Both values are valid. */
269 } else if(!a && !b) {