// HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT const char* parse_http_version(unsigned char** p) { const unsigned char STR_HTTP[] = "HTTP/"; unsigned char* ptmp = *p; if(parse_string(p, STR_HTTP, sizeof(STR_HTTP)-1, 1)) return (char*)ERR; int failed = 0; if(parse_digits(p)) failed = 1; if(!failed && parse_char(p, '.')) failed = 1; if(!failed && parse_digits(p)) failed = 1; if(failed) { *p = ptmp; return ERR; } return NULL; }
long parse_time(const char* time) { if (*time != 0) return parse_digits(time, 2) * 3600 + parse_digits(time + 2, 2) * 60 + parse_digits(time + 4, 2); return 0; }
/*! * \brief Parse time of day string. * * Parses a string of the format hour ':' minute ':' second. * * \param str Pointer to the time string. * \param hour Points to the variable that will receive the hour (0..23). * \param min Points to the variable that will receive the minute (0..59). * \param sec Points to the variable that will receive the second (0..59). * * \return Pointer into the string after the parsed characters. */ char *TimeParseHms(const char *str, int *hour, int *min, int *sec) { str = parse_digits(str, hour); if (*str == ':') { str = parse_digits(str + 1, min); if (*str == ':') { str = parse_digits(str + 1, sec); } else { *sec = 0; } } else { *min = 0; } return (char *)str; }
/*! * \brief Parse string containing the year. * * Works with years including and excluding the century. If the * resulting value is lower than 70, the 21st century is assumed. * Values * * \param str Pointer to the time string. * \param year Points to the variable that will receive the years since 1900. * * \return Pointer into the string after the parsed characters. */ char *TimeParseYear(const char *str, int *year) { str = parse_digits(str, year); if (*year < 70) { *year += 100; } else if (*year > 1900) { *year -= 1900; } return (char *)str; }
/* Parse an IPv4 subnet, formatted like "192.168.0.0/24". If successful, * advance the pointer by the number of chars parsed, write the subnet * info to *out, and return 0. Otherwise, return a negative. */ static int parse_ipv4_subnet(const char **s, struct ipv4_subnet *out) { int i; int mask_len; u8 *ip_bytes = (u8 *)&out->ip; /* Get IP address part. */ for (i = 0; i < 4; i++) { const int value = parse_digits(s, 10, 3); if (value < 0 || value > 255) return -EINVAL; ip_bytes[i] = value; /* Every octet but the last ends with '.' */ if (i < 3 && *(*s)++ != '.') return -EINVAL; } /* Parse /N from the end, or assume 32. */ if (**s == '/') { (*s)++; mask_len = parse_digits(s, 10, 2); } else { mask_len = 32; } /* Convert mask length into a mask: 11111...000 */ if (mask_len == 0) { out->mask = 0; } else if (1 <= mask_len && mask_len <= 32) { out->mask = cpu_to_be32(~0 << (32 - mask_len)); } else { return -EINVAL; } /* Drop redundant bits from ip part. */ out->ip &= out->mask; return 0; }
/*! * \brief Parse date string. * * Parses a string of the format day 'x' month-name 'x' year, where * 'x' is any non-alphanumeric character. * * \param str Pointer to the date string. * \param mday Points to the variable that will receive the day (1..31). * \param mon Points to the variable that will receive the month (0..11). * \param year Points to the variable that will receive the years since 1900. * * \return Pointer into the string after the parsed characters. */ char *TimeParseDmy(const char *str, int *mday, int *mon, int *year) { str = parse_digits(str, mday); while (*str && !isalpha((unsigned char)*str)) { str++; } str = TimeParseMonth(str, mon); while (*str && !isdigit((unsigned char)*str)) { str++; } str = TimeParseYear(str, year); return (char *)str; }
/*! * \brief Parse RFC date and time string. * * This routine accepts RFC 850, RFC 1123 and asctime time formats. * * \param str Pointer to the date and time string. * * \return Number of seconds since epoch or -1 in case of any error. */ time_t RfcTimeParse(CONST char *str) { struct _tm dts = { 0, 0, 0, 1, 0, 0, 0, 0, 0 }; /* Skip leading whitespace. */ str = skip_spaces(str); /* Skip weekday, optional in RFC 822. */ if (isalpha((unsigned char)*str)) { while (*str && *str != ' ' && *str != '\t') str++; str = skip_spaces(str); } if (isalpha((unsigned char)*str)) { /* asctime format 'Fri Feb 2 2007 07:30:05'. */ str = TimeParseMonth(str, &dts.tm_mon); str = skip_spaces(str); str = parse_digits(str, &dts.tm_mday); str = skip_spaces(str); str = TimeParseYear(str, &dts.tm_year); str = skip_spaces(str); str = TimeParseHms(str, &dts.tm_hour, &dts.tm_min, &dts.tm_sec); } else if (*str) { /* RFC 850 'Friday, 02-Feb-2007 07:30:05 GMT'. */ /* RFC 1123 'Fri, 02 Feb 2007 07:30:05 GMT'. */ str = TimeParseDmy(str, &dts.tm_mday, &dts.tm_mon, &dts.tm_year); str = skip_spaces(str); str = TimeParseHms(str, &dts.tm_hour, &dts.tm_min, &dts.tm_sec); } str = skip_spaces(str); if ( (strcmp(str, "GMT") == 0) || (strcmp(str, "UTC") == 0) ) { return mktime(&dts); } return _mkgmtime(&dts); }
/* Parse a 64-bit IPv6 prefix to an array of 8 bytes. * Input should be formatted like "aaaa:bbbb:cccc:dddd\n". * Return 0 if successful, negative on error. */ static int parse_ipv6_prefix64(const char *in, __be16 *out) { int i; /* Get four 16-bit chunks. */ for (i = 0; i < 4; i++) { /* Consume one chunk, abort on failure. */ const int value = parse_digits(&in, 16, 4); if (value < 0) return -EINVAL; out[i] = cpu_to_be16(value); /* Every chunk but the last ends with a : */ if (i < 3 && *in++ != ':') return -EINVAL; } /* Only whitespace is allowed at the end. */ for (; *in != '\0'; in++) if (!isspace(*in)) return -EINVAL; return 0; }