diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2016-11-17 12:09:11 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2016-11-18 10:25:07 +0100 |
commit | 51e3d3d8372e615e9c9a62408638cd8a480f5a14 (patch) | |
tree | 25b05a8843d22e86b55c5be14791b83bde0050f1 /src/mm-modem-helpers.c | |
parent | 64b4afa960e7440505dfb1f18ca9c20506d7e16e (diff) | |
download | ModemManager-51e3d3d8372e615e9c9a62408638cd8a480f5a14.tar.gz |
modem-helpers: improve +CCLK parsing
Added support for 4-digit format years (i.e. YYYY), and also made the
timezone information optional, as per +CSDF in 3GPP TS 27.007.
https://bugs.freedesktop.org/show_bug.cgi?id=95319
Diffstat (limited to 'src/mm-modem-helpers.c')
-rw-r--r-- | src/mm-modem-helpers.c | 96 |
1 files changed, 59 insertions, 37 deletions
diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c index d51f7782a..bc6e48b49 100644 --- a/src/mm-modem-helpers.c +++ b/src/mm-modem-helpers.c @@ -3773,7 +3773,7 @@ mm_parse_cclk_response (const char *response, g_assert (iso8601p || tzp); /* at least one */ /* Sample reply: +CCLK: "15/03/05,14:14:26-32" */ - r = g_regex_new ("[+]CCLK: \"(\\d+)/(\\d+)/(\\d+),(\\d+):(\\d+):(\\d+)([-+]\\d+)\"", 0, 0, NULL); + r = g_regex_new ("[+]CCLK: \"(\\d+)/(\\d+)/(\\d+),(\\d+):(\\d+):(\\d+)([-+]\\d+)?\"", 0, 0, NULL); g_assert (r != NULL); if (!g_regex_match_full (r, response, -1, 0, 0, &match_info, &match_error)) { @@ -3781,47 +3781,69 @@ mm_parse_cclk_response (const char *response, g_propagate_error (error, match_error); g_prefix_error (error, "Could not parse +CCLK results: "); } else { - g_set_error_literal (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't match +CCLK reply"); + g_set_error (error, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Couldn't match +CCLK reply: %s", response); } - } else { - /* Remember that g_match_info_get_match_count() includes match #0 */ - g_assert (g_match_info_get_match_count (match_info) >= 8); - - if (mm_get_uint_from_match_info (match_info, 1, &year) && - mm_get_uint_from_match_info (match_info, 2, &month) && - mm_get_uint_from_match_info (match_info, 3, &day) && - mm_get_uint_from_match_info (match_info, 4, &hour) && - mm_get_uint_from_match_info (match_info, 5, &minute) && - mm_get_uint_from_match_info (match_info, 6, &second) && - mm_get_int_from_match_info (match_info, 7, &tz)) { - /* adjust year */ + goto out; + } + + /* Remember that g_match_info_get_match_count() includes match #0 */ + g_assert (g_match_info_get_match_count (match_info) >= 7); + + /* Parse mandatory date and time fields */ + if (!mm_get_uint_from_match_info (match_info, 1, &year) || + !mm_get_uint_from_match_info (match_info, 2, &month) || + !mm_get_uint_from_match_info (match_info, 3, &day) || + !mm_get_uint_from_match_info (match_info, 4, &hour) || + !mm_get_uint_from_match_info (match_info, 5, &minute) || + !mm_get_uint_from_match_info (match_info, 6, &second)) { + g_set_error (error, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Failed to parse +CCLK reply: %s", response); + goto out; + } + + /* Read optional time zone offset; if not given assume UTC (tz = 0). + * Note that timezone offset is given in 15 minute intervals. + */ + if ((g_match_info_get_match_count (match_info) >= 8) && + (!mm_get_int_from_match_info (match_info, 7, &tz))) { + g_set_error (error, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Failed to parse timezone in +CCLK reply: %s", response); + goto out; + } + + /* Adjust year to support YYYY format, as per +CSDF in 3GPP TS 27.007. Also, + * don't assume the reported date is actually the current real one, as some + * devices report an initial date of e.g. January 1st 1980. */ + if (year < 100) { + if (year >= 70) + year += 1900; + else year += 2000; - /* - * tz = timezone offset in 15 minute intervals - */ - if (iso8601p) { - /* Return ISO-8601 format date/time string */ - *iso8601p = mm_new_iso8601_time (year, month, day, hour, - minute, second, - TRUE, (tz * 15)); - } - if (tzp) { - *tzp = mm_network_timezone_new (); - mm_network_timezone_set_offset (*tzp, tz * 15); - } + } - ret = TRUE; - } else { - g_set_error_literal (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Failed to parse +CCLK reply"); - } + if (tzp) { + *tzp = mm_network_timezone_new (); + mm_network_timezone_set_offset (*tzp, tz * 15); + } + + if (iso8601p) { + /* Return ISO-8601 format date/time string */ + *iso8601p = mm_new_iso8601_time (year, month, day, hour, + minute, second, + TRUE, (tz * 15)); } + ret = TRUE; + + out: + if (match_info) g_match_info_free (match_info); g_regex_unref (r); |