summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2011-03-01 14:22:41 +0100
committerWerner Koch <wk@gnupg.org>2011-03-01 14:22:41 +0100
commitdfdda3b344e525f4fdb5e2c07ac63b52e501941f (patch)
tree763b777bdd2f8653889118a3203f6318ae3d15b8
parentUpdate gpg-error.m4 and libgcrypt.m4 (diff)
downloadgnupg2-dfdda3b344e525f4fdb5e2c07ac63b52e501941f.tar.xz
gnupg2-dfdda3b344e525f4fdb5e2c07ac63b52e501941f.zip
Add new functions to convert iso time strings.
Diffstat (limited to '')
-rw-r--r--common/ChangeLog8
-rw-r--r--common/gettime.c159
-rw-r--r--common/gettime.h3
-rw-r--r--common/t-gettime.c87
-rw-r--r--common/tlv.c10
-rw-r--r--common/tlv.h10
6 files changed, 253 insertions, 24 deletions
diff --git a/common/ChangeLog b/common/ChangeLog
index f6380c64d..cebc0ece6 100644
--- a/common/ChangeLog
+++ b/common/ChangeLog
@@ -1,3 +1,11 @@
+2011-02-27 Werner Koch <wk@g10code.com>
+
+ * gettime.c (isotime2epoch): Factor check code out to ..
+ (isotime_p): .. new.
+ (isotime_human_p): New.
+ (string2isotime): New.
+ * t-gettime.c (test_string2isotime): New.
+
2011-02-11 Andrey Jivsov <openpgp@brainhub.org>
* openpgp-oid.c (openpgp_oid_to_str): Use unsigned int for
diff --git a/common/gettime.c b/common/gettime.c
index 27dc8456e..e5462a7c6 100644
--- a/common/gettime.c
+++ b/common/gettime.c
@@ -1,5 +1,5 @@
/* gettime.c - Wrapper for time functions
- * Copyright (C) 1998, 2002, 2007 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 2002, 2007, 2011 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -179,29 +179,162 @@ scan_isodatestr( const char *string )
return stamp;
}
-/* Scan am ISO timestamp and return an Epoch based timestamp. The only
- supported format is "yyyymmddThhmmss" delimited by white space, nul, a
- colon or a comma. Returns (time_t)(-1) for an invalid string. */
-time_t
-isotime2epoch (const char *string)
+
+int
+isotime_p (const char *string)
{
const char *s;
- int year, month, day, hour, minu, sec;
- struct tm tmbuf;
int i;
if (!*string)
- return (time_t)(-1);
+ return 0;
for (s=string, i=0; i < 8; i++, s++)
if (!digitp (s))
- return (time_t)(-1);
+ return 0;
if (*s != 'T')
- return (time_t)(-1);
+ return 0;
for (s++, i=9; i < 15; i++, s++)
if (!digitp (s))
- return (time_t)(-1);
+ return 0;
if ( !(!*s || (isascii (*s) && isspace(*s)) || *s == ':' || *s == ','))
- return (time_t)(-1); /* Wrong delimiter. */
+ return 0; /* Wrong delimiter. */
+
+ return 1;
+}
+
+
+/* Scan a string and return true if the string represents the human
+ readable format of an ISO time. This format is:
+ yyyy-mm-dd[ hh[:mm[:ss]]]
+ Scanning stops at the second space or at a comma. */
+int
+isotime_human_p (const char *string)
+{
+ const char *s;
+ int i;
+
+ if (!*string)
+ return 0;
+ for (s=string, i=0; i < 4; i++, s++)
+ if (!digitp (s))
+ return 0;
+ if (*s != '-')
+ return 0;
+ s++;
+ if (!digitp (s) || !digitp (s+1) || s[2] != '-')
+ return 0;
+ i = atoi_2 (s);
+ if (i < 1 || i > 12)
+ return 0;
+ s += 3;
+ if (!digitp (s) || !digitp (s+1))
+ return 0;
+ i = atoi_2 (s);
+ if (i < 1 || i > 31)
+ return 0;
+ s += 2;
+ if (!*s || *s == ',')
+ return 1; /* Okay; only date given. */
+ if (!spacep (s))
+ return 0;
+ s++;
+ if (spacep (s))
+ return 1; /* Okay, second space stops scanning. */
+ if (!digitp (s) || !digitp (s+1))
+ return 0;
+ i = atoi_2 (s);
+ if (i < 0 || i > 23)
+ return 0;
+ s += 2;
+ if (!*s || *s == ',')
+ return 1; /* Okay; only date and hour given. */
+ if (*s != ':')
+ return 0;
+ s++;
+ if (!digitp (s) || !digitp (s+1))
+ return 0;
+ i = atoi_2 (s);
+ if (i < 0 || i > 59)
+ return 0;
+ s += 2;
+ if (!*s || *s == ',')
+ return 1; /* Okay; only date, hour and minute given. */
+ if (*s != ':')
+ return 0;
+ s++;
+ if (!digitp (s) || !digitp (s+1))
+ return 0;
+ i = atoi_2 (s);
+ if (i < 0 || i > 60)
+ return 0;
+ s += 2;
+ if (!*s || *s == ',' || spacep (s))
+ return 1; /* Okay; date, hour and minute and second given. */
+
+ return 0; /* Unexpected delimiter. */
+}
+
+/* Convert a standard isotime or a human readable variant into an
+ isotime structure. The allowed formats are those described by
+ isotime_p and isotime_human_p. The function returns 0 on failure
+ or the length of the scanned string on success. */
+size_t
+string2isotime (gnupg_isotime_t atime, const char *string)
+{
+ gnupg_isotime_t dummyatime;
+
+ if (!atime)
+ atime = dummyatime;
+
+ atime[0] = 0;
+ if (isotime_p (string))
+ {
+ memcpy (atime, string, 15);
+ atime[15] = 0;
+ return 15;
+ }
+ if (!isotime_human_p (string))
+ return 0;
+ atime[0] = string[0];
+ atime[1] = string[1];
+ atime[2] = string[2];
+ atime[3] = string[3];
+ atime[4] = string[5];
+ atime[5] = string[6];
+ atime[6] = string[8];
+ atime[7] = string[9];
+ atime[8] = 'T';
+ memset (atime+9, '0', 6);
+ atime[15] = 0;
+ if (!spacep (string+10))
+ return 10;
+ if (spacep (string+11))
+ return 11; /* As per def, second space stops scanning. */
+ atime[9] = string[11];
+ atime[10] = string[12];
+ if (string[13] != ':')
+ return 13;
+ atime[11] = string[14];
+ atime[12] = string[15];
+ if (string[16] != ':')
+ return 16;
+ atime[13] = string[17];
+ atime[14] = string[18];
+ return 19;
+}
+
+
+/* Scan an ISO timestamp and return an Epoch based timestamp. The only
+ supported format is "yyyymmddThhmmss" delimited by white space, nul, a
+ colon or a comma. Returns (time_t)(-1) for an invalid string. */
+time_t
+isotime2epoch (const char *string)
+{
+ int year, month, day, hour, minu, sec;
+ struct tm tmbuf;
+
+ if (!isotime_p (string))
+ return (time_t)(-1);
year = atoi_4 (string);
month = atoi_2 (string + 4);
diff --git a/common/gettime.h b/common/gettime.h
index 731be569b..4199369e4 100644
--- a/common/gettime.h
+++ b/common/gettime.h
@@ -34,6 +34,9 @@ void gnupg_set_time (time_t newtime, int freeze);
int gnupg_faked_time_p (void);
u32 make_timestamp (void);
u32 scan_isodatestr (const char *string);
+int isotime_p (const char *string);
+int isotime_human_p (const char *string);
+size_t string2isotime (gnupg_isotime_t atime, const char *string);
time_t isotime2epoch (const char *string);
void epoch2isotime (gnupg_isotime_t timebuf, time_t atime);
u32 add_days_to_timestamp (u32 stamp, u16 days);
diff --git a/common/t-gettime.c b/common/t-gettime.c
index 1cfde69c7..79c3d4335 100644
--- a/common/t-gettime.c
+++ b/common/t-gettime.c
@@ -1,5 +1,5 @@
/* t-gettime.c - Module test for gettime.c
- * Copyright (C) 2007 Free Software Foundation, Inc.
+ * Copyright (C) 2007, 2011 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -89,6 +89,90 @@ test_isotime2epoch (void)
+static void
+test_string2isotime (void)
+{
+ struct {
+ const char *string;
+ size_t result;
+ const char *expected;
+ } array [] = {
+ { "19700101T000001", 15, "19700101T000001" },
+ { "19700101T235959", 15, "19700101T235959" },
+ { "19980815T143712", 15, "19980815T143712" },
+ { "19700101T000000", 15, "19700101T000000" },
+ { "19691231T235959", 15, "19691231T235959" },
+ { "19000101T000000", 15, "19000101T000000" },
+ { "", 0, "" },
+ { "19000101T00000", 0, "" },
+ { "20010101t123456", 0, "" },
+ { "20010101T123456", 15, "20010101T123456" },
+ { "20070629T160000", 15, "20070629T160000" },
+ { "20070629T160000:", 15, "20070629T160000" },
+ { "20070629T160000,", 15, "20070629T160000" },
+ { "20070629T160000 ", 15, "20070629T160000" },
+ { "20070629T160000\n", 15,"20070629T160000" },
+ { "20070629T160000.", 0, "" },
+ { "1066-03-20", 10, "10660320T000000" },
+ { "1066-03-20,", 10, "10660320T000000" },
+ { "1066-03-20:", 0, "" },
+ { "1066-03-20 00", 13, "10660320T000000" },
+ { "1066-03-20 01", 13, "10660320T010000" },
+ { "1066-03-20 23", 13, "10660320T230000" },
+ { "1066-03-20 24", 0, "" },
+ { "1066-03-20 00:", 0, "" },
+ { "1066-03-20 00:3", 0, "" },
+ { "1066-03-20 00:31", 16, "10660320T003100" },
+ { "1066-03-20 00:31:47", 19, "10660320T003147" },
+ { "1066-03-20 00:31:47 ", 19, "10660320T003147" },
+ { "1066-03-20 00:31:47,", 19, "10660320T003147" },
+ { "1066-03-20 00:31:47:", 0, "" },
+ { "1-03-20 00:31:47:", 0, "" },
+ { "10-03-20 00:31:47:", 0, "" },
+ { "106-03-20 00:31:47:", 0, "" },
+ { "1066-23-20 00:31:47:", 0, "" },
+ { "1066-00-20 00:31:47:", 0, "" },
+ { "1066-0-20 00:31:47:", 0, "" },
+ { "1066-01-2 00:31:47:", 0, "" },
+ { "1066-01-2 00:31:47:", 0, "" },
+ { "1066-01-32 00:31:47:", 0, "" },
+ { "1066-01-00 00:31:47:", 0, "" },
+ { "1066-03-20 00:31:47:",11, "10660320T000000" },
+ { "1066-03-2000:31:47:", 0, "" },
+ { "10666-03-20 00:31:47:", 0, "" },
+ { NULL, 0 }
+ };
+ int idx;
+ size_t result;
+ gnupg_isotime_t tbuf;
+
+ for (idx=0; array[idx].string; idx++)
+ {
+ result = string2isotime (tbuf, array[idx].string);
+ if (result != array[idx].result)
+ {
+ fail (idx);
+ if (verbose)
+ fprintf (stderr, "string `%s' expected: %d, got: %d\n",
+ array[idx].string, (int)array[idx].result, (int)result);
+ }
+ else if (result && strlen (tbuf) != 15)
+ {
+ fail (idx);
+ if (verbose)
+ fprintf (stderr, "string `%s' invalid isotime returned\n",
+ array[idx].string);
+ }
+ else if (result && strcmp (array[idx].expected, tbuf))
+ {
+ fail (idx);
+ if (verbose)
+ fprintf (stderr, "string `%s' bad isotime '%s' returned\n",
+ array[idx].string, tbuf);
+ }
+ }
+}
+
int
main (int argc, char **argv)
@@ -97,6 +181,7 @@ main (int argc, char **argv)
verbose = 1;
test_isotime2epoch ();
+ test_string2isotime ();
return !!errcount;
}
diff --git a/common/tlv.c b/common/tlv.c
index 54ef6fca6..61f770e93 100644
--- a/common/tlv.c
+++ b/common/tlv.c
@@ -238,14 +238,14 @@ _parse_ber_header (unsigned char const **buffer, size_t *size,
is the pointer to the S-expression and BUFLEN is a pointer to the
length of this S-expression (used to validate the syntax). Both
are updated to reflect the new position. The token itself is
- returned as a pointer into the orginal buffer at TOK and TOKLEN.
+ returned as a pointer into the original buffer at TOK and TOKLEN.
If a parentheses is the next token, TOK will be set to NULL.
- TOKLEN is checked to be within the bounds. On error a error code
- is returned and all pointers should are not guaranteed to point to
- a meanigful value. DEPTH should be initialized to 0 and will
+ TOKLEN is checked to be within the bounds. On error an error code
+ is returned and no pointer is not guaranteed to point to
+ a meaningful value. DEPTH should be initialized to 0 and will
reflect on return the actual depth of the tree. To detect the end
of the S-expression it is advisable to check DEPTH after a
- successful return:
+ successful return.
depth = 0;
while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))
diff --git a/common/tlv.h b/common/tlv.h
index c7fafd547..fd57e1e90 100644
--- a/common/tlv.h
+++ b/common/tlv.h
@@ -90,15 +90,15 @@ gpg_error_t _parse_ber_header (unsigned char const **buffer, size_t *size,
GPG_ERR_SOURCE_DEFAULT)
-/* Return the next token of an canconical encoded S-expression. BUF
+/* Return the next token of an canonical encoded S-expression. BUF
is the pointer to the S-expression and BUFLEN is a pointer to the
length of this S-expression (used to validate the syntax). Both
are updated to reflect the new position. The token itself is
- returned as a pointer into the orginal buffer at TOK and TOKLEN.
+ returned as a pointer into the original buffer at TOK and TOKLEN.
If a parentheses is the next token, TOK will be set to NULL.
- TOKLEN is checked to be within the bounds. On error a error code
- is returned and all pointers should are not guaranteed to point to
- a meanigful value. DEPTH should be initialized to 0 and will
+ TOKLEN is checked to be within the bounds. On error an error code
+ is returned and no pointer is not guaranteed to point to
+ a meaningful value. DEPTH should be initialized to 0 and will
reflect on return the actual depth of the tree. To detect the end
of the S-expression it is advisable to check DEPTH after a
successful return. */