1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// all API conventions base mapped from https://www.leagueoflegends.com/en-pl/champions/kayle/

#[macro_use]
extern crate lazy_static;

mod strings;
mod utils;
use crate::strings::CaseInsensitiveString;
use select::document::Document;
use select::predicate::Name;
use std::collections::HashSet;
use utils::{convert_abs_path, convert_base_path, set_panic_hook};
use wasm_bindgen::prelude::*;

#[cfg(feature = "wee_alloc")]
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;

#[wasm_bindgen]
extern "C" {
    fn alert(s: &str);
}

#[wasm_bindgen]
/// perform an audit based on tree rules using dom APIs at runtime with speed.
pub fn kayle() {
    set_panic_hook();
    alert("Kayle!");
}

#[wasm_bindgen]
/// setup a structure tree alg for parsing and find links in document. Allow user to perform hybrid audits realtime.
pub fn radiant_blast(res: &str, domain: &str) -> Box<[JsValue]> {
    set_panic_hook();

    lazy_static! {
        /// include only list of resources
        static ref ONLY_RESOURCES: HashSet<CaseInsensitiveString> = {
            let mut m: HashSet<CaseInsensitiveString> = HashSet::with_capacity(14);

            m.extend([
                "html", "htm", "asp", "aspx", "php", "jps", "jpsx",
                // handle .. prefix for urls ending with an extra ending
                ".html", ".htm", ".asp", ".aspx", ".php", ".jps", ".jpsx",
            ].map(|s| s.into()));

            m
        };
    }

    let links = match url::Url::parse(domain) {
        Ok(base) => {
            let base_url = convert_base_path(base);
            let parent_host_scheme = base_url.scheme();
            let parent_host = base_url.host_str().unwrap_or_default();

            Document::from(res)
                .find(Name("a"))
                .filter_map(|n| match n.attr("href") {
                    Some(link) => {
                        let mut abs = convert_abs_path(&base_url, link);
                        let mut can_process = match abs.host_str() {
                            Some(host) => parent_host.ends_with(host),
                            _ => false,
                        };

                        let process = if can_process {
                            if abs.scheme() != parent_host_scheme {
                                let _ = abs.set_scheme(parent_host_scheme);
                            }

                            let h = abs.as_str();
                            let hlen = h.len();

                            if hlen > 4 && !h.ends_with("/") {
                                let hchars = &h[hlen - 5..hlen];
                                if let Some(position) = hchars.find('.') {
                                    let resource_ext = &hchars[position + 1..hchars.len()];

                                    if !ONLY_RESOURCES.contains(&resource_ext.into()) {
                                        can_process = false;
                                    }
                                }
                            }

                            if can_process {
                                Some(JsValue::from_str(&h.to_string()))
                            } else {
                                None
                            }
                        } else {
                            None
                        };

                        process
                    }
                    _ => None,
                })
                .collect::<Vec<_>>()
        }
        _ => Document::from(res)
            .find(Name("a"))
            .filter_map(|n| match n.attr("href") {
                Some(link) => Some(JsValue::from_str(link)),
                _ => None,
            })
            .collect::<Vec<_>>(),
    };

    links.into_boxed_slice()
}

#[wasm_bindgen]
/// try to fix all possible issues using a spec against the tree.
pub fn celestial_blessing() {
    alert("Celestial blessing from kayle!");
}

#[wasm_bindgen]
/// use gpu to accelerate layout rendering or workers.
pub fn starfire_spellblade() {
    alert("Starfire Spellblase from kayle!");
}

#[wasm_bindgen]
/// Perform the a judgement against a page to determine effort, access, and more.
pub fn divine_judgement() {
    alert("Divine judgement from kayle!");
}