mod date_time_filter;
mod status_filter;
mod str_filter;
mod method_filter;
mod time_filter;
pub use {
date_time_filter::*,
method_filter::*,
status_filter::*,
str_filter::*,
time_filter::*,
};
use {
crate::*,
smallvec::*,
std::{
str::FromStr,
},
};
pub enum Filter {
DateTime(DateTimeFilter),
Ip(StrFilter),
Method(MethodFilter),
Path(StrFilter),
Referer(StrFilter),
Status(StatusFilter),
Time(TimeFilter),
}
impl Filter {
pub fn accepts(&self, line: &LogLine) -> bool {
match self {
Self::DateTime(f) => f.contains(line.date_time),
Self::Ip(f) => f.accepts(&line.remote_addr),
Self::Method(f) => f.contains(line.method),
Self::Path(f) => f.accepts(&line.path),
Self::Referer(f) => f.accepts(&line.referer),
Self::Status(f) => f.accepts(line.status),
Self::Time(f) => f.contains(line.time()),
}
}
pub fn field_name(&self) -> &'static str {
match self {
Self::DateTime(_) => "date", Self::Ip(_) => "remote address",
Self::Method(_) => "method",
Self::Path(_) => "path",
Self::Referer(_) => "referer", Self::Status(_) => "status",
Self::Time(_) => "time",
}
}
}
pub struct Filtering {
pub pattern: String,
pub filter: Filter,
pub removed_count: usize,
}
impl Filtering {
pub fn new(pattern: &str, filter: Filter) -> Self {
Self {
pattern: pattern.to_owned(),
filter,
removed_count: 0,
}
}
}
pub struct Filterer {
pub first_date: Date,
pub filterings: SmallVec<[Filtering; 5]>,
}
impl Filterer {
pub fn new(
args: &args::Args,
first_date: Date,
last_date: Date,
) -> Result<Self, RhitError> {
let (default_year, default_month) = unique_year_month(first_date, last_date);
let mut filterings = SmallVec::new();
if let Some(s) = &args.date {
filterings.push(Filtering::new(
s,
Filter::DateTime(DateTimeFilter::new(s, default_year, default_month)?),
));
}
if let Some(s) = &args.ip {
filterings.push(Filtering::new(
s,
Filter::Ip(StrFilter::new(s)?),
));
}
if let Some(s) = &args.method {
filterings.push(Filtering::new(
s,
Filter::Method(MethodFilter::from_string(s)),
));
}
if let Some(s) = &args.path {
filterings.push(Filtering::new(
s,
Filter::Path(StrFilter::new(s)?),
));
}
if let Some(s) = &args.referer {
filterings.push(Filtering::new(
s,
Filter::Referer(StrFilter::new(s)?),
));
}
if let Some(s) = &args.status {
filterings.push(Filtering::new(
s,
Filter::Status(StatusFilter::from_str(s)?),
));
}
if let Some(s) = &args.time {
filterings.push(Filtering::new(
s,
Filter::Time(TimeFilter::from_str(s)?),
));
}
Ok(Self { first_date, filterings })
}
pub fn date_filter(&self) -> Option<&DateTimeFilter> {
for i in 0..self.filterings.len() {
if let Filter::DateTime(f) = &self.filterings[i].filter {
return Some(f);
}
}
None
}
pub fn accepts(&mut self, line: &LogLine) -> bool {
for filtering in &mut self.filterings {
if !filtering.filter.accepts(line) {
filtering.removed_count += 1;
return false;
}
}
true
}
pub fn has_filters(&self) -> bool {
!self.filterings.is_empty()
}
}