libsubconverter/utils/
system.rs1use std::env;
4use std::thread;
5use std::time::{Duration, SystemTime, UNIX_EPOCH};
6
7#[cfg(target_arch = "wasm32")]
8use js_sys::Date;
9
10#[cfg(target_os = "windows")]
11use winapi::shared::winerror::IS_ERROR;
12#[cfg(target_os = "windows")]
13use winapi::{
14 shared::minwindef::{BYTE, DWORD, HKEY},
15 um::{
16 winnt::KEY_ALL_ACCESS,
17 winreg::{RegEnumValueW, RegOpenKeyExW, RegQueryInfoKeyW, HKEY_CURRENT_USER},
18 },
19};
20
21pub fn safe_system_time() -> SystemTime {
30 #[cfg(target_arch = "wasm32")]
31 {
32 let now_ms = Date::now();
34 let seconds = (now_ms / 1000.0) as u64;
35 let nanos = ((now_ms % 1000.0) * 1_000_000.0) as u32;
36
37 UNIX_EPOCH
39 .checked_add(Duration::new(seconds, nanos))
40 .unwrap_or(UNIX_EPOCH) }
42
43 #[cfg(not(target_arch = "wasm32"))]
44 {
45 SystemTime::now()
47 }
48}
49
50pub fn safe_unix_timestamp() -> u64 {
59 safe_system_time()
60 .duration_since(UNIX_EPOCH)
61 .unwrap_or_default()
62 .as_secs()
63}
64
65pub fn sleep_ms(interval: u64) {
71 thread::sleep(Duration::from_millis(interval));
72}
73
74pub fn get_env(name: &str) -> String {
84 env::var(name).unwrap_or_default()
85}
86
87pub fn get_system_proxy() -> String {
93 #[cfg(target_arch = "wasm32")]
94 {
95 return String::new();
98 }
99
100 #[cfg(not(target_arch = "wasm32"))]
101 #[cfg(target_os = "windows")]
102 {
103 use std::ffi::OsString;
104 use std::os::windows::ffi::OsStringExt;
105 use std::ptr;
106
107 unsafe {
108 let subkey = "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings";
110 let mut hkey: HKEY = ptr::null_mut();
111 let wide_subkey: Vec<u16> = subkey.encode_utf16().chain(std::iter::once(0)).collect();
112
113 let ret = RegOpenKeyExW(
114 HKEY_CURRENT_USER,
115 wide_subkey.as_ptr(),
116 0,
117 KEY_ALL_ACCESS,
118 &mut hkey,
119 );
120
121 if IS_ERROR(ret) {
122 return String::new();
123 }
124
125 let mut values_count: DWORD = 0;
127 let mut max_value_name_len: DWORD = 0;
128 let mut max_value_len: DWORD = 0;
129
130 let ret = RegQueryInfoKeyW(
131 hkey,
132 ptr::null_mut(),
133 ptr::null_mut(),
134 ptr::null_mut(),
135 ptr::null_mut(),
136 ptr::null_mut(),
137 ptr::null_mut(),
138 &mut values_count,
139 &mut max_value_name_len,
140 &mut max_value_len,
141 ptr::null_mut(),
142 ptr::null_mut(),
143 );
144
145 if IS_ERROR(ret) {
146 return String::new();
147 }
148
149 max_value_name_len += 1;
151
152 let mut proxy_enable: DWORD = 0;
154 let mut proxy_server = String::new();
155
156 for i in 0..values_count {
157 let mut name_buf = vec![0u16; max_value_name_len as usize];
158 let mut name_len = max_value_name_len;
159 let mut value_type: DWORD = 0;
160 let mut value_len: DWORD = 0;
161
162 let ret = RegEnumValueW(
164 hkey,
165 i,
166 name_buf.as_mut_ptr(),
167 &mut name_len,
168 ptr::null_mut(),
169 &mut value_type,
170 ptr::null_mut(),
171 &mut value_len,
172 );
173
174 if IS_ERROR(ret) {
175 continue;
176 }
177
178 let mut value_buf = vec![0u8; value_len as usize];
179 name_len = max_value_name_len;
180
181 let ret = RegEnumValueW(
183 hkey,
184 i,
185 name_buf.as_mut_ptr(),
186 &mut name_len,
187 ptr::null_mut(),
188 &mut value_type,
189 value_buf.as_mut_ptr() as *mut BYTE,
190 &mut value_len,
191 );
192
193 if IS_ERROR(ret) {
194 continue;
195 }
196
197 let name_len = name_len as usize;
199 let name_os_string = OsString::from_wide(&name_buf[0..name_len]);
200 let name_string = name_os_string.to_string_lossy().to_string();
201
202 if name_string == "ProxyEnable" && value_len >= 4 {
204 proxy_enable = u32::from_ne_bytes([
205 value_buf[0],
206 value_buf[1],
207 value_buf[2],
208 value_buf[3],
209 ]);
210 } else if name_string == "ProxyServer" {
211 if value_len > 0 {
213 if let Ok(s) =
215 String::from_utf8(value_buf[0..(value_len as usize)].to_vec())
216 {
217 proxy_server = s.trim_end_matches('\0').to_string();
218 }
219 }
220 }
221 }
222
223 if proxy_enable != 0 && !proxy_server.is_empty() {
224 return proxy_server;
225 }
226
227 String::new()
228 }
229 }
230
231 #[cfg(not(target_arch = "wasm32"))]
232 #[cfg(not(target_os = "windows"))]
233 {
234 let proxy_env = [
235 "all_proxy",
236 "ALL_PROXY",
237 "http_proxy",
238 "HTTP_PROXY",
239 "https_proxy",
240 "HTTPS_PROXY",
241 ];
242
243 for var in &proxy_env {
244 if let Ok(proxy) = env::var(var) {
245 if !proxy.is_empty() {
246 return proxy;
247 }
248 }
249 }
250
251 String::new()
252 }
253}
254
255#[cfg(test)]
256mod tests {
257 use super::*;
258
259 #[test]
260 fn test_sleep_ms() {
261 sleep_ms(1);
263 }
264
265 #[test]
266 fn test_get_env() {
267 let path = get_env("PATH");
269 assert!(!path.is_empty());
270 }
271}