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