summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs107
1 files changed, 95 insertions, 12 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 01b105c..ca763bc 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -11,11 +11,11 @@
11 deprecated 11 deprecated
12)] 12)]
13 13
14use adblock::blocker::BlockerError as RustBlockerError; 14use adblock::blocker::{BlockerError as RustBlockerError, Redirection};
15use adblock::blocker::BlockerResult as RustBlockerResult; 15use adblock::blocker::BlockerResult as RustBlockerResult;
16use adblock::cosmetic_filter_cache::UrlSpecificResources as RustUrlSpecificResources; 16use adblock::cosmetic_filter_cache::UrlSpecificResources as RustUrlSpecificResources;
17use adblock::engine::Engine as RustEngine; 17use adblock::engine::Engine as RustEngine;
18use adblock::lists::FilterFormat; 18use adblock::lists::{FilterFormat, ParseOptions};
19use adblock::lists::FilterSet as RustFilterSet; 19use adblock::lists::FilterSet as RustFilterSet;
20use pyo3::class::PyObjectProtocol; 20use pyo3::class::PyObjectProtocol;
21use pyo3::create_exception; 21use pyo3::create_exception;
@@ -30,6 +30,10 @@ use std::error::Error;
30use std::fmt::{self, Display}; 30use std::fmt::{self, Display};
31use std::fs; 31use std::fs;
32use std::io::{Read, Write}; 32use std::io::{Read, Write};
33use adblock::resources::{
34 AddResourceError as RustAddResourceError, MimeType, Resource, ResourceType,
35};
36
33 37
34/// Brave's adblocking library in Python! 38/// Brave's adblocking library in Python!
35#[pymodule] 39#[pymodule]
@@ -55,6 +59,7 @@ fn adblock(py: Python<'_>, m: &PyModule) -> PyResult<()> {
55 py.get_type::<BadFilterAddUnsupported>(), 59 py.get_type::<BadFilterAddUnsupported>(),
56 )?; 60 )?;
57 m.add("FilterExists", py.get_type::<FilterExists>())?; 61 m.add("FilterExists", py.get_type::<FilterExists>())?;
62 m.add("AddResourceError", py.get_type::<AddResourceError>())?;
58 Ok(()) 63 Ok(())
59} 64}
60 65
@@ -80,6 +85,13 @@ pub struct BlockerResult {
80 /// 85 ///
81 /// [1]: https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#redirect 86 /// [1]: https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#redirect
82 #[pyo3(get)] 87 #[pyo3(get)]
88 pub redirect_type: Option<String>,
89 /// Exception is not `None` when the blocker matched on an exception rule.
90 /// Effectively this means that there was a match, but the request should
91 /// not be blocked. It is a non-empty string if the blocker was initialized
92 /// from a list of rules with debugging enabled, otherwise the original
93 /// string representation is discarded to reduce memory use.
94 #[pyo3(get)]
83 pub redirect: Option<String>, 95 pub redirect: Option<String>,
84 /// Exception is not `None` when the blocker matched on an exception rule. 96 /// Exception is not `None` when the blocker matched on an exception rule.
85 /// Effectively this means that there was a match, but the request should 97 /// Effectively this means that there was a match, but the request should
@@ -102,13 +114,30 @@ pub struct BlockerResult {
102 114
103impl From<RustBlockerResult> for BlockerResult { 115impl From<RustBlockerResult> for BlockerResult {
104 fn from(br: RustBlockerResult) -> Self { 116 fn from(br: RustBlockerResult) -> Self {
117 let mut redirect: Option<String> = None;
118 let mut redirect_type: Option<String> = None;
119 if br.redirect.is_some() {
120 let resource = br.redirect.unwrap();
121 redirect = Option::from(match resource {
122 Redirection::Resource(resource) => {
123 redirect_type = Some("resource".to_string());
124 resource
125 }
126 Redirection::Url(url) => {
127 redirect_type = Some("url".to_string());
128 url
129 }
130 });
131 }
132
105 Self { 133 Self {
106 matched: br.matched, 134 matched: br.matched,
107 important: br.important, 135 important: br.important,
108 redirect: br.redirect,
109 exception: br.exception, 136 exception: br.exception,
110 filter: br.filter, 137 filter: br.filter,
111 error: br.error, 138 error: br.error,
139 redirect_type: redirect_type,
140 redirect: redirect,
112 } 141 }
113 } 142 }
114} 143}
@@ -166,6 +195,8 @@ create_exception!(adblock, DeserializationError, BlockerException);
166create_exception!(adblock, OptimizedFilterExistence, BlockerException); 195create_exception!(adblock, OptimizedFilterExistence, BlockerException);
167create_exception!(adblock, BadFilterAddUnsupported, BlockerException); 196create_exception!(adblock, BadFilterAddUnsupported, BlockerException);
168create_exception!(adblock, FilterExists, BlockerException); 197create_exception!(adblock, FilterExists, BlockerException);
198create_exception!(adblock, AddResourceError, BlockerException);
199
169 200
170impl From<BlockerError> for PyErr { 201impl From<BlockerError> for PyErr {
171 fn from(err: BlockerError) -> Self { 202 fn from(err: BlockerError) -> Self {
@@ -234,11 +265,22 @@ impl FilterSet {
234 /// 265 ///
235 /// The format is a string containing either "standard" (ABP/uBO-style) 266 /// The format is a string containing either "standard" (ABP/uBO-style)
236 /// or "hosts". 267 /// or "hosts".
237 #[pyo3(text_signature = "($self, filter_list, format)")] 268 #[pyo3(text_signature = "($self, filter_list, format, include_redirect_urls)")]
238 #[args(filter_list, format = "\"standard\"")] 269 #[args(filter_list, format = "\"standard\"", include_redirect_urls = "false")]
239 pub fn add_filter_list(&mut self, filter_list: &str, format: &str) -> PyResult<()> { 270 pub fn add_filter_list(
271 &mut self,
272 filter_list: &str,
273 format: &str,
274 include_redirect_urls: bool,
275 ) -> PyResult<()> {
240 let filter_format = filter_format_from_string(format)?; 276 let filter_format = filter_format_from_string(format)?;
241 self.filter_set.add_filter_list(filter_list, filter_format); 277 self.filter_set.add_filter_list(
278 filter_list,
279 ParseOptions {
280 format: filter_format,
281 include_redirect_urls,
282 },
283 );
242 Ok(()) 284 Ok(())
243 } 285 }
244 286
@@ -247,11 +289,22 @@ impl FilterSet {
247 /// 289 ///
248 /// The format is a string containing either "standard" (ABP/uBO-style) 290 /// The format is a string containing either "standard" (ABP/uBO-style)
249 /// or "hosts". 291 /// or "hosts".
250 #[pyo3(text_signature = "($self, filters, format)")] 292 #[pyo3(text_signature = "($self, filters, format, include_redirect_urls)")]
251 #[args(filters, format = "\"standard\"")] 293 #[args(filters, format = "\"standard\"", include_redirect_urls = "false")]
252 pub fn add_filters(&mut self, filters: Vec<String>, format: &str) -> PyResult<()> { 294 pub fn add_filters(
295 &mut self,
296 filters: Vec<String>,
297 format: &str,
298 include_redirect_urls: bool,
299 ) -> PyResult<()> {
253 let filter_format = filter_format_from_string(format)?; 300 let filter_format = filter_format_from_string(format)?;
254 self.filter_set.add_filters(&filters, filter_format); 301 self.filter_set.add_filters(
302 &filters,
303 ParseOptions {
304 format: filter_format,
305 include_redirect_urls,
306 },
307 );
255 Ok(()) 308 Ok(())
256 } 309 }
257} 310}
@@ -446,6 +499,36 @@ impl Engine {
446 blocker_result.into() 499 blocker_result.into()
447 } 500 }
448 501
502 /// Sets this engine's resources to additionally include `resource`.
503 ///
504 /// # Arguments
505 /// * `name`: Represents the primary name of the resource, often a filename
506 /// * `content_type`: How to interpret the resource data within `content`
507 /// * `content`: The resource data, encoded using standard base64 configuration
508 #[pyo3(text_signature = "($self, name, content_type, content)")]
509 pub fn add_resource(&mut self, name: &str, content_type: &str, content: &str) -> PyResult<()> {
510 let result = self.engine.add_resource(Resource {
511 name: name.to_string(),
512 aliases: vec![],
513 kind: ResourceType::Mime(MimeType::from(std::borrow::Cow::from(
514 content_type.to_string(),
515 ))),
516 content: content.to_string(),
517 });
518
519 match result {
520 Ok(_) => Ok(()),
521 Err(err) => match err {
522 RustAddResourceError::InvalidBase64Content => Err(AddResourceError::new_err(
523 "invalid base64 content".to_string(),
524 )),
525 RustAddResourceError::InvalidUtf8Content => {
526 Err(AddResourceError::new_err("invalid utf content".to_string()))
527 }
528 },
529 }
530 }
531
449 /// Serialize this blocking engine to bytes. They can then be deserialized 532 /// Serialize this blocking engine to bytes. They can then be deserialized
450 /// using `deserialize()` to get the same engine again. 533 /// using `deserialize()` to get the same engine again.
451 #[pyo3(text_signature = "($self)")] 534 #[pyo3(text_signature = "($self)")]
@@ -456,7 +539,7 @@ impl Engine {
456 } 539 }
457 540
458 fn serialize_inner(&mut self) -> PyResult<Vec<u8>> { 541 fn serialize_inner(&mut self) -> PyResult<Vec<u8>> {
459 let result = self.engine.serialize(); 542 let result = self.engine.serialize_raw();
460 match result { 543 match result {
461 Ok(x) => Ok(x), 544 Ok(x) => Ok(x),
462 Err(error) => { 545 Err(error) => {