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 '\u{2028}' => result.push_str("\\u2028"),
15 '\u{2029}' => result.push_str("\\u2029"),
16 c if (c as u32) < 0x20 => {
18 result.push_str(&format!("\\u{:04x}", c as u32));
19 }
20 _ => result.push(c),
21 }
22 }
23 result
24}
25
26pub fn generate_pac(config: &PacConfig) -> String {
27 let mut body = String::new();
28
29 body.push_str("function FindProxyForURL(url, host) {\n");
30 body.push_str(" if (isPlainHostName(host)) return \"DIRECT\";\n");
31
32 let mut direct_hosts = config.direct_hosts.clone();
33 direct_hosts.sort();
34
35 if !direct_hosts.is_empty() {
36 body.push_str(" var directHosts = [");
37 for (i, h) in direct_hosts.iter().enumerate() {
38 if i > 0 {
39 body.push_str(", ");
40 }
41 body.push('"');
42 body.push_str(&js_escape(h));
43 body.push('"');
44 }
45 body.push_str("];\n");
46 body.push_str(" for (var i = 0; i < directHosts.length; i++) {\n");
47 body.push_str(
48 " if (host == directHosts[i] || shExpMatch(host, \"*.\" + directHosts[i]))\n",
49 );
50 body.push_str(" return \"DIRECT\";\n");
51 body.push_str(" }\n");
52 }
53
54 let mut direct_suffixes = config.direct_suffixes.clone();
55 direct_suffixes.sort();
56
57 if !direct_suffixes.is_empty() {
58 body.push_str(" var directSuffixes = [");
59 for (i, s) in direct_suffixes.iter().enumerate() {
60 if i > 0 {
61 body.push_str(", ");
62 }
63 body.push('"');
64 body.push_str(&js_escape(s));
65 body.push('"');
66 }
67 body.push_str("];\n");
68 body.push_str(" for (var i = 0; i < directSuffixes.length; i++) {\n");
69 body.push_str(" if (shExpMatch(host, \"*.\" + directSuffixes[i]))\n");
70 body.push_str(" return \"DIRECT\";\n");
71 body.push_str(" }\n");
72 }
73
74 let proxy = js_escape(&config.proxy_directive);
75 body.push_str(&format!(
76 " return \"PROXY {}{}",
77 proxy,
78 if config.direct_fallback {
79 "; DIRECT\";\n"
80 } else {
81 "\";\n"
82 }
83 ));
84
85 body.push_str("}\n");
86 body
87}