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}