]> git.ipfire.org Git - thirdparty/wireguard-apple.git/commitdiff
Highlighter: use original file from contrib/examples/highlighter
authorJason A. Donenfeld <Jason@zx2c4.com>
Mon, 7 Jan 2019 17:02:23 +0000 (12:02 -0500)
committerRoopesh Chander <roop@roopc.net>
Mon, 14 Jan 2019 09:22:34 +0000 (14:52 +0530)
This makes it easier to track updates and make diffs. Also, disable
things we don't support in the NetworkExtension app.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
WireGuard/WireGuard/UI/macOS/highlighter.c
WireGuard/WireGuard/UI/macOS/highlighter.h

index 6edf57586ce1619f36425af17c1dcff15d2026af..cc4a74af63d2c65294f02fccf7d0d1314ae0b8e6 100644 (file)
 #include "highlighter.h"
 
 typedef struct {
-    const char *s;
-    size_t len;
+       const char *s;
+       size_t len;
 } string_span_t;
 
 static bool is_valid_key(string_span_t s)
 {
-    if (s.len != 44 || s.s[43] != '=')
-        return false;
-    
-    for (size_t i = 0; i < 43; ++i) {
-        if (!((s.s[i] >= '/' && s.s[i] <= '9') ||
-              (s.s[i] >= 'A' && s.s[i] <= 'Z') ||
-              (s.s[i] >= 'a' && s.s[i] <= 'z') ||
-              s.s[i] == '+'))
-            return false;
-    }
-    return true;
+       if (s.len != 44 || s.s[43] != '=')
+               return false;
+
+       for (size_t i = 0; i < 43; ++i) {
+               if (!((s.s[i] >= '/' && s.s[i] <= '9') ||
+                     (s.s[i] >= 'A' && s.s[i] <= 'Z') ||
+                     (s.s[i] >= 'a' && s.s[i] <= 'z') ||
+                     s.s[i] == '+'))
+                       return false;
+       }
+       return true;
 }
 
 static bool is_valid_hostname(string_span_t s)
 {
-    size_t num_digit = 0, num_entity = s.len;
-    
-    if (s.len > 63 || !s.len)
-        return false;
-    if (s.s[0] == '-' || s.s[s.len - 1] == '-')
-        return false;
-    if (s.s[0] == '.' || s.s[s.len - 1] == '.')
-        return false;
-    
-    for (size_t i = 0; i < s.len; ++i) {
-        if (isdigit(s.s[i])) {
-            ++num_digit;
-            continue;
-        }
-        if (s.s[i] == '.') {
-            --num_entity;
-            continue;
-        }
-        
-        if (!((s.s[i] >= 'A' && s.s[i] <= 'Z') ||
-              (s.s[i] >= 'a' && s.s[i] <= 'z') ||
-              s.s[i] == '-'))
-            return false;
-        
-        if (i && s.s[i] == '.' && s.s[i - 1] == '.')
-            return false;
-    }
-    return num_digit != num_entity;
+       size_t num_digit = 0, num_entity = s.len;
+
+       if (s.len > 63 || !s.len)
+               return false;
+       if (s.s[0] == '-' || s.s[s.len - 1] == '-')
+               return false;
+       if (s.s[0] == '.' || s.s[s.len - 1] == '.')
+               return false;
+
+       for (size_t i = 0; i < s.len; ++i) {
+               if (isdigit(s.s[i])) {
+                       ++num_digit;
+                       continue;
+               }
+               if (s.s[i] == '.') {
+                       --num_entity;
+                       continue;
+               }
+
+               if (!((s.s[i] >= 'A' && s.s[i] <= 'Z') ||
+                     (s.s[i] >= 'a' && s.s[i] <= 'z') ||
+                     s.s[i] == '-'))
+                       return false;
+
+               if (i && s.s[i] == '.' && s.s[i - 1] == '.')
+                       return false;
+       }
+       return num_digit != num_entity;
 }
 
 static bool is_valid_ipv4(string_span_t s)
 {
-    for (size_t j, i = 0, pos = 0; i < 4 && pos < s.len; ++i) {
-        uint32_t val = 0;
-        
-        for (j = 0; j < 3 && pos + j < s.len && isdigit(s.s[pos + j]); ++j)
-            val = 10 * val + s.s[pos + j] - '0';
-        if (j == 0 || (j > 1 && s.s[pos] == '0') || val > 255)
-            return false;
-        if (pos + j == s.len && i == 3)
-            return true;
-        if (s.s[pos + j] != '.')
-            return false;
-        pos += j + 1;
-    }
-    return false;
+       for (size_t j, i = 0, pos = 0; i < 4 && pos < s.len; ++i) {
+               uint32_t val = 0;
+
+               for (j = 0; j < 3 && pos + j < s.len && isdigit(s.s[pos + j]); ++j)
+                       val = 10 * val + s.s[pos + j] - '0';
+               if (j == 0 || (j > 1 && s.s[pos] == '0') || val > 255)
+                       return false;
+               if (pos + j == s.len && i == 3)
+                       return true;
+               if (s.s[pos + j] != '.')
+                       return false;
+               pos += j + 1;
+       }
+       return false;
 }
 
 static bool is_valid_ipv6(string_span_t s)
 {
-    size_t pos = 0;
-    bool seen_colon = false;
-    
-    if (s.len < 2)
-        return false;
-    if (s.s[pos] == ':' && s.s[++pos] != ':')
-        return false;
-    if (s.s[s.len - 1] == ':' && s.s[s.len - 2] != ':')
-        return false;
-    
-    for (size_t j, i = 0; pos < s.len; ++i) {
-        if (s.s[pos] == ':' && !seen_colon) {
-            seen_colon = true;
-            if (++pos == s.len)
-                break;
-            if (i == 7)
-                return false;
-            continue;
-        }
-        for (j = 0; j < 4 && pos + j < s.len && isxdigit(s.s[pos + j]); ++j);
-        if (j == 0)
-            return false;
-        if (pos + j == s.len && (seen_colon || i == 7))
-            break;
-        if (i == 7)
-            return false;
-        if (s.s[pos + j] != ':') {
-            if (s.s[pos + j] != '.' || (i < 6 && !seen_colon))
-                return false;
-            return is_valid_ipv4((string_span_t){ s.s + pos, s.len - pos });
-        }
-        pos += j + 1;
-    }
-    return true;
+       size_t pos = 0;
+       bool seen_colon = false;
+
+       if (s.len < 2)
+               return false;
+       if (s.s[pos] == ':' && s.s[++pos] != ':')
+               return false;
+       if (s.s[s.len - 1] == ':' && s.s[s.len - 2] != ':')
+               return false;
+
+       for (size_t j, i = 0; pos < s.len; ++i) {
+               if (s.s[pos] == ':' && !seen_colon) {
+                       seen_colon = true;
+                       if (++pos == s.len)
+                               break;
+                       if (i == 7)
+                               return false;
+                       continue;
+               }
+               for (j = 0; j < 4 && pos + j < s.len && isxdigit(s.s[pos + j]); ++j);
+               if (j == 0)
+                       return false;
+               if (pos + j == s.len && (seen_colon || i == 7))
+                       break;
+               if (i == 7)
+                       return false;
+               if (s.s[pos + j] != ':') {
+                       if (s.s[pos + j] != '.' || (i < 6 && !seen_colon))
+                               return false;
+                       return is_valid_ipv4((string_span_t){ s.s + pos, s.len - pos });
+               }
+               pos += j + 1;
+       }
+       return true;
 }
 
 static bool is_valid_u16(string_span_t s)
 {
-    uint32_t val = 0;
-    
-    if (s.len > 5 || !s.len)
-        return false;
-    
-    for (size_t i = 0; i < s.len; ++i) {
-        if (!isdigit(s.s[i]))
-            return false;
-        val = 10 * val + s.s[i] - '0';
-    }
-    return val <= 65535;
+       uint32_t val = 0;
+
+       if (s.len > 5 || !s.len)
+               return false;
+
+       for (size_t i = 0; i < s.len; ++i) {
+               if (!isdigit(s.s[i]))
+                       return false;
+               val = 10 * val + s.s[i] - '0';
+       }
+       return val <= 65535;
 }
 
 static bool is_valid_port(string_span_t s)
 {
-    return is_valid_u16(s);
+       return is_valid_u16(s);
 }
 
 static bool is_valid_mtu(string_span_t s)
 {
-    return is_valid_u16(s);
+       return is_valid_u16(s);
 }
 
 static bool is_valid_persistentkeepalive(string_span_t s)
 {
-    if (s.len == 3 && !memcmp(s.s, "off", 3))
-        return true;
-    return is_valid_u16(s);
+       if (s.len == 3 && !memcmp(s.s, "off", 3))
+               return true;
+       return is_valid_u16(s);
 }
 
+#ifndef MOBILE_WGQUICK_SUBSET
 static bool is_valid_u32(string_span_t s)
 {
-    uint64_t val = 0;
-    
-    if (s.len > 10 || !s.len)
-        return false;
-    
-    if (s.len > 2 && s.s[0] == '0' && s.s[1] == 'x') {
-        for (size_t i = 2; i < s.len; ++i) {
-            if (s.s[i] - '0' < 10)
-                val = 16 * val + (s.s[i] - '0');
-            else if ((s.s[i] | 32) - 'a' < 6)
-                val = 16 * val + (s.s[i] | 32) - 'a' + 10;
-            else
-                return false;
-        }
-    } else {
-        for (size_t i = 0; i < s.len; ++i) {
-            if (!isdigit(s.s[i]))
-                return false;
-            val = 10 * val + s.s[i] - '0';
-        }
-    }
-    return val <= 4294967295U;
+       uint64_t val = 0;
+
+       if (s.len > 10 || !s.len)
+               return false;
+
+       if (s.len > 2 && s.s[0] == '0' && s.s[1] == 'x') {
+               for (size_t i = 2; i < s.len; ++i) {
+                       if (s.s[i] - '0' < 10)
+                               val = 16 * val + (s.s[i] - '0');
+                       else if ((s.s[i] | 32) - 'a' < 6)
+                               val = 16 * val + (s.s[i] | 32) - 'a' + 10;
+                       else
+                               return false;
+               }
+       } else {
+               for (size_t i = 0; i < s.len; ++i) {
+                       if (!isdigit(s.s[i]))
+                               return false;
+                       val = 10 * val + s.s[i] - '0';
+               }
+       }
+       return val <= 4294967295U;
 }
 
 static bool is_valid_fwmark(string_span_t s)
 {
-    if (s.len == 3 && !memcmp(s.s, "off", 3))
-        return true;
-    return is_valid_u32(s);
+       if (s.len == 3 && !memcmp(s.s, "off", 3))
+               return true;
+       return is_valid_u32(s);
 }
 
 static bool is_valid_table(string_span_t s)
 {
-    if (s.len == 4 && !memcmp(s.s, "auto", 3))
-        return true;
-    if (s.len == 3 && !memcmp(s.s, "off", 3))
-        return true;
-    /* This pretty much invalidates the other checks, but rt_names.c's
-     * fread_id_name does no validation aside from this. */
-    if (s.len < 512)
-        return true;
-    return is_valid_u32(s);
+       if (s.len == 4 && !memcmp(s.s, "auto", 3))
+               return true;
+       if (s.len == 3 && !memcmp(s.s, "off", 3))
+               return true;
+       /* This pretty much invalidates the other checks, but rt_names.c's
+        * fread_id_name does no validation aside from this. */
+       if (s.len < 512)
+               return true;
+       return is_valid_u32(s);
 }
 
 static bool is_valid_saveconfig(string_span_t s)
 {
-    return (s.len == 4 && !memcmp(s.s, "true", 4)) ||
-    (s.len == 5 && !memcmp(s.s, "false", 5));
+       return (s.len == 4 && !memcmp(s.s, "true", 4)) ||
+              (s.len == 5 && !memcmp(s.s, "false", 5));
+}
+
+static bool is_valid_prepostupdown(string_span_t s)
+{
+       /* It's probably not worthwhile to try to validate a bash expression.
+        * So instead we just demand non-zero length. */
+       return s.len;
 }
+#endif
 
 static bool is_valid_scope(string_span_t s)
 {
-    if (s.len > 64 || !s.len)
-        return false;
-    for (size_t i = 0; i < s.len; ++i) {
-        if (!((s.s[i] >= 'A' && s.s[i] <= 'Z') ||
-              (s.s[i] >= 'a' && s.s[i] <= 'z') ||
-              isdigit(s.s[i]) || s.s[i] == '_' ||
-              s.s[i] == '=' || s.s[i] == '+' ||
-              s.s[i] == '.' || s.s[i] == '-'))
-            return false;
-    }
-    return true;
+       if (s.len > 64 || !s.len)
+               return false;
+       for (size_t i = 0; i < s.len; ++i) {
+               if (!((s.s[i] >= 'A' && s.s[i] <= 'Z') ||
+                     (s.s[i] >= 'a' && s.s[i] <= 'z') ||
+                     isdigit(s.s[i]) || s.s[i] == '_' ||
+                     s.s[i] == '=' || s.s[i] == '+' ||
+                     s.s[i] == '.' || s.s[i] == '-'))
+                       return false;
+       }
+       return true;
 }
 
 static bool is_valid_endpoint(string_span_t s)
 {
-    
-    if (!s.len)
-        return false;
-    
-    if (s.s[0] == '[') {
-        bool seen_scope = false;
-        string_span_t hostspan = { s.s + 1, 0 };
-        
-        for (size_t i = 1; i < s.len; ++i) {
-            if (s.s[i] == '%') {
-                if (seen_scope)
-                    return false;
-                seen_scope = true;
-                if (!is_valid_ipv6(hostspan))
-                    return false;
-                hostspan = (string_span_t){ s.s + i + 1, 0 };
-            } else if (s.s[i] == ']') {
-                if (seen_scope) {
-                    if (!is_valid_scope(hostspan))
-                        return false;
-                } else if (!is_valid_ipv6(hostspan)) {
-                    return false;
-                }
-                if (i == s.len - 1 || s.s[i + 1] != ':')
-                    return false;
-                return is_valid_port((string_span_t){ s.s + i + 2, s.len - i - 2 });
-            } else {
-                ++hostspan.len;
-            }
-        }
-        return false;
-    }
-    for (size_t i = 0; i < s.len; ++i) {
-        if (s.s[i] == ':') {
-            string_span_t host = { s.s, i }, port = { s.s + i + 1, s.len - i - 1};
-            return is_valid_port(port) && (is_valid_ipv4(host) || is_valid_hostname(host));
-        }
-    }
-    return false;
+
+       if (!s.len)
+               return false;
+
+       if (s.s[0] == '[') {
+               bool seen_scope = false;
+               string_span_t hostspan = { s.s + 1, 0 };
+
+               for (size_t i = 1; i < s.len; ++i) {
+                       if (s.s[i] == '%') {
+                               if (seen_scope)
+                                       return false;
+                               seen_scope = true;
+                               if (!is_valid_ipv6(hostspan))
+                                       return false;
+                               hostspan = (string_span_t){ s.s + i + 1, 0 };
+                       } else if (s.s[i] == ']') {
+                               if (seen_scope) {
+                                       if (!is_valid_scope(hostspan))
+                                               return false;
+                               } else if (!is_valid_ipv6(hostspan)) {
+                                       return false;
+                               }
+                               if (i == s.len - 1 || s.s[i + 1] != ':')
+                                       return false;
+                               return is_valid_port((string_span_t){ s.s + i + 2, s.len - i - 2 });
+                       } else {
+                               ++hostspan.len;
+                       }
+               }
+               return false;
+       }
+       for (size_t i = 0; i < s.len; ++i) {
+               if (s.s[i] == ':') {
+                       string_span_t host = { s.s, i }, port = { s.s + i + 1, s.len - i - 1};
+                       return is_valid_port(port) && (is_valid_ipv4(host) || is_valid_hostname(host));
+               }
+       }
+       return false;
 }
 
 static bool is_valid_network(string_span_t s)
 {
-    for (size_t i = 0; i < s.len; ++i) {
-        if (s.s[i] == '/') {
-            string_span_t ip = { s.s, i }, cidr = { s.s + i + 1, s.len - i - 1};
-            uint16_t cidrval = 0;
-            
-            if (cidr.len > 3 || !cidr.len)
-                return false;
-            
-            for (size_t j = 0; j < cidr.len; ++j) {
-                if (!isdigit(cidr.s[j]))
-                    return false;
-                cidrval = 10 * cidrval + cidr.s[j] - '0';
-            }
-            if (is_valid_ipv4(ip))
-                return cidrval <= 32;
-            else if (is_valid_ipv6(ip))
-                return cidrval <= 128;
-            return false;
-        }
-    }
-    return is_valid_ipv4(s) || is_valid_ipv6(s);
-}
+       for (size_t i = 0; i < s.len; ++i) {
+               if (s.s[i] == '/') {
+                       string_span_t ip = { s.s, i }, cidr = { s.s + i + 1, s.len - i - 1};
+                       uint16_t cidrval = 0;
 
-static bool is_valid_dns(string_span_t s)
-{
-    return is_valid_ipv4(s) || is_valid_ipv6(s);
+                       if (cidr.len > 3 || !cidr.len)
+                               return false;
+
+                       for (size_t j = 0; j < cidr.len; ++j) {
+                               if (!isdigit(cidr.s[j]))
+                                       return false;
+                               cidrval = 10 * cidrval + cidr.s[j] - '0';
+                       }
+                       if (is_valid_ipv4(ip))
+                               return cidrval <= 32;
+                       else if (is_valid_ipv6(ip))
+                               return cidrval <= 128;
+                       return false;
+               }
+       }
+       return is_valid_ipv4(s) || is_valid_ipv6(s);
 }
 
-static bool is_valid_prepostupdown(string_span_t s)
+static bool is_valid_dns(string_span_t s)
 {
-    /* It's probably not worthwhile to try to validate a bash expression.
-     * So instead we just demand non-zero length. */
-    return s.len;
+       return is_valid_ipv4(s) || is_valid_ipv6(s);
 }
 
 enum keytype {
-    InterfaceSection,
-    PrivateKey,
-    ListenPort,
-    FwMark,
-    Address,
-    DNS,
-    MTU,
-    Table,
-    PreUp, PostUp, PreDown, PostDown,
-    SaveConfig,
-    
-    PeerSection,
-    PublicKey,
-    PresharedKey,
-    AllowedIPs,
-    Endpoint,
-    PersistentKeepalive,
-    
-    Invalid
+       InterfaceSection,
+       PrivateKey,
+       ListenPort,
+       Address,
+       DNS,
+       MTU,
+#ifndef MOBILE_WGQUICK_SUBSET
+       FwMark,
+       Table,
+       PreUp, PostUp, PreDown, PostDown,
+       SaveConfig,
+#endif
+
+       PeerSection,
+       PublicKey,
+       PresharedKey,
+       AllowedIPs,
+       Endpoint,
+       PersistentKeepalive,
+
+       Invalid
 };
 
 static enum keytype section_for_keytype(enum keytype t)
 {
-    if (t > InterfaceSection && t < PeerSection)
-        return InterfaceSection;
-    if (t > PeerSection && t < Invalid)
-        return PeerSection;
-    return Invalid;
+       if (t > InterfaceSection && t < PeerSection)
+               return InterfaceSection;
+       if (t > PeerSection && t < Invalid)
+               return PeerSection;
+       return Invalid;
 }
 
 static enum keytype get_keytype(string_span_t s)
 {
 #define check_enum(t) do { if (s.len == strlen(#t) && !strncasecmp(#t, s.s, s.len)) return t; } while (0)
-    check_enum(PrivateKey);
-    check_enum(ListenPort);
-    check_enum(FwMark);
-    check_enum(Address);
-    check_enum(DNS);
-    check_enum(MTU);
-    check_enum(Table);
-    check_enum(PreUp);
-    check_enum(PostUp);
-    check_enum(PreDown);
-    check_enum(PostDown);
-    check_enum(PublicKey);
-    check_enum(PresharedKey);
-    check_enum(AllowedIPs);
-    check_enum(Endpoint);
-    check_enum(PersistentKeepalive);
-    check_enum(SaveConfig);
-    return Invalid;
+       check_enum(PrivateKey);
+       check_enum(ListenPort);
+       check_enum(Address);
+       check_enum(DNS);
+       check_enum(MTU);
+       check_enum(PublicKey);
+       check_enum(PresharedKey);
+       check_enum(AllowedIPs);
+       check_enum(Endpoint);
+       check_enum(PersistentKeepalive);
+#ifndef MOBILE_WGQUICK_SUBSET
+       check_enum(FwMark);
+       check_enum(Table);
+       check_enum(PreUp);
+       check_enum(PostUp);
+       check_enum(PreDown);
+       check_enum(PostDown);
+       check_enum(SaveConfig);
+#endif
+       return Invalid;
 #undef check_enum
 }
 
 static enum keytype get_sectiontype(string_span_t s)
 {
-    if (s.len == 6 && !strncasecmp("[Peer]", s.s, 6))
-        return PeerSection;
-    if (s.len == 11 && !strncasecmp("[Interface]", s.s, 11))
-        return InterfaceSection;
-    return Invalid;
+       if (s.len == 6 && !strncasecmp("[Peer]", s.s, 6))
+               return PeerSection;
+       if (s.len == 11 && !strncasecmp("[Interface]", s.s, 11))
+               return InterfaceSection;
+       return Invalid;
 }
 
 struct highlight_span_array {
-    size_t len, capacity;
-    struct highlight_span *spans;
+       size_t len, capacity;
+       struct highlight_span *spans;
 };
 
 /* A useful OpenBSD-ism. */
 static void *realloc_array(void *optr, size_t nmemb, size_t size)
 {
-    if ((nmemb >= (size_t)1 << (sizeof(size_t) * 4) ||
-         size >= (size_t)1 << (sizeof(size_t) * 4)) &&
-        nmemb > 0 && SIZE_MAX / nmemb < size) {
-        errno = ENOMEM;
-        return NULL;
-    }
-    return realloc(optr, size * nmemb);
+       if ((nmemb >= (size_t)1 << (sizeof(size_t) * 4) ||
+            size >= (size_t)1 << (sizeof(size_t) * 4)) &&
+           nmemb > 0 && SIZE_MAX / nmemb < size) {
+               errno = ENOMEM;
+               return NULL;
+       }
+       return realloc(optr, size * nmemb);
 }
 
 static bool append_highlight_span(struct highlight_span_array *a, const char *o, string_span_t s, enum highlight_type t)
 {
-    if (!s.len)
-        return true;
-    if (a->len >= a->capacity) {
-        struct highlight_span *resized;
-        
-        a->capacity = a->capacity ? a->capacity * 2 : 64;
-        resized = realloc_array(a->spans, a->capacity, sizeof(*resized));
-        if (!resized) {
-            free(a->spans);
-            memset(a, 0, sizeof(*a));
-            return false;
-        }
-        a->spans = resized;
-    }
-    a->spans[a->len++] = (struct highlight_span){ t, s.s - o, s.len };
-    return true;
+       if (!s.len)
+               return true;
+       if (a->len >= a->capacity) {
+               struct highlight_span *resized;
+
+               a->capacity = a->capacity ? a->capacity * 2 : 64;
+               resized = realloc_array(a->spans, a->capacity, sizeof(*resized));
+               if (!resized) {
+                       free(a->spans);
+                       memset(a, 0, sizeof(*a));
+                       return false;
+               }
+               a->spans = resized;
+       }
+       a->spans[a->len++] = (struct highlight_span){ t, s.s - o, s.len };
+       return true;
 }
 
 static void highlight_multivalue_value(struct highlight_span_array *ret, const string_span_t parent, const string_span_t s, enum keytype section)
 {
-    switch (section) {
-        case DNS:
-            append_highlight_span(ret, parent.s, s, is_valid_dns(s) ? HighlightIP : HighlightError);
-            break;
-        case Address:
-        case AllowedIPs: {
-            size_t slash;
-            
-            if (!is_valid_network(s)) {
-                append_highlight_span(ret, parent.s, s, HighlightError);
-                break;
-            }
-            for (slash = 0; slash < s.len; ++slash) {
-                if (s.s[slash] == '/')
-                    break;
-            }
-            if (slash == s.len) {
-                append_highlight_span(ret, parent.s, s, HighlightIP);
-            } else {
-                append_highlight_span(ret, parent.s, (string_span_t){ s.s, slash }, HighlightIP);
-                append_highlight_span(ret, parent.s, (string_span_t){ s.s + slash, 1 }, HighlightDelimiter);
-                append_highlight_span(ret, parent.s, (string_span_t){ s.s + slash + 1, s.len - slash - 1 }, HighlightCidr);
-            }
-            break;
-        }
-        default:
-            append_highlight_span(ret, parent.s, s, HighlightError);
-    }
+       switch (section) {
+       case DNS:
+               append_highlight_span(ret, parent.s, s, is_valid_dns(s) ? HighlightIP : HighlightError);
+               break;
+       case Address:
+       case AllowedIPs: {
+               size_t slash;
+
+               if (!is_valid_network(s)) {
+                       append_highlight_span(ret, parent.s, s, HighlightError);
+                       break;
+               }
+               for (slash = 0; slash < s.len; ++slash) {
+                       if (s.s[slash] == '/')
+                               break;
+               }
+               if (slash == s.len) {
+                       append_highlight_span(ret, parent.s, s, HighlightIP);
+               } else {
+                       append_highlight_span(ret, parent.s, (string_span_t){ s.s, slash }, HighlightIP);
+                       append_highlight_span(ret, parent.s, (string_span_t){ s.s + slash, 1 }, HighlightDelimiter);
+                       append_highlight_span(ret, parent.s, (string_span_t){ s.s + slash + 1, s.len - slash - 1 }, HighlightCidr);
+               }
+               break;
+       }
+       default:
+               append_highlight_span(ret, parent.s, s, HighlightError);
+       }
 }
 
 static void highlight_multivalue(struct highlight_span_array *ret, const string_span_t parent, const string_span_t s, enum keytype section)
 {
-    string_span_t current_span = { s.s, 0 };
-    size_t len_at_last_space = 0;
-    
-    for (size_t i = 0; i < s.len; ++i) {
-        if (s.s[i] == ',') {
-            current_span.len = len_at_last_space;
-            highlight_multivalue_value(ret, parent, current_span, section);
-            append_highlight_span(ret, parent.s, (string_span_t){ s.s + i, 1 }, HighlightDelimiter);
-            len_at_last_space = 0;
-            current_span = (string_span_t){ s.s + i + 1, 0 };
-        } else if (s.s[i] == ' ' || s.s[i] == '\t') {
-            if (&s.s[i] == current_span.s && !current_span.len)
-                ++current_span.s;
-            else
-                ++current_span.len;
-        } else {
-            len_at_last_space = ++current_span.len;
-        }
-    }
-    current_span.len = len_at_last_space;
-    if (current_span.len)
-        highlight_multivalue_value(ret, parent, current_span, section);
-    else if (ret->spans[ret->len - 1].type == HighlightDelimiter)
-        ret->spans[ret->len - 1].type = HighlightError;
+       string_span_t current_span = { s.s, 0 };
+       size_t len_at_last_space = 0;
+
+       for (size_t i = 0; i < s.len; ++i) {
+               if (s.s[i] == ',') {
+                       current_span.len = len_at_last_space;
+                       highlight_multivalue_value(ret, parent, current_span, section);
+                       append_highlight_span(ret, parent.s, (string_span_t){ s.s + i, 1 }, HighlightDelimiter);
+                       len_at_last_space = 0;
+                       current_span = (string_span_t){ s.s + i + 1, 0 };
+               } else if (s.s[i] == ' ' || s.s[i] == '\t') {
+                       if (&s.s[i] == current_span.s && !current_span.len)
+                               ++current_span.s;
+                       else
+                               ++current_span.len;
+               } else {
+                       len_at_last_space = ++current_span.len;
+               }
+       }
+       current_span.len = len_at_last_space;
+       if (current_span.len)
+               highlight_multivalue_value(ret, parent, current_span, section);
+       else if (ret->spans[ret->len - 1].type == HighlightDelimiter)
+               ret->spans[ret->len - 1].type = HighlightError;
 }
 
 static void highlight_value(struct highlight_span_array *ret, const string_span_t parent, const string_span_t s, enum keytype section)
 {
-    switch (section) {
-        case PrivateKey:
-        case PublicKey:
-        case PresharedKey:
-            append_highlight_span(ret, parent.s, s, is_valid_key(s) ? HighlightKey : HighlightError);
-            break;
-        case FwMark:
-            append_highlight_span(ret, parent.s, s, is_valid_fwmark(s) ? HighlightFwMark : HighlightError);
-            break;
-        case Table:
-            append_highlight_span(ret, parent.s, s, is_valid_table(s) ? HighlightTable : HighlightError);
-            break;
-        case MTU:
-            append_highlight_span(ret, parent.s, s, is_valid_mtu(s) ? HighlightMTU : HighlightError);
-            break;
-        case SaveConfig:
-            append_highlight_span(ret, parent.s, s, is_valid_saveconfig(s) ? HighlightSaveConfig : HighlightError);
-            break;
-        case PreUp:
-        case PostUp:
-        case PreDown:
-        case PostDown:
-            append_highlight_span(ret, parent.s, s, is_valid_prepostupdown(s) ? HighlightCmd : HighlightError);
-            break;
-        case ListenPort:
-            append_highlight_span(ret, parent.s, s, is_valid_port(s) ? HighlightPort : HighlightError);
-            break;
-        case PersistentKeepalive:
-            append_highlight_span(ret, parent.s, s, is_valid_persistentkeepalive(s) ? HighlightKeepalive : HighlightError);
-            break;
-        case Endpoint: {
-            size_t colon;
-            
-            if (!is_valid_endpoint(s)) {
-                append_highlight_span(ret, parent.s, s, HighlightError);
-                break;
-            }
-            for (colon = s.len; colon --> 0;) {
-                if (s.s[colon] == ':')
-                    break;
-            }
-            append_highlight_span(ret, parent.s, (string_span_t){ s.s, colon }, HighlightHost);
-            append_highlight_span(ret, parent.s, (string_span_t){ s.s + colon, 1 }, HighlightDelimiter);
-            append_highlight_span(ret, parent.s, (string_span_t){ s.s + colon + 1, s.len - colon - 1 }, HighlightPort);
-            break;
-        }
-        case Address:
-        case DNS:
-        case AllowedIPs:
-            highlight_multivalue(ret, parent, s, section);
-            break;
-        default:
-            append_highlight_span(ret, parent.s, s, HighlightError);
-    }
+       switch (section) {
+       case PrivateKey:
+       case PublicKey:
+       case PresharedKey:
+               append_highlight_span(ret, parent.s, s, is_valid_key(s) ? HighlightKey : HighlightError);
+               break;
+       case MTU:
+               append_highlight_span(ret, parent.s, s, is_valid_mtu(s) ? HighlightMTU : HighlightError);
+               break;
+#ifndef MOBILE_WGQUICK_SUBSET
+       case SaveConfig:
+               append_highlight_span(ret, parent.s, s, is_valid_saveconfig(s) ? HighlightSaveConfig : HighlightError);
+               break;
+       case FwMark:
+               append_highlight_span(ret, parent.s, s, is_valid_fwmark(s) ? HighlightFwMark : HighlightError);
+               break;
+       case Table:
+               append_highlight_span(ret, parent.s, s, is_valid_table(s) ? HighlightTable : HighlightError);
+               break;
+       case PreUp:
+       case PostUp:
+       case PreDown:
+       case PostDown:
+               append_highlight_span(ret, parent.s, s, is_valid_prepostupdown(s) ? HighlightCmd : HighlightError);
+               break;
+#endif
+       case ListenPort:
+               append_highlight_span(ret, parent.s, s, is_valid_port(s) ? HighlightPort : HighlightError);
+               break;
+       case PersistentKeepalive:
+               append_highlight_span(ret, parent.s, s, is_valid_persistentkeepalive(s) ? HighlightKeepalive : HighlightError);
+               break;
+       case Endpoint: {
+               size_t colon;
+
+               if (!is_valid_endpoint(s)) {
+                       append_highlight_span(ret, parent.s, s, HighlightError);
+                       break;
+               }
+               for (colon = s.len; colon --> 0;) {
+                       if (s.s[colon] == ':')
+                               break;
+               }
+               append_highlight_span(ret, parent.s, (string_span_t){ s.s, colon }, HighlightHost);
+               append_highlight_span(ret, parent.s, (string_span_t){ s.s + colon, 1 }, HighlightDelimiter);
+               append_highlight_span(ret, parent.s, (string_span_t){ s.s + colon + 1, s.len - colon - 1 }, HighlightPort);
+               break;
+       }
+       case Address:
+       case DNS:
+       case AllowedIPs:
+               highlight_multivalue(ret, parent, s, section);
+               break;
+       default:
+               append_highlight_span(ret, parent.s, s, HighlightError);
+       }
 }
 
 struct highlight_span *highlight_config(const char *config)
 {
-    struct highlight_span_array ret = { 0 };
-    const string_span_t s = { config, strlen(config) };
-    string_span_t current_span = { s.s, 0 };
-    enum keytype current_section = Invalid, current_keytype = Invalid;
-    enum { OnNone, OnKey, OnValue, OnComment, OnSection } state = OnNone;
-    size_t len_at_last_space = 0, equals_location = 0;
-    
-    for (size_t i = 0; i <= s.len; ++i) {
-        if (i == s.len || s.s[i] == '\n' || (state != OnComment && s.s[i] == '#')) {
-            if (state == OnKey) {
-                current_span.len = len_at_last_space;
-                append_highlight_span(&ret, s.s, current_span, HighlightError);
-            } else if (state == OnValue) {
-                if (current_span.len) {
-                    append_highlight_span(&ret, s.s, (string_span_t){ s.s + equals_location, 1 }, HighlightDelimiter);
-                    current_span.len = len_at_last_space;
-                    highlight_value(&ret, s, current_span, current_keytype);
-                } else {
-                    append_highlight_span(&ret, s.s, (string_span_t){ s.s + equals_location, 1 }, HighlightError);
-                }
-            } else if (state == OnSection) {
-                current_span.len = len_at_last_space;
-                current_section = get_sectiontype(current_span);
-                append_highlight_span(&ret, s.s, current_span, current_section == Invalid ? HighlightError : HighlightSection);
-            } else if (state == OnComment) {
-                append_highlight_span(&ret, s.s, current_span, HighlightComment);
-            }
-            if (i == s.len)
-                break;
-            len_at_last_space = 0;
-            current_keytype = Invalid;
-            if (s.s[i] == '#') {
-                current_span = (string_span_t){ s.s + i, 1 };
-                state = OnComment;
-            } else {
-                current_span = (string_span_t){ s.s + i + 1, 0 };
-                state = OnNone;
-            }
-        } else if (state == OnComment) {
-            ++current_span.len;
-        } else if (s.s[i] == ' ' || s.s[i] == '\t') {
-            if (&s.s[i] == current_span.s && !current_span.len)
-                ++current_span.s;
-            else
-                ++current_span.len;
-        } else if (s.s[i] == '=' && state == OnKey) {
-            current_span.len = len_at_last_space;
-            current_keytype = get_keytype(current_span);
-            enum keytype section = section_for_keytype(current_keytype);
-            if (section == Invalid || current_keytype == Invalid || section != current_section)
-                append_highlight_span(&ret, s.s, current_span, HighlightError);
-            else
-                append_highlight_span(&ret, s.s, current_span, HighlightKeytype);
-            equals_location = i;
-            current_span = (string_span_t){ s.s + i + 1, 0 };
-            state = OnValue;
-        } else {
-            if (state == OnNone)
-                state = s.s[i] == '[' ? OnSection : OnKey;
-            len_at_last_space = ++current_span.len;
-        }
-    }
-    
-    append_highlight_span(&ret, s.s, (string_span_t){ s.s, -1 }, HighlightEnd);
-    return ret.spans;
+       struct highlight_span_array ret = { 0 };
+       const string_span_t s = { config, strlen(config) };
+       string_span_t current_span = { s.s, 0 };
+       enum keytype current_section = Invalid, current_keytype = Invalid;
+       enum { OnNone, OnKey, OnValue, OnComment, OnSection } state = OnNone;
+       size_t len_at_last_space = 0, equals_location = 0;
+
+       for (size_t i = 0; i <= s.len; ++i) {
+               if (i == s.len || s.s[i] == '\n' || (state != OnComment && s.s[i] == '#')) {
+                       if (state == OnKey) {
+                               current_span.len = len_at_last_space;
+                               append_highlight_span(&ret, s.s, current_span, HighlightError);
+                       } else if (state == OnValue) {
+                               if (current_span.len) {
+                                       append_highlight_span(&ret, s.s, (string_span_t){ s.s + equals_location, 1 }, HighlightDelimiter);
+                                       current_span.len = len_at_last_space;
+                                       highlight_value(&ret, s, current_span, current_keytype);
+                               } else {
+                                       append_highlight_span(&ret, s.s, (string_span_t){ s.s + equals_location, 1 }, HighlightError);
+                               }
+                       } else if (state == OnSection) {
+                               current_span.len = len_at_last_space;
+                               current_section = get_sectiontype(current_span);
+                               append_highlight_span(&ret, s.s, current_span, current_section == Invalid ? HighlightError : HighlightSection);
+                       } else if (state == OnComment) {
+                               append_highlight_span(&ret, s.s, current_span, HighlightComment);
+                       }
+                       if (i == s.len)
+                               break;
+                       len_at_last_space = 0;
+                       current_keytype = Invalid;
+                       if (s.s[i] == '#') {
+                               current_span = (string_span_t){ s.s + i, 1 };
+                               state = OnComment;
+                       } else {
+                               current_span = (string_span_t){ s.s + i + 1, 0 };
+                               state = OnNone;
+                       }
+               } else if (state == OnComment) {
+                       ++current_span.len;
+               } else if (s.s[i] == ' ' || s.s[i] == '\t') {
+                       if (&s.s[i] == current_span.s && !current_span.len)
+                               ++current_span.s;
+                       else
+                               ++current_span.len;
+               } else if (s.s[i] == '=' && state == OnKey) {
+                       current_span.len = len_at_last_space;
+                       current_keytype = get_keytype(current_span);
+                       enum keytype section = section_for_keytype(current_keytype);
+                       if (section == Invalid || current_keytype == Invalid || section != current_section)
+                               append_highlight_span(&ret, s.s, current_span, HighlightError);
+                       else
+                               append_highlight_span(&ret, s.s, current_span, HighlightKeytype);
+                       equals_location = i;
+                       current_span = (string_span_t){ s.s + i + 1, 0 };
+                       state = OnValue;
+               } else {
+                       if (state == OnNone)
+                               state = s.s[i] == '[' ? OnSection : OnKey;
+                       len_at_last_space = ++current_span.len;
+               }
+       }
+
+       append_highlight_span(&ret, s.s, (string_span_t){ s.s, -1 }, HighlightEnd);
+       return ret.spans;
 }
index 9368af638b853685f84cf65bdbbda8e4f3e21306..d88638b8385de165645acf1548d4e4264adde23b 100644 (file)
@@ -6,28 +6,30 @@
 #include <sys/types.h>
 
 enum highlight_type {
-    HighlightSection,
-    HighlightKeytype,
-    HighlightKey,
-    HighlightCmd,
-    HighlightIP,
-    HighlightCidr,
-    HighlightHost,
-    HighlightPort,
-    HighlightTable,
-    HighlightFwMark,
-    HighlightMTU,
-    HighlightSaveConfig,
-    HighlightKeepalive,
-    HighlightComment,
-    HighlightDelimiter,
-    HighlightError,
-    HighlightEnd
+       HighlightSection,
+       HighlightKeytype,
+       HighlightKey,
+       HighlightIP,
+       HighlightCidr,
+       HighlightHost,
+       HighlightPort,
+       HighlightMTU,
+       HighlightKeepalive,
+       HighlightComment,
+       HighlightDelimiter,
+#ifndef MOBILE_WGQUICK_SUBSET
+       HighlightTable,
+       HighlightFwMark,
+       HighlightSaveConfig,
+       HighlightCmd,
+#endif
+       HighlightError,
+       HighlightEnd
 };
 
 struct highlight_span {
-    enum highlight_type type;
-    size_t start, len;
+       enum highlight_type type;
+       size_t start, len;
 };
 
 struct highlight_span *highlight_config(const char *config);