[AT]
authorEric Kohl <eric.kohl@reactos.org>
Fri, 14 Apr 2017 15:54:08 +0000 (15:54 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Fri, 14 Apr 2017 15:54:08 +0000 (15:54 +0000)
Improve the time parser to handle 12-hour and 24-hour formats correctly.

svn path=/trunk/; revision=74306

reactos/base/applications/cmdutils/at/at.c

index ded545b..22d3622 100644 (file)
@@ -77,31 +77,127 @@ ParseTime(
     PULONG pulJobHour,
     PULONG pulJobMinute)
 {
+    WCHAR szHour[3], szMinute[3], szAmPm[5];
     PWSTR startPtr, endPtr;
     ULONG ulHour = 0, ulMinute = 0;
-    BOOL bResult = FALSE;
+    INT nLength;
+
+    if (pszTime == NULL)
+        return FALSE;
 
     startPtr = pszTime;
-    endPtr = NULL;
-    ulHour = wcstoul(startPtr, &endPtr, 10);
-    if (ulHour < 24 && endPtr != NULL && *endPtr == L':')
+
+    /* Extract the hour string */
+    nLength = 0;
+    while (*startPtr != L'\0' && iswdigit(*startPtr))
     {
-        startPtr = endPtr + 1;
-        endPtr = NULL;
-        ulMinute = wcstoul(startPtr, &endPtr, 10);
-        if (ulMinute < 60 && endPtr != NULL && *endPtr == UNICODE_NULL)
+        if (nLength >= 2)
+            return FALSE;
+
+        szHour[nLength] = *startPtr;
+        nLength++;
+
+        startPtr++;
+    }
+    szHour[nLength] = L'\0';
+
+    /* Check for a valid time separator */
+    if (*startPtr != L':')
+        return FALSE;
+
+    /* Skip the time separator */
+    startPtr++;
+
+    /* Extract the minute string */
+    nLength = 0;
+    while (*startPtr != L'\0' && iswdigit(*startPtr))
+    {
+        if (nLength >= 2)
+            return FALSE;
+
+        szMinute[nLength] = *startPtr;
+        nLength++;
+
+        startPtr++;
+    }
+    szMinute[nLength] = L'\0';
+
+    /* Extract the optional AM/PM indicator string */
+    nLength = 0;
+    while (*startPtr != L'\0')
+    {
+        if (nLength >= 4)
+            return FALSE;
+
+        if (!iswspace(*startPtr))
         {
-            bResult = TRUE;
+            szAmPm[nLength] = *startPtr;
+            nLength++;
+        }
 
-            if (pulJobHour != NULL)
-                *pulJobHour = ulHour;
+        startPtr++;
+    }
+    szAmPm[nLength] = L'\0';
 
-            if (pulJobMinute != NULL)
-                *pulJobMinute = ulMinute;
+    /* Convert the hour string */
+    ulHour = wcstoul(szHour, &endPtr, 10);
+    if (ulHour == 0 && *endPtr != UNICODE_NULL)
+        return FALSE;
+
+    /* Convert the minute string */
+    ulMinute = wcstoul(szMinute, &endPtr, 10);
+    if (ulMinute == 0 && *endPtr != UNICODE_NULL)
+        return FALSE;
+
+    /* Check for valid AM/PM indicator */
+    if (wcslen(szAmPm) > 0 &&
+        _wcsicmp(szAmPm, L"a") != 0 &&
+        _wcsicmp(szAmPm, L"am") != 0 &&
+        _wcsicmp(szAmPm, L"p") != 0 &&
+        _wcsicmp(szAmPm, L"pm") != 0)
+        return FALSE;
+
+    /* Check for the valid minute range [0-59] */
+    if (ulMinute > 59)
+        return FALSE;
+
+    if (wcslen(szAmPm) > 0)
+    {
+        /* 12 hour time format */
+
+         /* Check for the valid hour range [1-12] */
+        if (ulHour == 0 || ulHour > 12)
+            return FALSE;
+
+        /* Convert 12 hour format to 24 hour format */
+        if (_wcsicmp(szAmPm, L"a") == 0 ||
+            _wcsicmp(szAmPm, L"am") == 0)
+        {
+            if (ulHour == 12)
+                ulHour = 0;
+        }
+        else
+        {
+            if (ulHour >= 1 && ulHour <= 11)
+                ulHour += 12;
         }
     }
+    else
+    {
+        /* 24 hour time format */
 
-    return bResult;
+        /* Check for the valid hour range [0-23] */
+        if (ulHour > 23)
+            return FALSE;
+    }
+
+    if (pulJobHour != NULL)
+        *pulJobHour = ulHour;
+
+    if (pulJobMinute != NULL)
+        *pulJobMinute = ulMinute;
+
+    return TRUE;
 }