Settings hot reloading - All tests passing
This commit is contained in:
@@ -24,7 +24,7 @@ ring = { version = "0.17" }
|
||||
base64 = "0.21"
|
||||
serde_json = "1.0"
|
||||
rcgen = "0.12"
|
||||
reqwest = { version = "0.12", default-features = false, features = ["rustls-tls-webpki-roots"]}
|
||||
reqwest = { version = "0.12", default-features = false, features = ["rustls-tls-webpki-roots", "http2"]}
|
||||
x509-parser = "0.16.0"
|
||||
pem = "3.0"
|
||||
parking_lot = "0.12"
|
||||
|
||||
127
crates/utils/src/glob.rs
Normal file
127
crates/utils/src/glob.rs
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2023, Stalwart Labs Ltd.
|
||||
*
|
||||
* This file is part of the Stalwart Sieve Interpreter.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
* in the LICENSE file at the top-level directory of this distribution.
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* You can be released from the requirements of the AGPLv3 license by
|
||||
* purchasing a commercial license. Please contact licensing@stalw.art
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct GlobPattern {
|
||||
pattern: Vec<PatternChar>,
|
||||
to_lower: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum PatternChar {
|
||||
WildcardMany { num: usize, match_pos: usize },
|
||||
WildcardSingle { match_pos: usize },
|
||||
Char { char: char, match_pos: usize },
|
||||
}
|
||||
|
||||
impl GlobPattern {
|
||||
pub fn compile(pattern: &str, to_lower: bool) -> Self {
|
||||
let mut chars = Vec::new();
|
||||
let mut is_escaped = false;
|
||||
let mut str = pattern.chars().peekable();
|
||||
|
||||
while let Some(char) = str.next() {
|
||||
match char {
|
||||
'*' if !is_escaped => {
|
||||
let mut num = 1;
|
||||
while let Some('*') = str.peek() {
|
||||
num += 1;
|
||||
str.next();
|
||||
}
|
||||
chars.push(PatternChar::WildcardMany { num, match_pos: 0 });
|
||||
}
|
||||
'?' if !is_escaped => {
|
||||
chars.push(PatternChar::WildcardSingle { match_pos: 0 });
|
||||
}
|
||||
'\\' if !is_escaped => {
|
||||
is_escaped = true;
|
||||
continue;
|
||||
}
|
||||
_ => {
|
||||
if is_escaped {
|
||||
is_escaped = false;
|
||||
}
|
||||
if to_lower && char.is_uppercase() {
|
||||
for char in char.to_lowercase() {
|
||||
chars.push(PatternChar::Char { char, match_pos: 0 });
|
||||
}
|
||||
} else {
|
||||
chars.push(PatternChar::Char { char, match_pos: 0 });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GlobPattern {
|
||||
pattern: chars,
|
||||
to_lower,
|
||||
}
|
||||
}
|
||||
|
||||
// Credits: Algorithm ported from https://research.swtch.com/glob
|
||||
pub fn matches(&self, value: &str) -> bool {
|
||||
let value = if self.to_lower {
|
||||
value.to_lowercase().chars().collect::<Vec<_>>()
|
||||
} else {
|
||||
value.chars().collect::<Vec<_>>()
|
||||
};
|
||||
|
||||
let mut px = 0;
|
||||
let mut nx = 0;
|
||||
let mut next_px = 0;
|
||||
let mut next_nx = 0;
|
||||
|
||||
while px < self.pattern.len() || nx < value.len() {
|
||||
match self.pattern.get(px) {
|
||||
Some(PatternChar::Char { char, .. }) => {
|
||||
if matches!(value.get(nx), Some(nc) if nc == char ) {
|
||||
px += 1;
|
||||
nx += 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Some(PatternChar::WildcardSingle { .. }) => {
|
||||
if nx < value.len() {
|
||||
px += 1;
|
||||
nx += 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Some(PatternChar::WildcardMany { .. }) => {
|
||||
next_px = px;
|
||||
next_nx = nx + 1;
|
||||
px += 1;
|
||||
continue;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
if 0 < next_nx && next_nx <= value.len() {
|
||||
px = next_px;
|
||||
nx = next_nx;
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ use std::sync::Arc;
|
||||
|
||||
pub mod codec;
|
||||
pub mod config;
|
||||
pub mod glob;
|
||||
pub mod lru_cache;
|
||||
pub mod map;
|
||||
pub mod snowflake;
|
||||
|
||||
Reference in New Issue
Block a user