/******************************************************************************* uBlock Origin - a comprehensive, efficient content blocker Copyright (C) 2019-present Raymond Hill This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. Home: https://github.com/gorhill/uBlock */ import { registerScriptlet } from './base.js'; import { safeSelf } from './safe-self.js'; /******************************************************************************/ export function getRandomTokenFn() { const safe = safeSelf(); return safe.String_fromCharCode(Date.now() % 26 + 97) + safe.Math_floor(safe.Math_random() * 982451653 + 982451653).toString(36); } registerScriptlet(getRandomTokenFn, { name: 'get-random-token.fn', dependencies: [ safeSelf, ], }); /******************************************************************************/ export function getExceptionTokenFn() { const token = getRandomTokenFn(); const oe = self.onerror; self.onerror = function(msg, ...args) { if ( typeof msg === 'string' && msg.includes(token) ) { return true; } if ( oe instanceof Function ) { return oe.call(this, msg, ...args); } }.bind(); return token; } registerScriptlet(getExceptionTokenFn, { name: 'get-exception-token.fn', dependencies: [ getRandomTokenFn, ], }); /******************************************************************************/ export function parsePropertiesToMatchFn(propsToMatch, implicit = '') { const safe = safeSelf(); const needles = new Map(); if ( propsToMatch === undefined || propsToMatch === '' ) { return needles; } const options = { canNegate: true }; for ( const needle of safe.String_split.call(propsToMatch, /\s+/) ) { let [ prop, pattern ] = safe.String_split.call(needle, ':'); if ( prop === '' ) { continue; } if ( pattern !== undefined && /[^$\w -]/.test(prop) ) { prop = `${prop}:${pattern}`; pattern = undefined; } if ( pattern !== undefined ) { needles.set(prop, safe.initPattern(pattern, options)); } else if ( implicit !== '' ) { needles.set(implicit, safe.initPattern(prop, options)); } } return needles; } registerScriptlet(parsePropertiesToMatchFn, { name: 'parse-properties-to-match.fn', dependencies: [ safeSelf, ], }); /******************************************************************************/ export function matchObjectPropertiesFn(propNeedles, ...objs) { const safe = safeSelf(); const matched = []; for ( const obj of objs ) { if ( obj instanceof Object === false ) { continue; } for ( const [ prop, details ] of propNeedles ) { let value = obj[prop]; if ( value === undefined ) { continue; } if ( typeof value !== 'string' ) { try { value = safe.JSON_stringify(value); } catch { } if ( typeof value !== 'string' ) { continue; } } if ( safe.testPattern(details, value) === false ) { return; } matched.push(`${prop}: ${value}`); } } return matched; } registerScriptlet(matchObjectPropertiesFn, { name: 'match-object-properties.fn', dependencies: [ safeSelf, ], }); /******************************************************************************/