1 /*------------------------------------------------------------------------------
2  *
3  * Copyright (c) 2011-2021, EURid vzw. All rights reserved.
4  * The YADIFA TM software product is provided under the BSD 3-clause license:
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  *        * Redistributions of source code must retain the above copyright
11  *          notice, this list of conditions and the following disclaimer.
12  *        * Redistributions in binary form must reproduce the above copyright
13  *          notice, this list of conditions and the following disclaimer in the
14  *          documentation and/or other materials provided with the distribution.
15  *        * Neither the name of EURid nor the names of its contributors may be
16  *          used to endorse or promote products derived from this software
17  *          without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  *------------------------------------------------------------------------------
32  *
33  */
34 
35 /** @defgroup format C-string formatting
36  *  @ingroup dnscore
37  *  @brief
38  *
39  *
40  *
41  * @{
42  *
43  *----------------------------------------------------------------------------*/
44 #include "dnscore/dnscore-config.h"
45 #include <stdio.h>
46 #include <stdlib.h>
47 
48 #include <sys/types.h>	/* Required for BSD */
49 #include <sys/socket.h>
50 #include <netinet/in.h>
51 #include <arpa/inet.h>
52 #include <time.h>
53 
54 //#include "dnscore/dnscore-config.h"
55 #include "dnscore/rfc.h"
56 #include "dnscore/ctrl-rfc.h"
57 #include "dnscore/format.h"
58 #include "dnscore/dnsname.h"
59 #include "dnscore/base32hex.h"
60 #include "dnscore/dnsformat.h"
61 #include "dnscore/host_address.h"
62 
63 #define NULL_STRING_SUBSTITUTE (u8*)"(NULL)"
64 #define NULL_STRING_SUBSTITUTE_LEN 6 /*(sizeof(NULL_STRING_SUBSTITUTE)-1)*/
65 #define PORT_SEPARATOR '#'
66 #define PORT_SEPARATOR_V4 PORT_SEPARATOR
67 #define PORT_SEPARATOR_V6 PORT_SEPARATOR
68 
69 static const char dateseparator[1] = {'-'};
70 static const char timeseparator[1] = {':'};
71 static const char fracseparator[1] = {'.'};
72 static const char datetimeseparator[1] = {' '};
73 static const char utcsuffix[1] = {'Z'};
74 
75 /**
76  *  dtus
77  *
78  *  @note 64 bits epoch written up to the us
79  */
80 
81 void
datetimeus_format_handler_method(const void * restrict val,output_stream * stream,s32 padding,char pad_char,bool left_justified,void * restrict reserved_for_method_parameters)82 datetimeus_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters)
83 {
84     (void)padding;
85     (void)pad_char;
86     (void)left_justified;
87     (void)reserved_for_method_parameters;
88     u64 epoch_us = (u64)(intptr)val;
89     time_t epoch = (time_t)(epoch_us / 1000000);
90     u32 us = (u32)(epoch_us % 1000000);
91 
92     struct tm t;
93     gmtime_r(&epoch, &t);
94 
95     format_dec_u64(t.tm_year + 1900, stream, 4, '0', FALSE);
96     output_stream_write(stream, dateseparator, 1);
97     format_dec_u64(t.tm_mon + 1    , stream, 2, '0', FALSE);
98     output_stream_write(stream, dateseparator, 1);
99     format_dec_u64(t.tm_mday       , stream, 2, '0', FALSE);
100     output_stream_write(stream, datetimeseparator, 1);
101     format_dec_u64(t.tm_hour       , stream, 2, '0', FALSE);
102     output_stream_write(stream, timeseparator, 1);
103     format_dec_u64(t.tm_min        , stream, 2, '0', FALSE);
104     output_stream_write(stream, timeseparator, 1);
105     format_dec_u64(t.tm_sec        , stream, 2, '0', FALSE);
106     output_stream_write(stream, fracseparator, 1);
107     format_dec_u64(us              , stream, 6, '0', FALSE);
108     output_stream_write(stream, utcsuffix, 1);
109 }
110 
111 void
localdatetimeus_format_handler_method(const void * restrict val,output_stream * stream,s32 padding,char pad_char,bool left_justified,void * restrict reserved_for_method_parameters)112 localdatetimeus_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters)
113 {
114     (void)padding;
115     (void)pad_char;
116     (void)left_justified;
117     (void)reserved_for_method_parameters;
118     u64 epoch_us = (u64)(intptr)val;
119     time_t epoch = (time_t)(epoch_us / 1000000);
120     u32 us = (u32)(epoch_us % 1000000);
121 
122     struct tm t;
123     localtime_r(&epoch, &t);
124 
125     format_dec_u64(t.tm_year + 1900, stream, 4, '0', FALSE);
126     output_stream_write(stream, dateseparator, 1);
127     format_dec_u64(t.tm_mon + 1    , stream, 2, '0', FALSE);
128     output_stream_write(stream, dateseparator, 1);
129     format_dec_u64(t.tm_mday       , stream, 2, '0', FALSE);
130     output_stream_write(stream, datetimeseparator, 1);
131     format_dec_u64(t.tm_hour       , stream, 2, '0', FALSE);
132     output_stream_write(stream, timeseparator, 1);
133     format_dec_u64(t.tm_min        , stream, 2, '0', FALSE);
134     output_stream_write(stream, timeseparator, 1);
135     format_dec_u64(t.tm_sec        , stream, 2, '0', FALSE);
136     output_stream_write(stream, fracseparator, 1);
137     format_dec_u64(us              , stream, 6, '0', FALSE);
138 }
139 
140 static format_handler_descriptor datetimeus_format_handler_descriptor =
141 {
142     "dtus",
143     4,
144     datetimeus_format_handler_method
145 };
146 
147 /**
148  *  dtms
149  *
150  *  @note 64 bits epoch written up to the ms
151  */
152 
153 void
datetimems_format_handler_method(const void * restrict val,output_stream * stream,s32 padding,char pad_char,bool left_justified,void * restrict reserved_for_method_parameters)154 datetimems_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters)
155 {
156     (void)padding;
157     (void)pad_char;
158     (void)left_justified;
159     (void)reserved_for_method_parameters;
160     u64 epoch_us = (u64)(intptr)val;
161     time_t epoch = (time_t)(epoch_us / 1000000);
162     u32 ms = (u32)(epoch_us % 1000000);
163     ms /= 1000;
164 
165     struct tm t;
166 
167     gmtime_r(&epoch, &t);
168 
169     format_dec_u64(t.tm_year + 1900, stream, 4, '0', FALSE);
170     output_stream_write(stream, dateseparator, 1);
171     format_dec_u64(t.tm_mon + 1    , stream, 2, '0', FALSE);
172     output_stream_write(stream, dateseparator, 1);
173     format_dec_u64(t.tm_mday       , stream, 2, '0', FALSE);
174     output_stream_write(stream, datetimeseparator, 1);
175     format_dec_u64(t.tm_hour       , stream, 2, '0', FALSE);
176     output_stream_write(stream, timeseparator, 1);
177     format_dec_u64(t.tm_min        , stream, 2, '0', FALSE);
178     output_stream_write(stream, timeseparator, 1);
179     format_dec_u64(t.tm_sec        , stream, 2, '0', FALSE);
180     output_stream_write(stream, fracseparator, 1);
181     format_dec_u64(ms              , stream, 3, '0', FALSE);
182 }
183 
184 static format_handler_descriptor datetimems_format_handler_descriptor =
185 {
186     "dtms",
187     4,
188     datetimems_format_handler_method
189 };
190 
191 /**
192  *  dts
193  *
194  *  @note 64 bits epoch written up to the s
195  */
196 
197 void
datetime_format_handler_method(const void * restrict val,output_stream * stream,s32 padding,char pad_char,bool left_justified,void * restrict reserved_for_method_parameters)198 datetime_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters)
199 {
200     (void)padding;
201     (void)pad_char;
202     (void)left_justified;
203     (void)reserved_for_method_parameters;
204     u64 epoch_us = (u64)(intptr)val;
205     time_t epoch = (time_t)(epoch_us / 1000000);
206 
207     struct tm t;
208 
209     gmtime_r(&epoch, &t);
210 
211     format_dec_u64(t.tm_year + 1900, stream, 4, '0', FALSE);
212     output_stream_write(stream, dateseparator, 1);
213     format_dec_u64(t.tm_mon + 1    , stream, 2, '0', FALSE);
214     output_stream_write(stream, dateseparator, 1);
215     format_dec_u64(t.tm_mday       , stream, 2, '0', FALSE);
216     output_stream_write(stream, datetimeseparator, 1);
217     format_dec_u64(t.tm_hour       , stream, 2, '0', FALSE);
218     output_stream_write(stream, timeseparator, 1);
219     format_dec_u64(t.tm_min        , stream, 2, '0', FALSE);
220     output_stream_write(stream, timeseparator, 1);
221     format_dec_u64(t.tm_sec        , stream, 2, '0', FALSE);
222 }
223 
224 static format_handler_descriptor datetime_format_handler_descriptor =
225 {
226     "dts",
227     3,
228     datetime_format_handler_method
229 };
230 
231 /**
232  *  dts
233  *
234  *  @note 64 bits epoch written up to the s
235  */
236 
237 void
localdatetime_format_handler_method(const void * restrict val,output_stream * stream,s32 padding,char pad_char,bool left_justified,void * restrict reserved_for_method_parameters)238 localdatetime_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters)
239 {
240     (void)padding;
241     (void)pad_char;
242     (void)left_justified;
243     (void)reserved_for_method_parameters;
244     u64 epoch_us = (u64)(intptr)val;
245     time_t epoch = (time_t)(epoch_us / 1000000);
246 
247     struct tm t;
248 
249     gmtime_r(&epoch, &t);
250 
251     format_dec_u64(t.tm_year + 1900, stream, 4, '0', FALSE);
252     output_stream_write(stream, dateseparator, 1);
253     format_dec_u64(t.tm_mon + 1    , stream, 2, '0', FALSE);
254     output_stream_write(stream, dateseparator, 1);
255     format_dec_u64(t.tm_mday       , stream, 2, '0', FALSE);
256     output_stream_write(stream, datetimeseparator, 1);
257     format_dec_u64(t.tm_hour       , stream, 2, '0', FALSE);
258     output_stream_write(stream, timeseparator, 1);
259     format_dec_u64(t.tm_min        , stream, 2, '0', FALSE);
260     output_stream_write(stream, timeseparator, 1);
261     format_dec_u64(t.tm_sec        , stream, 2, '0', FALSE);
262 }
263 
264 static format_handler_descriptor localdatetime_format_handler_descriptor =
265 {
266     "ldts",
267     4,
268     localdatetime_format_handler_method
269 };
270 
271 /**
272  *  date
273  *
274  *  @note 64 bits epoch written up to the day
275  */
276 
277 void
date_format_handler_method(const void * restrict val,output_stream * stream,s32 padding,char pad_char,bool left_justified,void * restrict reserved_for_method_parameters)278 date_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters)
279 {
280     (void)padding;
281     (void)pad_char;
282     (void)left_justified;
283     (void)reserved_for_method_parameters;
284     u64 epoch_us = (u64)(intptr)val;
285     time_t epoch = (time_t)(epoch_us / 1000000);
286 
287     struct tm t;
288 
289     gmtime_r(&epoch, &t);
290 
291     format_dec_u64(t.tm_year + 1900, stream, 4, '0', FALSE);
292     output_stream_write(stream, dateseparator, 1);
293     format_dec_u64(t.tm_mon + 1    , stream, 2, '0', FALSE);
294     output_stream_write(stream, dateseparator, 1);
295     format_dec_u64(t.tm_mday       , stream, 2, '0', FALSE);
296 }
297 
298 static format_handler_descriptor date_format_handler_descriptor =
299 {
300     "date",
301     4,
302     date_format_handler_method
303 };
304 
305 /**
306  *  time
307  *
308  *  @note 64 bits with only HH:MM:SS
309  */
310 
311 void
time_format_handler_method(const void * restrict val,output_stream * stream,s32 padding,char pad_char,bool left_justified,void * restrict reserved_for_method_parameters)312 time_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters)
313 {
314     (void)padding;
315     (void)pad_char;
316     (void)left_justified;
317     (void)reserved_for_method_parameters;
318     u64 epoch_us = (u64)(intptr)val;
319     time_t epoch = (time_t)(epoch_us / 1000000);
320 
321     struct tm t;
322 
323     gmtime_r(&epoch, &t);
324 
325     format_dec_u64(t.tm_hour       , stream, 2, '0', FALSE);
326     output_stream_write(stream, timeseparator, 1);
327     format_dec_u64(t.tm_min        , stream, 2, '0', FALSE);
328     output_stream_write(stream, timeseparator, 1);
329     format_dec_u64(t.tm_sec        , stream, 2, '0', FALSE);
330 }
331 
332 static format_handler_descriptor time_format_handler_descriptor =
333 {
334     "time",
335     4,
336     time_format_handler_method
337 };
338 
339 /**
340  *  epoch
341  *
342  *  @note 32 bits epoch written up to the s
343  */
344 
345 void
epoch_format_handler_method(const void * restrict val,output_stream * stream,s32 padding,char pad_char,bool left_justified,void * restrict reserved_for_method_parameters)346 epoch_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters)
347 {
348     (void)padding;
349     (void)pad_char;
350     (void)left_justified;
351     (void)reserved_for_method_parameters;
352     time_t epoch = (time_t)(intptr)val;
353     struct tm t;
354     gmtime_r(&epoch, &t);
355 
356     format_dec_u64(t.tm_year + 1900, stream, 4, '0', FALSE);
357     output_stream_write(stream, dateseparator, 1);
358     format_dec_u64(t.tm_mon + 1    , stream, 2, '0', FALSE);
359     output_stream_write(stream, dateseparator, 1);
360     format_dec_u64(t.tm_mday       , stream, 2, '0', FALSE);
361     output_stream_write(stream, datetimeseparator, 1);
362     format_dec_u64(t.tm_hour       , stream, 2, '0', FALSE);
363     output_stream_write(stream, timeseparator, 1);
364     format_dec_u64(t.tm_min        , stream, 2, '0', FALSE);
365     output_stream_write(stream, timeseparator, 1);
366     format_dec_u64(t.tm_sec        , stream, 2, '0', FALSE);
367     output_stream_write(stream, utcsuffix, 1);
368 }
369 
370 void
localepoch_format_handler_method(const void * restrict val,output_stream * stream,s32 padding,char pad_char,bool left_justified,void * restrict reserved_for_method_parameters)371 localepoch_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters)
372 {
373     (void)padding;
374     (void)pad_char;
375     (void)left_justified;
376     (void)reserved_for_method_parameters;
377     time_t epoch = (time_t)(intptr)val;
378     struct tm t;
379     localtime_r(&epoch, &t);
380 
381     format_dec_u64(t.tm_year + 1900, stream, 4, '0', FALSE);
382     output_stream_write(stream, dateseparator, 1);
383     format_dec_u64(t.tm_mon + 1    , stream, 2, '0', FALSE);
384     output_stream_write(stream, dateseparator, 1);
385     format_dec_u64(t.tm_mday       , stream, 2, '0', FALSE);
386     output_stream_write(stream, datetimeseparator, 1);
387     format_dec_u64(t.tm_hour       , stream, 2, '0', FALSE);
388     output_stream_write(stream, timeseparator, 1);
389     format_dec_u64(t.tm_min        , stream, 2, '0', FALSE);
390     output_stream_write(stream, timeseparator, 1);
391     format_dec_u64(t.tm_sec        , stream, 2, '0', FALSE);
392 }
393 
394 static format_handler_descriptor epoch_format_handler_descriptor =
395 {
396     "epoch",
397     5,
398     epoch_format_handler_method
399 };
400 
401 /**
402  *  epoch where value 0 prints nothing
403  *
404  *  @note 32 bits epoch written up to the s
405  */
406 
407 void
epochz_format_handler_method(const void * restrict val,output_stream * stream,s32 padding,char pad_char,bool left_justified,void * restrict reserved_for_method_parameters)408 epochz_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters)
409 {
410     (void)padding;
411     (void)pad_char;
412     (void)left_justified;
413     (void)reserved_for_method_parameters;
414     time_t epoch = (time_t)(intptr)val;
415 
416     if(epoch != 0)
417     {
418         struct tm t;
419 
420         gmtime_r(&epoch, &t);
421 
422         format_dec_u64(t.tm_year + 1900, stream, 4, '0', FALSE);
423         output_stream_write(stream, dateseparator, 1);
424         format_dec_u64(t.tm_mon + 1    , stream, 2, '0', FALSE);
425         output_stream_write(stream, dateseparator, 1);
426         format_dec_u64(t.tm_mday       , stream, 2, '0', FALSE);
427         output_stream_write(stream, datetimeseparator, 1);
428         format_dec_u64(t.tm_hour       , stream, 2, '0', FALSE);
429         output_stream_write(stream, timeseparator, 1);
430         format_dec_u64(t.tm_min        , stream, 2, '0', FALSE);
431         output_stream_write(stream, timeseparator, 1);
432         format_dec_u64(t.tm_sec        , stream, 2, '0', FALSE);
433     }
434     else
435     {
436         while(padding > 0)
437         {
438             output_stream_write(stream, "-", 1);
439             --padding;
440         }
441     }
442 }
443 
444 static format_handler_descriptor epochz_format_handler_descriptor =
445 {
446     "epochz",
447     6,
448     epochz_format_handler_method
449 };
450 
451 /**
452  *  epoch
453  *
454  *  @note 32 bits epoch written up to the s
455  */
456 
457 void
packedepoch_format_handler_method(const void * restrict val,output_stream * stream,s32 padding,char pad_char,bool left_justified,void * restrict reserved_for_method_parameters)458 packedepoch_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters)
459 {
460     (void)padding;
461     (void)pad_char;
462     (void)left_justified;
463     (void)reserved_for_method_parameters;
464     time_t epoch = (time_t)(intptr)val;
465     struct tm t;
466 
467     gmtime_r(&epoch, &t);
468 
469     format_dec_u64(t.tm_year + 1900, stream, 4, '0', FALSE);
470     format_dec_u64(t.tm_mon + 1    , stream, 2, '0', FALSE);
471     format_dec_u64(t.tm_mday       , stream, 2, '0', FALSE);
472     format_dec_u64(t.tm_hour       , stream, 2, '0', FALSE);
473     format_dec_u64(t.tm_min        , stream, 2, '0', FALSE);
474     format_dec_u64(t.tm_sec        , stream, 2, '0', FALSE);
475     // DO NOT ADD A SUFFIX HERE
476 }
477 
478 static format_handler_descriptor packedepoch_format_handler_descriptor =
479 {
480     "packedepoch",
481     11,
482     packedepoch_format_handler_method
483 };
484 
485 static bool timeformat_class_init_done = FALSE;
486 
487 void
timeformat_class_init()488 timeformat_class_init()
489 {
490     if(timeformat_class_init_done)
491     {
492         return;
493     }
494 
495     timeformat_class_init_done = TRUE;
496 
497     format_class_init();
498 
499     // 64 bits
500 
501     format_registerclass(&datetimeus_format_handler_descriptor);
502     format_registerclass(&datetimems_format_handler_descriptor);
503     format_registerclass(&datetime_format_handler_descriptor);
504     format_registerclass(&date_format_handler_descriptor);
505     format_registerclass(&time_format_handler_descriptor);
506     format_registerclass(&localdatetime_format_handler_descriptor);
507 
508     // 32 bits
509 
510     format_registerclass(&epoch_format_handler_descriptor);
511     format_registerclass(&epochz_format_handler_descriptor);
512     format_registerclass(&packedepoch_format_handler_descriptor);
513 }
514 
515 /** @} */
516