adblock-rust-server 0.1.0

Server wrapper around the adblock crate using Unix domain sockets
use std::io::prelude::*;
use std::thread;
use std::os::unix::net::{UnixStream, UnixListener};
use std::io::BufReader;
use std::sync::Arc;
use std::fs;
use std::env::var;

use adblock::engine::Engine;
use adblock::lists::{FilterFormat, FilterSet};

fn handle_client(mut stream: UnixStream, blocker: Arc<Engine>) {
    let buf = BufReader::new(stream.try_clone().unwrap());
    for line in buf.lines() {
        let uline = line.unwrap();
        let mut parts = uline.split(' ');
        let mut res = String::new();

        match parts.next().unwrap() {
            "n" => {
                let source = parts.next().unwrap();
                let req_url = parts.next().unwrap();
                let req_type = parts.next().unwrap();

                let result = blocker.check_network_urls(source, req_url, req_type);

                if result.matched == true { res.push('1') } else { res.push('0') };
            },
            "c" => {
                let url = parts.next().unwrap();
                let resources = blocker.url_cosmetic_resources(url);
                let ids : Vec<String> = parts.next().unwrap().split('\t').map(|x| x.to_string()).collect();
                let classes : Vec<String> = parts.next().unwrap().split('\t').map(|x| x.to_string()).collect();

                let mut selectors = blocker.hidden_class_id_selectors(&classes, &ids, &resources.exceptions);
                let mut hides : Vec<String> = resources.hide_selectors.into_iter().collect();
                selectors.append(&mut hides);
                let mut style = selectors.join(", ");

                if style.len() != 0 {
                    style.push_str(" { display: none !important; }");
                }
                style.push('\n');

                res.push_str(&style);
            },
            _ => {
                res.push_str("Unknown code supplied");
            }
        };

        stream.write(res.as_bytes()).unwrap();
    }
}

fn main() -> std::io::Result<()> {
    let mut rules = String::new();
    let home_dir = var("HOME").unwrap();
    let lists_dir = home_dir.to_owned() + "/.config/ars/lists";

    for entry in fs::read_dir(lists_dir).unwrap() {
        let entry = entry.unwrap();
        let path = entry.path();

        if path.is_file() {
            let mut temp = String::new();
            let mut file = fs::File::open(path).unwrap();
            file.read_to_string(&mut temp).unwrap();
            rules.push_str(&temp);
        }
    }

    let mut filter_set = FilterSet::new(false);
    filter_set.add_filter_list(&rules, FilterFormat::Standard);

    let blocker = Arc::new(Engine::from_filter_set(filter_set, true));

    let socket_path = "/tmp/ars";

    if std::path::Path::new(socket_path).exists() {
        fs::remove_file(socket_path).unwrap();
    }

    let listener = UnixListener::bind(socket_path).unwrap();
    println!("init-done");

    for stream in listener.incoming() {
        match stream {
            Ok(stream) => {
                let blocker = blocker.clone();
                thread::spawn(move || handle_client(stream, blocker));
            }
            Err(err) => {
                println!("Error: {}", err);
            }
        }
    }

    Ok(())
}