Version Description
This version adds support for the latest version of WordPress. Introduces new features and fixes some bugs reported by the WordPress community as well as bugs found by our automated testing system.
=
Download this release
Release Info
Developer | yorman |
Plugin | Sucuri Security – Auditing, Malware Scanner and Security Hardening |
Version | 1.8.8 |
Comparing to | |
See all releases |
Code changes from version 1.8.7 to 1.8.8
- inc/css/c3.min.css +0 -1
- inc/css/styles.css +22 -4
- inc/js/c3.min.js +0 -6
- inc/js/d3.min.js +0 -5
- inc/js/scripts.js +18 -1
- inc/tpl/auditlogs-report.html.tpl +0 -103
- inc/tpl/auditlogs.html.tpl +31 -13
- inc/tpl/dashboard.html.tpl +23 -8
- inc/tpl/firewall-auditlogs.snippet.tpl +42 -38
- inc/tpl/firewall-clearcache.html.tpl +50 -5
- inc/tpl/firewall-ipaccess.html.tpl +118 -0
- inc/tpl/firewall-settings.html.tpl +34 -2
- inc/tpl/firewall-settings.snippet.tpl +0 -5
- inc/tpl/firewall.html.tpl +5 -0
- inc/tpl/integrity-diff-utility.html.tpl +3 -10
- inc/tpl/integrity-incorrect.html.tpl +73 -5
- inc/tpl/settings-alerts-events.html.tpl +4 -0
- inc/tpl/settings-alerts-ignore-posts.html.tpl +3 -3
- inc/tpl/settings-apiservice-checksums.html.tpl +23 -0
- inc/tpl/{settings-general-auditlogstats.html.tpl → settings-general-timezone.html.tpl} +7 -4
- inc/tpl/settings-webinfo-wpconfig.html.tpl +0 -19
- inc/tpl/settings-webinfo-wpconfig.snippet.tpl +0 -6
- inc/tpl/settings.html.tpl +5 -3
- inc/tpl/sitecheck-links.html.tpl +0 -6
- inc/tpl/sitecheck-links.snippet.tpl +0 -7
- inc/tpl/sitecheck-target.html.tpl +24 -0
- languages/sucuri-scanner-en_US.mo +0 -0
- languages/sucuri-scanner-en_US.po +55 -16
- languages/sucuri-scanner-es_ES.mo +0 -0
- languages/sucuri-scanner-es_ES.po +162 -122
- readme.txt +100 -113
- src/api.lib.php +206 -85
- src/auditlogs.lib.php +43 -103
- src/cache.lib.php +4 -2
- src/command.lib.php +14 -20
- src/event.lib.php +77 -65
- src/fileinfo.lib.php +32 -17
- src/firewall.lib.php +282 -110
- src/fsscanner.lib.php +1 -1
- src/globals.php +29 -32
- src/hook.lib.php +40 -9
- src/integrity.lib.php +205 -217
- src/interface.lib.php +30 -40
- src/lastlogins-failed.php +2 -1
- src/lastlogins.php +2 -2
- src/mail.lib.php +1 -1
- src/option.lib.php +61 -6
- src/pagehandler.php +16 -15
- src/settings-alerts.php +119 -89
- src/settings-apiservice.php +37 -0
- src/settings-general.php +58 -45
- src/settings-hardening.php +15 -3
- src/settings-integrity.php +1 -1
- src/settings-scanner.php +4 -11
- src/settings-webinfo.php +22 -105
- src/sitecheck.lib.php +58 -88
- src/sucuriscan.lib.php +48 -81
- src/template.lib.php +9 -8
- sucuri.php +3 -13
inc/css/c3.min.css
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
.c3 svg{font:10px sans-serif;-webkit-tap-highlight-color:transparent}.c3 line,.c3 path{fill:none;stroke:#000}.c3 text{-webkit-user-select:none;-moz-user-select:none;user-select:none}.c3-bars path,.c3-event-rect,.c3-legend-item-tile,.c3-xgrid-focus,.c3-ygrid{shape-rendering:crispEdges}.c3-chart-arc path{stroke:#fff}.c3-chart-arc text{fill:#fff;font-size:13px}.c3-grid line{stroke:#aaa}.c3-grid text{fill:#aaa}.c3-xgrid,.c3-ygrid{stroke-dasharray:3 3}.c3-text.c3-empty{fill:gray;font-size:2em}.c3-line{stroke-width:1px}.c3-circle._expanded_{stroke-width:1px;stroke:#fff}.c3-selected-circle{fill:#fff;stroke-width:2px}.c3-bar{stroke-width:0}.c3-bar._expanded_{fill-opacity:.75}.c3-target.c3-focused{opacity:1}.c3-target.c3-focused path.c3-line,.c3-target.c3-focused path.c3-step{stroke-width:2px}.c3-target.c3-defocused{opacity:.3!important}.c3-region{fill:#4682b4;fill-opacity:.1}.c3-brush .extent{fill-opacity:.1}.c3-legend-item{font-size:12px}.c3-legend-item-hidden{opacity:.15}.c3-legend-background{opacity:.75;fill:#fff;stroke:#d3d3d3;stroke-width:1}.c3-title{font:14px sans-serif}.c3-tooltip-container{z-index:10}.c3-tooltip{border-collapse:collapse;border-spacing:0;background-color:#fff;empty-cells:show;-webkit-box-shadow:7px 7px 12px -9px #777;-moz-box-shadow:7px 7px 12px -9px #777;box-shadow:7px 7px 12px -9px #777;opacity:.9}.c3-tooltip tr{border:1px solid #CCC}.c3-tooltip th{background-color:#aaa;font-size:14px;padding:2px 5px;text-align:left;color:#FFF}.c3-tooltip td{font-size:13px;padding:3px 6px;background-color:#fff;border-left:1px dotted #999}.c3-tooltip td>span{display:inline-block;width:10px;height:10px;margin-right:6px}.c3-tooltip td.value{text-align:right}.c3-area{stroke-width:0;opacity:.2}.c3-chart-arcs-title{dominant-baseline:middle;font-size:1.3em}.c3-chart-arcs .c3-chart-arcs-background{fill:#e0e0e0;stroke:none}.c3-chart-arcs .c3-chart-arcs-gauge-unit{fill:#000;font-size:16px}.c3-chart-arcs .c3-chart-arcs-gauge-max,.c3-chart-arcs .c3-chart-arcs-gauge-min{fill:#777}.c3-chart-arc .c3-gauge-value{fill:#000}
|
|
inc/css/styles.css
CHANGED
@@ -224,6 +224,7 @@ body.sucuri-security_page_sucuriscan_hardening {
|
|
224 |
padding: 20px;
|
225 |
font-size: 12px;
|
226 |
color: #fff;
|
|
|
227 |
}
|
228 |
.sucuriscan-tooltip-object::before {
|
229 |
left: 50%;
|
@@ -775,13 +776,11 @@ body.sucuri-security_page_sucuriscan_hardening {
|
|
775 |
text-overflow: ellipsis;
|
776 |
}
|
777 |
.sucuriscan-auditlog-entry-time {
|
778 |
-
width:
|
779 |
color: #808080;
|
780 |
-
margin-right: 20px;
|
781 |
}
|
782 |
.sucuriscan-auditlog-entry-event {
|
783 |
-
width:
|
784 |
-
margin-right: 20px;
|
785 |
}
|
786 |
.sucuriscan-auditlog-entry-message {
|
787 |
width: 64.3111%;
|
@@ -845,3 +844,22 @@ body.sucuri-security_page_sucuriscan_hardening {
|
|
845 |
.sucuriscan-accesslog-label {
|
846 |
font-weight: 700;
|
847 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
224 |
padding: 20px;
|
225 |
font-size: 12px;
|
226 |
color: #fff;
|
227 |
+
z-index: 10;
|
228 |
}
|
229 |
.sucuriscan-tooltip-object::before {
|
230 |
left: 50%;
|
776 |
text-overflow: ellipsis;
|
777 |
}
|
778 |
.sucuriscan-auditlog-entry-time {
|
779 |
+
width: 45px;
|
780 |
color: #808080;
|
|
|
781 |
}
|
782 |
.sucuriscan-auditlog-entry-event {
|
783 |
+
width: 28px;
|
|
|
784 |
}
|
785 |
.sucuriscan-auditlog-entry-message {
|
786 |
width: 64.3111%;
|
844 |
.sucuriscan-accesslog-label {
|
845 |
font-weight: 700;
|
846 |
}
|
847 |
+
.sucuriscan-ipaccess-form,
|
848 |
+
.sucuriscan-ipaccess-table {
|
849 |
+
margin-top: 20px;
|
850 |
+
}
|
851 |
+
.sucuriscan-ipaccess-table tbody td + td {
|
852 |
+
text-align: right;
|
853 |
+
}
|
854 |
+
.sucuriscan-ipaccess-table .sucuriscan-monospace {
|
855 |
+
line-height: 30px;
|
856 |
+
}
|
857 |
+
.sucuriscan-settings-alerts .dashicons-before::before {
|
858 |
+
padding-right: 10px;
|
859 |
+
}
|
860 |
+
#firewall-clear-cache-auto {
|
861 |
+
margin-bottom: 15px;
|
862 |
+
}
|
863 |
+
.sucuriscan-firewall-accesslog {
|
864 |
+
word-break: break-all;
|
865 |
+
}
|
inc/js/c3.min.js
DELETED
@@ -1,6 +0,0 @@
|
|
1 |
-
!function(a){"use strict";function b(a){this.owner=a}function c(a,b){if(Object.create)b.prototype=Object.create(a.prototype);else{var c=function(){};c.prototype=a.prototype,b.prototype=new c}return b.prototype.constructor=b,b}function d(a){var b=this.internal=new e(this);b.loadConfig(a),b.beforeInit(a),b.init(),b.afterInit(a),function c(a,b,d){Object.keys(a).forEach(function(e){b[e]=a[e].bind(d),Object.keys(a[e]).length>0&&c(a[e],b[e],d)})}(h,this,this)}function e(b){var c=this;c.d3=a.d3?a.d3:"undefined"!=typeof require?require("d3"):void 0,c.api=b,c.config=c.getDefaultConfig(),c.data={},c.cache={},c.axes={}}function f(a){b.call(this,a)}function g(a,b){function c(a,b){a.attr("transform",function(a){return"translate("+Math.ceil(b(a)+u)+", 0)"})}function d(a,b){a.attr("transform",function(a){return"translate(0,"+Math.ceil(b(a))+")"})}function e(a){var b=a[0],c=a[a.length-1];return c>b?[b,c]:[c,b]}function f(a){var b,c,d=[];if(a.ticks)return a.ticks.apply(a,n);for(c=a.domain(),b=Math.ceil(c[0]);b<c[1];b++)d.push(b);return d.length>0&&d[0]>0&&d.unshift(d[0]-(d[1]-d[0])),d}function g(){var a,c=p.copy();return b.isCategory&&(a=p.domain(),c.domain([a[0],a[1]-1])),c}function h(a){var b=m?m(a):a;return"undefined"!=typeof b?b:""}function i(a){if(A)return A;var b={h:11.5,w:5.5};return a.select("text").text(h).each(function(a){var c=this.getBoundingClientRect(),d=h(a),e=c.height,f=d?c.width/d.length:void 0;e&&f&&(b.h=e,b.w=f)}).text(""),A=b,b}function j(c){return b.withoutTransition?c:a.transition(c)}function k(m){m.each(function(){function m(a,c){function d(a,b){f=void 0;for(var h=1;h<b.length;h++)if(" "===b.charAt(h)&&(f=h),e=b.substr(0,h+1),g=U.w*e.length,g>c)return d(a.concat(b.substr(0,f?f:h)),b.slice(f?f+1:h));return a.concat(b)}var e,f,g,i=h(a),j=[];return"[object Array]"===Object.prototype.toString.call(i)?i:((!c||0>=c)&&(c=X?95:b.isCategory?Math.ceil(F(G[1])-F(G[0]))-12:110),d(j,i+""))}function n(a,b){var c=U.h;return 0===b&&(c="left"===q||"right"===q?-((V[a.index]-1)*(U.h/2)-3):".71em"),c}function v(a){var b=p(a)+(o?0:u);return L[0]<b&&b<L[1]?r:0}function w(a){return a?a>0?"start":"end":"middle"}function x(a){return a?"rotate("+a+")":""}function y(a){return a?8*Math.sin(Math.PI*(a/180)):0}function z(a){return a?11.5-2.5*(a/15)*(a>0?1:-1):W}var A,B,C,D=k.g=a.select(this),E=this.__chart__||p,F=this.__chart__=g(),G=t?t:f(F),H=D.selectAll(".tick").data(G,F),I=H.enter().insert("g",".domain").attr("class","tick").style("opacity",1e-6),J=H.exit().remove(),K=j(H).style("opacity",1),L=p.rangeExtent?p.rangeExtent():e(p.range()),M=D.selectAll(".domain").data([0]),N=(M.enter().append("path").attr("class","domain"),j(M));I.append("line"),I.append("text");var O=I.select("line"),P=K.select("line"),Q=I.select("text"),R=K.select("text");b.isCategory?(u=Math.ceil((F(1)-F(0))/2),B=o?0:u,C=o?u:0):u=B=0;var S,T,U=i(D.select(".tick")),V=[],W=Math.max(r,0)+s,X="left"===q||"right"===q;S=H.select("text"),T=S.selectAll("tspan").data(function(a,c){var d=b.tickMultiline?m(a,b.tickWidth):[].concat(h(a));return V[c]=d.length,d.map(function(a){return{index:c,splitted:a}})}),T.enter().append("tspan"),T.exit().remove(),T.text(function(a){return a.splitted});var Y=b.tickTextRotate;switch(q){case"bottom":A=c,O.attr("y2",r),Q.attr("y",W),P.attr("x1",B).attr("x2",B).attr("y2",v),R.attr("x",0).attr("y",z(Y)).style("text-anchor",w(Y)).attr("transform",x(Y)),T.attr("x",0).attr("dy",n).attr("dx",y(Y)),N.attr("d","M"+L[0]+","+l+"V0H"+L[1]+"V"+l);break;case"top":A=c,O.attr("y2",-r),Q.attr("y",-W),P.attr("x2",0).attr("y2",-r),R.attr("x",0).attr("y",-W),S.style("text-anchor","middle"),T.attr("x",0).attr("dy","0em"),N.attr("d","M"+L[0]+","+-l+"V0H"+L[1]+"V"+-l);break;case"left":A=d,O.attr("x2",-r),Q.attr("x",-W),P.attr("x2",-r).attr("y1",C).attr("y2",C),R.attr("x",-W).attr("y",u),S.style("text-anchor","end"),T.attr("x",-W).attr("dy",n),N.attr("d","M"+-l+","+L[0]+"H0V"+L[1]+"H"+-l);break;case"right":A=d,O.attr("x2",r),Q.attr("x",W),P.attr("x2",r).attr("y2",0),R.attr("x",W).attr("y",0),S.style("text-anchor","start"),T.attr("x",W).attr("dy",n),N.attr("d","M"+l+","+L[0]+"H0V"+L[1]+"H"+l)}if(F.rangeBand){var Z=F,$=Z.rangeBand()/2;E=F=function(a){return Z(a)+$}}else E.rangeBand?E=F:J.call(A,F);I.call(A,E),K.call(A,F)})}var l,m,n,o,p=a.scale.linear(),q="bottom",r=6,s=3,t=null,u=0,v=!0;return b=b||{},l=b.withOuterTick?6:0,k.scale=function(a){return arguments.length?(p=a,k):p},k.orient=function(a){return arguments.length?(q=a in{top:1,right:1,bottom:1,left:1}?a+"":"bottom",k):q},k.tickFormat=function(a){return arguments.length?(m=a,k):m},k.tickCentered=function(a){return arguments.length?(o=a,k):o},k.tickOffset=function(){return u},k.tickInterval=function(){var a,c;return b.isCategory?a=2*u:(c=k.g.select("path.domain").node().getTotalLength()-2*l,a=c/k.g.selectAll("line").size()),a===1/0?0:a},k.ticks=function(){return arguments.length?(n=arguments,k):n},k.tickCulling=function(a){return arguments.length?(v=a,k):v},k.tickValues=function(a){if("function"==typeof a)t=function(){return a(p.domain())};else{if(!arguments.length)return t;t=a}return k},k}var h,i,j,k={version:"0.4.11"};k.generate=function(a){return new d(a)},k.chart={fn:d.prototype,internal:{fn:e.prototype,axis:{fn:f.prototype}}},h=k.chart.fn,i=k.chart.internal.fn,j=k.chart.internal.axis.fn,i.beforeInit=function(){},i.afterInit=function(){},i.init=function(){var a=this,b=a.config;if(a.initParams(),b.data_url)a.convertUrlToData(b.data_url,b.data_mimeType,b.data_headers,b.data_keys,a.initWithData);else if(b.data_json)a.initWithData(a.convertJsonToData(b.data_json,b.data_keys));else if(b.data_rows)a.initWithData(a.convertRowsToData(b.data_rows));else{if(!b.data_columns)throw Error("url or json or rows or columns is required.");a.initWithData(a.convertColumnsToData(b.data_columns))}},i.initParams=function(){var a=this,b=a.d3,c=a.config;a.clipId="c3-"+ +new Date+"-clip",a.clipIdForXAxis=a.clipId+"-xaxis",a.clipIdForYAxis=a.clipId+"-yaxis",a.clipIdForGrid=a.clipId+"-grid",a.clipIdForSubchart=a.clipId+"-subchart",a.clipPath=a.getClipPath(a.clipId),a.clipPathForXAxis=a.getClipPath(a.clipIdForXAxis),a.clipPathForYAxis=a.getClipPath(a.clipIdForYAxis),a.clipPathForGrid=a.getClipPath(a.clipIdForGrid),a.clipPathForSubchart=a.getClipPath(a.clipIdForSubchart),a.dragStart=null,a.dragging=!1,a.flowing=!1,a.cancelClick=!1,a.mouseover=!1,a.transiting=!1,a.color=a.generateColor(),a.levelColor=a.generateLevelColor(),a.dataTimeFormat=c.data_xLocaltime?b.time.format:b.time.format.utc,a.axisTimeFormat=c.axis_x_localtime?b.time.format:b.time.format.utc,a.defaultAxisTimeFormat=a.axisTimeFormat.multi([[".%L",function(a){return a.getMilliseconds()}],[":%S",function(a){return a.getSeconds()}],["%I:%M",function(a){return a.getMinutes()}],["%I %p",function(a){return a.getHours()}],["%-m/%-d",function(a){return a.getDay()&&1!==a.getDate()}],["%-m/%-d",function(a){return 1!==a.getDate()}],["%-m/%-d",function(a){return a.getMonth()}],["%Y/%-m/%-d",function(){return!0}]]),a.hiddenTargetIds=[],a.hiddenLegendIds=[],a.focusedTargetIds=[],a.defocusedTargetIds=[],a.xOrient=c.axis_rotated?"left":"bottom",a.yOrient=c.axis_rotated?c.axis_y_inner?"top":"bottom":c.axis_y_inner?"right":"left",a.y2Orient=c.axis_rotated?c.axis_y2_inner?"bottom":"top":c.axis_y2_inner?"left":"right",a.subXOrient=c.axis_rotated?"left":"bottom",a.isLegendRight="right"===c.legend_position,a.isLegendInset="inset"===c.legend_position,a.isLegendTop="top-left"===c.legend_inset_anchor||"top-right"===c.legend_inset_anchor,a.isLegendLeft="top-left"===c.legend_inset_anchor||"bottom-left"===c.legend_inset_anchor,a.legendStep=0,a.legendItemWidth=0,a.legendItemHeight=0,a.currentMaxTickWidths={x:0,y:0,y2:0},a.rotated_padding_left=30,a.rotated_padding_right=c.axis_rotated&&!c.axis_x_show?0:30,a.rotated_padding_top=5,a.withoutFadeIn={},a.intervalForObserveInserted=void 0,a.axes.subx=b.selectAll([])},i.initChartElements=function(){this.initBar&&this.initBar(),this.initLine&&this.initLine(),this.initArc&&this.initArc(),this.initGauge&&this.initGauge(),this.initText&&this.initText()},i.initWithData=function(a){var b,c,d=this,e=d.d3,g=d.config,h=!0;d.axis=new f(d),d.initPie&&d.initPie(),d.initBrush&&d.initBrush(),d.initZoom&&d.initZoom(),g.bindto?"function"==typeof g.bindto.node?d.selectChart=g.bindto:d.selectChart=e.select(g.bindto):d.selectChart=e.selectAll([]),d.selectChart.empty()&&(d.selectChart=e.select(document.createElement("div")).style("opacity",0),d.observeInserted(d.selectChart),h=!1),d.selectChart.html("").classed("c3",!0),d.data.xs={},d.data.targets=d.convertDataToTargets(a),g.data_filter&&(d.data.targets=d.data.targets.filter(g.data_filter)),g.data_hide&&d.addHiddenTargetIds(g.data_hide===!0?d.mapToIds(d.data.targets):g.data_hide),g.legend_hide&&d.addHiddenLegendIds(g.legend_hide===!0?d.mapToIds(d.data.targets):g.legend_hide),d.hasType("gauge")&&(g.legend_show=!1),d.updateSizes(),d.updateScales(),d.x.domain(e.extent(d.getXDomain(d.data.targets))),d.y.domain(d.getYDomain(d.data.targets,"y")),d.y2.domain(d.getYDomain(d.data.targets,"y2")),d.subX.domain(d.x.domain()),d.subY.domain(d.y.domain()),d.subY2.domain(d.y2.domain()),d.orgXDomain=d.x.domain(),d.brush&&d.brush.scale(d.subX),g.zoom_enabled&&d.zoom.scale(d.x),d.svg=d.selectChart.append("svg").style("overflow","hidden").on("mouseenter",function(){return g.onmouseover.call(d)}).on("mouseleave",function(){return g.onmouseout.call(d)}),d.config.svg_classname&&d.svg.attr("class",d.config.svg_classname),b=d.svg.append("defs"),d.clipChart=d.appendClip(b,d.clipId),d.clipXAxis=d.appendClip(b,d.clipIdForXAxis),d.clipYAxis=d.appendClip(b,d.clipIdForYAxis),d.clipGrid=d.appendClip(b,d.clipIdForGrid),d.clipSubchart=d.appendClip(b,d.clipIdForSubchart),d.updateSvgSize(),c=d.main=d.svg.append("g").attr("transform",d.getTranslate("main")),d.initSubchart&&d.initSubchart(),d.initTooltip&&d.initTooltip(),d.initLegend&&d.initLegend(),d.initTitle&&d.initTitle(),c.append("text").attr("class",l.text+" "+l.empty).attr("text-anchor","middle").attr("dominant-baseline","middle"),d.initRegion(),d.initGrid(),c.append("g").attr("clip-path",d.clipPath).attr("class",l.chart),g.grid_lines_front&&d.initGridLines(),d.initEventRect(),d.initChartElements(),c.insert("rect",g.zoom_privileged?null:"g."+l.regions).attr("class",l.zoomRect).attr("width",d.width).attr("height",d.height).style("opacity",0).on("dblclick.zoom",null),g.axis_x_extent&&d.brush.extent(d.getDefaultExtent()),d.axis.init(),d.updateTargets(d.data.targets),h&&(d.updateDimension(),d.config.oninit.call(d),d.redraw({withTransition:!1,withTransform:!0,withUpdateXDomain:!0,withUpdateOrgXDomain:!0,withTransitionForAxis:!1})),d.bindResize(),d.api.element=d.selectChart.node()},i.smoothLines=function(a,b){var c=this;"grid"===b&&a.each(function(){var a=c.d3.select(this),b=a.attr("x1"),d=a.attr("x2"),e=a.attr("y1"),f=a.attr("y2");a.attr({x1:Math.ceil(b),x2:Math.ceil(d),y1:Math.ceil(e),y2:Math.ceil(f)})})},i.updateSizes=function(){var a=this,b=a.config,c=a.legend?a.getLegendHeight():0,d=a.legend?a.getLegendWidth():0,e=a.isLegendRight||a.isLegendInset?0:c,f=a.hasArcType(),g=b.axis_rotated||f?0:a.getHorizontalAxisHeight("x"),h=b.subchart_show&&!f?b.subchart_size_height+g:0;a.currentWidth=a.getCurrentWidth(),a.currentHeight=a.getCurrentHeight(),a.margin=b.axis_rotated?{top:a.getHorizontalAxisHeight("y2")+a.getCurrentPaddingTop(),right:f?0:a.getCurrentPaddingRight(),bottom:a.getHorizontalAxisHeight("y")+e+a.getCurrentPaddingBottom(),left:h+(f?0:a.getCurrentPaddingLeft())}:{top:4+a.getCurrentPaddingTop(),right:f?0:a.getCurrentPaddingRight(),bottom:g+h+e+a.getCurrentPaddingBottom(),left:f?0:a.getCurrentPaddingLeft()},a.margin2=b.axis_rotated?{top:a.margin.top,right:NaN,bottom:20+e,left:a.rotated_padding_left}:{top:a.currentHeight-h-e,right:NaN,bottom:g+e,left:a.margin.left},a.margin3={top:0,right:NaN,bottom:0,left:0},a.updateSizeForLegend&&a.updateSizeForLegend(c,d),a.width=a.currentWidth-a.margin.left-a.margin.right,a.height=a.currentHeight-a.margin.top-a.margin.bottom,a.width<0&&(a.width=0),a.height<0&&(a.height=0),a.width2=b.axis_rotated?a.margin.left-a.rotated_padding_left-a.rotated_padding_right:a.width,a.height2=b.axis_rotated?a.height:a.currentHeight-a.margin2.top-a.margin2.bottom,a.width2<0&&(a.width2=0),a.height2<0&&(a.height2=0),a.arcWidth=a.width-(a.isLegendRight?d+10:0),a.arcHeight=a.height-(a.isLegendRight?0:10),a.hasType("gauge")&&!b.gauge_fullCircle&&(a.arcHeight+=a.height-a.getGaugeLabelHeight()),a.updateRadius&&a.updateRadius(),a.isLegendRight&&f&&(a.margin3.left=a.arcWidth/2+1.1*a.radiusExpanded)},i.updateTargets=function(a){var b=this;b.updateTargetsForText(a),b.updateTargetsForBar(a),b.updateTargetsForLine(a),b.hasArcType()&&b.updateTargetsForArc&&b.updateTargetsForArc(a),b.updateTargetsForSubchart&&b.updateTargetsForSubchart(a),b.showTargets()},i.showTargets=function(){var a=this;a.svg.selectAll("."+l.target).filter(function(b){return a.isTargetToShow(b.id)}).transition().duration(a.config.transition_duration).style("opacity",1)},i.redraw=function(a,b){var c,d,e,f,g,h,i,j,k,m,n,o,p,q,r,s,t,u,v,x,y,z,A,B,C,D,E,F,G,H=this,I=H.main,J=H.d3,K=H.config,L=H.getShapeIndices(H.isAreaType),M=H.getShapeIndices(H.isBarType),N=H.getShapeIndices(H.isLineType),O=H.hasArcType(),P=H.filterTargetsToShow(H.data.targets),Q=H.xv.bind(H);if(a=a||{},c=w(a,"withY",!0),d=w(a,"withSubchart",!0),e=w(a,"withTransition",!0),h=w(a,"withTransform",!1),i=w(a,"withUpdateXDomain",!1),j=w(a,"withUpdateOrgXDomain",!1),k=w(a,"withTrimXDomain",!0),p=w(a,"withUpdateXAxis",i),m=w(a,"withLegend",!1),n=w(a,"withEventRect",!0),o=w(a,"withDimension",!0),f=w(a,"withTransitionForExit",e),g=w(a,"withTransitionForAxis",e),v=e?K.transition_duration:0,x=f?v:0,y=g?v:0,b=b||H.axis.generateTransitions(y),m&&K.legend_show?H.updateLegend(H.mapToIds(H.data.targets),a,b):o&&H.updateDimension(!0),H.isCategorized()&&0===P.length&&H.x.domain([0,H.axes.x.selectAll(".tick").size()]),P.length?(H.updateXDomain(P,i,j,k),K.axis_x_tick_values||(B=H.axis.updateXAxisTickValues(P))):(H.xAxis.tickValues([]),H.subXAxis.tickValues([])),K.zoom_rescale&&!a.flow&&(E=H.x.orgDomain()),H.y.domain(H.getYDomain(P,"y",E)),H.y2.domain(H.getYDomain(P,"y2",E)),!K.axis_y_tick_values&&K.axis_y_tick_count&&H.yAxis.tickValues(H.axis.generateTickValues(H.y.domain(),K.axis_y_tick_count)),!K.axis_y2_tick_values&&K.axis_y2_tick_count&&H.y2Axis.tickValues(H.axis.generateTickValues(H.y2.domain(),K.axis_y2_tick_count)),H.axis.redraw(b,O),H.axis.updateLabels(e),(i||p)&&P.length)if(K.axis_x_tick_culling&&B){for(C=1;C<B.length;C++)if(B.length/C<K.axis_x_tick_culling_max){D=C;break}H.svg.selectAll("."+l.axisX+" .tick text").each(function(a){var b=B.indexOf(a);b>=0&&J.select(this).style("display",b%D?"none":"block")})}else H.svg.selectAll("."+l.axisX+" .tick text").style("display","block");q=H.generateDrawArea?H.generateDrawArea(L,!1):void 0,r=H.generateDrawBar?H.generateDrawBar(M):void 0,s=H.generateDrawLine?H.generateDrawLine(N,!1):void 0,t=H.generateXYForText(L,M,N,!0),u=H.generateXYForText(L,M,N,!1),c&&(H.subY.domain(H.getYDomain(P,"y")),H.subY2.domain(H.getYDomain(P,"y2"))),H.updateXgridFocus(),I.select("text."+l.text+"."+l.empty).attr("x",H.width/2).attr("y",H.height/2).text(K.data_empty_label_text).transition().style("opacity",P.length?0:1),H.updateGrid(v),H.updateRegion(v),H.updateBar(x),H.updateLine(x),H.updateArea(x),H.updateCircle(),H.hasDataLabel()&&H.updateText(x),H.redrawTitle&&H.redrawTitle(),H.redrawArc&&H.redrawArc(v,x,h),H.redrawSubchart&&H.redrawSubchart(d,b,v,x,L,M,N),I.selectAll("."+l.selectedCircles).filter(H.isBarType.bind(H)).selectAll("circle").remove(),K.interaction_enabled&&!a.flow&&n&&(H.redrawEventRect(),H.updateZoom&&H.updateZoom()),H.updateCircleY(),F=(H.config.axis_rotated?H.circleY:H.circleX).bind(H),G=(H.config.axis_rotated?H.circleX:H.circleY).bind(H),a.flow&&(A=H.generateFlow({targets:P,flow:a.flow,duration:a.flow.duration,drawBar:r,drawLine:s,drawArea:q,cx:F,cy:G,xv:Q,xForText:t,yForText:u})),(v||A)&&H.isTabVisible()?J.transition().duration(v).each(function(){var b=[];[H.redrawBar(r,!0),H.redrawLine(s,!0),H.redrawArea(q,!0),H.redrawCircle(F,G,!0),H.redrawText(t,u,a.flow,!0),H.redrawRegion(!0),H.redrawGrid(!0)].forEach(function(a){a.forEach(function(a){b.push(a)})}),z=H.generateWait(),b.forEach(function(a){z.add(a)})}).call(z,function(){A&&A(),K.onrendered&&K.onrendered.call(H)}):(H.redrawBar(r),H.redrawLine(s),H.redrawArea(q),H.redrawCircle(F,G),H.redrawText(t,u,a.flow),H.redrawRegion(),H.redrawGrid(),K.onrendered&&K.onrendered.call(H)),H.mapToIds(H.data.targets).forEach(function(a){H.withoutFadeIn[a]=!0})},i.updateAndRedraw=function(a){var b,c=this,d=c.config;a=a||{},a.withTransition=w(a,"withTransition",!0),a.withTransform=w(a,"withTransform",!1),a.withLegend=w(a,"withLegend",!1),a.withUpdateXDomain=!0,a.withUpdateOrgXDomain=!0,a.withTransitionForExit=!1,a.withTransitionForTransform=w(a,"withTransitionForTransform",a.withTransition),c.updateSizes(),a.withLegend&&d.legend_show||(b=c.axis.generateTransitions(a.withTransitionForAxis?d.transition_duration:0),c.updateScales(),c.updateSvgSize(),c.transformAll(a.withTransitionForTransform,b)),c.redraw(a,b)},i.redrawWithoutRescale=function(){this.redraw({withY:!1,withSubchart:!1,withEventRect:!1,withTransitionForAxis:!1})},i.isTimeSeries=function(){return"timeseries"===this.config.axis_x_type},i.isCategorized=function(){return this.config.axis_x_type.indexOf("categor")>=0},i.isCustomX=function(){var a=this,b=a.config;return!a.isTimeSeries()&&(b.data_x||v(b.data_xs))},i.isTimeSeriesY=function(){return"timeseries"===this.config.axis_y_type},i.getTranslate=function(a){var b,c,d=this,e=d.config;return"main"===a?(b=s(d.margin.left),c=s(d.margin.top)):"context"===a?(b=s(d.margin2.left),c=s(d.margin2.top)):"legend"===a?(b=d.margin3.left,c=d.margin3.top):"x"===a?(b=0,c=e.axis_rotated?0:d.height):"y"===a?(b=0,c=e.axis_rotated?d.height:0):"y2"===a?(b=e.axis_rotated?0:d.width,c=e.axis_rotated?1:0):"subx"===a?(b=0,c=e.axis_rotated?0:d.height2):"arc"===a&&(b=d.arcWidth/2,c=d.arcHeight/2),"translate("+b+","+c+")"},i.initialOpacity=function(a){return null!==a.value&&this.withoutFadeIn[a.id]?1:0},i.initialOpacityForCircle=function(a){return null!==a.value&&this.withoutFadeIn[a.id]?this.opacityForCircle(a):0},i.opacityForCircle=function(a){var b=this.config.point_show?1:0;return m(a.value)?this.isScatterType(a)?.5:b:0},i.opacityForText=function(){return this.hasDataLabel()?1:0},i.xx=function(a){return a?this.x(a.x):null},i.xv=function(a){var b=this,c=a.value;return b.isTimeSeries()?c=b.parseDate(a.value):b.isCategorized()&&"string"==typeof a.value&&(c=b.config.axis_x_categories.indexOf(a.value)),Math.ceil(b.x(c))},i.yv=function(a){var b=this,c=a.axis&&"y2"===a.axis?b.y2:b.y;return Math.ceil(c(a.value))},i.subxx=function(a){return a?this.subX(a.x):null},i.transformMain=function(a,b){var c,d,e,f=this;b&&b.axisX?c=b.axisX:(c=f.main.select("."+l.axisX),a&&(c=c.transition())),b&&b.axisY?d=b.axisY:(d=f.main.select("."+l.axisY),a&&(d=d.transition())),b&&b.axisY2?e=b.axisY2:(e=f.main.select("."+l.axisY2),a&&(e=e.transition())),(a?f.main.transition():f.main).attr("transform",f.getTranslate("main")),c.attr("transform",f.getTranslate("x")),d.attr("transform",f.getTranslate("y")),e.attr("transform",f.getTranslate("y2")),f.main.select("."+l.chartArcs).attr("transform",f.getTranslate("arc"))},i.transformAll=function(a,b){var c=this;c.transformMain(a,b),c.config.subchart_show&&c.transformContext(a,b),c.legend&&c.transformLegend(a)},i.updateSvgSize=function(){var a=this,b=a.svg.select(".c3-brush .background");a.svg.attr("width",a.currentWidth).attr("height",a.currentHeight),a.svg.selectAll(["#"+a.clipId,"#"+a.clipIdForGrid]).select("rect").attr("width",a.width).attr("height",a.height),a.svg.select("#"+a.clipIdForXAxis).select("rect").attr("x",a.getXAxisClipX.bind(a)).attr("y",a.getXAxisClipY.bind(a)).attr("width",a.getXAxisClipWidth.bind(a)).attr("height",a.getXAxisClipHeight.bind(a)),a.svg.select("#"+a.clipIdForYAxis).select("rect").attr("x",a.getYAxisClipX.bind(a)).attr("y",a.getYAxisClipY.bind(a)).attr("width",a.getYAxisClipWidth.bind(a)).attr("height",a.getYAxisClipHeight.bind(a)),a.svg.select("#"+a.clipIdForSubchart).select("rect").attr("width",a.width).attr("height",b.size()?b.attr("height"):0),a.svg.select("."+l.zoomRect).attr("width",a.width).attr("height",a.height),a.selectChart.style("max-height",a.currentHeight+"px")},i.updateDimension=function(a){var b=this;a||(b.config.axis_rotated?(b.axes.x.call(b.xAxis),b.axes.subx.call(b.subXAxis)):(b.axes.y.call(b.yAxis),b.axes.y2.call(b.y2Axis))),b.updateSizes(),b.updateScales(),b.updateSvgSize(),b.transformAll(!1)},i.observeInserted=function(b){var c,d=this;return"undefined"==typeof MutationObserver?void a.console.error("MutationObserver not defined."):(c=new MutationObserver(function(e){e.forEach(function(e){"childList"===e.type&&e.previousSibling&&(c.disconnect(),d.intervalForObserveInserted=a.setInterval(function(){b.node().parentNode&&(a.clearInterval(d.intervalForObserveInserted),d.updateDimension(),d.brush&&d.brush.update(),d.config.oninit.call(d),d.redraw({withTransform:!0,withUpdateXDomain:!0,withUpdateOrgXDomain:!0,withTransition:!1,withTransitionForTransform:!1,withLegend:!0}),b.transition().style("opacity",1))},10))})}),void c.observe(b.node(),{attributes:!0,childList:!0,characterData:!0}))},i.bindResize=function(){var b=this,c=b.config;if(b.resizeFunction=b.generateResize(),b.resizeFunction.add(function(){c.onresize.call(b)}),c.resize_auto&&b.resizeFunction.add(function(){void 0!==b.resizeTimeout&&a.clearTimeout(b.resizeTimeout),b.resizeTimeout=a.setTimeout(function(){delete b.resizeTimeout,b.api.flush()},100)}),b.resizeFunction.add(function(){c.onresized.call(b)}),a.attachEvent)a.attachEvent("onresize",b.resizeFunction);else if(a.addEventListener)a.addEventListener("resize",b.resizeFunction,!1);else{var d=a.onresize;d?d.add&&d.remove||(d=b.generateResize(),d.add(a.onresize)):d=b.generateResize(),d.add(b.resizeFunction),a.onresize=d}},i.generateResize=function(){function a(){b.forEach(function(a){a()})}var b=[];return a.add=function(a){b.push(a)},a.remove=function(a){for(var c=0;c<b.length;c++)if(b[c]===a){b.splice(c,1);break}},a},i.endall=function(a,b){var c=0;a.each(function(){++c}).each("end",function(){--c||b.apply(this,arguments)})},i.generateWait=function(){var a=[],b=function(b,c){var d=setInterval(function(){var b=0;a.forEach(function(a){if(a.empty())return void(b+=1);try{a.transition()}catch(c){b+=1}}),b===a.length&&(clearInterval(d),c&&c())},10)};return b.add=function(b){a.push(b)},b},i.parseDate=function(b){var c,d=this;return b instanceof Date?c=b:"string"==typeof b?c=d.dataTimeFormat(d.config.data_xFormat).parse(b):"number"!=typeof b||isNaN(b)||(c=new Date(+b)),c&&!isNaN(+c)||a.console.error("Failed to parse x '"+b+"' to Date object"),c},i.isTabVisible=function(){var a;return"undefined"!=typeof document.hidden?a="hidden":"undefined"!=typeof document.mozHidden?a="mozHidden":"undefined"!=typeof document.msHidden?a="msHidden":"undefined"!=typeof document.webkitHidden&&(a="webkitHidden"),!document[a]},i.getDefaultConfig=function(){var a={bindto:"#chart",svg_classname:void 0,size_width:void 0,size_height:void 0,padding_left:void 0,padding_right:void 0,padding_top:void 0,padding_bottom:void 0,resize_auto:!0,zoom_enabled:!1,zoom_extent:void 0,zoom_privileged:!1,zoom_rescale:!1,zoom_onzoom:function(){},zoom_onzoomstart:function(){},zoom_onzoomend:function(){},zoom_x_min:void 0,zoom_x_max:void 0,interaction_brighten:!0,interaction_enabled:!0,onmouseover:function(){},onmouseout:function(){},onresize:function(){},onresized:function(){},oninit:function(){},onrendered:function(){},transition_duration:350,data_x:void 0,data_xs:{},data_xFormat:"%Y-%m-%d",data_xLocaltime:!0,data_xSort:!0,data_idConverter:function(a){return a},data_names:{},data_classes:{},data_groups:[],data_axes:{},data_type:void 0,data_types:{},data_labels:{},data_order:"desc",data_regions:{},data_color:void 0,data_colors:{},data_hide:!1,data_filter:void 0,data_selection_enabled:!1,data_selection_grouped:!1,data_selection_isselectable:function(){return!0},data_selection_multiple:!0,data_selection_draggable:!1,data_onclick:function(){},data_onmouseover:function(){},data_onmouseout:function(){},data_onselected:function(){},data_onunselected:function(){},data_url:void 0,data_headers:void 0,data_json:void 0,data_rows:void 0,data_columns:void 0,data_mimeType:void 0,data_keys:void 0,data_empty_label_text:"",subchart_show:!1,subchart_size_height:60,subchart_axis_x_show:!0,subchart_onbrush:function(){},color_pattern:[],color_threshold:{},legend_show:!0,legend_hide:!1,legend_position:"bottom",legend_inset_anchor:"top-left",legend_inset_x:10,legend_inset_y:0,legend_inset_step:void 0,legend_item_onclick:void 0,legend_item_onmouseover:void 0,legend_item_onmouseout:void 0,legend_equally:!1,legend_padding:0,legend_item_tile_width:10,legend_item_tile_height:10,axis_rotated:!1,axis_x_show:!0,axis_x_type:"indexed",axis_x_localtime:!0,axis_x_categories:[],axis_x_tick_centered:!1,axis_x_tick_format:void 0,axis_x_tick_culling:{},axis_x_tick_culling_max:10,axis_x_tick_count:void 0,axis_x_tick_fit:!0,axis_x_tick_values:null,axis_x_tick_rotate:0,axis_x_tick_outer:!0,axis_x_tick_multiline:!0,axis_x_tick_width:null,axis_x_max:void 0,axis_x_min:void 0,axis_x_padding:{},axis_x_height:void 0,axis_x_extent:void 0,axis_x_label:{},axis_y_show:!0,axis_y_type:void 0,axis_y_max:void 0,axis_y_min:void 0,axis_y_inverted:!1,axis_y_center:void 0,axis_y_inner:void 0,axis_y_label:{},axis_y_tick_format:void 0,axis_y_tick_outer:!0,axis_y_tick_values:null,axis_y_tick_rotate:0,axis_y_tick_count:void 0,axis_y_tick_time_value:void 0,axis_y_tick_time_interval:void 0,axis_y_padding:{},axis_y_default:void 0,axis_y2_show:!1,axis_y2_max:void 0,axis_y2_min:void 0,axis_y2_inverted:!1,axis_y2_center:void 0,axis_y2_inner:void 0,axis_y2_label:{},axis_y2_tick_format:void 0,axis_y2_tick_outer:!0,axis_y2_tick_values:null,axis_y2_tick_count:void 0,axis_y2_padding:{},axis_y2_default:void 0,grid_x_show:!1,grid_x_type:"tick",grid_x_lines:[],grid_y_show:!1,grid_y_lines:[],grid_y_ticks:10,grid_focus_show:!0,grid_lines_front:!0,point_show:!0,point_r:2.5,point_sensitivity:10,point_focus_expand_enabled:!0,point_focus_expand_r:void 0,point_select_r:void 0,line_connectNull:!1,line_step_type:"step",bar_width:void 0,bar_width_ratio:.6,bar_width_max:void 0,bar_zerobased:!0,area_zerobased:!0,area_above:!1,pie_label_show:!0,pie_label_format:void 0,pie_label_threshold:.05,pie_label_ratio:void 0,pie_expand:{},pie_expand_duration:50,gauge_fullCircle:!1,gauge_label_show:!0,gauge_label_format:void 0,gauge_min:0,gauge_max:100,gauge_startingAngle:-1*Math.PI/2,gauge_units:void 0,gauge_width:void 0,gauge_expand:{},gauge_expand_duration:50,donut_label_show:!0,donut_label_format:void 0,donut_label_threshold:.05,donut_label_ratio:void 0,donut_width:void 0,donut_title:"",donut_expand:{},donut_expand_duration:50,spline_interpolation_type:"cardinal",regions:[],tooltip_show:!0,tooltip_grouped:!0,tooltip_format_title:void 0,tooltip_format_name:void 0,tooltip_format_value:void 0,tooltip_position:void 0,tooltip_contents:function(a,b,c,d){return this.getTooltipContent?this.getTooltipContent(a,b,c,d):""},tooltip_init_show:!1,tooltip_init_x:0,tooltip_init_position:{top:"0px",left:"50px"},tooltip_onshow:function(){},tooltip_onhide:function(){},title_text:void 0,title_padding:{top:0,right:0,bottom:0,left:0},title_position:"top-center"};return Object.keys(this.additionalConfig).forEach(function(b){a[b]=this.additionalConfig[b]},this),a},i.additionalConfig={},i.loadConfig=function(a){function b(){var a=d.shift();return a&&c&&"object"==typeof c&&a in c?(c=c[a],b()):a?void 0:c}var c,d,e,f=this.config;Object.keys(f).forEach(function(g){c=a,d=g.split("_"),e=b(),q(e)&&(f[g]=e)})},i.getScale=function(a,b,c){return(c?this.d3.time.scale():this.d3.scale.linear()).range([a,b])},i.getX=function(a,b,c,d){var e,f=this,g=f.getScale(a,b,f.isTimeSeries()),h=c?g.domain(c):g;f.isCategorized()?(d=d||function(){return 0},g=function(a,b){var c=h(a)+d(a);return b?c:Math.ceil(c)}):g=function(a,b){var c=h(a);return b?c:Math.ceil(c)};for(e in h)g[e]=h[e];return g.orgDomain=function(){return h.domain()},f.isCategorized()&&(g.domain=function(a){return arguments.length?(h.domain(a),g):(a=this.orgDomain(),[a[0],a[1]+1])}),g},i.getY=function(a,b,c){var d=this.getScale(a,b,this.isTimeSeriesY());return c&&d.domain(c),d},i.getYScale=function(a){return"y2"===this.axis.getId(a)?this.y2:this.y},i.getSubYScale=function(a){return"y2"===this.axis.getId(a)?this.subY2:this.subY},i.updateScales=function(){var a=this,b=a.config,c=!a.x;a.xMin=b.axis_rotated?1:0,a.xMax=b.axis_rotated?a.height:a.width,a.yMin=b.axis_rotated?0:a.height,a.yMax=b.axis_rotated?a.width:1,a.subXMin=a.xMin,a.subXMax=a.xMax,a.subYMin=b.axis_rotated?0:a.height2,a.subYMax=b.axis_rotated?a.width2:1,a.x=a.getX(a.xMin,a.xMax,c?void 0:a.x.orgDomain(),function(){return a.xAxis.tickOffset()}),a.y=a.getY(a.yMin,a.yMax,c?b.axis_y_default:a.y.domain()),a.y2=a.getY(a.yMin,a.yMax,c?b.axis_y2_default:a.y2.domain()),a.subX=a.getX(a.xMin,a.xMax,a.orgXDomain,function(b){return b%1?0:a.subXAxis.tickOffset()}),a.subY=a.getY(a.subYMin,a.subYMax,c?b.axis_y_default:a.subY.domain()),a.subY2=a.getY(a.subYMin,a.subYMax,c?b.axis_y2_default:a.subY2.domain()),a.xAxisTickFormat=a.axis.getXAxisTickFormat(),a.xAxisTickValues=a.axis.getXAxisTickValues(),a.yAxisTickValues=a.axis.getYAxisTickValues(),a.y2AxisTickValues=a.axis.getY2AxisTickValues(),a.xAxis=a.axis.getXAxis(a.x,a.xOrient,a.xAxisTickFormat,a.xAxisTickValues,b.axis_x_tick_outer),a.subXAxis=a.axis.getXAxis(a.subX,a.subXOrient,a.xAxisTickFormat,a.xAxisTickValues,b.axis_x_tick_outer),a.yAxis=a.axis.getYAxis(a.y,a.yOrient,b.axis_y_tick_format,a.yAxisTickValues,b.axis_y_tick_outer),a.y2Axis=a.axis.getYAxis(a.y2,a.y2Orient,b.axis_y2_tick_format,a.y2AxisTickValues,b.axis_y2_tick_outer),c||(a.brush&&a.brush.scale(a.subX),b.zoom_enabled&&a.zoom.scale(a.x)),a.updateArc&&a.updateArc()},i.getYDomainMin=function(a){var b,c,d,e,f,g,h=this,i=h.config,j=h.mapToIds(a),k=h.getValuesAsIdKeyed(a);if(i.data_groups.length>0)for(g=h.hasNegativeValueInTargets(a),b=0;b<i.data_groups.length;b++)if(e=i.data_groups[b].filter(function(a){return j.indexOf(a)>=0}),0!==e.length)for(d=e[0],g&&k[d]&&k[d].forEach(function(a,b){k[d][b]=0>a?a:0}),c=1;c<e.length;c++)f=e[c],k[f]&&k[f].forEach(function(a,b){h.axis.getId(f)!==h.axis.getId(d)||!k[d]||g&&+a>0||(k[d][b]+=+a)});return h.d3.min(Object.keys(k).map(function(a){return h.d3.min(k[a])}))},i.getYDomainMax=function(a){var b,c,d,e,f,g,h=this,i=h.config,j=h.mapToIds(a),k=h.getValuesAsIdKeyed(a);if(i.data_groups.length>0)for(g=h.hasPositiveValueInTargets(a),b=0;b<i.data_groups.length;b++)if(e=i.data_groups[b].filter(function(a){return j.indexOf(a)>=0}),0!==e.length)for(d=e[0],g&&k[d]&&k[d].forEach(function(a,b){k[d][b]=a>0?a:0}),c=1;c<e.length;c++)f=e[c],k[f]&&k[f].forEach(function(a,b){h.axis.getId(f)!==h.axis.getId(d)||!k[d]||g&&0>+a||(k[d][b]+=+a)});return h.d3.max(Object.keys(k).map(function(a){return h.d3.max(k[a])}))},i.getYDomain=function(a,b,c){var d,e,f,g,h,i,j,k,l,n,o,p=this,q=p.config,r=a.filter(function(a){return p.axis.getId(a.id)===b}),s=c?p.filterByXDomain(r,c):r,u="y2"===b?q.axis_y2_min:q.axis_y_min,w="y2"===b?q.axis_y2_max:q.axis_y_max,x=p.getYDomainMin(s),y=p.getYDomainMax(s),z="y2"===b?q.axis_y2_center:q.axis_y_center,A=p.hasType("bar",s)&&q.bar_zerobased||p.hasType("area",s)&&q.area_zerobased,B="y2"===b?q.axis_y2_inverted:q.axis_y_inverted,C=p.hasDataLabel()&&q.axis_rotated,D=p.hasDataLabel()&&!q.axis_rotated;return x=m(u)?u:m(w)?w>x?x:w-10:x,y=m(w)?w:m(u)?y>u?y:u+10:y,0===s.length?"y2"===b?p.y2.domain():p.y.domain():(isNaN(x)&&(x=0),isNaN(y)&&(y=x),x===y&&(0>x?y=0:x=0),n=x>=0&&y>=0,o=0>=x&&0>=y,(m(u)&&n||m(w)&&o)&&(A=!1),A&&(n&&(x=0),o&&(y=0)),e=Math.abs(y-x),f=g=h=.1*e,"undefined"!=typeof z&&(i=Math.max(Math.abs(x),Math.abs(y)),y=z+i,x=z-i),C?(j=p.getDataLabelLength(x,y,"width"),k=t(p.y.range()),l=[j[0]/k,j[1]/k],
|
2 |
-
g+=e*(l[1]/(1-l[0]-l[1])),h+=e*(l[0]/(1-l[0]-l[1]))):D&&(j=p.getDataLabelLength(x,y,"height"),g+=p.axis.convertPixelsToAxisPadding(j[1],e),h+=p.axis.convertPixelsToAxisPadding(j[0],e)),"y"===b&&v(q.axis_y_padding)&&(g=p.axis.getPadding(q.axis_y_padding,"top",g,e),h=p.axis.getPadding(q.axis_y_padding,"bottom",h,e)),"y2"===b&&v(q.axis_y2_padding)&&(g=p.axis.getPadding(q.axis_y2_padding,"top",g,e),h=p.axis.getPadding(q.axis_y2_padding,"bottom",h,e)),A&&(n&&(h=x),o&&(g=-y)),d=[x-h,y+g],B?d.reverse():d)},i.getXDomainMin=function(a){var b=this,c=b.config;return q(c.axis_x_min)?b.isTimeSeries()?this.parseDate(c.axis_x_min):c.axis_x_min:b.d3.min(a,function(a){return b.d3.min(a.values,function(a){return a.x})})},i.getXDomainMax=function(a){var b=this,c=b.config;return q(c.axis_x_max)?b.isTimeSeries()?this.parseDate(c.axis_x_max):c.axis_x_max:b.d3.max(a,function(a){return b.d3.max(a.values,function(a){return a.x})})},i.getXDomainPadding=function(a){var b,c,d,e,f=this,g=f.config,h=a[1]-a[0];return f.isCategorized()?c=0:f.hasType("bar")?(b=f.getMaxDataCount(),c=b>1?h/(b-1)/2:.5):c=.01*h,"object"==typeof g.axis_x_padding&&v(g.axis_x_padding)?(d=m(g.axis_x_padding.left)?g.axis_x_padding.left:c,e=m(g.axis_x_padding.right)?g.axis_x_padding.right:c):d=e="number"==typeof g.axis_x_padding?g.axis_x_padding:c,{left:d,right:e}},i.getXDomain=function(a){var b=this,c=[b.getXDomainMin(a),b.getXDomainMax(a)],d=c[0],e=c[1],f=b.getXDomainPadding(c),g=0,h=0;return d-e!==0||b.isCategorized()||(b.isTimeSeries()?(d=new Date(.5*d.getTime()),e=new Date(1.5*e.getTime())):(d=0===d?1:.5*d,e=0===e?-1:1.5*e)),(d||0===d)&&(g=b.isTimeSeries()?new Date(d.getTime()-f.left):d-f.left),(e||0===e)&&(h=b.isTimeSeries()?new Date(e.getTime()+f.right):e+f.right),[g,h]},i.updateXDomain=function(a,b,c,d,e){var f=this,g=f.config;return c&&(f.x.domain(e?e:f.d3.extent(f.getXDomain(a))),f.orgXDomain=f.x.domain(),g.zoom_enabled&&f.zoom.scale(f.x).updateScaleExtent(),f.subX.domain(f.x.domain()),f.brush&&f.brush.scale(f.subX)),b&&(f.x.domain(e?e:!f.brush||f.brush.empty()?f.orgXDomain:f.brush.extent()),g.zoom_enabled&&f.zoom.scale(f.x).updateScaleExtent()),d&&f.x.domain(f.trimXDomain(f.x.orgDomain())),f.x.domain()},i.trimXDomain=function(a){var b=this.getZoomDomain(),c=b[0],d=b[1];return a[0]<=c&&(a[1]=+a[1]+(c-a[0]),a[0]=c),d<=a[1]&&(a[0]=+a[0]-(a[1]-d),a[1]=d),a},i.isX=function(a){var b=this,c=b.config;return c.data_x&&a===c.data_x||v(c.data_xs)&&x(c.data_xs,a)},i.isNotX=function(a){return!this.isX(a)},i.getXKey=function(a){var b=this,c=b.config;return c.data_x?c.data_x:v(c.data_xs)?c.data_xs[a]:null},i.getXValuesOfXKey=function(a,b){var c,d=this,e=b&&v(b)?d.mapToIds(b):[];return e.forEach(function(b){d.getXKey(b)===a&&(c=d.data.xs[b])}),c},i.getIndexByX=function(a){var b=this,c=b.filterByX(b.data.targets,a);return c.length?c[0].index:null},i.getXValue=function(a,b){var c=this;return a in c.data.xs&&c.data.xs[a]&&m(c.data.xs[a][b])?c.data.xs[a][b]:b},i.getOtherTargetXs=function(){var a=this,b=Object.keys(a.data.xs);return b.length?a.data.xs[b[0]]:null},i.getOtherTargetX=function(a){var b=this.getOtherTargetXs();return b&&a<b.length?b[a]:null},i.addXs=function(a){var b=this;Object.keys(a).forEach(function(c){b.config.data_xs[c]=a[c]})},i.hasMultipleX=function(a){return this.d3.set(Object.keys(a).map(function(b){return a[b]})).size()>1},i.isMultipleX=function(){return v(this.config.data_xs)||!this.config.data_xSort||this.hasType("scatter")},i.addName=function(a){var b,c=this;return a&&(b=c.config.data_names[a.id],a.name=void 0!==b?b:a.id),a},i.getValueOnIndex=function(a,b){var c=a.filter(function(a){return a.index===b});return c.length?c[0]:null},i.updateTargetX=function(a,b){var c=this;a.forEach(function(a){a.values.forEach(function(d,e){d.x=c.generateTargetX(b[e],a.id,e)}),c.data.xs[a.id]=b})},i.updateTargetXs=function(a,b){var c=this;a.forEach(function(a){b[a.id]&&c.updateTargetX([a],b[a.id])})},i.generateTargetX=function(a,b,c){var d,e=this;return d=e.isTimeSeries()?a?e.parseDate(a):e.parseDate(e.getXValue(b,c)):e.isCustomX()&&!e.isCategorized()?m(a)?+a:e.getXValue(b,c):c},i.cloneTarget=function(a){return{id:a.id,id_org:a.id_org,values:a.values.map(function(a){return{x:a.x,value:a.value,id:a.id}})}},i.updateXs=function(){var a=this;a.data.targets.length&&(a.xs=[],a.data.targets[0].values.forEach(function(b){a.xs[b.index]=b.x}))},i.getPrevX=function(a){var b=this.xs[a-1];return"undefined"!=typeof b?b:null},i.getNextX=function(a){var b=this.xs[a+1];return"undefined"!=typeof b?b:null},i.getMaxDataCount=function(){var a=this;return a.d3.max(a.data.targets,function(a){return a.values.length})},i.getMaxDataCountTarget=function(a){var b,c=a.length,d=0;return c>1?a.forEach(function(a){a.values.length>d&&(b=a,d=a.values.length)}):b=c?a[0]:null,b},i.getEdgeX=function(a){var b=this;return a.length?[b.d3.min(a,function(a){return a.values[0].x}),b.d3.max(a,function(a){return a.values[a.values.length-1].x})]:[0,0]},i.mapToIds=function(a){return a.map(function(a){return a.id})},i.mapToTargetIds=function(a){var b=this;return a?[].concat(a):b.mapToIds(b.data.targets)},i.hasTarget=function(a,b){var c,d=this.mapToIds(a);for(c=0;c<d.length;c++)if(d[c]===b)return!0;return!1},i.isTargetToShow=function(a){return this.hiddenTargetIds.indexOf(a)<0},i.isLegendToShow=function(a){return this.hiddenLegendIds.indexOf(a)<0},i.filterTargetsToShow=function(a){var b=this;return a.filter(function(a){return b.isTargetToShow(a.id)})},i.mapTargetsToUniqueXs=function(a){var b=this,c=b.d3.set(b.d3.merge(a.map(function(a){return a.values.map(function(a){return+a.x})}))).values();return c=b.isTimeSeries()?c.map(function(a){return new Date(+a)}):c.map(function(a){return+a}),c.sort(function(a,b){return b>a?-1:a>b?1:a>=b?0:NaN})},i.addHiddenTargetIds=function(a){this.hiddenTargetIds=this.hiddenTargetIds.concat(a)},i.removeHiddenTargetIds=function(a){this.hiddenTargetIds=this.hiddenTargetIds.filter(function(b){return a.indexOf(b)<0})},i.addHiddenLegendIds=function(a){this.hiddenLegendIds=this.hiddenLegendIds.concat(a)},i.removeHiddenLegendIds=function(a){this.hiddenLegendIds=this.hiddenLegendIds.filter(function(b){return a.indexOf(b)<0})},i.getValuesAsIdKeyed=function(a){var b={};return a.forEach(function(a){b[a.id]=[],a.values.forEach(function(c){b[a.id].push(c.value)})}),b},i.checkValueInTargets=function(a,b){var c,d,e,f=Object.keys(a);for(c=0;c<f.length;c++)for(e=a[f[c]].values,d=0;d<e.length;d++)if(b(e[d].value))return!0;return!1},i.hasNegativeValueInTargets=function(a){return this.checkValueInTargets(a,function(a){return 0>a})},i.hasPositiveValueInTargets=function(a){return this.checkValueInTargets(a,function(a){return a>0})},i.isOrderDesc=function(){var a=this.config;return"string"==typeof a.data_order&&"desc"===a.data_order.toLowerCase()},i.isOrderAsc=function(){var a=this.config;return"string"==typeof a.data_order&&"asc"===a.data_order.toLowerCase()},i.orderTargets=function(a){var b=this,c=b.config,d=b.isOrderAsc(),e=b.isOrderDesc();return d||e?a.sort(function(a,b){var c=function(a,b){return a+Math.abs(b.value)},e=a.values.reduce(c,0),f=b.values.reduce(c,0);return d?f-e:e-f}):n(c.data_order)&&a.sort(c.data_order),a},i.filterByX=function(a,b){return this.d3.merge(a.map(function(a){return a.values})).filter(function(a){return a.x-b===0})},i.filterRemoveNull=function(a){return a.filter(function(a){return m(a.value)})},i.filterByXDomain=function(a,b){return a.map(function(a){return{id:a.id,id_org:a.id_org,values:a.values.filter(function(a){return b[0]<=a.x&&a.x<=b[1]})}})},i.hasDataLabel=function(){var a=this.config;return"boolean"==typeof a.data_labels&&a.data_labels?!0:!("object"!=typeof a.data_labels||!v(a.data_labels))},i.getDataLabelLength=function(a,b,c){var d=this,e=[0,0],f=1.3;return d.selectChart.select("svg").selectAll(".dummy").data([a,b]).enter().append("text").text(function(a){return d.dataLabelFormat(a.id)(a)}).each(function(a,b){e[b]=this.getBoundingClientRect()[c]*f}).remove(),e},i.isNoneArc=function(a){return this.hasTarget(this.data.targets,a.id)},i.isArc=function(a){return"data"in a&&this.hasTarget(this.data.targets,a.data.id)},i.findSameXOfValues=function(a,b){var c,d=a[b].x,e=[];for(c=b-1;c>=0&&d===a[c].x;c--)e.push(a[c]);for(c=b;c<a.length&&d===a[c].x;c++)e.push(a[c]);return e},i.findClosestFromTargets=function(a,b){var c,d=this;return c=a.map(function(a){return d.findClosest(a.values,b)}),d.findClosest(c,b)},i.findClosest=function(a,b){var c,d=this,e=d.config.point_sensitivity;return a.filter(function(a){return a&&d.isBarType(a.id)}).forEach(function(a){var b=d.main.select("."+l.bars+d.getTargetSelectorSuffix(a.id)+" ."+l.bar+"-"+a.index).node();!c&&d.isWithinBar(b)&&(c=a)}),a.filter(function(a){return a&&!d.isBarType(a.id)}).forEach(function(a){var f=d.dist(a,b);e>f&&(e=f,c=a)}),c},i.dist=function(a,b){var c=this,d=c.config,e=d.axis_rotated?1:0,f=d.axis_rotated?0:1,g=c.circleY(a,a.index),h=c.x(a.x);return Math.sqrt(Math.pow(h-b[e],2)+Math.pow(g-b[f],2))},i.convertValuesToStep=function(a){var b,c=[].concat(a);if(!this.isCategorized())return a;for(b=a.length+1;b>0;b--)c[b]=c[b-1];return c[0]={x:c[0].x-1,value:c[0].value,id:c[0].id},c[a.length+1]={x:c[a.length].x+1,value:c[a.length].value,id:c[a.length].id},c},i.updateDataAttributes=function(a,b){var c=this,d=c.config,e=d["data_"+a];return"undefined"==typeof b?e:(Object.keys(b).forEach(function(a){e[a]=b[a]}),c.redraw({withLegend:!0}),e)},i.convertUrlToData=function(a,b,c,d,e){var f=this,g=b?b:"csv",h=f.d3.xhr(a);c&&Object.keys(c).forEach(function(a){h.header(a,c[a])}),h.get(function(a,b){var c;if(!b)throw new Error(a.responseURL+" "+a.status+" ("+a.statusText+")");c="json"===g?f.convertJsonToData(JSON.parse(b.response),d):"tsv"===g?f.convertTsvToData(b.response):f.convertCsvToData(b.response),e.call(f,c)})},i.convertXsvToData=function(a,b){var c,d=b.parseRows(a);return 1===d.length?(c=[{}],d[0].forEach(function(a){c[0][a]=null})):c=b.parse(a),c},i.convertCsvToData=function(a){return this.convertXsvToData(a,this.d3.csv)},i.convertTsvToData=function(a){return this.convertXsvToData(a,this.d3.tsv)},i.convertJsonToData=function(a,b){var c,d,e=this,f=[];return b?(b.x?(c=b.value.concat(b.x),e.config.data_x=b.x):c=b.value,f.push(c),a.forEach(function(a){var b=[];c.forEach(function(c){var d=e.findValueInJson(a,c);p(d)&&(d=null),b.push(d)}),f.push(b)}),d=e.convertRowsToData(f)):(Object.keys(a).forEach(function(b){f.push([b].concat(a[b]))}),d=e.convertColumnsToData(f)),d},i.findValueInJson=function(a,b){b=b.replace(/\[(\w+)\]/g,".$1"),b=b.replace(/^\./,"");for(var c=b.split("."),d=0;d<c.length;++d){var e=c[d];if(!(e in a))return;a=a[e]}return a},i.convertRowsToData=function(a){var b,c,d=a[0],e={},f=[];for(b=1;b<a.length;b++){for(e={},c=0;c<a[b].length;c++){if(p(a[b][c]))throw new Error("Source data is missing a component at ("+b+","+c+")!");e[d[c]]=a[b][c]}f.push(e)}return f},i.convertColumnsToData=function(a){var b,c,d,e=[];for(b=0;b<a.length;b++)for(d=a[b][0],c=1;c<a[b].length;c++){if(p(e[c-1])&&(e[c-1]={}),p(a[b][c]))throw new Error("Source data is missing a component at ("+b+","+c+")!");e[c-1][d]=a[b][c]}return e},i.convertDataToTargets=function(a,b){var c,d=this,e=d.config,f=d.d3.keys(a[0]).filter(d.isNotX,d),g=d.d3.keys(a[0]).filter(d.isX,d);return f.forEach(function(c){var f=d.getXKey(c);d.isCustomX()||d.isTimeSeries()?g.indexOf(f)>=0?d.data.xs[c]=(b&&d.data.xs[c]?d.data.xs[c]:[]).concat(a.map(function(a){return a[f]}).filter(m).map(function(a,b){return d.generateTargetX(a,c,b)})):e.data_x?d.data.xs[c]=d.getOtherTargetXs():v(e.data_xs)&&(d.data.xs[c]=d.getXValuesOfXKey(f,d.data.targets)):d.data.xs[c]=a.map(function(a,b){return b})}),f.forEach(function(a){if(!d.data.xs[a])throw new Error('x is not defined for id = "'+a+'".')}),c=f.map(function(b,c){var f=e.data_idConverter(b);return{id:f,id_org:b,values:a.map(function(a,g){var h,i=d.getXKey(b),j=a[i],k=null===a[b]||isNaN(a[b])?null:+a[b];return d.isCustomX()&&d.isCategorized()&&0===c&&!p(j)?(0===c&&0===g&&(e.axis_x_categories=[]),h=e.axis_x_categories.indexOf(j),-1===h&&(h=e.axis_x_categories.length,e.axis_x_categories.push(j))):h=d.generateTargetX(j,b,g),(p(a[b])||d.data.xs[b].length<=g)&&(h=void 0),{x:h,value:k,id:f}}).filter(function(a){return q(a.x)})}}),c.forEach(function(a){var b;e.data_xSort&&(a.values=a.values.sort(function(a,b){var c=a.x||0===a.x?a.x:1/0,d=b.x||0===b.x?b.x:1/0;return c-d})),b=0,a.values.forEach(function(a){a.index=b++}),d.data.xs[a.id].sort(function(a,b){return a-b})}),d.hasNegativeValue=d.hasNegativeValueInTargets(c),d.hasPositiveValue=d.hasPositiveValueInTargets(c),e.data_type&&d.setTargetType(d.mapToIds(c).filter(function(a){return!(a in e.data_types)}),e.data_type),c.forEach(function(a){d.addCache(a.id_org,a)}),c},i.load=function(a,b){var c=this;a&&(b.filter&&(a=a.filter(b.filter)),(b.type||b.types)&&a.forEach(function(a){var d=b.types&&b.types[a.id]?b.types[a.id]:b.type;c.setTargetType(a.id,d)}),c.data.targets.forEach(function(b){for(var c=0;c<a.length;c++)if(b.id===a[c].id){b.values=a[c].values,a.splice(c,1);break}}),c.data.targets=c.data.targets.concat(a)),c.updateTargets(c.data.targets),c.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0,withLegend:!0}),b.done&&b.done()},i.loadFromArgs=function(a){var b=this;a.data?b.load(b.convertDataToTargets(a.data),a):a.url?b.convertUrlToData(a.url,a.mimeType,a.headers,a.keys,function(c){b.load(b.convertDataToTargets(c),a)}):a.json?b.load(b.convertDataToTargets(b.convertJsonToData(a.json,a.keys)),a):a.rows?b.load(b.convertDataToTargets(b.convertRowsToData(a.rows)),a):a.columns?b.load(b.convertDataToTargets(b.convertColumnsToData(a.columns)),a):b.load(null,a)},i.unload=function(a,b){var c=this;return b||(b=function(){}),a=a.filter(function(a){return c.hasTarget(c.data.targets,a)}),a&&0!==a.length?(c.svg.selectAll(a.map(function(a){return c.selectorTarget(a)})).transition().style("opacity",0).remove().call(c.endall,b),void a.forEach(function(a){c.withoutFadeIn[a]=!1,c.legend&&c.legend.selectAll("."+l.legendItem+c.getTargetSelectorSuffix(a)).remove(),c.data.targets=c.data.targets.filter(function(b){return b.id!==a})})):void b()},i.categoryName=function(a){var b=this.config;return a<b.axis_x_categories.length?b.axis_x_categories[a]:a},i.initEventRect=function(){var a=this;a.main.select("."+l.chart).append("g").attr("class",l.eventRects).style("fill-opacity",0)},i.redrawEventRect=function(){var a,b,c=this,d=c.config,e=c.isMultipleX(),f=c.main.select("."+l.eventRects).style("cursor",d.zoom_enabled?d.axis_rotated?"ns-resize":"ew-resize":null).classed(l.eventRectsMultiple,e).classed(l.eventRectsSingle,!e);f.selectAll("."+l.eventRect).remove(),c.eventRect=f.selectAll("."+l.eventRect),e?(a=c.eventRect.data([0]),c.generateEventRectsForMultipleXs(a.enter()),c.updateEventRect(a)):(b=c.getMaxDataCountTarget(c.data.targets),f.datum(b?b.values:[]),c.eventRect=f.selectAll("."+l.eventRect),a=c.eventRect.data(function(a){return a}),c.generateEventRectsForSingleX(a.enter()),c.updateEventRect(a),a.exit().remove())},i.updateEventRect=function(a){var b,c,d,e,f,g,h=this,i=h.config;a=a||h.eventRect.data(function(a){return a}),h.isMultipleX()?(b=0,c=0,d=h.width,e=h.height):(!h.isCustomX()&&!h.isTimeSeries()||h.isCategorized()?(f=h.getEventRectWidth(),g=function(a){return h.x(a.x)-f/2}):(h.updateXs(),f=function(a){var b=h.getPrevX(a.index),c=h.getNextX(a.index);return null===b&&null===c?i.axis_rotated?h.height:h.width:(null===b&&(b=h.x.domain()[0]),null===c&&(c=h.x.domain()[1]),Math.max(0,(h.x(c)-h.x(b))/2))},g=function(a){var b=h.getPrevX(a.index),c=h.getNextX(a.index),d=h.data.xs[a.id][a.index];return null===b&&null===c?0:(null===b&&(b=h.x.domain()[0]),(h.x(d)+h.x(b))/2)}),b=i.axis_rotated?0:g,c=i.axis_rotated?g:0,d=i.axis_rotated?h.width:f,e=i.axis_rotated?f:h.height),a.attr("class",h.classEvent.bind(h)).attr("x",b).attr("y",c).attr("width",d).attr("height",e)},i.generateEventRectsForSingleX=function(a){var b=this,c=b.d3,d=b.config;a.append("rect").attr("class",b.classEvent.bind(b)).style("cursor",d.data_selection_enabled&&d.data_selection_grouped?"pointer":null).on("mouseover",function(a){var c=a.index;b.dragging||b.flowing||b.hasArcType()||(d.point_focus_expand_enabled&&b.expandCircles(c,null,!0),b.expandBars(c,null,!0),b.main.selectAll("."+l.shape+"-"+c).each(function(a){d.data_onmouseover.call(b.api,a)}))}).on("mouseout",function(a){var c=a.index;b.config&&(b.hasArcType()||(b.hideXGridFocus(),b.hideTooltip(),b.unexpandCircles(),b.unexpandBars(),b.main.selectAll("."+l.shape+"-"+c).each(function(a){d.data_onmouseout.call(b.api,a)})))}).on("mousemove",function(a){var e,f=a.index,g=b.svg.select("."+l.eventRect+"-"+f);b.dragging||b.flowing||b.hasArcType()||(b.isStepType(a)&&"step-after"===b.config.line_step_type&&c.mouse(this)[0]<b.x(b.getXValue(a.id,f))&&(f-=1),e=b.filterTargetsToShow(b.data.targets).map(function(a){return b.addName(b.getValueOnIndex(a.values,f))}),d.tooltip_grouped&&(b.showTooltip(e,this),b.showXGridFocus(e)),(!d.tooltip_grouped||d.data_selection_enabled&&!d.data_selection_grouped)&&b.main.selectAll("."+l.shape+"-"+f).each(function(){c.select(this).classed(l.EXPANDED,!0),d.data_selection_enabled&&g.style("cursor",d.data_selection_grouped?"pointer":null),d.tooltip_grouped||(b.hideXGridFocus(),b.hideTooltip(),d.data_selection_grouped||(b.unexpandCircles(f),b.unexpandBars(f)))}).filter(function(a){return b.isWithinShape(this,a)}).each(function(a){d.data_selection_enabled&&(d.data_selection_grouped||d.data_selection_isselectable(a))&&g.style("cursor","pointer"),d.tooltip_grouped||(b.showTooltip([a],this),b.showXGridFocus([a]),d.point_focus_expand_enabled&&b.expandCircles(f,a.id,!0),b.expandBars(f,a.id,!0))}))}).on("click",function(a){var e=a.index;if(!b.hasArcType()&&b.toggleShape){if(b.cancelClick)return void(b.cancelClick=!1);b.isStepType(a)&&"step-after"===d.line_step_type&&c.mouse(this)[0]<b.x(b.getXValue(a.id,e))&&(e-=1),b.main.selectAll("."+l.shape+"-"+e).each(function(a){(d.data_selection_grouped||b.isWithinShape(this,a))&&(b.toggleShape(this,a,e),b.config.data_onclick.call(b.api,a,this))})}}).call(d.data_selection_draggable&&b.drag?c.behavior.drag().origin(Object).on("drag",function(){b.drag(c.mouse(this))}).on("dragstart",function(){b.dragstart(c.mouse(this))}).on("dragend",function(){b.dragend()}):function(){})},i.generateEventRectsForMultipleXs=function(a){function b(){c.svg.select("."+l.eventRect).style("cursor",null),c.hideXGridFocus(),c.hideTooltip(),c.unexpandCircles(),c.unexpandBars()}var c=this,d=c.d3,e=c.config;a.append("rect").attr("x",0).attr("y",0).attr("width",c.width).attr("height",c.height).attr("class",l.eventRect).on("mouseout",function(){c.config&&(c.hasArcType()||b())}).on("mousemove",function(){var a,f,g,h,i=c.filterTargetsToShow(c.data.targets);if(!c.dragging&&!c.hasArcType(i)){if(a=d.mouse(this),f=c.findClosestFromTargets(i,a),!c.mouseover||f&&f.id===c.mouseover.id||(e.data_onmouseout.call(c.api,c.mouseover),c.mouseover=void 0),!f)return void b();g=c.isScatterType(f)||!e.tooltip_grouped?[f]:c.filterByX(i,f.x),h=g.map(function(a){return c.addName(a)}),c.showTooltip(h,this),e.point_focus_expand_enabled&&c.expandCircles(f.index,f.id,!0),c.expandBars(f.index,f.id,!0),c.showXGridFocus(h),(c.isBarType(f.id)||c.dist(f,a)<e.point_sensitivity)&&(c.svg.select("."+l.eventRect).style("cursor","pointer"),c.mouseover||(e.data_onmouseover.call(c.api,f),c.mouseover=f))}}).on("click",function(){var a,b,f=c.filterTargetsToShow(c.data.targets);c.hasArcType(f)||(a=d.mouse(this),b=c.findClosestFromTargets(f,a),b&&(c.isBarType(b.id)||c.dist(b,a)<e.point_sensitivity)&&c.main.selectAll("."+l.shapes+c.getTargetSelectorSuffix(b.id)).selectAll("."+l.shape+"-"+b.index).each(function(){(e.data_selection_grouped||c.isWithinShape(this,b))&&(c.toggleShape(this,b,b.index),c.config.data_onclick.call(c.api,b,this))}))}).call(e.data_selection_draggable&&c.drag?d.behavior.drag().origin(Object).on("drag",function(){c.drag(d.mouse(this))}).on("dragstart",function(){c.dragstart(d.mouse(this))}).on("dragend",function(){c.dragend()}):function(){})},i.dispatchEvent=function(b,c,d){var e=this,f="."+l.eventRect+(e.isMultipleX()?"":"-"+c),g=e.main.select(f).node(),h=g.getBoundingClientRect(),i=h.left+(d?d[0]:0),j=h.top+(d?d[1]:0),k=document.createEvent("MouseEvents");k.initMouseEvent(b,!0,!0,a,0,i,j,i,j,!1,!1,!1,!1,0,null),g.dispatchEvent(k)},i.getCurrentWidth=function(){var a=this,b=a.config;return b.size_width?b.size_width:a.getParentWidth()},i.getCurrentHeight=function(){var a=this,b=a.config,c=b.size_height?b.size_height:a.getParentHeight();return c>0?c:320/(a.hasType("gauge")&&!b.gauge_fullCircle?2:1)},i.getCurrentPaddingTop=function(){var a=this,b=a.config,c=m(b.padding_top)?b.padding_top:0;return a.title&&a.title.node()&&(c+=a.getTitlePadding()),c},i.getCurrentPaddingBottom=function(){var a=this.config;return m(a.padding_bottom)?a.padding_bottom:0},i.getCurrentPaddingLeft=function(a){var b=this,c=b.config;return m(c.padding_left)?c.padding_left:c.axis_rotated?c.axis_x_show?Math.max(r(b.getAxisWidthByAxisId("x",a)),40):1:!c.axis_y_show||c.axis_y_inner?b.axis.getYAxisLabelPosition().isOuter?30:1:r(b.getAxisWidthByAxisId("y",a))},i.getCurrentPaddingRight=function(){var a=this,b=a.config,c=10,d=a.isLegendRight?a.getLegendWidth()+20:0;return m(b.padding_right)?b.padding_right+1:b.axis_rotated?c+d:!b.axis_y2_show||b.axis_y2_inner?2+d+(a.axis.getY2AxisLabelPosition().isOuter?20:0):r(a.getAxisWidthByAxisId("y2"))+d},i.getParentRectValue=function(a){for(var b,c=this.selectChart.node();c&&"BODY"!==c.tagName;){try{b=c.getBoundingClientRect()[a]}catch(d){"width"===a&&(b=c.offsetWidth)}if(b)break;c=c.parentNode}return b},i.getParentWidth=function(){return this.getParentRectValue("width")},i.getParentHeight=function(){var a=this.selectChart.style("height");return a.indexOf("px")>0?+a.replace("px",""):0},i.getSvgLeft=function(a){var b=this,c=b.config,d=c.axis_rotated||!c.axis_rotated&&!c.axis_y_inner,e=c.axis_rotated?l.axisX:l.axisY,f=b.main.select("."+e).node(),g=f&&d?f.getBoundingClientRect():{right:0},h=b.selectChart.node().getBoundingClientRect(),i=b.hasArcType(),j=g.right-h.left-(i?0:b.getCurrentPaddingLeft(a));return j>0?j:0},i.getAxisWidthByAxisId=function(a,b){var c=this,d=c.axis.getLabelPositionById(a);return c.axis.getMaxTickWidth(a,b)+(d.isInner?20:40)},i.getHorizontalAxisHeight=function(a){var b=this,c=b.config,d=30;return"x"!==a||c.axis_x_show?"x"===a&&c.axis_x_height?c.axis_x_height:"y"!==a||c.axis_y_show?"y2"!==a||c.axis_y2_show?("x"===a&&!c.axis_rotated&&c.axis_x_tick_rotate&&(d=30+b.axis.getMaxTickWidth(a)*Math.cos(Math.PI*(90-c.axis_x_tick_rotate)/180)),"y"===a&&c.axis_rotated&&c.axis_y_tick_rotate&&(d=30+b.axis.getMaxTickWidth(a)*Math.cos(Math.PI*(90-c.axis_y_tick_rotate)/180)),d+(b.axis.getLabelPositionById(a).isInner?0:10)+("y2"===a?-10:0)):b.rotated_padding_top:!c.legend_show||b.isLegendRight||b.isLegendInset?1:10:8},i.getEventRectWidth=function(){return Math.max(0,this.xAxis.tickInterval())},i.getShapeIndices=function(a){var b,c,d=this,e=d.config,f={},g=0;return d.filterTargetsToShow(d.data.targets.filter(a,d)).forEach(function(a){for(b=0;b<e.data_groups.length;b++)if(!(e.data_groups[b].indexOf(a.id)<0))for(c=0;c<e.data_groups[b].length;c++)if(e.data_groups[b][c]in f){f[a.id]=f[e.data_groups[b][c]];break}p(f[a.id])&&(f[a.id]=g++)}),f.__max__=g-1,f},i.getShapeX=function(a,b,c,d){var e=this,f=d?e.subX:e.x;return function(d){var e=d.id in c?c[d.id]:0;return d.x||0===d.x?f(d.x)-a*(b/2-e):0}},i.getShapeY=function(a){var b=this;return function(c){var d=a?b.getSubYScale(c.id):b.getYScale(c.id);return d(c.value)}},i.getShapeOffset=function(a,b,c){var d=this,e=d.orderTargets(d.filterTargetsToShow(d.data.targets.filter(a,d))),f=e.map(function(a){return a.id});return function(a,g){var h=c?d.getSubYScale(a.id):d.getYScale(a.id),i=h(0),j=i;return e.forEach(function(c){var e=d.isStepType(a)?d.convertValuesToStep(c.values):c.values;c.id!==a.id&&b[c.id]===b[a.id]&&f.indexOf(c.id)<f.indexOf(a.id)&&("undefined"!=typeof e[g]&&+e[g].x===+a.x||(g=-1,e.forEach(function(b,c){b.x===a.x&&(g=c)})),g in e&&e[g].value*a.value>=0&&(j+=h(e[g].value)-i))}),j}},i.isWithinShape=function(a,b){var c,d=this,e=d.d3.select(a);return d.isTargetToShow(b.id)?"circle"===a.nodeName?c=d.isStepType(b)?d.isWithinStep(a,d.getYScale(b.id)(b.value)):d.isWithinCircle(a,1.5*d.pointSelectR(b)):"path"===a.nodeName&&(c=e.classed(l.bar)?d.isWithinBar(a):!0):c=!1,c},i.getInterpolate=function(a){var b=this,c=b.isInterpolationType(b.config.spline_interpolation_type)?b.config.spline_interpolation_type:"cardinal";return b.isSplineType(a)?c:b.isStepType(a)?b.config.line_step_type:"linear"},i.initLine=function(){var a=this;a.main.select("."+l.chart).append("g").attr("class",l.chartLines)},i.updateTargetsForLine=function(a){var b,c,d=this,e=d.config,f=d.classChartLine.bind(d),g=d.classLines.bind(d),h=d.classAreas.bind(d),i=d.classCircles.bind(d),j=d.classFocus.bind(d);b=d.main.select("."+l.chartLines).selectAll("."+l.chartLine).data(a).attr("class",function(a){return f(a)+j(a)}),c=b.enter().append("g").attr("class",f).style("opacity",0).style("pointer-events","none"),c.append("g").attr("class",g),c.append("g").attr("class",h),c.append("g").attr("class",function(a){return d.generateClass(l.selectedCircles,a.id)}),c.append("g").attr("class",i).style("cursor",function(a){return e.data_selection_isselectable(a)?"pointer":null}),a.forEach(function(a){d.main.selectAll("."+l.selectedCircles+d.getTargetSelectorSuffix(a.id)).selectAll("."+l.selectedCircle).each(function(b){b.value=a.values[b.index].value})})},i.updateLine=function(a){var b=this;b.mainLine=b.main.selectAll("."+l.lines).selectAll("."+l.line).data(b.lineData.bind(b)),b.mainLine.enter().append("path").attr("class",b.classLine.bind(b)).style("stroke",b.color),b.mainLine.style("opacity",b.initialOpacity.bind(b)).style("shape-rendering",function(a){return b.isStepType(a)?"crispEdges":""}).attr("transform",null),b.mainLine.exit().transition().duration(a).style("opacity",0).remove()},i.redrawLine=function(a,b){return[(b?this.mainLine.transition(Math.random().toString()):this.mainLine).attr("d",a).style("stroke",this.color).style("opacity",1)]},i.generateDrawLine=function(a,b){var c=this,d=c.config,e=c.d3.svg.line(),f=c.generateGetLinePoints(a,b),g=b?c.getSubYScale:c.getYScale,h=function(a){return(b?c.subxx:c.xx).call(c,a)},i=function(a,b){return d.data_groups.length>0?f(a,b)[0][1]:g.call(c,a.id)(a.value)};return e=d.axis_rotated?e.x(i).y(h):e.x(h).y(i),d.line_connectNull||(e=e.defined(function(a){return null!=a.value})),function(a){var f,h=d.line_connectNull?c.filterRemoveNull(a.values):a.values,i=b?c.x:c.subX,j=g.call(c,a.id),k=0,l=0;return c.isLineType(a)?d.data_regions[a.id]?f=c.lineWithRegions(h,i,j,d.data_regions[a.id]):(c.isStepType(a)&&(h=c.convertValuesToStep(h)),f=e.interpolate(c.getInterpolate(a))(h)):(h[0]&&(k=i(h[0].x),l=j(h[0].value)),f=d.axis_rotated?"M "+l+" "+k:"M "+k+" "+l),f?f:"M 0 0"}},i.generateGetLinePoints=function(a,b){var c=this,d=c.config,e=a.__max__+1,f=c.getShapeX(0,e,a,!!b),g=c.getShapeY(!!b),h=c.getShapeOffset(c.isLineType,a,!!b),i=b?c.getSubYScale:c.getYScale;return function(a,b){var e=i.call(c,a.id)(0),j=h(a,b)||e,k=f(a),l=g(a);return d.axis_rotated&&(0<a.value&&e>l||a.value<0&&l>e)&&(l=e),[[k,l-(e-j)],[k,l-(e-j)],[k,l-(e-j)],[k,l-(e-j)]]}},i.lineWithRegions=function(a,b,c,d){function e(a,b){var c;for(c=0;c<b.length;c++)if(b[c].start<a&&a<=b[c].end)return!0;return!1}function f(a){return"M"+a[0][0]+" "+a[0][1]+" "+a[1][0]+" "+a[1][1]}var g,h,i,j,k,l,m,n,o,r,s,t,u=this,v=u.config,w=-1,x="M",y=u.isCategorized()?.5:0,z=[];if(q(d))for(g=0;g<d.length;g++)z[g]={},p(d[g].start)?z[g].start=a[0].x:z[g].start=u.isTimeSeries()?u.parseDate(d[g].start):d[g].start,p(d[g].end)?z[g].end=a[a.length-1].x:z[g].end=u.isTimeSeries()?u.parseDate(d[g].end):d[g].end;for(s=v.axis_rotated?function(a){return c(a.value)}:function(a){return b(a.x)},t=v.axis_rotated?function(a){return b(a.x)}:function(a){return c(a.value)},i=u.isTimeSeries()?function(a,d,e,g){var h,i=a.x.getTime(),j=d.x-a.x,l=new Date(i+j*e),m=new Date(i+j*(e+g));return h=v.axis_rotated?[[c(k(e)),b(l)],[c(k(e+g)),b(m)]]:[[b(l),c(k(e))],[b(m),c(k(e+g))]],f(h)}:function(a,d,e,g){var h;return h=v.axis_rotated?[[c(k(e),!0),b(j(e))],[c(k(e+g),!0),b(j(e+g))]]:[[b(j(e),!0),c(k(e))],[b(j(e+g),!0),c(k(e+g))]],f(h)},g=0;g<a.length;g++){if(p(z)||!e(a[g].x,z))x+=" "+s(a[g])+" "+t(a[g]);else for(j=u.getScale(a[g-1].x+y,a[g].x+y,u.isTimeSeries()),k=u.getScale(a[g-1].value,a[g].value),l=b(a[g].x)-b(a[g-1].x),m=c(a[g].value)-c(a[g-1].value),n=Math.sqrt(Math.pow(l,2)+Math.pow(m,2)),o=2/n,r=2*o,h=o;1>=h;h+=r)x+=i(a[g-1],a[g],h,o);w=a[g].x}return x},i.updateArea=function(a){var b=this,c=b.d3;b.mainArea=b.main.selectAll("."+l.areas).selectAll("."+l.area).data(b.lineData.bind(b)),b.mainArea.enter().append("path").attr("class",b.classArea.bind(b)).style("fill",b.color).style("opacity",function(){return b.orgAreaOpacity=+c.select(this).style("opacity"),0}),b.mainArea.style("opacity",b.orgAreaOpacity),b.mainArea.exit().transition().duration(a).style("opacity",0).remove()},i.redrawArea=function(a,b){return[(b?this.mainArea.transition(Math.random().toString()):this.mainArea).attr("d",a).style("fill",this.color).style("opacity",this.orgAreaOpacity)]},i.generateDrawArea=function(a,b){var c=this,d=c.config,e=c.d3.svg.area(),f=c.generateGetAreaPoints(a,b),g=b?c.getSubYScale:c.getYScale,h=function(a){return(b?c.subxx:c.xx).call(c,a)},i=function(a,b){return d.data_groups.length>0?f(a,b)[0][1]:g.call(c,a.id)(c.getAreaBaseValue(a.id))},j=function(a,b){return d.data_groups.length>0?f(a,b)[1][1]:g.call(c,a.id)(a.value)};return e=d.axis_rotated?e.x0(i).x1(j).y(h):e.x(h).y0(d.area_above?0:i).y1(j),d.line_connectNull||(e=e.defined(function(a){return null!==a.value})),function(a){var b,f=d.line_connectNull?c.filterRemoveNull(a.values):a.values,g=0,h=0;return c.isAreaType(a)?(c.isStepType(a)&&(f=c.convertValuesToStep(f)),b=e.interpolate(c.getInterpolate(a))(f)):(f[0]&&(g=c.x(f[0].x),h=c.getYScale(a.id)(f[0].value)),b=d.axis_rotated?"M "+h+" "+g:"M "+g+" "+h),b?b:"M 0 0"}},i.getAreaBaseValue=function(){return 0},i.generateGetAreaPoints=function(a,b){var c=this,d=c.config,e=a.__max__+1,f=c.getShapeX(0,e,a,!!b),g=c.getShapeY(!!b),h=c.getShapeOffset(c.isAreaType,a,!!b),i=b?c.getSubYScale:c.getYScale;return function(a,b){var e=i.call(c,a.id)(0),j=h(a,b)||e,k=f(a),l=g(a);return d.axis_rotated&&(0<a.value&&e>l||a.value<0&&l>e)&&(l=e),[[k,j],[k,l-(e-j)],[k,l-(e-j)],[k,j]]}},i.updateCircle=function(){var a=this;a.mainCircle=a.main.selectAll("."+l.circles).selectAll("."+l.circle).data(a.lineOrScatterData.bind(a)),a.mainCircle.enter().append("circle").attr("class",a.classCircle.bind(a)).attr("r",a.pointR.bind(a)).style("fill",a.color),a.mainCircle.style("opacity",a.initialOpacityForCircle.bind(a)),a.mainCircle.exit().remove()},i.redrawCircle=function(a,b,c){var d=this.main.selectAll("."+l.selectedCircle);return[(c?this.mainCircle.transition(Math.random().toString()):this.mainCircle).style("opacity",this.opacityForCircle.bind(this)).style("fill",this.color).attr("cx",a).attr("cy",b),(c?d.transition(Math.random().toString()):d).attr("cx",a).attr("cy",b)]},i.circleX=function(a){return a.x||0===a.x?this.x(a.x):null},i.updateCircleY=function(){var a,b,c=this;c.config.data_groups.length>0?(a=c.getShapeIndices(c.isLineType),b=c.generateGetLinePoints(a),c.circleY=function(a,c){return b(a,c)[0][1]}):c.circleY=function(a){return c.getYScale(a.id)(a.value)}},i.getCircles=function(a,b){var c=this;return(b?c.main.selectAll("."+l.circles+c.getTargetSelectorSuffix(b)):c.main).selectAll("."+l.circle+(m(a)?"-"+a:""))},i.expandCircles=function(a,b,c){var d=this,e=d.pointExpandedR.bind(d);c&&d.unexpandCircles(),d.getCircles(a,b).classed(l.EXPANDED,!0).attr("r",e)},i.unexpandCircles=function(a){var b=this,c=b.pointR.bind(b);b.getCircles(a).filter(function(){return b.d3.select(this).classed(l.EXPANDED)}).classed(l.EXPANDED,!1).attr("r",c)},i.pointR=function(a){var b=this,c=b.config;return b.isStepType(a)?0:n(c.point_r)?c.point_r(a):c.point_r;
|
3 |
-
},i.pointExpandedR=function(a){var b=this,c=b.config;return c.point_focus_expand_enabled?c.point_focus_expand_r?c.point_focus_expand_r:1.75*b.pointR(a):b.pointR(a)},i.pointSelectR=function(a){var b=this,c=b.config;return n(c.point_select_r)?c.point_select_r(a):c.point_select_r?c.point_select_r:4*b.pointR(a)},i.isWithinCircle=function(a,b){var c=this.d3,d=c.mouse(a),e=c.select(a),f=+e.attr("cx"),g=+e.attr("cy");return Math.sqrt(Math.pow(f-d[0],2)+Math.pow(g-d[1],2))<b},i.isWithinStep=function(a,b){return Math.abs(b-this.d3.mouse(a)[1])<30},i.initBar=function(){var a=this;a.main.select("."+l.chart).append("g").attr("class",l.chartBars)},i.updateTargetsForBar=function(a){var b,c,d=this,e=d.config,f=d.classChartBar.bind(d),g=d.classBars.bind(d),h=d.classFocus.bind(d);b=d.main.select("."+l.chartBars).selectAll("."+l.chartBar).data(a).attr("class",function(a){return f(a)+h(a)}),c=b.enter().append("g").attr("class",f).style("opacity",0).style("pointer-events","none"),c.append("g").attr("class",g).style("cursor",function(a){return e.data_selection_isselectable(a)?"pointer":null})},i.updateBar=function(a){var b=this,c=b.barData.bind(b),d=b.classBar.bind(b),e=b.initialOpacity.bind(b),f=function(a){return b.color(a.id)};b.mainBar=b.main.selectAll("."+l.bars).selectAll("."+l.bar).data(c),b.mainBar.enter().append("path").attr("class",d).style("stroke",f).style("fill",f),b.mainBar.style("opacity",e),b.mainBar.exit().transition().duration(a).style("opacity",0).remove()},i.redrawBar=function(a,b){return[(b?this.mainBar.transition(Math.random().toString()):this.mainBar).attr("d",a).style("fill",this.color).style("opacity",1)]},i.getBarW=function(a,b){var c=this,d=c.config,e="number"==typeof d.bar_width?d.bar_width:b?a.tickInterval()*d.bar_width_ratio/b:0;return d.bar_width_max&&e>d.bar_width_max?d.bar_width_max:e},i.getBars=function(a,b){var c=this;return(b?c.main.selectAll("."+l.bars+c.getTargetSelectorSuffix(b)):c.main).selectAll("."+l.bar+(m(a)?"-"+a:""))},i.expandBars=function(a,b,c){var d=this;c&&d.unexpandBars(),d.getBars(a,b).classed(l.EXPANDED,!0)},i.unexpandBars=function(a){var b=this;b.getBars(a).classed(l.EXPANDED,!1)},i.generateDrawBar=function(a,b){var c=this,d=c.config,e=c.generateGetBarPoints(a,b);return function(a,b){var c=e(a,b),f=d.axis_rotated?1:0,g=d.axis_rotated?0:1,h="M "+c[0][f]+","+c[0][g]+" L"+c[1][f]+","+c[1][g]+" L"+c[2][f]+","+c[2][g]+" L"+c[3][f]+","+c[3][g]+" z";return h}},i.generateGetBarPoints=function(a,b){var c=this,d=b?c.subXAxis:c.xAxis,e=a.__max__+1,f=c.getBarW(d,e),g=c.getShapeX(f,e,a,!!b),h=c.getShapeY(!!b),i=c.getShapeOffset(c.isBarType,a,!!b),j=b?c.getSubYScale:c.getYScale;return function(a,b){var d=j.call(c,a.id)(0),e=i(a,b)||d,k=g(a),l=h(a);return c.config.axis_rotated&&(0<a.value&&d>l||a.value<0&&l>d)&&(l=d),[[k,e],[k,l-(d-e)],[k+f,l-(d-e)],[k+f,e]]}},i.isWithinBar=function(a){var b=this.d3.mouse(a),c=a.getBoundingClientRect(),d=a.pathSegList.getItem(0),e=a.pathSegList.getItem(1),f=Math.min(d.x,e.x),g=Math.min(d.y,e.y),h=c.width,i=c.height,j=2,k=f-j,l=f+h+j,m=g+i+j,n=g-j;return k<b[0]&&b[0]<l&&n<b[1]&&b[1]<m},i.initText=function(){var a=this;a.main.select("."+l.chart).append("g").attr("class",l.chartTexts),a.mainText=a.d3.selectAll([])},i.updateTargetsForText=function(a){var b,c,d=this,e=d.classChartText.bind(d),f=d.classTexts.bind(d),g=d.classFocus.bind(d);b=d.main.select("."+l.chartTexts).selectAll("."+l.chartText).data(a).attr("class",function(a){return e(a)+g(a)}),c=b.enter().append("g").attr("class",e).style("opacity",0).style("pointer-events","none"),c.append("g").attr("class",f)},i.updateText=function(a){var b=this,c=b.config,d=b.barOrLineData.bind(b),e=b.classText.bind(b);b.mainText=b.main.selectAll("."+l.texts).selectAll("."+l.text).data(d),b.mainText.enter().append("text").attr("class",e).attr("text-anchor",function(a){return c.axis_rotated?a.value<0?"end":"start":"middle"}).style("stroke","none").style("fill",function(a){return b.color(a)}).style("fill-opacity",0),b.mainText.text(function(a,c,d){return b.dataLabelFormat(a.id)(a.value,a.id,c,d)}),b.mainText.exit().transition().duration(a).style("fill-opacity",0).remove()},i.redrawText=function(a,b,c,d){return[(d?this.mainText.transition():this.mainText).attr("x",a).attr("y",b).style("fill",this.color).style("fill-opacity",c?0:this.opacityForText.bind(this))]},i.getTextRect=function(a,b,c){var d,e=this.d3.select("body").append("div").classed("c3",!0),f=e.append("svg").style("visibility","hidden").style("position","fixed").style("top",0).style("left",0),g=this.d3.select(c).style("font");return f.selectAll(".dummy").data([a]).enter().append("text").classed(b?b:"",!0).style("font",g).text(a).each(function(){d=this.getBoundingClientRect()}),e.remove(),d},i.generateXYForText=function(a,b,c,d){var e=this,f=e.generateGetAreaPoints(a,!1),g=e.generateGetBarPoints(b,!1),h=e.generateGetLinePoints(c,!1),i=d?e.getXForText:e.getYForText;return function(a,b){var c=e.isAreaType(a)?f:e.isBarType(a)?g:h;return i.call(e,c(a,b),a,this)}},i.getXForText=function(a,b,c){var d,e,f=this,g=c.getBoundingClientRect();return f.config.axis_rotated?(e=f.isBarType(b)?4:6,d=a[2][1]+e*(b.value<0?-1:1)):d=f.hasType("bar")?(a[2][0]+a[0][0])/2:a[0][0],null===b.value&&(d>f.width?d=f.width-g.width:0>d&&(d=4)),d},i.getYForText=function(a,b,c){var d,e=this,f=c.getBoundingClientRect();return e.config.axis_rotated?d=(a[0][0]+a[2][0]+.6*f.height)/2:(d=a[2][1],b.value<0||0===b.value&&!e.hasPositiveValue?(d+=f.height,e.isBarType(b)&&e.isSafari()?d-=3:!e.isBarType(b)&&e.isChrome()&&(d+=3)):d+=e.isBarType(b)?-3:-6),null!==b.value||e.config.axis_rotated||(d<f.height?d=f.height:d>this.height&&(d=this.height-4)),d},i.setTargetType=function(a,b){var c=this,d=c.config;c.mapToTargetIds(a).forEach(function(a){c.withoutFadeIn[a]=b===d.data_types[a],d.data_types[a]=b}),a||(d.data_type=b)},i.hasType=function(a,b){var c=this,d=c.config.data_types,e=!1;return b=b||c.data.targets,b&&b.length?b.forEach(function(b){var c=d[b.id];(c&&c.indexOf(a)>=0||!c&&"line"===a)&&(e=!0)}):Object.keys(d).length?Object.keys(d).forEach(function(b){d[b]===a&&(e=!0)}):e=c.config.data_type===a,e},i.hasArcType=function(a){return this.hasType("pie",a)||this.hasType("donut",a)||this.hasType("gauge",a)},i.isLineType=function(a){var b=this.config,c=o(a)?a:a.id;return!b.data_types[c]||["line","spline","area","area-spline","step","area-step"].indexOf(b.data_types[c])>=0},i.isStepType=function(a){var b=o(a)?a:a.id;return["step","area-step"].indexOf(this.config.data_types[b])>=0},i.isSplineType=function(a){var b=o(a)?a:a.id;return["spline","area-spline"].indexOf(this.config.data_types[b])>=0},i.isAreaType=function(a){var b=o(a)?a:a.id;return["area","area-spline","area-step"].indexOf(this.config.data_types[b])>=0},i.isBarType=function(a){var b=o(a)?a:a.id;return"bar"===this.config.data_types[b]},i.isScatterType=function(a){var b=o(a)?a:a.id;return"scatter"===this.config.data_types[b]},i.isPieType=function(a){var b=o(a)?a:a.id;return"pie"===this.config.data_types[b]},i.isGaugeType=function(a){var b=o(a)?a:a.id;return"gauge"===this.config.data_types[b]},i.isDonutType=function(a){var b=o(a)?a:a.id;return"donut"===this.config.data_types[b]},i.isArcType=function(a){return this.isPieType(a)||this.isDonutType(a)||this.isGaugeType(a)},i.lineData=function(a){return this.isLineType(a)?[a]:[]},i.arcData=function(a){return this.isArcType(a.data)?[a]:[]},i.barData=function(a){return this.isBarType(a)?a.values:[]},i.lineOrScatterData=function(a){return this.isLineType(a)||this.isScatterType(a)?a.values:[]},i.barOrLineData=function(a){return this.isBarType(a)||this.isLineType(a)?a.values:[]},i.isInterpolationType=function(a){return["linear","linear-closed","basis","basis-open","basis-closed","bundle","cardinal","cardinal-open","cardinal-closed","monotone"].indexOf(a)>=0},i.initGrid=function(){var a=this,b=a.config,c=a.d3;a.grid=a.main.append("g").attr("clip-path",a.clipPathForGrid).attr("class",l.grid),b.grid_x_show&&a.grid.append("g").attr("class",l.xgrids),b.grid_y_show&&a.grid.append("g").attr("class",l.ygrids),b.grid_focus_show&&a.grid.append("g").attr("class",l.xgridFocus).append("line").attr("class",l.xgridFocus),a.xgrid=c.selectAll([]),b.grid_lines_front||a.initGridLines()},i.initGridLines=function(){var a=this,b=a.d3;a.gridLines=a.main.append("g").attr("clip-path",a.clipPathForGrid).attr("class",l.grid+" "+l.gridLines),a.gridLines.append("g").attr("class",l.xgridLines),a.gridLines.append("g").attr("class",l.ygridLines),a.xgridLines=b.selectAll([])},i.updateXGrid=function(a){var b=this,c=b.config,d=b.d3,e=b.generateGridData(c.grid_x_type,b.x),f=b.isCategorized()?b.xAxis.tickOffset():0;b.xgridAttr=c.axis_rotated?{x1:0,x2:b.width,y1:function(a){return b.x(a)-f},y2:function(a){return b.x(a)-f}}:{x1:function(a){return b.x(a)+f},x2:function(a){return b.x(a)+f},y1:0,y2:b.height},b.xgrid=b.main.select("."+l.xgrids).selectAll("."+l.xgrid).data(e),b.xgrid.enter().append("line").attr("class",l.xgrid),a||b.xgrid.attr(b.xgridAttr).style("opacity",function(){return+d.select(this).attr(c.axis_rotated?"y1":"x1")===(c.axis_rotated?b.height:0)?0:1}),b.xgrid.exit().remove()},i.updateYGrid=function(){var a=this,b=a.config,c=a.yAxis.tickValues()||a.y.ticks(b.grid_y_ticks);a.ygrid=a.main.select("."+l.ygrids).selectAll("."+l.ygrid).data(c),a.ygrid.enter().append("line").attr("class",l.ygrid),a.ygrid.attr("x1",b.axis_rotated?a.y:0).attr("x2",b.axis_rotated?a.y:a.width).attr("y1",b.axis_rotated?0:a.y).attr("y2",b.axis_rotated?a.height:a.y),a.ygrid.exit().remove(),a.smoothLines(a.ygrid,"grid")},i.gridTextAnchor=function(a){return a.position?a.position:"end"},i.gridTextDx=function(a){return"start"===a.position?4:"middle"===a.position?0:-4},i.xGridTextX=function(a){return"start"===a.position?-this.height:"middle"===a.position?-this.height/2:0},i.yGridTextX=function(a){return"start"===a.position?0:"middle"===a.position?this.width/2:this.width},i.updateGrid=function(a){var b,c,d,e=this,f=e.main,g=e.config;e.grid.style("visibility",e.hasArcType()?"hidden":"visible"),f.select("line."+l.xgridFocus).style("visibility","hidden"),g.grid_x_show&&e.updateXGrid(),e.xgridLines=f.select("."+l.xgridLines).selectAll("."+l.xgridLine).data(g.grid_x_lines),b=e.xgridLines.enter().append("g").attr("class",function(a){return l.xgridLine+(a["class"]?" "+a["class"]:"")}),b.append("line").style("opacity",0),b.append("text").attr("text-anchor",e.gridTextAnchor).attr("transform",g.axis_rotated?"":"rotate(-90)").attr("dx",e.gridTextDx).attr("dy",-5).style("opacity",0),e.xgridLines.exit().transition().duration(a).style("opacity",0).remove(),g.grid_y_show&&e.updateYGrid(),e.ygridLines=f.select("."+l.ygridLines).selectAll("."+l.ygridLine).data(g.grid_y_lines),c=e.ygridLines.enter().append("g").attr("class",function(a){return l.ygridLine+(a["class"]?" "+a["class"]:"")}),c.append("line").style("opacity",0),c.append("text").attr("text-anchor",e.gridTextAnchor).attr("transform",g.axis_rotated?"rotate(-90)":"").attr("dx",e.gridTextDx).attr("dy",-5).style("opacity",0),d=e.yv.bind(e),e.ygridLines.select("line").transition().duration(a).attr("x1",g.axis_rotated?d:0).attr("x2",g.axis_rotated?d:e.width).attr("y1",g.axis_rotated?0:d).attr("y2",g.axis_rotated?e.height:d).style("opacity",1),e.ygridLines.select("text").transition().duration(a).attr("x",g.axis_rotated?e.xGridTextX.bind(e):e.yGridTextX.bind(e)).attr("y",d).text(function(a){return a.text}).style("opacity",1),e.ygridLines.exit().transition().duration(a).style("opacity",0).remove()},i.redrawGrid=function(a){var b=this,c=b.config,d=b.xv.bind(b),e=b.xgridLines.select("line"),f=b.xgridLines.select("text");return[(a?e.transition():e).attr("x1",c.axis_rotated?0:d).attr("x2",c.axis_rotated?b.width:d).attr("y1",c.axis_rotated?d:0).attr("y2",c.axis_rotated?d:b.height).style("opacity",1),(a?f.transition():f).attr("x",c.axis_rotated?b.yGridTextX.bind(b):b.xGridTextX.bind(b)).attr("y",d).text(function(a){return a.text}).style("opacity",1)]},i.showXGridFocus=function(a){var b=this,c=b.config,d=a.filter(function(a){return a&&m(a.value)}),e=b.main.selectAll("line."+l.xgridFocus),f=b.xx.bind(b);c.tooltip_show&&(b.hasType("scatter")||b.hasArcType()||(e.style("visibility","visible").data([d[0]]).attr(c.axis_rotated?"y1":"x1",f).attr(c.axis_rotated?"y2":"x2",f),b.smoothLines(e,"grid")))},i.hideXGridFocus=function(){this.main.select("line."+l.xgridFocus).style("visibility","hidden")},i.updateXgridFocus=function(){var a=this,b=a.config;a.main.select("line."+l.xgridFocus).attr("x1",b.axis_rotated?0:-10).attr("x2",b.axis_rotated?a.width:-10).attr("y1",b.axis_rotated?-10:0).attr("y2",b.axis_rotated?-10:a.height)},i.generateGridData=function(a,b){var c,d,e,f,g=this,h=[],i=g.main.select("."+l.axisX).selectAll(".tick").size();if("year"===a)for(c=g.getXDomain(),d=c[0].getFullYear(),e=c[1].getFullYear(),f=d;e>=f;f++)h.push(new Date(f+"-01-01 00:00:00"));else h=b.ticks(10),h.length>i&&(h=h.filter(function(a){return(""+a).indexOf(".")<0}));return h},i.getGridFilterToRemove=function(a){return a?function(b){var c=!1;return[].concat(a).forEach(function(a){("value"in a&&b.value===a.value||"class"in a&&b["class"]===a["class"])&&(c=!0)}),c}:function(){return!0}},i.removeGridLines=function(a,b){var c=this,d=c.config,e=c.getGridFilterToRemove(a),f=function(a){return!e(a)},g=b?l.xgridLines:l.ygridLines,h=b?l.xgridLine:l.ygridLine;c.main.select("."+g).selectAll("."+h).filter(e).transition().duration(d.transition_duration).style("opacity",0).remove(),b?d.grid_x_lines=d.grid_x_lines.filter(f):d.grid_y_lines=d.grid_y_lines.filter(f)},i.initTooltip=function(){var a,b=this,c=b.config;if(b.tooltip=b.selectChart.style("position","relative").append("div").attr("class",l.tooltipContainer).style("position","absolute").style("pointer-events","none").style("display","none"),c.tooltip_init_show){if(b.isTimeSeries()&&o(c.tooltip_init_x)){for(c.tooltip_init_x=b.parseDate(c.tooltip_init_x),a=0;a<b.data.targets[0].values.length&&b.data.targets[0].values[a].x-c.tooltip_init_x!==0;a++);c.tooltip_init_x=a}b.tooltip.html(c.tooltip_contents.call(b,b.data.targets.map(function(a){return b.addName(a.values[c.tooltip_init_x])}),b.axis.getXAxisTickFormat(),b.getYFormat(b.hasArcType()),b.color)),b.tooltip.style("top",c.tooltip_init_position.top).style("left",c.tooltip_init_position.left).style("display","block")}},i.getTooltipContent=function(a,b,c,d){var e,f,g,h,i,j,k=this,l=k.config,m=l.tooltip_format_title||b,n=l.tooltip_format_name||function(a){return a},o=l.tooltip_format_value||c,p=k.isOrderAsc();if(0===l.data_groups.length)a.sort(function(a,b){var c=a?a.value:null,d=b?b.value:null;return p?c-d:d-c});else{var q=k.orderTargets(k.data.targets).map(function(a){return a.id});a.sort(function(a,b){var c=a?a.value:null,d=b?b.value:null;return c>0&&d>0&&(c=a?q.indexOf(a.id):null,d=b?q.indexOf(b.id):null),p?c-d:d-c})}for(f=0;f<a.length;f++)if(a[f]&&(a[f].value||0===a[f].value)&&(e||(g=y(m?m(a[f].x):a[f].x),e="<table class='"+k.CLASS.tooltip+"'>"+(g||0===g?"<tr><th colspan='2'>"+g+"</th></tr>":"")),h=y(o(a[f].value,a[f].ratio,a[f].id,a[f].index,a)),void 0!==h)){if(null===a[f].name)continue;i=y(n(a[f].name,a[f].ratio,a[f].id,a[f].index)),j=k.levelColor?k.levelColor(a[f].value):d(a[f].id),e+="<tr class='"+k.CLASS.tooltipName+"-"+k.getTargetSelectorSuffix(a[f].id)+"'>",e+="<td class='name'><span style='background-color:"+j+"'></span>"+i+"</td>",e+="<td class='value'>"+h+"</td>",e+="</tr>"}return e+"</table>"},i.tooltipPosition=function(a,b,c,d){var e,f,g,h,i,j=this,k=j.config,l=j.d3,m=j.hasArcType(),n=l.mouse(d);return m?(f=(j.width-(j.isLegendRight?j.getLegendWidth():0))/2+n[0],h=j.height/2+n[1]+20):(e=j.getSvgLeft(!0),k.axis_rotated?(f=e+n[0]+100,g=f+b,i=j.currentWidth-j.getCurrentPaddingRight(),h=j.x(a[0].x)+20):(f=e+j.getCurrentPaddingLeft(!0)+j.x(a[0].x)+20,g=f+b,i=e+j.currentWidth-j.getCurrentPaddingRight(),h=n[1]+15),g>i&&(f-=g-i+20),h+c>j.currentHeight&&(h-=c+30)),0>h&&(h=0),{top:h,left:f}},i.showTooltip=function(a,b){var c,d,e,f=this,g=f.config,h=f.hasArcType(),j=a.filter(function(a){return a&&m(a.value)}),k=g.tooltip_position||i.tooltipPosition;0!==j.length&&g.tooltip_show&&(f.tooltip.html(g.tooltip_contents.call(f,a,f.axis.getXAxisTickFormat(),f.getYFormat(h),f.color)).style("display","block"),c=f.tooltip.property("offsetWidth"),d=f.tooltip.property("offsetHeight"),e=k.call(this,j,c,d,b),f.tooltip.style("top",e.top+"px").style("left",e.left+"px"))},i.hideTooltip=function(){this.tooltip.style("display","none")},i.initLegend=function(){var a=this;return a.legendItemTextBox={},a.legendHasRendered=!1,a.legend=a.svg.append("g").attr("transform",a.getTranslate("legend")),a.config.legend_show?void a.updateLegendWithDefaults():(a.legend.style("visibility","hidden"),void(a.hiddenLegendIds=a.mapToIds(a.data.targets)))},i.updateLegendWithDefaults=function(){var a=this;a.updateLegend(a.mapToIds(a.data.targets),{withTransform:!1,withTransitionForTransform:!1,withTransition:!1})},i.updateSizeForLegend=function(a,b){var c=this,d=c.config,e={top:c.isLegendTop?c.getCurrentPaddingTop()+d.legend_inset_y+5.5:c.currentHeight-a-c.getCurrentPaddingBottom()-d.legend_inset_y,left:c.isLegendLeft?c.getCurrentPaddingLeft()+d.legend_inset_x+.5:c.currentWidth-b-c.getCurrentPaddingRight()-d.legend_inset_x+.5};c.margin3={top:c.isLegendRight?0:c.isLegendInset?e.top:c.currentHeight-a,right:NaN,bottom:0,left:c.isLegendRight?c.currentWidth-b:c.isLegendInset?e.left:0}},i.transformLegend=function(a){var b=this;(a?b.legend.transition():b.legend).attr("transform",b.getTranslate("legend"))},i.updateLegendStep=function(a){this.legendStep=a},i.updateLegendItemWidth=function(a){this.legendItemWidth=a},i.updateLegendItemHeight=function(a){this.legendItemHeight=a},i.getLegendWidth=function(){var a=this;return a.config.legend_show?a.isLegendRight||a.isLegendInset?a.legendItemWidth*(a.legendStep+1):a.currentWidth:0},i.getLegendHeight=function(){var a=this,b=0;return a.config.legend_show&&(b=a.isLegendRight?a.currentHeight:Math.max(20,a.legendItemHeight)*(a.legendStep+1)),b},i.opacityForLegend=function(a){return a.classed(l.legendItemHidden)?null:1},i.opacityForUnfocusedLegend=function(a){return a.classed(l.legendItemHidden)?null:.3},i.toggleFocusLegend=function(a,b){var c=this;a=c.mapToTargetIds(a),c.legend.selectAll("."+l.legendItem).filter(function(b){return a.indexOf(b)>=0}).classed(l.legendItemFocused,b).transition().duration(100).style("opacity",function(){var a=b?c.opacityForLegend:c.opacityForUnfocusedLegend;return a.call(c,c.d3.select(this))})},i.revertLegend=function(){var a=this,b=a.d3;a.legend.selectAll("."+l.legendItem).classed(l.legendItemFocused,!1).transition().duration(100).style("opacity",function(){return a.opacityForLegend(b.select(this))})},i.showLegend=function(a){var b=this,c=b.config;c.legend_show||(c.legend_show=!0,b.legend.style("visibility","visible"),b.legendHasRendered||b.updateLegendWithDefaults()),b.removeHiddenLegendIds(a),b.legend.selectAll(b.selectorLegends(a)).style("visibility","visible").transition().style("opacity",function(){return b.opacityForLegend(b.d3.select(this))})},i.hideLegend=function(a){var b=this,c=b.config;c.legend_show&&u(a)&&(c.legend_show=!1,b.legend.style("visibility","hidden")),b.addHiddenLegendIds(a),b.legend.selectAll(b.selectorLegends(a)).style("opacity",0).style("visibility","hidden")},i.clearLegendItemTextBoxCache=function(){this.legendItemTextBox={}},i.updateLegend=function(a,b,c){function d(a,b){return y.legendItemTextBox[b]||(y.legendItemTextBox[b]=y.getTextRect(a.textContent,l.legendItem,a)),y.legendItemTextBox[b]}function e(b,c,e){function f(a,b){b||(g=(o-G-n)/2,E>g&&(g=(o-n)/2,G=0,M++)),L[a]=M,K[M]=y.isLegendInset?10:g,H[a]=G,G+=n}var g,h,i=0===e,j=e===a.length-1,k=d(b,c),l=k.width+F+(!j||y.isLegendRight||y.isLegendInset?B:0)+z.legend_padding,m=k.height+A,n=y.isLegendRight||y.isLegendInset?m:l,o=y.isLegendRight||y.isLegendInset?y.getLegendHeight():y.getLegendWidth();return i&&(G=0,M=0,C=0,D=0),z.legend_show&&!y.isLegendToShow(c)?void(I[c]=J[c]=L[c]=H[c]=0):(I[c]=l,J[c]=m,(!C||l>=C)&&(C=l),(!D||m>=D)&&(D=m),h=y.isLegendRight||y.isLegendInset?D:C,void(z.legend_equally?(Object.keys(I).forEach(function(a){I[a]=C}),Object.keys(J).forEach(function(a){J[a]=D}),g=(o-h*a.length)/2,E>g?(G=0,M=0,a.forEach(function(a){f(a)})):f(c,!0)):f(c)))}var f,g,h,i,j,k,m,n,o,p,r,s,t,u,v,x,y=this,z=y.config,A=4,B=10,C=0,D=0,E=10,F=z.legend_item_tile_width+5,G=0,H={},I={},J={},K=[0],L={},M=0;a=a.filter(function(a){return!q(z.data_names[a])||null!==z.data_names[a]}),b=b||{},r=w(b,"withTransition",!0),s=w(b,"withTransitionForTransform",!0),y.isLegendInset&&(M=z.legend_inset_step?z.legend_inset_step:a.length,y.updateLegendStep(M)),y.isLegendRight?(f=function(a){return C*L[a]},i=function(a){return K[L[a]]+H[a]}):y.isLegendInset?(f=function(a){return C*L[a]+10},i=function(a){return K[L[a]]+H[a]}):(f=function(a){return K[L[a]]+H[a]},i=function(a){return D*L[a]}),g=function(a,b){return f(a,b)+4+z.legend_item_tile_width},j=function(a,b){return i(a,b)+9},h=function(a,b){return f(a,b)},k=function(a,b){return i(a,b)-5},m=function(a,b){return f(a,b)-2},n=function(a,b){return f(a,b)-2+z.legend_item_tile_width},o=function(a,b){return i(a,b)+4},p=y.legend.selectAll("."+l.legendItem).data(a).enter().append("g").attr("class",function(a){return y.generateClass(l.legendItem,a)}).style("visibility",function(a){return y.isLegendToShow(a)?"visible":"hidden"}).style("cursor","pointer").on("click",function(a){z.legend_item_onclick?z.legend_item_onclick.call(y,a):y.d3.event.altKey?(y.api.hide(),y.api.show(a)):(y.api.toggle(a),y.isTargetToShow(a)?y.api.focus(a):y.api.revert())}).on("mouseover",function(a){z.legend_item_onmouseover?z.legend_item_onmouseover.call(y,a):(y.d3.select(this).classed(l.legendItemFocused,!0),!y.transiting&&y.isTargetToShow(a)&&y.api.focus(a))}).on("mouseout",function(a){z.legend_item_onmouseout?z.legend_item_onmouseout.call(y,a):(y.d3.select(this).classed(l.legendItemFocused,!1),y.api.revert())}),p.append("text").text(function(a){return q(z.data_names[a])?z.data_names[a]:a}).each(function(a,b){e(this,a,b)}).style("pointer-events","none").attr("x",y.isLegendRight||y.isLegendInset?g:-200).attr("y",y.isLegendRight||y.isLegendInset?-200:j),p.append("rect").attr("class",l.legendItemEvent).style("fill-opacity",0).attr("x",y.isLegendRight||y.isLegendInset?h:-200).attr("y",y.isLegendRight||y.isLegendInset?-200:k),p.append("line").attr("class",l.legendItemTile).style("stroke",y.color).style("pointer-events","none").attr("x1",y.isLegendRight||y.isLegendInset?m:-200).attr("y1",y.isLegendRight||y.isLegendInset?-200:o).attr("x2",y.isLegendRight||y.isLegendInset?n:-200).attr("y2",y.isLegendRight||y.isLegendInset?-200:o).attr("stroke-width",z.legend_item_tile_height),x=y.legend.select("."+l.legendBackground+" rect"),y.isLegendInset&&C>0&&0===x.size()&&(x=y.legend.insert("g","."+l.legendItem).attr("class",l.legendBackground).append("rect")),t=y.legend.selectAll("text").data(a).text(function(a){return q(z.data_names[a])?z.data_names[a]:a}).each(function(a,b){e(this,a,b)}),(r?t.transition():t).attr("x",g).attr("y",j),u=y.legend.selectAll("rect."+l.legendItemEvent).data(a),(r?u.transition():u).attr("width",function(a){return I[a]}).attr("height",function(a){return J[a]}).attr("x",h).attr("y",k),v=y.legend.selectAll("line."+l.legendItemTile).data(a),(r?v.transition():v).style("stroke",y.color).attr("x1",m).attr("y1",o).attr("x2",n).attr("y2",o),x&&(r?x.transition():x).attr("height",y.getLegendHeight()-12).attr("width",C*(M+1)+10),y.legend.selectAll("."+l.legendItem).classed(l.legendItemHidden,function(a){return!y.isTargetToShow(a)}),y.updateLegendItemWidth(C),y.updateLegendItemHeight(D),y.updateLegendStep(M),y.updateSizes(),y.updateScales(),y.updateSvgSize(),y.transformAll(s,c),y.legendHasRendered=!0},i.initTitle=function(){var a=this;a.title=a.svg.append("text").text(a.config.title_text).attr("class",a.CLASS.title)},i.redrawTitle=function(){var a=this;a.title.attr("x",a.xForTitle.bind(a)).attr("y",a.yForTitle.bind(a))},i.xForTitle=function(){var a,b=this,c=b.config,d=c.title_position||"left";return a=d.indexOf("right")>=0?b.currentWidth-b.getTextRect(b.title.node().textContent,b.CLASS.title,b.title.node()).width-c.title_padding.right:d.indexOf("center")>=0?(b.currentWidth-b.getTextRect(b.title.node().textContent,b.CLASS.title,b.title.node()).width)/2:c.title_padding.left},i.yForTitle=function(){var a=this;return a.config.title_padding.top+a.getTextRect(a.title.node().textContent,a.CLASS.title,a.title.node()).height},i.getTitlePadding=function(){var a=this;return a.yForTitle()+a.config.title_padding.bottom},c(b,f),f.prototype.init=function(){var a=this.owner,b=a.config,c=a.main;a.axes.x=c.append("g").attr("class",l.axis+" "+l.axisX).attr("clip-path",a.clipPathForXAxis).attr("transform",a.getTranslate("x")).style("visibility",b.axis_x_show?"visible":"hidden"),a.axes.x.append("text").attr("class",l.axisXLabel).attr("transform",b.axis_rotated?"rotate(-90)":"").style("text-anchor",this.textAnchorForXAxisLabel.bind(this)),a.axes.y=c.append("g").attr("class",l.axis+" "+l.axisY).attr("clip-path",b.axis_y_inner?"":a.clipPathForYAxis).attr("transform",a.getTranslate("y")).style("visibility",b.axis_y_show?"visible":"hidden"),a.axes.y.append("text").attr("class",l.axisYLabel).attr("transform",b.axis_rotated?"":"rotate(-90)").style("text-anchor",this.textAnchorForYAxisLabel.bind(this)),a.axes.y2=c.append("g").attr("class",l.axis+" "+l.axisY2).attr("transform",a.getTranslate("y2")).style("visibility",b.axis_y2_show?"visible":"hidden"),a.axes.y2.append("text").attr("class",l.axisY2Label).attr("transform",b.axis_rotated?"":"rotate(-90)").style("text-anchor",this.textAnchorForY2AxisLabel.bind(this))},f.prototype.getXAxis=function(a,b,c,d,e,f,h){var i=this.owner,j=i.config,k={isCategory:i.isCategorized(),withOuterTick:e,tickMultiline:j.axis_x_tick_multiline,tickWidth:j.axis_x_tick_width,tickTextRotate:h?0:j.axis_x_tick_rotate,withoutTransition:f},l=g(i.d3,k).scale(a).orient(b);return i.isTimeSeries()&&d&&"function"!=typeof d&&(d=d.map(function(a){return i.parseDate(a)})),l.tickFormat(c).tickValues(d),i.isCategorized()&&(l.tickCentered(j.axis_x_tick_centered),u(j.axis_x_tick_culling)&&(j.axis_x_tick_culling=!1)),l},f.prototype.updateXAxisTickValues=function(a,b){var c,d=this.owner,e=d.config;return(e.axis_x_tick_fit||e.axis_x_tick_count)&&(c=this.generateTickValues(d.mapTargetsToUniqueXs(a),e.axis_x_tick_count,d.isTimeSeries())),b?b.tickValues(c):(d.xAxis.tickValues(c),d.subXAxis.tickValues(c)),c},f.prototype.getYAxis=function(a,b,c,d,e,f,h){var i=this.owner,j=i.config,k={withOuterTick:e,withoutTransition:f,tickTextRotate:h?0:j.axis_y_tick_rotate},l=g(i.d3,k).scale(a).orient(b).tickFormat(c);return i.isTimeSeriesY()?l.ticks(i.d3.time[j.axis_y_tick_time_value],j.axis_y_tick_time_interval):l.tickValues(d),l},f.prototype.getId=function(a){var b=this.owner.config;return a in b.data_axes?b.data_axes[a]:"y"},f.prototype.getXAxisTickFormat=function(){var a=this.owner,b=a.config,c=a.isTimeSeries()?a.defaultAxisTimeFormat:a.isCategorized()?a.categoryName:function(a){return 0>a?a.toFixed(0):a};return b.axis_x_tick_format&&(n(b.axis_x_tick_format)?c=b.axis_x_tick_format:a.isTimeSeries()&&(c=function(c){return c?a.axisTimeFormat(b.axis_x_tick_format)(c):""})),n(c)?function(b){return c.call(a,b)}:c},f.prototype.getTickValues=function(a,b){return a?a:b?b.tickValues():void 0},f.prototype.getXAxisTickValues=function(){return this.getTickValues(this.owner.config.axis_x_tick_values,this.owner.xAxis)},f.prototype.getYAxisTickValues=function(){return this.getTickValues(this.owner.config.axis_y_tick_values,this.owner.yAxis)},f.prototype.getY2AxisTickValues=function(){return this.getTickValues(this.owner.config.axis_y2_tick_values,this.owner.y2Axis)},f.prototype.getLabelOptionByAxisId=function(a){var b,c=this.owner,d=c.config;return"y"===a?b=d.axis_y_label:"y2"===a?b=d.axis_y2_label:"x"===a&&(b=d.axis_x_label),b},f.prototype.getLabelText=function(a){var b=this.getLabelOptionByAxisId(a);return o(b)?b:b?b.text:null},f.prototype.setLabelText=function(a,b){var c=this.owner,d=c.config,e=this.getLabelOptionByAxisId(a);o(e)?"y"===a?d.axis_y_label=b:"y2"===a?d.axis_y2_label=b:"x"===a&&(d.axis_x_label=b):e&&(e.text=b)},f.prototype.getLabelPosition=function(a,b){var c=this.getLabelOptionByAxisId(a),d=c&&"object"==typeof c&&c.position?c.position:b;return{isInner:d.indexOf("inner")>=0,isOuter:d.indexOf("outer")>=0,isLeft:d.indexOf("left")>=0,isCenter:d.indexOf("center")>=0,isRight:d.indexOf("right")>=0,isTop:d.indexOf("top")>=0,isMiddle:d.indexOf("middle")>=0,isBottom:d.indexOf("bottom")>=0}},f.prototype.getXAxisLabelPosition=function(){return this.getLabelPosition("x",this.owner.config.axis_rotated?"inner-top":"inner-right")},f.prototype.getYAxisLabelPosition=function(){return this.getLabelPosition("y",this.owner.config.axis_rotated?"inner-right":"inner-top")},f.prototype.getY2AxisLabelPosition=function(){return this.getLabelPosition("y2",this.owner.config.axis_rotated?"inner-right":"inner-top")},f.prototype.getLabelPositionById=function(a){return"y2"===a?this.getY2AxisLabelPosition():"y"===a?this.getYAxisLabelPosition():this.getXAxisLabelPosition()},f.prototype.textForXAxisLabel=function(){return this.getLabelText("x")},f.prototype.textForYAxisLabel=function(){return this.getLabelText("y")},f.prototype.textForY2AxisLabel=function(){return this.getLabelText("y2")},f.prototype.xForAxisLabel=function(a,b){var c=this.owner;return a?b.isLeft?0:b.isCenter?c.width/2:c.width:b.isBottom?-c.height:b.isMiddle?-c.height/2:0},f.prototype.dxForAxisLabel=function(a,b){return a?b.isLeft?"0.5em":b.isRight?"-0.5em":"0":b.isTop?"-0.5em":b.isBottom?"0.5em":"0"},f.prototype.textAnchorForAxisLabel=function(a,b){return a?b.isLeft?"start":b.isCenter?"middle":"end":b.isBottom?"start":b.isMiddle?"middle":"end"},f.prototype.xForXAxisLabel=function(){return this.xForAxisLabel(!this.owner.config.axis_rotated,this.getXAxisLabelPosition())},f.prototype.xForYAxisLabel=function(){return this.xForAxisLabel(this.owner.config.axis_rotated,this.getYAxisLabelPosition())},f.prototype.xForY2AxisLabel=function(){return this.xForAxisLabel(this.owner.config.axis_rotated,this.getY2AxisLabelPosition())},f.prototype.dxForXAxisLabel=function(){return this.dxForAxisLabel(!this.owner.config.axis_rotated,this.getXAxisLabelPosition())},f.prototype.dxForYAxisLabel=function(){return this.dxForAxisLabel(this.owner.config.axis_rotated,this.getYAxisLabelPosition())},f.prototype.dxForY2AxisLabel=function(){return this.dxForAxisLabel(this.owner.config.axis_rotated,this.getY2AxisLabelPosition())},f.prototype.dyForXAxisLabel=function(){var a=this.owner,b=a.config,c=this.getXAxisLabelPosition();return b.axis_rotated?c.isInner?"1.2em":-25-this.getMaxTickWidth("x"):c.isInner?"-0.5em":b.axis_x_height?b.axis_x_height-10:"3em"},f.prototype.dyForYAxisLabel=function(){var a=this.owner,b=this.getYAxisLabelPosition();return a.config.axis_rotated?b.isInner?"-0.5em":"3em":b.isInner?"1.2em":-10-(a.config.axis_y_inner?0:this.getMaxTickWidth("y")+10)},f.prototype.dyForY2AxisLabel=function(){var a=this.owner,b=this.getY2AxisLabelPosition();return a.config.axis_rotated?b.isInner?"1.2em":"-2.2em":b.isInner?"-0.5em":15+(a.config.axis_y2_inner?0:this.getMaxTickWidth("y2")+15)},f.prototype.textAnchorForXAxisLabel=function(){var a=this.owner;return this.textAnchorForAxisLabel(!a.config.axis_rotated,this.getXAxisLabelPosition())},f.prototype.textAnchorForYAxisLabel=function(){var a=this.owner;return this.textAnchorForAxisLabel(a.config.axis_rotated,this.getYAxisLabelPosition())},f.prototype.textAnchorForY2AxisLabel=function(){var a=this.owner;return this.textAnchorForAxisLabel(a.config.axis_rotated,this.getY2AxisLabelPosition())},f.prototype.getMaxTickWidth=function(a,b){var c,d,e,f,g,h=this.owner,i=h.config,j=0;return b&&h.currentMaxTickWidths[a]?h.currentMaxTickWidths[a]:(h.svg&&(c=h.filterTargetsToShow(h.data.targets),"y"===a?(d=h.y.copy().domain(h.getYDomain(c,"y")),e=this.getYAxis(d,h.yOrient,i.axis_y_tick_format,h.yAxisTickValues,!1,!0,!0)):"y2"===a?(d=h.y2.copy().domain(h.getYDomain(c,"y2")),
|
4 |
-
e=this.getYAxis(d,h.y2Orient,i.axis_y2_tick_format,h.y2AxisTickValues,!1,!0,!0)):(d=h.x.copy().domain(h.getXDomain(c)),e=this.getXAxis(d,h.xOrient,h.xAxisTickFormat,h.xAxisTickValues,!1,!0,!0),this.updateXAxisTickValues(c,e)),f=h.d3.select("body").append("div").classed("c3",!0),g=f.append("svg").style("visibility","hidden").style("position","fixed").style("top",0).style("left",0),g.append("g").call(e).each(function(){h.d3.select(this).selectAll("text").each(function(){var a=this.getBoundingClientRect();j<a.width&&(j=a.width)}),f.remove()})),h.currentMaxTickWidths[a]=0>=j?h.currentMaxTickWidths[a]:j,h.currentMaxTickWidths[a])},f.prototype.updateLabels=function(a){var b=this.owner,c=b.main.select("."+l.axisX+" ."+l.axisXLabel),d=b.main.select("."+l.axisY+" ."+l.axisYLabel),e=b.main.select("."+l.axisY2+" ."+l.axisY2Label);(a?c.transition():c).attr("x",this.xForXAxisLabel.bind(this)).attr("dx",this.dxForXAxisLabel.bind(this)).attr("dy",this.dyForXAxisLabel.bind(this)).text(this.textForXAxisLabel.bind(this)),(a?d.transition():d).attr("x",this.xForYAxisLabel.bind(this)).attr("dx",this.dxForYAxisLabel.bind(this)).attr("dy",this.dyForYAxisLabel.bind(this)).text(this.textForYAxisLabel.bind(this)),(a?e.transition():e).attr("x",this.xForY2AxisLabel.bind(this)).attr("dx",this.dxForY2AxisLabel.bind(this)).attr("dy",this.dyForY2AxisLabel.bind(this)).text(this.textForY2AxisLabel.bind(this))},f.prototype.getPadding=function(a,b,c,d){var e="number"==typeof a?a:a[b];return m(e)?"ratio"===a.unit?a[b]*d:this.convertPixelsToAxisPadding(e,d):c},f.prototype.convertPixelsToAxisPadding=function(a,b){var c=this.owner,d=c.config.axis_rotated?c.width:c.height;return b*(a/d)},f.prototype.generateTickValues=function(a,b,c){var d,e,f,g,h,i,j,k=a;if(b)if(d=n(b)?b():b,1===d)k=[a[0]];else if(2===d)k=[a[0],a[a.length-1]];else if(d>2){for(g=d-2,e=a[0],f=a[a.length-1],h=(f-e)/(g+1),k=[e],i=0;g>i;i++)j=+e+h*(i+1),k.push(c?new Date(j):j);k.push(f)}return c||(k=k.sort(function(a,b){return a-b})),k},f.prototype.generateTransitions=function(a){var b=this.owner,c=b.axes;return{axisX:a?c.x.transition().duration(a):c.x,axisY:a?c.y.transition().duration(a):c.y,axisY2:a?c.y2.transition().duration(a):c.y2,axisSubX:a?c.subx.transition().duration(a):c.subx}},f.prototype.redraw=function(a,b){var c=this.owner;c.axes.x.style("opacity",b?0:1),c.axes.y.style("opacity",b?0:1),c.axes.y2.style("opacity",b?0:1),c.axes.subx.style("opacity",b?0:1),a.axisX.call(c.xAxis),a.axisY.call(c.yAxis),a.axisY2.call(c.y2Axis),a.axisSubX.call(c.subXAxis)},i.getClipPath=function(b){var c=a.navigator.appVersion.toLowerCase().indexOf("msie 9.")>=0;return"url("+(c?"":document.URL.split("#")[0])+"#"+b+")"},i.appendClip=function(a,b){return a.append("clipPath").attr("id",b).append("rect")},i.getAxisClipX=function(a){var b=Math.max(30,this.margin.left);return a?-(1+b):-(b-1)},i.getAxisClipY=function(a){return a?-20:-this.margin.top},i.getXAxisClipX=function(){var a=this;return a.getAxisClipX(!a.config.axis_rotated)},i.getXAxisClipY=function(){var a=this;return a.getAxisClipY(!a.config.axis_rotated)},i.getYAxisClipX=function(){var a=this;return a.config.axis_y_inner?-1:a.getAxisClipX(a.config.axis_rotated)},i.getYAxisClipY=function(){var a=this;return a.getAxisClipY(a.config.axis_rotated)},i.getAxisClipWidth=function(a){var b=this,c=Math.max(30,b.margin.left),d=Math.max(30,b.margin.right);return a?b.width+2+c+d:b.margin.left+20},i.getAxisClipHeight=function(a){return(a?this.margin.bottom:this.margin.top+this.height)+20},i.getXAxisClipWidth=function(){var a=this;return a.getAxisClipWidth(!a.config.axis_rotated)},i.getXAxisClipHeight=function(){var a=this;return a.getAxisClipHeight(!a.config.axis_rotated)},i.getYAxisClipWidth=function(){var a=this;return a.getAxisClipWidth(a.config.axis_rotated)+(a.config.axis_y_inner?20:0)},i.getYAxisClipHeight=function(){var a=this;return a.getAxisClipHeight(a.config.axis_rotated)},i.initPie=function(){var a=this,b=a.d3,c=a.config;a.pie=b.layout.pie().value(function(a){return a.values.reduce(function(a,b){return a+b.value},0)}),c.data_order||a.pie.sort(null)},i.updateRadius=function(){var a=this,b=a.config,c=b.gauge_width||b.donut_width;a.radiusExpanded=Math.min(a.arcWidth,a.arcHeight)/2,a.radius=.95*a.radiusExpanded,a.innerRadiusRatio=c?(a.radius-c)/a.radius:.6,a.innerRadius=a.hasType("donut")||a.hasType("gauge")?a.radius*a.innerRadiusRatio:0},i.updateArc=function(){var a=this;a.svgArc=a.getSvgArc(),a.svgArcExpanded=a.getSvgArcExpanded(),a.svgArcExpandedSub=a.getSvgArcExpanded(.98)},i.updateAngle=function(a){var b,c,d,e,f=this,g=f.config,h=!1,i=0;return g?(f.pie(f.filterTargetsToShow(f.data.targets)).forEach(function(b){h||b.data.id!==a.data.id||(h=!0,a=b,a.index=i),i++}),isNaN(a.startAngle)&&(a.startAngle=0),isNaN(a.endAngle)&&(a.endAngle=a.startAngle),f.isGaugeType(a.data)&&(b=g.gauge_min,c=g.gauge_max,d=Math.PI*(g.gauge_fullCircle?2:1)/(c-b),e=a.value<b?0:a.value<c?a.value-b:c-b,a.startAngle=g.gauge_startingAngle,a.endAngle=a.startAngle+d*e),h?a:null):null},i.getSvgArc=function(){var a=this,b=a.d3.svg.arc().outerRadius(a.radius).innerRadius(a.innerRadius),c=function(c,d){var e;return d?b(c):(e=a.updateAngle(c),e?b(e):"M 0 0")};return c.centroid=b.centroid,c},i.getSvgArcExpanded=function(a){var b=this,c=b.d3.svg.arc().outerRadius(b.radiusExpanded*(a?a:1)).innerRadius(b.innerRadius);return function(a){var d=b.updateAngle(a);return d?c(d):"M 0 0"}},i.getArc=function(a,b,c){return c||this.isArcType(a.data)?this.svgArc(a,b):"M 0 0"},i.transformForArcLabel=function(a){var b,c,d,e,f,g=this,h=g.config,i=g.updateAngle(a),j="";return i&&!g.hasType("gauge")&&(b=this.svgArc.centroid(i),c=isNaN(b[0])?0:b[0],d=isNaN(b[1])?0:b[1],e=Math.sqrt(c*c+d*d),f=g.hasType("donut")&&h.donut_label_ratio?n(h.donut_label_ratio)?h.donut_label_ratio(a,g.radius,e):h.donut_label_ratio:g.hasType("pie")&&h.pie_label_ratio?n(h.pie_label_ratio)?h.pie_label_ratio(a,g.radius,e):h.pie_label_ratio:g.radius&&e?(36/g.radius>.375?1.175-36/g.radius:.8)*g.radius/e:0,j="translate("+c*f+","+d*f+")"),j},i.getArcRatio=function(a){var b=this,c=b.config,d=Math.PI*(b.hasType("gauge")&&!c.gauge_fullCircle?1:2);return a?(a.endAngle-a.startAngle)/d:null},i.convertToArcData=function(a){return this.addName({id:a.data.id,value:a.value,ratio:this.getArcRatio(a),index:a.index})},i.textForArcLabel=function(a){var b,c,d,e,f,g=this;return g.shouldShowArcLabel()?(b=g.updateAngle(a),c=b?b.value:null,d=g.getArcRatio(b),e=a.data.id,g.hasType("gauge")||g.meetsArcLabelThreshold(d)?(f=g.getArcLabelFormat(),f?f(c,d,e):g.defaultArcValueFormat(c,d)):""):""},i.expandArc=function(b){var c,d=this;return d.transiting?void(c=a.setInterval(function(){d.transiting||(a.clearInterval(c),d.legend.selectAll(".c3-legend-item-focused").size()>0&&d.expandArc(b))},10)):(b=d.mapToTargetIds(b),void d.svg.selectAll(d.selectorTargets(b,"."+l.chartArc)).each(function(a){d.shouldExpand(a.data.id)&&d.d3.select(this).selectAll("path").transition().duration(d.expandDuration(a.data.id)).attr("d",d.svgArcExpanded).transition().duration(2*d.expandDuration(a.data.id)).attr("d",d.svgArcExpandedSub).each(function(a){d.isDonutType(a.data)})}))},i.unexpandArc=function(a){var b=this;b.transiting||(a=b.mapToTargetIds(a),b.svg.selectAll(b.selectorTargets(a,"."+l.chartArc)).selectAll("path").transition().duration(function(a){return b.expandDuration(a.data.id)}).attr("d",b.svgArc),b.svg.selectAll("."+l.arc).style("opacity",1))},i.expandDuration=function(a){var b=this,c=b.config;return b.isDonutType(a)?c.donut_expand_duration:b.isGaugeType(a)?c.gauge_expand_duration:b.isPieType(a)?c.pie_expand_duration:50},i.shouldExpand=function(a){var b=this,c=b.config;return b.isDonutType(a)&&c.donut_expand||b.isGaugeType(a)&&c.gauge_expand||b.isPieType(a)&&c.pie_expand},i.shouldShowArcLabel=function(){var a=this,b=a.config,c=!0;return a.hasType("donut")?c=b.donut_label_show:a.hasType("pie")&&(c=b.pie_label_show),c},i.meetsArcLabelThreshold=function(a){var b=this,c=b.config,d=b.hasType("donut")?c.donut_label_threshold:c.pie_label_threshold;return a>=d},i.getArcLabelFormat=function(){var a=this,b=a.config,c=b.pie_label_format;return a.hasType("gauge")?c=b.gauge_label_format:a.hasType("donut")&&(c=b.donut_label_format),c},i.getArcTitle=function(){var a=this;return a.hasType("donut")?a.config.donut_title:""},i.updateTargetsForArc=function(a){var b,c,d=this,e=d.main,f=d.classChartArc.bind(d),g=d.classArcs.bind(d),h=d.classFocus.bind(d);b=e.select("."+l.chartArcs).selectAll("."+l.chartArc).data(d.pie(a)).attr("class",function(a){return f(a)+h(a.data)}),c=b.enter().append("g").attr("class",f),c.append("g").attr("class",g),c.append("text").attr("dy",d.hasType("gauge")?"-.1em":".35em").style("opacity",0).style("text-anchor","middle").style("pointer-events","none")},i.initArc=function(){var a=this;a.arcs=a.main.select("."+l.chart).append("g").attr("class",l.chartArcs).attr("transform",a.getTranslate("arc")),a.arcs.append("text").attr("class",l.chartArcsTitle).style("text-anchor","middle").text(a.getArcTitle())},i.redrawArc=function(a,b,c){var d,e=this,f=e.d3,g=e.config,h=e.main;d=h.selectAll("."+l.arcs).selectAll("."+l.arc).data(e.arcData.bind(e)),d.enter().append("path").attr("class",e.classArc.bind(e)).style("fill",function(a){return e.color(a.data)}).style("cursor",function(a){return g.interaction_enabled&&g.data_selection_isselectable(a)?"pointer":null}).style("opacity",0).each(function(a){e.isGaugeType(a.data)&&(a.startAngle=a.endAngle=g.gauge_startingAngle),this._current=a}),d.attr("transform",function(a){return!e.isGaugeType(a.data)&&c?"scale(0)":""}).style("opacity",function(a){return a===this._current?0:1}).on("mouseover",g.interaction_enabled?function(a){var b,c;e.transiting||(b=e.updateAngle(a),b&&(c=e.convertToArcData(b),e.expandArc(b.data.id),e.api.focus(b.data.id),e.toggleFocusLegend(b.data.id,!0),e.config.data_onmouseover(c,this)))}:null).on("mousemove",g.interaction_enabled?function(a){var b,c,d=e.updateAngle(a);d&&(b=e.convertToArcData(d),c=[b],e.showTooltip(c,this))}:null).on("mouseout",g.interaction_enabled?function(a){var b,c;e.transiting||(b=e.updateAngle(a),b&&(c=e.convertToArcData(b),e.unexpandArc(b.data.id),e.api.revert(),e.revertLegend(),e.hideTooltip(),e.config.data_onmouseout(c,this)))}:null).on("click",g.interaction_enabled?function(a,b){var c,d=e.updateAngle(a);d&&(c=e.convertToArcData(d),e.toggleShape&&e.toggleShape(this,c,b),e.config.data_onclick.call(e.api,c,this))}:null).each(function(){e.transiting=!0}).transition().duration(a).attrTween("d",function(a){var b,c=e.updateAngle(a);return c?(isNaN(this._current.startAngle)&&(this._current.startAngle=0),isNaN(this._current.endAngle)&&(this._current.endAngle=this._current.startAngle),b=f.interpolate(this._current,c),this._current=b(0),function(c){var d=b(c);return d.data=a.data,e.getArc(d,!0)}):function(){return"M 0 0"}}).attr("transform",c?"scale(1)":"").style("fill",function(a){return e.levelColor?e.levelColor(a.data.values[0].value):e.color(a.data.id)}).style("opacity",1).call(e.endall,function(){e.transiting=!1}),d.exit().transition().duration(b).style("opacity",0).remove(),h.selectAll("."+l.chartArc).select("text").style("opacity",0).attr("class",function(a){return e.isGaugeType(a.data)?l.gaugeValue:""}).text(e.textForArcLabel.bind(e)).attr("transform",e.transformForArcLabel.bind(e)).style("font-size",function(a){return e.isGaugeType(a.data)?Math.round(e.radius/5)+"px":""}).transition().duration(a).style("opacity",function(a){return e.isTargetToShow(a.data.id)&&e.isArcType(a.data)?1:0}),h.select("."+l.chartArcsTitle).style("opacity",e.hasType("donut")||e.hasType("gauge")?1:0),e.hasType("gauge")&&(e.arcs.select("."+l.chartArcsBackground).attr("d",function(){var a={data:[{value:g.gauge_max}],startAngle:g.gauge_startingAngle,endAngle:-1*g.gauge_startingAngle};return e.getArc(a,!0,!0)}),e.arcs.select("."+l.chartArcsGaugeUnit).attr("dy",".75em").text(g.gauge_label_show?g.gauge_units:""),e.arcs.select("."+l.chartArcsGaugeMin).attr("dx",-1*(e.innerRadius+(e.radius-e.innerRadius)/(g.gauge_fullCircle?1:2))+"px").attr("dy","1.2em").text(g.gauge_label_show?g.gauge_min:""),e.arcs.select("."+l.chartArcsGaugeMax).attr("dx",e.innerRadius+(e.radius-e.innerRadius)/(g.gauge_fullCircle?1:2)+"px").attr("dy","1.2em").text(g.gauge_label_show?g.gauge_max:""))},i.initGauge=function(){var a=this.arcs;this.hasType("gauge")&&(a.append("path").attr("class",l.chartArcsBackground),a.append("text").attr("class",l.chartArcsGaugeUnit).style("text-anchor","middle").style("pointer-events","none"),a.append("text").attr("class",l.chartArcsGaugeMin).style("text-anchor","middle").style("pointer-events","none"),a.append("text").attr("class",l.chartArcsGaugeMax).style("text-anchor","middle").style("pointer-events","none"))},i.getGaugeLabelHeight=function(){return this.config.gauge_label_show?20:0},i.initRegion=function(){var a=this;a.region=a.main.append("g").attr("clip-path",a.clipPath).attr("class",l.regions)},i.updateRegion=function(a){var b=this,c=b.config;b.region.style("visibility",b.hasArcType()?"hidden":"visible"),b.mainRegion=b.main.select("."+l.regions).selectAll("."+l.region).data(c.regions),b.mainRegion.enter().append("g").append("rect").style("fill-opacity",0),b.mainRegion.attr("class",b.classRegion.bind(b)),b.mainRegion.exit().transition().duration(a).style("opacity",0).remove()},i.redrawRegion=function(a){var b=this,c=b.mainRegion.selectAll("rect").each(function(){var a=b.d3.select(this.parentNode).datum();b.d3.select(this).datum(a)}),d=b.regionX.bind(b),e=b.regionY.bind(b),f=b.regionWidth.bind(b),g=b.regionHeight.bind(b);return[(a?c.transition():c).attr("x",d).attr("y",e).attr("width",f).attr("height",g).style("fill-opacity",function(a){return m(a.opacity)?a.opacity:.1})]},i.regionX=function(a){var b,c=this,d=c.config,e="y"===a.axis?c.y:c.y2;return b="y"===a.axis||"y2"===a.axis?d.axis_rotated&&"start"in a?e(a.start):0:d.axis_rotated?0:"start"in a?c.x(c.isTimeSeries()?c.parseDate(a.start):a.start):0},i.regionY=function(a){var b,c=this,d=c.config,e="y"===a.axis?c.y:c.y2;return b="y"===a.axis||"y2"===a.axis?d.axis_rotated?0:"end"in a?e(a.end):0:d.axis_rotated&&"start"in a?c.x(c.isTimeSeries()?c.parseDate(a.start):a.start):0},i.regionWidth=function(a){var b,c=this,d=c.config,e=c.regionX(a),f="y"===a.axis?c.y:c.y2;return b="y"===a.axis||"y2"===a.axis?d.axis_rotated&&"end"in a?f(a.end):c.width:d.axis_rotated?c.width:"end"in a?c.x(c.isTimeSeries()?c.parseDate(a.end):a.end):c.width,e>b?0:b-e},i.regionHeight=function(a){var b,c=this,d=c.config,e=this.regionY(a),f="y"===a.axis?c.y:c.y2;return b="y"===a.axis||"y2"===a.axis?d.axis_rotated?c.height:"start"in a?f(a.start):c.height:d.axis_rotated&&"end"in a?c.x(c.isTimeSeries()?c.parseDate(a.end):a.end):c.height,e>b?0:b-e},i.isRegionOnX=function(a){return!a.axis||"x"===a.axis},i.drag=function(a){var b,c,d,e,f,g,h,i,j=this,k=j.config,m=j.main,n=j.d3;j.hasArcType()||k.data_selection_enabled&&(k.zoom_enabled&&!j.zoom.altDomain||k.data_selection_multiple&&(b=j.dragStart[0],c=j.dragStart[1],d=a[0],e=a[1],f=Math.min(b,d),g=Math.max(b,d),h=k.data_selection_grouped?j.margin.top:Math.min(c,e),i=k.data_selection_grouped?j.height:Math.max(c,e),m.select("."+l.dragarea).attr("x",f).attr("y",h).attr("width",g-f).attr("height",i-h),m.selectAll("."+l.shapes).selectAll("."+l.shape).filter(function(a){return k.data_selection_isselectable(a)}).each(function(a,b){var c,d,e,k,m,o,p=n.select(this),q=p.classed(l.SELECTED),r=p.classed(l.INCLUDED),s=!1;if(p.classed(l.circle))c=1*p.attr("cx"),d=1*p.attr("cy"),m=j.togglePoint,s=c>f&&g>c&&d>h&&i>d;else{if(!p.classed(l.bar))return;o=z(this),c=o.x,d=o.y,e=o.width,k=o.height,m=j.togglePath,s=!(c>g||f>c+e||d>i||h>d+k)}s^r&&(p.classed(l.INCLUDED,!r),p.classed(l.SELECTED,!q),m.call(j,!q,p,a,b))})))},i.dragstart=function(a){var b=this,c=b.config;b.hasArcType()||c.data_selection_enabled&&(b.dragStart=a,b.main.select("."+l.chart).append("rect").attr("class",l.dragarea).style("opacity",.1),b.dragging=!0)},i.dragend=function(){var a=this,b=a.config;a.hasArcType()||b.data_selection_enabled&&(a.main.select("."+l.dragarea).transition().duration(100).style("opacity",0).remove(),a.main.selectAll("."+l.shape).classed(l.INCLUDED,!1),a.dragging=!1)},i.selectPoint=function(a,b,c){var d=this,e=d.config,f=(e.axis_rotated?d.circleY:d.circleX).bind(d),g=(e.axis_rotated?d.circleX:d.circleY).bind(d),h=d.pointSelectR.bind(d);e.data_onselected.call(d.api,b,a.node()),d.main.select("."+l.selectedCircles+d.getTargetSelectorSuffix(b.id)).selectAll("."+l.selectedCircle+"-"+c).data([b]).enter().append("circle").attr("class",function(){return d.generateClass(l.selectedCircle,c)}).attr("cx",f).attr("cy",g).attr("stroke",function(){return d.color(b)}).attr("r",function(a){return 1.4*d.pointSelectR(a)}).transition().duration(100).attr("r",h)},i.unselectPoint=function(a,b,c){var d=this;d.config.data_onunselected.call(d.api,b,a.node()),d.main.select("."+l.selectedCircles+d.getTargetSelectorSuffix(b.id)).selectAll("."+l.selectedCircle+"-"+c).transition().duration(100).attr("r",0).remove()},i.togglePoint=function(a,b,c,d){a?this.selectPoint(b,c,d):this.unselectPoint(b,c,d)},i.selectPath=function(a,b){var c=this;c.config.data_onselected.call(c,b,a.node()),c.config.interaction_brighten&&a.transition().duration(100).style("fill",function(){return c.d3.rgb(c.color(b)).brighter(.75)})},i.unselectPath=function(a,b){var c=this;c.config.data_onunselected.call(c,b,a.node()),c.config.interaction_brighten&&a.transition().duration(100).style("fill",function(){return c.color(b)})},i.togglePath=function(a,b,c,d){a?this.selectPath(b,c,d):this.unselectPath(b,c,d)},i.getToggle=function(a,b){var c,d=this;return"circle"===a.nodeName?c=d.isStepType(b)?function(){}:d.togglePoint:"path"===a.nodeName&&(c=d.togglePath),c},i.toggleShape=function(a,b,c){var d=this,e=d.d3,f=d.config,g=e.select(a),h=g.classed(l.SELECTED),i=d.getToggle(a,b).bind(d);f.data_selection_enabled&&f.data_selection_isselectable(b)&&(f.data_selection_multiple||d.main.selectAll("."+l.shapes+(f.data_selection_grouped?d.getTargetSelectorSuffix(b.id):"")).selectAll("."+l.shape).each(function(a,b){var c=e.select(this);c.classed(l.SELECTED)&&i(!1,c.classed(l.SELECTED,!1),a,b)}),g.classed(l.SELECTED,!h),i(!h,g,b,c))},i.initBrush=function(){var a=this,b=a.d3;a.brush=b.svg.brush().on("brush",function(){a.redrawForBrush()}),a.brush.update=function(){return a.context&&a.context.select("."+l.brush).call(this),this},a.brush.scale=function(b){return a.config.axis_rotated?this.y(b):this.x(b)}},i.initSubchart=function(){var a=this,b=a.config,c=a.context=a.svg.append("g").attr("transform",a.getTranslate("context")),d=b.subchart_show?"visible":"hidden";c.style("visibility",d),c.append("g").attr("clip-path",a.clipPathForSubchart).attr("class",l.chart),c.select("."+l.chart).append("g").attr("class",l.chartBars),c.select("."+l.chart).append("g").attr("class",l.chartLines),c.append("g").attr("clip-path",a.clipPath).attr("class",l.brush).call(a.brush),a.axes.subx=c.append("g").attr("class",l.axisX).attr("transform",a.getTranslate("subx")).attr("clip-path",b.axis_rotated?"":a.clipPathForXAxis).style("visibility",b.subchart_axis_x_show?d:"hidden")},i.updateTargetsForSubchart=function(a){var b,c,d,e,f=this,g=f.context,h=f.config,i=f.classChartBar.bind(f),j=f.classBars.bind(f),k=f.classChartLine.bind(f),m=f.classLines.bind(f),n=f.classAreas.bind(f);h.subchart_show&&(e=g.select("."+l.chartBars).selectAll("."+l.chartBar).data(a).attr("class",i),d=e.enter().append("g").style("opacity",0).attr("class",i),d.append("g").attr("class",j),c=g.select("."+l.chartLines).selectAll("."+l.chartLine).data(a).attr("class",k),b=c.enter().append("g").style("opacity",0).attr("class",k),b.append("g").attr("class",m),b.append("g").attr("class",n),g.selectAll("."+l.brush+" rect").attr(h.axis_rotated?"width":"height",h.axis_rotated?f.width2:f.height2))},i.updateBarForSubchart=function(a){var b=this;b.contextBar=b.context.selectAll("."+l.bars).selectAll("."+l.bar).data(b.barData.bind(b)),b.contextBar.enter().append("path").attr("class",b.classBar.bind(b)).style("stroke","none").style("fill",b.color),b.contextBar.style("opacity",b.initialOpacity.bind(b)),b.contextBar.exit().transition().duration(a).style("opacity",0).remove()},i.redrawBarForSubchart=function(a,b,c){(b?this.contextBar.transition(Math.random().toString()).duration(c):this.contextBar).attr("d",a).style("opacity",1)},i.updateLineForSubchart=function(a){var b=this;b.contextLine=b.context.selectAll("."+l.lines).selectAll("."+l.line).data(b.lineData.bind(b)),b.contextLine.enter().append("path").attr("class",b.classLine.bind(b)).style("stroke",b.color),b.contextLine.style("opacity",b.initialOpacity.bind(b)),b.contextLine.exit().transition().duration(a).style("opacity",0).remove()},i.redrawLineForSubchart=function(a,b,c){(b?this.contextLine.transition(Math.random().toString()).duration(c):this.contextLine).attr("d",a).style("opacity",1)},i.updateAreaForSubchart=function(a){var b=this,c=b.d3;b.contextArea=b.context.selectAll("."+l.areas).selectAll("."+l.area).data(b.lineData.bind(b)),b.contextArea.enter().append("path").attr("class",b.classArea.bind(b)).style("fill",b.color).style("opacity",function(){return b.orgAreaOpacity=+c.select(this).style("opacity"),0}),b.contextArea.style("opacity",0),b.contextArea.exit().transition().duration(a).style("opacity",0).remove()},i.redrawAreaForSubchart=function(a,b,c){(b?this.contextArea.transition(Math.random().toString()).duration(c):this.contextArea).attr("d",a).style("fill",this.color).style("opacity",this.orgAreaOpacity)},i.redrawSubchart=function(a,b,c,d,e,f,g){var h,i,j,k=this,l=k.d3,m=k.config;k.context.style("visibility",m.subchart_show?"visible":"hidden"),m.subchart_show&&(l.event&&"zoom"===l.event.type&&k.brush.extent(k.x.orgDomain()).update(),a&&(k.brush.empty()||k.brush.extent(k.x.orgDomain()).update(),h=k.generateDrawArea(e,!0),i=k.generateDrawBar(f,!0),j=k.generateDrawLine(g,!0),k.updateBarForSubchart(c),k.updateLineForSubchart(c),k.updateAreaForSubchart(c),k.redrawBarForSubchart(i,c,c),k.redrawLineForSubchart(j,c,c),k.redrawAreaForSubchart(h,c,c)))},i.redrawForBrush=function(){var a=this,b=a.x;a.redraw({withTransition:!1,withY:a.config.zoom_rescale,withSubchart:!1,withUpdateXDomain:!0,withDimension:!1}),a.config.subchart_onbrush.call(a.api,b.orgDomain())},i.transformContext=function(a,b){var c,d=this;b&&b.axisSubX?c=b.axisSubX:(c=d.context.select("."+l.axisX),a&&(c=c.transition())),d.context.attr("transform",d.getTranslate("context")),c.attr("transform",d.getTranslate("subx"))},i.getDefaultExtent=function(){var a=this,b=a.config,c=n(b.axis_x_extent)?b.axis_x_extent(a.getXDomain(a.data.targets)):b.axis_x_extent;return a.isTimeSeries()&&(c=[a.parseDate(c[0]),a.parseDate(c[1])]),c},i.initZoom=function(){var a,b=this,c=b.d3,d=b.config;b.zoom=c.behavior.zoom().on("zoomstart",function(){a=c.event.sourceEvent,b.zoom.altDomain=c.event.sourceEvent.altKey?b.x.orgDomain():null,d.zoom_onzoomstart.call(b.api,c.event.sourceEvent)}).on("zoom",function(){b.redrawForZoom.call(b)}).on("zoomend",function(){var e=c.event.sourceEvent;e&&a.clientX===e.clientX&&a.clientY===e.clientY||(b.redrawEventRect(),b.updateZoom(),d.zoom_onzoomend.call(b.api,b.x.orgDomain()))}),b.zoom.scale=function(a){return d.axis_rotated?this.y(a):this.x(a)},b.zoom.orgScaleExtent=function(){var a=d.zoom_extent?d.zoom_extent:[1,10];return[a[0],Math.max(b.getMaxDataCount()/a[1],a[1])]},b.zoom.updateScaleExtent=function(){var a=t(b.x.orgDomain())/t(b.getZoomDomain()),c=this.orgScaleExtent();return this.scaleExtent([c[0]*a,c[1]*a]),this}},i.getZoomDomain=function(){var a=this,b=a.config,c=a.d3,d=c.min([a.orgXDomain[0],b.zoom_x_min]),e=c.max([a.orgXDomain[1],b.zoom_x_max]);return[d,e]},i.updateZoom=function(){var a=this,b=a.config.zoom_enabled?a.zoom:function(){};a.main.select("."+l.zoomRect).call(b).on("dblclick.zoom",null),a.main.selectAll("."+l.eventRect).call(b).on("dblclick.zoom",null)},i.redrawForZoom=function(){var a=this,b=a.d3,c=a.config,d=a.zoom,e=a.x;if(c.zoom_enabled&&0!==a.filterTargetsToShow(a.data.targets).length){if("mousemove"===b.event.sourceEvent.type&&d.altDomain)return e.domain(d.altDomain),void d.scale(e).updateScaleExtent();a.isCategorized()&&e.orgDomain()[0]===a.orgXDomain[0]&&e.domain([a.orgXDomain[0]-1e-10,e.orgDomain()[1]]),a.redraw({withTransition:!1,withY:c.zoom_rescale,withSubchart:!1,withEventRect:!1,withDimension:!1}),"mousemove"===b.event.sourceEvent.type&&(a.cancelClick=!0),c.zoom_onzoom.call(a.api,e.orgDomain())}},i.generateColor=function(){var a=this,b=a.config,c=a.d3,d=b.data_colors,e=v(b.color_pattern)?b.color_pattern:c.scale.category10().range(),f=b.data_color,g=[];return function(a){var b,c=a.id||a.data&&a.data.id||a;return d[c]instanceof Function?b=d[c](a):d[c]?b=d[c]:(g.indexOf(c)<0&&g.push(c),b=e[g.indexOf(c)%e.length],d[c]=b),f instanceof Function?f(b,a):b}},i.generateLevelColor=function(){var a=this,b=a.config,c=b.color_pattern,d=b.color_threshold,e="value"===d.unit,f=d.values&&d.values.length?d.values:[],g=d.max||100;return v(b.color_threshold)?function(a){var b,d,h=c[c.length-1];for(b=0;b<f.length;b++)if(d=e?a:100*a/g,d<f[b]){h=c[b];break}return h}:null},i.getYFormat=function(a){var b=this,c=a&&!b.hasType("gauge")?b.defaultArcValueFormat:b.yFormat,d=a&&!b.hasType("gauge")?b.defaultArcValueFormat:b.y2Format;return function(a,e,f){var g="y2"===b.axis.getId(f)?d:c;return g.call(b,a,e)}},i.yFormat=function(a){var b=this,c=b.config,d=c.axis_y_tick_format?c.axis_y_tick_format:b.defaultValueFormat;return d(a)},i.y2Format=function(a){var b=this,c=b.config,d=c.axis_y2_tick_format?c.axis_y2_tick_format:b.defaultValueFormat;return d(a)},i.defaultValueFormat=function(a){return m(a)?+a:""},i.defaultArcValueFormat=function(a,b){return(100*b).toFixed(1)+"%"},i.dataLabelFormat=function(a){var b,c=this,d=c.config.data_labels,e=function(a){return m(a)?+a:""};return b="function"==typeof d.format?d.format:"object"==typeof d.format?d.format[a]?d.format[a]===!0?e:d.format[a]:function(){return""}:e},i.hasCaches=function(a){for(var b=0;b<a.length;b++)if(!(a[b]in this.cache))return!1;return!0},i.addCache=function(a,b){this.cache[a]=this.cloneTarget(b)},i.getCaches=function(a){var b,c=[];for(b=0;b<a.length;b++)a[b]in this.cache&&c.push(this.cloneTarget(this.cache[a[b]]));return c};var l=i.CLASS={target:"c3-target",chart:"c3-chart",chartLine:"c3-chart-line",chartLines:"c3-chart-lines",chartBar:"c3-chart-bar",chartBars:"c3-chart-bars",chartText:"c3-chart-text",chartTexts:"c3-chart-texts",chartArc:"c3-chart-arc",chartArcs:"c3-chart-arcs",chartArcsTitle:"c3-chart-arcs-title",chartArcsBackground:"c3-chart-arcs-background",chartArcsGaugeUnit:"c3-chart-arcs-gauge-unit",chartArcsGaugeMax:"c3-chart-arcs-gauge-max",chartArcsGaugeMin:"c3-chart-arcs-gauge-min",selectedCircle:"c3-selected-circle",selectedCircles:"c3-selected-circles",eventRect:"c3-event-rect",eventRects:"c3-event-rects",eventRectsSingle:"c3-event-rects-single",eventRectsMultiple:"c3-event-rects-multiple",zoomRect:"c3-zoom-rect",brush:"c3-brush",focused:"c3-focused",defocused:"c3-defocused",region:"c3-region",regions:"c3-regions",title:"c3-title",tooltipContainer:"c3-tooltip-container",tooltip:"c3-tooltip",tooltipName:"c3-tooltip-name",shape:"c3-shape",shapes:"c3-shapes",line:"c3-line",lines:"c3-lines",bar:"c3-bar",bars:"c3-bars",circle:"c3-circle",circles:"c3-circles",arc:"c3-arc",arcs:"c3-arcs",area:"c3-area",areas:"c3-areas",empty:"c3-empty",text:"c3-text",texts:"c3-texts",gaugeValue:"c3-gauge-value",grid:"c3-grid",gridLines:"c3-grid-lines",xgrid:"c3-xgrid",xgrids:"c3-xgrids",xgridLine:"c3-xgrid-line",xgridLines:"c3-xgrid-lines",xgridFocus:"c3-xgrid-focus",ygrid:"c3-ygrid",ygrids:"c3-ygrids",ygridLine:"c3-ygrid-line",ygridLines:"c3-ygrid-lines",axis:"c3-axis",axisX:"c3-axis-x",axisXLabel:"c3-axis-x-label",axisY:"c3-axis-y",axisYLabel:"c3-axis-y-label",axisY2:"c3-axis-y2",axisY2Label:"c3-axis-y2-label",legendBackground:"c3-legend-background",legendItem:"c3-legend-item",legendItemEvent:"c3-legend-item-event",legendItemTile:"c3-legend-item-tile",legendItemHidden:"c3-legend-item-hidden",legendItemFocused:"c3-legend-item-focused",dragarea:"c3-dragarea",EXPANDED:"_expanded_",SELECTED:"_selected_",INCLUDED:"_included_"};i.generateClass=function(a,b){return" "+a+" "+a+this.getTargetSelectorSuffix(b)},i.classText=function(a){return this.generateClass(l.text,a.index)},i.classTexts=function(a){return this.generateClass(l.texts,a.id)},i.classShape=function(a){return this.generateClass(l.shape,a.index)},i.classShapes=function(a){return this.generateClass(l.shapes,a.id)},i.classLine=function(a){return this.classShape(a)+this.generateClass(l.line,a.id)},i.classLines=function(a){return this.classShapes(a)+this.generateClass(l.lines,a.id)},i.classCircle=function(a){return this.classShape(a)+this.generateClass(l.circle,a.index)},i.classCircles=function(a){return this.classShapes(a)+this.generateClass(l.circles,a.id)},i.classBar=function(a){return this.classShape(a)+this.generateClass(l.bar,a.index)},i.classBars=function(a){return this.classShapes(a)+this.generateClass(l.bars,a.id)},i.classArc=function(a){return this.classShape(a.data)+this.generateClass(l.arc,a.data.id)},i.classArcs=function(a){return this.classShapes(a.data)+this.generateClass(l.arcs,a.data.id)},i.classArea=function(a){return this.classShape(a)+this.generateClass(l.area,a.id)},i.classAreas=function(a){return this.classShapes(a)+this.generateClass(l.areas,a.id)},i.classRegion=function(a,b){return this.generateClass(l.region,b)+" "+("class"in a?a["class"]:"")},i.classEvent=function(a){return this.generateClass(l.eventRect,a.index)},i.classTarget=function(a){var b=this,c=b.config.data_classes[a],d="";return c&&(d=" "+l.target+"-"+c),b.generateClass(l.target,a)+d},i.classFocus=function(a){return this.classFocused(a)+this.classDefocused(a)},i.classFocused=function(a){return" "+(this.focusedTargetIds.indexOf(a.id)>=0?l.focused:"")},i.classDefocused=function(a){return" "+(this.defocusedTargetIds.indexOf(a.id)>=0?l.defocused:"")},i.classChartText=function(a){return l.chartText+this.classTarget(a.id)},i.classChartLine=function(a){return l.chartLine+this.classTarget(a.id)},i.classChartBar=function(a){return l.chartBar+this.classTarget(a.id)},i.classChartArc=function(a){return l.chartArc+this.classTarget(a.data.id)},i.getTargetSelectorSuffix=function(a){return a||0===a?("-"+a).replace(/[\s?!@#$%^&*()_=+,.<>'":;\[\]\/|~`{}\\]/g,"-"):""},i.selectorTarget=function(a,b){return(b||"")+"."+l.target+this.getTargetSelectorSuffix(a)},i.selectorTargets=function(a,b){var c=this;return a=a||[],a.length?a.map(function(a){return c.selectorTarget(a,b)}):null},i.selectorLegend=function(a){return"."+l.legendItem+this.getTargetSelectorSuffix(a)},i.selectorLegends=function(a){var b=this;return a&&a.length?a.map(function(a){return b.selectorLegend(a)}):null};var m=i.isValue=function(a){return a||0===a},n=i.isFunction=function(a){return"function"==typeof a},o=i.isString=function(a){return"string"==typeof a},p=i.isUndefined=function(a){return"undefined"==typeof a},q=i.isDefined=function(a){return"undefined"!=typeof a},r=i.ceil10=function(a){return 10*Math.ceil(a/10)},s=i.asHalfPixel=function(a){return Math.ceil(a)+.5},t=i.diffDomain=function(a){return a[1]-a[0]},u=i.isEmpty=function(a){return"undefined"==typeof a||null===a||o(a)&&0===a.length||"object"==typeof a&&0===Object.keys(a).length},v=i.notEmpty=function(a){return!i.isEmpty(a)},w=i.getOption=function(a,b,c){return q(a[b])?a[b]:c},x=i.hasValue=function(a,b){var c=!1;return Object.keys(a).forEach(function(d){a[d]===b&&(c=!0)}),c},y=i.sanitise=function(a){return"string"==typeof a?a.replace(/</g,"<").replace(/>/g,">"):a},z=i.getPathBox=function(a){var b=a.getBoundingClientRect(),c=[a.pathSegList.getItem(0),a.pathSegList.getItem(1)],d=c[0].x,e=Math.min(c[0].y,c[1].y);return{x:d,y:e,width:b.width,height:b.height}};h.focus=function(a){var b,c=this.internal;a=c.mapToTargetIds(a),b=c.svg.selectAll(c.selectorTargets(a.filter(c.isTargetToShow,c))),this.revert(),this.defocus(),b.classed(l.focused,!0).classed(l.defocused,!1),
|
5 |
-
c.hasArcType()&&c.expandArc(a),c.toggleFocusLegend(a,!0),c.focusedTargetIds=a,c.defocusedTargetIds=c.defocusedTargetIds.filter(function(b){return a.indexOf(b)<0})},h.defocus=function(a){var b,c=this.internal;a=c.mapToTargetIds(a),b=c.svg.selectAll(c.selectorTargets(a.filter(c.isTargetToShow,c))),b.classed(l.focused,!1).classed(l.defocused,!0),c.hasArcType()&&c.unexpandArc(a),c.toggleFocusLegend(a,!1),c.focusedTargetIds=c.focusedTargetIds.filter(function(b){return a.indexOf(b)<0}),c.defocusedTargetIds=a},h.revert=function(a){var b,c=this.internal;a=c.mapToTargetIds(a),b=c.svg.selectAll(c.selectorTargets(a)),b.classed(l.focused,!1).classed(l.defocused,!1),c.hasArcType()&&c.unexpandArc(a),c.config.legend_show&&(c.showLegend(a.filter(c.isLegendToShow.bind(c))),c.legend.selectAll(c.selectorLegends(a)).filter(function(){return c.d3.select(this).classed(l.legendItemFocused)}).classed(l.legendItemFocused,!1)),c.focusedTargetIds=[],c.defocusedTargetIds=[]},h.show=function(a,b){var c,d=this.internal;a=d.mapToTargetIds(a),b=b||{},d.removeHiddenTargetIds(a),c=d.svg.selectAll(d.selectorTargets(a)),c.transition().style("opacity",1,"important").call(d.endall,function(){c.style("opacity",null).style("opacity",1)}),b.withLegend&&d.showLegend(a),d.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0,withLegend:!0})},h.hide=function(a,b){var c,d=this.internal;a=d.mapToTargetIds(a),b=b||{},d.addHiddenTargetIds(a),c=d.svg.selectAll(d.selectorTargets(a)),c.transition().style("opacity",0,"important").call(d.endall,function(){c.style("opacity",null).style("opacity",0)}),b.withLegend&&d.hideLegend(a),d.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0,withLegend:!0})},h.toggle=function(a,b){var c=this,d=this.internal;d.mapToTargetIds(a).forEach(function(a){d.isTargetToShow(a)?c.hide(a,b):c.show(a,b)})},h.zoom=function(a){var b=this.internal;return a&&(b.isTimeSeries()&&(a=a.map(function(a){return b.parseDate(a)})),b.brush.extent(a),b.redraw({withUpdateXDomain:!0,withY:b.config.zoom_rescale}),b.config.zoom_onzoom.call(this,b.x.orgDomain())),b.brush.extent()},h.zoom.enable=function(a){var b=this.internal;b.config.zoom_enabled=a,b.updateAndRedraw()},h.unzoom=function(){var a=this.internal;a.brush.clear().update(),a.redraw({withUpdateXDomain:!0})},h.zoom.max=function(a){var b=this.internal,c=b.config,d=b.d3;return 0===a||a?void(c.zoom_x_max=d.max([b.orgXDomain[1],a])):c.zoom_x_max},h.zoom.min=function(a){var b=this.internal,c=b.config,d=b.d3;return 0===a||a?void(c.zoom_x_min=d.min([b.orgXDomain[0],a])):c.zoom_x_min},h.zoom.range=function(a){return arguments.length?(q(a.max)&&this.domain.max(a.max),void(q(a.min)&&this.domain.min(a.min))):{max:this.domain.max(),min:this.domain.min()}},h.load=function(a){var b=this.internal,c=b.config;return a.xs&&b.addXs(a.xs),"names"in a&&h.data.names.bind(this)(a.names),"classes"in a&&Object.keys(a.classes).forEach(function(b){c.data_classes[b]=a.classes[b]}),"categories"in a&&b.isCategorized()&&(c.axis_x_categories=a.categories),"axes"in a&&Object.keys(a.axes).forEach(function(b){c.data_axes[b]=a.axes[b]}),"colors"in a&&Object.keys(a.colors).forEach(function(b){c.data_colors[b]=a.colors[b]}),"cacheIds"in a&&b.hasCaches(a.cacheIds)?void b.load(b.getCaches(a.cacheIds),a.done):void("unload"in a?b.unload(b.mapToTargetIds("boolean"==typeof a.unload&&a.unload?null:a.unload),function(){b.loadFromArgs(a)}):b.loadFromArgs(a))},h.unload=function(a){var b=this.internal;a=a||{},a instanceof Array?a={ids:a}:"string"==typeof a&&(a={ids:[a]}),b.unload(b.mapToTargetIds(a.ids),function(){b.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0,withLegend:!0}),a.done&&a.done()})},h.flow=function(a){var b,c,d,e,f,g,h,i,j=this.internal,k=[],l=j.getMaxDataCount(),n=0,o=0;if(a.json)c=j.convertJsonToData(a.json,a.keys);else if(a.rows)c=j.convertRowsToData(a.rows);else{if(!a.columns)return;c=j.convertColumnsToData(a.columns)}b=j.convertDataToTargets(c,!0),j.data.targets.forEach(function(a){var c,d,e=!1;for(c=0;c<b.length;c++)if(a.id===b[c].id){for(e=!0,a.values[a.values.length-1]&&(o=a.values[a.values.length-1].index+1),n=b[c].values.length,d=0;n>d;d++)b[c].values[d].index=o+d,j.isTimeSeries()||(b[c].values[d].x=o+d);a.values=a.values.concat(b[c].values),b.splice(c,1);break}e||k.push(a.id)}),j.data.targets.forEach(function(a){var b,c;for(b=0;b<k.length;b++)if(a.id===k[b])for(o=a.values[a.values.length-1].index+1,c=0;n>c;c++)a.values.push({id:a.id,index:o+c,x:j.isTimeSeries()?j.getOtherTargetX(o+c):o+c,value:null})}),j.data.targets.length&&b.forEach(function(a){var b,c=[];for(b=j.data.targets[0].values[0].index;o>b;b++)c.push({id:a.id,index:b,x:j.isTimeSeries()?j.getOtherTargetX(b):b,value:null});a.values.forEach(function(a){a.index+=o,j.isTimeSeries()||(a.x+=o)}),a.values=c.concat(a.values)}),j.data.targets=j.data.targets.concat(b),d=j.getMaxDataCount(),f=j.data.targets[0],g=f.values[0],q(a.to)?(n=0,i=j.isTimeSeries()?j.parseDate(a.to):a.to,f.values.forEach(function(a){a.x<i&&n++})):q(a.length)&&(n=a.length),l?1===l&&j.isTimeSeries()&&(h=(f.values[f.values.length-1].x-g.x)/2,e=[new Date(+g.x-h),new Date(+g.x+h)],j.updateXDomain(null,!0,!0,!1,e)):(h=j.isTimeSeries()?f.values.length>1?f.values[f.values.length-1].x-g.x:g.x-j.getXDomain(j.data.targets)[0]:1,e=[g.x-h,g.x],j.updateXDomain(null,!0,!0,!1,e)),j.updateTargets(j.data.targets),j.redraw({flow:{index:g.index,length:n,duration:m(a.duration)?a.duration:j.config.transition_duration,done:a.done,orgDataCount:l},withLegend:!0,withTransition:l>1,withTrimXDomain:!1,withUpdateXAxis:!0})},i.generateFlow=function(a){var b=this,c=b.config,d=b.d3;return function(){var e,f,g,h=a.targets,i=a.flow,j=a.drawBar,k=a.drawLine,m=a.drawArea,n=a.cx,o=a.cy,p=a.xv,q=a.xForText,r=a.yForText,s=a.duration,u=1,v=i.index,w=i.length,x=b.getValueOnIndex(b.data.targets[0].values,v),y=b.getValueOnIndex(b.data.targets[0].values,v+w),z=b.x.domain(),A=i.duration||s,B=i.done||function(){},C=b.generateWait(),D=b.xgrid||d.selectAll([]),E=b.xgridLines||d.selectAll([]),F=b.mainRegion||d.selectAll([]),G=b.mainText||d.selectAll([]),H=b.mainBar||d.selectAll([]),I=b.mainLine||d.selectAll([]),J=b.mainArea||d.selectAll([]),K=b.mainCircle||d.selectAll([]);b.flowing=!0,b.data.targets.forEach(function(a){a.values.splice(0,w)}),g=b.updateXDomain(h,!0,!0),b.updateXGrid&&b.updateXGrid(!0),i.orgDataCount?e=1===i.orgDataCount||(x&&x.x)===(y&&y.x)?b.x(z[0])-b.x(g[0]):b.isTimeSeries()?b.x(z[0])-b.x(g[0]):b.x(x.x)-b.x(y.x):1!==b.data.targets[0].values.length?e=b.x(z[0])-b.x(g[0]):b.isTimeSeries()?(x=b.getValueOnIndex(b.data.targets[0].values,0),y=b.getValueOnIndex(b.data.targets[0].values,b.data.targets[0].values.length-1),e=b.x(x.x)-b.x(y.x)):e=t(g)/2,u=t(z)/t(g),f="translate("+e+",0) scale("+u+",1)",b.hideXGridFocus(),d.transition().ease("linear").duration(A).each(function(){C.add(b.axes.x.transition().call(b.xAxis)),C.add(H.transition().attr("transform",f)),C.add(I.transition().attr("transform",f)),C.add(J.transition().attr("transform",f)),C.add(K.transition().attr("transform",f)),C.add(G.transition().attr("transform",f)),C.add(F.filter(b.isRegionOnX).transition().attr("transform",f)),C.add(D.transition().attr("transform",f)),C.add(E.transition().attr("transform",f))}).call(C,function(){var a,d=[],e=[],f=[];if(w){for(a=0;w>a;a++)d.push("."+l.shape+"-"+(v+a)),e.push("."+l.text+"-"+(v+a)),f.push("."+l.eventRect+"-"+(v+a));b.svg.selectAll("."+l.shapes).selectAll(d).remove(),b.svg.selectAll("."+l.texts).selectAll(e).remove(),b.svg.selectAll("."+l.eventRects).selectAll(f).remove(),b.svg.select("."+l.xgrid).remove()}D.attr("transform",null).attr(b.xgridAttr),E.attr("transform",null),E.select("line").attr("x1",c.axis_rotated?0:p).attr("x2",c.axis_rotated?b.width:p),E.select("text").attr("x",c.axis_rotated?b.width:0).attr("y",p),H.attr("transform",null).attr("d",j),I.attr("transform",null).attr("d",k),J.attr("transform",null).attr("d",m),K.attr("transform",null).attr("cx",n).attr("cy",o),G.attr("transform",null).attr("x",q).attr("y",r).style("fill-opacity",b.opacityForText.bind(b)),F.attr("transform",null),F.select("rect").filter(b.isRegionOnX).attr("x",b.regionX.bind(b)).attr("width",b.regionWidth.bind(b)),c.interaction_enabled&&b.redrawEventRect(),B(),b.flowing=!1})}},h.selected=function(a){var b=this.internal,c=b.d3;return c.merge(b.main.selectAll("."+l.shapes+b.getTargetSelectorSuffix(a)).selectAll("."+l.shape).filter(function(){return c.select(this).classed(l.SELECTED)}).map(function(a){return a.map(function(a){var b=a.__data__;return b.data?b.data:b})}))},h.select=function(a,b,c){var d=this.internal,e=d.d3,f=d.config;f.data_selection_enabled&&d.main.selectAll("."+l.shapes).selectAll("."+l.shape).each(function(g,h){var i=e.select(this),j=g.data?g.data.id:g.id,k=d.getToggle(this,g).bind(d),m=f.data_selection_grouped||!a||a.indexOf(j)>=0,n=!b||b.indexOf(h)>=0,o=i.classed(l.SELECTED);i.classed(l.line)||i.classed(l.area)||(m&&n?f.data_selection_isselectable(g)&&!o&&k(!0,i.classed(l.SELECTED,!0),g,h):q(c)&&c&&o&&k(!1,i.classed(l.SELECTED,!1),g,h))})},h.unselect=function(a,b){var c=this.internal,d=c.d3,e=c.config;e.data_selection_enabled&&c.main.selectAll("."+l.shapes).selectAll("."+l.shape).each(function(f,g){var h=d.select(this),i=f.data?f.data.id:f.id,j=c.getToggle(this,f).bind(c),k=e.data_selection_grouped||!a||a.indexOf(i)>=0,m=!b||b.indexOf(g)>=0,n=h.classed(l.SELECTED);h.classed(l.line)||h.classed(l.area)||k&&m&&e.data_selection_isselectable(f)&&n&&j(!1,h.classed(l.SELECTED,!1),f,g)})},h.transform=function(a,b){var c=this.internal,d=["pie","donut"].indexOf(a)>=0?{withTransform:!0}:null;c.transformTo(b,a,d)},i.transformTo=function(a,b,c){var d=this,e=!d.hasArcType(),f=c||{withTransitionForAxis:e};f.withTransitionForTransform=!1,d.transiting=!1,d.setTargetType(a,b),d.updateTargets(d.data.targets),d.updateAndRedraw(f)},h.groups=function(a){var b=this.internal,c=b.config;return p(a)?c.data_groups:(c.data_groups=a,b.redraw(),c.data_groups)},h.xgrids=function(a){var b=this.internal,c=b.config;return a?(c.grid_x_lines=a,b.redrawWithoutRescale(),c.grid_x_lines):c.grid_x_lines},h.xgrids.add=function(a){var b=this.internal;return this.xgrids(b.config.grid_x_lines.concat(a?a:[]))},h.xgrids.remove=function(a){var b=this.internal;b.removeGridLines(a,!0)},h.ygrids=function(a){var b=this.internal,c=b.config;return a?(c.grid_y_lines=a,b.redrawWithoutRescale(),c.grid_y_lines):c.grid_y_lines},h.ygrids.add=function(a){var b=this.internal;return this.ygrids(b.config.grid_y_lines.concat(a?a:[]))},h.ygrids.remove=function(a){var b=this.internal;b.removeGridLines(a,!1)},h.regions=function(a){var b=this.internal,c=b.config;return a?(c.regions=a,b.redrawWithoutRescale(),c.regions):c.regions},h.regions.add=function(a){var b=this.internal,c=b.config;return a?(c.regions=c.regions.concat(a),b.redrawWithoutRescale(),c.regions):c.regions},h.regions.remove=function(a){var b,c,d,e=this.internal,f=e.config;return a=a||{},b=e.getOption(a,"duration",f.transition_duration),c=e.getOption(a,"classes",[l.region]),d=e.main.select("."+l.regions).selectAll(c.map(function(a){return"."+a})),(b?d.transition().duration(b):d).style("opacity",0).remove(),f.regions=f.regions.filter(function(a){var b=!1;return a["class"]?(a["class"].split(" ").forEach(function(a){c.indexOf(a)>=0&&(b=!0)}),!b):!0}),f.regions},h.data=function(a){var b=this.internal.data.targets;return"undefined"==typeof a?b:b.filter(function(b){return[].concat(a).indexOf(b.id)>=0})},h.data.shown=function(a){return this.internal.filterTargetsToShow(this.data(a))},h.data.values=function(a){var b,c=null;return a&&(b=this.data(a),c=b[0]?b[0].values.map(function(a){return a.value}):null),c},h.data.names=function(a){return this.internal.clearLegendItemTextBoxCache(),this.internal.updateDataAttributes("names",a)},h.data.colors=function(a){return this.internal.updateDataAttributes("colors",a)},h.data.axes=function(a){return this.internal.updateDataAttributes("axes",a)},h.category=function(a,b){var c=this.internal,d=c.config;return arguments.length>1&&(d.axis_x_categories[a]=b,c.redraw()),d.axis_x_categories[a]},h.categories=function(a){var b=this.internal,c=b.config;return arguments.length?(c.axis_x_categories=a,b.redraw(),c.axis_x_categories):c.axis_x_categories},h.color=function(a){var b=this.internal;return b.color(a)},h.x=function(a){var b=this.internal;return arguments.length&&(b.updateTargetX(b.data.targets,a),b.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0})),b.data.xs},h.xs=function(a){var b=this.internal;return arguments.length&&(b.updateTargetXs(b.data.targets,a),b.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0})),b.data.xs},h.axis=function(){},h.axis.labels=function(a){var b=this.internal;arguments.length&&(Object.keys(a).forEach(function(c){b.axis.setLabelText(c,a[c])}),b.axis.updateLabels())},h.axis.max=function(a){var b=this.internal,c=b.config;return arguments.length?("object"==typeof a?(m(a.x)&&(c.axis_x_max=a.x),m(a.y)&&(c.axis_y_max=a.y),m(a.y2)&&(c.axis_y2_max=a.y2)):c.axis_y_max=c.axis_y2_max=a,void b.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0})):{x:c.axis_x_max,y:c.axis_y_max,y2:c.axis_y2_max}},h.axis.min=function(a){var b=this.internal,c=b.config;return arguments.length?("object"==typeof a?(m(a.x)&&(c.axis_x_min=a.x),m(a.y)&&(c.axis_y_min=a.y),m(a.y2)&&(c.axis_y2_min=a.y2)):c.axis_y_min=c.axis_y2_min=a,void b.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0})):{x:c.axis_x_min,y:c.axis_y_min,y2:c.axis_y2_min}},h.axis.range=function(a){return arguments.length?(q(a.max)&&this.axis.max(a.max),void(q(a.min)&&this.axis.min(a.min))):{max:this.axis.max(),min:this.axis.min()}},h.legend=function(){},h.legend.show=function(a){var b=this.internal;b.showLegend(b.mapToTargetIds(a)),b.updateAndRedraw({withLegend:!0})},h.legend.hide=function(a){var b=this.internal;b.hideLegend(b.mapToTargetIds(a)),b.updateAndRedraw({withLegend:!0})},h.resize=function(a){var b=this.internal,c=b.config;c.size_width=a?a.width:null,c.size_height=a?a.height:null,this.flush()},h.flush=function(){var a=this.internal;a.updateAndRedraw({withLegend:!0,withTransition:!1,withTransitionForTransform:!1})},h.destroy=function(){var b=this.internal;if(a.clearInterval(b.intervalForObserveInserted),void 0!==b.resizeTimeout&&a.clearTimeout(b.resizeTimeout),a.detachEvent)a.detachEvent("onresize",b.resizeFunction);else if(a.removeEventListener)a.removeEventListener("resize",b.resizeFunction);else{var c=a.onresize;c&&c.add&&c.remove&&c.remove(b.resizeFunction)}return b.selectChart.classed("c3",!1).html(""),Object.keys(b).forEach(function(a){b[a]=null}),null},h.tooltip=function(){},h.tooltip.show=function(a){var b,c,d=this.internal;a.mouse&&(c=a.mouse),a.data?d.isMultipleX()?(c=[d.x(a.data.x),d.getYScale(a.data.id)(a.data.value)],b=null):b=m(a.data.index)?a.data.index:d.getIndexByX(a.data.x):"undefined"!=typeof a.x?b=d.getIndexByX(a.x):"undefined"!=typeof a.index&&(b=a.index),d.dispatchEvent("mouseover",b,c),d.dispatchEvent("mousemove",b,c),d.config.tooltip_onshow.call(d,a.data)},h.tooltip.hide=function(){this.internal.dispatchEvent("mouseout",0),this.internal.config.tooltip_onhide.call(this)};var A;i.isSafari=function(){var b=a.navigator.userAgent;return b.indexOf("Safari")>=0&&b.indexOf("Chrome")<0},i.isChrome=function(){var b=a.navigator.userAgent;return b.indexOf("Chrome")>=0},Function.prototype.bind||(Function.prototype.bind=function(a){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var b=Array.prototype.slice.call(arguments,1),c=this,d=function(){},e=function(){return c.apply(this instanceof d?this:a,b.concat(Array.prototype.slice.call(arguments)))};return d.prototype=this.prototype,e.prototype=new d,e}),function(){"SVGPathSeg"in a||(a.SVGPathSeg=function(a,b,c){this.pathSegType=a,this.pathSegTypeAsLetter=b,this._owningPathSegList=c},SVGPathSeg.PATHSEG_UNKNOWN=0,SVGPathSeg.PATHSEG_CLOSEPATH=1,SVGPathSeg.PATHSEG_MOVETO_ABS=2,SVGPathSeg.PATHSEG_MOVETO_REL=3,SVGPathSeg.PATHSEG_LINETO_ABS=4,SVGPathSeg.PATHSEG_LINETO_REL=5,SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS=6,SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL=7,SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS=8,SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL=9,SVGPathSeg.PATHSEG_ARC_ABS=10,SVGPathSeg.PATHSEG_ARC_REL=11,SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS=12,SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL=13,SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS=14,SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL=15,SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS=16,SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL=17,SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS=18,SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL=19,SVGPathSeg.prototype._segmentChanged=function(){this._owningPathSegList&&this._owningPathSegList.segmentChanged(this)},a.SVGPathSegClosePath=function(a){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_CLOSEPATH,"z",a)},SVGPathSegClosePath.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegClosePath.prototype.toString=function(){return"[object SVGPathSegClosePath]"},SVGPathSegClosePath.prototype._asPathString=function(){return this.pathSegTypeAsLetter},SVGPathSegClosePath.prototype.clone=function(){return new SVGPathSegClosePath(void 0)},a.SVGPathSegMovetoAbs=function(a,b,c){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_MOVETO_ABS,"M",a),this._x=b,this._y=c},SVGPathSegMovetoAbs.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegMovetoAbs.prototype.toString=function(){return"[object SVGPathSegMovetoAbs]"},SVGPathSegMovetoAbs.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._x+" "+this._y},SVGPathSegMovetoAbs.prototype.clone=function(){return new SVGPathSegMovetoAbs(void 0,this._x,this._y)},Object.defineProperty(SVGPathSegMovetoAbs.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegMovetoAbs.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegMovetoRel=function(a,b,c){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_MOVETO_REL,"m",a),this._x=b,this._y=c},SVGPathSegMovetoRel.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegMovetoRel.prototype.toString=function(){return"[object SVGPathSegMovetoRel]"},SVGPathSegMovetoRel.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._x+" "+this._y},SVGPathSegMovetoRel.prototype.clone=function(){return new SVGPathSegMovetoRel(void 0,this._x,this._y)},Object.defineProperty(SVGPathSegMovetoRel.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegMovetoRel.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegLinetoAbs=function(a,b,c){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_LINETO_ABS,"L",a),this._x=b,this._y=c},SVGPathSegLinetoAbs.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegLinetoAbs.prototype.toString=function(){return"[object SVGPathSegLinetoAbs]"},SVGPathSegLinetoAbs.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._x+" "+this._y},SVGPathSegLinetoAbs.prototype.clone=function(){return new SVGPathSegLinetoAbs(void 0,this._x,this._y)},Object.defineProperty(SVGPathSegLinetoAbs.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegLinetoAbs.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegLinetoRel=function(a,b,c){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_LINETO_REL,"l",a),this._x=b,this._y=c},SVGPathSegLinetoRel.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegLinetoRel.prototype.toString=function(){return"[object SVGPathSegLinetoRel]"},SVGPathSegLinetoRel.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._x+" "+this._y},SVGPathSegLinetoRel.prototype.clone=function(){return new SVGPathSegLinetoRel(void 0,this._x,this._y)},Object.defineProperty(SVGPathSegLinetoRel.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegLinetoRel.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegCurvetoCubicAbs=function(a,b,c,d,e,f,g){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS,"C",a),this._x=b,this._y=c,this._x1=d,this._y1=e,this._x2=f,this._y2=g},SVGPathSegCurvetoCubicAbs.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegCurvetoCubicAbs.prototype.toString=function(){return"[object SVGPathSegCurvetoCubicAbs]"},SVGPathSegCurvetoCubicAbs.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._x1+" "+this._y1+" "+this._x2+" "+this._y2+" "+this._x+" "+this._y},SVGPathSegCurvetoCubicAbs.prototype.clone=function(){return new SVGPathSegCurvetoCubicAbs(void 0,this._x,this._y,this._x1,this._y1,this._x2,this._y2)},Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype,"x1",{get:function(){return this._x1},set:function(a){this._x1=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype,"y1",{get:function(){return this._y1},set:function(a){this._y1=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype,"x2",{get:function(){return this._x2},set:function(a){this._x2=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype,"y2",{get:function(){return this._y2},set:function(a){this._y2=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegCurvetoCubicRel=function(a,b,c,d,e,f,g){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL,"c",a),this._x=b,this._y=c,this._x1=d,this._y1=e,this._x2=f,this._y2=g},SVGPathSegCurvetoCubicRel.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegCurvetoCubicRel.prototype.toString=function(){return"[object SVGPathSegCurvetoCubicRel]"},SVGPathSegCurvetoCubicRel.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._x1+" "+this._y1+" "+this._x2+" "+this._y2+" "+this._x+" "+this._y},SVGPathSegCurvetoCubicRel.prototype.clone=function(){return new SVGPathSegCurvetoCubicRel(void 0,this._x,this._y,this._x1,this._y1,this._x2,this._y2)},Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype,"x1",{get:function(){return this._x1},set:function(a){this._x1=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype,"y1",{get:function(){return this._y1},set:function(a){this._y1=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype,"x2",{get:function(){return this._x2},set:function(a){this._x2=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype,"y2",{get:function(){return this._y2},set:function(a){this._y2=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegCurvetoQuadraticAbs=function(a,b,c,d,e){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS,"Q",a),this._x=b,this._y=c,this._x1=d,this._y1=e},SVGPathSegCurvetoQuadraticAbs.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegCurvetoQuadraticAbs.prototype.toString=function(){return"[object SVGPathSegCurvetoQuadraticAbs]"},SVGPathSegCurvetoQuadraticAbs.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._x1+" "+this._y1+" "+this._x+" "+this._y},SVGPathSegCurvetoQuadraticAbs.prototype.clone=function(){return new SVGPathSegCurvetoQuadraticAbs(void 0,this._x,this._y,this._x1,this._y1)},Object.defineProperty(SVGPathSegCurvetoQuadraticAbs.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoQuadraticAbs.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoQuadraticAbs.prototype,"x1",{get:function(){return this._x1},set:function(a){this._x1=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoQuadraticAbs.prototype,"y1",{get:function(){return this._y1},set:function(a){this._y1=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegCurvetoQuadraticRel=function(a,b,c,d,e){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL,"q",a),this._x=b,this._y=c,this._x1=d,this._y1=e},SVGPathSegCurvetoQuadraticRel.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegCurvetoQuadraticRel.prototype.toString=function(){return"[object SVGPathSegCurvetoQuadraticRel]"},SVGPathSegCurvetoQuadraticRel.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._x1+" "+this._y1+" "+this._x+" "+this._y},SVGPathSegCurvetoQuadraticRel.prototype.clone=function(){return new SVGPathSegCurvetoQuadraticRel(void 0,this._x,this._y,this._x1,this._y1)},Object.defineProperty(SVGPathSegCurvetoQuadraticRel.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoQuadraticRel.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoQuadraticRel.prototype,"x1",{get:function(){return this._x1},set:function(a){this._x1=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoQuadraticRel.prototype,"y1",{get:function(){return this._y1},set:function(a){this._y1=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegArcAbs=function(a,b,c,d,e,f,g,h){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_ARC_ABS,"A",a),this._x=b,this._y=c,this._r1=d,this._r2=e,this._angle=f,this._largeArcFlag=g,this._sweepFlag=h},SVGPathSegArcAbs.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegArcAbs.prototype.toString=function(){return"[object SVGPathSegArcAbs]"},SVGPathSegArcAbs.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._r1+" "+this._r2+" "+this._angle+" "+(this._largeArcFlag?"1":"0")+" "+(this._sweepFlag?"1":"0")+" "+this._x+" "+this._y},SVGPathSegArcAbs.prototype.clone=function(){return new SVGPathSegArcAbs(void 0,this._x,this._y,this._r1,this._r2,this._angle,this._largeArcFlag,this._sweepFlag)},Object.defineProperty(SVGPathSegArcAbs.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegArcAbs.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegArcAbs.prototype,"r1",{get:function(){return this._r1},set:function(a){this._r1=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegArcAbs.prototype,"r2",{get:function(){return this._r2},set:function(a){this._r2=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegArcAbs.prototype,"angle",{get:function(){return this._angle},set:function(a){this._angle=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegArcAbs.prototype,"largeArcFlag",{get:function(){return this._largeArcFlag},set:function(a){this._largeArcFlag=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegArcAbs.prototype,"sweepFlag",{get:function(){return this._sweepFlag},set:function(a){this._sweepFlag=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegArcRel=function(a,b,c,d,e,f,g,h){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_ARC_REL,"a",a),this._x=b,this._y=c,this._r1=d,this._r2=e,this._angle=f,this._largeArcFlag=g,this._sweepFlag=h},SVGPathSegArcRel.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegArcRel.prototype.toString=function(){return"[object SVGPathSegArcRel]"},SVGPathSegArcRel.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._r1+" "+this._r2+" "+this._angle+" "+(this._largeArcFlag?"1":"0")+" "+(this._sweepFlag?"1":"0")+" "+this._x+" "+this._y},SVGPathSegArcRel.prototype.clone=function(){return new SVGPathSegArcRel(void 0,this._x,this._y,this._r1,this._r2,this._angle,this._largeArcFlag,this._sweepFlag)},Object.defineProperty(SVGPathSegArcRel.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegArcRel.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegArcRel.prototype,"r1",{get:function(){return this._r1},set:function(a){this._r1=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegArcRel.prototype,"r2",{get:function(){return this._r2},set:function(a){this._r2=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegArcRel.prototype,"angle",{get:function(){return this._angle},set:function(a){this._angle=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegArcRel.prototype,"largeArcFlag",{get:function(){return this._largeArcFlag},set:function(a){this._largeArcFlag=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegArcRel.prototype,"sweepFlag",{get:function(){return this._sweepFlag},set:function(a){this._sweepFlag=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegLinetoHorizontalAbs=function(a,b){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS,"H",a),this._x=b},SVGPathSegLinetoHorizontalAbs.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegLinetoHorizontalAbs.prototype.toString=function(){return"[object SVGPathSegLinetoHorizontalAbs]"},SVGPathSegLinetoHorizontalAbs.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._x},SVGPathSegLinetoHorizontalAbs.prototype.clone=function(){return new SVGPathSegLinetoHorizontalAbs(void 0,this._x)},Object.defineProperty(SVGPathSegLinetoHorizontalAbs.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegLinetoHorizontalRel=function(a,b){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL,"h",a),this._x=b},SVGPathSegLinetoHorizontalRel.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegLinetoHorizontalRel.prototype.toString=function(){return"[object SVGPathSegLinetoHorizontalRel]"},SVGPathSegLinetoHorizontalRel.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._x},SVGPathSegLinetoHorizontalRel.prototype.clone=function(){return new SVGPathSegLinetoHorizontalRel(void 0,this._x)},Object.defineProperty(SVGPathSegLinetoHorizontalRel.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegLinetoVerticalAbs=function(a,b){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS,"V",a),this._y=b},SVGPathSegLinetoVerticalAbs.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegLinetoVerticalAbs.prototype.toString=function(){return"[object SVGPathSegLinetoVerticalAbs]"},SVGPathSegLinetoVerticalAbs.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._y},SVGPathSegLinetoVerticalAbs.prototype.clone=function(){return new SVGPathSegLinetoVerticalAbs(void 0,this._y)},Object.defineProperty(SVGPathSegLinetoVerticalAbs.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegLinetoVerticalRel=function(a,b){
|
6 |
-
SVGPathSeg.call(this,SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL,"v",a),this._y=b},SVGPathSegLinetoVerticalRel.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegLinetoVerticalRel.prototype.toString=function(){return"[object SVGPathSegLinetoVerticalRel]"},SVGPathSegLinetoVerticalRel.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._y},SVGPathSegLinetoVerticalRel.prototype.clone=function(){return new SVGPathSegLinetoVerticalRel(void 0,this._y)},Object.defineProperty(SVGPathSegLinetoVerticalRel.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegCurvetoCubicSmoothAbs=function(a,b,c,d,e){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS,"S",a),this._x=b,this._y=c,this._x2=d,this._y2=e},SVGPathSegCurvetoCubicSmoothAbs.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegCurvetoCubicSmoothAbs.prototype.toString=function(){return"[object SVGPathSegCurvetoCubicSmoothAbs]"},SVGPathSegCurvetoCubicSmoothAbs.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._x2+" "+this._y2+" "+this._x+" "+this._y},SVGPathSegCurvetoCubicSmoothAbs.prototype.clone=function(){return new SVGPathSegCurvetoCubicSmoothAbs(void 0,this._x,this._y,this._x2,this._y2)},Object.defineProperty(SVGPathSegCurvetoCubicSmoothAbs.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicSmoothAbs.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicSmoothAbs.prototype,"x2",{get:function(){return this._x2},set:function(a){this._x2=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicSmoothAbs.prototype,"y2",{get:function(){return this._y2},set:function(a){this._y2=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegCurvetoCubicSmoothRel=function(a,b,c,d,e){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL,"s",a),this._x=b,this._y=c,this._x2=d,this._y2=e},SVGPathSegCurvetoCubicSmoothRel.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegCurvetoCubicSmoothRel.prototype.toString=function(){return"[object SVGPathSegCurvetoCubicSmoothRel]"},SVGPathSegCurvetoCubicSmoothRel.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._x2+" "+this._y2+" "+this._x+" "+this._y},SVGPathSegCurvetoCubicSmoothRel.prototype.clone=function(){return new SVGPathSegCurvetoCubicSmoothRel(void 0,this._x,this._y,this._x2,this._y2)},Object.defineProperty(SVGPathSegCurvetoCubicSmoothRel.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicSmoothRel.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicSmoothRel.prototype,"x2",{get:function(){return this._x2},set:function(a){this._x2=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoCubicSmoothRel.prototype,"y2",{get:function(){return this._y2},set:function(a){this._y2=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegCurvetoQuadraticSmoothAbs=function(a,b,c){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS,"T",a),this._x=b,this._y=c},SVGPathSegCurvetoQuadraticSmoothAbs.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegCurvetoQuadraticSmoothAbs.prototype.toString=function(){return"[object SVGPathSegCurvetoQuadraticSmoothAbs]"},SVGPathSegCurvetoQuadraticSmoothAbs.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._x+" "+this._y},SVGPathSegCurvetoQuadraticSmoothAbs.prototype.clone=function(){return new SVGPathSegCurvetoQuadraticSmoothAbs(void 0,this._x,this._y)},Object.defineProperty(SVGPathSegCurvetoQuadraticSmoothAbs.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoQuadraticSmoothAbs.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),a.SVGPathSegCurvetoQuadraticSmoothRel=function(a,b,c){SVGPathSeg.call(this,SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL,"t",a),this._x=b,this._y=c},SVGPathSegCurvetoQuadraticSmoothRel.prototype=Object.create(SVGPathSeg.prototype),SVGPathSegCurvetoQuadraticSmoothRel.prototype.toString=function(){return"[object SVGPathSegCurvetoQuadraticSmoothRel]"},SVGPathSegCurvetoQuadraticSmoothRel.prototype._asPathString=function(){return this.pathSegTypeAsLetter+" "+this._x+" "+this._y},SVGPathSegCurvetoQuadraticSmoothRel.prototype.clone=function(){return new SVGPathSegCurvetoQuadraticSmoothRel(void 0,this._x,this._y)},Object.defineProperty(SVGPathSegCurvetoQuadraticSmoothRel.prototype,"x",{get:function(){return this._x},set:function(a){this._x=a,this._segmentChanged()},enumerable:!0}),Object.defineProperty(SVGPathSegCurvetoQuadraticSmoothRel.prototype,"y",{get:function(){return this._y},set:function(a){this._y=a,this._segmentChanged()},enumerable:!0}),SVGPathElement.prototype.createSVGPathSegClosePath=function(){return new SVGPathSegClosePath(void 0)},SVGPathElement.prototype.createSVGPathSegMovetoAbs=function(a,b){return new SVGPathSegMovetoAbs(void 0,a,b)},SVGPathElement.prototype.createSVGPathSegMovetoRel=function(a,b){return new SVGPathSegMovetoRel(void 0,a,b)},SVGPathElement.prototype.createSVGPathSegLinetoAbs=function(a,b){return new SVGPathSegLinetoAbs(void 0,a,b)},SVGPathElement.prototype.createSVGPathSegLinetoRel=function(a,b){return new SVGPathSegLinetoRel(void 0,a,b)},SVGPathElement.prototype.createSVGPathSegCurvetoCubicAbs=function(a,b,c,d,e,f){return new SVGPathSegCurvetoCubicAbs(void 0,a,b,c,d,e,f)},SVGPathElement.prototype.createSVGPathSegCurvetoCubicRel=function(a,b,c,d,e,f){return new SVGPathSegCurvetoCubicRel(void 0,a,b,c,d,e,f)},SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticAbs=function(a,b,c,d){return new SVGPathSegCurvetoQuadraticAbs(void 0,a,b,c,d)},SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticRel=function(a,b,c,d){return new SVGPathSegCurvetoQuadraticRel(void 0,a,b,c,d)},SVGPathElement.prototype.createSVGPathSegArcAbs=function(a,b,c,d,e,f,g){return new SVGPathSegArcAbs(void 0,a,b,c,d,e,f,g)},SVGPathElement.prototype.createSVGPathSegArcRel=function(a,b,c,d,e,f,g){return new SVGPathSegArcRel(void 0,a,b,c,d,e,f,g)},SVGPathElement.prototype.createSVGPathSegLinetoHorizontalAbs=function(a){return new SVGPathSegLinetoHorizontalAbs(void 0,a)},SVGPathElement.prototype.createSVGPathSegLinetoHorizontalRel=function(a){return new SVGPathSegLinetoHorizontalRel(void 0,a)},SVGPathElement.prototype.createSVGPathSegLinetoVerticalAbs=function(a){return new SVGPathSegLinetoVerticalAbs(void 0,a)},SVGPathElement.prototype.createSVGPathSegLinetoVerticalRel=function(a){return new SVGPathSegLinetoVerticalRel(void 0,a)},SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothAbs=function(a,b,c,d){return new SVGPathSegCurvetoCubicSmoothAbs(void 0,a,b,c,d)},SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothRel=function(a,b,c,d){return new SVGPathSegCurvetoCubicSmoothRel(void 0,a,b,c,d)},SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothAbs=function(a,b){return new SVGPathSegCurvetoQuadraticSmoothAbs(void 0,a,b)},SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothRel=function(a,b){return new SVGPathSegCurvetoQuadraticSmoothRel(void 0,a,b)}),"SVGPathSegList"in a||(a.SVGPathSegList=function(a){this._pathElement=a,this._list=this._parsePath(this._pathElement.getAttribute("d")),this._mutationObserverConfig={attributes:!0,attributeFilter:["d"]},this._pathElementMutationObserver=new MutationObserver(this._updateListFromPathMutations.bind(this)),this._pathElementMutationObserver.observe(this._pathElement,this._mutationObserverConfig)},Object.defineProperty(SVGPathSegList.prototype,"numberOfItems",{get:function(){return this._checkPathSynchronizedToList(),this._list.length},enumerable:!0}),Object.defineProperty(SVGPathElement.prototype,"pathSegList",{get:function(){return this._pathSegList||(this._pathSegList=new SVGPathSegList(this)),this._pathSegList},enumerable:!0}),Object.defineProperty(SVGPathElement.prototype,"normalizedPathSegList",{get:function(){return this.pathSegList},enumerable:!0}),Object.defineProperty(SVGPathElement.prototype,"animatedPathSegList",{get:function(){return this.pathSegList},enumerable:!0}),Object.defineProperty(SVGPathElement.prototype,"animatedNormalizedPathSegList",{get:function(){return this.pathSegList},enumerable:!0}),SVGPathSegList.prototype._checkPathSynchronizedToList=function(){this._updateListFromPathMutations(this._pathElementMutationObserver.takeRecords())},SVGPathSegList.prototype._updateListFromPathMutations=function(a){if(this._pathElement){var b=!1;a.forEach(function(a){"d"==a.attributeName&&(b=!0)}),b&&(this._list=this._parsePath(this._pathElement.getAttribute("d")))}},SVGPathSegList.prototype._writeListToPath=function(){this._pathElementMutationObserver.disconnect(),this._pathElement.setAttribute("d",SVGPathSegList._pathSegArrayAsString(this._list)),this._pathElementMutationObserver.observe(this._pathElement,this._mutationObserverConfig)},SVGPathSegList.prototype.segmentChanged=function(a){this._writeListToPath()},SVGPathSegList.prototype.clear=function(){this._checkPathSynchronizedToList(),this._list.forEach(function(a){a._owningPathSegList=null}),this._list=[],this._writeListToPath()},SVGPathSegList.prototype.initialize=function(a){return this._checkPathSynchronizedToList(),this._list=[a],a._owningPathSegList=this,this._writeListToPath(),a},SVGPathSegList.prototype._checkValidIndex=function(a){if(isNaN(a)||0>a||a>=this.numberOfItems)throw"INDEX_SIZE_ERR"},SVGPathSegList.prototype.getItem=function(a){return this._checkPathSynchronizedToList(),this._checkValidIndex(a),this._list[a]},SVGPathSegList.prototype.insertItemBefore=function(a,b){return this._checkPathSynchronizedToList(),b>this.numberOfItems&&(b=this.numberOfItems),a._owningPathSegList&&(a=a.clone()),this._list.splice(b,0,a),a._owningPathSegList=this,this._writeListToPath(),a},SVGPathSegList.prototype.replaceItem=function(a,b){return this._checkPathSynchronizedToList(),a._owningPathSegList&&(a=a.clone()),this._checkValidIndex(b),this._list[b]=a,a._owningPathSegList=this,this._writeListToPath(),a},SVGPathSegList.prototype.removeItem=function(a){this._checkPathSynchronizedToList(),this._checkValidIndex(a);var b=this._list[a];return this._list.splice(a,1),this._writeListToPath(),b},SVGPathSegList.prototype.appendItem=function(a){return this._checkPathSynchronizedToList(),a._owningPathSegList&&(a=a.clone()),this._list.push(a),a._owningPathSegList=this,this._writeListToPath(),a},SVGPathSegList._pathSegArrayAsString=function(a){var b="",c=!0;return a.forEach(function(a){c?(c=!1,b+=a._asPathString()):b+=" "+a._asPathString()}),b},SVGPathSegList.prototype._parsePath=function(a){if(!a||0==a.length)return[];var b=this,c=function(){this.pathSegList=[]};c.prototype.appendSegment=function(a){this.pathSegList.push(a)};var d=function(a){this._string=a,this._currentIndex=0,this._endIndex=this._string.length,this._previousCommand=SVGPathSeg.PATHSEG_UNKNOWN,this._skipOptionalSpaces()};d.prototype._isCurrentSpace=function(){var a=this._string[this._currentIndex];return" ">=a&&(" "==a||"\n"==a||" "==a||"\r"==a||"\f"==a)},d.prototype._skipOptionalSpaces=function(){for(;this._currentIndex<this._endIndex&&this._isCurrentSpace();)this._currentIndex++;return this._currentIndex<this._endIndex},d.prototype._skipOptionalSpacesOrDelimiter=function(){return this._currentIndex<this._endIndex&&!this._isCurrentSpace()&&","!=this._string.charAt(this._currentIndex)?!1:(this._skipOptionalSpaces()&&this._currentIndex<this._endIndex&&","==this._string.charAt(this._currentIndex)&&(this._currentIndex++,this._skipOptionalSpaces()),this._currentIndex<this._endIndex)},d.prototype.hasMoreData=function(){return this._currentIndex<this._endIndex},d.prototype.peekSegmentType=function(){var a=this._string[this._currentIndex];return this._pathSegTypeFromChar(a)},d.prototype._pathSegTypeFromChar=function(a){switch(a){case"Z":case"z":return SVGPathSeg.PATHSEG_CLOSEPATH;case"M":return SVGPathSeg.PATHSEG_MOVETO_ABS;case"m":return SVGPathSeg.PATHSEG_MOVETO_REL;case"L":return SVGPathSeg.PATHSEG_LINETO_ABS;case"l":return SVGPathSeg.PATHSEG_LINETO_REL;case"C":return SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS;case"c":return SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL;case"Q":return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS;case"q":return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL;case"A":return SVGPathSeg.PATHSEG_ARC_ABS;case"a":return SVGPathSeg.PATHSEG_ARC_REL;case"H":return SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS;case"h":return SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL;case"V":return SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS;case"v":return SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL;case"S":return SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS;case"s":return SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL;case"T":return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS;case"t":return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL;default:return SVGPathSeg.PATHSEG_UNKNOWN}},d.prototype._nextCommandHelper=function(a,b){return("+"==a||"-"==a||"."==a||a>="0"&&"9">=a)&&b!=SVGPathSeg.PATHSEG_CLOSEPATH?b==SVGPathSeg.PATHSEG_MOVETO_ABS?SVGPathSeg.PATHSEG_LINETO_ABS:b==SVGPathSeg.PATHSEG_MOVETO_REL?SVGPathSeg.PATHSEG_LINETO_REL:b:SVGPathSeg.PATHSEG_UNKNOWN},d.prototype.initialCommandIsMoveTo=function(){if(!this.hasMoreData())return!0;var a=this.peekSegmentType();return a==SVGPathSeg.PATHSEG_MOVETO_ABS||a==SVGPathSeg.PATHSEG_MOVETO_REL},d.prototype._parseNumber=function(){var a=0,b=0,c=1,d=0,e=1,f=1,g=this._currentIndex;if(this._skipOptionalSpaces(),this._currentIndex<this._endIndex&&"+"==this._string.charAt(this._currentIndex)?this._currentIndex++:this._currentIndex<this._endIndex&&"-"==this._string.charAt(this._currentIndex)&&(this._currentIndex++,e=-1),!(this._currentIndex==this._endIndex||(this._string.charAt(this._currentIndex)<"0"||this._string.charAt(this._currentIndex)>"9")&&"."!=this._string.charAt(this._currentIndex))){for(var h=this._currentIndex;this._currentIndex<this._endIndex&&this._string.charAt(this._currentIndex)>="0"&&this._string.charAt(this._currentIndex)<="9";)this._currentIndex++;if(this._currentIndex!=h)for(var i=this._currentIndex-1,j=1;i>=h;)b+=j*(this._string.charAt(i--)-"0"),j*=10;if(this._currentIndex<this._endIndex&&"."==this._string.charAt(this._currentIndex)){if(this._currentIndex++,this._currentIndex>=this._endIndex||this._string.charAt(this._currentIndex)<"0"||this._string.charAt(this._currentIndex)>"9")return;for(;this._currentIndex<this._endIndex&&this._string.charAt(this._currentIndex)>="0"&&this._string.charAt(this._currentIndex)<="9";)d+=(this._string.charAt(this._currentIndex++)-"0")*(c*=.1)}if(this._currentIndex!=g&&this._currentIndex+1<this._endIndex&&("e"==this._string.charAt(this._currentIndex)||"E"==this._string.charAt(this._currentIndex))&&"x"!=this._string.charAt(this._currentIndex+1)&&"m"!=this._string.charAt(this._currentIndex+1)){if(this._currentIndex++,"+"==this._string.charAt(this._currentIndex)?this._currentIndex++:"-"==this._string.charAt(this._currentIndex)&&(this._currentIndex++,f=-1),this._currentIndex>=this._endIndex||this._string.charAt(this._currentIndex)<"0"||this._string.charAt(this._currentIndex)>"9")return;for(;this._currentIndex<this._endIndex&&this._string.charAt(this._currentIndex)>="0"&&this._string.charAt(this._currentIndex)<="9";)a*=10,a+=this._string.charAt(this._currentIndex)-"0",this._currentIndex++}var k=b+d;if(k*=e,a&&(k*=Math.pow(10,f*a)),g!=this._currentIndex)return this._skipOptionalSpacesOrDelimiter(),k}},d.prototype._parseArcFlag=function(){if(!(this._currentIndex>=this._endIndex)){var a=!1,b=this._string.charAt(this._currentIndex++);if("0"==b)a=!1;else{if("1"!=b)return;a=!0}return this._skipOptionalSpacesOrDelimiter(),a}},d.prototype.parseSegment=function(){var a=this._string[this._currentIndex],c=this._pathSegTypeFromChar(a);if(c==SVGPathSeg.PATHSEG_UNKNOWN){if(this._previousCommand==SVGPathSeg.PATHSEG_UNKNOWN)return null;if(c=this._nextCommandHelper(a,this._previousCommand),c==SVGPathSeg.PATHSEG_UNKNOWN)return null}else this._currentIndex++;switch(this._previousCommand=c,c){case SVGPathSeg.PATHSEG_MOVETO_REL:return new SVGPathSegMovetoRel(b,this._parseNumber(),this._parseNumber());case SVGPathSeg.PATHSEG_MOVETO_ABS:return new SVGPathSegMovetoAbs(b,this._parseNumber(),this._parseNumber());case SVGPathSeg.PATHSEG_LINETO_REL:return new SVGPathSegLinetoRel(b,this._parseNumber(),this._parseNumber());case SVGPathSeg.PATHSEG_LINETO_ABS:return new SVGPathSegLinetoAbs(b,this._parseNumber(),this._parseNumber());case SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL:return new SVGPathSegLinetoHorizontalRel(b,this._parseNumber());case SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS:return new SVGPathSegLinetoHorizontalAbs(b,this._parseNumber());case SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL:return new SVGPathSegLinetoVerticalRel(b,this._parseNumber());case SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS:return new SVGPathSegLinetoVerticalAbs(b,this._parseNumber());case SVGPathSeg.PATHSEG_CLOSEPATH:return this._skipOptionalSpaces(),new SVGPathSegClosePath(b);case SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL:var d={x1:this._parseNumber(),y1:this._parseNumber(),x2:this._parseNumber(),y2:this._parseNumber(),x:this._parseNumber(),y:this._parseNumber()};return new SVGPathSegCurvetoCubicRel(b,d.x,d.y,d.x1,d.y1,d.x2,d.y2);case SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS:var d={x1:this._parseNumber(),y1:this._parseNumber(),x2:this._parseNumber(),y2:this._parseNumber(),x:this._parseNumber(),y:this._parseNumber()};return new SVGPathSegCurvetoCubicAbs(b,d.x,d.y,d.x1,d.y1,d.x2,d.y2);case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL:var d={x2:this._parseNumber(),y2:this._parseNumber(),x:this._parseNumber(),y:this._parseNumber()};return new SVGPathSegCurvetoCubicSmoothRel(b,d.x,d.y,d.x2,d.y2);case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:var d={x2:this._parseNumber(),y2:this._parseNumber(),x:this._parseNumber(),y:this._parseNumber()};return new SVGPathSegCurvetoCubicSmoothAbs(b,d.x,d.y,d.x2,d.y2);case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL:var d={x1:this._parseNumber(),y1:this._parseNumber(),x:this._parseNumber(),y:this._parseNumber()};return new SVGPathSegCurvetoQuadraticRel(b,d.x,d.y,d.x1,d.y1);case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS:var d={x1:this._parseNumber(),y1:this._parseNumber(),x:this._parseNumber(),y:this._parseNumber()};return new SVGPathSegCurvetoQuadraticAbs(b,d.x,d.y,d.x1,d.y1);case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:return new SVGPathSegCurvetoQuadraticSmoothRel(b,this._parseNumber(),this._parseNumber());case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:return new SVGPathSegCurvetoQuadraticSmoothAbs(b,this._parseNumber(),this._parseNumber());case SVGPathSeg.PATHSEG_ARC_REL:var d={x1:this._parseNumber(),y1:this._parseNumber(),arcAngle:this._parseNumber(),arcLarge:this._parseArcFlag(),arcSweep:this._parseArcFlag(),x:this._parseNumber(),y:this._parseNumber()};return new SVGPathSegArcRel(b,d.x,d.y,d.x1,d.y1,d.arcAngle,d.arcLarge,d.arcSweep);case SVGPathSeg.PATHSEG_ARC_ABS:var d={x1:this._parseNumber(),y1:this._parseNumber(),arcAngle:this._parseNumber(),arcLarge:this._parseArcFlag(),arcSweep:this._parseArcFlag(),x:this._parseNumber(),y:this._parseNumber()};return new SVGPathSegArcAbs(b,d.x,d.y,d.x1,d.y1,d.arcAngle,d.arcLarge,d.arcSweep);default:throw"Unknown path seg type."}};var e=new c,f=new d(a);if(!f.initialCommandIsMoveTo())return[];for(;f.hasMoreData();){var g=f.parseSegment();if(!g)return[];e.appendSegment(g)}return e.pathSegList})}(),"function"==typeof define&&define.amd?define("c3",["d3"],function(){return k}):"undefined"!=typeof exports&&"undefined"!=typeof module?module.exports=k:a.c3=k}(window);
|
|
|
|
|
|
|
|
|
|
|
|
inc/js/d3.min.js
DELETED
@@ -1,5 +0,0 @@
|
|
1 |
-
!function(){function n(n){return n&&(n.ownerDocument||n.document||n).documentElement}function t(n){return n&&(n.ownerDocument&&n.ownerDocument.defaultView||n.document&&n||n.defaultView)}function e(n,t){return t>n?-1:n>t?1:n>=t?0:NaN}function r(n){return null===n?NaN:+n}function i(n){return!isNaN(n)}function u(n){return{left:function(t,e,r,i){for(arguments.length<3&&(r=0),arguments.length<4&&(i=t.length);i>r;){var u=r+i>>>1;n(t[u],e)<0?r=u+1:i=u}return r},right:function(t,e,r,i){for(arguments.length<3&&(r=0),arguments.length<4&&(i=t.length);i>r;){var u=r+i>>>1;n(t[u],e)>0?i=u:r=u+1}return r}}}function o(n){return n.length}function a(n){for(var t=1;n*t%1;)t*=10;return t}function l(n,t){for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}function c(){this._=Object.create(null)}function f(n){return(n+="")===bo||n[0]===_o?_o+n:n}function s(n){return(n+="")[0]===_o?n.slice(1):n}function h(n){return f(n)in this._}function p(n){return(n=f(n))in this._&&delete this._[n]}function g(){var n=[];for(var t in this._)n.push(s(t));return n}function v(){var n=0;for(var t in this._)++n;return n}function d(){for(var n in this._)return!1;return!0}function y(){this._=Object.create(null)}function m(n){return n}function M(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function x(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.slice(1);for(var e=0,r=wo.length;r>e;++e){var i=wo[e]+t;if(i in n)return i}}function b(){}function _(){}function w(n){function t(){for(var t,r=e,i=-1,u=r.length;++i<u;)(t=r[i].on)&&t.apply(this,arguments);return n}var e=[],r=new c;return t.on=function(t,i){var u,o=r.get(t);return arguments.length<2?o&&o.on:(o&&(o.on=null,e=e.slice(0,u=e.indexOf(o)).concat(e.slice(u+1)),r.remove(t)),i&&e.push(r.set(t,{on:i})),n)},t}function S(){ao.event.preventDefault()}function k(){for(var n,t=ao.event;n=t.sourceEvent;)t=n;return t}function N(n){for(var t=new _,e=0,r=arguments.length;++e<r;)t[arguments[e]]=w(t);return t.of=function(e,r){return function(i){try{var u=i.sourceEvent=ao.event;i.target=n,ao.event=i,t[i.type].apply(e,r)}finally{ao.event=u}}},t}function E(n){return ko(n,Co),n}function A(n){return"function"==typeof n?n:function(){return No(n,this)}}function C(n){return"function"==typeof n?n:function(){return Eo(n,this)}}function z(n,t){function e(){this.removeAttribute(n)}function r(){this.removeAttributeNS(n.space,n.local)}function i(){this.setAttribute(n,t)}function u(){this.setAttributeNS(n.space,n.local,t)}function o(){var e=t.apply(this,arguments);null==e?this.removeAttribute(n):this.setAttribute(n,e)}function a(){var e=t.apply(this,arguments);null==e?this.removeAttributeNS(n.space,n.local):this.setAttributeNS(n.space,n.local,e)}return n=ao.ns.qualify(n),null==t?n.local?r:e:"function"==typeof t?n.local?a:o:n.local?u:i}function L(n){return n.trim().replace(/\s+/g," ")}function q(n){return new RegExp("(?:^|\\s+)"+ao.requote(n)+"(?:\\s+|$)","g")}function T(n){return(n+"").trim().split(/^|\s+/)}function R(n,t){function e(){for(var e=-1;++e<i;)n[e](this,t)}function r(){for(var e=-1,r=t.apply(this,arguments);++e<i;)n[e](this,r)}n=T(n).map(D);var i=n.length;return"function"==typeof t?r:e}function D(n){var t=q(n);return function(e,r){if(i=e.classList)return r?i.add(n):i.remove(n);var i=e.getAttribute("class")||"";r?(t.lastIndex=0,t.test(i)||e.setAttribute("class",L(i+" "+n))):e.setAttribute("class",L(i.replace(t," ")))}}function P(n,t,e){function r(){this.style.removeProperty(n)}function i(){this.style.setProperty(n,t,e)}function u(){var r=t.apply(this,arguments);null==r?this.style.removeProperty(n):this.style.setProperty(n,r,e)}return null==t?r:"function"==typeof t?u:i}function U(n,t){function e(){delete this[n]}function r(){this[n]=t}function i(){var e=t.apply(this,arguments);null==e?delete this[n]:this[n]=e}return null==t?e:"function"==typeof t?i:r}function j(n){function t(){var t=this.ownerDocument,e=this.namespaceURI;return e===zo&&t.documentElement.namespaceURI===zo?t.createElement(n):t.createElementNS(e,n)}function e(){return this.ownerDocument.createElementNS(n.space,n.local)}return"function"==typeof n?n:(n=ao.ns.qualify(n)).local?e:t}function F(){var n=this.parentNode;n&&n.removeChild(this)}function H(n){return{__data__:n}}function O(n){return function(){return Ao(this,n)}}function I(n){return arguments.length||(n=e),function(t,e){return t&&e?n(t.__data__,e.__data__):!t-!e}}function Y(n,t){for(var e=0,r=n.length;r>e;e++)for(var i,u=n[e],o=0,a=u.length;a>o;o++)(i=u[o])&&t(i,o,e);return n}function Z(n){return ko(n,qo),n}function V(n){var t,e;return function(r,i,u){var o,a=n[u].update,l=a.length;for(u!=e&&(e=u,t=0),i>=t&&(t=i+1);!(o=a[t])&&++t<l;);return o}}function X(n,t,e){function r(){var t=this[o];t&&(this.removeEventListener(n,t,t.$),delete this[o])}function i(){var i=l(t,co(arguments));r.call(this),this.addEventListener(n,this[o]=i,i.$=e),i._=t}function u(){var t,e=new RegExp("^__on([^.]+)"+ao.requote(n)+"$");for(var r in this)if(t=r.match(e)){var i=this[r];this.removeEventListener(t[1],i,i.$),delete this[r]}}var o="__on"+n,a=n.indexOf("."),l=$;a>0&&(n=n.slice(0,a));var c=To.get(n);return c&&(n=c,l=B),a?t?i:r:t?b:u}function $(n,t){return function(e){var r=ao.event;ao.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{ao.event=r}}}function B(n,t){var e=$(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function W(e){var r=".dragsuppress-"+ ++Do,i="click"+r,u=ao.select(t(e)).on("touchmove"+r,S).on("dragstart"+r,S).on("selectstart"+r,S);if(null==Ro&&(Ro="onselectstart"in e?!1:x(e.style,"userSelect")),Ro){var o=n(e).style,a=o[Ro];o[Ro]="none"}return function(n){if(u.on(r,null),Ro&&(o[Ro]=a),n){var t=function(){u.on(i,null)};u.on(i,function(){S(),t()},!0),setTimeout(t,0)}}}function J(n,e){e.changedTouches&&(e=e.changedTouches[0]);var r=n.ownerSVGElement||n;if(r.createSVGPoint){var i=r.createSVGPoint();if(0>Po){var u=t(n);if(u.scrollX||u.scrollY){r=ao.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var o=r[0][0].getScreenCTM();Po=!(o.f||o.e),r.remove()}}return Po?(i.x=e.pageX,i.y=e.pageY):(i.x=e.clientX,i.y=e.clientY),i=i.matrixTransform(n.getScreenCTM().inverse()),[i.x,i.y]}var a=n.getBoundingClientRect();return[e.clientX-a.left-n.clientLeft,e.clientY-a.top-n.clientTop]}function G(){return ao.event.changedTouches[0].identifier}function K(n){return n>0?1:0>n?-1:0}function Q(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(t[1]-n[1])*(e[0]-n[0])}function nn(n){return n>1?0:-1>n?Fo:Math.acos(n)}function tn(n){return n>1?Io:-1>n?-Io:Math.asin(n)}function en(n){return((n=Math.exp(n))-1/n)/2}function rn(n){return((n=Math.exp(n))+1/n)/2}function un(n){return((n=Math.exp(2*n))-1)/(n+1)}function on(n){return(n=Math.sin(n/2))*n}function an(){}function ln(n,t,e){return this instanceof ln?(this.h=+n,this.s=+t,void(this.l=+e)):arguments.length<2?n instanceof ln?new ln(n.h,n.s,n.l):_n(""+n,wn,ln):new ln(n,t,e)}function cn(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?u+(o-u)*n/60:180>n?o:240>n?u+(o-u)*(240-n)/60:u}function i(n){return Math.round(255*r(n))}var u,o;return n=isNaN(n)?0:(n%=360)<0?n+360:n,t=isNaN(t)?0:0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,o=.5>=e?e*(1+t):e+t-e*t,u=2*e-o,new mn(i(n+120),i(n),i(n-120))}function fn(n,t,e){return this instanceof fn?(this.h=+n,this.c=+t,void(this.l=+e)):arguments.length<2?n instanceof fn?new fn(n.h,n.c,n.l):n instanceof hn?gn(n.l,n.a,n.b):gn((n=Sn((n=ao.rgb(n)).r,n.g,n.b)).l,n.a,n.b):new fn(n,t,e)}function sn(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),new hn(e,Math.cos(n*=Yo)*t,Math.sin(n)*t)}function hn(n,t,e){return this instanceof hn?(this.l=+n,this.a=+t,void(this.b=+e)):arguments.length<2?n instanceof hn?new hn(n.l,n.a,n.b):n instanceof fn?sn(n.h,n.c,n.l):Sn((n=mn(n)).r,n.g,n.b):new hn(n,t,e)}function pn(n,t,e){var r=(n+16)/116,i=r+t/500,u=r-e/200;return i=vn(i)*na,r=vn(r)*ta,u=vn(u)*ea,new mn(yn(3.2404542*i-1.5371385*r-.4985314*u),yn(-.969266*i+1.8760108*r+.041556*u),yn(.0556434*i-.2040259*r+1.0572252*u))}function gn(n,t,e){return n>0?new fn(Math.atan2(e,t)*Zo,Math.sqrt(t*t+e*e),n):new fn(NaN,NaN,n)}function vn(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function dn(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function yn(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.pow(n,1/2.4)-.055))}function mn(n,t,e){return this instanceof mn?(this.r=~~n,this.g=~~t,void(this.b=~~e)):arguments.length<2?n instanceof mn?new mn(n.r,n.g,n.b):_n(""+n,mn,cn):new mn(n,t,e)}function Mn(n){return new mn(n>>16,n>>8&255,255&n)}function xn(n){return Mn(n)+""}function bn(n){return 16>n?"0"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function _n(n,t,e){var r,i,u,o=0,a=0,l=0;if(r=/([a-z]+)\((.*)\)/.exec(n=n.toLowerCase()))switch(i=r[2].split(","),r[1]){case"hsl":return e(parseFloat(i[0]),parseFloat(i[1])/100,parseFloat(i[2])/100);case"rgb":return t(Nn(i[0]),Nn(i[1]),Nn(i[2]))}return(u=ua.get(n))?t(u.r,u.g,u.b):(null==n||"#"!==n.charAt(0)||isNaN(u=parseInt(n.slice(1),16))||(4===n.length?(o=(3840&u)>>4,o=o>>4|o,a=240&u,a=a>>4|a,l=15&u,l=l<<4|l):7===n.length&&(o=(16711680&u)>>16,a=(65280&u)>>8,l=255&u)),t(o,a,l))}function wn(n,t,e){var r,i,u=Math.min(n/=255,t/=255,e/=255),o=Math.max(n,t,e),a=o-u,l=(o+u)/2;return a?(i=.5>l?a/(o+u):a/(2-o-u),r=n==o?(t-e)/a+(e>t?6:0):t==o?(e-n)/a+2:(n-t)/a+4,r*=60):(r=NaN,i=l>0&&1>l?0:r),new ln(r,i,l)}function Sn(n,t,e){n=kn(n),t=kn(t),e=kn(e);var r=dn((.4124564*n+.3575761*t+.1804375*e)/na),i=dn((.2126729*n+.7151522*t+.072175*e)/ta),u=dn((.0193339*n+.119192*t+.9503041*e)/ea);return hn(116*i-16,500*(r-i),200*(i-u))}function kn(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function Nn(n){var t=parseFloat(n);return"%"===n.charAt(n.length-1)?Math.round(2.55*t):t}function En(n){return"function"==typeof n?n:function(){return n}}function An(n){return function(t,e,r){return 2===arguments.length&&"function"==typeof e&&(r=e,e=null),Cn(t,e,n,r)}}function Cn(n,t,e,r){function i(){var n,t=l.status;if(!t&&Ln(l)||t>=200&&300>t||304===t){try{n=e.call(u,l)}catch(r){return void o.error.call(u,r)}o.load.call(u,n)}else o.error.call(u,l)}var u={},o=ao.dispatch("beforesend","progress","load","error"),a={},l=new XMLHttpRequest,c=null;return!this.XDomainRequest||"withCredentials"in l||!/^(http(s)?:)?\/\//.test(n)||(l=new XDomainRequest),"onload"in l?l.onload=l.onerror=i:l.onreadystatechange=function(){l.readyState>3&&i()},l.onprogress=function(n){var t=ao.event;ao.event=n;try{o.progress.call(u,l)}finally{ao.event=t}},u.header=function(n,t){return n=(n+"").toLowerCase(),arguments.length<2?a[n]:(null==t?delete a[n]:a[n]=t+"",u)},u.mimeType=function(n){return arguments.length?(t=null==n?null:n+"",u):t},u.responseType=function(n){return arguments.length?(c=n,u):c},u.response=function(n){return e=n,u},["get","post"].forEach(function(n){u[n]=function(){return u.send.apply(u,[n].concat(co(arguments)))}}),u.send=function(e,r,i){if(2===arguments.length&&"function"==typeof r&&(i=r,r=null),l.open(e,n,!0),null==t||"accept"in a||(a.accept=t+",*/*"),l.setRequestHeader)for(var f in a)l.setRequestHeader(f,a[f]);return null!=t&&l.overrideMimeType&&l.overrideMimeType(t),null!=c&&(l.responseType=c),null!=i&&u.on("error",i).on("load",function(n){i(null,n)}),o.beforesend.call(u,l),l.send(null==r?null:r),u},u.abort=function(){return l.abort(),u},ao.rebind(u,o,"on"),null==r?u:u.get(zn(r))}function zn(n){return 1===n.length?function(t,e){n(null==t?e:null)}:n}function Ln(n){var t=n.responseType;return t&&"text"!==t?n.response:n.responseText}function qn(n,t,e){var r=arguments.length;2>r&&(t=0),3>r&&(e=Date.now());var i=e+t,u={c:n,t:i,n:null};return aa?aa.n=u:oa=u,aa=u,la||(ca=clearTimeout(ca),la=1,fa(Tn)),u}function Tn(){var n=Rn(),t=Dn()-n;t>24?(isFinite(t)&&(clearTimeout(ca),ca=setTimeout(Tn,t)),la=0):(la=1,fa(Tn))}function Rn(){for(var n=Date.now(),t=oa;t;)n>=t.t&&t.c(n-t.t)&&(t.c=null),t=t.n;return n}function Dn(){for(var n,t=oa,e=1/0;t;)t.c?(t.t<e&&(e=t.t),t=(n=t).n):t=n?n.n=t.n:oa=t.n;return aa=n,e}function Pn(n,t){return t-(n?Math.ceil(Math.log(n)/Math.LN10):1)}function Un(n,t){var e=Math.pow(10,3*xo(8-t));return{scale:t>8?function(n){return n/e}:function(n){return n*e},symbol:n}}function jn(n){var t=n.decimal,e=n.thousands,r=n.grouping,i=n.currency,u=r&&e?function(n,t){for(var i=n.length,u=[],o=0,a=r[0],l=0;i>0&&a>0&&(l+a+1>t&&(a=Math.max(1,t-l)),u.push(n.substring(i-=a,i+a)),!((l+=a+1)>t));)a=r[o=(o+1)%r.length];return u.reverse().join(e)}:m;return function(n){var e=ha.exec(n),r=e[1]||" ",o=e[2]||">",a=e[3]||"-",l=e[4]||"",c=e[5],f=+e[6],s=e[7],h=e[8],p=e[9],g=1,v="",d="",y=!1,m=!0;switch(h&&(h=+h.substring(1)),(c||"0"===r&&"="===o)&&(c=r="0",o="="),p){case"n":s=!0,p="g";break;case"%":g=100,d="%",p="f";break;case"p":g=100,d="%",p="r";break;case"b":case"o":case"x":case"X":"#"===l&&(v="0"+p.toLowerCase());case"c":m=!1;case"d":y=!0,h=0;break;case"s":g=-1,p="r"}"$"===l&&(v=i[0],d=i[1]),"r"!=p||h||(p="g"),null!=h&&("g"==p?h=Math.max(1,Math.min(21,h)):"e"!=p&&"f"!=p||(h=Math.max(0,Math.min(20,h)))),p=pa.get(p)||Fn;var M=c&&s;return function(n){var e=d;if(y&&n%1)return"";var i=0>n||0===n&&0>1/n?(n=-n,"-"):"-"===a?"":a;if(0>g){var l=ao.formatPrefix(n,h);n=l.scale(n),e=l.symbol+d}else n*=g;n=p(n,h);var x,b,_=n.lastIndexOf(".");if(0>_){var w=m?n.lastIndexOf("e"):-1;0>w?(x=n,b=""):(x=n.substring(0,w),b=n.substring(w))}else x=n.substring(0,_),b=t+n.substring(_+1);!c&&s&&(x=u(x,1/0));var S=v.length+x.length+b.length+(M?0:i.length),k=f>S?new Array(S=f-S+1).join(r):"";return M&&(x=u(k+x,k.length?f-b.length:1/0)),i+=v,n=x+b,("<"===o?i+n+k:">"===o?k+i+n:"^"===o?k.substring(0,S>>=1)+i+n+k.substring(S):i+(M?n:k+n))+e}}}function Fn(n){return n+""}function Hn(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function On(n,t,e){function r(t){var e=n(t),r=u(e,1);return r-t>t-e?e:r}function i(e){return t(e=n(new va(e-1)),1),e}function u(n,e){return t(n=new va(+n),e),n}function o(n,r,u){var o=i(n),a=[];if(u>1)for(;r>o;)e(o)%u||a.push(new Date(+o)),t(o,1);else for(;r>o;)a.push(new Date(+o)),t(o,1);return a}function a(n,t,e){try{va=Hn;var r=new Hn;return r._=n,o(r,t,e)}finally{va=Date}}n.floor=n,n.round=r,n.ceil=i,n.offset=u,n.range=o;var l=n.utc=In(n);return l.floor=l,l.round=In(r),l.ceil=In(i),l.offset=In(u),l.range=a,n}function In(n){return function(t,e){try{va=Hn;var r=new Hn;return r._=t,n(r,e)._}finally{va=Date}}}function Yn(n){function t(n){function t(t){for(var e,i,u,o=[],a=-1,l=0;++a<r;)37===n.charCodeAt(a)&&(o.push(n.slice(l,a)),null!=(i=ya[e=n.charAt(++a)])&&(e=n.charAt(++a)),(u=A[e])&&(e=u(t,null==i?"e"===e?" ":"0":i)),o.push(e),l=a+1);return o.push(n.slice(l,a)),o.join("")}var r=n.length;return t.parse=function(t){var r={y:1900,m:0,d:1,H:0,M:0,S:0,L:0,Z:null},i=e(r,n,t,0);if(i!=t.length)return null;"p"in r&&(r.H=r.H%12+12*r.p);var u=null!=r.Z&&va!==Hn,o=new(u?Hn:va);return"j"in r?o.setFullYear(r.y,0,r.j):"W"in r||"U"in r?("w"in r||(r.w="W"in r?1:0),o.setFullYear(r.y,0,1),o.setFullYear(r.y,0,"W"in r?(r.w+6)%7+7*r.W-(o.getDay()+5)%7:r.w+7*r.U-(o.getDay()+6)%7)):o.setFullYear(r.y,r.m,r.d),o.setHours(r.H+(r.Z/100|0),r.M+r.Z%100,r.S,r.L),u?o._:o},t.toString=function(){return n},t}function e(n,t,e,r){for(var i,u,o,a=0,l=t.length,c=e.length;l>a;){if(r>=c)return-1;if(i=t.charCodeAt(a++),37===i){if(o=t.charAt(a++),u=C[o in ya?t.charAt(a++):o],!u||(r=u(n,e,r))<0)return-1}else if(i!=e.charCodeAt(r++))return-1}return r}function r(n,t,e){_.lastIndex=0;var r=_.exec(t.slice(e));return r?(n.w=w.get(r[0].toLowerCase()),e+r[0].length):-1}function i(n,t,e){x.lastIndex=0;var r=x.exec(t.slice(e));return r?(n.w=b.get(r[0].toLowerCase()),e+r[0].length):-1}function u(n,t,e){N.lastIndex=0;var r=N.exec(t.slice(e));return r?(n.m=E.get(r[0].toLowerCase()),e+r[0].length):-1}function o(n,t,e){S.lastIndex=0;var r=S.exec(t.slice(e));return r?(n.m=k.get(r[0].toLowerCase()),e+r[0].length):-1}function a(n,t,r){return e(n,A.c.toString(),t,r)}function l(n,t,r){return e(n,A.x.toString(),t,r)}function c(n,t,r){return e(n,A.X.toString(),t,r)}function f(n,t,e){var r=M.get(t.slice(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}var s=n.dateTime,h=n.date,p=n.time,g=n.periods,v=n.days,d=n.shortDays,y=n.months,m=n.shortMonths;t.utc=function(n){function e(n){try{va=Hn;var t=new va;return t._=n,r(t)}finally{va=Date}}var r=t(n);return e.parse=function(n){try{va=Hn;var t=r.parse(n);return t&&t._}finally{va=Date}},e.toString=r.toString,e},t.multi=t.utc.multi=ct;var M=ao.map(),x=Vn(v),b=Xn(v),_=Vn(d),w=Xn(d),S=Vn(y),k=Xn(y),N=Vn(m),E=Xn(m);g.forEach(function(n,t){M.set(n.toLowerCase(),t)});var A={a:function(n){return d[n.getDay()]},A:function(n){return v[n.getDay()]},b:function(n){return m[n.getMonth()]},B:function(n){return y[n.getMonth()]},c:t(s),d:function(n,t){return Zn(n.getDate(),t,2)},e:function(n,t){return Zn(n.getDate(),t,2)},H:function(n,t){return Zn(n.getHours(),t,2)},I:function(n,t){return Zn(n.getHours()%12||12,t,2)},j:function(n,t){return Zn(1+ga.dayOfYear(n),t,3)},L:function(n,t){return Zn(n.getMilliseconds(),t,3)},m:function(n,t){return Zn(n.getMonth()+1,t,2)},M:function(n,t){return Zn(n.getMinutes(),t,2)},p:function(n){return g[+(n.getHours()>=12)]},S:function(n,t){return Zn(n.getSeconds(),t,2)},U:function(n,t){return Zn(ga.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return Zn(ga.mondayOfYear(n),t,2)},x:t(h),X:t(p),y:function(n,t){return Zn(n.getFullYear()%100,t,2)},Y:function(n,t){return Zn(n.getFullYear()%1e4,t,4)},Z:at,"%":function(){return"%"}},C={a:r,A:i,b:u,B:o,c:a,d:tt,e:tt,H:rt,I:rt,j:et,L:ot,m:nt,M:it,p:f,S:ut,U:Bn,w:$n,W:Wn,x:l,X:c,y:Gn,Y:Jn,Z:Kn,"%":lt};return t}function Zn(n,t,e){var r=0>n?"-":"",i=(r?-n:n)+"",u=i.length;return r+(e>u?new Array(e-u+1).join(t)+i:i)}function Vn(n){return new RegExp("^(?:"+n.map(ao.requote).join("|")+")","i")}function Xn(n){for(var t=new c,e=-1,r=n.length;++e<r;)t.set(n[e].toLowerCase(),e);return t}function $n(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+1));return r?(n.w=+r[0],e+r[0].length):-1}function Bn(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e));return r?(n.U=+r[0],e+r[0].length):-1}function Wn(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e));return r?(n.W=+r[0],e+r[0].length):-1}function Jn(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+4));return r?(n.y=+r[0],e+r[0].length):-1}function Gn(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.y=Qn(+r[0]),e+r[0].length):-1}function Kn(n,t,e){return/^[+-]\d{4}$/.test(t=t.slice(e,e+5))?(n.Z=-t,e+5):-1}function Qn(n){return n+(n>68?1900:2e3)}function nt(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.m=r[0]-1,e+r[0].length):-1}function tt(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.d=+r[0],e+r[0].length):-1}function et(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+3));return r?(n.j=+r[0],e+r[0].length):-1}function rt(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.H=+r[0],e+r[0].length):-1}function it(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.M=+r[0],e+r[0].length):-1}function ut(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.S=+r[0],e+r[0].length):-1}function ot(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+3));return r?(n.L=+r[0],e+r[0].length):-1}function at(n){var t=n.getTimezoneOffset(),e=t>0?"-":"+",r=xo(t)/60|0,i=xo(t)%60;return e+Zn(r,"0",2)+Zn(i,"0",2)}function lt(n,t,e){Ma.lastIndex=0;var r=Ma.exec(t.slice(e,e+1));return r?e+r[0].length:-1}function ct(n){for(var t=n.length,e=-1;++e<t;)n[e][0]=this(n[e][0]);return function(t){for(var e=0,r=n[e];!r[1](t);)r=n[++e];return r[0](t)}}function ft(){}function st(n,t,e){var r=e.s=n+t,i=r-n,u=r-i;e.t=n-u+(t-i)}function ht(n,t){n&&wa.hasOwnProperty(n.type)&&wa[n.type](n,t)}function pt(n,t,e){var r,i=-1,u=n.length-e;for(t.lineStart();++i<u;)r=n[i],t.point(r[0],r[1],r[2]);t.lineEnd()}function gt(n,t){var e=-1,r=n.length;for(t.polygonStart();++e<r;)pt(n[e],t,1);t.polygonEnd()}function vt(){function n(n,t){n*=Yo,t=t*Yo/2+Fo/4;var e=n-r,o=e>=0?1:-1,a=o*e,l=Math.cos(t),c=Math.sin(t),f=u*c,s=i*l+f*Math.cos(a),h=f*o*Math.sin(a);ka.add(Math.atan2(h,s)),r=n,i=l,u=c}var t,e,r,i,u;Na.point=function(o,a){Na.point=n,r=(t=o)*Yo,i=Math.cos(a=(e=a)*Yo/2+Fo/4),u=Math.sin(a)},Na.lineEnd=function(){n(t,e)}}function dt(n){var t=n[0],e=n[1],r=Math.cos(e);return[r*Math.cos(t),r*Math.sin(t),Math.sin(e)]}function yt(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]}function mt(n,t){return[n[1]*t[2]-n[2]*t[1],n[2]*t[0]-n[0]*t[2],n[0]*t[1]-n[1]*t[0]]}function Mt(n,t){n[0]+=t[0],n[1]+=t[1],n[2]+=t[2]}function xt(n,t){return[n[0]*t,n[1]*t,n[2]*t]}function bt(n){var t=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);n[0]/=t,n[1]/=t,n[2]/=t}function _t(n){return[Math.atan2(n[1],n[0]),tn(n[2])]}function wt(n,t){return xo(n[0]-t[0])<Uo&&xo(n[1]-t[1])<Uo}function St(n,t){n*=Yo;var e=Math.cos(t*=Yo);kt(e*Math.cos(n),e*Math.sin(n),Math.sin(t))}function kt(n,t,e){++Ea,Ca+=(n-Ca)/Ea,za+=(t-za)/Ea,La+=(e-La)/Ea}function Nt(){function n(n,i){n*=Yo;var u=Math.cos(i*=Yo),o=u*Math.cos(n),a=u*Math.sin(n),l=Math.sin(i),c=Math.atan2(Math.sqrt((c=e*l-r*a)*c+(c=r*o-t*l)*c+(c=t*a-e*o)*c),t*o+e*a+r*l);Aa+=c,qa+=c*(t+(t=o)),Ta+=c*(e+(e=a)),Ra+=c*(r+(r=l)),kt(t,e,r)}var t,e,r;ja.point=function(i,u){i*=Yo;var o=Math.cos(u*=Yo);t=o*Math.cos(i),e=o*Math.sin(i),r=Math.sin(u),ja.point=n,kt(t,e,r)}}function Et(){ja.point=St}function At(){function n(n,t){n*=Yo;var e=Math.cos(t*=Yo),o=e*Math.cos(n),a=e*Math.sin(n),l=Math.sin(t),c=i*l-u*a,f=u*o-r*l,s=r*a-i*o,h=Math.sqrt(c*c+f*f+s*s),p=r*o+i*a+u*l,g=h&&-nn(p)/h,v=Math.atan2(h,p);Da+=g*c,Pa+=g*f,Ua+=g*s,Aa+=v,qa+=v*(r+(r=o)),Ta+=v*(i+(i=a)),Ra+=v*(u+(u=l)),kt(r,i,u)}var t,e,r,i,u;ja.point=function(o,a){t=o,e=a,ja.point=n,o*=Yo;var l=Math.cos(a*=Yo);r=l*Math.cos(o),i=l*Math.sin(o),u=Math.sin(a),kt(r,i,u)},ja.lineEnd=function(){n(t,e),ja.lineEnd=Et,ja.point=St}}function Ct(n,t){function e(e,r){return e=n(e,r),t(e[0],e[1])}return n.invert&&t.invert&&(e.invert=function(e,r){return e=t.invert(e,r),e&&n.invert(e[0],e[1])}),e}function zt(){return!0}function Lt(n,t,e,r,i){var u=[],o=[];if(n.forEach(function(n){if(!((t=n.length-1)<=0)){var t,e=n[0],r=n[t];if(wt(e,r)){i.lineStart();for(var a=0;t>a;++a)i.point((e=n[a])[0],e[1]);return void i.lineEnd()}var l=new Tt(e,n,null,!0),c=new Tt(e,null,l,!1);l.o=c,u.push(l),o.push(c),l=new Tt(r,n,null,!1),c=new Tt(r,null,l,!0),l.o=c,u.push(l),o.push(c)}}),o.sort(t),qt(u),qt(o),u.length){for(var a=0,l=e,c=o.length;c>a;++a)o[a].e=l=!l;for(var f,s,h=u[0];;){for(var p=h,g=!0;p.v;)if((p=p.n)===h)return;f=p.z,i.lineStart();do{if(p.v=p.o.v=!0,p.e){if(g)for(var a=0,c=f.length;c>a;++a)i.point((s=f[a])[0],s[1]);else r(p.x,p.n.x,1,i);p=p.n}else{if(g){f=p.p.z;for(var a=f.length-1;a>=0;--a)i.point((s=f[a])[0],s[1])}else r(p.x,p.p.x,-1,i);p=p.p}p=p.o,f=p.z,g=!g}while(!p.v);i.lineEnd()}}}function qt(n){if(t=n.length){for(var t,e,r=0,i=n[0];++r<t;)i.n=e=n[r],e.p=i,i=e;i.n=e=n[0],e.p=i}}function Tt(n,t,e,r){this.x=n,this.z=t,this.o=e,this.e=r,this.v=!1,this.n=this.p=null}function Rt(n,t,e,r){return function(i,u){function o(t,e){var r=i(t,e);n(t=r[0],e=r[1])&&u.point(t,e)}function a(n,t){var e=i(n,t);d.point(e[0],e[1])}function l(){m.point=a,d.lineStart()}function c(){m.point=o,d.lineEnd()}function f(n,t){v.push([n,t]);var e=i(n,t);x.point(e[0],e[1])}function s(){x.lineStart(),v=[]}function h(){f(v[0][0],v[0][1]),x.lineEnd();var n,t=x.clean(),e=M.buffer(),r=e.length;if(v.pop(),g.push(v),v=null,r)if(1&t){n=e[0];var i,r=n.length-1,o=-1;if(r>0){for(b||(u.polygonStart(),b=!0),u.lineStart();++o<r;)u.point((i=n[o])[0],i[1]);u.lineEnd()}}else r>1&&2&t&&e.push(e.pop().concat(e.shift())),p.push(e.filter(Dt))}var p,g,v,d=t(u),y=i.invert(r[0],r[1]),m={point:o,lineStart:l,lineEnd:c,polygonStart:function(){m.point=f,m.lineStart=s,m.lineEnd=h,p=[],g=[]},polygonEnd:function(){m.point=o,m.lineStart=l,m.lineEnd=c,p=ao.merge(p);var n=Ot(y,g);p.length?(b||(u.polygonStart(),b=!0),Lt(p,Ut,n,e,u)):n&&(b||(u.polygonStart(),b=!0),u.lineStart(),e(null,null,1,u),u.lineEnd()),b&&(u.polygonEnd(),b=!1),p=g=null},sphere:function(){u.polygonStart(),u.lineStart(),e(null,null,1,u),u.lineEnd(),u.polygonEnd()}},M=Pt(),x=t(M),b=!1;return m}}function Dt(n){return n.length>1}function Pt(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:b,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function Ut(n,t){return((n=n.x)[0]<0?n[1]-Io-Uo:Io-n[1])-((t=t.x)[0]<0?t[1]-Io-Uo:Io-t[1])}function jt(n){var t,e=NaN,r=NaN,i=NaN;return{lineStart:function(){n.lineStart(),t=1},point:function(u,o){var a=u>0?Fo:-Fo,l=xo(u-e);xo(l-Fo)<Uo?(n.point(e,r=(r+o)/2>0?Io:-Io),n.point(i,r),n.lineEnd(),n.lineStart(),n.point(a,r),n.point(u,r),t=0):i!==a&&l>=Fo&&(xo(e-i)<Uo&&(e-=i*Uo),xo(u-a)<Uo&&(u-=a*Uo),r=Ft(e,r,u,o),n.point(i,r),n.lineEnd(),n.lineStart(),n.point(a,r),t=0),n.point(e=u,r=o),i=a},lineEnd:function(){n.lineEnd(),e=r=NaN},clean:function(){return 2-t}}}function Ft(n,t,e,r){var i,u,o=Math.sin(n-e);return xo(o)>Uo?Math.atan((Math.sin(t)*(u=Math.cos(r))*Math.sin(e)-Math.sin(r)*(i=Math.cos(t))*Math.sin(n))/(i*u*o)):(t+r)/2}function Ht(n,t,e,r){var i;if(null==n)i=e*Io,r.point(-Fo,i),r.point(0,i),r.point(Fo,i),r.point(Fo,0),r.point(Fo,-i),r.point(0,-i),r.point(-Fo,-i),r.point(-Fo,0),r.point(-Fo,i);else if(xo(n[0]-t[0])>Uo){var u=n[0]<t[0]?Fo:-Fo;i=e*u/2,r.point(-u,i),r.point(0,i),r.point(u,i)}else r.point(t[0],t[1])}function Ot(n,t){var e=n[0],r=n[1],i=[Math.sin(e),-Math.cos(e),0],u=0,o=0;ka.reset();for(var a=0,l=t.length;l>a;++a){var c=t[a],f=c.length;if(f)for(var s=c[0],h=s[0],p=s[1]/2+Fo/4,g=Math.sin(p),v=Math.cos(p),d=1;;){d===f&&(d=0),n=c[d];var y=n[0],m=n[1]/2+Fo/4,M=Math.sin(m),x=Math.cos(m),b=y-h,_=b>=0?1:-1,w=_*b,S=w>Fo,k=g*M;if(ka.add(Math.atan2(k*_*Math.sin(w),v*x+k*Math.cos(w))),u+=S?b+_*Ho:b,S^h>=e^y>=e){var N=mt(dt(s),dt(n));bt(N);var E=mt(i,N);bt(E);var A=(S^b>=0?-1:1)*tn(E[2]);(r>A||r===A&&(N[0]||N[1]))&&(o+=S^b>=0?1:-1)}if(!d++)break;h=y,g=M,v=x,s=n}}return(-Uo>u||Uo>u&&-Uo>ka)^1&o}function It(n){function t(n,t){return Math.cos(n)*Math.cos(t)>u}function e(n){var e,u,l,c,f;return{lineStart:function(){c=l=!1,f=1},point:function(s,h){var p,g=[s,h],v=t(s,h),d=o?v?0:i(s,h):v?i(s+(0>s?Fo:-Fo),h):0;if(!e&&(c=l=v)&&n.lineStart(),v!==l&&(p=r(e,g),(wt(e,p)||wt(g,p))&&(g[0]+=Uo,g[1]+=Uo,v=t(g[0],g[1]))),v!==l)f=0,v?(n.lineStart(),p=r(g,e),n.point(p[0],p[1])):(p=r(e,g),n.point(p[0],p[1]),n.lineEnd()),e=p;else if(a&&e&&o^v){var y;d&u||!(y=r(g,e,!0))||(f=0,o?(n.lineStart(),n.point(y[0][0],y[0][1]),n.point(y[1][0],y[1][1]),n.lineEnd()):(n.point(y[1][0],y[1][1]),n.lineEnd(),n.lineStart(),n.point(y[0][0],y[0][1])))}!v||e&&wt(e,g)||n.point(g[0],g[1]),e=g,l=v,u=d},lineEnd:function(){l&&n.lineEnd(),e=null},clean:function(){return f|(c&&l)<<1}}}function r(n,t,e){var r=dt(n),i=dt(t),o=[1,0,0],a=mt(r,i),l=yt(a,a),c=a[0],f=l-c*c;if(!f)return!e&&n;var s=u*l/f,h=-u*c/f,p=mt(o,a),g=xt(o,s),v=xt(a,h);Mt(g,v);var d=p,y=yt(g,d),m=yt(d,d),M=y*y-m*(yt(g,g)-1);if(!(0>M)){var x=Math.sqrt(M),b=xt(d,(-y-x)/m);if(Mt(b,g),b=_t(b),!e)return b;var _,w=n[0],S=t[0],k=n[1],N=t[1];w>S&&(_=w,w=S,S=_);var E=S-w,A=xo(E-Fo)<Uo,C=A||Uo>E;if(!A&&k>N&&(_=k,k=N,N=_),C?A?k+N>0^b[1]<(xo(b[0]-w)<Uo?k:N):k<=b[1]&&b[1]<=N:E>Fo^(w<=b[0]&&b[0]<=S)){var z=xt(d,(-y+x)/m);return Mt(z,g),[b,_t(z)]}}}function i(t,e){var r=o?n:Fo-n,i=0;return-r>t?i|=1:t>r&&(i|=2),-r>e?i|=4:e>r&&(i|=8),i}var u=Math.cos(n),o=u>0,a=xo(u)>Uo,l=ve(n,6*Yo);return Rt(t,e,l,o?[0,-n]:[-Fo,n-Fo])}function Yt(n,t,e,r){return function(i){var u,o=i.a,a=i.b,l=o.x,c=o.y,f=a.x,s=a.y,h=0,p=1,g=f-l,v=s-c;if(u=n-l,g||!(u>0)){if(u/=g,0>g){if(h>u)return;p>u&&(p=u)}else if(g>0){if(u>p)return;u>h&&(h=u)}if(u=e-l,g||!(0>u)){if(u/=g,0>g){if(u>p)return;u>h&&(h=u)}else if(g>0){if(h>u)return;p>u&&(p=u)}if(u=t-c,v||!(u>0)){if(u/=v,0>v){if(h>u)return;p>u&&(p=u)}else if(v>0){if(u>p)return;u>h&&(h=u)}if(u=r-c,v||!(0>u)){if(u/=v,0>v){if(u>p)return;u>h&&(h=u)}else if(v>0){if(h>u)return;p>u&&(p=u)}return h>0&&(i.a={x:l+h*g,y:c+h*v}),1>p&&(i.b={x:l+p*g,y:c+p*v}),i}}}}}}function Zt(n,t,e,r){function i(r,i){return xo(r[0]-n)<Uo?i>0?0:3:xo(r[0]-e)<Uo?i>0?2:1:xo(r[1]-t)<Uo?i>0?1:0:i>0?3:2}function u(n,t){return o(n.x,t.x)}function o(n,t){var e=i(n,1),r=i(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}return function(a){function l(n){for(var t=0,e=d.length,r=n[1],i=0;e>i;++i)for(var u,o=1,a=d[i],l=a.length,c=a[0];l>o;++o)u=a[o],c[1]<=r?u[1]>r&&Q(c,u,n)>0&&++t:u[1]<=r&&Q(c,u,n)<0&&--t,c=u;return 0!==t}function c(u,a,l,c){var f=0,s=0;if(null==u||(f=i(u,l))!==(s=i(a,l))||o(u,a)<0^l>0){do c.point(0===f||3===f?n:e,f>1?r:t);while((f=(f+l+4)%4)!==s)}else c.point(a[0],a[1])}function f(i,u){return i>=n&&e>=i&&u>=t&&r>=u}function s(n,t){f(n,t)&&a.point(n,t)}function h(){C.point=g,d&&d.push(y=[]),S=!0,w=!1,b=_=NaN}function p(){v&&(g(m,M),x&&w&&E.rejoin(),v.push(E.buffer())),C.point=s,w&&a.lineEnd()}function g(n,t){n=Math.max(-Ha,Math.min(Ha,n)),t=Math.max(-Ha,Math.min(Ha,t));var e=f(n,t);if(d&&y.push([n,t]),S)m=n,M=t,x=e,S=!1,e&&(a.lineStart(),a.point(n,t));else if(e&&w)a.point(n,t);else{var r={a:{x:b,y:_},b:{x:n,y:t}};A(r)?(w||(a.lineStart(),a.point(r.a.x,r.a.y)),a.point(r.b.x,r.b.y),e||a.lineEnd(),k=!1):e&&(a.lineStart(),a.point(n,t),k=!1)}b=n,_=t,w=e}var v,d,y,m,M,x,b,_,w,S,k,N=a,E=Pt(),A=Yt(n,t,e,r),C={point:s,lineStart:h,lineEnd:p,polygonStart:function(){a=E,v=[],d=[],k=!0},polygonEnd:function(){a=N,v=ao.merge(v);var t=l([n,r]),e=k&&t,i=v.length;(e||i)&&(a.polygonStart(),e&&(a.lineStart(),c(null,null,1,a),a.lineEnd()),i&&Lt(v,u,t,c,a),a.polygonEnd()),v=d=y=null}};return C}}function Vt(n){var t=0,e=Fo/3,r=ae(n),i=r(t,e);return i.parallels=function(n){return arguments.length?r(t=n[0]*Fo/180,e=n[1]*Fo/180):[t/Fo*180,e/Fo*180]},i}function Xt(n,t){function e(n,t){var e=Math.sqrt(u-2*i*Math.sin(t))/i;return[e*Math.sin(n*=i),o-e*Math.cos(n)]}var r=Math.sin(n),i=(r+Math.sin(t))/2,u=1+r*(2*i-r),o=Math.sqrt(u)/i;return e.invert=function(n,t){var e=o-t;return[Math.atan2(n,e)/i,tn((u-(n*n+e*e)*i*i)/(2*i))]},e}function $t(){function n(n,t){Ia+=i*n-r*t,r=n,i=t}var t,e,r,i;$a.point=function(u,o){$a.point=n,t=r=u,e=i=o},$a.lineEnd=function(){n(t,e)}}function Bt(n,t){Ya>n&&(Ya=n),n>Va&&(Va=n),Za>t&&(Za=t),t>Xa&&(Xa=t)}function Wt(){function n(n,t){o.push("M",n,",",t,u)}function t(n,t){o.push("M",n,",",t),a.point=e}function e(n,t){o.push("L",n,",",t)}function r(){a.point=n}function i(){o.push("Z")}var u=Jt(4.5),o=[],a={point:n,lineStart:function(){a.point=t},lineEnd:r,polygonStart:function(){a.lineEnd=i},polygonEnd:function(){a.lineEnd=r,a.point=n},pointRadius:function(n){return u=Jt(n),a},result:function(){if(o.length){var n=o.join("");return o=[],n}}};return a}function Jt(n){return"m0,"+n+"a"+n+","+n+" 0 1,1 0,"+-2*n+"a"+n+","+n+" 0 1,1 0,"+2*n+"z"}function Gt(n,t){Ca+=n,za+=t,++La}function Kt(){function n(n,r){var i=n-t,u=r-e,o=Math.sqrt(i*i+u*u);qa+=o*(t+n)/2,Ta+=o*(e+r)/2,Ra+=o,Gt(t=n,e=r)}var t,e;Wa.point=function(r,i){Wa.point=n,Gt(t=r,e=i)}}function Qt(){Wa.point=Gt}function ne(){function n(n,t){var e=n-r,u=t-i,o=Math.sqrt(e*e+u*u);qa+=o*(r+n)/2,Ta+=o*(i+t)/2,Ra+=o,o=i*n-r*t,Da+=o*(r+n),Pa+=o*(i+t),Ua+=3*o,Gt(r=n,i=t)}var t,e,r,i;Wa.point=function(u,o){Wa.point=n,Gt(t=r=u,e=i=o)},Wa.lineEnd=function(){n(t,e)}}function te(n){function t(t,e){n.moveTo(t+o,e),n.arc(t,e,o,0,Ho)}function e(t,e){n.moveTo(t,e),a.point=r}function r(t,e){n.lineTo(t,e)}function i(){a.point=t}function u(){n.closePath()}var o=4.5,a={point:t,lineStart:function(){a.point=e},lineEnd:i,polygonStart:function(){a.lineEnd=u},polygonEnd:function(){a.lineEnd=i,a.point=t},pointRadius:function(n){return o=n,a},result:b};return a}function ee(n){function t(n){return(a?r:e)(n)}function e(t){return ue(t,function(e,r){e=n(e,r),t.point(e[0],e[1])})}function r(t){function e(e,r){e=n(e,r),t.point(e[0],e[1])}function r(){M=NaN,S.point=u,t.lineStart()}function u(e,r){var u=dt([e,r]),o=n(e,r);i(M,x,m,b,_,w,M=o[0],x=o[1],m=e,b=u[0],_=u[1],w=u[2],a,t),t.point(M,x)}function o(){S.point=e,t.lineEnd()}function l(){
|
2 |
-
r(),S.point=c,S.lineEnd=f}function c(n,t){u(s=n,h=t),p=M,g=x,v=b,d=_,y=w,S.point=u}function f(){i(M,x,m,b,_,w,p,g,s,v,d,y,a,t),S.lineEnd=o,o()}var s,h,p,g,v,d,y,m,M,x,b,_,w,S={point:e,lineStart:r,lineEnd:o,polygonStart:function(){t.polygonStart(),S.lineStart=l},polygonEnd:function(){t.polygonEnd(),S.lineStart=r}};return S}function i(t,e,r,a,l,c,f,s,h,p,g,v,d,y){var m=f-t,M=s-e,x=m*m+M*M;if(x>4*u&&d--){var b=a+p,_=l+g,w=c+v,S=Math.sqrt(b*b+_*_+w*w),k=Math.asin(w/=S),N=xo(xo(w)-1)<Uo||xo(r-h)<Uo?(r+h)/2:Math.atan2(_,b),E=n(N,k),A=E[0],C=E[1],z=A-t,L=C-e,q=M*z-m*L;(q*q/x>u||xo((m*z+M*L)/x-.5)>.3||o>a*p+l*g+c*v)&&(i(t,e,r,a,l,c,A,C,N,b/=S,_/=S,w,d,y),y.point(A,C),i(A,C,N,b,_,w,f,s,h,p,g,v,d,y))}}var u=.5,o=Math.cos(30*Yo),a=16;return t.precision=function(n){return arguments.length?(a=(u=n*n)>0&&16,t):Math.sqrt(u)},t}function re(n){var t=ee(function(t,e){return n([t*Zo,e*Zo])});return function(n){return le(t(n))}}function ie(n){this.stream=n}function ue(n,t){return{point:t,sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function oe(n){return ae(function(){return n})()}function ae(n){function t(n){return n=a(n[0]*Yo,n[1]*Yo),[n[0]*h+l,c-n[1]*h]}function e(n){return n=a.invert((n[0]-l)/h,(c-n[1])/h),n&&[n[0]*Zo,n[1]*Zo]}function r(){a=Ct(o=se(y,M,x),u);var n=u(v,d);return l=p-n[0]*h,c=g+n[1]*h,i()}function i(){return f&&(f.valid=!1,f=null),t}var u,o,a,l,c,f,s=ee(function(n,t){return n=u(n,t),[n[0]*h+l,c-n[1]*h]}),h=150,p=480,g=250,v=0,d=0,y=0,M=0,x=0,b=Fa,_=m,w=null,S=null;return t.stream=function(n){return f&&(f.valid=!1),f=le(b(o,s(_(n)))),f.valid=!0,f},t.clipAngle=function(n){return arguments.length?(b=null==n?(w=n,Fa):It((w=+n)*Yo),i()):w},t.clipExtent=function(n){return arguments.length?(S=n,_=n?Zt(n[0][0],n[0][1],n[1][0],n[1][1]):m,i()):S},t.scale=function(n){return arguments.length?(h=+n,r()):h},t.translate=function(n){return arguments.length?(p=+n[0],g=+n[1],r()):[p,g]},t.center=function(n){return arguments.length?(v=n[0]%360*Yo,d=n[1]%360*Yo,r()):[v*Zo,d*Zo]},t.rotate=function(n){return arguments.length?(y=n[0]%360*Yo,M=n[1]%360*Yo,x=n.length>2?n[2]%360*Yo:0,r()):[y*Zo,M*Zo,x*Zo]},ao.rebind(t,s,"precision"),function(){return u=n.apply(this,arguments),t.invert=u.invert&&e,r()}}function le(n){return ue(n,function(t,e){n.point(t*Yo,e*Yo)})}function ce(n,t){return[n,t]}function fe(n,t){return[n>Fo?n-Ho:-Fo>n?n+Ho:n,t]}function se(n,t,e){return n?t||e?Ct(pe(n),ge(t,e)):pe(n):t||e?ge(t,e):fe}function he(n){return function(t,e){return t+=n,[t>Fo?t-Ho:-Fo>t?t+Ho:t,e]}}function pe(n){var t=he(n);return t.invert=he(-n),t}function ge(n,t){function e(n,t){var e=Math.cos(t),a=Math.cos(n)*e,l=Math.sin(n)*e,c=Math.sin(t),f=c*r+a*i;return[Math.atan2(l*u-f*o,a*r-c*i),tn(f*u+l*o)]}var r=Math.cos(n),i=Math.sin(n),u=Math.cos(t),o=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),a=Math.cos(n)*e,l=Math.sin(n)*e,c=Math.sin(t),f=c*u-l*o;return[Math.atan2(l*u+c*o,a*r+f*i),tn(f*r-a*i)]},e}function ve(n,t){var e=Math.cos(n),r=Math.sin(n);return function(i,u,o,a){var l=o*t;null!=i?(i=de(e,i),u=de(e,u),(o>0?u>i:i>u)&&(i+=o*Ho)):(i=n+o*Ho,u=n-.5*l);for(var c,f=i;o>0?f>u:u>f;f-=l)a.point((c=_t([e,-r*Math.cos(f),-r*Math.sin(f)]))[0],c[1])}}function de(n,t){var e=dt(t);e[0]-=n,bt(e);var r=nn(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-Uo)%(2*Math.PI)}function ye(n,t,e){var r=ao.range(n,t-Uo,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function me(n,t,e){var r=ao.range(n,t-Uo,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function Me(n){return n.source}function xe(n){return n.target}function be(n,t,e,r){var i=Math.cos(t),u=Math.sin(t),o=Math.cos(r),a=Math.sin(r),l=i*Math.cos(n),c=i*Math.sin(n),f=o*Math.cos(e),s=o*Math.sin(e),h=2*Math.asin(Math.sqrt(on(r-t)+i*o*on(e-n))),p=1/Math.sin(h),g=h?function(n){var t=Math.sin(n*=h)*p,e=Math.sin(h-n)*p,r=e*l+t*f,i=e*c+t*s,o=e*u+t*a;return[Math.atan2(i,r)*Zo,Math.atan2(o,Math.sqrt(r*r+i*i))*Zo]}:function(){return[n*Zo,t*Zo]};return g.distance=h,g}function _e(){function n(n,i){var u=Math.sin(i*=Yo),o=Math.cos(i),a=xo((n*=Yo)-t),l=Math.cos(a);Ja+=Math.atan2(Math.sqrt((a=o*Math.sin(a))*a+(a=r*u-e*o*l)*a),e*u+r*o*l),t=n,e=u,r=o}var t,e,r;Ga.point=function(i,u){t=i*Yo,e=Math.sin(u*=Yo),r=Math.cos(u),Ga.point=n},Ga.lineEnd=function(){Ga.point=Ga.lineEnd=b}}function we(n,t){function e(t,e){var r=Math.cos(t),i=Math.cos(e),u=n(r*i);return[u*i*Math.sin(t),u*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),i=t(r),u=Math.sin(i),o=Math.cos(i);return[Math.atan2(n*u,r*o),Math.asin(r&&e*u/r)]},e}function Se(n,t){function e(n,t){o>0?-Io+Uo>t&&(t=-Io+Uo):t>Io-Uo&&(t=Io-Uo);var e=o/Math.pow(i(t),u);return[e*Math.sin(u*n),o-e*Math.cos(u*n)]}var r=Math.cos(n),i=function(n){return Math.tan(Fo/4+n/2)},u=n===t?Math.sin(n):Math.log(r/Math.cos(t))/Math.log(i(t)/i(n)),o=r*Math.pow(i(n),u)/u;return u?(e.invert=function(n,t){var e=o-t,r=K(u)*Math.sqrt(n*n+e*e);return[Math.atan2(n,e)/u,2*Math.atan(Math.pow(o/r,1/u))-Io]},e):Ne}function ke(n,t){function e(n,t){var e=u-t;return[e*Math.sin(i*n),u-e*Math.cos(i*n)]}var r=Math.cos(n),i=n===t?Math.sin(n):(r-Math.cos(t))/(t-n),u=r/i+n;return xo(i)<Uo?ce:(e.invert=function(n,t){var e=u-t;return[Math.atan2(n,e)/i,u-K(i)*Math.sqrt(n*n+e*e)]},e)}function Ne(n,t){return[n,Math.log(Math.tan(Fo/4+t/2))]}function Ee(n){var t,e=oe(n),r=e.scale,i=e.translate,u=e.clipExtent;return e.scale=function(){var n=r.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.translate=function(){var n=i.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.clipExtent=function(n){var o=u.apply(e,arguments);if(o===e){if(t=null==n){var a=Fo*r(),l=i();u([[l[0]-a,l[1]-a],[l[0]+a,l[1]+a]])}}else t&&(o=null);return o},e.clipExtent(null)}function Ae(n,t){return[Math.log(Math.tan(Fo/4+t/2)),-n]}function Ce(n){return n[0]}function ze(n){return n[1]}function Le(n){for(var t=n.length,e=[0,1],r=2,i=2;t>i;i++){for(;r>1&&Q(n[e[r-2]],n[e[r-1]],n[i])<=0;)--r;e[r++]=i}return e.slice(0,r)}function qe(n,t){return n[0]-t[0]||n[1]-t[1]}function Te(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function Re(n,t,e,r){var i=n[0],u=e[0],o=t[0]-i,a=r[0]-u,l=n[1],c=e[1],f=t[1]-l,s=r[1]-c,h=(a*(l-c)-s*(i-u))/(s*o-a*f);return[i+h*o,l+h*f]}function De(n){var t=n[0],e=n[n.length-1];return!(t[0]-e[0]||t[1]-e[1])}function Pe(){rr(this),this.edge=this.site=this.circle=null}function Ue(n){var t=cl.pop()||new Pe;return t.site=n,t}function je(n){Be(n),ol.remove(n),cl.push(n),rr(n)}function Fe(n){var t=n.circle,e=t.x,r=t.cy,i={x:e,y:r},u=n.P,o=n.N,a=[n];je(n);for(var l=u;l.circle&&xo(e-l.circle.x)<Uo&&xo(r-l.circle.cy)<Uo;)u=l.P,a.unshift(l),je(l),l=u;a.unshift(l),Be(l);for(var c=o;c.circle&&xo(e-c.circle.x)<Uo&&xo(r-c.circle.cy)<Uo;)o=c.N,a.push(c),je(c),c=o;a.push(c),Be(c);var f,s=a.length;for(f=1;s>f;++f)c=a[f],l=a[f-1],nr(c.edge,l.site,c.site,i);l=a[0],c=a[s-1],c.edge=Ke(l.site,c.site,null,i),$e(l),$e(c)}function He(n){for(var t,e,r,i,u=n.x,o=n.y,a=ol._;a;)if(r=Oe(a,o)-u,r>Uo)a=a.L;else{if(i=u-Ie(a,o),!(i>Uo)){r>-Uo?(t=a.P,e=a):i>-Uo?(t=a,e=a.N):t=e=a;break}if(!a.R){t=a;break}a=a.R}var l=Ue(n);if(ol.insert(t,l),t||e){if(t===e)return Be(t),e=Ue(t.site),ol.insert(l,e),l.edge=e.edge=Ke(t.site,l.site),$e(t),void $e(e);if(!e)return void(l.edge=Ke(t.site,l.site));Be(t),Be(e);var c=t.site,f=c.x,s=c.y,h=n.x-f,p=n.y-s,g=e.site,v=g.x-f,d=g.y-s,y=2*(h*d-p*v),m=h*h+p*p,M=v*v+d*d,x={x:(d*m-p*M)/y+f,y:(h*M-v*m)/y+s};nr(e.edge,c,g,x),l.edge=Ke(c,n,null,x),e.edge=Ke(n,g,null,x),$e(t),$e(e)}}function Oe(n,t){var e=n.site,r=e.x,i=e.y,u=i-t;if(!u)return r;var o=n.P;if(!o)return-(1/0);e=o.site;var a=e.x,l=e.y,c=l-t;if(!c)return a;var f=a-r,s=1/u-1/c,h=f/c;return s?(-h+Math.sqrt(h*h-2*s*(f*f/(-2*c)-l+c/2+i-u/2)))/s+r:(r+a)/2}function Ie(n,t){var e=n.N;if(e)return Oe(e,t);var r=n.site;return r.y===t?r.x:1/0}function Ye(n){this.site=n,this.edges=[]}function Ze(n){for(var t,e,r,i,u,o,a,l,c,f,s=n[0][0],h=n[1][0],p=n[0][1],g=n[1][1],v=ul,d=v.length;d--;)if(u=v[d],u&&u.prepare())for(a=u.edges,l=a.length,o=0;l>o;)f=a[o].end(),r=f.x,i=f.y,c=a[++o%l].start(),t=c.x,e=c.y,(xo(r-t)>Uo||xo(i-e)>Uo)&&(a.splice(o,0,new tr(Qe(u.site,f,xo(r-s)<Uo&&g-i>Uo?{x:s,y:xo(t-s)<Uo?e:g}:xo(i-g)<Uo&&h-r>Uo?{x:xo(e-g)<Uo?t:h,y:g}:xo(r-h)<Uo&&i-p>Uo?{x:h,y:xo(t-h)<Uo?e:p}:xo(i-p)<Uo&&r-s>Uo?{x:xo(e-p)<Uo?t:s,y:p}:null),u.site,null)),++l)}function Ve(n,t){return t.angle-n.angle}function Xe(){rr(this),this.x=this.y=this.arc=this.site=this.cy=null}function $e(n){var t=n.P,e=n.N;if(t&&e){var r=t.site,i=n.site,u=e.site;if(r!==u){var o=i.x,a=i.y,l=r.x-o,c=r.y-a,f=u.x-o,s=u.y-a,h=2*(l*s-c*f);if(!(h>=-jo)){var p=l*l+c*c,g=f*f+s*s,v=(s*p-c*g)/h,d=(l*g-f*p)/h,s=d+a,y=fl.pop()||new Xe;y.arc=n,y.site=i,y.x=v+o,y.y=s+Math.sqrt(v*v+d*d),y.cy=s,n.circle=y;for(var m=null,M=ll._;M;)if(y.y<M.y||y.y===M.y&&y.x<=M.x){if(!M.L){m=M.P;break}M=M.L}else{if(!M.R){m=M;break}M=M.R}ll.insert(m,y),m||(al=y)}}}}function Be(n){var t=n.circle;t&&(t.P||(al=t.N),ll.remove(t),fl.push(t),rr(t),n.circle=null)}function We(n){for(var t,e=il,r=Yt(n[0][0],n[0][1],n[1][0],n[1][1]),i=e.length;i--;)t=e[i],(!Je(t,n)||!r(t)||xo(t.a.x-t.b.x)<Uo&&xo(t.a.y-t.b.y)<Uo)&&(t.a=t.b=null,e.splice(i,1))}function Je(n,t){var e=n.b;if(e)return!0;var r,i,u=n.a,o=t[0][0],a=t[1][0],l=t[0][1],c=t[1][1],f=n.l,s=n.r,h=f.x,p=f.y,g=s.x,v=s.y,d=(h+g)/2,y=(p+v)/2;if(v===p){if(o>d||d>=a)return;if(h>g){if(u){if(u.y>=c)return}else u={x:d,y:l};e={x:d,y:c}}else{if(u){if(u.y<l)return}else u={x:d,y:c};e={x:d,y:l}}}else if(r=(h-g)/(v-p),i=y-r*d,-1>r||r>1)if(h>g){if(u){if(u.y>=c)return}else u={x:(l-i)/r,y:l};e={x:(c-i)/r,y:c}}else{if(u){if(u.y<l)return}else u={x:(c-i)/r,y:c};e={x:(l-i)/r,y:l}}else if(v>p){if(u){if(u.x>=a)return}else u={x:o,y:r*o+i};e={x:a,y:r*a+i}}else{if(u){if(u.x<o)return}else u={x:a,y:r*a+i};e={x:o,y:r*o+i}}return n.a=u,n.b=e,!0}function Ge(n,t){this.l=n,this.r=t,this.a=this.b=null}function Ke(n,t,e,r){var i=new Ge(n,t);return il.push(i),e&&nr(i,n,t,e),r&&nr(i,t,n,r),ul[n.i].edges.push(new tr(i,n,t)),ul[t.i].edges.push(new tr(i,t,n)),i}function Qe(n,t,e){var r=new Ge(n,null);return r.a=t,r.b=e,il.push(r),r}function nr(n,t,e,r){n.a||n.b?n.l===e?n.b=r:n.a=r:(n.a=r,n.l=t,n.r=e)}function tr(n,t,e){var r=n.a,i=n.b;this.edge=n,this.site=t,this.angle=e?Math.atan2(e.y-t.y,e.x-t.x):n.l===t?Math.atan2(i.x-r.x,r.y-i.y):Math.atan2(r.x-i.x,i.y-r.y)}function er(){this._=null}function rr(n){n.U=n.C=n.L=n.R=n.P=n.N=null}function ir(n,t){var e=t,r=t.R,i=e.U;i?i.L===e?i.L=r:i.R=r:n._=r,r.U=i,e.U=r,e.R=r.L,e.R&&(e.R.U=e),r.L=e}function ur(n,t){var e=t,r=t.L,i=e.U;i?i.L===e?i.L=r:i.R=r:n._=r,r.U=i,e.U=r,e.L=r.R,e.L&&(e.L.U=e),r.R=e}function or(n){for(;n.L;)n=n.L;return n}function ar(n,t){var e,r,i,u=n.sort(lr).pop();for(il=[],ul=new Array(n.length),ol=new er,ll=new er;;)if(i=al,u&&(!i||u.y<i.y||u.y===i.y&&u.x<i.x))u.x===e&&u.y===r||(ul[u.i]=new Ye(u),He(u),e=u.x,r=u.y),u=n.pop();else{if(!i)break;Fe(i.arc)}t&&(We(t),Ze(t));var o={cells:ul,edges:il};return ol=ll=il=ul=null,o}function lr(n,t){return t.y-n.y||t.x-n.x}function cr(n,t,e){return(n.x-e.x)*(t.y-n.y)-(n.x-t.x)*(e.y-n.y)}function fr(n){return n.x}function sr(n){return n.y}function hr(){return{leaf:!0,nodes:[],point:null,x:null,y:null}}function pr(n,t,e,r,i,u){if(!n(t,e,r,i,u)){var o=.5*(e+i),a=.5*(r+u),l=t.nodes;l[0]&&pr(n,l[0],e,r,o,a),l[1]&&pr(n,l[1],o,r,i,a),l[2]&&pr(n,l[2],e,a,o,u),l[3]&&pr(n,l[3],o,a,i,u)}}function gr(n,t,e,r,i,u,o){var a,l=1/0;return function c(n,f,s,h,p){if(!(f>u||s>o||r>h||i>p)){if(g=n.point){var g,v=t-n.x,d=e-n.y,y=v*v+d*d;if(l>y){var m=Math.sqrt(l=y);r=t-m,i=e-m,u=t+m,o=e+m,a=g}}for(var M=n.nodes,x=.5*(f+h),b=.5*(s+p),_=t>=x,w=e>=b,S=w<<1|_,k=S+4;k>S;++S)if(n=M[3&S])switch(3&S){case 0:c(n,f,s,x,b);break;case 1:c(n,x,s,h,b);break;case 2:c(n,f,b,x,p);break;case 3:c(n,x,b,h,p)}}}(n,r,i,u,o),a}function vr(n,t){n=ao.rgb(n),t=ao.rgb(t);var e=n.r,r=n.g,i=n.b,u=t.r-e,o=t.g-r,a=t.b-i;return function(n){return"#"+bn(Math.round(e+u*n))+bn(Math.round(r+o*n))+bn(Math.round(i+a*n))}}function dr(n,t){var e,r={},i={};for(e in n)e in t?r[e]=Mr(n[e],t[e]):i[e]=n[e];for(e in t)e in n||(i[e]=t[e]);return function(n){for(e in r)i[e]=r[e](n);return i}}function yr(n,t){return n=+n,t=+t,function(e){return n*(1-e)+t*e}}function mr(n,t){var e,r,i,u=hl.lastIndex=pl.lastIndex=0,o=-1,a=[],l=[];for(n+="",t+="";(e=hl.exec(n))&&(r=pl.exec(t));)(i=r.index)>u&&(i=t.slice(u,i),a[o]?a[o]+=i:a[++o]=i),(e=e[0])===(r=r[0])?a[o]?a[o]+=r:a[++o]=r:(a[++o]=null,l.push({i:o,x:yr(e,r)})),u=pl.lastIndex;return u<t.length&&(i=t.slice(u),a[o]?a[o]+=i:a[++o]=i),a.length<2?l[0]?(t=l[0].x,function(n){return t(n)+""}):function(){return t}:(t=l.length,function(n){for(var e,r=0;t>r;++r)a[(e=l[r]).i]=e.x(n);return a.join("")})}function Mr(n,t){for(var e,r=ao.interpolators.length;--r>=0&&!(e=ao.interpolators[r](n,t)););return e}function xr(n,t){var e,r=[],i=[],u=n.length,o=t.length,a=Math.min(n.length,t.length);for(e=0;a>e;++e)r.push(Mr(n[e],t[e]));for(;u>e;++e)i[e]=n[e];for(;o>e;++e)i[e]=t[e];return function(n){for(e=0;a>e;++e)i[e]=r[e](n);return i}}function br(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function _r(n){return function(t){return 1-n(1-t)}}function wr(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function Sr(n){return n*n}function kr(n){return n*n*n}function Nr(n){if(0>=n)return 0;if(n>=1)return 1;var t=n*n,e=t*n;return 4*(.5>n?e:3*(n-t)+e-.75)}function Er(n){return function(t){return Math.pow(t,n)}}function Ar(n){return 1-Math.cos(n*Io)}function Cr(n){return Math.pow(2,10*(n-1))}function zr(n){return 1-Math.sqrt(1-n*n)}function Lr(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/Ho*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,-10*r)*Math.sin((r-e)*Ho/t)}}function qr(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function Tr(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function Rr(n,t){n=ao.hcl(n),t=ao.hcl(t);var e=n.h,r=n.c,i=n.l,u=t.h-e,o=t.c-r,a=t.l-i;return isNaN(o)&&(o=0,r=isNaN(r)?t.c:r),isNaN(u)?(u=0,e=isNaN(e)?t.h:e):u>180?u-=360:-180>u&&(u+=360),function(n){return sn(e+u*n,r+o*n,i+a*n)+""}}function Dr(n,t){n=ao.hsl(n),t=ao.hsl(t);var e=n.h,r=n.s,i=n.l,u=t.h-e,o=t.s-r,a=t.l-i;return isNaN(o)&&(o=0,r=isNaN(r)?t.s:r),isNaN(u)?(u=0,e=isNaN(e)?t.h:e):u>180?u-=360:-180>u&&(u+=360),function(n){return cn(e+u*n,r+o*n,i+a*n)+""}}function Pr(n,t){n=ao.lab(n),t=ao.lab(t);var e=n.l,r=n.a,i=n.b,u=t.l-e,o=t.a-r,a=t.b-i;return function(n){return pn(e+u*n,r+o*n,i+a*n)+""}}function Ur(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function jr(n){var t=[n.a,n.b],e=[n.c,n.d],r=Hr(t),i=Fr(t,e),u=Hr(Or(e,t,-i))||0;t[0]*e[1]<e[0]*t[1]&&(t[0]*=-1,t[1]*=-1,r*=-1,i*=-1),this.rotate=(r?Math.atan2(t[1],t[0]):Math.atan2(-e[0],e[1]))*Zo,this.translate=[n.e,n.f],this.scale=[r,u],this.skew=u?Math.atan2(i,u)*Zo:0}function Fr(n,t){return n[0]*t[0]+n[1]*t[1]}function Hr(n){var t=Math.sqrt(Fr(n,n));return t&&(n[0]/=t,n[1]/=t),t}function Or(n,t,e){return n[0]+=e*t[0],n[1]+=e*t[1],n}function Ir(n){return n.length?n.pop()+",":""}function Yr(n,t,e,r){if(n[0]!==t[0]||n[1]!==t[1]){var i=e.push("translate(",null,",",null,")");r.push({i:i-4,x:yr(n[0],t[0])},{i:i-2,x:yr(n[1],t[1])})}else(t[0]||t[1])&&e.push("translate("+t+")")}function Zr(n,t,e,r){n!==t?(n-t>180?t+=360:t-n>180&&(n+=360),r.push({i:e.push(Ir(e)+"rotate(",null,")")-2,x:yr(n,t)})):t&&e.push(Ir(e)+"rotate("+t+")")}function Vr(n,t,e,r){n!==t?r.push({i:e.push(Ir(e)+"skewX(",null,")")-2,x:yr(n,t)}):t&&e.push(Ir(e)+"skewX("+t+")")}function Xr(n,t,e,r){if(n[0]!==t[0]||n[1]!==t[1]){var i=e.push(Ir(e)+"scale(",null,",",null,")");r.push({i:i-4,x:yr(n[0],t[0])},{i:i-2,x:yr(n[1],t[1])})}else 1===t[0]&&1===t[1]||e.push(Ir(e)+"scale("+t+")")}function $r(n,t){var e=[],r=[];return n=ao.transform(n),t=ao.transform(t),Yr(n.translate,t.translate,e,r),Zr(n.rotate,t.rotate,e,r),Vr(n.skew,t.skew,e,r),Xr(n.scale,t.scale,e,r),n=t=null,function(n){for(var t,i=-1,u=r.length;++i<u;)e[(t=r[i]).i]=t.x(n);return e.join("")}}function Br(n,t){return t=(t-=n=+n)||1/t,function(e){return(e-n)/t}}function Wr(n,t){return t=(t-=n=+n)||1/t,function(e){return Math.max(0,Math.min(1,(e-n)/t))}}function Jr(n){for(var t=n.source,e=n.target,r=Kr(t,e),i=[t];t!==r;)t=t.parent,i.push(t);for(var u=i.length;e!==r;)i.splice(u,0,e),e=e.parent;return i}function Gr(n){for(var t=[],e=n.parent;null!=e;)t.push(n),n=e,e=e.parent;return t.push(n),t}function Kr(n,t){if(n===t)return n;for(var e=Gr(n),r=Gr(t),i=e.pop(),u=r.pop(),o=null;i===u;)o=i,i=e.pop(),u=r.pop();return o}function Qr(n){n.fixed|=2}function ni(n){n.fixed&=-7}function ti(n){n.fixed|=4,n.px=n.x,n.py=n.y}function ei(n){n.fixed&=-5}function ri(n,t,e){var r=0,i=0;if(n.charge=0,!n.leaf)for(var u,o=n.nodes,a=o.length,l=-1;++l<a;)u=o[l],null!=u&&(ri(u,t,e),n.charge+=u.charge,r+=u.charge*u.cx,i+=u.charge*u.cy);if(n.point){n.leaf||(n.point.x+=Math.random()-.5,n.point.y+=Math.random()-.5);var c=t*e[n.point.index];n.charge+=n.pointCharge=c,r+=c*n.point.x,i+=c*n.point.y}n.cx=r/n.charge,n.cy=i/n.charge}function ii(n,t){return ao.rebind(n,t,"sort","children","value"),n.nodes=n,n.links=fi,n}function ui(n,t){for(var e=[n];null!=(n=e.pop());)if(t(n),(i=n.children)&&(r=i.length))for(var r,i;--r>=0;)e.push(i[r])}function oi(n,t){for(var e=[n],r=[];null!=(n=e.pop());)if(r.push(n),(u=n.children)&&(i=u.length))for(var i,u,o=-1;++o<i;)e.push(u[o]);for(;null!=(n=r.pop());)t(n)}function ai(n){return n.children}function li(n){return n.value}function ci(n,t){return t.value-n.value}function fi(n){return ao.merge(n.map(function(n){return(n.children||[]).map(function(t){return{source:n,target:t}})}))}function si(n){return n.x}function hi(n){return n.y}function pi(n,t,e){n.y0=t,n.y=e}function gi(n){return ao.range(n.length)}function vi(n){for(var t=-1,e=n[0].length,r=[];++t<e;)r[t]=0;return r}function di(n){for(var t,e=1,r=0,i=n[0][1],u=n.length;u>e;++e)(t=n[e][1])>i&&(r=e,i=t);return r}function yi(n){return n.reduce(mi,0)}function mi(n,t){return n+t[1]}function Mi(n,t){return xi(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function xi(n,t){for(var e=-1,r=+n[0],i=(n[1]-r)/t,u=[];++e<=t;)u[e]=i*e+r;return u}function bi(n){return[ao.min(n),ao.max(n)]}function _i(n,t){return n.value-t.value}function wi(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function Si(n,t){n._pack_next=t,t._pack_prev=n}function ki(n,t){var e=t.x-n.x,r=t.y-n.y,i=n.r+t.r;return.999*i*i>e*e+r*r}function Ni(n){function t(n){f=Math.min(n.x-n.r,f),s=Math.max(n.x+n.r,s),h=Math.min(n.y-n.r,h),p=Math.max(n.y+n.r,p)}if((e=n.children)&&(c=e.length)){var e,r,i,u,o,a,l,c,f=1/0,s=-(1/0),h=1/0,p=-(1/0);if(e.forEach(Ei),r=e[0],r.x=-r.r,r.y=0,t(r),c>1&&(i=e[1],i.x=i.r,i.y=0,t(i),c>2))for(u=e[2],zi(r,i,u),t(u),wi(r,u),r._pack_prev=u,wi(u,i),i=r._pack_next,o=3;c>o;o++){zi(r,i,u=e[o]);var g=0,v=1,d=1;for(a=i._pack_next;a!==i;a=a._pack_next,v++)if(ki(a,u)){g=1;break}if(1==g)for(l=r._pack_prev;l!==a._pack_prev&&!ki(l,u);l=l._pack_prev,d++);g?(d>v||v==d&&i.r<r.r?Si(r,i=a):Si(r=l,i),o--):(wi(r,u),i=u,t(u))}var y=(f+s)/2,m=(h+p)/2,M=0;for(o=0;c>o;o++)u=e[o],u.x-=y,u.y-=m,M=Math.max(M,u.r+Math.sqrt(u.x*u.x+u.y*u.y));n.r=M,e.forEach(Ai)}}function Ei(n){n._pack_next=n._pack_prev=n}function Ai(n){delete n._pack_next,delete n._pack_prev}function Ci(n,t,e,r){var i=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,i)for(var u=-1,o=i.length;++u<o;)Ci(i[u],t,e,r)}function zi(n,t,e){var r=n.r+e.r,i=t.x-n.x,u=t.y-n.y;if(r&&(i||u)){var o=t.r+e.r,a=i*i+u*u;o*=o,r*=r;var l=.5+(r-o)/(2*a),c=Math.sqrt(Math.max(0,2*o*(r+a)-(r-=a)*r-o*o))/(2*a);e.x=n.x+l*i+c*u,e.y=n.y+l*u-c*i}else e.x=n.x+r,e.y=n.y}function Li(n,t){return n.parent==t.parent?1:2}function qi(n){var t=n.children;return t.length?t[0]:n.t}function Ti(n){var t,e=n.children;return(t=e.length)?e[t-1]:n.t}function Ri(n,t,e){var r=e/(t.i-n.i);t.c-=r,t.s+=e,n.c+=r,t.z+=e,t.m+=e}function Di(n){for(var t,e=0,r=0,i=n.children,u=i.length;--u>=0;)t=i[u],t.z+=e,t.m+=e,e+=t.s+(r+=t.c)}function Pi(n,t,e){return n.a.parent===t.parent?n.a:e}function Ui(n){return 1+ao.max(n,function(n){return n.y})}function ji(n){return n.reduce(function(n,t){return n+t.x},0)/n.length}function Fi(n){var t=n.children;return t&&t.length?Fi(t[0]):n}function Hi(n){var t,e=n.children;return e&&(t=e.length)?Hi(e[t-1]):n}function Oi(n){return{x:n.x,y:n.y,dx:n.dx,dy:n.dy}}function Ii(n,t){var e=n.x+t[3],r=n.y+t[0],i=n.dx-t[1]-t[3],u=n.dy-t[0]-t[2];return 0>i&&(e+=i/2,i=0),0>u&&(r+=u/2,u=0),{x:e,y:r,dx:i,dy:u}}function Yi(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Zi(n){return n.rangeExtent?n.rangeExtent():Yi(n.range())}function Vi(n,t,e,r){var i=e(n[0],n[1]),u=r(t[0],t[1]);return function(n){return u(i(n))}}function Xi(n,t){var e,r=0,i=n.length-1,u=n[r],o=n[i];return u>o&&(e=r,r=i,i=e,e=u,u=o,o=e),n[r]=t.floor(u),n[i]=t.ceil(o),n}function $i(n){return n?{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}:Sl}function Bi(n,t,e,r){var i=[],u=[],o=0,a=Math.min(n.length,t.length)-1;for(n[a]<n[0]&&(n=n.slice().reverse(),t=t.slice().reverse());++o<=a;)i.push(e(n[o-1],n[o])),u.push(r(t[o-1],t[o]));return function(t){var e=ao.bisect(n,t,1,a)-1;return u[e](i[e](t))}}function Wi(n,t,e,r){function i(){var i=Math.min(n.length,t.length)>2?Bi:Vi,l=r?Wr:Br;return o=i(n,t,l,e),a=i(t,n,l,Mr),u}function u(n){return o(n)}var o,a;return u.invert=function(n){return a(n)},u.domain=function(t){return arguments.length?(n=t.map(Number),i()):n},u.range=function(n){return arguments.length?(t=n,i()):t},u.rangeRound=function(n){return u.range(n).interpolate(Ur)},u.clamp=function(n){return arguments.length?(r=n,i()):r},u.interpolate=function(n){return arguments.length?(e=n,i()):e},u.ticks=function(t){return Qi(n,t)},u.tickFormat=function(t,e){return nu(n,t,e)},u.nice=function(t){return Gi(n,t),i()},u.copy=function(){return Wi(n,t,e,r)},i()}function Ji(n,t){return ao.rebind(n,t,"range","rangeRound","interpolate","clamp")}function Gi(n,t){return Xi(n,$i(Ki(n,t)[2])),Xi(n,$i(Ki(n,t)[2])),n}function Ki(n,t){null==t&&(t=10);var e=Yi(n),r=e[1]-e[0],i=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),u=t/r*i;return.15>=u?i*=10:.35>=u?i*=5:.75>=u&&(i*=2),e[0]=Math.ceil(e[0]/i)*i,e[1]=Math.floor(e[1]/i)*i+.5*i,e[2]=i,e}function Qi(n,t){return ao.range.apply(ao,Ki(n,t))}function nu(n,t,e){var r=Ki(n,t);if(e){var i=ha.exec(e);if(i.shift(),"s"===i[8]){var u=ao.formatPrefix(Math.max(xo(r[0]),xo(r[1])));return i[7]||(i[7]="."+tu(u.scale(r[2]))),i[8]="f",e=ao.format(i.join("")),function(n){return e(u.scale(n))+u.symbol}}i[7]||(i[7]="."+eu(i[8],r)),e=i.join("")}else e=",."+tu(r[2])+"f";return ao.format(e)}function tu(n){return-Math.floor(Math.log(n)/Math.LN10+.01)}function eu(n,t){var e=tu(t[2]);return n in kl?Math.abs(e-tu(Math.max(xo(t[0]),xo(t[1]))))+ +("e"!==n):e-2*("%"===n)}function ru(n,t,e,r){function i(n){return(e?Math.log(0>n?0:n):-Math.log(n>0?0:-n))/Math.log(t)}function u(n){return e?Math.pow(t,n):-Math.pow(t,-n)}function o(t){return n(i(t))}return o.invert=function(t){return u(n.invert(t))},o.domain=function(t){return arguments.length?(e=t[0]>=0,n.domain((r=t.map(Number)).map(i)),o):r},o.base=function(e){return arguments.length?(t=+e,n.domain(r.map(i)),o):t},o.nice=function(){var t=Xi(r.map(i),e?Math:El);return n.domain(t),r=t.map(u),o},o.ticks=function(){var n=Yi(r),o=[],a=n[0],l=n[1],c=Math.floor(i(a)),f=Math.ceil(i(l)),s=t%1?2:t;if(isFinite(f-c)){if(e){for(;f>c;c++)for(var h=1;s>h;h++)o.push(u(c)*h);o.push(u(c))}else for(o.push(u(c));c++<f;)for(var h=s-1;h>0;h--)o.push(u(c)*h);for(c=0;o[c]<a;c++);for(f=o.length;o[f-1]>l;f--);o=o.slice(c,f)}return o},o.tickFormat=function(n,e){if(!arguments.length)return Nl;arguments.length<2?e=Nl:"function"!=typeof e&&(e=ao.format(e));var r=Math.max(1,t*n/o.ticks().length);return function(n){var o=n/u(Math.round(i(n)));return t-.5>o*t&&(o*=t),r>=o?e(n):""}},o.copy=function(){return ru(n.copy(),t,e,r)},Ji(o,n)}function iu(n,t,e){function r(t){return n(i(t))}var i=uu(t),u=uu(1/t);return r.invert=function(t){return u(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(i)),r):e},r.ticks=function(n){return Qi(e,n)},r.tickFormat=function(n,t){return nu(e,n,t)},r.nice=function(n){return r.domain(Gi(e,n))},r.exponent=function(o){return arguments.length?(i=uu(t=o),u=uu(1/t),n.domain(e.map(i)),r):t},r.copy=function(){return iu(n.copy(),t,e)},Ji(r,n)}function uu(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function ou(n,t){function e(e){return u[((i.get(e)||("range"===t.t?i.set(e,n.push(e)):NaN))-1)%u.length]}function r(t,e){return ao.range(n.length).map(function(n){return t+e*n})}var i,u,o;return e.domain=function(r){if(!arguments.length)return n;n=[],i=new c;for(var u,o=-1,a=r.length;++o<a;)i.has(u=r[o])||i.set(u,n.push(u));return e[t.t].apply(e,t.a)},e.range=function(n){return arguments.length?(u=n,o=0,t={t:"range",a:arguments},e):u},e.rangePoints=function(i,a){arguments.length<2&&(a=0);var l=i[0],c=i[1],f=n.length<2?(l=(l+c)/2,0):(c-l)/(n.length-1+a);return u=r(l+f*a/2,f),o=0,t={t:"rangePoints",a:arguments},e},e.rangeRoundPoints=function(i,a){arguments.length<2&&(a=0);var l=i[0],c=i[1],f=n.length<2?(l=c=Math.round((l+c)/2),0):(c-l)/(n.length-1+a)|0;return u=r(l+Math.round(f*a/2+(c-l-(n.length-1+a)*f)/2),f),o=0,t={t:"rangeRoundPoints",a:arguments},e},e.rangeBands=function(i,a,l){arguments.length<2&&(a=0),arguments.length<3&&(l=a);var c=i[1]<i[0],f=i[c-0],s=i[1-c],h=(s-f)/(n.length-a+2*l);return u=r(f+h*l,h),c&&u.reverse(),o=h*(1-a),t={t:"rangeBands",a:arguments},e},e.rangeRoundBands=function(i,a,l){arguments.length<2&&(a=0),arguments.length<3&&(l=a);var c=i[1]<i[0],f=i[c-0],s=i[1-c],h=Math.floor((s-f)/(n.length-a+2*l));return u=r(f+Math.round((s-f-(n.length-a)*h)/2),h),c&&u.reverse(),o=Math.round(h*(1-a)),t={t:"rangeRoundBands",a:arguments},e},e.rangeBand=function(){return o},e.rangeExtent=function(){return Yi(t.a[0])},e.copy=function(){return ou(n,t)},e.domain(n)}function au(n,t){function u(){var e=0,r=t.length;for(a=[];++e<r;)a[e-1]=ao.quantile(n,e/r);return o}function o(n){return isNaN(n=+n)?void 0:t[ao.bisect(a,n)]}var a;return o.domain=function(t){return arguments.length?(n=t.map(r).filter(i).sort(e),u()):n},o.range=function(n){return arguments.length?(t=n,u()):t},o.quantiles=function(){return a},o.invertExtent=function(e){return e=t.indexOf(e),0>e?[NaN,NaN]:[e>0?a[e-1]:n[0],e<a.length?a[e]:n[n.length-1]]},o.copy=function(){return au(n,t)},u()}function lu(n,t,e){function r(t){return e[Math.max(0,Math.min(o,Math.floor(u*(t-n))))]}function i(){return u=e.length/(t-n),o=e.length-1,r}var u,o;return r.domain=function(e){return arguments.length?(n=+e[0],t=+e[e.length-1],i()):[n,t]},r.range=function(n){return arguments.length?(e=n,i()):e},r.invertExtent=function(t){return t=e.indexOf(t),t=0>t?NaN:t/u+n,[t,t+1/u]},r.copy=function(){return lu(n,t,e)},i()}function cu(n,t){function e(e){return e>=e?t[ao.bisect(n,e)]:void 0}return e.domain=function(t){return arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.invertExtent=function(e){return e=t.indexOf(e),[n[e-1],n[e]]},e.copy=function(){return cu(n,t)},e}function fu(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return Qi(n,t)},t.tickFormat=function(t,e){return nu(n,t,e)},t.copy=function(){return fu(n)},t}function su(){return 0}function hu(n){return n.innerRadius}function pu(n){return n.outerRadius}function gu(n){return n.startAngle}function vu(n){return n.endAngle}function du(n){return n&&n.padAngle}function yu(n,t,e,r){return(n-e)*t-(t-r)*n>0?0:1}function mu(n,t,e,r,i){var u=n[0]-t[0],o=n[1]-t[1],a=(i?r:-r)/Math.sqrt(u*u+o*o),l=a*o,c=-a*u,f=n[0]+l,s=n[1]+c,h=t[0]+l,p=t[1]+c,g=(f+h)/2,v=(s+p)/2,d=h-f,y=p-s,m=d*d+y*y,M=e-r,x=f*p-h*s,b=(0>y?-1:1)*Math.sqrt(Math.max(0,M*M*m-x*x)),_=(x*y-d*b)/m,w=(-x*d-y*b)/m,S=(x*y+d*b)/m,k=(-x*d+y*b)/m,N=_-g,E=w-v,A=S-g,C=k-v;return N*N+E*E>A*A+C*C&&(_=S,w=k),[[_-l,w-c],[_*e/M,w*e/M]]}function Mu(n){function t(t){function o(){c.push("M",u(n(f),a))}for(var l,c=[],f=[],s=-1,h=t.length,p=En(e),g=En(r);++s<h;)i.call(this,l=t[s],s)?f.push([+p.call(this,l,s),+g.call(this,l,s)]):f.length&&(o(),f=[]);return f.length&&o(),c.length?c.join(""):null}var e=Ce,r=ze,i=zt,u=xu,o=u.key,a=.7;return t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t.defined=function(n){return arguments.length?(i=n,t):i},t.interpolate=function(n){return arguments.length?(o="function"==typeof n?u=n:(u=Tl.get(n)||xu).key,t):o},t.tension=function(n){return arguments.length?(a=n,t):a},t}function xu(n){return n.length>1?n.join("L"):n+"Z"}function bu(n){return n.join("L")+"Z"}function _u(n){for(var t=0,e=n.length,r=n[0],i=[r[0],",",r[1]];++t<e;)i.push("H",(r[0]+(r=n[t])[0])/2,"V",r[1]);return e>1&&i.push("H",r[0]),i.join("")}function wu(n){for(var t=0,e=n.length,r=n[0],i=[r[0],",",r[1]];++t<e;)i.push("V",(r=n[t])[1],"H",r[0]);return i.join("")}function Su(n){for(var t=0,e=n.length,r=n[0],i=[r[0],",",r[1]];++t<e;)i.push("H",(r=n[t])[0],"V",r[1]);return i.join("")}function ku(n,t){return n.length<4?xu(n):n[1]+Au(n.slice(1,-1),Cu(n,t))}function Nu(n,t){return n.length<3?bu(n):n[0]+Au((n.push(n[0]),n),Cu([n[n.length-2]].concat(n,[n[1]]),t))}function Eu(n,t){return n.length<3?xu(n):n[0]+Au(n,Cu(n,t))}function Au(n,t){if(t.length<1||n.length!=t.length&&n.length!=t.length+2)return xu(n);var e=n.length!=t.length,r="",i=n[0],u=n[1],o=t[0],a=o,l=1;if(e&&(r+="Q"+(u[0]-2*o[0]/3)+","+(u[1]-2*o[1]/3)+","+u[0]+","+u[1],i=n[1],l=2),t.length>1){a=t[1],u=n[l],l++,r+="C"+(i[0]+o[0])+","+(i[1]+o[1])+","+(u[0]-a[0])+","+(u[1]-a[1])+","+u[0]+","+u[1];for(var c=2;c<t.length;c++,l++)u=n[l],a=t[c],r+="S"+(u[0]-a[0])+","+(u[1]-a[1])+","+u[0]+","+u[1]}if(e){var f=n[l];r+="Q"+(u[0]+2*a[0]/3)+","+(u[1]+2*a[1]/3)+","+f[0]+","+f[1]}return r}function Cu(n,t){for(var e,r=[],i=(1-t)/2,u=n[0],o=n[1],a=1,l=n.length;++a<l;)e=u,u=o,o=n[a],r.push([i*(o[0]-e[0]),i*(o[1]-e[1])]);return r}function zu(n){if(n.length<3)return xu(n);var t=1,e=n.length,r=n[0],i=r[0],u=r[1],o=[i,i,i,(r=n[1])[0]],a=[u,u,u,r[1]],l=[i,",",u,"L",Ru(Pl,o),",",Ru(Pl,a)];for(n.push(n[e-1]);++t<=e;)r=n[t],o.shift(),o.push(r[0]),a.shift(),a.push(r[1]),Du(l,o,a);return n.pop(),l.push("L",r),l.join("")}function Lu(n){if(n.length<4)return xu(n);for(var t,e=[],r=-1,i=n.length,u=[0],o=[0];++r<3;)t=n[r],u.push(t[0]),o.push(t[1]);for(e.push(Ru(Pl,u)+","+Ru(Pl,o)),--r;++r<i;)t=n[r],u.shift(),u.push(t[0]),o.shift(),o.push(t[1]),Du(e,u,o);return e.join("")}function qu(n){for(var t,e,r=-1,i=n.length,u=i+4,o=[],a=[];++r<4;)e=n[r%i],o.push(e[0]),a.push(e[1]);for(t=[Ru(Pl,o),",",Ru(Pl,a)],--r;++r<u;)e=n[r%i],o.shift(),o.push(e[0]),a.shift(),a.push(e[1]),Du(t,o,a);return t.join("")}function Tu(n,t){var e=n.length-1;if(e)for(var r,i,u=n[0][0],o=n[0][1],a=n[e][0]-u,l=n[e][1]-o,c=-1;++c<=e;)r=n[c],i=c/e,r[0]=t*r[0]+(1-t)*(u+i*a),r[1]=t*r[1]+(1-t)*(o+i*l);return zu(n)}function Ru(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]+n[3]*t[3]}function Du(n,t,e){n.push("C",Ru(Rl,t),",",Ru(Rl,e),",",Ru(Dl,t),",",Ru(Dl,e),",",Ru(Pl,t),",",Ru(Pl,e))}function Pu(n,t){return(t[1]-n[1])/(t[0]-n[0])}function Uu(n){for(var t=0,e=n.length-1,r=[],i=n[0],u=n[1],o=r[0]=Pu(i,u);++t<e;)r[t]=(o+(o=Pu(i=u,u=n[t+1])))/2;return r[t]=o,r}function ju(n){for(var t,e,r,i,u=[],o=Uu(n),a=-1,l=n.length-1;++a<l;)t=Pu(n[a],n[a+1]),xo(t)<Uo?o[a]=o[a+1]=0:(e=o[a]/t,r=o[a+1]/t,i=e*e+r*r,i>9&&(i=3*t/Math.sqrt(i),o[a]=i*e,o[a+1]=i*r));for(a=-1;++a<=l;)i=(n[Math.min(l,a+1)][0]-n[Math.max(0,a-1)][0])/(6*(1+o[a]*o[a])),u.push([i||0,o[a]*i||0]);return u}function Fu(n){return n.length<3?xu(n):n[0]+Au(n,ju(n))}function Hu(n){for(var t,e,r,i=-1,u=n.length;++i<u;)t=n[i],e=t[0],r=t[1]-Io,t[0]=e*Math.cos(r),t[1]=e*Math.sin(r);return n}function Ou(n){function t(t){function l(){v.push("M",a(n(y),s),f,c(n(d.reverse()),s),"Z")}for(var h,p,g,v=[],d=[],y=[],m=-1,M=t.length,x=En(e),b=En(i),_=e===r?function(){
|
3 |
-
return p}:En(r),w=i===u?function(){return g}:En(u);++m<M;)o.call(this,h=t[m],m)?(d.push([p=+x.call(this,h,m),g=+b.call(this,h,m)]),y.push([+_.call(this,h,m),+w.call(this,h,m)])):d.length&&(l(),d=[],y=[]);return d.length&&l(),v.length?v.join(""):null}var e=Ce,r=Ce,i=0,u=ze,o=zt,a=xu,l=a.key,c=a,f="L",s=.7;return t.x=function(n){return arguments.length?(e=r=n,t):r},t.x0=function(n){return arguments.length?(e=n,t):e},t.x1=function(n){return arguments.length?(r=n,t):r},t.y=function(n){return arguments.length?(i=u=n,t):u},t.y0=function(n){return arguments.length?(i=n,t):i},t.y1=function(n){return arguments.length?(u=n,t):u},t.defined=function(n){return arguments.length?(o=n,t):o},t.interpolate=function(n){return arguments.length?(l="function"==typeof n?a=n:(a=Tl.get(n)||xu).key,c=a.reverse||a,f=a.closed?"M":"L",t):l},t.tension=function(n){return arguments.length?(s=n,t):s},t}function Iu(n){return n.radius}function Yu(n){return[n.x,n.y]}function Zu(n){return function(){var t=n.apply(this,arguments),e=t[0],r=t[1]-Io;return[e*Math.cos(r),e*Math.sin(r)]}}function Vu(){return 64}function Xu(){return"circle"}function $u(n){var t=Math.sqrt(n/Fo);return"M0,"+t+"A"+t+","+t+" 0 1,1 0,"+-t+"A"+t+","+t+" 0 1,1 0,"+t+"Z"}function Bu(n){return function(){var t,e,r;(t=this[n])&&(r=t[e=t.active])&&(r.timer.c=null,r.timer.t=NaN,--t.count?delete t[e]:delete this[n],t.active+=.5,r.event&&r.event.interrupt.call(this,this.__data__,r.index))}}function Wu(n,t,e){return ko(n,Yl),n.namespace=t,n.id=e,n}function Ju(n,t,e,r){var i=n.id,u=n.namespace;return Y(n,"function"==typeof e?function(n,o,a){n[u][i].tween.set(t,r(e.call(n,n.__data__,o,a)))}:(e=r(e),function(n){n[u][i].tween.set(t,e)}))}function Gu(n){return null==n&&(n=""),function(){this.textContent=n}}function Ku(n){return null==n?"__transition__":"__transition_"+n+"__"}function Qu(n,t,e,r,i){function u(n){var t=v.delay;return f.t=t+l,n>=t?o(n-t):void(f.c=o)}function o(e){var i=g.active,u=g[i];u&&(u.timer.c=null,u.timer.t=NaN,--g.count,delete g[i],u.event&&u.event.interrupt.call(n,n.__data__,u.index));for(var o in g)if(r>+o){var c=g[o];c.timer.c=null,c.timer.t=NaN,--g.count,delete g[o]}f.c=a,qn(function(){return f.c&&a(e||1)&&(f.c=null,f.t=NaN),1},0,l),g.active=r,v.event&&v.event.start.call(n,n.__data__,t),p=[],v.tween.forEach(function(e,r){(r=r.call(n,n.__data__,t))&&p.push(r)}),h=v.ease,s=v.duration}function a(i){for(var u=i/s,o=h(u),a=p.length;a>0;)p[--a].call(n,o);return u>=1?(v.event&&v.event.end.call(n,n.__data__,t),--g.count?delete g[r]:delete n[e],1):void 0}var l,f,s,h,p,g=n[e]||(n[e]={active:0,count:0}),v=g[r];v||(l=i.time,f=qn(u,0,l),v=g[r]={tween:new c,time:l,timer:f,delay:i.delay,duration:i.duration,ease:i.ease,index:t},i=null,++g.count)}function no(n,t,e){n.attr("transform",function(n){var r=t(n);return"translate("+(isFinite(r)?r:e(n))+",0)"})}function to(n,t,e){n.attr("transform",function(n){var r=t(n);return"translate(0,"+(isFinite(r)?r:e(n))+")"})}function eo(n){return n.toISOString()}function ro(n,t,e){function r(t){return n(t)}function i(n,e){var r=n[1]-n[0],i=r/e,u=ao.bisect(Kl,i);return u==Kl.length?[t.year,Ki(n.map(function(n){return n/31536e6}),e)[2]]:u?t[i/Kl[u-1]<Kl[u]/i?u-1:u]:[tc,Ki(n,e)[2]]}return r.invert=function(t){return io(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain(t),r):n.domain().map(io)},r.nice=function(n,t){function e(e){return!isNaN(e)&&!n.range(e,io(+e+1),t).length}var u=r.domain(),o=Yi(u),a=null==n?i(o,10):"number"==typeof n&&i(o,n);return a&&(n=a[0],t=a[1]),r.domain(Xi(u,t>1?{floor:function(t){for(;e(t=n.floor(t));)t=io(t-1);return t},ceil:function(t){for(;e(t=n.ceil(t));)t=io(+t+1);return t}}:n))},r.ticks=function(n,t){var e=Yi(r.domain()),u=null==n?i(e,10):"number"==typeof n?i(e,n):!n.range&&[{range:n},t];return u&&(n=u[0],t=u[1]),n.range(e[0],io(+e[1]+1),1>t?1:t)},r.tickFormat=function(){return e},r.copy=function(){return ro(n.copy(),t,e)},Ji(r,n)}function io(n){return new Date(n)}function uo(n){return JSON.parse(n.responseText)}function oo(n){var t=fo.createRange();return t.selectNode(fo.body),t.createContextualFragment(n.responseText)}var ao={version:"3.5.17"},lo=[].slice,co=function(n){return lo.call(n)},fo=this.document;if(fo)try{co(fo.documentElement.childNodes)[0].nodeType}catch(so){co=function(n){for(var t=n.length,e=new Array(t);t--;)e[t]=n[t];return e}}if(Date.now||(Date.now=function(){return+new Date}),fo)try{fo.createElement("DIV").style.setProperty("opacity",0,"")}catch(ho){var po=this.Element.prototype,go=po.setAttribute,vo=po.setAttributeNS,yo=this.CSSStyleDeclaration.prototype,mo=yo.setProperty;po.setAttribute=function(n,t){go.call(this,n,t+"")},po.setAttributeNS=function(n,t,e){vo.call(this,n,t,e+"")},yo.setProperty=function(n,t,e){mo.call(this,n,t+"",e)}}ao.ascending=e,ao.descending=function(n,t){return n>t?-1:t>n?1:t>=n?0:NaN},ao.min=function(n,t){var e,r,i=-1,u=n.length;if(1===arguments.length){for(;++i<u;)if(null!=(r=n[i])&&r>=r){e=r;break}for(;++i<u;)null!=(r=n[i])&&e>r&&(e=r)}else{for(;++i<u;)if(null!=(r=t.call(n,n[i],i))&&r>=r){e=r;break}for(;++i<u;)null!=(r=t.call(n,n[i],i))&&e>r&&(e=r)}return e},ao.max=function(n,t){var e,r,i=-1,u=n.length;if(1===arguments.length){for(;++i<u;)if(null!=(r=n[i])&&r>=r){e=r;break}for(;++i<u;)null!=(r=n[i])&&r>e&&(e=r)}else{for(;++i<u;)if(null!=(r=t.call(n,n[i],i))&&r>=r){e=r;break}for(;++i<u;)null!=(r=t.call(n,n[i],i))&&r>e&&(e=r)}return e},ao.extent=function(n,t){var e,r,i,u=-1,o=n.length;if(1===arguments.length){for(;++u<o;)if(null!=(r=n[u])&&r>=r){e=i=r;break}for(;++u<o;)null!=(r=n[u])&&(e>r&&(e=r),r>i&&(i=r))}else{for(;++u<o;)if(null!=(r=t.call(n,n[u],u))&&r>=r){e=i=r;break}for(;++u<o;)null!=(r=t.call(n,n[u],u))&&(e>r&&(e=r),r>i&&(i=r))}return[e,i]},ao.sum=function(n,t){var e,r=0,u=n.length,o=-1;if(1===arguments.length)for(;++o<u;)i(e=+n[o])&&(r+=e);else for(;++o<u;)i(e=+t.call(n,n[o],o))&&(r+=e);return r},ao.mean=function(n,t){var e,u=0,o=n.length,a=-1,l=o;if(1===arguments.length)for(;++a<o;)i(e=r(n[a]))?u+=e:--l;else for(;++a<o;)i(e=r(t.call(n,n[a],a)))?u+=e:--l;return l?u/l:void 0},ao.quantile=function(n,t){var e=(n.length-1)*t+1,r=Math.floor(e),i=+n[r-1],u=e-r;return u?i+u*(n[r]-i):i},ao.median=function(n,t){var u,o=[],a=n.length,l=-1;if(1===arguments.length)for(;++l<a;)i(u=r(n[l]))&&o.push(u);else for(;++l<a;)i(u=r(t.call(n,n[l],l)))&&o.push(u);return o.length?ao.quantile(o.sort(e),.5):void 0},ao.variance=function(n,t){var e,u,o=n.length,a=0,l=0,c=-1,f=0;if(1===arguments.length)for(;++c<o;)i(e=r(n[c]))&&(u=e-a,a+=u/++f,l+=u*(e-a));else for(;++c<o;)i(e=r(t.call(n,n[c],c)))&&(u=e-a,a+=u/++f,l+=u*(e-a));return f>1?l/(f-1):void 0},ao.deviation=function(){var n=ao.variance.apply(this,arguments);return n?Math.sqrt(n):n};var Mo=u(e);ao.bisectLeft=Mo.left,ao.bisect=ao.bisectRight=Mo.right,ao.bisector=function(n){return u(1===n.length?function(t,r){return e(n(t),r)}:n)},ao.shuffle=function(n,t,e){(u=arguments.length)<3&&(e=n.length,2>u&&(t=0));for(var r,i,u=e-t;u;)i=Math.random()*u--|0,r=n[u+t],n[u+t]=n[i+t],n[i+t]=r;return n},ao.permute=function(n,t){for(var e=t.length,r=new Array(e);e--;)r[e]=n[t[e]];return r},ao.pairs=function(n){for(var t,e=0,r=n.length-1,i=n[0],u=new Array(0>r?0:r);r>e;)u[e]=[t=i,i=n[++e]];return u},ao.transpose=function(n){if(!(i=n.length))return[];for(var t=-1,e=ao.min(n,o),r=new Array(e);++t<e;)for(var i,u=-1,a=r[t]=new Array(i);++u<i;)a[u]=n[u][t];return r},ao.zip=function(){return ao.transpose(arguments)},ao.keys=function(n){var t=[];for(var e in n)t.push(e);return t},ao.values=function(n){var t=[];for(var e in n)t.push(n[e]);return t},ao.entries=function(n){var t=[];for(var e in n)t.push({key:e,value:n[e]});return t},ao.merge=function(n){for(var t,e,r,i=n.length,u=-1,o=0;++u<i;)o+=n[u].length;for(e=new Array(o);--i>=0;)for(r=n[i],t=r.length;--t>=0;)e[--o]=r[t];return e};var xo=Math.abs;ao.range=function(n,t,e){if(arguments.length<3&&(e=1,arguments.length<2&&(t=n,n=0)),(t-n)/e===1/0)throw new Error("infinite range");var r,i=[],u=a(xo(e)),o=-1;if(n*=u,t*=u,e*=u,0>e)for(;(r=n+e*++o)>t;)i.push(r/u);else for(;(r=n+e*++o)<t;)i.push(r/u);return i},ao.map=function(n,t){var e=new c;if(n instanceof c)n.forEach(function(n,t){e.set(n,t)});else if(Array.isArray(n)){var r,i=-1,u=n.length;if(1===arguments.length)for(;++i<u;)e.set(i,n[i]);else for(;++i<u;)e.set(t.call(n,r=n[i],i),r)}else for(var o in n)e.set(o,n[o]);return e};var bo="__proto__",_o="\x00";l(c,{has:h,get:function(n){return this._[f(n)]},set:function(n,t){return this._[f(n)]=t},remove:p,keys:g,values:function(){var n=[];for(var t in this._)n.push(this._[t]);return n},entries:function(){var n=[];for(var t in this._)n.push({key:s(t),value:this._[t]});return n},size:v,empty:d,forEach:function(n){for(var t in this._)n.call(this,s(t),this._[t])}}),ao.nest=function(){function n(t,o,a){if(a>=u.length)return r?r.call(i,o):e?o.sort(e):o;for(var l,f,s,h,p=-1,g=o.length,v=u[a++],d=new c;++p<g;)(h=d.get(l=v(f=o[p])))?h.push(f):d.set(l,[f]);return t?(f=t(),s=function(e,r){f.set(e,n(t,r,a))}):(f={},s=function(e,r){f[e]=n(t,r,a)}),d.forEach(s),f}function t(n,e){if(e>=u.length)return n;var r=[],i=o[e++];return n.forEach(function(n,i){r.push({key:n,values:t(i,e)})}),i?r.sort(function(n,t){return i(n.key,t.key)}):r}var e,r,i={},u=[],o=[];return i.map=function(t,e){return n(e,t,0)},i.entries=function(e){return t(n(ao.map,e,0),0)},i.key=function(n){return u.push(n),i},i.sortKeys=function(n){return o[u.length-1]=n,i},i.sortValues=function(n){return e=n,i},i.rollup=function(n){return r=n,i},i},ao.set=function(n){var t=new y;if(n)for(var e=0,r=n.length;r>e;++e)t.add(n[e]);return t},l(y,{has:h,add:function(n){return this._[f(n+="")]=!0,n},remove:p,values:g,size:v,empty:d,forEach:function(n){for(var t in this._)n.call(this,s(t))}}),ao.behavior={},ao.rebind=function(n,t){for(var e,r=1,i=arguments.length;++r<i;)n[e=arguments[r]]=M(n,t,t[e]);return n};var wo=["webkit","ms","moz","Moz","o","O"];ao.dispatch=function(){for(var n=new _,t=-1,e=arguments.length;++t<e;)n[arguments[t]]=w(n);return n},_.prototype.on=function(n,t){var e=n.indexOf("."),r="";if(e>=0&&(r=n.slice(e+1),n=n.slice(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},ao.event=null,ao.requote=function(n){return n.replace(So,"\\$&")};var So=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,ko={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},No=function(n,t){return t.querySelector(n)},Eo=function(n,t){return t.querySelectorAll(n)},Ao=function(n,t){var e=n.matches||n[x(n,"matchesSelector")];return(Ao=function(n,t){return e.call(n,t)})(n,t)};"function"==typeof Sizzle&&(No=function(n,t){return Sizzle(n,t)[0]||null},Eo=Sizzle,Ao=Sizzle.matchesSelector),ao.selection=function(){return ao.select(fo.documentElement)};var Co=ao.selection.prototype=[];Co.select=function(n){var t,e,r,i,u=[];n=A(n);for(var o=-1,a=this.length;++o<a;){u.push(t=[]),t.parentNode=(r=this[o]).parentNode;for(var l=-1,c=r.length;++l<c;)(i=r[l])?(t.push(e=n.call(i,i.__data__,l,o)),e&&"__data__"in i&&(e.__data__=i.__data__)):t.push(null)}return E(u)},Co.selectAll=function(n){var t,e,r=[];n=C(n);for(var i=-1,u=this.length;++i<u;)for(var o=this[i],a=-1,l=o.length;++a<l;)(e=o[a])&&(r.push(t=co(n.call(e,e.__data__,a,i))),t.parentNode=e);return E(r)};var zo="http://www.w3.org/1999/xhtml",Lo={svg:"http://www.w3.org/2000/svg",xhtml:zo,xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};ao.ns={prefix:Lo,qualify:function(n){var t=n.indexOf(":"),e=n;return t>=0&&"xmlns"!==(e=n.slice(0,t))&&(n=n.slice(t+1)),Lo.hasOwnProperty(e)?{space:Lo[e],local:n}:n}},Co.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node();return n=ao.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(z(t,n[t]));return this}return this.each(z(n,t))},Co.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node(),r=(n=T(n)).length,i=-1;if(t=e.classList){for(;++i<r;)if(!t.contains(n[i]))return!1}else for(t=e.getAttribute("class");++i<r;)if(!q(n[i]).test(t))return!1;return!0}for(t in n)this.each(R(t,n[t]));return this}return this.each(R(n,t))},Co.style=function(n,e,r){var i=arguments.length;if(3>i){if("string"!=typeof n){2>i&&(e="");for(r in n)this.each(P(r,n[r],e));return this}if(2>i){var u=this.node();return t(u).getComputedStyle(u,null).getPropertyValue(n)}r=""}return this.each(P(n,e,r))},Co.property=function(n,t){if(arguments.length<2){if("string"==typeof n)return this.node()[n];for(t in n)this.each(U(t,n[t]));return this}return this.each(U(n,t))},Co.text=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?"":t}:null==n?function(){this.textContent=""}:function(){this.textContent=n}):this.node().textContent},Co.html=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?"":t}:null==n?function(){this.innerHTML=""}:function(){this.innerHTML=n}):this.node().innerHTML},Co.append=function(n){return n=j(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},Co.insert=function(n,t){return n=j(n),t=A(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments)||null)})},Co.remove=function(){return this.each(F)},Co.data=function(n,t){function e(n,e){var r,i,u,o=n.length,s=e.length,h=Math.min(o,s),p=new Array(s),g=new Array(s),v=new Array(o);if(t){var d,y=new c,m=new Array(o);for(r=-1;++r<o;)(i=n[r])&&(y.has(d=t.call(i,i.__data__,r))?v[r]=i:y.set(d,i),m[r]=d);for(r=-1;++r<s;)(i=y.get(d=t.call(e,u=e[r],r)))?i!==!0&&(p[r]=i,i.__data__=u):g[r]=H(u),y.set(d,!0);for(r=-1;++r<o;)r in m&&y.get(m[r])!==!0&&(v[r]=n[r])}else{for(r=-1;++r<h;)i=n[r],u=e[r],i?(i.__data__=u,p[r]=i):g[r]=H(u);for(;s>r;++r)g[r]=H(e[r]);for(;o>r;++r)v[r]=n[r]}g.update=p,g.parentNode=p.parentNode=v.parentNode=n.parentNode,a.push(g),l.push(p),f.push(v)}var r,i,u=-1,o=this.length;if(!arguments.length){for(n=new Array(o=(r=this[0]).length);++u<o;)(i=r[u])&&(n[u]=i.__data__);return n}var a=Z([]),l=E([]),f=E([]);if("function"==typeof n)for(;++u<o;)e(r=this[u],n.call(r,r.parentNode.__data__,u));else for(;++u<o;)e(r=this[u],n);return l.enter=function(){return a},l.exit=function(){return f},l},Co.datum=function(n){return arguments.length?this.property("__data__",n):this.property("__data__")},Co.filter=function(n){var t,e,r,i=[];"function"!=typeof n&&(n=O(n));for(var u=0,o=this.length;o>u;u++){i.push(t=[]),t.parentNode=(e=this[u]).parentNode;for(var a=0,l=e.length;l>a;a++)(r=e[a])&&n.call(r,r.__data__,a,u)&&t.push(r)}return E(i)},Co.order=function(){for(var n=-1,t=this.length;++n<t;)for(var e,r=this[n],i=r.length-1,u=r[i];--i>=0;)(e=r[i])&&(u&&u!==e.nextSibling&&u.parentNode.insertBefore(e,u),u=e);return this},Co.sort=function(n){n=I.apply(this,arguments);for(var t=-1,e=this.length;++t<e;)this[t].sort(n);return this.order()},Co.each=function(n){return Y(this,function(t,e,r){n.call(t,t.__data__,e,r)})},Co.call=function(n){var t=co(arguments);return n.apply(t[0]=this,t),this},Co.empty=function(){return!this.node()},Co.node=function(){for(var n=0,t=this.length;t>n;n++)for(var e=this[n],r=0,i=e.length;i>r;r++){var u=e[r];if(u)return u}return null},Co.size=function(){var n=0;return Y(this,function(){++n}),n};var qo=[];ao.selection.enter=Z,ao.selection.enter.prototype=qo,qo.append=Co.append,qo.empty=Co.empty,qo.node=Co.node,qo.call=Co.call,qo.size=Co.size,qo.select=function(n){for(var t,e,r,i,u,o=[],a=-1,l=this.length;++a<l;){r=(i=this[a]).update,o.push(t=[]),t.parentNode=i.parentNode;for(var c=-1,f=i.length;++c<f;)(u=i[c])?(t.push(r[c]=e=n.call(i.parentNode,u.__data__,c,a)),e.__data__=u.__data__):t.push(null)}return E(o)},qo.insert=function(n,t){return arguments.length<2&&(t=V(this)),Co.insert.call(this,n,t)},ao.select=function(t){var e;return"string"==typeof t?(e=[No(t,fo)],e.parentNode=fo.documentElement):(e=[t],e.parentNode=n(t)),E([e])},ao.selectAll=function(n){var t;return"string"==typeof n?(t=co(Eo(n,fo)),t.parentNode=fo.documentElement):(t=co(n),t.parentNode=null),E([t])},Co.on=function(n,t,e){var r=arguments.length;if(3>r){if("string"!=typeof n){2>r&&(t=!1);for(e in n)this.each(X(e,n[e],t));return this}if(2>r)return(r=this.node()["__on"+n])&&r._;e=!1}return this.each(X(n,t,e))};var To=ao.map({mouseenter:"mouseover",mouseleave:"mouseout"});fo&&To.forEach(function(n){"on"+n in fo&&To.remove(n)});var Ro,Do=0;ao.mouse=function(n){return J(n,k())};var Po=this.navigator&&/WebKit/.test(this.navigator.userAgent)?-1:0;ao.touch=function(n,t,e){if(arguments.length<3&&(e=t,t=k().changedTouches),t)for(var r,i=0,u=t.length;u>i;++i)if((r=t[i]).identifier===e)return J(n,r)},ao.behavior.drag=function(){function n(){this.on("mousedown.drag",u).on("touchstart.drag",o)}function e(n,t,e,u,o){return function(){function a(){var n,e,r=t(h,v);r&&(n=r[0]-M[0],e=r[1]-M[1],g|=n|e,M=r,p({type:"drag",x:r[0]+c[0],y:r[1]+c[1],dx:n,dy:e}))}function l(){t(h,v)&&(y.on(u+d,null).on(o+d,null),m(g),p({type:"dragend"}))}var c,f=this,s=ao.event.target.correspondingElement||ao.event.target,h=f.parentNode,p=r.of(f,arguments),g=0,v=n(),d=".drag"+(null==v?"":"-"+v),y=ao.select(e(s)).on(u+d,a).on(o+d,l),m=W(s),M=t(h,v);i?(c=i.apply(f,arguments),c=[c.x-M[0],c.y-M[1]]):c=[0,0],p({type:"dragstart"})}}var r=N(n,"drag","dragstart","dragend"),i=null,u=e(b,ao.mouse,t,"mousemove","mouseup"),o=e(G,ao.touch,m,"touchmove","touchend");return n.origin=function(t){return arguments.length?(i=t,n):i},ao.rebind(n,r,"on")},ao.touches=function(n,t){return arguments.length<2&&(t=k().touches),t?co(t).map(function(t){var e=J(n,t);return e.identifier=t.identifier,e}):[]};var Uo=1e-6,jo=Uo*Uo,Fo=Math.PI,Ho=2*Fo,Oo=Ho-Uo,Io=Fo/2,Yo=Fo/180,Zo=180/Fo,Vo=Math.SQRT2,Xo=2,$o=4;ao.interpolateZoom=function(n,t){var e,r,i=n[0],u=n[1],o=n[2],a=t[0],l=t[1],c=t[2],f=a-i,s=l-u,h=f*f+s*s;if(jo>h)r=Math.log(c/o)/Vo,e=function(n){return[i+n*f,u+n*s,o*Math.exp(Vo*n*r)]};else{var p=Math.sqrt(h),g=(c*c-o*o+$o*h)/(2*o*Xo*p),v=(c*c-o*o-$o*h)/(2*c*Xo*p),d=Math.log(Math.sqrt(g*g+1)-g),y=Math.log(Math.sqrt(v*v+1)-v);r=(y-d)/Vo,e=function(n){var t=n*r,e=rn(d),a=o/(Xo*p)*(e*un(Vo*t+d)-en(d));return[i+a*f,u+a*s,o*e/rn(Vo*t+d)]}}return e.duration=1e3*r,e},ao.behavior.zoom=function(){function n(n){n.on(L,s).on(Wo+".zoom",p).on("dblclick.zoom",g).on(R,h)}function e(n){return[(n[0]-k.x)/k.k,(n[1]-k.y)/k.k]}function r(n){return[n[0]*k.k+k.x,n[1]*k.k+k.y]}function i(n){k.k=Math.max(A[0],Math.min(A[1],n))}function u(n,t){t=r(t),k.x+=n[0]-t[0],k.y+=n[1]-t[1]}function o(t,e,r,o){t.__chart__={x:k.x,y:k.y,k:k.k},i(Math.pow(2,o)),u(d=e,r),t=ao.select(t),C>0&&(t=t.transition().duration(C)),t.call(n.event)}function a(){b&&b.domain(x.range().map(function(n){return(n-k.x)/k.k}).map(x.invert)),w&&w.domain(_.range().map(function(n){return(n-k.y)/k.k}).map(_.invert))}function l(n){z++||n({type:"zoomstart"})}function c(n){a(),n({type:"zoom",scale:k.k,translate:[k.x,k.y]})}function f(n){--z||(n({type:"zoomend"}),d=null)}function s(){function n(){a=1,u(ao.mouse(i),h),c(o)}function r(){s.on(q,null).on(T,null),p(a),f(o)}var i=this,o=D.of(i,arguments),a=0,s=ao.select(t(i)).on(q,n).on(T,r),h=e(ao.mouse(i)),p=W(i);Il.call(i),l(o)}function h(){function n(){var n=ao.touches(g);return p=k.k,n.forEach(function(n){n.identifier in d&&(d[n.identifier]=e(n))}),n}function t(){var t=ao.event.target;ao.select(t).on(x,r).on(b,a),_.push(t);for(var e=ao.event.changedTouches,i=0,u=e.length;u>i;++i)d[e[i].identifier]=null;var l=n(),c=Date.now();if(1===l.length){if(500>c-M){var f=l[0];o(g,f,d[f.identifier],Math.floor(Math.log(k.k)/Math.LN2)+1),S()}M=c}else if(l.length>1){var f=l[0],s=l[1],h=f[0]-s[0],p=f[1]-s[1];y=h*h+p*p}}function r(){var n,t,e,r,o=ao.touches(g);Il.call(g);for(var a=0,l=o.length;l>a;++a,r=null)if(e=o[a],r=d[e.identifier]){if(t)break;n=e,t=r}if(r){var f=(f=e[0]-n[0])*f+(f=e[1]-n[1])*f,s=y&&Math.sqrt(f/y);n=[(n[0]+e[0])/2,(n[1]+e[1])/2],t=[(t[0]+r[0])/2,(t[1]+r[1])/2],i(s*p)}M=null,u(n,t),c(v)}function a(){if(ao.event.touches.length){for(var t=ao.event.changedTouches,e=0,r=t.length;r>e;++e)delete d[t[e].identifier];for(var i in d)return void n()}ao.selectAll(_).on(m,null),w.on(L,s).on(R,h),N(),f(v)}var p,g=this,v=D.of(g,arguments),d={},y=0,m=".zoom-"+ao.event.changedTouches[0].identifier,x="touchmove"+m,b="touchend"+m,_=[],w=ao.select(g),N=W(g);t(),l(v),w.on(L,null).on(R,t)}function p(){var n=D.of(this,arguments);m?clearTimeout(m):(Il.call(this),v=e(d=y||ao.mouse(this)),l(n)),m=setTimeout(function(){m=null,f(n)},50),S(),i(Math.pow(2,.002*Bo())*k.k),u(d,v),c(n)}function g(){var n=ao.mouse(this),t=Math.log(k.k)/Math.LN2;o(this,n,e(n),ao.event.shiftKey?Math.ceil(t)-1:Math.floor(t)+1)}var v,d,y,m,M,x,b,_,w,k={x:0,y:0,k:1},E=[960,500],A=Jo,C=250,z=0,L="mousedown.zoom",q="mousemove.zoom",T="mouseup.zoom",R="touchstart.zoom",D=N(n,"zoomstart","zoom","zoomend");return Wo||(Wo="onwheel"in fo?(Bo=function(){return-ao.event.deltaY*(ao.event.deltaMode?120:1)},"wheel"):"onmousewheel"in fo?(Bo=function(){return ao.event.wheelDelta},"mousewheel"):(Bo=function(){return-ao.event.detail},"MozMousePixelScroll")),n.event=function(n){n.each(function(){var n=D.of(this,arguments),t=k;Hl?ao.select(this).transition().each("start.zoom",function(){k=this.__chart__||{x:0,y:0,k:1},l(n)}).tween("zoom:zoom",function(){var e=E[0],r=E[1],i=d?d[0]:e/2,u=d?d[1]:r/2,o=ao.interpolateZoom([(i-k.x)/k.k,(u-k.y)/k.k,e/k.k],[(i-t.x)/t.k,(u-t.y)/t.k,e/t.k]);return function(t){var r=o(t),a=e/r[2];this.__chart__=k={x:i-r[0]*a,y:u-r[1]*a,k:a},c(n)}}).each("interrupt.zoom",function(){f(n)}).each("end.zoom",function(){f(n)}):(this.__chart__=k,l(n),c(n),f(n))})},n.translate=function(t){return arguments.length?(k={x:+t[0],y:+t[1],k:k.k},a(),n):[k.x,k.y]},n.scale=function(t){return arguments.length?(k={x:k.x,y:k.y,k:null},i(+t),a(),n):k.k},n.scaleExtent=function(t){return arguments.length?(A=null==t?Jo:[+t[0],+t[1]],n):A},n.center=function(t){return arguments.length?(y=t&&[+t[0],+t[1]],n):y},n.size=function(t){return arguments.length?(E=t&&[+t[0],+t[1]],n):E},n.duration=function(t){return arguments.length?(C=+t,n):C},n.x=function(t){return arguments.length?(b=t,x=t.copy(),k={x:0,y:0,k:1},n):b},n.y=function(t){return arguments.length?(w=t,_=t.copy(),k={x:0,y:0,k:1},n):w},ao.rebind(n,D,"on")};var Bo,Wo,Jo=[0,1/0];ao.color=an,an.prototype.toString=function(){return this.rgb()+""},ao.hsl=ln;var Go=ln.prototype=new an;Go.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),new ln(this.h,this.s,this.l/n)},Go.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new ln(this.h,this.s,n*this.l)},Go.rgb=function(){return cn(this.h,this.s,this.l)},ao.hcl=fn;var Ko=fn.prototype=new an;Ko.brighter=function(n){return new fn(this.h,this.c,Math.min(100,this.l+Qo*(arguments.length?n:1)))},Ko.darker=function(n){return new fn(this.h,this.c,Math.max(0,this.l-Qo*(arguments.length?n:1)))},Ko.rgb=function(){return sn(this.h,this.c,this.l).rgb()},ao.lab=hn;var Qo=18,na=.95047,ta=1,ea=1.08883,ra=hn.prototype=new an;ra.brighter=function(n){return new hn(Math.min(100,this.l+Qo*(arguments.length?n:1)),this.a,this.b)},ra.darker=function(n){return new hn(Math.max(0,this.l-Qo*(arguments.length?n:1)),this.a,this.b)},ra.rgb=function(){return pn(this.l,this.a,this.b)},ao.rgb=mn;var ia=mn.prototype=new an;ia.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,i=30;return t||e||r?(t&&i>t&&(t=i),e&&i>e&&(e=i),r&&i>r&&(r=i),new mn(Math.min(255,t/n),Math.min(255,e/n),Math.min(255,r/n))):new mn(i,i,i)},ia.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new mn(n*this.r,n*this.g,n*this.b)},ia.hsl=function(){return wn(this.r,this.g,this.b)},ia.toString=function(){return"#"+bn(this.r)+bn(this.g)+bn(this.b)};var ua=ao.map({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074});ua.forEach(function(n,t){ua.set(n,Mn(t))}),ao.functor=En,ao.xhr=An(m),ao.dsv=function(n,t){function e(n,e,u){arguments.length<3&&(u=e,e=null);var o=Cn(n,t,null==e?r:i(e),u);return o.row=function(n){return arguments.length?o.response(null==(e=n)?r:i(n)):e},o}function r(n){return e.parse(n.responseText)}function i(n){return function(t){return e.parse(t.responseText,n)}}function u(t){return t.map(o).join(n)}function o(n){return a.test(n)?'"'+n.replace(/\"/g,'""')+'"':n}var a=new RegExp('["'+n+"\n]"),l=n.charCodeAt(0);return e.parse=function(n,t){var r;return e.parseRows(n,function(n,e){if(r)return r(n,e-1);var i=new Function("d","return {"+n.map(function(n,t){return JSON.stringify(n)+": d["+t+"]"}).join(",")+"}");r=t?function(n,e){return t(i(n),e)}:i})},e.parseRows=function(n,t){function e(){if(f>=c)return o;if(i)return i=!1,u;var t=f;if(34===n.charCodeAt(t)){for(var e=t;e++<c;)if(34===n.charCodeAt(e)){if(34!==n.charCodeAt(e+1))break;++e}f=e+2;var r=n.charCodeAt(e+1);return 13===r?(i=!0,10===n.charCodeAt(e+2)&&++f):10===r&&(i=!0),n.slice(t+1,e).replace(/""/g,'"')}for(;c>f;){var r=n.charCodeAt(f++),a=1;if(10===r)i=!0;else if(13===r)i=!0,10===n.charCodeAt(f)&&(++f,++a);else if(r!==l)continue;return n.slice(t,f-a)}return n.slice(t)}for(var r,i,u={},o={},a=[],c=n.length,f=0,s=0;(r=e())!==o;){for(var h=[];r!==u&&r!==o;)h.push(r),r=e();t&&null==(h=t(h,s++))||a.push(h)}return a},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new y,i=[];return t.forEach(function(n){for(var t in n)r.has(t)||i.push(r.add(t))}),[i.map(o).join(n)].concat(t.map(function(t){return i.map(function(n){return o(t[n])}).join(n)})).join("\n")},e.formatRows=function(n){return n.map(u).join("\n")},e},ao.csv=ao.dsv(",","text/csv"),ao.tsv=ao.dsv(" ","text/tab-separated-values");var oa,aa,la,ca,fa=this[x(this,"requestAnimationFrame")]||function(n){setTimeout(n,17)};ao.timer=function(){qn.apply(this,arguments)},ao.timer.flush=function(){Rn(),Dn()},ao.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)};var sa=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"].map(Un);ao.formatPrefix=function(n,t){var e=0;return(n=+n)&&(0>n&&(n*=-1),t&&(n=ao.round(n,Pn(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((e-1)/3)))),sa[8+e/3]};var ha=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,pa=ao.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=ao.round(n,Pn(n,t))).toFixed(Math.max(0,Math.min(20,Pn(n*(1+1e-15),t))))}}),ga=ao.time={},va=Date;Hn.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){da.setUTCDate.apply(this._,arguments)},setDay:function(){da.setUTCDay.apply(this._,arguments)},setFullYear:function(){da.setUTCFullYear.apply(this._,arguments)},setHours:function(){da.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){da.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){da.setUTCMinutes.apply(this._,arguments)},setMonth:function(){da.setUTCMonth.apply(this._,arguments)},setSeconds:function(){da.setUTCSeconds.apply(this._,arguments)},setTime:function(){da.setTime.apply(this._,arguments)}};var da=Date.prototype;ga.year=On(function(n){return n=ga.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),ga.years=ga.year.range,ga.years.utc=ga.year.utc.range,ga.day=On(function(n){var t=new va(2e3,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),ga.days=ga.day.range,ga.days.utc=ga.day.utc.range,ga.dayOfYear=function(n){var t=ga.year(n);return Math.floor((n-t-6e4*(n.getTimezoneOffset()-t.getTimezoneOffset()))/864e5)},["sunday","monday","tuesday","wednesday","thursday","friday","saturday"].forEach(function(n,t){t=7-t;var e=ga[n]=On(function(n){return(n=ga.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+7*Math.floor(t))},function(n){var e=ga.year(n).getDay();return Math.floor((ga.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});ga[n+"s"]=e.range,ga[n+"s"].utc=e.utc.range,ga[n+"OfYear"]=function(n){var e=ga.year(n).getDay();return Math.floor((ga.dayOfYear(n)+(e+t)%7)/7)}}),ga.week=ga.sunday,ga.weeks=ga.sunday.range,ga.weeks.utc=ga.sunday.utc.range,ga.weekOfYear=ga.sundayOfYear;var ya={"-":"",_:" ",0:"0"},ma=/^\s*\d+/,Ma=/^%/;ao.locale=function(n){return{numberFormat:jn(n),timeFormat:Yn(n)}};var xa=ao.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],dateTime:"%a %b %e %X %Y",date:"%m/%d/%Y",time:"%H:%M:%S",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],
|
4 |
-
shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});ao.format=xa.numberFormat,ao.geo={},ft.prototype={s:0,t:0,add:function(n){st(n,this.t,ba),st(ba.s,this.s,this),this.s?this.t+=ba.t:this.s=ba.t},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var ba=new ft;ao.geo.stream=function(n,t){n&&_a.hasOwnProperty(n.type)?_a[n.type](n,t):ht(n,t)};var _a={Feature:function(n,t){ht(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,i=e.length;++r<i;)ht(e[r].geometry,t)}},wa={Sphere:function(n,t){t.sphere()},Point:function(n,t){n=n.coordinates,t.point(n[0],n[1],n[2])},MultiPoint:function(n,t){for(var e=n.coordinates,r=-1,i=e.length;++r<i;)n=e[r],t.point(n[0],n[1],n[2])},LineString:function(n,t){pt(n.coordinates,t,0)},MultiLineString:function(n,t){for(var e=n.coordinates,r=-1,i=e.length;++r<i;)pt(e[r],t,0)},Polygon:function(n,t){gt(n.coordinates,t)},MultiPolygon:function(n,t){for(var e=n.coordinates,r=-1,i=e.length;++r<i;)gt(e[r],t)},GeometryCollection:function(n,t){for(var e=n.geometries,r=-1,i=e.length;++r<i;)ht(e[r],t)}};ao.geo.area=function(n){return Sa=0,ao.geo.stream(n,Na),Sa};var Sa,ka=new ft,Na={sphere:function(){Sa+=4*Fo},point:b,lineStart:b,lineEnd:b,polygonStart:function(){ka.reset(),Na.lineStart=vt},polygonEnd:function(){var n=2*ka;Sa+=0>n?4*Fo+n:n,Na.lineStart=Na.lineEnd=Na.point=b}};ao.geo.bounds=function(){function n(n,t){M.push(x=[f=n,h=n]),s>t&&(s=t),t>p&&(p=t)}function t(t,e){var r=dt([t*Yo,e*Yo]);if(y){var i=mt(y,r),u=[i[1],-i[0],0],o=mt(u,i);bt(o),o=_t(o);var l=t-g,c=l>0?1:-1,v=o[0]*Zo*c,d=xo(l)>180;if(d^(v>c*g&&c*t>v)){var m=o[1]*Zo;m>p&&(p=m)}else if(v=(v+360)%360-180,d^(v>c*g&&c*t>v)){var m=-o[1]*Zo;s>m&&(s=m)}else s>e&&(s=e),e>p&&(p=e);d?g>t?a(f,t)>a(f,h)&&(h=t):a(t,h)>a(f,h)&&(f=t):h>=f?(f>t&&(f=t),t>h&&(h=t)):t>g?a(f,t)>a(f,h)&&(h=t):a(t,h)>a(f,h)&&(f=t)}else n(t,e);y=r,g=t}function e(){b.point=t}function r(){x[0]=f,x[1]=h,b.point=n,y=null}function i(n,e){if(y){var r=n-g;m+=xo(r)>180?r+(r>0?360:-360):r}else v=n,d=e;Na.point(n,e),t(n,e)}function u(){Na.lineStart()}function o(){i(v,d),Na.lineEnd(),xo(m)>Uo&&(f=-(h=180)),x[0]=f,x[1]=h,y=null}function a(n,t){return(t-=n)<0?t+360:t}function l(n,t){return n[0]-t[0]}function c(n,t){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:n<t[0]||t[1]<n}var f,s,h,p,g,v,d,y,m,M,x,b={point:n,lineStart:e,lineEnd:r,polygonStart:function(){b.point=i,b.lineStart=u,b.lineEnd=o,m=0,Na.polygonStart()},polygonEnd:function(){Na.polygonEnd(),b.point=n,b.lineStart=e,b.lineEnd=r,0>ka?(f=-(h=180),s=-(p=90)):m>Uo?p=90:-Uo>m&&(s=-90),x[0]=f,x[1]=h}};return function(n){p=h=-(f=s=1/0),M=[],ao.geo.stream(n,b);var t=M.length;if(t){M.sort(l);for(var e,r=1,i=M[0],u=[i];t>r;++r)e=M[r],c(e[0],i)||c(e[1],i)?(a(i[0],e[1])>a(i[0],i[1])&&(i[1]=e[1]),a(e[0],i[1])>a(i[0],i[1])&&(i[0]=e[0])):u.push(i=e);for(var o,e,g=-(1/0),t=u.length-1,r=0,i=u[t];t>=r;i=e,++r)e=u[r],(o=a(i[1],e[0]))>g&&(g=o,f=e[0],h=i[1])}return M=x=null,f===1/0||s===1/0?[[NaN,NaN],[NaN,NaN]]:[[f,s],[h,p]]}}(),ao.geo.centroid=function(n){Ea=Aa=Ca=za=La=qa=Ta=Ra=Da=Pa=Ua=0,ao.geo.stream(n,ja);var t=Da,e=Pa,r=Ua,i=t*t+e*e+r*r;return jo>i&&(t=qa,e=Ta,r=Ra,Uo>Aa&&(t=Ca,e=za,r=La),i=t*t+e*e+r*r,jo>i)?[NaN,NaN]:[Math.atan2(e,t)*Zo,tn(r/Math.sqrt(i))*Zo]};var Ea,Aa,Ca,za,La,qa,Ta,Ra,Da,Pa,Ua,ja={sphere:b,point:St,lineStart:Nt,lineEnd:Et,polygonStart:function(){ja.lineStart=At},polygonEnd:function(){ja.lineStart=Nt}},Fa=Rt(zt,jt,Ht,[-Fo,-Fo/2]),Ha=1e9;ao.geo.clipExtent=function(){var n,t,e,r,i,u,o={stream:function(n){return i&&(i.valid=!1),i=u(n),i.valid=!0,i},extent:function(a){return arguments.length?(u=Zt(n=+a[0][0],t=+a[0][1],e=+a[1][0],r=+a[1][1]),i&&(i.valid=!1,i=null),o):[[n,t],[e,r]]}};return o.extent([[0,0],[960,500]])},(ao.geo.conicEqualArea=function(){return Vt(Xt)}).raw=Xt,ao.geo.albers=function(){return ao.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},ao.geo.albersUsa=function(){function n(n){var u=n[0],o=n[1];return t=null,e(u,o),t||(r(u,o),t)||i(u,o),t}var t,e,r,i,u=ao.geo.albers(),o=ao.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),a=ao.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),l={point:function(n,e){t=[n,e]}};return n.invert=function(n){var t=u.scale(),e=u.translate(),r=(n[0]-e[0])/t,i=(n[1]-e[1])/t;return(i>=.12&&.234>i&&r>=-.425&&-.214>r?o:i>=.166&&.234>i&&r>=-.214&&-.115>r?a:u).invert(n)},n.stream=function(n){var t=u.stream(n),e=o.stream(n),r=a.stream(n);return{point:function(n,i){t.point(n,i),e.point(n,i),r.point(n,i)},sphere:function(){t.sphere(),e.sphere(),r.sphere()},lineStart:function(){t.lineStart(),e.lineStart(),r.lineStart()},lineEnd:function(){t.lineEnd(),e.lineEnd(),r.lineEnd()},polygonStart:function(){t.polygonStart(),e.polygonStart(),r.polygonStart()},polygonEnd:function(){t.polygonEnd(),e.polygonEnd(),r.polygonEnd()}}},n.precision=function(t){return arguments.length?(u.precision(t),o.precision(t),a.precision(t),n):u.precision()},n.scale=function(t){return arguments.length?(u.scale(t),o.scale(.35*t),a.scale(t),n.translate(u.translate())):u.scale()},n.translate=function(t){if(!arguments.length)return u.translate();var c=u.scale(),f=+t[0],s=+t[1];return e=u.translate(t).clipExtent([[f-.455*c,s-.238*c],[f+.455*c,s+.238*c]]).stream(l).point,r=o.translate([f-.307*c,s+.201*c]).clipExtent([[f-.425*c+Uo,s+.12*c+Uo],[f-.214*c-Uo,s+.234*c-Uo]]).stream(l).point,i=a.translate([f-.205*c,s+.212*c]).clipExtent([[f-.214*c+Uo,s+.166*c+Uo],[f-.115*c-Uo,s+.234*c-Uo]]).stream(l).point,n},n.scale(1070)};var Oa,Ia,Ya,Za,Va,Xa,$a={point:b,lineStart:b,lineEnd:b,polygonStart:function(){Ia=0,$a.lineStart=$t},polygonEnd:function(){$a.lineStart=$a.lineEnd=$a.point=b,Oa+=xo(Ia/2)}},Ba={point:Bt,lineStart:b,lineEnd:b,polygonStart:b,polygonEnd:b},Wa={point:Gt,lineStart:Kt,lineEnd:Qt,polygonStart:function(){Wa.lineStart=ne},polygonEnd:function(){Wa.point=Gt,Wa.lineStart=Kt,Wa.lineEnd=Qt}};ao.geo.path=function(){function n(n){return n&&("function"==typeof a&&u.pointRadius(+a.apply(this,arguments)),o&&o.valid||(o=i(u)),ao.geo.stream(n,o)),u.result()}function t(){return o=null,n}var e,r,i,u,o,a=4.5;return n.area=function(n){return Oa=0,ao.geo.stream(n,i($a)),Oa},n.centroid=function(n){return Ca=za=La=qa=Ta=Ra=Da=Pa=Ua=0,ao.geo.stream(n,i(Wa)),Ua?[Da/Ua,Pa/Ua]:Ra?[qa/Ra,Ta/Ra]:La?[Ca/La,za/La]:[NaN,NaN]},n.bounds=function(n){return Va=Xa=-(Ya=Za=1/0),ao.geo.stream(n,i(Ba)),[[Ya,Za],[Va,Xa]]},n.projection=function(n){return arguments.length?(i=(e=n)?n.stream||re(n):m,t()):e},n.context=function(n){return arguments.length?(u=null==(r=n)?new Wt:new te(n),"function"!=typeof a&&u.pointRadius(a),t()):r},n.pointRadius=function(t){return arguments.length?(a="function"==typeof t?t:(u.pointRadius(+t),+t),n):a},n.projection(ao.geo.albersUsa()).context(null)},ao.geo.transform=function(n){return{stream:function(t){var e=new ie(t);for(var r in n)e[r]=n[r];return e}}},ie.prototype={point:function(n,t){this.stream.point(n,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},ao.geo.projection=oe,ao.geo.projectionMutator=ae,(ao.geo.equirectangular=function(){return oe(ce)}).raw=ce.invert=ce,ao.geo.rotation=function(n){function t(t){return t=n(t[0]*Yo,t[1]*Yo),t[0]*=Zo,t[1]*=Zo,t}return n=se(n[0]%360*Yo,n[1]*Yo,n.length>2?n[2]*Yo:0),t.invert=function(t){return t=n.invert(t[0]*Yo,t[1]*Yo),t[0]*=Zo,t[1]*=Zo,t},t},fe.invert=ce,ao.geo.circle=function(){function n(){var n="function"==typeof r?r.apply(this,arguments):r,t=se(-n[0]*Yo,-n[1]*Yo,0).invert,i=[];return e(null,null,1,{point:function(n,e){i.push(n=t(n,e)),n[0]*=Zo,n[1]*=Zo}}),{type:"Polygon",coordinates:[i]}}var t,e,r=[0,0],i=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=ve((t=+r)*Yo,i*Yo),n):t},n.precision=function(r){return arguments.length?(e=ve(t*Yo,(i=+r)*Yo),n):i},n.angle(90)},ao.geo.distance=function(n,t){var e,r=(t[0]-n[0])*Yo,i=n[1]*Yo,u=t[1]*Yo,o=Math.sin(r),a=Math.cos(r),l=Math.sin(i),c=Math.cos(i),f=Math.sin(u),s=Math.cos(u);return Math.atan2(Math.sqrt((e=s*o)*e+(e=c*f-l*s*a)*e),l*f+c*s*a)},ao.geo.graticule=function(){function n(){return{type:"MultiLineString",coordinates:t()}}function t(){return ao.range(Math.ceil(u/d)*d,i,d).map(h).concat(ao.range(Math.ceil(c/y)*y,l,y).map(p)).concat(ao.range(Math.ceil(r/g)*g,e,g).filter(function(n){return xo(n%d)>Uo}).map(f)).concat(ao.range(Math.ceil(a/v)*v,o,v).filter(function(n){return xo(n%y)>Uo}).map(s))}var e,r,i,u,o,a,l,c,f,s,h,p,g=10,v=g,d=90,y=360,m=2.5;return n.lines=function(){return t().map(function(n){return{type:"LineString",coordinates:n}})},n.outline=function(){return{type:"Polygon",coordinates:[h(u).concat(p(l).slice(1),h(i).reverse().slice(1),p(c).reverse().slice(1))]}},n.extent=function(t){return arguments.length?n.majorExtent(t).minorExtent(t):n.minorExtent()},n.majorExtent=function(t){return arguments.length?(u=+t[0][0],i=+t[1][0],c=+t[0][1],l=+t[1][1],u>i&&(t=u,u=i,i=t),c>l&&(t=c,c=l,l=t),n.precision(m)):[[u,c],[i,l]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],a=+t[0][1],o=+t[1][1],r>e&&(t=r,r=e,e=t),a>o&&(t=a,a=o,o=t),n.precision(m)):[[r,a],[e,o]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(d=+t[0],y=+t[1],n):[d,y]},n.minorStep=function(t){return arguments.length?(g=+t[0],v=+t[1],n):[g,v]},n.precision=function(t){return arguments.length?(m=+t,f=ye(a,o,90),s=me(r,e,m),h=ye(c,l,90),p=me(u,i,m),n):m},n.majorExtent([[-180,-90+Uo],[180,90-Uo]]).minorExtent([[-180,-80-Uo],[180,80+Uo]])},ao.geo.greatArc=function(){function n(){return{type:"LineString",coordinates:[t||r.apply(this,arguments),e||i.apply(this,arguments)]}}var t,e,r=Me,i=xe;return n.distance=function(){return ao.geo.distance(t||r.apply(this,arguments),e||i.apply(this,arguments))},n.source=function(e){return arguments.length?(r=e,t="function"==typeof e?null:e,n):r},n.target=function(t){return arguments.length?(i=t,e="function"==typeof t?null:t,n):i},n.precision=function(){return arguments.length?n:0},n},ao.geo.interpolate=function(n,t){return be(n[0]*Yo,n[1]*Yo,t[0]*Yo,t[1]*Yo)},ao.geo.length=function(n){return Ja=0,ao.geo.stream(n,Ga),Ja};var Ja,Ga={sphere:b,point:b,lineStart:_e,lineEnd:b,polygonStart:b,polygonEnd:b},Ka=we(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(ao.geo.azimuthalEqualArea=function(){return oe(Ka)}).raw=Ka;var Qa=we(function(n){var t=Math.acos(n);return t&&t/Math.sin(t)},m);(ao.geo.azimuthalEquidistant=function(){return oe(Qa)}).raw=Qa,(ao.geo.conicConformal=function(){return Vt(Se)}).raw=Se,(ao.geo.conicEquidistant=function(){return Vt(ke)}).raw=ke;var nl=we(function(n){return 1/n},Math.atan);(ao.geo.gnomonic=function(){return oe(nl)}).raw=nl,Ne.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-Io]},(ao.geo.mercator=function(){return Ee(Ne)}).raw=Ne;var tl=we(function(){return 1},Math.asin);(ao.geo.orthographic=function(){return oe(tl)}).raw=tl;var el=we(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(ao.geo.stereographic=function(){return oe(el)}).raw=el,Ae.invert=function(n,t){return[-t,2*Math.atan(Math.exp(n))-Io]},(ao.geo.transverseMercator=function(){var n=Ee(Ae),t=n.center,e=n.rotate;return n.center=function(n){return n?t([-n[1],n[0]]):(n=t(),[n[1],-n[0]])},n.rotate=function(n){return n?e([n[0],n[1],n.length>2?n[2]+90:90]):(n=e(),[n[0],n[1],n[2]-90])},e([0,0,90])}).raw=Ae,ao.geom={},ao.geom.hull=function(n){function t(n){if(n.length<3)return[];var t,i=En(e),u=En(r),o=n.length,a=[],l=[];for(t=0;o>t;t++)a.push([+i.call(this,n[t],t),+u.call(this,n[t],t),t]);for(a.sort(qe),t=0;o>t;t++)l.push([a[t][0],-a[t][1]]);var c=Le(a),f=Le(l),s=f[0]===c[0],h=f[f.length-1]===c[c.length-1],p=[];for(t=c.length-1;t>=0;--t)p.push(n[a[c[t]][2]]);for(t=+s;t<f.length-h;++t)p.push(n[a[f[t]][2]]);return p}var e=Ce,r=ze;return arguments.length?t(n):(t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t)},ao.geom.polygon=function(n){return ko(n,rl),n};var rl=ao.geom.polygon.prototype=[];rl.area=function(){for(var n,t=-1,e=this.length,r=this[e-1],i=0;++t<e;)n=r,r=this[t],i+=n[1]*r[0]-n[0]*r[1];return.5*i},rl.centroid=function(n){var t,e,r=-1,i=this.length,u=0,o=0,a=this[i-1];for(arguments.length||(n=-1/(6*this.area()));++r<i;)t=a,a=this[r],e=t[0]*a[1]-a[0]*t[1],u+=(t[0]+a[0])*e,o+=(t[1]+a[1])*e;return[u*n,o*n]},rl.clip=function(n){for(var t,e,r,i,u,o,a=De(n),l=-1,c=this.length-De(this),f=this[c-1];++l<c;){for(t=n.slice(),n.length=0,i=this[l],u=t[(r=t.length-a)-1],e=-1;++e<r;)o=t[e],Te(o,f,i)?(Te(u,f,i)||n.push(Re(u,o,f,i)),n.push(o)):Te(u,f,i)&&n.push(Re(u,o,f,i)),u=o;a&&n.push(n[0]),f=i}return n};var il,ul,ol,al,ll,cl=[],fl=[];Ye.prototype.prepare=function(){for(var n,t=this.edges,e=t.length;e--;)n=t[e].edge,n.b&&n.a||t.splice(e,1);return t.sort(Ve),t.length},tr.prototype={start:function(){return this.edge.l===this.site?this.edge.a:this.edge.b},end:function(){return this.edge.l===this.site?this.edge.b:this.edge.a}},er.prototype={insert:function(n,t){var e,r,i;if(n){if(t.P=n,t.N=n.N,n.N&&(n.N.P=t),n.N=t,n.R){for(n=n.R;n.L;)n=n.L;n.L=t}else n.R=t;e=n}else this._?(n=or(this._),t.P=null,t.N=n,n.P=n.L=t,e=n):(t.P=t.N=null,this._=t,e=null);for(t.L=t.R=null,t.U=e,t.C=!0,n=t;e&&e.C;)r=e.U,e===r.L?(i=r.R,i&&i.C?(e.C=i.C=!1,r.C=!0,n=r):(n===e.R&&(ir(this,e),n=e,e=n.U),e.C=!1,r.C=!0,ur(this,r))):(i=r.L,i&&i.C?(e.C=i.C=!1,r.C=!0,n=r):(n===e.L&&(ur(this,e),n=e,e=n.U),e.C=!1,r.C=!0,ir(this,r))),e=n.U;this._.C=!1},remove:function(n){n.N&&(n.N.P=n.P),n.P&&(n.P.N=n.N),n.N=n.P=null;var t,e,r,i=n.U,u=n.L,o=n.R;if(e=u?o?or(o):u:o,i?i.L===n?i.L=e:i.R=e:this._=e,u&&o?(r=e.C,e.C=n.C,e.L=u,u.U=e,e!==o?(i=e.U,e.U=n.U,n=e.R,i.L=n,e.R=o,o.U=e):(e.U=i,i=e,n=e.R)):(r=n.C,n=e),n&&(n.U=i),!r){if(n&&n.C)return void(n.C=!1);do{if(n===this._)break;if(n===i.L){if(t=i.R,t.C&&(t.C=!1,i.C=!0,ir(this,i),t=i.R),t.L&&t.L.C||t.R&&t.R.C){t.R&&t.R.C||(t.L.C=!1,t.C=!0,ur(this,t),t=i.R),t.C=i.C,i.C=t.R.C=!1,ir(this,i),n=this._;break}}else if(t=i.L,t.C&&(t.C=!1,i.C=!0,ur(this,i),t=i.L),t.L&&t.L.C||t.R&&t.R.C){t.L&&t.L.C||(t.R.C=!1,t.C=!0,ir(this,t),t=i.L),t.C=i.C,i.C=t.L.C=!1,ur(this,i),n=this._;break}t.C=!0,n=i,i=i.U}while(!n.C);n&&(n.C=!1)}}},ao.geom.voronoi=function(n){function t(n){var t=new Array(n.length),r=a[0][0],i=a[0][1],u=a[1][0],o=a[1][1];return ar(e(n),a).cells.forEach(function(e,a){var l=e.edges,c=e.site,f=t[a]=l.length?l.map(function(n){var t=n.start();return[t.x,t.y]}):c.x>=r&&c.x<=u&&c.y>=i&&c.y<=o?[[r,o],[u,o],[u,i],[r,i]]:[];f.point=n[a]}),t}function e(n){return n.map(function(n,t){return{x:Math.round(u(n,t)/Uo)*Uo,y:Math.round(o(n,t)/Uo)*Uo,i:t}})}var r=Ce,i=ze,u=r,o=i,a=sl;return n?t(n):(t.links=function(n){return ar(e(n)).edges.filter(function(n){return n.l&&n.r}).map(function(t){return{source:n[t.l.i],target:n[t.r.i]}})},t.triangles=function(n){var t=[];return ar(e(n)).cells.forEach(function(e,r){for(var i,u,o=e.site,a=e.edges.sort(Ve),l=-1,c=a.length,f=a[c-1].edge,s=f.l===o?f.r:f.l;++l<c;)i=f,u=s,f=a[l].edge,s=f.l===o?f.r:f.l,r<u.i&&r<s.i&&cr(o,u,s)<0&&t.push([n[r],n[u.i],n[s.i]])}),t},t.x=function(n){return arguments.length?(u=En(r=n),t):r},t.y=function(n){return arguments.length?(o=En(i=n),t):i},t.clipExtent=function(n){return arguments.length?(a=null==n?sl:n,t):a===sl?null:a},t.size=function(n){return arguments.length?t.clipExtent(n&&[[0,0],n]):a===sl?null:a&&a[1]},t)};var sl=[[-1e6,-1e6],[1e6,1e6]];ao.geom.delaunay=function(n){return ao.geom.voronoi().triangles(n)},ao.geom.quadtree=function(n,t,e,r,i){function u(n){function u(n,t,e,r,i,u,o,a){if(!isNaN(e)&&!isNaN(r))if(n.leaf){var l=n.x,f=n.y;if(null!=l)if(xo(l-e)+xo(f-r)<.01)c(n,t,e,r,i,u,o,a);else{var s=n.point;n.x=n.y=n.point=null,c(n,s,l,f,i,u,o,a),c(n,t,e,r,i,u,o,a)}else n.x=e,n.y=r,n.point=t}else c(n,t,e,r,i,u,o,a)}function c(n,t,e,r,i,o,a,l){var c=.5*(i+a),f=.5*(o+l),s=e>=c,h=r>=f,p=h<<1|s;n.leaf=!1,n=n.nodes[p]||(n.nodes[p]=hr()),s?i=c:a=c,h?o=f:l=f,u(n,t,e,r,i,o,a,l)}var f,s,h,p,g,v,d,y,m,M=En(a),x=En(l);if(null!=t)v=t,d=e,y=r,m=i;else if(y=m=-(v=d=1/0),s=[],h=[],g=n.length,o)for(p=0;g>p;++p)f=n[p],f.x<v&&(v=f.x),f.y<d&&(d=f.y),f.x>y&&(y=f.x),f.y>m&&(m=f.y),s.push(f.x),h.push(f.y);else for(p=0;g>p;++p){var b=+M(f=n[p],p),_=+x(f,p);v>b&&(v=b),d>_&&(d=_),b>y&&(y=b),_>m&&(m=_),s.push(b),h.push(_)}var w=y-v,S=m-d;w>S?m=d+w:y=v+S;var k=hr();if(k.add=function(n){u(k,n,+M(n,++p),+x(n,p),v,d,y,m)},k.visit=function(n){pr(n,k,v,d,y,m)},k.find=function(n){return gr(k,n[0],n[1],v,d,y,m)},p=-1,null==t){for(;++p<g;)u(k,n[p],s[p],h[p],v,d,y,m);--p}else n.forEach(k.add);return s=h=n=f=null,k}var o,a=Ce,l=ze;return(o=arguments.length)?(a=fr,l=sr,3===o&&(i=e,r=t,e=t=0),u(n)):(u.x=function(n){return arguments.length?(a=n,u):a},u.y=function(n){return arguments.length?(l=n,u):l},u.extent=function(n){return arguments.length?(null==n?t=e=r=i=null:(t=+n[0][0],e=+n[0][1],r=+n[1][0],i=+n[1][1]),u):null==t?null:[[t,e],[r,i]]},u.size=function(n){return arguments.length?(null==n?t=e=r=i=null:(t=e=0,r=+n[0],i=+n[1]),u):null==t?null:[r-t,i-e]},u)},ao.interpolateRgb=vr,ao.interpolateObject=dr,ao.interpolateNumber=yr,ao.interpolateString=mr;var hl=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,pl=new RegExp(hl.source,"g");ao.interpolate=Mr,ao.interpolators=[function(n,t){var e=typeof t;return("string"===e?ua.has(t.toLowerCase())||/^(#|rgb\(|hsl\()/i.test(t)?vr:mr:t instanceof an?vr:Array.isArray(t)?xr:"object"===e&&isNaN(t)?dr:yr)(n,t)}],ao.interpolateArray=xr;var gl=function(){return m},vl=ao.map({linear:gl,poly:Er,quad:function(){return Sr},cubic:function(){return kr},sin:function(){return Ar},exp:function(){return Cr},circle:function(){return zr},elastic:Lr,back:qr,bounce:function(){return Tr}}),dl=ao.map({"in":m,out:_r,"in-out":wr,"out-in":function(n){return wr(_r(n))}});ao.ease=function(n){var t=n.indexOf("-"),e=t>=0?n.slice(0,t):n,r=t>=0?n.slice(t+1):"in";return e=vl.get(e)||gl,r=dl.get(r)||m,br(r(e.apply(null,lo.call(arguments,1))))},ao.interpolateHcl=Rr,ao.interpolateHsl=Dr,ao.interpolateLab=Pr,ao.interpolateRound=Ur,ao.transform=function(n){var t=fo.createElementNS(ao.ns.prefix.svg,"g");return(ao.transform=function(n){if(null!=n){t.setAttribute("transform",n);var e=t.transform.baseVal.consolidate()}return new jr(e?e.matrix:yl)})(n)},jr.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var yl={a:1,b:0,c:0,d:1,e:0,f:0};ao.interpolateTransform=$r,ao.layout={},ao.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++e<r;)t.push(Jr(n[e]));return t}},ao.layout.chord=function(){function n(){var n,c,s,h,p,g={},v=[],d=ao.range(u),y=[];for(e=[],r=[],n=0,h=-1;++h<u;){for(c=0,p=-1;++p<u;)c+=i[h][p];v.push(c),y.push(ao.range(u)),n+=c}for(o&&d.sort(function(n,t){return o(v[n],v[t])}),a&&y.forEach(function(n,t){n.sort(function(n,e){return a(i[t][n],i[t][e])})}),n=(Ho-f*u)/n,c=0,h=-1;++h<u;){for(s=c,p=-1;++p<u;){var m=d[h],M=y[m][p],x=i[m][M],b=c,_=c+=x*n;g[m+"-"+M]={index:m,subindex:M,startAngle:b,endAngle:_,value:x}}r[m]={index:m,startAngle:s,endAngle:c,value:v[m]},c+=f}for(h=-1;++h<u;)for(p=h-1;++p<u;){var w=g[h+"-"+p],S=g[p+"-"+h];(w.value||S.value)&&e.push(w.value<S.value?{source:S,target:w}:{source:w,target:S})}l&&t()}function t(){e.sort(function(n,t){return l((n.source.value+n.target.value)/2,(t.source.value+t.target.value)/2)})}var e,r,i,u,o,a,l,c={},f=0;return c.matrix=function(n){return arguments.length?(u=(i=n)&&i.length,e=r=null,c):i},c.padding=function(n){return arguments.length?(f=n,e=r=null,c):f},c.sortGroups=function(n){return arguments.length?(o=n,e=r=null,c):o},c.sortSubgroups=function(n){return arguments.length?(a=n,e=null,c):a},c.sortChords=function(n){return arguments.length?(l=n,e&&t(),c):l},c.chords=function(){return e||n(),e},c.groups=function(){return r||n(),r},c},ao.layout.force=function(){function n(n){return function(t,e,r,i){if(t.point!==n){var u=t.cx-n.x,o=t.cy-n.y,a=i-e,l=u*u+o*o;if(l>a*a/y){if(v>l){var c=t.charge/l;n.px-=u*c,n.py-=o*c}return!0}if(t.point&&l&&v>l){var c=t.pointCharge/l;n.px-=u*c,n.py-=o*c}}return!t.charge}}function t(n){n.px=ao.event.x,n.py=ao.event.y,l.resume()}var e,r,i,u,o,a,l={},c=ao.dispatch("start","tick","end"),f=[1,1],s=.9,h=ml,p=Ml,g=-30,v=xl,d=.1,y=.64,M=[],x=[];return l.tick=function(){if((i*=.99)<.005)return e=null,c.end({type:"end",alpha:i=0}),!0;var t,r,l,h,p,v,y,m,b,_=M.length,w=x.length;for(r=0;w>r;++r)l=x[r],h=l.source,p=l.target,m=p.x-h.x,b=p.y-h.y,(v=m*m+b*b)&&(v=i*o[r]*((v=Math.sqrt(v))-u[r])/v,m*=v,b*=v,p.x-=m*(y=h.weight+p.weight?h.weight/(h.weight+p.weight):.5),p.y-=b*y,h.x+=m*(y=1-y),h.y+=b*y);if((y=i*d)&&(m=f[0]/2,b=f[1]/2,r=-1,y))for(;++r<_;)l=M[r],l.x+=(m-l.x)*y,l.y+=(b-l.y)*y;if(g)for(ri(t=ao.geom.quadtree(M),i,a),r=-1;++r<_;)(l=M[r]).fixed||t.visit(n(l));for(r=-1;++r<_;)l=M[r],l.fixed?(l.x=l.px,l.y=l.py):(l.x-=(l.px-(l.px=l.x))*s,l.y-=(l.py-(l.py=l.y))*s);c.tick({type:"tick",alpha:i})},l.nodes=function(n){return arguments.length?(M=n,l):M},l.links=function(n){return arguments.length?(x=n,l):x},l.size=function(n){return arguments.length?(f=n,l):f},l.linkDistance=function(n){return arguments.length?(h="function"==typeof n?n:+n,l):h},l.distance=l.linkDistance,l.linkStrength=function(n){return arguments.length?(p="function"==typeof n?n:+n,l):p},l.friction=function(n){return arguments.length?(s=+n,l):s},l.charge=function(n){return arguments.length?(g="function"==typeof n?n:+n,l):g},l.chargeDistance=function(n){return arguments.length?(v=n*n,l):Math.sqrt(v)},l.gravity=function(n){return arguments.length?(d=+n,l):d},l.theta=function(n){return arguments.length?(y=n*n,l):Math.sqrt(y)},l.alpha=function(n){return arguments.length?(n=+n,i?n>0?i=n:(e.c=null,e.t=NaN,e=null,c.end({type:"end",alpha:i=0})):n>0&&(c.start({type:"start",alpha:i=n}),e=qn(l.tick)),l):i},l.start=function(){function n(n,r){if(!e){for(e=new Array(i),l=0;i>l;++l)e[l]=[];for(l=0;c>l;++l){var u=x[l];e[u.source.index].push(u.target),e[u.target.index].push(u.source)}}for(var o,a=e[t],l=-1,f=a.length;++l<f;)if(!isNaN(o=a[l][n]))return o;return Math.random()*r}var t,e,r,i=M.length,c=x.length,s=f[0],v=f[1];for(t=0;i>t;++t)(r=M[t]).index=t,r.weight=0;for(t=0;c>t;++t)r=x[t],"number"==typeof r.source&&(r.source=M[r.source]),"number"==typeof r.target&&(r.target=M[r.target]),++r.source.weight,++r.target.weight;for(t=0;i>t;++t)r=M[t],isNaN(r.x)&&(r.x=n("x",s)),isNaN(r.y)&&(r.y=n("y",v)),isNaN(r.px)&&(r.px=r.x),isNaN(r.py)&&(r.py=r.y);if(u=[],"function"==typeof h)for(t=0;c>t;++t)u[t]=+h.call(this,x[t],t);else for(t=0;c>t;++t)u[t]=h;if(o=[],"function"==typeof p)for(t=0;c>t;++t)o[t]=+p.call(this,x[t],t);else for(t=0;c>t;++t)o[t]=p;if(a=[],"function"==typeof g)for(t=0;i>t;++t)a[t]=+g.call(this,M[t],t);else for(t=0;i>t;++t)a[t]=g;return l.resume()},l.resume=function(){return l.alpha(.1)},l.stop=function(){return l.alpha(0)},l.drag=function(){return r||(r=ao.behavior.drag().origin(m).on("dragstart.force",Qr).on("drag.force",t).on("dragend.force",ni)),arguments.length?void this.on("mouseover.force",ti).on("mouseout.force",ei).call(r):r},ao.rebind(l,c,"on")};var ml=20,Ml=1,xl=1/0;ao.layout.hierarchy=function(){function n(i){var u,o=[i],a=[];for(i.depth=0;null!=(u=o.pop());)if(a.push(u),(c=e.call(n,u,u.depth))&&(l=c.length)){for(var l,c,f;--l>=0;)o.push(f=c[l]),f.parent=u,f.depth=u.depth+1;r&&(u.value=0),u.children=c}else r&&(u.value=+r.call(n,u,u.depth)||0),delete u.children;return oi(i,function(n){var e,i;t&&(e=n.children)&&e.sort(t),r&&(i=n.parent)&&(i.value+=n.value)}),a}var t=ci,e=ai,r=li;return n.sort=function(e){return arguments.length?(t=e,n):t},n.children=function(t){return arguments.length?(e=t,n):e},n.value=function(t){return arguments.length?(r=t,n):r},n.revalue=function(t){return r&&(ui(t,function(n){n.children&&(n.value=0)}),oi(t,function(t){var e;t.children||(t.value=+r.call(n,t,t.depth)||0),(e=t.parent)&&(e.value+=t.value)})),t},n},ao.layout.partition=function(){function n(t,e,r,i){var u=t.children;if(t.x=e,t.y=t.depth*i,t.dx=r,t.dy=i,u&&(o=u.length)){var o,a,l,c=-1;for(r=t.value?r/t.value:0;++c<o;)n(a=u[c],e,l=a.value*r,i),e+=l}}function t(n){var e=n.children,r=0;if(e&&(i=e.length))for(var i,u=-1;++u<i;)r=Math.max(r,t(e[u]));return 1+r}function e(e,u){var o=r.call(this,e,u);return n(o[0],0,i[0],i[1]/t(o[0])),o}var r=ao.layout.hierarchy(),i=[1,1];return e.size=function(n){return arguments.length?(i=n,e):i},ii(e,r)},ao.layout.pie=function(){function n(o){var a,l=o.length,c=o.map(function(e,r){return+t.call(n,e,r)}),f=+("function"==typeof r?r.apply(this,arguments):r),s=("function"==typeof i?i.apply(this,arguments):i)-f,h=Math.min(Math.abs(s)/l,+("function"==typeof u?u.apply(this,arguments):u)),p=h*(0>s?-1:1),g=ao.sum(c),v=g?(s-l*p)/g:0,d=ao.range(l),y=[];return null!=e&&d.sort(e===bl?function(n,t){return c[t]-c[n]}:function(n,t){return e(o[n],o[t])}),d.forEach(function(n){y[n]={data:o[n],value:a=c[n],startAngle:f,endAngle:f+=a*v+p,padAngle:h}}),y}var t=Number,e=bl,r=0,i=Ho,u=0;return n.value=function(e){return arguments.length?(t=e,n):t},n.sort=function(t){return arguments.length?(e=t,n):e},n.startAngle=function(t){return arguments.length?(r=t,n):r},n.endAngle=function(t){return arguments.length?(i=t,n):i},n.padAngle=function(t){return arguments.length?(u=t,n):u},n};var bl={};ao.layout.stack=function(){function n(a,l){if(!(h=a.length))return a;var c=a.map(function(e,r){return t.call(n,e,r)}),f=c.map(function(t){return t.map(function(t,e){return[u.call(n,t,e),o.call(n,t,e)]})}),s=e.call(n,f,l);c=ao.permute(c,s),f=ao.permute(f,s);var h,p,g,v,d=r.call(n,f,l),y=c[0].length;for(g=0;y>g;++g)for(i.call(n,c[0][g],v=d[g],f[0][g][1]),p=1;h>p;++p)i.call(n,c[p][g],v+=f[p-1][g][1],f[p][g][1]);return a}var t=m,e=gi,r=vi,i=pi,u=si,o=hi;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e="function"==typeof t?t:_l.get(t)||gi,n):e},n.offset=function(t){return arguments.length?(r="function"==typeof t?t:wl.get(t)||vi,n):r},n.x=function(t){return arguments.length?(u=t,n):u},n.y=function(t){return arguments.length?(o=t,n):o},n.out=function(t){return arguments.length?(i=t,n):i},n};var _l=ao.map({"inside-out":function(n){var t,e,r=n.length,i=n.map(di),u=n.map(yi),o=ao.range(r).sort(function(n,t){return i[n]-i[t]}),a=0,l=0,c=[],f=[];for(t=0;r>t;++t)e=o[t],l>a?(a+=u[e],c.push(e)):(l+=u[e],f.push(e));return f.reverse().concat(c)},reverse:function(n){return ao.range(n.length).reverse()},"default":gi}),wl=ao.map({silhouette:function(n){var t,e,r,i=n.length,u=n[0].length,o=[],a=0,l=[];for(e=0;u>e;++e){for(t=0,r=0;i>t;t++)r+=n[t][e][1];r>a&&(a=r),o.push(r)}for(e=0;u>e;++e)l[e]=(a-o[e])/2;return l},wiggle:function(n){var t,e,r,i,u,o,a,l,c,f=n.length,s=n[0],h=s.length,p=[];for(p[0]=l=c=0,e=1;h>e;++e){for(t=0,i=0;f>t;++t)i+=n[t][e][1];for(t=0,u=0,a=s[e][0]-s[e-1][0];f>t;++t){for(r=0,o=(n[t][e][1]-n[t][e-1][1])/(2*a);t>r;++r)o+=(n[r][e][1]-n[r][e-1][1])/a;u+=o*n[t][e][1]}p[e]=l-=i?u/i*a:0,c>l&&(c=l)}for(e=0;h>e;++e)p[e]-=c;return p},expand:function(n){var t,e,r,i=n.length,u=n[0].length,o=1/i,a=[];for(e=0;u>e;++e){for(t=0,r=0;i>t;t++)r+=n[t][e][1];if(r)for(t=0;i>t;t++)n[t][e][1]/=r;else for(t=0;i>t;t++)n[t][e][1]=o}for(e=0;u>e;++e)a[e]=0;return a},zero:vi});ao.layout.histogram=function(){function n(n,u){for(var o,a,l=[],c=n.map(e,this),f=r.call(this,c,u),s=i.call(this,f,c,u),u=-1,h=c.length,p=s.length-1,g=t?1:1/h;++u<p;)o=l[u]=[],o.dx=s[u+1]-(o.x=s[u]),o.y=0;if(p>0)for(u=-1;++u<h;)a=c[u],a>=f[0]&&a<=f[1]&&(o=l[ao.bisect(s,a,1,p)-1],o.y+=g,o.push(n[u]));return l}var t=!0,e=Number,r=bi,i=Mi;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=En(t),n):r},n.bins=function(t){return arguments.length?(i="number"==typeof t?function(n){return xi(n,t)}:En(t),n):i},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},ao.layout.pack=function(){function n(n,u){var o=e.call(this,n,u),a=o[0],l=i[0],c=i[1],f=null==t?Math.sqrt:"function"==typeof t?t:function(){return t};if(a.x=a.y=0,oi(a,function(n){n.r=+f(n.value)}),oi(a,Ni),r){var s=r*(t?1:Math.max(2*a.r/l,2*a.r/c))/2;oi(a,function(n){n.r+=s}),oi(a,Ni),oi(a,function(n){n.r-=s})}return Ci(a,l/2,c/2,t?1:1/Math.max(2*a.r/l,2*a.r/c)),o}var t,e=ao.layout.hierarchy().sort(_i),r=0,i=[1,1];return n.size=function(t){return arguments.length?(i=t,n):i},n.radius=function(e){return arguments.length?(t=null==e||"function"==typeof e?e:+e,n):t},n.padding=function(t){return arguments.length?(r=+t,n):r},ii(n,e)},ao.layout.tree=function(){function n(n,i){var f=o.call(this,n,i),s=f[0],h=t(s);if(oi(h,e),h.parent.m=-h.z,ui(h,r),c)ui(s,u);else{var p=s,g=s,v=s;ui(s,function(n){n.x<p.x&&(p=n),n.x>g.x&&(g=n),n.depth>v.depth&&(v=n)});var d=a(p,g)/2-p.x,y=l[0]/(g.x+a(g,p)/2+d),m=l[1]/(v.depth||1);ui(s,function(n){n.x=(n.x+d)*y,n.y=n.depth*m})}return f}function t(n){for(var t,e={A:null,children:[n]},r=[e];null!=(t=r.pop());)for(var i,u=t.children,o=0,a=u.length;a>o;++o)r.push((u[o]=i={_:u[o],parent:t,children:(i=u[o].children)&&i.slice()||[],A:null,a:null,z:0,m:0,c:0,s:0,t:null,i:o}).a=i);return e.children[0]}function e(n){var t=n.children,e=n.parent.children,r=n.i?e[n.i-1]:null;if(t.length){Di(n);var u=(t[0].z+t[t.length-1].z)/2;r?(n.z=r.z+a(n._,r._),n.m=n.z-u):n.z=u}else r&&(n.z=r.z+a(n._,r._));n.parent.A=i(n,r,n.parent.A||e[0])}function r(n){n._.x=n.z+n.parent.m,n.m+=n.parent.m}function i(n,t,e){if(t){for(var r,i=n,u=n,o=t,l=i.parent.children[0],c=i.m,f=u.m,s=o.m,h=l.m;o=Ti(o),i=qi(i),o&&i;)l=qi(l),u=Ti(u),u.a=n,r=o.z+s-i.z-c+a(o._,i._),r>0&&(Ri(Pi(o,n,e),n,r),c+=r,f+=r),s+=o.m,c+=i.m,h+=l.m,f+=u.m;o&&!Ti(u)&&(u.t=o,u.m+=s-f),i&&!qi(l)&&(l.t=i,l.m+=c-h,e=n)}return e}function u(n){n.x*=l[0],n.y=n.depth*l[1]}var o=ao.layout.hierarchy().sort(null).value(null),a=Li,l=[1,1],c=null;return n.separation=function(t){return arguments.length?(a=t,n):a},n.size=function(t){return arguments.length?(c=null==(l=t)?u:null,n):c?null:l},n.nodeSize=function(t){return arguments.length?(c=null==(l=t)?null:u,n):c?l:null},ii(n,o)},ao.layout.cluster=function(){function n(n,u){var o,a=t.call(this,n,u),l=a[0],c=0;oi(l,function(n){var t=n.children;t&&t.length?(n.x=ji(t),n.y=Ui(t)):(n.x=o?c+=e(n,o):0,n.y=0,o=n)});var f=Fi(l),s=Hi(l),h=f.x-e(f,s)/2,p=s.x+e(s,f)/2;return oi(l,i?function(n){n.x=(n.x-l.x)*r[0],n.y=(l.y-n.y)*r[1]}:function(n){n.x=(n.x-h)/(p-h)*r[0],n.y=(1-(l.y?n.y/l.y:1))*r[1]}),a}var t=ao.layout.hierarchy().sort(null).value(null),e=Li,r=[1,1],i=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(i=null==(r=t),n):i?null:r},n.nodeSize=function(t){return arguments.length?(i=null!=(r=t),n):i?r:null},ii(n,t)},ao.layout.treemap=function(){function n(n,t){for(var e,r,i=-1,u=n.length;++i<u;)r=(e=n[i]).value*(0>t?0:t),e.area=isNaN(r)||0>=r?0:r}function t(e){var u=e.children;if(u&&u.length){var o,a,l,c=s(e),f=[],h=u.slice(),g=1/0,v="slice"===p?c.dx:"dice"===p?c.dy:"slice-dice"===p?1&e.depth?c.dy:c.dx:Math.min(c.dx,c.dy);for(n(h,c.dx*c.dy/e.value),f.area=0;(l=h.length)>0;)f.push(o=h[l-1]),f.area+=o.area,"squarify"!==p||(a=r(f,v))<=g?(h.pop(),g=a):(f.area-=f.pop().area,i(f,v,c,!1),v=Math.min(c.dx,c.dy),f.length=f.area=0,g=1/0);f.length&&(i(f,v,c,!0),f.length=f.area=0),u.forEach(t)}}function e(t){var r=t.children;if(r&&r.length){var u,o=s(t),a=r.slice(),l=[];for(n(a,o.dx*o.dy/t.value),l.area=0;u=a.pop();)l.push(u),l.area+=u.area,null!=u.z&&(i(l,u.z?o.dx:o.dy,o,!a.length),l.length=l.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,i=0,u=1/0,o=-1,a=n.length;++o<a;)(e=n[o].area)&&(u>e&&(u=e),e>i&&(i=e));return r*=r,t*=t,r?Math.max(t*i*g/r,r/(t*u*g)):1/0}function i(n,t,e,r){var i,u=-1,o=n.length,a=e.x,c=e.y,f=t?l(n.area/t):0;
|
5 |
-
if(t==e.dx){for((r||f>e.dy)&&(f=e.dy);++u<o;)i=n[u],i.x=a,i.y=c,i.dy=f,a+=i.dx=Math.min(e.x+e.dx-a,f?l(i.area/f):0);i.z=!0,i.dx+=e.x+e.dx-a,e.y+=f,e.dy-=f}else{for((r||f>e.dx)&&(f=e.dx);++u<o;)i=n[u],i.x=a,i.y=c,i.dx=f,c+=i.dy=Math.min(e.y+e.dy-c,f?l(i.area/f):0);i.z=!1,i.dy+=e.y+e.dy-c,e.x+=f,e.dx-=f}}function u(r){var i=o||a(r),u=i[0];return u.x=u.y=0,u.value?(u.dx=c[0],u.dy=c[1]):u.dx=u.dy=0,o&&a.revalue(u),n([u],u.dx*u.dy/u.value),(o?e:t)(u),h&&(o=i),i}var o,a=ao.layout.hierarchy(),l=Math.round,c=[1,1],f=null,s=Oi,h=!1,p="squarify",g=.5*(1+Math.sqrt(5));return u.size=function(n){return arguments.length?(c=n,u):c},u.padding=function(n){function t(t){var e=n.call(u,t,t.depth);return null==e?Oi(t):Ii(t,"number"==typeof e?[e,e,e,e]:e)}function e(t){return Ii(t,n)}if(!arguments.length)return f;var r;return s=null==(f=n)?Oi:"function"==(r=typeof n)?t:"number"===r?(n=[n,n,n,n],e):e,u},u.round=function(n){return arguments.length?(l=n?Math.round:Number,u):l!=Number},u.sticky=function(n){return arguments.length?(h=n,o=null,u):h},u.ratio=function(n){return arguments.length?(g=n,u):g},u.mode=function(n){return arguments.length?(p=n+"",u):p},ii(u,a)},ao.random={normal:function(n,t){var e=arguments.length;return 2>e&&(t=1),1>e&&(n=0),function(){var e,r,i;do e=2*Math.random()-1,r=2*Math.random()-1,i=e*e+r*r;while(!i||i>1);return n+t*e*Math.sqrt(-2*Math.log(i)/i)}},logNormal:function(){var n=ao.random.normal.apply(ao,arguments);return function(){return Math.exp(n())}},bates:function(n){var t=ao.random.irwinHall(n);return function(){return t()/n}},irwinHall:function(n){return function(){for(var t=0,e=0;n>e;e++)t+=Math.random();return t}}},ao.scale={};var Sl={floor:m,ceil:m};ao.scale.linear=function(){return Wi([0,1],[0,1],Mr,!1)};var kl={s:1,g:1,p:1,r:1,e:1};ao.scale.log=function(){return ru(ao.scale.linear().domain([0,1]),10,!0,[1,10])};var Nl=ao.format(".0e"),El={floor:function(n){return-Math.ceil(-n)},ceil:function(n){return-Math.floor(-n)}};ao.scale.pow=function(){return iu(ao.scale.linear(),1,[0,1])},ao.scale.sqrt=function(){return ao.scale.pow().exponent(.5)},ao.scale.ordinal=function(){return ou([],{t:"range",a:[[]]})},ao.scale.category10=function(){return ao.scale.ordinal().range(Al)},ao.scale.category20=function(){return ao.scale.ordinal().range(Cl)},ao.scale.category20b=function(){return ao.scale.ordinal().range(zl)},ao.scale.category20c=function(){return ao.scale.ordinal().range(Ll)};var Al=[2062260,16744206,2924588,14034728,9725885,9197131,14907330,8355711,12369186,1556175].map(xn),Cl=[2062260,11454440,16744206,16759672,2924588,10018698,14034728,16750742,9725885,12955861,9197131,12885140,14907330,16234194,8355711,13092807,12369186,14408589,1556175,10410725].map(xn),zl=[3750777,5395619,7040719,10264286,6519097,9216594,11915115,13556636,9202993,12426809,15186514,15190932,8666169,11356490,14049643,15177372,8077683,10834324,13528509,14589654].map(xn),Ll=[3244733,7057110,10406625,13032431,15095053,16616764,16625259,16634018,3253076,7652470,10607003,13101504,7695281,10394312,12369372,14342891,6513507,9868950,12434877,14277081].map(xn);ao.scale.quantile=function(){return au([],[])},ao.scale.quantize=function(){return lu(0,1,[0,1])},ao.scale.threshold=function(){return cu([.5],[0,1])},ao.scale.identity=function(){return fu([0,1])},ao.svg={},ao.svg.arc=function(){function n(){var n=Math.max(0,+e.apply(this,arguments)),c=Math.max(0,+r.apply(this,arguments)),f=o.apply(this,arguments)-Io,s=a.apply(this,arguments)-Io,h=Math.abs(s-f),p=f>s?0:1;if(n>c&&(g=c,c=n,n=g),h>=Oo)return t(c,p)+(n?t(n,1-p):"")+"Z";var g,v,d,y,m,M,x,b,_,w,S,k,N=0,E=0,A=[];if((y=(+l.apply(this,arguments)||0)/2)&&(d=u===ql?Math.sqrt(n*n+c*c):+u.apply(this,arguments),p||(E*=-1),c&&(E=tn(d/c*Math.sin(y))),n&&(N=tn(d/n*Math.sin(y)))),c){m=c*Math.cos(f+E),M=c*Math.sin(f+E),x=c*Math.cos(s-E),b=c*Math.sin(s-E);var C=Math.abs(s-f-2*E)<=Fo?0:1;if(E&&yu(m,M,x,b)===p^C){var z=(f+s)/2;m=c*Math.cos(z),M=c*Math.sin(z),x=b=null}}else m=M=0;if(n){_=n*Math.cos(s-N),w=n*Math.sin(s-N),S=n*Math.cos(f+N),k=n*Math.sin(f+N);var L=Math.abs(f-s+2*N)<=Fo?0:1;if(N&&yu(_,w,S,k)===1-p^L){var q=(f+s)/2;_=n*Math.cos(q),w=n*Math.sin(q),S=k=null}}else _=w=0;if(h>Uo&&(g=Math.min(Math.abs(c-n)/2,+i.apply(this,arguments)))>.001){v=c>n^p?0:1;var T=g,R=g;if(Fo>h){var D=null==S?[_,w]:null==x?[m,M]:Re([m,M],[S,k],[x,b],[_,w]),P=m-D[0],U=M-D[1],j=x-D[0],F=b-D[1],H=1/Math.sin(Math.acos((P*j+U*F)/(Math.sqrt(P*P+U*U)*Math.sqrt(j*j+F*F)))/2),O=Math.sqrt(D[0]*D[0]+D[1]*D[1]);R=Math.min(g,(n-O)/(H-1)),T=Math.min(g,(c-O)/(H+1))}if(null!=x){var I=mu(null==S?[_,w]:[S,k],[m,M],c,T,p),Y=mu([x,b],[_,w],c,T,p);g===T?A.push("M",I[0],"A",T,",",T," 0 0,",v," ",I[1],"A",c,",",c," 0 ",1-p^yu(I[1][0],I[1][1],Y[1][0],Y[1][1]),",",p," ",Y[1],"A",T,",",T," 0 0,",v," ",Y[0]):A.push("M",I[0],"A",T,",",T," 0 1,",v," ",Y[0])}else A.push("M",m,",",M);if(null!=S){var Z=mu([m,M],[S,k],n,-R,p),V=mu([_,w],null==x?[m,M]:[x,b],n,-R,p);g===R?A.push("L",V[0],"A",R,",",R," 0 0,",v," ",V[1],"A",n,",",n," 0 ",p^yu(V[1][0],V[1][1],Z[1][0],Z[1][1]),",",1-p," ",Z[1],"A",R,",",R," 0 0,",v," ",Z[0]):A.push("L",V[0],"A",R,",",R," 0 0,",v," ",Z[0])}else A.push("L",_,",",w)}else A.push("M",m,",",M),null!=x&&A.push("A",c,",",c," 0 ",C,",",p," ",x,",",b),A.push("L",_,",",w),null!=S&&A.push("A",n,",",n," 0 ",L,",",1-p," ",S,",",k);return A.push("Z"),A.join("")}function t(n,t){return"M0,"+n+"A"+n+","+n+" 0 1,"+t+" 0,"+-n+"A"+n+","+n+" 0 1,"+t+" 0,"+n}var e=hu,r=pu,i=su,u=ql,o=gu,a=vu,l=du;return n.innerRadius=function(t){return arguments.length?(e=En(t),n):e},n.outerRadius=function(t){return arguments.length?(r=En(t),n):r},n.cornerRadius=function(t){return arguments.length?(i=En(t),n):i},n.padRadius=function(t){return arguments.length?(u=t==ql?ql:En(t),n):u},n.startAngle=function(t){return arguments.length?(o=En(t),n):o},n.endAngle=function(t){return arguments.length?(a=En(t),n):a},n.padAngle=function(t){return arguments.length?(l=En(t),n):l},n.centroid=function(){var n=(+e.apply(this,arguments)+ +r.apply(this,arguments))/2,t=(+o.apply(this,arguments)+ +a.apply(this,arguments))/2-Io;return[Math.cos(t)*n,Math.sin(t)*n]},n};var ql="auto";ao.svg.line=function(){return Mu(m)};var Tl=ao.map({linear:xu,"linear-closed":bu,step:_u,"step-before":wu,"step-after":Su,basis:zu,"basis-open":Lu,"basis-closed":qu,bundle:Tu,cardinal:Eu,"cardinal-open":ku,"cardinal-closed":Nu,monotone:Fu});Tl.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var Rl=[0,2/3,1/3,0],Dl=[0,1/3,2/3,0],Pl=[0,1/6,2/3,1/6];ao.svg.line.radial=function(){var n=Mu(Hu);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},wu.reverse=Su,Su.reverse=wu,ao.svg.area=function(){return Ou(m)},ao.svg.area.radial=function(){var n=Ou(Hu);return n.radius=n.x,delete n.x,n.innerRadius=n.x0,delete n.x0,n.outerRadius=n.x1,delete n.x1,n.angle=n.y,delete n.y,n.startAngle=n.y0,delete n.y0,n.endAngle=n.y1,delete n.y1,n},ao.svg.chord=function(){function n(n,a){var l=t(this,u,n,a),c=t(this,o,n,a);return"M"+l.p0+r(l.r,l.p1,l.a1-l.a0)+(e(l,c)?i(l.r,l.p1,l.r,l.p0):i(l.r,l.p1,c.r,c.p0)+r(c.r,c.p1,c.a1-c.a0)+i(c.r,c.p1,l.r,l.p0))+"Z"}function t(n,t,e,r){var i=t.call(n,e,r),u=a.call(n,i,r),o=l.call(n,i,r)-Io,f=c.call(n,i,r)-Io;return{r:u,a0:o,a1:f,p0:[u*Math.cos(o),u*Math.sin(o)],p1:[u*Math.cos(f),u*Math.sin(f)]}}function e(n,t){return n.a0==t.a0&&n.a1==t.a1}function r(n,t,e){return"A"+n+","+n+" 0 "+ +(e>Fo)+",1 "+t}function i(n,t,e,r){return"Q 0,0 "+r}var u=Me,o=xe,a=Iu,l=gu,c=vu;return n.radius=function(t){return arguments.length?(a=En(t),n):a},n.source=function(t){return arguments.length?(u=En(t),n):u},n.target=function(t){return arguments.length?(o=En(t),n):o},n.startAngle=function(t){return arguments.length?(l=En(t),n):l},n.endAngle=function(t){return arguments.length?(c=En(t),n):c},n},ao.svg.diagonal=function(){function n(n,i){var u=t.call(this,n,i),o=e.call(this,n,i),a=(u.y+o.y)/2,l=[u,{x:u.x,y:a},{x:o.x,y:a},o];return l=l.map(r),"M"+l[0]+"C"+l[1]+" "+l[2]+" "+l[3]}var t=Me,e=xe,r=Yu;return n.source=function(e){return arguments.length?(t=En(e),n):t},n.target=function(t){return arguments.length?(e=En(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},ao.svg.diagonal.radial=function(){var n=ao.svg.diagonal(),t=Yu,e=n.projection;return n.projection=function(n){return arguments.length?e(Zu(t=n)):t},n},ao.svg.symbol=function(){function n(n,r){return(Ul.get(t.call(this,n,r))||$u)(e.call(this,n,r))}var t=Xu,e=Vu;return n.type=function(e){return arguments.length?(t=En(e),n):t},n.size=function(t){return arguments.length?(e=En(t),n):e},n};var Ul=ao.map({circle:$u,cross:function(n){var t=Math.sqrt(n/5)/2;return"M"+-3*t+","+-t+"H"+-t+"V"+-3*t+"H"+t+"V"+-t+"H"+3*t+"V"+t+"H"+t+"V"+3*t+"H"+-t+"V"+t+"H"+-3*t+"Z"},diamond:function(n){var t=Math.sqrt(n/(2*Fl)),e=t*Fl;return"M0,"+-t+"L"+e+",0 0,"+t+" "+-e+",0Z"},square:function(n){var t=Math.sqrt(n)/2;return"M"+-t+","+-t+"L"+t+","+-t+" "+t+","+t+" "+-t+","+t+"Z"},"triangle-down":function(n){var t=Math.sqrt(n/jl),e=t*jl/2;return"M0,"+e+"L"+t+","+-e+" "+-t+","+-e+"Z"},"triangle-up":function(n){var t=Math.sqrt(n/jl),e=t*jl/2;return"M0,"+-e+"L"+t+","+e+" "+-t+","+e+"Z"}});ao.svg.symbolTypes=Ul.keys();var jl=Math.sqrt(3),Fl=Math.tan(30*Yo);Co.transition=function(n){for(var t,e,r=Hl||++Zl,i=Ku(n),u=[],o=Ol||{time:Date.now(),ease:Nr,delay:0,duration:250},a=-1,l=this.length;++a<l;){u.push(t=[]);for(var c=this[a],f=-1,s=c.length;++f<s;)(e=c[f])&&Qu(e,f,i,r,o),t.push(e)}return Wu(u,i,r)},Co.interrupt=function(n){return this.each(null==n?Il:Bu(Ku(n)))};var Hl,Ol,Il=Bu(Ku()),Yl=[],Zl=0;Yl.call=Co.call,Yl.empty=Co.empty,Yl.node=Co.node,Yl.size=Co.size,ao.transition=function(n,t){return n&&n.transition?Hl?n.transition(t):n:ao.selection().transition(n)},ao.transition.prototype=Yl,Yl.select=function(n){var t,e,r,i=this.id,u=this.namespace,o=[];n=A(n);for(var a=-1,l=this.length;++a<l;){o.push(t=[]);for(var c=this[a],f=-1,s=c.length;++f<s;)(r=c[f])&&(e=n.call(r,r.__data__,f,a))?("__data__"in r&&(e.__data__=r.__data__),Qu(e,f,u,i,r[u][i]),t.push(e)):t.push(null)}return Wu(o,u,i)},Yl.selectAll=function(n){var t,e,r,i,u,o=this.id,a=this.namespace,l=[];n=C(n);for(var c=-1,f=this.length;++c<f;)for(var s=this[c],h=-1,p=s.length;++h<p;)if(r=s[h]){u=r[a][o],e=n.call(r,r.__data__,h,c),l.push(t=[]);for(var g=-1,v=e.length;++g<v;)(i=e[g])&&Qu(i,g,a,o,u),t.push(i)}return Wu(l,a,o)},Yl.filter=function(n){var t,e,r,i=[];"function"!=typeof n&&(n=O(n));for(var u=0,o=this.length;o>u;u++){i.push(t=[]);for(var e=this[u],a=0,l=e.length;l>a;a++)(r=e[a])&&n.call(r,r.__data__,a,u)&&t.push(r)}return Wu(i,this.namespace,this.id)},Yl.tween=function(n,t){var e=this.id,r=this.namespace;return arguments.length<2?this.node()[r][e].tween.get(n):Y(this,null==t?function(t){t[r][e].tween.remove(n)}:function(i){i[r][e].tween.set(n,t)})},Yl.attr=function(n,t){function e(){this.removeAttribute(a)}function r(){this.removeAttributeNS(a.space,a.local)}function i(n){return null==n?e:(n+="",function(){var t,e=this.getAttribute(a);return e!==n&&(t=o(e,n),function(n){this.setAttribute(a,t(n))})})}function u(n){return null==n?r:(n+="",function(){var t,e=this.getAttributeNS(a.space,a.local);return e!==n&&(t=o(e,n),function(n){this.setAttributeNS(a.space,a.local,t(n))})})}if(arguments.length<2){for(t in n)this.attr(t,n[t]);return this}var o="transform"==n?$r:Mr,a=ao.ns.qualify(n);return Ju(this,"attr."+n,t,a.local?u:i)},Yl.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(i));return r&&function(n){this.setAttribute(i,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(i.space,i.local));return r&&function(n){this.setAttributeNS(i.space,i.local,r(n))}}var i=ao.ns.qualify(n);return this.tween("attr."+n,i.local?r:e)},Yl.style=function(n,e,r){function i(){this.style.removeProperty(n)}function u(e){return null==e?i:(e+="",function(){var i,u=t(this).getComputedStyle(this,null).getPropertyValue(n);return u!==e&&(i=Mr(u,e),function(t){this.style.setProperty(n,i(t),r)})})}var o=arguments.length;if(3>o){if("string"!=typeof n){2>o&&(e="");for(r in n)this.style(r,n[r],e);return this}r=""}return Ju(this,"style."+n,e,u)},Yl.styleTween=function(n,e,r){function i(i,u){var o=e.call(this,i,u,t(this).getComputedStyle(this,null).getPropertyValue(n));return o&&function(t){this.style.setProperty(n,o(t),r)}}return arguments.length<3&&(r=""),this.tween("style."+n,i)},Yl.text=function(n){return Ju(this,"text",n,Gu)},Yl.remove=function(){var n=this.namespace;return this.each("end.transition",function(){var t;this[n].count<2&&(t=this.parentNode)&&t.removeChild(this)})},Yl.ease=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].ease:("function"!=typeof n&&(n=ao.ease.apply(ao,arguments)),Y(this,function(r){r[e][t].ease=n}))},Yl.delay=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].delay:Y(this,"function"==typeof n?function(r,i,u){r[e][t].delay=+n.call(r,r.__data__,i,u)}:(n=+n,function(r){r[e][t].delay=n}))},Yl.duration=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].duration:Y(this,"function"==typeof n?function(r,i,u){r[e][t].duration=Math.max(1,n.call(r,r.__data__,i,u))}:(n=Math.max(1,n),function(r){r[e][t].duration=n}))},Yl.each=function(n,t){var e=this.id,r=this.namespace;if(arguments.length<2){var i=Ol,u=Hl;try{Hl=e,Y(this,function(t,i,u){Ol=t[r][e],n.call(t,t.__data__,i,u)})}finally{Ol=i,Hl=u}}else Y(this,function(i){var u=i[r][e];(u.event||(u.event=ao.dispatch("start","end","interrupt"))).on(n,t)});return this},Yl.transition=function(){for(var n,t,e,r,i=this.id,u=++Zl,o=this.namespace,a=[],l=0,c=this.length;c>l;l++){a.push(n=[]);for(var t=this[l],f=0,s=t.length;s>f;f++)(e=t[f])&&(r=e[o][i],Qu(e,f,o,u,{time:r.time,ease:r.ease,delay:r.delay+r.duration,duration:r.duration})),n.push(e)}return Wu(a,o,u)},ao.svg.axis=function(){function n(n){n.each(function(){var n,c=ao.select(this),f=this.__chart__||e,s=this.__chart__=e.copy(),h=null==l?s.ticks?s.ticks.apply(s,a):s.domain():l,p=null==t?s.tickFormat?s.tickFormat.apply(s,a):m:t,g=c.selectAll(".tick").data(h,s),v=g.enter().insert("g",".domain").attr("class","tick").style("opacity",Uo),d=ao.transition(g.exit()).style("opacity",Uo).remove(),y=ao.transition(g.order()).style("opacity",1),M=Math.max(i,0)+o,x=Zi(s),b=c.selectAll(".domain").data([0]),_=(b.enter().append("path").attr("class","domain"),ao.transition(b));v.append("line"),v.append("text");var w,S,k,N,E=v.select("line"),A=y.select("line"),C=g.select("text").text(p),z=v.select("text"),L=y.select("text"),q="top"===r||"left"===r?-1:1;if("bottom"===r||"top"===r?(n=no,w="x",k="y",S="x2",N="y2",C.attr("dy",0>q?"0em":".71em").style("text-anchor","middle"),_.attr("d","M"+x[0]+","+q*u+"V0H"+x[1]+"V"+q*u)):(n=to,w="y",k="x",S="y2",N="x2",C.attr("dy",".32em").style("text-anchor",0>q?"end":"start"),_.attr("d","M"+q*u+","+x[0]+"H0V"+x[1]+"H"+q*u)),E.attr(N,q*i),z.attr(k,q*M),A.attr(S,0).attr(N,q*i),L.attr(w,0).attr(k,q*M),s.rangeBand){var T=s,R=T.rangeBand()/2;f=s=function(n){return T(n)+R}}else f.rangeBand?f=s:d.call(n,s,f);v.call(n,f,s),y.call(n,s,s)})}var t,e=ao.scale.linear(),r=Vl,i=6,u=6,o=3,a=[10],l=null;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in Xl?t+"":Vl,n):r},n.ticks=function(){return arguments.length?(a=co(arguments),n):a},n.tickValues=function(t){return arguments.length?(l=t,n):l},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t){var e=arguments.length;return e?(i=+t,u=+arguments[e-1],n):i},n.innerTickSize=function(t){return arguments.length?(i=+t,n):i},n.outerTickSize=function(t){return arguments.length?(u=+t,n):u},n.tickPadding=function(t){return arguments.length?(o=+t,n):o},n.tickSubdivide=function(){return arguments.length&&n},n};var Vl="bottom",Xl={top:1,right:1,bottom:1,left:1};ao.svg.brush=function(){function n(t){t.each(function(){var t=ao.select(this).style("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush",u).on("touchstart.brush",u),o=t.selectAll(".background").data([0]);o.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),t.selectAll(".extent").data([0]).enter().append("rect").attr("class","extent").style("cursor","move");var a=t.selectAll(".resize").data(v,m);a.exit().remove(),a.enter().append("g").attr("class",function(n){return"resize "+n}).style("cursor",function(n){return $l[n]}).append("rect").attr("x",function(n){return/[ew]$/.test(n)?-3:null}).attr("y",function(n){return/^[ns]/.test(n)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),a.style("display",n.empty()?"none":null);var l,s=ao.transition(t),h=ao.transition(o);c&&(l=Zi(c),h.attr("x",l[0]).attr("width",l[1]-l[0]),r(s)),f&&(l=Zi(f),h.attr("y",l[0]).attr("height",l[1]-l[0]),i(s)),e(s)})}function e(n){n.selectAll(".resize").attr("transform",function(n){return"translate("+s[+/e$/.test(n)]+","+h[+/^s/.test(n)]+")"})}function r(n){n.select(".extent").attr("x",s[0]),n.selectAll(".extent,.n>rect,.s>rect").attr("width",s[1]-s[0])}function i(n){n.select(".extent").attr("y",h[0]),n.selectAll(".extent,.e>rect,.w>rect").attr("height",h[1]-h[0])}function u(){function u(){32==ao.event.keyCode&&(C||(M=null,L[0]-=s[1],L[1]-=h[1],C=2),S())}function v(){32==ao.event.keyCode&&2==C&&(L[0]+=s[1],L[1]+=h[1],C=0,S())}function d(){var n=ao.mouse(b),t=!1;x&&(n[0]+=x[0],n[1]+=x[1]),C||(ao.event.altKey?(M||(M=[(s[0]+s[1])/2,(h[0]+h[1])/2]),L[0]=s[+(n[0]<M[0])],L[1]=h[+(n[1]<M[1])]):M=null),E&&y(n,c,0)&&(r(k),t=!0),A&&y(n,f,1)&&(i(k),t=!0),t&&(e(k),w({type:"brush",mode:C?"move":"resize"}))}function y(n,t,e){var r,i,u=Zi(t),l=u[0],c=u[1],f=L[e],v=e?h:s,d=v[1]-v[0];return C&&(l-=f,c-=d+f),r=(e?g:p)?Math.max(l,Math.min(c,n[e])):n[e],C?i=(r+=f)+d:(M&&(f=Math.max(l,Math.min(c,2*M[e]-r))),r>f?(i=r,r=f):i=f),v[0]!=r||v[1]!=i?(e?a=null:o=null,v[0]=r,v[1]=i,!0):void 0}function m(){d(),k.style("pointer-events","all").selectAll(".resize").style("display",n.empty()?"none":null),ao.select("body").style("cursor",null),q.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touchend.brush",null).on("keydown.brush",null).on("keyup.brush",null),z(),w({type:"brushend"})}var M,x,b=this,_=ao.select(ao.event.target),w=l.of(b,arguments),k=ao.select(b),N=_.datum(),E=!/^(n|s)$/.test(N)&&c,A=!/^(e|w)$/.test(N)&&f,C=_.classed("extent"),z=W(b),L=ao.mouse(b),q=ao.select(t(b)).on("keydown.brush",u).on("keyup.brush",v);if(ao.event.changedTouches?q.on("touchmove.brush",d).on("touchend.brush",m):q.on("mousemove.brush",d).on("mouseup.brush",m),k.interrupt().selectAll("*").interrupt(),C)L[0]=s[0]-L[0],L[1]=h[0]-L[1];else if(N){var T=+/w$/.test(N),R=+/^n/.test(N);x=[s[1-T]-L[0],h[1-R]-L[1]],L[0]=s[T],L[1]=h[R]}else ao.event.altKey&&(M=L.slice());k.style("pointer-events","none").selectAll(".resize").style("display",null),ao.select("body").style("cursor",_.style("cursor")),w({type:"brushstart"}),d()}var o,a,l=N(n,"brushstart","brush","brushend"),c=null,f=null,s=[0,0],h=[0,0],p=!0,g=!0,v=Bl[0];return n.event=function(n){n.each(function(){var n=l.of(this,arguments),t={x:s,y:h,i:o,j:a},e=this.__chart__||t;this.__chart__=t,Hl?ao.select(this).transition().each("start.brush",function(){o=e.i,a=e.j,s=e.x,h=e.y,n({type:"brushstart"})}).tween("brush:brush",function(){var e=xr(s,t.x),r=xr(h,t.y);return o=a=null,function(i){s=t.x=e(i),h=t.y=r(i),n({type:"brush",mode:"resize"})}}).each("end.brush",function(){o=t.i,a=t.j,n({type:"brush",mode:"resize"}),n({type:"brushend"})}):(n({type:"brushstart"}),n({type:"brush",mode:"resize"}),n({type:"brushend"}))})},n.x=function(t){return arguments.length?(c=t,v=Bl[!c<<1|!f],n):c},n.y=function(t){return arguments.length?(f=t,v=Bl[!c<<1|!f],n):f},n.clamp=function(t){return arguments.length?(c&&f?(p=!!t[0],g=!!t[1]):c?p=!!t:f&&(g=!!t),n):c&&f?[p,g]:c?p:f?g:null},n.extent=function(t){var e,r,i,u,l;return arguments.length?(c&&(e=t[0],r=t[1],f&&(e=e[0],r=r[0]),o=[e,r],c.invert&&(e=c(e),r=c(r)),e>r&&(l=e,e=r,r=l),e==s[0]&&r==s[1]||(s=[e,r])),f&&(i=t[0],u=t[1],c&&(i=i[1],u=u[1]),a=[i,u],f.invert&&(i=f(i),u=f(u)),i>u&&(l=i,i=u,u=l),i==h[0]&&u==h[1]||(h=[i,u])),n):(c&&(o?(e=o[0],r=o[1]):(e=s[0],r=s[1],c.invert&&(e=c.invert(e),r=c.invert(r)),e>r&&(l=e,e=r,r=l))),f&&(a?(i=a[0],u=a[1]):(i=h[0],u=h[1],f.invert&&(i=f.invert(i),u=f.invert(u)),i>u&&(l=i,i=u,u=l))),c&&f?[[e,i],[r,u]]:c?[e,r]:f&&[i,u])},n.clear=function(){return n.empty()||(s=[0,0],h=[0,0],o=a=null),n},n.empty=function(){return!!c&&s[0]==s[1]||!!f&&h[0]==h[1]},ao.rebind(n,l,"on")};var $l={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},Bl=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]],Wl=ga.format=xa.timeFormat,Jl=Wl.utc,Gl=Jl("%Y-%m-%dT%H:%M:%S.%LZ");Wl.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?eo:Gl,eo.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},eo.toString=Gl.toString,ga.second=On(function(n){return new va(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),ga.seconds=ga.second.range,ga.seconds.utc=ga.second.utc.range,ga.minute=On(function(n){return new va(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),ga.minutes=ga.minute.range,ga.minutes.utc=ga.minute.utc.range,ga.hour=On(function(n){var t=n.getTimezoneOffset()/60;return new va(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),ga.hours=ga.hour.range,ga.hours.utc=ga.hour.utc.range,ga.month=On(function(n){return n=ga.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),ga.months=ga.month.range,ga.months.utc=ga.month.utc.range;var Kl=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Ql=[[ga.second,1],[ga.second,5],[ga.second,15],[ga.second,30],[ga.minute,1],[ga.minute,5],[ga.minute,15],[ga.minute,30],[ga.hour,1],[ga.hour,3],[ga.hour,6],[ga.hour,12],[ga.day,1],[ga.day,2],[ga.week,1],[ga.month,1],[ga.month,3],[ga.year,1]],nc=Wl.multi([[".%L",function(n){return n.getMilliseconds()}],[":%S",function(n){return n.getSeconds()}],["%I:%M",function(n){return n.getMinutes()}],["%I %p",function(n){return n.getHours()}],["%a %d",function(n){return n.getDay()&&1!=n.getDate()}],["%b %d",function(n){return 1!=n.getDate()}],["%B",function(n){return n.getMonth()}],["%Y",zt]]),tc={range:function(n,t,e){return ao.range(Math.ceil(n/e)*e,+t,e).map(io)},floor:m,ceil:m};Ql.year=ga.year,ga.scale=function(){return ro(ao.scale.linear(),Ql,nc)};var ec=Ql.map(function(n){return[n[0].utc,n[1]]}),rc=Jl.multi([[".%L",function(n){return n.getUTCMilliseconds()}],[":%S",function(n){return n.getUTCSeconds()}],["%I:%M",function(n){return n.getUTCMinutes()}],["%I %p",function(n){return n.getUTCHours()}],["%a %d",function(n){return n.getUTCDay()&&1!=n.getUTCDate()}],["%b %d",function(n){return 1!=n.getUTCDate()}],["%B",function(n){return n.getUTCMonth()}],["%Y",zt]]);ec.year=ga.year.utc,ga.scale.utc=function(){return ro(ao.scale.linear(),ec,rc)},ao.text=An(function(n){return n.responseText}),ao.json=function(n,t){return Cn(n,"application/json",uo,t)},ao.html=function(n,t){return Cn(n,"text/html",oo,t)},ao.xml=An(function(n){return n.responseXML}),"function"==typeof define&&define.amd?(this.d3=ao,define(ao)):"object"==typeof module&&module.exports?module.exports=ao:this.d3=ao}();
|
|
|
|
|
|
|
|
|
|
inc/js/scripts.js
CHANGED
@@ -82,9 +82,26 @@ jQuery(document).ready(function ($) {
|
|
82 |
$('.sucuriscan-container').on('mouseover', '.sucuriscan-tooltip', function (event) {
|
83 |
var element = $(this);
|
84 |
var content = element.attr('content');
|
|
|
|
|
|
|
|
|
|
|
|
|
85 |
var tooltip = $('<div>', { 'class': 'sucuriscan-tooltip-object' });
|
86 |
|
87 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
element.append(tooltip);
|
89 |
var arrowHeight = 10; /* border width */
|
90 |
var tooltipHeight = tooltip.outerHeight();
|
82 |
$('.sucuriscan-container').on('mouseover', '.sucuriscan-tooltip', function (event) {
|
83 |
var element = $(this);
|
84 |
var content = element.attr('content');
|
85 |
+
|
86 |
+
if (!content) {
|
87 |
+
return;
|
88 |
+
}
|
89 |
+
|
90 |
+
/* create instance of tooltip container */
|
91 |
var tooltip = $('<div>', { 'class': 'sucuriscan-tooltip-object' });
|
92 |
|
93 |
+
if (element.attr('tooltip-width')) {
|
94 |
+
var customWidth = element.attr('tooltip-width');
|
95 |
+
tooltip.css('width', customWidth);
|
96 |
+
}
|
97 |
+
|
98 |
+
/* interpret HTML code as is; careful with XSS */
|
99 |
+
if (element.attr('tooltip-html') === 'true') {
|
100 |
+
tooltip.html(content);
|
101 |
+
} else {
|
102 |
+
tooltip.text(content);
|
103 |
+
}
|
104 |
+
|
105 |
element.append(tooltip);
|
106 |
var arrowHeight = 10; /* border width */
|
107 |
var tooltipHeight = tooltip.outerHeight();
|
inc/tpl/auditlogs-report.html.tpl
DELETED
@@ -1,103 +0,0 @@
|
|
1 |
-
|
2 |
-
<script type="text/javascript">
|
3 |
-
/* global c3 */
|
4 |
-
/* global jQuery */
|
5 |
-
/* jshint camelcase:false */
|
6 |
-
jQuery(function ($) {
|
7 |
-
var sucuriscanPieChart = function (element, series, colors) {
|
8 |
-
c3.generate({
|
9 |
-
bindto: element,
|
10 |
-
size: { height: 250 },
|
11 |
-
padding: { top: 10, bottom: 10 },
|
12 |
-
color: { pattern: colors },
|
13 |
-
legend: { position: 'right' },
|
14 |
-
data: { type: 'pie', labels: true, columns: series },
|
15 |
-
});
|
16 |
-
};
|
17 |
-
|
18 |
-
var sucuriscanBarChart = function (element, categories, series) {
|
19 |
-
c3.generate({
|
20 |
-
bindto: element,
|
21 |
-
size: { height: 320 },
|
22 |
-
padding: { top: 10, bottom: 0 },
|
23 |
-
tooltip: { show: false },
|
24 |
-
legend: { show: false },
|
25 |
-
data: { type: 'bar', labels: true, columns: [ series ] },
|
26 |
-
axis: {
|
27 |
-
rotated: true,
|
28 |
-
x: { type: 'category', categories: categories },
|
29 |
-
},
|
30 |
-
});
|
31 |
-
};
|
32 |
-
|
33 |
-
$.post('%%SUCURI.AjaxURL.Dashboard%%', {
|
34 |
-
action: 'sucuriscan_ajax',
|
35 |
-
sucuriscan_page_nonce: '%%SUCURI.PageNonce%%',
|
36 |
-
form_action: 'get_audit_logs_report',
|
37 |
-
}, function (data) {
|
38 |
-
$('#sucuriscan-audit-report-response').html(data.message);
|
39 |
-
|
40 |
-
if (data.status) {
|
41 |
-
$('.sucuriscan-report-chart').removeClass('sucuriscan-hidden');
|
42 |
-
|
43 |
-
/* Pie-chart with number of audit logs per event type. */
|
44 |
-
sucuriscanPieChart(
|
45 |
-
'#sucuriscan-report-events-per-type',
|
46 |
-
data.eventsPerTypePoints,
|
47 |
-
data.eventsPerTypeColors
|
48 |
-
);
|
49 |
-
|
50 |
-
/* Column-chart with number of audit logs per event login. */
|
51 |
-
sucuriscanPieChart(
|
52 |
-
'#sucuriscan-report-events-per-login',
|
53 |
-
data.eventsPerLogin,
|
54 |
-
[ '#5cb85c', '#f27d7d' ]
|
55 |
-
);
|
56 |
-
|
57 |
-
/* Bar-chart with number of audit logs per user account. */
|
58 |
-
sucuriscanBarChart(
|
59 |
-
'#sucuriscan-report-events-per-user',
|
60 |
-
data.eventsPerUserCategories,
|
61 |
-
data.eventsPerUserSeries
|
62 |
-
);
|
63 |
-
|
64 |
-
/* Bar-chart with number of audit logs per remote address. */
|
65 |
-
sucuriscanBarChart(
|
66 |
-
'#sucuriscan-report-events-per-ipaddress',
|
67 |
-
data.eventsPerIPAddressCategories,
|
68 |
-
data.eventsPerIPAddressSeries
|
69 |
-
);
|
70 |
-
}
|
71 |
-
});
|
72 |
-
});
|
73 |
-
</script>
|
74 |
-
|
75 |
-
<div class="sucuriscan-audit-report">
|
76 |
-
<div class="sucuriscan-inline-alert-info">
|
77 |
-
<p>@@SUCURI.LogsReportInfo@@</p>
|
78 |
-
</div>
|
79 |
-
|
80 |
-
<div id="sucuriscan-audit-report-response">
|
81 |
-
<p>@@SUCURI.Loading@@</p>
|
82 |
-
</div>
|
83 |
-
|
84 |
-
<div class="sucuriscan-report-chart sucuriscan-hidden">
|
85 |
-
<h4>@@SUCURI.LogsPerEvent@@</h4>
|
86 |
-
<div id="sucuriscan-report-events-per-type"></div>
|
87 |
-
</div>
|
88 |
-
|
89 |
-
<div class="sucuriscan-report-chart sucuriscan-hidden">
|
90 |
-
<h4>@@SUCURI.LogsForLogins@@</h4>
|
91 |
-
<div id="sucuriscan-report-events-per-login"></div>
|
92 |
-
</div>
|
93 |
-
|
94 |
-
<div class="sucuriscan-report-chart sucuriscan-hidden">
|
95 |
-
<h4>@@SUCURI.LogsPerUser@@</h4>
|
96 |
-
<div id="sucuriscan-report-events-per-user"></div>
|
97 |
-
</div>
|
98 |
-
|
99 |
-
<div class="sucuriscan-report-chart sucuriscan-hidden">
|
100 |
-
<h4>@@SUCURI.LogsPerIP@@</h4>
|
101 |
-
<div id="sucuriscan-report-events-per-ipaddress"></div>
|
102 |
-
</div>
|
103 |
-
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inc/tpl/auditlogs.html.tpl
CHANGED
@@ -3,8 +3,7 @@
|
|
3 |
/* global jQuery */
|
4 |
/* jshint camelcase:false */
|
5 |
jQuery(function ($) {
|
6 |
-
var writeQueueSize = function (queueSize)
|
7 |
-
{
|
8 |
if (queueSize === 0) {
|
9 |
$('.sucuriscan-auditlogs-sendlogs-response').html('');
|
10 |
$('.sucuriscan-sendlogs-panel').addClass('sucuriscan-hidden');
|
@@ -15,19 +14,16 @@ jQuery(function ($) {
|
|
15 |
}
|
16 |
};
|
17 |
|
18 |
-
var sucuriscanLoadAuditLogs = function (page
|
19 |
var url = '%%SUCURI.AjaxURL.Dashboard%%';
|
20 |
|
21 |
if (page !== undefined && page > 0) {
|
22 |
url += '&paged=' + page;
|
23 |
}
|
24 |
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
$('.sucuriscan-auditlog-status').html('');
|
30 |
-
$('.sucuriscan-pagination-loading').html('');
|
31 |
$('.sucuriscan-pagination-panel').addClass('sucuriscan-hidden');
|
32 |
$('.sucuriscan-auditlog-footer').addClass('sucuriscan-hidden');
|
33 |
|
@@ -63,23 +59,44 @@ jQuery(function ($) {
|
|
63 |
}
|
64 |
|
65 |
setTimeout(function () {
|
66 |
-
sucuriscanLoadAuditLogs(0
|
67 |
}, 100);
|
68 |
|
69 |
$('.sucuriscan-auditlog-table').on('click', '.sucuriscan-pagination-link', function (event) {
|
70 |
event.preventDefault();
|
|
|
71 |
sucuriscanLoadAuditLogs($(this).attr('data-page'));
|
72 |
});
|
73 |
|
74 |
$('.sucuriscan-auditlog-table').on('click', '.sucuriscan-auditlogs-sendlogs', function (event) {
|
75 |
event.preventDefault();
|
|
|
|
|
76 |
$('.sucuriscan-auditlogs-sendlogs-response').html('@@SUCURI.Loading@@');
|
|
|
77 |
$.post('%%SUCURI.AjaxURL.Dashboard%%', {
|
78 |
action: 'sucuriscan_ajax',
|
79 |
sucuriscan_page_nonce: '%%SUCURI.PageNonce%%',
|
80 |
form_action: 'auditlogs_send_logs',
|
81 |
-
}, function () {
|
82 |
-
sucuriscanLoadAuditLogs(0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
83 |
});
|
84 |
});
|
85 |
});
|
@@ -101,7 +118,8 @@ jQuery(function ($) {
|
|
101 |
</div>
|
102 |
|
103 |
<div class="sucuriscan-clearfix sucuriscan-auditlog-footer">
|
104 |
-
<div class="sucuriscan-pull-left sucuriscan-hidden sucuriscan-
|
|
|
105 |
<small class="sucuriscan-auditlogs-sendlogs-response"></small>
|
106 |
<small><a href="#" class="sucuriscan-auditlogs-sendlogs">@@SUCURI.SendLogs@@</a></small>
|
107 |
</div>
|
3 |
/* global jQuery */
|
4 |
/* jshint camelcase:false */
|
5 |
jQuery(function ($) {
|
6 |
+
var writeQueueSize = function (queueSize) {
|
|
|
7 |
if (queueSize === 0) {
|
8 |
$('.sucuriscan-auditlogs-sendlogs-response').html('');
|
9 |
$('.sucuriscan-sendlogs-panel').addClass('sucuriscan-hidden');
|
14 |
}
|
15 |
};
|
16 |
|
17 |
+
var sucuriscanLoadAuditLogs = function (page) {
|
18 |
var url = '%%SUCURI.AjaxURL.Dashboard%%';
|
19 |
|
20 |
if (page !== undefined && page > 0) {
|
21 |
url += '&paged=' + page;
|
22 |
}
|
23 |
|
24 |
+
$('.sucuriscan-auditlog-response').html('<em>@@SUCURI.Loading@@</em>');
|
25 |
+
$('.sucuriscan-auditlog-status').html('@@SUCURI.Loading@@');
|
26 |
+
$('.sucuriscan-pagination-loading').html('@@SUCURI.Loading@@');
|
|
|
|
|
|
|
27 |
$('.sucuriscan-pagination-panel').addClass('sucuriscan-hidden');
|
28 |
$('.sucuriscan-auditlog-footer').addClass('sucuriscan-hidden');
|
29 |
|
59 |
}
|
60 |
|
61 |
setTimeout(function () {
|
62 |
+
sucuriscanLoadAuditLogs(0);
|
63 |
}, 100);
|
64 |
|
65 |
$('.sucuriscan-auditlog-table').on('click', '.sucuriscan-pagination-link', function (event) {
|
66 |
event.preventDefault();
|
67 |
+
window.scrollTo(0, $('#sucuriscan-integrity-response').height() + 100);
|
68 |
sucuriscanLoadAuditLogs($(this).attr('data-page'));
|
69 |
});
|
70 |
|
71 |
$('.sucuriscan-auditlog-table').on('click', '.sucuriscan-auditlogs-sendlogs', function (event) {
|
72 |
event.preventDefault();
|
73 |
+
|
74 |
+
$('.sucuriscan-sendlogs-panel').attr('content', '');
|
75 |
$('.sucuriscan-auditlogs-sendlogs-response').html('@@SUCURI.Loading@@');
|
76 |
+
|
77 |
$.post('%%SUCURI.AjaxURL.Dashboard%%', {
|
78 |
action: 'sucuriscan_ajax',
|
79 |
sucuriscan_page_nonce: '%%SUCURI.PageNonce%%',
|
80 |
form_action: 'auditlogs_send_logs',
|
81 |
+
}, function (data) {
|
82 |
+
sucuriscanLoadAuditLogs(0);
|
83 |
+
|
84 |
+
setTimeout(function (){
|
85 |
+
var tooltipContent =
|
86 |
+
'Total logs in the queue: {TTLLOGS}<br>' +
|
87 |
+
'Maximum execution time: {MAXTIME}<br>' +
|
88 |
+
'Successfully sent to the API: {SUCCESS}<br>' +
|
89 |
+
'Total request timeouts (failures): {FAILURE}<br>' +
|
90 |
+
'Total execution time: {ELAPSED} secs';
|
91 |
+
$('.sucuriscan-sendlogs-panel')
|
92 |
+
.attr('content', tooltipContent
|
93 |
+
.replace('{MAXTIME}', data.maxtime)
|
94 |
+
.replace('{TTLLOGS}', data.ttllogs)
|
95 |
+
.replace('{SUCCESS}', data.success)
|
96 |
+
.replace('{FAILURE}', data.failure)
|
97 |
+
.replace('{ELAPSED}', data.elapsed)
|
98 |
+
);
|
99 |
+
}, 200);
|
100 |
});
|
101 |
});
|
102 |
});
|
118 |
</div>
|
119 |
|
120 |
<div class="sucuriscan-clearfix sucuriscan-auditlog-footer">
|
121 |
+
<div class="sucuriscan-pull-left sucuriscan-hidden sucuriscan-tooltip
|
122 |
+
sucuriscan-sendlogs-panel" tooltip-width="250" tooltip-html="true">
|
123 |
<small class="sucuriscan-auditlogs-sendlogs-response"></small>
|
124 |
<small><a href="#" class="sucuriscan-auditlogs-sendlogs">@@SUCURI.SendLogs@@</a></small>
|
125 |
</div>
|
inc/tpl/dashboard.html.tpl
CHANGED
@@ -5,6 +5,26 @@
|
|
5 |
/* global jQuery */
|
6 |
/* jshint camelcase: false */
|
7 |
jQuery(function ($) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8 |
$.post('%%SUCURI.AjaxURL.Dashboard%%', {
|
9 |
action: 'sucuriscan_ajax',
|
10 |
sucuriscan_page_nonce: '%%SUCURI.PageNonce%%',
|
@@ -14,9 +34,9 @@ jQuery(function ($) {
|
|
14 |
$('#sucuriscan-title-links').html(data.links.title);
|
15 |
$('#sucuriscan-title-scripts').html(data.scripts.title);
|
16 |
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
|
21 |
$('#sucuriscan-malware').html(data.malware);
|
22 |
$('#sucuriscan-blacklist').html(data.blacklist);
|
@@ -31,7 +51,6 @@ jQuery(function ($) {
|
|
31 |
<div class="sucuriscan-tabs">
|
32 |
<ul class="sucuriscan-clearfix sucuriscan-tabs-buttons">
|
33 |
<li><a href="%%SUCURI.URL.Dashboard%%#auditlogs">@@SUCURI.AuditLogs@@</a></li>
|
34 |
-
<li><a href="%%SUCURI.URL.Dashboard%%#stats">@@SUCURI.Statistics@@</a></li>
|
35 |
<li><a href="%%SUCURI.URL.Dashboard%%#iframes" id="sucuriscan-title-iframes">%%SUCURI.SiteCheck.iFramesTitle%%</a></li>
|
36 |
<li><a href="%%SUCURI.URL.Dashboard%%#links" id="sucuriscan-title-links">%%SUCURI.SiteCheck.LinksTitle%%</a></li>
|
37 |
<li><a href="%%SUCURI.URL.Dashboard%%#scripts" id="sucuriscan-title-scripts">%%SUCURI.SiteCheck.ScriptsTitle%%</a></li>
|
@@ -42,10 +61,6 @@ jQuery(function ($) {
|
|
42 |
%%%SUCURI.AuditLogs%%%
|
43 |
</div>
|
44 |
|
45 |
-
<div id="sucuriscan-tabs-stats">
|
46 |
-
%%%SUCURI.AuditLogsReport%%%
|
47 |
-
</div>
|
48 |
-
|
49 |
<div id="sucuriscan-tabs-iframes">
|
50 |
%%%SUCURI.SiteCheck.iFramesContent%%%
|
51 |
</div>
|
5 |
/* global jQuery */
|
6 |
/* jshint camelcase: false */
|
7 |
jQuery(function ($) {
|
8 |
+
var sucuriscanSiteCheckLinks = function (target, links) {
|
9 |
+
if (links.length === 0) {
|
10 |
+
$(target).html('<div><em>@@SUCURI.NoData@@</em></div>');
|
11 |
+
return;
|
12 |
+
}
|
13 |
+
|
14 |
+
var tbody = $('<tbody>');
|
15 |
+
var options = {class: 'wp-list-table widefat sucuriscan-table'};
|
16 |
+
|
17 |
+
for (var key in links) {
|
18 |
+
if (links.hasOwnProperty(key)) {
|
19 |
+
tbody.append('<tr><td><a href="' + links[key] + '" target="_b' +
|
20 |
+
'lank" class="sucuriscan-monospace">' + links[key] + '</a></t' +
|
21 |
+
'd></tr>');
|
22 |
+
}
|
23 |
+
}
|
24 |
+
|
25 |
+
$(target).html($('<table>', options).html(tbody));
|
26 |
+
};
|
27 |
+
|
28 |
$.post('%%SUCURI.AjaxURL.Dashboard%%', {
|
29 |
action: 'sucuriscan_ajax',
|
30 |
sucuriscan_page_nonce: '%%SUCURI.PageNonce%%',
|
34 |
$('#sucuriscan-title-links').html(data.links.title);
|
35 |
$('#sucuriscan-title-scripts').html(data.scripts.title);
|
36 |
|
37 |
+
sucuriscanSiteCheckLinks('#sucuriscan-tabs-iframes', data.iframes.content);
|
38 |
+
sucuriscanSiteCheckLinks('#sucuriscan-tabs-links', data.links.content);
|
39 |
+
sucuriscanSiteCheckLinks('#sucuriscan-tabs-scripts', data.scripts.content);
|
40 |
|
41 |
$('#sucuriscan-malware').html(data.malware);
|
42 |
$('#sucuriscan-blacklist').html(data.blacklist);
|
51 |
<div class="sucuriscan-tabs">
|
52 |
<ul class="sucuriscan-clearfix sucuriscan-tabs-buttons">
|
53 |
<li><a href="%%SUCURI.URL.Dashboard%%#auditlogs">@@SUCURI.AuditLogs@@</a></li>
|
|
|
54 |
<li><a href="%%SUCURI.URL.Dashboard%%#iframes" id="sucuriscan-title-iframes">%%SUCURI.SiteCheck.iFramesTitle%%</a></li>
|
55 |
<li><a href="%%SUCURI.URL.Dashboard%%#links" id="sucuriscan-title-links">%%SUCURI.SiteCheck.LinksTitle%%</a></li>
|
56 |
<li><a href="%%SUCURI.URL.Dashboard%%#scripts" id="sucuriscan-title-scripts">%%SUCURI.SiteCheck.ScriptsTitle%%</a></li>
|
61 |
%%%SUCURI.AuditLogs%%%
|
62 |
</div>
|
63 |
|
|
|
|
|
|
|
|
|
64 |
<div id="sucuriscan-tabs-iframes">
|
65 |
%%%SUCURI.SiteCheck.iFramesContent%%%
|
66 |
</div>
|
inc/tpl/firewall-auditlogs.snippet.tpl
CHANGED
@@ -1,43 +1,47 @@
|
|
1 |
|
2 |
<tr>
|
3 |
-
<td>
|
4 |
-
<div class="sucuriscan-
|
5 |
-
<
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
</
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
<
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
<
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
|
|
|
|
|
|
|
|
41 |
</div>
|
42 |
</td>
|
43 |
</tr>
|
1 |
|
2 |
<tr>
|
3 |
+
<td class="sucuriscan-firewall-accesslog sucuriscan-monospace">
|
4 |
+
<div class="sucuriscan-accesslog-origin">
|
5 |
+
<img src="%%SUCURI.SucuriURL%%/inc/images/blank.png"
|
6 |
+
class="sucuriscan-flag sucuriscan-flag-%%SUCURI.AccessLog.RequestCountryCode%%" />
|
7 |
+
<span>%%SUCURI.AccessLog.RemoteAddr%%</span>
|
8 |
+
<span>(%%SUCURI.AccessLog.RequestCountryName%%)</span>
|
9 |
+
</div>
|
10 |
+
|
11 |
+
<div class="sucuriscan-accesslog-datetime">
|
12 |
+
<span class="sucuriscan-accesslog-label">Date/Time:</span>
|
13 |
+
<span>%%SUCURI.AccessLog.RequestDate%%</span>
|
14 |
+
<span>%%SUCURI.AccessLog.RequestTime%%</span>
|
15 |
+
<span>%%SUCURI.AccessLog.RequestTimezone%%</span>
|
16 |
+
</div>
|
17 |
+
|
18 |
+
<div class="sucuriscan-accesslog-signature">
|
19 |
+
<span class="sucuriscan-accesslog-label">Signature:</span>
|
20 |
+
<span>%%SUCURI.AccessLog.SucuriBlockCode%%</span>
|
21 |
+
<span>(%%SUCURI.AccessLog.SucuriBlockReason%%)</span>
|
22 |
+
</div>
|
23 |
+
|
24 |
+
<div class="sucuriscan-accesslog-request">
|
25 |
+
<span class="sucuriscan-accesslog-label">Request:</span>
|
26 |
+
<span>%%SUCURI.AccessLog.HttpProtocol%%</span>
|
27 |
+
<span>%%SUCURI.AccessLog.RequestMethod%%</span>
|
28 |
+
<span>%%SUCURI.AccessLog.HttpStatus%%</span>
|
29 |
+
<span>%%SUCURI.AccessLog.HttpStatusTitle%%</span>
|
30 |
+
</div>
|
31 |
+
|
32 |
+
<div class="sucuriscan-accesslog-useragent">
|
33 |
+
<span class="sucuriscan-accesslog-label">U-Agent:</span>
|
34 |
+
<span>%%SUCURI.AccessLog.HttpUserAgent%%</span>
|
35 |
+
</div>
|
36 |
+
|
37 |
+
<div class="sucuriscan-accesslog-target">
|
38 |
+
<span class="sucuriscan-accesslog-label">Target.:</span>
|
39 |
+
<span>%%SUCURI.AccessLog.ResourcePath%%</span>
|
40 |
+
</div>
|
41 |
+
|
42 |
+
<div class="sucuriscan-accesslog-referer">
|
43 |
+
<span class="sucuriscan-accesslog-label">Referer:</span>
|
44 |
+
<span>%%SUCURI.AccessLog.HttpReferer%%</span>
|
45 |
</div>
|
46 |
</td>
|
47 |
</tr>
|
inc/tpl/firewall-clearcache.html.tpl
CHANGED
@@ -1,4 +1,45 @@
|
|
1 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
<div class="sucuriscan-panel">
|
3 |
<h3 class="sucuriscan-title">@@SUCURI.FirewallCacheTitle@@</h3>
|
4 |
|
@@ -11,10 +52,14 @@
|
|
11 |
|
12 |
<p>@@SUCURI.FirewallCacheWiki@@</p>
|
13 |
|
14 |
-
<
|
15 |
-
<
|
16 |
-
|
17 |
-
|
18 |
-
|
|
|
|
|
|
|
|
|
19 |
</div>
|
20 |
</div>
|
1 |
|
2 |
+
<script type="text/javascript">
|
3 |
+
/* global jQuery */
|
4 |
+
/* jshint camelcase: false */
|
5 |
+
jQuery(function ($) {
|
6 |
+
$('#firewall-clear-cache-button').on('click', function (event) {
|
7 |
+
event.preventDefault();
|
8 |
+
|
9 |
+
var button = $(this);
|
10 |
+
button.attr('disabled', true);
|
11 |
+
button.html('@@SUCURI.Loading@@');
|
12 |
+
$('#firewall-clear-cache-response').html('');
|
13 |
+
|
14 |
+
$.post('%%SUCURI.AjaxURL.Firewall%%', {
|
15 |
+
action: 'sucuriscan_ajax',
|
16 |
+
sucuriscan_page_nonce: '%%SUCURI.PageNonce%%',
|
17 |
+
form_action: 'firewall_clear_cache',
|
18 |
+
}, function (data) {
|
19 |
+
button.addClass('sucuriscan-hidden');
|
20 |
+
$('#firewall-clear-cache-response').html(data);
|
21 |
+
});
|
22 |
+
});
|
23 |
+
|
24 |
+
$('#firewall-clear-cache-auto').on('change', 'input:checkbox', function () {
|
25 |
+
var checked = $(this).is(':checked');
|
26 |
+
|
27 |
+
$('#firewall-clear-cache-auto span').html(
|
28 |
+
'@@SUCURI.FirewallAutoClearCache@@ (@@SUCURI.Loading@@)');
|
29 |
+
|
30 |
+
$.post('%%SUCURI.AjaxURL.Firewall%%', {
|
31 |
+
action: 'sucuriscan_ajax',
|
32 |
+
sucuriscan_page_nonce: '%%SUCURI.PageNonce%%',
|
33 |
+
form_action: 'firewall_auto_clear_cache',
|
34 |
+
auto_clear_cache: (checked?'enable':'disable'),
|
35 |
+
}, function () {
|
36 |
+
$('#firewall-clear-cache-auto span')
|
37 |
+
.html('@@SUCURI.FirewallAutoClearCache@@');
|
38 |
+
});
|
39 |
+
});
|
40 |
+
});
|
41 |
+
</script>
|
42 |
+
|
43 |
<div class="sucuriscan-panel">
|
44 |
<h3 class="sucuriscan-title">@@SUCURI.FirewallCacheTitle@@</h3>
|
45 |
|
52 |
|
53 |
<p>@@SUCURI.FirewallCacheWiki@@</p>
|
54 |
|
55 |
+
<div id="firewall-clear-cache-auto">
|
56 |
+
<label>
|
57 |
+
<input type="checkbox" name="sucuriscan_auto_clear_cache" value="true" %%SUCURI.FirewallAutoClearCache%% />
|
58 |
+
<span>@@SUCURI.FirewallAutoClearCache@@</span>
|
59 |
+
</label>
|
60 |
+
</div>
|
61 |
+
|
62 |
+
<div id="firewall-clear-cache-response"></div>
|
63 |
+
<button id="firewall-clear-cache-button" class="button button-primary">@@SUCURI.FirewallCacheButton@@</button>
|
64 |
</div>
|
65 |
</div>
|
inc/tpl/firewall-ipaccess.html.tpl
ADDED
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<script type="text/javascript">
|
3 |
+
/* global jQuery */
|
4 |
+
/* jshint forin: false */
|
5 |
+
/* jshint camelcase: false */
|
6 |
+
jQuery(document).ready(function ($) {
|
7 |
+
var sucuriscanLoadIPAccess = function () {
|
8 |
+
// $('.sucuriscan-ipaccess-table tbody').html('<tr>' +
|
9 |
+
// '<td colspan="2">@@SUCURI.Loading@@</td></tr>');
|
10 |
+
|
11 |
+
$.post('%%SUCURI.AjaxURL.Firewall%%', {
|
12 |
+
action: 'sucuriscan_ajax',
|
13 |
+
sucuriscan_page_nonce: '%%SUCURI.PageNonce%%',
|
14 |
+
form_action: 'firewall_ipaccess',
|
15 |
+
}, function (data) {
|
16 |
+
$('.sucuriscan-ipaccess-table tbody').html('');
|
17 |
+
|
18 |
+
for (var i in data.blacklist) {
|
19 |
+
$('.sucuriscan-ipaccess-table tbody').append('<tr>' +
|
20 |
+
'<td><span class="sucuriscan-monospace">' + data.blacklist[i] + '</span></td>' +
|
21 |
+
'<td><button class="button button-primary sucuriscan-deblacklist" ' +
|
22 |
+
'ip="' + data.blacklist[i] + '">@@SUCURI.Delete@@</button></td>' +
|
23 |
+
'</tr>');
|
24 |
+
}
|
25 |
+
});
|
26 |
+
};
|
27 |
+
|
28 |
+
var sucuriscanPrintStatus = function (button, data) {
|
29 |
+
button.attr('disabled', false);
|
30 |
+
button.html('@@SUCURI.Submit@@');
|
31 |
+
|
32 |
+
if (data.ok) {
|
33 |
+
sucuriscanLoadIPAccess();
|
34 |
+
|
35 |
+
$('#sucuriscan-ipaccess-response').html('<div '+
|
36 |
+
'class="sucuriscan-inline-alert-success"><p>' +
|
37 |
+
data.msg + '</p></div>');
|
38 |
+
} else {
|
39 |
+
$('#sucuriscan-ipaccess-response').html('<div '+
|
40 |
+
'class="sucuriscan-inline-alert-error"><p>' +
|
41 |
+
data.msg + '</p></div>');
|
42 |
+
}
|
43 |
+
};
|
44 |
+
|
45 |
+
$('.sucuriscan-container').on('click', '.sucuriscan-ipaccess-button', function (event) {
|
46 |
+
event.preventDefault();
|
47 |
+
|
48 |
+
var button = $(this);
|
49 |
+
var ip = $('.sucuriscan-ipaccess-form input[name=sucuriscan_ip]').val();
|
50 |
+
|
51 |
+
button.attr('disabled', true);
|
52 |
+
button.html('@@SUCURI.Loading@@');
|
53 |
+
$('#sucuriscan-ipaccess-response').html('');
|
54 |
+
|
55 |
+
$.post('%%SUCURI.AjaxURL.Firewall%%', {
|
56 |
+
action: 'sucuriscan_ajax',
|
57 |
+
sucuriscan_page_nonce: '%%SUCURI.PageNonce%%',
|
58 |
+
form_action: 'firewall_blacklist',
|
59 |
+
ip: ip,
|
60 |
+
}, function (data) {
|
61 |
+
sucuriscanPrintStatus(button, data);
|
62 |
+
});
|
63 |
+
});
|
64 |
+
|
65 |
+
$('.sucuriscan-container').on('click', '.sucuriscan-deblacklist', function (event) {
|
66 |
+
event.preventDefault();
|
67 |
+
|
68 |
+
var button = $(this);
|
69 |
+
|
70 |
+
button.attr('disabled', true);
|
71 |
+
button.html('@@SUCURI.Loading@@');
|
72 |
+
$('#sucuriscan-ipaccess-response').html('');
|
73 |
+
|
74 |
+
$.post('%%SUCURI.AjaxURL.Firewall%%', {
|
75 |
+
action: 'sucuriscan_ajax',
|
76 |
+
sucuriscan_page_nonce: '%%SUCURI.PageNonce%%',
|
77 |
+
form_action: 'firewall_deblacklist',
|
78 |
+
ip: button.attr('ip'),
|
79 |
+
}, function (data) {
|
80 |
+
sucuriscanPrintStatus(button, data);
|
81 |
+
});
|
82 |
+
});
|
83 |
+
|
84 |
+
sucuriscanLoadIPAccess();
|
85 |
+
});
|
86 |
+
</script>
|
87 |
+
|
88 |
+
<div class="sucuriscan-panel">
|
89 |
+
<h3 class="sucuriscan-title">@@SUCURI.FirewallIPAccessTitle@@</h3>
|
90 |
+
|
91 |
+
<div class="inside">
|
92 |
+
<p>@@SUCURI.FirewallIPAccessInfo@@</p>
|
93 |
+
|
94 |
+
<div id="sucuriscan-ipaccess-response"></div>
|
95 |
+
|
96 |
+
<form action="%%SUCURI.URL.Firewall%%#ipaccess" method="post" class="sucuriscan-ipaccess-form">
|
97 |
+
<input type="hidden" name="sucuriscan_blacklist_ip" value="true" />
|
98 |
+
<fieldset class="sucuriscan-clearfix">
|
99 |
+
<label>@@SUCURI.BlacklistIP@@:</label>
|
100 |
+
<input type="text" name="sucuriscan_ip" placeholder="e.g. 192.168.1.54" />
|
101 |
+
<button class="button button-primary sucuriscan-ipaccess-button">@@SUCURI.Submit@@</button>
|
102 |
+
</fieldset>
|
103 |
+
</form>
|
104 |
+
|
105 |
+
<table class="wp-list-table widefat sucuriscan-table sucuriscan-ipaccess-table">
|
106 |
+
<thead>
|
107 |
+
<tr>
|
108 |
+
<th>@@SUCURI.RemoteAddr@@</th>
|
109 |
+
<th> </th>
|
110 |
+
</tr>
|
111 |
+
</thead>
|
112 |
+
|
113 |
+
<tbody>
|
114 |
+
<tr><td colspan="2">@@SUCURI.Loading@@</td></tr>
|
115 |
+
</tbody>
|
116 |
+
</table>
|
117 |
+
</div>
|
118 |
+
</div>
|
inc/tpl/firewall-settings.html.tpl
CHANGED
@@ -1,4 +1,35 @@
|
|
1 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
<div class="sucuriscan-panel">
|
3 |
<h3 class="sucuriscan-title">@@SUCURI.FirewallSettingsTitle@@</h3>
|
4 |
|
@@ -10,6 +41,7 @@
|
|
10 |
</div>
|
11 |
|
12 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-2 sucuriscan-firewall-apikey sucuriscan-%%SUCURI.Firewall.APIKeyVisibility%%">
|
|
|
13 |
<span class="sucuriscan-monospace">%%SUCURI.Firewall.APIKey%%</span>
|
14 |
<form action="%%SUCURI.URL.Firewall%%" method="post">
|
15 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
@@ -27,7 +59,7 @@
|
|
27 |
<br>
|
28 |
</form>
|
29 |
|
30 |
-
<table class="wp-list-table widefat sucuriscan-table
|
31 |
<thead>
|
32 |
<tr>
|
33 |
<th>@@SUCURI.Name@@</th>
|
@@ -36,7 +68,7 @@
|
|
36 |
</thead>
|
37 |
|
38 |
<tbody>
|
39 |
-
|
40 |
</tbody>
|
41 |
</table>
|
42 |
|
1 |
|
2 |
+
<script type="text/javascript">
|
3 |
+
/* global jQuery */
|
4 |
+
/* jshint camelcase: false */
|
5 |
+
jQuery(document).ready(function ($) {
|
6 |
+
$.post('%%SUCURI.AjaxURL.Firewall%%', {
|
7 |
+
action: 'sucuriscan_ajax',
|
8 |
+
sucuriscan_page_nonce: '%%SUCURI.PageNonce%%',
|
9 |
+
form_action: 'firewall_settings',
|
10 |
+
}, function (data) {
|
11 |
+
if (data.ok) {
|
12 |
+
var value;
|
13 |
+
$('#firewall-settings-table tbody').html('');
|
14 |
+
for (var name in data.settings) {
|
15 |
+
if (data.settings.hasOwnProperty(name) &&
|
16 |
+
typeof data.settings[name] === 'string'
|
17 |
+
) {
|
18 |
+
value = data.settings[name];
|
19 |
+
$('#firewall-settings-table tbody').append('<tr>' +
|
20 |
+
'<td><label>' + name + '</label></td>' +
|
21 |
+
'<td><span class="sucuriscan-monospace">' +
|
22 |
+
value + '</span></td></tr>');
|
23 |
+
}
|
24 |
+
}
|
25 |
+
} else {
|
26 |
+
$('#firewall-settings-table tbody')
|
27 |
+
.html('<tr><td colspan="2">' + data.error + '</td></tr>');
|
28 |
+
}
|
29 |
+
});
|
30 |
+
});
|
31 |
+
</script>
|
32 |
+
|
33 |
<div class="sucuriscan-panel">
|
34 |
<h3 class="sucuriscan-title">@@SUCURI.FirewallSettingsTitle@@</h3>
|
35 |
|
41 |
</div>
|
42 |
|
43 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-2 sucuriscan-firewall-apikey sucuriscan-%%SUCURI.Firewall.APIKeyVisibility%%">
|
44 |
+
<strong>@@SUCURI.FirewallKey@@:</strong>
|
45 |
<span class="sucuriscan-monospace">%%SUCURI.Firewall.APIKey%%</span>
|
46 |
<form action="%%SUCURI.URL.Firewall%%" method="post">
|
47 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
59 |
<br>
|
60 |
</form>
|
61 |
|
62 |
+
<table class="wp-list-table widefat sucuriscan-table" id="firewall-settings-table">
|
63 |
<thead>
|
64 |
<tr>
|
65 |
<th>@@SUCURI.Name@@</th>
|
68 |
</thead>
|
69 |
|
70 |
<tbody>
|
71 |
+
<tr><td colspan="2">@@SUCURI.Loading@@</td></tr>
|
72 |
</tbody>
|
73 |
</table>
|
74 |
|
inc/tpl/firewall-settings.snippet.tpl
DELETED
@@ -1,5 +0,0 @@
|
|
1 |
-
|
2 |
-
<tr>
|
3 |
-
<td><label>%%SUCURI.Firewall.OptionName%%</label></td>
|
4 |
-
<td><span class="sucuriscan-monospace">%%%SUCURI.Firewall.OptionValue%%%</span></td>
|
5 |
-
</tr>
|
|
|
|
|
|
|
|
|
|
inc/tpl/firewall.html.tpl
CHANGED
@@ -3,6 +3,7 @@
|
|
3 |
<ul class="sucuriscan-clearfix sucuriscan-tabs-buttons">
|
4 |
<li><a href="%%SUCURI.URL.Firewall%%#settings">@@SUCURI.Settings@@</a></li>
|
5 |
<li><a href="%%SUCURI.URL.Firewall%%#auditlogs">@@SUCURI.AuditLogs@@</a></li>
|
|
|
6 |
<li><a href="%%SUCURI.URL.Firewall%%#clearcache">@@SUCURI.ClearCache@@</a></li>
|
7 |
</ul>
|
8 |
|
@@ -15,6 +16,10 @@
|
|
15 |
%%%SUCURI.Firewall.AuditLogs%%%
|
16 |
</div>
|
17 |
|
|
|
|
|
|
|
|
|
18 |
<div id="sucuriscan-tabs-clearcache" class="sucuriscan-hidden">
|
19 |
%%%SUCURI.Firewall.ClearCache%%%
|
20 |
</div>
|
3 |
<ul class="sucuriscan-clearfix sucuriscan-tabs-buttons">
|
4 |
<li><a href="%%SUCURI.URL.Firewall%%#settings">@@SUCURI.Settings@@</a></li>
|
5 |
<li><a href="%%SUCURI.URL.Firewall%%#auditlogs">@@SUCURI.AuditLogs@@</a></li>
|
6 |
+
<li><a href="%%SUCURI.URL.Firewall%%#ipaccess">@@SUCURI.IPAccess@@</a></li>
|
7 |
<li><a href="%%SUCURI.URL.Firewall%%#clearcache">@@SUCURI.ClearCache@@</a></li>
|
8 |
</ul>
|
9 |
|
16 |
%%%SUCURI.Firewall.AuditLogs%%%
|
17 |
</div>
|
18 |
|
19 |
+
<div id="sucuriscan-tabs-ipaccess" class="sucuriscan-hidden">
|
20 |
+
%%%SUCURI.Firewall.IPAccess%%%
|
21 |
+
</div>
|
22 |
+
|
23 |
<div id="sucuriscan-tabs-clearcache" class="sucuriscan-hidden">
|
24 |
%%%SUCURI.Firewall.ClearCache%%%
|
25 |
</div>
|
inc/tpl/integrity-diff-utility.html.tpl
CHANGED
@@ -1,19 +1,13 @@
|
|
1 |
|
2 |
<div class="sucuriscan-integrity-diff-utility">
|
3 |
-
<div class="sucuriscan-inline-alert-info">
|
4 |
-
<p>@@SUCURI.DiffUtilityInfo@@</p>
|
5 |
-
</div>
|
6 |
-
|
7 |
-
<div class="sucuriscan-hidden sucuriscan-diff-instructions">
|
8 |
-
<p>@@SUCURI.DiffUtilityInstructions@@</p>
|
9 |
-
</div>
|
10 |
-
|
11 |
%%%SUCURI.DiffUtility.Modal%%%
|
12 |
|
13 |
<script type="text/javascript">
|
14 |
/* global jQuery */
|
15 |
/* jshint camelcase: false */
|
16 |
jQuery(function ($) {
|
|
|
|
|
17 |
$('.sucuriscan-integrity-table .sucuriscan-integrity-filepath').on('click', function (event) {
|
18 |
event.preventDefault();
|
19 |
|
@@ -28,9 +22,8 @@
|
|
28 |
form_action: 'integrity_diff_utility',
|
29 |
filepath: filepath,
|
30 |
}, function (data) {
|
31 |
-
var instructions = $('.sucuriscan-diff-instructions').html();
|
32 |
$('.sucuriscan-diff-utility-modal .sucuriscan-modal-inside').html(data);
|
33 |
-
$('.sucuriscan-diff-content').before(
|
34 |
});
|
35 |
});
|
36 |
});
|
1 |
|
2 |
<div class="sucuriscan-integrity-diff-utility">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
%%%SUCURI.DiffUtility.Modal%%%
|
4 |
|
5 |
<script type="text/javascript">
|
6 |
/* global jQuery */
|
7 |
/* jshint camelcase: false */
|
8 |
jQuery(function ($) {
|
9 |
+
$('.sucuriscan-integrity-table th .sucuriscan-tooltip').removeClass('sucuriscan-hidden');
|
10 |
+
|
11 |
$('.sucuriscan-integrity-table .sucuriscan-integrity-filepath').on('click', function (event) {
|
12 |
event.preventDefault();
|
13 |
|
22 |
form_action: 'integrity_diff_utility',
|
23 |
filepath: filepath,
|
24 |
}, function (data) {
|
|
|
25 |
$('.sucuriscan-diff-utility-modal .sucuriscan-modal-inside').html(data);
|
26 |
+
$('.sucuriscan-diff-content').before('<p>@@SUCURI.DiffUtilityInstructions@@</p>');
|
27 |
});
|
28 |
});
|
29 |
});
|
inc/tpl/integrity-incorrect.html.tpl
CHANGED
@@ -26,7 +26,43 @@
|
|
26 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-integrity-table">
|
27 |
<thead>
|
28 |
<tr>
|
29 |
-
<th colspan="5"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
</tr>
|
31 |
|
32 |
<tr>
|
@@ -46,10 +82,6 @@
|
|
46 |
</tbody>
|
47 |
</table>
|
48 |
|
49 |
-
<div class="sucuriscan-inline-alert-info">
|
50 |
-
<p>@@SUCURI.MarkFixedDescription@@</p>
|
51 |
-
</div>
|
52 |
-
|
53 |
<p>
|
54 |
<label>
|
55 |
<input type="hidden" name="sucuriscan_process_form" value="0" />
|
@@ -60,12 +92,48 @@
|
|
60 |
|
61 |
<fieldset class="sucuriscan-clearfix">
|
62 |
<label>@@SUCURI.Action@@:</label>
|
|
|
63 |
<select name="sucuriscan_integrity_action">
|
64 |
<option value="fixed">@@SUCURI.MarkFixed@@</option>
|
65 |
<option value="restore">@@SUCURI.RestoreFile@@</option>
|
66 |
<option value="delete">@@SUCURI.DeleteFile@@</option>
|
67 |
</select>
|
|
|
68 |
<button type="submit" class="button button-primary">@@SUCURI.Submit@@</button>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
69 |
</fieldset>
|
70 |
</form>
|
71 |
</div>
|
26 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-integrity-table">
|
27 |
<thead>
|
28 |
<tr>
|
29 |
+
<th colspan="5">
|
30 |
+
<span>@@SUCURI.IntegrityTitle@@ (%%SUCURI.Integrity.ListCount%%)</span>
|
31 |
+
|
32 |
+
<span class="sucuriscan-tooltip sucuriscan-hidden" content="@@SUCURI.DiffUtilityInfo@@">
|
33 |
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="14" height="14">
|
34 |
+
<path fill="#000000" d="m6.998315,0.033333c-3.846307,0 -6.964982,
|
35 |
+
3.118675 -6.964982,6.964982s3.118675,6.965574 6.964982,6.965574s6.965574,
|
36 |
+
-3.119267 6.965574,-6.965574s-3.119267,-6.964982 -6.965574,-6.964982zm1.449957,
|
37 |
+
10.794779c-0.358509,0.141517 -0.643901,0.248833 -0.857945,0.32313c-0.213455,
|
38 |
+
0.074296 -0.461699,0.111444 -0.744143,0.111444c-0.433985,0 -0.771855,
|
39 |
+
-0.106137 -1.012434,-0.317823s-0.360279,-0.479978 -0.360279,-0.806055c0,
|
40 |
+
-0.126776 0.008845,-0.256499 0.026534,-0.388581c0.018281,-0.132082 0.047174,
|
41 |
+
-0.280675 0.086679,-0.447547l0.448727,-1.584988c0.039507,-0.152131 0.073707,
|
42 |
+
-0.296596 0.100831,-0.431036c0.027123,-0.135621 0.040097,-0.260037 0.040097,
|
43 |
+
-0.37325c0,-0.201661 -0.041865,-0.343178 -0.125008,-0.422782c-0.08432,
|
44 |
+
-0.079603 -0.242937,-0.11852 -0.479388,-0.11852c-0.115572,0 -0.234682,
|
45 |
+
0.0171 -0.35674,0.05307c-0.120879,0.037148 -0.225837,0.070758 -0.311926,
|
46 |
+
0.103779l0.118521,-0.488235c0.293647,-0.119699 0.574911,-0.222299 0.843204,
|
47 |
+
-0.307209c0.268291,-0.086089 0.521842,-0.128543 0.760652,-0.128543c0.431036,
|
48 |
+
0 0.7636,0.104959 0.997693,0.312517c0.232913,0.208147 0.350253,0.478797 0.350253,
|
49 |
+
0.811363c0,0.068989 -0.008255,0.190458 -0.024174,0.363815c-0.015921,
|
50 |
+
0.173947 -0.045994,0.332565 -0.089628,0.478209l-0.446368,1.580269c-0.036558,
|
51 |
+
0.126776 -0.068988,0.271831 -0.098472,0.433985c-0.028893,0.162156 -0.043043,
|
52 |
+
0.285983 -0.043043,0.369123c0,0.209916 0.046582,0.353202 0.140926,
|
53 |
+
0.429268c0.093164,0.076064 0.256498,0.114392 0.487643,0.114392c0.109086,
|
54 |
+
0 0.231144,-0.019459 0.369124,-0.057197c0.136799,-0.037737 0.23586,
|
55 |
+
-0.071349 0.298364,-0.100241l-0.119699,0.487643zm-0.079014,-6.414247c-0.208148,
|
56 |
+
0.193407 -0.45875,0.290109 -0.751808,0.290109c-0.292469,0 -0.54484,
|
57 |
+
-0.096702 -0.754756,-0.290109c-0.208737,-0.193406 -0.314285,-0.428678 -0.314285,
|
58 |
+
-0.703457c0,-0.274188 0.106138,-0.51005 0.314285,-0.705225c0.208148,
|
59 |
+
-0.195175 0.462287,-0.293058 0.754756,-0.293058c0.293058,0 0.54425,
|
60 |
+
0.097293 0.751808,0.293058c0.208146,0.195175 0.312516,0.431036 0.312516,
|
61 |
+
0.705225c0,0.275368 -0.10437,0.510051 -0.312516,0.703457z">
|
62 |
+
</path>
|
63 |
+
</svg>
|
64 |
+
</span>
|
65 |
+
</th>
|
66 |
</tr>
|
67 |
|
68 |
<tr>
|
82 |
</tbody>
|
83 |
</table>
|
84 |
|
|
|
|
|
|
|
|
|
85 |
<p>
|
86 |
<label>
|
87 |
<input type="hidden" name="sucuriscan_process_form" value="0" />
|
92 |
|
93 |
<fieldset class="sucuriscan-clearfix">
|
94 |
<label>@@SUCURI.Action@@:</label>
|
95 |
+
|
96 |
<select name="sucuriscan_integrity_action">
|
97 |
<option value="fixed">@@SUCURI.MarkFixed@@</option>
|
98 |
<option value="restore">@@SUCURI.RestoreFile@@</option>
|
99 |
<option value="delete">@@SUCURI.DeleteFile@@</option>
|
100 |
</select>
|
101 |
+
|
102 |
<button type="submit" class="button button-primary">@@SUCURI.Submit@@</button>
|
103 |
+
|
104 |
+
<span class="sucuriscan-tooltip" content="@@SUCURI.MarkFixedDescription@@">
|
105 |
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="14" height="14">
|
106 |
+
<path fill="#000000" d="m6.998315,0.033333c-3.846307,0 -6.964982,
|
107 |
+
3.118675 -6.964982,6.964982s3.118675,6.965574 6.964982,6.965574s6.965574,
|
108 |
+
-3.119267 6.965574,-6.965574s-3.119267,-6.964982 -6.965574,-6.964982zm1.449957,
|
109 |
+
10.794779c-0.358509,0.141517 -0.643901,0.248833 -0.857945,0.32313c-0.213455,
|
110 |
+
0.074296 -0.461699,0.111444 -0.744143,0.111444c-0.433985,0 -0.771855,
|
111 |
+
-0.106137 -1.012434,-0.317823s-0.360279,-0.479978 -0.360279,-0.806055c0,
|
112 |
+
-0.126776 0.008845,-0.256499 0.026534,-0.388581c0.018281,-0.132082 0.047174,
|
113 |
+
-0.280675 0.086679,-0.447547l0.448727,-1.584988c0.039507,-0.152131 0.073707,
|
114 |
+
-0.296596 0.100831,-0.431036c0.027123,-0.135621 0.040097,-0.260037 0.040097,
|
115 |
+
-0.37325c0,-0.201661 -0.041865,-0.343178 -0.125008,-0.422782c-0.08432,
|
116 |
+
-0.079603 -0.242937,-0.11852 -0.479388,-0.11852c-0.115572,0 -0.234682,
|
117 |
+
0.0171 -0.35674,0.05307c-0.120879,0.037148 -0.225837,0.070758 -0.311926,
|
118 |
+
0.103779l0.118521,-0.488235c0.293647,-0.119699 0.574911,-0.222299 0.843204,
|
119 |
+
-0.307209c0.268291,-0.086089 0.521842,-0.128543 0.760652,-0.128543c0.431036,
|
120 |
+
0 0.7636,0.104959 0.997693,0.312517c0.232913,0.208147 0.350253,0.478797 0.350253,
|
121 |
+
0.811363c0,0.068989 -0.008255,0.190458 -0.024174,0.363815c-0.015921,
|
122 |
+
0.173947 -0.045994,0.332565 -0.089628,0.478209l-0.446368,1.580269c-0.036558,
|
123 |
+
0.126776 -0.068988,0.271831 -0.098472,0.433985c-0.028893,0.162156 -0.043043,
|
124 |
+
0.285983 -0.043043,0.369123c0,0.209916 0.046582,0.353202 0.140926,
|
125 |
+
0.429268c0.093164,0.076064 0.256498,0.114392 0.487643,0.114392c0.109086,
|
126 |
+
0 0.231144,-0.019459 0.369124,-0.057197c0.136799,-0.037737 0.23586,
|
127 |
+
-0.071349 0.298364,-0.100241l-0.119699,0.487643zm-0.079014,-6.414247c-0.208148,
|
128 |
+
0.193407 -0.45875,0.290109 -0.751808,0.290109c-0.292469,0 -0.54484,
|
129 |
+
-0.096702 -0.754756,-0.290109c-0.208737,-0.193406 -0.314285,-0.428678 -0.314285,
|
130 |
+
-0.703457c0,-0.274188 0.106138,-0.51005 0.314285,-0.705225c0.208148,
|
131 |
+
-0.195175 0.462287,-0.293058 0.754756,-0.293058c0.293058,0 0.54425,
|
132 |
+
0.097293 0.751808,0.293058c0.208146,0.195175 0.312516,0.431036 0.312516,
|
133 |
+
0.705225c0,0.275368 -0.10437,0.510051 -0.312516,0.703457z">
|
134 |
+
</path>
|
135 |
+
</svg>
|
136 |
+
</span>
|
137 |
</fieldset>
|
138 |
</form>
|
139 |
</div>
|
inc/tpl/settings-alerts-events.html.tpl
CHANGED
@@ -3,6 +3,10 @@
|
|
3 |
<h3 class="sucuriscan-title">@@SUCURI.SecurityAlerts@@</h3>
|
4 |
|
5 |
<div class="inside">
|
|
|
|
|
|
|
|
|
6 |
<form action="%%SUCURI.URL.Settings%%#alerts" method="post">
|
7 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
8 |
|
3 |
<h3 class="sucuriscan-title">@@SUCURI.SecurityAlerts@@</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<div class="sucuriscan-inline-alert-error sucuriscan-%%SUCURI.Alerts.NoAlertsVisibility%%">
|
7 |
+
<p>@@SUCURI.NoAlertsError@@</p>
|
8 |
+
</div>
|
9 |
+
|
10 |
<form action="%%SUCURI.URL.Settings%%#alerts" method="post">
|
11 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
12 |
|
inc/tpl/settings-alerts-ignore-posts.html.tpl
CHANGED
@@ -3,9 +3,9 @@
|
|
3 |
<h3 class="sucuriscan-title">@@SUCURI.PostTypeAlerts@@</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<
|
7 |
-
|
8 |
-
</
|
9 |
|
10 |
<p>@@SUCURI.PostTypeAlertsInfo@@</p>
|
11 |
|
3 |
<h3 class="sucuriscan-title">@@SUCURI.PostTypeAlerts@@</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<div class="sucuriscan-inline-alert-error sucuriscan-%%SUCURI.IgnoreRules.ErrorVisibility%%">
|
7 |
+
<p>@@SUCURI.PostTypeAlertsDisabled@@</p>
|
8 |
+
</div>
|
9 |
|
10 |
<p>@@SUCURI.PostTypeAlertsInfo@@</p>
|
11 |
|
inc/tpl/settings-apiservice-checksums.html.tpl
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">@@SUCURI.ChecksumsAPI@@</h3>
|
4 |
+
|
5 |
+
<div class="inside">
|
6 |
+
<p>@@SUCURI.ChecksumsAPIInfo@@</p>
|
7 |
+
|
8 |
+
<div class="sucuriscan-hstatus sucuriscan-hstatus-2">
|
9 |
+
<span>@@SUCURI.ChecksumsAPI@@ — <a target="_blank"
|
10 |
+
href="%%SUCURI.ChecksumsAPI%%">%%SUCURI.ChecksumsAPI%%</a>
|
11 |
+
</span>
|
12 |
+
</div>
|
13 |
+
|
14 |
+
<form action="%%SUCURI.URL.Settings%%#apiservice" method="post">
|
15 |
+
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
16 |
+
<fieldset class="sucuriscan-clearfix">
|
17 |
+
<label>@@SUCURI.ChecksumsAPI@@:</label>
|
18 |
+
<input type="text" name="sucuriscan_checksum_api" placeholder="e.g. URL — or — user/repo" size="30" />
|
19 |
+
<button type="submit" class="button button-primary">@@SUCURI.Submit@@</button>
|
20 |
+
</fieldset>
|
21 |
+
</form>
|
22 |
+
</div>
|
23 |
+
</div>
|
inc/tpl/{settings-general-auditlogstats.html.tpl → settings-general-timezone.html.tpl}
RENAMED
@@ -1,16 +1,19 @@
|
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title">@@SUCURI.
|
4 |
|
5 |
<div class="inside">
|
6 |
-
<p>@@SUCURI.
|
7 |
|
8 |
<form action="%%SUCURI.URL.Settings%%" method="post">
|
9 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
10 |
<fieldset class="sucuriscan-clearfix">
|
11 |
-
<label>@@SUCURI.
|
12 |
-
<
|
|
|
|
|
13 |
<button type="submit" class="button button-primary">@@SUCURI.Submit@@</button>
|
|
|
14 |
</fieldset>
|
15 |
</form>
|
16 |
</div>
|
1 |
|
2 |
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">@@SUCURI.TimezoneTitle@@</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
<p>@@SUCURI.TimezoneInfo@@</p>
|
7 |
|
8 |
<form action="%%SUCURI.URL.Settings%%" method="post">
|
9 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
10 |
<fieldset class="sucuriscan-clearfix">
|
11 |
+
<label>@@SUCURI.TimezoneTitle@@:</label>
|
12 |
+
<select name="sucuriscan_timezone">
|
13 |
+
%%%SUCURI.Timezone.Dropdown%%%
|
14 |
+
</select>
|
15 |
<button type="submit" class="button button-primary">@@SUCURI.Submit@@</button>
|
16 |
+
<span><em>(%%SUCURI.Timezone.Example%%)</em></span>
|
17 |
</fieldset>
|
18 |
</form>
|
19 |
</div>
|
inc/tpl/settings-webinfo-wpconfig.html.tpl
DELETED
@@ -1,19 +0,0 @@
|
|
1 |
-
|
2 |
-
<div class="sucuriscan-panel">
|
3 |
-
<h3 class="sucuriscan-title">@@SUCURI.ConfigVariables@@</h3>
|
4 |
-
|
5 |
-
<div class="inside">
|
6 |
-
<table class="wp-list-table widefat sucuriscan-table">
|
7 |
-
<thead>
|
8 |
-
<tr>
|
9 |
-
<th>@@SUCURI.Name@@</th>
|
10 |
-
<th>@@SUCURI.Value@@</th>
|
11 |
-
</tr>
|
12 |
-
</thead>
|
13 |
-
|
14 |
-
<tbody>
|
15 |
-
%%%SUCURI.WordpressConfig.Rules%%%
|
16 |
-
</tbody>
|
17 |
-
</table>
|
18 |
-
</div>
|
19 |
-
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inc/tpl/settings-webinfo-wpconfig.snippet.tpl
DELETED
@@ -1,6 +0,0 @@
|
|
1 |
-
|
2 |
-
<tr>
|
3 |
-
<td><span class="sucuriscan-monospace">%%SUCURI.WordpressConfig.VariableName%%</span></td>
|
4 |
-
|
5 |
-
<td><span class="sucuriscan-monospace sucuriscan-wraptext">%%SUCURI.WordpressConfig.VariableValue%%</span></td>
|
6 |
-
</tr>
|
|
|
|
|
|
|
|
|
|
|
|
inc/tpl/settings.html.tpl
CHANGED
@@ -22,7 +22,7 @@
|
|
22 |
|
23 |
%%%SUCURI.Settings.General.IPDiscoverer%%%
|
24 |
|
25 |
-
%%%SUCURI.Settings.General.
|
26 |
|
27 |
%%%SUCURI.Settings.General.ImportExport%%%
|
28 |
|
@@ -103,13 +103,15 @@
|
|
103 |
%%%SUCURI.Settings.APIService.Status%%%
|
104 |
|
105 |
%%%SUCURI.Settings.APIService.Proxy%%%
|
|
|
|
|
|
|
|
|
106 |
</div>
|
107 |
|
108 |
<div id="sucuriscan-tabs-webinfo">
|
109 |
%%%SUCURI.Settings.Webinfo.Details%%%
|
110 |
|
111 |
-
%%%SUCURI.Settings.Webinfo.WPConfig%%%
|
112 |
-
|
113 |
%%%SUCURI.Settings.Webinfo.HTAccess%%%
|
114 |
</div>
|
115 |
</div>
|
22 |
|
23 |
%%%SUCURI.Settings.General.IPDiscoverer%%%
|
24 |
|
25 |
+
%%%SUCURI.Settings.General.Timezone%%%
|
26 |
|
27 |
%%%SUCURI.Settings.General.ImportExport%%%
|
28 |
|
103 |
%%%SUCURI.Settings.APIService.Status%%%
|
104 |
|
105 |
%%%SUCURI.Settings.APIService.Proxy%%%
|
106 |
+
|
107 |
+
%%%SUCURI.Settings.SiteCheck.Target%%%
|
108 |
+
|
109 |
+
%%%SUCURI.Settings.APIService.Checksums%%%
|
110 |
</div>
|
111 |
|
112 |
<div id="sucuriscan-tabs-webinfo">
|
113 |
%%%SUCURI.Settings.Webinfo.Details%%%
|
114 |
|
|
|
|
|
115 |
%%%SUCURI.Settings.Webinfo.HTAccess%%%
|
116 |
</div>
|
117 |
</div>
|
inc/tpl/sitecheck-links.html.tpl
DELETED
@@ -1,6 +0,0 @@
|
|
1 |
-
|
2 |
-
<table class="wp-list-table widefat sucuriscan-table">
|
3 |
-
<tbody>
|
4 |
-
%%%SUCURI.SiteCheck.Resources%%%
|
5 |
-
</tbody>
|
6 |
-
</table>
|
|
|
|
|
|
|
|
|
|
|
|
inc/tpl/sitecheck-links.snippet.tpl
DELETED
@@ -1,7 +0,0 @@
|
|
1 |
-
|
2 |
-
<tr>
|
3 |
-
<td>
|
4 |
-
<a href="%%SUCURI.SiteCheck.URL%%" target="_blank"
|
5 |
-
class="sucuriscan-monospace">%%SUCURI.SiteCheck.URL%%</a>
|
6 |
-
</td>
|
7 |
-
</tr>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inc/tpl/sitecheck-target.html.tpl
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<div class="sucuriscan-panel">
|
3 |
+
<h3 class="sucuriscan-title">@@SUCURI.SiteCheckTarget@@</h3>
|
4 |
+
|
5 |
+
<div class="inside">
|
6 |
+
<p>@@SUCURI.SiteCheckTargetInfo@@</p>
|
7 |
+
|
8 |
+
<div class="sucuriscan-hstatus sucuriscan-hstatus-2">
|
9 |
+
<span>@@SUCURI.SiteCheckTarget@@ — <a target="_blank"
|
10 |
+
href="https://sitecheck.sucuri.net/results/%%SUCURI.SiteCheck.Target%%">
|
11 |
+
https://sitecheck.sucuri.net/results/%%SUCURI.SiteCheck.Target%%</a>
|
12 |
+
</span>
|
13 |
+
</div>
|
14 |
+
|
15 |
+
<form action="%%SUCURI.URL.Settings%%#apiservice" method="post">
|
16 |
+
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
17 |
+
<fieldset class="sucuriscan-clearfix">
|
18 |
+
<label>@@SUCURI.SiteCheckTarget@@:</label>
|
19 |
+
<input type="text" name="sucuriscan_sitecheck_target" />
|
20 |
+
<button type="submit" class="button button-primary">@@SUCURI.Submit@@</button>
|
21 |
+
</fieldset>
|
22 |
+
</form>
|
23 |
+
</div>
|
24 |
+
</div>
|
languages/sucuri-scanner-en_US.mo
CHANGED
Binary file
|
languages/sucuri-scanner-en_US.po
CHANGED
@@ -29,12 +29,12 @@ msgstr "Settings"
|
|
29 |
msgid "AuditLogs"
|
30 |
msgstr "Audit Logs"
|
31 |
|
32 |
-
msgid "Statistics"
|
33 |
-
msgstr "Statistics"
|
34 |
-
|
35 |
msgid "ClearCache"
|
36 |
msgstr "Clear Cache"
|
37 |
|
|
|
|
|
|
|
38 |
msgid "GenerateAPIKey"
|
39 |
msgstr "Generate API Key"
|
40 |
|
@@ -183,7 +183,7 @@ msgid "SelfHostingDisabled"
|
|
183 |
msgstr "The log exporter feature has been disabled"
|
184 |
|
185 |
msgid "SelfHostingInfo"
|
186 |
-
msgstr "This option allows you to export the WordPress audit logs to a local log file that can be read by a SIEM or any log analysis software <em>(we recommend OSSEC)</em>. That will give visibility from within WordPress to complement your log monitoring infrastructure."
|
187 |
|
188 |
msgid "SelfHostingFallback"
|
189 |
msgstr "You don't have a valid API key to communicate with the remote API service. However, the self-hosting monitor is enabled, the plugin will read the logs from that file and display the data here. Notice that only the latest logs will be processed to keep a low memory footprint. Consider to generate a free API key to get a better coverage of the activity in your website."
|
@@ -209,8 +209,8 @@ msgstr "WordPress version is not supported."
|
|
209 |
msgid "NoWordPressFile"
|
210 |
msgstr "File is not part of the official WordPress installation."
|
211 |
|
212 |
-
msgid "
|
213 |
-
msgstr "
|
214 |
|
215 |
msgid "ScheduledTask"
|
216 |
msgstr "%1$s (every %2$d seconds)"
|
@@ -464,6 +464,9 @@ msgstr "The plugin has no permission to restore this file because its directory
|
|
464 |
msgid "SecurityAlerts"
|
465 |
msgstr "Security Alerts"
|
466 |
|
|
|
|
|
|
|
467 |
msgid "AlertSettingsUpdated"
|
468 |
msgstr "The alert settings have been updated"
|
469 |
|
@@ -494,6 +497,9 @@ msgstr "Receive email alerts for successful login attempts"
|
|
494 |
msgid "OptionNotifyFailedLogin"
|
495 |
msgstr "Receive email alerts for failed login attempts <em>(you may receive tons of emails)</em>"
|
496 |
|
|
|
|
|
|
|
497 |
msgid "OptionNotifyBruteforceAttack"
|
498 |
msgstr "Receive email alerts for password guessing attacks <em>(summary of failed logins per hour)</em>"
|
499 |
|
@@ -603,7 +609,7 @@ msgid "DiffUtilityDescription"
|
|
603 |
msgstr "If your server allows the execution of system commands, you can configure the plugin to use the <a href=\"https://en.wikipedia.org/wiki/Diff_utility\" target=\"_blank\" rel=\"noopener\">Unix Diff Utility</a> to compare the actual content of the file installed in the website and the original file provided by WordPress. This will show the differences between both files and then you can act upon the information provided."
|
604 |
|
605 |
msgid "DiffUtilityInfo"
|
606 |
-
msgstr "The Unix Diff Utility is enabled. You can click the files
|
607 |
|
608 |
msgid "DiffUtilityInstructions"
|
609 |
msgstr "Lines with a <b>minus</b> sign as the prefix <em>(here in red)</em> show the original code. Lines with a <b>plus</b> sign as the prefix <em>(here in green)</em> show the modified code. You can read more about the DIFF format from the WikiPedia article about the <a target=\"_blank\" href=\"https://en.wikipedia.org/wiki/Diff_utility\" rel=\"noopener\">Unix Diff Utility</a>."
|
@@ -830,6 +836,9 @@ msgstr "Most of the tools in this plugin can be used without a specific configur
|
|
830 |
msgid "APIKeyTerms"
|
831 |
msgstr "Generating an API key implies that you agree to send the information collected by the plugin to the Sucuri API service which is a remote server where the information for the audit logs is stored, this is to prevent malicious users to delete the logs during an attack which may affect an investigation if you suspect that your website was hacked. We also use this information to display <a href=\"https://sucuri.net/security-reports/brute-force/\" target=\"_blank\">statistics</a> and try to use the data in an anonymous way as we are concerned about your privacy too. Please do not generate an API key if you do not agree with this, you can keep using the plugin without it anyway."
|
832 |
|
|
|
|
|
|
|
833 |
msgid "APIKeyInvalidDomain"
|
834 |
msgstr "Your domain <code>%%SUCURI.CleanDomain%%</code> does not seems to have a DNS <code>A</code> record so it will be considered as <em>invalid</em> by the API interface when you request the generation of a new key. Adding <code>www</code> at the beginning of the domain name may fix this issue. If you do not understand what is this then send an email to our support team requesting the key."
|
835 |
|
@@ -1080,7 +1089,7 @@ msgid "IntegrityBadDescription"
|
|
1080 |
msgstr "We identified that some of your WordPress core files were modified. That might indicate a hack or a broken file on your installation. If you are experiencing other malware issues, please use a <a href=\"https://sucuri.net/website-security/malware-removal\" target=\"_blank\">Server Side Scanner</a>."
|
1081 |
|
1082 |
msgid "MarkFixedDescription"
|
1083 |
-
msgstr "Marking one or more files as fixed will force the plugin to ignore them during the next scan, very useful when you find false positives. Additionally you can restore the original content of the core files that appear as modified or deleted, this will tell the plugin to download a copy of the original files from the official
|
1084 |
|
1085 |
msgid "Action"
|
1086 |
msgstr "Action"
|
@@ -1154,6 +1163,18 @@ msgstr "The firewall logs every request involved in an attack and separates them
|
|
1154 |
msgid "FirewallLogsNote"
|
1155 |
msgstr "Note that non-blocked requests are hidden from the logs, this is intentional."
|
1156 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1157 |
msgid "FirewallCacheTitle"
|
1158 |
msgstr "Clear Cache"
|
1159 |
|
@@ -1169,6 +1190,9 @@ msgstr "Note that the firewall has <a href=\"https://kb.sucuri.net/firewall/Perf
|
|
1169 |
msgid "FirewallCacheWiki"
|
1170 |
msgstr "A web cache (or HTTP cache) is an information technology for the temporary storage (caching) of web documents, such as HTML pages and images, to reduce bandwidth usage, server load, and perceived lag. A web cache system stores copies of documents passing through it; subsequent requests may be satisfied from the cache if certain conditions are met. A web cache system can refer either to an appliance, or to a computer program. — <a href=\"https://en.wikipedia.org/wiki/Web_cache\" target=\"_blank\" rel=\"noopener\">WikiPedia - Web Cache</a>"
|
1171 |
|
|
|
|
|
|
|
1172 |
msgid "LoginsAdmins"
|
1173 |
msgstr "Successful Logins (admins)"
|
1174 |
|
@@ -1223,6 +1247,12 @@ msgstr "Recomendations"
|
|
1223 |
msgid "SiteCheckNoResults"
|
1224 |
msgstr "If our free scanner did not detect any issue, you may have a more complicated and hidden problem. You can <a target=\"_blank\" href=\"https://sucuri.net/website-security-platform/signup\">sign up with Sucuri</a> for a complete and in-depth scan + cleanup (not included in the free checks)."
|
1225 |
|
|
|
|
|
|
|
|
|
|
|
|
|
1226 |
msgid "PasswordAttack"
|
1227 |
msgstr "Password Guessing Brute Force Attacks"
|
1228 |
|
@@ -1460,14 +1490,23 @@ msgstr "Data Storage"
|
|
1460 |
msgid "DataStorageInfo"
|
1461 |
msgstr "This is the directory where the plugin will store the security logs, the list of files marked as fixed in the core integrity tool, the cache for the malware scanner and 3rd-party plugin metadata. The plugin requires write permissions in this directory as well as the files contained in it. If you prefer to keep these files in a non-public directory <em>(one level up the document root) </em> please define a constant in the <em>\"wp-config.php\"</em> file named <em>\"SUCURI_DATA_STORAGE\"</em> with the absolute path to the new directory."
|
1462 |
|
1463 |
-
msgid "
|
1464 |
-
msgstr "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1465 |
|
1466 |
-
msgid "
|
1467 |
-
msgstr "The
|
1468 |
|
1469 |
-
msgid "
|
1470 |
-
msgstr "The
|
1471 |
|
1472 |
-
msgid "
|
1473 |
-
msgstr "
|
29 |
msgid "AuditLogs"
|
30 |
msgstr "Audit Logs"
|
31 |
|
|
|
|
|
|
|
32 |
msgid "ClearCache"
|
33 |
msgstr "Clear Cache"
|
34 |
|
35 |
+
msgid "IPAccess"
|
36 |
+
msgstr "IP Access"
|
37 |
+
|
38 |
msgid "GenerateAPIKey"
|
39 |
msgstr "Generate API Key"
|
40 |
|
183 |
msgstr "The log exporter feature has been disabled"
|
184 |
|
185 |
msgid "SelfHostingInfo"
|
186 |
+
msgstr "This option allows you to export the WordPress audit logs to a local log file that can be read by a SIEM or any log analysis software <em>(we recommend OSSEC)</em>. That will give visibility from within WordPress to complement your log monitoring infrastructure. <b>NOTE:</b> Do not use a publicly accessible file, you must use a file at least one level up the document root to prevent leaks of information."
|
187 |
|
188 |
msgid "SelfHostingFallback"
|
189 |
msgstr "You don't have a valid API key to communicate with the remote API service. However, the self-hosting monitor is enabled, the plugin will read the logs from that file and display the data here. Notice that only the latest logs will be processed to keep a low memory footprint. Consider to generate a free API key to get a better coverage of the activity in your website."
|
209 |
msgid "NoWordPressFile"
|
210 |
msgstr "File is not part of the official WordPress installation."
|
211 |
|
212 |
+
msgid "ThereAreNoDifferences"
|
213 |
+
msgstr "There are no differences between the installed and original files"
|
214 |
|
215 |
msgid "ScheduledTask"
|
216 |
msgstr "%1$s (every %2$d seconds)"
|
464 |
msgid "SecurityAlerts"
|
465 |
msgstr "Security Alerts"
|
466 |
|
467 |
+
msgid "NoAlertsError"
|
468 |
+
msgstr "You have installed a plugin or theme that is not fully compatible with our plugin, some of the security alerts (like the successful and failed logins) will not be sent to you. To prevent an infinite loop while detecting these changes in the website and sending the email alerts via a custom SMTP plugin, we have decided to stop any attempt to send the emails to prevent fatal errors."
|
469 |
+
|
470 |
msgid "AlertSettingsUpdated"
|
471 |
msgstr "The alert settings have been updated"
|
472 |
|
497 |
msgid "OptionNotifyFailedLogin"
|
498 |
msgstr "Receive email alerts for failed login attempts <em>(you may receive tons of emails)</em>"
|
499 |
|
500 |
+
msgid "OptionNotifyFailedPassword"
|
501 |
+
msgstr "Receive email alerts for failed login attempts including the submitted password"
|
502 |
+
|
503 |
msgid "OptionNotifyBruteforceAttack"
|
504 |
msgstr "Receive email alerts for password guessing attacks <em>(summary of failed logins per hour)</em>"
|
505 |
|
609 |
msgstr "If your server allows the execution of system commands, you can configure the plugin to use the <a href=\"https://en.wikipedia.org/wiki/Diff_utility\" target=\"_blank\" rel=\"noopener\">Unix Diff Utility</a> to compare the actual content of the file installed in the website and the original file provided by WordPress. This will show the differences between both files and then you can act upon the information provided."
|
610 |
|
611 |
msgid "DiffUtilityInfo"
|
612 |
+
msgstr "The Unix Diff Utility is enabled. You can click the files in the table to see the differences detected by the scanner. If you consider the differences to be harmless you can mark the file as fixed, otherwise it is adviced to restore the original content immediately."
|
613 |
|
614 |
msgid "DiffUtilityInstructions"
|
615 |
msgstr "Lines with a <b>minus</b> sign as the prefix <em>(here in red)</em> show the original code. Lines with a <b>plus</b> sign as the prefix <em>(here in green)</em> show the modified code. You can read more about the DIFF format from the WikiPedia article about the <a target=\"_blank\" href=\"https://en.wikipedia.org/wiki/Diff_utility\" rel=\"noopener\">Unix Diff Utility</a>."
|
836 |
msgid "APIKeyTerms"
|
837 |
msgstr "Generating an API key implies that you agree to send the information collected by the plugin to the Sucuri API service which is a remote server where the information for the audit logs is stored, this is to prevent malicious users to delete the logs during an attack which may affect an investigation if you suspect that your website was hacked. We also use this information to display <a href=\"https://sucuri.net/security-reports/brute-force/\" target=\"_blank\">statistics</a> and try to use the data in an anonymous way as we are concerned about your privacy too. Please do not generate an API key if you do not agree with this, you can keep using the plugin without it anyway."
|
838 |
|
839 |
+
msgid "APIKeyMissing"
|
840 |
+
msgstr "API key is missing"
|
841 |
+
|
842 |
msgid "APIKeyInvalidDomain"
|
843 |
msgstr "Your domain <code>%%SUCURI.CleanDomain%%</code> does not seems to have a DNS <code>A</code> record so it will be considered as <em>invalid</em> by the API interface when you request the generation of a new key. Adding <code>www</code> at the beginning of the domain name may fix this issue. If you do not understand what is this then send an email to our support team requesting the key."
|
844 |
|
1089 |
msgstr "We identified that some of your WordPress core files were modified. That might indicate a hack or a broken file on your installation. If you are experiencing other malware issues, please use a <a href=\"https://sucuri.net/website-security/malware-removal\" target=\"_blank\">Server Side Scanner</a>."
|
1090 |
|
1091 |
msgid "MarkFixedDescription"
|
1092 |
+
msgstr "Marking one or more files as fixed will force the plugin to ignore them during the next scan, very useful when you find false positives. Additionally you can restore the original content of the core files that appear as modified or deleted, this will tell the plugin to download a copy of the original files from the official WordPress repository. Deleting a file is an irreversible action, be careful."
|
1093 |
|
1094 |
msgid "Action"
|
1095 |
msgstr "Action"
|
1163 |
msgid "FirewallLogsNote"
|
1164 |
msgstr "Note that non-blocked requests are hidden from the logs, this is intentional."
|
1165 |
|
1166 |
+
msgid "FirewallIPAccessTitle"
|
1167 |
+
msgstr "IP Address Access"
|
1168 |
+
|
1169 |
+
msgid "FirewallIPAccessInfo"
|
1170 |
+
msgstr "This tool allows you to whitleist and blacklist one or more IP addresses from accessing your website. You can also configure the plugin to automatically blacklist any IP address involved in a password guessing brute-force attack. If a legitimate user fails to submit the correct credentials of their account they will have to log into the Firewall dashboard in order to delete their IP address from the blacklist, or try to login once again through a VPN."
|
1171 |
+
|
1172 |
+
msgid "WhitelistIP"
|
1173 |
+
msgstr "Whitelist IP"
|
1174 |
+
|
1175 |
+
msgid "BlacklistIP"
|
1176 |
+
msgstr "Blacklist IP"
|
1177 |
+
|
1178 |
msgid "FirewallCacheTitle"
|
1179 |
msgstr "Clear Cache"
|
1180 |
|
1190 |
msgid "FirewallCacheWiki"
|
1191 |
msgstr "A web cache (or HTTP cache) is an information technology for the temporary storage (caching) of web documents, such as HTML pages and images, to reduce bandwidth usage, server load, and perceived lag. A web cache system stores copies of documents passing through it; subsequent requests may be satisfied from the cache if certain conditions are met. A web cache system can refer either to an appliance, or to a computer program. — <a href=\"https://en.wikipedia.org/wiki/Web_cache\" target=\"_blank\" rel=\"noopener\">WikiPedia - Web Cache</a>"
|
1192 |
|
1193 |
+
msgid "FirewallAutoClearCache"
|
1194 |
+
msgstr "Clear cache automatically when a post or page is updated"
|
1195 |
+
|
1196 |
msgid "LoginsAdmins"
|
1197 |
msgstr "Successful Logins (admins)"
|
1198 |
|
1247 |
msgid "SiteCheckNoResults"
|
1248 |
msgstr "If our free scanner did not detect any issue, you may have a more complicated and hidden problem. You can <a target=\"_blank\" href=\"https://sucuri.net/website-security-platform/signup\">sign up with Sucuri</a> for a complete and in-depth scan + cleanup (not included in the free checks)."
|
1249 |
|
1250 |
+
msgid "SiteCheckTarget"
|
1251 |
+
msgstr "Malware Scan Target"
|
1252 |
+
|
1253 |
+
msgid "SiteCheckTargetInfo"
|
1254 |
+
msgstr "The remote malware scanner provided by the plugin is powered by <a href=\"https://sitecheck.sucuri.net/\" target=\"_blank\">Sucuri SiteCheck</a>, a service that takes a publicly accessible URL and scans it for malicious code. If your website is not visible to the Internet, for example, if it is hosted in a local development environment or a restricted network, the scanner will not be able to work on it. Additionally, if the website was installed in a non-standard directory the scanner will report a \"404 Not Found\" error. You can use this option to change the URL that will be scanned."
|
1255 |
+
|
1256 |
msgid "PasswordAttack"
|
1257 |
msgstr "Password Guessing Brute Force Attacks"
|
1258 |
|
1490 |
msgid "DataStorageInfo"
|
1491 |
msgstr "This is the directory where the plugin will store the security logs, the list of files marked as fixed in the core integrity tool, the cache for the malware scanner and 3rd-party plugin metadata. The plugin requires write permissions in this directory as well as the files contained in it. If you prefer to keep these files in a non-public directory <em>(one level up the document root) </em> please define a constant in the <em>\"wp-config.php\"</em> file named <em>\"SUCURI_DATA_STORAGE\"</em> with the absolute path to the new directory."
|
1492 |
|
1493 |
+
msgid "TimezoneTitle"
|
1494 |
+
msgstr "Timezone"
|
1495 |
+
|
1496 |
+
msgid "TimezoneInfo"
|
1497 |
+
msgstr "This option defines the timezone that will be used through out the entire plugin to print the dates and times whenever is necessary. This option also affects the date and time of the logs visible in the audit logs panel which is data that comes from a remote server configured to use Eastern Daylight Time (EDT). WordPress offers an option in the general settings page to allow you to configure the timezone for the entire website, however, if you are experiencing problems with the time in the audit logs, this option will help you fix them."
|
1498 |
+
|
1499 |
+
msgid "TimezoneStatus"
|
1500 |
+
msgstr "The timezone for the date and time in the audit logs has been changed"
|
1501 |
+
|
1502 |
+
msgid "ChecksumsAPI"
|
1503 |
+
msgstr "WordPress Checksums API"
|
1504 |
|
1505 |
+
msgid "ChecksumsAPIInfo"
|
1506 |
+
msgstr "The WordPress integrity tool uses a remote API service maintained by the WordPress organization to determine which files in the installation were added, removed or modified. The API returns a list of files with their respective checksums, this information guarantees that the installation is not corrupt. You can, however, point the integrity tool to a GitHub repository in case that you are using a custom version of WordPress like the <a href=\"https://github.com/WordPress/WordPress\" target=\"_blank\">development version of the code</a>."
|
1507 |
|
1508 |
+
msgid "ChecksumsAPIChanged"
|
1509 |
+
msgstr "The URL to retrieve the WordPress checksums has been changed"
|
1510 |
|
1511 |
+
msgid "MaxExecutionTimeAlert"
|
1512 |
+
msgstr "Server is not fast enough to process this action; maximum execution time reached"
|
languages/sucuri-scanner-es_ES.mo
CHANGED
Binary file
|
languages/sucuri-scanner-es_ES.po
CHANGED
@@ -10,9 +10,10 @@ msgstr ""
|
|
10 |
"PO-Revision-Date: \n"
|
11 |
"POT-Creation-Date: 2017-06-01 09:00-0700\n"
|
12 |
"Project-Id-Version: Sucuri Scanner\n"
|
|
|
13 |
|
14 |
msgid "Review"
|
15 |
-
msgstr "
|
16 |
|
17 |
msgid "Dashboard"
|
18 |
msgstr "Inicio"
|
@@ -29,12 +30,12 @@ msgstr "Ajustes"
|
|
29 |
msgid "AuditLogs"
|
30 |
msgstr "Registros"
|
31 |
|
32 |
-
msgid "Statistics"
|
33 |
-
msgstr "Estadísticas"
|
34 |
-
|
35 |
msgid "ClearCache"
|
36 |
msgstr "Limpiar Cache"
|
37 |
|
|
|
|
|
|
|
38 |
msgid "GenerateAPIKey"
|
39 |
msgstr "Generar Llave"
|
40 |
|
@@ -48,13 +49,13 @@ msgid "AccessDenied"
|
|
48 |
msgstr "Accesso denegado por Sucuri Inc."
|
49 |
|
50 |
msgid "NonceFailure"
|
51 |
-
msgstr "Error al verificar el código Nonce del formulario,
|
52 |
|
53 |
msgid "NewsletterInvitation"
|
54 |
-
msgstr "¿
|
55 |
|
56 |
msgid "EnableAPIServiceAgain"
|
57 |
-
msgstr "La comunicación con la API de Sucuri está deshabilitada, si
|
58 |
|
59 |
msgid "Save"
|
60 |
msgstr "Guardar"
|
@@ -69,13 +70,13 @@ msgid "ErrorNoInfo"
|
|
69 |
msgstr "Error desconocido, no hay más información."
|
70 |
|
71 |
msgid "ErrorLogFileNotFound"
|
72 |
-
msgstr "; esto generalmente sucede cuando una llave inválida es agregada al plugin, la llave será eliminada automáticamente para reducir la cantidad de errores, si
|
73 |
|
74 |
msgid "ErrorWrongAPIKey"
|
75 |
msgstr "; la llave del Firewall es inválida: %1$s"
|
76 |
|
77 |
msgid "ErrorSSLCertificate"
|
78 |
-
msgstr ".
|
79 |
|
80 |
msgid "ErrorInvalidEmail"
|
81 |
msgstr "El correo electrónico tiene un formato inválido o el dominio asociado no tiene asociado un servidor MX."
|
@@ -183,10 +184,10 @@ msgid "SelfHostingDisabled"
|
|
183 |
msgstr "La herramienta para exportar los registros de seguridad ha sido desactivada"
|
184 |
|
185 |
msgid "SelfHostingInfo"
|
186 |
-
msgstr "Esta opción
|
187 |
|
188 |
msgid "SelfHostingFallback"
|
189 |
-
msgstr "
|
190 |
|
191 |
msgid "AuditLogsCache"
|
192 |
msgstr "Los registros son guardados por %%SUCURI.AuditLogs.Lifetime%% segundos"
|
@@ -209,8 +210,8 @@ msgstr "esta versión de WordPress no tiene soporte."
|
|
209 |
msgid "NoWordPressFile"
|
210 |
msgstr "El archivo no hace parte de la instalación oficial de WordPress."
|
211 |
|
212 |
-
msgid "
|
213 |
-
msgstr "No
|
214 |
|
215 |
msgid "ScheduledTask"
|
216 |
msgstr "%1$s (cada %2$d segundos)"
|
@@ -303,7 +304,7 @@ msgid "EmailSubject.password_change"
|
|
303 |
msgstr "Cambio de Contraseña"
|
304 |
|
305 |
msgid "FailedLoginFooter"
|
306 |
-
msgstr "<br><br><em>
|
307 |
|
308 |
msgid "FirewallAPIKeySet"
|
309 |
msgstr "La llave del Firewall ha sido guardada"
|
@@ -333,10 +334,10 @@ msgid "FirewallNoCacheAtAll"
|
|
333 |
msgstr "Desactivada (use con precaución)"
|
334 |
|
335 |
msgid "FirewallNotEnabled"
|
336 |
-
msgstr "El Firewall no ha sido activado en
|
337 |
|
338 |
msgid "FirewallClearCacheFailure"
|
339 |
-
msgstr "No se pudo actualizar la cache de
|
340 |
|
341 |
msgid "Active"
|
342 |
msgstr "activo"
|
@@ -429,7 +430,7 @@ msgid "AttemptDatetime"
|
|
429 |
msgstr "Fecha/Hora"
|
430 |
|
431 |
msgid "ConfirmOperation"
|
432 |
-
msgstr "
|
433 |
|
434 |
msgid "UnderstandTheRisk"
|
435 |
msgstr "Entiendo que esta operación no puede ser revertida."
|
@@ -453,17 +454,20 @@ msgid "SomeItemsProcessed"
|
|
453 |
msgstr "Solo <b>%1$d</b> de <b>%2$d</b> archivos fueron procesados."
|
454 |
|
455 |
msgid "ErrorIntegrityAdded"
|
456 |
-
msgstr "El plugin no tiene permiso para eliminar este archivo porque fué creado por otro usuario del sistema con más privilegios que
|
457 |
|
458 |
msgid "ErrorIntegrityModified"
|
459 |
-
msgstr "El plugin no tiene permiso para restablecer el contenido de este archivo porque fué modificado por otro usuario del sistema con más privilegios que
|
460 |
|
461 |
msgid "ErrorIntegrityRemoved"
|
462 |
-
msgstr "El plugin no tiene permiso para restablecer el contenido de este archivo porque el directorio donde está ubicado pertenece a otro usuario del sistema con más privilegios que
|
463 |
|
464 |
msgid "SecurityAlerts"
|
465 |
msgstr "Alertas de Seguridad"
|
466 |
|
|
|
|
|
|
|
467 |
msgid "AlertSettingsUpdated"
|
468 |
msgstr "La configuración para las alertas de seguridad ha sido actualizada"
|
469 |
|
@@ -471,13 +475,13 @@ msgid "OptionNotifyPluginChange"
|
|
471 |
msgstr "Recibir alertas por cambios en la configuración del plugin de Sucuri"
|
472 |
|
473 |
msgid "OptionPrettifyMails"
|
474 |
-
msgstr "Recibir alertas en HTML <em>(
|
475 |
|
476 |
msgid "OptionUseWordPressMail"
|
477 |
-
msgstr "Usar funciones nativas de WordPress para enviar las alertas <em>(
|
478 |
|
479 |
msgid "OptionLastLoginRedirection"
|
480 |
-
msgstr "Permitir redirección durante el login para reportar información acerca de la última autenticación exitosa de
|
481 |
|
482 |
msgid "OptionNotifyScanChecksums"
|
483 |
msgstr "Recibir alertas por diferencias en los archivos originales de WordPress"
|
@@ -492,19 +496,22 @@ msgid "OptionNotifySuccessLogin"
|
|
492 |
msgstr "Recibir alertas por autenticaciones exitosas de usuario"
|
493 |
|
494 |
msgid "OptionNotifyFailedLogin"
|
495 |
-
msgstr "Recibir alertas por autenticaciones de usuario fallidas <em>(si
|
|
|
|
|
|
|
496 |
|
497 |
msgid "OptionNotifyBruteforceAttack"
|
498 |
msgstr "Recibir un resumen con todos los intentos de autenticación de usuario fallidos durante la misma hora. El reporte será eliminado del servidor una vez la información sea enviada a su correo"
|
499 |
|
500 |
msgid "OptionNotifyPostPublication"
|
501 |
-
msgstr "Recibir alertas por cambios en el estado de las publicaciones y páginas <em>(
|
502 |
|
503 |
msgid "OptionNotifyWebsiteUpdated"
|
504 |
-
msgstr "Recibir alertas cuando
|
505 |
|
506 |
msgid "OptionNotifySettingsUpdated"
|
507 |
-
msgstr "Recibir alertas por cambios en la configuración general de
|
508 |
|
509 |
msgid "OptionNotifyThemeEditor"
|
510 |
msgstr "Recibir alertas cuando un archivo sea modificado a través del editor de Plugins/Plantillas"
|
@@ -525,10 +532,10 @@ msgid "OptionNotifyPluginDeleted"
|
|
525 |
msgstr "Recibir alertas cuando un <b>plugin sea eliminado</b>"
|
526 |
|
527 |
msgid "OptionNotifyWidgetAdded"
|
528 |
-
msgstr "Recibir alertas cuando un <b>widget sea agregado</b> a
|
529 |
|
530 |
msgid "OptionNotifyWidgetDeleted"
|
531 |
-
msgstr "Recibir alertas cuando un <b>widget sea eliminado</b> de
|
532 |
|
533 |
msgid "OptionNotifyThemeInstalled"
|
534 |
msgstr "Recibir alertas cuando una <b>plantilla sea instalada</b>"
|
@@ -567,7 +574,7 @@ msgid "OptionPerHour160"
|
|
567 |
msgstr "Máximo 160 por hora"
|
568 |
|
569 |
msgid "BruteForceAlertSuccess"
|
570 |
-
msgstr "El plugin asumirá que
|
571 |
|
572 |
msgid "BruteForceAlertFailure"
|
573 |
msgstr "Ese número no está soportado por el plugin, use uno de la lista"
|
@@ -600,13 +607,13 @@ msgid "DiffUtility"
|
|
600 |
msgstr "Herramienta de Integridad de Archivos"
|
601 |
|
602 |
msgid "DiffUtilityDescription"
|
603 |
-
msgstr "Si
|
604 |
|
605 |
msgid "DiffUtilityInfo"
|
606 |
-
msgstr "El
|
607 |
|
608 |
msgid "DiffUtilityInstructions"
|
609 |
-
msgstr "Las lineas con un signo <b>negativo</b> como prefijo <em>(marcadas en rojo)</em> muestran el código original. Las lineas con un signo <b>positivo</b> como prefijo <em>(marcadas en verde)</em> muestran el código actual.
|
610 |
|
611 |
msgid "AccountsWereBlocked"
|
612 |
msgstr "Las cuentas de usuario seleccionadas han sido bloqueadas"
|
@@ -615,7 +622,7 @@ msgid "AccountsWereUnblocked"
|
|
615 |
msgstr "Las cuentas de usuario seleccionadas han sido desbloqueadas"
|
616 |
|
617 |
msgid "LastLoginMessage"
|
618 |
-
msgstr "El último acceso de
|
619 |
|
620 |
msgid "LastLoginsNotWritable"
|
621 |
msgstr "El archivo para los registros de autenticaciones de usuario no es modificable: <code>%1$s</code>"
|
@@ -630,13 +637,13 @@ msgid "ReverseProxyStatus"
|
|
630 |
msgstr "El soporte para túneles proxy ha sido cambiado a <b>%1$s</b>"
|
631 |
|
632 |
msgid "ReverseProxyInfo"
|
633 |
-
msgstr "El plugin utiliza la dirección IP de cada usuario para registrar los eventos ejecutados, el plugin utiliza dos métodos para obtener esta dirección: el método principal usa una variable global del servidor llamada <em>Remote-Addr</em> disponible en la mayoría de servidores web, un método alternativo usa cabeceras de HTTP personalizadas <em>(que son consideradas inseguras por defecto)</em>. No es necesario que
|
634 |
|
635 |
msgid "IPDiscoverer"
|
636 |
msgstr "Detección de Direcciones IP"
|
637 |
|
638 |
msgid "IPDiscovererInfo"
|
639 |
-
msgstr "La detección de direcciones IP hace uso de DNS para detectar si el sitio web está detrás del <a href=\"https://sucuri.net/
|
640 |
|
641 |
msgid "HTTPHeader"
|
642 |
msgstr "Cabecera de HTTP"
|
@@ -735,7 +742,7 @@ msgid "WillNotReceiveAlerts"
|
|
735 |
msgstr "Estos correos no recibirán más alertas de seguridad: <code>%1$s</code>"
|
736 |
|
737 |
msgid "TestAlertSent"
|
738 |
-
msgstr "Un correo de prueba ha sido enviado a
|
739 |
|
740 |
msgid "InvalidEmail"
|
741 |
msgstr "Formato de correo electrónico inválido."
|
@@ -795,7 +802,7 @@ msgid "Cronjobs"
|
|
795 |
msgstr "Acciones Automatizadas"
|
796 |
|
797 |
msgid "CronjobsInfo"
|
798 |
-
msgstr "Acciones automatizadas son reglas registradas en
|
799 |
|
800 |
msgid "CronjobRunNow"
|
801 |
msgstr "Ejecutar Ahora (en +10 segundos)"
|
@@ -813,7 +820,7 @@ msgid "CronjobsWereNotSelected"
|
|
813 |
msgstr "Ninguna acción automatizada ha sido seleccionada de la lista"
|
814 |
|
815 |
msgid "DNSLookupStatus"
|
816 |
-
msgstr "El estado las conexiones
|
817 |
|
818 |
msgid "IncorrectEncoding"
|
819 |
msgstr "Los datos han sido codificados incorrectamente"
|
@@ -825,19 +832,22 @@ msgid "APIKey"
|
|
825 |
msgstr "Llave de Autenticación"
|
826 |
|
827 |
msgid "APIKeyInfo"
|
828 |
-
msgstr "La mayoría de herramientas en este plugin pueden ser usadas sin una configuración específica, pero las herramientas más importantes requieren de una <b>llave de autenticación</b> para establecer un túnel de comunicación segura con los servidores de Sucuri. La llave es generada usando
|
829 |
|
830 |
msgid "APIKeyTerms"
|
831 |
-
msgstr "
|
|
|
|
|
|
|
832 |
|
833 |
msgid "APIKeyInvalidDomain"
|
834 |
-
msgstr "
|
835 |
|
836 |
msgid "APIKeyRecoverButton"
|
837 |
msgstr "Recuperar Por Correo Electrónico"
|
838 |
|
839 |
msgid "APIKeyRecoveryCondition"
|
840 |
-
msgstr "Si
|
841 |
|
842 |
msgid "ApplyHardening"
|
843 |
msgstr "Aplicar Hardening"
|
@@ -849,16 +859,16 @@ msgid "HardeningFirewallTitle"
|
|
849 |
msgstr "Firewall Para Aplicaciones Web"
|
850 |
|
851 |
msgid "HardeningFirewallDescription"
|
852 |
-
msgstr "Un WAF (Web Application Firewall) es una capa de protección para
|
853 |
|
854 |
msgid "HardeningFirewallPurchase"
|
855 |
-
msgstr "El Firewall de Sucuri es un servicio premium que
|
856 |
|
857 |
msgid "HardeningVersionTitle"
|
858 |
msgstr "Verificar la Versión de WordPress"
|
859 |
|
860 |
msgid "HardeningVersionDescription"
|
861 |
-
msgstr "¿Por qué mantener
|
862 |
|
863 |
msgid "HardeningPHPVersionTitle"
|
864 |
msgstr "Verificar la Versión de PHP"
|
@@ -867,31 +877,31 @@ msgid "HardeningPHPVersionDescription"
|
|
867 |
msgstr "PHP %1$s está instalado."
|
868 |
|
869 |
msgid "HardeningPHPVersionLifetime"
|
870 |
-
msgstr "
|
871 |
|
872 |
msgid "HardeningGeneratorTitle"
|
873 |
msgstr "Eliminar Versión de WordPress"
|
874 |
|
875 |
msgid "HardeningGeneratorDescription"
|
876 |
-
msgstr "Esta opción verifica si la versión de WordPress usada en
|
877 |
|
878 |
msgid "HardeningNginxTitle"
|
879 |
msgstr "Bloquear Algunos Archivos PHP"
|
880 |
|
881 |
msgid "HardeningNginxDescription"
|
882 |
-
msgstr "Esta opción bloquea la ejecución de archivos PHP en directorios sensitivos.
|
883 |
|
884 |
msgid "HardeningNginxField"
|
885 |
msgstr "Verificar Hardening"
|
886 |
|
887 |
msgid "HardeningNginxSuggestion"
|
888 |
-
msgstr "
|
889 |
|
890 |
msgid "HardeningUploadsTitle"
|
891 |
msgstr "Bloquear Archivos PHP en el Directorio de Subidas"
|
892 |
|
893 |
msgid "HardeningUploadsDescription"
|
894 |
-
msgstr "Esta opción bloquea la ejecución de archivos PHP en directorios sensitivos.
|
895 |
|
896 |
msgid "HardeningUploadsApplySuccess"
|
897 |
msgstr "Hardening aplicado al directorio de subidas"
|
@@ -909,7 +919,7 @@ msgid "HardeningContentTitle"
|
|
909 |
msgstr "Bloquear Archivos PHP en el Directorio de Contenido"
|
910 |
|
911 |
msgid "HardeningContentDescription"
|
912 |
-
msgstr "Esta opción bloquea la ejecución de archivos PHP en directorios sensitivos.
|
913 |
|
914 |
msgid "HardeningContentApplySuccess"
|
915 |
msgstr "Hardening aplicado al directorio de contenido"
|
@@ -927,7 +937,7 @@ msgid "HardeningIncludesTitle"
|
|
927 |
msgstr "Bloquear Archivos PHP en el Directorio de Inclusiones"
|
928 |
|
929 |
msgid "HardeningIncludesDescription"
|
930 |
-
msgstr "Esta opción bloquea la ejecución de archivos PHP en directorios sensitivos.
|
931 |
|
932 |
msgid "HardeningIncludesApplySuccess"
|
933 |
msgstr "Hardening aplicado al directory de inclusiones"
|
@@ -945,7 +955,7 @@ msgid "HardeningReadmeTitle"
|
|
945 |
msgstr "Exposición de Información"
|
946 |
|
947 |
msgid "HardeningReadmeDescription"
|
948 |
-
msgstr "Esta opción verifica si el archivo README todavía existe. La información en este archivo puede ser usada por personas maliciosas para encontrar vulnerabilidades asociadas con la versión de WordPress que
|
949 |
|
950 |
msgid "HardeningReadmeApplySuccess"
|
951 |
msgstr "Hardening aplicado sobre el archivo README"
|
@@ -957,7 +967,7 @@ msgid "HardeningAdminUserTitle"
|
|
957 |
msgstr "Cuenta de Administración Primaria"
|
958 |
|
959 |
msgid "HardeningAdminUserDescription"
|
960 |
-
msgstr "Esta opción verifica si la cuenta de administración primaria está usando un nombre fácil de adivinar como \"admin\". Esto permite a personas maliciosas
|
961 |
|
962 |
msgid "HardeningFileEditorTitle"
|
963 |
msgstr "Editor de Plugins y Plantillas"
|
@@ -972,7 +982,7 @@ msgid "HardeningFileEditorRevertSuccess"
|
|
972 |
msgstr "Hardening revertido en el editor de plugins y plantillas"
|
973 |
|
974 |
msgid "HardeningFileEditorRevertFailure"
|
975 |
-
msgstr "El editor de plugins y plantillas no fue desactivado usando el plugin de Sucuri.
|
976 |
|
977 |
msgid "PHPWhitelistSuccess"
|
978 |
msgstr "El archivo ha sido agregado a la lista blanca de archivos PHP"
|
@@ -987,7 +997,7 @@ msgid "DiffUtilityStatus"
|
|
987 |
msgstr "El estado de la herramienta de integridad ha sido cambiado"
|
988 |
|
989 |
msgid "DiffUtilityMissing"
|
990 |
-
msgstr "
|
991 |
|
992 |
msgid "IntegrityLanguage"
|
993 |
msgstr "El idioma para la herramienta de integridad de archivos de WordPress ha sido cambiado"
|
@@ -1032,22 +1042,22 @@ msgid "NotBlacklisted"
|
|
1032 |
msgstr "Sin Lista Negra"
|
1033 |
|
1034 |
msgid "APIKeyExplanation"
|
1035 |
-
msgstr "Una llave de autenticación es necesaria para activar herramientas adicionales disponibles en el plugin. Las llaves son gratuitas y
|
1036 |
|
1037 |
msgid "APIKeyHelp"
|
1038 |
-
msgstr "Si
|
1039 |
|
1040 |
msgid "APIKeyGenerated"
|
1041 |
-
msgstr "Felicitaciones! Todas las herramientas disponibles en el plugin han sido habilitadas. Este producto está diseñado para suplementar productos de seguridad existentes en
|
1042 |
|
1043 |
msgid "APIKeyContinueSetup"
|
1044 |
-
msgstr "Sucuri Inc. ha generado una llave única para
|
1045 |
|
1046 |
msgid "APIKeyRecoveryExplanation"
|
1047 |
-
msgstr "Si esta operación
|
1048 |
|
1049 |
msgid "APIKeyRecoveryPossibleFailures"
|
1050 |
-
msgstr "Existen casos en los que esta operación puede fallar, un ejemplo sería cuando el correo electrónico ya no está asociado al sitio web, esto sucede cuando la base de la URL cambia <em>(de www a nada y viceversa)</em>. Si
|
1051 |
|
1052 |
msgid "DNSLookups"
|
1053 |
msgstr "Conexiones DNS"
|
@@ -1056,7 +1066,7 @@ msgid "DNSLookupsLabel"
|
|
1056 |
msgstr "Activar conexiones DNS al inicio de cada proceso"
|
1057 |
|
1058 |
msgid "DNSLookupsText"
|
1059 |
-
msgstr "
|
1060 |
|
1061 |
msgid "IntegrityTitle"
|
1062 |
msgstr "Integridad de la Instalación"
|
@@ -1071,16 +1081,16 @@ msgid "IntegrityGoodTitle"
|
|
1071 |
msgstr "Todos los Archivos Están Intáctos"
|
1072 |
|
1073 |
msgid "IntegrityGoodDescription"
|
1074 |
-
msgstr "No hemos detectado archivos adicionales, eliminados
|
1075 |
|
1076 |
msgid "IntegrityBadTitle"
|
1077 |
msgstr "Archivos de WordPress Modificados"
|
1078 |
|
1079 |
msgid "IntegrityBadDescription"
|
1080 |
-
msgstr "Hemos identificado que algunos de los archivos de WordPress han sido modificados. Esto podría indicar un ataque o la existencia de un archivo corrupto en
|
1081 |
|
1082 |
msgid "MarkFixedDescription"
|
1083 |
-
msgstr "Marcar uno o más archivos como revisado forzará al plugin a ignorar dichos archivos durante futuros escaneos, esto es útil cuando un archivo contiene falsos/positivos. Adicionalmente,
|
1084 |
|
1085 |
msgid "Action"
|
1086 |
msgstr "Acción"
|
@@ -1134,40 +1144,55 @@ msgid "FirewallSettingsTitle"
|
|
1134 |
msgstr "Ajustes del Firewall"
|
1135 |
|
1136 |
msgid "FirewallSettingsInfo"
|
1137 |
-
msgstr "Un poderoso Firewall para aplicaciones web y <b>Sistema para la Detección de Intrusiones</b> para cualquier usuario de WordPress y cualquier otra plataforma. Esta página
|
1138 |
|
1139 |
msgid "FirewallKey"
|
1140 |
msgstr "Llave del Firewall"
|
1141 |
|
1142 |
msgid "FirewallAddKey"
|
1143 |
-
msgstr "
|
1144 |
|
1145 |
msgid "FirewallFootNote"
|
1146 |
-
msgstr "<em>[1]</em> Más información acerca del <a href=\"https://sucuri.net/
|
1147 |
|
1148 |
msgid "FirewallLogsTitle"
|
1149 |
msgstr "Registros de Seguridad del Firewall"
|
1150 |
|
1151 |
msgid "FirewallLogsInfo"
|
1152 |
-
msgstr "El Firewall de Sucuri registra todas las conexiones HTTP involucradas en un ataque y las separa de las conexiones legítimas.
|
1153 |
|
1154 |
msgid "FirewallLogsNote"
|
1155 |
-
msgstr "Las conexiones que no fueron bloqueadas son omitidas
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1156 |
|
1157 |
msgid "FirewallCacheTitle"
|
1158 |
-
msgstr "
|
1159 |
|
1160 |
msgid "FirewallCacheButton"
|
1161 |
-
msgstr "Limpiar
|
1162 |
|
1163 |
msgid "FirewallCacheInfo"
|
1164 |
-
msgstr "El Firewall ofrece multiples opciones para configurar el nivel de
|
1165 |
|
1166 |
msgid "FirewallCacheNote"
|
1167 |
-
msgstr "Tenga en cuenta que el Firewall tiene unas <a href=\"https://kb.sucuri.net/firewall/Performance/cache-exceptions\" target=\"_blank\">reglas especiales para la
|
1168 |
|
1169 |
msgid "FirewallCacheWiki"
|
1170 |
-
msgstr "La
|
|
|
|
|
|
|
1171 |
|
1172 |
msgid "LoginsAdmins"
|
1173 |
msgstr "Autenticaciones Exitosas (admins)"
|
@@ -1200,28 +1225,34 @@ msgid "BlockedUsersInfo"
|
|
1200 |
msgstr "Todo intento de autenticación que haga uso de las funciones nativas de WordPress será interceptado y analizado por el plugin, si el nombre de usuario coincide con alguno en esta lista la conexión al servidor será inmediatamente detenida. Estos intentos no serán registrados y ninguna alerta de seguridad será enviada."
|
1201 |
|
1202 |
msgid "BlockedUsersNote"
|
1203 |
-
msgstr "
|
1204 |
|
1205 |
msgid "BlockedUsersByIP"
|
1206 |
-
msgstr "El bloqueo de usuarios por dirección IP es una opción disponible en el <a href=\"https://sucuri.net/
|
1207 |
|
1208 |
msgid "FailedLogins"
|
1209 |
msgstr "Autenticaciones Fallidas"
|
1210 |
|
1211 |
msgid "FailedLoginsInfo"
|
1212 |
-
msgstr "Esta información será usada para determinar si
|
1213 |
|
1214 |
msgid "LoggedInUsers"
|
1215 |
msgstr "Usuarios Activos"
|
1216 |
|
1217 |
msgid "LoggedInUsersInfo"
|
1218 |
-
msgstr "Aquí
|
1219 |
|
1220 |
msgid "Recomendations"
|
1221 |
msgstr "Recomendaciones"
|
1222 |
|
1223 |
msgid "SiteCheckNoResults"
|
1224 |
-
msgstr "Si nuestro escáner gratuito no ha detectado
|
|
|
|
|
|
|
|
|
|
|
|
|
1225 |
|
1226 |
msgid "PasswordAttack"
|
1227 |
msgstr "Ataque De Fuerza Bruta En Contra De Contraseñas"
|
@@ -1230,7 +1261,7 @@ msgid "PasswordAttackAfter"
|
|
1230 |
msgstr "Considerar Ataque Después De"
|
1231 |
|
1232 |
msgid "PasswordAttackInfo"
|
1233 |
-
msgstr "Los <a href=\"https://kb.sucuri.net/definitions/attacks/brute-force/password-guessing\" target=\"_blank\">ataques de fuerza bruta en contra de contraseñas</a> son muy comunes en sitios web y páneles de administración. Estos son uno de los vectores más comunes usado para comprometer sitios web. El proceso es muy simple, los atacantes básicamente intentan múltiple combinaciones de usuario y contraseña hasta que encuentran una que funciona. Una vez el acceso al sitio es obtenido, ellos inyectan código malicioso
|
1234 |
|
1235 |
msgid "PostTypeAlerts"
|
1236 |
msgstr "Alerts Para Diferentes Tipos de Publicaciones"
|
@@ -1242,13 +1273,13 @@ msgid "PostType"
|
|
1242 |
msgstr "Tipo de Publicación"
|
1243 |
|
1244 |
msgid "PostTypeAlertsDisabled"
|
1245 |
-
msgstr "
|
1246 |
|
1247 |
msgid "PostTypeAlertsInfo"
|
1248 |
-
msgstr "Esta es una lista de <a href=\"https://codex.wordpress.org/Post_Types\" target=\"_blank\" rel=\"noopener\">tipos de publicaciones</a> registradas.
|
1249 |
|
1250 |
msgid "PostTypeAlertsInvisible"
|
1251 |
-
msgstr "Si
|
1252 |
|
1253 |
msgid "PostTypeAlertsStop"
|
1254 |
msgstr "Ignorar Cambios En Este Tipo De Publicaciones"
|
@@ -1260,7 +1291,7 @@ msgid "AlertsPerHourMaximum"
|
|
1260 |
msgstr "Número Máximo De Alertas Por Hora"
|
1261 |
|
1262 |
msgid "AlertsPerHourInfo"
|
1263 |
-
msgstr "
|
1264 |
|
1265 |
msgid "TestAlerts"
|
1266 |
msgstr "Probar Alertas"
|
@@ -1269,7 +1300,7 @@ msgid "AlertsRecipient"
|
|
1269 |
msgstr "Quién Recibirá Alertas"
|
1270 |
|
1271 |
msgid "AlertsRecipientInfo"
|
1272 |
-
msgstr "Por defecto, el plugin enviará las alertas de seguridad a la cuenta de administración primaria, la misma cuenta que
|
1273 |
|
1274 |
msgid "CustomFormat"
|
1275 |
msgstr "Formato Personalizado"
|
@@ -1278,7 +1309,7 @@ msgid "AlertsSubject"
|
|
1278 |
msgstr "Asunto de la Alerta"
|
1279 |
|
1280 |
msgid "AlertsSubjectInfo"
|
1281 |
-
msgstr "El formato para el asunto de las alertas de seguridad, por defecto las alertas incluirán el nombre del sitio web y el identificador del evento,
|
1282 |
|
1283 |
msgid "TrustedIPs"
|
1284 |
msgstr "Direcciones IP Seguras"
|
@@ -1290,13 +1321,13 @@ msgid "IPAddedAt"
|
|
1290 |
msgstr "Dirección Agregada en"
|
1291 |
|
1292 |
msgid "TrustedIPsInfo"
|
1293 |
-
msgstr "Si
|
1294 |
|
1295 |
msgid "APIViaProxy"
|
1296 |
msgstr "API a Través de un Proxy"
|
1297 |
|
1298 |
msgid "APIViaProxyInfo"
|
1299 |
-
msgstr "Todas las conexiones a través de HTTP usadas para comunicarse con la API utilizan las funciones nativas de WordPress, esto significa que
|
1300 |
|
1301 |
msgid "ProxyHostname"
|
1302 |
msgstr "Dirección del Servidor Proxy"
|
@@ -1314,10 +1345,10 @@ msgid "APICommunication"
|
|
1314 |
msgstr "Conexión con la API"
|
1315 |
|
1316 |
msgid "APICommunicationInfo"
|
1317 |
-
msgstr "Una vez la llave para la API haya sido generada, el plugin establecerá una comunicación con un servicio remoto que actuará como una caja fuerte para almacenar los registros de seguridad generados cuando algo sospechoso
|
1318 |
|
1319 |
msgid "APICommunicationDisabled"
|
1320 |
-
msgstr "Desactivar la comunicación entre el plugin y la API detendrá el monitor de eventos de seguridad.
|
1321 |
|
1322 |
msgid "APITimeout"
|
1323 |
msgstr "Tiempo de Espera para la API"
|
@@ -1329,7 +1360,7 @@ msgid "APITimeoutValue"
|
|
1329 |
msgstr "Esperar <b>%%SUCURI.RequestTimeout%%</b> antes de terminar la conexión"
|
1330 |
|
1331 |
msgid "APITimeoutInfo"
|
1332 |
-
msgstr "El plugin envía a la API información asociada a los eventos generados por WordPress que sean considerados sospechosos. El envío de estos datos
|
1333 |
|
1334 |
msgid "HTAccessTitle"
|
1335 |
msgstr "Integridad del Archivo .htaccess"
|
@@ -1344,22 +1375,22 @@ msgid "HTAccessNotFound"
|
|
1344 |
msgstr "El sitio web no tiene un archivo <code>.htaccess</code> o no se encuentra en la ubicación esperada."
|
1345 |
|
1346 |
msgid "HTAccessStandard"
|
1347 |
-
msgstr "El archivo <code>.htaccess</code> principal contiene las reglas estándares de WordPress generadas durante la instalación del sitio web.
|
1348 |
|
1349 |
msgid "ScannerDescription"
|
1350 |
-
msgstr "El plugin escanea
|
1351 |
|
1352 |
msgid "ScannerWithoutSPL"
|
1353 |
-
msgstr "El escáner hace uso de las librerías <a href=\"http://php.net/manual/en/class.splfileobject.php\" target=\"_blank\" rel=\"noopener\">SPL</a> y <a target=\"_blank\" href=\"http://php.net/manual/en/class.filesystemiterator.php\" rel=\"noopener\">Filesystem Iterator</a> de PHP para escanear el árbol de directorios de
|
1354 |
|
1355 |
msgid "IntegrityLanguageTitle"
|
1356 |
msgstr "Integridad de WordPress (Idioma)"
|
1357 |
|
1358 |
msgid "IntegrityInfo"
|
1359 |
-
msgstr "La información necesaria para verificar la integridad de
|
1360 |
|
1361 |
msgid "IntegrityNote"
|
1362 |
-
msgstr "<b>Nota:</b> No todos los idiomas están soportados por la API de WordPress. Es posible que
|
1363 |
|
1364 |
msgid "Reason"
|
1365 |
msgstr "Motivo"
|
@@ -1371,7 +1402,7 @@ msgid "FalsePositivesUnignore"
|
|
1371 |
msgstr "No Ignorar Estos Archivos"
|
1372 |
|
1373 |
msgid "FalsePositivesInfo"
|
1374 |
-
msgstr "El escáner de archivos no lee el contenido de estos sino que compara el Checksum para saber si han sido modificados. Un falso/positivo ocurre cuando la modificación no hace parte de una inyección de código malicioso, estas modificaciones pueden ser consideradas inofencivas. Los archivos en esta lista han sido marcados como falsos/positivos y serán ignorados durante los próximos escaneos del sistema."
|
1375 |
|
1376 |
msgid "IgnoreFiles"
|
1377 |
msgstr "Ignorar Archivos Durante Los Escaneos"
|
@@ -1380,34 +1411,34 @@ msgid "IgnoreFilesSingle"
|
|
1380 |
msgstr "Ignorar Un Solo Archivo"
|
1381 |
|
1382 |
msgid "IgnoreFilesInfo"
|
1383 |
-
msgstr "
|
1384 |
|
1385 |
msgid "SecretKeys"
|
1386 |
msgstr "Llaves de Seguridad"
|
1387 |
|
1388 |
msgid "SecretKeysUpdated"
|
1389 |
-
msgstr "Las llaves de seguridad han sido cambiadas (abajo
|
1390 |
|
1391 |
msgid "SecretKeysGenerate"
|
1392 |
msgstr "Generar Nuevas Llaves de Seguridad"
|
1393 |
|
1394 |
msgid "SecretKeysExpiration"
|
1395 |
-
msgstr "
|
1396 |
|
1397 |
msgid "SecretKeysInfo"
|
1398 |
-
msgstr "
|
1399 |
|
1400 |
msgid "PluginReinstall"
|
1401 |
msgstr "Re-Instalar Plugins"
|
1402 |
|
1403 |
msgid "PluginReinstallInfo"
|
1404 |
-
msgstr "En el caso de que
|
1405 |
|
1406 |
msgid "PluginReinstallCache"
|
1407 |
-
msgstr "La información mostrada aquí es guardada en cache por %%SUCURI.ResetPlugin.CacheLifeTime%% segundos, esto es necesario para reducir el número de conexiones HTTP y subsecuentemente el consumo de ancho de banda de
|
1408 |
|
1409 |
msgid "PluginReinstallWarning"
|
1410 |
-
msgstr "<b
|
1411 |
|
1412 |
msgid "Roles"
|
1413 |
msgstr "Privilegios"
|
@@ -1419,10 +1450,10 @@ msgid "PasswordChange"
|
|
1419 |
msgstr "Cambiar la Contraseña de Usuario"
|
1420 |
|
1421 |
msgid "PasswordChangeInfo"
|
1422 |
-
msgstr "
|
1423 |
|
1424 |
msgid "PasswordChangeAlert"
|
1425 |
-
msgstr "WordPress ha generado una nueva contraseña de forma aleatoria para
|
1426 |
|
1427 |
msgid "Update"
|
1428 |
msgstr "Actualización"
|
@@ -1434,40 +1465,49 @@ msgid "AvailableUpdates"
|
|
1434 |
msgstr "Actualizaciones Disponibles"
|
1435 |
|
1436 |
msgid "AvailableUpdatesInfo"
|
1437 |
-
msgstr "WordPress tiene una acogida muy grande en Internet, esto atrae la atención de personas maliciosas para encontrar vulnerabilidades en el código al igual que en el código de plugins y plantillas que otras
|
1438 |
|
1439 |
msgid "WhitelistScript"
|
1440 |
msgstr "Desbloquear Archivos PHP"
|
1441 |
|
1442 |
msgid "WhitelistScriptInfo"
|
1443 |
-
msgstr "Después de aplicar el hardening en los directorios soportados por el plugin, un archivo .htaccess será creado con reglas para bloquear el acceso directo a todos los archivos PHP contenidos en dichos directorios, esta es una buena precaución para evitar la ejecución de código malicioso; con algunas excepciones el archivo <em>\"index.php\"</em> es el único que debería tener acceso público, sin embargo muchos plugins y plantillas requieren de este acceso también, utilice esta herramienta para desbloquearlos."
|
1444 |
|
1445 |
msgid "Uninstall"
|
1446 |
msgstr "Eliminar Registros de Seguridad, Hardening y Configuraciones"
|
1447 |
|
1448 |
msgid "UninstallInfo"
|
1449 |
-
msgstr "Esta acción iniciará el proceso de desactivación / desinstalación del plugin. Todos los registro de seguridad guardados en el disco local, las reglas de hardening y las configuraciones serán eliminadas.
|
1450 |
|
1451 |
msgid "ImportExport"
|
1452 |
msgstr "Importar Y Exportar Ajustes"
|
1453 |
|
1454 |
msgid "ImportExportInfo"
|
1455 |
-
msgstr "Copie la información codificada en JSON que aparece en la caja de abajo,
|
1456 |
|
1457 |
msgid "DataStorage"
|
1458 |
msgstr "Almacenamiento de Datos"
|
1459 |
|
1460 |
msgid "DataStorageInfo"
|
1461 |
-
msgstr "Este es el directorio donde el plugin guardará los registros de seguridad, el archivo con las configuraciones, la
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1462 |
|
1463 |
-
msgid "
|
1464 |
-
msgstr "
|
1465 |
|
1466 |
-
msgid "
|
1467 |
-
msgstr "
|
1468 |
|
1469 |
-
msgid "
|
1470 |
-
msgstr "
|
1471 |
|
1472 |
-
msgid "
|
1473 |
-
msgstr "
|
10 |
"PO-Revision-Date: \n"
|
11 |
"POT-Creation-Date: 2017-06-01 09:00-0700\n"
|
12 |
"Project-Id-Version: Sucuri Scanner\n"
|
13 |
+
"X-Generator: Poedit 1.8.12\n"
|
14 |
|
15 |
msgid "Review"
|
16 |
+
msgstr "Revisión"
|
17 |
|
18 |
msgid "Dashboard"
|
19 |
msgstr "Inicio"
|
30 |
msgid "AuditLogs"
|
31 |
msgstr "Registros"
|
32 |
|
|
|
|
|
|
|
33 |
msgid "ClearCache"
|
34 |
msgstr "Limpiar Cache"
|
35 |
|
36 |
+
msgid "IPAccess"
|
37 |
+
msgstr "Acceso Por IP"
|
38 |
+
|
39 |
msgid "GenerateAPIKey"
|
40 |
msgstr "Generar Llave"
|
41 |
|
49 |
msgstr "Accesso denegado por Sucuri Inc."
|
50 |
|
51 |
msgid "NonceFailure"
|
52 |
+
msgstr "Error al verificar el código Nonce del formulario, verifica los datos e inténtalo de nuevo."
|
53 |
|
54 |
msgid "NewsletterInvitation"
|
55 |
+
msgstr "¿Te gustaría recibir información sobre vulnerabilidades descubiertas? Subscríbete a nuestro newsletter <a href=\"http://sucuri.hs-sites.com/subscribe-to-security\" target=\"_blank\" rel=\"noopener\">aquí</a>"
|
56 |
|
57 |
msgid "EnableAPIServiceAgain"
|
58 |
+
msgstr "La comunicación con la API de Sucuri está deshabilitada, si acabas de actualizar el plugin esta podría ser una buena oportunidad para probar esta herramienta una vez más con el nuevo código. Habilite la comunicación con la API desde la página de ajustes."
|
59 |
|
60 |
msgid "Save"
|
61 |
msgstr "Guardar"
|
70 |
msgstr "Error desconocido, no hay más información."
|
71 |
|
72 |
msgid "ErrorLogFileNotFound"
|
73 |
+
msgstr "; esto generalmente sucede cuando una llave inválida es agregada al plugin, la llave será eliminada automáticamente para reducir la cantidad de errores, si quieres recuperarla, utiliza el botón de recuperación en la página de ajustes, y recibirás un correo con las instrucciones de activación: %1$s"
|
74 |
|
75 |
msgid "ErrorWrongAPIKey"
|
76 |
msgstr "; la llave del Firewall es inválida: %1$s"
|
77 |
|
78 |
msgid "ErrorSSLCertificate"
|
79 |
+
msgstr ". Tu sitio web parece estar usando una versión desactualizada de la librería OpenSSL o el módulo de CURL ha sido compilado sin soporte para el algoritmo usado para establecer un enlace de comunicación segura con la API. Contácta a tu proveedor de hosting para solucionar el problema."
|
80 |
|
81 |
msgid "ErrorInvalidEmail"
|
82 |
msgstr "El correo electrónico tiene un formato inválido o el dominio asociado no tiene asociado un servidor MX."
|
184 |
msgstr "La herramienta para exportar los registros de seguridad ha sido desactivada"
|
185 |
|
186 |
msgid "SelfHostingInfo"
|
187 |
+
msgstr "Esta opción te permite guardar una copia de los registros de seguridad en un archivo ubicado en tu servidor que puede ser leído por un SIEM o cualquier otro sistema de análisis (le recomendamos OSSEC). Esto te dará visibilidad de lo que sucede en tu sitio web para complementar tu infraestructura de monitoreo. <b>NOTA:</b> No use archivos que sean accesibles de forma pública, use un archivo que esté por lo menos un nivel arriva de la raíz del sitio web para evitar fugas de información."
|
188 |
|
189 |
msgid "SelfHostingFallback"
|
190 |
+
msgstr "No tienes una llave para comunicarte con la API. Sin embargo, la herramienta para exportar los registros de seguridad está activada, el plugin leerá el contenido de este archivo y mostrará esa información aquí. Ten en cuenta que solo los últimos registros serán procesados para mantener un consumo de memoria bajo. Considera generar una llave para obtener una mayor cobertura en la actividad de tu sitio web."
|
191 |
|
192 |
msgid "AuditLogsCache"
|
193 |
msgstr "Los registros son guardados por %%SUCURI.AuditLogs.Lifetime%% segundos"
|
210 |
msgid "NoWordPressFile"
|
211 |
msgstr "El archivo no hace parte de la instalación oficial de WordPress."
|
212 |
|
213 |
+
msgid "ThereAreNoDifferences"
|
214 |
+
msgstr "No existen diferencias entre el archivo instalado y el original"
|
215 |
|
216 |
msgid "ScheduledTask"
|
217 |
msgstr "%1$s (cada %2$d segundos)"
|
304 |
msgstr "Cambio de Contraseña"
|
305 |
|
306 |
msgid "FailedLoginFooter"
|
307 |
+
msgstr "<br><br><em>Explicación: Alguien intentó ingresar al sistema de administración de tu sitio web. Si estás recibiendo muchas de estas alertas, es posible que alguien esté utilizando un ataque de fuerza bruta para vulnerar tu sitio [1]. Puedes desactivar estas alertas desde aquí [2]. También puedes considerar la instalación de un Firewall para filtrar el tráfico malicioso y ataques como este [3].</em><br><br>[1] <a href='https://kb.sucuri.net/definitions/attacks/brute-force/password-guessing'>https://kb.sucuri.net/definitions/attacks/brute-force/password-guessing</a><br>[2] <a href='%1$s'>%2$s</a> <br>[3] <a href='https://sucuri.net/es/firewall-de-sitios-web/?wpalert'>https://sucuri.net/es/firewall-de-sitios-web/</a><br>"
|
308 |
|
309 |
msgid "FirewallAPIKeySet"
|
310 |
msgstr "La llave del Firewall ha sido guardada"
|
334 |
msgstr "Desactivada (use con precaución)"
|
335 |
|
336 |
msgid "FirewallNotEnabled"
|
337 |
+
msgstr "El Firewall no ha sido activado en tu sitio o la llave de autenticación es inválida."
|
338 |
|
339 |
msgid "FirewallClearCacheFailure"
|
340 |
+
msgstr "No se pudo actualizar la cache de tu sitio, inténtalo más tarde."
|
341 |
|
342 |
msgid "Active"
|
343 |
msgstr "activo"
|
430 |
msgstr "Fecha/Hora"
|
431 |
|
432 |
msgid "ConfirmOperation"
|
433 |
+
msgstr "Debes confirmar que entiendes el riesgo de esta operación."
|
434 |
|
435 |
msgid "UnderstandTheRisk"
|
436 |
msgstr "Entiendo que esta operación no puede ser revertida."
|
454 |
msgstr "Solo <b>%1$d</b> de <b>%2$d</b> archivos fueron procesados."
|
455 |
|
456 |
msgid "ErrorIntegrityAdded"
|
457 |
+
msgstr "El plugin no tiene permiso para eliminar este archivo porque fué creado por otro usuario del sistema con más privilegios que tu cuenta. Conéctate a tu sitio a través de FTP para eliminarlo."
|
458 |
|
459 |
msgid "ErrorIntegrityModified"
|
460 |
+
msgstr "El plugin no tiene permiso para restablecer el contenido de este archivo porque fué modificado por otro usuario del sistema con más privilegios que tu cuenta. Conéctate a tu sitio a través de FTP para restablecerlo."
|
461 |
|
462 |
msgid "ErrorIntegrityRemoved"
|
463 |
+
msgstr "El plugin no tiene permiso para restablecer el contenido de este archivo porque el directorio donde está ubicado pertenece a otro usuario del sistema con más privilegios que tu cuenta. Conéctate a tu sitio a través de FTP para restablecerlo."
|
464 |
|
465 |
msgid "SecurityAlerts"
|
466 |
msgstr "Alertas de Seguridad"
|
467 |
|
468 |
+
msgid "NoAlertsError"
|
469 |
+
msgstr "Usted ha instalado un plugin o plantilla que no es completamente compatible con nuestro plugin, algunas de las alertas de seguridad (como las autenticaciones exitosas y fallidas de usuario) no serán enviadas. Para prevenir un ciclo infinito mientras el plugin detecta cambios en el sitio y envía las alertas de seguridad a través de un plugin de SMTP personalizado, hemos decidido detener cualquier intento de enviar los correos para prevenir errores fatales."
|
470 |
+
|
471 |
msgid "AlertSettingsUpdated"
|
472 |
msgstr "La configuración para las alertas de seguridad ha sido actualizada"
|
473 |
|
475 |
msgstr "Recibir alertas por cambios en la configuración del plugin de Sucuri"
|
476 |
|
477 |
msgid "OptionPrettifyMails"
|
478 |
+
msgstr "Recibir alertas en HTML <em>(podrías experimentar problemas con tu servicio de correo electrónico)</em>"
|
479 |
|
480 |
msgid "OptionUseWordPressMail"
|
481 |
+
msgstr "Usar funciones nativas de WordPress para enviar las alertas <em>(deselecciona para usar funciones nativas de PHP)</em>"
|
482 |
|
483 |
msgid "OptionLastLoginRedirection"
|
484 |
+
msgstr "Permitir redirección durante el login para reportar información acerca de la última autenticación exitosa de tu cuenta de usuario"
|
485 |
|
486 |
msgid "OptionNotifyScanChecksums"
|
487 |
msgstr "Recibir alertas por diferencias en los archivos originales de WordPress"
|
496 |
msgstr "Recibir alertas por autenticaciones exitosas de usuario"
|
497 |
|
498 |
msgid "OptionNotifyFailedLogin"
|
499 |
+
msgstr "Recibir alertas por autenticaciones de usuario fallidas <em>(si tu sitio está siendo atacado recibirás multiples alertas por segundo, deselecciona para reducir el Spam)</em>"
|
500 |
+
|
501 |
+
msgid "OptionNotifyFailedPassword"
|
502 |
+
msgstr "Recibir alertas por autenticaciones de usuario fallidas incluyendo la contraseña enviada"
|
503 |
|
504 |
msgid "OptionNotifyBruteforceAttack"
|
505 |
msgstr "Recibir un resumen con todos los intentos de autenticación de usuario fallidos durante la misma hora. El reporte será eliminado del servidor una vez la información sea enviada a su correo"
|
506 |
|
507 |
msgid "OptionNotifyPostPublication"
|
508 |
+
msgstr "Recibir alertas por cambios en el estado de las publicaciones y páginas <em>(puedes configurar qué alertas serán monitoreadas desde el panel \"Ignorar Cambios en Publicaciones\")</em>"
|
509 |
|
510 |
msgid "OptionNotifyWebsiteUpdated"
|
511 |
+
msgstr "Recibir alertas cuando tu sitio web sea actualizado"
|
512 |
|
513 |
msgid "OptionNotifySettingsUpdated"
|
514 |
+
msgstr "Recibir alertas por cambios en la configuración general de tu sitio web"
|
515 |
|
516 |
msgid "OptionNotifyThemeEditor"
|
517 |
msgstr "Recibir alertas cuando un archivo sea modificado a través del editor de Plugins/Plantillas"
|
532 |
msgstr "Recibir alertas cuando un <b>plugin sea eliminado</b>"
|
533 |
|
534 |
msgid "OptionNotifyWidgetAdded"
|
535 |
+
msgstr "Recibir alertas cuando un <b>widget sea agregado</b> a tu sitio web"
|
536 |
|
537 |
msgid "OptionNotifyWidgetDeleted"
|
538 |
+
msgstr "Recibir alertas cuando un <b>widget sea eliminado</b> de tu sitio web"
|
539 |
|
540 |
msgid "OptionNotifyThemeInstalled"
|
541 |
msgstr "Recibir alertas cuando una <b>plantilla sea instalada</b>"
|
574 |
msgstr "Máximo 160 por hora"
|
575 |
|
576 |
msgid "BruteForceAlertSuccess"
|
577 |
+
msgstr "El plugin asumirá que tu sitio web está siendo atacado después de %1$s autenticaciones de usuario fallidas durante la misma hora"
|
578 |
|
579 |
msgid "BruteForceAlertFailure"
|
580 |
msgstr "Ese número no está soportado por el plugin, use uno de la lista"
|
607 |
msgstr "Herramienta de Integridad de Archivos"
|
608 |
|
609 |
msgid "DiffUtilityDescription"
|
610 |
+
msgstr "Si tu proveedor de hosting permite la ejecución de comandos del sistema a través de PHP, puedes configurar el plugin para usar el comando <a href=\"https://en.wikipedia.org/wiki/Diff_utility\" target=\"_blank\" rel=\"noopener\">Diff de UNIX</a> para comparar el contenido actual de tus archivos con los archivos originales de WordPress. Esta herramienta te permitirá ver las diferencias entre ambos repositorios y actuar dependiendo de la información encontrada."
|
611 |
|
612 |
msgid "DiffUtilityInfo"
|
613 |
+
msgstr "El comando diff de Unix está activado. Puedes hacer clic en los archivos en la tabla para ver las diferencias detectadas por el escáner. Si consideras que las diferencias no causan daño a tu sitio, puedes marcar el archivo como revisado, de otra forma se te sugiere restaurar el contenido original inmediatamente."
|
614 |
|
615 |
msgid "DiffUtilityInstructions"
|
616 |
+
msgstr "Las lineas con un signo <b>negativo</b> como prefijo <em>(marcadas en rojo)</em> muestran el código original. Las lineas con un signo <b>positivo</b> como prefijo <em>(marcadas en verde)</em> muestran el código actual. Puedes leer más acerca del formato DIFF en el artículo de WikiPedia <a target=\"_blank\" href=\"https://en.wikipedia.org/wiki/Diff_utility\" rel=\"noopener\">Unix Diff Utility</a>."
|
617 |
|
618 |
msgid "AccountsWereBlocked"
|
619 |
msgstr "Las cuentas de usuario seleccionadas han sido bloqueadas"
|
622 |
msgstr "Las cuentas de usuario seleccionadas han sido desbloqueadas"
|
623 |
|
624 |
msgid "LastLoginMessage"
|
625 |
+
msgstr "El último acceso de tu cuenta fué en <b>%1$s</b> desde <b>%2$s</b> <em>(%3$s)</em> <a href='%4$s'>ver todos los registros</a>"
|
626 |
|
627 |
msgid "LastLoginsNotWritable"
|
628 |
msgstr "El archivo para los registros de autenticaciones de usuario no es modificable: <code>%1$s</code>"
|
637 |
msgstr "El soporte para túneles proxy ha sido cambiado a <b>%1$s</b>"
|
638 |
|
639 |
msgid "ReverseProxyInfo"
|
640 |
+
msgstr "El plugin utiliza la dirección IP de cada usuario para registrar los eventos ejecutados, el plugin utiliza dos métodos para obtener esta dirección: el método principal usa una variable global del servidor llamada <em>Remote-Addr</em> disponible en la mayoría de servidores web, un método alternativo usa cabeceras de HTTP personalizadas <em>(que son consideradas inseguras por defecto)</em>. No es necesario que te preocupes por esta opción a menos que tu sitio web esté detrás de un túnel proxy. Servicios como el <a href=\"https://sucuri.net/es/firewall-de-sitios-web/\" target=\"_blank\">Firewall de Sucuri</a> — una vez activo — fuerzan el paso del tráfico de red a través de ellos para filtrar amenazas de seguridad que podrían afectar el servidor original. Un efecto secundario del uso de estos servicios es que la dirección IP de los usuarios ya no está disponible entre las variables globales del servidor sino que es enviada a través de una cabecera HTTP personalizada."
|
641 |
|
642 |
msgid "IPDiscoverer"
|
643 |
msgstr "Detección de Direcciones IP"
|
644 |
|
645 |
msgid "IPDiscovererInfo"
|
646 |
+
msgstr "La detección de direcciones IP hace uso de DNS para detectar si el sitio web está detrás del <a href=\"https://sucuri.net/es/firewall-de-sitios-web/\" target=\"_blank\">Firewall de Sucuri</a> en cuyo caso modificará las variables globales del servidor para configurar la dirección IP real de cada visitante del sitio. Este proceso es ejecutado con cada proceso de WordPress, y es posible que la velocidad de tu sitio sea afectada ya que algunos proveedores de hosting utilizan servidores DNS lentos, lo que hace que esta operación tome más tiempo de lo que se espera."
|
647 |
|
648 |
msgid "HTTPHeader"
|
649 |
msgstr "Cabecera de HTTP"
|
742 |
msgstr "Estos correos no recibirán más alertas de seguridad: <code>%1$s</code>"
|
743 |
|
744 |
msgid "TestAlertSent"
|
745 |
+
msgstr "Un correo de prueba ha sido enviado a tu dirección, revisa tu bandeja de entrada"
|
746 |
|
747 |
msgid "InvalidEmail"
|
748 |
msgstr "Formato de correo electrónico inválido."
|
802 |
msgstr "Acciones Automatizadas"
|
803 |
|
804 |
msgid "CronjobsInfo"
|
805 |
+
msgstr "Acciones automatizadas son reglas registradas en tu base de datos por un plugin, plantilla o WordPress; estas reglas son usadas para ejecutar automáticamente acciones definidas en el código con un intervalo de tiempo definido. Un buen uso de estas reglas es la generación de copias de seguridad, la ejecución de escáneres de seguridad o la remoción de elementos innecesarios de la base de datos como borradores de publicaciones. <b>Nota:</b> Las acciones automatizadas pueden ser re-instaladas por cualquier plugin/plantilla automáticamente, considera desactivar el plugin completamente si quieres eliminar una de estas acciones."
|
806 |
|
807 |
msgid "CronjobRunNow"
|
808 |
msgstr "Ejecutar Ahora (en +10 segundos)"
|
820 |
msgstr "Ninguna acción automatizada ha sido seleccionada de la lista"
|
821 |
|
822 |
msgid "DNSLookupStatus"
|
823 |
+
msgstr "El estado de las conexiones vía DNS para detectar el uso de túneles proxy ha sido cambiado"
|
824 |
|
825 |
msgid "IncorrectEncoding"
|
826 |
msgstr "Los datos han sido codificados incorrectamente"
|
832 |
msgstr "Llave de Autenticación"
|
833 |
|
834 |
msgid "APIKeyInfo"
|
835 |
+
msgstr "La mayoría de herramientas en este plugin pueden ser usadas sin una configuración específica, pero las herramientas más importantes requieren de una <b>llave de autenticación</b> para establecer un túnel de comunicación segura con los servidores de Sucuri. La llave es generada usando tu correo electrónico y el nombre de dominio de tu sitio web, esto te permitirá tener acceso a la herramienta de monitoreo y opciones extra."
|
836 |
|
837 |
msgid "APIKeyTerms"
|
838 |
+
msgstr "Ten en cuenta que generar una llave implica que estás de acuerdo con enviar la información recolectada por el plugin a los servidores de Sucuri, esto te permite mantener los Tem de seguridad fuera del alcance de usuarios maliciosos que podrían intentar eliminarlos para limpiar sus huellas durante un ataque. Nosotros además usamos esta información de forma anónima para generar <a href=\"https://sucuri.net/security-reports/brute-force/\" target=\"_blank\">estadísticas</a>. Por favor, no generes la llave de autenticación si estás en desacuerdo con esto, puedes seguir usando el plugin sin la llave."
|
839 |
+
|
840 |
+
msgid "APIKeyMissing"
|
841 |
+
msgstr "La llave no existe"
|
842 |
|
843 |
msgid "APIKeyInvalidDomain"
|
844 |
+
msgstr "Tu sitio web <code>%%SUCURI.CleanDomain%%</code> parece no tener un registro de DNS tipo <code>A</code> así que la API lo considerará inválido durante el proceso de generación de la llave. Agrega <code>www</code> al inicio del dominio para intentar solucionar el problema. Envía un mensaje a nuestro servicio de soporte si no entiendes qué significa esto."
|
845 |
|
846 |
msgid "APIKeyRecoverButton"
|
847 |
msgstr "Recuperar Por Correo Electrónico"
|
848 |
|
849 |
msgid "APIKeyRecoveryCondition"
|
850 |
+
msgstr "Si no tienes acceso al correo electrónico usado para generar la llave pero tienes una copia de la misma a la mano, haz <a target=\"_self\" href=\"%%SUCURI.URL.Settings%%&recover\">clic aquí</a> para activar el plugin manualmente. Ten en cuenta que si la llave es inválida el plugin la eliminará inmediatamente."
|
851 |
|
852 |
msgid "ApplyHardening"
|
853 |
msgstr "Aplicar Hardening"
|
859 |
msgstr "Firewall Para Aplicaciones Web"
|
860 |
|
861 |
msgid "HardeningFirewallDescription"
|
862 |
+
msgstr "Un WAF (Web Application Firewall) es una capa de protección para tu sitio web que bloquea todo tipo de ataques (fuerza bruta, denegación de servicios, inyecciones a base de datos, etc) y te ayuda a permanecer limpio de código malicioso y fuera de listas negras. Esta opción verifica si tu sitio web está usando el Firewall de Sucuri como tu capa de protección primaria."
|
863 |
|
864 |
msgid "HardeningFirewallPurchase"
|
865 |
+
msgstr "El Firewall de Sucuri es un servicio premium que puedes comprar aquí - <a href='https://goo.gl/qfNkMq' target='_blank'>Sucuri Firewall</a>"
|
866 |
|
867 |
msgid "HardeningVersionTitle"
|
868 |
msgstr "Verificar la Versión de WordPress"
|
869 |
|
870 |
msgid "HardeningVersionDescription"
|
871 |
+
msgstr "¿Por qué mantener tu sitio web actualizado? WordPress es un proyecto de código libre lo que significa que todos los cambios hechos al código son hechos de forma pública, si alguno de esos cambios hace parte de una solución para un problema de seguridad, cualquier persona puede utilizar esta información para atacar tu sitio web si este aún no ha aplicado el parche de seguridad."
|
872 |
|
873 |
msgid "HardeningPHPVersionTitle"
|
874 |
msgstr "Verificar la Versión de PHP"
|
877 |
msgstr "PHP %1$s está instalado."
|
878 |
|
879 |
msgid "HardeningPHPVersionLifetime"
|
880 |
+
msgstr "Comunícate con tu proveedor de hosting para instalar una versión actualizada de PHP - <a href='http://php.net/supported-versions.php' target='_blank' rel='noopener'>Lista de Versiones de PHP Soportadas</a>"
|
881 |
|
882 |
msgid "HardeningGeneratorTitle"
|
883 |
msgstr "Eliminar Versión de WordPress"
|
884 |
|
885 |
msgid "HardeningGeneratorDescription"
|
886 |
+
msgstr "Esta opción verifica si la versión de WordPress usada en tu sitio web está siendo expuesta de forma pública a través del código HTML. Muchos escáneres de vulnerabilidades web utilizan esta información para determinar si tu página web tiene vulnerabilidades para luego ser explotadas. Ten en cuenta que aún sin esta información un escáner inteligente puede detectar la versión de WordPress en uso comparando los Checksums de algunos archivos estáticos distribuidos con cada instalación."
|
887 |
|
888 |
msgid "HardeningNginxTitle"
|
889 |
msgstr "Bloquear Algunos Archivos PHP"
|
890 |
|
891 |
msgid "HardeningNginxDescription"
|
892 |
+
msgstr "Esta opción bloquea la ejecución de archivos PHP en directorios sensitivos. Se cuidadoso cuando apliques esta opción, ya que algunos plugins y plantillas requieren de acceso público a este directorio para algunas de sus herramientas, por ejemplo, para generar imágenes o guardar información temporalmente. Agrega los archivos que están siendo bloqueados a la lista blanca de archivos PHP."
|
893 |
|
894 |
msgid "HardeningNginxField"
|
895 |
msgstr "Verificar Hardening"
|
896 |
|
897 |
msgid "HardeningNginxSuggestion"
|
898 |
+
msgstr "Lee las instrucciones oficiales de WordPress para aprender como restringir el acceso a archivos PHP en directorios sensitivos - <a href='https://codex.wordpress.org/Nginx#Global_restrictions_file' target='_blank' rel='noopener'>Restricciones Globales para Nginx y WordPress</a>"
|
899 |
|
900 |
msgid "HardeningUploadsTitle"
|
901 |
msgstr "Bloquear Archivos PHP en el Directorio de Subidas"
|
902 |
|
903 |
msgid "HardeningUploadsDescription"
|
904 |
+
msgstr "Esta opción bloquea la ejecución de archivos PHP en directorios sensitivos. Se cuidadoso cuando aplique esta opción ya que algunos plugins y plantillas requieren de acceso público a este directorio para algunas de sus herramientas, por ejemplo, para generar imágenes o guardar información temporalmente. Agrega los archivos que están siendo bloqueados a la lista blanca de archivos PHP."
|
905 |
|
906 |
msgid "HardeningUploadsApplySuccess"
|
907 |
msgstr "Hardening aplicado al directorio de subidas"
|
919 |
msgstr "Bloquear Archivos PHP en el Directorio de Contenido"
|
920 |
|
921 |
msgid "HardeningContentDescription"
|
922 |
+
msgstr "Esta opción bloquea la ejecución de archivos PHP en directorios sensitivos. Se cuidadoso cuando aplique esta opción ya que algunos plugins y plantillas requieren de acceso público a este directorio para algunas de sus herramientas, por ejemplo, para generar imágenes o guardar información temporalmente. Agrega los archivos que están siendo bloqueados a la lista blanca de archivos PHP."
|
923 |
|
924 |
msgid "HardeningContentApplySuccess"
|
925 |
msgstr "Hardening aplicado al directorio de contenido"
|
937 |
msgstr "Bloquear Archivos PHP en el Directorio de Inclusiones"
|
938 |
|
939 |
msgid "HardeningIncludesDescription"
|
940 |
+
msgstr "Esta opción bloquea la ejecución de archivos PHP en directorios sensitivos. Se cuidadoso cuando aplique esta opción ya que algunos plugins y plantillas requieren de acceso público a este directorio para algunas de sus herramientas, por ejemplo, para generar imágenes o guardar información temporalmente. Agrega los archivos que están siendo bloqueados a la lista blanca de archivos PHP."
|
941 |
|
942 |
msgid "HardeningIncludesApplySuccess"
|
943 |
msgstr "Hardening aplicado al directory de inclusiones"
|
955 |
msgstr "Exposición de Información"
|
956 |
|
957 |
msgid "HardeningReadmeDescription"
|
958 |
+
msgstr "Esta opción verifica si el archivo README todavía existe. La información en este archivo puede ser usada por personas maliciosas para encontrar vulnerabilidades asociadas con la versión de WordPress que has instalado. Ten en cuenta que este archivo is re-creado cada vez que una actualización es ejecutada."
|
959 |
|
960 |
msgid "HardeningReadmeApplySuccess"
|
961 |
msgstr "Hardening aplicado sobre el archivo README"
|
967 |
msgstr "Cuenta de Administración Primaria"
|
968 |
|
969 |
msgid "HardeningAdminUserDescription"
|
970 |
+
msgstr "Esta opción verifica si la cuenta de administración primaria está usando un nombre fácil de adivinar como \"admin\". Esto permite a personas maliciosas identificar fácilmente qué cuenta tiene los privilegios más altos entre todos los usuarios registrados."
|
971 |
|
972 |
msgid "HardeningFileEditorTitle"
|
973 |
msgstr "Editor de Plugins y Plantillas"
|
982 |
msgstr "Hardening revertido en el editor de plugins y plantillas"
|
983 |
|
984 |
msgid "HardeningFileEditorRevertFailure"
|
985 |
+
msgstr "El editor de plugins y plantillas no fue desactivado usando el plugin de Sucuri. Debes escanear tu sitio web por una constante definida como \"DISALLOW_FILE_EDIT\" cuando la encuentres, debes eliminarla o cambiar su valor a \"False\". Ten en cuenta que cualquier otro plugin o plantilla puede desactivar el editor, así que es imposible determinar el origen de la constante."
|
986 |
|
987 |
msgid "PHPWhitelistSuccess"
|
988 |
msgstr "El archivo ha sido agregado a la lista blanca de archivos PHP"
|
997 |
msgstr "El estado de la herramienta de integridad ha sido cambiado"
|
998 |
|
999 |
msgid "DiffUtilityMissing"
|
1000 |
+
msgstr "Tu proveedor de hosting no permite la ejecución de comandos del sistema a través de archivos PHP."
|
1001 |
|
1002 |
msgid "IntegrityLanguage"
|
1003 |
msgstr "El idioma para la herramienta de integridad de archivos de WordPress ha sido cambiado"
|
1042 |
msgstr "Sin Lista Negra"
|
1043 |
|
1044 |
msgid "APIKeyExplanation"
|
1045 |
+
msgstr "Una llave de autenticación es necesaria para activar herramientas adicionales disponibles en el plugin. Las llaves son gratuitas y puedes generar un número ilimitado de ellas siempre y cuando el nombre del sitio web y el correo electrónico sean únicos. La llave es usada para autenticar las conexiones a través de HTTP hechas a la API administrada por Sucuri Inc. No generes la llave si estás en desacuerdo con el envío de información a nuestros servidores."
|
1046 |
|
1047 |
msgid "APIKeyHelp"
|
1048 |
+
msgstr "Si experimentas problemas con la generación de la llave, puedes solicitar una enviando la dirección de tu sitio web y el correo electrónico que deseas usar para la asociación a <a href=\"mailto:info@sucuri.net\">info@sucuri.net</a>. Ten en cuenta que generar una llave para un sitio web que no es público en Internet no es posible, ya que la API necesita validar que el nombre del host existe, sin embargo, si deseas probar el plugin en un ambiente de desarrollo, por favor contáctanos para poder generar una llave manualmente."
|
1049 |
|
1050 |
msgid "APIKeyGenerated"
|
1051 |
+
msgstr "¡Felicitaciones! Todas las herramientas disponibles en el plugin han sido habilitadas. Este producto está diseñado para suplementar productos de seguridad existentes en tu sitio web. El plugin no provee una solución completa a tus necesidades de seguridad, pero te ofrece más herramientas para controlar el funcionamiento de tu sitio y tener una mejor postura con respecto a ataques que puedas sufrir en el futuro, todo esto con la intensión de reducir riesgos."
|
1052 |
|
1053 |
msgid "APIKeyContinueSetup"
|
1054 |
+
msgstr "Sucuri Inc. ha generado una llave única para tu sitio web, esta llave fue asociada al correo electrónico que seleccionaste anteriormente, correo que puedes utilizar para recuperar dicha llave si llegaras a perderla en el futuro. Te invitamos a revisar el resto de opciones disponibles en la página de ajustes para que configures el plugin a la medida de tu sitio."
|
1055 |
|
1056 |
msgid "APIKeyRecoveryExplanation"
|
1057 |
+
msgstr "Si esta operación fue exitosa, recibirás un mensaje en el correo electrónico que usaste durante la generación de la llave <em>(usualmente este correo es el mismo asociado a la cuenta de administración primaria)</em>. Este mensaje contiene una copia de la llave, por favor copia y pega la llave en el formulario de abajo. El plugin verificará la autenticidad de la misma, si esta verificación falla, la llave será eliminada automáticamente y deberás iniciar el proceso de recuperación nuevamente."
|
1058 |
|
1059 |
msgid "APIKeyRecoveryPossibleFailures"
|
1060 |
+
msgstr "Existen casos en los que esta operación puede fallar, un ejemplo sería cuando el correo electrónico ya no está asociado al sitio web, esto sucede cuando la base de la URL cambia <em>(de www a nada y viceversa)</em>. Si estás teniendo problemas con el proceso de recuperación de la llave, por favor envía un mensaje explicando la situación a <a href=\"mailto:info@sucuri.net\">info@sucuri.net</a>"
|
1061 |
|
1062 |
msgid "DNSLookups"
|
1063 |
msgstr "Conexiones DNS"
|
1066 |
msgstr "Activar conexiones DNS al inicio de cada proceso"
|
1067 |
|
1068 |
msgid "DNSLookupsText"
|
1069 |
+
msgstr "Activa esta opción si tu sitio web está detrás de un Firewall, esto garantizará que la dirección IP de tus visitantes será detectada correctamente para los registros de seguridad. Puedes cambiar esto después desde la página de configuraciones del plugin."
|
1070 |
|
1071 |
msgid "IntegrityTitle"
|
1072 |
msgstr "Integridad de la Instalación"
|
1081 |
msgstr "Todos los Archivos Están Intáctos"
|
1082 |
|
1083 |
msgid "IntegrityGoodDescription"
|
1084 |
+
msgstr "No hemos detectado archivos adicionales, eliminados o cambios relevantes en los archivos originales de WordPress. Si estás experimentando otros problemas, por favor usa un <a target=\"_blank\" href=\"https://sucuri.net/es/seguridad-de-sitios-web/remocion-de-malware\">servicio de limpieza de malware</a>."
|
1085 |
|
1086 |
msgid "IntegrityBadTitle"
|
1087 |
msgstr "Archivos de WordPress Modificados"
|
1088 |
|
1089 |
msgid "IntegrityBadDescription"
|
1090 |
+
msgstr "Hemos identificado que algunos de los archivos de WordPress han sido modificados. Esto podría indicar un ataque o la existencia de un archivo corrupto en tu instalación. Si estás experimentando otros problemas, por favor usa un <a target=\"_blank\" href=\"https://sucuri.net/es/seguridad-de-sitios-web/remocion-de-malware\">servicio de limpieza de malware</a>."
|
1091 |
|
1092 |
msgid "MarkFixedDescription"
|
1093 |
+
msgstr "Marcar uno o más archivos como revisado forzará al plugin a ignorar dichos archivos durante futuros escaneos, esto es útil cuando un archivo contiene falsos/positivos. Adicionalmente, puedes restaurar el contenido original si estos han sido modificados o eliminados, el plugin descargará una copia del código desde el repositorio oficial de WordPress. La eliminación de archivos es una operación irreversible, ten cuidado."
|
1094 |
|
1095 |
msgid "Action"
|
1096 |
msgstr "Acción"
|
1144 |
msgstr "Ajustes del Firewall"
|
1145 |
|
1146 |
msgid "FirewallSettingsInfo"
|
1147 |
+
msgstr "Un poderoso Firewall para aplicaciones web y <b>Sistema para la Detección de Intrusiones</b> para cualquier usuario de WordPress y cualquier otra plataforma. Esta página te ayudará a configurar y monitorear tu sitio web a través del <b>Firewall de Sucuri</b>. Una vez activado, nuestro Firewall actuará como un escudo, protegiendo tu sitio de ataques y previniendo infecciones de malware y reinfecciones. El Firewall también bloqueará inyecciones a bases de datos, ataques de fuerza bruta, XSS, RFI, puertas traseras y muchas otras amenazas en contra de tu sitio web."
|
1148 |
|
1149 |
msgid "FirewallKey"
|
1150 |
msgstr "Llave del Firewall"
|
1151 |
|
1152 |
msgid "FirewallAddKey"
|
1153 |
+
msgstr "Agrega la <a href=\"https://waf.sucuri.net/?settings&panel=api\" target=\"_blank\">llave del Firewall</a> en el formulario para iniciar una conexión con la API."
|
1154 |
|
1155 |
msgid "FirewallFootNote"
|
1156 |
+
msgstr "<em>[1]</em> Más información acerca del <a href=\"https://sucuri.net/es/firewall-de-sitios-web/\" target=\"_blank\">Firewall de Sucuri</a>, herramientas disponibles y precios.<br><em>[2]</em> Instrucciones y videos en la <a href=\"https://kb.sucuri.net/firewall\" target=\"_blank\">Wiki de Sucuri</a>.<br><em>[3]</em> <a href=\"https://login.sucuri.net/signup2/create?CloudProxy\" target=\"_blank\">Registra</a> una cuenta nueva y empieza a proteger tu sitio web."
|
1157 |
|
1158 |
msgid "FirewallLogsTitle"
|
1159 |
msgstr "Registros de Seguridad del Firewall"
|
1160 |
|
1161 |
msgid "FirewallLogsInfo"
|
1162 |
+
msgstr "El Firewall de Sucuri registra todas las conexiones HTTP involucradas en un ataque y las separa de las conexiones legítimas. Puedes usar esta herramienta para analizar la información de las últimas conexiones y tomar acción. O sea, activando las herramientas avanzadas del IDS <em>(Intrusion Detection System)</em> desde el <a target=\"_blank\" href=\"https://waf.sucuri.net/?settings\">panel de administración del Firewall</a> y/o bloquear las direcciones IP y URL directamente desde la <a href=\"https://waf.sucuri.net/?audit\" target=\"_blank\">página de registros de seguridad del Firewall</a>."
|
1163 |
|
1164 |
msgid "FirewallLogsNote"
|
1165 |
+
msgstr "Las conexiones que no fueron bloqueadas son omitidas de la lista, esto es intencional."
|
1166 |
+
|
1167 |
+
msgid "FirewallIPAccessTitle"
|
1168 |
+
msgstr "Dirección IP (Acceso)"
|
1169 |
+
|
1170 |
+
msgid "FirewallIPAccessInfo"
|
1171 |
+
msgstr "Esta herramienta le permite bloquear y desbloquear el acceso a su sitio web de una o mas direcciones IP. Además, puede bloquear direcciones IP automáticamente cuando estas están involucradas en un ataque de fuerza bruta para adivinar la contraseña de uno o más usuarios registrados. Si un usuario legítimo es bloqueado después de enviar las credenciales incorrectas de su cuenta más de tres veces, ellos deberán ingresar al panel de control del Firewall para eliminar su dirección IP de la lista negra, o intentar acceder al sitio a través de una VPN."
|
1172 |
+
|
1173 |
+
msgid "WhitelistIP"
|
1174 |
+
msgstr "Desbloquear Dirección IP"
|
1175 |
+
|
1176 |
+
msgid "BlacklistIP"
|
1177 |
+
msgstr "Bloquear Dirección IP"
|
1178 |
|
1179 |
msgid "FirewallCacheTitle"
|
1180 |
+
msgstr "Caché del Firewall"
|
1181 |
|
1182 |
msgid "FirewallCacheButton"
|
1183 |
+
msgstr "Limpiar Caché"
|
1184 |
|
1185 |
msgid "FirewallCacheInfo"
|
1186 |
+
msgstr "El Firewall ofrece multiples opciones para configurar el nivel de caché aplicado a tu sitio web. Puedes considerar activar la cobertura total de la caché <em>(que es lo recomendado)</em>, o puedes configurar la caché a un nivel mínimo, o forzar el uso de las cabeceras HTTP <em>(solo para usuarios avanzados)</em>, o en casos extremos donde no necesitas la caché, puedes desactivarla completamente. Puedes encontrar más información acerca de estas opciones <a target=\"_blank\" href=\"https://kb.sucuri.net/firewall/Performance/caching-options\">aquí</a>."
|
1187 |
|
1188 |
msgid "FirewallCacheNote"
|
1189 |
+
msgstr "Tenga en cuenta que el Firewall tiene unas <a href=\"https://kb.sucuri.net/firewall/Performance/cache-exceptions\" target=\"_blank\">reglas especiales para la caché</a> de imágenes, archivos CSS, archivos PDF, archivos de texto, código JavaScript, archivos audio visuales y algunas otros formatos de archivo que son guardados en nuestros <a href=\"https://en.wikipedia.org/wiki/Edge_device\" target=\"_blank\" rel=\"noopener\">Edge Devices</a>. La única forma de limpiar la caché de estos archivos es haciendo uso de parámetros aleatorios en la URL, puede agregar un parametro como este <code>?ver=1.2.3</code> e incrementar el número con cada actualización."
|
1190 |
|
1191 |
msgid "FirewallCacheWiki"
|
1192 |
+
msgstr "La caché web es una tecnología para el almacenamiento temporal (caching) de documentos web, como páginas en HTML e imágenes, para reducir el uso de ancho de banda, la carga del servidor, y retrasos en las descargas. Un sistema de caché web guarda copias de los documentos que pasan a través de él; conexiones subsecuentes pueden devolver el contenido desde la caché si las condiciones lo permiten. — <a href=\"https://en.wikipedia.org/wiki/Web_cache\" target=\"_blank\" rel=\"noopener\">WikiPedia - Web Cache</a>"
|
1193 |
+
|
1194 |
+
msgid "FirewallAutoClearCache"
|
1195 |
+
msgstr "Limpiar cache automáticamente cuando una publicación o página sea modificada"
|
1196 |
|
1197 |
msgid "LoginsAdmins"
|
1198 |
msgstr "Autenticaciones Exitosas (admins)"
|
1225 |
msgstr "Todo intento de autenticación que haga uso de las funciones nativas de WordPress será interceptado y analizado por el plugin, si el nombre de usuario coincide con alguno en esta lista la conexión al servidor será inmediatamente detenida. Estos intentos no serán registrados y ninguna alerta de seguridad será enviada."
|
1226 |
|
1227 |
msgid "BlockedUsersNote"
|
1228 |
+
msgstr "Ten en cuenta que esta herramienta no intenta proveer una protección completa para bloquear autenticaciones indeseadas de usuarios maliciosos. Dependiendo de la configuración de tu sitio web, los plugins o plantillas que sean instalados, o inclusive la versión de WordPress que estés usando, habrán huecos en el sistema que usuarios maliciosos pueden utilizar para evadir estos bloqueos e iniciar un ataque por fuerza bruta. <a target=\"_blank\" href=\"https://sucuri.net/es/firewall-de-sitios-web/?wp=bu\">Instala un Firewall</a> para obtener protección completa y mitigar este y otros ataques en contra tu sitio web."
|
1229 |
|
1230 |
msgid "BlockedUsersByIP"
|
1231 |
+
msgstr "El bloqueo de usuarios por dirección IP es una opción disponible en el <a href=\"https://sucuri.net/es/firewall-de-sitios-web/\" target=\"_blank\">Firewall de Sucuri</a>; para evitar la duplicación de código y reducir la cantidad de falsos/positivos esta opción nunca será implementada en este plugin."
|
1232 |
|
1233 |
msgid "FailedLogins"
|
1234 |
msgstr "Autenticaciones Fallidas"
|
1235 |
|
1236 |
msgid "FailedLoginsInfo"
|
1237 |
+
msgstr "Esta información será usada para determinar si tu sitio es víctima de un <a href=\"https://kb.sucuri.net/definitions/attacks/brute-force/password-guessing\" target=\"_blank\">Password Guessing Brute Force Attacks</a>. Estos registros serán acumulados, si más de <code>%%SUCURI.FailedLogins.MaxFailedLogins%%</code> autenticaciones fallidas son registradas durante la misma hora, el plugin enviará un correo electrónico con un resumen del ataque <em>(debe activar esta opción desde la página de ajustes, sección alertas)</em>. <b>NOTA:</b> Algunos plugins que ofrecen la opción de <em>\"Autenticación por Dos-Pasos\"</em> no usan las funciones nativas de WordPress, motivo por el cual algunos intentos de autenticación no podrán ser interceptados ni analizados."
|
1238 |
|
1239 |
msgid "LoggedInUsers"
|
1240 |
msgstr "Usuarios Activos"
|
1241 |
|
1242 |
msgid "LoggedInUsersInfo"
|
1243 |
+
msgstr "Aquí puedes encontrar una lista de usuarios que han iniciado una sesión en los últimos minutos."
|
1244 |
|
1245 |
msgid "Recomendations"
|
1246 |
msgstr "Recomendaciones"
|
1247 |
|
1248 |
msgid "SiteCheckNoResults"
|
1249 |
+
msgstr "Si nuestro escáner gratuito no ha detectado ningún problema, es posible que tu sitio tenga un problema más complicado y la infección esté escondida. Puede <a target=\"_blank\" href=\"https://sucuri.net/es/plataforma-de-seguridad-de-sitios-web/signup\">registrar una cuenta con Sucuri</a> para obtener un escaneo más detallado y eventualmente una limpieza absoluta de tu sitio web (no incluido con el plan gratuito)."
|
1250 |
+
|
1251 |
+
msgid "SiteCheckTarget"
|
1252 |
+
msgstr "URL Para el Escáner de Malware"
|
1253 |
+
|
1254 |
+
msgid "SiteCheckTargetInfo"
|
1255 |
+
msgstr "El escáner remoto de malware funciona gracias a <a href=\"https://sitecheck.sucuri.net/\" target=\"_blank\">Sucuri SiteCheck</a>, un servicio que toma la dirección de un sitio web con acceso público y la escanea en busca de código malicioso. Si su sitio web no es visible a través de Internet, por ejemplo, si el sitio está en un ambiente de desarrollo local or una red restringida, el escáner no podrá trabajar en él. Adicionalmente, si el sitio web fué instalado en un directorio diferente al sugerido el escáner reportará un error \"404 Not Found\". Puedes usar esta opción para cambiar la dirección del sitio web que será escaneado."
|
1256 |
|
1257 |
msgid "PasswordAttack"
|
1258 |
msgstr "Ataque De Fuerza Bruta En Contra De Contraseñas"
|
1261 |
msgstr "Considerar Ataque Después De"
|
1262 |
|
1263 |
msgid "PasswordAttackInfo"
|
1264 |
+
msgstr "Los <a href=\"https://kb.sucuri.net/definitions/attacks/brute-force/password-guessing\" target=\"_blank\">ataques de fuerza bruta en contra de contraseñas</a> son muy comunes en sitios web y páneles de administración. Estos son uno de los vectores más comunes usado para comprometer sitios web. El proceso es muy simple, los atacantes básicamente intentan múltiple combinaciones de usuario y contraseña hasta que encuentran una que funciona. Una vez el acceso al sitio es obtenido, ellos inyectan código malicioso para generar spam, crear páginas fraudulentas, etc."
|
1265 |
|
1266 |
msgid "PostTypeAlerts"
|
1267 |
msgstr "Alerts Para Diferentes Tipos de Publicaciones"
|
1273 |
msgstr "Tipo de Publicación"
|
1274 |
|
1275 |
msgid "PostTypeAlertsDisabled"
|
1276 |
+
msgstr "Desactivaste las alertas de seguridad, cuando una publicación es creada o modificada, esta herramienta espera que esa opción esté activa para poder filtrar los tipos de publicaciones que no son relevantes para el administrador del sitio."
|
1277 |
|
1278 |
msgid "PostTypeAlertsInfo"
|
1279 |
+
msgstr "Esta es una lista de <a href=\"https://codex.wordpress.org/Post_Types\" target=\"_blank\" rel=\"noopener\">tipos de publicaciones</a> registradas. Recibirás alertas de seguridad cuando una página o publicación sea creada o modificada. Algunos de estos tipos son nativos de WordPress pero la mayoría son creados por plugins y plantillas que tengas instalados. Si no quieres recibir alertas por cambios en uno o más de estos tipos, puedes usar este panel para desactivarlas."
|
1280 |
|
1281 |
msgid "PostTypeAlertsInvisible"
|
1282 |
+
msgstr "Si estás recibiendo alertas por cambios en tipos de publicaciones que no aparecen en la lista, es posible que estas hayan sido creadas dinámicamente por un plugin o plantilla sin usar las funciones nativas de WordPress. Si conoce el identificador único del tipo de publicación, puedes ingresarlo en el formulario y el plugin de Sucuri hará lo mejor posible para ignorar estas alertas."
|
1283 |
|
1284 |
msgid "PostTypeAlertsStop"
|
1285 |
msgstr "Ignorar Cambios En Este Tipo De Publicaciones"
|
1291 |
msgstr "Número Máximo De Alertas Por Hora"
|
1292 |
|
1293 |
msgid "AlertsPerHourInfo"
|
1294 |
+
msgstr "Utiliza esta opción para configurar el número máximo de alertas de seguridad por hora. Si el número es excedido y el plugin detecta más eventos durante la misma hora, estos serán agregados al registro de seguridad pero no serán enviados por correo electrónico. Ten cuidado con esta opción, ya que puedes perder información importante."
|
1295 |
|
1296 |
msgid "TestAlerts"
|
1297 |
msgstr "Probar Alertas"
|
1300 |
msgstr "Quién Recibirá Alertas"
|
1301 |
|
1302 |
msgid "AlertsRecipientInfo"
|
1303 |
+
msgstr "Por defecto, el plugin enviará las alertas de seguridad a la cuenta de administración primaria, la misma cuenta que fue creada durante el proceso de instalación de WordPress en tu servidor web. Puedes agregar más direcciones de correo a la lista, ellos recibirán una copia de las mismas alertas de seguridad."
|
1304 |
|
1305 |
msgid "CustomFormat"
|
1306 |
msgstr "Formato Personalizado"
|
1309 |
msgstr "Asunto de la Alerta"
|
1310 |
|
1311 |
msgid "AlertsSubjectInfo"
|
1312 |
+
msgstr "El formato para el asunto de las alertas de seguridad, por defecto las alertas incluirán el nombre del sitio web y el identificador del evento, puedes usar este panel para agregar la dirección IP del usuario o cualquier otra información adicional. También puedes crear filtros en tu cliente de correo electrónico, agregando etiquetas personalizadas en el formulario."
|
1313 |
|
1314 |
msgid "TrustedIPs"
|
1315 |
msgstr "Direcciones IP Seguras"
|
1321 |
msgstr "Dirección Agregada en"
|
1322 |
|
1323 |
msgid "TrustedIPsInfo"
|
1324 |
+
msgstr "Si estás trabajando en una red de área local, puedes querer incluir las direcciones IP de todos los nodos de la red en esta lista, esto hará que el plugin ignore todos los eventos originados desde estas direcciones para reducir la cantidad de falsos/positivos. Puede usar el formato CIDR <em>(Classless Inter Domain Routing)</em> para especificar un rango de direcciones IP <em>(solo 8, 16, y 24)</em>."
|
1325 |
|
1326 |
msgid "APIViaProxy"
|
1327 |
msgstr "API a Través de un Proxy"
|
1328 |
|
1329 |
msgid "APIViaProxyInfo"
|
1330 |
+
msgstr "Todas las conexiones a través de HTTP usadas para comunicarse con la API utilizan las funciones nativas de WordPress, esto significa que puedes usar el mismo mecanismo sugerido por WordPress para establecer estas conexiones a través de un proxy. De acuerdo a la <a href=\"https://developer.wordpress.org/reference/classes/wp_http_proxy/\" target=\"_blank\" rel=\"noopener\">documentación oficial</a>, debes agregar estas constantes en el archivo de configuración: <em>WP_PROXY_HOST, WP_PROXY_PORT, WP_PROXY_USERNAME, WP_PROXY_PASSWORD</em>."
|
1331 |
|
1332 |
msgid "ProxyHostname"
|
1333 |
msgstr "Dirección del Servidor Proxy"
|
1345 |
msgstr "Conexión con la API"
|
1346 |
|
1347 |
msgid "APICommunicationInfo"
|
1348 |
+
msgstr "Una vez la llave para la API haya sido generada, el plugin establecerá una comunicación con un servicio remoto que actuará como una caja fuerte para almacenar los registros de seguridad generados cuando algo sospechoso suceda en tu sitio web. Si el sitio es comprometido, el hacker no podrá eliminar los registros de seguridad para encubrir sus huellas, de esta forma podrás investigar el ataque y prevenir futuros problemas."
|
1349 |
|
1350 |
msgid "APICommunicationDisabled"
|
1351 |
+
msgstr "Desactivar la comunicación entre el plugin y la API detendrá el monitor de eventos de seguridad. Considera activar el exportador de registros desde la página general de ajustes para mantener el monitor de eventos funcionando sin enviar datos a la API, de lo contrario, un usuario malicioso podrá ejecutar acciones sin que un administrador se de cuenta de lo que está sucediendo."
|
1352 |
|
1353 |
msgid "APITimeout"
|
1354 |
msgstr "Tiempo de Espera para la API"
|
1360 |
msgstr "Esperar <b>%%SUCURI.RequestTimeout%%</b> antes de terminar la conexión"
|
1361 |
|
1362 |
msgid "APITimeoutInfo"
|
1363 |
+
msgstr "El plugin envía a la API información asociada a los eventos generados por WordPress que sean considerados sospechosos. El envío de estos datos se hace a través de HTTP usando uno de los protocolos de comunicación disponibles en el sistema y <a target=\"_blank\" href=\"https://developer.wordpress.org/reference/functions/wp_remote_post/\" rel=\"noopener\">funciones nativas de WordPress</a>. Si la conexión o el servicio remoto excede la cantidad de segundos configurados en esta opción, la operación es cancelada. Si experimentas problemas de conexión, por favor comunícate con tu proveedor de hosting para investigar los bloqueos."
|
1364 |
|
1365 |
msgid "HTAccessTitle"
|
1366 |
msgstr "Integridad del Archivo .htaccess"
|
1375 |
msgstr "El sitio web no tiene un archivo <code>.htaccess</code> o no se encuentra en la ubicación esperada."
|
1376 |
|
1377 |
msgid "HTAccessStandard"
|
1378 |
+
msgstr "El archivo <code>.htaccess</code> principal contiene las reglas estándares de WordPress generadas durante la instalación del sitio web. Puedes modificar estas reglas para aumentar el rendimiento del servidor o para generar redirecciones a otras páginas. Para obtener más información al respecto visita la página oficial con la documentación en <a target=\"_blank\" rel=\"noopener\" href=\"https://codex.wordpress.org/Using_Permalinks#Creating_and_editing_.28.htaccess.29\"> Codex WordPress - Creating and editing (.htaccess)</a>"
|
1379 |
|
1380 |
msgid "ScannerDescription"
|
1381 |
+
msgstr "El plugin escanea tu sitio web en busca de cambios que son eventualmente reportados a la API y visualizados a través de los registros de seguridad. Este escáner es ejecutado automáticamente cada día, pero puedes cambiar la frecuencia dependiendo de tus necesidades. Ten en cuenta que si tu sitio contiene una gran cantidad de archivos, es posible que el escáner sea bloqueado por tu proveedor de hosting si este excede el límite de ejecución que ellos hayan impuesto sobre su cuenta."
|
1382 |
|
1383 |
msgid "ScannerWithoutSPL"
|
1384 |
+
msgstr "El escáner hace uso de las librerías <a href=\"http://php.net/manual/en/class.splfileobject.php\" target=\"_blank\" rel=\"noopener\">SPL</a> y <a target=\"_blank\" href=\"http://php.net/manual/en/class.filesystemiterator.php\" rel=\"noopener\">Filesystem Iterator</a> de PHP para escanear el árbol de directorios de tu sitio web. Esta librería solo está disponible en PHP 5 >= 5.3.0 — y — PHP 7; si tu servidor hace uso de una versión antigua, el plugin no funcionará como se espera. Por favor, contacta a tu proveedor de hosting para obtener ayuda al respecto."
|
1385 |
|
1386 |
msgid "IntegrityLanguageTitle"
|
1387 |
msgstr "Integridad de WordPress (Idioma)"
|
1388 |
|
1389 |
msgid "IntegrityInfo"
|
1390 |
+
msgstr "La información necesaria para verificar la integridad de tu instalación de WordPress proviene de la <a href=\"http://codex.wordpress.org/WordPress.org_API\" target=\"_blank\" rel=\"noopener\">API Oficial de WordPress</a>. El plugin compara esta información con los archivos instalados en tu sitio web. Por defecto, la API provee una copia de los archivos en Inglés, si instalaste un idioma diferente, por favor selecciónalo en esta opción para reducir la cantidad de falsos/positivos que el escáner pueda encontrar."
|
1391 |
|
1392 |
msgid "IntegrityNote"
|
1393 |
+
msgstr "<b>Nota:</b> No todos los idiomas están soportados por la API de WordPress. Es posible que tengas que usar la versión en Inglés para reducir la cantidad de falsos/positivos arrojados por el escáner durante su ejecución. Como alternativa, puede seleccionar dichos archivos y marcarlos como revisados para que el escáner los ignore."
|
1394 |
|
1395 |
msgid "Reason"
|
1396 |
msgstr "Motivo"
|
1402 |
msgstr "No Ignorar Estos Archivos"
|
1403 |
|
1404 |
msgid "FalsePositivesInfo"
|
1405 |
+
msgstr "El escáner de archivos no lee el contenido de estos, sino que compara el Checksum para saber si han sido modificados. Un falso/positivo ocurre cuando la modificación no hace parte de una inyección de código malicioso, estas modificaciones pueden ser consideradas inofencivas. Los archivos en esta lista han sido marcados como falsos/positivos y serán ignorados durante los próximos escaneos del sistema."
|
1406 |
|
1407 |
msgid "IgnoreFiles"
|
1408 |
msgstr "Ignorar Archivos Durante Los Escaneos"
|
1411 |
msgstr "Ignorar Un Solo Archivo"
|
1412 |
|
1413 |
msgid "IgnoreFilesInfo"
|
1414 |
+
msgstr "Utiliza esta herramienta para seleccionar directorios que contienen muchos archivos o archivos que son muy pesados para ser procesados por el escáner de seguridad. Esto usualmente incluye directorios con imágenes, archivos multimedia, y en general cualquier archivo que no tenga código. Ignorar estos archivos mejorará el rendimiento del plugin y mantendrá el consumo de memoria a niveles mínimos."
|
1415 |
|
1416 |
msgid "SecretKeys"
|
1417 |
msgstr "Llaves de Seguridad"
|
1418 |
|
1419 |
msgid "SecretKeysUpdated"
|
1420 |
+
msgstr "Las llaves de seguridad han sido cambiadas (abajo puedes encontrar un resumen de la operación)."
|
1421 |
|
1422 |
msgid "SecretKeysGenerate"
|
1423 |
msgstr "Generar Nuevas Llaves de Seguridad"
|
1424 |
|
1425 |
msgid "SecretKeysExpiration"
|
1426 |
+
msgstr "Tu sesión de usuario expirará inmediatamente cuando las nuevas llaves de seguridad sean generadas."
|
1427 |
|
1428 |
msgid "SecretKeysInfo"
|
1429 |
+
msgstr "Las llaves secretas o de seguridad son una lista de constantes aleatorias agregadas a tu sitio web, para mejorar el proceso de encriptación de las cookies para cada usuario. Las llaves hacen que tu sitio sea más difícil de vulnerar, al agregar elementos aleatorios en las contraseñas. No necesitas memorizar estas llaves, ellas serán guardadas en el archivo de configuración de WordPress. Puede cambiarlas en cualquier momento para invalidar sesiones de usuario existentes, forzando a todos los usuarios a autenticar sus cuentas nuevamente."
|
1430 |
|
1431 |
msgid "PluginReinstall"
|
1432 |
msgstr "Re-Instalar Plugins"
|
1433 |
|
1434 |
msgid "PluginReinstallInfo"
|
1435 |
+
msgstr "En el caso de que sospeches que tu sitio web está infectado con código maliciosos, o incluso después de limpiar tu sitio, es una buena idea reinstalar todos los plugins y plantillas, incluso aquellos que no están activados, para asegurar que el código es el original. Ten en cuenta que plugins y plantillas premium no pueden ser reinstaladas por motivos de compatibilidad con sus licencias."
|
1436 |
|
1437 |
msgid "PluginReinstallCache"
|
1438 |
+
msgstr "La información mostrada aquí es guardada en cache por %%SUCURI.ResetPlugin.CacheLifeTime%% segundos, esto es necesario para reducir el número de conexiones HTTP y subsecuentemente el consumo de ancho de banda de tu servidor. Actualmente no existe una opción para limpiar esta caché, debes esperar a que el plugin la regenere automáticamente."
|
1439 |
|
1440 |
msgid "PluginReinstallWarning"
|
1441 |
+
msgstr "<b>¡ADVERTENCIA!</b> La reinstalación de uno o más plugin puede ocasionar daños irreversibles a tu sitio web, procede con cuidado y asegúrate de mantener una copia de seguridad actualizada del sitio a la mano. Esta herramienta no tendrá ningún efecto sobre la base de datos."
|
1442 |
|
1443 |
msgid "Roles"
|
1444 |
msgstr "Privilegios"
|
1450 |
msgstr "Cambiar la Contraseña de Usuario"
|
1451 |
|
1452 |
msgid "PasswordChangeInfo"
|
1453 |
+
msgstr "Puedes generar una nueva contraseña aleatoria para las cuentas de usuario que selecciones de la lista. Un correo será enviado a cada usuario. Si decides cambiar tu propia contraseña, tu sesión de usuario expirará inmediatamente. Necesitarás autenticar tu cuenta nuevamente con la nueva contraseña que recibirás en tu correo electrónico."
|
1454 |
|
1455 |
msgid "PasswordChangeAlert"
|
1456 |
+
msgstr "WordPress ha generado una nueva contraseña de forma aleatoria para tu cuenta de usuario <b>%%SUCURI.ResetPassword.UserName%%</b> en este sitio web <a target=\"_blank\" href=\"http://%%SUCURI.ResetPassword.Website%%\">%%SUCURI.ResetPassword.Website%%</a>. El cambio ha sido solicitado por uno de los administradores del sitio por motivos de seguridad. Tu nueva contraseña es — <span style=\"font-family:Menlo, Monaco, monospace, serif;font-weight:700\">%%%SUCURI.ResetPassword.Password%%%</span> — por favor cámbiala lo antes posible."
|
1457 |
|
1458 |
msgid "Update"
|
1459 |
msgstr "Actualización"
|
1465 |
msgstr "Actualizaciones Disponibles"
|
1466 |
|
1467 |
msgid "AvailableUpdatesInfo"
|
1468 |
+
msgstr "WordPress tiene una acogida muy grande en Internet, esto atrae la atención de personas maliciosas para encontrar vulnerabilidades en el código, al igual que en el código de plugins y plantillas que otras empresas desarrollan. Es recomendable mantener plugins y plantillas actualizadas para prevenir ataques tan pronto como vulnerabilidades sean descubiertas."
|
1469 |
|
1470 |
msgid "WhitelistScript"
|
1471 |
msgstr "Desbloquear Archivos PHP"
|
1472 |
|
1473 |
msgid "WhitelistScriptInfo"
|
1474 |
+
msgstr "Después de aplicar el hardening en los directorios soportados por el plugin, un archivo .htaccess será creado con reglas para bloquear el acceso directo a todos los archivos PHP contenidos en dichos directorios, esta es una buena precaución para evitar la ejecución de código malicioso; con algunas excepciones, el archivo <em>\"index.php\"</em> es el único que debería tener acceso público, sin embargo muchos plugins y plantillas requieren de este acceso también, utilice esta herramienta para desbloquearlos."
|
1475 |
|
1476 |
msgid "Uninstall"
|
1477 |
msgstr "Eliminar Registros de Seguridad, Hardening y Configuraciones"
|
1478 |
|
1479 |
msgid "UninstallInfo"
|
1480 |
+
msgstr "Esta acción iniciará el proceso de desactivación / desinstalación del plugin. Todos los registro de seguridad guardados en el disco local, las reglas de hardening y las configuraciones serán eliminadas. Ten en cuenta que los registros de seguridad guardados en el servidor de Sucuri no serán eliminados, esto es para prevenir que usuarios maliciosos intenten borrar sus huellas después de ejecutar un ataque en contra del sitio web."
|
1481 |
|
1482 |
msgid "ImportExport"
|
1483 |
msgstr "Importar Y Exportar Ajustes"
|
1484 |
|
1485 |
msgid "ImportExportInfo"
|
1486 |
+
msgstr "Copie la información codificada en JSON que aparece en la caja de abajo, pegue esta información en la misma caja en el sitio web donde desea importar esta configuración. Ten en cuenta que algunas opciones serán omitidas, ya que estas contienen información irrelevante para otros sitios. Para importar la configuración de otro sitio web a este, reemplace el contenido de la caja con los datos codificados en JSON de otro sitio, luego presione el botón para continuar. Ten en cuenta que algunas opciones no serán importadas para reducir el riesgo de insertar datos arbitrarios en el disco."
|
1487 |
|
1488 |
msgid "DataStorage"
|
1489 |
msgstr "Almacenamiento de Datos"
|
1490 |
|
1491 |
msgid "DataStorageInfo"
|
1492 |
+
msgstr "Este es el directorio donde el plugin guardará los registros de seguridad, el archivo con las configuraciones, la caché y datos adicionales de otras herramientas. El plugin requiere de permisos de escritura en este directorio, así como en los archivos contenidos allí. Si prefieres mantener estos archivos en un directorio diferente al especificado, por favor define una constante llamada <em>\"SUCURI_DATA_STORAGE\"</em> en el archivo de configuración de WordPress, con la ruta absoluta del nuevo directorio."
|
1493 |
+
|
1494 |
+
msgid "TimezoneTitle"
|
1495 |
+
msgstr "Zona Horaria"
|
1496 |
+
|
1497 |
+
msgid "TimezoneInfo"
|
1498 |
+
msgstr "Esta opción define la zona horaria que será usada a través de todo el plugin para mostrar las fechas y horas cuando sea necesario. Esta opción también afecta la fecha y hora de la información visible en el panel de registros de seguridad que viene de un servidor remoto configurado para usar Horario del este de Norteamérica (EDT por sus siglas en Inglés). WordPress ofrece una opción en la página de ajustes generales que te permite configurar la zona horaria para todo el sitio web, sin embargo, si estás experimentando problemas con la hora en los registros de seguridad, esta opción te ayudará a solucionarlos."
|
1499 |
+
|
1500 |
+
msgid "TimezoneStatus"
|
1501 |
+
msgstr "La zona horaria para la fecha y hora en los registros de seguridad ha sido cambiada"
|
1502 |
|
1503 |
+
msgid "ChecksumsAPI"
|
1504 |
+
msgstr "WordPress Checksums API"
|
1505 |
|
1506 |
+
msgid "ChecksumsAPIInfo"
|
1507 |
+
msgstr "La herramienta que verifica la integridad de la instalación usa un servicio remoto mantenido por WordPress.org para determinar qué archivos fueron agregados, eliminados o modificados. La API devuelve una lista de archivos con sus respectivos checksums, esta información garantiza que la instalación no está corrupta. Tu puedes, sin embargo, apuntar el plugin a un repositorio en GitHub en caso de que estés usando una versión personalizada de WordPress como la <a href=\"https://github.com/WordPress/WordPress\" target=\"_blank\">versión alpha del código</a>."
|
1508 |
|
1509 |
+
msgid "ChecksumsAPIChanged"
|
1510 |
+
msgstr "La dirección web para obtener los checksums de WordPress ha sido cambiada"
|
1511 |
|
1512 |
+
msgid "MaxExecutionTimeAlert"
|
1513 |
+
msgstr "El servidor no pudo procesar esta acción rápido; tiempo máximo de ejecución alcanzado"
|
readme.txt
CHANGED
@@ -3,160 +3,114 @@ Contributors: dd@sucuri.net
|
|
3 |
Donate Link: https://sucuri.net/
|
4 |
Tags: malware, security, firewall, scan, spam, virus, sucuri, protection, WordPress Security, Login Security, Security Auditing, File Integrity, htaccess, phishing, backdoors, SQL Injection, RFI, LFI, XSS, CSRF, website firewall, Website Security, Performance Optimization, Zero Day, Software Vulnerability, Exploits, Hacks, Attackers, Bad Actors, Reverse Proxy, Two Factor Security, Two Factor Authentication, Security Logs, HeatBleed Vulnerability, Website Protection, Bash Vulnerability, RevSlider Vulnerability, MailPoet Vulnerability, Malware Prevention, Website Security, Website Firewall, Website AntiVirus, Security Response, Security Detection, Security Prevention
|
5 |
Requires at least: 3.6
|
6 |
-
Stable tag: 1.8.7
|
7 |
Tested up to: 4.8.0
|
|
|
8 |
|
9 |
The Sucuri WordPress Security plugin is a security toolset for security integrity monitoring, malware detection and security hardening.
|
10 |
|
11 |
-
|
12 |
== Description ==
|
13 |
|
14 |
Sucuri Inc. is a globally recognized authority in all matters related to website security, with specialization in WordPress Security.
|
15 |
|
16 |
The Sucuri Security WordPress plugin is free to all WordPress users. It is a security suite meant to complement your existing security posture. It offers its users a set of security features for their website, each designed to have a positive affect on their security posture:
|
17 |
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
<li>Website Firewall (add on)</li>
|
27 |
-
</ol>
|
28 |
-
|
29 |
|
30 |
-
|
31 |
|
32 |
-
|
33 |
|
34 |
-
|
35 |
|
36 |
-
|
|
|
|
|
|
|
|
|
|
|
37 |
|
38 |
-
|
39 |
|
40 |
-
|
41 |
|
|
|
42 |
|
43 |
-
=
|
44 |
|
45 |
-
|
46 |
|
47 |
-
|
48 |
|
49 |
-
|
50 |
|
|
|
51 |
|
52 |
-
=
|
53 |
|
54 |
-
|
55 |
|
56 |
-
|
57 |
|
58 |
-
|
59 |
|
|
|
60 |
|
61 |
-
=
|
62 |
|
63 |
Another very interesting feature of the Security Malware Scanner is that it incorporates various blacklist engines. Security blacklist engines include the following:
|
64 |
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
<li>Bitdefender</li>
|
76 |
-
</ol>
|
77 |
|
78 |
These are some of the largest blacklisting entities, each having the ability to directly impact your brands online reputation. By synchronize with their environments we’re able to tell you, upon scan, whether any of them are negatively flagging your website with a security related issue. If they do, then via our website security product, we’re able to help you get off the their security blacklist.
|
79 |
|
80 |
-
|
81 |
-
= Effective Security Hardening =
|
82 |
|
83 |
It’s easy to get lost in the world of security hardening. At Sucuri we clean hundreds of websites a day, many with the various security hardening configurations you find in various WordPress Security presentations. In this section, we add those that we feel to be most effective, and that complement the entire Sucuri suite of products.
|
84 |
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
= Post-Hack Security Actions =
|
89 |
|
90 |
Regardless of how good your security posture is, sometimes it’s impossible to prevent the inevitable. When this happens, we’ve included a section to help you walk through the three key things you should do after a compromise.
|
91 |
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
= Security Notifications =
|
96 |
|
97 |
Having all these security features would be useless unless you were notified of the issues. This is why we have made available security alerts. We have also expanded the various security related events, to provide website owners more flexibility in regards to what they want to know about. As a website owner, you have the option to make these security alerts as quiet or noisy as you would like.
|
98 |
|
99 |
-
|
100 |
-
= Sucuri Firewall (Add On Security Service) =
|
101 |
|
102 |
This is by far the coolest security feature Sucuri has to offer everyday website owners. It’s an enterprise grade Website Firewall designed to give you the best security protection any website can hope for. It protects your website from a variety of website attacks and security events to include:
|
103 |
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
<li>Brute Force Attacks against your Access Control Mechanisms</li>
|
109 |
-
</ol>
|
110 |
|
111 |
This is coupled with a number of features like:
|
112 |
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
<li>Failover and Redundancy</li>
|
117 |
-
</ol>
|
118 |
|
119 |
-
This is
|
120 |
-
|
121 |
-
[youtube https://www.youtube.com/watch?v=fN-3DLObLF0]
|
122 |
|
123 |
The Sucuri Security WordPress Security plugin is built by the team that is known for their proactive approach to security. It is built using intelligence gathered from thousands upon thousands of remediation cases, millions of unique domain scans and 10’s of millions of website security attack blocks.
|
124 |
|
125 |
-
|
126 |
-
== Installation ==
|
127 |
-
|
128 |
-
The installation of the Sucuri Security WordPress Security plugin is very simple and straight forward. <a href="https://sucuri.net/wordpress-security-plugin-installation" target="_blank">A detailed breakdown of the process is available, including images,</a> below however we outline the bare minimum steps.
|
129 |
-
|
130 |
-
[youtube https://www.youtube.com/watch?v=KC3UC_Y27G0]
|
131 |
-
|
132 |
-
To install Sucuri Security and complement your Security posture:
|
133 |
-
|
134 |
-
1. You will want to log into your WordPress administration panel - (e.g., https://example.com/wp-admin/),
|
135 |
-
2. Navigate to <strong>Plugins Menu</strong> option in your WordPress administration panel,
|
136 |
-
3. Select <strong>Add New</strong>,
|
137 |
-
4. Type <strong>Sucuri</strong> in the <strong>Search</strong> box, and click
|
138 |
-
<strong>Search</strong> plugins,
|
139 |
-
5. The first option you get should be for <strong>Sucuri Security - Auditing,
|
140 |
-
Malware Scanner and Hardening</strong>,
|
141 |
-
6. Select <strong>Install Now</strong>,
|
142 |
-
7. Now choose to <strong>Activate</strong> the plugin,
|
143 |
-
8. Once activated, you will need to create an API key, this is done automatically for you. Simply click on <strong>Generate API Key for [...]</strong>,
|
144 |
-
9. Once the API key is generated the page will redirect you to your dashboard and the plugin is automatically configured for you.
|
145 |
-
|
146 |
-
To configure the Sucuri WordPress Security plugin for your specific Security needs:
|
147 |
-
|
148 |
-
1. Navigate to the <strong>Sucuri Security</strong> menu option (left hand side),
|
149 |
-
2. Hover or click on the name,
|
150 |
-
3. Click on <strong>Settings</strong>.
|
151 |
-
|
152 |
-
The <strong>Settings</strong> page allows you to configure the website to your preferred security needs. Some of it’s features include changing the email alerts, via the <strong>alert settings</strong> tab or disabling integrity checking. We encourage you to visit this section and tune your security needs as you see fit.
|
153 |
-
|
154 |
-
|
155 |
-
== Frequently Asked Questions ==
|
156 |
-
|
157 |
-
More information can be found on the the Sucuri Security WordPress Security plugin via our free [Knowledge Base](https://kb.sucuri.net/plugins/WordPress+Plugin).
|
158 |
-
|
159 |
-
= What does this plugin do that other WordPress security plugins don't do? =
|
160 |
|
161 |
A few other security plugins provide activity monitoring features, but few do them well. The activity monitoring in this plugin is second to none, tying the activity into the Sucuri Security Operations Center (SOC) ensuring it's safe keeping.
|
162 |
|
@@ -176,27 +130,27 @@ Yes. This plugin compliments your existing security toolsets. It is not designed
|
|
176 |
|
177 |
= Where do I get support for this plugin? =
|
178 |
|
179 |
-
The best place is to engage us via the
|
180 |
|
181 |
= Does your plugin conflict with WordFence? =
|
182 |
|
183 |
The plugin does not, but there might be issues with our scanners. If you get an “Unable to Properly Scan Your Site” It’s likely because the WordFence plugin is blocking our scanner as an invalid crawler. You would have to white list our IP address on the WordFence dashboard.
|
184 |
|
185 |
-
= What are the Remote
|
186 |
|
187 |
Because the security malware scanner is remote, it is unable to see things that are on the server but that are not displaying on the browser. If you are interested in this, we encourage you to subscribe to our website security product. This issues includes things like Phishing pages, Backdoors, Mailer Scripts, etc.
|
188 |
|
189 |
= Your plugin didn’t detect this malware? =
|
190 |
|
191 |
-
This happens, reference the remote scanner limitations above. This should not be confused with our website security product. If you have malware, and you are a client, submit a ticket so that
|
192 |
|
193 |
-
If you are not a client, and you want to share what you have found please send it to
|
194 |
|
195 |
The plugin is not performing application level malware / security scanning so this is not uncommon.
|
196 |
|
197 |
= Is it free to enable the Website Firewall option? =
|
198 |
|
199 |
-
No, it is not. To enable you must subscribe to the
|
200 |
|
201 |
= Will this plugin impact the performance of my website? =
|
202 |
|
@@ -210,17 +164,55 @@ No, it does not.
|
|
210 |
|
211 |
Not that we are aware of.
|
212 |
|
213 |
-
= Do I need
|
214 |
|
215 |
No, it is not required. The Website Firewall runs in the cloud without the need of anything installed. This plugin only helps see and manage the service from the WordPress dashboard.
|
216 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
217 |
== Upgrade Notice ==
|
218 |
|
219 |
-
= 1.8.
|
220 |
This version adds support for the latest version of WordPress. Introduces new features and fixes some bugs reported by the WordPress community as well as bugs found by our automated testing system.
|
221 |
|
222 |
== Changelog ==
|
223 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
224 |
= 1.8.7 =
|
225 |
* Fix multiple issues with the API calls
|
226 |
* Add queue system to fix website performance
|
@@ -585,8 +577,3 @@ This version adds support for the latest version of WordPress. Introduces new fe
|
|
585 |
|
586 |
= 1.1.1 =
|
587 |
* First public release.
|
588 |
-
|
589 |
-
|
590 |
-
== Credits ==
|
591 |
-
|
592 |
-
* <a href="https://sucuri.net/" target="_blank">Sucuri Inc.</a>
|
3 |
Donate Link: https://sucuri.net/
|
4 |
Tags: malware, security, firewall, scan, spam, virus, sucuri, protection, WordPress Security, Login Security, Security Auditing, File Integrity, htaccess, phishing, backdoors, SQL Injection, RFI, LFI, XSS, CSRF, website firewall, Website Security, Performance Optimization, Zero Day, Software Vulnerability, Exploits, Hacks, Attackers, Bad Actors, Reverse Proxy, Two Factor Security, Two Factor Authentication, Security Logs, HeatBleed Vulnerability, Website Protection, Bash Vulnerability, RevSlider Vulnerability, MailPoet Vulnerability, Malware Prevention, Website Security, Website Firewall, Website AntiVirus, Security Response, Security Detection, Security Prevention
|
5 |
Requires at least: 3.6
|
|
|
6 |
Tested up to: 4.8.0
|
7 |
+
Stable tag: 1.8.8
|
8 |
|
9 |
The Sucuri WordPress Security plugin is a security toolset for security integrity monitoring, malware detection and security hardening.
|
10 |
|
|
|
11 |
== Description ==
|
12 |
|
13 |
Sucuri Inc. is a globally recognized authority in all matters related to website security, with specialization in WordPress Security.
|
14 |
|
15 |
The Sucuri Security WordPress plugin is free to all WordPress users. It is a security suite meant to complement your existing security posture. It offers its users a set of security features for their website, each designed to have a positive affect on their security posture:
|
16 |
|
17 |
+
* Security Activity Auditing
|
18 |
+
* File Integrity Monitoring
|
19 |
+
* Remote Malware Scanning
|
20 |
+
* Blacklist Monitoring
|
21 |
+
* Effective Security Hardening
|
22 |
+
* Post-Hack Security Actions
|
23 |
+
* Security Notifications
|
24 |
+
* Website Firewall (premium)
|
|
|
|
|
|
|
25 |
|
26 |
+
== Installation ==
|
27 |
|
28 |
+
The installation of the Sucuri Security WordPress Security plugin is very simple and straight forward. A detailed breakdown of the process is available [here](https://sucuri.net/wordpress-security-plugin-installation) (including images), however, below we outline the bare minimum steps.
|
29 |
|
30 |
+
To install Sucuri Security and complement your Security posture:
|
31 |
|
32 |
+
1. Log into your WordPress administration panel,
|
33 |
+
2. In the sidebar, choose "Plugins" and then "Add New",
|
34 |
+
3. Type "sucuri" or "sucuri-scanner" in the search box,
|
35 |
+
4. Install the option with the "By Sucuri Inc." at the foot,
|
36 |
+
5. Once activated, you will find a new icon in the sidebar with the Sucuri logo, go to the plugin's dashboard and click the button that says "Generate API Key" to activate the event monitoring, this will generate an unique key to authenticate your website against the remote Sucuri WordPress API service,
|
37 |
+
6. Feel free to visit the plugin' settings page to configure other options including the security alerts, hardening options, file system scanner paths, API service communication, among other things.
|
38 |
|
39 |
+
Visit the [Support Forum](https://wordpress.org/support/plugin/sucuri-scanner) to ask questions, suggest new features, or report bugs. And recommend the plugin to your friends and colleagues if you think it can help other people.
|
40 |
|
41 |
+
== Frequently Asked Questions ==
|
42 |
|
43 |
+
More information can be found on the the Sucuri Security WordPress Security plugin via our free [Knowledge Base](https://kb.sucuri.net/plugins/WordPress+Plugin).
|
44 |
|
45 |
+
= What is the security activity auditing? =
|
46 |
|
47 |
+
This is perhaps the most underutilized security function. It’s the act of monitoring all security related events within your WordPress install. The challenge is, what makes up a security event. In the eyes of Sucuri, any change that occurs within the application could be categorized as a security event, as such we try to record it.
|
48 |
|
49 |
+
This is important because it gives you, the website owner, the ability to keep a good eye on the various changes occurring within your environment. Who is logging in? What changes are being made?
|
50 |
|
51 |
+
This feature is logging all activity to the Sucuri cloud, for safe keeping. This ensures that an attacker is not able to wipe your forensic data and prevent further security analysis after a compromise. If an attacker is able to bypass your security controls, your security logs will be kept safe within the Sucuri Security Operations Center (SOC).
|
52 |
|
53 |
+
This feature is particularly important to website / system administrators and security experts looking to understand what is going on with their website and when it’s happening.
|
54 |
|
55 |
+
= What is the file integrity monitoring =
|
56 |
|
57 |
+
Security File Integrity Monitoring has been fundamental to the world of security. It’s the act of comparing a known good with the current state. If the current state differs from the known good, you know you have a problem. This is the basis of a lot of host intrusion detection systems. It’s what we have built into the plugin.
|
58 |
|
59 |
+
It will create a known good the minute the plugin is installed. This will be of all the directories at the root of the install, this includes plugins, themes and core files.
|
60 |
|
61 |
+
= What is the remote malware scanning? =
|
62 |
|
63 |
+
This feature is powered by our scanning engine, found on our free security scanner - [SiteCheck](https://sitecheck.sucuri.net/). It’s important to take some time to [understand how this scanner works](https://blog.sucuri.net/2012/10/ask-sucuri-how-does-sitecheck-work.html). There are limitations with the way this scanner works, you can find more information in the FAQ section.
|
64 |
|
65 |
+
= What is the blacklist monitoring? =
|
66 |
|
67 |
Another very interesting feature of the Security Malware Scanner is that it incorporates various blacklist engines. Security blacklist engines include the following:
|
68 |
|
69 |
+
* Sucuri Labs
|
70 |
+
* Google Safe Browsing
|
71 |
+
* Norton
|
72 |
+
* AVG
|
73 |
+
* Phish Tank
|
74 |
+
* ESET
|
75 |
+
* McAfee Site Advisor
|
76 |
+
* Yandex
|
77 |
+
* SpamHaus
|
78 |
+
* Bitdefender
|
|
|
|
|
79 |
|
80 |
These are some of the largest blacklisting entities, each having the ability to directly impact your brands online reputation. By synchronize with their environments we’re able to tell you, upon scan, whether any of them are negatively flagging your website with a security related issue. If they do, then via our website security product, we’re able to help you get off the their security blacklist.
|
81 |
|
82 |
+
= What is the effective security hardening =
|
|
|
83 |
|
84 |
It’s easy to get lost in the world of security hardening. At Sucuri we clean hundreds of websites a day, many with the various security hardening configurations you find in various WordPress Security presentations. In this section, we add those that we feel to be most effective, and that complement the entire Sucuri suite of products.
|
85 |
|
86 |
+
= What are the post-hack security actions =
|
|
|
|
|
|
|
87 |
|
88 |
Regardless of how good your security posture is, sometimes it’s impossible to prevent the inevitable. When this happens, we’ve included a section to help you walk through the three key things you should do after a compromise.
|
89 |
|
90 |
+
= What are the security notifications =
|
|
|
|
|
|
|
91 |
|
92 |
Having all these security features would be useless unless you were notified of the issues. This is why we have made available security alerts. We have also expanded the various security related events, to provide website owners more flexibility in regards to what they want to know about. As a website owner, you have the option to make these security alerts as quiet or noisy as you would like.
|
93 |
|
94 |
+
= What is the website firewall (premium) =
|
|
|
95 |
|
96 |
This is by far the coolest security feature Sucuri has to offer everyday website owners. It’s an enterprise grade Website Firewall designed to give you the best security protection any website can hope for. It protects your website from a variety of website attacks and security events to include:
|
97 |
|
98 |
+
* Denial of Service (DOS / DDOS) Attacks
|
99 |
+
* Exploitation of Software Vulnerabilities
|
100 |
+
* Zero Day Disclosure Patches
|
101 |
+
* Brute Force Attacks against your Access Control Mechanisms
|
|
|
|
|
102 |
|
103 |
This is coupled with a number of features like:
|
104 |
|
105 |
+
* Performance Optimization
|
106 |
+
* Advanced Access Control Features
|
107 |
+
* Failover and Redundancy
|
|
|
|
|
108 |
|
109 |
+
This is **not included as a free** option to the plugin, but is integrated so that if purchased you are able to activate. If you prefer to leverage the Sucuri Firewall product by itself, you have the option to operate the [Website Firewall WordPress Security](https://wordpress.org/plugins/sucuri-cloudproxy-waf/) plugin in standalone mode.
|
|
|
|
|
110 |
|
111 |
The Sucuri Security WordPress Security plugin is built by the team that is known for their proactive approach to security. It is built using intelligence gathered from thousands upon thousands of remediation cases, millions of unique domain scans and 10’s of millions of website security attack blocks.
|
112 |
|
113 |
+
= What does this plugin do that other security plugins don't do? =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
114 |
|
115 |
A few other security plugins provide activity monitoring features, but few do them well. The activity monitoring in this plugin is second to none, tying the activity into the Sucuri Security Operations Center (SOC) ensuring it's safe keeping.
|
116 |
|
130 |
|
131 |
= Where do I get support for this plugin? =
|
132 |
|
133 |
+
The best place is to engage us via the [Support Forum](https://wordpress.org/support/plugin/sucuri-scanner). If you are a client, you can submit a ticket [here](https://support.sucuri.net/support/?new).
|
134 |
|
135 |
= Does your plugin conflict with WordFence? =
|
136 |
|
137 |
The plugin does not, but there might be issues with our scanners. If you get an “Unable to Properly Scan Your Site” It’s likely because the WordFence plugin is blocking our scanner as an invalid crawler. You would have to white list our IP address on the WordFence dashboard.
|
138 |
|
139 |
+
= What are the Remote Malware Scanner limitations? =
|
140 |
|
141 |
Because the security malware scanner is remote, it is unable to see things that are on the server but that are not displaying on the browser. If you are interested in this, we encourage you to subscribe to our website security product. This issues includes things like Phishing pages, Backdoors, Mailer Scripts, etc.
|
142 |
|
143 |
= Your plugin didn’t detect this malware? =
|
144 |
|
145 |
+
This happens, reference the remote scanner limitations above. This should not be confused with our website security product. If you have malware, and you are a client, submit a ticket so that [we can help you get clean](https://support.sucuri.net/support/?new&mremoval).
|
146 |
|
147 |
+
If you are not a client, and you want to share what you have found please send it to [labs@sucuri.net](mailto:labs@sucuri.net).
|
148 |
|
149 |
The plugin is not performing application level malware / security scanning so this is not uncommon.
|
150 |
|
151 |
= Is it free to enable the Website Firewall option? =
|
152 |
|
153 |
+
No, it is not. To enable you must subscribe to the [Website Firewall](https://sucuri.net/website-firewall-signup) service.
|
154 |
|
155 |
= Will this plugin impact the performance of my website? =
|
156 |
|
164 |
|
165 |
Not that we are aware of.
|
166 |
|
167 |
+
= Do I need this plugin to use the Website Firewall service? =
|
168 |
|
169 |
No, it is not required. The Website Firewall runs in the cloud without the need of anything installed. This plugin only helps see and manage the service from the WordPress dashboard.
|
170 |
|
171 |
+
== Screenshots ==
|
172 |
+
|
173 |
+
1. WordPress Integrity Tool - Detects added, modified, and removed files.
|
174 |
+
2. Integrity Diff Utility - Shows differences in the core WordPress files.
|
175 |
+
3. Audit Logs and Malware Scanner - Reports suspicious events and malicious code.
|
176 |
+
4. Sucuri Firewall - Settings visibility, audit logs, IP blacklisting, and cache.
|
177 |
+
5. Website Hardening - Offers multiple options to increase the security of the website.
|
178 |
+
6. Failed Logins - Shows failed login attempts, successful logins and online users.
|
179 |
+
7. Post Hack Tools - Offers multiple tools to react after the suspiciousness of a hack.
|
180 |
+
8. Settings - Offers multiple settings to configure the functionality of the plugin.
|
181 |
+
|
182 |
== Upgrade Notice ==
|
183 |
|
184 |
+
= 1.8.8 =
|
185 |
This version adds support for the latest version of WordPress. Introduces new features and fixes some bugs reported by the WordPress community as well as bugs found by our automated testing system.
|
186 |
|
187 |
== Changelog ==
|
188 |
|
189 |
+
= 1.8.8 =
|
190 |
+
* Add smart limit to send logs from the queue to the API
|
191 |
+
* Add option to ignore events for post transitions
|
192 |
+
* Fix infinite loop with email alerts and SMTP plugin
|
193 |
+
* Add option to configure the malware scanner target URL
|
194 |
+
* Add option to enable the auto clear cache firewall function
|
195 |
+
* Modify status of the directory hardening using the Firewall
|
196 |
+
* Modify error message in audit logs when the API key is missing
|
197 |
+
* Modify timing for the dashboard alerts after an update
|
198 |
+
* Modify firewall clear cache button to execute via Ajax
|
199 |
+
* Modify firewall settings page to load data via Ajax
|
200 |
+
* Add option to blacklist IP addresses with the Firewall API
|
201 |
+
* Fix order of the audit logs when the queue is merged
|
202 |
+
* Add more directories to ignore during the scans
|
203 |
+
* Add option to customize the URL for the malware scans
|
204 |
+
* Fix error interception for Firewall API errors
|
205 |
+
* Add support for other English and Spanish based languages
|
206 |
+
* Modify mechanism to ignore files from integrity checks
|
207 |
+
* Add option to stop sending the failed login passwords
|
208 |
+
* Modify default value for some of the alert settings
|
209 |
+
* Remove unnecessary statistics panel for the audit logs
|
210 |
+
* Modify output for the malware results to simplify links
|
211 |
+
* Add option to override the timezone for the datetime
|
212 |
+
* Add option to configure the WordPress checksums API
|
213 |
+
* Add maximum execution time avoidance in the integrity tool
|
214 |
+
* Add support to run diff on deleted WordPress files
|
215 |
+
|
216 |
= 1.8.7 =
|
217 |
* Fix multiple issues with the API calls
|
218 |
* Add queue system to fix website performance
|
577 |
|
578 |
= 1.1.1 =
|
579 |
* First public release.
|
|
|
|
|
|
|
|
|
|
src/api.lib.php
CHANGED
@@ -82,7 +82,7 @@ class SucuriScanAPI extends SucuriScanOption
|
|
82 |
return self::throwException('Only GET and POST methods allowed');
|
83 |
}
|
84 |
|
85 |
-
$
|
86 |
$timeout = SUCURISCAN_MAX_REQUEST_TIMEOUT;
|
87 |
$args = is_array($args) ? $args : array();
|
88 |
|
@@ -98,6 +98,22 @@ class SucuriScanAPI extends SucuriScanOption
|
|
98 |
$args['blocking'] = true;
|
99 |
$args['sslverify'] = true;
|
100 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
101 |
if (!array_key_exists('time', $params)) {
|
102 |
$params['time'] = time();
|
103 |
}
|
@@ -106,25 +122,30 @@ class SucuriScanAPI extends SucuriScanOption
|
|
106 |
if ($method === 'GET') {
|
107 |
$args['body'] = null;
|
108 |
$url .= '?' . self::buildQuery($params);
|
109 |
-
$
|
110 |
}
|
111 |
|
112 |
/* support HTTP POST requests */
|
113 |
if ($method === 'POST') {
|
|
|
|
|
|
|
|
|
|
|
114 |
$args['body'] = $params;
|
115 |
-
$
|
116 |
}
|
117 |
|
118 |
-
if (is_wp_error($
|
119 |
-
return self::throwException($
|
120 |
}
|
121 |
|
122 |
/* try to return a JSON-encode object */
|
123 |
-
if ($data = @json_decode($
|
124 |
return $data; /* associative array */
|
125 |
}
|
126 |
|
127 |
-
return $
|
128 |
}
|
129 |
|
130 |
/**
|
@@ -185,7 +206,6 @@ class SucuriScanAPI extends SucuriScanOption
|
|
185 |
*/
|
186 |
public static function apiCallWordpress($method = 'GET', $params = array(), $send_api_key = true, $args = array())
|
187 |
{
|
188 |
-
$url = SUCURISCAN_API_URL;
|
189 |
$params[SUCURISCAN_API_VERSION] = 1;
|
190 |
$params['p'] = 'wordpress';
|
191 |
|
@@ -199,7 +219,7 @@ class SucuriScanAPI extends SucuriScanOption
|
|
199 |
$params['k'] = $api_key;
|
200 |
}
|
201 |
|
202 |
-
return self::apiCall(
|
203 |
}
|
204 |
|
205 |
/**
|
@@ -233,34 +253,34 @@ class SucuriScanAPI extends SucuriScanOption
|
|
233 |
* verification, this option it disable automatically when the error is detected
|
234 |
* for the first time.
|
235 |
*
|
236 |
-
* @param array $
|
237 |
* @return bool False if the API call failed, true otherwise.
|
238 |
*/
|
239 |
-
public static function handleResponse($
|
240 |
{
|
241 |
-
if (!$
|
242 |
return false;
|
243 |
}
|
244 |
|
245 |
-
if (is_array($
|
246 |
-
&& array_key_exists('status', $
|
247 |
-
&& intval($
|
248 |
) {
|
249 |
return true;
|
250 |
}
|
251 |
|
252 |
-
if (is_string($
|
253 |
-
return SucuriScanInterface::error($
|
254 |
}
|
255 |
|
256 |
-
if (!is_array($
|
257 |
-
|| !isset($
|
258 |
-
|| empty($
|
259 |
) {
|
260 |
return SucuriScanInterface::error(__('ErrorNoInfo', SUCURISCAN_TEXTDOMAIN));
|
261 |
}
|
262 |
|
263 |
-
$msg = implode(".\x20", $
|
264 |
$raw = $msg; /* Keep a copy of the original message. */
|
265 |
|
266 |
// Special response for invalid API keys.
|
@@ -313,14 +333,14 @@ class SucuriScanAPI extends SucuriScanOption
|
|
313 |
$email = self::getSiteEmail();
|
314 |
}
|
315 |
|
316 |
-
$
|
317 |
'e' => $email,
|
318 |
's' => self::getDomain(),
|
319 |
'a' => 'register_site',
|
320 |
), false);
|
321 |
|
322 |
-
if (self::handleResponse($
|
323 |
-
self::setPluginKey($
|
324 |
|
325 |
SucuriScanEvent::installScheduledTask();
|
326 |
SucuriScanEvent::notifyEvent('plugin_change', 'API key was generated and set');
|
@@ -339,15 +359,15 @@ class SucuriScanAPI extends SucuriScanOption
|
|
339 |
{
|
340 |
$domain = self::getDomain();
|
341 |
|
342 |
-
$
|
343 |
'e' => self::getSiteEmail(),
|
344 |
's' => $domain,
|
345 |
'a' => 'recover_key',
|
346 |
), false);
|
347 |
|
348 |
-
if (self::handleResponse($
|
349 |
SucuriScanEvent::notifyEvent('plugin_change', 'API key recovery for domain: ' . $domain);
|
350 |
-
return SucuriScanInterface::info($
|
351 |
}
|
352 |
|
353 |
return false;
|
@@ -361,16 +381,16 @@ class SucuriScanAPI extends SucuriScanOption
|
|
361 |
*/
|
362 |
public static function getAuditLogs($lines = 50)
|
363 |
{
|
364 |
-
$
|
365 |
'a' => 'get_logs',
|
366 |
'l' => $lines,
|
367 |
));
|
368 |
|
369 |
-
if (!self::handleResponse($
|
370 |
return false;
|
371 |
}
|
372 |
|
373 |
-
return self::parseAuditLogs($
|
374 |
}
|
375 |
|
376 |
/**
|
@@ -391,7 +411,7 @@ class SucuriScanAPI extends SucuriScanOption
|
|
391 |
$time = substr($micro, 0, $offset);
|
392 |
$auditlogs[] = sprintf(
|
393 |
'%s %s : %s',
|
394 |
-
|
395 |
SucuriScan::getSiteEmail(),
|
396 |
$message
|
397 |
);
|
@@ -411,15 +431,18 @@ class SucuriScanAPI extends SucuriScanOption
|
|
411 |
/**
|
412 |
* Reads, parses and extracts relevant data from the security logs.
|
413 |
*
|
414 |
-
* @param array $
|
415 |
* @return array Full data extracted from the logs.
|
416 |
*/
|
417 |
-
private static function parseAuditLogs($
|
418 |
{
|
419 |
-
|
420 |
-
|
|
|
421 |
|
422 |
-
|
|
|
|
|
423 |
/* YYYY-MM-dd HH:ii:ss EMAIL : MESSAGE: (multiple entries): a,b,c */
|
424 |
if (strpos($log, "\x20:\x20") === false) {
|
425 |
continue; /* ignore; invalid format */
|
@@ -449,9 +472,9 @@ class SucuriScanAPI extends SucuriScanOption
|
|
449 |
/* extract and fix the date and time using the Eastern time zone */
|
450 |
$datetime = sprintf('%s %s EDT', $dateAndEmail[0], $dateAndEmail[1]);
|
451 |
$log_data['timestamp'] = strtotime($datetime);
|
452 |
-
$log_data['datetime'] =
|
453 |
-
$log_data['date'] =
|
454 |
-
$log_data['time'] =
|
455 |
|
456 |
/* extract more information from the generic audit logs */
|
457 |
$log_data['message'] = str_replace('<br>', ";\x20", $log_data['message']);
|
@@ -526,11 +549,11 @@ class SucuriScanAPI extends SucuriScanOption
|
|
526 |
}
|
527 |
|
528 |
if ($log_data = self::getLogsHotfix($log_data)) {
|
529 |
-
$
|
530 |
}
|
531 |
}
|
532 |
|
533 |
-
return $
|
534 |
}
|
535 |
|
536 |
/**
|
@@ -591,15 +614,14 @@ class SucuriScanAPI extends SucuriScanOption
|
|
591 |
* Parse the event logs with multiple entries.
|
592 |
*
|
593 |
* @param string $event_log Event log that will be processed.
|
594 |
-
* @return array List of parts of the event log.
|
595 |
*/
|
596 |
public static function parseMultipleEntries($event_log = '')
|
597 |
{
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
$event_log = array_merge($event_log, $grouped_items);
|
603 |
}
|
604 |
|
605 |
return $event_log;
|
@@ -704,12 +726,12 @@ class SucuriScanAPI extends SucuriScanOption
|
|
704 |
return false;
|
705 |
}
|
706 |
|
707 |
-
$
|
708 |
'a' => 'send_hashes',
|
709 |
'h' => $hashes,
|
710 |
));
|
711 |
|
712 |
-
return self::handleResponse($
|
713 |
}
|
714 |
|
715 |
/**
|
@@ -721,9 +743,9 @@ class SucuriScanAPI extends SucuriScanOption
|
|
721 |
{
|
722 |
$new_keys = array();
|
723 |
$pattern = self::secretKeyPattern();
|
724 |
-
$
|
725 |
|
726 |
-
if ($
|
727 |
foreach ($match[1] as $key => $value) {
|
728 |
$new_keys[$value] = $match[3][$key];
|
729 |
}
|
@@ -733,30 +755,123 @@ class SucuriScanAPI extends SucuriScanOption
|
|
733 |
}
|
734 |
|
735 |
/**
|
736 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
737 |
*
|
738 |
* @see Release Archive https://wordpress.org/download/release-archive/
|
|
|
739 |
*
|
740 |
-
* @
|
741 |
-
* @return array|bool Associative object with the relative filepath and the checksums of the project files.
|
742 |
*/
|
743 |
-
public static function getOfficialChecksums(
|
744 |
{
|
745 |
$result = false;
|
746 |
-
$
|
747 |
-
$
|
748 |
-
|
749 |
-
|
750 |
-
|
751 |
-
|
752 |
-
|
753 |
-
)
|
754 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
755 |
|
756 |
-
if (is_array($
|
757 |
-
$result = isset($
|
758 |
-
? $
|
759 |
-
: $
|
760 |
}
|
761 |
|
762 |
return $result;
|
@@ -859,11 +974,8 @@ class SucuriScanAPI extends SucuriScanOption
|
|
859 |
*/
|
860 |
public static function getRemotePluginData($plugin = '')
|
861 |
{
|
862 |
-
$
|
863 |
-
|
864 |
-
$response = ($response === 'null') ? false : $response;
|
865 |
-
|
866 |
-
return $response ? $response : false;
|
867 |
}
|
868 |
|
869 |
/**
|
@@ -875,27 +987,36 @@ class SucuriScanAPI extends SucuriScanOption
|
|
875 |
* @see https://i18n.svn.wordpress.org/
|
876 |
* @see https://core.svn.wordpress.org/tags/VERSION_NUMBER/
|
877 |
*
|
878 |
-
* @param string $
|
879 |
-
* @param string|int $version Optional Wordpress version number.
|
880 |
* @return string|bool Original code for the core file, false otherwise.
|
881 |
*/
|
882 |
-
public static function getOriginalCoreFile($
|
883 |
{
|
884 |
-
|
885 |
-
|
886 |
-
}
|
887 |
|
888 |
-
if ($
|
889 |
-
$
|
|
|
|
|
|
|
890 |
}
|
891 |
|
892 |
-
$url =
|
893 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
894 |
|
895 |
-
if (strpos($
|
|
|
896 |
return self::throwException('WordPress version is not supported anymore');
|
897 |
}
|
898 |
|
899 |
-
return $
|
900 |
}
|
901 |
}
|
82 |
return self::throwException('Only GET and POST methods allowed');
|
83 |
}
|
84 |
|
85 |
+
$res = null;
|
86 |
$timeout = SUCURISCAN_MAX_REQUEST_TIMEOUT;
|
87 |
$args = is_array($args) ? $args : array();
|
88 |
|
98 |
$args['blocking'] = true;
|
99 |
$args['sslverify'] = true;
|
100 |
|
101 |
+
/* separate hardcoded query parameters */
|
102 |
+
if (empty($params) && strpos($url, '?')) {
|
103 |
+
$parts = @parse_url($url);
|
104 |
+
|
105 |
+
if (array_key_exists('query', $parts)) {
|
106 |
+
$portions = explode('&', $parts['query']);
|
107 |
+
$url = str_replace('?' . $parts['query'], '', $url);
|
108 |
+
|
109 |
+
foreach ($portions as $portion) {
|
110 |
+
$bits = explode('=', $portion, 2);
|
111 |
+
$params[$bits[0]] = $bits[1];
|
112 |
+
}
|
113 |
+
}
|
114 |
+
}
|
115 |
+
|
116 |
+
/* include current timestamp for trackability */
|
117 |
if (!array_key_exists('time', $params)) {
|
118 |
$params['time'] = time();
|
119 |
}
|
122 |
if ($method === 'GET') {
|
123 |
$args['body'] = null;
|
124 |
$url .= '?' . self::buildQuery($params);
|
125 |
+
$res = wp_remote_get($url, $args);
|
126 |
}
|
127 |
|
128 |
/* support HTTP POST requests */
|
129 |
if ($method === 'POST') {
|
130 |
+
if (array_key_exists('a', $params)) {
|
131 |
+
/* include action to increase visibility */
|
132 |
+
$url .= '?a=' . $params['a'];
|
133 |
+
}
|
134 |
+
|
135 |
$args['body'] = $params;
|
136 |
+
$res = wp_remote_post($url, $args);
|
137 |
}
|
138 |
|
139 |
+
if (is_wp_error($res)) {
|
140 |
+
return self::throwException($res->get_error_message());
|
141 |
}
|
142 |
|
143 |
/* try to return a JSON-encode object */
|
144 |
+
if ($data = @json_decode($res['body'], true)) {
|
145 |
return $data; /* associative array */
|
146 |
}
|
147 |
|
148 |
+
return $res['body'];
|
149 |
}
|
150 |
|
151 |
/**
|
206 |
*/
|
207 |
public static function apiCallWordpress($method = 'GET', $params = array(), $send_api_key = true, $args = array())
|
208 |
{
|
|
|
209 |
$params[SUCURISCAN_API_VERSION] = 1;
|
210 |
$params['p'] = 'wordpress';
|
211 |
|
219 |
$params['k'] = $api_key;
|
220 |
}
|
221 |
|
222 |
+
return self::apiCall(SUCURISCAN_API_URL, $method, $params, $args);
|
223 |
}
|
224 |
|
225 |
/**
|
253 |
* verification, this option it disable automatically when the error is detected
|
254 |
* for the first time.
|
255 |
*
|
256 |
+
* @param array $res HTTP response after API endpoint execution.
|
257 |
* @return bool False if the API call failed, true otherwise.
|
258 |
*/
|
259 |
+
public static function handleResponse($res = array())
|
260 |
{
|
261 |
+
if (!$res || getenv('SUCURISCAN_NO_API_HANDLE')) {
|
262 |
return false;
|
263 |
}
|
264 |
|
265 |
+
if (is_array($res)
|
266 |
+
&& array_key_exists('status', $res)
|
267 |
+
&& intval($res['status']) === 1
|
268 |
) {
|
269 |
return true;
|
270 |
}
|
271 |
|
272 |
+
if (is_string($res) && !empty($res)) {
|
273 |
+
return SucuriScanInterface::error($res);
|
274 |
}
|
275 |
|
276 |
+
if (!is_array($res)
|
277 |
+
|| !isset($res['messages'])
|
278 |
+
|| empty($res['messages'])
|
279 |
) {
|
280 |
return SucuriScanInterface::error(__('ErrorNoInfo', SUCURISCAN_TEXTDOMAIN));
|
281 |
}
|
282 |
|
283 |
+
$msg = implode(".\x20", $res['messages']);
|
284 |
$raw = $msg; /* Keep a copy of the original message. */
|
285 |
|
286 |
// Special response for invalid API keys.
|
333 |
$email = self::getSiteEmail();
|
334 |
}
|
335 |
|
336 |
+
$res = self::apiCallWordpress('POST', array(
|
337 |
'e' => $email,
|
338 |
's' => self::getDomain(),
|
339 |
'a' => 'register_site',
|
340 |
), false);
|
341 |
|
342 |
+
if (self::handleResponse($res)) {
|
343 |
+
self::setPluginKey($res['output']['api_key']);
|
344 |
|
345 |
SucuriScanEvent::installScheduledTask();
|
346 |
SucuriScanEvent::notifyEvent('plugin_change', 'API key was generated and set');
|
359 |
{
|
360 |
$domain = self::getDomain();
|
361 |
|
362 |
+
$res = self::apiCallWordpress('GET', array(
|
363 |
'e' => self::getSiteEmail(),
|
364 |
's' => $domain,
|
365 |
'a' => 'recover_key',
|
366 |
), false);
|
367 |
|
368 |
+
if (self::handleResponse($res)) {
|
369 |
SucuriScanEvent::notifyEvent('plugin_change', 'API key recovery for domain: ' . $domain);
|
370 |
+
return SucuriScanInterface::info($res['output']['message']);
|
371 |
}
|
372 |
|
373 |
return false;
|
381 |
*/
|
382 |
public static function getAuditLogs($lines = 50)
|
383 |
{
|
384 |
+
$res = self::apiCallWordpress('GET', array(
|
385 |
'a' => 'get_logs',
|
386 |
'l' => $lines,
|
387 |
));
|
388 |
|
389 |
+
if (!self::handleResponse($res)) {
|
390 |
return false;
|
391 |
}
|
392 |
|
393 |
+
return self::parseAuditLogs($res);
|
394 |
}
|
395 |
|
396 |
/**
|
411 |
$time = substr($micro, 0, $offset);
|
412 |
$auditlogs[] = sprintf(
|
413 |
'%s %s : %s',
|
414 |
+
SucuriScan::datetime($time, 'Y-m-d H:i:s'),
|
415 |
SucuriScan::getSiteEmail(),
|
416 |
$message
|
417 |
);
|
431 |
/**
|
432 |
* Reads, parses and extracts relevant data from the security logs.
|
433 |
*
|
434 |
+
* @param array $res JSON-decoded logs.
|
435 |
* @return array Full data extracted from the logs.
|
436 |
*/
|
437 |
+
private static function parseAuditLogs($res)
|
438 |
{
|
439 |
+
if (!is_array($res)) {
|
440 |
+
$res = array();
|
441 |
+
}
|
442 |
|
443 |
+
$res['output_data'] = array();
|
444 |
+
|
445 |
+
foreach ((array) @$res['output'] as $log) {
|
446 |
/* YYYY-MM-dd HH:ii:ss EMAIL : MESSAGE: (multiple entries): a,b,c */
|
447 |
if (strpos($log, "\x20:\x20") === false) {
|
448 |
continue; /* ignore; invalid format */
|
472 |
/* extract and fix the date and time using the Eastern time zone */
|
473 |
$datetime = sprintf('%s %s EDT', $dateAndEmail[0], $dateAndEmail[1]);
|
474 |
$log_data['timestamp'] = strtotime($datetime);
|
475 |
+
$log_data['datetime'] = SucuriScan::datetime($log_data['timestamp'], 'Y-m-d H:i:s');
|
476 |
+
$log_data['date'] = SucuriScan::datetime($log_data['timestamp'], 'Y-m-d');
|
477 |
+
$log_data['time'] = SucuriScan::datetime($log_data['timestamp'], 'H:i:s');
|
478 |
|
479 |
/* extract more information from the generic audit logs */
|
480 |
$log_data['message'] = str_replace('<br>', ";\x20", $log_data['message']);
|
549 |
}
|
550 |
|
551 |
if ($log_data = self::getLogsHotfix($log_data)) {
|
552 |
+
$res['output_data'][] = $log_data;
|
553 |
}
|
554 |
}
|
555 |
|
556 |
+
return $res;
|
557 |
}
|
558 |
|
559 |
/**
|
614 |
* Parse the event logs with multiple entries.
|
615 |
*
|
616 |
* @param string $event_log Event log that will be processed.
|
617 |
+
* @return string|array List of parts of the event log.
|
618 |
*/
|
619 |
public static function parseMultipleEntries($event_log = '')
|
620 |
{
|
621 |
+
$pattern = "\x20(multiple entries):\x20";
|
622 |
+
|
623 |
+
if (strpos($event_log, $pattern)) {
|
624 |
+
return explode(',', str_replace($pattern, ',', $event_log));
|
|
|
625 |
}
|
626 |
|
627 |
return $event_log;
|
726 |
return false;
|
727 |
}
|
728 |
|
729 |
+
$res = self::apiCallWordpress('POST', array(
|
730 |
'a' => 'send_hashes',
|
731 |
'h' => $hashes,
|
732 |
));
|
733 |
|
734 |
+
return self::handleResponse($res);
|
735 |
}
|
736 |
|
737 |
/**
|
743 |
{
|
744 |
$new_keys = array();
|
745 |
$pattern = self::secretKeyPattern();
|
746 |
+
$res = self::apiCall('https://api.wordpress.org/secret-key/1.1/salt/', 'GET');
|
747 |
|
748 |
+
if ($res && @preg_match_all($pattern, $res, $match)) {
|
749 |
foreach ($match[1] as $key => $value) {
|
750 |
$new_keys[$value] = $match[3][$key];
|
751 |
}
|
755 |
}
|
756 |
|
757 |
/**
|
758 |
+
* Returns the URL for the WordPress checksums API service.
|
759 |
+
*
|
760 |
+
* @return string URL for the WordPress checksums API.
|
761 |
+
*/
|
762 |
+
public static function checksumAPI()
|
763 |
+
{
|
764 |
+
$url = 'https://api.wordpress.org/core/checksums/1.0/?version={version}&locale={locale}';
|
765 |
+
|
766 |
+
if ($custom = SucuriScanOption::getOption(':checksum_api')) {
|
767 |
+
$url = sprintf(
|
768 |
+
'https://api.github.com/repos/%s/git/trees/master?recursive=1',
|
769 |
+
$custom /* expect: username/repository */
|
770 |
+
);
|
771 |
+
}
|
772 |
+
|
773 |
+
$url = str_replace('{version}', SucuriScan::siteVersion(), $url);
|
774 |
+
$url = str_replace('{locale}', SucuriScanOption::getOption(':language'), $url);
|
775 |
+
|
776 |
+
return $url;
|
777 |
+
}
|
778 |
+
|
779 |
+
/**
|
780 |
+
* Returns the name of the hash to use in the integrity tool
|
781 |
+
*
|
782 |
+
* By default, the plugin will use MD5 to hash the content of the specified
|
783 |
+
* file, however, if the core integrity tool is using a custom URL, and this
|
784 |
+
* URL is pointing to GitHub API, then we will assume that the checksum that
|
785 |
+
* comes from this service is using SHA1.
|
786 |
+
*
|
787 |
+
* @return string Hash to use in the integrity tool.
|
788 |
+
*/
|
789 |
+
public static function checksumAlgorithm()
|
790 |
+
{
|
791 |
+
return strpos(self::checksumAPI(), '//api.github.com') ? 'sha1' : 'md5';
|
792 |
+
}
|
793 |
+
|
794 |
+
/**
|
795 |
+
* Calculates the md5/sha1 hash of a given file.
|
796 |
+
*
|
797 |
+
* When the user decides to configure the integrity tool to use the checksum
|
798 |
+
* from a GitHub repository the plugin will have to use the SHA1 algorithm
|
799 |
+
* instead of MD5 (which is what WordPress uses in their API). For this, we
|
800 |
+
* will have to calculate the GIT hash object of the file which is basically
|
801 |
+
* the merge of the text "blob" a single white space, the length of the text
|
802 |
+
* a null byte and then the text in itself (content of the file).
|
803 |
+
*
|
804 |
+
* Example:
|
805 |
+
*
|
806 |
+
* - Input: "hello world\n"
|
807 |
+
* - GIT (object): "blob 16\u0000hello world\n"
|
808 |
+
* - GIT (shaobj): "3b18e512dba79e4c8300dd08aeb37f8e728b8dad"
|
809 |
+
*
|
810 |
+
* @see https://git-scm.com/book/en/v2/Git-Internals-Git-Objects#_object_storage
|
811 |
+
*
|
812 |
+
* @param string $algorithm Either md5 or sha1.
|
813 |
+
* @param string $filename Absolute path to the given file.
|
814 |
+
* @return string Hash of the given file.
|
815 |
+
*/
|
816 |
+
public static function checksum($algorithm, $filename)
|
817 |
+
{
|
818 |
+
if ($algorithm === 'sha1') {
|
819 |
+
$content = SucuriScanFileInfo::fileContent($filename);
|
820 |
+
return @sha1("blob\x20" . strlen($content) . "\x00" . $content);
|
821 |
+
}
|
822 |
+
|
823 |
+
return @md5_file($filename);
|
824 |
+
}
|
825 |
+
|
826 |
+
/**
|
827 |
+
* Returns the checksum of all the files of the current WordPress version.
|
828 |
+
*
|
829 |
+
* The webmaster can change this URL using an option form the settings page.
|
830 |
+
* This allows them to control which repository will be used to check the
|
831 |
+
* integrity of the installation.
|
832 |
+
*
|
833 |
+
* For example, projectnami.org offers an option to use Microsoft SQL Server
|
834 |
+
* instead of MySQL has a different set of files and even with the same
|
835 |
+
* filenames many of them have been modified to support the new database
|
836 |
+
* engine, since the checksums are different than the official ones the
|
837 |
+
* number of false positives will increase. This option allows the webmaster
|
838 |
+
* to point the plugin to a different URL where the new checksums for this
|
839 |
+
* project will be retrieved.
|
840 |
+
*
|
841 |
+
* If the custom API is part of GitHub infrastructure, the plugin will try
|
842 |
+
* to build the expected JSON object from the output, if it fails it will
|
843 |
+
* pass the unmodified response to the rest of the code and try to analyze
|
844 |
+
* the integrity of the installation with that information.
|
845 |
*
|
846 |
* @see Release Archive https://wordpress.org/download/release-archive/
|
847 |
+
* @see https://api.github.com/repos/user/repo/git/trees/master?recursive=1
|
848 |
*
|
849 |
+
* @return array|bool Checksums of the WordPress installation.
|
|
|
850 |
*/
|
851 |
+
public static function getOfficialChecksums()
|
852 |
{
|
853 |
$result = false;
|
854 |
+
$url = self::checksumAPI();
|
855 |
+
$version = SucuriScan::siteVersion();
|
856 |
+
$res = self::apiCall($url, 'GET', array());
|
857 |
+
|
858 |
+
if (is_array($res)
|
859 |
+
&& array_key_exists('sha', $res)
|
860 |
+
&& array_key_exists('url', $res)
|
861 |
+
&& array_key_exists('tree', $res)
|
862 |
+
&& strpos($url, '//api.github.com')
|
863 |
+
) {
|
864 |
+
$checksums = array();
|
865 |
+
foreach ($res['tree'] as $meta) {
|
866 |
+
$checksums[$meta['path']] = $meta['sha'];
|
867 |
+
}
|
868 |
+
$res = array('checksums' => array($version => $checksums));
|
869 |
+
}
|
870 |
|
871 |
+
if (is_array($res) && isset($res['checksums'])) {
|
872 |
+
$result = isset($res['checksums'][$version])
|
873 |
+
? $res['checksums'][$version]
|
874 |
+
: $res['checksums'];
|
875 |
}
|
876 |
|
877 |
return $result;
|
974 |
*/
|
975 |
public static function getRemotePluginData($plugin = '')
|
976 |
{
|
977 |
+
$resp = self::apiCall('https://api.wordpress.org/plugins/info/1.0/' . $plugin . '.json', 'GET');
|
978 |
+
return ($resp === 'null') ? false : $resp;
|
|
|
|
|
|
|
979 |
}
|
980 |
|
981 |
/**
|
987 |
* @see https://i18n.svn.wordpress.org/
|
988 |
* @see https://core.svn.wordpress.org/tags/VERSION_NUMBER/
|
989 |
*
|
990 |
+
* @param string $filename Relative path of a core file.
|
|
|
991 |
* @return string|bool Original code for the core file, false otherwise.
|
992 |
*/
|
993 |
+
public static function getOriginalCoreFile($filename)
|
994 |
{
|
995 |
+
$version = self::siteVersion();
|
996 |
+
$url = 'https://core.svn.wordpress.org/tags/{version}/{filename}';
|
|
|
997 |
|
998 |
+
if ($custom = SucuriScanOption::getOption(':checksum_api')) {
|
999 |
+
$url = sprintf(
|
1000 |
+
'https://raw.githubusercontent.com/%s/master/{filename}',
|
1001 |
+
$custom /* expect: username/repository */
|
1002 |
+
);
|
1003 |
}
|
1004 |
|
1005 |
+
$url = str_replace('{version}', $version, $url);
|
1006 |
+
$url = str_replace('{filename}', $filename, $url);
|
1007 |
+
|
1008 |
+
$resp = self::apiCall($url, 'GET');
|
1009 |
+
|
1010 |
+
if (strpos($resp, '404 Not Found') !== false) {
|
1011 |
+
/* not found comes from the official WordPress API */
|
1012 |
+
return self::throwException('WordPress version is not supported anymore');
|
1013 |
+
}
|
1014 |
|
1015 |
+
if (strpos($resp, '400: Invalid request') !== false) {
|
1016 |
+
/* invalid request comes from the unofficial GitHub API */
|
1017 |
return self::throwException('WordPress version is not supported anymore');
|
1018 |
}
|
1019 |
|
1020 |
+
return $resp ? $resp : false;
|
1021 |
}
|
1022 |
}
|
src/auditlogs.lib.php
CHANGED
@@ -97,6 +97,11 @@ class SucuriScanAuditLogs
|
|
97 |
: sprintf('API %s secs', round($duration, 4));
|
98 |
}
|
99 |
|
|
|
|
|
|
|
|
|
|
|
100 |
/* stop everything and report errors */
|
101 |
if (!empty($errors)) {
|
102 |
$response['content'] .= $errors;
|
@@ -112,28 +117,34 @@ class SucuriScanAuditLogs
|
|
112 |
if (!$auditlogs) {
|
113 |
$auditlogs = $queuelogs;
|
114 |
} else {
|
115 |
-
$auditlogs['total_entries']
|
|
|
|
|
116 |
$auditlogs['output'] = array_merge(
|
117 |
$queuelogs['output'],
|
118 |
-
|
119 |
);
|
120 |
$auditlogs['output_data'] = array_merge(
|
121 |
$queuelogs['output_data'],
|
122 |
-
|
123 |
);
|
124 |
}
|
125 |
}
|
126 |
|
127 |
-
if ($auditlogs)
|
|
|
|
|
|
|
|
|
|
|
128 |
$counter_i = 0;
|
129 |
$total_items = 0;
|
130 |
$previousDate = '';
|
131 |
-
$todaysDate =
|
132 |
$iterator_start = ($pageNumber - 1) * $maxPerPage;
|
|
|
133 |
|
134 |
-
|
135 |
-
$total_items = count($auditlogs['output_data']);
|
136 |
-
}
|
137 |
|
138 |
for ($i = $iterator_start; $i < $total_items; $i++) {
|
139 |
if ($counter_i > $maxPerPage) {
|
@@ -148,15 +159,15 @@ class SucuriScanAuditLogs
|
|
148 |
|
149 |
$snippet_data = array(
|
150 |
'AuditLog.Event' => $audit_log['event'],
|
151 |
-
'AuditLog.Time' =>
|
152 |
-
'AuditLog.Date' =>
|
153 |
'AuditLog.Username' => $audit_log['username'],
|
154 |
'AuditLog.Address' => $audit_log['remote_addr'],
|
155 |
'AuditLog.Message' => $audit_log['message'],
|
156 |
'AuditLog.Extra' => '',
|
157 |
);
|
158 |
|
159 |
-
|
160 |
if ($snippet_data['AuditLog.Date'] === $previousDate) {
|
161 |
$snippet_data['AuditLog.Date'] = '';
|
162 |
} elseif ($snippet_data['AuditLog.Date'] === $todaysDate) {
|
@@ -166,7 +177,7 @@ class SucuriScanAuditLogs
|
|
166 |
$previousDate = $snippet_data['AuditLog.Date'];
|
167 |
}
|
168 |
|
169 |
-
|
170 |
if (!empty($snippet_data['AuditLog.Date'])) {
|
171 |
$snippet_data['AuditLog.Date'] =
|
172 |
'<div class="sucuriscan-auditlog-date">'
|
@@ -174,10 +185,9 @@ class SucuriScanAuditLogs
|
|
174 |
. '</div>';
|
175 |
}
|
176 |
|
177 |
-
|
178 |
if ($audit_log['file_list']) {
|
179 |
-
$
|
180 |
-
$snippet_data['AuditLog.Extra'] .= '<ul class="sucuriscan-list-as-table ' . $css_scrollable . '">';
|
181 |
|
182 |
foreach ($audit_log['file_list'] as $log_extra) {
|
183 |
$snippet_data['AuditLog.Extra'] .= '<li>' . SucuriScan::escape($log_extra) . '</li>';
|
@@ -225,32 +235,7 @@ class SucuriScanAuditLogs
|
|
225 |
}
|
226 |
|
227 |
/**
|
228 |
-
*
|
229 |
-
*
|
230 |
-
* The percentage of successful and failed logins. The percentage of events
|
231 |
-
* distributed by severity. The amount of events triggered by each user. And
|
232 |
-
* the amount of events triggered from each IP address. All these statistics
|
233 |
-
* will be rendered in the page.
|
234 |
-
*
|
235 |
-
* @return string HTML with the stats about the security logs.
|
236 |
-
*/
|
237 |
-
public static function pageAuditLogsReport()
|
238 |
-
{
|
239 |
-
$params = array();
|
240 |
-
$logs4report = SucuriScanOption::getOption(':logs4report');
|
241 |
-
|
242 |
-
$params['AuditReport.Logs4Report'] = $logs4report;
|
243 |
-
|
244 |
-
return SucuriScanTemplate::getSection('auditlogs-report', $params);
|
245 |
-
}
|
246 |
-
|
247 |
-
/**
|
248 |
-
* Analyzes the latest security logs and generates statistics.
|
249 |
-
*
|
250 |
-
* A JSON-encoded data structure will be returned after the plugin reads,
|
251 |
-
* processes and extracts relevant information from the latest security logs.
|
252 |
-
* By default the plugin will use the latest 500 logs but the website owner
|
253 |
-
* can increase or decrease this value to reduce or extend the statistics.
|
254 |
*
|
255 |
* @codeCoverageIgnore - Notice that there is a test case that covers this
|
256 |
* code, but since the WP-Send-JSON method uses die() to stop any further
|
@@ -258,79 +243,34 @@ class SucuriScanAuditLogs
|
|
258 |
* with a missing line in the coverage. Since the test case takes care of
|
259 |
* the functionality of this code we will assume that it is fully covered.
|
260 |
*/
|
261 |
-
public static function
|
262 |
{
|
263 |
-
if (SucuriScanRequest::post('form_action') !== '
|
264 |
return;
|
265 |
}
|
266 |
|
267 |
-
|
268 |
-
|
269 |
-
$report = SucuriScanAPI::getAuditReport($logs4report);
|
270 |
-
|
271 |
-
$response['status'] = false;
|
272 |
-
$response['message'] = 'Not enough logs';
|
273 |
-
$response['eventsPerUserSeries'] = array();
|
274 |
-
$response['eventsPerUserCategories'] = array();
|
275 |
-
$response['eventsPerIPAddressSeries'] = array();
|
276 |
-
$response['eventsPerIPAddressCategories'] = array();
|
277 |
-
$response['eventsPerTypePoints'] = array();
|
278 |
-
$response['eventsPerTypeColors'] = array();
|
279 |
-
$response['eventsPerLogin'] = array();
|
280 |
-
|
281 |
-
if ($report) {
|
282 |
-
$response['status'] = true;
|
283 |
-
$response['message'] = '';
|
284 |
-
$response['eventsPerTypeColors'] = $report['event_colors'];
|
285 |
-
|
286 |
-
/* Generate report chart data for the events per type */
|
287 |
-
foreach ($report['events_per_type'] as $event => $times) {
|
288 |
-
$response['eventsPerTypePoints'][] = array(
|
289 |
-
ucwords($event . "\x20events"),
|
290 |
-
$times /* amount of events */
|
291 |
-
);
|
292 |
-
}
|
293 |
-
|
294 |
-
/* Generate report chart data for the events per login */
|
295 |
-
foreach ($report['events_per_login'] as $event => $times) {
|
296 |
-
$response['eventsPerLogin'][] = array(
|
297 |
-
ucwords($event . "\x20logins"),
|
298 |
-
$times /* number of logins */
|
299 |
-
);
|
300 |
-
}
|
301 |
-
|
302 |
-
/* Generate report chart data for the events per user */
|
303 |
-
$users = array_values($report['events_per_user']);
|
304 |
-
$response['eventsPerUserSeries'] = array_merge(array('data'), $users);
|
305 |
-
$response['eventsPerUserCategories'] = array_keys($report['events_per_user']);
|
306 |
-
|
307 |
-
/* Generate report chart data for the events per remote address */
|
308 |
-
$ips = array_values($report['events_per_ipaddress']);
|
309 |
-
$response['eventsPerIPAddressSeries'] = array_merge(array('data'), $ips);
|
310 |
-
$response['eventsPerIPAddressCategories'] = array_keys($report['events_per_ipaddress']);
|
311 |
-
}
|
312 |
-
|
313 |
-
wp_send_json($response, 200);
|
314 |
}
|
315 |
|
316 |
/**
|
317 |
-
*
|
318 |
*
|
319 |
-
*
|
320 |
-
*
|
321 |
-
*
|
322 |
-
*
|
323 |
-
*
|
|
|
|
|
|
|
324 |
*/
|
325 |
-
public static function
|
326 |
{
|
327 |
-
if (
|
328 |
-
return;
|
329 |
}
|
330 |
|
331 |
-
|
332 |
-
SucuriScanEvent::sendLogsFromQueue();
|
333 |
-
|
334 |
-
wp_send_json(array('ok' => true), 200);
|
335 |
}
|
336 |
}
|
97 |
: sprintf('API %s secs', round($duration, 4));
|
98 |
}
|
99 |
|
100 |
+
/* explain missing API key */
|
101 |
+
if (!SucuriScanAPI::getPluginKey()) {
|
102 |
+
$response['status'] = __('APIKeyMissing', SUCURISCAN_TEXTDOMAIN);
|
103 |
+
}
|
104 |
+
|
105 |
/* stop everything and report errors */
|
106 |
if (!empty($errors)) {
|
107 |
$response['content'] .= $errors;
|
117 |
if (!$auditlogs) {
|
118 |
$auditlogs = $queuelogs;
|
119 |
} else {
|
120 |
+
$auditlogs['total_entries'] = isset($auditlogs['total_entries'])
|
121 |
+
? ($auditlogs['total_entries'] + $queuelogs['total_entries'])
|
122 |
+
: $queuelogs['total_entries'];
|
123 |
$auditlogs['output'] = array_merge(
|
124 |
$queuelogs['output'],
|
125 |
+
@$auditlogs['output']
|
126 |
);
|
127 |
$auditlogs['output_data'] = array_merge(
|
128 |
$queuelogs['output_data'],
|
129 |
+
@$auditlogs['output_data']
|
130 |
);
|
131 |
}
|
132 |
}
|
133 |
|
134 |
+
if (is_array($auditlogs)
|
135 |
+
&& isset($auditlogs['output_data'])
|
136 |
+
&& isset($auditlogs['total_entries'])
|
137 |
+
&& is_array($auditlogs['output_data'])
|
138 |
+
&& is_numeric($auditlogs['total_entries'])
|
139 |
+
) {
|
140 |
$counter_i = 0;
|
141 |
$total_items = 0;
|
142 |
$previousDate = '';
|
143 |
+
$todaysDate = SucuriScan::datetime(null, 'M d, Y');
|
144 |
$iterator_start = ($pageNumber - 1) * $maxPerPage;
|
145 |
+
$total_items = count($auditlogs['output_data']);
|
146 |
|
147 |
+
usort($auditlogs['output_data'], array('SucuriScanAuditLogs', 'sortByDate'));
|
|
|
|
|
148 |
|
149 |
for ($i = $iterator_start; $i < $total_items; $i++) {
|
150 |
if ($counter_i > $maxPerPage) {
|
159 |
|
160 |
$snippet_data = array(
|
161 |
'AuditLog.Event' => $audit_log['event'],
|
162 |
+
'AuditLog.Time' => SucuriScan::datetime($audit_log['timestamp'], 'H:i'),
|
163 |
+
'AuditLog.Date' => SucuriScan::datetime($audit_log['timestamp'], 'M d, Y'),
|
164 |
'AuditLog.Username' => $audit_log['username'],
|
165 |
'AuditLog.Address' => $audit_log['remote_addr'],
|
166 |
'AuditLog.Message' => $audit_log['message'],
|
167 |
'AuditLog.Extra' => '',
|
168 |
);
|
169 |
|
170 |
+
/* determine if we need to print the date */
|
171 |
if ($snippet_data['AuditLog.Date'] === $previousDate) {
|
172 |
$snippet_data['AuditLog.Date'] = '';
|
173 |
} elseif ($snippet_data['AuditLog.Date'] === $todaysDate) {
|
177 |
$previousDate = $snippet_data['AuditLog.Date'];
|
178 |
}
|
179 |
|
180 |
+
/* decorate date if necessary */
|
181 |
if (!empty($snippet_data['AuditLog.Date'])) {
|
182 |
$snippet_data['AuditLog.Date'] =
|
183 |
'<div class="sucuriscan-auditlog-date">'
|
185 |
. '</div>';
|
186 |
}
|
187 |
|
188 |
+
/* print every file_list information item in a separate table */
|
189 |
if ($audit_log['file_list']) {
|
190 |
+
$snippet_data['AuditLog.Extra'] .= '<ul class="sucuriscan-list-as-table">';
|
|
|
191 |
|
192 |
foreach ($audit_log['file_list'] as $log_extra) {
|
193 |
$snippet_data['AuditLog.Extra'] .= '<li>' . SucuriScan::escape($log_extra) . '</li>';
|
235 |
}
|
236 |
|
237 |
/**
|
238 |
+
* Send the logs from the queue to the API.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
239 |
*
|
240 |
* @codeCoverageIgnore - Notice that there is a test case that covers this
|
241 |
* code, but since the WP-Send-JSON method uses die() to stop any further
|
243 |
* with a missing line in the coverage. Since the test case takes care of
|
244 |
* the functionality of this code we will assume that it is fully covered.
|
245 |
*/
|
246 |
+
public static function ajaxAuditLogsSendLogs()
|
247 |
{
|
248 |
+
if (SucuriScanRequest::post('form_action') !== 'auditlogs_send_logs') {
|
249 |
return;
|
250 |
}
|
251 |
|
252 |
+
/* blocking; might take a while */
|
253 |
+
wp_send_json(SucuriScanEvent::sendLogsFromQueue(), 200);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
254 |
}
|
255 |
|
256 |
/**
|
257 |
+
* Sort the audit logs by date.
|
258 |
*
|
259 |
+
* Considering that the logs from the API service will be merged with the
|
260 |
+
* logs from the local queue system to complement the information until the
|
261 |
+
* queue is emptied, we will have to sort the entries in the list to keep
|
262 |
+
* the dates in sync.
|
263 |
+
*
|
264 |
+
* @param array $a Data associated to a single log.
|
265 |
+
* @param array $b Data associated to another log.
|
266 |
+
* @return int Comparison between the dates of both logs.
|
267 |
*/
|
268 |
+
public static function sortByDate($a, $b)
|
269 |
{
|
270 |
+
if ($a['timestamp'] === $b['timestamp']) {
|
271 |
+
return 0;
|
272 |
}
|
273 |
|
274 |
+
return ($a['timestamp'] > $b['timestamp']) ? -1 : 1;
|
|
|
|
|
|
|
275 |
}
|
276 |
}
|
src/cache.lib.php
CHANGED
@@ -368,7 +368,9 @@ class SucuriScanCache extends SucuriScan
|
|
368 |
|
369 |
$finfo = $this->getDatastoreContent($assoc === 'array');
|
370 |
|
371 |
-
if ($this->dataHasExpired($lifetime, $finfo)
|
|
|
|
|
372 |
return false;
|
373 |
}
|
374 |
|
@@ -425,7 +427,7 @@ class SucuriScanCache extends SucuriScan
|
|
425 |
$finfo = $this->getDatastoreContent(true);
|
426 |
|
427 |
if (!array_key_exists($key, $finfo['entries'])) {
|
428 |
-
return
|
429 |
}
|
430 |
|
431 |
unset($finfo['entries'][$key]);
|
368 |
|
369 |
$finfo = $this->getDatastoreContent($assoc === 'array');
|
370 |
|
371 |
+
if ($this->dataHasExpired($lifetime, $finfo)
|
372 |
+
|| !array_key_exists($key, $finfo['entries'])
|
373 |
+
) {
|
374 |
return false;
|
375 |
}
|
376 |
|
427 |
$finfo = $this->getDatastoreContent(true);
|
428 |
|
429 |
if (!array_key_exists($key, $finfo['entries'])) {
|
430 |
+
return true;
|
431 |
}
|
432 |
|
433 |
unset($finfo['entries'][$key]);
|
src/command.lib.php
CHANGED
@@ -100,12 +100,11 @@ class SucuriScanCommand extends SucuriScan
|
|
100 |
* the elements in the code to facilitate the styling of the diff report.
|
101 |
*
|
102 |
* @param string $filepath Relative path to the core WordPress file.
|
103 |
-
* @param string $version Version number of the WordPress installation.
|
104 |
* @return string|bool HTML code with the diff report, false on failure.
|
105 |
*/
|
106 |
-
public static function diffHTML($filepath
|
107 |
{
|
108 |
-
$checksums = SucuriScanAPI::getOfficialChecksums(
|
109 |
|
110 |
if (!$checksums) {
|
111 |
return SucuriScanInterface::error(__('UnsupportedWordPress', SUCURISCAN_TEXTDOMAIN));
|
@@ -115,25 +114,22 @@ class SucuriScanCommand extends SucuriScan
|
|
115 |
return SucuriScanInterface::error(__('NoWordPressFile', SUCURISCAN_TEXTDOMAIN));
|
116 |
}
|
117 |
|
118 |
-
if (!file_exists(ABSPATH . '/' . $filepath)) {
|
119 |
-
return SucuriScanInterface::error(__('CannotCheckMissingFile', SUCURISCAN_TEXTDOMAIN));
|
120 |
-
}
|
121 |
-
|
122 |
$output = ''; /* initialize empty with no differences */
|
123 |
-
$
|
|
|
124 |
|
125 |
-
if ($handle = @fopen($
|
126 |
-
$
|
127 |
-
|
128 |
-
$content = SucuriScanAPI::getOriginalCoreFile($filepath, $version);
|
129 |
-
@fwrite($handle, $content); /* create a copy of the original file */
|
130 |
$output = self::diff($a, $b);
|
131 |
-
@fclose($
|
132 |
-
@unlink($tempfile);
|
133 |
}
|
134 |
|
|
|
|
|
|
|
135 |
if (!is_array($output) || empty($output)) {
|
136 |
-
return '';
|
137 |
}
|
138 |
|
139 |
$response = "<ul class='" . SUCURISCAN . "-diff-content'>\n";
|
@@ -144,13 +140,11 @@ class SucuriScanCommand extends SucuriScan
|
|
144 |
$cssclass .= "\x20" . SUCURISCAN . '-diff-line' . $number;
|
145 |
|
146 |
if ($number === 1) {
|
147 |
-
$line =
|
148 |
$cssclass .= "\x20" . SUCURISCAN . '-diff-header';
|
149 |
-
$line = substr($line, 0, 4 + strlen($b) + 11);
|
150 |
} elseif ($number === 2) {
|
151 |
-
$line =
|
152 |
$cssclass .= "\x20" . SUCURISCAN . '-diff-header';
|
153 |
-
$line = substr($line, 0, 4 + strlen($b) + 11);
|
154 |
} elseif ($number === 3) {
|
155 |
$cssclass .= "\x20" . SUCURISCAN . '-diff-header';
|
156 |
} elseif ($line === '') {
|
100 |
* the elements in the code to facilitate the styling of the diff report.
|
101 |
*
|
102 |
* @param string $filepath Relative path to the core WordPress file.
|
|
|
103 |
* @return string|bool HTML code with the diff report, false on failure.
|
104 |
*/
|
105 |
+
public static function diffHTML($filepath)
|
106 |
{
|
107 |
+
$checksums = SucuriScanAPI::getOfficialChecksums();
|
108 |
|
109 |
if (!$checksums) {
|
110 |
return SucuriScanInterface::error(__('UnsupportedWordPress', SUCURISCAN_TEXTDOMAIN));
|
114 |
return SucuriScanInterface::error(__('NoWordPressFile', SUCURISCAN_TEXTDOMAIN));
|
115 |
}
|
116 |
|
|
|
|
|
|
|
|
|
117 |
$output = ''; /* initialize empty with no differences */
|
118 |
+
$a = tempnam(sys_get_temp_dir(), SUCURISCAN . '-integrity-');
|
119 |
+
$b = tempnam(sys_get_temp_dir(), SUCURISCAN . '-integrity-');
|
120 |
|
121 |
+
if ($handle = @fopen($a, 'w')) {
|
122 |
+
@fwrite($handle, SucuriScanAPI::getOriginalCoreFile($filepath));
|
123 |
+
@copy(ABSPATH . '/' . $filepath, $b);
|
|
|
|
|
124 |
$output = self::diff($a, $b);
|
125 |
+
@fclose($handle);
|
|
|
126 |
}
|
127 |
|
128 |
+
@unlink($a); /* delete original file */
|
129 |
+
@unlink($b); /* delete modified file */
|
130 |
+
|
131 |
if (!is_array($output) || empty($output)) {
|
132 |
+
return SucuriScanInterface::error(__('ThereAreNoDifferences', SUCURISCAN_TEXTDOMAIN));
|
133 |
}
|
134 |
|
135 |
$response = "<ul class='" . SUCURISCAN . "-diff-content'>\n";
|
140 |
$cssclass .= "\x20" . SUCURISCAN . '-diff-line' . $number;
|
141 |
|
142 |
if ($number === 1) {
|
143 |
+
$line = sprintf('--- %s (ORIGINAL)', $filepath);
|
144 |
$cssclass .= "\x20" . SUCURISCAN . '-diff-header';
|
|
|
145 |
} elseif ($number === 2) {
|
146 |
+
$line = sprintf('+++ %s (MODIFIED)', $filepath);
|
147 |
$cssclass .= "\x20" . SUCURISCAN . '-diff-header';
|
|
|
148 |
} elseif ($number === 3) {
|
149 |
$cssclass .= "\x20" . SUCURISCAN . '-diff-header';
|
150 |
} elseif ($line === '') {
|
src/event.lib.php
CHANGED
@@ -170,10 +170,11 @@ class SucuriScanEvent extends SucuriScan
|
|
170 |
* to write the log into the queue when the previous request failed.
|
171 |
*
|
172 |
* @param string $message Information about the event.
|
173 |
-
* @param string $timestamp Time when the event was triggered.
|
|
|
174 |
* @return bool True if the event was logged, false otherwise.
|
175 |
*/
|
176 |
-
private static function sendLogToAPI($message = '', $timestamp = '')
|
177 |
{
|
178 |
if (empty($message)) {
|
179 |
return self::throwException('Event identifier cannot be empty');
|
@@ -183,7 +184,7 @@ class SucuriScanEvent extends SucuriScan
|
|
183 |
$params['a'] = 'send_log';
|
184 |
$params['m'] = $message;
|
185 |
$params['time'] = $timestamp;
|
186 |
-
$args = array('timeout' =>
|
187 |
|
188 |
$resp = SucuriScanAPI::apiCallWordpress('POST', $params, true, $args);
|
189 |
|
@@ -197,6 +198,10 @@ class SucuriScanEvent extends SucuriScan
|
|
197 |
/**
|
198 |
* Sends the event message to a local queue system.
|
199 |
*
|
|
|
|
|
|
|
|
|
200 |
* @param string $message Information about the security event.
|
201 |
* @return bool True if the operation succeeded, false otherwise.
|
202 |
*/
|
@@ -219,7 +224,7 @@ class SucuriScanEvent extends SucuriScan
|
|
219 |
if ($monitor_fpath !== false) {
|
220 |
$local_event = sprintf(
|
221 |
"%s WordPressAudit %s %s : %s\n",
|
222 |
-
|
223 |
SucuriScan::getTopLevelDomain(),
|
224 |
SucuriScanOption::getOption(':account'),
|
225 |
$message
|
@@ -232,7 +237,17 @@ class SucuriScanEvent extends SucuriScan
|
|
232 |
}
|
233 |
}
|
234 |
|
235 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
236 |
if (SucuriScanOption::isEnabled(':api_service')) {
|
237 |
$cache = new SucuriScanCache('auditqueue');
|
238 |
$key = str_replace('.', '_', microtime(true));
|
@@ -244,47 +259,77 @@ class SucuriScanEvent extends SucuriScan
|
|
244 |
|
245 |
/**
|
246 |
* Sends all the events from the queue to the API.
|
|
|
|
|
247 |
*/
|
248 |
public static function sendLogsFromQueue()
|
249 |
{
|
250 |
if (SucuriScanOption::isDisabled(':api_service')) {
|
251 |
-
return;
|
252 |
}
|
253 |
|
254 |
$cache = new SucuriScanCache('auditqueue');
|
255 |
$finfo = $cache->getDatastoreInfo();
|
256 |
$events = $cache->getAll();
|
257 |
-
$counter = 0;
|
258 |
|
259 |
if (!$events) {
|
260 |
-
return;
|
261 |
}
|
262 |
|
263 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
264 |
$maxtime = (int) SucuriScan::iniGet('max_execution_time');
|
265 |
-
$
|
|
|
|
|
|
|
|
|
|
|
266 |
|
267 |
foreach ($events as $keyname => $message) {
|
268 |
$offset = strpos($keyname, '_');
|
269 |
$timestamp = substr($keyname, 0, $offset);
|
270 |
$status = self::sendLogToAPI($message, $timestamp);
|
271 |
|
|
|
272 |
if ($status !== true) {
|
273 |
-
|
274 |
-
|
275 |
}
|
276 |
|
277 |
/* dequeue event message */
|
278 |
unset($events[$keyname]);
|
279 |
-
$
|
280 |
|
281 |
-
/* avoid
|
282 |
-
|
|
|
283 |
break;
|
284 |
}
|
285 |
}
|
286 |
|
|
|
287 |
$cache->override($events);
|
|
|
|
|
288 |
}
|
289 |
|
290 |
/**
|
@@ -415,58 +460,19 @@ class SucuriScanEvent extends SucuriScan
|
|
415 |
{
|
416 |
$message = strip_tags($message);
|
417 |
|
418 |
-
/* auto-detect the action performed
|
419 |
-
if (
|
420 |
-
$action = $match[2];
|
421 |
-
}
|
422 |
-
|
423 |
-
if ($action === 'enabled') {
|
424 |
return self::reportNoticeEvent($message);
|
425 |
}
|
426 |
|
427 |
-
|
|
|
428 |
return self::reportErrorEvent($message);
|
429 |
}
|
430 |
|
431 |
return self::reportInfoEvent($message);
|
432 |
}
|
433 |
|
434 |
-
/**
|
435 |
-
* Reports an esception on the code.
|
436 |
-
*
|
437 |
-
* @param Exception $exception A valid exception object of any type.
|
438 |
-
* @return bool Whether the report was filled correctly or not.
|
439 |
-
*/
|
440 |
-
public static function reportException($exception)
|
441 |
-
{
|
442 |
-
$e_trace = $exception->getTrace();
|
443 |
-
$multiple_entries = array();
|
444 |
-
|
445 |
-
foreach ($e_trace as $e_child) {
|
446 |
-
$e_file = array_key_exists('file', $e_child)
|
447 |
-
? basename($e_child['file'])
|
448 |
-
: '[internal function]';
|
449 |
-
$e_line = array_key_exists('line', $e_child)
|
450 |
-
? basename($e_child['line'])
|
451 |
-
: '0';
|
452 |
-
$e_method = array_key_exists('class', $e_child)
|
453 |
-
? $e_child['class'] . $e_child['type'] . $e_child['function']
|
454 |
-
: $e_child['function'];
|
455 |
-
$multiple_entries[] = sprintf(
|
456 |
-
'%s(%s): %s',
|
457 |
-
$e_file,
|
458 |
-
$e_line,
|
459 |
-
$e_method
|
460 |
-
);
|
461 |
-
}
|
462 |
-
|
463 |
-
return self::reportDebugEvent(sprintf(
|
464 |
-
'%s: (multiple entries): %s',
|
465 |
-
$exception->getMessage(),
|
466 |
-
@implode(',', $multiple_entries)
|
467 |
-
));
|
468 |
-
}
|
469 |
-
|
470 |
/**
|
471 |
* Send a notification to the administrator of the specified events, only if
|
472 |
* the administrator accepted to receive alerts for this type of events.
|
@@ -506,7 +512,11 @@ class SucuriScanEvent extends SucuriScan
|
|
506 |
|
507 |
case 'failed_login':
|
508 |
$settings_url = SucuriScanTemplate::getUrl('settings');
|
509 |
-
$content .= sprintf(
|
|
|
|
|
|
|
|
|
510 |
break;
|
511 |
|
512 |
case 'bruteforce_attack':
|
@@ -644,13 +654,15 @@ class SucuriScanEvent extends SucuriScan
|
|
644 |
}
|
645 |
|
646 |
/**
|
647 |
-
*
|
648 |
-
*
|
649 |
-
*
|
650 |
-
*
|
651 |
-
*
|
|
|
|
|
652 |
*
|
653 |
-
* @return array|bool
|
654 |
*/
|
655 |
public static function setNewConfigKeys()
|
656 |
{
|
170 |
* to write the log into the queue when the previous request failed.
|
171 |
*
|
172 |
* @param string $message Information about the event.
|
173 |
+
* @param string|int $timestamp Time when the event was triggered.
|
174 |
+
* @param int $timeout Maximum time in seconds to connect to the API.
|
175 |
* @return bool True if the event was logged, false otherwise.
|
176 |
*/
|
177 |
+
private static function sendLogToAPI($message = '', $timestamp = '', $timeout = 1)
|
178 |
{
|
179 |
if (empty($message)) {
|
180 |
return self::throwException('Event identifier cannot be empty');
|
184 |
$params['a'] = 'send_log';
|
185 |
$params['m'] = $message;
|
186 |
$params['time'] = $timestamp;
|
187 |
+
$args = array('timeout' => $timeout);
|
188 |
|
189 |
$resp = SucuriScanAPI::apiCallWordpress('POST', $params, true, $args);
|
190 |
|
198 |
/**
|
199 |
* Sends the event message to a local queue system.
|
200 |
*
|
201 |
+
* Note: The method is public to facilitate the execution of some unit-tests
|
202 |
+
* but it could be private and be mocked by the test bootstrap script. Take
|
203 |
+
* this in consideration during the static analysis of the code.
|
204 |
+
*
|
205 |
* @param string $message Information about the security event.
|
206 |
* @return bool True if the operation succeeded, false otherwise.
|
207 |
*/
|
224 |
if ($monitor_fpath !== false) {
|
225 |
$local_event = sprintf(
|
226 |
"%s WordPressAudit %s %s : %s\n",
|
227 |
+
SucuriScan::datetime(null, 'Y-m-d H:i:s'),
|
228 |
SucuriScan::getTopLevelDomain(),
|
229 |
SucuriScanOption::getOption(':account'),
|
230 |
$message
|
237 |
}
|
238 |
}
|
239 |
|
240 |
+
/**
|
241 |
+
* Send event to the API if possible.
|
242 |
+
*
|
243 |
+
* If the user have not disabled the communication with the API service,
|
244 |
+
* the plugin will send a message with information about every triggered
|
245 |
+
* event in the website in realtime with a maximum connection time of
|
246 |
+
* two seconds. If the API service does not responds on time the plugin
|
247 |
+
* will insert the event into the local queue system and it will try to
|
248 |
+
* send the message again with a scheduled task every 24 hours, once the
|
249 |
+
* operation succeeds the event will be deleted from the queue.
|
250 |
+
*/
|
251 |
if (SucuriScanOption::isEnabled(':api_service')) {
|
252 |
$cache = new SucuriScanCache('auditqueue');
|
253 |
$key = str_replace('.', '_', microtime(true));
|
259 |
|
260 |
/**
|
261 |
* Sends all the events from the queue to the API.
|
262 |
+
*
|
263 |
+
* @return array|bool Information about the dequeue process.
|
264 |
*/
|
265 |
public static function sendLogsFromQueue()
|
266 |
{
|
267 |
if (SucuriScanOption::isDisabled(':api_service')) {
|
268 |
+
return false;
|
269 |
}
|
270 |
|
271 |
$cache = new SucuriScanCache('auditqueue');
|
272 |
$finfo = $cache->getDatastoreInfo();
|
273 |
$events = $cache->getAll();
|
|
|
274 |
|
275 |
if (!$events) {
|
276 |
+
return false;
|
277 |
}
|
278 |
|
279 |
+
$result = array(
|
280 |
+
'maxtime' => -1,
|
281 |
+
'ttllogs' => 0,
|
282 |
+
'success' => 0,
|
283 |
+
'failure' => 0,
|
284 |
+
'elapsed' => 0,
|
285 |
+
);
|
286 |
+
|
287 |
+
/**
|
288 |
+
* Send logs to the API with a limit.
|
289 |
+
*
|
290 |
+
* We will use the maximum execution time setting to limit the number of
|
291 |
+
* logs that the plugin will try to send to the API service before the
|
292 |
+
* server times out. In a regular installation, the limit is set to 30
|
293 |
+
* seconds, since the timeout for the HTTP request is 5 seconds we will
|
294 |
+
* instruct the plugin to wait (30 secs - 5 secs) and an additional one
|
295 |
+
* second to spare processing, so in a regular installation the plugin
|
296 |
+
* will try to send as much logs as possible to the API service in less
|
297 |
+
* than 25 seconds.
|
298 |
+
*/
|
299 |
$maxtime = (int) SucuriScan::iniGet('max_execution_time');
|
300 |
+
$timeout = ($maxtime > 1) ? ($maxtime - 6) : 30;
|
301 |
+
|
302 |
+
/* record some statistics */
|
303 |
+
$startTime = microtime(true);
|
304 |
+
$result['maxtime'] = $maxtime;
|
305 |
+
$result['ttllogs'] = count($events);
|
306 |
|
307 |
foreach ($events as $keyname => $message) {
|
308 |
$offset = strpos($keyname, '_');
|
309 |
$timestamp = substr($keyname, 0, $offset);
|
310 |
$status = self::sendLogToAPI($message, $timestamp);
|
311 |
|
312 |
+
/* skip; API is busy */
|
313 |
if ($status !== true) {
|
314 |
+
$result['failure']++;
|
315 |
+
continue;
|
316 |
}
|
317 |
|
318 |
/* dequeue event message */
|
319 |
unset($events[$keyname]);
|
320 |
+
$result['success']++;
|
321 |
|
322 |
+
/* avoid gateway timeout; max execution time */
|
323 |
+
$elapsedTime = (microtime(true) - $startTime);
|
324 |
+
if ($elapsedTime >= $timeout) {
|
325 |
break;
|
326 |
}
|
327 |
}
|
328 |
|
329 |
+
$result['elapsed'] = round(microtime(true) - $startTime, 4);
|
330 |
$cache->override($events);
|
331 |
+
|
332 |
+
return $result;
|
333 |
}
|
334 |
|
335 |
/**
|
460 |
{
|
461 |
$message = strip_tags($message);
|
462 |
|
463 |
+
/* auto-detect the action performed: enabled */
|
464 |
+
if (strpos($message, 'enabled') !== false) {
|
|
|
|
|
|
|
|
|
465 |
return self::reportNoticeEvent($message);
|
466 |
}
|
467 |
|
468 |
+
/* auto-detect the action performed: disabled */
|
469 |
+
if (strpos($message, 'disabled') !== false) {
|
470 |
return self::reportErrorEvent($message);
|
471 |
}
|
472 |
|
473 |
return self::reportInfoEvent($message);
|
474 |
}
|
475 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
476 |
/**
|
477 |
* Send a notification to the administrator of the specified events, only if
|
478 |
* the administrator accepted to receive alerts for this type of events.
|
512 |
|
513 |
case 'failed_login':
|
514 |
$settings_url = SucuriScanTemplate::getUrl('settings');
|
515 |
+
$content .= "\n" . sprintf(
|
516 |
+
__('FailedLoginFooter', SUCURISCAN_TEXTDOMAIN),
|
517 |
+
$settings_url,
|
518 |
+
$settings_url
|
519 |
+
);
|
520 |
break;
|
521 |
|
522 |
case 'bruteforce_attack':
|
654 |
}
|
655 |
|
656 |
/**
|
657 |
+
* Changes the WordPress secret keys.
|
658 |
+
*
|
659 |
+
* Modify the WordPress configuration file to define new secret keys from a
|
660 |
+
* new randomly generated list of strings from the official WordPress API.
|
661 |
+
* The result of the operation will be either False in case of error, or an
|
662 |
+
* array containing multiple indexes explaining the modification, among them
|
663 |
+
* you will find the old and new keys.
|
664 |
*
|
665 |
+
* @return array|bool Array with the old and new keys, false otherwise.
|
666 |
*/
|
667 |
public static function setNewConfigKeys()
|
668 |
{
|
src/fileinfo.lib.php
CHANGED
@@ -136,7 +136,10 @@ class SucuriScanFileInfo extends SucuriScan
|
|
136 |
private function ignoreFolder($path)
|
137 |
{
|
138 |
return (bool) ($this->ignore_directories && (
|
139 |
-
strpos($path, '
|
|
|
|
|
|
|
140 |
|| strpos($path, 'wp-content/cache') !== false
|
141 |
|| strpos($path, 'wp-content/uploads') !== false
|
142 |
|| strpos($path, 'wp-content/w3tc') !== false
|
@@ -206,7 +209,7 @@ class SucuriScanFileInfo extends SucuriScan
|
|
206 |
$objects = new DirectoryIterator($directory);
|
207 |
}
|
208 |
} catch (RuntimeException $exception) {
|
209 |
-
|
210 |
}
|
211 |
// @codeCoverageIgnoreEnd
|
212 |
|
@@ -314,6 +317,20 @@ class SucuriScanFileInfo extends SucuriScan
|
|
314 |
*/
|
315 |
public function removeDirectoryTree($directory = '')
|
316 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
317 |
/* force complete scan */
|
318 |
$this->ignore_files = false;
|
319 |
$this->skip_directories = false;
|
@@ -328,24 +345,10 @@ class SucuriScanFileInfo extends SucuriScan
|
|
328 |
}
|
329 |
}
|
330 |
|
331 |
-
if (!function_exists('sucuriscanStrlenDiff')) {
|
332 |
-
/**
|
333 |
-
* Evaluates the difference between the length of two strings.
|
334 |
-
*
|
335 |
-
* @param string $a First string of characters that will be measured.
|
336 |
-
* @param string $b Second string of characters that will be measured.
|
337 |
-
* @return int The difference in length between the two strings.
|
338 |
-
*/
|
339 |
-
function sucuriscanStrlenDiff($a = '', $b = '')
|
340 |
-
{
|
341 |
-
return strlen($b) - strlen($a);
|
342 |
-
}
|
343 |
-
}
|
344 |
-
|
345 |
/* delete directories starting from the deepest level */
|
346 |
if ($dir_tree = $this->getDirectoryTree($directory, 'directory')) {
|
347 |
$dir_tree = array_unique($dir_tree);
|
348 |
-
usort($dir_tree, '
|
349 |
foreach ($dir_tree as $dir_path) {
|
350 |
@rmdir($dir_path);
|
351 |
}
|
@@ -357,6 +360,18 @@ class SucuriScanFileInfo extends SucuriScan
|
|
357 |
return (bool) !($this->getDirectoryTree($directory));
|
358 |
}
|
359 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
360 |
/**
|
361 |
* Returns the content of a file.
|
362 |
*
|
136 |
private function ignoreFolder($path)
|
137 |
{
|
138 |
return (bool) ($this->ignore_directories && (
|
139 |
+
strpos($path, '/.hg') !== false
|
140 |
+
|| strpos($path, '/.git') !== false
|
141 |
+
|| strpos($path, '/.svn') !== false
|
142 |
+
|| strpos($path, 'wp-content/backup') !== false
|
143 |
|| strpos($path, 'wp-content/cache') !== false
|
144 |
|| strpos($path, 'wp-content/uploads') !== false
|
145 |
|| strpos($path, 'wp-content/w3tc') !== false
|
209 |
$objects = new DirectoryIterator($directory);
|
210 |
}
|
211 |
} catch (RuntimeException $exception) {
|
212 |
+
/* ignore failure */
|
213 |
}
|
214 |
// @codeCoverageIgnoreEnd
|
215 |
|
317 |
*/
|
318 |
public function removeDirectoryTree($directory = '')
|
319 |
{
|
320 |
+
$directory = realpath($directory);
|
321 |
+
|
322 |
+
if (!is_dir($directory)) {
|
323 |
+
return self::throwException('Directory does not exists');
|
324 |
+
}
|
325 |
+
|
326 |
+
if ($directory === ABSPATH . 'wp-content') {
|
327 |
+
return self::throwException('Cannot delete content directory');
|
328 |
+
}
|
329 |
+
|
330 |
+
if ($directory === ABSPATH . 'wp-content/uploads') {
|
331 |
+
return self::throwException('Cannot delete uploads directory');
|
332 |
+
}
|
333 |
+
|
334 |
/* force complete scan */
|
335 |
$this->ignore_files = false;
|
336 |
$this->skip_directories = false;
|
345 |
}
|
346 |
}
|
347 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
348 |
/* delete directories starting from the deepest level */
|
349 |
if ($dir_tree = $this->getDirectoryTree($directory, 'directory')) {
|
350 |
$dir_tree = array_unique($dir_tree);
|
351 |
+
usort($dir_tree, array('SucuriScanFileInfo', 'sortByLength'));
|
352 |
foreach ($dir_tree as $dir_path) {
|
353 |
@rmdir($dir_path);
|
354 |
}
|
360 |
return (bool) !($this->getDirectoryTree($directory));
|
361 |
}
|
362 |
|
363 |
+
/**
|
364 |
+
* Evaluates the difference between the length of two strings.
|
365 |
+
*
|
366 |
+
* @param string $a First string of characters that will be measured.
|
367 |
+
* @param string $b Second string of characters that will be measured.
|
368 |
+
* @return int The difference in length between the two strings.
|
369 |
+
*/
|
370 |
+
public static function sortByLength($a, $b)
|
371 |
+
{
|
372 |
+
return strlen($b) - strlen($a);
|
373 |
+
}
|
374 |
+
|
375 |
/**
|
376 |
* Returns the content of a file.
|
377 |
*
|
src/firewall.lib.php
CHANGED
@@ -80,22 +80,16 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
80 |
|
81 |
if (isset($params['k']) && isset($params['s'])) {
|
82 |
$send_request = true;
|
83 |
-
}
|
84 |
-
$
|
85 |
-
|
86 |
-
|
87 |
-
$send_request = true;
|
88 |
-
$params['k'] = $api_key['k'];
|
89 |
-
$params['s'] = $api_key['s'];
|
90 |
-
}
|
91 |
}
|
92 |
|
93 |
if ($send_request) {
|
94 |
-
$url = SUCURISCAN_CLOUDPROXY_API;
|
95 |
-
$params[ SUCURISCAN_CLOUDPROXY_API_VERSION ] = 1;
|
96 |
unset($params['string']);
|
97 |
-
|
98 |
-
return self::apiCall(
|
99 |
}
|
100 |
|
101 |
return false;
|
@@ -136,8 +130,6 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
136 |
'Firewall.APIKey' => '',
|
137 |
'Firewall.APIKeyVisibility' => 'hidden',
|
138 |
'Firewall.APIKeyFormVisibility' => 'visible',
|
139 |
-
'Firewall.SettingsVisibility' => 'hidden',
|
140 |
-
'Firewall.SettingOptions' => '',
|
141 |
);
|
142 |
|
143 |
if (SucuriScanInterface::checkNonce()) {
|
@@ -167,50 +159,12 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
167 |
}
|
168 |
}
|
169 |
|
170 |
-
$api_key = self::getKey();
|
171 |
|
172 |
if ($api_key && array_key_exists('string', $api_key)) {
|
173 |
-
$settings = self::settings($api_key);
|
174 |
-
|
175 |
$params['Firewall.APIKeyVisibility'] = 'visible';
|
176 |
$params['Firewall.APIKeyFormVisibility'] = 'hidden';
|
177 |
$params['Firewall.APIKey'] = $api_key['string'];
|
178 |
-
|
179 |
-
if ($settings) {
|
180 |
-
$params['Firewall.SettingsVisibility'] = 'visible';
|
181 |
-
$settings = self::settingsExplanation($settings);
|
182 |
-
|
183 |
-
foreach ($settings as $option_name => $option_value) {
|
184 |
-
$option_title = ucwords(str_replace('_', "\x20", $option_name));
|
185 |
-
|
186 |
-
// Generate a HTML list when the option's value is an array.
|
187 |
-
if (is_array($option_value)) {
|
188 |
-
$css_scrollable = count($option_value) > 10 ? 'sucuriscan-list-as-table-scrollable' : '';
|
189 |
-
$html_list = '<ul class="sucuriscan-list-as-table ' . $css_scrollable . '">';
|
190 |
-
|
191 |
-
if (!empty($option_value)) {
|
192 |
-
foreach ($option_value as $single_value) {
|
193 |
-
$single_value = SucuriScan::escape($single_value);
|
194 |
-
$html_list .= '<li>' . SucuriScan::escape($single_value) . '</li>';
|
195 |
-
}
|
196 |
-
} else {
|
197 |
-
$html_list .= '<li>(' . __('NoData', SUCURISCAN_TEXTDOMAIN) . ')</li>';
|
198 |
-
}
|
199 |
-
|
200 |
-
$html_list .= '</ul>';
|
201 |
-
$option_value = $html_list;
|
202 |
-
} else {
|
203 |
-
$option_value = SucuriScan::escape($option_value);
|
204 |
-
}
|
205 |
-
|
206 |
-
// Parse the snippet template and replace the pseudo-variables.
|
207 |
-
$params['Firewall.SettingOptions']
|
208 |
-
.= SucuriScanTemplate::getSnippet('firewall-settings', array(
|
209 |
-
'Firewall.OptionName' => $option_title,
|
210 |
-
'Firewall.OptionValue' => $option_value,
|
211 |
-
));
|
212 |
-
}
|
213 |
-
}
|
214 |
}
|
215 |
|
216 |
return SucuriScanTemplate::getSection('firewall-settings', $params);
|
@@ -226,6 +180,10 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
226 |
*/
|
227 |
public static function settingsExplanation($settings = array())
|
228 |
{
|
|
|
|
|
|
|
|
|
229 |
$cache_modes = array(
|
230 |
'docache' => __('FirewallDoCache', SUCURISCAN_TEXTDOMAIN),
|
231 |
'sitecache' => __('FirewallSiteCache', SUCURISCAN_TEXTDOMAIN),
|
@@ -233,9 +191,6 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
233 |
'nocacheatall' => __('FirewallNoCacheAtAll', SUCURISCAN_TEXTDOMAIN),
|
234 |
);
|
235 |
|
236 |
-
// TODO: Prefer Array over stdClass, modify the API library.
|
237 |
-
$settings = @json_decode(json_encode($settings), true);
|
238 |
-
|
239 |
foreach ($settings as $keyname => $value) {
|
240 |
if ($keyname == 'proxy_active') {
|
241 |
$settings[$keyname] = ($value === 1)
|
@@ -253,6 +208,45 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
253 |
return $settings;
|
254 |
}
|
255 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
256 |
/**
|
257 |
* Retrieve the audit logs of the account associated with the API keys
|
258 |
* registered b the administrator of the site. This method will send a HTTP
|
@@ -300,7 +294,7 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
300 |
$params = array();
|
301 |
|
302 |
/* logs are available after 24 hours */
|
303 |
-
$date =
|
304 |
|
305 |
$params['AuditLogs.DateYears'] = self::dates('years', $date);
|
306 |
$params['AuditLogs.DateMonths'] = self::dates('months', $date);
|
@@ -325,41 +319,49 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
325 |
return;
|
326 |
}
|
327 |
|
328 |
-
$response = '';
|
|
|
329 |
|
330 |
-
if (
|
331 |
-
|
332 |
-
|
333 |
-
$
|
334 |
-
$
|
335 |
-
|
336 |
-
$offset = 1;
|
337 |
-
|
338 |
-
if ($year && $month && $day) {
|
339 |
-
$date = sprintf('%s-%s-%s', $year, $month, $day);
|
340 |
-
} else {
|
341 |
-
$date = date('Y-m-d');
|
342 |
-
}
|
343 |
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
);
|
351 |
|
352 |
-
|
353 |
-
|
|
|
|
|
|
|
354 |
|
355 |
-
|
356 |
-
|
357 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
358 |
}
|
359 |
-
} else {
|
360 |
-
ob_start();
|
361 |
-
SucuriScanInterface::error(__('FirewallAPIKeyMissing', SUCURISCAN_TEXTDOMAIN));
|
362 |
-
$response = ob_get_clean();
|
363 |
}
|
364 |
|
365 |
wp_send_json($response, 200);
|
@@ -453,10 +455,11 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
453 |
switch ($type) {
|
454 |
case 'years':
|
455 |
$selected = $s_year;
|
456 |
-
$current_year = (int)
|
457 |
$max_years = 5; /* Maximum number of years to keep the logs. */
|
458 |
$options = range(($current_year - $max_years), $current_year);
|
459 |
break;
|
|
|
460 |
case 'months':
|
461 |
$selected = $s_month;
|
462 |
$options = array(
|
@@ -474,6 +477,7 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
474 |
'12' => __('December', SUCURISCAN_TEXTDOMAIN),
|
475 |
);
|
476 |
break;
|
|
|
477 |
case 'days':
|
478 |
$options = range(1, 31);
|
479 |
$selected = $s_day;
|
@@ -502,6 +506,133 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
502 |
return $options;
|
503 |
}
|
504 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
505 |
/**
|
506 |
* Flush the cache of the site(s) associated with the API key.
|
507 |
*
|
@@ -532,23 +663,9 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
532 |
{
|
533 |
$params = array();
|
534 |
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
if (!$response) {
|
540 |
-
SucuriScanInterface::error(__('FirewallNotEnabled', SUCURISCAN_TEXTDOMAIN));
|
541 |
-
} elseif (!isset($response['messages'][0])) {
|
542 |
-
SucuriScanInterface::error(__('FirewallClearCacheFailure', SUCURISCAN_TEXTDOMAIN));
|
543 |
-
} else {
|
544 |
-
// Clear W3 Total Cache if it is installed.
|
545 |
-
if (function_exists('w3tc_flush_all')) {
|
546 |
-
w3tc_flush_all();
|
547 |
-
}
|
548 |
-
|
549 |
-
SucuriScanInterface::info($response['messages'][0]);
|
550 |
-
}
|
551 |
-
}
|
552 |
|
553 |
return SucuriScanTemplate::getSection('firewall-clearcache', $params);
|
554 |
}
|
@@ -562,13 +679,68 @@ class SucuriScanFirewall extends SucuriScanAPI
|
|
562 |
* of certain files is going to stay as it is due to the configuration on the
|
563 |
* edge of the servers.
|
564 |
*
|
565 |
-
* @param
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
566 |
*/
|
567 |
-
public static function
|
568 |
{
|
569 |
-
|
570 |
-
|
571 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
572 |
}
|
|
|
|
|
573 |
}
|
574 |
}
|
80 |
|
81 |
if (isset($params['k']) && isset($params['s'])) {
|
82 |
$send_request = true;
|
83 |
+
} elseif ($api_key = self::getKey()) {
|
84 |
+
$send_request = true;
|
85 |
+
$params['k'] = $api_key['k'];
|
86 |
+
$params['s'] = $api_key['s'];
|
|
|
|
|
|
|
|
|
87 |
}
|
88 |
|
89 |
if ($send_request) {
|
|
|
|
|
90 |
unset($params['string']);
|
91 |
+
$params[SUCURISCAN_CLOUDPROXY_API_VERSION] = 1;
|
92 |
+
return self::apiCall(SUCURISCAN_CLOUDPROXY_API, $method, $params);
|
93 |
}
|
94 |
|
95 |
return false;
|
130 |
'Firewall.APIKey' => '',
|
131 |
'Firewall.APIKeyVisibility' => 'hidden',
|
132 |
'Firewall.APIKeyFormVisibility' => 'visible',
|
|
|
|
|
133 |
);
|
134 |
|
135 |
if (SucuriScanInterface::checkNonce()) {
|
159 |
}
|
160 |
}
|
161 |
|
162 |
+
$api_key = self::getKey();
|
163 |
|
164 |
if ($api_key && array_key_exists('string', $api_key)) {
|
|
|
|
|
165 |
$params['Firewall.APIKeyVisibility'] = 'visible';
|
166 |
$params['Firewall.APIKeyFormVisibility'] = 'hidden';
|
167 |
$params['Firewall.APIKey'] = $api_key['string'];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
168 |
}
|
169 |
|
170 |
return SucuriScanTemplate::getSection('firewall-settings', $params);
|
180 |
*/
|
181 |
public static function settingsExplanation($settings = array())
|
182 |
{
|
183 |
+
if (!is_array($settings)) {
|
184 |
+
return array(/* empty */);
|
185 |
+
}
|
186 |
+
|
187 |
$cache_modes = array(
|
188 |
'docache' => __('FirewallDoCache', SUCURISCAN_TEXTDOMAIN),
|
189 |
'sitecache' => __('FirewallSiteCache', SUCURISCAN_TEXTDOMAIN),
|
191 |
'nocacheatall' => __('FirewallNoCacheAtAll', SUCURISCAN_TEXTDOMAIN),
|
192 |
);
|
193 |
|
|
|
|
|
|
|
194 |
foreach ($settings as $keyname => $value) {
|
195 |
if ($keyname == 'proxy_active') {
|
196 |
$settings[$keyname] = ($value === 1)
|
208 |
return $settings;
|
209 |
}
|
210 |
|
211 |
+
/**
|
212 |
+
* Returns the public firewall settings.
|
213 |
+
*
|
214 |
+
* @codeCoverageIgnore
|
215 |
+
*/
|
216 |
+
public static function getSettingsAjax()
|
217 |
+
{
|
218 |
+
if (SucuriScanRequest::post('form_action') !== 'firewall_settings') {
|
219 |
+
return;
|
220 |
+
}
|
221 |
+
|
222 |
+
$response = array();
|
223 |
+
$response['ok'] = false;
|
224 |
+
$api_key = self::getKey();
|
225 |
+
|
226 |
+
ob_start();
|
227 |
+
$settings = self::settings($api_key);
|
228 |
+
$error = ob_get_clean();
|
229 |
+
|
230 |
+
if (!$settings) {
|
231 |
+
if (empty($error)) {
|
232 |
+
ob_start();
|
233 |
+
SucuriScanInterface::error(__('FirewallAPIKeyMissing', SUCURISCAN_TEXTDOMAIN));
|
234 |
+
$response['error'] = ob_get_clean();
|
235 |
+
} else {
|
236 |
+
$response['error'] = $error;
|
237 |
+
}
|
238 |
+
|
239 |
+
wp_send_json($response, 200);
|
240 |
+
}
|
241 |
+
|
242 |
+
$response['ok'] = true;
|
243 |
+
$response['settings'] = self::settingsExplanation($settings);
|
244 |
+
unset($response['settings']['whitelist_list']);
|
245 |
+
unset($response['settings']['blacklist_list']);
|
246 |
+
|
247 |
+
wp_send_json($response, 200);
|
248 |
+
}
|
249 |
+
|
250 |
/**
|
251 |
* Retrieve the audit logs of the account associated with the API keys
|
252 |
* registered b the administrator of the site. This method will send a HTTP
|
294 |
$params = array();
|
295 |
|
296 |
/* logs are available after 24 hours */
|
297 |
+
$date = SucuriScan::datetime(strtotime('-1 day'), 'Y-m-d');
|
298 |
|
299 |
$params['AuditLogs.DateYears'] = self::dates('years', $date);
|
300 |
$params['AuditLogs.DateMonths'] = self::dates('months', $date);
|
319 |
return;
|
320 |
}
|
321 |
|
322 |
+
$response = '';
|
323 |
+
$api_key = self::getKey();
|
324 |
|
325 |
+
if (!$api_key) {
|
326 |
+
ob_start();
|
327 |
+
SucuriScanInterface::error(__('FirewallAPIKeyMissing', SUCURISCAN_TEXTDOMAIN));
|
328 |
+
$response = ob_get_clean();
|
329 |
+
wp_send_json($response, 200);
|
330 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
331 |
|
332 |
+
$query = SucuriScanRequest::post(':query');
|
333 |
+
$month = SucuriScanRequest::post(':month');
|
334 |
+
$year = SucuriScanRequest::post(':year');
|
335 |
+
$day = SucuriScanRequest::post(':day');
|
336 |
+
$limit = 50;
|
337 |
+
$offset = 1;
|
|
|
338 |
|
339 |
+
if ($year && $month && $day) {
|
340 |
+
$date = sprintf('%s-%s-%s', $year, $month, $day);
|
341 |
+
} else {
|
342 |
+
$date = SucuriScan::datetime(null, 'Y-m-d');
|
343 |
+
}
|
344 |
|
345 |
+
ob_start();
|
346 |
+
$auditlogs = self::auditlogs(
|
347 |
+
$api_key,
|
348 |
+
$date, /* Retrieve the data from this date. */
|
349 |
+
$query, /* Filter the data to match this query. */
|
350 |
+
$limit, /* Retrieve this maximum of data. */
|
351 |
+
$offset /* Retrieve the data from this point. */
|
352 |
+
);
|
353 |
+
$error = ob_get_clean();
|
354 |
+
|
355 |
+
if (!$auditlogs && !empty($error)) {
|
356 |
+
wp_send_json($error, 200);
|
357 |
+
}
|
358 |
+
|
359 |
+
if ($auditlogs && array_key_exists('total_lines', $auditlogs)) {
|
360 |
+
$response = self::auditlogsEntries($auditlogs['access_logs']);
|
361 |
+
|
362 |
+
if (empty($response)) {
|
363 |
+
$response = '<tr><td>' . __('NoData', SUCURISCAN_TEXTDOMAIN) . '.</td></tr>';
|
364 |
}
|
|
|
|
|
|
|
|
|
365 |
}
|
366 |
|
367 |
wp_send_json($response, 200);
|
455 |
switch ($type) {
|
456 |
case 'years':
|
457 |
$selected = $s_year;
|
458 |
+
$current_year = (int) SucuriScan::datetime(null, 'Y');
|
459 |
$max_years = 5; /* Maximum number of years to keep the logs. */
|
460 |
$options = range(($current_year - $max_years), $current_year);
|
461 |
break;
|
462 |
+
|
463 |
case 'months':
|
464 |
$selected = $s_month;
|
465 |
$options = array(
|
477 |
'12' => __('December', SUCURISCAN_TEXTDOMAIN),
|
478 |
);
|
479 |
break;
|
480 |
+
|
481 |
case 'days':
|
482 |
$options = range(1, 31);
|
483 |
$selected = $s_day;
|
506 |
return $options;
|
507 |
}
|
508 |
|
509 |
+
/**
|
510 |
+
* Generate the HTML code for the firewall IP access panel.
|
511 |
+
*
|
512 |
+
* @return string The parsed-content of the firewall IP access panel.
|
513 |
+
*/
|
514 |
+
public static function ipAccessPage()
|
515 |
+
{
|
516 |
+
$params = array();
|
517 |
+
|
518 |
+
return SucuriScanTemplate::getSection('firewall-ipaccess', $params);
|
519 |
+
}
|
520 |
+
|
521 |
+
/**
|
522 |
+
* Returns the whitelisted and blacklisted IP addresses.
|
523 |
+
*
|
524 |
+
* @codeCoverageIgnore
|
525 |
+
*/
|
526 |
+
public static function ipAccessAjax()
|
527 |
+
{
|
528 |
+
if (SucuriScanRequest::post('form_action') !== 'firewall_ipaccess') {
|
529 |
+
return;
|
530 |
+
}
|
531 |
+
|
532 |
+
$response = array();
|
533 |
+
$response['ok'] = false;
|
534 |
+
$api_key = self::getKey();
|
535 |
+
|
536 |
+
ob_start();
|
537 |
+
$settings = self::settings($api_key);
|
538 |
+
$error = ob_get_clean();
|
539 |
+
|
540 |
+
if (!$settings) {
|
541 |
+
if (empty($error)) {
|
542 |
+
ob_start();
|
543 |
+
SucuriScanInterface::error(__('FirewallAPIKeyMissing', SUCURISCAN_TEXTDOMAIN));
|
544 |
+
$response['error'] = ob_get_clean();
|
545 |
+
} else {
|
546 |
+
$response['error'] = $error;
|
547 |
+
}
|
548 |
+
|
549 |
+
wp_send_json($response, 200);
|
550 |
+
}
|
551 |
+
|
552 |
+
$response['ok'] = true;
|
553 |
+
$response['whitelist'] = $settings['whitelist_list'];
|
554 |
+
$response['blacklist'] = $settings['blacklist_list'];
|
555 |
+
|
556 |
+
wp_send_json($response, 200);
|
557 |
+
}
|
558 |
+
|
559 |
+
/**
|
560 |
+
* Blacklists an IP address.
|
561 |
+
*
|
562 |
+
* @codeCoverageIgnore
|
563 |
+
*/
|
564 |
+
public static function blacklistAjax()
|
565 |
+
{
|
566 |
+
if (SucuriScanRequest::post('form_action') !== 'firewall_blacklist') {
|
567 |
+
return;
|
568 |
+
}
|
569 |
+
|
570 |
+
$response = array();
|
571 |
+
$response['ok'] = false;
|
572 |
+
$params = self::getKey();
|
573 |
+
|
574 |
+
if (!$params) {
|
575 |
+
ob_start();
|
576 |
+
SucuriScanInterface::error(__('FirewallAPIKeyMissing', SUCURISCAN_TEXTDOMAIN));
|
577 |
+
$response['msg'] = ob_get_clean();
|
578 |
+
wp_send_json($response, 200);
|
579 |
+
}
|
580 |
+
|
581 |
+
$params['a'] = 'blacklist_ip';
|
582 |
+
$params['ip'] = SucuriScanRequest::post('ip');
|
583 |
+
$out = self::apiCallFirewall('POST', $params);
|
584 |
+
$response['msg'] = 'Failure connecting to the API service; try again.';
|
585 |
+
|
586 |
+
if ($out && !empty($out['messages'])) {
|
587 |
+
$response['ok'] = (bool) ($out['status'] == 1);
|
588 |
+
$response['msg'] = implode(";\x20", $out['messages']);
|
589 |
+
|
590 |
+
if ($out['status'] == 1) {
|
591 |
+
SucuriScanEvent::reportInfoEvent(
|
592 |
+
'IP has been blacklisted: ' . $params['ip']);
|
593 |
+
}
|
594 |
+
}
|
595 |
+
|
596 |
+
wp_send_json($response, 200);
|
597 |
+
}
|
598 |
+
|
599 |
+
/**
|
600 |
+
* Deletes an IP address from the blacklist.
|
601 |
+
*
|
602 |
+
* @codeCoverageIgnore
|
603 |
+
*/
|
604 |
+
public static function deblacklistAjax()
|
605 |
+
{
|
606 |
+
if (SucuriScanRequest::post('form_action') !== 'firewall_deblacklist') {
|
607 |
+
return;
|
608 |
+
}
|
609 |
+
|
610 |
+
$response = array();
|
611 |
+
$params = self::getKey();
|
612 |
+
|
613 |
+
if (!$params) {
|
614 |
+
ob_start();
|
615 |
+
$response['ok'] = false;
|
616 |
+
SucuriScanInterface::error(__('FirewallAPIKeyMissing', SUCURISCAN_TEXTDOMAIN));
|
617 |
+
$response['error'] = ob_get_clean();
|
618 |
+
wp_send_json($response, 200);
|
619 |
+
}
|
620 |
+
|
621 |
+
$params['a'] = 'delete_blacklist_ip';
|
622 |
+
$params['ip'] = SucuriScanRequest::post('ip');
|
623 |
+
$out = self::apiCallFirewall('POST', $params);
|
624 |
+
|
625 |
+
$response['ok'] = (bool) ($out['status'] == 1);
|
626 |
+
$response['msg'] = implode(";\x20", $out['messages']);
|
627 |
+
|
628 |
+
if ($out['status'] == 1) {
|
629 |
+
SucuriScanEvent::reportInfoEvent(
|
630 |
+
'IP has been unblacklisted: ' . $params['ip']);
|
631 |
+
}
|
632 |
+
|
633 |
+
wp_send_json($response, 200);
|
634 |
+
}
|
635 |
+
|
636 |
/**
|
637 |
* Flush the cache of the site(s) associated with the API key.
|
638 |
*
|
663 |
{
|
664 |
$params = array();
|
665 |
|
666 |
+
$params['FirewallAutoClearCache'] =
|
667 |
+
SucuriScanOption::isEnabled(':auto_clear_cache')
|
668 |
+
? 'checked="checked"' : 'data-status="disabled"';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
669 |
|
670 |
return SucuriScanTemplate::getSection('firewall-clearcache', $params);
|
671 |
}
|
679 |
* of certain files is going to stay as it is due to the configuration on the
|
680 |
* edge of the servers.
|
681 |
*
|
682 |
+
* @param array $data The post metadata.
|
683 |
+
*/
|
684 |
+
public static function clearCacheHook($data)
|
685 |
+
{
|
686 |
+
if (SucuriScanOption::isEnabled(':auto_clear_cache')) {
|
687 |
+
ob_start();
|
688 |
+
self::clearCache();
|
689 |
+
$error = ob_get_clean();
|
690 |
+
}
|
691 |
+
}
|
692 |
+
|
693 |
+
/**
|
694 |
+
* Requests a cache flush to the firewall service.
|
695 |
+
*
|
696 |
+
* @codeCoverageIgnore
|
697 |
+
*/
|
698 |
+
public static function clearCacheAjax()
|
699 |
+
{
|
700 |
+
if (SucuriScanRequest::post('form_action') !== 'firewall_clear_cache') {
|
701 |
+
return;
|
702 |
+
}
|
703 |
+
|
704 |
+
ob_start();
|
705 |
+
SucuriScanInterface::error(__('FirewallAPIKeyMissing', SUCURISCAN_TEXTDOMAIN));
|
706 |
+
$response = ob_get_clean();
|
707 |
+
|
708 |
+
if ($api_key = self::getKey()) {
|
709 |
+
$res = self::clearCache($api_key);
|
710 |
+
|
711 |
+
if (is_array($res) && isset($res['messages'])) {
|
712 |
+
$response = sprintf(
|
713 |
+
'<div class="sucuriscan-inline-alert-%s"><p>%s</p></div>',
|
714 |
+
($res['status'] == 1) ? 'success' : 'error',
|
715 |
+
implode('<br>', $res['messages'])
|
716 |
+
);
|
717 |
+
}
|
718 |
+
}
|
719 |
+
|
720 |
+
wp_send_json($response, 200);
|
721 |
+
}
|
722 |
+
|
723 |
+
/**
|
724 |
+
* Configures the status of the automatic cache flush.
|
725 |
+
*
|
726 |
+
* @codeCoverageIgnore
|
727 |
*/
|
728 |
+
public static function clearAutoCacheAjax()
|
729 |
{
|
730 |
+
if (SucuriScanRequest::post('form_action') !== 'firewall_auto_clear_cache') {
|
731 |
+
return;
|
732 |
+
}
|
733 |
+
|
734 |
+
$response = array();
|
735 |
+
|
736 |
+
if (SucuriScanRequest::post('auto_clear_cache') === 'enable') {
|
737 |
+
$response['ok'] = SucuriScanOption::updateOption(':auto_clear_cache', 'enabled');
|
738 |
+
$response['status'] = 'enabled';
|
739 |
+
} else {
|
740 |
+
$response['ok'] = SucuriScanOption::deleteOption(':auto_clear_cache');
|
741 |
+
$response['status'] = 'disabled';
|
742 |
}
|
743 |
+
|
744 |
+
wp_send_json($response, 200);
|
745 |
}
|
746 |
}
|
src/fsscanner.lib.php
CHANGED
@@ -60,7 +60,7 @@ class SucuriScanFSScanner extends SucuriScan
|
|
60 |
$resource_type = SucuriScanFileInfo::getResourceType($path);
|
61 |
$cache_value = array(
|
62 |
'directory_path' => $path,
|
63 |
-
'ignored_at' =>
|
64 |
'resource_type' => $resource_type,
|
65 |
);
|
66 |
|
60 |
$resource_type = SucuriScanFileInfo::getResourceType($path);
|
61 |
$cache_value = array(
|
62 |
'directory_path' => $path,
|
63 |
+
'ignored_at' => time(),
|
64 |
'resource_type' => $resource_type,
|
65 |
);
|
66 |
|
src/globals.php
CHANGED
@@ -36,20 +36,6 @@ if (defined('SUCURISCAN')) {
|
|
36 |
*/
|
37 |
$sucuriscan_action_prefix = SucuriScan::isMultiSite() ? 'network_' : '';
|
38 |
|
39 |
-
/**
|
40 |
-
* Settings options.
|
41 |
-
*
|
42 |
-
* The following global variables are mostly associative arrays where the
|
43 |
-
* key is linked to an option that will be stored in the database, and their
|
44 |
-
* correspondent values are the description of the option. These variables
|
45 |
-
* will be used in the settings page to offer the user a way to configure
|
46 |
-
* the behaviour of the plugin.
|
47 |
-
*
|
48 |
-
* @var string
|
49 |
-
*/
|
50 |
-
$sucuriscan_date_format = get_option('date_format');
|
51 |
-
$sucuriscan_time_format = get_option('time_format');
|
52 |
-
|
53 |
/**
|
54 |
* Remove the WordPress generator meta-tag from the source code.
|
55 |
*/
|
@@ -76,7 +62,6 @@ if (defined('SUCURISCAN')) {
|
|
76 |
if (SucuriScan::runAdminInit()) {
|
77 |
add_action('admin_init', 'SucuriScanInterface::handleOldPlugins');
|
78 |
add_action('admin_init', 'SucuriScanInterface::createStorageFolder');
|
79 |
-
add_action('admin_init', 'SucuriScanInterface::noticeAfterUpdate');
|
80 |
}
|
81 |
|
82 |
/**
|
@@ -111,6 +96,7 @@ if (defined('SUCURISCAN')) {
|
|
111 |
{
|
112 |
global $locale;
|
113 |
|
|
|
114 |
$pofile = sprintf(
|
115 |
'%s/languages/%s-%s.po',
|
116 |
SUCURISCAN_PLUGIN_PATH,
|
@@ -126,15 +112,37 @@ if (defined('SUCURISCAN')) {
|
|
126 |
|
127 |
/* attempt to import the English POT file into LOCALE */
|
128 |
if (!file_exists($pofile) || !file_exists($mofile)) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
129 |
$en_pofile = sprintf(
|
130 |
-
'%s/languages/%s
|
131 |
SUCURISCAN_PLUGIN_PATH,
|
132 |
-
SUCURISCAN_TEXTDOMAIN
|
|
|
133 |
);
|
134 |
$en_mofile = sprintf(
|
135 |
-
'%s/languages/%s
|
136 |
SUCURISCAN_PLUGIN_PATH,
|
137 |
-
SUCURISCAN_TEXTDOMAIN
|
|
|
138 |
);
|
139 |
|
140 |
@copy($en_pofile, $pofile);
|
@@ -143,8 +151,8 @@ if (defined('SUCURISCAN')) {
|
|
143 |
|
144 |
/* fallback to English on language import failure */
|
145 |
if (!file_exists($pofile) || !file_exists($mofile)) {
|
146 |
-
$locale =
|
147 |
-
setlocale(LC_ALL,
|
148 |
}
|
149 |
|
150 |
load_plugin_textdomain(
|
@@ -247,15 +255,4 @@ if (defined('SUCURISCAN')) {
|
|
247 |
add_action('admin_init', 'SucuriScanHook::hookWidgetDelete');
|
248 |
}
|
249 |
}
|
250 |
-
|
251 |
-
/**
|
252 |
-
* Clear the firewall cache if necessary.
|
253 |
-
*
|
254 |
-
* Every time a page or post is modified and saved into the database the
|
255 |
-
* plugin will send a HTTP request to the firewall API service and except
|
256 |
-
* that, if the API key is valid, the cache is reset. Notice that the cache
|
257 |
-
* of certain files is going to stay as it is due to the configuration on the
|
258 |
-
* edge of the servers.
|
259 |
-
*/
|
260 |
-
add_action('save_post', 'SucuriScanFirewall::clearCacheHook');
|
261 |
}
|
36 |
*/
|
37 |
$sucuriscan_action_prefix = SucuriScan::isMultiSite() ? 'network_' : '';
|
38 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
39 |
/**
|
40 |
* Remove the WordPress generator meta-tag from the source code.
|
41 |
*/
|
62 |
if (SucuriScan::runAdminInit()) {
|
63 |
add_action('admin_init', 'SucuriScanInterface::handleOldPlugins');
|
64 |
add_action('admin_init', 'SucuriScanInterface::createStorageFolder');
|
|
|
65 |
}
|
66 |
|
67 |
/**
|
96 |
{
|
97 |
global $locale;
|
98 |
|
99 |
+
$default_locale = 'en_US';
|
100 |
$pofile = sprintf(
|
101 |
'%s/languages/%s-%s.po',
|
102 |
SUCURISCAN_PLUGIN_PATH,
|
112 |
|
113 |
/* attempt to import the English POT file into LOCALE */
|
114 |
if (!file_exists($pofile) || !file_exists($mofile)) {
|
115 |
+
$fallback = array(
|
116 |
+
'en_NZ' => 'en_US', /* English (New Zealand) */
|
117 |
+
'en_CA' => 'en_US', /* English (Canada) */
|
118 |
+
'en_ZA' => 'en_US', /* English (South Africa) */
|
119 |
+
'en_GB' => 'en_US', /* English (UK) */
|
120 |
+
'en_AU' => 'en_US', /* English (Australia) */
|
121 |
+
'es_AR' => 'es_ES', /* Español de Argentina */
|
122 |
+
'es_MX' => 'es_ES', /* Español de México */
|
123 |
+
'es_CO' => 'es_ES', /* Español de Colombia */
|
124 |
+
'es_GT' => 'es_ES', /* Español de Guatemala */
|
125 |
+
'es_VE' => 'es_ES', /* Español de Venezuela */
|
126 |
+
'es_CL' => 'es_ES', /* Español de Chile */
|
127 |
+
'es_PE' => 'es_ES', /* Español de Perú */
|
128 |
+
);
|
129 |
+
|
130 |
+
/* try to find a similar translation */
|
131 |
+
if (array_key_exists($locale, $fallback)) {
|
132 |
+
$default_locale = $fallback[$locale];
|
133 |
+
}
|
134 |
+
|
135 |
$en_pofile = sprintf(
|
136 |
+
'%s/languages/%s-%s.po',
|
137 |
SUCURISCAN_PLUGIN_PATH,
|
138 |
+
SUCURISCAN_TEXTDOMAIN,
|
139 |
+
$default_locale
|
140 |
);
|
141 |
$en_mofile = sprintf(
|
142 |
+
'%s/languages/%s-%s.mo',
|
143 |
SUCURISCAN_PLUGIN_PATH,
|
144 |
+
SUCURISCAN_TEXTDOMAIN,
|
145 |
+
$default_locale
|
146 |
);
|
147 |
|
148 |
@copy($en_pofile, $pofile);
|
151 |
|
152 |
/* fallback to English on language import failure */
|
153 |
if (!file_exists($pofile) || !file_exists($mofile)) {
|
154 |
+
$locale = $default_locale;
|
155 |
+
setlocale(LC_ALL, $default_locale);
|
156 |
}
|
157 |
|
158 |
load_plugin_textdomain(
|
255 |
add_action('admin_init', 'SucuriScanHook::hookWidgetDelete');
|
256 |
}
|
257 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
258 |
}
|
src/hook.lib.php
CHANGED
@@ -151,15 +151,20 @@ class SucuriScanHook extends SucuriScanEvent
|
|
151 |
{
|
152 |
$password = SucuriScanRequest::post('pwd');
|
153 |
$title = empty($title) ? 'Unknown' : sanitize_user($title, true);
|
154 |
-
$message = 'User authentication failed: ' . $title
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
155 |
|
156 |
self::reportErrorEvent($message);
|
157 |
|
158 |
self::notifyEvent('failed_login', $message);
|
159 |
|
160 |
-
/* log the failed login in the internal storage */
|
161 |
-
sucuriscan_log_failed_login($title, $password);
|
162 |
-
|
163 |
/* report brute-force attack if necessary */
|
164 |
if ($logins = sucuriscan_get_failed_logins()) {
|
165 |
$max_time = 3600; /* report logins in the last hour */
|
@@ -281,7 +286,7 @@ class SucuriScanHook extends SucuriScanEvent
|
|
281 |
|
282 |
if ($options_changed_count) {
|
283 |
$message = $page_referer . ' settings changed';
|
284 |
-
|
285 |
'%s: (multiple entries): %s',
|
286 |
$message,
|
287 |
rtrim($options_changed_simple, ',')
|
@@ -443,7 +448,7 @@ class SucuriScanHook extends SucuriScanEvent
|
|
443 |
|
444 |
$plugin = $plugin ? $plugin : 'Unknown';
|
445 |
$message = 'Plugin installed: ' . self::escape($plugin);
|
446 |
-
|
447 |
self::notifyEvent('plugin_installed', $message);
|
448 |
}
|
449 |
}
|
@@ -577,7 +582,7 @@ class SucuriScanHook extends SucuriScanEvent
|
|
577 |
|
578 |
/* ignore; the same */
|
579 |
if ($old === $new) {
|
580 |
-
return;
|
581 |
}
|
582 |
|
583 |
$post_type = 'post'; /* either post or page */
|
@@ -586,11 +591,35 @@ class SucuriScanHook extends SucuriScanEvent
|
|
586 |
$post_type = $post->post_type;
|
587 |
}
|
588 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
589 |
/* check if email alerts are disabled for this type */
|
590 |
if (SucuriScanOption::isIgnoredEvent($post_type)) {
|
591 |
return self::throwException('Skip events for ignored post-types');
|
592 |
}
|
593 |
|
|
|
|
|
|
|
|
|
|
|
|
|
594 |
$pieces = array();
|
595 |
$post_type = ucwords($post_type);
|
596 |
|
@@ -654,6 +683,8 @@ class SucuriScanHook extends SucuriScanEvent
|
|
654 |
if ($data->post_date === $data->post_modified) {
|
655 |
$action = 'created';
|
656 |
}
|
|
|
|
|
657 |
}
|
658 |
|
659 |
$message = sprintf(
|
@@ -734,7 +765,7 @@ class SucuriScanHook extends SucuriScanEvent
|
|
734 |
$theme = $theme ? $theme : 'Unknown';
|
735 |
|
736 |
$message = 'Theme deleted: ' . self::escape($theme);
|
737 |
-
|
738 |
self::notifyEvent('theme_deleted', $message);
|
739 |
}
|
740 |
}
|
@@ -772,7 +803,7 @@ class SucuriScanHook extends SucuriScanEvent
|
|
772 |
$theme = $theme ? $theme : 'Unknown';
|
773 |
|
774 |
$message = 'Theme installed: ' . self::escape($theme);
|
775 |
-
|
776 |
self::notifyEvent('theme_installed', $message);
|
777 |
}
|
778 |
}
|
151 |
{
|
152 |
$password = SucuriScanRequest::post('pwd');
|
153 |
$title = empty($title) ? 'Unknown' : sanitize_user($title, true);
|
154 |
+
$message = 'User authentication failed: ' . $title;
|
155 |
+
|
156 |
+
/* send the submitted password along with the alert */
|
157 |
+
if (SucuriScanOption::isEnabled(':notify_failed_password')) {
|
158 |
+
$message .= '; password: ' . $password;
|
159 |
+
sucuriscan_log_failed_login($title, $password);
|
160 |
+
} else {
|
161 |
+
sucuriscan_log_failed_login($title, '[hidden]');
|
162 |
+
}
|
163 |
|
164 |
self::reportErrorEvent($message);
|
165 |
|
166 |
self::notifyEvent('failed_login', $message);
|
167 |
|
|
|
|
|
|
|
168 |
/* report brute-force attack if necessary */
|
169 |
if ($logins = sucuriscan_get_failed_logins()) {
|
170 |
$max_time = 3600; /* report logins in the last hour */
|
286 |
|
287 |
if ($options_changed_count) {
|
288 |
$message = $page_referer . ' settings changed';
|
289 |
+
self::reportErrorEvent(sprintf(
|
290 |
'%s: (multiple entries): %s',
|
291 |
$message,
|
292 |
rtrim($options_changed_simple, ',')
|
448 |
|
449 |
$plugin = $plugin ? $plugin : 'Unknown';
|
450 |
$message = 'Plugin installed: ' . self::escape($plugin);
|
451 |
+
self::reportWarningEvent($message);
|
452 |
self::notifyEvent('plugin_installed', $message);
|
453 |
}
|
454 |
}
|
582 |
|
583 |
/* ignore; the same */
|
584 |
if ($old === $new) {
|
585 |
+
return self::throwException('Skip events for equal transitions');
|
586 |
}
|
587 |
|
588 |
$post_type = 'post'; /* either post or page */
|
591 |
$post_type = $post->post_type;
|
592 |
}
|
593 |
|
594 |
+
if ($post_type === 'postman_sent_mail') {
|
595 |
+
/**
|
596 |
+
* Stop infinite loop sending the email alerts.
|
597 |
+
*
|
598 |
+
* The plugin detects changes in the posts, there are some other
|
599 |
+
* plugins that intercept PHPMailer and create a post object that is
|
600 |
+
* later used to send the real message to the users. This object is
|
601 |
+
* also detected by our plugin and is considered an additional event
|
602 |
+
* that must be reported, so after the first execution the operation
|
603 |
+
* falls into an infinite loop.
|
604 |
+
*
|
605 |
+
* @date 30 June, 2017
|
606 |
+
* @see https://wordpress.org/plugins/postman-smtp/
|
607 |
+
* @see https://wordpress.org/support/topic/unable-to-access-wordpress-dashboard-after-update-to-1-8-7/
|
608 |
+
*/
|
609 |
+
return self::throwException('Skip events for postman-smtp alerts');
|
610 |
+
}
|
611 |
+
|
612 |
/* check if email alerts are disabled for this type */
|
613 |
if (SucuriScanOption::isIgnoredEvent($post_type)) {
|
614 |
return self::throwException('Skip events for ignored post-types');
|
615 |
}
|
616 |
|
617 |
+
/* check if email alerts are disabled for this transition */
|
618 |
+
$custom_type = sprintf('from_%s_to_%s', $old, $new);
|
619 |
+
if (SucuriScanOption::isIgnoredEvent($custom_type)) {
|
620 |
+
return self::throwException('Skip events for ignored post transitions');
|
621 |
+
}
|
622 |
+
|
623 |
$pieces = array();
|
624 |
$post_type = ucwords($post_type);
|
625 |
|
683 |
if ($data->post_date === $data->post_modified) {
|
684 |
$action = 'created';
|
685 |
}
|
686 |
+
|
687 |
+
SucuriScanFirewall::clearCacheHook($data);
|
688 |
}
|
689 |
|
690 |
$message = sprintf(
|
765 |
$theme = $theme ? $theme : 'Unknown';
|
766 |
|
767 |
$message = 'Theme deleted: ' . self::escape($theme);
|
768 |
+
self::reportWarningEvent($message);
|
769 |
self::notifyEvent('theme_deleted', $message);
|
770 |
}
|
771 |
}
|
803 |
$theme = $theme ? $theme : 'Unknown';
|
804 |
|
805 |
$message = 'Theme installed: ' . self::escape($theme);
|
806 |
+
self::reportWarningEvent($message);
|
807 |
self::notifyEvent('theme_installed', $message);
|
808 |
}
|
809 |
}
|
src/integrity.lib.php
CHANGED
@@ -117,57 +117,76 @@ class SucuriScanIntegrity
|
|
117 |
return SucuriScanInterface::error(__('NothingSelected', SUCURISCAN_TEXTDOMAIN));
|
118 |
}
|
119 |
|
|
|
|
|
|
|
|
|
|
|
|
|
120 |
foreach ((array) $core_files as $file_meta) {
|
121 |
-
if (strpos($file_meta, '@')) {
|
122 |
-
|
|
|
123 |
|
124 |
-
|
125 |
-
|
126 |
-
|
|
|
|
|
|
|
127 |
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
143 |
$files_affected[] = $full_path;
|
144 |
-
|
145 |
}
|
|
|
|
|
146 |
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
@mkdir($basedir, 0755, true);
|
154 |
|
155 |
-
|
156 |
-
|
157 |
-
$files_processed += ($restored ? 1 : 0);
|
158 |
-
$files_affected[] = $full_path;
|
159 |
-
}
|
160 |
}
|
161 |
-
continue;
|
162 |
-
}
|
163 |
|
164 |
-
|
165 |
-
if (@unlink($full_path)) {
|
166 |
-
$files_processed += 1;
|
167 |
$files_affected[] = $full_path;
|
|
|
168 |
}
|
169 |
-
continue;
|
170 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
171 |
}
|
172 |
}
|
173 |
|
@@ -197,6 +216,10 @@ class SucuriScanIntegrity
|
|
197 |
}
|
198 |
}
|
199 |
|
|
|
|
|
|
|
|
|
200 |
if ($files_processed != $files_selected) {
|
201 |
return SucuriScanInterface::error(sprintf(
|
202 |
__('SomeItemsProcessed', SUCURISCAN_TEXTDOMAIN),
|
@@ -231,7 +254,6 @@ class SucuriScanIntegrity
|
|
231 |
{
|
232 |
$params = array();
|
233 |
$affected_files = 0;
|
234 |
-
$siteVersion = SucuriScan::siteVersion();
|
235 |
|
236 |
$params['Version'] = SucuriScan::siteVersion();
|
237 |
$params['Integrity.List'] = '';
|
@@ -241,91 +263,84 @@ class SucuriScanIntegrity
|
|
241 |
$params['Integrity.GoodVisibility'] = 'hidden';
|
242 |
$params['Integrity.FailureVisibility'] = 'visible';
|
243 |
$params['Integrity.FalsePositivesVisibility'] = 'hidden';
|
|
|
|
|
|
|
|
|
|
|
244 |
|
245 |
-
|
246 |
-
|
|
|
|
|
247 |
|
248 |
-
|
249 |
-
|
250 |
-
$
|
251 |
-
$language = SucuriScanOption::getOption(':language');
|
252 |
-
$params['Integrity.RemoteChecksumsURL'] =
|
253 |
-
'https://api.wordpress.org/core/checksums/1.0/'
|
254 |
-
. '?version=' . $siteVersion . '&locale=' . $language;
|
255 |
|
256 |
-
|
257 |
-
$
|
258 |
-
|
259 |
-
|
260 |
|
261 |
-
$
|
262 |
-
|
263 |
-
|
264 |
|
265 |
-
|
266 |
-
|
|
|
|
|
267 |
continue;
|
268 |
}
|
269 |
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
if ($ignored_files /* skip files marked as fixed */
|
275 |
-
&& array_key_exists(md5($file_path), $ignored_files)
|
276 |
-
) {
|
277 |
-
$params['Integrity.FalsePositivesVisibility'] = 'visible';
|
278 |
-
continue;
|
279 |
-
}
|
280 |
-
|
281 |
-
// Add extra information to the file list.
|
282 |
-
$file_size = @filesize($full_filepath);
|
283 |
-
$file_size_human = ''; /* empty */
|
284 |
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
|
289 |
-
|
290 |
-
|
291 |
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
}
|
299 |
-
}
|
300 |
-
|
301 |
-
// Pretty-print the file size in human-readable form.
|
302 |
-
if ($file_size !== false) {
|
303 |
-
$file_size_human = SucuriScan::humanFileSize($file_size);
|
304 |
}
|
|
|
305 |
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
'Integrity.StatusType' => $list_type,
|
310 |
-
'Integrity.FilePath' => $file_path,
|
311 |
-
'Integrity.FileSize' => $file_size,
|
312 |
-
'Integrity.FileSizeHuman' => $file_size_human,
|
313 |
-
'Integrity.FileSizeNumber' => number_format($file_size),
|
314 |
-
'Integrity.ModifiedAt' => SucuriScan::datetime($file_info['modified_at']),
|
315 |
-
'Integrity.ErrorVisibility' => $visibility,
|
316 |
-
'Integrity.ErrorMessage' => $error,
|
317 |
-
));
|
318 |
-
$affected_files++;
|
319 |
-
$counter++;
|
320 |
}
|
321 |
-
}
|
322 |
|
323 |
-
|
324 |
-
$params['Integrity.
|
325 |
-
|
326 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
327 |
}
|
328 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
329 |
}
|
330 |
|
331 |
if ($send_email === true) {
|
@@ -398,11 +413,9 @@ class SucuriScanIntegrity
|
|
398 |
return;
|
399 |
}
|
400 |
|
401 |
-
$version = SucuriScan::siteVersion();
|
402 |
-
$filepath = SucuriScanRequest::post('filepath');
|
403 |
-
|
404 |
ob_start();
|
405 |
-
|
|
|
406 |
$response = ob_get_clean();
|
407 |
|
408 |
wp_send_json($response, 200);
|
@@ -440,12 +453,11 @@ class SucuriScanIntegrity
|
|
440 |
* <li>added: Files present in the local project but not in the official WordPress packages.</li>
|
441 |
* </ul>
|
442 |
*
|
443 |
-
* @param string|int $version Valid version number of the WordPress project.
|
444 |
* @return array|bool Associative array with these keys: modified, stable, removed, added.
|
445 |
*/
|
446 |
-
private static function checkIntegrityIntegrity(
|
447 |
{
|
448 |
-
$latest_hashes = SucuriScanAPI::getOfficialChecksums(
|
449 |
$base_content_dir = defined('WP_CONTENT_DIR')
|
450 |
? basename(rtrim(WP_CONTENT_DIR, '/'))
|
451 |
: '';
|
@@ -468,6 +480,7 @@ class SucuriScanIntegrity
|
|
468 |
$wp_admin_hashes = self::integrityTree(ABSPATH . 'wp-admin', true);
|
469 |
$wp_includes_hashes = self::integrityTree(ABSPATH . 'wp-includes', true);
|
470 |
$wp_core_hashes = array_merge($wp_top_hashes, $wp_admin_hashes, $wp_includes_hashes);
|
|
|
471 |
|
472 |
// Compare remote and local checksums and search removed files.
|
473 |
foreach ($latest_hashes as $file_path => $remote) {
|
@@ -491,7 +504,17 @@ class SucuriScanIntegrity
|
|
491 |
|
492 |
// Check whether the official file exists or not.
|
493 |
if (file_exists($full_filepath)) {
|
494 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
495 |
|
496 |
if ($local !== false && $local === $remote) {
|
497 |
$output['stable'][] = array(
|
@@ -550,10 +573,69 @@ class SucuriScanIntegrity
|
|
550 |
*/
|
551 |
private static function ignoreIntegrityFilepath($path = '')
|
552 |
{
|
553 |
-
|
554 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
555 |
'^sucuri-[0-9a-z\-]+\.php$',
|
556 |
'^\S+-sucuri-db-dump-gzip-[0-9]{10}-[0-9a-z]{32}\.gz$',
|
|
|
557 |
'^([^\/]*)\.(pdf|css|txt|jpg|gif|png|jpeg)$',
|
558 |
'^wp-content\/(themes|plugins)\/.+',
|
559 |
'^google[0-9a-z]{16}\.html$',
|
@@ -561,107 +643,13 @@ class SucuriScanIntegrity
|
|
561 |
'\.ico$',
|
562 |
);
|
563 |
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
}
|
569 |
}
|
570 |
|
571 |
-
return
|
572 |
-
}
|
573 |
-
|
574 |
-
/**
|
575 |
-
* Includes some irrelevant files into the integrity cache.
|
576 |
-
*/
|
577 |
-
private static function ignoreIrrelevantFiles()
|
578 |
-
{
|
579 |
-
global $wp_local_package;
|
580 |
-
|
581 |
-
if (SucuriScanOption::getOption(':integrity_startup') !== 'done') {
|
582 |
-
/* ignore files no matter if they do not exist */
|
583 |
-
self::ignoreIrrelevantFile('php.ini', false);
|
584 |
-
self::ignoreIrrelevantFile('.htaccess', false);
|
585 |
-
self::ignoreIrrelevantFile('.htpasswd', false);
|
586 |
-
self::ignoreIrrelevantFile('.ftpquota', false);
|
587 |
-
self::ignoreIrrelevantFile('wp-includes/.htaccess', false);
|
588 |
-
self::ignoreIrrelevantFile('wp-admin/setup-config.php', false);
|
589 |
-
self::ignoreIrrelevantFile('wp-config.php', false);
|
590 |
-
self::ignoreIrrelevantFile('sitemap.xml', false);
|
591 |
-
self::ignoreIrrelevantFile('sitemap.xml.gz', false);
|
592 |
-
self::ignoreIrrelevantFile('readme.html', false);
|
593 |
-
self::ignoreIrrelevantFile('error_log', false);
|
594 |
-
|
595 |
-
/* ignore irrelevant files only if they exist */
|
596 |
-
self::ignoreIrrelevantFile('wp-pass.php');
|
597 |
-
self::ignoreIrrelevantFile('wp-rss.php');
|
598 |
-
self::ignoreIrrelevantFile('wp-feed.php');
|
599 |
-
self::ignoreIrrelevantFile('wp-register.php');
|
600 |
-
self::ignoreIrrelevantFile('wp-atom.php');
|
601 |
-
self::ignoreIrrelevantFile('wp-commentsrss2.php');
|
602 |
-
self::ignoreIrrelevantFile('wp-rss2.php');
|
603 |
-
self::ignoreIrrelevantFile('wp-rdf.php');
|
604 |
-
self::ignoreIrrelevantFile('404.php');
|
605 |
-
self::ignoreIrrelevantFile('503.php');
|
606 |
-
self::ignoreIrrelevantFile('500.php');
|
607 |
-
self::ignoreIrrelevantFile('500.shtml');
|
608 |
-
self::ignoreIrrelevantFile('400.shtml');
|
609 |
-
self::ignoreIrrelevantFile('401.shtml');
|
610 |
-
self::ignoreIrrelevantFile('402.shtml');
|
611 |
-
self::ignoreIrrelevantFile('403.shtml');
|
612 |
-
self::ignoreIrrelevantFile('404.shtml');
|
613 |
-
self::ignoreIrrelevantFile('405.shtml');
|
614 |
-
self::ignoreIrrelevantFile('406.shtml');
|
615 |
-
self::ignoreIrrelevantFile('407.shtml');
|
616 |
-
self::ignoreIrrelevantFile('408.shtml');
|
617 |
-
self::ignoreIrrelevantFile('409.shtml');
|
618 |
-
self::ignoreIrrelevantFile('healthcheck.html');
|
619 |
-
|
620 |
-
/**
|
621 |
-
* Ignore i18n files.
|
622 |
-
*
|
623 |
-
* Sites with i18n have differences compared with the official English version
|
624 |
-
* of the project, basically they have files with new variables specifying the
|
625 |
-
* language that will be used in the admin panel, site options, and emails.
|
626 |
-
*/
|
627 |
-
if (isset($wp_local_package) && $wp_local_package != 'en_US') {
|
628 |
-
self::ignoreIrrelevantFile('wp-includes/version.php');
|
629 |
-
self::ignoreIrrelevantFile('wp-config-sample.php');
|
630 |
-
}
|
631 |
-
|
632 |
-
SucuriScanOption::updateOption(':integrity_startup', 'done');
|
633 |
-
}
|
634 |
-
}
|
635 |
-
|
636 |
-
/**
|
637 |
-
* Forces the integrity checker to ignore a file.
|
638 |
-
*
|
639 |
-
* The first time the WordPress integrity checker it will include some files
|
640 |
-
* into a storage file that will be used to skip these files during the next
|
641 |
-
* scans. This is to reduce the amount of false/positives. The website owner
|
642 |
-
* is free to add more files that are considered harmless, or stop ignoring
|
643 |
-
* these files from a tool available in the scanner section in the settings
|
644 |
-
* page.
|
645 |
-
*
|
646 |
-
* @param string $path Relative path to the file.
|
647 |
-
* @param bool $checkExistence Stop if the file does not exists.
|
648 |
-
* @return bool True if the file was ignored, false otherwise.
|
649 |
-
*/
|
650 |
-
private static function ignoreIrrelevantFile($path = '', $checkExistence = true)
|
651 |
-
{
|
652 |
-
if ($checkExistence && !file_exists(ABSPATH . '/' . $path)) {
|
653 |
-
return; /* skip if the file does not exists */
|
654 |
-
}
|
655 |
-
|
656 |
-
$cache = new SucuriScanCache('integrity');
|
657 |
-
|
658 |
-
$cache_key = md5($path);
|
659 |
-
$cache_value = array(
|
660 |
-
'file_path' => $path,
|
661 |
-
'file_status' => 'added',
|
662 |
-
'ignored_at' => time(),
|
663 |
-
);
|
664 |
-
|
665 |
-
return $cache->add($cache_key, $cache_value);
|
666 |
}
|
667 |
}
|
117 |
return SucuriScanInterface::error(__('NothingSelected', SUCURISCAN_TEXTDOMAIN));
|
118 |
}
|
119 |
|
120 |
+
/* process files until the maximum execution time is reached */
|
121 |
+
$startTime = microtime(true);
|
122 |
+
$displayTimeoutAlert = false;
|
123 |
+
$maxtime = (int) SucuriScan::iniGet('max_execution_time');
|
124 |
+
$timeout = ($maxtime > 1) ? ($maxtime - 6) : 30;
|
125 |
+
|
126 |
foreach ((array) $core_files as $file_meta) {
|
127 |
+
if (strpos($file_meta, '@') === false) {
|
128 |
+
continue;
|
129 |
+
}
|
130 |
|
131 |
+
/* avoid gateway timeout; max execution time */
|
132 |
+
$elapsedTime = (microtime(true) - $startTime);
|
133 |
+
if ($elapsedTime >= $timeout) {
|
134 |
+
$displayTimeoutAlert = true;
|
135 |
+
break;
|
136 |
+
}
|
137 |
|
138 |
+
@list($status_type, $file_path) = explode('@', $file_meta, 2);
|
139 |
+
|
140 |
+
if (!$file_path || !$status_type) {
|
141 |
+
continue;
|
142 |
+
}
|
143 |
+
|
144 |
+
$full_path = ABSPATH . '/' . $file_path;
|
145 |
+
|
146 |
+
if ($action === 'fixed' && (
|
147 |
+
$status_type === 'added'
|
148 |
+
|| $status_type === 'removed'
|
149 |
+
|| $status_type === 'modified'
|
150 |
+
)) {
|
151 |
+
$cache_key = md5($file_path);
|
152 |
+
$cache_value = array(
|
153 |
+
'file_path' => $file_path,
|
154 |
+
'file_status' => $status_type,
|
155 |
+
'ignored_at' => time(),
|
156 |
+
);
|
157 |
+
|
158 |
+
if ($cache->add($cache_key, $cache_value)) {
|
159 |
$files_affected[] = $full_path;
|
160 |
+
$files_processed++;
|
161 |
}
|
162 |
+
continue;
|
163 |
+
}
|
164 |
|
165 |
+
if ($action === 'restore' && (
|
166 |
+
$status_type === 'removed'
|
167 |
+
|| $status_type === 'modified'
|
168 |
+
)) {
|
169 |
+
if ($content = SucuriScanAPI::getOriginalCoreFile($file_path)) {
|
170 |
+
$basedir = dirname($full_path);
|
|
|
171 |
|
172 |
+
if (!file_exists($basedir)) {
|
173 |
+
@mkdir($basedir, 0755, true);
|
|
|
|
|
|
|
174 |
}
|
|
|
|
|
175 |
|
176 |
+
if (@file_put_contents($full_path, $content)) {
|
|
|
|
|
177 |
$files_affected[] = $full_path;
|
178 |
+
$files_processed++;
|
179 |
}
|
|
|
180 |
}
|
181 |
+
continue;
|
182 |
+
}
|
183 |
+
|
184 |
+
if ($action === 'delete' && $status_type === 'added') {
|
185 |
+
if (@unlink($full_path)) {
|
186 |
+
$files_affected[] = $full_path;
|
187 |
+
$files_processed++;
|
188 |
+
}
|
189 |
+
continue;
|
190 |
}
|
191 |
}
|
192 |
|
216 |
}
|
217 |
}
|
218 |
|
219 |
+
if ($displayTimeoutAlert) {
|
220 |
+
SucuriScanInterface::error(__('MaxExecutionTimeAlert', SUCURISCAN_TEXTDOMAIN));
|
221 |
+
}
|
222 |
+
|
223 |
if ($files_processed != $files_selected) {
|
224 |
return SucuriScanInterface::error(sprintf(
|
225 |
__('SomeItemsProcessed', SUCURISCAN_TEXTDOMAIN),
|
254 |
{
|
255 |
$params = array();
|
256 |
$affected_files = 0;
|
|
|
257 |
|
258 |
$params['Version'] = SucuriScan::siteVersion();
|
259 |
$params['Integrity.List'] = '';
|
263 |
$params['Integrity.GoodVisibility'] = 'hidden';
|
264 |
$params['Integrity.FailureVisibility'] = 'visible';
|
265 |
$params['Integrity.FalsePositivesVisibility'] = 'hidden';
|
266 |
+
$params['Integrity.DiffUtility'] = '';
|
267 |
+
|
268 |
+
// Check if there are added, removed, or modified files.
|
269 |
+
$latest_hashes = self::checkIntegrityIntegrity();
|
270 |
+
$params['Integrity.RemoteChecksumsURL'] = SucuriScanAPI::checksumAPI();
|
271 |
|
272 |
+
if ($latest_hashes) {
|
273 |
+
$cache = new SucuriScanCache('integrity');
|
274 |
+
$ignored_files = $cache->getAll();
|
275 |
+
$counter = 0;
|
276 |
|
277 |
+
$params['Integrity.BadVisibility'] = 'hidden';
|
278 |
+
$params['Integrity.GoodVisibility'] = 'visible';
|
279 |
+
$params['Integrity.FailureVisibility'] = 'hidden';
|
|
|
|
|
|
|
|
|
280 |
|
281 |
+
foreach ($latest_hashes as $list_type => $file_list) {
|
282 |
+
if ($list_type == 'stable' || empty($file_list)) {
|
283 |
+
continue;
|
284 |
+
}
|
285 |
|
286 |
+
foreach ($file_list as $file_info) {
|
287 |
+
$file_path = $file_info['filepath'];
|
288 |
+
$full_filepath = sprintf('%s/%s', rtrim(ABSPATH, '/'), $file_path);
|
289 |
|
290 |
+
if ($ignored_files /* skip files marked as fixed */
|
291 |
+
&& array_key_exists(md5($file_path), $ignored_files)
|
292 |
+
) {
|
293 |
+
$params['Integrity.FalsePositivesVisibility'] = 'visible';
|
294 |
continue;
|
295 |
}
|
296 |
|
297 |
+
// Add extra information to the file list.
|
298 |
+
$file_size = @filesize($full_filepath);
|
299 |
+
$file_size_human = ''; /* empty */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
300 |
|
301 |
+
/* error message if the file cannot be fixed */
|
302 |
+
$error = '';
|
303 |
+
$visibility = 'hidden';
|
304 |
|
305 |
+
if ($file_info['is_fixable'] !== true) {
|
306 |
+
$visibility = 'visible';
|
307 |
|
308 |
+
if ($list_type === 'added') {
|
309 |
+
$error = __('ErrorIntegrityAdded', SUCURISCAN_TEXTDOMAIN);
|
310 |
+
} elseif ($list_type === 'modified') {
|
311 |
+
$error = __('ErrorIntegrityModified', SUCURISCAN_TEXTDOMAIN);
|
312 |
+
} elseif ($list_type === 'removed') {
|
313 |
+
$error = __('ErrorIntegrityRemoved', SUCURISCAN_TEXTDOMAIN);
|
|
|
|
|
|
|
|
|
|
|
|
|
314 |
}
|
315 |
+
}
|
316 |
|
317 |
+
// Pretty-print the file size in human-readable form.
|
318 |
+
if ($file_size !== false) {
|
319 |
+
$file_size_human = SucuriScan::humanFileSize($file_size);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
320 |
}
|
|
|
321 |
|
322 |
+
// Generate the HTML code from the snippet template for this file.
|
323 |
+
$params['Integrity.List'] .=
|
324 |
+
SucuriScanTemplate::getSnippet('integrity-incorrect', array(
|
325 |
+
'Integrity.StatusType' => $list_type,
|
326 |
+
'Integrity.FilePath' => $file_path,
|
327 |
+
'Integrity.FileSize' => $file_size,
|
328 |
+
'Integrity.FileSizeHuman' => $file_size_human,
|
329 |
+
'Integrity.FileSizeNumber' => number_format($file_size),
|
330 |
+
'Integrity.ModifiedAt' => SucuriScan::datetime($file_info['modified_at']),
|
331 |
+
'Integrity.ErrorVisibility' => $visibility,
|
332 |
+
'Integrity.ErrorMessage' => $error,
|
333 |
+
));
|
334 |
+
$affected_files++;
|
335 |
+
$counter++;
|
336 |
}
|
337 |
}
|
338 |
+
|
339 |
+
if ($counter > 0) {
|
340 |
+
$params['Integrity.ListCount'] = $counter;
|
341 |
+
$params['Integrity.BadVisibility'] = 'visible';
|
342 |
+
$params['Integrity.GoodVisibility'] = 'hidden';
|
343 |
+
}
|
344 |
}
|
345 |
|
346 |
if ($send_email === true) {
|
413 |
return;
|
414 |
}
|
415 |
|
|
|
|
|
|
|
416 |
ob_start();
|
417 |
+
$filename = SucuriScanRequest::post('filepath');
|
418 |
+
print(SucuriScanCommand::diffHTML($filename));
|
419 |
$response = ob_get_clean();
|
420 |
|
421 |
wp_send_json($response, 200);
|
453 |
* <li>added: Files present in the local project but not in the official WordPress packages.</li>
|
454 |
* </ul>
|
455 |
*
|
|
|
456 |
* @return array|bool Associative array with these keys: modified, stable, removed, added.
|
457 |
*/
|
458 |
+
private static function checkIntegrityIntegrity()
|
459 |
{
|
460 |
+
$latest_hashes = SucuriScanAPI::getOfficialChecksums();
|
461 |
$base_content_dir = defined('WP_CONTENT_DIR')
|
462 |
? basename(rtrim(WP_CONTENT_DIR, '/'))
|
463 |
: '';
|
480 |
$wp_admin_hashes = self::integrityTree(ABSPATH . 'wp-admin', true);
|
481 |
$wp_includes_hashes = self::integrityTree(ABSPATH . 'wp-includes', true);
|
482 |
$wp_core_hashes = array_merge($wp_top_hashes, $wp_admin_hashes, $wp_includes_hashes);
|
483 |
+
$checksumAlgorithm = SucuriScanAPI::checksumAlgorithm();
|
484 |
|
485 |
// Compare remote and local checksums and search removed files.
|
486 |
foreach ($latest_hashes as $file_path => $remote) {
|
504 |
|
505 |
// Check whether the official file exists or not.
|
506 |
if (file_exists($full_filepath)) {
|
507 |
+
/* skip folders; cannot calculate a hash easily */
|
508 |
+
if (is_dir($full_filepath)) {
|
509 |
+
$output['stable'][] = array(
|
510 |
+
'filepath' => $file_path,
|
511 |
+
'is_fixable' => false,
|
512 |
+
'modified_at' => 0,
|
513 |
+
);
|
514 |
+
continue;
|
515 |
+
}
|
516 |
+
|
517 |
+
$local = SucuriScanAPI::checksum($checksumAlgorithm, $full_filepath);
|
518 |
|
519 |
if ($local !== false && $local === $remote) {
|
520 |
$output['stable'][] = array(
|
573 |
*/
|
574 |
private static function ignoreIntegrityFilepath($path = '')
|
575 |
{
|
576 |
+
global $wp_local_package;
|
577 |
+
|
578 |
+
$irrelevant = array(
|
579 |
+
'php.ini',
|
580 |
+
'.htaccess',
|
581 |
+
'.htpasswd',
|
582 |
+
'.ftpquota',
|
583 |
+
'wp-includes/.htaccess',
|
584 |
+
'wp-admin/setup-config.php',
|
585 |
+
'wp-tests-config.php',
|
586 |
+
'wp-config.php',
|
587 |
+
'sitemap.xml',
|
588 |
+
'sitemap.xml.gz',
|
589 |
+
'readme.html',
|
590 |
+
'error_log',
|
591 |
+
'wp-pass.php',
|
592 |
+
'wp-rss.php',
|
593 |
+
'wp-feed.php',
|
594 |
+
'wp-register.php',
|
595 |
+
'wp-atom.php',
|
596 |
+
'wp-commentsrss2.php',
|
597 |
+
'wp-rss2.php',
|
598 |
+
'wp-rdf.php',
|
599 |
+
'404.php',
|
600 |
+
'503.php',
|
601 |
+
'500.php',
|
602 |
+
'500.shtml',
|
603 |
+
'400.shtml',
|
604 |
+
'401.shtml',
|
605 |
+
'402.shtml',
|
606 |
+
'403.shtml',
|
607 |
+
'404.shtml',
|
608 |
+
'405.shtml',
|
609 |
+
'406.shtml',
|
610 |
+
'407.shtml',
|
611 |
+
'408.shtml',
|
612 |
+
'409.shtml',
|
613 |
+
'healthcheck.html',
|
614 |
+
);
|
615 |
+
|
616 |
+
/**
|
617 |
+
* Ignore i18n files.
|
618 |
+
*
|
619 |
+
* Sites with i18n have differences compared with the official English
|
620 |
+
* version of the project, basically they have files with new variables
|
621 |
+
* specifying the language that will be used in the admin panel, site
|
622 |
+
* options, and emails.
|
623 |
+
*/
|
624 |
+
if (isset($wp_local_package) && $wp_local_package != 'en_US') {
|
625 |
+
$irrelevant[] = 'wp-includes/version.php';
|
626 |
+
$irrelevant[] = 'wp-config-sample.php';
|
627 |
+
}
|
628 |
+
|
629 |
+
if (in_array($path, $irrelevant)) {
|
630 |
+
return true;
|
631 |
+
}
|
632 |
+
|
633 |
+
/* use regular expressions */
|
634 |
+
$ignore = false;
|
635 |
+
$irrelevant = array(
|
636 |
'^sucuri-[0-9a-z\-]+\.php$',
|
637 |
'^\S+-sucuri-db-dump-gzip-[0-9]{10}-[0-9a-z]{32}\.gz$',
|
638 |
+
'^\.sucuri-sss-resume-[0-9a-z]{32}\.php$',
|
639 |
'^([^\/]*)\.(pdf|css|txt|jpg|gif|png|jpeg)$',
|
640 |
'^wp-content\/(themes|plugins)\/.+',
|
641 |
'^google[0-9a-z]{16}\.html$',
|
643 |
'\.ico$',
|
644 |
);
|
645 |
|
646 |
+
foreach ($irrelevant as $pattern) {
|
647 |
+
if (@preg_match('/'.$pattern.'/', $path)) {
|
648 |
+
$ignore = true;
|
649 |
+
break;
|
650 |
}
|
651 |
}
|
652 |
|
653 |
+
return $ignore;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
654 |
}
|
655 |
}
|
src/interface.lib.php
CHANGED
@@ -69,32 +69,6 @@ class SucuriScanInterface
|
|
69 |
);
|
70 |
wp_enqueue_script('sucuriscan1');
|
71 |
|
72 |
-
if (SucuriScanRequest::get('page', 'sucuriscan') !== false) {
|
73 |
-
wp_register_style(
|
74 |
-
'sucuriscan2',
|
75 |
-
SUCURISCAN_URL . '/inc/css/c3.min.css',
|
76 |
-
array(/* empty */),
|
77 |
-
$asset
|
78 |
-
);
|
79 |
-
wp_enqueue_style('sucuriscan2');
|
80 |
-
|
81 |
-
wp_register_script(
|
82 |
-
'sucuriscan2',
|
83 |
-
SUCURISCAN_URL . '/inc/js/d3.min.js',
|
84 |
-
array(/* empty */),
|
85 |
-
$asset
|
86 |
-
);
|
87 |
-
wp_enqueue_script('sucuriscan2');
|
88 |
-
|
89 |
-
wp_register_script(
|
90 |
-
'sucuriscan3',
|
91 |
-
SUCURISCAN_URL . '/inc/js/c3.min.js',
|
92 |
-
array(/* empty */),
|
93 |
-
$asset
|
94 |
-
);
|
95 |
-
wp_enqueue_script('sucuriscan3');
|
96 |
-
}
|
97 |
-
|
98 |
if (SucuriScanRequest::get('page', 'sucuriscan_firewall') !== false) {
|
99 |
wp_register_style(
|
100 |
'sucuriscan3',
|
@@ -175,6 +149,35 @@ class SucuriScanInterface
|
|
175 |
}
|
176 |
}
|
177 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
178 |
/**
|
179 |
* Do something if the plugin was updated.
|
180 |
*
|
@@ -191,20 +194,7 @@ class SucuriScanInterface
|
|
191 |
$version = SucuriScanOption::getOption(':plugin_version');
|
192 |
|
193 |
/* use simple comparison to force type cast. */
|
194 |
-
if (
|
195 |
-
return;
|
196 |
-
}
|
197 |
-
|
198 |
-
if (!is_writable(SucuriScanOption::optionsFilePath())) {
|
199 |
-
/**
|
200 |
-
* Stop if the settings file is not writable.
|
201 |
-
*
|
202 |
-
* In some cases where the settings file is not writable, or for
|
203 |
-
* some reason the option cannot be updated, the alerts below will
|
204 |
-
* be rendered all the time, to avoid unnecessary complains from
|
205 |
-
* the website owners we will not display the alerts if the option
|
206 |
-
* cannot be updated.
|
207 |
-
*/
|
208 |
return;
|
209 |
}
|
210 |
|
69 |
);
|
70 |
wp_enqueue_script('sucuriscan1');
|
71 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
72 |
if (SucuriScanRequest::get('page', 'sucuriscan_firewall') !== false) {
|
73 |
wp_register_style(
|
74 |
'sucuriscan3',
|
149 |
}
|
150 |
}
|
151 |
|
152 |
+
/**
|
153 |
+
* Display alerts and execute pre-checks before every page.
|
154 |
+
*
|
155 |
+
* This method verifies if the visibility of the requested page is allowed
|
156 |
+
* for the current user in session which usually needs to be granted admin
|
157 |
+
* privileges to access the plugin's tools. It also checks if the required
|
158 |
+
* SPL library is available and if the settings file is writable.
|
159 |
+
*/
|
160 |
+
public static function startupChecks()
|
161 |
+
{
|
162 |
+
self::checkPageVisibility();
|
163 |
+
|
164 |
+
self::noticeAfterUpdate();
|
165 |
+
|
166 |
+
if (!SucuriScanFileInfo::isSplAvailable()) {
|
167 |
+
/* display a warning when system dependencies are not met */
|
168 |
+
self::error(__('RequiresModernPHP', SUCURISCAN_TEXTDOMAIN));
|
169 |
+
}
|
170 |
+
|
171 |
+
if ($filename = SucuriScanOption::optionsFilePath()) {
|
172 |
+
if (!is_writable($filename)) {
|
173 |
+
self::error(sprintf(
|
174 |
+
__('StorageNotWritable', SUCURISCAN_TEXTDOMAIN),
|
175 |
+
$filename /* absolute path of the settings file */
|
176 |
+
));
|
177 |
+
}
|
178 |
+
}
|
179 |
+
}
|
180 |
+
|
181 |
/**
|
182 |
* Do something if the plugin was updated.
|
183 |
*
|
194 |
$version = SucuriScanOption::getOption(':plugin_version');
|
195 |
|
196 |
/* use simple comparison to force type cast. */
|
197 |
+
if ($version == SUCURISCAN_VERSION) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
198 |
return;
|
199 |
}
|
200 |
|
src/lastlogins-failed.php
CHANGED
@@ -254,7 +254,6 @@ function sucuriscan_get_failed_logins($get_old_logs = false, $offset = 0, $limit
|
|
254 |
$processed++; /* count decoded data */
|
255 |
|
256 |
if (is_array($login_data)) {
|
257 |
-
$login_data['attempt_date'] = date('r', $login_data['attempt_time']);
|
258 |
$login_data['attempt_count'] = ( $key + 1 );
|
259 |
|
260 |
if (!$login_data['user_agent']) {
|
@@ -360,6 +359,8 @@ function sucuriscan_report_failed_logins($failed_logins = array())
|
|
360 |
}
|
361 |
|
362 |
foreach ($failed_logins['entries'] as $login_data) {
|
|
|
|
|
363 |
if ($prettify_mails) {
|
364 |
$table_html .= '<tr>';
|
365 |
$table_html .= '<td>' . esc_attr($login_data['user_login']) . '</td>';
|
254 |
$processed++; /* count decoded data */
|
255 |
|
256 |
if (is_array($login_data)) {
|
|
|
257 |
$login_data['attempt_count'] = ( $key + 1 );
|
258 |
|
259 |
if (!$login_data['user_agent']) {
|
359 |
}
|
360 |
|
361 |
foreach ($failed_logins['entries'] as $login_data) {
|
362 |
+
$login_data['attempt_date'] = SucuriScan::datetime($login_data['attempt_time']);
|
363 |
+
|
364 |
if ($prettify_mails) {
|
365 |
$table_html .= '<tr>';
|
366 |
$table_html .= '<td>' . esc_attr($login_data['user_login']) . '</td>';
|
src/lastlogins.php
CHANGED
@@ -103,7 +103,7 @@ function sucuriscan_lastlogins_all()
|
|
103 |
|
104 |
if (!sucuriscan_lastlogins_datastore_is_writable()) {
|
105 |
$fpath = SucuriScan::escape(sucuriscan_lastlogins_datastore_filepath());
|
106 |
-
SucuriScanInterface::error(sprintf(__('LastLoginsNotWritable'), $fpath));
|
107 |
}
|
108 |
|
109 |
if ($last_logins = sucuriscan_get_logins($max_per_page, $offset)) {
|
@@ -128,7 +128,7 @@ function sucuriscan_lastlogins_all()
|
|
128 |
'UserList.RemoteAddr' => $user->user_remoteaddr,
|
129 |
'UserList.Hostname' => $user->user_hostname,
|
130 |
'UserList.Datetime' => $user->user_lastlogin,
|
131 |
-
'UserList.TimeAgo' => SucuriScan::
|
132 |
'UserList.UserURL' => SucuriScan::adminURL('user-edit.php?user_id=' . $user->user_id),
|
133 |
);
|
134 |
|
103 |
|
104 |
if (!sucuriscan_lastlogins_datastore_is_writable()) {
|
105 |
$fpath = SucuriScan::escape(sucuriscan_lastlogins_datastore_filepath());
|
106 |
+
SucuriScanInterface::error(sprintf(__('LastLoginsNotWritable', SUCURISCAN_TEXTDOMAIN), $fpath));
|
107 |
}
|
108 |
|
109 |
if ($last_logins = sucuriscan_get_logins($max_per_page, $offset)) {
|
128 |
'UserList.RemoteAddr' => $user->user_remoteaddr,
|
129 |
'UserList.Hostname' => $user->user_hostname,
|
130 |
'UserList.Datetime' => $user->user_lastlogin,
|
131 |
+
'UserList.TimeAgo' => SucuriScan::humanTime($user->user_lastlogin_timestamp),
|
132 |
'UserList.UserURL' => SucuriScan::adminURL('user-edit.php?user_id=' . $user->user_id),
|
133 |
);
|
134 |
|
src/mail.lib.php
CHANGED
@@ -192,7 +192,7 @@ class SucuriScanMail extends SucuriScanOption
|
|
192 |
$params['RemoteAddress'] = self::getRemoteAddr();
|
193 |
$params['Message'] = $message;
|
194 |
$params['User'] = $display_name;
|
195 |
-
$params['Time'] = SucuriScan::
|
196 |
|
197 |
foreach ($data_set as $var_key => $var_value) {
|
198 |
$params[ $var_key ] = $var_value;
|
192 |
$params['RemoteAddress'] = self::getRemoteAddr();
|
193 |
$params['Message'] = $message;
|
194 |
$params['User'] = $display_name;
|
195 |
+
$params['Time'] = SucuriScan::datetime();
|
196 |
|
197 |
foreach ($data_set as $var_key => $var_value) {
|
198 |
$params[ $var_key ] = $var_value;
|
src/option.lib.php
CHANGED
@@ -54,6 +54,8 @@ class SucuriScanOption extends SucuriScanRequest
|
|
54 |
'sucuriscan_api_key' => false,
|
55 |
'sucuriscan_api_protocol' => 'https',
|
56 |
'sucuriscan_api_service' => 'enabled',
|
|
|
|
|
57 |
'sucuriscan_cloudproxy_apikey' => '',
|
58 |
'sucuriscan_diff_utility' => 'disabled',
|
59 |
'sucuriscan_dns_lookups' => 'enabled',
|
@@ -65,22 +67,22 @@ class SucuriScanOption extends SucuriScanRequest
|
|
65 |
'sucuriscan_language' => 'en_US',
|
66 |
'sucuriscan_last_email_at' => time(),
|
67 |
'sucuriscan_lastlogin_redirection' => 'enabled',
|
68 |
-
'sucuriscan_logs4report' => 500,
|
69 |
'sucuriscan_maximum_failed_logins' => 30,
|
70 |
'sucuriscan_notify_available_updates' => 'disabled',
|
71 |
'sucuriscan_notify_bruteforce_attack' => 'disabled',
|
72 |
'sucuriscan_notify_failed_login' => 'enabled',
|
73 |
-
'
|
74 |
-
'
|
|
|
75 |
'sucuriscan_notify_plugin_deactivated' => 'disabled',
|
76 |
'sucuriscan_notify_plugin_deleted' => 'disabled',
|
77 |
'sucuriscan_notify_plugin_installed' => 'disabled',
|
78 |
'sucuriscan_notify_plugin_updated' => 'disabled',
|
79 |
'sucuriscan_notify_post_publication' => 'enabled',
|
80 |
'sucuriscan_notify_scan_checksums' => 'disabled',
|
81 |
-
'sucuriscan_notify_settings_updated' => '
|
82 |
'sucuriscan_notify_success_login' => 'enabled',
|
83 |
-
'sucuriscan_notify_theme_activated' => '
|
84 |
'sucuriscan_notify_theme_deleted' => 'disabled',
|
85 |
'sucuriscan_notify_theme_editor' => 'enabled',
|
86 |
'sucuriscan_notify_theme_installed' => 'disabled',
|
@@ -97,6 +99,8 @@ class SucuriScanOption extends SucuriScanRequest
|
|
97 |
'sucuriscan_selfhosting_fpath' => '',
|
98 |
'sucuriscan_selfhosting_monitor' => 'disabled',
|
99 |
'sucuriscan_site_version' => '0.0',
|
|
|
|
|
100 |
'sucuriscan_use_wpmail' => 'enabled',
|
101 |
);
|
102 |
|
@@ -134,7 +138,7 @@ class SucuriScanOption extends SucuriScanRequest
|
|
134 |
|
135 |
$default['sucuriscan_email_subject'] =
|
136 |
__('SucuriAlert', SUCURISCAN_TEXTDOMAIN)
|
137 |
-
. ', :domain, :event';
|
138 |
}
|
139 |
|
140 |
return @$default[$option];
|
@@ -452,6 +456,57 @@ class SucuriScanOption extends SucuriScanRequest
|
|
452 |
);
|
453 |
}
|
454 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
455 |
/**
|
456 |
* Check whether an event is being ignored to send alerts or not.
|
457 |
*
|
54 |
'sucuriscan_api_key' => false,
|
55 |
'sucuriscan_api_protocol' => 'https',
|
56 |
'sucuriscan_api_service' => 'enabled',
|
57 |
+
'sucuriscan_auto_clear_cache' => 'disabled',
|
58 |
+
'sucuriscan_checksum_api' => '',
|
59 |
'sucuriscan_cloudproxy_apikey' => '',
|
60 |
'sucuriscan_diff_utility' => 'disabled',
|
61 |
'sucuriscan_dns_lookups' => 'enabled',
|
67 |
'sucuriscan_language' => 'en_US',
|
68 |
'sucuriscan_last_email_at' => time(),
|
69 |
'sucuriscan_lastlogin_redirection' => 'enabled',
|
|
|
70 |
'sucuriscan_maximum_failed_logins' => 30,
|
71 |
'sucuriscan_notify_available_updates' => 'disabled',
|
72 |
'sucuriscan_notify_bruteforce_attack' => 'disabled',
|
73 |
'sucuriscan_notify_failed_login' => 'enabled',
|
74 |
+
'sucuriscan_notify_failed_password' => 'disabled',
|
75 |
+
'sucuriscan_notify_plugin_activated' => 'enabled',
|
76 |
+
'sucuriscan_notify_plugin_change' => 'enabled',
|
77 |
'sucuriscan_notify_plugin_deactivated' => 'disabled',
|
78 |
'sucuriscan_notify_plugin_deleted' => 'disabled',
|
79 |
'sucuriscan_notify_plugin_installed' => 'disabled',
|
80 |
'sucuriscan_notify_plugin_updated' => 'disabled',
|
81 |
'sucuriscan_notify_post_publication' => 'enabled',
|
82 |
'sucuriscan_notify_scan_checksums' => 'disabled',
|
83 |
+
'sucuriscan_notify_settings_updated' => 'enabled',
|
84 |
'sucuriscan_notify_success_login' => 'enabled',
|
85 |
+
'sucuriscan_notify_theme_activated' => 'enabled',
|
86 |
'sucuriscan_notify_theme_deleted' => 'disabled',
|
87 |
'sucuriscan_notify_theme_editor' => 'enabled',
|
88 |
'sucuriscan_notify_theme_installed' => 'disabled',
|
99 |
'sucuriscan_selfhosting_fpath' => '',
|
100 |
'sucuriscan_selfhosting_monitor' => 'disabled',
|
101 |
'sucuriscan_site_version' => '0.0',
|
102 |
+
'sucuriscan_sitecheck_target' => '',
|
103 |
+
'sucuriscan_timezone' => 'UTC+00.00',
|
104 |
'sucuriscan_use_wpmail' => 'enabled',
|
105 |
);
|
106 |
|
138 |
|
139 |
$default['sucuriscan_email_subject'] =
|
140 |
__('SucuriAlert', SUCURISCAN_TEXTDOMAIN)
|
141 |
+
. ', :domain, :event, :remoteaddr';
|
142 |
}
|
143 |
|
144 |
return @$default[$option];
|
456 |
);
|
457 |
}
|
458 |
|
459 |
+
/**
|
460 |
+
* Returns a list of post-types.
|
461 |
+
*
|
462 |
+
* The list of post-types includes objects such as Post and Page but also
|
463 |
+
* the transitions between each post type, for example, if there are posts
|
464 |
+
* of type Draft and they change to Trash, this function will include a new
|
465 |
+
* post type called "from_draft_to_trash" and so on.
|
466 |
+
*
|
467 |
+
* @return array List of post-types with transitions.
|
468 |
+
*/
|
469 |
+
public static function getPostTypes()
|
470 |
+
{
|
471 |
+
$postTypes = get_post_types();
|
472 |
+
$transitions = array(
|
473 |
+
'new',
|
474 |
+
'publish',
|
475 |
+
'pending',
|
476 |
+
'draft',
|
477 |
+
'auto-draft',
|
478 |
+
'future',
|
479 |
+
'private',
|
480 |
+
'inherit',
|
481 |
+
'trash',
|
482 |
+
);
|
483 |
+
|
484 |
+
/* include post-type transitions */
|
485 |
+
foreach ($transitions as $from) {
|
486 |
+
foreach ($transitions as $to) {
|
487 |
+
if ($from === $to) {
|
488 |
+
continue;
|
489 |
+
}
|
490 |
+
|
491 |
+
$event = sprintf('from_%s_to_%s', $from, $to);
|
492 |
+
|
493 |
+
if (!array_key_exists($event, $postTypes)) {
|
494 |
+
$postTypes[$event] = $event;
|
495 |
+
}
|
496 |
+
}
|
497 |
+
}
|
498 |
+
|
499 |
+
/* include custom non-registered post-types */
|
500 |
+
$ignoredEvents = SucuriScanOption::getIgnoredEvents();
|
501 |
+
foreach ($ignoredEvents as $event => $time) {
|
502 |
+
if (!array_key_exists($event, $postTypes)) {
|
503 |
+
$postTypes[$event] = $event;
|
504 |
+
}
|
505 |
+
}
|
506 |
+
|
507 |
+
return $postTypes;
|
508 |
+
}
|
509 |
+
|
510 |
/**
|
511 |
* Check whether an event is being ignored to send alerts or not.
|
512 |
*
|
src/pagehandler.php
CHANGED
@@ -23,19 +23,13 @@ function sucuriscan_page()
|
|
23 |
{
|
24 |
$params = array();
|
25 |
|
26 |
-
SucuriScanInterface::
|
27 |
-
|
28 |
-
if (!SucuriScanFileInfo::isSplAvailable()) {
|
29 |
-
/* display a warning when system dependencies are not met */
|
30 |
-
SucuriScanInterface::error(__('RequiresModernPHP', SUCURISCAN_TEXTDOMAIN));
|
31 |
-
}
|
32 |
|
33 |
/* load data for the Integrity section */
|
34 |
$params['Integrity'] = SucuriScanIntegrity::pageIntegrity();
|
35 |
|
36 |
/* load data for the AuditLogs section */
|
37 |
$params['AuditLogs'] = SucuriScanAuditLogs::pageAuditLogs();
|
38 |
-
$params['AuditLogsReport'] = SucuriScanAuditLogs::pageAuditLogsReport();
|
39 |
|
40 |
/* load data for the SiteCheck section */
|
41 |
$params['SiteCheck.iFramesTitle'] = __('iFrames', SUCURISCAN_TEXTDOMAIN);
|
@@ -56,11 +50,12 @@ function sucuriscan_page()
|
|
56 |
*/
|
57 |
function sucuriscan_firewall_page()
|
58 |
{
|
59 |
-
SucuriScanInterface::
|
60 |
|
61 |
$params = array(
|
62 |
'Firewall.Settings' => SucuriScanFirewall::settingsPage(),
|
63 |
'Firewall.AuditLogs' => SucuriScanFirewall::auditlogsPage(),
|
|
|
64 |
'Firewall.ClearCache' => SucuriScanFirewall::clearCachePage(),
|
65 |
);
|
66 |
|
@@ -72,7 +67,7 @@ function sucuriscan_firewall_page()
|
|
72 |
*/
|
73 |
function sucuriscan_lastlogins_page()
|
74 |
{
|
75 |
-
SucuriScanInterface::
|
76 |
|
77 |
// Reset the file with the last-logins logs.
|
78 |
if (SucuriScanInterface::checkNonce()
|
@@ -105,7 +100,7 @@ function sucuriscan_lastlogins_page()
|
|
105 |
*/
|
106 |
function sucuriscan_settings_page()
|
107 |
{
|
108 |
-
SucuriScanInterface::
|
109 |
|
110 |
$params = array();
|
111 |
$nonce = SucuriScanInterface::checkNonce();
|
@@ -115,15 +110,15 @@ function sucuriscan_settings_page()
|
|
115 |
|
116 |
/* settings - general */
|
117 |
$params['Settings.General.ApiKey'] = sucuriscan_settings_general_apikey($nonce);
|
118 |
-
$params['Settings.General.DataStorage'] = sucuriscan_settings_general_datastorage();
|
119 |
$params['Settings.General.SelfHosting'] = sucuriscan_settings_general_selfhosting($nonce);
|
120 |
$params['Settings.General.ReverseProxy'] = sucuriscan_settings_general_reverseproxy($nonce);
|
121 |
$params['Settings.General.IPDiscoverer'] = sucuriscan_settings_general_ipdiscoverer($nonce);
|
122 |
-
$params['Settings.General.AuditLogStats'] = sucuriscan_settings_general_auditlogstats($nonce);
|
123 |
$params['Settings.General.ImportExport'] = sucuriscan_settings_general_importexport($nonce);
|
|
|
124 |
|
125 |
/* settings - scanner */
|
126 |
-
$params['Settings.Scanner.Cronjobs'] = SucuriScanSettingsScanner::cronjobs();
|
127 |
$params['Settings.Scanner.IntegrityDiffUtility'] = SucuriScanSettingsIntegrity::diffUtility($nonce);
|
128 |
$params['Settings.Scanner.IntegrityLanguage'] = SucuriScanSettingsIntegrity::language($nonce);
|
129 |
$params['Settings.Scanner.IntegrityCache'] = SucuriScanSettingsIntegrity::cache($nonce);
|
@@ -161,10 +156,11 @@ function sucuriscan_settings_page()
|
|
161 |
/* settings - api service */
|
162 |
$params['Settings.APIService.Status'] = sucuriscan_settings_apiservice_status($nonce);
|
163 |
$params['Settings.APIService.Proxy'] = sucuriscan_settings_apiservice_proxy();
|
|
|
|
|
164 |
|
165 |
/* settings - website info */
|
166 |
$params['Settings.Webinfo.Details'] = sucuriscan_settings_webinfo_details();
|
167 |
-
$params['Settings.Webinfo.WPConfig'] = sucuriscan_settings_webinfo_wpconfig();
|
168 |
$params['Settings.Webinfo.HTAccess'] = sucuriscan_settings_webinfo_htaccess();
|
169 |
|
170 |
echo SucuriScanTemplate::getTemplate('settings', $params);
|
@@ -179,10 +175,15 @@ function sucuriscan_ajax()
|
|
179 |
|
180 |
if (SucuriScanInterface::checkNonce()) {
|
181 |
SucuriScanAuditLogs::ajaxAuditLogs();
|
182 |
-
SucuriScanAuditLogs::ajaxAuditLogsReport();
|
183 |
SucuriScanAuditLogs::ajaxAuditLogsSendLogs();
|
184 |
SucuriScanSiteCheck::ajaxMalwareScan();
|
185 |
SucuriScanFirewall::auditlogsAjax();
|
|
|
|
|
|
|
|
|
|
|
|
|
186 |
SucuriScanIntegrity::ajaxIntegrity();
|
187 |
SucuriScanIntegrity::ajaxIntegrityDiffUtility();
|
188 |
SucuriScanSettingsPosthack::availableUpdatesAjax();
|
23 |
{
|
24 |
$params = array();
|
25 |
|
26 |
+
SucuriScanInterface::startupChecks();
|
|
|
|
|
|
|
|
|
|
|
27 |
|
28 |
/* load data for the Integrity section */
|
29 |
$params['Integrity'] = SucuriScanIntegrity::pageIntegrity();
|
30 |
|
31 |
/* load data for the AuditLogs section */
|
32 |
$params['AuditLogs'] = SucuriScanAuditLogs::pageAuditLogs();
|
|
|
33 |
|
34 |
/* load data for the SiteCheck section */
|
35 |
$params['SiteCheck.iFramesTitle'] = __('iFrames', SUCURISCAN_TEXTDOMAIN);
|
50 |
*/
|
51 |
function sucuriscan_firewall_page()
|
52 |
{
|
53 |
+
SucuriScanInterface::startupChecks();
|
54 |
|
55 |
$params = array(
|
56 |
'Firewall.Settings' => SucuriScanFirewall::settingsPage(),
|
57 |
'Firewall.AuditLogs' => SucuriScanFirewall::auditlogsPage(),
|
58 |
+
'Firewall.IPAccess' => SucuriScanFirewall::ipAccessPage(),
|
59 |
'Firewall.ClearCache' => SucuriScanFirewall::clearCachePage(),
|
60 |
);
|
61 |
|
67 |
*/
|
68 |
function sucuriscan_lastlogins_page()
|
69 |
{
|
70 |
+
SucuriScanInterface::startupChecks();
|
71 |
|
72 |
// Reset the file with the last-logins logs.
|
73 |
if (SucuriScanInterface::checkNonce()
|
100 |
*/
|
101 |
function sucuriscan_settings_page()
|
102 |
{
|
103 |
+
SucuriScanInterface::startupChecks();
|
104 |
|
105 |
$params = array();
|
106 |
$nonce = SucuriScanInterface::checkNonce();
|
110 |
|
111 |
/* settings - general */
|
112 |
$params['Settings.General.ApiKey'] = sucuriscan_settings_general_apikey($nonce);
|
113 |
+
$params['Settings.General.DataStorage'] = sucuriscan_settings_general_datastorage($nonce);
|
114 |
$params['Settings.General.SelfHosting'] = sucuriscan_settings_general_selfhosting($nonce);
|
115 |
$params['Settings.General.ReverseProxy'] = sucuriscan_settings_general_reverseproxy($nonce);
|
116 |
$params['Settings.General.IPDiscoverer'] = sucuriscan_settings_general_ipdiscoverer($nonce);
|
|
|
117 |
$params['Settings.General.ImportExport'] = sucuriscan_settings_general_importexport($nonce);
|
118 |
+
$params['Settings.General.Timezone'] = sucuriscan_settings_general_timezone($nonce);
|
119 |
|
120 |
/* settings - scanner */
|
121 |
+
$params['Settings.Scanner.Cronjobs'] = SucuriScanSettingsScanner::cronjobs($nonce);
|
122 |
$params['Settings.Scanner.IntegrityDiffUtility'] = SucuriScanSettingsIntegrity::diffUtility($nonce);
|
123 |
$params['Settings.Scanner.IntegrityLanguage'] = SucuriScanSettingsIntegrity::language($nonce);
|
124 |
$params['Settings.Scanner.IntegrityCache'] = SucuriScanSettingsIntegrity::cache($nonce);
|
156 |
/* settings - api service */
|
157 |
$params['Settings.APIService.Status'] = sucuriscan_settings_apiservice_status($nonce);
|
158 |
$params['Settings.APIService.Proxy'] = sucuriscan_settings_apiservice_proxy();
|
159 |
+
$params['Settings.SiteCheck.Target'] = SucuriScanSiteCheck::targetURLOption();
|
160 |
+
$params['Settings.APIService.Checksums'] = sucuriscan_settings_apiservice_checksums($nonce);
|
161 |
|
162 |
/* settings - website info */
|
163 |
$params['Settings.Webinfo.Details'] = sucuriscan_settings_webinfo_details();
|
|
|
164 |
$params['Settings.Webinfo.HTAccess'] = sucuriscan_settings_webinfo_htaccess();
|
165 |
|
166 |
echo SucuriScanTemplate::getTemplate('settings', $params);
|
175 |
|
176 |
if (SucuriScanInterface::checkNonce()) {
|
177 |
SucuriScanAuditLogs::ajaxAuditLogs();
|
|
|
178 |
SucuriScanAuditLogs::ajaxAuditLogsSendLogs();
|
179 |
SucuriScanSiteCheck::ajaxMalwareScan();
|
180 |
SucuriScanFirewall::auditlogsAjax();
|
181 |
+
SucuriScanFirewall::ipAccessAjax();
|
182 |
+
SucuriScanFirewall::blacklistAjax();
|
183 |
+
SucuriScanFirewall::deblacklistAjax();
|
184 |
+
SucuriScanFirewall::getSettingsAjax();
|
185 |
+
SucuriScanFirewall::clearCacheAjax();
|
186 |
+
SucuriScanFirewall::clearAutoCacheAjax();
|
187 |
SucuriScanIntegrity::ajaxIntegrity();
|
188 |
SucuriScanIntegrity::ajaxIntegrityDiffUtility();
|
189 |
SucuriScanSettingsPosthack::availableUpdatesAjax();
|
src/settings-alerts.php
CHANGED
@@ -50,7 +50,7 @@ function sucuriscan_settings_alerts_recipients($nonce)
|
|
50 |
$message = sprintf(__('WillReceiveAlerts', SUCURISCAN_TEXTDOMAIN), $new_email);
|
51 |
|
52 |
SucuriScanOption::updateOption(':notify_to', implode(',', $emails));
|
53 |
-
SucuriScanEvent::reportInfoEvent($
|
54 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
55 |
SucuriScanInterface::info($message);
|
56 |
} else {
|
@@ -76,7 +76,7 @@ function sucuriscan_settings_alerts_recipients($nonce)
|
|
76 |
$message = sprintf(__('WillNotReceiveAlerts', SUCURISCAN_TEXTDOMAIN), $deleted_emails_str);
|
77 |
|
78 |
SucuriScanOption::updateOption(':notify_to', implode(',', $emails));
|
79 |
-
SucuriScanEvent::reportInfoEvent($
|
80 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
81 |
SucuriScanInterface::info($message);
|
82 |
}
|
@@ -88,7 +88,7 @@ function sucuriscan_settings_alerts_recipients($nonce)
|
|
88 |
SucuriScanMail::sendMail(
|
89 |
$recipients,
|
90 |
'Test Email Alert',
|
91 |
-
sprintf('Test email alert sent at %s',
|
92 |
array('Force' => true)
|
93 |
);
|
94 |
SucuriScanInterface::info(__('TestAlertSent', SUCURISCAN_TEXTDOMAIN));
|
@@ -130,7 +130,7 @@ function sucuriscan_settings_alerts_trustedips()
|
|
130 |
if ($trust_ip = SucuriScanRequest::post(':trust_ip')) {
|
131 |
if (SucuriScan::isValidIP($trust_ip) || SucuriScan::isValidCIDR($trust_ip)) {
|
132 |
$ip_info = SucuriScan::getIPInfo($trust_ip);
|
133 |
-
$ip_info['added_at'] =
|
134 |
$cache_key = md5($ip_info['remote_addr']);
|
135 |
|
136 |
if ($cache->exists($cache_key)) {
|
@@ -373,22 +373,24 @@ function sucuriscan_settings_alerts_events($nonce)
|
|
373 |
{
|
374 |
$params = array();
|
375 |
$params['Alerts.Events'] = '';
|
|
|
376 |
|
377 |
$notify_options = array(
|
378 |
-
'sucuriscan_notify_plugin_change' => __('OptionNotifyPluginChange', SUCURISCAN_TEXTDOMAIN),
|
379 |
-
'sucuriscan_prettify_mails' => __('OptionPrettifyMails', SUCURISCAN_TEXTDOMAIN),
|
380 |
-
'sucuriscan_use_wpmail' => __('OptionUseWordPressMail', SUCURISCAN_TEXTDOMAIN),
|
381 |
-
'sucuriscan_lastlogin_redirection' => __('OptionLastLoginRedirection', SUCURISCAN_TEXTDOMAIN),
|
382 |
-
'sucuriscan_notify_scan_checksums' => __('OptionNotifyScanChecksums', SUCURISCAN_TEXTDOMAIN),
|
383 |
-
'sucuriscan_notify_available_updates' => __('OptionNotifyAvailableUpdates', SUCURISCAN_TEXTDOMAIN),
|
384 |
'sucuriscan_notify_user_registration' => 'user:' . __('OptionNotifyUserRegistration', SUCURISCAN_TEXTDOMAIN),
|
385 |
'sucuriscan_notify_success_login' => 'user:' . __('OptionNotifySuccessLogin', SUCURISCAN_TEXTDOMAIN),
|
386 |
'sucuriscan_notify_failed_login' => 'user:' . __('OptionNotifyFailedLogin', SUCURISCAN_TEXTDOMAIN),
|
|
|
387 |
'sucuriscan_notify_bruteforce_attack' => 'user:' . __('OptionNotifyBruteforceAttack', SUCURISCAN_TEXTDOMAIN),
|
388 |
-
'sucuriscan_notify_post_publication' => __('OptionNotifyPostPublication', SUCURISCAN_TEXTDOMAIN),
|
389 |
-
'sucuriscan_notify_website_updated' => __('OptionNotifyWebsiteUpdated', SUCURISCAN_TEXTDOMAIN),
|
390 |
-
'sucuriscan_notify_settings_updated' => __('OptionNotifySettingsUpdated', SUCURISCAN_TEXTDOMAIN),
|
391 |
-
'sucuriscan_notify_theme_editor' => __('OptionNotifyThemeEditor', SUCURISCAN_TEXTDOMAIN),
|
392 |
'sucuriscan_notify_plugin_installed' => 'plugin:' . __('OptionNotifyPluginInstalled', SUCURISCAN_TEXTDOMAIN),
|
393 |
'sucuriscan_notify_plugin_activated' => 'plugin:' . __('OptionNotifyPluginActivated', SUCURISCAN_TEXTDOMAIN),
|
394 |
'sucuriscan_notify_plugin_deactivated' => 'plugin:' . __('OptionNotifyPluginDeactivated', SUCURISCAN_TEXTDOMAIN),
|
@@ -402,6 +404,25 @@ function sucuriscan_settings_alerts_events($nonce)
|
|
402 |
'sucuriscan_notify_theme_deleted' => 'theme:' . __('OptionNotifyThemeDeleted', SUCURISCAN_TEXTDOMAIN),
|
403 |
);
|
404 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
405 |
// Process form submission to change the alert settings.
|
406 |
if ($nonce) {
|
407 |
// Update the notification settings.
|
@@ -433,42 +454,46 @@ function sucuriscan_settings_alerts_events($nonce)
|
|
433 |
}
|
434 |
}
|
435 |
|
436 |
-
|
437 |
-
|
438 |
-
$
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
'Event.Checked' => $checked,
|
468 |
-
'Event.Label' => $alert_label,
|
469 |
-
'Event.LabelIcon' => $alert_icon,
|
470 |
-
));
|
471 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
472 |
}
|
473 |
|
474 |
return SucuriScanTemplate::getSection('settings-alerts-events', $params);
|
@@ -481,11 +506,9 @@ function sucuriscan_settings_alerts_events($nonce)
|
|
481 |
*/
|
482 |
function sucuriscan_settings_alerts_ignore_posts()
|
483 |
{
|
484 |
-
$notify_new_site_content = SucuriScanOption::getOption(':notify_post_publication');
|
485 |
-
|
486 |
$params = array(
|
487 |
-
'IgnoreRules.MessageVisibility' => 'visible',
|
488 |
'IgnoreRules.PostTypes' => '',
|
|
|
489 |
);
|
490 |
|
491 |
if (SucuriScanInterface::checkNonce()) {
|
@@ -510,48 +533,55 @@ function sucuriscan_settings_alerts_ignore_posts()
|
|
510 |
}
|
511 |
}
|
512 |
|
513 |
-
|
514 |
-
|
515 |
-
$
|
|
|
|
|
|
|
|
|
516 |
|
517 |
-
|
518 |
-
|
519 |
-
/* Include custom non-registered post-types */
|
520 |
-
foreach ($ignored_events as $event => $time) {
|
521 |
-
if (!array_key_exists($event, $post_types)) {
|
522 |
-
$post_types[$event] = $event;
|
523 |
-
}
|
524 |
-
}
|
525 |
|
526 |
-
|
527 |
-
|
528 |
-
$post_type_title = ucwords(str_replace('_', chr(32), $post_type));
|
529 |
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
} else {
|
537 |
-
$is_ignored_text = __('No', SUCURISCAN_TEXTDOMAIN);
|
538 |
-
$was_ignored_at = '--';
|
539 |
-
$is_ignored_class = 'success';
|
540 |
-
$button_action = 'add';
|
541 |
-
$button_text = __('PostTypeUnignore', SUCURISCAN_TEXTDOMAIN);
|
542 |
-
}
|
543 |
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
554 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
555 |
}
|
556 |
|
557 |
return SucuriScanTemplate::getSection('settings-alerts-ignore-posts', $params);
|
50 |
$message = sprintf(__('WillReceiveAlerts', SUCURISCAN_TEXTDOMAIN), $new_email);
|
51 |
|
52 |
SucuriScanOption::updateOption(':notify_to', implode(',', $emails));
|
53 |
+
SucuriScanEvent::reportInfoEvent('The email alerts will be sent to: ' . $new_email);
|
54 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
55 |
SucuriScanInterface::info($message);
|
56 |
} else {
|
76 |
$message = sprintf(__('WillNotReceiveAlerts', SUCURISCAN_TEXTDOMAIN), $deleted_emails_str);
|
77 |
|
78 |
SucuriScanOption::updateOption(':notify_to', implode(',', $emails));
|
79 |
+
SucuriScanEvent::reportInfoEvent('These emails will stop receiving alerts: ' . $deleted_emails_str);
|
80 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
81 |
SucuriScanInterface::info($message);
|
82 |
}
|
88 |
SucuriScanMail::sendMail(
|
89 |
$recipients,
|
90 |
'Test Email Alert',
|
91 |
+
sprintf('Test email alert sent at %s', SucuriScan::datetime()),
|
92 |
array('Force' => true)
|
93 |
);
|
94 |
SucuriScanInterface::info(__('TestAlertSent', SUCURISCAN_TEXTDOMAIN));
|
130 |
if ($trust_ip = SucuriScanRequest::post(':trust_ip')) {
|
131 |
if (SucuriScan::isValidIP($trust_ip) || SucuriScan::isValidCIDR($trust_ip)) {
|
132 |
$ip_info = SucuriScan::getIPInfo($trust_ip);
|
133 |
+
$ip_info['added_at'] = time();
|
134 |
$cache_key = md5($ip_info['remote_addr']);
|
135 |
|
136 |
if ($cache->exists($cache_key)) {
|
373 |
{
|
374 |
$params = array();
|
375 |
$params['Alerts.Events'] = '';
|
376 |
+
$params['Alerts.NoAlertsVisibility'] = 'hidden';
|
377 |
|
378 |
$notify_options = array(
|
379 |
+
'sucuriscan_notify_plugin_change' => 'setting:' . __('OptionNotifyPluginChange', SUCURISCAN_TEXTDOMAIN),
|
380 |
+
'sucuriscan_prettify_mails' => 'setting:' . __('OptionPrettifyMails', SUCURISCAN_TEXTDOMAIN),
|
381 |
+
'sucuriscan_use_wpmail' => 'setting:' . __('OptionUseWordPressMail', SUCURISCAN_TEXTDOMAIN),
|
382 |
+
'sucuriscan_lastlogin_redirection' => 'setting:' . __('OptionLastLoginRedirection', SUCURISCAN_TEXTDOMAIN),
|
383 |
+
'sucuriscan_notify_scan_checksums' => 'setting:' . __('OptionNotifyScanChecksums', SUCURISCAN_TEXTDOMAIN),
|
384 |
+
'sucuriscan_notify_available_updates' => 'setting:' . __('OptionNotifyAvailableUpdates', SUCURISCAN_TEXTDOMAIN),
|
385 |
'sucuriscan_notify_user_registration' => 'user:' . __('OptionNotifyUserRegistration', SUCURISCAN_TEXTDOMAIN),
|
386 |
'sucuriscan_notify_success_login' => 'user:' . __('OptionNotifySuccessLogin', SUCURISCAN_TEXTDOMAIN),
|
387 |
'sucuriscan_notify_failed_login' => 'user:' . __('OptionNotifyFailedLogin', SUCURISCAN_TEXTDOMAIN),
|
388 |
+
'sucuriscan_notify_failed_password' => 'user:' . __('OptionNotifyFailedPassword', SUCURISCAN_TEXTDOMAIN),
|
389 |
'sucuriscan_notify_bruteforce_attack' => 'user:' . __('OptionNotifyBruteforceAttack', SUCURISCAN_TEXTDOMAIN),
|
390 |
+
'sucuriscan_notify_post_publication' => 'setting:' . __('OptionNotifyPostPublication', SUCURISCAN_TEXTDOMAIN),
|
391 |
+
'sucuriscan_notify_website_updated' => 'setting:' . __('OptionNotifyWebsiteUpdated', SUCURISCAN_TEXTDOMAIN),
|
392 |
+
'sucuriscan_notify_settings_updated' => 'setting:' . __('OptionNotifySettingsUpdated', SUCURISCAN_TEXTDOMAIN),
|
393 |
+
'sucuriscan_notify_theme_editor' => 'setting:' . __('OptionNotifyThemeEditor', SUCURISCAN_TEXTDOMAIN),
|
394 |
'sucuriscan_notify_plugin_installed' => 'plugin:' . __('OptionNotifyPluginInstalled', SUCURISCAN_TEXTDOMAIN),
|
395 |
'sucuriscan_notify_plugin_activated' => 'plugin:' . __('OptionNotifyPluginActivated', SUCURISCAN_TEXTDOMAIN),
|
396 |
'sucuriscan_notify_plugin_deactivated' => 'plugin:' . __('OptionNotifyPluginDeactivated', SUCURISCAN_TEXTDOMAIN),
|
404 |
'sucuriscan_notify_theme_deleted' => 'theme:' . __('OptionNotifyThemeDeleted', SUCURISCAN_TEXTDOMAIN),
|
405 |
);
|
406 |
|
407 |
+
/**
|
408 |
+
* Hide successful and failed logins option.
|
409 |
+
*
|
410 |
+
* Due to an incompatibility with the Postman-SMTP plugin we cannot sent
|
411 |
+
* email alerts when a successful or failed user authentication happens, the
|
412 |
+
* result is an infinite loop while our plugin tries to notify about changes
|
413 |
+
* in the posts and the other plugin creates temporary post objects to track
|
414 |
+
* the emails.
|
415 |
+
*
|
416 |
+
* @date 30 June, 2017
|
417 |
+
* @see https://wordpress.org/plugins/postman-smtp/
|
418 |
+
* @see https://wordpress.org/support/topic/unable-to-access-wordpress-dashboard-after-update-to-1-8-7/
|
419 |
+
*/
|
420 |
+
if (is_plugin_active('postman-smtp/postman-smtp.php')) {
|
421 |
+
$params['Alerts.NoAlertsVisibility'] = 'visible';
|
422 |
+
unset($notify_options['sucuriscan_notify_success_login']);
|
423 |
+
unset($notify_options['sucuriscan_notify_failed_login']);
|
424 |
+
}
|
425 |
+
|
426 |
// Process form submission to change the alert settings.
|
427 |
if ($nonce) {
|
428 |
// Update the notification settings.
|
454 |
}
|
455 |
}
|
456 |
|
457 |
+
/* build the HTML code for the checkbox input fields */
|
458 |
+
foreach ($notify_options as $alert_type => $alert_label) {
|
459 |
+
$alert_value = SucuriScanOption::getOption($alert_type);
|
460 |
+
$checked = ($alert_value == 'enabled') ? 'checked="checked"' : '';
|
461 |
+
$alert_icon = '';
|
462 |
+
|
463 |
+
/* identify the optional icon */
|
464 |
+
$offset = strpos($alert_label, ':');
|
465 |
+
$alert_group = substr($alert_label, 0, $offset);
|
466 |
+
$alert_label = substr($alert_label, $offset+1);
|
467 |
+
|
468 |
+
switch ($alert_group) {
|
469 |
+
case 'user':
|
470 |
+
$alert_icon = 'dashicons-before dashicons-admin-users';
|
471 |
+
break;
|
472 |
+
|
473 |
+
case 'plugin':
|
474 |
+
$alert_icon = 'dashicons-before dashicons-admin-plugins';
|
475 |
+
break;
|
476 |
+
|
477 |
+
case 'theme':
|
478 |
+
$alert_icon = 'dashicons-before dashicons-admin-appearance';
|
479 |
+
break;
|
480 |
+
|
481 |
+
case 'setting':
|
482 |
+
$alert_icon = 'dashicons-before dashicons-admin-tools';
|
483 |
+
break;
|
484 |
+
|
485 |
+
case 'widget':
|
486 |
+
$alert_icon = 'dashicons-before dashicons-admin-post';
|
487 |
+
break;
|
|
|
|
|
|
|
|
|
488 |
}
|
489 |
+
|
490 |
+
$params['Alerts.Events'] .=
|
491 |
+
SucuriScanTemplate::getSnippet('settings-alerts-events', array(
|
492 |
+
'Event.Name' => $alert_type,
|
493 |
+
'Event.Checked' => $checked,
|
494 |
+
'Event.Label' => $alert_label,
|
495 |
+
'Event.LabelIcon' => $alert_icon,
|
496 |
+
));
|
497 |
}
|
498 |
|
499 |
return SucuriScanTemplate::getSection('settings-alerts-events', $params);
|
506 |
*/
|
507 |
function sucuriscan_settings_alerts_ignore_posts()
|
508 |
{
|
|
|
|
|
509 |
$params = array(
|
|
|
510 |
'IgnoreRules.PostTypes' => '',
|
511 |
+
'IgnoreRules.ErrorVisibility' => 'hidden',
|
512 |
);
|
513 |
|
514 |
if (SucuriScanInterface::checkNonce()) {
|
533 |
}
|
534 |
}
|
535 |
|
536 |
+
/* notifications are post updates are disabled; print error */
|
537 |
+
if (SucuriScanOption::isDisabled(':notify_post_publication')) {
|
538 |
+
$params['IgnoreRules.ErrorVisibility'] = 'visible';
|
539 |
+
$params['IgnoreRules.PostTypes'] = sprintf(
|
540 |
+
'<tr><td colspan="4">%s</td></tr>',
|
541 |
+
__('NoData', SUCURISCAN_TEXTDOMAIN)
|
542 |
+
);
|
543 |
|
544 |
+
return SucuriScanTemplate::getSection('settings-alerts-ignore-posts', $params);
|
545 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
546 |
|
547 |
+
$post_types = SucuriScanOption::getPostTypes();
|
548 |
+
$ignored_events = SucuriScanOption::getIgnoredEvents();
|
|
|
549 |
|
550 |
+
/* include custom non-registered post-types */
|
551 |
+
foreach ($ignored_events as $event => $time) {
|
552 |
+
if (!array_key_exists($event, $post_types)) {
|
553 |
+
$post_types[$event] = $event;
|
554 |
+
}
|
555 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
556 |
|
557 |
+
/* Check which post-types are being ignored */
|
558 |
+
foreach ($post_types as $post_type) {
|
559 |
+
$post_type_title = ucwords(str_replace('_', chr(32), $post_type));
|
560 |
+
|
561 |
+
if (array_key_exists($post_type, $ignored_events)) {
|
562 |
+
$is_ignored_text = __('Yes', SUCURISCAN_TEXTDOMAIN);
|
563 |
+
$was_ignored_at = SucuriScan::datetime($ignored_events[ $post_type ]);
|
564 |
+
$is_ignored_class = 'danger';
|
565 |
+
$button_action = 'remove';
|
566 |
+
$button_text = __('PostTypeIgnore', SUCURISCAN_TEXTDOMAIN);
|
567 |
+
} else {
|
568 |
+
$is_ignored_text = __('No', SUCURISCAN_TEXTDOMAIN);
|
569 |
+
$was_ignored_at = '--';
|
570 |
+
$is_ignored_class = 'success';
|
571 |
+
$button_action = 'add';
|
572 |
+
$button_text = __('PostTypeUnignore', SUCURISCAN_TEXTDOMAIN);
|
573 |
}
|
574 |
+
|
575 |
+
$params['IgnoreRules.PostTypes'] .=
|
576 |
+
SucuriScanTemplate::getSnippet('settings-alerts-ignore-posts', array(
|
577 |
+
'IgnoreRules.PostTypeTitle' => $post_type_title,
|
578 |
+
'IgnoreRules.IsIgnored' => $is_ignored_text,
|
579 |
+
'IgnoreRules.WasIgnoredAt' => $was_ignored_at,
|
580 |
+
'IgnoreRules.IsIgnoredClass' => $is_ignored_class,
|
581 |
+
'IgnoreRules.PostType' => $post_type,
|
582 |
+
'IgnoreRules.Action' => $button_action,
|
583 |
+
'IgnoreRules.ButtonText' => $button_text,
|
584 |
+
));
|
585 |
}
|
586 |
|
587 |
return SucuriScanTemplate::getSection('settings-alerts-ignore-posts', $params);
|
src/settings-apiservice.php
CHANGED
@@ -97,3 +97,40 @@ function sucuriscan_settings_apiservice_proxy()
|
|
97 |
|
98 |
return SucuriScanTemplate::getSection('settings-apiservice-proxy', $params);
|
99 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
97 |
|
98 |
return SucuriScanTemplate::getSection('settings-apiservice-proxy', $params);
|
99 |
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Returns the HTML to configure the URL for the checkums API.
|
103 |
+
*
|
104 |
+
* @param bool $nonce True if the CSRF protection worked, false otherwise.
|
105 |
+
* @return string HTML for the URL for the checksums API service.
|
106 |
+
*/
|
107 |
+
function sucuriscan_settings_apiservice_checksums($nonce)
|
108 |
+
{
|
109 |
+
$params = array();
|
110 |
+
$url = SucuriScanRequest::post(':checksum_api');
|
111 |
+
|
112 |
+
if ($nonce && $url !== false) {
|
113 |
+
/* https://github.com/WordPress/WordPress - OR - WordPress/WordPress */
|
114 |
+
$pattern = '/^(https:\/\/github\.com\/)?([0-9a-zA-Z_]+\/[0-9a-zA-Z_]+)/';
|
115 |
+
|
116 |
+
if (@preg_match($pattern, $url, $match)) {
|
117 |
+
SucuriScanOption::updateOption(':checksum_api', $match[2]);
|
118 |
+
|
119 |
+
$message = 'Core integrity API changed: ' . SucuriScanAPI::checksumAPI();
|
120 |
+
SucuriScanEvent::reportInfoEvent($message);
|
121 |
+
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
122 |
+
SucuriScanInterface::info(__('ChecksumsAPIChanged', SUCURISCAN_TEXTDOMAIN));
|
123 |
+
} else {
|
124 |
+
SucuriScanOption::deleteOption(':checksum_api');
|
125 |
+
|
126 |
+
$message = 'Core integrity API changed: ' . SucuriScanAPI::checksumAPI();
|
127 |
+
SucuriScanEvent::reportInfoEvent($message);
|
128 |
+
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
129 |
+
SucuriScanInterface::info(__('ChecksumsAPIChanged', SUCURISCAN_TEXTDOMAIN));
|
130 |
+
}
|
131 |
+
}
|
132 |
+
|
133 |
+
$params['ChecksumsAPI'] = SucuriScanAPI::checksumAPI();
|
134 |
+
|
135 |
+
return SucuriScanTemplate::getSection('settings-apiservice-checksums', $params);
|
136 |
+
}
|
src/settings-general.php
CHANGED
@@ -61,23 +61,16 @@ function sucuriscan_settings_general_apikey($nonce)
|
|
61 |
$display_manual_key_form = (bool) (SucuriScanRequest::post(':recover_key') !== false);
|
62 |
|
63 |
if ($nonce) {
|
64 |
-
if (!empty($_POST)) {
|
65 |
-
$fpath = SucuriScanOption::optionsFilePath();
|
66 |
-
|
67 |
-
if (!is_writable($fpath)) {
|
68 |
-
SucuriScanInterface::error(sprintf(
|
69 |
-
__('StorageNotWritable', SUCURISCAN_TEXTDOMAIN),
|
70 |
-
$fpath /* absolute path of the data storage folder */
|
71 |
-
));
|
72 |
-
}
|
73 |
-
}
|
74 |
-
|
75 |
// Remove API key from the local storage.
|
76 |
-
if (SucuriScanRequest::post(':remove_api_key') !== false
|
77 |
-
SucuriScanAPI::setPluginKey('')
|
|
|
78 |
wp_clear_scheduled_hook('sucuriscan_scheduled_scan');
|
79 |
-
|
|
|
80 |
SucuriScanEvent::notifyEvent('plugin_change', 'Sucuri API key removed');
|
|
|
|
|
81 |
}
|
82 |
|
83 |
// Save API key after it was recovered by the administrator.
|
@@ -147,7 +140,7 @@ function sucuriscan_settings_general_apikey($nonce)
|
|
147 |
* @param bool $nonce True if the CSRF protection worked.
|
148 |
* @return string Page with information about the data storage.
|
149 |
*/
|
150 |
-
function sucuriscan_settings_general_datastorage()
|
151 |
{
|
152 |
$params = array();
|
153 |
$files = array(
|
@@ -170,7 +163,7 @@ function sucuriscan_settings_general_datastorage()
|
|
170 |
$params['Storage.Files'] = '';
|
171 |
$params['Storage.Path'] = SucuriScan::dataStorePath();
|
172 |
|
173 |
-
if (
|
174 |
if ($filenames = SucuriScanRequest::post(':filename', '_array')) {
|
175 |
$deleted = 0;
|
176 |
|
@@ -458,34 +451,6 @@ function sucuriscan_settings_general_ipdiscoverer($nonce)
|
|
458 |
return SucuriScanTemplate::getSection('settings-general-ipdiscoverer', $params);
|
459 |
}
|
460 |
|
461 |
-
/**
|
462 |
-
* Renders a page with information about the auditlog stats feature.
|
463 |
-
*
|
464 |
-
* @param bool $nonce True if the CSRF protection worked.
|
465 |
-
* @return string Page with information about the auditlog stats.
|
466 |
-
*/
|
467 |
-
function sucuriscan_settings_general_auditlogstats($nonce)
|
468 |
-
{
|
469 |
-
$params = array();
|
470 |
-
|
471 |
-
if ($nonce) {
|
472 |
-
// Update the limit for audit logs report.
|
473 |
-
if ($logs4report = SucuriScanRequest::post(':logs4report', '[0-9]{1,4}')) {
|
474 |
-
$message = 'Audit log statistics limit set to <code>' . $logs4report . '</code>';
|
475 |
-
|
476 |
-
SucuriScanOption::updateOption(':logs4report', $logs4report);
|
477 |
-
SucuriScanEvent::reportInfoEvent($message);
|
478 |
-
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
479 |
-
SucuriScanInterface::info(__('LogsReportLimit', SUCURISCAN_TEXTDOMAIN));
|
480 |
-
}
|
481 |
-
}
|
482 |
-
|
483 |
-
$logs4report = SucuriScanOption::getOption(':logs4report');
|
484 |
-
$params['AuditLogStats.Limit'] = SucuriScan::escape($logs4report);
|
485 |
-
|
486 |
-
return SucuriScanTemplate::getSection('settings-general-auditlogstats', $params);
|
487 |
-
}
|
488 |
-
|
489 |
/**
|
490 |
* Renders a page with information about the import export feature.
|
491 |
*
|
@@ -509,7 +474,6 @@ function sucuriscan_settings_general_importexport($nonce)
|
|
509 |
':ignored_events',
|
510 |
':language',
|
511 |
':lastlogin_redirection',
|
512 |
-
':logs4report',
|
513 |
':maximum_failed_logins',
|
514 |
':notify_available_updates',
|
515 |
':notify_bruteforce_attack',
|
@@ -595,3 +559,52 @@ function sucuriscan_settings_general_importexport($nonce)
|
|
595 |
|
596 |
return SucuriScanTemplate::getSection('settings-general-importexport', $params);
|
597 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
61 |
$display_manual_key_form = (bool) (SucuriScanRequest::post(':recover_key') !== false);
|
62 |
|
63 |
if ($nonce) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
// Remove API key from the local storage.
|
65 |
+
if (SucuriScanRequest::post(':remove_api_key') !== false
|
66 |
+
&& SucuriScanAPI::setPluginKey('') !== false
|
67 |
+
) {
|
68 |
wp_clear_scheduled_hook('sucuriscan_scheduled_scan');
|
69 |
+
|
70 |
+
SucuriScanEvent::reportCriticalEvent('Sucuri API key has been deleted.');
|
71 |
SucuriScanEvent::notifyEvent('plugin_change', 'Sucuri API key removed');
|
72 |
+
SucuriScanInterface::info('Sucuri API key has been deleted <code>'
|
73 |
+
. SucuriScan::escape(SucuriScanAPI::getPluginKey()) . '</code>');
|
74 |
}
|
75 |
|
76 |
// Save API key after it was recovered by the administrator.
|
140 |
* @param bool $nonce True if the CSRF protection worked.
|
141 |
* @return string Page with information about the data storage.
|
142 |
*/
|
143 |
+
function sucuriscan_settings_general_datastorage($nonce)
|
144 |
{
|
145 |
$params = array();
|
146 |
$files = array(
|
163 |
$params['Storage.Files'] = '';
|
164 |
$params['Storage.Path'] = SucuriScan::dataStorePath();
|
165 |
|
166 |
+
if ($nonce) {
|
167 |
if ($filenames = SucuriScanRequest::post(':filename', '_array')) {
|
168 |
$deleted = 0;
|
169 |
|
451 |
return SucuriScanTemplate::getSection('settings-general-ipdiscoverer', $params);
|
452 |
}
|
453 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
454 |
/**
|
455 |
* Renders a page with information about the import export feature.
|
456 |
*
|
474 |
':ignored_events',
|
475 |
':language',
|
476 |
':lastlogin_redirection',
|
|
|
477 |
':maximum_failed_logins',
|
478 |
':notify_available_updates',
|
479 |
':notify_bruteforce_attack',
|
559 |
|
560 |
return SucuriScanTemplate::getSection('settings-general-importexport', $params);
|
561 |
}
|
562 |
+
|
563 |
+
/**
|
564 |
+
* Renders a page with the option to configure the timezone.
|
565 |
+
*
|
566 |
+
* @param bool $nonce True if the CSRF protection worked.
|
567 |
+
* @return string Page to configure the timezone.
|
568 |
+
*/
|
569 |
+
function sucuriscan_settings_general_timezone($nonce)
|
570 |
+
{
|
571 |
+
$params = array();
|
572 |
+
$current = time();
|
573 |
+
$options = array();
|
574 |
+
$offsets = array(
|
575 |
+
-12.0, -11.5, -11.0, -10.5, -10.0, -9.50, -9.00, -8.50, -8.00, -7.50,
|
576 |
+
-7.00, -6.50, -6.00, -5.50, -5.00, -4.50, -4.00, -3.50, -3.00, -2.50,
|
577 |
+
-2.00, -1.50, -1.00, -0.50, +0.00, +0.50, +1.00, +1.50, +2.00, +2.50,
|
578 |
+
+3.00, +3.50, +4.00, +4.50, +5.00, +5.50, +5.75, +6.00, +6.50, +7.00,
|
579 |
+
+7.50, +8.00, +8.50, +8.75, +9.00, +9.50, 10.00, 10.50, 11.00, 11.50,
|
580 |
+
12.00, 12.75, 13.00, 13.75, 14.00
|
581 |
+
);
|
582 |
+
|
583 |
+
foreach ($offsets as $hour) {
|
584 |
+
$sign = ($hour < 0) ? '-' : '+';
|
585 |
+
$fill = (abs($hour) < 10) ? '0' : '';
|
586 |
+
$keyname = sprintf('UTC%s%s%.2f', $sign, $fill, abs($hour));
|
587 |
+
$label = date('d M, Y H:i:s', $current + ($hour * 3600));
|
588 |
+
$options[$keyname] = $label;
|
589 |
+
}
|
590 |
+
|
591 |
+
if ($nonce) {
|
592 |
+
$pattern = 'UTC[\-\+][0-9]{2}\.[0-9]{2}';
|
593 |
+
$timezone = SucuriScanRequest::post(':timezone', $pattern);
|
594 |
+
|
595 |
+
if ($timezone) {
|
596 |
+
$message = 'Timezone override will use ' . $timezone;
|
597 |
+
|
598 |
+
SucuriScanOption::updateOption(':timezone', $timezone);
|
599 |
+
SucuriScanEvent::reportInfoEvent($message);
|
600 |
+
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
601 |
+
SucuriScanInterface::info(__('TimezoneStatus', SUCURISCAN_TEXTDOMAIN));
|
602 |
+
}
|
603 |
+
}
|
604 |
+
|
605 |
+
$val = SucuriScanOption::getOption(':timezone');
|
606 |
+
$params['Timezone.Dropdown'] = SucuriScanTemplate::selectOptions($options, $val);
|
607 |
+
$params['Timezone.Example'] = SucuriScan::datetime();
|
608 |
+
|
609 |
+
return SucuriScanTemplate::getSection('settings-general-timezone', $params);
|
610 |
+
}
|
src/settings-hardening.php
CHANGED
@@ -255,7 +255,11 @@ class SucuriScanHardeningPage extends SucuriScan
|
|
255 |
$params['Hardening.Title'] = __('HardeningUploadsTitle', SUCURISCAN_TEXTDOMAIN);
|
256 |
$params['Hardening.Description'] = __('HardeningUploadsDescription', SUCURISCAN_TEXTDOMAIN);
|
257 |
|
258 |
-
if (
|
|
|
|
|
|
|
|
|
259 |
$params['Hardening.Status'] = 1;
|
260 |
$params['Hardening.FieldName'] = __FUNCTION__ . '_revert';
|
261 |
$params['Hardening.FieldText'] = __('RevertHardening', SUCURISCAN_TEXTDOMAIN);
|
@@ -308,7 +312,11 @@ class SucuriScanHardeningPage extends SucuriScan
|
|
308 |
$params['Hardening.Title'] = __('HardeningContentTitle', SUCURISCAN_TEXTDOMAIN);
|
309 |
$params['Hardening.Description'] = __('HardeningContentDescription', SUCURISCAN_TEXTDOMAIN);
|
310 |
|
311 |
-
if (
|
|
|
|
|
|
|
|
|
312 |
$params['Hardening.Status'] = 1;
|
313 |
$params['Hardening.FieldName'] = __FUNCTION__ . '_revert';
|
314 |
$params['Hardening.FieldText'] = __('RevertHardening', SUCURISCAN_TEXTDOMAIN);
|
@@ -371,7 +379,11 @@ class SucuriScanHardeningPage extends SucuriScan
|
|
371 |
$params['Hardening.Title'] = __('HardeningIncludesTitle', SUCURISCAN_TEXTDOMAIN);
|
372 |
$params['Hardening.Description'] = __('HardeningIncludesDescription', SUCURISCAN_TEXTDOMAIN);
|
373 |
|
374 |
-
if (
|
|
|
|
|
|
|
|
|
375 |
$params['Hardening.Status'] = 1;
|
376 |
$params['Hardening.FieldName'] = __FUNCTION__ . '_revert';
|
377 |
$params['Hardening.FieldText'] = __('RevertHardening', SUCURISCAN_TEXTDOMAIN);
|
255 |
$params['Hardening.Title'] = __('HardeningUploadsTitle', SUCURISCAN_TEXTDOMAIN);
|
256 |
$params['Hardening.Description'] = __('HardeningUploadsDescription', SUCURISCAN_TEXTDOMAIN);
|
257 |
|
258 |
+
if (SucuriScan::isBehindFirewall()) {
|
259 |
+
$params['Hardening.Status'] = 1;
|
260 |
+
$params['Hardening.FieldAttrs'] = 'disabled';
|
261 |
+
$params['Hardening.FieldText'] = __('RevertHardening', SUCURISCAN_TEXTDOMAIN);
|
262 |
+
} elseif (SucuriScanHardening::isHardened($folder)) {
|
263 |
$params['Hardening.Status'] = 1;
|
264 |
$params['Hardening.FieldName'] = __FUNCTION__ . '_revert';
|
265 |
$params['Hardening.FieldText'] = __('RevertHardening', SUCURISCAN_TEXTDOMAIN);
|
312 |
$params['Hardening.Title'] = __('HardeningContentTitle', SUCURISCAN_TEXTDOMAIN);
|
313 |
$params['Hardening.Description'] = __('HardeningContentDescription', SUCURISCAN_TEXTDOMAIN);
|
314 |
|
315 |
+
if (SucuriScan::isBehindFirewall()) {
|
316 |
+
$params['Hardening.Status'] = 1;
|
317 |
+
$params['Hardening.FieldAttrs'] = 'disabled';
|
318 |
+
$params['Hardening.FieldText'] = __('RevertHardening', SUCURISCAN_TEXTDOMAIN);
|
319 |
+
} elseif (SucuriScanHardening::isHardened(WP_CONTENT_DIR)) {
|
320 |
$params['Hardening.Status'] = 1;
|
321 |
$params['Hardening.FieldName'] = __FUNCTION__ . '_revert';
|
322 |
$params['Hardening.FieldText'] = __('RevertHardening', SUCURISCAN_TEXTDOMAIN);
|
379 |
$params['Hardening.Title'] = __('HardeningIncludesTitle', SUCURISCAN_TEXTDOMAIN);
|
380 |
$params['Hardening.Description'] = __('HardeningIncludesDescription', SUCURISCAN_TEXTDOMAIN);
|
381 |
|
382 |
+
if (SucuriScan::isBehindFirewall()) {
|
383 |
+
$params['Hardening.Status'] = 1;
|
384 |
+
$params['Hardening.FieldAttrs'] = 'disabled';
|
385 |
+
$params['Hardening.FieldText'] = __('RevertHardening', SUCURISCAN_TEXTDOMAIN);
|
386 |
+
} elseif (SucuriScanHardening::isHardened($folder)) {
|
387 |
$params['Hardening.Status'] = 1;
|
388 |
$params['Hardening.FieldName'] = __FUNCTION__ . '_revert';
|
389 |
$params['Hardening.FieldText'] = __('RevertHardening', SUCURISCAN_TEXTDOMAIN);
|
src/settings-integrity.php
CHANGED
@@ -87,7 +87,7 @@ class SucuriScanSettingsIntegrity extends SucuriScanSettings
|
|
87 |
$message = 'Core integrity language set to <code>' . $language . '</code>';
|
88 |
|
89 |
SucuriScanOption::updateOption(':language', $language);
|
90 |
-
SucuriScanEvent::
|
91 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
92 |
SucuriScanInterface::info(__('IntegrityLanguage', SUCURISCAN_TEXTDOMAIN));
|
93 |
} else {
|
87 |
$message = 'Core integrity language set to <code>' . $language . '</code>';
|
88 |
|
89 |
SucuriScanOption::updateOption(':language', $language);
|
90 |
+
SucuriScanEvent::reportInfoEvent($message);
|
91 |
SucuriScanEvent::notifyEvent('plugin_change', $message);
|
92 |
SucuriScanInterface::info(__('IntegrityLanguage', SUCURISCAN_TEXTDOMAIN));
|
93 |
} else {
|
src/settings-scanner.php
CHANGED
@@ -27,7 +27,7 @@ class SucuriScanSettingsScanner extends SucuriScanSettings
|
|
27 |
* @param bool $nonce True if the CSRF protection worked.
|
28 |
* @return string Page with information about the cronjobs.
|
29 |
*/
|
30 |
-
public static function cronjobs()
|
31 |
{
|
32 |
$params = array(
|
33 |
'Cronjobs.List' => '',
|
@@ -35,14 +35,9 @@ class SucuriScanSettingsScanner extends SucuriScanSettings
|
|
35 |
'Cronjob.Schedules' => '',
|
36 |
);
|
37 |
|
38 |
-
|
39 |
-
|
40 |
-
if (SucuriScanInterface::checkNonce()) {
|
41 |
// Modify the scheduled tasks (run now, remove, re-schedule).
|
42 |
-
$
|
43 |
-
? SucuriScanEvent::availableSchedules()
|
44 |
-
: $schedule_allowed;
|
45 |
-
$allowed_actions = array_keys($available);
|
46 |
$allowed_actions[] = 'runnow'; /* execute in the next 10 seconds */
|
47 |
$allowed_actions[] = 'remove'; /* can be reinstalled automatically */
|
48 |
$allowed_actions = sprintf('(%s)', implode('|', $allowed_actions));
|
@@ -105,9 +100,7 @@ class SucuriScanSettingsScanner extends SucuriScanSettings
|
|
105 |
}
|
106 |
|
107 |
$cronjobs = _get_cron_array();
|
108 |
-
$available = (
|
109 |
-
? SucuriScanEvent::availableSchedules()
|
110 |
-
: $schedule_allowed;
|
111 |
|
112 |
/* Hardcode the first one to allow the immediate execution of the cronjob(s) */
|
113 |
$params['Cronjob.Schedules'] .= '<option value="runnow">'
|
27 |
* @param bool $nonce True if the CSRF protection worked.
|
28 |
* @return string Page with information about the cronjobs.
|
29 |
*/
|
30 |
+
public static function cronjobs($nonce)
|
31 |
{
|
32 |
$params = array(
|
33 |
'Cronjobs.List' => '',
|
35 |
'Cronjob.Schedules' => '',
|
36 |
);
|
37 |
|
38 |
+
if ($nonce) {
|
|
|
|
|
39 |
// Modify the scheduled tasks (run now, remove, re-schedule).
|
40 |
+
$allowed_actions = array_keys(SucuriScanEvent::availableSchedules());
|
|
|
|
|
|
|
41 |
$allowed_actions[] = 'runnow'; /* execute in the next 10 seconds */
|
42 |
$allowed_actions[] = 'remove'; /* can be reinstalled automatically */
|
43 |
$allowed_actions = sprintf('(%s)', implode('|', $allowed_actions));
|
100 |
}
|
101 |
|
102 |
$cronjobs = _get_cron_array();
|
103 |
+
$available = SucuriScanEvent::availableSchedules();
|
|
|
|
|
104 |
|
105 |
/* Hardcode the first one to allow the immediate execution of the cronjob(s) */
|
106 |
$params['Cronjob.Schedules'] .= '<option value="runnow">'
|
src/settings-webinfo.php
CHANGED
@@ -35,7 +35,7 @@ function sucuriscan_settings_webinfo_details()
|
|
35 |
'Datetime_and_Timezone' => '',
|
36 |
'Operating_system' => sprintf('%s (%d Bit)', PHP_OS, PHP_INT_SIZE * 8),
|
37 |
'Server' => __('Unknown', SUCURISCAN_TEXTDOMAIN),
|
38 |
-
'
|
39 |
'Memory_usage' => __('Unknown', SUCURISCAN_TEXTDOMAIN),
|
40 |
'MySQL_version' => '0.0',
|
41 |
'SQL_mode' => __('NotSet', SUCURISCAN_TEXTDOMAIN),
|
@@ -43,13 +43,13 @@ function sucuriscan_settings_webinfo_details()
|
|
43 |
);
|
44 |
|
45 |
$info_vars['Datetime_and_Timezone'] = sprintf(
|
46 |
-
'%s (
|
47 |
-
SucuriScan::
|
48 |
-
SucuriScanOption::getOption('
|
49 |
);
|
50 |
|
51 |
if (defined('WP_DEBUG') && WP_DEBUG) {
|
52 |
-
$info_vars['
|
53 |
}
|
54 |
|
55 |
if (function_exists('memory_get_usage')) {
|
@@ -69,6 +69,7 @@ function sucuriscan_settings_webinfo_details()
|
|
69 |
}
|
70 |
}
|
71 |
|
|
|
72 |
$field_names = array(
|
73 |
'safe_mode',
|
74 |
'expose_php',
|
@@ -86,6 +87,22 @@ function sucuriscan_settings_webinfo_details()
|
|
86 |
$info_vars[$php_flag_name] = $php_flag_value ? $php_flag_value : 'N/A';
|
87 |
}
|
88 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
89 |
foreach ($info_vars as $var_name => $var_value) {
|
90 |
$var_name = str_replace('_', "\x20", $var_name);
|
91 |
|
@@ -99,106 +116,6 @@ function sucuriscan_settings_webinfo_details()
|
|
99 |
return SucuriScanTemplate::getSection('settings-webinfo-details', $params);
|
100 |
}
|
101 |
|
102 |
-
/**
|
103 |
-
* Retrieve all the constants and variables with their respective values defined
|
104 |
-
* in the WordPress configuration file, only the database password constant is
|
105 |
-
* omitted for security reasons.
|
106 |
-
*
|
107 |
-
* @return string The HTML code displaying the constants and variables found in the wp-config file.
|
108 |
-
*/
|
109 |
-
function sucuriscan_settings_webinfo_wpconfig()
|
110 |
-
{
|
111 |
-
$params = array(
|
112 |
-
'WordpressConfig.Rules' => '',
|
113 |
-
'WordpressConfig.Total' => 0,
|
114 |
-
);
|
115 |
-
|
116 |
-
$ignore_wp_rules = array('DB_PASSWORD');
|
117 |
-
$wp_config_path = SucuriScan::getWPConfigPath();
|
118 |
-
|
119 |
-
if ($wp_config_path) {
|
120 |
-
$wp_config_rules = array();
|
121 |
-
$wp_config_content = SucuriScanFileInfo::fileLines($wp_config_path);
|
122 |
-
|
123 |
-
// Parse the main configuration file and look for constants and global variables.
|
124 |
-
foreach ((array) $wp_config_content as $line) {
|
125 |
-
if (@preg_match('/^\s?(#|\/\/)/', $line)) {
|
126 |
-
continue; /* Ignore commented lines. */
|
127 |
-
} elseif (@preg_match('/define\(/', $line)) {
|
128 |
-
// Detect PHP constants even if the line if indented.
|
129 |
-
$line = preg_replace('/.*define\((.+)\);.*/', '$1', $line);
|
130 |
-
$line_parts = explode(',', $line, 2);
|
131 |
-
} elseif (@preg_match('/^\$[a-zA-Z_]+/', $line)) {
|
132 |
-
// Detect global variables like the database table prefix.
|
133 |
-
$line = @preg_replace('/;\s\/\/.*/', ';', $line);
|
134 |
-
$line_parts = explode('=', $line, 2);
|
135 |
-
} else {
|
136 |
-
continue; /* Ignore other lines. */
|
137 |
-
}
|
138 |
-
|
139 |
-
// Clean and append the rule to the wp_config_rules variable.
|
140 |
-
if (isset($line_parts) && count($line_parts) === 2) {
|
141 |
-
$key_name = '';
|
142 |
-
$key_value = '';
|
143 |
-
|
144 |
-
// TODO: A foreach loop is not really necessary, find a better way.
|
145 |
-
foreach ($line_parts as $i => $line_part) {
|
146 |
-
$line_part = trim($line_part);
|
147 |
-
$line_part = ltrim($line_part, '$');
|
148 |
-
$line_part = rtrim($line_part, ';');
|
149 |
-
|
150 |
-
// Remove single/double quotes at the beginning and end of the string.
|
151 |
-
$line_part = ltrim($line_part, "'");
|
152 |
-
$line_part = rtrim($line_part, "'");
|
153 |
-
$line_part = ltrim($line_part, '"');
|
154 |
-
$line_part = rtrim($line_part, '"');
|
155 |
-
|
156 |
-
// Assign the clean strings to specific variables.
|
157 |
-
if ($i == 0) {
|
158 |
-
$key_name = $line_part;
|
159 |
-
}
|
160 |
-
|
161 |
-
if ($i == 1) {
|
162 |
-
if (defined($key_name)) {
|
163 |
-
$key_value = constant($key_name);
|
164 |
-
|
165 |
-
if (is_bool($key_value)) {
|
166 |
-
$key_value = ($key_value === true) ? 'True' : 'False';
|
167 |
-
}
|
168 |
-
} else {
|
169 |
-
$key_value = $line_part;
|
170 |
-
}
|
171 |
-
}
|
172 |
-
}
|
173 |
-
|
174 |
-
// Remove the value of sensitive variables like the database password.
|
175 |
-
if (in_array($key_name, $ignore_wp_rules)) {
|
176 |
-
$key_value = 'hidden';
|
177 |
-
}
|
178 |
-
|
179 |
-
// Append the value to the configuration rules.
|
180 |
-
$wp_config_rules[$key_name] = $key_value;
|
181 |
-
}
|
182 |
-
}
|
183 |
-
|
184 |
-
// Pass the WordPress configuration rules to the template and show them.
|
185 |
-
foreach ($wp_config_rules as $var_name => $var_value) {
|
186 |
-
if (empty($var_value)) {
|
187 |
-
$var_value = '--';
|
188 |
-
}
|
189 |
-
|
190 |
-
$params['WordpressConfig.Total'] += 1;
|
191 |
-
$params['WordpressConfig.Rules'] .=
|
192 |
-
SucuriScanTemplate::getSnippet('settings-webinfo-wpconfig', array(
|
193 |
-
'WordpressConfig.VariableName' => $var_name,
|
194 |
-
'WordpressConfig.VariableValue' => $var_value,
|
195 |
-
));
|
196 |
-
}
|
197 |
-
}
|
198 |
-
|
199 |
-
return SucuriScanTemplate::getSection('settings-webinfo-wpconfig', $params);
|
200 |
-
}
|
201 |
-
|
202 |
/**
|
203 |
* Find the main htaccess file for the site and check whether the rules of the
|
204 |
* main htaccess file of the site are the default rules generated by WordPress.
|
35 |
'Datetime_and_Timezone' => '',
|
36 |
'Operating_system' => sprintf('%s (%d Bit)', PHP_OS, PHP_INT_SIZE * 8),
|
37 |
'Server' => __('Unknown', SUCURISCAN_TEXTDOMAIN),
|
38 |
+
'WordPress_debug' => __('NotActive', SUCURISCAN_TEXTDOMAIN),
|
39 |
'Memory_usage' => __('Unknown', SUCURISCAN_TEXTDOMAIN),
|
40 |
'MySQL_version' => '0.0',
|
41 |
'SQL_mode' => __('NotSet', SUCURISCAN_TEXTDOMAIN),
|
43 |
);
|
44 |
|
45 |
$info_vars['Datetime_and_Timezone'] = sprintf(
|
46 |
+
'%s (%s)',
|
47 |
+
SucuriScan::datetime(),
|
48 |
+
SucuriScanOption::getOption(':timezone')
|
49 |
);
|
50 |
|
51 |
if (defined('WP_DEBUG') && WP_DEBUG) {
|
52 |
+
$info_vars['WordPress_debug'] = __('Active', SUCURISCAN_TEXTDOMAIN);
|
53 |
}
|
54 |
|
55 |
if (function_exists('memory_get_usage')) {
|
69 |
}
|
70 |
}
|
71 |
|
72 |
+
/* PHP INI Settings */
|
73 |
$field_names = array(
|
74 |
'safe_mode',
|
75 |
'expose_php',
|
87 |
$info_vars[$php_flag_name] = $php_flag_value ? $php_flag_value : 'N/A';
|
88 |
}
|
89 |
|
90 |
+
/* PHP constants */
|
91 |
+
$constants = array(
|
92 |
+
'ABSPATH',
|
93 |
+
// 'SUCURISCAN',
|
94 |
+
// 'SUCURISCAN_INIT',
|
95 |
+
'SUCURISCAN_API_URL',
|
96 |
+
'SUCURI_DATA_STORAGE',
|
97 |
+
// 'SUCURISCAN_ADMIN_INIT',
|
98 |
+
'SUCURISCAN_GET_PLUGINS_LIFETIME',
|
99 |
+
'SUCURISCAN_THROW_EXCEPTIONS',
|
100 |
+
);
|
101 |
+
|
102 |
+
foreach ($constants as $name) {
|
103 |
+
$info_vars[$name] = defined($name) ? constant($name) : '--';
|
104 |
+
}
|
105 |
+
|
106 |
foreach ($info_vars as $var_name => $var_value) {
|
107 |
$var_name = str_replace('_', "\x20", $var_name);
|
108 |
|
116 |
return SucuriScanTemplate::getSection('settings-webinfo-details', $params);
|
117 |
}
|
118 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
119 |
/**
|
120 |
* Find the main htaccess file for the site and check whether the rules of the
|
121 |
* main htaccess file of the site are the default rules generated by WordPress.
|
src/sitecheck.lib.php
CHANGED
@@ -32,27 +32,39 @@ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
|
|
32 |
*/
|
33 |
class SucuriScanSiteCheck extends SucuriScanAPI
|
34 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
/**
|
36 |
* Executes a malware scan against the specified website.
|
37 |
*
|
38 |
* @see https://sitecheck.sucuri.net/
|
39 |
*
|
40 |
-
* @param string $domain The clean version of the website's domain.
|
41 |
* @param bool $clear Request the results from a fresh scan or not.
|
42 |
* @return array|bool JSON encoded website scan results.
|
43 |
*/
|
44 |
-
public static function runMalwareScan($
|
45 |
{
|
46 |
-
if (empty($domain)) {
|
47 |
-
return false;
|
48 |
-
}
|
49 |
-
|
50 |
$params = array();
|
51 |
-
$params['scan'] = $domain;
|
52 |
-
$params['fromwp'] = 2;
|
53 |
$params['json'] = 1;
|
|
|
|
|
54 |
|
55 |
-
|
56 |
if ($clear === true) {
|
57 |
$params['clear'] = 1;
|
58 |
}
|
@@ -86,33 +98,19 @@ class SucuriScanSiteCheck extends SucuriScanAPI
|
|
86 |
*/
|
87 |
public static function scanAndCollectData()
|
88 |
{
|
89 |
-
$tld = SucuriScan::getDomain();
|
90 |
$cache = new SucuriScanCache('sitecheck');
|
91 |
$results = $cache->get('scan_results', SUCURISCAN_SITECHECK_LIFETIME, 'array');
|
92 |
|
93 |
-
/**
|
94 |
-
* Allow the user to scan foreign domains.
|
95 |
-
*
|
96 |
-
* This condition allows for the execution of the malware scanner on a
|
97 |
-
* website different than the one where the plugin is installed. This is
|
98 |
-
* basically the same as scanning any domain on the SiteCheck website.
|
99 |
-
* In this case, this is mostly used to allow the development execute
|
100 |
-
* tests and to troubleshoot issues reported by other users.
|
101 |
-
*
|
102 |
-
* @var boolean
|
103 |
-
*/
|
104 |
-
if ($custom = SucuriScanRequest::get('s')) {
|
105 |
-
$tld = SucuriScan::escape($custom);
|
106 |
-
$results = false /* invalid cache */;
|
107 |
-
}
|
108 |
-
|
109 |
/* return cached malware scan results. */
|
110 |
if ($results && !empty($results)) {
|
111 |
return $results;
|
112 |
}
|
113 |
|
|
|
|
|
|
|
114 |
/* send HTTP request to SiteCheck's API service. */
|
115 |
-
$results = self::runMalwareScan(
|
116 |
|
117 |
/* check for error in the request's response. */
|
118 |
if (is_string($results) || isset($results['SYSTEM']['ERROR'])) {
|
@@ -124,7 +122,6 @@ class SucuriScanSiteCheck extends SucuriScanAPI
|
|
124 |
}
|
125 |
|
126 |
/* cache the results for some time. */
|
127 |
-
$cache = new SucuriScanCache('sitecheck');
|
128 |
$cache->add('scan_results', $results);
|
129 |
|
130 |
return $results;
|
@@ -398,23 +395,8 @@ class SucuriScanSiteCheck extends SucuriScanAPI
|
|
398 |
*/
|
399 |
public static function iFramesContent()
|
400 |
{
|
401 |
-
$params = array();
|
402 |
$data = self::scanAndCollectData();
|
403 |
-
|
404 |
-
if (!isset($data['LINKS']['IFRAME'])) {
|
405 |
-
return ''; /* empty content */
|
406 |
-
}
|
407 |
-
|
408 |
-
$params['SiteCheck.Resources'] = '';
|
409 |
-
|
410 |
-
foreach ($data['LINKS']['IFRAME'] as $url) {
|
411 |
-
$params['SiteCheck.Resources'] .=
|
412 |
-
SucuriScanTemplate::getSnippet('sitecheck-links', array(
|
413 |
-
'SiteCheck.URL' => $url,
|
414 |
-
));
|
415 |
-
}
|
416 |
-
|
417 |
-
return SucuriScanTemplate::getSection('sitecheck-links', $params);
|
418 |
}
|
419 |
|
420 |
/**
|
@@ -424,64 +406,29 @@ class SucuriScanSiteCheck extends SucuriScanAPI
|
|
424 |
*/
|
425 |
public static function linksContent()
|
426 |
{
|
427 |
-
$params = array();
|
428 |
$data = self::scanAndCollectData();
|
429 |
-
|
430 |
-
if (!isset($data['LINKS']['URL'])) {
|
431 |
-
return ''; /* empty content */
|
432 |
-
}
|
433 |
-
|
434 |
-
$params['SiteCheck.Resources'] = '';
|
435 |
-
|
436 |
-
foreach ($data['LINKS']['URL'] as $url) {
|
437 |
-
$params['SiteCheck.Resources'] .=
|
438 |
-
SucuriScanTemplate::getSnippet('sitecheck-links', array(
|
439 |
-
'SiteCheck.URL' => $url,
|
440 |
-
));
|
441 |
-
}
|
442 |
-
|
443 |
-
return SucuriScanTemplate::getSection('sitecheck-links', $params);
|
444 |
}
|
445 |
|
446 |
/**
|
447 |
* Returns the content for the scripts section.
|
448 |
*
|
449 |
-
* @return
|
450 |
*/
|
451 |
public static function scriptsContent()
|
452 |
{
|
453 |
-
$
|
454 |
-
$params = array();
|
455 |
$data = self::scanAndCollectData();
|
456 |
|
457 |
-
$params['SiteCheck.Resources'] = '';
|
458 |
-
|
459 |
if (isset($data['LINKS']['JSLOCAL'])) {
|
460 |
-
|
461 |
-
$total++;
|
462 |
-
|
463 |
-
$params['SiteCheck.Resources'] .=
|
464 |
-
SucuriScanTemplate::getSnippet('sitecheck-links', array(
|
465 |
-
'SiteCheck.URL' => $url,
|
466 |
-
));
|
467 |
-
}
|
468 |
}
|
469 |
|
470 |
if (isset($data['LINKS']['JSEXTERNAL'])) {
|
471 |
-
|
472 |
-
$total++;
|
473 |
-
$params['SiteCheck.Resources'] .=
|
474 |
-
SucuriScanTemplate::getSnippet('sitecheck-links', array(
|
475 |
-
'SiteCheck.URL' => $url,
|
476 |
-
));
|
477 |
-
}
|
478 |
-
}
|
479 |
-
|
480 |
-
if ($total === 0) {
|
481 |
-
return ''; /* empty content */
|
482 |
}
|
483 |
|
484 |
-
return
|
485 |
}
|
486 |
|
487 |
/**
|
@@ -516,9 +463,11 @@ class SucuriScanSiteCheck extends SucuriScanAPI
|
|
516 |
$malware_parts = explode("\n", $malware[1]);
|
517 |
|
518 |
if (isset($malware_parts[1])) {
|
519 |
-
|
520 |
-
|
521 |
-
$
|
|
|
|
|
522 |
}
|
523 |
|
524 |
$data['malware_payload'] = trim($malware_parts[1]);
|
@@ -573,4 +522,25 @@ class SucuriScanSiteCheck extends SucuriScanAPI
|
|
573 |
|
574 |
wp_send_json($response, 200);
|
575 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
576 |
}
|
32 |
*/
|
33 |
class SucuriScanSiteCheck extends SucuriScanAPI
|
34 |
{
|
35 |
+
/**
|
36 |
+
* Returns the URL that will be scanned by SiteCheck.
|
37 |
+
*
|
38 |
+
* @return string URL to be scanned.
|
39 |
+
*/
|
40 |
+
private static function targetURL()
|
41 |
+
{
|
42 |
+
$url = SucuriScan::getDomain();
|
43 |
+
|
44 |
+
/* allow to set a custom URL for the scans */
|
45 |
+
if ($custom = SucuriScanOption::getOption(':sitecheck_target')) {
|
46 |
+
return $custom;
|
47 |
+
}
|
48 |
+
|
49 |
+
return $url;
|
50 |
+
}
|
51 |
+
|
52 |
/**
|
53 |
* Executes a malware scan against the specified website.
|
54 |
*
|
55 |
* @see https://sitecheck.sucuri.net/
|
56 |
*
|
|
|
57 |
* @param bool $clear Request the results from a fresh scan or not.
|
58 |
* @return array|bool JSON encoded website scan results.
|
59 |
*/
|
60 |
+
public static function runMalwareScan($clear = false)
|
61 |
{
|
|
|
|
|
|
|
|
|
62 |
$params = array();
|
|
|
|
|
63 |
$params['json'] = 1;
|
64 |
+
$params['fromwp'] = 2;
|
65 |
+
$params['scan'] = self::targetURL();
|
66 |
|
67 |
+
/* force clear scan */
|
68 |
if ($clear === true) {
|
69 |
$params['clear'] = 1;
|
70 |
}
|
98 |
*/
|
99 |
public static function scanAndCollectData()
|
100 |
{
|
|
|
101 |
$cache = new SucuriScanCache('sitecheck');
|
102 |
$results = $cache->get('scan_results', SUCURISCAN_SITECHECK_LIFETIME, 'array');
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
/* return cached malware scan results. */
|
105 |
if ($results && !empty($results)) {
|
106 |
return $results;
|
107 |
}
|
108 |
|
109 |
+
/* delete expired cache */
|
110 |
+
$cache->delete('scan_results');
|
111 |
+
|
112 |
/* send HTTP request to SiteCheck's API service. */
|
113 |
+
$results = self::runMalwareScan();
|
114 |
|
115 |
/* check for error in the request's response. */
|
116 |
if (is_string($results) || isset($results['SYSTEM']['ERROR'])) {
|
122 |
}
|
123 |
|
124 |
/* cache the results for some time. */
|
|
|
125 |
$cache->add('scan_results', $results);
|
126 |
|
127 |
return $results;
|
395 |
*/
|
396 |
public static function iFramesContent()
|
397 |
{
|
|
|
398 |
$data = self::scanAndCollectData();
|
399 |
+
return isset($data['LINKS']['IFRAME']) ? $data['LINKS']['IFRAME'] : array();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
400 |
}
|
401 |
|
402 |
/**
|
406 |
*/
|
407 |
public static function linksContent()
|
408 |
{
|
|
|
409 |
$data = self::scanAndCollectData();
|
410 |
+
return isset($data['LINKS']['URL']) ? $data['LINKS']['URL'] : array();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
411 |
}
|
412 |
|
413 |
/**
|
414 |
* Returns the content for the scripts section.
|
415 |
*
|
416 |
+
* @return array Content for the scripts section.
|
417 |
*/
|
418 |
public static function scriptsContent()
|
419 |
{
|
420 |
+
$links = array();
|
|
|
421 |
$data = self::scanAndCollectData();
|
422 |
|
|
|
|
|
423 |
if (isset($data['LINKS']['JSLOCAL'])) {
|
424 |
+
$links = array_merge($links, $data['LINKS']['JSLOCAL']);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
425 |
}
|
426 |
|
427 |
if (isset($data['LINKS']['JSEXTERNAL'])) {
|
428 |
+
$links = array_merge($links, $data['LINKS']['JSEXTERNAL']);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
429 |
}
|
430 |
|
431 |
+
return $links;
|
432 |
}
|
433 |
|
434 |
/**
|
463 |
$malware_parts = explode("\n", $malware[1]);
|
464 |
|
465 |
if (isset($malware_parts[1])) {
|
466 |
+
$pattern = ".\x20Details:\x20";
|
467 |
+
if (strpos($malware_parts[0], $pattern) !== false) {
|
468 |
+
$offset = strpos($malware_parts[0], $pattern);
|
469 |
+
$data['malware_type'] = substr($malware_parts[0], 0, $offset);
|
470 |
+
$data['malware_docs'] = substr($malware_parts[0], $offset+11);
|
471 |
}
|
472 |
|
473 |
$data['malware_payload'] = trim($malware_parts[1]);
|
522 |
|
523 |
wp_send_json($response, 200);
|
524 |
}
|
525 |
+
|
526 |
+
/**
|
527 |
+
* Returns the HTML to configure the API SiteCheck service.
|
528 |
+
*
|
529 |
+
* @return string HTML for the API SiteCheck service option.
|
530 |
+
*/
|
531 |
+
public static function targetURLOption()
|
532 |
+
{
|
533 |
+
$params = array();
|
534 |
+
|
535 |
+
if (SucuriScanInterface::checkNonce()) {
|
536 |
+
$custom = SucuriScanRequest::post(':sitecheck_target');
|
537 |
+
if ($custom !== false) {
|
538 |
+
SucuriScanOption::updateOption(':sitecheck_target', $custom);
|
539 |
+
}
|
540 |
+
}
|
541 |
+
|
542 |
+
$params['SiteCheck.Target'] = self::targetURL();
|
543 |
+
|
544 |
+
return SucuriScanTemplate::getSection('sitecheck-target', $params);
|
545 |
+
}
|
546 |
}
|
src/sucuriscan.lib.php
CHANGED
@@ -593,25 +593,31 @@ class SucuriScan
|
|
593 |
*/
|
594 |
public static function isBehindFirewall($verbose = false)
|
595 |
{
|
|
|
|
|
|
|
596 |
$http_host = self::getTopLevelDomain();
|
597 |
|
598 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
599 |
$host_by_addr = @gethostbyname($http_host);
|
600 |
$host_by_name = @gethostbyaddr($host_by_addr);
|
601 |
$status = (bool) preg_match('/^cloudproxy[0-9]+\.sucuri\.net$/', $host_by_name);
|
602 |
-
} else {
|
603 |
-
$status = false;
|
604 |
-
$host_by_addr = '::1';
|
605 |
-
$host_by_name = 'localhost';
|
606 |
-
}
|
607 |
-
|
608 |
-
/*
|
609 |
-
* If the DNS reversion failed but the firewall API key is set, then consider
|
610 |
-
* the site as protected by a firewall. A fake key can be used to bypass the DNS
|
611 |
-
* checking, but that is not something that will affect us, only the client.
|
612 |
-
*/
|
613 |
-
if (!$status && SucuriScanFirewall::getKey()) {
|
614 |
-
$status = true;
|
615 |
}
|
616 |
|
617 |
if ($verbose) {
|
@@ -697,17 +703,6 @@ class SucuriScan
|
|
697 |
return $valid_users;
|
698 |
}
|
699 |
|
700 |
-
/**
|
701 |
-
* Returns the current time measured in the number of seconds since the Unix Epoch.
|
702 |
-
*
|
703 |
-
* @see https://developer.wordpress.org/reference/functions/current_time/
|
704 |
-
* @return int Return current Unix timestamp.
|
705 |
-
*/
|
706 |
-
public static function localTime()
|
707 |
-
{
|
708 |
-
return current_time('timestamp', false);
|
709 |
-
}
|
710 |
-
|
711 |
/**
|
712 |
* Retrieve the date in localized format, based on timestamp.
|
713 |
*
|
@@ -715,70 +710,42 @@ class SucuriScan
|
|
715 |
* take over the format for the date. If it isn't, then the date format string
|
716 |
* will be used instead.
|
717 |
*
|
718 |
-
* @param int $timestamp Unix timestamp.
|
|
|
719 |
* @return string The date, translated if locale specifies it.
|
720 |
*/
|
721 |
-
public static function datetime($timestamp = null)
|
722 |
{
|
723 |
-
|
|
|
|
|
724 |
|
725 |
-
|
726 |
-
|
727 |
-
if (is_numeric($timestamp) && $timestamp > 0) {
|
728 |
-
return date_i18n($tz_format, $timestamp);
|
729 |
}
|
730 |
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
}
|
743 |
-
|
744 |
-
/**
|
745 |
-
* Return the time passed since the specified timestamp until now.
|
746 |
-
*
|
747 |
-
* @param int|string $timestamp Unix time of a day in the past.
|
748 |
-
* @return string Time passed since the timestamp specified.
|
749 |
-
*/
|
750 |
-
public static function timeAgo($timestamp = 0)
|
751 |
-
{
|
752 |
-
if (!is_numeric($timestamp)) {
|
753 |
-
$timestamp = strtotime($timestamp);
|
754 |
}
|
755 |
|
756 |
-
$
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
|
|
761 |
}
|
762 |
|
763 |
-
$
|
764 |
-
1 => array( 'year', 31556926, ),
|
765 |
-
$diff < 31556926 => array( 'month', 2592000, ),
|
766 |
-
$diff < 2592000 => array( 'week', 604800, ),
|
767 |
-
$diff < 604800 => array( 'day', 86400, ),
|
768 |
-
$diff < 86400 => array( 'hour', 3600, ),
|
769 |
-
$diff < 3600 => array( 'minute', 60, ),
|
770 |
-
$diff < 60 => array( 'second', 1, ),
|
771 |
-
);
|
772 |
-
|
773 |
-
$value = floor($diff / $intervals[1][1]);
|
774 |
-
$time_ago = sprintf(
|
775 |
-
'%s %s%s ago',
|
776 |
-
$value,
|
777 |
-
$intervals[1][0],
|
778 |
-
( $value > 1 ? 's' : '' )
|
779 |
-
);
|
780 |
-
|
781 |
-
return $time_ago;
|
782 |
}
|
783 |
|
784 |
/**
|
@@ -925,7 +892,7 @@ class SucuriScan
|
|
925 |
*/
|
926 |
public static function isNginxServer()
|
927 |
{
|
928 |
-
return (bool)
|
929 |
}
|
930 |
|
931 |
/**
|
@@ -935,7 +902,7 @@ class SucuriScan
|
|
935 |
*/
|
936 |
public static function isIISServer()
|
937 |
{
|
938 |
-
return (bool)
|
939 |
}
|
940 |
|
941 |
/**
|
593 |
*/
|
594 |
public static function isBehindFirewall($verbose = false)
|
595 |
{
|
596 |
+
$status = false;
|
597 |
+
$host_by_addr = '::1';
|
598 |
+
$host_by_name = 'localhost';
|
599 |
$http_host = self::getTopLevelDomain();
|
600 |
|
601 |
+
/**
|
602 |
+
* Consider firewall protected if the API key is set.
|
603 |
+
*
|
604 |
+
* Assume that the Sucuri Firewall is protecting this website if there
|
605 |
+
* is a valid API key set in the Firewall page, otherwise execute the
|
606 |
+
* DNS lookup to try to find the name of the server which will help us
|
607 |
+
* determine if the website is behind the Sucuri Firewall or not.
|
608 |
+
*
|
609 |
+
* Notice that this DNS lookup may slow down a website that is hosted in
|
610 |
+
* a hosting pointing to a slow DNS server, the latency in the queries
|
611 |
+
* will be noticeable. Webmasters can disable this behavior by setting
|
612 |
+
* the ":dns_lookups" option as "disabled" or adding this constant to
|
613 |
+
* the WordPress configuration file: (NOT_USING_CLOUDPROXY, true)
|
614 |
+
*/
|
615 |
+
if (SucuriScanFirewall::getKey()) {
|
616 |
+
$status = true;
|
617 |
+
} elseif (self::executeDNSLookups()) {
|
618 |
$host_by_addr = @gethostbyname($http_host);
|
619 |
$host_by_name = @gethostbyaddr($host_by_addr);
|
620 |
$status = (bool) preg_match('/^cloudproxy[0-9]+\.sucuri\.net$/', $host_by_name);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
621 |
}
|
622 |
|
623 |
if ($verbose) {
|
703 |
return $valid_users;
|
704 |
}
|
705 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
706 |
/**
|
707 |
* Retrieve the date in localized format, based on timestamp.
|
708 |
*
|
710 |
* take over the format for the date. If it isn't, then the date format string
|
711 |
* will be used instead.
|
712 |
*
|
713 |
+
* @param null|string|int $timestamp Unix timestamp.
|
714 |
+
* @param string $format Optional format for the date and time.
|
715 |
* @return string The date, translated if locale specifies it.
|
716 |
*/
|
717 |
+
public static function datetime($timestamp = null, $format = null)
|
718 |
{
|
719 |
+
$diff = 0; /* use server time */
|
720 |
+
$tz = SucuriScanOption::getOption(':timezone');
|
721 |
+
$length = strlen($tz); /* example: UTC+12.75 */
|
722 |
|
723 |
+
if ($timestamp === null) {
|
724 |
+
$timestamp = time();
|
|
|
|
|
725 |
}
|
726 |
|
727 |
+
if ($length === 9
|
728 |
+
&& substr($tz, 0, 3) === 'UTC'
|
729 |
+
&& ($tz[3] === '-' || $tz[3] === '+')
|
730 |
+
&& $tz[6] === '.'
|
731 |
+
) {
|
732 |
+
$hour = (float) substr($tz, 4);
|
733 |
+
$sign = ($tz[3] === '-') ? -1 : +1;
|
734 |
+
$diff = ($hour * $sign);
|
735 |
+
} else {
|
736 |
+
/* reset; value seems to be corrupt */
|
737 |
+
SucuriScanOption::deleteOption(':timezone');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
738 |
}
|
739 |
|
740 |
+
if ($format === null) {
|
741 |
+
$format = sprintf(
|
742 |
+
"%s\x20%s",
|
743 |
+
SucuriScanOption::getOption('date_format'),
|
744 |
+
SucuriScanOption::getOption('time_format')
|
745 |
+
);
|
746 |
}
|
747 |
|
748 |
+
return date($format, (intval($timestamp) + ($diff * 3600)));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
749 |
}
|
750 |
|
751 |
/**
|
892 |
*/
|
893 |
public static function isNginxServer()
|
894 |
{
|
895 |
+
return (bool) (stripos(@$_SERVER['SERVER_SOFTWARE'], 'nginx') !== false);
|
896 |
}
|
897 |
|
898 |
/**
|
902 |
*/
|
903 |
public static function isIISServer()
|
904 |
{
|
905 |
+
return (bool) (stripos(@$_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== false);
|
906 |
}
|
907 |
|
908 |
/**
|
src/template.lib.php
CHANGED
@@ -292,7 +292,7 @@ class SucuriScanTemplate extends SucuriScanRequest
|
|
292 |
/* replace the global pseudo-variables in the section/snippets templates. */
|
293 |
if ($template == 'base'
|
294 |
&& array_key_exists('PageContent', $params)
|
295 |
-
&&
|
296 |
) {
|
297 |
$params['PageContent'] = self::replacePseudoVars($params['PageContent'], $params);
|
298 |
}
|
@@ -432,7 +432,7 @@ class SucuriScanTemplate extends SucuriScanRequest
|
|
432 |
*/
|
433 |
public static function pagination($base_url = '', $total_items = 0, $max_per_page = 1)
|
434 |
{
|
435 |
-
|
436 |
$html_links = '';
|
437 |
$page_number = self::pageNumber();
|
438 |
$max_pages = ceil($total_items / $max_per_page);
|
@@ -440,13 +440,14 @@ class SucuriScanTemplate extends SucuriScanRequest
|
|
440 |
$start_page = 1;
|
441 |
$extra_url = '';
|
442 |
|
443 |
-
|
444 |
-
if (
|
445 |
-
$
|
446 |
-
$extra_url = $
|
|
|
447 |
}
|
448 |
|
449 |
-
|
450 |
if ($max_pages > SUCURISCAN_MAX_PAGINATION_BUTTONS) {
|
451 |
$final_page = SUCURISCAN_MAX_PAGINATION_BUTTONS;
|
452 |
$middle = $final_page / 2; /* middle point */
|
@@ -457,7 +458,7 @@ class SucuriScanTemplate extends SucuriScanRequest
|
|
457 |
}
|
458 |
}
|
459 |
|
460 |
-
|
461 |
for ($j = $start_page; $j <= $final_page; $j++) {
|
462 |
$link_class = 'sucuriscan-pagination-link';
|
463 |
|
292 |
/* replace the global pseudo-variables in the section/snippets templates. */
|
293 |
if ($template == 'base'
|
294 |
&& array_key_exists('PageContent', $params)
|
295 |
+
&& strpos($params['PageContent'], '%%SUCURI.') !== false
|
296 |
) {
|
297 |
$params['PageContent'] = self::replacePseudoVars($params['PageContent'], $params);
|
298 |
}
|
432 |
*/
|
433 |
public static function pagination($base_url = '', $total_items = 0, $max_per_page = 1)
|
434 |
{
|
435 |
+
/* calculate the number of links for the pagination */
|
436 |
$html_links = '';
|
437 |
$page_number = self::pageNumber();
|
438 |
$max_pages = ceil($total_items / $max_per_page);
|
440 |
$start_page = 1;
|
441 |
$extra_url = '';
|
442 |
|
443 |
+
/* fix for inline anchor URLs */
|
444 |
+
if (($offset = strpos($base_url, '#')) !== false) {
|
445 |
+
$clean_url = substr($base_url, 0, $offset);
|
446 |
+
$extra_url = substr($base_url, $offset);
|
447 |
+
$base_url = $clean_url;
|
448 |
}
|
449 |
|
450 |
+
/* keep the number of pagination buttons at limit */
|
451 |
if ($max_pages > SUCURISCAN_MAX_PAGINATION_BUTTONS) {
|
452 |
$final_page = SUCURISCAN_MAX_PAGINATION_BUTTONS;
|
453 |
$middle = $final_page / 2; /* middle point */
|
458 |
}
|
459 |
}
|
460 |
|
461 |
+
/* generate the HTML links for the pagination */
|
462 |
for ($j = $start_page; $j <= $final_page; $j++) {
|
463 |
$link_class = 'sucuriscan-pagination-link';
|
464 |
|
sucuri.php
CHANGED
@@ -7,7 +7,7 @@
|
|
7 |
* Author URI: https://sucuri.net/
|
8 |
* Text Domain: sucuri-scanner
|
9 |
* Author: Sucuri Inc.
|
10 |
-
* Version: 1.8.
|
11 |
*/
|
12 |
|
13 |
|
@@ -83,12 +83,7 @@ define('SUCURISCAN', 'sucuriscan');
|
|
83 |
/**
|
84 |
* Current version of the plugin's code.
|
85 |
*/
|
86 |
-
define('SUCURISCAN_VERSION', '1.8.
|
87 |
-
|
88 |
-
/**
|
89 |
-
* The name of the Sucuri plugin main file.
|
90 |
-
*/
|
91 |
-
define('SUCURISCAN_PLUGIN_FILE', 'sucuri.php');
|
92 |
|
93 |
/**
|
94 |
* Unique name of the plugin text domain.
|
@@ -111,15 +106,10 @@ define('SUCURISCAN_PLUGIN_FOLDER', basename(dirname(__FILE__)));
|
|
111 |
*/
|
112 |
define('SUCURISCAN_PLUGIN_PATH', WP_PLUGIN_DIR . '/' . SUCURISCAN_PLUGIN_FOLDER);
|
113 |
|
114 |
-
/**
|
115 |
-
* The fullpath of the main plugin file.
|
116 |
-
*/
|
117 |
-
define('SUCURISCAN_PLUGIN_FILEPATH', SUCURISCAN_PLUGIN_PATH . '/' . SUCURISCAN_PLUGIN_FILE);
|
118 |
-
|
119 |
/**
|
120 |
* The local URL where the plugin's files and assets are served.
|
121 |
*/
|
122 |
-
define('SUCURISCAN_URL',
|
123 |
|
124 |
/**
|
125 |
* Remote URL where the public Sucuri API service is running.
|
7 |
* Author URI: https://sucuri.net/
|
8 |
* Text Domain: sucuri-scanner
|
9 |
* Author: Sucuri Inc.
|
10 |
+
* Version: 1.8.8
|
11 |
*/
|
12 |
|
13 |
|
83 |
/**
|
84 |
* Current version of the plugin's code.
|
85 |
*/
|
86 |
+
define('SUCURISCAN_VERSION', '1.8.8');
|
|
|
|
|
|
|
|
|
|
|
87 |
|
88 |
/**
|
89 |
* Unique name of the plugin text domain.
|
106 |
*/
|
107 |
define('SUCURISCAN_PLUGIN_PATH', WP_PLUGIN_DIR . '/' . SUCURISCAN_PLUGIN_FOLDER);
|
108 |
|
|
|
|
|
|
|
|
|
|
|
109 |
/**
|
110 |
* The local URL where the plugin's files and assets are served.
|
111 |
*/
|
112 |
+
define('SUCURISCAN_URL', plugin_dir_url(__FILE__));
|
113 |
|
114 |
/**
|
115 |
* Remote URL where the public Sucuri API service is running.
|