OpenVAS Scanner  7.0.1~git
nasl_isotime.c
Go to the documentation of this file.
1 /* Portions Copyright (C) 2012-2019 Greenbone Networks GmbH
2  * Based on work Copyright (C) 1998, 2002, 2007, 2011 Free Software Foundation,
3  * Inc.
4  *
5  * SPDX-License-Identifier: GPL-2.0-or-later
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21 
22 /* This code is based on code from GnuPG 2.x, file common/gettime.c,
23  commit id 76055d4. The copyright was LGPLv3+ or GPLv2+; we chose
24  GPLv2+. The only author of that code is Werner Koch; who assigned
25  the copyright to the FSF. */
26 
49 #include "nasl_isotime.h"
50 
51 #include "nasl_debug.h"
52 #include "nasl_global_ctxt.h"
53 #include "nasl_lex_ctxt.h"
54 #include "nasl_tree.h"
55 #include "nasl_var.h"
56 
57 #include <ctype.h>
58 #include <glib.h>
59 #include <glib/gstdio.h>
60 #include <stdio.h>
61 #include <stdlib.h>
62 #include <string.h>
63 #include <time.h>
64 #include <unistd.h>
65 
66 #ifndef DIM
67 #define DIM(v) (sizeof (v) / sizeof ((v)[0]))
68 #define DIMof(type, member) DIM (((type *) 0)->member)
69 #endif
70 
71 /* The type used to represent the time here is a string with a fixed
72  length. */
73 #define ISOTIME_SIZE 19
74 typedef char my_isotime_t[ISOTIME_SIZE];
75 
76 /* Correction used to map to real Julian days. */
77 #define JD_DIFF 1721060L
78 
79 /* Useful helper macros to avoid problems with locales. */
80 #define spacep(p) (*(p) == ' ' || *(p) == '\t')
81 #define digitp(p) (*(p) >= '0' && *(p) <= '9')
82 
83 /* The atoi macros assume that the buffer has only valid digits. */
84 #define atoi_1(p) (*(p) - '0')
85 #define atoi_2(p) ((atoi_1 (p) * 10) + atoi_1 ((p) + 1))
86 #define atoi_4(p) ((atoi_2 (p) * 100) + atoi_2 ((p) + 2))
87 
88 /* Convert an Epoch time to an ISO timestamp. */
89 static void
90 epoch2isotime (my_isotime_t timebuf, time_t atime)
91 {
92  if (atime == (time_t) (-1))
93  *timebuf = 0;
94  else
95  {
96  struct tm *tp;
97 
98  tp = gmtime (&atime);
99  if (snprintf (timebuf, ISOTIME_SIZE, "%04d%02d%02dT%02d%02d%02d",
100  1900 + tp->tm_year, tp->tm_mon + 1, tp->tm_mday,
101  tp->tm_hour, tp->tm_min, tp->tm_sec)
102  < 0)
103  {
104  *timebuf = '\0';
105  return;
106  }
107  }
108 }
109 
110 /* Return the current time in ISO format. */
111 static void
113 {
114  epoch2isotime (timebuf, time (NULL));
115 }
116 
117 /* Check that the 15 bytes in ATIME represent a valid ISO timestamp.
118  Returns 0 if ATIME has a valid format. Note that this function
119  does not expect a string but a check just the plain 15 bytes of the
120  the buffer without looking at the string terminator. */
121 static int
123 {
124  int i;
125  const char *s;
126 
127  if (!*atime)
128  return 1;
129 
130  for (s = atime, i = 0; i < 8; i++, s++)
131  if (!digitp (s))
132  return 1;
133  if (*s != 'T')
134  return 1;
135  for (s++, i = 9; i < 15; i++, s++)
136  if (!digitp (s))
137  return 1;
138  return 0;
139 }
140 
141 /* Return true if STRING holds an isotime string. The expected format is
142  yyyymmddThhmmss
143  optionally terminated by white space, comma, or a colon.
144  */
145 static int
146 isotime_p (const char *string)
147 {
148  const char *s;
149  int i;
150 
151  if (!*string)
152  return 0;
153  for (s = string, i = 0; i < 8; i++, s++)
154  if (!digitp (s))
155  return 0;
156  if (*s != 'T')
157  return 0;
158  for (s++, i = 9; i < 15; i++, s++)
159  if (!digitp (s))
160  return 0;
161  if (!(!*s || (isascii (*s) && isspace (*s)) || *s == ':' || *s == ','))
162  return 0; /* Wrong delimiter. */
163 
164  return 1;
165 }
166 
167 /* Scan a string and return true if the string represents the human
168  readable format of an ISO time. This format is:
169  yyyy-mm-dd[ hh[:mm[:ss]]]
170  Scanning stops at the second space or at a comma. */
171 static int
172 isotime_human_p (const char *string)
173 {
174  const char *s;
175  int i;
176 
177  if (!*string)
178  return 0;
179  for (s = string, i = 0; i < 4; i++, s++)
180  if (!digitp (s))
181  return 0;
182  if (*s != '-')
183  return 0;
184  s++;
185  if (!digitp (s) || !digitp (s + 1) || s[2] != '-')
186  return 0;
187  i = atoi_2 (s);
188  if (i < 1 || i > 12)
189  return 0;
190  s += 3;
191  if (!digitp (s) || !digitp (s + 1))
192  return 0;
193  i = atoi_2 (s);
194  if (i < 1 || i > 31)
195  return 0;
196  s += 2;
197  if (!*s || *s == ',')
198  return 1; /* Okay; only date given. */
199  if (!spacep (s))
200  return 0;
201  s++;
202  if (spacep (s))
203  return 1; /* Okay, second space stops scanning. */
204  if (!digitp (s) || !digitp (s + 1))
205  return 0;
206  i = atoi_2 (s);
207  if (i < 0 || i > 23)
208  return 0;
209  s += 2;
210  if (!*s || *s == ',')
211  return 1; /* Okay; only date and hour given. */
212  if (*s != ':')
213  return 0;
214  s++;
215  if (!digitp (s) || !digitp (s + 1))
216  return 0;
217  i = atoi_2 (s);
218  if (i < 0 || i > 59)
219  return 0;
220  s += 2;
221  if (!*s || *s == ',')
222  return 1; /* Okay; only date, hour and minute given. */
223  if (*s != ':')
224  return 0;
225  s++;
226  if (!digitp (s) || !digitp (s + 1))
227  return 0;
228  i = atoi_2 (s);
229  if (i < 0 || i > 60)
230  return 0;
231  s += 2;
232  if (!*s || *s == ',' || spacep (s))
233  return 1; /* Okay; date, hour and minute and second given. */
234 
235  return 0; /* Unexpected delimiter. */
236 }
237 
238 /* Convert a standard isotime or a human readable variant into an
239  isotime structure. The allowed formats are those described by
240  isotime_p and isotime_human_p. The function returns 0 on failure
241  or the length of the scanned string on success. */
242 static int
243 string2isotime (my_isotime_t atime, const char *string)
244 {
245  my_isotime_t dummyatime;
246 
247  if (!atime)
248  atime = dummyatime;
249 
250  memset (atime, '\0', sizeof (my_isotime_t));
251  atime[0] = 0;
252  if (isotime_p (string))
253  {
254  memcpy (atime, string, 15);
255  atime[15] = 0;
256  return 15;
257  }
258  if (!isotime_human_p (string))
259  return 0;
260  atime[0] = string[0];
261  atime[1] = string[1];
262  atime[2] = string[2];
263  atime[3] = string[3];
264  atime[4] = string[5];
265  atime[5] = string[6];
266  atime[6] = string[8];
267  atime[7] = string[9];
268  atime[8] = 'T';
269  if (!spacep (string + 10))
270  return 10;
271  if (spacep (string + 11))
272  return 11; /* As per def, second space stops scanning. */
273  atime[9] = string[11];
274  atime[10] = string[12];
275  if (string[13] != ':')
276  return 13;
277  atime[11] = string[14];
278  atime[12] = string[15];
279  if (string[16] != ':')
280  return 16;
281  atime[13] = string[17];
282  atime[14] = string[18];
283  return 19;
284 }
285 
286 /* Helper for jd2date. */
287 static int
289 {
290  int s;
291 
292  s = !(y % 4);
293  if (!(y % 100))
294  if ((y % 400))
295  s = 0;
296  return s ? 366 : 365;
297 }
298 
299 /* Helper for jd2date. */
300 static int
301 days_per_month (int y, int m)
302 {
303  int s;
304 
305  switch (m)
306  {
307  case 1:
308  case 3:
309  case 5:
310  case 7:
311  case 8:
312  case 10:
313  case 12:
314  return 31;
315  case 2:
316  s = !(y % 4);
317  if (!(y % 100))
318  if ((y % 400))
319  s = 0;
320  return s ? 29 : 28;
321  case 4:
322  case 6:
323  case 9:
324  case 11:
325  return 30;
326  default:
327  abort ();
328  }
329 }
330 
331 /* Convert YEAR, MONTH and DAY into the Julian date. We assume that
332  it is already noon. We do not support dates before 1582-10-15. */
333 static unsigned long
334 date2jd (int year, int month, int day)
335 {
336  unsigned long jd;
337 
338  jd = 365L * year + 31 * (month - 1) + day + JD_DIFF;
339  if (month < 3)
340  year--;
341  else
342  jd -= (4 * month + 23) / 10;
343 
344  jd += year / 4 - ((year / 100 + 1) * 3) / 4;
345 
346  return jd;
347 }
348 
349 /* Convert a Julian date back to YEAR, MONTH and DAY. Return day of
350  the year or 0 on error. This function uses some more or less
351  arbitrary limits, most important is that days before 1582-10-15 are
352  not supported. */
353 static int
354 jd2date (unsigned long jd, int *year, int *month, int *day)
355 {
356  int y, m, d;
357  long delta;
358 
359  if (!jd)
360  return 0;
361  if (jd < 1721425 || jd > 2843085)
362  return 0;
363 
364  y = (jd - JD_DIFF) / 366;
365  d = m = 1;
366 
367  while ((delta = jd - date2jd (y, m, d)) > days_per_year (y))
368  y++;
369 
370  m = (delta / 31) + 1;
371  while ((delta = jd - date2jd (y, m, d)) > days_per_month (y, m))
372  if (++m > 12)
373  {
374  m = 1;
375  y++;
376  }
377 
378  d = delta + 1;
379  if (d > days_per_month (y, m))
380  {
381  d = 1;
382  m++;
383  }
384  if (m > 12)
385  {
386  m = 1;
387  y++;
388  }
389 
390  if (year)
391  *year = y;
392  if (month)
393  *month = m;
394  if (day)
395  *day = d;
396 
397  return (jd - date2jd (y, 1, 1)) + 1;
398 }
399 
400 /* Add SECONDS to ATIME. SECONDS may not be negative and is limited
401  to about the equivalent of 62 years which should be more then
402  enough for our purposes. Returns 0 on success. */
403 static int
405 {
406  int year, month, day, hour, minute, sec, ndays;
407  unsigned long jd;
408 
409  if (check_isotime (atime))
410  return 1;
411 
412  if (nseconds < 0 || nseconds >= (0x7fffffff - 61))
413  return 1;
414 
415  year = atoi_4 (atime + 0);
416  month = atoi_2 (atime + 4);
417  day = atoi_2 (atime + 6);
418  hour = atoi_2 (atime + 9);
419  minute = atoi_2 (atime + 11);
420  sec = atoi_2 (atime + 13);
421 
422  /* The julian date functions don't support this. */
423  if (year < 1582 || (year == 1582 && month < 10)
424  || (year == 1582 && month == 10 && day < 15))
425  return 1;
426 
427  sec += nseconds;
428  minute += sec / 60;
429  sec %= 60;
430  hour += minute / 60;
431  minute %= 60;
432  ndays = hour / 24;
433  hour %= 24;
434 
435  jd = date2jd (year, month, day) + ndays;
436  jd2date (jd, &year, &month, &day);
437 
438  if (year > 9999 || month > 12 || day > 31 || year < 0 || month < 1 || day < 1)
439  return 1;
440 
441  if (snprintf (atime, ISOTIME_SIZE, "%04d%02d%02dT%02d%02d%02d", year, month,
442  day, hour, minute, sec)
443  < 0)
444  return 1;
445 
446  return 0;
447 }
448 
449 /* Add NDAYS to ATIME. Returns 0 on success. */
450 static int
452 {
453  int year, month, day, hour, minute, sec;
454  unsigned long jd;
455 
456  if (check_isotime (atime))
457  return 1;
458 
459  if (ndays < 0 || ndays >= 9999 * 366)
460  return 1;
461 
462  year = atoi_4 (atime + 0);
463  month = atoi_2 (atime + 4);
464  day = atoi_2 (atime + 6);
465  hour = atoi_2 (atime + 9);
466  minute = atoi_2 (atime + 11);
467  sec = atoi_2 (atime + 13);
468 
469  /* The julian date functions don't support this. */
470  if (year < 1582 || (year == 1582 && month < 10)
471  || (year == 1582 && month == 10 && day < 15))
472  return 1;
473 
474  jd = date2jd (year, month, day) + ndays;
475  jd2date (jd, &year, &month, &day);
476 
477  if (year > 9999 || month > 12 || day > 31 || year < 0 || month < 1 || day < 1)
478  return 1;
479 
480  if (snprintf (atime, ISOTIME_SIZE, "%04d%02d%02dT%02d%02d%02d", year, month,
481  day, hour, minute, sec)
482  < 0)
483  return 1;
484  return 0;
485 }
486 
487 /* Add NYEARS to ATIME. Returns 0 on success. */
488 static int
490 {
491  int year, month, day, hour, minute, sec;
492  unsigned long jd;
493 
494  if (check_isotime (atime))
495  return 1;
496 
497  if (nyears < 0 || nyears >= 9999)
498  return 1;
499 
500  year = atoi_4 (atime + 0);
501  month = atoi_2 (atime + 4);
502  day = atoi_2 (atime + 6);
503  hour = atoi_2 (atime + 9);
504  minute = atoi_2 (atime + 11);
505  sec = atoi_2 (atime + 13);
506 
507  /* The julian date functions don't support this. */
508  if (year < 1582 || (year == 1582 && month < 10)
509  || (year == 1582 && month == 10 && day < 15))
510  return 1;
511 
512  jd = date2jd (year + nyears, month, day);
513  jd2date (jd, &year, &month, &day);
514 
515  if (year > 9999 || month > 12 || day > 31 || year < 0 || month < 1 || day < 1)
516  return 1;
517 
518  if (snprintf (atime, ISOTIME_SIZE, "%04d%02d%02dT%02d%02d%02d", year, month,
519  day, hour, minute, sec)
520  < 0)
521  return 1;
522 
523  return 0;
524 }
525 
541 tree_cell *
543 {
544  tree_cell *retc;
545  my_isotime_t timebuf;
546 
547  (void) lexic;
548  get_current_isotime (timebuf);
549 
550  retc = alloc_typed_cell (CONST_STR);
551  retc->x.str_val = g_strdup (timebuf);
552  retc->size = strlen (timebuf);
553  return retc;
554 }
555 
573 tree_cell *
575 {
576  int result = 0;
577  tree_cell *retc;
578  my_isotime_t timebuf;
579  const char *string;
580  int datalen;
581 
582  string = get_str_var_by_num (lexic, 0);
583  if (string)
584  {
585  switch (get_var_type_by_num (lexic, 0))
586  {
587  case VAR2_DATA:
588  datalen = get_var_size_by_num (lexic, 0);
589  if (datalen < ISOTIME_SIZE - 1)
590  break; /* Too short */
591  memcpy (timebuf, string, ISOTIME_SIZE - 1);
592  timebuf[ISOTIME_SIZE - 1] = 0;
593  string = timebuf;
594  /* FALLTHRU */
595  case VAR2_STRING:
596  if (isotime_p (string) || isotime_human_p (string))
597  result = 1;
598  break;
599  default:
600  break;
601  }
602  }
603 
604  retc = alloc_typed_cell (CONST_INT);
605  retc->x.i_val = result;
606  return retc;
607 }
608 
624 tree_cell *
626 {
627  tree_cell *retc;
628  my_isotime_t timebuf;
629  int datalen;
630  const char *string;
631 
632  *timebuf = 0;
633  string = get_str_var_by_num (lexic, 0);
634  if (!string)
635  return NULL;
636  switch (get_var_type_by_num (lexic, 0))
637  {
638  case VAR2_DATA:
639  datalen = get_var_size_by_num (lexic, 0);
640  if (datalen < ISOTIME_SIZE - 1)
641  return NULL; /* Too short */
642  memcpy (timebuf, string, ISOTIME_SIZE - 1);
643  timebuf[ISOTIME_SIZE - 1] = 0;
644  string = timebuf;
645  /* FALLTHRU */
646  case VAR2_STRING:
647  if (!string2isotime (timebuf, string))
648  return NULL;
649  break;
650  default:
651  return NULL;
652  }
653 
654  retc = alloc_typed_cell (CONST_STR);
655  retc->x.str_val = g_strdup (timebuf);
656  retc->size = strlen (timebuf);
657  return retc;
658 }
659 
675 tree_cell *
677 {
678  tree_cell *retc;
679  const char *string;
680  char helpbuf[20];
681 
682  string = get_str_var_by_num (lexic, 0);
683  if (!string || get_var_size_by_num (lexic, 0) < 15 || check_isotime (string))
684  strcpy (helpbuf, "[none]");
685  else
686  snprintf (helpbuf, sizeof helpbuf, "%.4s-%.2s-%.2s %.2s:%.2s:%.2s", string,
687  string + 4, string + 6, string + 9, string + 11, string + 13);
688  retc = alloc_typed_cell (CONST_STR);
689  retc->x.str_val = g_strdup (helpbuf);
690  retc->size = strlen (helpbuf);
691  return retc;
692 }
693 
725 tree_cell *
727 {
728  tree_cell *retc;
729  my_isotime_t timebuf;
730  const char *string;
731  int nyears, ndays, nseconds;
732 
733  string = get_str_var_by_num (lexic, 0);
734  if (!string || get_var_size_by_num (lexic, 0) < ISOTIME_SIZE - 1
735  || check_isotime (string))
736  return NULL;
737  memcpy (timebuf, string, ISOTIME_SIZE - 1);
738  timebuf[ISOTIME_SIZE - 1] = 0;
739 
740  nyears = get_int_var_by_name (lexic, "years", 0);
741  ndays = get_int_var_by_name (lexic, "days", 0);
742  nseconds = get_int_var_by_name (lexic, "seconds", 0);
743 
744  if (nyears && add_years_to_isotime (timebuf, nyears))
745  return NULL;
746  if (ndays && add_days_to_isotime (timebuf, ndays))
747  return NULL;
748  if (nseconds && add_seconds_to_isotime (timebuf, nseconds))
749  return NULL;
750  /* If nothing was added, explicitly add 0 years. */
751  if (!nyears && !ndays && !nseconds && add_years_to_isotime (timebuf, 0))
752  return NULL;
753 
754  retc = alloc_typed_cell (CONST_STR);
755  retc->x.str_val = g_strdup (timebuf);
756  retc->size = strlen (timebuf);
757  return retc;
758 }
static unsigned long date2jd(int year, int month, int day)
Definition: nasl_isotime.c:334
static int check_isotime(const my_isotime_t atime)
Definition: nasl_isotime.c:122
char * str_val
Definition: nasl_tree.h:112
static int string2isotime(my_isotime_t atime, const char *string)
Definition: nasl_isotime.c:243
char my_isotime_t[ISOTIME_SIZE]
Definition: nasl_isotime.c:74
static int isotime_p(const char *string)
Definition: nasl_isotime.c:146
tree_cell * nasl_isotime_print(lex_ctxt *lexic)
Convert an SIO time string into a better readable string.
Definition: nasl_isotime.c:676
static int add_days_to_isotime(my_isotime_t atime, int ndays)
Definition: nasl_isotime.c:451
static int days_per_month(int y, int m)
Definition: nasl_isotime.c:301
#define atoi_2(p)
Definition: nasl_isotime.c:85
#define JD_DIFF
Definition: nasl_isotime.c:77
tree_cell * alloc_typed_cell(int typ)
Definition: nasl_tree.c:40
#define atoi_4(p)
Definition: nasl_isotime.c:86
tree_cell * nasl_isotime_add(lex_ctxt *lexic)
Add days or seconds to an ISO time string.
Definition: nasl_isotime.c:726
#define ISOTIME_SIZE
Definition: nasl_isotime.c:73
Definition: nasl_tree.h:104
int get_var_size_by_num(lex_ctxt *, int)
Definition: nasl_var.c:1154
union TC::@2 x
static int add_seconds_to_isotime(my_isotime_t atime, int nseconds)
Definition: nasl_isotime.c:404
static int isotime_human_p(const char *string)
Definition: nasl_isotime.c:172
#define digitp(p)
Definition: nasl_isotime.c:81
static int days_per_year(int y)
Definition: nasl_isotime.c:288
char * get_str_var_by_num(lex_ctxt *, int)
Definition: nasl_var.c:1120
static void epoch2isotime(my_isotime_t timebuf, time_t atime)
Definition: nasl_isotime.c:90
long int get_int_var_by_name(lex_ctxt *, const char *, int)
Definition: nasl_var.c:1113
long int i_val
Definition: nasl_tree.h:113
static void get_current_isotime(my_isotime_t timebuf)
Definition: nasl_isotime.c:112
Protos and data structures for ISOTIME functions used by NASL scripts.
static int add_years_to_isotime(my_isotime_t atime, int nyears)
Definition: nasl_isotime.c:489
static int jd2date(unsigned long jd, int *year, int *month, int *day)
Definition: nasl_isotime.c:354
tree_cell * nasl_isotime_is_valid(lex_ctxt *lexic)
Check whether an ISO time string is valid.
Definition: nasl_isotime.c:574
tree_cell * nasl_isotime_scan(lex_ctxt *lexic)
Convert a string into an ISO time string.
Definition: nasl_isotime.c:625
#define spacep(p)
Definition: nasl_isotime.c:80
tree_cell * nasl_isotime_now(lex_ctxt *lexic)
Return the current time in ISO format.
Definition: nasl_isotime.c:542
int get_var_type_by_num(lex_ctxt *, int)
Returns NASL variable/cell type, VAR2_UNDEF if value is NULL.
Definition: nasl_var.c:1164
int size
Definition: nasl_tree.h:109