+bool
+fw3_parse_date(void *ptr, const char *val)
+{
+ unsigned int year = 1970, mon = 1, day = 1, hour = 0, min = 0, sec = 0;
+ struct tm tm = { 0 };
+ char *p;
+
+ year = strtoul(val, &p, 10);
+ if ((*p != '-' && *p) || year < 1970 || year > 2038)
+ goto fail;
+ else if (!*p)
+ goto ret;
+
+ mon = strtoul(++p, &p, 10);
+ if ((*p != '-' && *p) || mon > 12)
+ goto fail;
+ else if (!*p)
+ goto ret;
+
+ day = strtoul(++p, &p, 10);
+ if ((*p != 'T' && *p) || day > 31)
+ goto fail;
+ else if (!*p)
+ goto ret;
+
+ hour = strtoul(++p, &p, 10);
+ if ((*p != ':' && *p) || hour > 23)
+ goto fail;
+ else if (!*p)
+ goto ret;
+
+ min = strtoul(++p, &p, 10);
+ if ((*p != ':' && *p) || min > 59)
+ goto fail;
+ else if (!*p)
+ goto ret;
+
+ sec = strtoul(++p, &p, 10);
+ if (*p || sec > 59)
+ goto fail;
+
+ret:
+ tm.tm_year = year - 1900;
+ tm.tm_mon = mon - 1;
+ tm.tm_mday = day;
+ tm.tm_hour = hour;
+ tm.tm_min = min;
+ tm.tm_sec = sec;
+
+ if (mktime(&tm) >= 0)
+ {
+ *((struct tm *)ptr) = tm;
+ return true;
+ }
+
+fail:
+ return false;
+}
+
+bool
+fw3_parse_time(void *ptr, const char *val)
+{
+ unsigned int hour = 0, min = 0, sec = 0;
+ char *p;
+
+ hour = strtoul(val, &p, 10);
+ if (*p != ':' || hour > 23)
+ goto fail;
+
+ min = strtoul(++p, &p, 10);
+ if ((*p != ':' && *p) || min > 59)
+ goto fail;
+ else if (!*p)
+ goto ret;
+
+ sec = strtoul(++p, &p, 10);
+ if (*p || sec > 59)
+ goto fail;
+
+ret:
+ *((int *)ptr) = 60 * 60 * hour + 60 * min + sec;
+ return true;
+
+fail:
+ return false;
+}
+
+bool
+fw3_parse_weekdays(void *ptr, const char *val)
+{
+ unsigned int w;
+ char *p;
+
+ if (*val == '!')
+ {
+ setbit(*(uint8_t *)ptr, 0);
+ while (isspace(*++val));
+ }
+
+ for (p = strtok((char *)val, " \t"); p; p = strtok(NULL, " \t"))
+ {
+ if (!strncasecmp(p, "monday", strlen(p)))
+ w = 1;
+ else if (!strncasecmp(p, "tuesday", strlen(p)))
+ w = 2;
+ else if (!strncasecmp(p, "wednesday", strlen(p)))
+ w = 3;
+ else if (!strncasecmp(p, "thursday", strlen(p)))
+ w = 4;
+ else if (!strncasecmp(p, "friday", strlen(p)))
+ w = 5;
+ else if (!strncasecmp(p, "saturday", strlen(p)))
+ w = 6;
+ else if (!strncasecmp(p, "sunday", strlen(p)))
+ w = 7;
+ else
+ {
+ w = strtoul(p, &p, 10);
+
+ if (*p || w < 1 || w > 7)
+ return false;
+ }
+
+ setbit(*(uint8_t *)ptr, w);
+ }
+
+ return true;
+}
+
+bool
+fw3_parse_monthdays(void *ptr, const char *val)
+{
+ unsigned int d;
+ char *p;
+
+ if (*val == '!')
+ {
+ setbit(*(uint32_t *)ptr, 0);
+ while (isspace(*++val));
+ }
+
+ for (p = strtok((char *)val, " \t"); p; p = strtok(NULL, " \t"))
+ {
+ d = strtoul(p, &p, 10);
+
+ if (*p || d < 1 || d > 31)
+ return false;
+
+ setbit(*(uint32_t *)ptr, d);
+ }
+
+ return true;
+}
+