ISSUE ID:- RICAPP-216
[ric-app/bouncer.git] / Bouncer / e2sm_kpm / lib / UTCTime.c
1 /*-
2  * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
3  * Redistribution and modifications are permitted subject to BSD license.
4  */
5 #include <asn_internal.h>
6 #include <UTCTime.h>
7 #include <GeneralizedTime.h>
8 #include <errno.h>
9
10 #ifdef  __CYGWIN__
11 #include "/usr/include/time.h"
12 #else
13 #include <time.h>
14 #endif  /* __CYGWIN__ */
15
16 #ifndef ASN___INTERNAL_TEST_MODE
17
18 /*
19  * UTCTime basic type description.
20  */
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 */
25 };
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 */
29         0, 0
30 };
31 asn_TYPE_operation_t asn_OP_UTCTime = {
32         OCTET_STRING_free,
33         UTCTime_print,
34         UTCTime_compare,
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,
38         UTCTime_encode_xer,
39 #ifdef  ASN_DISABLE_OER_SUPPORT
40         0,
41         0,
42 #else
43         OCTET_STRING_decode_oer,
44         OCTET_STRING_encode_oer,
45 #endif  /* ASN_DISABLE_OER_SUPPORT */
46 #ifdef  ASN_DISABLE_PER_SUPPORT
47         0,
48         0,
49         0,
50         0,
51 #else
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 */
57         UTCTime_random_fill,
58         0       /* Use generic outmost tag fetcher */
59 };
60 asn_TYPE_descriptor_t asn_DEF_UTCTime = {
61         "UTCTime",
62         "UTCTime",
63         &asn_OP_UTCTime,
64         asn_DEF_UTCTime_tags,
65         sizeof(asn_DEF_UTCTime_tags)
66           / sizeof(asn_DEF_UTCTime_tags[0]) - 2,
67         asn_DEF_UTCTime_tags,
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 */
72         0       /* No specifics */
73 };
74
75 #endif  /* ASN___INTERNAL_TEST_MODE */
76
77 /*
78  * Check that the time looks like the time.
79  */
80 int
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;
84         time_t tloc;
85
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__);
91         return -1;
92         }
93
94         return 0;
95 }
96
97 #ifndef ASN___INTERNAL_TEST_MODE
98
99 asn_enc_rval_t
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) {
104                 asn_enc_rval_t rv;
105                 UTCTime_t *ut;
106                 struct tm tm;
107
108                 errno = EPERM;
109                 if(asn_UT2time((const UTCTime_t *)sptr, &tm, 1) == -1
110                                 && errno != EPERM)
111                         ASN__ENCODE_FAILED;
112
113                 /* Fractions are not allowed in UTCTime */
114                 ut = asn_time2UT(0, &tm, 1);
115                 if(!ut) ASN__ENCODE_FAILED;
116
117                 rv = OCTET_STRING_encode_xer_utf8(td, sptr, ilevel, flags,
118                         cb, app_key);
119                 OCTET_STRING_free(&asn_DEF_UTCTime, ut, 0);
120                 return rv;
121         } else {
122                 return OCTET_STRING_encode_xer_utf8(td, sptr, ilevel, flags,
123                         cb, app_key);
124         }
125 }
126
127 #endif  /* ASN___INTERNAL_TEST_MODE */
128
129 int
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;
133
134         (void)td;       /* Unused argument */
135         (void)ilevel;   /* Unused argument */
136
137         if(st && st->buf) {
138                 char buf[32];
139                 struct tm tm;
140                 int ret;
141
142                 errno = EPERM;
143                 if(asn_UT2time(st, &tm, 1) == -1 && errno != EPERM)
144                         return (cb("<bad-value>", 11, app_key) < 0) ? -1 : 0;
145
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;
152         } else {
153                 return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
154         }
155 }
156
157 time_t
158 asn_UT2time(const UTCTime_t *st, struct tm *_tm, int as_gmt) {
159         char buf[24];   /* "AAMMJJhhmmss+hhmm" + cushion */
160         GeneralizedTime_t gt;
161
162         if(!st || !st->buf
163         || st->size < 11 || st->size >= ((int)sizeof(buf) - 2)) {
164                 errno = EINVAL;
165                 return -1;
166         }
167
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) {
172                 /* 19xx */
173                 gt.buf[0] = 0x31;
174                 gt.buf[1] = 0x39;
175         } else {
176                 /* 20xx */
177                 gt.buf[0] = 0x32;
178                 gt.buf[1] = 0x30;
179         }
180
181         return asn_GT2time(&gt, _tm, as_gmt);
182 }
183
184 UTCTime_t *
185 asn_time2UT(UTCTime_t *opt_ut, const struct tm *tm, int force_gmt) {
186         GeneralizedTime_t *gt = (GeneralizedTime_t *)opt_ut;
187
188         gt = asn_time2GT(gt, tm, force_gmt);
189         if(gt == 0) return 0;
190
191         assert(gt->size >= 2);
192         gt->size -= 2;
193         memmove(gt->buf, gt->buf + 2, gt->size + 1);
194
195         return (UTCTime_t *)gt;
196 }
197
198
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,
202                     size_t max_length) {
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",
209         "821106210629Z",
210     };
211     size_t rnd = asn_random_between(0, sizeof(values)/sizeof(values[0])-1);
212
213     (void)constraints;
214
215     if(max_length < sizeof("yymmddhhmmss") && !*sptr) {
216         return result_skipped;
217     }
218
219     if(*sptr) {
220         if(OCTET_STRING_fromBuf(*sptr, values[rnd], -1) != 0) {
221             if(!sptr) return result_failed;
222         }
223     } else {
224         *sptr = OCTET_STRING_new_fromBuf(td, values[rnd], -1);
225         if(!sptr) return result_failed;
226     }
227
228     return result_ok;
229 }
230
231 int
232 UTCTime_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
233                         const void *bptr) {
234     const GeneralizedTime_t *a = aptr;
235     const GeneralizedTime_t *b = bptr;
236
237     (void)td;
238
239     if(a && b) {
240         time_t at, bt;
241         int aerr, berr;
242
243         errno = EPERM;
244         at = asn_UT2time(a, 0, 0);
245         aerr = errno;
246         errno = EPERM;
247         bt = asn_UT2time(b, 0, 0);
248         berr = errno;
249
250         if(at == -1 && aerr != EPERM) {
251             if(bt == -1 && berr != EPERM) {
252                 return OCTET_STRING_compare(td, aptr, bptr);
253             } else {
254                 return -1;
255             }
256         } else if(bt == -1 && berr != EPERM) {
257             return 1;
258         } else {
259             /* Both values are valid. */
260         }
261
262         if(at < bt) {
263             return -1;
264         } else if(at > bt) {
265             return 1;
266         } else {
267             return 0;
268         }
269     } else if(!a && !b) {
270         return 0;
271     } else if(!a) {
272         return -1;
273     } else {
274         return 1;
275     }
276 }
277