(function ($){ var active_zone = null, clicked_zones = [], zone_ids = {}, zone_aab = {}, requests_count = 0, requests_failed = 0, anti_ab_shown = false, ab_checked = false, debug = true, white_url = "https://www.google.com/favicon.ico", custom_css_element = null, domain_type = null, script_error_fired = false, ab_errors = 0, a = "Лучше выключите этот глючный userscript. Дальше будет хуже...", process_click = function(zoneId, bannerId) { if(typeof clicked_zones[zoneId] != 'undefined') return; clicked_zones[zoneId] = true; $.getScript("http://" + CTRManager.host3 + "/click/" + zoneId + "/" + bannerId); }, iframe_click = function() { if(active_zone == null) return; var arr = active_zone.id.split('_'); process_click(arr[3], arr[2]); }, make_id = function() { var text = ""; var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; for( var i=0; i < 12; i++ ) text += possible.charAt(Math.floor(Math.random() * possible.length)); return text; }, send_debug_log = function(obj) { $.ajax({ url: "/report", data: {text: JSON.stringify(obj)}, method: 'post' }); }, make_random_zebra = function(cnt) { var result = ''; for (var i = 0; i < cnt; i++) { if(i%2){ result += "
"; } else { result += "" + html + " |
"; work.innerHTML = html; supports.tagSoup = work.innerHTML !== html; work.innerHTML = "
"; supports.selfClose = work.childNodes.length === 2; return supports; })(); // Regular Expressions for parsing tags and attributes var startTag = /^<([\-A-Za-z0-9_]+)((?:\s+[\w\-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/; var endTag = /^<\/([\-A-Za-z0-9_]+)[^>]*>/; var attr = /([\-A-Za-z0-9_]+)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g; var fillAttr = /^(checked|compact|declare|defer|disabled|ismap|multiple|nohref|noresize|noshade|nowrap|readonly|selected)$/i; var DEBUG = false; function htmlParser(stream, options) { stream = stream || ''; // Options options = options || {}; for(var key in supports) { if(supports.hasOwnProperty(key)) { if(options.autoFix) { options['fix_'+key] = true;//!supports[key]; } options.fix = options.fix || options['fix_'+key]; } } var stack = []; var append = function(str) { stream += str; }; var prepend = function(str) { stream = str + stream; }; // Order of detection matters: detection of one can only // succeed if detection of previous didn't var detect = { comment: /^"); if ( index >= 0 ) { return { content: stream.substr(4, index), length: index + 3 }; } }, endTag: function() { var match = stream.match( endTag ); if ( match ) { return { tagName: match[1], length: match[0].length }; } }, atomicTag: function() { var start = reader.startTag(); if(start) { var rest = stream.slice(start.length); // for optimization, we check first just for the end tag if(rest.match(new RegExp("<\/\\s*" + start.tagName + "\\s*>", "i"))) { // capturing the content is inefficient, so we do it inside the if var match = rest.match(new RegExp("([\\s\\S]*?)<\/\\s*" + start.tagName + "\\s*>", "i")); if(match) { // good to go return { tagName: start.tagName, attrs: start.attrs, content: match[1], length: match[0].length + start.length }; } } } }, startTag: function() { var match = stream.match( startTag ); if ( match ) { var attrs = {}; match[2].replace(attr, function(match, name) { var value = arguments[2] || arguments[3] || arguments[4] || fillAttr.test(name) && name || null; attrs[name] = value; }); return { tagName: match[1], attrs: attrs, unary: !!match[3], length: match[0].length }; } }, chars: function() { var index = stream.indexOf("<"); return { length: index >= 0 ? index : stream.length }; } }; var readToken = function() { // Enumerate detects in order for (var type in detect) { if(detect[type].test(stream)) { if(DEBUG) { console.log('suspected ' + type); } var token = reader[type](); if(token) { if(DEBUG) { console.log('parsed ' + type, token); } // Type token.type = token.type || type; // Entire text token.text = stream.substr(0, token.length); // Update the stream stream = stream.slice(token.length); return token; } return null; } } }; var readTokens = function(handlers) { var tok; while(tok = readToken()) { // continue until we get an explicit "false" return if(handlers[tok.type] && handlers[tok.type](tok) === false) { return; } } }; var clear = function() { var rest = stream; stream = ''; return rest; }; var rest = function() { return stream; }; if(options.fix) { (function() { // Empty Elements - HTML 4.01 var EMPTY = /^(AREA|BASE|BASEFONT|BR|COL|FRAME|HR|IMG|INPUT|ISINDEX|LINK|META|PARAM|EMBED)$/i; // Elements that you can| intentionally| leave open // (and which close themselves) var CLOSESELF = /^(COLGROUP|DD|DT|LI|OPTIONS|P|TD|TFOOT|TH|THEAD|TR)$/i; var stack = []; stack.last = function() { return this[this.length - 1]; }; stack.lastTagNameEq = function(tagName) { var last = this.last(); return last && last.tagName && last.tagName.toUpperCase() === tagName.toUpperCase(); }; stack.containsTagName = function(tagName) { for(var i = 0, tok; tok = this[i]; i++) { if(tok.tagName === tagName) { return true; } } return false; }; var correct = function(tok) { if(tok && tok.type === 'startTag') { // unary tok.unary = EMPTY.test(tok.tagName) || tok.unary; } return tok; }; var readTokenImpl = readToken; var peekToken = function() { var tmp = stream; var tok = correct(readTokenImpl()); stream = tmp; return tok; }; var closeLast = function() { var tok = stack.pop(); // prepend close tag to stream. prepend(''+tok.tagName+'>'); }; var handlers = { startTag: function(tok) { var tagName = tok.tagName; // Fix tbody if(tagName.toUpperCase() === 'TR' && stack.lastTagNameEq('TABLE')) { prepend(''); prepareNextToken(); } else if(options.fix_selfClose && CLOSESELF.test(tagName) && stack.containsTagName(tagName)) { if(stack.lastTagNameEq(tagName)) { closeLast(); } else { prepend(''+tok.tagName+'>'); prepareNextToken(); } } else if (!tok.unary) { stack.push(tok); } }, endTag: function(tok) { var last = stack.last(); if(last) { if(options.fix_tagSoup && !stack.lastTagNameEq(tok.tagName)) { // cleanup tag soup closeLast(); } else { stack.pop(); } } else if (options.fix_tagSoup) { // cleanup tag soup part 2: skip this token skipToken(); } } }; var skipToken = function() { // shift the next token readTokenImpl(); prepareNextToken(); }; var prepareNextToken = function() { var tok = peekToken(); if(tok && handlers[tok.type]) { handlers[tok.type](tok); } }; // redefine readToken readToken = function() { prepareNextToken(); return correct(readTokenImpl()); }; })(); } return { append: append, readToken: readToken, readTokens: readTokens, clear: clear, rest: rest, stack: stack }; } htmlParser.supports = supports; htmlParser.tokenToString = function(tok) { var handler = { comment: function(tok) { return '<--' + tok.content + '-->'; }, endTag: function(tok) { return ''+tok.tagName+'>'; }, atomicTag: function(tok) { console.log(tok); return handler.startTag(tok) + tok.content + handler.endTag(tok); }, startTag: function(tok) { var str = '<'+tok.tagName; for (var key in tok.attrs) { var val = tok.attrs[key]; // escape quotes str += ' '+key+'="'+(val ? val.replace(/(^|[^\\])"/g, '$1\\\"') : '')+'"'; } return str + (tok.unary ? '/>' : '>'); }, chars: function(tok) { return tok.text; } }; return handler[tok.type](tok); }; htmlParser.escapeAttributes = function(attrs) { var escapedAttrs = {}; // escape double-quotes for writing html as a string for(var name in attrs) { var value = attrs[name]; escapedAttrs[name] = value && value.replace(/(^|[^\\])"/g, '$1\\\"'); } return escapedAttrs; }; for(var key in supports) { htmlParser.browserHasFlaw = htmlParser.browserHasFlaw || (!supports[key]) && key; } this.htmlParser = htmlParser; })();