Skip to main content

eggress_admin/
pac.rs

1use crate::PacConfig;
2
3fn js_escape(s: &str) -> String {
4    let mut result = String::with_capacity(s.len());
5    for c in s.chars() {
6        match c {
7            '\\' => result.push_str("\\\\"),
8            '"' => result.push_str("\\\""),
9            '\n' => result.push_str("\\n"),
10            '\r' => result.push_str("\\r"),
11            '\t' => result.push_str("\\t"),
12            _ => result.push(c),
13        }
14    }
15    result
16}
17
18pub fn generate_pac(config: &PacConfig) -> String {
19    let mut body = String::new();
20
21    body.push_str("function FindProxyForURL(url, host) {\n");
22    body.push_str("  if (isPlainHostName(host)) return \"DIRECT\";\n");
23
24    let mut direct_hosts = config.direct_hosts.clone();
25    direct_hosts.sort();
26
27    if !direct_hosts.is_empty() {
28        body.push_str("  var directHosts = [");
29        for (i, h) in direct_hosts.iter().enumerate() {
30            if i > 0 {
31                body.push_str(", ");
32            }
33            body.push('"');
34            body.push_str(&js_escape(h));
35            body.push('"');
36        }
37        body.push_str("];\n");
38        body.push_str("  for (var i = 0; i < directHosts.length; i++) {\n");
39        body.push_str(
40            "    if (host == directHosts[i] || shExpMatch(host, \"*.\" + directHosts[i]))\n",
41        );
42        body.push_str("      return \"DIRECT\";\n");
43        body.push_str("  }\n");
44    }
45
46    let mut direct_suffixes = config.direct_suffixes.clone();
47    direct_suffixes.sort();
48
49    if !direct_suffixes.is_empty() {
50        body.push_str("  var directSuffixes = [");
51        for (i, s) in direct_suffixes.iter().enumerate() {
52            if i > 0 {
53                body.push_str(", ");
54            }
55            body.push('"');
56            body.push_str(&js_escape(s));
57            body.push('"');
58        }
59        body.push_str("];\n");
60        body.push_str("  for (var i = 0; i < directSuffixes.length; i++) {\n");
61        body.push_str("    if (shExpMatch(host, \"*.\" + directSuffixes[i]))\n");
62        body.push_str("      return \"DIRECT\";\n");
63        body.push_str("  }\n");
64    }
65
66    let proxy = js_escape(&config.proxy_directive);
67    body.push_str(&format!(
68        "  return \"PROXY {}{}",
69        proxy,
70        if config.direct_fallback {
71            "; DIRECT\";\n"
72        } else {
73            "\";\n"
74        }
75    ));
76
77    body.push_str("}\n");
78    body
79}