PageSourceSearch

https://www.cruise1323.com.au/wp-content/themes/arn/frontend/lib/abd.js

js cruise1323.com.au collected 2026-09-25 05:54:43 UTC 14,928 bytes, 635 lines download raw bytes

1// ===============================================
2// AdBlock detector
3//
4// Attempts to detect the presence of Ad Blocker software and notify listener of its existence.
5// Copyright (c) 2017 IAB
6//
7// The BSD-3 License
8// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
9// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
10// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
11// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
12// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13// ===============================================
14
15/**
16 * @name window.adblockDetector
17 *
18 * IAB Adblock detector.
19 * Usage: window.adblockDetector.init(options);
20 *
21 * Options object settings
22 *
23 *	@prop debug:  boolean
24 *         Flag to indicate additional debug output should be printed to console
25 *
26 *	@prop found: @function
27 *         Callback function to fire if adblock is detected
28 *
29 *	@prop notfound: @function
30 *         Callback function to fire if adblock is not detected.
31 *         NOTE: this function may fire multiple times and give false negative
32 *         responses during a test until adblock is successfully detected.
33 *
34 *	@prop complete: @function
35 *         Callback function to fire once a round of testing is complete.
36 *         The test result (boolean) is included as a parameter to callback
37 *
38 * example: 	window.adblockDetector.init(
39 {
40					found: function(){ ...},
41 					notFound: function(){...}
42				}
43 );
44 *
45 *
46 */
47
48"use strict";
49(function(win) {
50
51  var version = '1.0';
52
53  var ofs = 'offset', cl = 'client';
54  var noop = function(){};
55
56  var testedOnce = false;
57  var testExecuting = false;
58
59  var isOldIEevents = (win.addEventListener === undefined);
60
61  /**
62   * Options set with default options initialized
63   *
64   */
65  var _options = {
66    loopDelay: 50,
67    maxLoop: 5,
68    debug: true,
69    found: noop, 					// function to fire when adblock detected
70    notfound: noop, 				// function to fire if adblock not detected after testing
71    complete: noop  				// function to fire after testing completes, passing result as parameter
72  }
73
74  function parseAsJson(data){
75    var result, fnData;
76    try{
77      result = JSON.parse(data);
78    }
79    catch(ex){
80      try{
81        fnData = new Function("return " + data);
82        result = fnData();
83      }
84      catch(ex){
85        log('Failed secondary JSON parse', true);
86      }
87    }
88
89    return result;
90  }
91
92  /**
93   * Ajax helper object to download external scripts.
94   * Initialize object with an options object
95   * Ex:
96   {
97		  url : 'http://example.org/url_to_download',
98		  method: 'POST|GET',
99		  success: callback_function,
100		  fail:  callback_function
101	  }
102   */
103  var AjaxHelper = function(opts){
104    var xhr = new XMLHttpRequest();
105
106    this.success = opts.success || noop;
107    this.fail = opts.fail || noop;
108    var me = this;
109
110    var method = opts.method || 'get';
111
112    /**
113     * Abort the request
114     */
115    this.abort = function(){
116      try{
117        xhr.abort();
118      }
119      catch(ex){
120      }
121    }
122
123    function stateChange(vals){
124      if(xhr.readyState == 4){
125        if(xhr.status == 200){
126          me.success(xhr.response);
127        }
128        else{
129          // failed
130          me.fail(xhr.status);
131        }
132      }
133    }
134
135    xhr.onreadystatechange = stateChange;
136
137    function start(){
138      xhr.open(method, opts.url, true);
139      xhr.send();
140    }
141
142    start();
143  }
144
145  /**
146   * Object tracking the various block lists
147   */
148  var BlockListTracker = function(){
149    var me = this;
150    var externalBlocklistData = {};
151
152    /**
153     * Add a new external URL to track
154     */
155    this.addUrl = function(url){
156      externalBlocklistData[url] = {
157        url: url,
158        state: 'pending',
159        format: null,
160        data: null,
161        result: null
162      }
163
164      return externalBlocklistData[url];
165    }
166
167    /**
168     * Loads a block list definition
169     */
170    this.setResult = function(urlKey, state, data){
171      var obj = externalBlocklistData[urlKey];
172      if(obj == null){
173        obj = this.addUrl(urlKey);
174      }
175
176      obj.state = state;
177      if(data == null){
178        obj.result = null;
179        return;
180      }
181
182      if(typeof data === 'string'){
183        try{
184          data = parseAsJson(data);
185          obj.format = 'json';
186        }
187        catch(ex){
188          obj.format = 'easylist';
189          // parseEasyList(data);
190        }
191      }
192      obj.data = data;
193
194      return obj;
195    }
196
197  }
198
199  var listeners = []; // event response listeners
200  var baitNode = null;
201  var quickBait = {
202    cssClass: 'pub_300x250 pub_300x250m pub_728x90 text-ad textAd text_ad text_ads text-ads text-ad-links'
203  };
204  var baitTriggers = {
205    nullProps: [ofs + 'Parent'],
206    zeroProps: []
207  };
208
209  baitTriggers.zeroProps = [
210    ofs +'Height', ofs +'Left', ofs +'Top', ofs +'Width', ofs +'Height',
211    cl + 'Height', cl + 'Width'
212  ];
213
214  // result object
215  var exeResult = {
216    quick: null,
217    remote: null
218  };
219
220  var findResult = null; // result of test for ad blocker
221
222  var timerIds = {
223    test: 0,
224    download: 0
225  };
226
227  function isFunc(fn){
228    return typeof(fn) == 'function';
229  }
230
231  /**
232   * Make a DOM element
233   */
234  function makeEl(tag, attributes){
235    var k, v, el, attr = attributes;
236    var d = document;
237
238    el = d.createElement(tag);
239
240    if(attr){
241      for(k in attr){
242        if(attr.hasOwnProperty(k)){
243          el.setAttribute(k, attr[k]);
244        }
245      }
246    }
247
248    return el;
249  }
250
251  function attachEventListener(dom, eventName, handler){
252    if(isOldIEevents){
253      dom.attachEvent('on' + eventName, handler);
254    }
255    else{
256      dom.addEventListener(eventName, handler, false);
257    }
258  }
259
260  function log(message, isError){
261    if(!_options.debug && !isError){
262      return;
263    }
264    if(win.console && win.console.log){
265      if(isError){
266        console.error('[ABD] ' + message);
267      }
268      else{
269        console.log('[ABD] ' + message);
270      }
271    }
272  }
273
274  var ajaxDownloads = [];
275
276  /**
277   * Load and execute the URL inside a closure function
278   */
279  function loadExecuteUrl(url){
280    var ajax, result;
281
282    blockLists.addUrl(url);
283    // setup call for remote list
284    ajax = new AjaxHelper(
285      {
286        url: url,
287        success: function(data){
288          log('downloaded file ' + url); // todo - parse and store until use
289          result = blockLists.setResult(url, 'success', data);
290          try{
291            var intervalId = 0,
292              retryCount = 0;
293
294            var tryExecuteTest = function(listData){
295              if(!testExecuting){
296                beginTest(listData, true);
297                return true;
298              }
299              return false;
300            }
301
302            if(findResult == true){
303              return;
304            }
305
306            if(tryExecuteTest(result.data)){
307              return;
308            }
309            else{
310              log('Pause before test execution');
311              intervalId = setInterval(function(){
312                if(tryExecuteTest(result.data) || retryCount++ > 5){
313                  clearInterval(intervalId);
314                }
315              }, 250);
316            }
317          }
318          catch(ex){
319            log(ex.message + ' url: ' + url, true);
320          }
321        },
322        fail: function(status){
323          log(status, true);
324          blockLists.setResult(url, 'error', null);
325        }
326      });
327
328    ajaxDownloads.push(ajax);
329  }
330
331
332  /**
333   * Fetch the external lists and initiate the tests
334   */
335  function fetchRemoteLists(){
336    var i, url;
337    var opts = _options;
338
339    for(i=0;i<opts.blockLists.length;i++){
340      url = opts.blockLists[i];
341      loadExecuteUrl(url);
342    }
343  }
344
345  function cancelRemoteDownloads(){
346    var i, aj;
347
348    for(i=ajaxDownloads.length-1;i >= 0;i--){
349      aj = ajaxDownloads.pop();
350      aj.abort();
351    }
352  }
353
354
355  // =============================================================================
356  /**
357   * Begin execution of the test
358   */
359  function beginTest(bait){
360    log('start beginTest');
361    if(findResult == true){
362      return; // we found it. don't continue executing
363    }
364    testExecuting = true;
365    castBait(bait);
366
367    exeResult.quick = 'testing';
368
369    timerIds.test = setTimeout(
370      function(){ reelIn(bait, 1); },
371      5);
372  }
373
374  /**
375   * Create the bait node to see how the browser page reacts
376   */
377  function castBait(bait){
378    var i, d = document, b = d.body;
379    var t;
380    var baitStyle = 'width: 1px !important; height: 1px !important; position: absolute !important; left: -10000px !important; top: -1000px !important;'
381
382    if(bait == null || typeof(bait) == 'string'){
383      log('invalid bait being cast');
384      return;
385    }
386
387    if(bait.style != null){
388      baitStyle += bait.style;
389    }
390
391    baitNode = makeEl('div', {
392      'class': bait.cssClass,
393      'style': baitStyle
394    });
395
396    log('adding bait node to DOM');
397
398    b.appendChild(baitNode);
399
400    // touch these properties
401    for(i=0;i<baitTriggers.nullProps.length;i++){
402      t = baitNode[baitTriggers.nullProps[i]];
403    }
404    for(i=0;i<baitTriggers.zeroProps.length;i++){
405      t = baitNode[baitTriggers.zeroProps[i]];
406    }
407  }
408
409  /**
410   * Run tests to see if browser has taken the bait and blocked the bait element
411   */
412  function reelIn(bait, attemptNum){
413    var i, k, v;
414    var body = document.body;
415    var found = false;
416
417    if(baitNode == null){
418      log('recast bait');
419      castBait(bait || quickBait);
420    }
421
422    if(typeof(bait) == 'string'){
423      log('invalid bait used', true);
424      if(clearBaitNode()){
425        setTimeout(function(){
426          testExecuting = false;
427        }, 5);
428      }
429
430      return;
431    }
432
433    if(timerIds.test > 0){
434      clearTimeout(timerIds.test);
435      timerIds.test = 0;
436    }
437
438    // test for issues
439
440    if(body.getAttribute('abp') !== null){
441      log('found adblock body attribute');
442      found = true;
443    }
444
445    for(i=0;i<baitTriggers.nullProps.length;i++){
446      if(baitNode[baitTriggers.nullProps[i]] == null){
447        if(attemptNum>4)
448          found = true;
449        log('found adblock null attr: ' + baitTriggers.nullProps[i]);
450        break;
451      }
452      if(found == true){
453        break;
454      }
455    }
456
457    for(i=0;i<baitTriggers.zeroProps.length;i++){
458      if(found == true){
459        break;
460      }
461      if(baitNode[baitTriggers.zeroProps[i]] == 0){
462        if(attemptNum>4)
463          found = true;
464        log('found adblock zero attr: ' + baitTriggers.zeroProps[i]);
465      }
466    }
467
468    if(window.getComputedStyle !== undefined) {
469      var baitTemp = window.getComputedStyle(baitNode, null);
470      if(baitTemp.getPropertyValue('display') == 'none'
471        || baitTemp.getPropertyValue('visibility') == 'hidden') {
472        if(attemptNum>4)
473          found = true;
474        log('found adblock computedStyle indicator');
475      }
476    }
477
478    testedOnce = true;
479
480    if(found || attemptNum++ >= _options.maxLoop){
481      findResult = found;
482      log('exiting test loop - value: ' + findResult);
483      notifyListeners();
484      if(clearBaitNode()){
485        setTimeout(function(){
486          testExecuting = false;
487        }, 5);
488      }
489    }
490    else{
491      timerIds.test = setTimeout(function(){
492        reelIn(bait, attemptNum);
493      }, _options.loopDelay);
494    }
495  }
496
497  function clearBaitNode(){
498    if(baitNode === null){
499      return true;
500    }
501
502    try{
503      if(isFunc(baitNode.remove)){
504        baitNode.remove();
505      }
506      document.body.removeChild(baitNode);
507    }
508    catch(ex){
509    }
510    baitNode = null;
511
512    return true;
513  }
514
515  /**
516   * Halt the test and any pending timeouts
517   */
518  function stopFishing(){
519    if(timerIds.test > 0){
520      clearTimeout(timerIds.test);
521    }
522    if(timerIds.download > 0){
523      clearTimeout(timerIds.download);
524    }
525
526    cancelRemoteDownloads();
527
528    clearBaitNode();
529  }
530
531  /**
532   * Fire all registered listeners
533   */
534  function notifyListeners(){
535    var i, funcs;
536    if(findResult === null){
537      return;
538    }
539    for(i=0;i<listeners.length;i++){
540      funcs = listeners[i];
541      try{
542        if(funcs != null){
543          if(isFunc(funcs['complete'])){
544            funcs['complete'](findResult);
545          }
546
547          if(findResult && isFunc(funcs['found'])){
548            funcs['found']();
549          }
550          else if(findResult === false && isFunc(funcs['notfound'])){
551            funcs['notfound']();
552          }
553        }
554      }
555      catch(ex){
556        log('Failure in notify listeners ' + ex.Message, true);
557      }
558    }
559  }
560
561  /**
562   * Attaches event listener or fires if events have already passed.
563   */
564  function attachOrFire(){
565    var fireNow = false;
566    var fn;
567
568    if(document.readyState){
569      if(document.readyState == 'complete'){
570        fireNow = true;
571      }
572    }
573
574    fn = function(){
575      beginTest(quickBait, false);
576    }
577
578    if(fireNow){
579      fn();
580    }
581    else{
582      attachEventListener(win, 'load', fn);
583    }
584  }
585
586
587  var blockLists; // tracks external block lists
588
589  /**
590   * Public interface of adblock detector
591   */
592  var impl = {
593    /**
594     * Version of the adblock detector package
595     */
596    version: version,
597
598    /**
599     * Initialization function. See comments at top for options object
600     */
601    init: function(options){
602      var k, v, funcs;
603
604      if(!options){
605        return;
606      }
607
608      funcs = {
609        complete: noop,
610        found: noop,
611        notfound: noop
612      };
613
614      for(k in options){
615        if(options.hasOwnProperty(k)){
616          if(k == 'complete' || k == 'found' || k == 'notFound'){
617            funcs[k.toLowerCase()] = options[k];
618          }
619          else{
620            _options[k] = options[k];
621          }
622        }
623      }
624
625      listeners.push(funcs);
626
627      blockLists = new BlockListTracker();
628
629      attachOrFire();
630    }
631  }
632
633  win['adblockDetector'] = impl;
634
635})(window)

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.