repo_description: A fast, simple, recursive content discovery tool written in Rust.
repo_topics: content-discovery enumeration hacktoberfest pentest pentesting-tool rust url-bruteforcer web
code: use super::*;
  use crate::nlp::preprocess;
  use crate::NEAR_DUPLICATE_DISTANCE;
  use gaoya::simhash::{SimHash, SimHashBits, SimSipHasher64};
  use lazy_static::lazy_static;
  
  lazy_static! {
      /// single instance of the sip hasher used in similarity filtering
      pub static ref SIM_HASHER: SimHash<SimSipHasher64, u64, 64> =
          SimHash::<SimSipHasher64, u64, 64>::new(SimSipHasher64::new(1, 2));
  }
  
  /// Simple implementor of FeroxFilter; used to filter out responses based on the similarity of a
  /// Response body with a known response; specified using --filter-similar-to
  #[derive(Default, Debug, PartialEq, Eq, Serialize, Deserialize)]
  pub struct SimilarityFilter {
      /// Hash of Response's body to be used during similarity comparison
      pub hash: u64,
  
      /// Url originally requested for the similarity filter
      pub original_url: String,
  
      /// Maximum hamming distance allowed between two signatures
      pub cutoff: usize,
  }
  
  impl SimilarityFilter {
      /// Create a new SimilarityFilter
      pub fn new(hash: u64, original_url: String, cutoff: usize) -> Self {
          Self {
              hash,
              original_url,
              cutoff,
          }
      }
  }
  
  impl From<&FeroxResponse> for SimilarityFilter {
      fn from(response: &FeroxResponse) -> Self {
          Self::new(
              SIM_HASHER.create_signature(preprocess(response.text()).iter()),
              response.url().to_string(),
              NEAR_DUPLICATE_DISTANCE,
          )
      }
  }
  
  /// implementation of FeroxFilter for SimilarityFilter
  impl FeroxFilter for SimilarityFilter {
      /// Check `FeroxResponse::text` against what was requested from the site passed in via
      /// --filter-similar-to
      fn should_filter_response(&self, response: &FeroxResponse) -> bool {
          let other = SIM_HASHER.create_signature(preprocess(response.text()).iter());
          self.hash.hamming_distance(&other) <= self.cutoff
      }
  
      /// Compare one SimilarityFilter to another
      fn box_eq(&self, other: &dyn Any) -> bool {
          other
              .downcast_ref::<Self>()
              .is_some_and(|a| self.hash == a.hash)
      }
  
      /// Return self as Any for dynamic dispatch purposes
      fn as_any(&self) -> &dyn Any {
          self
      }
  }
  