├── package.json ├── GeoIP.dat ├── sniffer.gif ├── LICENSE ├── Dockerfile ├── client ├── js │ ├── data.js │ ├── exporting.js │ ├── map.js │ └── jquery-1.11.1.min.js └── index.html ├── sniffer_cache_oui.js ├── README.md ├── sniffer_cache.js └── sniffer.js /package.json: -------------------------------------------------------------------------------- 1 | package_node-v11.2.0.json -------------------------------------------------------------------------------- /GeoIP.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyphunk/snifferjs/HEAD/GeoIP.dat -------------------------------------------------------------------------------- /sniffer.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyphunk/snifferjs/HEAD/sniffer.gif -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | License: Non-White-Heterosexual-Male 2 | 3 | If you are not a white heterosexual male you are permitted to copy, sell and use 4 | this work in any manner you choose without need to include any attribution you 5 | do not see fit. You are asked as a courtesy to retain this license in any 6 | derivatives but you are not required. If you are a white heterosexual male you 7 | are provided the same permissions (reuse, modification, resale) but are 8 | required to include this license in any documentation and any public facing 9 | derivative. You are also required to include attribution to the original author 10 | or to an author responsible for redistribution of a derivative. 11 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:14.04 2 | MAINTAINER Nathan Fain "cyphunk@deadhacker.com" 3 | 4 | # This file can be used to build a docker image or to determine OS/build 5 | # dependencies. 6 | 7 | ### Setup OS ### 8 | 9 | RUN apt-get update 10 | RUN apt-get -y install nodejs 11 | RUN apt-get -y install npm 12 | RUN ln -s /usr/bin/nodejs /usr/bin/node # Handle npm ``/bin/sh: 1: node: not found`` 13 | RUN apt-get -y install libpcap-dev # for node_pcap 14 | RUN apt-get -y install wget # to get GeoIP db 15 | 16 | ### Get sniffer.js code ### 17 | 18 | # from remote: 19 | RUN apt-get -y install git; git clone https://github.com/cyphunk/snifferjs.git /root/snifferjs 20 | # from local: 21 | #COPY . /root/snifferjs 22 | 23 | ### Install sniffer.js dependencies ### 24 | 25 | RUN cd /root/snifferjs; npm install 26 | RUN cd /root/snifferjs; wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz; gzip -d GeoIP.dat.gz 27 | 28 | ### Run ### 29 | 30 | EXPOSE 8080 31 | # Optionally you could map the port on the execution host as well with: 32 | # EXPOSE 8080: 33 | # But this is not recommended, and instead: 34 | # $ docker run -p 8080:8080 35 | 36 | CMD cd /root/snifferjs; DEFAULTROUTE=$(route -n | head -3 | tail -1 | awk '{print $2}'); node sniffer.js eth0 'ip' ${DEFAULTROUTE}; /bin/bash 37 | 38 | # build A: docker build -t snifferjs --rm . 39 | # build B: docker build -t snifferjs https://raw.githubusercontent.com/cyphunk/snifferjs/master/Dockerfile 40 | # run: docker run -p 8080:8080 -it --rm snifferjs 41 | -------------------------------------------------------------------------------- /client/js/data.js: -------------------------------------------------------------------------------- 1 | /* 2 | Data plugin for Highcharts 3 | 4 | (c) 2012-2014 Torstein Honsi 5 | 6 | License: www.highcharts.com/license 7 | */ 8 | (function(j){var m=j.each,n=function(b,a){this.init(b,a)};j.extend(n.prototype,{init:function(b,a){this.options=b;this.chartOptions=a;this.columns=b.columns||this.rowsToColumns(b.rows)||[];this.columns.length?this.dataFound():(this.parseCSV(),this.parseTable(),this.parseGoogleSpreadsheet())},getColumnDistribution:function(){var b=this.chartOptions,a=b&&b.chart&&b.chart.type,c=[];m(b&&b.series||[],function(b){c.push((j.seriesTypes[b.type||a||"line"].prototype.pointArrayMap||[0]).length)});this.valueCount= 9 | {global:(j.seriesTypes[a||"line"].prototype.pointArrayMap||[0]).length,individual:c}},dataFound:function(){if(this.options.switchRowsAndColumns)this.columns=this.rowsToColumns(this.columns);this.parseTypes();this.findHeaderRow();this.parsed();this.complete()},parseCSV:function(){var b=this,a=this.options,c=a.csv,d=this.columns,e=a.startRow||0,f=a.endRow||Number.MAX_VALUE,i=a.startColumn||0,h=a.endColumn||Number.MAX_VALUE,g,k,o=0;c&&(k=c.replace(/\r\n/g,"\n").replace(/\r/g,"\n").split(a.lineDelimiter|| 10 | "\n"),g=a.itemDelimiter||(c.indexOf("\t")!==-1?"\t":","),m(k,function(a,c){var k=b.trim(a),j=k.indexOf("#")===0;c>=e&&c<=f&&!j&&k!==""&&(k=a.split(g),m(k,function(b,a){a>=i&&a<=h&&(d[a-i]||(d[a-i]=[]),d[a-i][o]=b)}),o+=1)}),this.dataFound())},parseTable:function(){var b=this.options,a=b.table,c=this.columns,d=b.startRow||0,e=b.endRow||Number.MAX_VALUE,f=b.startColumn||0,i=b.endColumn||Number.MAX_VALUE;a&&(typeof a==="string"&&(a=document.getElementById(a)),m(a.getElementsByTagName("tr"),function(a, 11 | b){b>=d&&b<=e&&m(a.children,function(a,e){if((a.tagName==="TD"||a.tagName==="TH")&&e>=f&&e<=i)c[e-f]||(c[e-f]=[]),c[e-f][b-d]=a.innerHTML})}),this.dataFound())},parseGoogleSpreadsheet:function(){var b=this,a=this.options,c=a.googleSpreadsheetKey,d=this.columns,e=a.startRow||0,f=a.endRow||Number.MAX_VALUE,i=a.startColumn||0,h=a.endColumn||Number.MAX_VALUE,g,k;c&&jQuery.ajax({dataType:"json",url:"https://spreadsheets.google.com/feeds/cells/"+c+"/"+(a.googleSpreadsheetWorksheet||"od6")+"/public/values?alt=json-in-script&callback=?", 12 | error:a.error,success:function(a){var a=a.feed.entry,c,j=a.length,m=0,n=0,l;for(l=0;l=i&&l<=h)d[l-i]=[],d[l-i].length=Math.min(n,f-e);for(l=0;l=i&&k<=h&&g>=e&&g<=f)d[k-i][g-e]=c.content.$t;b.dataFound()}})},findHeaderRow:function(){m(this.columns,function(){});this.headerRow=0},trim:function(b){return typeof b==="string"?b.replace(/^\s+|\s+$/g,""):b},parseTypes:function(){for(var b= 13 | this.columns,a=b.length,c,d,e,f;a--;)for(c=b[a].length;c--;)d=b[a][c],e=parseFloat(d),f=this.trim(d),f==e?(b[a][c]=e,e>31536E6?b[a].isDatetime=!0:b[a].isNumeric=!0):(d=this.parseDate(d),a===0&&typeof d==="number"&&!isNaN(d)?(b[a][c]=d,b[a].isDatetime=!0):b[a][c]=f===""?null:f)},dateFormats:{"YYYY-mm-dd":{regex:"^([0-9]{4})-([0-9]{2})-([0-9]{2})$",parser:function(b){return Date.UTC(+b[1],b[2]-1,+b[3])}}},parseDate:function(b){var a=this.options.parseDate,c,d,e;a&&(c=a(b));if(typeof b==="string")for(d in this.dateFormats)a= 14 | this.dateFormats[d],(e=b.match(a.regex))&&(c=a.parser(e));return c},rowsToColumns:function(b){var a,c,d,e,f;if(b){f=[];c=b.length;for(a=0;a1&&(a=b.shift(),this.headerRow===0&&a.shift(),a.isDatetime? 15 | c="datetime":a.isNumeric||(c="category"));for(h=0;h1&&i[g].push(b[h+1][g]!==void 0?b[h+1][g]:null),e>2&&i[g].push(b[h+2][g]!==void 0?b[h+2][g]:null),e>3&&i[g].push(b[h+3][g]!==void 0?b[h+3][g]:null),e>4&&i[g].push(b[h+4][g]!==void 0?b[h+4][g]:null);f[k]= 16 | {name:b[h].name,data:i};h+=e}b={xAxis:{type:c},series:f};d.complete&&d.complete(b);d.afterComplete&&d.afterComplete(b)}}});j.Data=n;j.data=function(b,a){return new n(b,a)};j.wrap(j.Chart.prototype,"init",function(b,a,c){var d=this;a&&a.data?j.data(j.extend(a.data,{afterComplete:function(e){var f,i;if(a.hasOwnProperty("series"))if(typeof a.series==="object")for(f=Math.max(a.series.length,e.series.length);f--;)i=a.series[f]||{},a.series[f]=j.merge(i,e.series[f]);else delete a.series;a=j.merge(e,a); 17 | b.call(d,a,c)}}),a):b.call(d,a,c)})})(Highcharts); 18 | -------------------------------------------------------------------------------- /sniffer_cache_oui.js: -------------------------------------------------------------------------------- 1 | // This is a copy, perhaps slightly modified, of node-ieee-oui-lookup which 2 | // is no longer maintained. Mainly I needed to control the sqlite3 dependency 3 | // more directly when using sniffer.js within node-webkit. 4 | 5 | // Currently just reading in file. For Sqlite revert version of this file in: 6 | // https://github.com/cyphunk/snifferjs/commit/cae731e0ea2a578f7437dd475b68fe1e5533bc63 7 | // memory profiling shows that initially file->array method creates large 8 | // overhead until garbage collect: 9 | // { rss: 81932288, heapTotal: 56496224, heapUsed: 28114096 } 10 | // then later: 11 | // { rss: 53932032, heapTotal: 27606624, heapUsed: 23904760 } 12 | // old sqlite version: 13 | // { rss: 44187648, heapTotal: 20811872, heapUsed: 14601848 } 14 | // after db created first time: 15 | // { rss: 196759552, heapTotal: 86843744, heapUsed: 61633488 } 16 | // then later, 10 minutes or so: 17 | // { rss: 146825216, heapTotal: 37327456, heapUsed: 17600248 } 18 | // on second load it is smaller: 19 | // { rss: 58720256, heapTotal: 33183072, heapUsed: 14307504 } 20 | 21 | 22 | var fs = require('fs'); 23 | var http = require('http'); 24 | var readline = require('readline'); 25 | 26 | var OUI_URL = 'http://standards-oui.ieee.org/oui/oui.txt'; 27 | //var OUI_URL = 'http://localhost:8000/testoui10k.txt'; 28 | //var OUI_URL = 'http://localhost:8000/testoui.txt'; 29 | var OUI_TXT = __dirname + '/oui.txt'; 30 | var FETCH_EVERY_N_DAYS = 30; // fetch oui.txt 31 | 32 | exports.debug = false; 33 | // exports.verbose = false; // print out a lot about ouiitems 34 | 35 | var ouiitems = {}; 36 | 37 | exports.start = function(cb) { 38 | 39 | fs.stat(OUI_TXT, function(err, st1) { 40 | // on error or txt file older than 30 days: fetch (will call parse on finish) 41 | if ((!!err) || (st1.mtime.getTime() <= (new Date().getTime() - (FETCH_EVERY_N_DAYS * 86400 * 1000)))) 42 | return fetch(cb); 43 | 44 | return parse(cb); 45 | }); 46 | }; 47 | 48 | exports.lookup = function(oui, cb) { 49 | // remove : and - in name 50 | var h6 = oui.split('-').join('').split(':').join('').toUpperCase(); 51 | if (h6.length != 6) return cb(new Error('not an OUI'), null); 52 | // change to int which is ouiitems are indexed 53 | h6 = parseInt(h6.trimLeft('0'), 16) 54 | 55 | cb(null, ouiitems[h6]); 56 | }; 57 | 58 | exports.show = function() { 59 | console.log(ouiitems) 60 | }; 61 | 62 | var fetch = function(cb) { 63 | // handle cases where ieee site offline or network unavailble by loading to tmp 64 | exports.debug && cb(null, "begin downloading "+OUI_URL+". To avoid, stop process and touch "+OUI_TXT); 65 | 66 | var f = fs.createWriteStream(OUI_TXT+'.tmp'); 67 | f.on('finish', function(){ 68 | exports.debug && cb(null, "finished downloading "+OUI_URL); 69 | fs.rename(OUI_TXT+'.tmp', OUI_TXT, function() { 70 | parse(cb) }); }); 71 | f.on('error', function(){ 72 | cb(err, null); 73 | fs.unlink(OUI_TXT+'.tmp') }); 74 | 75 | var request = http.get(OUI_URL, function(response) { 76 | response.setEncoding('utf8'); 77 | response.pipe(f) 78 | }); 79 | request.on('error', function(err) { 80 | cb(err, null); 81 | fs.unlink(OUI_TXT+'.tmp') 82 | }); 83 | request.end(); 84 | 85 | }; 86 | 87 | /* 88 | 00-00-00 (hex)\t\t\t\t\tXEROX CORPORATION 89 | 000000 (base 16) XEROX CORPORATION 90 | M/S 105-50C 91 | 800 PHILLIPS ROAD 92 | WEBSTER NY 14580 93 | UNITED STATES 94 | */ 95 | 96 | var parse = function(cb) { 97 | exports.debug && cb(null, "begin parsing "+OUI_TXT); 98 | var rl = readline .createInterface({ input: fs.createReadStream(OUI_TXT)}); 99 | 100 | rl.on('line', function(line) { 101 | var h6, id, name; 102 | 103 | line = line.trim(); 104 | if (line.length > 15) { 105 | h6 = line.substr(0,6); 106 | line = line.substr(7).trimLeft(); 107 | if (line.substr(0,9) === '(base 16)') { 108 | name = line.substr(10).trimLeft(); 109 | exports.debug && console.log('line h6,name', h6,h6) 110 | } 111 | } 112 | 113 | if ((!!h6) && (h6.length === 6) && (!!name) && (name.length > 0)) { 114 | id = parseInt(h6.trimLeft('0'), 16); 115 | ouiitems[id] = name; 116 | } 117 | }); 118 | 119 | rl.on('close', function(){ 120 | exports.debug && cb(null, "finished parsing. Entries: "+Object.keys(ouiitems).length); 121 | }); 122 | }; 123 | 124 | exports.start(function(err, info) { 125 | if (!!err) return console.log('sniffer_cache_oui: ' + err.message); 126 | if (!!info) 127 | console.log('sniffer_cache_oui: ' + JSON.stringify(info)); 128 | }); 129 | 130 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Sniffer.js 2 | ========== 3 | 4 | This software intensely whitelists packets displayed. This permits easier 5 | monitoring of traffic by someone less familiar with packet filtering (such as 6 | actors on a stage). At the moment it is configured to only show outgoing packets 7 | from 192.168. 10. and 172. networks. Elements such as Logins via unencrypted 8 | POP / IMAP / HTTP-POST / HTTP-Auth shown. Images shown on mouse hover or 9 | automatically opened in a new tab/window. This is basically a Wall-Of-Sheep 10 | implementation for the theatrical stage. 11 | 12 | cyphunk@deadhacker.com for use in the Anonymous-P theater production. Pull 13 | requests and bug reports appreciated at any of: 14 | 15 | * 16 | * 17 | 18 | ![Screencast of use](./sniffer.gif) 19 | 20 | 21 | Features 22 | -------- 23 | 24 | * Alt+Click on Source IP filters current list by IP 25 | * Alt+Click Application Protocol column filters by protocol 26 | * MDNS host resolution 27 | * Entropy Graph (protocol agnostic method to measure amount of crypto in use) 28 | * Map of sessions for destinations geographical (not shown in screencast) 29 | * Auto open image urls in new tab/window (not show) 30 | * Hover over image url to show 31 | * Click found HTTP url to open in new tab/window 32 | * POP/IMAP Logins shown but unlike screen cast text is same color as 33 | background. 34 | * Login's via HTTP Post or HTTP Auth shown in light green 35 | 36 | 37 | License 38 | ------- 39 | 40 | License: Non-White-Heterosexual-Male 41 | 42 | If you are not a white heterosexual male you are permitted to copy, sell and use 43 | this work in any manner you choose without need to include any attribution you 44 | do not see fit. You are asked as a courtesy to retain this license in any 45 | derivatives but you are not required. If you are a white heterosexual male you 46 | are provided the same permissions (reuse, modification, resale) but are 47 | required to include this license in any documentation and any public facing 48 | derivative. You are also required to include attribution to the original author 49 | or to an author responsible for redistribution of a derivative. 50 | 51 | 52 | 53 | 54 | Install 55 | ------- 56 | 57 | Requires node libpcap-dev installed on your system. 58 | 59 | git clone https://github.com/cyphunk/snifferjs.git 60 | cd snifferjs 61 | npm install 62 | 63 | For resolving IP addresses to Geo Location download the Maxmind free dataset 64 | 65 | wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz 66 | gzip -d GeoIP.dat.gz 67 | 68 | 69 | Run 70 | --- 71 | 72 | node sniffer.js "" 73 | open http://localhost:8080 74 | 75 | (last arg is optional pcap fitler. e.g "ip") 76 | 77 | 78 | Sniffer.js has been tested with 79 | 80 | * node 4.2.6 81 | * npm 2.14.12 82 | * node-gyp 3.0.3 83 | 84 | Others have [reported](https://github.com/node-pcap/node_pcap/issues/196) 85 | ``4.4.4`` ``5.7.0`` ``8.9.2`` may also work. If you run into issues consider 86 | downgrading with ``n`: 87 | 88 | npm install -g -n 89 | n 4.2.6 90 | rm -rf node_modules 91 | npm install 92 | 93 | Configuration 94 | ------------- 95 | 96 | HTTP_ONLY_FIRST=true Only the first HTTP packet will be shown. If a network 97 | user accesses http://gessnerallee.ch only the GET for 98 | the index.html will be shown, not subsequent image and 99 | resource loads over HTTP. *_ONLY_FIRST applies in a 100 | similar many for other protocols. 101 | 102 | FIRST_PER_IP=false The *_ONLY_FIRST flags apply globally. This means if two 103 | network users access HTTP sites at the same time only 104 | the first will be shown. 105 | 106 | MAIL_ONLY_LOGIN=true Only LOGIN requests for POP/IMAP are shown. 107 | 108 | ONLY_OUTGOING=true Only show packets going out from 192.168 10. and 172. 109 | networks. (AT THE MOMENT NOT AVAILABLE. ONLY_OUTGOING 110 | is the default behavior) 111 | 112 | Installation Alternatives 113 | ------------------------- 114 | 115 | docker.io 116 | 117 | docker build -t snifferjs \ 118 | https://raw.githubusercontent.com/cyphunk/snifferjs/master/Dockerfile 119 | 120 | Older node v0.10.25 npm v1.3.24 121 | 122 | git reset --hard a68b74beef81d196969a0b9a06e25a2975f6b001 123 | rm -rf node_modules 124 | npm install 125 | 126 | 127 | Etc 128 | --- 129 | 130 | ### Entropy Graphs 131 | 132 | Currently disabled by default the code can display a graph of overall network 133 | data entropy levels. For this one needs to install libdisorder 134 | 135 | git clone https://github.com/locasto/libdisorder.git 136 | cd libdisorder/code/src 137 | make 138 | # ON OSX: 139 | gcc -dynamiclib -flat_namespace "*.o" -o libdisorder.dylib 140 | cp libdisorder.dylib 141 | # ON LINUX 142 | gcc -shared -o libdisorder.so -fPIC disorder.c 143 | cp libdisorder.so 144 | 145 | 146 | ### Troubleshooting MDNS 147 | 148 | To check that dig resolve for MDNS resolution: 149 | 150 | dig +noall +answer +time=1 -x -p 5353 @224.0.0.251 151 | dig +noall +answer +time=1 -x -p 5353 @ 152 | 153 | should return something like: 154 | 155 | .in-addr.arpa. 10 IN PTR thais.local. 156 | 157 | ``sniffer_cache.js`` uses this command and takes the last 158 | part of the text when split on spaces. 159 | 160 | ### Error: libpcap.so.0.8: cannot open shared object 161 | 162 | Recompile 163 | -------------------------------------------------------------------------------- /client/js/exporting.js: -------------------------------------------------------------------------------- 1 | /* 2 | Highmaps JS v1.0.2 (2014-06-13) 3 | Exporting module 4 | 5 | (c) 2010-2014 Torstein Honsi 6 | 7 | License: www.highcharts.com/license 8 | */ 9 | (function(f){var A=f.Chart,t=f.addEvent,B=f.removeEvent,l=f.createElement,o=f.discardElement,v=f.css,k=f.merge,r=f.each,p=f.extend,D=Math.max,j=document,C=window,E=f.isTouchDevice,F=f.Renderer.prototype.symbols,s=f.getOptions(),y;p(s.lang,{printChart:"Print chart",downloadPNG:"Download PNG image",downloadJPEG:"Download JPEG image",downloadPDF:"Download PDF document",downloadSVG:"Download SVG vector image",contextButtonTitle:"Chart context menu"});s.navigation={menuStyle:{border:"1px solid #A0A0A0", 10 | background:"#FFFFFF",padding:"5px 0"},menuItemStyle:{padding:"0 10px",background:"none",color:"#303030",fontSize:E?"14px":"11px"},menuItemHoverStyle:{background:"#4572A5",color:"#FFFFFF"},buttonOptions:{symbolFill:"#E0E0E0",symbolSize:14,symbolStroke:"#666",symbolStrokeWidth:3,symbolX:12.5,symbolY:10.5,align:"right",buttonSpacing:3,height:22,theme:{fill:"white",stroke:"none"},verticalAlign:"top",width:24}};s.exporting={type:"image/png",url:"http://export.highcharts.com/",buttons:{contextButton:{menuClassName:"highcharts-contextmenu", 11 | symbol:"menu",_titleKey:"contextButtonTitle",menuItems:[{textKey:"printChart",onclick:function(){this.print()}},{separator:!0},{textKey:"downloadPNG",onclick:function(){this.exportChart()}},{textKey:"downloadJPEG",onclick:function(){this.exportChart({type:"image/jpeg"})}},{textKey:"downloadPDF",onclick:function(){this.exportChart({type:"application/pdf"})}},{textKey:"downloadSVG",onclick:function(){this.exportChart({type:"image/svg+xml"})}}]}}};f.post=function(b,a,d){var c,b=l("form",k({method:"post", 12 | action:b,enctype:"multipart/form-data"},d),{display:"none"},j.body);for(c in a)l("input",{type:"hidden",name:c,value:a[c]},null,b);b.submit();o(b)};p(A.prototype,{getSVG:function(b){var a=this,d,c,z,h,g=k(a.options,b);if(!j.createElementNS)j.createElementNS=function(a,b){return j.createElement(b)};b=l("div",null,{position:"absolute",top:"-9999em",width:a.chartWidth+"px",height:a.chartHeight+"px"},j.body);c=a.renderTo.style.width;h=a.renderTo.style.height;c=g.exporting.sourceWidth||g.chart.width|| 13 | /px$/.test(c)&&parseInt(c,10)||600;h=g.exporting.sourceHeight||g.chart.height||/px$/.test(h)&&parseInt(h,10)||400;p(g.chart,{animation:!1,renderTo:b,forExport:!0,width:c,height:h});g.exporting.enabled=!1;g.series=[];r(a.series,function(a){z=k(a.options,{animation:!1,enableMouseTracking:!1,showCheckbox:!1,visible:a.visible});z.isInternal||g.series.push(z)});d=new f.Chart(g,a.callback);r(["xAxis","yAxis"],function(b){r(a[b],function(a,c){var g=d[b][c],f=a.getExtremes(),h=f.userMin,f=f.userMax;g&&(h!== 14 | void 0||f!==void 0)&&g.setExtremes(h,f,!0,!1)})});c=d.container.innerHTML;g=null;d.destroy();o(b);c=c.replace(/zIndex="[^"]+"/g,"").replace(/isShadow="[^"]+"/g,"").replace(/symbolName="[^"]+"/g,"").replace(/jQuery[0-9]+="[^"]+"/g,"").replace(/url\([^#]+#/g,"url(#").replace(/.*?$/,"").replace(/(fill|stroke)="rgba\(([ 0-9]+,[ 0-9]+,[ 0-9]+),([ 0-9\.]+)\)"/g,'$1="rgb($2)" $1-opacity="$3"').replace(/ /g, 15 | " ").replace(/­/g,"­").replace(//g,'xlink:href="$1"/>').replace(/id=([^" >]+)/g,'id="$1"').replace(/class=([^" >]+)/g,'class="$1"').replace(/ transform /g," ").replace(/:(path|rect)/g,"$1").replace(/style="([^"]+)"/g,function(a){return a.toLowerCase()});return c=c.replace(/(url\(#highcharts-[0-9]+)"/g,"$1").replace(/"/g,"'")},exportChart:function(b,a){var b= 16 | b||{},d=this.options.exporting,d=this.getSVG(k({chart:{borderRadius:0}},d.chartOptions,a,{exporting:{sourceWidth:b.sourceWidth||d.sourceWidth,sourceHeight:b.sourceHeight||d.sourceHeight}})),b=k(this.options.exporting,b);f.post(b.url,{filename:b.filename||"chart",type:b.type,width:b.width||0,scale:b.scale||2,svg:d},b.formAttributes)},print:function(){var b=this,a=b.container,d=[],c=a.parentNode,f=j.body,h=f.childNodes;if(!b.isPrinting)b.isPrinting=!0,r(h,function(a,b){if(a.nodeType===1)d[b]=a.style.display, 17 | a.style.display="none"}),f.appendChild(a),C.focus(),C.print(),setTimeout(function(){c.appendChild(a);r(h,function(a,b){if(a.nodeType===1)a.style.display=d[b]});b.isPrinting=!1},1E3)},contextMenu:function(b,a,d,c,f,h,g){var e=this,k=e.options.navigation,q=k.menuItemStyle,m=e.chartWidth,n=e.chartHeight,j="cache-"+b,i=e[j],u=D(f,h),w,x,o,s=function(a){e.pointer.inClass(a.target,b)||x()};if(!i)e[j]=i=l("div",{className:b},{position:"absolute",zIndex:1E3,padding:u+"px"},e.container),w=l("div",null,p({MozBoxShadow:"3px 3px 10px #888", 18 | WebkitBoxShadow:"3px 3px 10px #888",boxShadow:"3px 3px 10px #888"},k.menuStyle),i),x=function(){v(i,{display:"none"});g&&g.setState(0);e.openMenu=!1},t(i,"mouseleave",function(){o=setTimeout(x,500)}),t(i,"mouseenter",function(){clearTimeout(o)}),t(document,"mouseup",s),t(e,"destroy",function(){B(document,"mouseup",s)}),r(a,function(a){if(a){var b=a.separator?l("hr",null,null,w):l("div",{onmouseover:function(){v(this,k.menuItemHoverStyle)},onmouseout:function(){v(this,q)},onclick:function(){x();a.onclick.apply(e, 19 | arguments)},innerHTML:a.text||e.options.lang[a.textKey]},p({cursor:"pointer"},q),w);e.exportDivElements.push(b)}}),e.exportDivElements.push(w,i),e.exportMenuWidth=i.offsetWidth,e.exportMenuHeight=i.offsetHeight;a={display:"block"};d+e.exportMenuWidth>m?a.right=m-d-f-u+"px":a.left=d-u+"px";c+h+e.exportMenuHeight>n&&g.alignOptions.verticalAlign!=="top"?a.bottom=n-c-u+"px":a.top=c+h-u+"px";v(i,a);e.openMenu=!0},addButton:function(b){var a=this,d=a.renderer,c=k(a.options.navigation.buttonOptions,b),j= 20 | c.onclick,h=c.menuItems,g,e,l={stroke:c.symbolStroke,fill:c.symbolFill},q=c.symbolSize||12;if(!a.btnCount)a.btnCount=0;if(!a.exportDivElements)a.exportDivElements=[],a.exportSVGElements=[];if(c.enabled!==!1){var m=c.theme,n=m.states,o=n&&n.hover,n=n&&n.select,i;delete m.states;j?i=function(){j.apply(a,arguments)}:h&&(i=function(){a.contextMenu(e.menuClassName,h,e.translateX,e.translateY,e.width,e.height,e);e.setState(2)});c.text&&c.symbol?m.paddingLeft=f.pick(m.paddingLeft,25):c.text||p(m,{width:c.width, 21 | height:c.height,padding:0});e=d.button(c.text,0,0,i,m,o,n).attr({title:a.options.lang[c._titleKey],"stroke-linecap":"round"});e.menuClassName=b.menuClassName||"highcharts-menu-"+a.btnCount++;c.symbol&&(g=d.symbol(c.symbol,c.symbolX-q/2,c.symbolY-q/2,q,q).attr(p(l,{"stroke-width":c.symbolStrokeWidth||1,zIndex:1})).add(e));e.add().align(p(c,{width:e.width,x:f.pick(c.x,y)}),!0,"spacingBox");y+=(e.width+c.buttonSpacing)*(c.align==="right"?-1:1);a.exportSVGElements.push(e,g)}},destroyExport:function(b){var b= 22 | b.target,a,d;for(a=0;ac.minPixelPadding||c.min===c.dataMin&&c.max===c.dataMax)a=0;c.minPixelPadding-=a}});p(o.prototype, 12 | "render",function(a){a.call(this);this.fixTo=null});var D=i.ColorAxis=function(){this.isColorAxis=!0;this.init.apply(this,arguments)};q(D.prototype,o.prototype);q(D.prototype,{defaultColorAxisOptions:{lineWidth:0,gridLineWidth:1,tickPixelInterval:72,startOnTick:!0,endOnTick:!0,offset:0,marker:{animation:{duration:50},color:"gray",width:0.01},labels:{overflow:"justify"},minColor:"#EFEFFF",maxColor:"#003875",tickLength:5},init:function(a,b){var d=a.options.legend.layout!=="vertical",c;c=m(this.defaultColorAxisOptions, 13 | {side:d?2:1,reversed:!d},b,{isX:d,opposite:!d,showEmpty:!1,title:null,isColor:!0});o.prototype.init.call(this,a,c);b.dataClasses&&this.initDataClasses(b);this.initStops(b);this.isXAxis=!0;this.horiz=d;this.zoomEnabled=!1},tweenColors:function(a,b,d){var c=b.rgba[3]!==1||a.rgba[3]!==1;return(c?"rgba(":"rgb(")+Math.round(b.rgba[0]+(a.rgba[0]-b.rgba[0])*(1-d))+","+Math.round(b.rgba[1]+(a.rgba[1]-b.rgba[1])*(1-d))+","+Math.round(b.rgba[2]+(a.rgba[2]-b.rgba[2])*(1-d))+(c?","+(b.rgba[3]+(a.rgba[3]-b.rgba[3])* 14 | (1-d)):"")+")"},initDataClasses:function(a){var b=this,d=this.chart,c,e=0,f=this.options;this.dataClasses=c=[];this.legendItems=[];k(a.dataClasses,function(g,h){var j,g=m(g);c.push(g);if(!g.color)f.dataClassColor==="category"?(j=d.options.colors,g.color=j[e++],e===j.length&&(e=0)):g.color=b.tweenColors(z(f.minColor),z(f.maxColor),h/(a.dataClasses.length-1))})},initStops:function(a){this.stops=a.stops||[[0,this.options.minColor],[1,this.options.maxColor]];k(this.stops,function(a){a.color=z(a[1])})}, 15 | setOptions:function(a){o.prototype.setOptions.call(this,a);this.options.crosshair=this.options.marker;this.coll="colorAxis"},setAxisSize:function(){var a=this.legendSymbol,b=this.chart,d,c,e;if(a)this.left=d=a.attr("x"),this.top=c=a.attr("y"),this.width=e=a.attr("width"),this.height=a=a.attr("height"),this.right=b.chartWidth-d-e,this.bottom=b.chartHeight-c-a,this.len=this.horiz?e:a,this.pos=this.horiz?d:c},toColor:function(a,b){var d,c=this.stops,e,f=this.dataClasses,g,h;if(f)for(h=f.length;h--;){if(g= 16 | f[h],e=g.from,c=g.to,(e===void 0||a>=e)&&(c===void 0||a<=c)){d=g.color;if(b)b.dataClass=h;break}}else{this.isLog&&(a=this.val2lin(a));d=1-(this.max-a)/(this.max-this.min||1);for(h=c.length;h--;)if(d>c[h][0])break;e=c[h]||c[h+1];c=c[h+1]||e;d=1-(c[0]-d)/(c[0]-e[0]||1);d=this.tweenColors(e.color,c.color,d)}return d},getOffset:function(){var a=this.legendGroup,b=this.chart.axisOffset[this.side];if(a){o.prototype.getOffset.call(this);if(!this.axisGroup.parentGroup)this.axisGroup.add(a),this.gridGroup.add(a), 17 | this.labelGroup.add(a),this.added=!0;this.chart.axisOffset[this.side]=b}},setLegendColor:function(){var a,b=this.options;a=this.horiz?[0,0,1,0]:[0,0,0,1];this.legendColor={linearGradient:{x1:a[0],y1:a[1],x2:a[2],y2:a[3]},stops:b.stops||[[0,b.minColor],[1,b.maxColor]]}},drawLegendSymbol:function(a,b){var d=a.padding,c=a.options,e=this.horiz,f=n(c.symbolWidth,e?200:12),g=n(c.symbolHeight,e?12:200),h=n(c.labelPadding,e?16:30),c=n(c.itemDistance,10);this.setLegendColor();b.legendSymbol=this.chart.renderer.rect(0, 18 | a.baseline-11,f,g).attr({zIndex:1}).add(b.legendGroup);b.legendSymbol.getBBox();this.legendItemWidth=f+d+(e?c:h);this.legendItemHeight=g+d+(e?h:0)},setState:s,visible:!0,setVisible:s,getSeriesExtremes:function(){var a;if(this.series.length)a=this.series[0],this.dataMin=a.valueMin,this.dataMax=a.valueMax},drawCrosshair:function(a,b){var d=!this.cross,c=b&&b.plotX,e=b&&b.plotY,f,g=this.pos,h=this.len;if(b)f=this.toPixels(b.value),fg+h&&(f=g+h+2),b.plotX=f,b.plotY=this.len-f,o.prototype.drawCrosshair.call(this, 19 | a,b),b.plotX=c,b.plotY=e,!d&&this.cross&&this.cross.attr({fill:this.crosshair.color}).add(this.labelGroup)},getPlotLinePath:function(a,b,d,c,e){return e?this.horiz?["M",e-4,this.top-6,"L",e+4,this.top-6,e,this.top,"Z"]:["M",this.left,e,"L",this.left-6,e+6,this.left-6,e-6,"Z"]:o.prototype.getPlotLinePath.call(this,a,b,d,c)},update:function(a,b){k(this.series,function(a){a.isDirtyData=!0});o.prototype.update.call(this,a,b);this.legendItem&&(this.setLegendColor(),this.chart.legend.colorizeItem(this, 20 | !0))},getDataClassLegendSymbols:function(){var a=this,b=this.chart,d=this.legendItems,c=b.options.legend,e=c.valueDecimals,f=c.valueSuffix||"",g;d.length||k(this.dataClasses,function(c,j){var i=!0,x=c.from,l=c.to;g="";x===void 0?g="< ":l===void 0&&(g="> ");x!==void 0&&(g+=I(x,e)+f);x!==void 0&&l!==void 0&&(g+=" - ");l!==void 0&&(g+=I(l,e)+f);d.push(q({chart:b,name:g,options:{},drawLegendSymbol:E.drawRectangle,visible:!0,setState:s,setVisible:function(){i=this.visible=!i;k(a.series,function(a){k(a.points, 21 | function(a){a.dataClass===j&&a.setVisible(i)})});b.legend.colorizeItem(this,i)}},c))});return d},name:""});p(y.prototype,"getAxes",function(a){var b=this.options.colorAxis;a.call(this);this.colorAxis=[];b&&new D(this,b)});p(C.prototype,"getAllItems",function(a){var b=[],d=this.chart.colorAxis[0];d&&(d.options.dataClasses?b=b.concat(d.getDataClassLegendSymbols()):b.push(d),k(d.series,function(a){a.options.showInLegend=!1}));return b.concat(a.call(this))});C={pointAttrToOptions:{stroke:"borderColor", 22 | "stroke-width":"borderWidth",fill:"color",dashstyle:"dashStyle"},pointArrayMap:["value"],axisTypes:["xAxis","yAxis","colorAxis"],optionalAxis:"colorAxis",trackerGroups:["group","markerGroup","dataLabelsGroup"],getSymbol:s,parallelArrays:["x","y","value"],translateColors:function(){var a=this,b=this.options.nullColor,d=this.colorAxis;k(this.data,function(c){var e=c.value;if(e=e===null?b:d&&e!==void 0?d.toColor(e,c):c.color||a.color)c.color=e})}};p(B.prototype,"buildText",function(a,b){var d=b.styles&& 23 | b.styles.HcTextStroke;a.call(this,b);d&&b.applyTextStroke&&b.applyTextStroke(d)});B.prototype.Element.prototype.applyTextStroke=function(a){var b=this.element,d,c,a=a.split(" ");d=b.getElementsByTagName("tspan");c=b.firstChild;this.ySetter=this.xSetter;k([].slice.call(d),function(d,f){var g;f===0&&(d.setAttribute("x",b.getAttribute("x")),(f=b.getAttribute("y"))!==null&&d.setAttribute("y",f));g=d.cloneNode(1);g.setAttribute("stroke",a[1]);g.setAttribute("stroke-width",a[0]);g.setAttribute("stroke-linejoin", 24 | "round");b.insertBefore(g,c)})};q(y.prototype,{renderMapNavigation:function(){var a=this,b=this.options.mapNavigation,d=b.buttons,c,e,f,g,h=function(){this.handler.call(a)};if(n(b.enableButtons,b.enabled)&&!a.renderer.forExport)for(c in d)if(d.hasOwnProperty(c))f=m(b.buttonOptions,d[c]),e=f.theme,g=e.states,e=a.renderer.button(f.text,0,0,h,e,g&&g.hover,g&&g.select,0,c==="zoomIn"?"topbutton":"bottombutton").attr({width:f.width,height:f.height,title:a.options.lang[c],zIndex:5}).css(f.style).add(),e.handler= 25 | f.onclick,e.align(q(f,{width:e.width,height:2*e.height}),null,f.alignTo)},fitToBox:function(a,b){k([["x","width"],["y","height"]],function(d){var c=d[0],d=d[1];a[c]+a[d]>b[c]+b[d]&&(a[d]>b[d]?(a[d]=b[d],a[c]=b[c]):a[c]=b[c]+b[d]-a[d]);a[d]>b[d]&&(a[d]=b[d]);a[c]c.scaleY,this.pinchTranslateDirection(!a,b,d,c,e,f,g,a?c.scaleX:c.scaleY))});r.map=m(r.scatter,{allAreas:!0,animation:!1,nullColor:"#F8F8F8",borderColor:"silver",borderWidth:1,marker:null,stickyTracking:!1,dataLabels:{formatter:function(){return this.point.value},verticalAlign:"middle",crop:!1,overflow:!1,padding:0,style:{color:"white", 30 | fontWeight:"bold",HcTextStroke:"3px rgba(0,0,0,0.5)"}},turboThreshold:0,tooltip:{followPointer:!0,pointFormat:"{point.name}: {point.value}
"},states:{normal:{animation:!0},hover:{brightness:0.2,halo:null}}});u=t(A,{applyOptions:function(a,b){var d=A.prototype.applyOptions.call(this,a,b),c=this.series,e=c.joinBy;if(c.mapData)if(e=d[e[1]]&&c.mapMap[d[e[1]]]){if(c.xyFromShape)d.x=e._midX,d.y=e._midY;q(d,e)}else d.value=d.value||null;return d},setVisible:function(a){var b=this,d=a?"show":"hide";k(["graphic", 31 | "dataLabel"],function(a){if(b[a])b[a][d]()})},onMouseOver:function(a){clearTimeout(this.colorInterval);this.value!==null&&A.prototype.onMouseOver.call(this,a)},onMouseOut:function(){var a=this,b=+new Date,d=z(a.color),c=z(a.pointAttr.hover.fill),e=a.series.options.states.normal.animation,f=e&&(e.duration||500),g;if(f&&d.rgba.length===4&&c.rgba.length===4&&a.state!=="select")g=a.pointAttr[""].fill,delete a.pointAttr[""].fill,clearTimeout(a.colorInterval),a.colorInterval=setInterval(function(){var e= 32 | (new Date-b)/f,g=a.graphic;e>1&&(e=1);g&&g.attr("fill",D.prototype.tweenColors.call(0,c,d,e));e>=1&&clearTimeout(a.colorInterval)},13);A.prototype.onMouseOut.call(a);if(g)a.pointAttr[""].fill=g},zoomTo:function(){var a=this.series;a.xAxis.setExtremes(this._minX,this._maxX,!1);a.yAxis.setExtremes(this._minY,this._maxY,!1);a.chart.redraw()}});l.map=t(l.scatter,m(C,{type:"map",pointClass:u,supportsDrilldown:!0,getExtremesFromAll:!0,useMapGeometry:!0,forceDL:!0,getBox:function(a){var b=Number.MAX_VALUE, 33 | d=-b,c=b,e=-b,f=b,g=b,h=this.xAxis,j=this.yAxis,l;k(a||[],function(a){if(a.path){if(typeof a.path==="string")a.path=i.splitPath(a.path);var h=a.path||[],j=h.length,k=!1,m=-b,o=b,q=-b,p=b,r=a.properties;if(!a._foundBox){for(;j--;)typeof h[j]==="number"&&!isNaN(h[j])&&(k?(m=Math.max(m,h[j]),o=Math.min(o,h[j])):(q=Math.max(q,h[j]),p=Math.min(p,h[j])),k=!k);a._midX=o+(m-o)*(a.middleX||r&&r["hc-middle-x"]||0.5);a._midY=p+(q-p)*(a.middleY||r&&r["hc-middle-y"]||0.5);a._maxX=m;a._minX=o;a._maxY=q;a._minY= 34 | p;a.labelrank=n(a.labelrank,(m-o)*(q-p));a._foundBox=!0}d=Math.max(d,a._maxX);c=Math.min(c,a._minX);e=Math.max(e,a._maxY);f=Math.min(f,a._minY);g=Math.min(a._maxX-a._minX,a._maxY-a._minY,g);l=!0}});if(l){this.minY=Math.min(f,n(this.minY,b));this.maxY=Math.max(e,n(this.maxY,-b));this.minX=Math.min(c,n(this.minX,b));this.maxX=Math.max(d,n(this.maxX,-b));if(h&&h.options.minRange===void 0)h.minRange=Math.min(5*g,(this.maxX-this.minX)/5,h.minRange||b);if(j&&j.options.minRange===void 0)j.minRange=Math.min(5* 35 | g,(this.maxY-this.minY)/5,j.minRange||b)}},getExtremes:function(){v.prototype.getExtremes.call(this,this.valueData);this.chart.hasRendered&&this.isDirtyData&&this.getBox(this.options.data);this.valueMin=this.dataMin;this.valueMax=this.dataMax;this.dataMin=this.minY;this.dataMax=this.maxY},translatePath:function(a){var b=!1,d=this.xAxis,c=this.yAxis,e=d.min,f=d.transA,d=d.minPixelPadding,g=c.min,h=c.transA,c=c.minPixelPadding,j,i=[];if(a)for(j=a.length;j--;)typeof a[j]==="number"?(i[j]=b?(a[j]-e)* 36 | f+d:(a[j]-g)*h+c,b=!b):i[j]=a[j];return i},setData:function(a,b){var d=this.options,c=d.mapData,e=d.joinBy,f=e===null,g=[],h,j,l;f&&(e="_i");e=this.joinBy=i.splat(e);e[1]||(e[1]=e[0]);a&&k(a,function(b,c){typeof b==="number"&&(a[c]={value:b});if(f)a[c]._i=c});this.getBox(a);if(c){c.type==="FeatureCollection"&&(c=i.geojson(c,this.type,this));this.getBox(c);this.mapData=c;this.mapMap={};for(l=0;l0.99&&d<1.01&&c>0.99&&c<1.01?(b=a=0,c=d=1):(a=a.toPixels(f.originX,!0),b=b.toPixels(f.originY,!0)),this.transformGroup.animate({translateX:a, 40 | translateY:b,scaleX:d,scaleY:c}));this.drawMapDataLabels()},drawMapDataLabels:function(){v.prototype.drawDataLabels.call(this);this.dataLabelsGroup&&this.dataLabelsGroup.clip(this.chart.clipRect);this.hideOverlappingDataLabels()},hideOverlappingDataLabels:function(){var a=this.points,b=a.length,d,c,e,f;k(a,function(a,b){if(b=a.dataLabel)b.oldOpacity=b.opacity,b.newOpacity=1});for(d=0;d 41 | e.alignAttr.x+e.width||f.alignAttr.x+f.widthe.alignAttr.y+e.height||f.alignAttr.y+f.height3E3?setTimeout(function(){b.call(a)}):b.call(a)},animate:function(a){var b=this.options.animation, 42 | d=this.group,c=this.xAxis,e=this.yAxis,f=c.pos,g=e.pos;if(this.chart.renderer.isSVG)b===!0&&(b={duration:1E3}),a?d.attr({translateX:f+c.len/2,translateY:g+e.len/2,scaleX:0.001,scaleY:0.001}):(d.animate({translateX:f,translateY:g,scaleX:1,scaleY:1},b),this.animate=null)},animateDrilldown:function(a){var b=this.chart.plotBox,d=this.chart.drilldownLevels[this.chart.drilldownLevels.length-1],c=d.bBox,e=this.chart.options.drilldown.animation;if(!a)a=Math.min(c.width/b.width,c.height/b.height),d.shapeArgs= 43 | {scaleX:a,scaleY:a,translateX:c.x,translateY:c.y},k(this.points,function(a){a.graphic.attr(d.shapeArgs).animate({scaleX:1,scaleY:1,translateX:0,translateY:0},e)}),this.animate=null},drawLegendSymbol:E.drawRectangle,animateDrillupFrom:function(a){l.column.prototype.animateDrillupFrom.call(this,a)},animateDrillupTo:function(a){l.column.prototype.animateDrillupTo.call(this,a)}}));r.mapline=m(r.map,{lineWidth:1,fillColor:"none"});l.mapline=t(l.map,{type:"mapline",pointAttrToOptions:{stroke:"color","stroke-width":"lineWidth", 44 | fill:"fillColor",dashstyle:"dashStyle"},drawLegendSymbol:l.line.prototype.drawLegendSymbol});r.mappoint=m(r.scatter,{dataLabels:{enabled:!0,formatter:function(){return this.point.name},color:"black",crop:!1,defer:!1,overflow:!1,style:{HcTextStroke:"3px rgba(255,255,255,0.5)"}}});l.mappoint=t(l.scatter,{type:"mappoint",forceDL:!0});if(l.bubble)r.mapbubble=m(r.bubble,{animationLimit:500,tooltip:{pointFormat:"{point.name}: {point.z}"}}),l.mapbubble=t(l.bubble,{pointClass:t(A,{applyOptions:u.prototype.applyOptions}), 45 | xyFromShape:!0,type:"mapbubble",pointArrayMap:["z"],getMapData:l.map.prototype.getMapData,getBox:l.map.prototype.getBox,setData:l.map.prototype.setData});w.plotOptions.heatmap=m(w.plotOptions.scatter,{animation:!1,borderWidth:0,nullColor:"#F8F8F8",dataLabels:{formatter:function(){return this.point.value},verticalAlign:"middle",crop:!1,overflow:!1,style:{color:"white",fontWeight:"bold",HcTextStroke:"1px rgba(0,0,0,0.5)"}},marker:null,tooltip:{pointFormat:"{point.x}, {point.y}: {point.value}
"}, 46 | states:{normal:{animation:!0},hover:{brightness:0.2}}});l.heatmap=t(l.scatter,m(C,{type:"heatmap",pointArrayMap:["y","value"],hasPointSpecificOptions:!0,supportsDrilldown:!0,getExtremesFromAll:!0,init:function(){l.scatter.prototype.init.apply(this,arguments);this.pointRange=this.options.colsize||1;this.yAxis.axisPointRange=this.options.rowsize||1},translate:function(){var a=this.options,b=this.xAxis,d=this.yAxis;this.generatePoints();k(this.points,function(c){var e=(a.colsize||1)/2,f=(a.rowsize|| 47 | 1)/2,g=Math.round(b.len-b.translate(c.x-e,0,1,0,1)),e=Math.round(b.len-b.translate(c.x+e,0,1,0,1)),h=Math.round(d.translate(c.y-f,0,1,0,1)),f=Math.round(d.translate(c.y+f,0,1,0,1));c.plotX=(g+e)/2;c.plotY=(h+f)/2;c.shapeType="rect";c.shapeArgs={x:Math.min(g,e),y:Math.min(h,f),width:Math.abs(e-g),height:Math.abs(f-h)}});this.translateColors();this.chart.hasRendered&&k(this.points,function(a){a.shapeArgs.fill=a.color})},drawPoints:l.column.prototype.drawPoints,animate:s,getBox:s,drawLegendSymbol:E.drawRectangle, 48 | getExtremes:function(){v.prototype.getExtremes.call(this,this.valueData);this.valueMin=this.dataMin;this.valueMax=this.dataMax;v.prototype.getExtremes.call(this)}}));i.geojson=function(a,b,d){var c=[],e=[],f=function(a){var b=0,c=a.length;for(e.push("M");bHighcharts © '+a.copyrightShort+"";return c};p(y.prototype,"showCredits",function(a,b){if(w.credits.text===this.options.credits.text&&this.mapCredits)b.text=this.mapCredits, 50 | b.href=null;a.call(this,b)});q(w.lang,{zoomIn:"Zoom in",zoomOut:"Zoom out"});w.mapNavigation={buttonOptions:{alignTo:"plotBox",align:"left",verticalAlign:"top",x:0,width:18,height:18,style:{fontSize:"15px",fontWeight:"bold",textAlign:"center"},theme:{"stroke-width":1}},buttons:{zoomIn:{onclick:function(){this.mapZoom(0.5)},text:"+",y:0},zoomOut:{onclick:function(){this.mapZoom(2)},text:"-",y:28}}};i.splitPath=function(a){var b,a=a.replace(/([A-Za-z])/g," $1 "),a=a.replace(/^\s*/,"").replace(/\s*$/, 51 | ""),a=a.split(/[ ,]+/);for(b=0;b 2 | 3 | 16 | 19 | 20 | 21 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 555 | 652 | 653 |
 
 
654 |
655 |   656 | autoscroll 657 | names 658 | autoimg 659 | entropy 660 | map 661 |
662 |
663 | 664 | 665 | 666 |
667 |
668 |
669 | 670 | 671 | -------------------------------------------------------------------------------- /sniffer.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* 4 | License: Non-White-Heterosexual-Male 5 | 6 | If you are not a white heterosexual male you are permitted to copy, sell and use 7 | this work in any manner you choose without need to include any attribution you 8 | do not see fit. You are asked as a courtesy to retain this license in any 9 | derivatives but you are not required. If you are a white heterosexual male you 10 | are provided the same permissions (reuse, modification, resale) but are 11 | required to include this license in any documentation and any public facing 12 | derivative. You are also required to include attribution to the original author 13 | or to an author responsible for redistribution of a derivative. 14 | */ 15 | 16 | // cyphunk@deadhacker.com 17 | // originally for use in the Anonymous-P theater production 18 | // https://github.com/cyphunk/snifferjs 19 | // pull requests appreciated 20 | 21 | // 22 | // SETTINGS 23 | // 24 | var LOCAL_DOMAIN = '.local'; // is replaced with '' on output 25 | 26 | // ENTROPY GRAPH 27 | var ENTROPY_ENABLED = false; // if dropping packets, try disabling 28 | var ENTROPY_BUFFER_LEN = 2048*10; // entropy buffer size 29 | var ENTROPY_BUFFER_DEBUG = false; // debugging to check buffer utilization 30 | var ENTROPY_LOG = false; // show entropy results on console 31 | 32 | var VERBOSE_DEBUG = false; // show tuns of shit 33 | var HTTP_LENGTH_MAX = 128; // how many chars of HTTP requests to show 34 | 35 | // THROTTLING 36 | // enable some trottling if pcap drops too many packets for your taste 37 | var FIRST_PER_IP = false; 38 | var HTTP_ONLY_FIRST = false; // set false for shows with less people 39 | var BROADCAST_ONLY_FIRST = true; 40 | var DNS_ONLY_FIRST = false; 41 | var MAIL_ONLY_LOGIN = false; //false to show all unencrypted mail packets 42 | 43 | var PROCESS_EXIT_WAIT = 1500; // need to wait on exit so file saves complete 44 | 45 | var SHOW_OTHER_TYPE_DATA = false; // show non-http/mail/dns data as Other 46 | 47 | // not used atm: 48 | // var MAKE_STATE_CHANGE_ON_HIDDEN_OTHER = false; // will toggle state cache on any non-matched packet 49 | // var SHOW_ANY_TCP_UDP = false; // turnning this on will set dat.app.type='tcp' or 'udp' for any tcp udp packet 50 | 51 | 52 | 53 | var util = require('util'); 54 | var pcap = require("pcap"), pcap_session; 55 | var DNS = require("pcap/decode/dns"); // pcap@2.0.1 dns decoding requires 56 | var express = require('express') 57 | var app = express(); 58 | var server = require('http').createServer(app); 59 | var io = require('socket.io').listen(server); 60 | var cache = null; // loaded later when lowered process from root priv 61 | 62 | // 63 | // libdisorder for entropy graphing 64 | // 65 | if (ENTROPY_ENABLED) { 66 | var ref = require('ref'); 67 | var ffi = require('ffi'); 68 | var stringPtr = ref.refType(ref.types.CString); 69 | var libdisorder = ffi.Library(__dirname+'/libdisorder', { 70 | 'shannon_H': [ 'float', [ stringPtr, 'longlong' ] ], 71 | 'get_num_tokens': [ 'int', [] ], 72 | 'get_max_entropy': [ 'float', [] ], 73 | 'get_entropy_ratio': [ 'float', [] ] 74 | }); 75 | } 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | // if (process.getuid() != 0) { 88 | // console.error('PCAP probably needs root'); 89 | // console.error('Will setuid/gid to owner of .js after pcap session initialized.'); 90 | // } 91 | 92 | //console.log('clear your DNS cache after start. sudo killall -HUP mDNSResponder'); 93 | if (process.argv.length < 3) { 94 | console.error("\nuse:\n"); 95 | console.error(" sudo node sniffer.js []\n\n"); 96 | console.error("\t network inteface to listen on (eth0, en0, wlan0, etc)\n"); 97 | console.error("\t put \"\" for no filtering.\n"); 98 | console.error("\t Define DNS server. E.g. 127.0.0.1 or check upstream server currently defined\n"); 99 | console.error("\t On Linux define upstream gateway address.\n"); 100 | console.error("Examples:\n"); 101 | console.error(' sudo node sniffer.js "" "tcp port 80" 127.0.0.1'); 102 | console.error(' sudo node sniffer.js eth1 "" 127.0.0.1'); 103 | console.error(' sudo node sniffer.js lo0 "ip proto \\tcp and tcp port 80" 127.0.0.1'); 104 | console.error(' sudo node sniffer.js en0 "not net 192.168.1.0/27 and not host 192.168.1.32 and not host 192.168.1.33" 127.0.0.1'); 105 | process.exit(1); 106 | } 107 | 108 | 109 | var netinterface = process.argv[2] 110 | var filter = process.argv[3]; 111 | var dnsserver = process.argv[4]; 112 | 113 | var gatewayip; 114 | if (/^darwin/.test(process.platform)) { 115 | gatewayip = require('netroute').getGateway(netinterface); 116 | } 117 | else { 118 | if (process.argv.length <= 5) { 119 | console.error("On linux please supply gateway address as argument"); 120 | process.exit(1); 121 | } 122 | else { 123 | gatewayip = process.argv[5]; 124 | } 125 | } 126 | 127 | 128 | 129 | 130 | // var netinterface = "eth0"; 131 | // var netinterface = "wlan0"; 132 | // var filter = "ip"; 133 | // var gatewayip = "192.168.44.1" 134 | 135 | 136 | // Setup PCAP netinterface now with root permissions and then downgrade to low priv 137 | //console.log(pcap.lib_version); 138 | try { 139 | pcap_session = pcap.createSession(netinterface, filter); 140 | } catch (e) { 141 | console.error(e); 142 | console.log("\nConsider running snifferjs as root or give yourself permission to monitor network interface:"); 143 | if (process.platform == 'linux') 144 | console.log("\nsudo setcap cap_net_raw,cap_net_admin=eip "+process.argv[0]+"\n"); 145 | else if (process.platform == 'darwin') 146 | console.log("\nuse ChmodBPF to give permissions to "+process.argv[0]+"\n"); 147 | setTimeout(function(){process.exit()}, PROCESS_EXIT_WAIT); 148 | } 149 | 150 | if (process.getuid() == 0) { 151 | require('fs').stat(__filename, function(err,s) { 152 | console.log('change process uid/gid to \"'+__filename+'\" owner: '+s.uid+'/'+s.gid); 153 | process.setgid(s.gid); 154 | process.setuid(s.uid); 155 | }); 156 | } 157 | 158 | cache = require('./sniffer_cache.js'); //oui,geo,dns,etc caches 159 | cache.dns.setServer(dnsserver); 160 | 161 | function save_state() { 162 | console.log('saving state'); 163 | cache.save(); 164 | } 165 | 166 | process.on( 'SIGINT', function() { 167 | console.log( "\nGracefully shutting down from SIGINT (Ctrl-C)" ); 168 | save_state(); 169 | setTimeout(function(){process.exit()}, PROCESS_EXIT_WAIT); 170 | }) 171 | 172 | var stdin = process.openStdin(); 173 | stdin.setRawMode(true); 174 | stdin.resume(); 175 | stdin.setEncoding('utf8'); 176 | stdin.on( 'data', function( key ){ 177 | if ( key === '\u0003' ) { // ctrl+c aka quit 178 | save_state(); 179 | setTimeout(function(){process.exit()}, PROCESS_EXIT_WAIT); 180 | } 181 | else if ( key === '\u0013' || key === '\u0012') { // ctrl+s or r aka save 182 | save_state(); 183 | } 184 | else if ( key === '\u0014') { // ctrl+t aka test 185 | cache.oui.show(); 186 | cache.geo.show(); 187 | cache.mdns.show(); 188 | cache.dns.show(); 189 | } 190 | 191 | //console.log(util.inspect(key,{depth: null})); // use to see key 192 | // write the key to stdout all normal like 193 | process.stdout.write( key ); 194 | }); 195 | 196 | 197 | server.listen(8080); 198 | console.log("Sniffer.js client listening on http 8080"); 199 | 200 | app.get('/', function (req, res) { 201 | res.sendFile(__dirname + '/client/index.html'); 202 | }); 203 | app.use('/client', express.static(__dirname + '/client')); 204 | 205 | 206 | 207 | function dumpError(err) { 208 | if (typeof err === 'object') { 209 | if (err.message) { 210 | console.log('\nMessage: ' + err.message) 211 | } 212 | if (err.stack) { 213 | console.log('\nStacktrace:') 214 | console.log('====================') 215 | console.log(err.stack); 216 | } 217 | } else { 218 | console.log('dumpError :: argument is not an object'); 219 | } 220 | } 221 | 222 | 223 | 224 | 225 | var detect_http_request = function (buf) { 226 | // from pcap.js TCP_tracker.prototype.detect_http_request 227 | var str = buf.toString('utf8', 0, buf.length); 228 | 229 | return (/^(OPTIONS|GET|HEAD|POST|PUT|DELETE|TRACE|CONNECT|COPY|LOCK|MKCOL|MOVE|PROPFIND|PROPPATCH|UNLOCK) [^\s\r\n]+ HTTP\/\d\.\d\r\n/.test(str)); 230 | }; 231 | 232 | var http_request_content = function (buf) { 233 | // from pcap.js TCP_tracker.prototype.detect_http_request 234 | var str = buf.toString('utf8', 0, buf.length); 235 | var content = ""; 236 | var match_req = str.match(/(GET|POST)\s+[^\s\r\n]+/i) 237 | if (match_req) { 238 | content+=match_req[0].substring(4,HTTP_LENGTH_MAX+4).trimLeft(); 239 | var match_host = str.match(/(Host:)\s+[^\s\r\n]+/i); 240 | if (match_host) 241 | content=match_host[0].substring(6,HTTP_LENGTH_MAX+4)+content; 242 | } 243 | else { 244 | content = null; 245 | } 246 | // return (/^(OPTIONS|GET|HEAD|POST|PUT|DELETE|TRACE|CONNECT|COPY|LOCK|MKCOL|MOVE|PROPFIND|PROPPATCH|UNLOCK) [^\s\r\n]+ HTTP\/\d\.\d\r\n/.test(str)); 247 | return content; 248 | }; 249 | 250 | var detect_mail_login_request = function (buf) { 251 | // from pcap.js TCP_tracker.prototype.detect_http_request 252 | var str = buf.toString('utf8', 0, buf.length); 253 | 254 | return (/(LOGIN|login) /.test(str)); 255 | }; 256 | 257 | var mail_request_content = function (buf) { 258 | // from pcap.js TCP_tracker.prototype.detect_http_request 259 | var str = buf.toString('utf8', 0, buf.length); 260 | var isAscii = true; 261 | for (var i=0, len=str.length; i 127) { 263 | isAscii=false; 264 | break; 265 | } 266 | } 267 | if (isAscii) 268 | return str; 269 | return null; 270 | // var content = ""; 271 | // match = str.match(/(GET|POST)\s+[^\s\r\n]+/i) 272 | // match ? content+=match[0].substring(4,HTTP_LENGTH_MAX+4) : null; 273 | // return (/^(OPTIONS|GET|HEAD|POST|PUT|DELETE|TRACE|CONNECT|COPY|LOCK|MKCOL|MOVE|PROPFIND|PROPPATCH|UNLOCK) [^\s\r\n]+ HTTP\/\d\.\d\r\n/.test(str)); 274 | // return content; 275 | }; 276 | 277 | // var request_parser = new HTTPParser(HTTPParser.REQUEST), 278 | 279 | 280 | 281 | console.log("\nNetwork interfaces (*=chosen):"); 282 | pcap.findalldevs().forEach(function (dev) { 283 | if (pcap_session.device_name === dev.name) { 284 | process.stdout.write("* "); 285 | } 286 | process.stdout.write(dev.name + " "); 287 | if (dev.addresses.length > 0) { 288 | dev.addresses.forEach(function (address) { 289 | process.stdout.write(address.addr + "/" + address.netmask); 290 | }); 291 | process.stdout.write("\n"); 292 | } else { 293 | process.stdout.write("no address\n"); 294 | } 295 | }); 296 | 297 | 298 | 299 | // Routinely check for dropped packets 300 | setInterval(function () { 301 | var stats = pcap_session.stats(); 302 | if (stats.ps_drop > 0) { 303 | console.log("\n\nPCAP dropped packets: " + util.inspect(stats)); 304 | } 305 | }, 5000); 306 | 307 | 308 | 309 | 310 | var is_local_ip = function (ip) { 311 | // 172.19 check is improper quick check that works anyway 312 | if (ip.substring(0,3) === '10.' || ip.substring(0,8) === '192.168.' || ip.substring(0,7) === '172.19.') 313 | return true; 314 | return false; 315 | }; 316 | var is_broadcast_ip = function (ip) { 317 | // stupid way 318 | if (ip.substr(-3) == '255') 319 | return true; 320 | return false; 321 | }; 322 | 323 | 324 | /* 325 | 326 | Parse packet 327 | aka, tha meat 328 | 329 | */ 330 | 331 | 332 | 333 | var parse_packet = function(packet, callback) { 334 | 335 | 336 | // if not an internet IP packet than skip 337 | 338 | // pcap@<=1.2.0 339 | // if (!packet.link || !packet.link.shost || !packet.link.ip || !packet.link.ip.saddr) 340 | // pcap@2.0.1 341 | if (!packet.payload || !packet.payload.payload || !packet.payload.payload.saddr || !packet.payload.payload.payload) 342 | // ethernet ether ip ether ip addr 343 | return null 344 | 345 | var dat = {}; // what we send to the client 346 | 347 | 348 | 349 | // MAC ADDRESS DEVICE MANUFACTURER RESOLUTION 350 | var soui = packet.payload.shost.toString().substring(0,8); 351 | dat.sdevice = cache.oui.ptr(soui); 352 | var doui = packet.payload.dhost.toString().substring(0,8); 353 | dat.ddevice = cache.oui.ptr(doui); 354 | if (dat.sdevice) dat.sdevice = dat.sdevice.split(' ')[0] // cleanup 355 | if (dat.ddevice) dat.ddevice = dat.ddevice.split(' ')[0] 356 | VERBOSE_DEBUG && console.log('dat',dat) 357 | VERBOSE_DEBUG && console.log('shost',packet.payload.shost.toString()) 358 | VERBOSE_DEBUG && console.log('dhost',packet.payload.dhost.toString()) 359 | 360 | // IP's 361 | dat.sip = packet.payload.payload.saddr.toString(); 362 | dat.siplocal = is_local_ip(dat.sip); 363 | dat.dip = packet.payload.payload.daddr.toString(); 364 | dat.diplocal = is_local_ip(dat.dip); 365 | // used for cache key: 366 | var iplocal; 367 | if (dat.siplocal && dat.sip !== gatewayip) 368 | iplocal = dat.sip; 369 | else 370 | iplocal = dat.dip; 371 | dat.gatewayip = gatewayip; 372 | 373 | // DNS CACHE REVERSE RESOLUTION 374 | dat.sname = cache.dns.ptr(dat.sip).replace(LOCAL_DOMAIN,'') //replace the shows domain for now 375 | dat.dname = cache.dns.ptr(dat.dip).replace(LOCAL_DOMAIN,'') 376 | // cleanup 377 | if (dat.sname.match(/^\d+\.\d+\.\d+\.\d+$/)) dat.sname = null; 378 | else if (dat.sname.substr(-10) === '.1e100.net') dat.sname = 'google.com'; // deal with google 379 | else 380 | dat.sname = dat.sname.split('.').slice(-3).join('.'); //oo.aa.domain.com into aa.domain.com) 381 | 382 | if (dat.dname.match(/^\d+\.\d+\.\d+\.\d+$/)) dat.dname = null; 383 | else if (dat.dname.substr(-10) === '.1e100.net') dat.dname = 'google.com'; 384 | else 385 | dat.dname = dat.dname.split('.').slice(-3).join('.'); 386 | 387 | // MDNS 388 | if (dat.siplocal) dat.smdnsname = cache.mdns.ptr(dat.sip) 389 | else if (dat.diplocal) dat.dmdnsname = cache.mdns.ptr(dat.dip) 390 | // cleanup 391 | if (dat.smdnsname && dat.siplocal) dat.smdnsname = dat.smdnsname.replace('.local.',''); //replace the shows domain for now 392 | else if (dat.dmdnsname && dat.diplocal) dat.dmdnsname = dat.dmdnsname.replace('.local.',''); 393 | 394 | 395 | 396 | // GEOIP 397 | dat.sgeo = cache.geo.ptr(dat.sip); 398 | dat.dgeo = cache.geo.ptr(dat.dip); 399 | if (dat.sgeo.code == '--') dat.sgeo = null; //cleanup 400 | if (dat.dgeo.code == '--') dat.dgeo = null; 401 | 402 | 403 | // 404 | // Application layer 405 | // 406 | dat.app = {} 407 | dat.app.type = null 408 | 409 | // use DNS queries to populate reverse IP cache 410 | // debugger; 411 | if (packet.payload.payload.payload.decoderName === 'udp' && (packet.payload.payload.payload.sport === 53 || packet.payload.payload.payload.dport === 53)) { 412 | // register this port being matched 413 | // actually the new_port cache is not used yet 414 | // but could be used in the future to change 415 | // print logic based on app parsing vs new 416 | // port/servics access 417 | cache.new_port.ptr(iplocal, 'dns'); 418 | 419 | // console.log('udp 53. iplocal:',iplocal); 420 | 421 | var dns = new DNS().decode(packet.payload.payload.payload.data, 0, packet.payload.payload.payload.data.length); 422 | if (dns.answer.rrs.length > 0) { 423 | for (var i=0; i < dns.answer.rrs.length; i++) { 424 | if (dns.answer.rrs[i].rdata && dns.answer.rrs[i].rdata.addr && dns.answer.rrs[i].name) { 425 | // register this application was parsed 426 | var new_data = cache.new_data.ptr(iplocal, 'dns'); 427 | 428 | // populate dns cache with the response 429 | cache.dns.insert(dns.answer.rrs[i].rdata.addr.join('.'), dns.answer.rrs[i].name); 430 | 431 | // prepare data to be sent to client 432 | if (!DNS_ONLY_FIRST || new_data) { 433 | dat.app.type = 'dns response'; 434 | dat.app.name = dns.answer.rrs[i].name.split('.').slice(-3).join('.'); //only last 3 octets of a domain 435 | dat.app.ip = dns.answer.rrs[i].rdata.addr.join('.'); 436 | } 437 | } 438 | } 439 | } 440 | else if (dns.question.rrs.length > 0) { 441 | for (var i=0; i < dns.question.rrs.length; i++) { 442 | if (dns.question.rrs[i].type && dns.question.rrs[i].type === 1/*'A'*/ && dns.question.rrs[i].name) { 443 | var new_data = cache.new_data.ptr(iplocal, 'dns'); 444 | 445 | if (!DNS_ONLY_FIRST || new_data) { 446 | dat.app.type = 'dns request'; 447 | dat.app.name = dns.question.rrs[i].name.split('.').slice(-3).join('.'); 448 | } 449 | } 450 | } 451 | } 452 | } 453 | 454 | // HTTP 455 | // only checking dport to reduce amount of packets 456 | else if (packet.payload.payload.payload.decoderName === 'tcp' && packet.payload.payload.payload.dport === 80) {// || packet.payload.payload.payload.sport === 80)) { 457 | cache.new_port.ptr(iplocal, 'http'); 458 | 459 | var tcp = packet.payload.payload.payload 460 | 461 | if (tcp.data) { 462 | if (detect_http_request(tcp.data)){ 463 | var url = http_request_content(tcp.data); 464 | 465 | if (url) { 466 | var new_data = cache.new_data.ptr(iplocal, 'http'); 467 | if (!HTTP_ONLY_FIRST || new_data) { 468 | // means we do not care if it is a the first http url 469 | dat.app.type = 'http url'; 470 | dat.app.url = url; 471 | } 472 | } 473 | 474 | if (VERBOSE_DEBUG) 475 | console.log("HTTP DATA:\n"+tcp.data.toString('utf8', 0, tcp.dataLength)); 476 | } 477 | } 478 | } 479 | 480 | // HTTPS 481 | // only checking dport to reduce amount of packets 482 | else if (packet.payload.payload.payload.decoderName === 'tcp' && packet.payload.payload.payload.dport === 443) {// || packet.payload.payload.payload.sport === 443)) { 483 | cache.new_port.ptr(iplocal, 'https'); 484 | var new_data = cache.new_data.ptr(iplocal, 'https'); 485 | 486 | // we only ever show first HTTPS 487 | if (new_data) { 488 | dat.app.type = 'https'; 489 | } 490 | } 491 | 492 | // MAIL 493 | // only checking dport to reduce amount of packets 494 | else if (packet.payload.payload.payload.decoderName === 'tcp' && (packet.payload.payload.payload.dport === 143 || packet.payload.payload.payload.dport === 110)) {// || packet.payload.payload.payload.sport === 443)) { 495 | cache.new_port.ptr(iplocal, 'mail'); 496 | 497 | var tcp = packet.payload.payload.payload 498 | 499 | if (tcp.data_bytes) { 500 | if (!MAIL_ONLY_LOGIN || detect_mail_login_request(tcp.data)) { 501 | var data = mail_request_content(tcp.data); 502 | if (data) { 503 | // for now showing all plaintext. otherwise we would wathc to check new_data first 504 | cache.new_data.ptr(iplocal, 'mail'); 505 | dat.app.type = 'mail'; 506 | dat.app.data = data; 507 | 508 | if (VERBOSE_DEBUG) 509 | console.log("MAIL DATA: "+data); 510 | } 511 | } 512 | } 513 | } 514 | 515 | // MAILS 516 | else if (packet.payload.payload.payload.decoderName === 'tcp' && (packet.payload.payload.payload.dport === 993 || packet.payload.payload.payload.dport === 995)) {// || packet.payload.payload.payload.sport === 443)) { 517 | cache.new_port.ptr(iplocal, 'mails'); 518 | var new_data = cache.new_data.ptr(iplocal, 'mails'); 519 | // only show first mails 520 | if (new_data) { 521 | dat.app.type = 'mails'; 522 | } 523 | } 524 | 525 | // BROADCAST PACKET 526 | else if (is_broadcast_ip(dat.sip) || is_broadcast_ip(dat.dip)) { // || packet.link.ip.tcp.sport === 443)) { 527 | cache.new_port.ptr(iplocal, 'broadcast'); 528 | var new_data = cache.new_data.ptr(iplocal, 'broadcast'); 529 | 530 | if (!BROADCAST_ONLY_FIRST) 531 | dat.app.type = 'broadcast'; 532 | else if (BROADCAST_ONLY_FIRST && new_data) 533 | dat.app.type = 'broadcast'; 534 | } 535 | 536 | 537 | 538 | else if (SHOW_OTHER_TYPE_DATA && 539 | (packet.payload.payload.payload.decoderName === 'tcp' || 540 | packet.payload.payload.payload.decoderName === 'udp') 541 | ) { 542 | // ignore the other types. we could instead add this check for sport on each of the checks above but that may result in records for both going in and response data. So instead just check we dont include them here 543 | 544 | if ([53,80,443,110,143,993,995].indexOf(packet.payload.payload.payload.dport) == -1 && 545 | [53,80,443,110,143,993,995].indexOf(packet.payload.payload.payload.sport) == -1) { 546 | dat.app.type = 'other '+packet.payload.payload.payload.decoderName+' '+packet.payload.payload.payload.dport+'>'+packet.payload.payload.payload.sport 547 | } 548 | // if (MAKE_STATE_CHANGE_ON_HIDDEN_OTHER) 549 | // cache.new_data.ptr(dat.siplocal ? dat.sip : dat.dip, 000); 550 | 551 | // if (SHOW_ANY_TCP_UDP) 552 | // dat.app.type = packet.link.ip.tcp ? 'tcp' : 'udp'; 553 | 554 | // if (packet.link.ip.tcp) 555 | // proto = packet.link.ip.tcp; 556 | // else if (packet.link.ip.udp) 557 | // proto = packet.link.ip.udp 558 | // ret += '-- port '; 559 | // if (!dat.diplocal) 560 | // ret += proto.dport; 561 | // else 562 | // ret += proto.sport; 563 | 564 | } 565 | 566 | // Only return if application layer parsed 567 | if (dat.app.type != null) 568 | callback(dat); 569 | 570 | // or return all packets with dat defined (such as tcp/udp port parsing commented out above) 571 | // callback(dat); 572 | 573 | }; 574 | 575 | if (ENTROPY_ENABLED) { 576 | var entropy = (function () { 577 | var cache_buf = new Buffer(ENTROPY_BUFFER_LEN) 578 | cache_buf.type = ref.types.char 579 | var offset = 0; 580 | var current_run = 0 581 | var scan = function(callback) { 582 | current_run+=1; 583 | var entropy = libdisorder.shannon_H(cache_buf, ENTROPY_BUFFER_LEN); 584 | var maxent = libdisorder.get_max_entropy(); 585 | var ratio = libdisorder.get_entropy_ratio(); 586 | offset = 0; 587 | data = { 588 | entropy: entropy, 589 | maxent: maxent, 590 | ratio: ratio, 591 | count: current_run 592 | } 593 | callback(data); 594 | if (ENTROPY_LOG) 595 | console.log('<'+(" "+current_run).slice(-8)+'> entropy: '+entropy.toFixed(6)+' maxent: '+maxent.toFixed(6)+' ratio: '+ratio.toFixed(6)+' offset: '+offset); 596 | } 597 | 598 | function scan_ptr(buf, callback) { 599 | var buf_len = buf.length; 600 | 601 | while (buf_len > 0) { 602 | if (offset == ENTROPY_BUFFER_LEN) 603 | continue; // wait until scan has finished to continue reading rest of buffer 604 | 605 | // Buffer appears to handle over shots without loosing data (len_written reflects what was actually written) 606 | var len_written = buf.copy(cache_buf, offset, 0, buf_len <= (ENTROPY_BUFFER_LEN-offset) ? buf_len : (ENTROPY_BUFFER_LEN-offset)); 607 | offset += len_written; 608 | buf_len -= len_written; 609 | if (ENTROPY_BUFFER_DEBUG) 610 | console.log('entropy_buf wrote: '+len_written+ ' offset: '+offset+' buf_left: '+buf_len+' cache_free: '+(ENTROPY_BUFFER_LEN-offset)); 611 | 612 | if (offset >= ENTROPY_BUFFER_LEN) 613 | scan(callback); 614 | 615 | } 616 | } 617 | return { 618 | ptr: function (buf, callback) { 619 | return scan_ptr(buf, callback); 620 | } 621 | }; 622 | }()); 623 | } 624 | 625 | // using this for debug on console 626 | var print_packet = function(dat) { 627 | console.log(dat.count+': '+dat.sip+' > '+dat.dip+' '+dat.app.type); 628 | } 629 | 630 | 631 | var packet_count = 0; 632 | 633 | 634 | io.sockets.on('connection', function (socket) { 635 | console.log('connected'); 636 | socket.join('sniffer'); 637 | packet_count = 0; 638 | // socket = sock; 639 | }); 640 | 641 | /* If issues of reconnection persist perhaps switch back to single user mode 642 | and change "room" use to normal emits with a global socket */ 643 | pcap_session.on('packet', function (raw_packet) { 644 | // if (!io.socket) 645 | // return; 646 | 647 | // send a vanilla packet summary to the client 648 | //socket.emit('packet', { data: pcap.print.packet(packet) }); 649 | // send the full packet object (for debugging) 650 | //socket.emit('packet_obj', { data: packet }); 651 | // send parsed packet: 652 | 653 | try { 654 | var packet = pcap.decode.packet(raw_packet); 655 | } catch(err) { 656 | dumpError(err); 657 | return null; 658 | } 659 | 660 | parse_packet(packet, function(packet){ 661 | packet_count += 1; 662 | packet.count = packet_count; 663 | 664 | // try/catch statement to not crash on bugs such as dns bug described at EOF 665 | try { 666 | print_packet(packet); 667 | } 668 | catch(err) { 669 | dumpError(err); 670 | return; 671 | } 672 | io.to('sniffer').emit('packet', { data: packet }); 673 | }); 674 | 675 | // entropy 676 | if (ENTROPY_ENABLED && packet.link && packet.link.ip) { // || packet.link.ip.tcp.sport === 443)) { 677 | if (packet.link.ip.tcp && packet.link.ip.tcp.data_bytes) { 678 | entropy.ptr(packet.link.ip.tcp.data, function(entropy) { 679 | io.to('sniffer').emit('entropy', entropy); 680 | }); 681 | } 682 | else if (packet.link.ip.udp && packet.link.ip.udp.data_bytes) { 683 | entropy.ptr(packet.link.ip.udp.data, function(entropy) { 684 | io.to('sniffer').emit('entropy', entropy); 685 | }); 686 | } 687 | } 688 | }); 689 | 690 | 691 | 692 | /* 693 | tests 694 | 695 | // inspect packets in repl 696 | var util = require('util'); 697 | var pcap = require("pcap"), pcap_session; 698 | pcap_session = pcap.createSession('en1', 'ip and port 53'); 699 | global.ret = []; 700 | pcap_session.on('packet', function (raw_packet) { 701 | var packet = pcap.decode.packet(raw_packet); 702 | global.ret.push(packet.link.ip.udp); 703 | }); 704 | */ 705 | -------------------------------------------------------------------------------- /client/js/jquery-1.11.1.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery v1.11.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ 2 | !function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.1",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b=a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+-new Date,v=a.document,w=0,x=0,y=gb(),z=gb(),A=gb(),B=function(a,b){return a===b&&(l=!0),0},C="undefined",D=1<<31,E={}.hasOwnProperty,F=[],G=F.pop,H=F.push,I=F.push,J=F.slice,K=F.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},L="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",N="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=N.replace("w","w#"),P="\\["+M+"*("+N+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+O+"))|)"+M+"*\\]",Q=":("+N+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+P+")*)|.*)\\)|)",R=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),S=new RegExp("^"+M+"*,"+M+"*"),T=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),V=new RegExp(Q),W=new RegExp("^"+O+"$"),X={ID:new RegExp("^#("+N+")"),CLASS:new RegExp("^\\.("+N+")"),TAG:new RegExp("^("+N.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+Q),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("^(?:"+L+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{I.apply(F=J.call(v.childNodes),v.childNodes),F[v.childNodes.length].nodeType}catch(eb){I={apply:F.length?function(a,b){H.apply(a,J.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],!a||"string"!=typeof a)return d;if(1!==(k=b.nodeType)&&9!==k)return[];if(p&&!e){if(f=_.exec(a))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return I.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return I.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=9===k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+qb(o[l]);w=ab.test(a)&&ob(b.parentNode)||b,x=o.join(",")}if(x)try{return I.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function gb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function hb(a){return a[u]=!0,a}function ib(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function jb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function kb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||D)-(~a.sourceIndex||D);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function lb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function nb(a){return hb(function(b){return b=+b,hb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function ob(a){return a&&typeof a.getElementsByTagName!==C&&a}c=fb.support={},f=fb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fb.setDocument=function(a){var b,e=a?a.ownerDocument||a:v,g=e.defaultView;return e!==n&&9===e.nodeType&&e.documentElement?(n=e,o=e.documentElement,p=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){m()},!1):g.attachEvent&&g.attachEvent("onunload",function(){m()})),c.attributes=ib(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ib(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(e.getElementsByClassName)&&ib(function(a){return a.innerHTML="
",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=ib(function(a){return o.appendChild(a).id=u,!e.getElementsByName||!e.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==C&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c=typeof a.getAttributeNode!==C&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==C?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==C&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(e.querySelectorAll))&&(ib(function(a){a.innerHTML="",a.querySelectorAll("[msallowclip^='']").length&&q.push("[*^$]="+M+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+M+"*(?:value|"+L+")"),a.querySelectorAll(":checked").length||q.push(":checked")}),ib(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+M+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ib(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",Q)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===v&&t(v,a)?-1:b===e||b.ownerDocument===v&&t(v,b)?1:k?K.call(k,a)-K.call(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],i=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:k?K.call(k,a)-K.call(k,b):0;if(f===g)return kb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?kb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},e):n},fb.matches=function(a,b){return fb(a,null,null,b)},fb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fb(b,n,null,[a]).length>0},fb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&E.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fb.selectors={cacheLength:50,createPseudo:hb,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+M+")"+a+"("+M+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==C&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?hb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=K.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:hb(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?hb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:hb(function(a){return function(b){return fb(a,b).length>0}}),contains:hb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:hb(function(a){return W.test(a||"")||fb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:nb(function(){return[0]}),last:nb(function(a,b){return[b-1]}),eq:nb(function(a,b,c){return[0>c?c+b:c]}),even:nb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:nb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:nb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:nb(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function rb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function sb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function tb(a,b,c){for(var d=0,e=b.length;e>d;d++)fb(a,b[d],c);return c}function ub(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function vb(a,b,c,d,e,f){return d&&!d[u]&&(d=vb(d)),e&&!e[u]&&(e=vb(e,f)),hb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||tb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ub(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ub(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?K.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ub(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):I.apply(g,r)})}function wb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=rb(function(a){return a===b},h,!0),l=rb(function(a){return K.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>i;i++)if(c=d.relative[a[i].type])m=[rb(sb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return vb(i>1&&sb(m),i>1&&qb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&wb(a.slice(i,e)),f>e&&wb(a=a.slice(e)),f>e&&qb(a))}m.push(c)}return sb(m)}function xb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=G.call(i));s=ub(s)}I.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&fb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?hb(f):f}return h=fb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xb(e,d)),f.selector=a}return f},i=fb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&ob(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qb(j),!a)return I.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&ob(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ib(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ib(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||jb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ib(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||jb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ib(function(a){return null==a.getAttribute("disabled")})||jb(L,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fb}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h; 3 | if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML="
a",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function ab(){return!0}function bb(){return!1}function cb(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h]","i"),hb=/^\s+/,ib=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,jb=/<([\w:]+)/,kb=/\s*$/g,rb={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:k.htmlSerialize?[0,"",""]:[1,"X
","
"]},sb=db(y),tb=sb.appendChild(y.createElement("div"));rb.optgroup=rb.option,rb.tbody=rb.tfoot=rb.colgroup=rb.caption=rb.thead,rb.th=rb.td;function ub(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ub(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function vb(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wb(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xb(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function yb(a){var b=pb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function zb(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Ab(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Bb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xb(b).text=a.text,yb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!gb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(tb.innerHTML=a.outerHTML,tb.removeChild(f=tb.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ub(f),h=ub(a),g=0;null!=(e=h[g]);++g)d[g]&&Bb(e,d[g]);if(b)if(c)for(h=h||ub(a),d=d||ub(f),g=0;null!=(e=h[g]);g++)Ab(e,d[g]);else Ab(a,f);return d=ub(f,"script"),d.length>0&&zb(d,!i&&ub(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=db(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(lb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(jb.exec(f)||["",""])[1].toLowerCase(),l=rb[i]||rb._default,h.innerHTML=l[1]+f.replace(ib,"<$1>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&hb.test(f)&&p.push(b.createTextNode(hb.exec(f)[0])),!k.tbody){f="table"!==i||kb.test(f)?""!==l[1]||kb.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ub(p,"input"),vb),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ub(o.appendChild(f),"script"),g&&zb(h),c)){e=0;while(f=h[e++])ob.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ub(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&zb(ub(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ub(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fb,""):void 0;if(!("string"!=typeof a||mb.test(a)||!k.htmlSerialize&&gb.test(a)||!k.leadingWhitespace&&hb.test(a)||rb[(jb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ib,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ub(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ub(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&nb.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ub(i,"script"),xb),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ub(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,yb),j=0;f>j;j++)d=g[j],ob.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qb,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Cb,Db={};function Eb(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fb(a){var b=y,c=Db[a];return c||(c=Eb(a,b),"none"!==c&&c||(Cb=(Cb||m("