diff options
-rw-r--r-- | src/mm-modem-helpers.c | 96 | ||||
-rw-r--r-- | src/tests/test-modem-helpers.c | 7 |
2 files changed, 66 insertions, 37 deletions
diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c index d51f7782..bc6e48b4 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); diff --git a/src/tests/test-modem-helpers.c b/src/tests/test-modem-helpers.c index 0afa22fc..cd5ddfa1 100644 --- a/src/tests/test-modem-helpers.c +++ b/src/tests/test-modem-helpers.c @@ -2849,6 +2849,13 @@ typedef struct { } CclkTest; static const CclkTest cclk_tests[] = { + { "+CCLK: \"14/08/05,04:00:21\"", TRUE, TRUE, FALSE, + "2014-08-05T04:00:21+00:00", 0 }, + { "+CCLK: \"14/08/05,04:00:21\"", TRUE, FALSE, TRUE, + "2014-08-05T04:00:21+00:00", 0 }, + { "+CCLK: \"14/08/05,04:00:21\"", TRUE, TRUE, TRUE, + "2014-08-05T04:00:21+00:00", 0 }, + { "+CCLK: \"14/08/05,04:00:21+40\"", TRUE, TRUE, FALSE, "2014-08-05T04:00:21+10:00", 600 }, { "+CCLK: \"14/08/05,04:00:21+40\"", TRUE, FALSE, TRUE, |