From b9a9418b66d2d06e4023453c5a56dc8ea1e96677 Mon Sep 17 00:00:00 2001 From: Alexander Chemeris Date: Fri, 7 Mar 2014 21:03:44 +0100 Subject: sms: Fix gsm340_scts() to correctly decode absolute valid times. - Support negative timezone offsets decoding. - Correctly account timezone offset and artificial offset mktime() introduces. --- src/gsm/gsm0411_utils.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/gsm/gsm0411_utils.c b/src/gsm/gsm0411_utils.c index bb59a10d..197f2c3f 100644 --- a/src/gsm/gsm0411_utils.c +++ b/src/gsm/gsm0411_utils.c @@ -100,11 +100,13 @@ void gsm340_gen_scts(uint8_t *scts, time_t time) time_t gsm340_scts(uint8_t *scts) { struct tm tm; - uint8_t yr = gsm411_unbcdify(*scts++); + uint8_t yr, tz; int ofs; + time_t timestamp; memset(&tm, 0x00, sizeof(struct tm)); + yr = gsm411_unbcdify(*scts++); if (yr <= 80) tm.tm_year = 100 + yr; else @@ -114,15 +116,32 @@ time_t gsm340_scts(uint8_t *scts) tm.tm_hour = gsm411_unbcdify(*scts++); tm.tm_min = gsm411_unbcdify(*scts++); tm.tm_sec = gsm411_unbcdify(*scts++); -#ifdef HAVE_TM_GMTOFF_IN_TM - tm.tm_gmtoff = gsm411_unbcdify(*scts++) * 15*60; -#endif /* according to gsm 03.40 time zone is "expressed in quarters of an hour" */ - ofs = gsm411_unbcdify(*scts++) * 15*60; + tz = *scts++; + ofs = gsm411_unbcdify(tz&0x7f) * 15*60; + if (tz&0x80) + ofs = -ofs; + /* mktime() doesn't take tm.tm_gmtoff into account. Instead, it fills this + * field with the current timezone. Which means that the resulting time is + * off by several hours after that. So here we're setting tm.tm_isdt to -1 + * to indicate that the tm time is local, but later we subtract the + * offset introduced by mktime. */ + tm.tm_isdst = -1; + + timestamp = mktime(&tm); + if (timestamp < 0) + return -1; + + /* Take into account timezone offset */ + timestamp -= ofs; +#ifdef HAVE_TM_GMTOFF_IN_TM + /* Remove an artificial timezone offset, introduced by mktime() */ + timestamp += tm.tm_gmtoff; +#endif - return mktime(&tm) - ofs; + return timestamp; } /* Decode validity period format 'relative'. -- cgit v1.2.3