1/** 2 * NeverBlock 3 * 4 * Copyright (C) 2016 EXADS 5 */ 6 7// noinspection JSUnusedGlobalSymbols 8var ExoLoader; 9(function () { 10 var version = '3.12'; 11 12 var detection_started = false; 13 var detection_complete = false; 14 var adblock_detected = false; 15 var detector_func_queue = []; 16 17 var detector = { 18 domain_base: "exoclick.com", 19 detectCensorship: function (onComplete, timeout) { 20 detector_func_queue.push(onComplete); 21 detection_started = true; 22 var block = false; 23 var done = function () { 24 if (!detection_complete) { 25 try { 26 var checkVal = (window.document.location.protocol !== "https:" && window.document.location.protocol !== "http:") ? "https:" : window.document.location.protocol; 27 if (typeof window.exoDocumentProtocol === "undefined" 28 || window.exoDocumentProtocol !== checkVal 29 ) { 30 block = true; 31 } 32 } catch (err) { 33 block = true; 34 } 35 adblock_detected = block; 36 detection_complete = true; 37 } else { 38 block = adblock_detected; 39 } 40 do { 41 var currentFunction = detector_func_queue.shift(); 42 if (typeof currentFunction === 'function') { 43 currentFunction(block); 44 } 45 } while (typeof currentFunction !== "undefined"); 46 document.body.removeChild(testDomEl); 47 }; 48 49 if (detection_complete) { 50 done(); 51 return; 52 } 53 54 var testDomEl = document.createElement('iframe'), 55 randomNum = Math.floor(Math.random() * (10000 - 123 + 1)) + 123, 56 protocol = window.location.protocol, 57 id = 'adsbox_ex_' + randomNum; 58 59 testDomEl.setAttribute('height', "1px"); 60 testDomEl.setAttribute('width', "1px"); 61 testDomEl.setAttribute('id', id); 62 testDomEl.setAttribute('class', 'adsBox pub_300x250 pub_300x250m pub_728x90 text-ad textAd text_ad text_ads text-ads text-ad-links'); 63 testDomEl.setAttribute('style', "width: 1px !important; height: 1px !important; position: absolute !important; left: -10000px !important; top: -1000px !important; box-sizing: content-box !important; border-width: 0px !important;"); 64 65 try { 66 if (window.ExoLoader === null) { 67 window.ExoLoader = {'dummy': 1}; 68 if (window.ExoLoader !== {'dummy': 1}) { 69 block = true; 70 } 71 } 72 } catch (err) { 73 block = true; 74 } 75 76 var testScript = document.createElement('script'); 77 testScript.src = protocol + "//ads." + detector.domain_base + "/ads.js"; 78 testScript.onerror = function () { 79 block = true; 80 }; 81 82 document.body.appendChild(testDomEl); 83 document.head.appendChild(testScript); 84 var isTimeoutSet = false; 85 var timeUp = false; 86 var timeoutExceeded = function (thistimer) { 87 timeUp = true; 88 clearTimeout(thistimer); 89 }; 90 91 92 var loadedCheck = function (timeoutCycle) { 93 setTimeout(function () { 94 timeoutCycle--; 95 if (typeof exoDocumentProtocol !== 'undefined' ) { 96 //File loaded successfully 97 clearTimeout(timeupTimer); 98 } else if (timeoutCycle > 0 && document.readyState !== "complete" && !timeUp) { 99 loadedCheck(timeoutCycle); 100 } else { 101 domDetect(); 102 done(); 103 clearTimeout(timeupTimer); 104 } 105 }, 0); 106 }; 107 108 if(timeout) { 109 var timeupTimer = setTimeout(function () { 110 timeoutExceeded(timeupTimer); 111 }, timeout); 112 isTimeoutSet = true; 113 loadedCheck(timeout); 114 } 115 var domDetect = function () { 116 try { 117 var someAd = document.getElementById(id); 118 if (someAd === null 119 || someAd.style.display === "none" 120 || someAd.style.display === "hidden" 121 || someAd.style.visibility === "hidden" 122 || someAd.offsetParent === null 123 || someAd.offsetHeight === 0 124 || someAd.offsetLeft === 0 125 || someAd.offsetTop === 0 126 || someAd.offsetWidth === 0 127 || someAd.clientHeight === 0 128 || someAd.clientWidth === 0 129 ) { 130 block = true; 131 } 132 if (window.getComputedStyle !== undefined) { 133 var style = window.getComputedStyle(someAd, null); 134 if (style && (style.getPropertyValue('display') === 'none' || style.getPropertyValue('visibility') === 'hidden')) { 135 block = true; 136 } 137 } 138 } catch (err) { 139 } 140 }; 141 142 var maxReadyCheckAttempts = 45; 143 var readyCheckInterval = setInterval(function () { 144 if(isTimeoutSet) { 145 clearInterval(readyCheckInterval); 146 return; 147 } 148 if (document.readyState === "complete" || maxReadyCheckAttempts === 0 || block === true) { 149 domDetect(); 150 done(); 151 clearInterval(readyCheckInterval); 152 } 153 maxReadyCheckAttempts--; 154 }, 50); 155 } 156 }; 157 158 function urlDomain(url) { 159 var a = document.createElement('a'); 160 a.href = url; 161 return a.hostname; 162 } 163
164 var stylesheet = "{ %optional_styles% vertical-align:top; cursor: pointer; border: 0px solid #000000; display: inline-block; background-color: rgba(0, 0, 0, 0); margin: 0px 0px; padding: 0px 0px; }"; 165 var debug_messages = []; 166 var error_messages = []; 167 var request_stack = [];// array of request objects 168 var responses = {}; 169 var callback_function_pushed_to_detector = false; 170 var request_started = false; 171 var current_request = 0; 172 var waiting_request_queue = []; 173 var before_detect_queue = []; 174 175 var ZonesRequest = function() { 176 this.zone_params = []; 177 this.dom = []; 178 this.pushZone = function(zoneParams) { 179 this.zone_params.push(zoneParams); 180 }; 181 this.pushDom = function(domObj) { 182 this.dom.push(domObj); 183 }; 184 }; 185 186 var addDebugMessage = function (message) { 187 var date = new Date(); 188 debug_messages.push(date.toISOString() + ": " + message); 189 }; 190 var addErrorMessage = function (message) { 191 var date = new Date(); 192 error_messages.push(date.toISOString() + ": " + message); 193 console.error(message); 194 }; 195 196 var URLToArray = function(url) { 197 var request = {}; 198 var pairs = url.substring(url.indexOf('?') + 1).split('&'); 199 for (var i = 0; i < pairs.length; i++) { 200 if(!pairs[i]) 201 continue; 202 var pair = pairs[i].split('='); 203 request[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]); 204 } 205 return request; 206 }; 207 208 var stringify = function (value) { 209 var reassign_when_finished = false; 210 if (typeof Array.prototype.toJSON !== 'undefined') { 211 reassign_when_finished = true; 212 var array_to_json = Array.prototype.toJSON; 213 delete Array.prototype.toJSON; 214 } 215 var val = JSON.stringify(value); 216 if (reassign_when_finished) { 217 Array.prototype.toJSON = array_to_json; 218 } 219 return val; 220 }; 221 222 var randStr = function (length, possibleChars) 223 { 224 var text = ""; 225 var possible = possibleChars || "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; 226 227 for( var i=0; i < length; i++ ) 228 text += possible.charAt(Math.floor(Math.random() * possible.length)); 229 230 return text; 231 }; 232 233 var createStyle = function (doc, dom_anchor, style_text) 234 { 235 var class_name = randStr(1,"abcdefghijklmnopqrstuvwxyz") + randStr(7); 236 style_text = "." + class_name + " " + style_text; 237 var style = doc.createElement('style'); 238 style.setAttribute('type', 'text/css'); 239 style.innerHTML = style_text; 240 dom_anchor.parentNode.insertBefore(style, dom_anchor); 241 return class_name; 242 }; 243 244 // noinspection JSUnusedGlobalSymbols 245 var loader = { 246 bl_domain: null, 247 bl_cookie_domain: null, 248 timeout_check: null, 249 no_cookie: false, 250 cookie_name: "yuo1", 251 setTimeout: function(timeout) { 252 if(timeout) { 253 loader.timeout_check = timeout; 254 } 255 }, 256 addZone: function(params) { 257 258 if (typeof params !== 'object' 259 || typeof params.idzone === 'undefined' 260 ) { 261 addErrorMessage("addZone() invalid params"); 262 return false; 263 } 264 // noinspection JSUnresolvedVariable 265 var doc = params.doc || document; 266 var scripts = doc.getElementsByTagName('script'); 267 // The current <script> tag where the method is called 268 var here = params.here || scripts[ scripts.length - 1 ]; 269 270 if (!detection_complete) { 271 addDebugMessage("addZone() added to detect queue"); 272 params.here = here; 273 before_detect_queue.push({"func": 'addZone', "parameters": params}); 274 275 if (!callback_function_pushed_to_detector) { 276 callback_function_pushed_to_detector = true; 277 detector.detectCensorship(function(block) { 278 if (block) {
279 window.exoNoExternalUI38djdkjDDJsio96 = true; 280 for (var i = 0; i < before_detect_queue.length; i++) { 281 loader[before_detect_queue[i]['func']](before_detect_queue[i]['parameters']); 282 } 283 before_detect_queue = []; 284 } 285 }, loader.timeout_check); 286 } 287 288 return false; 289 } else { 290 if (adblock_detected && !window.exoNoExternalUI38djdkjDDJsio96) { 291 window.exoNoExternalUI38djdkjDDJsio96 = true; 292 } 293 if (!adblock_detected) { 294 addDebugMessage("addZone() ad blocker not enabled"); 295 return false; 296 } 297 } 298 299 var request; 300 if (typeof request_stack[current_request] === "object") { 301 request = request_stack[current_request]; 302 } else { 303 request = new ZonesRequest(); 304 request_stack[current_request] = request; 305 } 306 request.pushZone(params); 307 308 var optional_styles = ''; 309 var displayNone = false; 310 if ( 311 typeof params.width !== 'undefined' 312 && typeof params.height !== 'undefined' 313 ) { 314 optional_styles += 'width: ' + params.width + 'px;'; 315 optional_styles += ' height: ' + params.height + 'px;'; 316 } else { 317 displayNone = true; 318 } 319 320 var style_text = stylesheet.replace('%optional_styles%', optional_styles); 321 var class_name = createStyle(doc, here, style_text); 322 323 var placeholder = doc.createElement('div'); 324 if (displayNone) { 325 placeholder.style.display = 'none'; 326 } 327 placeholder.setAttribute('class', class_name); 328 if (typeof params.container === "object" && typeof params.container.appendChild === "function") { 329 params.container.appendChild(placeholder); 330 } else { 331 here.parentNode.insertBefore(placeholder, here); 332 } 333 request.pushDom({'placeholder': placeholder, 'doc_reference': doc}); 334 335 addDebugMessage("addZone() " + params.idzone + " added"); 336 return true; 337 }, 338 serve: function(params) { 339 /* 340 params = { 341 script_url: 'url/of/backend_loader.php', 342 force: {false|true}, 343 no_cookie: {false|true} 344 } 345 346 Important note: 347 If backend_loader.php & frontend_loader are hosted on different domains, 348 don't forget to take care about CORS issues! 349 In case the domains are not subdomains of a common domain it's impossible to pass data through cookie. no_cookie should be set to true. 350 */ 351 352 if (!detection_complete) { 353 addDebugMessage("serve() added to detect queue"); 354 params.force = true; 355 before_detect_queue.push({"func": 'serve', "parameters": params}); 356 return false; 357 } else { 358 if (adblock_detected && !window.exoNoExternalUI38djdkjDDJsio96) { 359 window.exoNoExternalUI38djdkjDDJsio96 = true; 360 } 361 if (!adblock_detected) { 362 addDebugMessage("serve() ad blocker not enabled"); 363 return false; 364 } 365 } 366 367 var request_id = current_request; 368 var increment_current_request = true; 369 if (typeof params.request_id !== "undefined" && params.request_id !== null) { 370 request_id = params.request_id; 371 increment_current_request = false; 372 } 373 var request = request_stack[request_id]; 374 375 if (typeof request === 'undefined' 376 || request.zone_params.length < 1 377 ) { 378 addErrorMessage("serve() called but no zones added for request: " + request_id); 379 return false;
380 } 381 382 if (increment_current_request) { 383 current_request++; 384 } 385 386 if (request_started) { 387 waiting_request_queue.push({"request_id": request_id, "parameters": params}); 388 return; 389 } 390 391 addDebugMessage("serve() called for request " + request_id); 392 //Start a request. If there are several others will wait since they share a cookie. 393 request_started = true; 394 var cookie_request_obj = { 395 "objName": objName, 396 "request_id": request_id, 397 "zones": request.zone_params 398 }; 399 400 loader.bl_domain = params.bl_domain || urlDomain(params.script_url); // Domain of backend_loader.php 401 loader.bl_cookie_domain = params.bl_cookie_domain || loader.bl_domain; 402 loader.no_cookie = params.no_cookie; 403 404 var request_str = stringify(cookie_request_obj); 405 406 if (!loader.no_cookie) { 407 loader.setCookie(this.cookie_name, request_str, 5, loader.bl_cookie_domain); 408 } 409 delete request.zone_params.request_id; 410 411 var loadDataScript = function () { 412 var dataScript = document.createElement("script"); 413 dataScript.async = true; 414 dataScript.setAttribute('type', 'text/javascript'); 415 var script_url = params.script_url; 416 if (loader.no_cookie) { 417 script_url += (/\?/.test(params.script_url) ? '&' : '?') + 418 loader.cookie_name + '=' + request_str; 419 } 420 if (params.no_cache) { 421 script_url += (/\?/.test(params.script_url) ? '&' : '?') + 422 '_=' + randStr(3) + (new Date()).getTime(); // Avoid caching! 423 } 424 dataScript.setAttribute('src', script_url); 425 dataScript.onload = function(){ 426 addDebugMessage("serve() hosted script loaded"); 427 }; 428 var processNext = function() { 429 request_started = false; 430 if (waiting_request_queue.length > 0) { 431 var next_request_obj = waiting_request_queue.shift(); 432 next_request_obj.parameters.request_id = next_request_obj.request_id; 433 loader.serve(next_request_obj.parameters); 434 } 435 }; 436 dataScript.onload = processNext; 437 dataScript.onerror = processNext; 438 document.getElementsByTagName("body").item(0).appendChild(dataScript); 439 }; 440 441 if (!params.force) { 442 if (window.addEventListener) { 443 window.addEventListener("load", loadDataScript, false); 444 } else if (window.attachEvent) { 445 window.attachEvent("onload", loadDataScript); 446 } else { 447 window.onload = loadDataScript; 448 } 449 } else { 450 loadDataScript(); 451 } 452 return true; 453 }, 454 getDebug: function() { 455 for (var i = 0; i < debug_messages.length; i++) { 456 console.log(debug_messages[i]); 457 } 458 }, 459 getVersion: function() { 460 return version; 461 }, 462 pushResponseData: function(response) { 463 if ( 464 typeof response !== 'object' 465 || typeof response.request_id !== 'number' 466 || typeof request_stack[response.request_id] === 'undefined' 467 ) { 468 addErrorMessage("pushResponseData() invalid response"); 469 } 470 responses[response.request_id] = response; 471 addDebugMessage("pushResponseData() called for request " + response.request_id); 472 }, 473 getAdData: function(request_id, ad_format) { 474 var adData = { 475 'zones': [] 476 }; 477 478 if (typeof request_stack[request_id] === 'undefined' 479 || typeof responses[request_id] === 'undefined' 480 ) { 481 addErrorMessage("getAdData() data for request_id not found"); 482 return adData; 483 } 484 if (typeof responses[request_id].zones[ad_format] === 'undefined') { 485 addErrorMessage("getAdData() data for ad_format " + ad_format + " not present in response"); 486 return adData; 487 } 488 489 for (var i = 0; i < responses[request_id].zones[ad_format].length; i++) { 490 var adId = responses[request_id].zones[ad_format][i].id; 491 var zone_params = request_stack[request_id].zone_params[adId]; 492 var idzone = zone_params.idzone; 493 494 var zoneObj = { 495 "idzone": idzone, 496 "dom": request_stack[request_id].dom[adId], 497 "data": responses[request_id].zones[ad_format][i].data 498 }; 499 if (typeof zone_params.sub !== 'undefined') { 500 zoneObj.sub = zone_params.sub; 501 } 502 if (typeof zone_params.sub2 !== 'undefined') { 503 zoneObj.sub2 = zone_params.sub2; 504 } 505 if (typeof zone_params.sub3 !== 'undefined') { 506 zoneObj.sub3 = zone_params.sub3; 507 } 508 if (typeof zone_params.cat !== 'undefined') {
509 zoneObj.cat = zone_params.cat; 510 } 511 adData.zones.push(zoneObj); 512 } 513 if (typeof responses[request_id].additional_images !== 'undefined' 514 && typeof responses[request_id].additional_images[ad_format] !== 'undefined' 515 ) { 516 adData.additional_images = responses[request_id].additional_images[ad_format]; 517 } 518 519 return adData; 520 }, 521 openLink: function(event, dest, force_method) { 522 if (typeof force_method !== 'undefined' 523 && force_method !== 'get' 524 && force_method !== 'post' 525 ) { 526 addErrorMessage("openLink() trying to force invalid method"); 527 } 528 if (typeof(event) !== "undefined") { 529 event.returnValue = false; 530 if (event.preventDefault) { 531 event.preventDefault(); 532 } 533 event.stopPropagation(); 534 } 535 536 var url_parts; 537 var parameters; 538 var method; 539 if (dest.indexOf("?") !== -1) { 540 url_parts = dest.split('?', 2); 541 parameters = URLToArray(url_parts[1]); 542 method = (force_method) ? force_method : "post"; 543 } else { 544 url_parts = [dest]; 545 parameters = []; 546 method = (force_method) ? force_method : "get"; 547 } 548 var f = document.createElement("form"); 549 f.setAttribute("action", url_parts[0]); 550 f.setAttribute("method", method); 551 f.setAttribute("target", "_blank"); 552 document.getElementsByTagName("body").item(0).appendChild(f); 553 for (var i in parameters) { 554 if (!parameters.hasOwnProperty(i)) { 555 continue; 556 } 557 var input = document.createElement("input"); 558 input.setAttribute("type", "hidden"); 559 input.setAttribute("name", i); 560 input.setAttribute("value", parameters[i]); 561 f.appendChild(input); 562 } 563 f.submit(); 564 document.getElementsByTagName("body").item(0).removeChild(f); 565 return false; 566 }, 567 formatImage: function (request_id, imageReference) { 568 if (typeof request_stack[request_id] === 'undefined' 569 || typeof responses[request_id] === 'undefined' 570 ) { 571 addErrorMessage("formatImage() data for request_id not found"); 572 return false; 573 } 574 var result = responses[request_id].banner_prefix + responses[request_id].images[imageReference]; 575 if (loader.bl_domain) { 576 result = "//" + loader.bl_domain + result; 577 } 578 return result; 579 }, 580 formatLink: function (request_id, link) { 581 if (typeof request_stack[request_id] === 'undefined' 582 || typeof responses[request_id] === 'undefined' 583 ) { 584 addErrorMessage("formatLink() data for request_id not found"); 585 return false; 586 } 587 var result = responses[request_id].link_prefix + link; 588 if (loader.bl_domain) { 589 result = "//" + loader.bl_domain + result; 590 } 591 return result; 592 }, 593 setCookie: function (name, value, minutes_ttl, domain) { 594 var exdate = new Date(); 595 exdate.setMinutes(exdate.getMinutes() + minutes_ttl); 596 var c_value = encodeURI(value) + "; expires=" + exdate.toUTCString() + "; path=/"; 597 if (domain) { 598 c_value += "; domain=" + domain; 599 } 600 document.cookie = name + "=" + c_value; 601 }, 602 getCookie: function (name) { 603 var i, x, y, ARRcookies = document.cookie.split(";"); 604 for (i = 0; i < ARRcookies.length; i++) { 605 x = ARRcookies[i].substr(0, ARRcookies[i].indexOf("=")); 606 y = ARRcookies[i].substr(ARRcookies[i].indexOf("=") + 1); 607 x = x.replace(/^\s+|\s+$/g, ""); 608 if (x === name) { 609 return decodeURI(y); 610 } 611 } 612 }, 613 getRandomClassName: function() { 614 return randStr(1,"abcdefghijklmnopqrstuvwxyz") + randStr(7); 615 }, 616 getRandomizedReference: function(name, reference_map) { 617 if (typeof name !== 'string' || name === '') { 618 addErrorMessage("getRandomizedReference() invalid name, non-empty string expected"); 619 return false;
620 } 621 if (typeof reference_map !== 'object') { 622 addErrorMessage("getRandomizedReference() invalid reference_map, object expected"); 623 return false; 624 } 625 if (typeof reference_map[name] === 'undefined') { 626 reference_map[name] = loader.getRandomClassName(); 627 } 628 return reference_map[name]; 629 }, 630 scrambleStyleString: function(style_str, reference_map, style_regexp) { 631 if (typeof style_str !== 'string' || style_str === '') { 632 addErrorMessage("scrambleStyleString() invalid style_str, non-empty string expected"); 633 return false; 634 } 635 if (typeof reference_map !== 'object') { 636 addErrorMessage("getRandomizedReference() invalid reference_map, object expected"); 637 return false; 638 } 639 if (style_regexp instanceof RegExp) { 640 var match; 641 while (match = style_regexp.exec(style_str)) { 642 loader.getRandomizedReference(match[1], reference_map); 643 } 644 } 645 for (var name in reference_map) { 646 if (!reference_map.hasOwnProperty(name)) { 647 continue; 648 } 649 style_str = style_str.replace(new RegExp('([#\.]{1,1})' + name + '([ :\.{])', 'g'), '$1' + reference_map[name] + '$2'); 650 } 651 return style_str; 652 }, 653 getDetector: function() { 654 return detector; 655 }, 656 cleanupPartiallyBlockedAds: function() { 657 detector.detectCensorship( 658 function(block){ if (block) { 659 var frames = document.getElementsByTagName("iframe"); 660 661 for (var iNum = 0; iNum < frames.length; ++iNum) { 662 if (frames[iNum].src.indexOf("//" + detector.domain_base + "/") > 0) { 663 frames[iNum].style.display = "none"; 664 } 665 } 666 }} 667 ); 668 } 669 }; 670 671 var objName; 672 for (var tries = 0; tries < 3; tries++) { 673 objName = randStr(1, "abcdefghijklmnopqrstuvwxyz") + randStr(Math.floor((Math.random() * 4) + 10)); 674 if (typeof window[objName] !== "undefined") { 675 continue; 676 } 677 window[objName] = loader; 678 break; 679 } 680 681 // custom event polyfill 682 (function() { 683 if (typeof window.CustomEvent === "function") return false; 684 685 function CustomEvent(event, params) { 686 params = params || {bubbles: false, cancelable: false, detail: undefined}; 687 var evt = document.createEvent('CustomEvent'); 688 evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail); 689 return evt; 690 } 691 692 CustomEvent.prototype = window.Event.prototype; 693 694 window.CustomEvent = CustomEvent; 695 })(); 696 697 window.document.addEventListener('getexoloader', function (e) { 698 e.detail.el = loader; 699 }, false); 700 701})();
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.