From 53e2f5f48a5a9f9c75439b3759812ce18f9b8a94 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Wed, 12 May 2021 17:31:44 +0900 Subject: [PATCH 1/2] module _scproxy --- Cargo.lock | 38 ++++++++++ vm/Cargo.toml | 3 + vm/src/stdlib/mod.rs | 6 ++ vm/src/stdlib/scproxy.rs | 147 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 194 insertions(+) create mode 100644 vm/src/stdlib/scproxy.rs diff --git a/Cargo.lock b/Cargo.lock index 9e0adb0b9..34c2ea203 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -313,6 +313,22 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "core-foundation" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" + [[package]] name = "cpuid-bool" version = "0.1.2" @@ -2058,6 +2074,7 @@ dependencies = [ "socket2", "sre-engine", "static_assertions", + "system-configuration", "termios", "thiserror", "thread_local", @@ -2361,6 +2378,27 @@ dependencies = [ "syn", ] +[[package]] +name = "system-configuration" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd4bc0637a2b8c0b1a5145cca3e21b707865edc7e32285771536af1ade129468" +dependencies = [ + "bitflags", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "269e271436d8e4bb2621c535a11fe03d5d012f74b19af72f80288f3a72f6180a" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "target-lexicon" version = "0.11.2" diff --git a/vm/Cargo.toml b/vm/Cargo.toml index dca9d1d99..de835936f 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -135,6 +135,9 @@ dns-lookup = "1.0" [target.'cfg(all(unix, not(target_os = "redox")))'.dependencies] termios = "0.3" +[target.'cfg(target_os = "macos")'.dependencies] +system-configuration = "0.4" + [target.'cfg(windows)'.dependencies] winreg = "0.8.0" schannel = "0.1" diff --git a/vm/src/stdlib/mod.rs b/vm/src/stdlib/mod.rs index 02997aa06..9a53f4334 100644 --- a/vm/src/stdlib/mod.rs +++ b/vm/src/stdlib/mod.rs @@ -62,6 +62,8 @@ mod pwd; // libc is missing constants on redox #[cfg(all(unix, not(target_os = "redox")))] mod resource; +#[cfg(target_os = "macos")] +mod scproxy; #[cfg(not(target_arch = "wasm32"))] mod select; #[cfg(not(target_arch = "wasm32"))] @@ -186,5 +188,9 @@ pub fn get_module_inits() -> StdlibMap { "_winapi" => winapi::make_module, "winreg" => winreg::make_module, } + #[cfg(target_os = "macos")] + { + "_scproxy" => scproxy::make_module, + } } } diff --git a/vm/src/stdlib/scproxy.rs b/vm/src/stdlib/scproxy.rs new file mode 100644 index 000000000..660bc1cf3 --- /dev/null +++ b/vm/src/stdlib/scproxy.rs @@ -0,0 +1,147 @@ +pub(crate) use _scproxy::make_module; + +#[pymodule] +mod _scproxy { + // straight-forward port of Modules/_scproxy.c + + use crate::builtins::{PyDictRef, PyStr}; + use crate::pyobject::{IntoPyObject, ItemProtocol, PyResult}; + use crate::VirtualMachine; + use system_configuration::core_foundation::{ + array::CFArray, + base::{CFType, FromVoid, TCFType}, + dictionary::CFDictionary, + number::CFNumber, + string::{CFString, CFStringRef}, + }; + use system_configuration::sys::{ + dynamic_store_copy_specific::SCDynamicStoreCopyProxies, schema_definitions::*, + }; + + fn proxy_dict() -> Option> { + // Py_BEGIN_ALLOW_THREADS + let proxy_dict = unsafe { SCDynamicStoreCopyProxies(std::ptr::null()) }; + // Py_END_ALLOW_THREADS + if proxy_dict.is_null() { + None + } else { + Some(unsafe { CFDictionary::wrap_under_create_rule(proxy_dict) }) + } + } + + #[pyfunction] + fn _get_proxy_settings(vm: &VirtualMachine) -> PyResult> { + let proxy_dict = if let Some(p) = proxy_dict() { + p + } else { + return Ok(None); + }; + + let result = vm.ctx.new_dict(); + + let v = 0 + != proxy_dict + .find(unsafe { kSCPropNetProxiesExcludeSimpleHostnames }) + .and_then(|v| v.downcast::()) + .and_then(|v| v.to_i32()) + .unwrap_or(0); + result.set_item("exclude_simple", vm.ctx.new_bool(v), vm)?; + + if let Some(an_array) = proxy_dict + .find(unsafe { kSCPropNetProxiesExceptionsList }) + .and_then(|v| v.downcast::()) + { + let v = an_array + .into_iter() + .map(|s| { + unsafe { CFType::from_void(*s) } + .downcast::() + .map(|s| { + let a_string: std::borrow::Cow = (&s).into(); + PyStr::from(a_string.into_owned()) + }) + .into_pyobject(vm) + }) + .collect(); + result.set_item("exceptions", vm.ctx.new_tuple(v), vm)?; + } + + Ok(Some(result)) + } + + #[pyfunction] + fn _get_proxies(vm: &VirtualMachine) -> PyResult> { + let proxy_dict = if let Some(p) = proxy_dict() { + p + } else { + return Ok(None); + }; + + let result = vm.ctx.new_dict(); + + let set_proxy = |result: &PyDictRef, + proto: &str, + enabled_key: CFStringRef, + host_key: CFStringRef, + port_key: CFStringRef| + -> PyResult<()> { + let enabled = 0 + != proxy_dict + .find(enabled_key) + .and_then(|v| v.downcast::()) + .and_then(|v| v.to_i32()) + .unwrap_or(0); + if enabled { + if let Some(host) = proxy_dict + .find(host_key) + .and_then(|v| v.downcast::()) + { + let h = std::borrow::Cow::::from(&host); + let v = if let Some(port) = proxy_dict + .find(port_key) + .and_then(|v| v.downcast::()) + .and_then(|v| v.to_i32()) + { + format!("http://{}:{}", h, port) + } else { + format!("http://{}", h) + }; + result.set_item(proto, vm.ctx.new_str(v), vm)?; + } + } + Ok(()) + }; + + unsafe { + set_proxy( + &result, + "http", + kSCPropNetProxiesHTTPEnable, + kSCPropNetProxiesHTTPProxy, + kSCPropNetProxiesHTTPPort, + )?; + set_proxy( + &result, + "https", + kSCPropNetProxiesHTTPSEnable, + kSCPropNetProxiesHTTPSProxy, + kSCPropNetProxiesHTTPSPort, + )?; + set_proxy( + &result, + "ftp", + kSCPropNetProxiesFTPEnable, + kSCPropNetProxiesFTPProxy, + kSCPropNetProxiesFTPPort, + )?; + set_proxy( + &result, + "gopher", + kSCPropNetProxiesGopherEnable, + kSCPropNetProxiesGopherProxy, + kSCPropNetProxiesGopherPort, + )?; + } + Ok(Some(result)) + } +} From 7b6519beefca3c894443dae7c0d859a8a9e13c98 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Thu, 13 May 2021 03:07:21 +0900 Subject: [PATCH 2/2] allow test_http_cookiejar and test_robotparser for macos --- .github/workflows/ci.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 46adfc218..2f73b628e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -96,8 +96,7 @@ jobs: - if: runner.os == 'macOS' name: run cpython tests (macOS lightweight) run: - target/release/rustpython -m test -v -x - test_http_cookiejar test_robotparser + target/release/rustpython -m test -v - if: runner.os == 'Windows' name: run cpython tests (windows partial - fixme) run: