diff --git a/.gitignore b/.gitignore index 09fe806ec..bd7ef01ea 100644 --- a/.gitignore +++ b/.gitignore @@ -128,6 +128,9 @@ __pypackages__/ # Rope project settings .ropeproject +# pycharm project settings +.idea + # mypy .mypy_cache/ .dmypy.json diff --git a/Cargo.lock b/Cargo.lock index df7e282ba..d6438cd42 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "adblock" -version = "0.3.13" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13df3d8a7e24ea2cc711b82a047ef2b9f743aa6580bea2552fcec68f0289603c" +checksum = "52bdd00675903fd86d5d3109bb7899387c85cab52f990d14481546cb9a7102bf" dependencies = [ "addr", "base64", @@ -17,7 +17,8 @@ dependencies = [ "once_cell", "percent-encoding", "regex", - "rmp-serde", + "rmp-serde 0.13.7", + "rmp-serde 0.15.5", "seahash", "serde", "twoway", @@ -28,7 +29,7 @@ dependencies = [ name = "adblock" version = "0.5.1" dependencies = [ - "adblock 0.3.13", + "adblock 0.4.3", "pyo3", ] @@ -59,9 +60,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64" @@ -71,9 +72,9 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] name = "bitflags" -version = "1.2.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "byteorder" @@ -89,9 +90,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "crc32fast" -version = "1.2.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ "cfg-if", ] @@ -104,9 +105,9 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "flate2" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd3aec53de10fe96d7d8c565eb17f2c687bb5518a2ec453b5b1252964526abe0" +checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" dependencies = [ "cfg-if", "crc32fast", @@ -126,9 +127,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89829a5d69c23d348314a7ac337fe39173b61149a9864deabd260983aed48c21" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" dependencies = [ "matches", "unicode-bidi", @@ -160,48 +161,48 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.9" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ "cfg-if", ] [[package]] name = "itertools" -version = "0.9.0" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" dependencies = [ "either", ] [[package]] name = "libc" -version = "0.2.93" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41" +checksum = "06e509672465a0504304aa87f9f176f2b2b716ed8fb105ebe5c02dc6dce96a94" [[package]] name = "lock_api" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3c91c24eae6777794bb1997ad98bbb87daf92890acab859f7eaa4320333176" +checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" dependencies = [ "scopeguard", ] [[package]] name = "matches" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "memchr" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "miniz_oxide" @@ -224,15 +225,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" +checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" [[package]] name = "parking_lot" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", @@ -241,9 +242,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" dependencies = [ "cfg-if", "instant", @@ -286,27 +287,27 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro2" -version = "1.0.26" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" dependencies = [ "unicode-xid", ] [[package]] name = "psl" -version = "2.0.18" +version = "2.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0cbbbcd909251c04efa3c0dda636f26a9e5b91734d5ce119212528b8ba32d55" +checksum = "2f51974f40b58fd94008d3c88fa47cf1c7a58bd4e85deb0d4390bc156b0a9625" dependencies = [ "psl-types", ] [[package]] name = "psl-types" -version = "2.0.7" +version = "2.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66b398073e7cdd6f05934389a8f5961e3aabfa66675b6f440df4e2c793d51a4f" +checksum = "e8eda7c62d9ecaafdf8b62374c006de0adf61666ae96a96ba74a37134aa4e470" [[package]] name = "pyo3" @@ -358,18 +359,18 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.9" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" dependencies = [ "proc-macro2", ] [[package]] name = "redox_syscall" -version = "0.2.5" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" dependencies = [ "bitflags", ] @@ -412,6 +413,17 @@ dependencies = [ "serde", ] +[[package]] +name = "rmp-serde" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "723ecff9ad04f4ad92fe1c8ca6c20d2196d9286e9c60727c4cb5511629260e9d" +dependencies = [ + "byteorder", + "rmp", + "serde", +] + [[package]] name = "scopeguard" version = "1.1.0" @@ -426,18 +438,18 @@ checksum = "58f57ca1d128a43733fd71d583e837b1f22239a37ebea09cde11d8d9a9080f47" [[package]] name = "serde" -version = "1.0.125" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.125" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d" +checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" dependencies = [ "proc-macro2", "quote", @@ -446,15 +458,15 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.6.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" [[package]] name = "syn" -version = "1.0.69" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48fe99c6bd8b1cc636890bcc071842de909d902c81ac7dab53ba33c421ab8ffb" +checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" dependencies = [ "proc-macro2", "quote", @@ -463,9 +475,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.2.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b5220f05bb7de7f3f53c7c065e1199b3172696fe2db9f9c4d8ad9b4ee74c342" +checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" dependencies = [ "tinyvec_macros", ] @@ -478,9 +490,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "twoway" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b40075910de3a912adbd80b5d8bad6ad10a23eeb1f5bf9d4006839e899ba5bc" +checksum = "c57ffb460d7c24cd6eda43694110189030a3d1dfe418416d9468fd1c1d290b47" dependencies = [ "memchr", "unchecked-index", @@ -494,27 +506,24 @@ checksum = "eeba86d422ce181a719445e51872fa30f1f7413b62becb52e95ec91aa262d85c" [[package]] name = "unicode-bidi" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeb8be209bb1c96b7c177c7420d26e04eccacb0eeae6b980e35fcb74678107e0" -dependencies = [ - "matches", -] +checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" [[package]] name = "unicode-normalization" -version = "0.1.17" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07fbfce1c8a97d547e8b5334978438d9d6ec8c20e38f56d4a4374d181493eaef" +checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" dependencies = [ "tinyvec", ] [[package]] name = "unicode-xid" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" [[package]] name = "unindent" @@ -524,9 +533,9 @@ checksum = "f14ee04d9415b52b3aeab06258a3f07093182b88ba0f9b8d203f211a7a7d41c7" [[package]] name = "url" -version = "2.2.1" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ccd964113622c8e9322cfac19eb1004a07e636c545f325da085d5cdde6f1f8b" +checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" dependencies = [ "form_urlencoded", "idna", diff --git a/Cargo.toml b/Cargo.toml index 6ac767b00..858d4f6fc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ requires-python = ">=3.6" debug = true [dependencies] -adblock = { version = "=0.3.13", default-features = false, features = ["full-regex-handling", "embedded-domain-resolver"] } +adblock = { version = "=0.4.3", default-features = false, features = ["full-regex-handling", "embedded-domain-resolver"] } pyo3 = { version = "0.15", features = ["abi3-py36", "extension-module"] } [lib] diff --git a/adblock/__init__.py b/adblock/__init__.py index 85d361402..b231aeb0d 100644 --- a/adblock/__init__.py +++ b/adblock/__init__.py @@ -11,6 +11,9 @@ OptimizedFilterExistence, BadFilterAddUnsupported, FilterExists, + AddResourceException, + InvalidUtf8ContentError, + InvalidBase64ContentError, ) @@ -26,4 +29,7 @@ "OptimizedFilterExistence", "BadFilterAddUnsupported", "FilterExists", + "AddResourceException", + "InvalidUtf8ContentError", + "InvalidBase64ContentError", ) diff --git a/adblock/adblock.pyi b/adblock/adblock.pyi index 051567478..9fae1dab3 100644 --- a/adblock/adblock.pyi +++ b/adblock/adblock.pyi @@ -21,10 +21,20 @@ class BadFilterAddUnsupported(BlockerException): class FilterExists(BlockerException): pass +class AddResourceException(AdblockException): + pass + +class InvalidUtf8ContentError(AddResourceException): + pass + +class InvalidBase64ContentError(AddResourceException): + pass + class BlockerResult: matched: bool explicit_cancel: bool important: bool + redirect_type: Optional[str] redirect: Optional[str] exception: Optional[str] filter: Optional[str] @@ -43,9 +53,19 @@ class UrlSpecificResources: class FilterSet: def __init__(self, debug: bool = False) -> None: pass - def add_filter_list(self, filter_list: str, format: str = "standard") -> None: + def add_filter_list( + self, + filter_list: str, + format: str = "standard", + include_redirect_urls: bool = False, + ) -> None: pass - def add_filters(self, filters: List[str], format: str = "standard") -> None: + def add_filters( + self, + filters: List[str], + format: str = "standard", + include_redirect_urls: bool = False, + ) -> None: pass class Engine: @@ -93,6 +113,8 @@ class Engine: pass def tag_exists(self, tag: str) -> bool: pass + def add_resource(self, name: str, content_type: str, content: str) -> bool: + pass def url_cosmetic_resources(self, url: str) -> UrlSpecificResources: pass def hidden_class_id_selectors( diff --git a/pyproject.toml b/pyproject.toml index 8bbdb76da..c3656a497 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,5 +13,5 @@ pytest = "*" toml = "*" [build-system] -requires = ["maturin"] -build-backend = "maturin" \ No newline at end of file +requires = ["maturin>=0.12,<0.13"] +build-backend = "maturin" diff --git a/src/lib.rs b/src/lib.rs index 01b105c2f..9117254dc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,12 +11,12 @@ deprecated )] -use adblock::blocker::BlockerError as RustBlockerError; use adblock::blocker::BlockerResult as RustBlockerResult; +use adblock::blocker::{BlockerError as RustBlockerError, Redirection}; use adblock::cosmetic_filter_cache::UrlSpecificResources as RustUrlSpecificResources; use adblock::engine::Engine as RustEngine; -use adblock::lists::FilterFormat; use adblock::lists::FilterSet as RustFilterSet; +use adblock::lists::{FilterFormat, ParseOptions}; use pyo3::class::PyObjectProtocol; use pyo3::create_exception; use pyo3::exceptions::PyException; @@ -24,6 +24,9 @@ use pyo3::prelude::*; use pyo3::types::PyBytes; use pyo3::PyErr; +use adblock::resources::{ + AddResourceError as RustAddResourceError, MimeType, Resource, ResourceType, +}; use std::collections::HashMap; use std::collections::HashSet; use std::error::Error; @@ -55,6 +58,18 @@ fn adblock(py: Python<'_>, m: &PyModule) -> PyResult<()> { py.get_type::(), )?; m.add("FilterExists", py.get_type::())?; + m.add( + "AddResourceException", + py.get_type::(), + )?; + m.add( + "InvalidBase64ContentError", + py.get_type::(), + )?; + m.add( + "InvalidUtf8ContentError", + py.get_type::(), + )?; Ok(()) } @@ -80,6 +95,13 @@ pub struct BlockerResult { /// /// [1]: https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#redirect #[pyo3(get)] + pub redirect_type: Option, + /// Exception is not `None` when the blocker matched on an exception rule. + /// Effectively this means that there was a match, but the request should + /// not be blocked. It is a non-empty string if the blocker was initialized + /// from a list of rules with debugging enabled, otherwise the original + /// string representation is discarded to reduce memory use. + #[pyo3(get)] pub redirect: Option, /// Exception is not `None` when the blocker matched on an exception rule. /// Effectively this means that there was a match, but the request should @@ -102,13 +124,23 @@ pub struct BlockerResult { impl From for BlockerResult { fn from(br: RustBlockerResult) -> Self { + let (redirect, redirect_type) = if let Some(resource) = br.redirect { + match resource { + Redirection::Resource(resource) => (Some(resource), Some("resource".to_string())), + Redirection::Url(url) => (Some(url), Some("url".to_string())), + } + } else { + (None, None) + }; + Self { matched: br.matched, important: br.important, - redirect: br.redirect, exception: br.exception, filter: br.filter, error: br.error, + redirect_type, + redirect, } } } @@ -161,6 +193,9 @@ impl Display for BlockerError { create_exception!(adblock, AdblockException, PyException); create_exception!(adblock, BlockerException, AdblockException); +create_exception!(adblock, AddResourceException, AdblockException); +create_exception!(adblock, InvalidBase64ContentError, AddResourceException); +create_exception!(adblock, InvalidUtf8ContentError, AddResourceException); create_exception!(adblock, SerializationError, BlockerException); create_exception!(adblock, DeserializationError, BlockerException); create_exception!(adblock, OptimizedFilterExistence, BlockerException); @@ -234,11 +269,22 @@ impl FilterSet { /// /// The format is a string containing either "standard" (ABP/uBO-style) /// or "hosts". - #[pyo3(text_signature = "($self, filter_list, format)")] - #[args(filter_list, format = "\"standard\"")] - pub fn add_filter_list(&mut self, filter_list: &str, format: &str) -> PyResult<()> { + #[pyo3(text_signature = "($self, filter_list, format, include_redirect_urls)")] + #[args(filter_list, format = "\"standard\"", include_redirect_urls = "false")] + pub fn add_filter_list( + &mut self, + filter_list: &str, + format: &str, + include_redirect_urls: bool, + ) -> PyResult<()> { let filter_format = filter_format_from_string(format)?; - self.filter_set.add_filter_list(filter_list, filter_format); + self.filter_set.add_filter_list( + filter_list, + ParseOptions { + format: filter_format, + include_redirect_urls, + }, + ); Ok(()) } @@ -247,11 +293,22 @@ impl FilterSet { /// /// The format is a string containing either "standard" (ABP/uBO-style) /// or "hosts". - #[pyo3(text_signature = "($self, filters, format)")] - #[args(filters, format = "\"standard\"")] - pub fn add_filters(&mut self, filters: Vec, format: &str) -> PyResult<()> { + #[pyo3(text_signature = "($self, filters, format, include_redirect_urls)")] + #[args(filters, format = "\"standard\"", include_redirect_urls = "false")] + pub fn add_filters( + &mut self, + filters: Vec, + format: &str, + include_redirect_urls: bool, + ) -> PyResult<()> { let filter_format = filter_format_from_string(format)?; - self.filter_set.add_filters(&filters, filter_format); + self.filter_set.add_filters( + &filters, + ParseOptions { + format: filter_format, + include_redirect_urls, + }, + ); Ok(()) } } @@ -446,6 +503,36 @@ impl Engine { blocker_result.into() } + /// Sets this engine's resources to additionally include `resource`. + /// + /// # Arguments + /// * `name`: Represents the primary name of the resource, often a filename + /// * `content_type`: How to interpret the resource data within `content` + /// * `content`: The resource data, encoded using standard base64 configuration + #[pyo3(text_signature = "($self, name, content_type, content)")] + pub fn add_resource(&mut self, name: &str, content_type: &str, content: &str) -> PyResult<()> { + let result = self.engine.add_resource(Resource { + name: name.to_string(), + aliases: vec![], + kind: ResourceType::Mime(MimeType::from(std::borrow::Cow::from( + content_type.to_string(), + ))), + content: content.to_string(), + }); + + match result { + Ok(_) => Ok(()), + Err(err) => match err { + RustAddResourceError::InvalidBase64Content => Err( + InvalidBase64ContentError::new_err("invalid base64 content".to_string()), + ), + RustAddResourceError::InvalidUtf8Content => Err(InvalidUtf8ContentError::new_err( + "invalid utf content".to_string(), + )), + }, + } + } + /// Serialize this blocking engine to bytes. They can then be deserialized /// using `deserialize()` to get the same engine again. #[pyo3(text_signature = "($self)")] @@ -456,7 +543,7 @@ impl Engine { } fn serialize_inner(&mut self) -> PyResult> { - let result = self.engine.serialize(); + let result = self.engine.serialize_raw(); match result { Ok(x) => Ok(x), Err(error) => { diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py index becf1079b..e1c357c55 100644 --- a/tests/test_exceptions.py +++ b/tests/test_exceptions.py @@ -1,11 +1,35 @@ import adblock +import pytest def test_correct_baseclasses(): assert issubclass(adblock.AdblockException, Exception) assert issubclass(adblock.BlockerException, adblock.AdblockException) + assert issubclass(adblock.AddResourceException, adblock.AdblockException) + assert issubclass(adblock.InvalidUtf8ContentError, adblock.AddResourceException) + assert issubclass(adblock.InvalidBase64ContentError, adblock.AddResourceException) assert issubclass(adblock.SerializationError, adblock.BlockerException) assert issubclass(adblock.DeserializationError, adblock.BlockerException) assert issubclass(adblock.OptimizedFilterExistence, adblock.BlockerException) assert issubclass(adblock.BadFilterAddUnsupported, adblock.BlockerException) assert issubclass(adblock.FilterExists, adblock.BlockerException) + + +def test_add_resource_error(): + filter_set = adblock.FilterSet() + engine = adblock.Engine(filter_set=filter_set) + + with pytest.raises(adblock.InvalidBase64ContentError) as exc: + engine.add_resource(name="aa", content_type="image/jpeg", content="111") + assert "invalid base64 content" in str(exc.value) + + with pytest.raises(adblock.InvalidUtf8ContentError) as exc: + # // Ensure any text contents are also valid utf8 + # MimeType::ApplicationJavascript | MimeType::TextPlain | MimeType::TextHtml => { + # let _ = String::from_utf8(decoded)?; + # } + # xOO6ww== => base64.b64encode('你好'.encode('gbk')) + engine.add_resource( + name="aa", content_type="application/javascript", content="xOO6ww==" + ) + assert "invalid utf content" in str(exc.value) diff --git a/tests/test_redirect.py b/tests/test_redirect.py new file mode 100644 index 000000000..cca3a9160 --- /dev/null +++ b/tests/test_redirect.py @@ -0,0 +1,77 @@ +import adblock + + +def test_redirect_worked_as_excepted_with_include_redirect_urls(): + # https://github.com/brave/adblock-rust/blob/b7f29af8c0a0d000201d8d769b6a0b25a9dd4e89/src/blocker.rs#L1242 + filter_set = adblock.FilterSet() + filter_set.add_filter_list( + "||foo.com$important,redirect-url=http://xyz.com", include_redirect_urls=True + ) + + engine = adblock.Engine(filter_set=filter_set) + + res = engine.check_network_urls("https://foo.com", "https://foo.com", "script") + assert res.matched is True + assert res.important is True + assert res.redirect_type == "url" + assert res.redirect == "http://xyz.com" + + +def test_redirect_url_is_not_recognized_without_include_redirect_urls(): + # https://github.com/brave/adblock-rust/blob/b7f29af8c0a0d000201d8d769b6a0b25a9dd4e89/src/blocker.rs#L1267 + filter_set2 = adblock.FilterSet() + filter_set2.add_filter_list( + "||foo.com$important,redirect-url=http://xyz.com", include_redirect_urls=False + ) + + engine2 = adblock.Engine(filter_set=filter_set2) + + res = engine2.check_network_urls("https://foo.com", "https://foo.com", "script") + assert res.matched is False + assert res.redirect is None + assert res.redirect_type is None + + +def test_redirect_url_exception(): + # https://github.com/brave/adblock-rust/blob/b7f29af8c0a0d000201d8d769b6a0b25a9dd4e89/src/blocker.rs#L1314 + filter_set = adblock.FilterSet(debug=True) + filter_set.add_filter_list( + """ + ||imdb-video.media-imdb.com$media,redirect-url=http://xyz.com + @@||imdb-video.media-imdb.com^$domain=imdb.com + """, + include_redirect_urls=True, + ) + + engine2 = adblock.Engine(filter_set=filter_set, optimize=False) + + res = engine2.check_network_urls( + "https://imdb-video.media-imdb.com/kBOeI88k1o23eNAi", + "https://www.imdb.com/video/13", + "media", + ) + assert res.matched is False + assert res.redirect == "http://xyz.com" + assert res.redirect_type == "url" + assert res.exception == "@@||imdb-video.media-imdb.com^$domain=imdb.com" + + +def test_redirect_with_custom_resource(): + filters = adblock.FilterSet() + filters.add_filter_list("-advertisement-$redirect=test\n") + + engine = adblock.Engine(filter_set=filters) + engine.add_resource( + name="test", content_type="application/javascript", content="YWxlcnQoMSk=" + ) + + result = engine.check_network_urls( + url="http://example.com/-advertisement-icon.", + source_url="example.com", + request_type="image", + ) + + assert result.matched + assert not result.exception + assert not result.important + assert result.redirect == "data:application/javascript;base64,YWxlcnQoMSk="