#![allow(dead_code)]
use std::fmt;
use ffi;
pub struct ScanSettings {
settings: u32,
}
impl ScanSettings {
pub fn flags(&self) -> u32 {
self.settings
}
}
impl Default for ScanSettings {
fn default() -> ScanSettings {
ScanSettings {
settings: ffi::CL_SCAN_STDOPT,
}
}
}
impl fmt::Display for ScanSettings {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut flags = String::new();
if self.settings == ffi::CL_SCAN_RAW {
flags.push_str("CL_SCAN_RAW ");
}
if self.settings & ffi::CL_SCAN_ARCHIVE == ffi::CL_SCAN_ARCHIVE {
flags.push_str("CL_SCAN_ARCHIVE ");
}
if self.settings & ffi::CL_SCAN_MAIL == ffi::CL_SCAN_MAIL {
flags.push_str("CL_SCAN_MAIL ");
}
if self.settings & ffi::CL_SCAN_OLE2 == ffi::CL_SCAN_OLE2 {
flags.push_str("CL_SCAN_OLE2 ");
}
if self.settings & ffi::CL_SCAN_BLOCKENCRYPTED == ffi::CL_SCAN_BLOCKENCRYPTED {
flags.push_str("CL_SCAN_BLOCKENCRYPTED ");
}
if self.settings & ffi::CL_SCAN_HTML == ffi::CL_SCAN_HTML {
flags.push_str("CL_SCAN_HTML ");
}
if self.settings & ffi::CL_SCAN_PE == ffi::CL_SCAN_PE {
flags.push_str("CL_SCAN_PE ");
}
if self.settings & ffi::CL_SCAN_BLOCKBROKEN == ffi::CL_SCAN_BLOCKBROKEN {
flags.push_str("CL_SCAN_BLOCKBROKEN ");
}
if self.settings & ffi::CL_SCAN_MAILURL == ffi::CL_SCAN_MAILURL {
flags.push_str("CL_SCAN_MAILURL ");
}
if self.settings & ffi::CL_SCAN_BLOCKMAX == ffi::CL_SCAN_BLOCKMAX {
flags.push_str("CL_SCAN_BLOCKMAX ");
}
if self.settings & ffi::CL_SCAN_ALGORITHMIC == ffi::CL_SCAN_ALGORITHMIC {
flags.push_str("CL_SCAN_ALGORITHMIC ");
}
if self.settings & ffi::CL_SCAN_PHISHING_BLOCKSSL == ffi::CL_SCAN_PHISHING_BLOCKSSL {
flags.push_str("CL_SCAN_PHISHING_BLOCKSSL ");
}
if self.settings & ffi::CL_SCAN_PHISHING_BLOCKCLOAK == ffi::CL_SCAN_PHISHING_BLOCKCLOAK {
flags.push_str("CL_SCAN_PHISHING_BLOCKCLOAK ");
}
if self.settings & ffi::CL_SCAN_ELF == ffi::CL_SCAN_ELF {
flags.push_str("CL_SCAN_ELF ");
}
if self.settings & ffi::CL_SCAN_PDF == ffi::CL_SCAN_PDF {
flags.push_str("CL_SCAN_PDF ");
}
if self.settings & ffi::CL_SCAN_STRUCTURED == ffi::CL_SCAN_STRUCTURED {
flags.push_str("CL_SCAN_STRUCTURED ");
}
if self.settings & ffi::CL_SCAN_STRUCTURED_SSN_NORMAL == ffi::CL_SCAN_STRUCTURED_SSN_NORMAL
{
flags.push_str("CL_SCAN_STRUCTURED_SSN_NORMAL ");
}
if self.settings & ffi::CL_SCAN_STRUCTURED_SSN_STRIPPED
== ffi::CL_SCAN_STRUCTURED_SSN_STRIPPED
{
flags.push_str("CL_SCAN_STRUCTURED_SSN_STRIPPED ");
}
if self.settings & ffi::CL_SCAN_PARTIAL_MESSAGE == ffi::CL_SCAN_PARTIAL_MESSAGE {
flags.push_str("CL_SCAN_PARTIAL_MESSAGE ");
}
if self.settings & ffi::CL_SCAN_HEURISTIC_PRECEDENCE == ffi::CL_SCAN_HEURISTIC_PRECEDENCE {
flags.push_str("CL_SCAN_HEURISTIC_PRECEDENCE ");
}
if self.settings & ffi::CL_SCAN_BLOCKMACROS == ffi::CL_SCAN_BLOCKMACROS {
flags.push_str("CL_SCAN_BLOCKMACROS ");
}
if self.settings & ffi::CL_SCAN_ALLMATCHES == ffi::CL_SCAN_ALLMATCHES {
flags.push_str("CL_SCAN_ALLMATCHES ");
}
if self.settings & ffi::CL_SCAN_SWF == ffi::CL_SCAN_SWF {
flags.push_str("CL_SCAN_SWF ");
}
if self.settings & ffi::CL_SCAN_PARTITION_INTXN == ffi::CL_SCAN_PARTITION_INTXN {
flags.push_str("CL_SCAN_PARTITION_INTXN ");
}
if self.settings & ffi::CL_SCAN_XMLDOCS == ffi::CL_SCAN_XMLDOCS {
flags.push_str("CL_SCAN_XMLDOCS ");
}
if self.settings & ffi::CL_SCAN_HWP3 == ffi::CL_SCAN_HWP3 {
flags.push_str("CL_SCAN_HWP3 ");
}
if self.settings & ffi::CL_SCAN_FILE_PROPERTIES == ffi::CL_SCAN_FILE_PROPERTIES {
flags.push_str("CL_SCAN_FILE_PROPERTIES ");
}
if self.settings & ffi::CL_SCAN_PERFORMANCE_INFO == ffi::CL_SCAN_PERFORMANCE_INFO {
flags.push_str("CL_SCAN_PERFORMANCE_INFO ");
}
if self.settings & ffi::CL_SCAN_INTERNAL_COLLECT_SHA == ffi::CL_SCAN_INTERNAL_COLLECT_SHA {
flags.push_str("CL_SCAN_INTERNAL_COLLECT_SHA ");
}
write!(f, "{:#X}: {}", self.settings, flags.trim_right())
}
}
pub struct ScanSettingsBuilder {
current: u32,
}
impl ScanSettingsBuilder {
pub fn new() -> Self {
ScanSettingsBuilder {
current: ffi::CL_SCAN_STDOPT,
}
}
pub fn build(&self) -> ScanSettings {
ScanSettings {
settings: self.current,
}
}
pub fn clear(&mut self) -> &mut Self {
self.current = ffi::CL_SCAN_RAW;
self
}
pub fn with_flag(&mut self, flag: u32) -> &mut Self {
self.current |= flag;
self
}
pub fn enable_archive(&mut self) -> &mut Self {
self.current |= ffi::CL_SCAN_ARCHIVE;
self
}
pub fn enable_mail(&mut self) -> &mut Self {
self.current |= ffi::CL_SCAN_MAIL;
self
}
pub fn enable_mail_url(&mut self) -> &mut Self {
self.current |= ffi::CL_SCAN_MAILURL;
self
}
pub fn enable_ole2(&mut self) -> &mut Self {
self.current |= ffi::CL_SCAN_OLE2;
self
}
pub fn block_encrypted(&mut self) -> &mut Self {
self.current |= ffi::CL_SCAN_BLOCKENCRYPTED;
self
}
pub fn enable_html(&mut self) -> &mut Self {
self.current |= ffi::CL_SCAN_HTML;
self
}
pub fn enable_pe(&mut self) -> &mut Self {
self.current |= ffi::CL_SCAN_PE;
self
}
pub fn block_broken_executables(&mut self) -> &mut Self {
self.current |= ffi::CL_SCAN_BLOCKBROKEN;
self
}
pub fn block_max_limit(&mut self) -> &mut Self {
self.current |= ffi::CL_SCAN_BLOCKMAX;
self
}
pub fn enable_algorithmic(&mut self) -> &mut Self {
self.current |= ffi::CL_SCAN_ALGORITHMIC;
self
}
pub fn enable_phishing_blockssl(&mut self) -> &mut Self {
self.current |= ffi::CL_SCAN_PHISHING_BLOCKSSL;
self
}
pub fn enable_phishing_blockcloak(&mut self) -> &mut Self {
self.current |= ffi::CL_SCAN_PHISHING_BLOCKCLOAK;
self
}
pub fn enable_elf(&mut self) -> &mut Self {
self.current |= ffi::CL_SCAN_ELF;
self
}
pub fn enable_pdf(&mut self) -> &mut Self {
self.current |= ffi::CL_SCAN_PDF;
self
}
pub fn enable_structured(&mut self) -> &mut Self {
self.current |= ffi::CL_SCAN_STRUCTURED;
self
}
pub fn enable_structured_ssn_normal(&mut self) -> &mut Self {
self.current |= ffi::CL_SCAN_STRUCTURED_SSN_NORMAL;
self
}
pub fn enable_structured_ssn_stripped(&mut self) -> &mut Self {
self.current |= ffi::CL_SCAN_STRUCTURED_SSN_STRIPPED;
self
}
pub fn enable_partial_message(&mut self) -> &mut Self {
self.current |= ffi::CL_SCAN_PARTIAL_MESSAGE;
self
}
pub fn enable_heuristic_precedence(&mut self) -> &mut Self {
self.current |= ffi::CL_SCAN_HEURISTIC_PRECEDENCE;
self
}
pub fn block_macros(&mut self) -> &mut Self {
self.current |= ffi::CL_SCAN_BLOCKMACROS;
self
}
pub fn enable_swf(&mut self) -> &mut Self {
self.current |= ffi::CL_SCAN_SWF;
self
}
pub fn enable_xmldocs(&mut self) -> &mut Self {
self.current |= ffi::CL_SCAN_XMLDOCS;
self
}
pub fn enable_hwp3(&mut self) -> &mut Self {
self.current |= ffi::CL_SCAN_HWP3;
self
}
pub fn enable_file_properties(&mut self) -> &mut Self {
self.current |= ffi::CL_SCAN_FILE_PROPERTIES;
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn builder_defaults_to_standard_opts() {
let settings = ScanSettingsBuilder::new().build();
assert_eq!(settings.settings, ffi::CL_SCAN_STDOPT);
}
#[test]
fn builder_clear_success() {
let settings = ScanSettingsBuilder::new().clear().build();
assert_eq!(settings.settings, 0);
}
#[test]
fn builder_just_pdf_success() {
let settings = ScanSettingsBuilder::new().clear().enable_pdf().build();
assert_eq!(settings.settings, ffi::CL_SCAN_PDF);
}
#[test]
fn builder_normal_files_success() {
let settings = ScanSettingsBuilder::new()
.clear()
.enable_pdf()
.enable_html()
.enable_pe()
.build();
assert_eq!(
settings.settings,
ffi::CL_SCAN_PDF | ffi::CL_SCAN_HTML | ffi::CL_SCAN_PE
);
}
#[test]
fn builder_all_success() {
let settings = ScanSettingsBuilder::new()
.clear()
.enable_algorithmic()
.enable_archive()
.enable_elf()
.enable_file_properties()
.enable_heuristic_precedence()
.enable_html()
.enable_hwp3()
.enable_mail()
.enable_mail_url()
.enable_ole2()
.enable_partial_message()
.enable_pdf()
.enable_pe()
.enable_phishing_blockcloak()
.enable_phishing_blockssl()
.enable_structured()
.enable_structured_ssn_normal()
.enable_structured_ssn_stripped()
.enable_swf()
.enable_xmldocs()
.block_broken_executables()
.block_encrypted()
.block_macros()
.block_max_limit()
.build();
assert_eq!(
settings.settings,
ffi::CL_SCAN_ARCHIVE | ffi::CL_SCAN_MAIL | ffi::CL_SCAN_OLE2
| ffi::CL_SCAN_BLOCKENCRYPTED | ffi::CL_SCAN_HTML | ffi::CL_SCAN_PE
| ffi::CL_SCAN_BLOCKBROKEN | ffi::CL_SCAN_MAILURL
| ffi::CL_SCAN_BLOCKMAX | ffi::CL_SCAN_ALGORITHMIC
| ffi::CL_SCAN_PHISHING_BLOCKSSL | ffi::CL_SCAN_PHISHING_BLOCKCLOAK
| ffi::CL_SCAN_ELF | ffi::CL_SCAN_PDF | ffi::CL_SCAN_STRUCTURED
| ffi::CL_SCAN_STRUCTURED_SSN_NORMAL
| ffi::CL_SCAN_STRUCTURED_SSN_STRIPPED | ffi::CL_SCAN_PARTIAL_MESSAGE
| ffi::CL_SCAN_HEURISTIC_PRECEDENCE | ffi::CL_SCAN_BLOCKMACROS
| ffi::CL_SCAN_SWF | ffi::CL_SCAN_XMLDOCS | ffi::CL_SCAN_HWP3
| ffi::CL_SCAN_FILE_PROPERTIES
);
}
#[test]
fn display_settings_raw_success() {
let string_settings = ScanSettings {
settings: ffi::CL_SCAN_RAW,
}.to_string();
assert_eq!(string_settings, "0x0: CL_SCAN_RAW");
}
#[test]
fn display_settings_standard_options_success() {
let string_settings = ScanSettings {
settings: ffi::CL_SCAN_STDOPT,
}.to_string();
assert!(string_settings.contains("CL_SCAN_ARCHIVE"));
assert!(string_settings.contains("CL_SCAN_MAIL"));
assert!(string_settings.contains("CL_SCAN_OLE2"));
assert!(string_settings.contains("CL_SCAN_PDF"));
assert!(string_settings.contains("CL_SCAN_HTML"));
assert!(string_settings.contains("CL_SCAN_PE"));
assert!(string_settings.contains("CL_SCAN_ALGORITHMIC"));
assert!(string_settings.contains("CL_SCAN_ELF"));
assert!(string_settings.contains("CL_SCAN_SWF"));
assert!(string_settings.contains("CL_SCAN_XMLDOCS"));
assert!(string_settings.contains("CL_SCAN_HWP3"));
}
#[test]
fn settings_default_to_standard() {
let settings: ScanSettings = Default::default();
assert_eq!(settings.settings, ffi::CL_SCAN_STDOPT);
}
}