Veröffentlichte Quellen
Quellen als ZIP herunterladen
CH-J Tools
Durchsuchen Sie Verzeichnisse und Dateien einer bestimmten Anwendungsausgabe.
CH-J / Server Manager
872 Dateien
core-20261030T220507Z-61e4558d889f
Hinzugefügt: · Erstellt:
1
//! Helpers shared by the Linux and Windows user services (0.1.0 semantics).3
use crate::core::error::CoreError;4
use once_cell::sync::Lazy;5
use regex::Regex;6
use serde_json::Value;7
use std::collections::BTreeMap;9
pub const SAMPLE_IPV4: &str = "192.0.2.10";10
pub const SAMPLE_IPV6: &str = "2001:db8::10";12
pub fn fail(code: &str, message: &str) -> CoreError {13
CoreError::new(code, message)14
}16
/// `String(value ?? "")`.17
pub fn js_string(value: &Value) -> String {18
match value {19
Value::Null => String::new(),20
Value::String(s) => s.clone(),21
other => other.to_string(),22
}23
}25
/// JavaScript `Number(text)` for decimal strings (empty → 0, invalid → None).26
pub fn js_number(text: &str) -> Option<f64> {27
let trimmed = text.trim();28
if trimmed.is_empty() {29
return Some(0.0);30
}31
if trimmed.chars().any(|c| c.is_ascii_alphabetic() && c != 'e' && c != 'E') {32
return None;33
}34
trimmed.parse::<f64>().ok()35
}37
pub fn js_number_value(value: &Value) -> Option<f64> {38
match value {39
Value::Number(n) => n.as_f64(),40
Value::String(s) => js_number(s),41
Value::Bool(b) => Some(if *b { 1.0 } else { 0.0 }),42
Value::Null => Some(0.0),43
_ => None,44
}45
}47
pub fn truthy(value: &Value) -> bool {48
match value {49
Value::Null => false,50
Value::Bool(b) => *b,51
Value::Number(n) => n.as_f64().is_some_and(|f| f != 0.0 && !f.is_nan()),52
Value::String(s) => !s.is_empty(),53
_ => true,54
}55
}57
pub fn clean_text(value: &str, limit: usize) -> String {58
let replaced: String = value.chars().map(|c| if (c as u32) < 0x20 || c as u32 == 0x7f { ' ' } else { c }).collect();59
let trimmed = replaced.trim();60
// JavaScript slices UTF-16 code units; BMP text is the common case.61
let mut out = String::new();62
let mut units = 0;63
for c in trimmed.chars() {64
units += c.len_utf16();65
if units > limit {66
break;67
}68
out.push(c);69
}70
out71
}73
pub fn now_iso() -> String {74
chrono::Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Millis, true)75
}77
static SECTION: Lazy<Regex> = Lazy::new(|| Regex::new(r"\x1eCHJ_SECTION=([a-z0-9]+)\r?\n").unwrap());79
pub fn split_sections(text: &str) -> BTreeMap<String, String> {80
let mut sections = BTreeMap::new();81
let mut current: Option<String> = None;82
let mut start = 0;83
for caps in SECTION.captures_iter(text) {84
let whole = caps.get(0).unwrap();85
if let Some(name) = current.take() {86
sections.insert(name, text[start..whole.start()].to_string());87
}88
current = Some(caps[1].to_string());89
start = whole.end();90
}91
if let Some(name) = current {92
sections.insert(name, text[start..].to_string());93
}94
sections95
}97
/// First `key=value` wins.98
pub fn key_values(text: &str) -> BTreeMap<String, String> {99
let mut values = BTreeMap::new();100
for line in text.split('\n') {101
let line = line.strip_suffix('\r').unwrap_or(line);102
if let Some(index) = line.find('=') {103
if index > 0 && !values.contains_key(&line[..index]) {104
values.insert(line[..index].to_string(), line[index + 1..].to_string());105
}106
}107
}108
values109
}111
pub fn lines(text: &str) -> Vec<&str> {112
text.split('\n').map(|l| l.strip_suffix('\r').unwrap_or(l)).filter(|l| !l.is_empty()).collect()113
}115
#[derive(Debug, Clone)]116
pub struct Addresses {117
pub ipv4: String,118
pub ipv6: String,119
pub ipv4_sample: bool,120
pub ipv6_sample: bool,121
}123
impl Addresses {124
pub fn get(&self, family: &str) -> String {125
if family == "ipv4" { self.ipv4.clone() } else { self.ipv6.clone() }126
}127
pub fn sample(&self, family: &str) -> bool {128
if family == "ipv4" { self.ipv4_sample } else { self.ipv6_sample }129
}130
}132
pub fn family_addresses(client: &str) -> Addresses {133
let family = match client.parse::<std::net::IpAddr>() {134
Ok(std::net::IpAddr::V4(_)) => 4,135
Ok(std::net::IpAddr::V6(_)) => 6,136
Err(_) => 0,137
};138
Addresses {139
ipv4: if family == 4 { client.to_string() } else { SAMPLE_IPV4.into() },140
ipv6: if family == 6 { client.to_string() } else { SAMPLE_IPV6.into() },141
ipv4_sample: family != 4,142
ipv6_sample: family != 6,143
}144
}SHA-256
9e227bc3a5044fd8eb0bc04dc518d3c67508054865ed670360c0612d8b3fd7e8CH-J Proprietary Software License 1.14 · Die Quellen werden unter der CH-J Proprietary Software License 1.14 bereitgestellt. Ihre Verfügbarkeit ändert die Lizenzbedingungen nicht und gewährt keine zusätzlichen Rechte.
SHA-256 des Archivs
77380d4805485ffa4027fbe7858b5836f197a4aa9d52358a43e2d12d018744df