diff --git a/format/desktop_entry/scan.ha b/format/desktop_entry/scan.ha index 0347d1a..38ae90b 100644 --- a/format/desktop_entry/scan.ha +++ b/format/desktop_entry/scan.ha @@ -1,3 +1,4 @@ +use ascii; use bufio; use encoding::utf8; use errors; @@ -30,7 +31,7 @@ export fn next(this: *scanner) (line | io::EOF | error) = { case io::EOF => return io::EOF; }; - + if (text == "") { // blank line return blank; @@ -43,7 +44,7 @@ export fn next(this: *scanner) (line | io::EOF | error) = { // group header let header = parse_group_header(text)?; free(this.group); - this.group = header: str; + this.group = strings::dup(header: str); return header; } else { @@ -89,21 +90,21 @@ fn parse_entry(line: str) (entry | error) = { if (!strings::contains(line, '=')) return invalid_entry; let (key, valu) = strings::cut(line, "="); key = strings::ltrim(strings::rtrim(key)); - if (!validate_entry_key(key)) return invalid_entry; let (key, local_string) = strings::cut(key, "["); - let local = if (local_string != "") { + let local = if (local_string == "") { yield locale::c; } else { local_string = strings::rtrim(local_string, ']'); - if (!validate_entry_locale(local_string)) return invalid_entry; - + validate_entry_locale(local_string)?; + yield match(locale::parse(local_string)) { case let local: locale::locale => yield local; case locale::invalid => return invalid_entry; }; }; + validate_entry_key(key)?; return entry { key = key, value = valu, @@ -112,10 +113,24 @@ fn parse_entry(line: str) (entry | error) = { }; }; -fn validate_entry_key(key: str) bool = { - return strings::contains(key, '[', ']', '='); +fn validate_entry_key(key: str) (void | error) = { + for (let byte .. strings::toutf8(key)) { + const ok = + (byte >= 'A' && byte <= 'Z') || + (byte >= 'a' && byte <= 'z') || + (byte >= '0' && byte <= '9') || + (byte == '-'); + if (!ok) return invalid_entry; + }; }; -fn validate_entry_locale(key: str) bool = { - return strings::contains(key, '[', ']', '='); +fn validate_entry_locale(locale: str) (void | error) = { + for (let byte .. strings::toutf8(locale)) { + const bad = + (byte == '[') || + (byte == ']') || + (byte == '=') || + !ascii::isprint(byte: rune); + if (bad) return invalid_entry; + }; };