-
Notifications
You must be signed in to change notification settings - Fork 32
Expand file tree
/
Copy pathutils.rs
More file actions
131 lines (108 loc) · 3.86 KB
/
utils.rs
File metadata and controls
131 lines (108 loc) · 3.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
use qstring::QString;
use reqwest::Url;
use std::borrow::Cow;
use std::collections::BTreeMap;
use std::env;
#[cfg(feature = "prefix-path")]
{
use once_cell::sync::Lazy;
static PREFIX_PATH: Lazy<Option<String>> = Lazy::new(|| match env::var("PREFIX_PATH") {
Ok(v) => Some(String::from(v)),
Err(e) => panic!("$PREFIX_PATH is not set ({})", e)
});
}
pub fn read_buf(buf: &[u8], pos: &mut usize) -> u8 {
let byte = buf[*pos];
*pos += 1;
byte
}
fn finalize_url(path: &str, query: BTreeMap<String, String>) -> String {
#[cfg(feature = "qhash")]
{
use std::collections::BTreeSet;
let qhash = {
let secret = env::var("HASH_SECRET");
if let Ok(secret) = secret {
let set = query
.iter()
.filter(|(key, _)| !matches!(key.as_str(), "qhash" | "range" | "rewrite"))
.map(|(key, value)| (key.as_bytes().to_owned(), value.as_bytes().to_owned()))
.collect::<BTreeSet<_>>();
let mut hasher = blake3::Hasher::new();
for (key, value) in set {
hasher.update(&key);
hasher.update(&value);
}
hasher.update(path.as_bytes());
hasher.update(secret.as_bytes());
let hash = hasher.finalize().to_hex();
Some(hash[..8].to_owned())
} else {
None
}
};
if let Some(qhash) = qhash {
let mut query = QString::new(query.into_iter().collect::<Vec<_>>());
query.add_pair(("qhash", qhash.unwrap()));
#[cfg(not(feature = "prefix-path"))]
{
return format!("{}?{}", path, query);
}
#[cfg(feature = "prefix-path")]
{
return format!("{}{}?{}", PREFIX_PATH.as_ref().unwrap().to_string(), path, query);
}
query.add_pair(("qhash", qhash));
return format!("{}?{}", path, query);
}
}
let query = QString::new(query.into_iter().collect::<Vec<_>>());
#[cfg(not(feature = "prefix-path"))]
{
format!("{}?{}", path, query)
}
#[cfg(feature = "prefix-path")]
{
format!("{}{}?{}", PREFIX_PATH.as_ref().unwrap().to_string(), path, query)
}
}
pub fn localize_url(url: &str, host: &str) -> String {
if url.starts_with("https://") {
let url = Url::parse(url).unwrap();
let host = url.host().unwrap().to_string();
let mut query = url.query_pairs().into_owned().collect::<BTreeMap<_, _>>();
query.insert("host".to_string(), host.clone());
return finalize_url(url.path(), query);
} else if url.ends_with(".m3u8") || url.ends_with(".ts") {
let mut query = BTreeMap::new();
query.insert("host".to_string(), host.to_string());
return finalize_url(url, query);
}
url.to_string()
}
pub fn escape_xml(raw: &str) -> Cow<'_, str> {
if !raw.contains(&['<', '>', '&', '\'', '"'][..]) {
// If there are no characters to escape, return the original string.
Cow::Borrowed(raw)
} else {
// If there are characters to escape, build a new string with the replacements.
let mut escaped = String::with_capacity(raw.len());
for c in raw.chars() {
match c {
'<' => escaped.push_str("<"),
'>' => escaped.push_str(">"),
'&' => escaped.push_str("&"),
'\'' => escaped.push_str("'"),
'"' => escaped.push_str("""),
_ => escaped.push(c),
}
}
Cow::Owned(escaped)
}
}
pub fn get_env_bool(key: &str) -> bool {
match env::var(key) {
Ok(val) => val.to_lowercase() == "true" || val == "1",
Err(_) => false,
}
}