inc/css/flags.min.css000060400000034755147177152050010520 0ustar00.sucuriscan-flag { background: url("../images/flags.sprite.png") no-repeat; height: 11px; width: 16px; } .sucuriscan-flag-ad { background-position: -16px 0; } .sucuriscan-flag-ae { background-position: -32px 0; } .sucuriscan-flag-af { background-position: -48px 0; } .sucuriscan-flag-ag { background-position: -64px 0; } .sucuriscan-flag-ai { background-position: -80px 0; } .sucuriscan-flag-al { background-position: -96px 0; } .sucuriscan-flag-am { background-position: -112px 0; } .sucuriscan-flag-an { background-position: -128px 0; } .sucuriscan-flag-ao { background-position: -144px 0; } .sucuriscan-flag-ar { background-position: -160px 0; } .sucuriscan-flag-as { background-position: -176px 0; } .sucuriscan-flag-at { background-position: -192px 0; } .sucuriscan-flag-au { background-position: -208px 0; } .sucuriscan-flag-aw { background-position: -224px 0; } .sucuriscan-flag-az { background-position: -240px 0; } .sucuriscan-flag-ba { background-position: 0 -11px; } .sucuriscan-flag-bb { background-position: -16px -11px; } .sucuriscan-flag-bd { background-position: -32px -11px; } .sucuriscan-flag-be { background-position: -48px -11px; } .sucuriscan-flag-bf { background-position: -64px -11px; } .sucuriscan-flag-bg { background-position: -80px -11px; } .sucuriscan-flag-bh { background-position: -96px -11px; } .sucuriscan-flag-bi { background-position: -112px -11px; } .sucuriscan-flag-bj { background-position: -128px -11px; } .sucuriscan-flag-bm { background-position: -144px -11px; } .sucuriscan-flag-bn { background-position: -160px -11px; } .sucuriscan-flag-bo { background-position: -176px -11px; } .sucuriscan-flag-br { background-position: -192px -11px; } .sucuriscan-flag-bs { background-position: -208px -11px; } .sucuriscan-flag-bt { background-position: -224px -11px; } .sucuriscan-flag-bv { background-position: -240px -11px; } .sucuriscan-flag-bw { background-position: 0 -22px; } .sucuriscan-flag-by { background-position: -16px -22px; } .sucuriscan-flag-bz { background-position: -32px -22px; } .sucuriscan-flag-ca { background-position: -48px -22px; } .sucuriscan-flag-cd { background-position: -80px -22px; } .sucuriscan-flag-cf { background-position: -96px -22px; } .sucuriscan-flag-cg { background-position: -112px -22px; } .sucuriscan-flag-ch { background-position: -128px -22px; } .sucuriscan-flag-ci { background-position: -144px -22px; } .sucuriscan-flag-ck { background-position: -160px -22px; } .sucuriscan-flag-cl { background-position: -176px -22px; } .sucuriscan-flag-cm { background-position: -192px -22px; } .sucuriscan-flag-cn { background-position: -208px -22px; } .sucuriscan-flag-co { background-position: -224px -22px; } .sucuriscan-flag-cr { background-position: -240px -22px; } .sucuriscan-flag-cu { background-position: 0 -33px; } .sucuriscan-flag-cv { background-position: -16px -33px; } .sucuriscan-flag-cw { background-position: -32px -33px; } .sucuriscan-flag-cy { background-position: -48px -33px; } .sucuriscan-flag-cz { background-position: -64px -33px; } .sucuriscan-flag-de { background-position: -80px -33px; } .sucuriscan-flag-dj { background-position: -96px -33px; } .sucuriscan-flag-dk { background-position: -112px -33px; } .sucuriscan-flag-dm { background-position: -128px -33px; } .sucuriscan-flag-do { background-position: -144px -33px; } .sucuriscan-flag-dz { background-position: -160px -33px; } .sucuriscan-flag-ec { background-position: -176px -33px; } .sucuriscan-flag-ee { background-position: -192px -33px; } .sucuriscan-flag-eg { background-position: -208px -33px; } .sucuriscan-flag-eh { background-position: -224px -33px; } .sucuriscan-flag-er { background-position: 0 -44px; } .sucuriscan-flag-es { background-position: -16px -44px; } .sucuriscan-flag-et { background-position: -32px -44px; } .sucuriscan-flag-eu { background-position: -48px -44px; } .sucuriscan-flag-fi { background-position: -64px -44px; } .sucuriscan-flag-fj { background-position: -80px -44px; } .sucuriscan-flag-fk { background-position: -96px -44px; } .sucuriscan-flag-fm { background-position: -112px -44px; } .sucuriscan-flag-fo { background-position: -128px -44px; } .sucuriscan-flag-fr { background-position: -144px -44px; } .sucuriscan-flag-ga { background-position: -160px -44px; } .sucuriscan-flag-gb { background-position: -176px -44px; } .sucuriscan-flag-gd { background-position: -192px -44px; } .sucuriscan-flag-ge { background-position: -208px -44px; } .sucuriscan-flag-gf { background-position: -224px -44px; } .sucuriscan-flag-gg { background-position: -240px -44px; } .sucuriscan-flag-gh { background-position: 0 -55px; } .sucuriscan-flag-gi { background-position: -16px -55px; } .sucuriscan-flag-gl { background-position: -32px -55px; } .sucuriscan-flag-gm { background-position: -48px -55px; } .sucuriscan-flag-gn { background-position: -64px -55px; } .sucuriscan-flag-gp { background-position: -80px -55px; } .sucuriscan-flag-gq { background-position: -96px -55px; } .sucuriscan-flag-gr { background-position: -112px -55px; } .sucuriscan-flag-gs { background-position: -128px -55px; } .sucuriscan-flag-gt { background-position: -144px -55px; } .sucuriscan-flag-gu { background-position: -160px -55px; } .sucuriscan-flag-gw { background-position: -176px -55px; } .sucuriscan-flag-gy { background-position: -192px -55px; } .sucuriscan-flag-hk { background-position: -208px -55px; } .sucuriscan-flag-hm { background-position: -224px -55px; } .sucuriscan-flag-hn { background-position: -240px -55px; } .sucuriscan-flag-hr { background-position: 0 -66px; } .sucuriscan-flag-ht { background-position: -16px -66px; } .sucuriscan-flag-hu { background-position: -32px -66px; } .sucuriscan-flag-ic { background-position: -48px -66px; } .sucuriscan-flag-id { background-position: -64px -66px; } .sucuriscan-flag-ie { background-position: -80px -66px; } .sucuriscan-flag-il { background-position: -96px -66px; } .sucuriscan-flag-im { background-position: -112px -66px; } .sucuriscan-flag-in { background-position: -128px -66px; } .sucuriscan-flag-io { background-position: -144px -66px; } .sucuriscan-flag-iq { background-position: -160px -66px; } .sucuriscan-flag-ir { background-position: -176px -66px; } .sucuriscan-flag-is { background-position: -192px -66px; } .sucuriscan-flag-it { background-position: -208px -66px; } .sucuriscan-flag-je { background-position: -224px -66px; } .sucuriscan-flag-jm { background-position: -240px -66px; } .sucuriscan-flag-jo { background-position: 0 -77px; } .sucuriscan-flag-jp { background-position: -16px -77px; } .sucuriscan-flag-ke { background-position: -32px -77px; } .sucuriscan-flag-kg { background-position: -48px -77px; } .sucuriscan-flag-kh { background-position: -64px -77px; } .sucuriscan-flag-ki { background-position: -80px -77px; } .sucuriscan-flag-km { background-position: -96px -77px; } .sucuriscan-flag-kn { background-position: -112px -77px; } .sucuriscan-flag-kp { background-position: -128px -77px; } .sucuriscan-flag-kr { background-position: -144px -77px; } .sucuriscan-flag-kw { background-position: -176px -77px; } .sucuriscan-flag-ky { background-position: -192px -77px; } .sucuriscan-flag-kz { background-position: -208px -77px; } .sucuriscan-flag-la { background-position: -224px -77px; } .sucuriscan-flag-lb { background-position: -240px -77px; } .sucuriscan-flag-lc { background-position: 0 -88px; } .sucuriscan-flag-li { background-position: -16px -88px; } .sucuriscan-flag-lk { background-position: -32px -88px; } .sucuriscan-flag-lr { background-position: -48px -88px; } .sucuriscan-flag-ls { background-position: -64px -88px; } .sucuriscan-flag-lt { background-position: -80px -88px; } .sucuriscan-flag-lu { background-position: -96px -88px; } .sucuriscan-flag-lv { background-position: -112px -88px; } .sucuriscan-flag-ly { background-position: -128px -88px; } .sucuriscan-flag-ma { background-position: -144px -88px; } .sucuriscan-flag-mc { background-position: -160px -88px; } .sucuriscan-flag-md { background-position: -176px -88px; } .sucuriscan-flag-me { background-position: -192px -88px; } .sucuriscan-flag-mg { background-position: -208px -88px; } .sucuriscan-flag-mh { background-position: -224px -88px; } .sucuriscan-flag-mk { background-position: -240px -88px; } .sucuriscan-flag-ml { background-position: 0 -99px; } .sucuriscan-flag-mm { background-position: -16px -99px; } .sucuriscan-flag-mn { background-position: -32px -99px; } .sucuriscan-flag-mo { background-position: -48px -99px; } .sucuriscan-flag-mp { background-position: -64px -99px; } .sucuriscan-flag-mq { background-position: -80px -99px; } .sucuriscan-flag-mr { background-position: -96px -99px; } .sucuriscan-flag-ms { background-position: -112px -99px; } .sucuriscan-flag-mt { background-position: -128px -99px; } .sucuriscan-flag-mu { background-position: -144px -99px; } .sucuriscan-flag-mv { background-position: -160px -99px; } .sucuriscan-flag-mw { background-position: -176px -99px; } .sucuriscan-flag-mx { background-position: -192px -99px; } .sucuriscan-flag-my { background-position: -208px -99px; } .sucuriscan-flag-mz { background-position: -224px -99px; } .sucuriscan-flag-na { background-position: -240px -99px; } .sucuriscan-flag-nc { background-position: 0 -110px; } .sucuriscan-flag-ne { background-position: -16px -110px; } .sucuriscan-flag-nf { background-position: -32px -110px; } .sucuriscan-flag-ng { background-position: -48px -110px; } .sucuriscan-flag-ni { background-position: -64px -110px; } .sucuriscan-flag-nl { background-position: -80px -110px; } .sucuriscan-flag-no { background-position: -96px -110px; } .sucuriscan-flag-np { background-position: -112px -110px; } .sucuriscan-flag-nr { background-position: -128px -110px; } .sucuriscan-flag-nu { background-position: -144px -110px; } .sucuriscan-flag-nz { background-position: -160px -110px; } .sucuriscan-flag-om { background-position: -176px -110px; } .sucuriscan-flag-pa { background-position: -192px -110px; } .sucuriscan-flag-pe { background-position: -208px -110px; } .sucuriscan-flag-pf { background-position: -224px -110px; } .sucuriscan-flag-pg { background-position: -240px -110px; } .sucuriscan-flag-ph { background-position: 0 -121px; } .sucuriscan-flag-pk { background-position: -16px -121px; } .sucuriscan-flag-pl { background-position: -32px -121px; } .sucuriscan-flag-pm { background-position: -48px -121px; } .sucuriscan-flag-pn { background-position: -64px -121px; } .sucuriscan-flag-pr { background-position: -80px -121px; } .sucuriscan-flag-ps { background-position: -96px -121px; } .sucuriscan-flag-pt { background-position: -112px -121px; } .sucuriscan-flag-pw { background-position: -128px -121px; } .sucuriscan-flag-py { background-position: -144px -121px; } .sucuriscan-flag-qa { background-position: -160px -121px; } .sucuriscan-flag-re { background-position: -176px -121px; } .sucuriscan-flag-ro { background-position: -192px -121px; } .sucuriscan-flag-rs { background-position: -208px -121px; } .sucuriscan-flag-ru { background-position: -224px -121px; } .sucuriscan-flag-rw { background-position: -240px -121px; } .sucuriscan-flag-sa { background-position: 0 -132px; } .sucuriscan-flag-sb { background-position: -16px -132px; } .sucuriscan-flag-sc { background-position: -32px -132px; } .sucuriscan-flag-sd { background-position: -64px -132px; } .sucuriscan-flag-se { background-position: -80px -132px; } .sucuriscan-flag-sg { background-position: -96px -132px; } .sucuriscan-flag-sh { background-position: -112px -132px; } .sucuriscan-flag-si { background-position: -128px -132px; } .sucuriscan-flag-sk { background-position: -144px -132px; } .sucuriscan-flag-sl { background-position: -160px -132px; } .sucuriscan-flag-sm { background-position: -176px -132px; } .sucuriscan-flag-sn { background-position: -192px -132px; } .sucuriscan-flag-so { background-position: -208px -132px; } .sucuriscan-flag-sr { background-position: -240px -132px; } .sucuriscan-flag-ss { background-position: 0 -143px; } .sucuriscan-flag-st { background-position: -16px -143px; } .sucuriscan-flag-sv { background-position: -32px -143px; } .sucuriscan-flag-sx { background-position: -48px -143px; } .sucuriscan-flag-sy { background-position: -64px -143px; } .sucuriscan-flag-sz { background-position: -80px -143px; } .sucuriscan-flag-tc { background-position: -96px -143px; } .sucuriscan-flag-td { background-position: -112px -143px; } .sucuriscan-flag-tf { background-position: -128px -143px; } .sucuriscan-flag-tg { background-position: -144px -143px; } .sucuriscan-flag-th { background-position: -160px -143px; } .sucuriscan-flag-tj { background-position: -176px -143px; } .sucuriscan-flag-tk { background-position: -192px -143px; } .sucuriscan-flag-tl { background-position: -208px -143px; } .sucuriscan-flag-tm { background-position: -224px -143px; } .sucuriscan-flag-tn { background-position: -240px -143px; } .sucuriscan-flag-to { background-position: 0 -154px; } .sucuriscan-flag-tr { background-position: -16px -154px; } .sucuriscan-flag-tt { background-position: -32px -154px; } .sucuriscan-flag-tv { background-position: -48px -154px; } .sucuriscan-flag-tw { background-position: -64px -154px; } .sucuriscan-flag-tz { background-position: -80px -154px; } .sucuriscan-flag-ua { background-position: -96px -154px; } .sucuriscan-flag-ug { background-position: -112px -154px; } .sucuriscan-flag-um { background-position: -128px -154px; } .sucuriscan-flag-us { background-position: -144px -154px; } .sucuriscan-flag-uy { background-position: -160px -154px; } .sucuriscan-flag-uz { background-position: -176px -154px; } .sucuriscan-flag-va { background-position: -192px -154px; } .sucuriscan-flag-vc { background-position: -208px -154px; } .sucuriscan-flag-ve { background-position: -224px -154px; } .sucuriscan-flag-vg { background-position: -240px -154px; } .sucuriscan-flag-vi { background-position: 0 -165px; } .sucuriscan-flag-vn { background-position: -16px -165px; } .sucuriscan-flag-vu { background-position: -32px -165px; } .sucuriscan-flag-wf { background-position: -64px -165px; } .sucuriscan-flag-ws { background-position: -80px -165px; } .sucuriscan-flag-ye { background-position: -96px -165px; } .sucuriscan-flag-yt { background-position: -112px -165px; } .sucuriscan-flag-za { background-position: -128px -165px; } .sucuriscan-flag-zm { background-position: -160px -165px; } .sucuriscan-flag-zw { background-position: -176px -165px; } .sucuriscan-flag-catalonia { background-position: -64px -22px; } .sucuriscan-flag-england { background-position: -240px -33px; } .sucuriscan-flag-kurdistan { background-position: -160px -77px; } .sucuriscan-flag-scotland { background-position: -48px -132px; } .sucuriscan-flag-somaliland { background-position: -224px -132px; } .sucuriscan-flag-wales { background-position: -48px -165px; } .sucuriscan-flag-zanzibar { background-position: -144px -165px; } inc/css/index.html000060400000000046147177152050010107 0ustar00 inc/css/styles.css000060400000103335147177152050010154 0ustar00@font-face { font-family: 'Titillium Web'; font-weight: 600; font-display: swap; src: url('../fonts/TitilliumWeb-SemiBold.woff2') format('woff2'), url('../fonts/TitilliumWeb-SemiBold.woff') format('woff'), url('../fonts/TitilliumWeb-SemiBold.ttf') format('truetype'); } @font-face { font-family: 'Titillium Web'; font-weight: 700; font-style: normal; font-display: swap; src: url('../fonts/TitilliumWeb-Bold.woff2') format('woff2'), url('../fonts/TitilliumWeb-Bold.woff') format('woff'), url('../fonts/TitilliumWeb-Bold.ttf') format('truetype'); } @font-face { font-family: 'Titillium Web'; font-weight: 900; font-style: normal; font-display: swap; src: url('../fonts/TitilliumWeb-Black.woff2') format('woff2'), url('../fonts/TitilliumWeb-Black.woff') format('woff'), url('../fonts/TitilliumWeb-Black.ttf') format('truetype'); } @font-face { font-family: 'Open Sans'; font-weight: normal; font-display: swap; src: url('../fonts/OpenSans-Regular.woff2') format('woff2'), url('../fonts/OpenSans-Regular.woff') format('woff'), url('../fonts/OpenSans-Regular.ttf') format('truetype'); } @font-face { font-family: 'Open Sans'; font-weight: 500; font-style: normal; font-display: swap; src: url('../fonts/OpenSans-Medium.woff2') format('woff2'), url('../fonts/OpenSans-Medium.woff') format('woff'), url('../fonts/OpenSans-Medium.ttf') format('truetype'); } @font-face { font-family: 'Open Sans'; font-weight: 600; font-style: normal; font-display: swap; src: url('../fonts/OpenSans-SemiBold.woff2') format('woff2'), url('../fonts/OpenSans-SemiBold.woff') format('woff'), url('../fonts/OpenSans-SemiBold.ttf') format('truetype'); } @font-face { font-family: 'Open Sans'; font-weight: 700; font-style: normal; font-display: swap; src: url('../fonts/OpenSans-Bold.woff2') format('woff2'), url('../fonts/OpenSans-Bold.woff') format('woff'), url('../fonts/OpenSans-Bold.ttf') format('truetype'); } body.toplevel_page_sucuriscan, body.sucuri-security_page_sucuriscan_settings, body.sucuri-security_page_sucuriscan_firewall, body.sucuri-security_page_sucuriscan_hardening { background: #E9E7E7; font-family: 'Open Sans', sans-serif; font-size: 14px; line-height: 1.5rem; color: #1A272C; -webkit-font-smoothing: antialiased; } .sucuriscan-container h1, .sucuriscan-container h2, .sucuriscan-container h3, .sucuriscan-container h4, .sucuriscan-container h5, .sucuriscan-container h6 { font-family: Titillium Web, Helvetica, Arial, Tahoma, sans-serif; font-weight: 700 !important; line-height: 1 !important; } .sucuriscan-container b, .sucuriscan-container strong { font-weight: 700; } .sucuriscan-container a { color: #028673; } .sucuriscan-container a:hover { color: #26BA9E; } .sucuriscan-container a:focus { box-shadow: 0 0 0 1px rgba(3, 134, 115, .32), 0 0 2px 1px rgba(3, 134, 115, .38); border-color: #26BA9E; } .sucuriscan-container { margin: 0; margin-left: 9px; margin-right: 28px; margin-top: 10px; } .sucuriscan-container *, .sucuriscan-container::after, .sucuriscan-container::before { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } .sucuriscan-clearfix::after, .sucuriscan-clearfix::before { content: ' '; display: table; } .sucuriscan-clearfix::after { clear: both; } .sucuriscan-pull-left { float: left; } .sucuriscan-pull-right { float: right; } .sucuriscan-hidden { display: none !important; } .sucuriscan-monospace { font-family: Menlo, Monaco, monospace, serif; } .sucuriscan-wraptext { word-break: break-all; } .sucuriscan-container select { margin: 0; padding: 0 30px 0 8px; height: 30px; line-height: normal; } .sucuriscan-container input[type='text'] { margin: 0; padding: 0 7px; line-height: 28px; font-weight: 400; } .sucuriscan-container fieldset { margin-bottom: 10px; } .sucuriscan-container fieldset:last-child { margin-bottom: 0; } .sucuriscan-container fieldset label { display: inline-block; text-transform: uppercase; line-height: 30px; font-weight: 700; cursor: initial; margin-left: 0; } .sucuriscan-container fieldset span { line-height: 30px; display: inline-block; } .sucuriscan-container fieldset span, .sucuriscan-container fieldset label, .sucuriscan-container fieldset select, .sucuriscan-container fieldset button, .sucuriscan-container fieldset input[type='text'], .sucuriscan-container fieldset input[type='checkbox'], .wp-core-ui .sucuriscan-container fieldset .button, .wp-core-ui .sucuriscan-container fieldset .button-primary, .wp-core-ui .sucuriscan-container fieldset .button-secondary { margin: 0; float: left; margin-left: 5px; } .sucuriscan-container fieldset input[type='checkbox'] { margin-top: 7px; margin-bottom: 7px; } .sucuriscan-container .sucuriscan-full-textarea { width: 100%; min-height: 400px; background: #E9E7E7; word-break: break-all; padding: 20px; margin: 0; } #adminmenu li.toplevel_page_sucuriscan .wp-menu-image img { width: 18px; height: 18px; } #adminmenu li.toplevel_page_sucuriscan div.wp-menu-image.svg { background-size: 16px; } .sucuriscan-header { margin-top: 4px; } .sucuriscan-logo-wrapper { display: flex; align-items: center; } .sucuriscan-header .sucuriscan-logo { display: inline-block; height: 50px; margin-left: 10px; margin-right: 15px; text-decoration: none; } .sucuriscan-header .sucuriscan-logo img { height: 50px; } .sucuriscan-header .sucuriscan-subtitle { color: #727376; font-size: 30px; font-weight: 200; } .sucuriscan-header .sucuriscan-version { color: #727376; font-size: 11px; margin-left: 0; margin-top: auto; margin-bottom: 5px; } .sucuriscan-header .sucuriscan-navbar ul { margin: 0; padding: 0; list-style: none; } .sucuriscan-header .sucuriscan-navbar li { float: left; margin-bottom: 0; margin-left: 5px; } .sucuriscan-container .button { -moz-box-shadow: none; -webkit-box-shadow: none; background: none; border-color: transparent; height: auto; line-height: normal; border-radius: 40px; box-shadow: none; text-shadow: none; padding: 6px 20px; } .sucuriscan-container .button-primary { background: #028673; border-color: #028673; color: #fff; } .sucuriscan-container .button-secondary { background: transparent; border-color: #028673; color: #028673; } .wp-core-ui .sucuriscan-container .button-primary:focus, .wp-core-ui .sucuriscan-container .button-primary:hover, .wp-core-ui .sucuriscan-container .button-primary:active, .wp-core-ui .sucuriscan-container .button-primary:visited, .wp-core-ui .sucuriscan-container .button-primary:disabled, .wp-core-ui .sucuriscan-container .button-primary[disabled] { color: #fff; background: #028673; border-color: #028673; text-shadow: none !important; box-shadow: none !important; } .wp-core-ui .sucuriscan-container .button-primary:disabled, .wp-core-ui .sucuriscan-container .button-primary[disabled] { color: #a0a5aa !important; border-color: #ddd !important; background: #f7f7f7 !important; } .sucuriscan-container .sucuriscan-register-site-button { background: #676767; border-color: #676767; } .wp-core-ui .sucuriscan-container .sucuriscan-register-site-button:focus, .wp-core-ui .sucuriscan-container .sucuriscan-register-site-button:hover, .wp-core-ui .sucuriscan-container .sucuriscan-register-site-button:active { background: #5e5f62; border-color: #5e5f62; } .sucuriscan-container .sucuriscan-register-site-modal fieldset label { min-width: 160px; } .sucuriscan-content { /* plugin content */ } .sucuriscan-footer { color: #555d66; font-size: 11px; text-align: center; margin-top: 30px; } .sucuriscan-panel { background: #fff; border-radius: 10px; box-shadow: 0 0 8px #dedede; border: 1px solid #dedede; margin-top: 30px; padding: 30px; } .sucuriscan-panel .sucuriscan-title { font-size: 30px; margin: 0; margin-bottom: 24px; } .sucuriscan-panel p { margin: 0; margin-bottom: 10px; } .sucuriscan-panel p:last-child { margin-bottom: 0; } .sucuriscan-panel hr { margin: 20px 0; } .sucuriscan-tooltip { position: relative; } .sucuriscan-tooltip-object { width: 300px; position: absolute; background: rgba(0, 0, 0, 0.9); line-height: normal; border-radius: 3px; padding: 20px; font-size: 12px; color: #fff; z-index: 10; } .sucuriscan-tooltip-object::before { left: 50%; content: ' '; position: absolute; border: 10px solid transparent; border-top-color: rgba(0, 0, 0, 0.9); border-bottom: none; margin-left: -10px; bottom: -10px; } .sucuriscan-overlay { background: #666; background: rgba(0, 0, 0, 0.8); bottom: 0; left: 0; position: fixed; right: 0; top: 0; z-index: 9990; } .sucuriscan-modal { left: 15%; position: absolute; top: 25px; width: 65%; z-index: 9990; } .sucuriscan-modal-outside { background: #fff; border-top: 10px solid #028673; left: 0; position: relative; } .sucuriscan-modal-header, .sucuriscan-modal-inside { padding: 30px; } .sucuriscan-modal-header { padding-bottom: 0; } .sucuriscan-modal-inside { padding-top: 10px; } .sucuriscan-modal-inside p { margin-top: 0; } .sucuriscan-modal-header .sucuriscan-modal-title { border-bottom: 0; font-size: 30px; line-height: 44px; margin: 0; padding: 0; font-weight: 800; letter-spacing: 0.1px; } .sucuriscan-modal-header .sucuriscan-modal-close { background: #028673; border-radius: 50%; color: #fff; display: inline-block; font-size: 16px; font-weight: 700; line-height: 31px; padding: 0 10px; position: absolute; right: -15px; text-decoration: none; top: -21px; } .sucuriscan-tabs { margin-top: 30px; } .sucuriscan-tabs .sucuriscan-tabs-buttons { margin: 0; padding: 0; border-bottom: 1px solid #ccc; } .sucuriscan-tabs .sucuriscan-tabs-buttons li { float: left; margin: 0; } .sucuriscan-tabs .sucuriscan-tabs-buttons li:first-child { margin-left: 12px; } .sucuriscan-tabs .sucuriscan-tabs-buttons li:first-child a { border-top-left-radius: 6px; } .sucuriscan-tabs .sucuriscan-tabs-buttons li:last-child a { border-right: 1px solid #ccc; border-top-right-radius: 6px; } .sucuriscan-tabs .sucuriscan-tabs-buttons a { background: #f1f1f1; border: 1px solid #dfdfdf; border-bottom: 0; border-right: 0; padding: 0 18px; line-height: 34px; display: inline-block; text-decoration: none; color: #1A272C; } .sucuriscan-tabs .sucuriscan-tabs-buttons .sucuriscan-tab-active { background: #fff; font-weight: 700; border-top-left-radius: 6px; border-top-right-radius: 6px; padding-top: 4px; margin-top: -4px; } .sucuriscan-tabs .sucuriscan-tabs-buttons a:hover { background: #fff; } .sucuriscan-pagination { border-radius: 4px; display: inline-block; margin: 0; padding: 0; } .sucuriscan-pagination > li { display: inline; } .sucuriscan-pagination > li > a, .sucuriscan-pagination > li > span { background: #fff; border: 1px solid #ddd; color: #428bca; float: left; line-height: 1.42857143; margin-left: -1px; padding: 6px 12px; position: relative; text-decoration: none; } .sucuriscan-pagination > li:first-child > a, .sucuriscan-pagination > li:first-child > span { border-radius: 4px 0 0 4px; margin-left: 0; } .sucuriscan-pagination > li:last-child > a, .sucuriscan-pagination > li:last-child > span { border-radius: 0 4px 4px 0; } .sucuriscan-pagination > li > a.sucuriscan-pagination-active, .sucuriscan-pagination > li > a:hover { background: #4F6CB5; color: #fff; } .wrap div.sucuriscan-alert { margin: 0; position: relative; } .wrap .sucuriscan-alert > .close { color: #fff; font-size: 18px; font-weight: 700; position: absolute; text-decoration: none; right: 20px; top: 20px; } .wrap .sucuriscan-alert.info, .wrap .sucuriscan-alert.error, .wrap .sucuriscan-alert.success, .wrap .sucuriscan-alert.updated, .sucuriscan-inline-alert, .sucuriscan-inline-alert-info, .sucuriscan-inline-alert-error, .sucuriscan-inline-alert-success { background: #ddd; border: 0; box-shadow: none; color: #fff; padding: 0; } .wrap .sucuriscan-alert.info, .sucuriscan-inline-alert-info { background: #4F6CB5; } .wrap .sucuriscan-alert.error, .sucuriscan-inline-alert-error { background: #CE3030; } .wrap .sucuriscan-alert.success, .wrap .sucuriscan-alert.updated, .sucuriscan-inline-alert-success { background: #028673; } .wrap .sucuriscan-alert.info, .wrap .sucuriscan-alert.error, .wrap .sucuriscan-alert.success, .wrap .sucuriscan-alert.updated, .sucuriscan-inline-alert, .sucuriscan-inline-alert-info, .sucuriscan-inline-alert-error, .sucuriscan-inline-alert-success, .sucuriscan-inline-alert-updated { margin-bottom: 20px; } .wrap .sucuriscan-alert.info:last-child, .wrap .sucuriscan-alert.error:last-child, .wrap .sucuriscan-alert.success:last-child, .wrap .sucuriscan-alert.updated:last-child, .sucuriscan-inline-alert:last-child, .sucuriscan-inline-alert-info:last-child, .sucuriscan-inline-alert-error:last-child, .sucuriscan-inline-alert-success:last-child, .sucuriscan-inline-alert-updated:last-child { margin-bottom: 0; } .wrap .sucuriscan-alert.info a, .wrap .sucuriscan-alert.error a, .wrap .sucuriscan-alert.success a, .wrap .sucuriscan-alert.updated a, .sucuriscan-inline-alert a, .sucuriscan-inline-alert-info a, .sucuriscan-inline-alert-error a, .sucuriscan-inline-alert-success a, .sucuriscan-inline-alert-updated a { color: #fff; text-decoration: none; } .wrap .sucuriscan-alert.info p, .wrap .sucuriscan-alert.error p, .wrap .sucuriscan-alert.success p, .wrap .sucuriscan-alert.updated p, .sucuriscan-inline-alert p, .sucuriscan-inline-alert-info p, .sucuriscan-inline-alert-error p, .sucuriscan-inline-alert-success p { margin: 0; color: #fff; padding: 20px; padding-bottom: 0; } .wrap .sucuriscan-alert.info p a, .wrap .sucuriscan-alert.error p a, .wrap .sucuriscan-alert.success p a, .wrap .sucuriscan-alert.updated p a, .sucuriscan-inline-alert p a, .sucuriscan-inline-alert-info p a, .sucuriscan-inline-alert-error p a, .sucuriscan-inline-alert-success p a { text-decoration: underline; } .wrap .sucuriscan-alert.info p:last-child, .wrap .sucuriscan-alert.error p:last-child, .wrap .sucuriscan-alert.success p:last-child, .wrap .sucuriscan-alert.updated p:last-child, .sucuriscan-inline-alert p:last-child, .sucuriscan-inline-alert-info p:last-child, .sucuriscan-inline-alert-error p:last-child, .sucuriscan-inline-alert-success p:last-child { padding-bottom: 20px; } .sucuriscan-hstatus { margin: 0; padding: 20px; position: relative; border: 1px solid transparent; margin-bottom: 20px; } .sucuriscan-hstatus:last-child { margin-bottom: 0; } .sucuriscan-hstatus-0 { background-color: rgba(206, 48, 48, .2); border-color: rgba(206, 48, 48, .4); color: #CE3030; } .sucuriscan-hstatus-0 .button-primary, .wp-core-ui .sucuriscan-container .sucuriscan-hstatus-0 .button-primary:visited { background: #9b2b27; border-color: #9b2b27; } .wp-core-ui .sucuriscan-hstatus-0 .button-primary:focus, .wp-core-ui .sucuriscan-hstatus-0 .button-primary:hover, .wp-core-ui .sucuriscan-hstatus-0 .button-primary:active, .wp-core-ui .sucuriscan-hstatus-0 .button-primary:disabled, .wp-core-ui .sucuriscan-hstatus-0 .button-primary[disabled] { background: #872522; border-color: #872522; } .sucuriscan-hstatus-1 { background-color: rgba(2, 134, 115, .2); border-color: rgba(2, 134, 115, .4); color: #028673; } .sucuriscan-hstatus-2 { background-color: rgba(79, 108, 181, .2); border-color: rgba(79, 108, 181, .4); color: #4F6CB5; } .sucuriscan-hstatus-2 .button-primary { background: #4F6CB5; border-color: #4F6CB5; } .wp-core-ui .sucuriscan-hstatus-2 .button-primary:focus, .wp-core-ui .sucuriscan-hstatus-2 .button-primary:hover, .wp-core-ui .sucuriscan-hstatus-2 .button-primary:active, .wp-core-ui .sucuriscan-hstatus-2 .button-primary:disabled, .wp-core-ui .sucuriscan-hstatus-2 .button-primary[disabled] { background: #3f6890; border-color: #3f6890; } .sucuriscan-hstatus form { position: absolute; right: 20px; top: 14px; } .apiservice .sucuriscan-hstatus form { position: relative; right: 0; top: 0; margin-top: 14px; } .sucuriscan-flag-bar { fill: #fff !important; } .sucuriscan-flag-icon-green path, .sucuriscan-auditlog-success path, .sucuriscan-integrity-added path { fill: #028673; } .sucuriscan-flag-icon-red path, .sucuriscan-auditlog-error path, .sucuriscan-integrity-removed path { fill: #CE3030; } .sucuriscan-flag-icon-purple path, .sucuriscan-auditlog-debug path, .sucuriscan-integrity-modified path { fill: #b406dc; } .sucuriscan-flag-icon-orange path, .sucuriscan-auditlog-warning path { fill: #F7BE17; } .sucuriscan-flag-icon-blue path, .sucuriscan-auditlog-notice path { fill: #4F6CB5; } .sucuriscan-flag-icon-white path, .sucuriscan-auditlog-info path { fill: #f3f3f3; } .sucuriscan-flag-icon-black path, .sucuriscan-auditlog-critical path { fill: #1A272C; } .sucuriscan-container .sucuriscan-table, .sucuriscan-container .sucuriscan-panel table.sucuriscan-last-logins, .sucuriscan-container .sucuriscan-panel table.sucuriscan-lastlogins-failed { margin-bottom: 20px; } .sucuriscan-container .sucuriscan-table:last-child { margin-bottom: 0; } .sucuriscan-container .sucuriscan-table tbody tr:nth-child(odd) { background: #f5f5f5; } .sucuriscan-dashboard-left { width: 68%; padding-right: 25px; } .sucuriscan-dashboard-right { width: 32%; } .sucuriscan-dashboard-left .sucuriscan-tabs { margin-top: 0; } .sucuriscan-dashboard-left .sucuriscan-tabs-containers { margin-top: 30px; } .sucuriscan-integrity .sucuriscan-integrity-left, .sucuriscan-integrity .sucuriscan-integrity-right { width: 50%; } .sucuriscan-integrity .sucuriscan-integrity-right { padding-left: 80px; } .sucuriscan-integrity .sucuriscan-subtitle { margin: 0; border-bottom: 1px solid #ddd; font-weight: 800; margin-bottom: 12px; padding-bottom: 11px; } .sucuriscan-integrity hr { margin: 20px 0; } .sucuriscan-integrity-correct .sucuriscan-integrity-right { background-image: url("data:image/svg+xml,%3Csvg id='Layer_1' data-name='Layer 1' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 60'%3E%3Cdefs%3E%3Cstyle%3E .cls-1 %7B fill: %231b262c; %7D .cls-2 %7B fill: none; stroke: %23008673; stroke-width: 6px; %7D %3C/style%3E%3C/defs%3E%3Cg id='Ellipse_33' data-name='Ellipse 33'%3E%3Cpath class='cls-1' d='M30,6c13.23,0,24,10.77,24,24s-10.77,24-24,24S6,43.23,6,30,16.77,6,30,6M30,0C13.43,0,0,13.43,0,30s13.43,30,30,30,30-13.43,30-30S46.57,0,30,0h0Z'/%3E%3C/g%3E%3Cpath id='Path_310' data-name='Path 310' class='cls-2' d='M18.36,28.89l7.91,7.91,16.09-15.54'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-size: 62px 62px; } .sucuriscan-integrity-incorrect .sucuriscan-integrity-right { background-image: url("data:image/svg+xml,%3Csvg id='Layer_1' data-name='Layer 1' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 60'%3E%3Cdefs%3E%3Cstyle%3E .cls-1 %7B fill: %23ce3030; %7D %3C/style%3E%3C/defs%3E%3Cg id='Ellipse_33' data-name='Ellipse 33'%3E%3Cpath class='cls-1' d='M30,6c13.23,0,24,10.77,24,24s-10.77,24-24,24S6,43.23,6,30,16.77,6,30,6M30,0C13.43,0,0,13.43,0,30s13.43,30,30,30,30-13.43,30-30S46.57,0,30,0h0Z'/%3E%3C/g%3E%3Cg%3E%3Crect class='cls-1' x='27.43' y='17.26' width='5.14' height='25.49' transform='translate(-12.43 30) rotate(-45)'/%3E%3Crect class='cls-1' x='17.26' y='27.43' width='25.49' height='5.14' transform='translate(-12.43 30) rotate(-45)'/%3E%3C/g%3E%3C/svg%3E"); background-repeat: no-repeat; background-size: 62px 62px; } .sucuriscan-integrity-loading .sucuriscan-integrity-missing { height: 147px; background: #E9E7E7; border: 3px dotted #ddd; border-radius: 14px; } .sucuriscan-integrity-correct .sucuriscan-subtitle { color: #028673; } .sucuriscan-integrity-incorrect .sucuriscan-subtitle { color: #CE3030; } .sucuriscan-integrity-incorrect .sucuriscan-table .sucuriscan-tooltip { left: 5px; position: relative; top: 3px; } .sucuriscan-container .sucuriscan-integrity-diff-utility { margin-bottom: 20px; } .sucuriscan-diff-utility-modal .sucuriscan-modal-inside p { margin-bottom: 20px; } .sucuriscan-container .sucuriscan-diff-content { background: #003140; font-family: Menlo, Monaco, monospace, serif; border: 1px solid #32636c; border-radius: 4px; font-size: 12px; padding: 20px 0; margin: 0; } .sucuriscan-container .sucuriscan-diff-line { color: #fff; white-space: pre-wrap; padding: 0 20px; margin: 0; } .sucuriscan-container .sucuriscan-diff-header { color: #999; } .sucuriscan-container .sucuriscan-diff-minus { color: #ff304b; } .sucuriscan-container .sucuriscan-diff-plus { color: #83e600; } .sucuriscan-sitecheck-details { margin-top: 20px; margin-bottom: 20px; padding-top: 20px; padding-bottom: 0; position: relative; border-top: 1px solid #dedede; border-bottom: 1px solid #dedede; } .sucuriscan-sitecheck-details ul { margin: 0; } .sucuriscan-sitecheck-details li { display: inline-block; margin-bottom: 20px; margin-right: 20px; } .sucuriscan-sitecheck-details .sucuriscan-details-title { display: block; font-weight: bold; } .sucuriscan-sitecheck-details .sucuriscan-details-value { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .sucuriscan-sitecheck-details .sucuriscan-pull-left { width: 80%; } .sucuriscan-sitecheck-details .sucuriscan-pull-right { width: 20%; } .sucuriscan-sitecheck-list ul { margin-top: 20px; margin-bottom: 0; } .sucuriscan-sitecheck-list li { margin-top: 10px; margin-bottom: 0; position: relative; padding-left: 30px; } .sucuriscan-sitecheck-list a { font-size: 14px; text-decoration: none; } .sucuriscan-sitecheck-list-INFO:before { content: ""; position: absolute; left: 0; top: 6px; width: 18px; height: 18px; display: inline-block; background-image: url("data:image/svg+xml,%3Csvg id='Layer_1' data-name='Layer 1' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 60'%3E%3Cdefs%3E%3Cstyle%3E .cls-1 %7B fill: none; stroke: %23008673; stroke-width: 8.3px; %7D %3C/style%3E%3C/defs%3E%3Cpath id='Path_310' data-name='Path 310' class='cls-1' d='M3.28,29.68l17.62,17.62L56.72,12.7'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-size: contain; margin-right: 10px; } .sucuriscan-sitecheck-list-WARN:before { content: ""; position: absolute; left: 0; top: 6px; width: 18px; height: 18px; display: inline-block; background-image: url("data:image/svg+xml,%3Csvg id='Layer_1' data-name='Layer 1' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 60'%3E%3Cdefs%3E%3Cstyle%3E .cls-1 %7B fill: %23CE3030; %7D .cls-2 %7B fill: none; stroke: %23CE3030; stroke-miterlimit: 10; stroke-width: 5px; %7D %3C/style%3E%3C/defs%3E%3Cg id='Ellipse_33' data-name='Ellipse 33'%3E%3Cpath class='cls-1' d='M30,6c13.23,0,24,10.77,24,24s-10.77,24-24,24S6,43.23,6,30,16.77,6,30,6M30,0C13.43,0,0,13.43,0,30s13.43,30,30,30,30-13.43,30-30S46.57,0,30,0h0Z'/%3E%3C/g%3E%3Cg%3E%3Cline class='cls-2' x1='30' y1='17.87' x2='30' y2='32.86'/%3E%3Cline class='cls-2' x1='28.23' y1='38.59' x2='31.77' y2='42.13'/%3E%3C/g%3E%3C/svg%3E"); background-repeat: no-repeat; background-size: contain; margin-right: 10px; } .sucuriscan-sitecheck-list-NOTICE:before { content: ""; position: absolute; left: 0; top: 6px; width: 18px; height: 18px; display: inline-block; background-image: url("data:image/svg+xml,%3Csvg id='Layer_1' data-name='Layer 1' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 60'%3E%3Cdefs%3E%3Cstyle%3E .cls-1 %7B fill: %234f6cb5; %7D .cls-2 %7B fill: none; stroke: %234f6cb5; stroke-miterlimit: 10; stroke-width: 5px; %7D %3C/style%3E%3C/defs%3E%3Cg id='Ellipse_33' data-name='Ellipse 33'%3E%3Cpath class='cls-1' d='M30,6c13.23,0,24,10.77,24,24s-10.77,24-24,24S6,43.23,6,30,16.77,6,30,6M30,0C13.43,0,0,13.43,0,30s13.43,30,30,30,30-13.43,30-30S46.57,0,30,0h0Z'/%3E%3C/g%3E%3Cg%3E%3Cline class='cls-2' x1='30' y1='17.87' x2='30' y2='32.86'/%3E%3Cline class='cls-2' x1='28.23' y1='38.59' x2='31.77' y2='42.13'/%3E%3C/g%3E%3C/svg%3E"); background-repeat: no-repeat; background-size: contain; margin-right: 10px; } .sucuriscan-sitecheck-list-INFO a, .sucuriscan-sitecheck-list-NOTICE a { color: #1A272C; } .sucuriscan-sitecheck-list-WARN a { color: #CE3030; font-weight: bold; } .sucuriscan-sitecheck-footnote { color: #989898; padding-top: 20px; border-top: 1px solid #ddd; margin-top: 20px; } .sucuriscan-sitecheck-footnote a, .sucuriscan-sitecheck-footnote p { font-size: 11px; margin: 0; } .sucuriscan-tag-title { color: #fff; display: table; font-size: 17px; font-weight: 900; margin: 0; padding: 8px 14px; position: relative; border-radius: 4px; } .sucuriscan-tag-green { background-color: #028673; } .sucuriscan-tag-red { background-color: #CE3030; } .sucuriscan-tag-blue { background-color: #4F6CB5; } .sucuriscan-auditlog-date { color: #676767; padding: 30px 0; font-size: 24px; font-weight: 200; border-bottom: 1px solid #dbdbdb; } .sucuriscan-auditlog-date:first-child { padding-top: 0; } .sucuriscan-auditlog-entry { padding: 10px 0; border-bottom: 1px solid #dbdbdb; } .sucuriscan-auditlog-entry-title, .sucuriscan-auditlog-entry-address, .sucuriscan-auditlog-entry-extra li { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } .sucuriscan-auditlog-entry-time { width: 45px; color: #676767; } .sucuriscan-auditlog-entry-event { width: 28px; } .sucuriscan-auditlog-entry-message { width: 64.3111%; color: #1A272C; } .sucuriscan-auditlog-entry-title strong { font-size: 14px; } .sucuriscan-auditlog-entry-title span { font-size: 14px; } .sucuriscan-auditlog-entry-extra { color: #717171; font-size: 11px; } .sucuriscan-auditlog-entry-extra ul { margin-top: 5px; } .sucuriscan-auditlog-entry-extra li { margin-bottom: 0; } .sucuriscan-auditlog-entry-address { width: 19.4311%; color: #676767; text-align: right; font-size: 14px; } .sucuriscan-auditlog-table .sucuriscan-pagination-loading { line-height: 32px; margin-left: 10px; } .sucuriscan-pagination-panel, .sucuriscan-auditlog-footer { margin-top: 30px; } .sucuriscan-hardening-option { margin-bottom: 8px; } .sucuriscan-hardening-option .button { min-width: 150px; } .sucuriscan-hardening-option > span { font-size: 16px; } .sucuriscan-hardening-option .sucuriscan-hardening-help { display: inline-block; padding: 8px 0; width: 14px; } .sucuriscan-hardening-option .sucuriscan-hardening-help svg { float: left; } .sucuriscan-accesslog-datetime, .sucuriscan-accesslog-signature, .sucuriscan-accesslog-request, .sucuriscan-accesslog-useragent, .sucuriscan-accesslog-target, .sucuriscan-accesslog-referer { margin-left: 24px; } .sucuriscan-accesslog-label { font-weight: 700; } .sucuriscan-ipaccess-form, .sucuriscan-ipaccess-table { margin-top: 20px; } .sucuriscan-ipaccess-table tbody td + td { text-align: right; } .sucuriscan-ipaccess-table .sucuriscan-monospace { line-height: 30px; } .sucuriscan-settings-alerts .dashicons-before::before { padding-right: 10px; } #firewall-clear-cache-auto { margin-bottom: 15px; } .sucuriscan-firewall-accesslog { word-break: break-all; } .sucuriscan-double-box { margin-top: 20px; } .sucuriscan-double-box p { display: inline-block; width: 70%; margin: 0; } .sucuriscan-double-box form { margin-top: 10px; width: 30%; text-align: right; } .sucuriscan-double-box select { padding: 5px 25px 5px 10px; margin-right: 5px; } .rtl .sucuriscan-header .sucuriscan-pull-left { float: right; } .rtl .sucuriscan-header .sucuriscan-pull-right { float: left; } .rtl .sucuriscan-header .sucuriscan-navbar li { float: right; } .rtl .sucuriscan-tabs .sucuriscan-tabs-buttons li { float: right; } .rtl .sucuriscan-tabs .sucuriscan-tabs-buttons li:first-child { margin-left: 0; margin-right: 12px; } .rtl .sucuriscan-tabs .sucuriscan-tabs-buttons a { border-right: 1px solid #dfdfdf; border-left: 0; } .rtl .sucuriscan-tabs .sucuriscan-tabs-buttons li:first-child a { border-top-right-radius: 6px; } .rtl .sucuriscan-tabs .sucuriscan-tabs-buttons li:last-child a { border-left: 1px solid #ccc; border-top-left-radius: 6px; } .rtl .sucuriscan-hstatus form { left: 20px; right: initial; } .rtl .sucuriscan-container fieldset span, .rtl .sucuriscan-container fieldset label, .rtl .sucuriscan-container fieldset select, .rtl .sucuriscan-container fieldset button, .rtl .sucuriscan-container fieldset input[type='text'], .rtl .sucuriscan-container fieldset input[type='checkbox'], .rtl .wp-core-ui .sucuriscan-container fieldset .button, .rtl .wp-core-ui .sucuriscan-container fieldset .button-primary, .rtl .wp-core-ui .sucuriscan-container fieldset .button-secondary { float: right !important; margin-left: 0; margin-right: 5px; } .rtl .wrap .sucuriscan-alert > .close { right: initial; left: 20px; } .firewall-clear-cache-path { margin-top: 20px; margin-bottom: 20px; } .firewall-clear-cache-path fieldset { display: flex; flex-direction: row; align-items: flex-end; } .firewall-clear-cache-path fieldset input { min-width: 300px; } .firewall-clear-cache-path fieldset label { display: flex; flex-direction: column; margin: 0; } .ml-0 { margin-left: 0 !important; } .mt-2 { margin-top: 2em !important; } h3.lead { margin: .5em 0; } .sucuriscan-hstatus-2 .btn-enable-api-s { display: none; } .sucuriscan-dropdown { position: relative; display: inline-block; } .sucuriscan-dropdown:hover .sucuriscan-dropdown-content, .sucuriscan-dropdown:hover .sucuriscan-pointer { display: block; } .sucuriscan-dropdown:hover::after { content: ''; position: absolute; left: 0; top: 100%; width: 100%; height: 15px; background: transparent; } .sucuriscan-dropdown-content { display: none; position: absolute; background-color: #ffffff; min-width: 200px; box-shadow: 0 2px 15px rgba(0, 0, 0, .1); border-radius: 6px; z-index: 1; margin-top: 15px; padding-top: 5px; padding-bottom: 10px; left: 0; } .sucuriscan-dropdown-content-sm { min-width: 120px; } .sucuriscan-dropdown-content option, .sucuriscan-dropdown-content a { color: black; padding: 6px 16px; text-decoration: none; display: block; } .sucuriscan-dropdown-content option:hover { color: #26BA9E; cursor: pointer; } .sucuriscan-pointer { display: none; position: absolute; top: -19px; left: 10%; width: 0; height: 0; border: 12px solid transparent; border-bottom-width: 12px; border-bottom-style: solid; border-bottom-color: transparent; border-bottom: 7px solid #fff; margin-left: 0; } .sucuriscan-tag-malware-container { display: flex; justify-content: space-between; align-items: center; } .sucuriscan-tag-malware-container a { margin-top: 0 !important; } #sucuriscan_toggle_wafkey { position: absolute; right: 115px; top: 14px; } @media (max-width: 1500px) { .sucuriscan-tag-malware-container-link-top { display: none !important; margin-top: 0 !important; } } @media (min-width: 1500px) { .sucuriscan-tag-malware-container-link-bottom { display: none !important; } } .sucuriscan-tag-malware-container-link-top, .sucuriscan-tag-malware-container-link-bottom { border-radius: 4px !important; } .sucuriscan-mt-20 { margin-top: 20px !important; } .sucuriscan-mb-5 { margin-bottom: 5px !important; } .vertical-align-middle { vertical-align: middle; } .sucuriscan-double-box-update p { vertical-align: middle; } .sucuriscan-double-box-update div { display: inline-block; vertical-align: middle; text-align: right; width: 29%; } .sucuriscan-headers-cache-input { width: 120px; height: auto; padding: 0; font-size: 1em; } .sucuriscan-headers-cache-is-editing { td { padding: 3px 10px; } } .sucuriscan-table-fixed-layout { table-layout: fixed; } .sucuriscan-table-fixed-layout .sucuriscan-tooltip > svg { vertical-align: middle; } .sucuriscan-table-fixed-layout .manage-column svg { width: 14px; height: 14px; } .sucuriscan-table-fixed-layout td { vertical-align: middle; } .sucuriscan-pagination-integrity { margin-top: 0; } .sucuriscan-pagination-integrity > ul { margin-bottom: 15px; } .sucuriscan-is-loading { padding: 15px; } #sucuriscan_integrity_files_per_page { margin-left: 10px; } #sucuriscan-filters { margin-bottom: 30px; } #sucuriscan-filters .filter-container { display: flex; align-items: center; flex-wrap: wrap; row-gap: 5px; } #sucuriscan-filters select, #sucuriscan-filters input, #sucuriscan-filters button { margin-right: 7px; } #clear-filter-button { display: none; } .sucuriscan-sitecheck-promo { color: #989898; padding-top: 20px; border-top: 1px solid #ddd; margin-top: 20px; } .sucuriscan-sitecheck-promo a, .sucuriscan-sitecheck-promo p { font-size: 13px; margin: 0; } inc/fonts/OpenSans-Bold.ttf000060400000375370147177152050011615 0ustar00 GDEFȱ`4GPOS{jq:7GSUB홗OS/2l m`STAT^AZcmap8mcvt =I, fpgmZqgasp#$glyf1a!,Qhead4[T6hhea m\$hmtx [locaA_RhmaxpRH namepost&'jprep{lu@  rr++23|/01A#!4632#"&3ZgIGggGIg^LL^ZPPBr+2201A#!#))))-9@   ?3?39/333233233301A!!####5!7#5!333337#/MNLJ/!MMNN/LjjiiXD$,5(@..(, - %#/333/393301E5&&'.5466753&&'6654&&'5VUkSmta^RIo~FB=-):9w-&)C6>udfZ -+"&)`x ;/,'Y*,&? '3"@(." r  r+22/2?+2201A2#"&546"32654&%#2#"&546"32654&1..11//+⬲1..11//|~~~}~|J|~~~}~|R%0<+@70& - r r1r+2++29/9901A2667!!'#"&&54667.54663267"6654&{vk}*;>w\-s;U~@xT5?m&9bBr/3]4+V\SJfHENssq)< h|hq0>lk;hS>F*Xd 4G2_1/_==5 r+01A#))Ry r+/01S473#&R@g@\g@1?#|0~x;=d r/+01A#654'3d@h]~@A~^h@1x~"9<%|?V@    /2901A%'%7)u!㜉'm)hy9w)hpX9  /33301A!!#!5!3}}?? /201e#>79C"&! HKQG=V/201S5!=u9  r+201w4632#"&ugIGggGIg^LL^ZPPD r?+01A!D!JJH  r r+2+201A#"&54632326654&&#"H7yČlc໯n5%XNMY&&YMNX%۱fQQpoߨqqyN @  r r++22/301a!4667'3N CN#gm, ?wNP@ r r+233+201a!5>54&#"'>32!Poo=aQUW?p`}sr~HWWNH6`;hqywNB.@ $,r r+2+29/39901A#"&'32654&&##5326654&#"'6632TY}y\^Y>oq3`pFs\#Voe^t'(01sh=T,3Y9NX#1>R#q @ r r++29/333301A#!!5!3!54>7#q"*//i#``K)M*kd5!#@r r+2+29/333301A2#"&'326654&#"'!!66fxsLL^\~A9{){7"PfƑz'( (71gPkr BHP"1@))# r r+2+29/33301S4>$32&&#"3>32#".2654&#"H%\+s&([-Q UzRfzߙp’R[rcdDg88Sm~۩a t͈1L-mΔyM|k{=]13dR27P@ r r++2301s!!%/ HJ.<@+6# r/r+2+2901A2#"&&54667.546632654&&''">54&J~ՀEvKNY昤xKMAk?hqosrAb2@_6Ld1Q0.P2eNvXc%)mazb^zdk&)hWtOOgcQ8TCHZ)NG2K86L5GNBJ"1@))#r  r+2+29/33301A#"&'532667##"&&546632%"326654.J%\+t&(Z.Q Oz^}eyp“RZrbdEf98SF~۩` t·0M-mϓzM|j|=]13dR2us r r+2+201w4632#"&4632#"&ugIGggGIggIGggGIg^LL^ZPP^LL^[OO?s r /9+201e#>74632#"&9C"&! /gIGggGIgHKQG^LL^[OOX9/22901e59TX9 /3201S5!5!X'{X9/32901S5XT=J+@ ##) r r+2+23/01A54667>54&#"'66324632#"&&TE>K#`VVWmd5kP<@gIGggGIgJDi_2,FE,AD6,8E͞T{i:,<;*<^LL^ZPPfTAO)@ILL%>r EE .5/32/323+222301A#"&'##"&546632326654&&#"32$7#"$546$3232677&&#"-\_Ks*avڔa:/.> Uwkb{EU]OgT :"at3_YH93N۲x#\*U7\\f5()1S?pcyU@ rr+2+9/3901a!!!.'7jj{j !! # i\D`T"ko))yl%@ rr+2+29/39901S! #!32654&##32654&&#$,5dHIvG6h{ʌn0qcSV IsesUSTIl[6R.wr  r+2+201A"3267#"$546$32&&%Y]0MYiau݌ZmddREss(%(#Qn70':u rr+2+201A#!!24&&##326ubR_dH @  r r+2+29/301a!!!!!!J @  rr++29/301a!!!!!Fw'!@ ! r r+2+29/301A!#"$54$32&&#"3267!DsОUt\gC^mNB[(5 &-PP2(".|ߗ} 1f @  rr+2+29/301a!!!!!!f6C5w= rr++01s!6JhR r/2+01S"&'32665!<[ I)6V26uR  )rkZiP@ rr+2+2901a!!!667!P6<Xh^c+V+y?rr+2+01s!!6QJ@  rr+22+2901a#!!3!!4667##  Zo {)KX^JE)@   r r+2+29901a!#!!3.'!v {REFPDCw r r+2+201A#"$&54$32326654#"TT63MKŃMݩkkQwwݙw @   r r++29/301A ##!#326654&:ڠÍfWFx`ON.bMliw%@ "r r+399+201A!""#"$&54$32326654#"M{`s T63MKŃMݣ8wHkQwwݙwH@ r r+2+29/3901A2!#!#32654&b~L|H^d`”dh!1ugdhX^/@,($r  r+2+2901A#"&&'326654&&'.546632&&#"~L739 !Jy,,yf)@$)rr+2+22901A!.'!!>7!>71% JZk_^j\$dme%&eiZ3e%20V @  rr+2+2901a!!!!V:V;5N5)+@ rr++2901A!!!1NP\Z/1q @ rr+23+2301a!5!!!qVDsr/3+201A!!#3s B rr++01A!!!J3r+2/301W3#5!!3qT/dr+2901S3#/J}NH/301A!5!NRR!  /]9901A#.'5UX 'hm^!.pi&QYRV;u(#@%%  r rr+2++9/33301A2#'##"&&5467754&#"'663265j;0d]cZ\RQNeYvsRBbuPj48jL_FFyz-%KqoG3.,'\q$%@ rr r r+233+233++01E"323&&5!#'#726754&#"PzY 2; Wx}gders%',J. }Bf.K,!\bs@   rr+2+29/301A2!3267#"$&546"!.mz/k^SYu /]sw⣔,,)&|rzDj>)u@r r r++2+23901A!!#57546632&&#"! ϨayY.N#R5@;yyRRA M32!4&#"! $cxEydX\\j,S:H"U'xzUw r r++201A!2#"&546ϙDbbDEaa^^?VUAAUV?}@  rr+2+201S"&'53265!4632#"&F4p%%A)>V1NBaEDbbDEa Ee)fdkV??VUAA @r   r r++29+01A3667!!! A%9XDH?~?,V(Ti r r++01a!!1Bs'(@$%! r!rr r+22+++23301A2!4&#"!4&&#"!33>32366RVyf$J:Ua))"g|@{.2s'xzPl6Uw^:H"PTVNs@r r r+233+2+01A2!4&#"!33>W]f)$ks'xz^:H"\s r r+2+201A#".54632326654&&#"K~vőO0fRQe//fRym1ؕLL،nLLnoJs(%@rr "" rr+233+233++01A2#"&&'#!33>"326654&n~QtR+VyP^+)aUFZ-fs)A%(T(=J-L-Be!lNNm\qs$%@rrr r+233+233++01A467##"463237!266754&#"? +{l{0Tc,dmjl*U)E`%_EBd%ws@ r rr+233++01A2&&#"!33>=7;oX3-!csCmO^9_9\s*@' r  r+2+2901A#"&'532654&&'.54632&&#"kԞuU[OYMfmiAhd\SLCD#eb_LLrQ#)55+-9.,Z{_*.$.$%*3('U}/7L@ r r+2+233901e267#"&&5#5773!!w2_/1Vd[X9IAf@?^@ r r r++233+201A#'##"&&5!32665)$lFxc1V^]j+^9H"UsxzUw^ @  r r++29901a!3667!V??V^8|15x8}^*@")r* r+2+22901a.'#!!3>7!3>7!7V % % Z0  P+#$}^4'`gS~&"4 ^ @  rr+2+2901A!!!!ZZ};#d^@ r r+2+2901Q!3667!#"&'5326677N  G'+k4L@#@\>^>B$6^.utN 6[677^ @ r r+23+2301a!5!5!!B Q%@  r%/2+29/39901A"&&54&춹4663կI;rSSr;I5O*xrrx*O59|b;AN$#O@>b{9<9^o o^9=///01A3#!R%@ r/2+29/39901S5>54675&&54&&'523"R5N+xqqx+N5I;rSSr;I=9+^o o^+9<9{b@O#$NAb|9X'9}@  /33/322/301A&&#"566323267#"&%Kj.:}33NPi48jK_P@Idi~˞*$KqoG($"~Rj#%@  rr+2+9/3333301A2&&#"!!!!5>55#535466oP]F?B`w.E$9P+w0"#M_ۏI`<;`N×Tq!#3J@#!(((  000    ?3/223333332233333301S467'766327'#"&''7&&7326654&&#"+g35a.}+d57e+}3V45W44W54V36d+*g67c-}}{}-b64V22V45V33V,@   r ?+29/332233301A!3#3#!5#535#53!H9<\Zݲ/ /2/301A3#3#j6E@/!3?mF5z{3pRYXfL2fO1'e^#7!X{%(tK/% 4-/!52&_|Qdy%(iJ)&-D1"14%*Yzq)E@!F4)E@!I  /33301A4632#"&%4632#"&Q:9TT9:QQ<9UU954.#"Toquoa?9<2a+yu/u31fg~ܨ^\݂ߦ\ZouooӉy [㈀a\䈈[/'@$$ r+22/992301A2#'#"&&54667754&#"'663265+|JIm#@ 5!r + r+22+22901A!2##32654&##"$&546$32'2>54.#"1b>fPPIYd}oquo~ܨ^\݂ߦ\ZaosXQ@IAouoo[㈀a\䈈[/301A!5! Pr+2201A"&&546632'2654&#"i[[ij[[jA[[A@[[WedZYeeWSGJSSJGSX9@   /23/3333301s5!!!#!5!3X}}}|/Tx w?32301A!57>54&#"'6632!y=E0((W5{Am-bPi`T}jFd tGy"#(264)BD)&2&(/>R!  /]9901A#5>7^lh'!WV!RYQ&ip.^!@  r rr+2++23333/01A#'##"&'#!!32665+H\;=c 1X^[i,^8L&/+Wa%JsxzUwq /2/39/301A####"&&54663!G,~hqˆ\P3 _ۻ^u'{B /29901E#"&'532654&'73-HT+J\N)J/s #%: = 3K\TH @ x w?901A#4667'%H .Nm-WN0=9  r+22/301A#"&5463232654&#"ṝaY#AHG@@GHA\UtdeeddccR^ @   /32901A'7'7ss#;w\\w9;w\\w9-%6@" r  r+2/9+2/9/9333301a34667'%35!533#35467?+ /Mm-}}L 1JJVO0=B̧?*^1f--&@++# r  r+2/9+23301a34>7'%357>54&#"'6632!?+ /Mm->E0((X4{Am-cPh`JJ<@3 0=772.. r'( !!r+2/229/399+2/9/9333301a3"&'532654&##532654&#"'66325!533#35467+KABHJFEaq\i;130T8e>g|QYfa"}}L 0J9##(274)AC*&2&(/>}kEd uGyǘB̧?*^1f7w]+@ ##)r /3+23}/01A3267#"&54667>55#"&54632&SF=L#aUVWmd5kP=?)fJFhhFJf]JCj^3,EF,@E6,7F͞T{i:,<;*<V^LL^ZPPy&$CX r+01y&$vX r+01y&$JX r+01f&$QX $r+01\&$jTX (r+01 &$OwX%+@    rr+23+99//332301a!!!!!!!!!#%3z\`Nw&&zBy&(CX r+01y&(v^X r+01y&(JfX r+01\&(jX !r+01y&,CRX r+01y&,vpX r+01y&,JPX r+01\&,jX r+01/u@   r r+2+29/33301A2#!#53#3#32654&&Rb٣bTddf&1QPX  r+01wy&2CVX 'r+01wy&2v%X (r+01wy&2J-X -r+01wf&2Q=X 2r+01w\&2jX 6*r+01  $@    /3/3/3/901A'7w-Ӗ)՘-ј-՘--w%09@*--r)) ""  r+233333+23333301A#"&''7&54$3274&'3266%&&#"TbEZZea6eFTXb` %Y6K'^8Mݩk! ld'Q$"}hbܶY:wݙ\<w^y&8C-X  r+01^y&8vX  r+01^y&8JX ! r+01^\&8jX ) r+01y&<vuX r+01@    rr++99//3301A##!!3 326654&##8Қ6Dd`@|^NJ.dQkhh<@ .9r4 r r+2++201A#"&'532654&&'.54>54&#"!46632:UU:(\LC_3i̗b; ak.PXPPTb*8TS8aHo?ϑLoQ=4+:2*[uQrN"(>=$4<.0SW6@YC=F1?N+YEs]LV;!&DC /r+01V;!&Dv` /r+01V;!&DJh 5r+01V;&DQy :r+01V;&Dj >2r+01V;&DO# )V+44Vu1=E3@ A%,r!229 r/>>r+23+299//3+233301A2!3267#"&&'#"&&54667754&#"'66326632665"!.!y-e]T[0\s&Fz\b!&HC &r+01\b!&HvT &r+01\b!&HJ\ ,r+01\b&Hj 5)r+01!&C` r+01!&v/ r+01!&J7 r+01&j  r+01\$4!@%$!  - r/+29/9301A7#"&&5466327&&''7&&'"32654.G9ddE{ٍEjM"]Ad#K*Sf/0fR{j8W G'h[w䢢v+!R=j/?}_TG/UC'&QQ 'r+01\!&RC 'r+01\!&Rvq 'r+01\!&RJy -r+01\&RQ 2r+01\&Rj *6r+01X9 /22201S5!"&54632"&54632X9SS97TT79SS97TTdyHPTCCTPHHOUCCUOH\"-5@&& r' **  r+233333+2333301A#"&''7&&5327&&#"4&'3266@u5CDIO$D}77:DJ =6ym.Qe/1eidK؍,RlTIц1S" (G2L!&XC  r+01!&Xv  r+01!&XJ  r+01&Xj3 -! r+01!&\v= %r+01*!@ rrr '' r+23+++2301A#"&&'#!!3>324&#"3266j~PyV1 WzOfkx``FZ-1%>&99;y1p.K-褦!N&\j 3'r+01&$LX r+01V;&DL +r+01&$MX r+01V;+&DM -r+01&$PuVQu&DPjwy&&vX &r+01\!&FvB $r+01wy&&JX ,r+01\!&FJJ *r+01wl&&NX &r+01\&FNX $r+01wy&&KX r+01\!&FKL r+01uy&'KX r+01\&G4X 1V+4/u\ ,*@ r'  ?23?33+?9/33301E"323&&55!5!5!3##'#726754&#"PzY ;2; Wx}gders +J/,43ǡT.K,&(LX r+01\b&HL "r+01&(MX r+01\b+&HM $r+01l&(NuX r+01\b&HNj &r+01&(P\bs-5)@#&1 & r.r+2+29/3333301E3267#"&5466772!3267#"$&546"!.N-# ? J1sR]&z/k^SYu /]*(  ey&(KhX r+01\b!&HK^ r+01w'y&*J1X . r+01m!&JJ R{V+4w'&*M^X & r+01m+&JMI P{V+4w'l&*N?X ( r+01m&JN, RV+4w;'&*qm!&6/J r+01fy&+JX r+01&KJ; !V+4'@  rr+2+29/32223301s#535!!5!3#!!!5!6C5C-wy"#@! "r r r+2+2+9/33301A!!3>32!4&#"!#535; $bxFycX\\j,ϜS:H"UdPxzVw/ǡf&,QdX V+4&QH r+01&,LX V+4&L r+01&,MyX V+4+&Md r+01&,P5\&LP l&,N\X  V+4R&,-P&LMqhRy&-JRX  r+01}!&J7  r+01;P&.q;&Nqq^@ r r+2+2901A!!!3667HƏ1#E%:^Z^=z<+T+n?y&/vFX r+01&Ov/ r+01;?&/qm;&Oq/y&/4 V+4`&O4 V+4?&/NP&ON? @  r r+2+901s'7!7!Eq6uQ)oXĞX @  r r++901s'7!7Hq1Ft+p-+phy&1v7X  r+01!&Qv r+01;&1q7;s&Qqy&1KBX  r+01!&QK r+01'QR!@  rr/2++2901A"&'532667#!!3.5!@c"%R/La1 {uR  'TCN97P{:2J[s$!@rr rr+2+++23301A"&'532654&#"!33>32=/g"6"2I[Y]j+)$kExcH EemnUw^:H"Ufdw&2LX #r+01\&RL #r+01w&2MZX %r+01\+&RM %r+01wy&2RX '4r+01\!&RR '4r+01wP(-@%"" r  rr&r+23+2+29/3+2301A2!!!!!!#"$54$"3267&&6-d3,5ލ#WS(Hs<&%~ TQDsw\{s$3;-@!%%74r,,  r+2323+239/32301A2!3267#"&'#"&54632>"326654&&%"!.w~qaUMFxpF0wPym0fRQe//f^| 1bsw⣔,,)&LONMOM4E#nLLnoJrzDj>Hy&5vX r+01!&Uv r+01;H&5q;ws&Uq5Hy&5KX r+01Z!&UK r+01^y&6v;X 7r+01\!&Vv 2r+01^y&6JDX =r+01N!&VJ 7r+01^&6zq\s&VzJ^y&6KFX 0r+01P!&VK +r+01);y&7qH/;7L&Wq)yy&7KRX r+01/&W4)y!@  rr++9/3332301a#53!!!3#sPsTb/7L%@r r+2+2333301S5!267#"&&5#5773!!BƑ2_/1Vd[X9IAf@?^f&8QX  r+01&XQ  r+01^&8LbX  r+01&XL  r+01^&8M1X  r+01+&XM  r+01^ &8OX V+44&XOZ V+44^y&8RX ( r+01!&XR+ , r+01^)@)r$$  r+2/3233+201E3267#"&546677# 5!326651# ; J2s=g>H\+}5f<44  pEi#BrbWN(Fq}^&XPy&:JX 7r+01!&ZJj 7r+01y&<J}X r+01!&\JF $r+01\&<jX r+011qy&=vRX r+017!&]v r+011ql&=NhX r+017&]N r+011qy&=K\X r+017!&]K r+01? r r++201A"!46632&&PF9axb.G#P-M<\A /%#@ !!  r/2+29/333301A2&&#"3##"&'53265#575466)\+HD.<1I0f"5"3J[ M7!ojjlf +' a/17)-43K@<VK_]##I+o~n,JJN!!tu!W`N0.-33-+3DF 494V;(4AM4@%% r CMMIGG)5/<r+2222/333?+9/32301A2#'##"&&5467754&#"'663265"32654&'2#"&546#5>7j;0d]cZ\RQNeYvsRBb*710)77)GsDkos.@<u7]b$656z5&b\!.pj% Y77W"&ip.R!@  /]223901A.'536673R\b&5z656$b].oj&"W77Y %jp.R /]301A!5ZRd+ /]3201A#"&'332667dgr=a:0bE+cV9565R /]301S2#"&546DbbDEaa?VUAAUV?RH  /2201A"&54632'2654&#"Joojk)77)*71on~mp4-,44,-4R# /3201E3267#"&54667%-# ? J1s3232673#".#"R.J]5)OMK$9 h)OMJ$9 PuK%*55 ) 56R! @ /]33322301A#5>7##5>7Oed&IF`Oed&GF!PZR'jn.PZR'jn.N^ /2201A5>7! :D'$[b^'5xA #@   /33301A#5>72#"&546!2#"&546;:F& 9JJ9:GG_8KK875>54&&~@>EDK|}KD˴]fg[kZZPT\PiP\TPV;m@ rr++229/33301A#!".5!3!2665C?"NzoW!͉ELG˃!x1/~x7'@r  r+23233+201A"!!.54$32!!>54&&%u[1tes`N88Obv}gv2[`vƝ7;ꉺ컉<5u`\&,jX r+01\&<jX r+01\^&}S= 4r+01N%^&S1 -r+01^&Sf r+01^&S r+01&T76*r+01\q 3'@rr$,,0 r+2323+233+01e266754&#""32366733267#"&'#oTc,dmjlw2 "!2"& 08g~#Y}Do $(TT#S,[E1 H_.L-0)@))**r!! rr+2+239+9/39901A2#"&'!466"32654&&##532654&䃙yܔc>ύ7c ,.V=*"(^RE9TR6$xB\$3@"%1)- rr+2+2901A2&&#"#"&&54667.546326654&my[XQB={\{Lhn>mB7xS4eHJh7n<3,8<($EM/>kqk͒u (e}LOl@g;=xVjN%s,@,,&r  r+2+29/39901A#"3267# $54675&&546632&&#"3Hi;5va}FM܉{kjކtV^Jgpo=-%8 6 #*{{ dk:.&126B7\)@ & r/+9933301E!>54&&'.54>7#!5!W3'D)MNj[sUVVv%D~Vz<%YG5nb"p^߶٫Bcb+Kcs@r rr r+23+++01A2!4&#"!33>xcW]]j+)$ksU;yxzUw^:H"\ @  r r+2+29/301A# 463 267!"!&&mktm7jxshkuc`Jy^r r+2+01A3267#"&&5I<3^0.Pha^@?A^!-@(  r r r++2+2901s'&&#"5>323267#"&&'.'##+bR6;@k)66$@FSoH` )!\j:TrUW8gD!A=76~2^ws^@  r r+2+9901S!3665!!9 N`+4L^UTg3\<%@!!0 r+2333/9/39901S46675.54667##5!#"33#"!>54&&'.\HTEb4=d0q]$KSvDssCD~VzYG5nb"l\sR^@ r r r+2++2301e267#"&5!!#57!#$A${?6!Buf22ys"@r r r+233++201A#"&'#!4632%"32654&qЎO8 }nm+t54&&'.546\RXL?~rGUz54&&BOUH{K⮕uB9@]K#PujчiI˃ }fOa bgXXm&"@ r r+2/3+92301S2!3267#"&&'!&&#"566avM!J39-9%/ +WAZ~X hM/=",Ym<~e%-3BaFu`M7 F!@rr rr++223++2/01A>54'!!&$&5!mD-#(&#7l Hx &s3tD;m{^0#@##0r )) r+22333+29/01A#"&'##"&&54667!32665!326654' '2eȖ& 'd1'%@=\g>EF=EU(y9e^bui~Ɨ`lo[/]WY`1(%(#Qn70':^6,\&,jX r+01hR-&0@'r0r r+2+29/3+201W"&'532667>7!32!!!32654&&##)K 4(5* &)Xsxi  Y^~G[H 5r2$rɁL>^[pNR#@rr+23+29/33301s!!!32!!!%32654&&##65sxi#^~H[H=rɁw[pNR)@r r+2+9/32301A!!2!4&#!!!JFPлYG^`y&vX r+01N&3oX "r+01V= @ rr+23+201a!!!!!!=TR65VL$ @ rr+2+29/301s!!32!'32654&&##z thOfOrɁ[pNR%T` V@ r ?2333+201A3!!!3667!!1lq9j\J4GW1;LTVr$Vjm("@   rr+22+22901A!!!!!!?!@<<B^.@ #+r r+2+29/39901A#"$'32654&##5326654&#"'>32ҡ،ʦ^@F¯׉{MrVK~}`o)&+pgi`-U7#!sZ>4~yZVJ8|[&3X r+01` @   rr+2+2901a!!!!`6 J<B=@ r rr++2+201a!!#"&'532667>7!= !Y{)K 4(5* &)^M^ 5r2$0f+w2=m3w&)y7N@ r  r+2+29901A#"&'32667!3>7N;=Ԭ6~62u4DT2H   k .N0CEGKf\rV;V @ r r+33+201e!!!!!65`L@m@ rr++29/33301a!#"&5!3267!ʁm5buVj65,.Ǹ\jk%% @ rr+23+2201a!!!!!!685LLV@  r r+333+2201e!!!!!!!"685`LL@u @ rr+2+29/301a!!32!'32654&&##o{uhOePrɁ[pNR @ r r+22+29/301s!32!'32654&&##!6d~ZQHcCd5rɁ[pNRyJ @ r r+2+9/301s!32!'32654&&##6z thOfOrɁ[pNRH#@  rr+2+29/301A"'6632#"&'32>7!5!.)b\bk[~iub^e9x4^8'07e#(%(/]]V^0'!@ $r r r r+2+++29/301A#"$'!!!!6$32326654&&#"O6 +FquDDssFݩk%ö wwݙww@ r r+2+29/3901A!.54$!!!#"33;wN"ʙPq;1`wJ1&QCapV;uD\"2,@.**# r r+223+29}/333301S4$76673>32#"&&26654&#"\z lx#4z|t/fHXUk|ȏL1Aa7YkAqN8aZ%D&O5n٢Z9o?QOxF^#@   r r+2+29/39901A#!!24&##3264&##326qntdڰxgeVpRP״ad9Ze`W^7B;@428^r r++201A!!-^^o1^@   ?2333?301A3!!!367#!^Je?1H4^opq"E|b\bsH^ @   r r+22+22901A!!!!!dVVd;^77FN#s/@""!! r)r+2+29/39901A2#"&&'5326654&&##532654&#"'667y҂zeGsDvZ1EsSOElvpjzOSZas?gew :fS]` 690-;2C66%"%/#^@ r  r+2+29901A!!4667!o ^F"gjT7v^#?&3 r+01^ @  r r+2+2901A!!!!}PE71^7^^@ r r r++2+201a!!#"&'532>7!:Zb6U#24.)"Nyd .q2!^@ r  r+22+2901A!467###!!!^%QBVC\^ ^ @   r r+2+29/301A!!!!!1V^R3^\sR^r r+2+201A!!!k^y^sS\sF/=^@ r r++2301A!!!5!=yy^\\'&%@r  r rr+++223+22301A!&$&546$7>54&  YFC\[CP k \Y[Z d Z[ ^[od^ @ r  r+33+201A!!!!!3dN12o^y{^@  r r++29/33301A3267!!#"&5G@XM1Iu^gII( &@!^ @ r  r+23+2201A!!!!!!1w1w^^yyo^@ r   r+333+2201A3!!!!!!!1w1w^^yyf^@  r r+2+29/301A32#!!5#32654&׬mdٰfYrg^PHolXy}ALA:-^ @ r r+22+29/301s!32#'32654&##!1ldدYrhg+1^PHolXALA:%^^ @  r r+2+9/301A32#!!4&##326׬ndڰ1hgYrHolX^A:AJs@ r r+2+29/301E"&'532667!5!&&#"'6632jHJXFg=ZkeH8VAk~ %".4q[|{&3fs&!@ #r r r r+2+++29/301A#"&&'#!!3>32326654&&#"뢊ڊ1ڌ%+]KJ\++]KJ\+1hդ3^RhnLLnoJJ^@ r  r+2+29/3901a!.5463!!#33#"J-9d>ϨoXRNU[bFOO\b&Hj 5)r+01/)@'#'r rr+2++/339/33301A"&'532654&#"!#535!!!3>32=/g"6"2I^V\j,Ϝ1; $bxFycH EennVw/ǡS:H"Ufd!&v' r+01\s @ r r+2+29/301E"&&54632&&#"!!3267\RXL?Eb: [ 7_DbSHwk'#$7mSWq8-#%$\sVL&j  r+01}M^(@! r r" r+2+2+29/301A32#!##"&'532>7#32654&^jaԬ;:Zb6U#24.)"Slb^PHolXyd .q2}ALA:^#@ r  r+23+29/33301A32#!!!!!#32654&^jaԬ;1\Slb^PHolX3^R}ALA:!&v r+01?&\3 "r+01o^ @ r  r+22+201a!!!!!!'y12x^yo}rr++301A!!!}qJ6r r++301A!!!^1y&:CX 0r+01!&ZC 1r+01y&:vX 0r+01!&Zvb 1r+01\&:jqX ?3r+01&Zj @4r+01y&<CX r+01!&\Co $r+01R/201S5!R\R/201S5!R\R1N /3201A!5!5!5!NRR1 r+901S'>73'9C"' IJQG  r+901A#>79C"IK<|5@'7   r+301A#.'7? '"C9FQKIw @  r+222301A!'>7#!'>7w' 9C"' 9C"QGIJQGIJw @   r+223301A#>7##>7h:B"&! 9C"IKQFIK<|5@ '7{ @  //9/33301A%!5!%77777LB_q'@  //99//33333301A%%!5'75!%%dL87K//K78L/-yxb) /301S46632#"&&bLQONNOQLs??sqAAub9&'H?  '3?K,@@4F: r(." r  r+22/2?+22+2201A2#"&546"32654&%#2#"&546"32654&%2#"&546"32654&1..11//+⬲1..11//׬1--11//|~~~}~|J|~~~}~||~~~}~|^} r+01A!#f^Br+2201A!!!#wR^/901SRs=wwR^/901A'-s9;w\\u&Hw r?+01A#+JhL@  /2/233301A2#4&#"#3366t9<\BƗ #ytKHIrkV4.#' @ r ?+29/322301s#53!!!!!!o<Rj),@ %%"!! r+2?339/33322301A2&&#"!!!!!!5>5#535#535466tP]NEHTggA8BO#s0"#M_qs#RLGY1ssT .-@% r,--*.  r /+29/3/3333+201A ##!#32654&!!3267#"&&5#577-! <5uTBH3/L&){G_MX`ONitli}>lgB6+@300'* # rr+2+29/32233301A2&&#"!!!!3267#"&&'#53&&5467#53>#eObExA=eN4 ^cSYO<9^vt*(#$FfCOm7u࠲ # }?6%@0#*#r  r+2/22+2/2201A##"&5463232654&#""&546632&&#"3267+-?FD==DF?Z\f8p17-T%MECI=h)#fJdeeddcc8HlYYe)#-"@ +'r r+23/+2901e2673#"&&555667466324&#"66}J89VsUteddccdde#+@ r+2/323393301A33#467###!#5!#ƻm !+/`+ R Tcnn7ufH"@ " r r+2+29/301E"&54>32!3267&&#"yy]^,\EH0x&je/#֊B/L{o)LL(OG.78D.@93'?-  r  r+2/9+2/22901a34667'%32654&''"&54667&&546326654&#"'+ .Nm-1;<@9 -:=,H*6ISg}QYeas;<@9 -:=,H*6IS}kEd uGyP:-)<$--:s8P;&eLnsqpLa"%bTs;2+..*1`"0IU=@ )*8DJP>1#1 r r+2/229/3333+2/22901a3"&'532654&#"'!!66322654&''"&54667&&546326654&#"}+F226N^WQEl$ 9$s;<@9 -9=,H*6IT324454&&#">"32>7&&l/0cՊH$O~9k8^973<# -ek6LSO!T;qN!  /3201A!5>7 2<#!(kn,-ek6 T @  xw?39/333301A##5!533!5467}} 1옘B̤*^1fTD@ xw?329/333301A!6632#"&'532654&#"':#F226N^WQEm% )m^{B.$*/;J1%&4^0  %1}o0oo/mmmmmmoo;mmJoooo/yhI\ii\\hhCS1D ;EPZb" "+% * f$2re]T!-@ !%++//9/999301A 5467>54&#"663232654&#"TV*C;N'9yp.RD7?>5DLCQ<8SS84/TbC,".:/:G5=qP;H??HL==}!&K9  r+01);G.@ #CC4#4#4- r</2+299/}/33333301A23##".546654&#"'66323266544'$$&5466".ӈƇQ?𱅫`&4L;[YhVgaAΈ[:GJ 0EVU~;o7_v?#GC) "4^X*X[/?[eԤ- t__48;lESX.@rr r+2++901A>7>32&&#"!!} >=:F]@(M" &3%KWU"PTE|l-4?  6!}Z/3^4-@((r $$ r. r+2+233+22339/01A!#"&'##"54667!57!32655!32654&&dȖ& &\g\DF=g\^=A|qaaqA=f>~>xPp:=y&0vX  r+01B!&Pv /!r+01&$SsV;u&DS/ V+44XN  |/3201A"&54632'2654&#"Poojk)77))70on~mp4-,44,-4w+@ (r! r+2+299201A#"$&54$32>5!326654#"TT7T)-"MKŃMݩkkQjaOmA5Pjwwݙw\)@ ' r r+2+299201A#"&532>5!326654&&#"$pF6B-I}0fRQe//fRym1,FDPuGc{!5!# 5!32665^2?-8c|5f<OsFSuP—(iDes")@r  r r++233+993/201A#'##"&&5!3265!>5d8e~)$lExc1V^f13B TvPϏ9H"UsxzuPuG@  /]29901A#'6654&#"56632RP K6*"(C b1MdG 3% " py&(CX r+01y&CX r+01\b!&HC &r+01#!&C r+01+u+@ *r% r+2+93301a& 5!3667.'!365!!.'XyED1GR) 1{  C,F[5 AW,BS*NH=X_ONyIOtX9BF'^(@(#  r r+2+93301A!.'!& 5!3>77&&'!367 N|$MEDk?3AX* '.v3 5L+8P1 ^BCbi(3`#LO'Wes5$@   rr+2+9/322301a!5!5!!!32!'32654&&##5y{ uiOfPrɁ[pNR'!@ rr+233+29/301A!!3 #!!5!5#32654&3gdٰYrh'ˣlXyALA:R*'@ rrr$ r+2+++29/33301E"$'#!!3>32&&#"!!3267s֟6ruedYVRe? d8bZarg%ÆڝU70':,V}QTj;(%(#s'&@r r ! r+2?+9/333+201E"&&'#!!3>32&&#"!!3267ś1ۆk@V7IC\2Z=gEYJIhդ3^RS3&4dI\p2."%  #@  r r+23+9/93301A!#!#!!'./df-(% %9# #%DwwTe[ZZZcT^ #@  r r+23+9/93301A!#!#!#!'.FۘNP׸ %#% %()^ZZ^ cU TPXd  0@  r ?333+29/9333301A!#!#!!!!!!'./dg6ۿ(% %9" #%DwwwCTe[ZZZcT7^.@  r  ?333+29/9333301A!#!#!!!!!#3'.^ۣBB '"&(^553^ReV //Va)F!&@!  r?33+29/333301A!.'!!>75!Xd'{4D13G3{ɘFVkB+bw;Ja9 q 8aKYa?Ջ^ &@  r ?33+29/333301A!.'!!>75!<\Ht^$-$1#^uI`<^jNvR'3?"?!@5ZSwNmjm#&?@""%##&  r?333?+9/33333333301A!.'!!667!!!!5!Xd'{4D13G3{ɗ/6C+bw;Ja9 q 8aK1b^#&:@""%##&  r ?333+9/33333333301A!.'!!667!!!!5!<]Hu^%.#1$^u ^jNvR'3?"?!@5Z @3^RDj)/Z=@$ /@@7/== +/RTWNNG r+22322/3/39/993993301A2&&#"#"326632&&#"#"&&546676654&##5326654&#"'667.'53>/> 41b)Rdc ?RLwf2KQa+-STU׉{MrVSw!UP.o4&[v VD"`t@+"&2UYbUaqi`-U{/< 1*R"nr_ClAkWXKYJ[L1JO _)-nRGVͰZu9ElvpjzOSZ9}HA>-j:&\vd <3mew :fS]`)4*L]hT:)-;2C66%"$ #JD g 8^Adn 7]1,4gMMg4qpKd2@ r rr++9+201A"!!>7>32&&B'4'9! *W}cB_5,T=s=`Z4&IHK)^ f@  r rr+2++901A2&&#"!!3667>=V%(( T?!{%Iqf  -^@22y@Xh>y&q X $1r+01!&r  "/r+01w !?&@?()":3-r"rr r+2+2++?3901A#"&&54$32326654&&#"%!3667!#"&'5326677II" ><;>JN  G'+k4L@#@[?ݩkkQwwݙww>B$6^.utN 6[67\ Xs&R\w918'@!$$$ r1.++ r+233+33301E"&'.54$766326632>54&'#"&'Z:JߒGH75HGޖKF/-Fa{;J01I_{;<}}9:z:B,,B̘{9:}))(&%%&~Ā\3'@%"r.1+11  r+333+23301A#"&'.54766324&&'#"&'663266pғ H69G v E1-F y D5=>?=NHLR9988SO14;;6 /##/Q[.99."x| '+-'w=)kC@#Lf rU\r #:3riIFFCGGCC* r+23/333+222/233+2+201A54>3233#".#"56654.54632"$546632&&#"3267!326654.#"'6632#"&'4Tb-9qvNojS).+ <9$/$OGMTWJ҉P;l#f<=dG&Qx0S%6%Y6yO&Gc>5:ZHClAeb>/7;vu{'t#"{uv;7/>bvHKKHw3R)g=@ Lb rSZr ##:3reBFFBB* r+23/3+222/233+2+201A256654.546233#".#"#54>".54632&&#"3267!326654&#"'6632#"&'MURW<8$.$O :pwNojR*.+ 4Ta}†E{ܐ\3w)L%XX!@Z9+M#24:Lg5XX&M)y5\{zp>?1YICkAV>4:!%/%!*!4;2]l4Dؕz2"T{Q(): */Go"2zyU_dP+u9&]X 7r+01'&^ 4r+01w# @  rr+2/+201A2&&#"3267!".546$XuleZYdh5WHI˙s8`70':EssE燦n\s@  rrr+2++201A2&&#"3267!.546\RXL?Tj2=pKVu5uGs*&%KqlJ  KΌkhy   //9901A%%'%7%7JG㴁FG IĤ{{J;{Z}) )7ESao@ IW-;le&/3/3901A6632#&&#"6632#&&#"6632#&&#"6632#&&#"6632#&&#"6632#&&#"6632#&&#"6632#&&#"\egbmPL3=B3egbmPL3=BdgclOL3=AegbmPM2=BfegbmPL3=B5egbmPL3=BsegblPL2=BdgclOL3=AYjmV9<%YjmV9'66&&'#667%&&''&&'&&'5#'>7sEI>;VTLWnqIPjjZoN?%'@! r r+33+2992201A!4667!!!!"&&'!3267! ' o+V _jXq  co3x$^F0|)jWnhRPjjZ/ @r?3+9/333201A!!32!!#535#32654&&+z VOhOrɁ!w[pNR @?33/3/9/33301A!!32#!#535#32654&y׬ndڰ윜Yrh?HolXoALA:7@   r r++29/33333333301A'##!! 3267'76654&##WeXs,d8Dz  Lex~uD}p CmnG.lis29@ r r r,++-**'' r+2323233333+++2301E"&&'#!33>32'"3267'76654&QtR +VxOMD^l:wP^+)aU j f)A%"`4OJ-L-J{v Be!lN{&]7/P @   rr++29/33301A!!!!#53PoʉTd^ @   r r++29/33301A!!!!#53Lω^^y&@  rr++2/39/33301A"!!!6632#"&'32>54&&0]7FnwXknG>IJpL'l kDS8gSU ^!#@!r rr+2++29/33301A!6632#"&'32654&#"!%M#@A,x3e1^x^V(@ r  r+233+22901A!!#!!!!oR=ը?!BL<<oX^(@ r  r+233/+22901A!!#!!!!d VVd;^77F^&kN#s&k1V!@   r r+23+2901A!!#!!DmGո6 BL<o5^@  r  r+33+2901A#!!!3#71PE)o7^`#@   rr+2+299//901e#3!!!!p6 Jk<B^#@    r r+2+299//901A#%!!!!\PE71dh7^-7@  rr+2+22901S5!!!!!-H6 J1<B)@r  rr+233+29+01A!!!!!#535;PE7Ϝ7ǡ @   rr+2+22901A!!!!2{ B<^ @   r r+2+22901A!!!5!hF7^7yV@  r r+33+29/301A!!!!!!!f6C5+Vw=TLo^@  r  r+33+29/301A!!!!!!!V11o3^R @ r r+2+239/301s!!!!!!6C{=Lw^ @ r r+2+239/301s!!!!!!1V^R3)#@"(&)r$(r/3+2+29/33301A6632#"&'32>54.#"!!!O9iڹqXkoG?HBoP,UD"P*m DS8gSO L ^#%@" #r" r r+2+2+29/33301A6632#"&'32654&#""#!!!y(@A-x2f  ^xy^w=N,@B::%r1.. rK/3333+23+29}/301A3267#"&'#"&&54$32&&#"3267.54>324&&#">Ic'>*D"@CVH4AWB%N#U2X}O&am#@)7fYgp1(++!>(ā'  11i Y Ewh)_tm4YɯHh9 "6654&&f2x)CM'w`:c> (JmX\bB<"P0I;.mM>))#/8(ss@8~goPH|, .(}ԟX :+Cj(kO&:!w&&k9\s&Fk)Vy @ r r+3+2301A!!!!!sPs+VVL/o=^ @  r r+2+2301A!!!!!5=^fy<^@  rr++2901A!!3667!NP% %NM^=33=%@  r r+2+9/33333301a!!5!!!!?P/1N?Z)^!@  rr++29/9933301A!!!!5!!3667M##NP% %^^=33=V @  r r+23+2901A#!!!!:V;5N5<%V)+)L o^ @   r  r+23+2901A#!!!!{ZZo;#d)VH@ r r+33+22301A!!!!!!!{;i6+VNTL/o7^!@   rr/++3323301A!#5!!!!!%V1oylymVF!@ rr+2+29/33301A!!!#"&5!3267+ʁm5buVjTL5,.Ǹ\jk%%{o^@  r r+2+29/301A!!!#"&5!3267Iu1G@XM^&@gII( m3@   rr++29/3/3333/3301A!#".5!3667Bv7lP5_p5wCJ5# 1#Tr\hkH!{^/@   r r++29/3/3333/301A!#5#"&5!33667$W1}%1NL}+V+^(gOC f@ rr++29/33301S!6632!4&#"!6mbuVj,.ƹjk$&qK)2%@$$//  r*r+2+29/3333/01A2!32667#"$'#"&5467333>"!4&;2_q3[Ȳ?)7)kNa9G{^5L 6W%ŋy;h* L #5ݛQ,W~Q`s'/%@##++  r(r+2+29/3333/01A2!3267#".'"&&5467333>"!.`|naUy̚] fO ,4ߏ^| 2bsw⣔,,)&=|-cP,Y 6%)erzDj>V,5)@!!((22  r-r+2+239/3333/01A2!32667!&&'#"&5467333>"!4&;2_q3MԠת?)7)kNa9G{^5L .M d y;h* L #5ݛQ,W~Qo`s)1(@ --) ' *r+2?339/3333/01E.'"&&5467333>32!3267!"!.ri fO ,4ߍ|naC\^| 2b{Ɗ-cP,Y 6%)ew⣔,,"#+rzDj>,&3X r+01?&35  r+01+)@*''"+%r$r/3++29/3333301A2232#"&'32>54.#"!!667` cۿxXknG?HBnQ,[I(a16"I(N9S0`^O @4h3 ^!#@r r r+2++29/33301e#"&'326654&&#"!!!2Ue2-Z:DnAIj7!=N !Y{)K 4(5* &) L^M^ 5r2$o^@r r r+2+2+201e!!!!#"&'532>7!+݉:Zb6U#24.)"Nyd .q2f@ rr /3++29/301A#"&'3265!!!!fdG?\6CǦ= ^@r r r+2++29/301A#"&'3267!!!!Lw?6x4byV1^s3^RV!@   r r+33+29/301A!!!!!!!!fN6C5 Lw=o^!@r r+33+29/301s!!!!!!!11+݉V^R3mV"@  r?3+29/33301a!!3#"&5!3267!m5buVj6V+,.Ǹ\jk%%{o^"@ r ?3+29/33301A!!35#"&5!3267Iu1G@XM^op&@gII( V!%@   r r+223+2901a#!!3!!!!4>7## ZoN {*z#X^TL'uoL^#@ r  r+333+2901e!!467###!!!Lމ%QBVC\^ ,&$3}X r+01VX?&D3% -r+01\&$jTX (r+01V;&Dj >2r+01%VuV&(3#X r+01\b?&H3 $r+01%@ ""  r r+2+29/301A">32#"$55!.2667!3/<ْ_Zϋ+`\i`G8L $F.lꫮg`H{^#NljPX^ss\&jX ;/ r+01X^&sj 5)r+01\&jXX 'r+01&j ' r+01^\&j)X D8+r+01N#&j E9r+019j%@ r r+2+9/3333301A#"&'326654&&##5!)Pafa33#"32659PUYO1h(+}hCՒsH[G/S6PfBAgp-ӾL??Jl̐aG1&]RFX(?=\&3+@&r!''r-- r r+2+23+9/33+01A32655!#"&&'#"323&&5"326754&RPXVL-AzkUxZ'!s6MuV gbchw_]iKFgpib.=0(>#%',J.+/fg!5#@&&%% r.r+2+299//39901A23265!#".54.##5326654&#"'>}uR #C5YO1ty>(Zi=kqh59Ro W`%E5gp-Ӿ:ql-O:!9_9NXB")A&9\s3%@&&%%% r-r+2+299//39901A232655!#".54&&##532654&#"'66 u}r_Li8$J:VL-Ayji}EFUerLOZ^s?gew ;\A%7gpib.%IoIGZ*2C66%"%/Vs( @ !r+2?39/39901A2!!!4.##5326654&#"'>ꂶ++`rBs{n8<Ro L-O:!9_9NXB")A&No-s& @  r+2?39/39901A2!!!4&&##532654&#"'66/y҂r_ClADkjzOSZas?gew :fSgF4C 2C66%"%/.@ .r% r r+2+2+29/01A3265!#"&&5!#"&'532667>7OWYO2׌z Y{)K 4(5* &)HCgp-ӾO=?3^ 5r2$^(@'r! r r+2+2+29/01A32655!#".5##"&'532>7!jQWVL-Ayji}E:Zb6U#24.)"/yIDgpib.,^ld .q2%@rrr r+2++99//3+01A3265!#"&&'!!!!=IUUI1Ӊw6KFgp-ӾO=^%@  r r rr++2++99//301A!!32655!#".55!!2PQUI-@xig}Dk^RHCgpib.,^kV3^w#@ #r r+2+29/301A!#"$54$32&&#"3266'!5DIbkCWX85{mPP7!!/g"6""7! !Y{)K 4(5* &)%G JCL^M^ 5r2$Jfd)^(@!r r# ?32+2+201A"&'5326655!!#"&'532>7!3b/R#3"-:Zb6U#24.)"NB)  4-yd .q2vHR&$BVR;u&D&$X#R r+01V;&DX .r+01&$c!R oV+44V&Dc 1V+44&$dR oV+44;&Dd 5V+44J&$e!R  oV+44V&De 6V+44o&$fR oV+44V;&Df /V+44Ry&$'DJX +r+01VR;!&D&Jh 6r+01&$g)R oV+44V;&Dg ,V+44&$h'R oV+44V;&Dh ,V+44X&$i'R oV+44V;&Di ,V+44o&$j'R oV+44V;&Dj ,V+44R&$'MXD r+01VR;+&D'M -r+01R&(\Rbs&H&(XR r+01\b&HX %r+01f&(QwX r+01\b&HQm r+01&(cR (r+01\&Hc <(r+01&(dR uV+44b&Hd ,}V+44J&(eR uV+44\&He -}V+44o&(fR uV+44\b&Hf &}V+44Ry&('JfX %r+01\Rb!&H&J\ -r+01Z&,XR r+01u<&X r+01R&,R&LwR&2\Rs&Rw&2XR &r+01\&RX &r+01w&2cR =)r+01\ &Rc =)r+01w&2dR -^V+44&Rd -}V+44wJ&2eR .^V+44\&Re .}V+44wo&2fR '^V+44\&Rf '}V+44wRy&2'J-X :r+01\R!&R'Jy :r+01wy&Tv%X 3r+01\!&Uvq 1 r+01wy&TCVX 2r+01\!&UC 0 r+01w&TXR 1r+01\&UX / r+01wf&TQ=X =r+01\&UQ ; r+01wR&T\R&UR^&8R^&X ^&8X^R  r+01&XX  r+01)y&VvX 'r+01s!&Wv *r+01)y&VC-X &r+01s!&WC )r+01)&VXdR %r+01s&WX (r+01)f&VQX 1r+01s&WQ 4r+01R)&VRs&W R&<^&\#&<XR r+01&\X #r+01f&<QX r+01&\QV /r+01\ &B / r+01-9#@@  /]399901C#&&'#5>7!'6673#3l46k2"LJ; JL"Y)A ,|;"T00T"'_d..d_',[B;h+ #@@  /2/92201A5>7!#&&''&&'53/"LJ< IL"3j64m2:}- A('_d..d_'"T00T"+h;B[,-(-@%""&@  /3/3392992301A#&&'#5>7%2#'6654&#"566? JL"3l46k2"LJ ^qB; G2%+' 1 .d_'"T00T"'_d.HP:E =t%1+%@++#(   /3/92/222/01A#&&'#5>7#".#"#66323267/ OU(=u56w;%UR 3^H,PG?+) } mg1RE>*) .ZU'I00I%U\.%Bk?")/d"-+1 @   /32/2|/3201C#"&'332677#5667 sXTu GL"@+VT[OLH)m31 @   /322|/3201C#"&'33267'#.'5 sXTu @"LF+VT[O3m)HL1 #@  /233|/29901C#"&'33267'2#'6654&#"566 sXTu Vd=+k 8"* 4+VT[OCD<=)n h1 &@ &#@  /32222201C#"&'33267#".#"#66323267 uUWt2^H-OG?+) } mg1RE>*) E<8IBk?")/d"-+   /3/301W4&'3#"&'5326NFKis1K ? #-4mB7yVe  () /3201S"&'5326655#!0g"6""8!;G JCLfd)y&7z/7L&Wz9w&2P\s&RPNw&2'LXP #r+01\&R'LPN #r+01X^s@  rr+2+29/301A2#"&&55!&&#"566!326!힚zk]ST.^HYus}v㢔+-)'=Ck=rX'2v2V+445 @  /222/33/301A5667!&&54632F2 EO$H@4@ '@95L,nn+X>Q3/$$+)?  xw?3201A"&54632'2654&#"2..21--?}~||~~~3D,@  'xw?229/33301A2&&#"36632#"&&54>"32654&K5nz3`KxPfhY,j (85*5B8 ?nG%=YO\`U# 1#E-G@8A+D+@ $$ xw?229/33301A2#"&'532667##"&546"326654&&uiY+jJ4oy3`Kx4C9:(86\`U ?nG%>FA7B 1$E-&@ !V+4444&@ V+4444&@ %V+4444&@ V+4444&@ (V+4444&@ "V+4444&@ ,V+4444&@ &dV+4444Rh&@rr/2?++23301A"&'326654&#"!33>32<[ H*6V2~|:1-]wC{R  )rk>lʏD^1gةy}:R ^(#@ rr r+2++2339/01E"$&55!32654&#"!33>325Ba~|;1-]w)n=alʏ9D^1gة= %1%@ +&& /33/232/3301A"&'332673"&54632!"&546325>73sXUu :GG:9JJ[:GG:8KK*(GK"׸VTZP?>?>??>?!HCHK V'@  '! /33/33301A!52#"&546!2#"&546#5>7Z9JJ9:GG8KK8:GGeGK")(>?>?KICH"V '@ " /33/33301A.'535!"&54632!"&54632!LG(*N:GG:9JJ[:GG:8KKIK"HC?>?>?  Ov{# sW ' @ r+2?39/39901S! ##!32654&##32654&&#$,5dHIvG6h{ʌn0qcSV Ise_USTIl[6R.?&/z V+4&1ze %V+4&$P&(PP&,P5 V+4^&8PB (@ r  ?3333+233301a!57'5!gRRRNR9 r r+2+01E"&'32665!)Nv,-d:7V25u  )rk@iy&CX r+01By&vX r+01Cy&JX r+018\&j!X !r+01-f&QX r+01>&LX r+01 &MX r+01B&PB&PsBl&NX r+01BR &-9y&JZX  r+01B&XR r+01BR&+'PSB8\&j!X !r+01B8\&j!X !r+019B^ r r++01a!!1^}^ rr+2+01S"&'53265!F4p%%A)>V1N Ee)fd~m\q!&6} :r+01_&&Oz V+4s&QzV+4V;u3>2@;;!544)((! r-r/2+2?+9/333333301A"&5466732672#'##"&&5467754&#"'663265sEm;2G&,$ ? Ja;0d]cZ\RQNeYvsRBbeV:#E{q7*(  a554&& g:~vagswt 8d)G`0lp:V91gsSQp%++"JWN23Kq FrS%xD\q!&J Ar+01\q+&M 8r+01\q&N :r+01 +%@''$r r /22+2+232301E"&54673265#57546632&&#"!! 5*/;axY.N#R5@;b;X"P55;IH%RRA Mf'& 0=6;mlԛoGjOW~W9PzQruOlNBh;@ |} {?323301A36632#4&#"#. #lCv:;[C2Z4.tKHIrkh;:@  |} {?3901A366773##.+3U^&K&4?h;. }{?01E#3.h;&%@ |{?332/3333301A2#4&#"#4&#"#33>32366|58OB587?Ɨ CP*Pp!vtKHIh`HI3cGV#+024.h;@  |{?32/33301A2#4&#"#3366t9<\BƗ #ytKHIrkV4.h"#@ |{?2/33333301A2#"&'##3366"32654&{{O] ơ cN?>SDAB氪5!3W(;YZbhhcccZ2fm "6J9]^3K/i@  |{?3333301E267#"&5#57733#!= ^8b^m9/? \CN='%\ #@   yr/2+2901s4667667!667665!!t aHO ,bIz& 1RL'2J{ @4)Gi51PI )I.fm!@ zr ?23+201s5!4&'&&#"566323fICC<%;tBp^:;P oU_ 8(%Wh?F!&@  ! z r+2?399?01W"&'32676654&#"5632#'#@% ?Dn%.9-V5qgb(<+-;%n  1/#]:GN &!0bXJ"-+1   yr/+2301a467667!5!M#s0G)=*J)*5n!@  zr ?+23/?01a4&'&&#"56676632!!w??C*Sܥ5j6KCu;&!@  zr ?+223?01s6676632!4&'&&#" L.WTv;=OLL6!"R2N>3mI[[d!6@ %zr yr r+2++201E"&'&&'&&5!32676654&'&&#"56632D7.Z$3./&&Q4:X% [8%F"J8'>##"nK:P=Wޓz|5')0.8lj4.+!(L2L׋bG]+!! yr+2/301S!.W+! zr/+201A4&'&&'&#"56676632 B{+O'N&#R.0h9s:0#"Dh.'6  C7B'Fa?B!8%zr r+2+201E"&'5326766766554&'&&#"56676632sH,o|A4O$ #$xE?D  A&5vBs:0 aO9 9"V0L-1( C7B'/itA[IDc "G @ yr ?+3301a!!!jk.g2! zr ?2+201s6676632%!4&'&&'&&#"K,XU{@1E(1;&"T0!E1*g>z)8f!5@%$ 4..zryr ?++2333?301s6654&'.'&&'!36676632!534&'.#"fQ  Q&(|IS.) (?/3Q*Rj0&G%,-  !C"=!0+<"?d>]22hI!  yr/+01S4&&'&&'!/ !-K,  J\!" zr ?2+201s5!6654&'&&#"56632\](%O1'a:b}((4  $J%$=$[2 L+9~p#5\!#<@ 11zr$ r+2+23301E"'&&'&&5466775>32'267>54&'&&#"xfRx&=.}^RN9Hk""tPs7!F4-W4O4 5)4)Kg@# %s$pZBCzk."F!/@ %zr/+29/3301A4&'&&#"'&&'&&54676676632M"^88a$4=0F_839C7F$AN\=1W#$sy+=$#L.5U <:6j\4/'(dALw\!J@ ())9zr r+2+29/301E"&&''532676676654&'&&'&&#"'&&'&&'&&54676632lEt#0ih2L#$ .'9 @Z$#6>0F:f,,H"$J;Np]>/T#%7/,D+j  #o75F/?\48b!T02U <&3Ok4FA))a@LxJCX  @  yr/+2901A!667665! C  <=-77)ZC({b\Bf4'7 iA @  yr/233+29901s5!!667!U2:L$9)1*  &:!c$Y8U1SI#&J'&E @  yr+233///01a445467>7!5!! b  /  .O MP# SR!EIB0+! zr/+201a4&'&&#"56632|FE7 -s|=aG==O[Va O>4iGf (@ yr/2+93301s!667667!""#!26767!#m$7!D #"# CD9_ h784#6 8*(kIUo rc<rr?77ljp=qNJt(7+G!/@  $$zr/2+23/01W"&'532655>32!4&'&#"%H'93<3#G#lƶS`m)/< II*A9.-  CI "K8(e>ZYc @Cl/7$"#f&#P) )yr+01f&$" )yr+01f&'!yK#P) 4yr+01f&'!yK$" 4yr+01\ &\K &\ &!Alfm!&!(F!&!")+1 &!=)!&!( &! * &!'*!&!* &!!+!&!B*B!&!_*G&!K*f!&!*\!&!*\!&!{*F!&!X\!&!xA &! &!z)+!&![*f &!yKG!&!"&9 yr+01!Cq^!v P!JQTL\}+M+ZNXj OH!RyR!Kj! %@  /]3/2233301A#.'5##.'5%;A"^^K`;@"^^K!.nj'RZP.nj'RZP<#R%} /301A"&54632EaaEDbbRATV@@VTAzB5#P/fX /301A4632./UMGN$.$8VAk-dX /301A56654.54632dUS<9$/$OGMTCkAV>5:Y?{P /3|01A#"&5463!6632#7/74498/851&+3H78=,2=6&:!Vo /23/301A2#&&#"##532>X-bT4 ,.*RjoNwp4l]1;4!+!$0$T  |/32/301Q"&54632"&54632(,,()++)(,,()++,'',,'',,''--&'-j ".: @ /55#))|/3323333301A"&546323"54632"&54632!"&54632'"&54632'--''--S,((--(,/%(,,o'--')++)'--')+++')+,('+R)+-''+,()),&(,+(',,&(,+'(,,('+6@  |/3333301E5!"&54632'"&54632m',.%(-,)',.%(-,gg,()),&(,+(*),('+7@ |/333301C5#5!#"&54632'"&54632l1(,,(),,)(,,(),,HggO+(',,&(,+(',,'(+U |/301C"54632S,()-.S(+-&&-  |/33301W"&54632!"&54632),,)(..(+.%(,,+()+-'&-,(*)-&'- #@  |/333201S"&546327"&54632!"&54632(--()++h),,)(..(+.%(,,+(',,&(,*()+-''++(*),'(+A% |/301G5!~ggEM~ /01C5#5!#2vMggU& /201C"54632S,()-.S(+-&',FU /201C"&54632(+,')..F+((+-&', # |/2/2/01C"&54632"&54632"&54632(+.%(,+'--'),,(,,()--,'*),'',,''--&'-+()+-'',"U /201C"54632S,()-."R)+-'&,2i /01C32dRFU /201C"54632T,()--FS(+-&',FU /201C"&54632(+,()-.F+((+-&',E|/3301C5#5!#.v\\)w\Hm{/t;u s7Tm83x;m9-:+ymjr r+2+201A#"&&5463232654&&#"j7yÍ}54&#"'>32!Hno=`RTW?p`}sr~HWWNH6`;hqywNB-@  $+ ?3?39/39901A#"&'326654&&##5326654&#"'6632}y\^Yo9>oq3`pi5Vo t'(014bE=T,3Y9NXI">R#q @   ??9/9333301a!5!3#4667# */i^/I;%H)mf7!!@ ?3?39/333301A2#"&'326654&#"'!!66hxsLL^\~A9{){7"PfƑz'( (71gPkr Bmu"1@ ))# ?3?39/3301S4>$32&&#"3>32#".2654&#"m%\+s&([-Q UzRfzߙp’R[rcdDg88Sm~۩a t͈1L-mΔyM|k{=]13dR2/ ?33?01s!!$0 bd0>@ ()18 ?2?3901E"&&54667.546632'26654&&''>54&#"dyLNAl?|~ՀDwKNXMf3Ab2?`62dM/P1eMKe1Q^zdk&)hWtONvXc%)mazb-Q68TCHZ95R/6L5GNNG2K8\d"1@ ))#  ?3?39/3301A#"&'532667##"&&546632%"326654.d%\+s&(Z.R Pz]}fzp’R[rcdEf88SF~۩` t·0M-mϓzM|j|=]13dR2)5w\JH{/Jt;:u J7T:83:x;J9-5:+:y`ur r+2+201E"&54632%2654&#"ov|ńDqhkprihO׈u   r/+22301a!4667'!;"3-[X&4c??u@ r/333+201a!5%>54&&#"'6632!?dh|7)O:YMljDiD[L-,> DA^]Sm^z@g =1-@  $+r /3+29/39901A#"&'32654&&##5326654&#"'6632Kfvo\WMxnpiNv[TTh1[fh"./1hiFX*.[DPO46MH-u @r  ?3333+2201e#!!5!3!54667#B#u3h`&'a5h9^!!@r/3+29/333301A2#"&'326654&#"'!!66dtyM[hYG4 XZ!0@((" r r+2+29/33301S46$2&&#"3>32#".2654&#&X`-d4.f9f $_vDcvޜňF ^mcb54&J~ՀEvKNY昤xKMAk?h2dJMe30jV@_6Ld1Q0.P2eNvXc%)mazb^zdk&)hWtO5R/-Q60LM1HZ)NG2K86L5GNHRu /@ ''!r /3+29/3301A#"&'532667##"&546632"326654.RXP&ڛ}W~mz6];8eN.JH$@ !r r+2+2901A'#"&54632326654&&#"^P7yČlc໯n5%XNMY&&YMNX%PfQQpoߨqq=`uDN2uEFCCuF;/G!wuHh9^IXZJFD^KNPL>HuM)ww\Hc{/wt;uu i7Tc83ux;c9-w:+uy=W /201S5!=L9  /01S473#&LWa\XV\aW(qv՚tk(Lcd99  /01A#654'3Y_^WX[aWqv-+tp9cfHo  /3333301A5#53533#עoHR /2201S5!5!HPPNjHjhHiD%@r r+233|/+223}/01s!2!4&&#!!!2665!#!NdAb aB iy?%B?yg7=3@:"63& ))0)r+22/322/3/3/901A33#467###"&'532654&'.54632&&#"ƻm C#2{7?T4SL]*u;y+#([996E_GO D~+/0W+ V+v}$&:&,73<# }-ek7(kn,\^&P R^&t_/*Hb;l(Ob=+I V 1R # : t  f  @ k  4 N d }  j /e!GL(Z;fw`Yr  ( @Lr4as#5GZl~*<O(;M ,>R   ' 9 J \ o !!!+!=!t!!"""$"6""""""""# ##1#B#T#f#x####$ $$1$C$U$g$y$$$%% %2%D%V%h%{%%%%%&=&P&b&u&&&&&&&&&''''']'o'''''''((&(8(J(V(b(t((())1)C)U)g)z))*W*i*{********+ ++'+8+C+N+`+l++++,,",4,F,Z,n,,,,---(-9-L-^-p-----.&.//./@/R/d/o/z///00,0Y00011U1a1j1w1111111112%2-252=2222222333&3^3f3n334 4Y4l44444457556%6v667:7_7g7778Y8a889%9e99::l:; ; ;2;C;T;f;y;;<<<%<8<@<<==!=3=W=_=====> >t>>>??%?-?5?=?E?M?U?????@ @M@@@A2AAAB.BwBBBC C]CCCCD1DXD`D|DDDDEEE4EfEEEF(FZFFGG0GGGGGGHHVHHHHHII!I3IEIWIiI|IIIIIIIJJ3JFNV^fnv~ƦϦئ 3 BBBB9BBmB8B89Bqq}H\q_BV\q\B\\\\# \Bjh9hhhjhJh<B1\fFa+AqpA2PE+B[GAfZIo\\FF\A:+EfGEfEfEfEf1\1\1\fFa+Aq2PE+B[Gfo\\F\A:+EfGq^P}Z Rj<5/-?VAEE)\/; T3;-+m#yDN#fmFb\)\/; T3;-+`?=-hXFHHJ=NC;!hXFN>)\/; T3;-+=LL99HHHHNZ37qq}^q\ 4 s332@ (GOOGH ` ~01ac7Y #(  OP\_?M   " & 0 3 : < D p z  !!!! !"!&!.!^""""""""+"H"`"e%ʧS6<>ADK 12bd7Y#& PQ]`>M   & 0 2 9 < D p t | !!!! !"!&!.![""""""""+"H"`"d%ʧS*8>@CF~ ZHyu`{xYM geb^Qyj h(;,us N$!WhX_HL|dHI#$t   5\78x9:yhidfkegmb@J~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSQPONMLKJIHGF( , C#Ce -, C#C -,CCe -,O+ @QX!KRXED!!Y#!@%E%EadcRXED!!YY-,CC -,KS#KQZX E`D!!Y-,KTX E`D!!Y-,KS#KQZX8!!Y-,KTX8!!Y-,CTXF+!!!!Y-,CTXG+!!!Y-,CTXH+!!!!Y-,CTXI+!!!Y-,# Pd%TX@%TXCYO+Y#b+#!#XeY-, !T`C-, !T`C-, GC bcW#bcWZX `fYH-,%%%S5#x%%` c %#bPX!`# %#bRX#!a!#! YY` c#!-,B#Q@SZX TXC`BY$QX @TXC`B$TX C`BKKRXC`BY@TXC`BY@cTXC`BY@cTXC`BY&QX@cTX@C`BY@cTXC`BY(QX@cTXC`BYYYYYYYCTX@ @@ @  CTX@   CRX@ @CRX@ @CRX@ @@ YYY@U@cUZX  YYYBBBBB-,EN+#O+ @QX!KQX%EN+`Y#KQX%E dc@SXN+`!Y!YYD-, P X#e#YpECKCQZX@O+Y#a&`+XCY#XeY#:-,%Ic#F`O+#%%I%cV `b`+% FF` ca:-,%%>> #eB #B%%?? #eB#BCTXE#E ic#b @PXgfYa c@#a#BB!!Y-, EN+D-,KQ@O+P[X EN+ D @&acaN+D!#!EN+ #DDY-,KQ@O+P[XE @ac`#!EYN+D-,#E E#a d@Q% S#@QZZ@O+TZX d#d#SX@@a ca cYYcN+`D-,-,-, C#Ce -, C#C -,%cf% b`#b-,%c `f% b`#b-,%cg% b`#b-,%cf `% b`#b-,#JN+-,#JN+-,#J#Ed%d%adCRX! dYN+#PXeY-,#J#Ed%d%adCRX! dYN+#PXeY-, %JN+;-, %JN+;-,%%g+;-,%%h+;-,%F%F`%.%%& PX!jlY+%F%F`ab #:# #:-,%G%G`%Gca%%Ic#%Jc Xb!Y&F`FF` ca-,&%%&n+ #:# #:-,# TX!%N+P `Y `` QX!! QX! fa@#a%P%%PZX %aSX!Y!YTX fae#!!!YYYN+-,%%JSX#Y%F fa &&I&&p+#ae ` fa ae-,%F PX!N+E#!Yae%;-,& b c#a ]`+% 9X]&cV`+#!  F N+#a#! IN+Y;-,] %cV`+%%&m+]%`+%%%%o+]&cV`+ RXP+%%%%%q+8R%RZX%%I%%I` @RX!RX TX%%%%I8%%%%I8YYYYY!!!!!-,] %cV`+%%%% % % %%n+8%%&m+%%&m+P+%%%q+%%%8 %%%q+`%%%e8%%` @SX!@a#@a#PX@`#@`#YY%%&8%%8 RX%%I%%I` @RX!RX%%%% % %I8%%%% % %%q+8%%%%%q+8%%8YYY!!!!!!!!-,%%%% PX!ehY+d%%%%I c% cQ%T[X!!#! c% ca S+c%%%&JPXeY& F#F& F#F#H#H #H#H #H#H##8 #8Y-,# c#c`d@cPX8 g=<;r:9O7@6^43O10+)(O(\'-&%@%\$1#"!g @\2[87[2[87[>Z1U1UYY 2 U2U YYU 2 U2U_UY YYYo 2U2UYY@@T+KRK P[%S@QZUZ[XYBKSXBYCQXYBs++++ss+s+++++++s++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Rqmkz:xHzqmzkz:q}x~Hyz 8    0   , F * ( B< >~ < " 4 N  h  t   ~    Copyright 2020 The Open Sans Project Authors (https://github.com/googlefonts/opensans)Open SansBold3.000;GOOG;OpenSans-BoldOpen Sans BoldVersion 3.000OpenSans-BoldOpen Sans is a trademark of Google and may be registered in certain jurisdictions.Monotype Imaging Inc.Monotype Design TeamDesigned by Monotype design team.http://www.google.com/get/noto/http://www.monotype.com/studioThis Font Software is licensed under the SIL Open Font License, Version 1.1. This license is available with a FAQ at: https://scripts.sil.org/OFLhttp://scripts.sil.org/OFLOpenSansRomanWeightWidthNormalItalicRoman2t  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`a  bcdefghjikmlnoqprsutvwxzy{}|~    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}NULLCRuni00A0uni00AD overscoreuni00B2uni00B3uni00B5uni00B9AmacronamacronAbreveabreveAogonekaogonek Ccircumflex ccircumflexCdotcdotDcarondcaronDcroatEmacronemacronEbreveebreve Edotaccent edotaccentEogonekeogonekEcaronecaron Gcircumflex gcircumflexGdotgdotuni0122uni0123 Hcircumflex hcircumflexHbarhbarItildeitildeImacronimacronIbreveibreveIogonekiogonekIJij Jcircumflex jcircumflexuni0136uni0137 kgreenlandicLacutelacuteuni013Buni013CLcaronlcaronLdotldotNacutenacuteuni0145uni0146Ncaronncaron napostropheEngengOmacronomacronObreveobreve Ohungarumlaut ohungarumlautRacuteracuteuni0156uni0157RcaronrcaronSacutesacute Scircumflex scircumflexuni021Auni021BTcarontcaronTbartbarUtildeutildeUmacronumacronUbreveubreveUringuring Uhungarumlaut uhungarumlautUogonekuogonek Wcircumflex wcircumflex Ycircumflex ycircumflexZacutezacute Zdotaccent zdotaccentlongs Aringacute aringacuteAEacuteaeacute Oslashacute oslashacuteuni0218uni0219tonos dieresistonos Alphatonos anoteleia EpsilontonosEtatonos Iotatonos Omicrontonos Upsilontonos OmegatonosiotadieresistonosAlphaBetaGammauni0394EpsilonZetaEtaThetaIotaKappaLambdaMuNuXiOmicronPiRhoSigmaTauUpsilonPhiChiPsiuni03A9 IotadieresisUpsilondieresis alphatonos epsilontonosetatonos iotatonosupsilondieresistonosalphabetagammadeltaepsilonzetaetathetaiotakappalambdauni03BCnuxiomicronrhouni03C2sigmatauupsilonphichipsiomega iotadieresisupsilondieresis omicrontonos upsilontonos omegatonosuni0401uni0402uni0403uni0404uni0405uni0406uni0407uni0408uni0409uni040Auni040Buni040Cuni040Euni040Funi0410uni0411uni0412uni0413uni0414uni0415uni0416uni0417uni0418uni0419uni041Auni041Buni041Cuni041Duni041Euni041Funi0420uni0421uni0422uni0423uni0424uni0425uni0426uni0427uni0428uni0429uni042Auni042Buni042Cuni042Duni042Euni042Funi0430uni0431uni0432uni0433uni0434uni0435uni0436uni0437uni0438uni0439uni043Auni043Buni043Cuni043Duni043Euni043Funi0440uni0441uni0442uni0443uni0444uni0445uni0446uni0447uni0448uni0449uni044Auni044Buni044Cuni044Duni044Euni044Funi0451uni0452uni0453uni0454uni0455uni0456uni0457uni0458uni0459uni045Auni045Buni045Cuni045Euni045Funi0490uni0491WgravewgraveWacutewacute Wdieresis wdieresisYgraveygraveuni2015 underscoredbl quotereversedminutesecond exclamdbluni207F afii08941pesetaEurouni2105uni2113uni2116uni2126 estimated oneeighth threeeighths fiveeighths seveneighthsuni2206 cyrillicbrevecaroncommaaccentuni0326commaaccentrotateuni2074uni2075uni2077uni2078uni2000uni2001uni2002uni2003uni2004uni2005uni2006uni2007uni2008uni2009uni200Auni200BuniFEFFuniFFFCuniFFFDuni01F0uni02BCuni03D1uni03D2uni03D6uni1E3Euni1E3Funi1E00uni1E01uni02F3OhornohornUhornuhornhookuni0400uni040Duni0450uni045Duni0460uni0461uni0462uni0463uni0464uni0465uni0466uni0467uni0468uni0469uni046Auni046Buni046Cuni046Duni046Euni046Funi0470uni0471uni0472uni0473uni0474uni0475uni0476uni0477uni0478uni0479uni047Auni047Buni047Cuni047Duni047Euni047Funi0480uni0481uni0482uni0488uni0489uni048Auni048Buni048Cuni048Duni048Euni048Funi0492uni0493uni0494uni0495uni0496uni0497uni0498uni0499uni049Auni049Buni049Cuni049Duni049Euni049Funi04A0uni04A1uni04A2uni04A3uni04A4uni04A5uni04A6uni04A7uni04A8uni04A9uni04AAuni04ABuni04ACuni04ADuni04AEuni04AFuni04B0uni04B1uni04B2uni04B3uni04B4uni04B5uni04B6uni04B7uni04B8uni04B9uni04BAuni04BBuni04BCuni04BDuni04BEuni04BFuni04C0uni04C1uni04C2uni04C3uni04C4uni04C5uni04C6uni04C7uni04C8uni04C9uni04CAuni04CBuni04CCuni04CDuni04CEuni04CFuni04D0uni04D1uni04D2uni04D3uni04D4uni04D5uni04D6uni04D7uni04D8uni04D9uni04DAuni04DBuni04DCuni04DDuni04DEuni04DFuni04E0uni04E1uni04E2uni04E3uni04E4uni04E5uni04E6uni04E7uni04E8uni04E9uni04EAuni04EBuni04ECuni04EDuni04EEuni04EFuni04F0uni04F1uni04F2uni04F3uni04F4uni04F5uni04F6uni04F7uni04F8uni04F9uni04FAuni04FBuni04FCuni04FDuni04FEuni04FFuni0500uni0501uni0502uni0503uni0504uni0505uni0506uni0507uni0508uni0509uni050Auni050Buni050Cuni050Duni050Euni050Funi0510uni0511uni0512uni0513uni1EA0uni1EA1uni1EA2uni1EA3uni1EA4uni1EA5uni1EA6uni1EA7uni1EA8uni1EA9uni1EAAuni1EABuni1EACuni1EADuni1EAEuni1EAFuni1EB0uni1EB1uni1EB2uni1EB3uni1EB4uni1EB5uni1EB6uni1EB7uni1EB8uni1EB9uni1EBAuni1EBBuni1EBCuni1EBDuni1EBEuni1EBFuni1EC0uni1EC1uni1EC2uni1EC3uni1EC4uni1EC5uni1EC6uni1EC7uni1EC8uni1EC9uni1ECAuni1ECBuni1ECCuni1ECDuni1ECEuni1ECFuni1ED0uni1ED1uni1ED2uni1ED3uni1ED4uni1ED5uni1ED6uni1ED7uni1ED8uni1ED9uni1EDAuni1EDBuni1EDCuni1EDDuni1EDEuni1EDFuni1EE0uni1EE1uni1EE2uni1EE3uni1EE4uni1EE5uni1EE6uni1EE7uni1EE8uni1EE9uni1EEAuni1EEBuni1EECuni1EEDuni1EEEuni1EEFuni1EF0uni1EF1uni1EF4uni1EF5uni1EF6uni1EF7uni1EF8uni1EF9uni20ABcircumflexacutecombcircumflexgravecombcircumflexhookcombcircumflextildecombbreveacutecombbrevegravecomb brevehookcombbrevetildecombcyrillichookleftcyrillicbighookUCuni0162uni0163uni01EAuni01EBuni01ECuni01EDuni0259 hookabovecombuni1F4Duni1FDEuni2070uni2076uni2079uni03B9030803040300uni03B9030803040301uni03B9030803060300uni03B9030803060301uni03C5030803040300uni03C5030803040301uni03C5030803060300uni03C5030803060301Eng.alt1Eng.alt2Eng.alt3uni030103060308uni030003060308uni030103040308uni030003040308cyrillic_otmarkf_ff_f_if_f_luni1E9EuniA7B3uniA7B4uni013B.loclMAHuni0145.loclMAHAogonek.loclNAVEogonek.loclNAVIogonek.loclNAVUogonek.loclNAVI.saltJ.salt Igrave.salt Iacute.saltIcircumflex.saltIdieresis.salt Itilde.salt Imacron.salt Ibreve.salt Iogonek.saltIogonek_loclNAV.saltIdotaccent.saltIJ.saltJcircumflex.salt uni1EC8.salt uni1ECA.saltIotatonos.salt Iota.saltIotadieresis.salt uni0406.salt uni0407.salt uni0408.salt uni04C0.saltuni0237uniA7B5uniAB53 uni0123.altuni013C.loclMAHuni0146.loclMAHaogonek.loclNAVeogonek.loclNAViogonek.loclNAVuogonek.loclNAVg.saltgcircumflex.salt gbreve.salt gdot.salt florin.ss03uni0431.loclSRB uni04CF.saltuni2095uni2096uni2097uni2098uni2099uni209Auni209Buni209Cuni05D0uni05D1uni05D2uni05D3uni05D4uni05D5uni05D6uni05D7uni05D8uni05D9uni05DAuni05DBuni05DCuni05DDuni05DEuni05DFuni05E0uni05E1uni05E2uni05E3uni05E4uni05E5uni05E6uni05E7uni05E8uni05E9uni05EAuniFB2AuniFB2BuniFB2CuniFB2DuniFB2EuniFB2FuniFB30uniFB31uniFB32uniFB33uniFB34uniFB35uniFB36uniFB38uniFB39uniFB3AuniFB3BuniFB3CuniFB3EuniFB40uniFB41uniFB43uniFB44uniFB46uniFB47uniFB48uniFB49uniFB4AuniFB4B gravecomb acutecombuni0302 tildecombuni0304uni0306uni0307uni0308uni030Auni030Buni030Cuni030Funi0312 dotbelowcombuni0327uni0328uni0485uni0486uni0483uni0484uni05B0uni05B1uni05B2uni05B3uni05B4uni05B5uni05B6uni05B7uni05B8uni05B9uni05BAuni05BBuni05BCuni05BDuni05C1uni05C2uni05C7 zero.dnomone.dnomtwo.dnom three.dnom four.dnom five.dnomsix.dnom seven.dnom eight.dnom nine.dnomzero.lfone.lftwo.lfthree.lffour.lffive.lfsix.lfseven.lfeight.lfnine.lf zero.numrone.numrtwo.numr three.numr four.numr five.numrsix.numr seven.numr eight.numr nine.numrzero.osfone.osftwo.osf three.osffour.osffive.osfsix.osf seven.osf eight.osfnine.osf zero.slash zero.tosfone.tosftwo.tosf three.tosf four.tosf five.tosfsix.tosf seven.tosf eight.tosf nine.tosfuni2080uni2081uni2082uni2083uni2084uni2085uni2086uni2087uni2088uni2089uni05BEuni207Duni208Duni207Euni208Euni207Auni207Cuni208Auni208Cuni2215uni20AAuni2120afii10103dotlessafii10105dotless commaaccent2iogonekdotlessuni1ECBdotless \7$=D]ll||ISTUUWXZeguw55JJMMORTWYv}~1335amsttuuvvz%oprs4\5 "%STttvv #" 8@HRmarkRmkmkZDFLTTcyrlTgrekThebrTlatnT8<@B4,V .8B48Bj!!!!!!r!x!~!5ttvv ST55ttvv%5 "%STttvv !$!*!0!6!$DJ$!&#p(P!(,V\% &b/ #|h.-n%2(Dt.z%>"\$$.0B/@/F%.&++.V.z#j1/,!B%)"&++/.2|!(  /&d /2d !1 /!+  "& (/0".1 . 4-% :(J @/"J"h F&X&^ L." R X/. ^ d j | p& v%+#.b. | " ,/.,/.,/. /.*(D ,,,,,, ,*B, , *T)"*-B.-B.-B.*r.&2^&2^&2^&j2^#1"0-1-1-1 1*1 1".".". .+. (P+.!/.!,,/.,,! !//!$%8!*&!$%8!*&!%8!&!$%8!*&!0!6++!<%8!B#v!H/:!N.!T/:!Z.!`/:!f./4!l//-6/:-B.!r!!x!!~!,.!!,L!()(!0!2^!2^!2^//!'!!&2d#p!!!.1!(,!!!!/!!(,/!!(,/!!(,/!"#|"0/ !/""#|"0""/ //&F".-.1" -"&1---1","2"8">"V"\"b"h%>"D"J"P"V"\"b"h"z$"&^"z$"&^$"n&X"t"z$"&^.".""0B"".0B.""/F"."/F"."/F"."/F"."/F"./@"//&&&&&.z+.#.z"1"""1"""1""## ###/.#",#(,(#.*T-*-1$#4&X#:'N'T#@#F#L&#R#X$$%*~#^1n/(/.#((%%#d0/4/:##j1),L#.-#p(%2#v% &/ #|##.-#%&%,%2(D#&@.0B.V.z#%D&++''####.z###,j###1n#.):########1/,j$6$N-#$$$ $1n.1$(,$$$$*$0$6$N.1$<%8$B$H&X$N)$T$Z0$`.)R$f//$l''$r$$x1n$~.$1$.$$$/:$$$%'$$$$$$$$$$$$($,@%&$/(/.++$$%%/(/4/:%*~,^,d%*%*'N(%&%,% &),L.-%&%,%2(D) %8.0B%>,@%D&++%J%P%V+ %\%b%h%n*+ %t+J++%z,@%%%%/,%%%%%&R,:%/.+*%,j%*(*/1+.%%+(.1%%-%)"&%%.b.%%%+&&%0&& && &&&+V&"(8&(*&.&4&:&@*r.&|&F&L&R(2&X&^/&d&j2^/2d&p&v&p&v&|0-1&.&&&&&*&&&&&&&&&&&&&.z+.&2d&&&&&/(&/&.*.(,/@'/+-6/:'*-B.' *'''.,'$'*'0('6'<'B'H'N'T):0*'Z'`'f'l)^'r'x.z'~'''''''''''.*.1'/'/:'/'/:''''''(((((( (&(,(2(8(>(D(J(P+\(V+h(\((b(h(n(t(z((,^(((/@(((((.1(((1(,X((/(++)(+(((((()* 0) ))"*.)).V.z)")(.V.z)")().)4):)@)F)L)R)X)^)d)j)p*+ * 0*+ ))v))|)))))*~)*))))))))))+)))))*** ****$***0/.*6,*+D+J+P+V+\+b+h+n+t+z++++++++++++++++++++++,, ,,,,",(,.,4,:,@,F,L,R,X,^,d/,j,p,v,|,/(,/,,/.,,,/.,,,/.,,,/.,,,/.,,,,,,,/.,,,/.,,,/.,,,/.,,,,,,/4-</-H,/:-.-/:- .-/:-.-/:-.-/:-$.-*/:-0.-6-<-B-H-N2^/-T.-.--Z--`1-f--l1-f--l1-r--x1-~--1------------------------/@-/--/F....,..8..,..8..,. .8.&.,.2.8.>.D.J.P.V.\.b..h.z.n..t.z...................1n.1n.1n.1n.........// //@///"/(/./4/:/@/F00/L/R/X/^/d0/d0/d0/0/j0/p0/v00/|0/|/0///00///00/000/0002p2^2p2d/0/////////0//0/0/000 0000$0*00060<0B0H0`0N0T0Z0`0f0l0r1J000x2 0~002 00000002 0000000000010111111 1&111,12181>1D1J1P1V1\1b1h1n1t1z1111111111111111111111111122 2222"2(2.242:2@2F2L2R2X2p2^2p2d2p2j2p2v;R"" ^55}+ !!!XX}R^^5^^}^^^^^^^^3^^^l3^P^u_i27Rb3;T'DbX//5?R -yo^X^/^hT$^3^/H9/^u^^{/^y^^+L/^?^Fm^^d^^^uuf  Bf/f\jj^{}^jmLyL!yh^h^+hm^m3y33m;y==999+Ty{;F{;Py9w;9;P9B;;By^^/{+^;^?;y!?%Fy!R;;Ryf+ y!\m\y!Jjy!%;;TXJ\BJJ`%%)\^^^J^PF^Fw^{yyNJ^w!^b^b^y^y'^^+^}^J{^^}^uh\yF%TR99yV?d^q!!VPPuu/HH}}^o1^^`^`^;7^7BBN^^^^b^u^^^`^`!^=9^H?^oTT ym!\mqy9!}y!jLy!^'))^%%^7^mm^/9d9/ZZZ^ym!HH^^HHV?owwuu^=h^h V^o9^9V^o3^V^ RV3oL^LV^oV+^+o77V^oFDFFVD^Do?  ^ ZZV^o ooV^oV^o%%V^oj?\j^h^?F\F^\\9T^TLL\L/\/V/{V  H\HyH!\??V^o\ff==^)^)Ph{^{V^o##^--^33^^9FF^)jjJjyj!jXjojjRj+jRh^hf^h^hJ^ho^hymR^!^R9=R/{/{/J{/o1{/y1R{!{RNy!NNfNNNR^RRRy ! f  R ^ RRH^HfHRRL/{^/1{{\^^JJ  RBBRhm^{yfmRR\j^j^^^9=^^^!+`1^_B_R_R_#+_/_/>7'7 j_j(8__0_ _(_(_'_'C_`_._.L*_0"__!_1_110'___{_{|0&__Y__x_xyM_8_880s_s__{__\__zT_0_BFB9^BR'ufT\bRRod?}jj z*DFLT2cyrl>grek6hebr:latnN'\dLllt|V` $,4<D aaltccmpccmpccmpccmpccmpdnomfracliga lnum&locl,locl2locl8locl>loclDloclJloclPloclVlocl\numrbonumhordnnpnumtsaltss01ss02zss03ss04subssupstnumzero0XMKD SRB dAPPHCAT IPPHMAH MOL HNAV vROM  ^b,PNLJ@>dB "    !$%& #$%     &' ;} $ ( H  HI#$l|l|4hropsVrZH@.(  jnrvz~ L         dfhw{tu78x9:yiN0123456789DEFGHIJKLM0OPQRSTUVWXOPQRSTUVWXDEFGHIJKLMegjYZ[\]^_`abk0v"0>LZh$*06<BHNTZ`flrx~`Jl|l|HIops#$&'()*+,-./AFN~DM:C/O:B(.4dnx mn_s~$2DR$D2RbdfhjlnprJ&/rtvxz|~LM55tt 34OX 09DM 09   Q  KNOPQSVW,-Yfv24defghjikrDEFGHIJKLM0O1P2Q3R4S5T6U7V8W9X0D1E2F3G4H5I6J7K8L9M{'1;PZt(2<Q[u)3=R\7*4>S]8+5?T^x,6@U_9-7AV`:.8BWay/9CXbw&0:NOY  QQ  09DMOX&J$,-2DJKLMNOPRSVW 34Y_fsv~245mn:;<=>?@ABCyOy/ILOILIOIy/yO }|{z~!!!!!!!!! 34opqLrL $(,28DHLRX,wdthwghtitaldinc/fonts/OpenSans-Bold.woff000060400000230514147177152050011747 0ustar00wOFF1LFFTM10EcGDEFxc[GPOS "L_ٶTGSUB 8,1OS/2U`ycmap YDcvt =I,fpgmZgasph#glyf"(ϣTthead664hhea!$) hmtxh~ӣ locaxOxmaxp lnameN-post'nQqprep{B̧_<w&Q xc`d`7ϟw\ @dR hv_/Jxc`aecjraf:`4 <`` dj xS7|6 xH^ǟsT82BED\(Yk̽qE? # )D,7E,RJ&٬da"El)JNFg}y=75o^=s=8y]?j\DP/ fF=Ȅw %mf@)ތH_\y͎;t>Hߓ0j`B$8#KAeɌs\XxXEt?!KY /AƇ;WA3/ٰRc"m+bv4i\ ~}%TI<`e, )z2㍖.m.FkR~_gy){fJ$LMQ*?f%9l ;piO{h(/eجe_%{H[D1kUׂŠMFU̵~5iw}`laJ8W-&mLr\egU˧8ҶM9HƢ8p<_RcqKcV㦜mcewsSǽ^93a8K8jU6 u,}Rcb9@<"΂7w ϊw"]EpIw>]I{t3fW]/̆`Q5!ZAޙE5҇i5 r'4ՇluּE[57=y6d$I h3*yY>QxVC;.UoJlǭHm,o\[KVҾ]$|a[o&}cQ1%|2`{bKv4Wdj^e\^UZi֑$A X;^m:mSl.A?}g_N}oҾ|~3K6OwAѵK4;Bߊ͋9"ٯ~e:3B>[Sexh6e&\dǚq/4Z^kIcr]z,ק76Ckr_\3<}v:FK|~vqFu\1%c/;IlnjoR MF 9 Z4cm#hQ4Ļ5\ߓb:& I؊G܀_sL2XM{_Xu3sn~164r̳UE='26mΎ2n9VW?U_!-G=R_~~ݻ}߻W9b}pRiL9V }-hbx-{'QP}Qljr1Pa@ڤc=Yp[Z?HM||xXySE7RW}٪Vѥe+?:']BM='m1'CyCI/vdƜzsX:/B~ȩwIL8=~*Ij\j;ֲYa-~5}`>v*}lK'9-(]p n8I18{xCb<8;C6c=h`tS+SsQߓrq޷E=4熊1 YP z1=_PK4hg)dJ,y)9OvGG~4o}GѬdy3<&a[4VpF|ӪuN,PdIϮu8m{fDõ0 O1:O3'\L?4~$( |R4P#V&T̂TxRE 6ۃ;c|͡W7`lIO~cۮu ~ T& x{MM"cv5o_ZQs=3^USRZw49_lj,:[\[3{g? C0TN/1v6\]]FQ!E?1Yr7%)$Y#keZߺQ)wWx{x'f$^PcT*SijRUZTSժܾ(_OL_o/403Œ4xkN1fi֣YAWpf058/0\rqvE7CⒶač;mGSdvw{<&moTRjΨ}*WAh{ۿ9hm'898[ӵOmsr:;'vRC1z'Tz.T*  CKC}>evh^4VjVUdZyVeeZV`YV5 t\߭s&1Sx-c 0tq#>8=| NM i*e<1^%5_NgYz#{I)XNf3E'x *N#b:|Yneʯ\%j6 BVRE[xZޢyw١;N#_E(/ D!b(CMxW[oR{U6v)U#!ڵ.ҮRSr/&ӋQumL oyY~ȏP3]]%9g9sn3nO:oxr7/?O?ƣ M~{ww;lkscF6kE+Z5--VGhRK5P #wk'j9;U*xmzӑN1X`VOlmF-nd3\SvNљ = /7hJ9؜xd[XA \AUX'-Ӟo#4C1nxٞҭ7a?OL?Q|ȹ*ybЍD8x'ŬԑpyON^/pf^lgA/K۲[jh™ 5&(ii,x]$dXc CB ѫYl8 i$S`;6`yl)4τbX aÞ _cU}Ӱ-' XY5t&NNy J`М0<ۧ+}`௿Xgi7qάAЦk"M<{miGb8{m5-B #teiOiBM4WsPt @;TcK'rჴ$b`a{: $N-=H!\>MȰ:CS\6:Y4̆zX]+SEQ$U.yS7MTaJũD&< iaZIRXZ}=Z:$I(u*R .*].j?~a.rT;^:.5' Ў")TT: {_ = D:IOznj7-$m áZ 3FuV.˒_ZQp Nm7ykWd2b02U1_7_}d)D!hl'R)IY7t>e iGA;W6`Ql~Gߠaf ҶN}Вn ݪxp*@.rN}(miuЇ(cB|PzMf;T>qPH]D$ Zd!d\iujz g5Zg™%>- yyލ FfV){Ow -a*z6ƪ:PTZ:î0ĺEp/mfU2b92=|^٨ae\QI;}JS?*:XG3Ō#23p)Bϛ0׊U1+Us"ފi%E:?7c*{y~'`B{S]ۼhYU}yZӹS^#@RN,KC(AT{p~sVi mU+.r4uH_c,CcD[us={@;b+&'YMKΛ2.6o]TgHNCG7lՃFV[vjt˛^ i>Ԅ=O\ń}$q%PO Rԝ| iM؏|@gpW; h,P॓.TW3K=94~k!\_I&yxmKSA{&Cx$b@ 82&QG_QZI|7J**6PT3f?%? Xeu{snmάu%ks)kc-M!CX=Ox?e7ӄ:U)B5<ϴ:j&LZx_98;8u$}dB9GGz.!H r 9\_&P(98&:f<=z ۔=Wۯ39^.Sqqq~Mh^n0oD mFĝ?<87OH Rقo[Fb0-;&c0ӘBl!PXX_/v~2Bl=Vb"RHZPRd/ px'ƩpF\;ŕbmqk8'x ^6<~M t "( MF*a%FQb8_+4KzKJ>L|)QKB$R4J"}%!d$M2l$yD^'R(OSLKP)+Rh_--͔.Q!T5uLݠ|&)h:fu´Z6EJ[ҕtJ驪# O~YNYcY(͔-m0\ch ))VOm2L, SrM[(gXpV6Kja9Y)VUPV++*+*V+6*v06Ʊl6ĶAvb8y7[Usu. s3YOiii/<ϓVRggggv2lY٪ٙJvee2}zNx\ܶ@*9O<=/9?Y2TYzVլj~ZY=R)$ yBAhzipB "H*E:Q* Ѵh^szQqvq+n{t/M^ړ$U$#Y԰j555jk25+5kRT*5I)eeˋ2L#3ɜ%z-[+Uצjkpy.Wȇx,) @1|rUq5zuNU]{zE=XZ5ʵk>+J?vUHVՠWͨK$7 77~4  77Y7m7'5pL4j@͔fVm-Iڵ)ޟ?guRRyu>Vocnnogno7PL1z~E߿}p`2 Kchc0ڌ~qŸӄh6MPӷM*  f 80͈fl3YԬo6G-Җޖ]4@ `jjԺpaƌ5##GGmm6u@h[mm11qMKEm,!U+*sjc;>Tt҆m|̦lN[k v0;*;s#11ٱرft{n!}ݾ9x!v8cαqD')q;Niqv9Csѹ悸r]WepY]ݮk5Zpv0w㦸n[6;sO?[YNb'SYߩtt˝;ӣ=ϰggm<^xVN{W>~v)Z]]̇}xUzg}ߘo[mBxۣ, }%z5jԫ, 0@&ЇC}Ѿ"A4H٠T8  2`ePj@tP0 f^3^_6 ̾z#xy3f7D C> %B㡅ط anAlP5>G#/"(#9F"D$,FE~Dvߡz7G Qk;n1yLŀX[bX"11ZzO|o}ߏ+ڸ1nxo<G7>}P|~'IhRJ'Gdr&\J$ג[ɽ,O1Rx @U86W6Dn# """"^@TDTATDKf-33ֵes]5nn h?3ysy3M-|P L]r$ TrrƱҞde;2=on9xpg5|\saJUE:0SL`J(uV v>Ac8g_G߸R n*r] "BEEE Zm0+**ܤy*r9v8'44b@iA_:_Αce^ʷ+.{~gHa:Sۺs6ԯ9L*pQB1jۨ(w5JC©;KPZf4 w 8 B: pd h/d鲸ÀInOK9;N1ay˯]մ=i!C V Wb3*R|ccʵVLp4Ug"xJq4D́b8 \bJ:˹ǔl_K"f):mąj-d]FMtÆ&DU.yptcϡ^=fؼxa{XcfkZMӪ2gqT>व3l Ɔ7o~'==vqCjU)rd!! Jod=}h}оzM)_FGljg4[6mܒ)i'Ύ:^ٞEoo|?TҜ6)]umbǤ. m\Jg[>aEm>Xkxf~Q7v,mY{BZ d.EL`^~E&6Q'h0,ck11qHdbyj@Vm8+E|}ˀbgq5$\ W(8`( ϧ $ ||dlV­1"_8pB:B* 2鵵O\ͦ9*eM2SJKRNRr~͊CS ~LS5Y$èͥUQa2nYI㔫Ӝha!4k |k41X0X-Ȍ1q\#j" -lji[M꤇gxq~vsZa>spj7V| &GM;Fd3c2՝rͪ$~BN|ΎZg[n0SӋfjqabwqyyAA5vK)1"h-(( 0i4% Y=Enh\Pqy m&xqI?o!P4LEDPfN~O[-hC`Éz T6xsdwob3n~ }LɃGmj]wf:a|({k~]vu;,C"Y *Zb kA!7y1WO~yK?W6O9 z=hÆ *l(K2N<>(?@1i+z#H2ĵp^HS xqu!Ȧ'̳q",pWbaB 'k8 F+p4N` 6ʯeˮK/ %A6~<Ϡ6+$4VlTA݂y+iLŸ,@6o/r)ј[j~2 c=u=; 0[9 !p(DtdA0B]*VT4HvY@8Zn< U+1x>,Ȏ}r=ѴkEgx.`,4gdLHW_Ք>%1gc͌[ n?JBL4kZъm|@Ԥ5mKڮq_X4I+=U v=}D'TH)iuj3G[j𔬑)!>$ K$ 5s&oa+[ 7YRh*58b\ װ;ܱ3 so+>@p_ : $rNxp T\D[x>*J Bzo}CJvLEIN#6䭨X&FEn)IcT;-HTtNrnO W=7פ:SDװPFSMhh ylӂYqN`}Zfen}4_Kl 4@u4;PG˰K\-K8Ԃ`ԟ4JO v xhAH V3xɝ=JOv8\dr &>%aH$LՉp\ O |mlw.'n%2@V {R 2!'HSK0}ǘjxz3ݲA{BRy⣩(q DNaœ fޒhn|xj~cRf*8ENG)nV6Q! =>Rk/zF?|Bt˵>͓7=4uSyz&_!h.n.}OӞ؊'ۏ?/3&UY?g{lcUiޒyn^lB,)Aꢢn5_JKԅāVL $V E L~o^h5jHw6,\ᮢ1%3_o@Oפ3x,38va7+(6#1QH#!{>ґ$B-L-4rr+QQĭӇ҂5j-Oiij#[v _U'Gy &/<-c6,wāRӢ;AolK]^Jx5":P$8)ZRBR ,4ȄxǒF ~r۶f9=<0y lϟٱf{J [Jֻ^>f)3<wȉ6՜vGX1rx^8rd'?Vivio03vL~)HhvM1J+͵٨0T'qS^;1 ]9Dtr|'`$$iOX%q1O:1w|ͯKK'͞w~{Tu1$U7zșoWa'k2f?drVڪkjC3g=l9\lG?E*g~WcᴉF9xwr6:+)C;,jkh~#0(wpr:/~y,\T0ؙm%M¤x;wE -czK .2M|4⏉`'#Jf`zj' 6;RS;Ї)x GRSta&J ւc3Ji>X\V2}ᮭ&ɼ"2^TKEBB˃(ySBv3@FYB%٨aq=GKU8Ӆ)+ZURj`gxo. ĩı3y;98+R%AqgsG_!<],^uKѼ!"[(}h(u}5[#$wJ¨^W[R`xv*]mƄ)l+oggmX\bM",˷Vvn p\p`ۀ` wd;@IT :r ĻO}1E>(y׿V犽p@{`iH8?M`+-Y;d{y9we7B]A7kH$~ ab䨏1Ԧ)8Gp^*52mX9E_0sm8;-WGI؇Vi,*q+X=Oa 19:_܄c'j^0wð?zSGXg5N\*Oٜܴ)+ɤŦƅ'9&t%-R6`P#&$"n׆#8nY%CY4{ƶڦ?2 ώn4{1:|M_zt!A:W~T ͰZ-|AxUA{c?Tv|&ȨmڒU\/{ZsT[lAs` O)Z\ H"EQOEX)c]Emt YlBw=H`"mǿ`&a 1<$䢭RD8bB6!lgcsj%qQ$2.Z:o5A!:NJiG@UĤRVZQQoldm]`>{|0yպ۳S@w!<8%Q\Ra_\@b\SEX\́^GHBӟ v6\B'JόsuEؤ6-i]U~o+rS~.aF^?-0"p郼kHe ^^uB6ԋ\a6SZ3YH;u'83ETbevV&-^ܖ\ @ rArBR$mX{+s:e:PR1rj ϫMSj/ȑ/q >sOǍnIptV=/5oeffe萑_elѦR~!­ӝ@$HF;߁K-< K)-o23ɭH'sҟ Qbb9q.V`l'NoaLJ0l. FOTZ=Ms__ŝ&E|kšض0*;a\ZNgT(*eT"wR8Wzky 5.@lhѧZx:X7gnUrcaVQuvhm>Qh}]VKdd!$$11h2EG+H~e •TqX)S>d$.1 $I $39NClLpHܵ&4"<&gάmaYΉYYYhXĚkfgLa [#1;63h#oD2eR\JbQj/BO6~m~$,<W~tFs_0ԕ>jzjΘ љ独5.¿TeQ.BdR)) ORQ)'e:` ɏj ^"wv<-_>3nX_( lno*KQ:J-"l|CUJiarju)m'ׄNuaA\C7?DcSt6WUq6:4a@8u3VƹF بwx=WA_boUL(LS5Q%AP%&z;8@]݁auu\uuL'f5=1ef=1Ǘk|s9pB$r9 8XK vs z+k{{jkL } uG($nk! Jx2?iĜ8ѹbkIm 35Gz\q6ܲ ZjI3?!:J^b6ڬ0LW)!@XR;{Z|^VW03gX&5Mܮ!dqM< bn%/m/1N0Bjتaa>}`ȔUY|n=]8diYtY @ŤZμ1A[DSHsry}[rNDn 1Z#>,BD)(|ۂc|!(B9.I2MSomg'VU7L"= y%ܑL2Q&Hq}'qr=uXe?>YfAA AS 9~^`V_82o`n%ֱ(F4fQٮCddH.&<ܨeTX6`89LG=[苼1Y@wCtRA,'EL}>L[f  kgFut9wXK{>zn(:Ԑ0ƸwܵuKONnUPe0(st >|/´j!QJD4jE[r(xʖ>@tpb5*rEe e/Lc4;!k B{#Qw"sna?Ɗdy!H^`?21H+j=ev`x:4 Kbwh*.c.SI%(&q+uW'X)z&_dMHכIgA |- WIvJoNi@'x vm<OQ (ˡ>58=>c6Qo1Qii.15Ac݉ 4*o0N-(DvgJHJvt21n4d-;'Ҽ}Y}I\nhߣ8Y t :<+M&`Lh~d?W3NKSP(c S4t+X^/ShAP$&XO%X.\)~n.?w]}xT|~k?H7A£?}bw:Zr?MHYo@7PK$FǑ1=ԁT2&1;1ɼgLoDI Z݇XN"TAsR9OQr9ϲ^ݎ]_%hte{^6ۅ~^_A>)G0\WDCj YwͦPH11r)8ӗ |+$x_qkIbr%B&No4b a%SN5CíIkaP79{ўp30_Th0&p tj뙼kG/w-CȲ+GHٷ &1m 1hY2rϘz6l.d!U(ηRKDX*! C<'EH_ Lj@bpDtɀ}aH5ǁ3iz 57G8Eᣨ|RwU^Ԋm户 z{Ze;9h60A<AR41C3#Ū.u܋VO Qq`Oi5e z<"e cXjxO=?g_xLN o O 6#9s41ϿD[} ! َEvű\,c#dF#BBJV:$$O2Rc5$%g8]΍|(Z MJ'޴򖒖1&iahz:: 7ӛWGELؼoNexM˾8xz}O&i5#=c0<_ r7^I_"4I{jD~8(Q6A@d~l'-#vnC%EzNW9>h6wBD\.$%ɤV_p^3~vq-u7bXёgr(0dG/yӧe3N &㬹MAJxhQg É##aTR ј"d"27xLCD 88g%urN4s8qF#9 ɤQ?LK/UnYB+V$u_͝oZ hnQY-gVUFXy42O\>7ymә靥SR \W5<)3EN8 .'5{xsTh-إ{sE9%u1si8+;i'e AzCI|i7{ЈOF‡p|]>&~*(<(z`2B-ƍZMAB%pu;AK£QTH. Ґ85|Ww$)ܞpO[C;w~*@ z8ٛt4Pۅ8`0g41G3 DA}!pl =o$pRP6ުh3""<^N3 ez y ;cE@E3\LF3Z7.<[=5,ྞTkf/j )]9~[Ud@NChV~?S*$\"y+RMTrHNNGNN(^8}pEB8zʇ.|.yK-a[<ףg~S:CA3pQD3KH#į'`Nr #ypFq!7G NJPDb Y5c8`3@^Bj ŚɓW_ŗ]Գo_yeڻq ̊1TW6(rr)HeV40:t { FVL_=OjJҷz誶嵇A;{s~&$!W߄hvwǕ1`M?&~XD%z%`. BxV.qM/i^ :R`SAsW+r1Iw sOꅹh#֨z0+h{kjvףPv0yzW Kb9+a#~@k"qqY<|Id:#70Uxlb_θA0 'Jy7#Xhx+tGo |Ua%q`()Az[za{w!oһ~|n&O=I5)`Xu<Dsl t)p%ELQ3ǟn滩6:Ge仅⍏}1y8DxɯyruyY|O}мȮ 11`^يd- sc}w Vl:E[d'}Ds53&^1#d/3IP3ݷ'߉[1t;;ި T,L!!*U_K}Wx*Z_)21Q1&OmIƷEt*i;>)߭Oc}ǚo3`U5Ctvk^"NNB Cukb{AfEewBV~cI^ e=>*< QnBi *5Ocw4I4{M*=۝-zme;[;Vq ᄰ)N|OLc6 bdYrxވ()qRRdjQsd? 0Lok{]W(M_}}a 2Lj;\1rwƎ*rސ{Q29yA %'4/n@zD|!bzwAVy歇$2`^W"B *\a8 b r>>8 y'b0g:8ۅ3(>XrVEgF'<Zgdb#R]zÀ8,lZ&6I]L./pN̵ kt>H"gjo">RS*7';&tUi.0㥶i#U\K+{vRG[,HJ}]oNoVߙ\5"-?/FJor8ʏ;̝6 ,: x)9SH7LMX,޾7܏ 7ڴpoN=9HjlydMT20v0szep#=TkU!lB]J<$I@x_z<&AQvGm ts,a/*T-i K;ԤwFfJEE&a;| g}; eE!Zi|f=ͅNkǶ?JyۧX>yóX( U:-QlpKWd#{=eq)2Uشהf77 Gq4k?X0iRL(nbB .9|1:Aa427cq,a iHdS 52VhWJSaMTzȈ=橍fw:;7GT-qѓsr&ƈWWw)ee`|_Z[tӁ;Q|[#9g;;?mjf/-l39:<ΰn& Ng wO|x4h'`d}D fI2K_ f Mo,{kOuk"~sTvSt-v5}2xR˿$7 ך Uxaˎ\#f/a\`-XR 8!> ߦFZЊ>;.qEJ*Yu^b*r<iVʃ5@C ܊Ocʧ:mcnj ک|bz]^Z::.*)ܿ;bPO}P|TR7뀎Lq|x}{\P<4]|94«TG'<RIKݭJD+UbIgW^,oA]ri`/?Ey3X^@ݫ^5";pGѳ^|ցmѳ,<~M8/ǽx;߳]xw}!]pO^4C2VFp gh@yVOEtۂwq. 2:EH[# 㯗5^8cް1 Ӎy.3yA偖)Uᆀ|-,ף0V a\SI;D>a5.Wm0n50:߅e_DZBϜه{`0'xo@WuKyD9  vMbr 8tD{9*!!9 ismMЊt,$2RX+}$ H%5ZQ-/:r$=mCGaHyi-mSc5=6_.R >a !8& A xWooi88oohBC~l/"NB>su㿁D$o`L|7_'kʢvɐbW"ɨdpζn׸FkLsnB2r=]s'Njl':`j-:ȥ!DgɻvLz&;}K9R WTVU=N)ߋTJ $f(bhZfAWl`mZmiS4C?w*Ľi>5Vn:]^h !8N1ˢ$H? +Gm#̃{Oy2pwWx^{E^RyV ~B5]ߣ @St;tn=AqOeyy+ }I'xxuonO9?s?R)慵Q($%M&AAj zāqrGv5t2aY|x>|\E ͱs}9l2?E~/sTe!BM!*[׈Hr#iLKtS#2L bkSn/,{uOJ`?zēܹn~ϏN}`3{;7潹{ U]5T\n*  ~؅hYɤfSFHf.E;ˡGh$! kwwʧ§'r=%t|\-m3im6p]k|qGGDDEI w%daCyODi$[|]ƒY5u_0䅱5=̬{=7dy=l<t{m;>|j:ѧ{k?r8?E H??M pt<_G<+ jș20 ';@lA,\ڟ=M+N+IB3֟C Bz"ݦTj٤#q lgK+IE4V.~VM/uӽӿ߲=`)3F/1^e5DN:bB38vA, :>*e: MKHhDws5g-)KJQ9r3x?4)>AO"}{ѵw1BxaO[ggn]2V>j];xS[ϵDGy泞ƛ݉@THiiÌi~&k |[Nb9%t}c7)&zXZtI1<τ' wOX{wmjV (j˰%Pm3ӗu3soA{&+.XQbÿkVY|ǥ!%c셻睸x}}it⬎<5;q~YJ`=b IIiM<F7[ž5زF:faʎ]|pF1Bsż_چ'g/ZQO RDgG߲&k ES+g4nY"T.vׂ›y7\[9lK[)x_2 <K fW߰?p/19.9#\hHOX5lryOsw>BK)Z5R. l1R悀-(CbTQ0#0RpٚXB:<BZ4l²J>ŝ6Ǭeiw_߄<{C=- r٫2aώ)oVDR#[0$[:-2-<<,T* *8 o""툚P1p}|-sl$ҼƠ FQ^Mz wb;|ɀȘbט_d:kJ :Ow?8GZ $c)[ZJF) ax꟣jzd@YۊhWCl$9VkIWoSuN9}0s슢-1$GK7{u^wGMҮ=f֎nA3wP[f6{/`vy{ymX yI{L*lH?1 ~ŚOᇡg';"|)KT7,F1VTzR#E#;' بϸ7I4ǽN4]9EuoY2ǪD+Z5B+jv:lr)Jm)sD@O{/wEyK͌95 ͹}͟u{cϒNк 3|Ϯu:Af7X3`i_6rIg3%6Oq~ ") s{Y[B4p"+v=_ҧnl| GC>k0R)F @#dSI<=`B ܕ 79(2vBيџyi~~Lqk*vc-70*f;un3mwܑ5>={Ib\ >TTx;$Pȑ1 Mtg_U4]sf#dL&I2I\$Bb5 9P@d]DdYd\wQQEeuOYWA?EE4~͑w/L^ё(Y!cwr!e 0,xءwOoWOGyM i%wO|+=˾3TbIF߇ T#y^5 G-XIM+L-xBȤ$e3<< /??=۪l{ZIC~wm.dzyu9!өb}jUJ\U%E-L <-%sBW)gWҽsC#3UQ1lD WhI.vv{e'>1c]׻zh^pKMZvN75ra :}D؞$=c gV:P=QB.%[(عR,XOF<\Ngl8BGK)˴s2.EN1UMeTbb\e<ljtW"v +zΑ`v[b2꺗$.w 7VQf0t=II<c?nL:m=C[|,;M9dD+ײ烻/kn>7rgueLݤ8ٖ6[>~ʟU̺wM|t?r {FУWe|X<!Ȧ[ }:ر\8H1B~qó2(:jBEe9.e9%Q3b݊r{2s֊Ȝ"+*~HD_)oA޻۵yFO/ <|kפW5; wp}2;)rW@ oDROCw^":$?pN\- 1(0o֐l2ڐN_deqi?@x[N\rnYbdqc 3 Kd-6aλW_cR+Bڗ¿AsS/}O-}kh:;=d cG(co){  bw0}䁏AnzNy3RDgA L؈hA0:#S-X? U]dt/& Z\ ˦K5w&9( k [{)SP!Hd3I~ѿ}P_7"}y'Reg.!5Kx Sm߬g Frd%Y  ~6} o)PaV@Q>9Gj.N͠\B/ hBA+"ӯK70ߔ"e?26a|FU"Sʅ. )`:aO<{篛:+~}ō˟:1jZ[F>y'^Nqʛo=97% i3&]Ko)9nh޹w$.V FRx!&8I]I|'p <8X""Rr^ڮe[oѯ]1^{s_pm}Lćš;ب5UA˔ 8 KΪA ?Bp[#^a!q k$!([N=X)#οϙQHURn{dK6-2zL C!DO#=</4$c#ywe->&KyP ]GǪ!Zs?m>5KJ>ako0UEU 5CwB]*LTvz /<#躟$ewB⢥@GᾜTkX1uNHFwWe{] [Dce"9理{Kٗ*2,lO;˾~mko+"4w +"4xڰ B珿'PC BM0뭈43@;n\>= o-SvUb WTa(+R5%u2-&4G> g;6>ZsߝL7Y؀-tp/S <"PK§QO3nYqcs(ZVlp@G][?}j·:M)d%LNjTƐ)>|g2`] &uCȾ}<;+`VMFz{B%& P$QոߜWv?=@A>O w mǀо8Po2#8sYk'.(_3mbR_4u_MY" ?Ȫs%\py~rNRwJurS!6ϣmtiJvV%L9Fn[w Kx79rd={j6SҌ ȑtUpJGaPuCbz;FBl<30CR}n]y-NK͞e?uKμa~ Z'ɕAA %\i9]o<Ю;;´V =鳆% +Y,Jebypd%ΉO!ޜ_]a/q\2}4$n܏Ͳ1EKi 8 10\[ #\`8r7I5x7oB$l]8dx"V)'=x5'qVA/zN^b~ Jbο~^>rPruat?܆]?<_;"Q,u߮_<]싇p ޯ%)Xx%I//5LzېC[`-G!XޕZU*2+o!/8R]Ѷk>'$jkH>^Mxy\U b{W 8ZbJ3n k [ 2b|j$]@`z%!01𛟿 TpޝJbPEhx^oe6t,o@Dxݗ?yoHS͎=ڐWCI{2x0{Y"( 8[:c;O?eok0i`Ѕi(%;@-ػz;7 _]?86zO;a~J tCkU_ :j5dTX,r6.p`^lgoCnjc_k@ҿ)Șvj4(*W3b~5tǐU& -G9JdE\1$_Mm|d%˪bp3{[YО\Hw#}7c Ft)p"_yĴ@r;/g>=v~AkWT߃omB7zORBw¹k2J q/ʠ%HlPm`۹ř|;Ю9z螮Pm *?~&й*"BkҡӈJ D =JI2J  5:l@k!] ^Hd/6cRS٠F9y&R 9(0ʚayp.{86 S`-uvå (]b8břL6U%\F7IJ:a!f֘clr:~IۣKG*Ӷ<¤A%V5>7b40lbjCMi{Al;,</{b+ `iO]; =gwYu=ccf"S!D׆UCR wqQT yAS|N۴v2 wMr7є¿7/@}A x*qLd]o:3IאȊA *"K'i IjbuL`8`(}:5g#~̎LPc%L_u`iOܧ.~7rXf؇$kNS¬a(iLKN@?]Hu(׬܂ÿZv ]4/t;ڼaJ O>)AZZȕjZ; bUۑnwV-Jdh)˔AǗK2H03`PuϞ| ظ^h_W[ّŃ]V:mĸ'j0,'OζJc^VF·xW:*AiWH`Pj81`C~ps<6.٥rB^1so՗cno9F?N_ߩ 4S.v7MGrɻ@K OLv%bL[G.#}TXmzMZZc"(9U.uϒG(Hc(G"Q 'AՏ8@v2H,'8*"i&h Rh4/bIHHub=> ^vux^r텗Jwgj'% ;Ҫzuq<ңUH/R$MDtX'j ./gr0GeL>>nNmݻ;˭93n{Uap#}Mczl1,&GU &ۄ&~Iz0ci::g JG‘F8r+~TQs8x=1өѵJ'iYs&fnX wvy"^7> lDC':3WāDh;"]PXb$Gh_@s 4] wqq33 l+\ϥ"&8Kh&ڐ4È j"6\ DPky>wBx_ae{wT;UZaOuQR+1c腷!;XH M| D#oq*XjfE(sl])yC/ۼ#wƗ7/5i'}ݯG>/Y\y9bi#%2UII{H͸_-xi3KU {^xя99*JFd> /U!Hڝ!+;LY9{ȟ^j=r5-;,)F ѴV)+e'7B)0wwçbs%pؕweeO)4b߂I9I5#Shy(5F=NF캋  Z""Fܛh4' <ǀ&1U<6=_HVfe-mהI1 qGbwsQ$f/1S6 <>?BpOjBj 2&r 7UvMKyr PM} /IE<<["m3 I¬]RMSW??{k׀W@ھ^R}uelh@Q2/_hc\T' /3LlGblb"CE+|VMcl,޺tgbMh/(* eð-%{Nի쌡&?.{N7,U*k7 ɬ5O\^\reaq<|i6v<Xn.,+SRloOI.WmwzW_cHX+!.Τ|L,^qB3I'Ks9PJ-8üw(j _UY O՗jꛍэtc_o).΋c?x5okƛ3 3/Yq4Iw=#Ey| eA,Y?Uk`|#k8#EٌoFmUUeuueeB8[xŜ\+Ep"CZ8\"´XĢ@ ɱ )vXHT?ӕ^8~S2`D큒.:c΂_ވaCk5o`5*pdSVL2һMqWw-iCtܪM*keIEe#ˌ>G˭{OptH<&`[e6l"7>RWULѴս'X(9I^$؝+1phh*YGϑrlߩmUḇU΀_@}8l1zم͙_4sv? |9eF7"miJ=-(1g#+8ܼqRr̶J`V'^^$M`Ր+Rpg"|7c^=F|вH,*!)@hx! [7nI4,w|+d8ாppA;HǚNXVkpUenW]P ۓ@`޽ o-X.&}듛o0}u贜_DF-V7z%DzJ:N_I4@hj󭁾c^] >р_T?77.@.2)*bQ=AbWy?ggq5Z!ѷX| al+Ds8 UΕHQz9|OA@Q=F_MIQ Su#S{qи cqy,ڗ,G ͖-nux|UͰMi- OhJE"eU ޺_7F>@Q]Ƙ(cB&(}F64. ˁ{_*pJ\\jJ6m6|~Kn^FmU#"m$q4x~J4e|fo$d2-`fjRK5?P*O w~;[{Z:xߛݼR^23u'q/hSF}u rw35 KZrX^+_do ;{-<H+4"ևtx)\v$:f-I^<2K{pvΎa:{$!iH٣lI=Ŕ/`K 6ᦚ=+=2r MFָO۠2S93>{~%$_L{<]1P#ĻVRߖYY t'X@wNgm :  Vr!/[ XW.-쟊-1- q~r 4 bJ!uGrkH16JrY p$/=}\߁4:* * i^')y:', )5WɤexhH5W t{ߚᵐqP(XN.8T0[ 2+!cwQ ?F $ ˡiJzjZ6FK.F4?MO>zA_4@+2EssA p,k)<(ўFԼTxW)"#EY8Wƒ`9 /}_"Q[*.p/ ۏȱ EHH#Q =yH ¤i|;瓹 9,njS^G-p:ιiN$< $=8F6/p÷d*:p'sgs@m?ϒnF2 T x}%= H3R#Pʟ+lVl6 i+ ؀pK+9UA Rah-=N(]+[@yrW~7GnZZ<=UU#w@6;=+M"^tzIQj < GnA

Kx-/=E/SnV8h<.t3!~_mM4z!?,=xP3玴<^<97j 7jP3dPQ!+rgsڃcc#Q/RSO/\b`<`6q\4 o^4|ڭ3KY9}xOIjZ~:;4+]!utZDGUDiAS) B逆gWP]j= d0FG ,Kfo?]'< <{C$ޫ-z1D̫L8!pk6JE8 # +AQXgX+Dc:xm~5qd/.[ӵh| 䫐0e2VѽOau7Ut5o|-%[h(>Z襔CġnA7vl9bX `@D>r\";ddA Ax5`+} xl9bǐ1c &]v@onl2z :~r! VE ^L 78:;vg,C"az1NOx^A;3?aprY%`]@V &Bz$rz33 p:u9{>L)p8{vVA|DjB;'0!0,\~K B=Q9y:ɜ"Ĺ 4Bυȋh{%ѣϚI͉gmFcQF"pڙP['x@{ ll=Cٶt+`2haa&\eI_C2_|t=KtibdkXـk)GDFDhR%0,]yԄ܄ǮAݬÀą5n ck 9ɧD6Fo5ax /!eV9  +PTXPZ#qTsJk t| H- f:@,$T)b]$4.d(Y:D# ݘ-<Dz~*KA|s>yº˰O!A:И]RkF ֎4J,kҕII/P]rӛh|KOulmn7^VʿLr|=qv92ҾdJ@iBsU[ryiS YٔšDn].e>cz! Ǵ{JBiCp@wmnjkCnV˒vcAoޏ/ZjWʴoOstsȪi~'fʈ)\.;.ó =uv:%q\R\2̔ަeփ , .ijק+_9YK/Ҳm3^ts)w5cLrȍP47=EK چ%24?]8݄(]ʗ.yJ =c=h@+}g$,}r挧VZղg懧kl(P9P]1ԕvnmu{jH@Bst^hR2jj!P<2g9 f虴w,s]/k9>KÃ`stҋ(`B" xJv{ ni]=$lou]Ztqq:TTƇ[ĵq 췑#@@J G CLtX$Yqe dUxҐF8QS)bS[ܲ*{0Fj \e26ѨqA*9ؙw l^vx@:w uq=lp?4їB!%SBٰﭴd}⚲!BHmt ϒ}ljc}1J)v'7BP8!D*%r΃@V%gL{rp"zYBF/wRbdw,Z+ |pfpxZ2L.=/< j,pA}K[=ȼMhw*LrP^4VbE+22JG>^l5^q:x ^z;i't|E弡w,iI6iƴO&)eM}{;k J'0/^*BM}q dFۙ, 4p+=9Z;gffdC =Ep^'9߁*OOLu.V6;}d1#Ը ›ט^Hyi,urZZrǓ"74}N'G3ykmAk9*Bf77wXv|EC z&;a!!hl<>RrׅPs_'ރ~%=)h)iIid4Ǎm(摇TdU*u:vE uC]0;-Õ"v44uOrj xh<6]k4&F2h@[L.=q ZгdF?aͻӦ-~NwO[{ЙJ QmS3=II[C Q<6!vOF|&ٓt˓!s+3KOGF"9C`*DpR(o3&@Rvz?h,aH\nmFG4Mdw4mYFQ+Fř{6EQ\/'!˟pHOrUT wA /Mpjt'͝Uy?cnQuH; <¡Xow< JK[K ܘLǥ_`#L'P-;>fTl΁PSB[عR%T!HB sUmJVVZK\{-EMQs[&JJ7 ]c]EUE%aJ. مBw2pьI rz'doEWbqEfΟֵ6tUȁZ&:' lI!`LHl&⋞W%8O☃QeQi/`!Ֆ4.&:E/Ը9}#G3Qde>LSR!i~Y\^Y:oOr%MMΌo4ZU8=4gFu ':QKa[} zfR;3J8g;"I)2\[I"NtG8&mӕqW>TT;:|k~F{bv&%ܑSGnj/\U u efK3h12T:;e+u (xgor2<, 9/nzz½l8N y}T^GZ*2Ǚb&)4xJ}LaY&H,>yɂӘ^ Ö{q I! >L&3nM1j`Y2?fha2'ѸHD^yh`l=>"M`B㖏i/դ]141ƚTi%# TM]4 ;h&7kjGQ¸!OߗT1 }3w]C;w'=WdR˛"='g,7LrXTȠ?= Y߸ɵK,HKkbGiY~"sh'Z8KqR˜!X:oUzJQg8 QWAc;W2hȈZӊS!JQj-$MpE1S`Q9V>hHJ^Q;z]=Eo^\;iff &U i麈Gehr D$~)eJṫZ/}|N.([,u)[6kV/=tp#ZVŚW=ZwaO#z$ N| ȉ\w yJ :\o$\E]+s*J+S]Ms1&^&^.K_Qx:%f$ᴷ+99ǺjOW. :wW*DG/B\F#W|J8 (+2: &GG%YsbKTMUAvae~tU fu&,)MtgXuV^}K~=Wgv'us-~uOqTt2 S{/ȕsY&23b]!34=>ʙ|U;0=ʞGˆTMMK%$7\7aow4qJR휛[-) k!Y-QHFD,%Ikgʩ7%ͤ s#E _j2Rѡ"pNEʯ""JJAz~~ʦJ*>_<M}$ǝϩf"]eHJ-E1 Tt+J F2YdBg "P S2eQ 5GD$٬E@];0q\aZgR;iD|wX X:m11Z:bD^d"0vҢi}_]omVLHuƎQMN͎" \R0(˴=>`& j澢j%?>}ɇ/%3uQ. yTllc1?w͏Jh20=,X"UafD Ձ;/8? -x Ndd/g 5yVmɹ\b,ۡw'ix4TqK u%C|!=UXdO%p˄_ A>]n'r!2EHBL -tp=u"2&ybfLbɾs4 ϻ<FHORl2wJkxa2^atP=ݯ)+)}3<=xиȸbG汛IH<_cW "!-_~үx?G PBv iBȉ,y9O="\"|S=o'֑tBx=xOƐU4~sj Zϐ]'U̇tNɨ*@"S&cV FHo$@Ĝ}@f(>҂e%\20$ΙcӏT _ 8L\Cׁ}'m6xڠm4te 8 coI.TR-=;H>uMw> ^ۀZE,Ϡs8eN{UZgQe%BN ({#{~S?ˮ{FezFxX[\)u^JYeR#eVx ќ -%.G9*w؁_. ~^D7|2ZSFQ⬃S࡙=Exh_ w|>x^mP(4*Y)H` _]){A90A{Vx02Hd2ڏl>gct:6#z?8!?23A@&~ /NCݤ@#(* ,M8}J,^,bW#l‘)Y۠f, ` u1 {82?wFA7޴VB @CŚUk*+T\Srm꘷yȐ5:a;A#)%b`B9(UN% ҆e+BA -G+(ԟ]V;uD,7=%wџ@k8q׺_MMNNM}n֯Ëz^9ڛ]IIyҭ[.l+:WX~p}/nzz?$9e a XQ;(d kQze"{?¬v?XQh>u9,@ I R 52=0^<"Z>Y cE Fo w9@ f{pd9HjKРCm;!+q}N[q>j.x@dEZQ.Ƿ~[:@X) H7Y`/\Ts gV^}ǽ+W=n맼m4oH 2'd !&E$_,bfJjp7jyϸ_&^Fra"Xd6R8NQB1oM6b9HaD!y5XܡjUXQv-")0ۙ kRZl=0onԨڎ GdUNQ˒CRvkh27+ h.B)+\afS[nFa:O fo!M4SϜt9|2?2c22%O{䍞aC2 #RMIhJaGL+˱OCL`qVa0@ŋ.^mW7}ͦx\"zFuHE+ {jw7?ڴMd+sRJȑF1LEk4ŠS{ƍ:qv?? $|<"vT3iЂՏ7c1o!HڵX<)-0Pz2dZTb(w\4fs d?~ڙ[Wx`y 5|9XZ>0&M_W"Fc6,Z 8nG-r`/\ Sv oVڝ-^ҏໍf %!.yaVv/?3 ; `Oza|#)H;`K-WF,Fة Xow v2$K<6(-K~P>< w'@8QtV s|GR1`6uJ^{tB ~E 2ih( C`Cݜ.%{$ά6`-I2=b4ѿG R~[鑁@gظ'O7466 sox쓢4(.+0whȶ K&4)+hG:w)Wﱅ'Nrŏ͊7ޞm@el81/B5! q) 19e)%uD͕ >ht !0 hdŋ>a٬ X@?PO3%PZka9瑎D:S/ML):/ Q0)uz[zS"FipK&>V7}bo,>p ӞSXc7ݶem++&`*I' T&'i,? LNĸ"4lW4Kj?1:E"$sDKC(؀PO.W5$zאdMe+HzNg\>p]9 So :T1UUʿ=Żyξo𞇽ga91AH>|<Ξ?doQB=6n-sVqSҰd&SR2j45t8[jTe' 3&_ίT?0AXN~{ >L|0ђ: Π y\2?+8z߀m"_IǨ̘y{xveGr}ц[SMv)H>Yy"}%#GV{/Nɮ_]ѧ,ƨ#*i@z,c -u =Pgl7܁fPFˇhpãGfR Jּ9+<ޙ|EF[{jQ+̖5鯬bN['->1k3~\3̐ꪍ'cVr&LCz}=93Yߌs`_^! O/񙒕wVsZ+s/Cg/Z">ۄBޤKV.gn]gNmns"&IO8 ._G[!=:bf/ c,A4Q:46'gP4>ݻUv fXf2f*޾]V+I 60LB` -0Z\dvxvTU4FXD[=~~{M5Olmg F”aY1YC ǎО55}G)XVYJ^# 9Ad  _|BΎqVɚi) NǪ2:2s*^Ȃ!᝴Q@ZmA'H/<3P]O k/k߻%d:p]$9!'Pek <<# ӛJiuse_xyloQQ6u?>׳G-sȯ=1&)DP Gzܙh=ôG`d>΅cr.6yx xs\!)ipm,:衳;Fœ(QChF}-*_گi{N7vm,  nIDpÅXx/*ıWSq.ƌ#"< =#B&M+F#2$BB<1]C%o~SSD{x?YYO&p1&! \D&p1\ED;be.!]>AC|.\![N b%OЏDّ+ 8(aм\؟wHQT-Zrt$ތ4Qtr̡\T(j2F-VSn&&(t3==2h="`6Ĥ+:ր_r|ux>s:~_9tGzt/hy/z]43P1GZNu_J[<ԋm?Gxa +QX/@ sڒ[?]V`S"68Hi;yA`;z wmmw_E1wsZ[~Dp[ w Pmؿã]]͘QWrhTP?FS\=4DED~ߕ5lG|MZudCh/M>91oBdKp,W͠Y!.]x"1z*Eڇ4OC-(K%skt( 5jTVHN7o,==?VPl[vIz޼zUZG0)*?6!"3WM9}Ė9؋ƭTDYOH-vOg^##jT 'MV1 %ľc|CfP`?o3~If.28n֜DFļ(h8"4 Bf7lﭩ4g$DE6n~:I_*Sw7}I%ɭTΤ XRHr 93OAh3 afd438}i*QD*&=)͒eE&it\.# BhX]#PJXc*s˂?**w%ov]{Ib/MzP8a+ks@R ֓J:JqH#1d1HܲU;T>cCGjyaN&0sɘiUN'Sz0>a uBLKRi /Τ " gP@@yr"{63Xf4`m٨` V6WH޶mcS[@R[o0 o8< ':hj@ۨ=m6߷UEm<5l {IfHJv=%> !1wN(Mc_nlSֿ<1Vr?:#TXYEQz&znѳ*~-X.Q^ ){ߚ]R>L q?G2PW+?F#KCwo-EDSb U*08AE93-sHE78y4,u\vmdEI$^Щ:({0OrF|_m:V%!Į}?zZ!=aN^Ss -^^E M>@[THmNJ" @mQ2XWZHYy! 3D/UR\ V*U%9!LXXbştFMVN{fjƑug\$'I,8Y ֓ݓvp. jHO=5 |B<1LM'XQF&@[6~<@'e??`;G_y#gj,h$#wt=55}5B^⋤U~y5*A|Ĥ1v3cpJ#֖ u[1&!ު+ix%4:Чbj=ihӏvh /=|dy'D<#IމHJ1T"=W.\[\Fl3GF+0.w}dž2?$—p4 yL~_hc}'eCw/3j£ 1yOD1m~}CchGİYY^maLX_{{ #܃/(蹠Cknc2ڢ$1b'9%~R#uMֵaދpJbGM/hq@9Ǡv9tv $МHy{6)@/;qVȎ+F;y͇5o΁D̈wul(nYo/Mp"OzB_JӚIO{T]ݕ >QS؀icv6/z*nwwVDW<5):&|ޖ0 r7OTP;ZF]>R'= WI\;OP\?&oIn 1);VG4$3:!^={Ͱ= uLV<؊ Slo4jmc//* Q@V.(!!Tޮ,Tڭ^IGfzfXb{`Ԩ7{=DHP6l?+ut٩c|ftk dJc!әQ#ۻܲZW :؁?ǝgJİQ1J=D.XM|Xm'#j@dʬMVch=%R]-@g!5Yj陃)dVK&OOԞH4פ?Ná挋IJ)+1Ol}aH+vDk[ 5kFYʄl5v@ӑxs8Fa2@TJ2`#i{cM&l?oj36u`K͜, ,)y9_Cm%3ƮE[td fW>D ^W q /?~?PJ q "̆`q; ro^z оoBEb|8NA9K,SC^$zaI˄m^={<]9h%5 *n`@(=EzZi| bff.y˺W~wƘN1b|4éS `C7{y)*qM4TʙvT W#ܵCBʋB_}\JD˴pZf0Vaۃ@pWL ;lRJ ySjj}յwk}:wʑ`EѾsEرeLi94o?X~qBg`Р yʕs X8xqNܒϏo[hۼ [Sؕu_~ O o!ȴqeQkz!<1!sTf`IĠ%K80zI6vw(&w"7& xC<$5# Lp f^~S[w8[QqnŐmO;/ˤMQ\[ L^==@^W%*/`?BF*!p0ch]}x!+ }5e@vMLhD2ziͪcK{4tzVH(غ˯M"?1"S{]2bOז,oRƎxgDseCñ}fȱ'm)r }Na716g*NAv LelZ_.ˁu);Xwz'e)bg/T2۵V ]T^eܚvhv id؛FتS(:R_ҦfƷ<2v[ԥIU[ -Lހ{y%3Cy`X%4g@?8c|C Sœ6!NRtRo~O&f'iW2-H`T38l;ofZfmѢ {ꙋ={ g:D+ɧ\&f.GcHӆ@I=quBB4V CB c 2 X3>hjY_=k3^yÙC* ЉIC4jWke<lt?`ݯJuU(~P3Xe`moygɶyfsxrjWOЩltx;cKm1l\VWe|:$U2X4j .mCs'VĢ|.t򧙵-Q`Ci (4o NO=eJej:#!8љ~ϵy2H|P7m5ǖ1eڒ56.ʤ7aEÉ~,.@Rٰ@5"#k.M`?A`M&.``B wSD; 7ߝԔrYpwy7Ɔiy , ~J i؛[7O|?Yf"U^Lx8? E<${81w=Թ+i jG=NG2*ZlO<ԢƉEub pWn]-._5b,n7 1͑2sL䌯+RG$Wۧg+½cH bD* x@8L 4&h-"AGI >mfarYO3iXtm*s_ԐR].~m|҇c?}9^uiƤid_liSј!#DI*Bf mXzX@vX%lzvW{9q#ƎQ9.E-!v!0o3+sۮ*H!0 S%XKI";zF{>ؘMdD:d[?]_|6r5{}o|4ߴ۔SpN^/|_ >|-$*Wh|5{jdw ρ~ |}')e xTAoU4i*BA/5NʅUJ[9dDw_/]=X3gν37ķNW~ٙo͛" />B`Wp>RM ^wk C߬N7 ޠIWN&-z" xp@U+<ܠV/I ^O׀|^WA;/ߥgoߣ?ߧOo6ޢ/N9YєJ2р<)ڧA:z K'luDcJl(“G1>4dœQ :r+>xMK o@H4.zYKxu4[:3~(3~0FY/l]da`ޛǣ+^g%X ?t +Ij{Ê"ݭnKd9TΑZu-{0{aqO1+,H;Slb,-f9r:%,Я/Q%XzOpƅDb8ø|: UqaЍĻ@$;n"#xa1߱]bJ85^ 22 M%5+ל˦u:\U):;]gscH7RBd~K;ڗ&[qy#yƨt`b0(rp.R4@K1ԩU&hCaTcLvdnX^*&[nױ>k k`uIiFޅ-^/w.zZo$z^(KEGT2]@ڛSF紈bڇ}6@:-C0>#(>cUz^7Mzޥ>D>OST>O3L>s\>|!_%|)_Ɨ? | _|7| ʷ|w|??ʏ?O ?o~_e~_s5~7-~w=~?#?O3/+o?_#?/+ƿUDH4J f.#EF(-cd,#r +J"j!kZ#zl Fl"f-UB8JTbl)[ֲl+%#Yx m2QvIL)2Uvi2]fH,3eUfn!{lK2G:S %#E+$R̗*}/5Y e,%+r(r*r)Gr+r('r*r)gr+@.bD.r\!WU/Zk:^n&Yn[6];.[{>_!yXG1y\')yZg9y^-/ȋ,ȫ.oț-Ȼ/ȇ|,ȧ|._ȗ|-ȷOQ~U~{LmFmaڬuHuetY]NtE]IWUtU]MW5tM]Kut]]O tCH7MtSL7qjHQG]jL-u+Zmu;^Ҵf49M':Iw:EN:M mםu,Mw=tO{i^hvjA[{suWZVO t.źD}u?_ =XC0=\#(=Zc8=^O$=YOS4=]3,=[sQMt3=Lt]Ez!CEt^z^+JJW5z^ zޤ7-zަzޥw=zާ>D?>>Ot>s[_3E:΢o%Nsr:Nv}Y_W5} }Sҷ}WP?ҏT? RүVw?Oo2lĨ14&34fi1#(3ڌ1c2fYYެ`V4+*fUYݬa4k:f]Yl`64&fS܌3[V2a1qML$̖f+lk3ۛIɘəfi3fL6STflf]̮fn0{f/7sL4eM)f)^S63mY`EfYb1I$=V.&[ʂBR-304udoZ)76&T @J0)ouDXv Ft,Mo:Cc#鴒|ZH!Y]P^4@6fB #u#t{ P8 Pעń9mRgHS\DlƴwE6QsGLc]j>DX˼jP.˝ŎIZI6R f^ɿϓmr]+DžF'Ve{je~OAn- ›bë2rJOܝzKZJ}q%W.Bsc,jeȈuobqy?@jG5Dn#^-jqd_՗15d̺>.w/g2|T^2h6*)=jۃc?ڨI(F>fZ'X,&?h6%V{}=֮,/P&Ĭ"BGwNsϷkps0ughGT*s* k')h xwrNTYQp7WʕBW JÓ=lΗ+Ro+z# )E?l)n[ilѫVC2Ba|7o;p3Kfx ;{O9yٱ&kK =ESi^| ѩ=EM{}EI&Zz47P~a @7s: ||%~h 4Yü Rd*-,*zϜ >Tt/ ^+6T;RGgK~jV6K˄aM&ub84MBS44Bm;!C?~f`v;!C? >O' ~0&? ~0a?~#cAur"Gԉ?~|||||| >V]Oo? ~|N(QG? ~(QG?~ 1c?~ 1c?~8q7n8qp&M7n p;~ 'O N$I'O? ~$I'O?~ ||8ZqRI?~ )O? ~4iO? ~4iO?>%뒓?~*~ 3gπ?~,Ygς? ~,xu.]? ~9sρ?~9sρ?g.}뾋uźbwX].}뾋uźbwX].}뾋uźb~.懛a~.懋b~.懋b~.惋"]䫋|u.EWfڣ?W"_]䫋|u.EW"_]䫋|u.EWk(kӐU~iqfӸLͷ0 ,.IM¯}z:PƠqh竧ih:YM?~ )SO?~ )SO? ~4iO? ~4iπ?~ 3gπ?~ 3gς? ~,Ygς _gς? ~\qWYs@ρ>]C9(ívxuQh &IhjY+wb;sNi5K:{`} 6ux_^-6ЇCbC }11z"fn{7n8qp$'? IO0nw 5/yB)Up#돧߇F }|R.==-=]vK7Vea@~&cISnDfw5xk.e,=MA 4 Y_ah@]h&Fǁ_¿/\־r ȎbTv9;޼j[gW-ܖ]a9{WwnpoofC n lqȠ8^l:fR@@^xzFR L~s.4\oEK_ zar|AQnRYݖnJo:/ƕ*lqLPytvHmHƶq}^'2-C96𢃺v m ~a9fm;Avk!}+/$ѱm̠lv^}!V_ҭ6#XchC&:X!rmt໇?{=mev*բwZm:PiB&K ʸrwGFB{fxJ {z}E^@fXE8l F5z/u5}={}u3OBe\V>7gߴ}9YiBP1`T|>f au|~ܷoR3@>%0|o ߴX'|TPϲ‚ͷ }xQ* pqnB(;R(,{tt xMj`sωF5TyhZ݋CI1hnC"@݁pAEba̠.{[{ǝ>jXcHm*J{]>>l߾$nHDO hy+:hZ`6]mLKLm+<\4S*WS+f(ެxFn"Ң+9LPq1-FL(^:H4A'G:Ioѻt@2}9y p1zM10a͐N#GyaNy+nO3ȉ\6*TKuTO Ȟmfڈ,tN{>}@?Ӈ1]K$cȣ<^Ws y/q)>o'd;q;L), M,e+>"[kiuS=L2 :/UNb.RdmWs#ds/2ww!c|'g&b91OOcEJ2`*Sȉص*Dk5F}in ~3NfviAQrV6Ϣv0ϡ8v+hI4bՃy=2d^@LO !s-Kw#se*C3e;0KZ\ li.v`tI'0W0RX-}N`1$lA`HwnWݡۦۡyw*1ծiyڄ_  ˅yB&#=9e p\VfY,S18}.3Z\20)h琉-zkhg.Žڤl<\)r0ދkUs0N אnX/۝kǵ+S|k=o+O1݉^xi GT`?v+I"ݒi]")GrH{0b9?  h5E4B6^rT]\k\>kk%OKv>t>r::v>s& 67 os퐏`Uxqzb'񤞆͢|#Te}OB֔iBm>G>&ЍmA{'уlv?_;TD%s̼h#i3n1ϚQyL7w4}OFyoMػ:Mctg5~sxHkkdcV~!m/6c?_5Z8"~3^fkpO޶dOefB>nXhS򹍞"ی׷yʌAJJVkupsۥEvHItH2ΤwgqJN ˀDdоJmgv {[;Z:2sSC!k]̯`ooH |M)UVn3f -^WW{-rW_*#SJrn]h/}bUdީ!xݜ}pםߟ繏jUJPtu%{%w-Ua<,aM`L qx)a)uTh(0a(8a]e]2 ={Wٙhᛯ=y9w^Y5MkVh[s5ǿ]r[+lՓ<5/ O?[mi[" &6hiſuSZ6IxP3+ =~i?,kYٲZ^e}˦Wle`jyޙZC]l9ԭі{v+D{Yziv G)}}]}UP7_ou.퇠O߄z'KkB}ac^: jJv@k *Zjo:jA֥P+Zi]b֭P;Zw@cNn}lǭ^oz[Q/=Gcc*txB# ocбjcccP8 588uqʁ8qqQ:IFmMmxmmxmHG[mFLmOh_@B%mORj{jCKT[^p~CmGNInT>vFTwƔj7&ONgJTs/ZԾjE3T_ܾjGn}TSk?Iu=S]hBu&JuhTvةPG*QE5c>`be+Vw T{:Rt:qT;Tg:>:qjT:F9 MTiTPΙT9$%N\$ N$]Nv?!'sp?N<$KN$;N2]5E\]"J.w?<s-r? ss?fsp?אȟ똋Nȟ묋.ȟ뺋nȟ[s?wɟ&sns?\7sɟ{Wɟ{ɟ{G}Mܧ}M}Mܷ}uN$͝I:}NzfvΦzsja';WQ=׹-Twzsj!'|sTt^y;Tc]R] ]tMj tŨ2]%ޮ~9]t-ZڵꙮuT/vmڵjwվTQ:M^Y.P]Nu6n%FSN*Ow*ѝtQK5{jq2ݫwoz{;=T{Gv:}3Tu}[TTMfi㣊xRT?Y!'=gKyC,q)}#W>rwˇw?jw}~FShg43%~FS*?Կhg44&~ꚟ4&X4K`4 L@W\br(MFi`Q4"@$,9@;$,0 a8`4 0MFiP 2d-85Hւ Y \4d4 2eAF ipS4=hd4 MGSAF i|4x5hd4  5_"!_R!"!В І m Ю  q7:n.nйwsK!B7Bͅ a&a p,L¥0 _x^_xEׅ_xsw_x(L/|,L§/|6L/|=L·/E_1B"S#/⌐H(B"E_dnE#/,B"#/)B"#/'B"#9!S9!![%щQm#J(/:#J/:%%Q]% Q%]Q(Q=%KQ%;Q3c/6)Fbc/#XJ1돑ؼ-؊툑P_XN_l._zn_\xcŧ_'Psq8_|YW_|Sŷ_|OG/~$N/~&N/~5N/~/A/ќ  G%| H%_bF%f'_b AK/*A/%A/1 C 8 w/q.A/q#Aw/i&_rR%'_+I$K/ٟ$yI\$I\$Iܑ$ɡ$KH$KN$K^H$KN"KMM3ERKR/՗")LԲKNԦKmOԞK_HN_LΧ_jn_^'_9MҎ4K/J4KN@_zU7_zKw_z8M҇/}"M_\/_F_̤̐ L2]@&eJLFYYeVdɬ23[3;2Pf_@F0999df>\^237336f٩Y{֙DdCD6dsg˲gWgg7eœnɊɊ=}'{&+e|bjVQdA"^*2P|A"EWUT)yAa8qv_Yjdž5#(Bt]Eh5&sQ}Gk /ou/ Z\ K8OAo~8cmJ߃uClE5!tg}RN1.sZˣ}xzO+K_i~iٚikncĞF%ZUҸcg}-/ Ù:E1UY/ʛp'оɫIAQYk-Gxr6< 'Km»y,ۢ qY ks+bud~+rZv|ףuVUsլ آƵZo|jX[ :B7Yiчvs:0 Wh\^mV^muEڜmU9 m>+:ùooM09\Zw`|<ߚ{k~ Y\xj=_n񛿮1 ǵuIVι\0k>/5_EaŏZ~lQJѢ״cYQZOƕq|ժNޚjkXǰzcRs_Śxf\@lZό-ཌ#Ж]:W{Q c*{X\hb3媸惢nop@?C#IsXUW##H?վMY<^ Qcēi|KԮGd1,+͚q-5b?l|'D[)ch[.ʺnPGoK@qgkіY˽hῦSmUVbX Yքj"99`>?7,ke=0g-j<0CUǽ?vno}>v&HAOCY czd }xo(Plcf=}߇y {J{ aܱP2eze̗AV}=21sf`$tr޷UQ%3`\!kjA凵 |'UDQ++9|u9] 0Xs>.B7o9fgUk.Ȇ]EW/Cώ#X>{WѦ:cs>:Ěn0HanqN>dB=P-G}M݅Zޒ#Rbu5~tWdz>|bI;Laa?r3u&PX8_䳵4Z9UEsoυƺmU<+N;UY2&&fm<߷VZw_ZdҌo݃YZ蟢OY>C9ںnx}m/[ 균e[sq֜Rug+}Yv_߯N¿v9LsuTsW9⺖o"ȎfVעk1dO6Ko5ʙ>ӮYY)O]w"}stG#՜#\ր>uy jnGb,U%"Z-m2nx܅k2cܯZ%s|r'8w>}|K֚K|%?Q-so9p}ѷGVi3'h_>)gbbڅȵk[87L-+c%[H 4'X5ߦoj \<OI;|d*OUcW'-j=o'&[8l3Tc<5*e\g*1Q^V%qoU ΐ*E;h!)㾎5i_J]SP+_Q߁TvlW٩Jp*Ÿ 'J=pJ_?p_>AQ=V%|-U%Y-&fZx;jTSShg:dLW7UgtlJs~dn9ln:ƌwwD?}Hm{EL9(yL+o9Hlp ߚ0"ȰV,Zޟ8߱O -v>S8Ώ-<Οgiqݍzǯ[4Dj>Ƨ1T?UYl,1nUvNRRS#j9Z-w _x$jCTGAGПYg1*#x[cf*v ׭k|_ͷUUGG-_lj>Ѐـ=6ovݨc9oVv&>sOWߥ:=O.mSh=Z>bޒ|F&mÄH7U+E/hӢ7ִj|\&Cz/}c#ß\[ONq75hX!mad7@[id9H@ ͫ5T=)~bz6i۴CۭU=q폵%mvE]?[kgv]vϿA.F_zeKU/>M?%~ OȨ=3VsEc~qNg3J-all.v6a~ÜbgN5]bWiO̠2.Q3k̛ysw*i(Ŏ#Ok6ƸM54mm֭ɿL9Yb}CvmC}v]CmK%.3KbM>L^E<)5]K&ucw*WWW]>EjLi6Efз oл4~\>k~kZGY~3σ5t46UGXiå㜃ț5ʟMQR>D͗Mi/ "ei|^ro_ʙ,+bDiZxJmX ZM0ciLRspŇk hABK نMkҚrӪ߲[+Q Kjdlgm& `?STATZv|  t/ j6$N .j [đH)]*9'dWP6]|Vvɚ#"stYen-D¥MZNFg:&Ogt5/늩\̷%Lp3ye,tX NĄ#l %mCahC)dk"bqh~ڵ݅׼݌E r4mXEQ8xbL&3(X;U@Fķ$>Z,G]n^ 2cѳc@TF}bP%JP}%)[d-LRrNF4-!xEi:xA<ěW^Ztӭ?uU%#x(kk[ ̬ug}AaO/ kGGA|=_,Sa"]" ]{*cDk? vVi@!NQ dۢ#^v6]~_K$,e7ssk/KUTRܑssM3& ׇ9-ibp@481 ǁ [8{Bim26Έi^\ZCޱDOa=|JIO%Huc!S@Q|GaiAi&H$PD,[Rר:/R$.N5E(p.W􂴩 [;2g+it,()îpPTKP(H$eyG$ENjsq"*" EL@ER-$(9{=Mvzq5WZKNӄħ:aq49D/ǙG<6ň.Pr@g4j6^z WxhC#~YGQ*ilM> (>8ד"q N"rMU\ro'Dm#@d6Yj?h,]r*CƠ6@7=tz-$$0ʪ)z(L‹VdQC]L0@'ccB ,;D;e `x[:wbfqs<,x"/s?Q;.N~?<7$h'ܒw=#}PӕӿL;=be%1$2$q d}-Kbqp$~99t${< d8frRo+WsJ}~7'p>MB PgXAOAA1EAmxXdDg*:"3X@g$̯eJH ҐJA{dhi HV0NHɥJv- Gϑ @}E([ > H UOcdUTպV?1Rjz܌%?x-d8U`Ѐ&a 8Le%}:+ey·*@\q3h%Nq ^J;b̢/R z1= 0:57 dEVD7)Dv4/= wIE@^/(&@!YPB,88ӄd(m@e| * gTapG2?5̟L4nNH[ \?*' 3ڊ;SᄉxP`B3LOu;Hux?ZO"8?BVfk}@+,ek ԞLKLadDf-3gI7Ȋ֢ΧfLi1q1zˀf$hxMItMO@DvGRT&P; BӍ ePܯ2&JxҬ);<ڂ:FN E+so II|ҴN7C1telG%*Ml"6B/1 'Q xIKfIH.g y"׼NBJk1ʺ%`bo))YV8Ry"AdYT6=B_B\7sb̌b_cY7$B% ɬBΎ%ZwƣѠRNp>"9[)53\t/֪;:Q;O2o:nDiRfs3A&{H1POny]81ySkЌՐ:e{U鬒}ѨSrEmzjx3a-I"Q7*-YvJ*.ZsY րV`蠌\!y*c;t!u=9E7ؐ Eڛv<鷓O|}}[^޿@/j6x!J<Xvg/_fw3k8d} \c"qggx+)p1ի!W'J}kx9{uBOk=uxx T+)L ope m*Fk4K+Uj­}FruW*O7 Hnpg2(^T=cQr1jTӺvV^ ܶ,ܘ{eCRQge81^ 44F r2VlYrrЂ]Aô-@nݖ=`Qً=COɾ&mgS8&%.8Y "ȎAdCOwj7v?KhpF;Th}Ka/OV~$E~{ԁ@V'sU7 a#p|%3^9AzdPGǤbsOtwFsx]Ԇfn)\/TJPrԫcZ'N=4Hhߏ"%RWᾟ3 /Egc ^pxgNM]]NmK`=.) {Mbٷ(XaJ(Vŭ*'JUy4,.IIK*KC֖tedMb ;:ȣ8O?B{6bXC*K| ѩ'Gp;r?GFG&T[WObđ!C% .~FeTn[LS74ys7cf|k1qT_PkƁo^dژAwJ%PuWpP0џ0Zl qږJPp?v?syEUS" ОnKђ 胞!|xwA.Vh>Unh5"Pĥ}閏[>>VXa=}h`3 \a&MJc#>AoPC75nLECiCgU*s"h٪SpNmsr &1ٝ h.q359"&Lc?YUzY>+tW*ym6 $i&)oy($ hM&¶Yoj[ xͩS{,aV{.[ uM6A EW$1SY}rށ64u=S2@=.\;;.B(FDEaS Ym;9:G[ Th(j&HwPW޵hdX?xTpjJ<;C b|ד,eCHeOR@ )CJ#e^IɐY<*n:?zrklrxٴdճ/׼x(N>/W͋@l ^θJ/[y*++^bWZc(eWCT9jTP?Dzz ET6구^5j ^o*8jQ^u\cZ Xóԣg%jR*M#ѤU)f=<7Ay*'Mh0cpѻ%BۋW17Ҹ12ЃDN4r|VQzۉ f)lr_'tT-n :֨Vi,8r DoRg38 S̉WUNI$E(A`# Vi00\0 xD?o7+`l)};nP _r44<6~3y `DJ{1Gϑ$&~6eh?M6p;ޡ90 & {Ys3<`f63oC=<"63 tUUWSmu >s'31Vfnaiq_:m=+-{ʗ%^x iZz ~2m`zҵ(Fˈ?AD$M<i뢔*ugXny p%Svk++]Y3g ke^祤ed@!khji[XZٰiˍ?3CF 5ؚ3)W"SL*V|tYa-v/)[ol̍h,ZܪE\kYS'nps yKɵ%d; {ߐ݄H%F.dp}TfSqzez4^4NGs# jW_6:5M~(+_T8^կkǰ <•=S(;qxHdHtȄlk mívj%a  J=,uM[n{[B^6y_[ik$%܄P_G'H;bipa,ni~AJQz+lr!K_l\kٻ*ZK \aXI1˸N%B>$TCZHG 9dP(԰TFai tFX\C^abLI1&ߞ)5<̟z"_F*&MK -lVK&52б`l4ܶc Kisd6 bl,^IIbF%x唙,G!.ʇ+*Lky1C5,- \ $ʕAjB!]nvU$!IWOF0eN]gjUPƩZZqAI.(>vߧZbME}3wg;Q|J;h2N+ |ҋ`/ dp%ݞp wXV@7bB*PpT, GLGՠPݨa *f,j7J#̅~0Sl<ƼCERȁV~S,6cY|It RgS௽O{Nx}2k[TT_x|%zߗ:BMINY2T .6V1oz~?4e )O4m @vs |c2yc~uh =v~{ds/e +]}n{)xU)oOo7өk/7uQ]NH0+ګRA<?=Z_8:/|_ M5z|  V<~[R.\4|"9㘴to9sٕ'V~UEs̡1*͓ƔzSG52jV?>ʼn&\|_S7EEjW)-}?o7Rp5&]z 8ӟ7\ZZw|x}?P_Xɾ^Χ㡮/پy& M'8?ѓǣaG~[7ҵZ/ki63O߈ uLw@YC4Ex&Lx_ =Ww~Anx]+n1O',ug,8%vDf9Q(EVYעAGbwJ)U VV$VatlXa~{v}%@ݨ=RpjBC~V4Z$cܯurP܅?wq4"UeIwNWuaqYj M 3kH]m:Cu*yEɁ^ˆQ朎r%P_sLBZ0ӕ"]a z@쩏hE⺅z 5Ǧ')_nSe+-ʴm&.I;Z䁴cf6w6(©F>ǧX]/Ԍ=/{ R6\!k r},/ݽkҜ* b{dVVrpiCjz.Yu^~Nl 3t 0nyѵ e)5Qչ Ƹz QuCi@ޅCE4F Wr3I+s `®r X(Gqͧʠ͂Ӽt^KMu-Z&9}/r*6u QRːIG7%Ѽ8yf\]@I!uqċrXz@zZ;[[0.SwVSojMO?P$9s1X'W踢E+ӥIB{x䍶a$ & %4rum!ό)krAV9bT@:u$ 3Wh/Ʒ?pXubJrK@3'gӜиG0^钫Pyvx+pg.xv۫ A;`l;d%5eoWx9a2l>/Z*4A벶 KcPon(P]/M 3Ҽdi52NP7#OZkxŇ3:LZ<6 @aJ"VnHǨuc/i=[D*ޢܲ-vy*TL/?4*U%hK"T#iAdcjGe?XqEƠYnh:aO9w,r.Ql{ݕVLR ³HW/Dbqw%K#eY!jJ77x>~H0Ul0Y:g=-'/Wd(1-q&`W"4+47f~~U3!7f-;IݞĆ(_|dͰ}8^ n=eovz!p 7^B1yd~]kQs/Pxn|*EoD zI!yNiSܬ~ @<[b [e0Γl^yI&?hzn~h%6O9ApЈ~KZ]bysmhwrO#T86`۟23W&d8} 0Ӱ L!9Tz)MV9UV1'E#.! }FU}bY[xgwnEn`@9^6Wcyk$W?gmE [ÇEvw&O(gXVYK`%hcl cXz?MT4mfn뗐N|ʶkLTpżgN 5>DgRbk!~0}'pLn>C9\aPT(R*^, i pCdNY^X0+G2(fAH,Rc2>08;h5j~Ћ89oߔB=L%P)rhj1:Eqst/^Ӏʱ94i ( ZС5G Qv'Zx'CCԬS%dY-(lQEk c[j\?b"$:(\n7T{㜰'\cߓ֟e4P\"j4ci;hl;vLӶr *{U b>̵o8:.M]Y5Fؕ?>^.S%Y!(idcC"ʧ CG :|?u"R(Օa[þ₨E,2M4zqzCĵ)}/_GR\öW)o3T w1)Gd!Xq2P \NXk 6ڲTUtD ™ CHј2AÃ^꿈p 1 &EC#i)~"j5S=Ok/MQp$x¬g{:Ӥ+jXBMHMn銮{@(!dnGK/3]۔9[="~$eL|]tFek鬳陮aT{u UTeO-OcΚ3u<͍N) |`fM/1as]oxe^4MV'l`rݬ(.._n 'Xywʼn6-b%@3D] hӯ=1sUHx [zwJ+ɝ Χ$pؖWkr}e+TǚGDݬN뇋YnK>PɤNHOPP[M wmSDW-bȑڂQrޢ8\Ӿ0Oߔ\= Y/$\_dܤ[ɐRNvwN]g=wiҠϽw\:tM46$VJ#+9`ni|]ә-P驍pd.ozt+.i3o\XUS_- N{ .vR͉'1*2c@7ayMM$r˼ ,pkLѢ D\ ȹFNa 1zÄ-(?(y*ԝJ.eyhhG2;Q;T$` ;VIژ%Ysb/atų,2{I[D%Q5=Ä-smRN\A 1/"vxwRjx&[ARWsщ%lRmo, WꁡI7fUzTP!Qm q#8KE_i2s.ɱi4R/Ȟ~fЦeZ1K3X>{fR4:Q7|)*T\S55HѦi,I»vdXkFJThq^f8wiqQdvnќĈ1[rCZ)&+ɲ=# rh8`3˭uV[/AuHq69na @^u1&ul_ 3Ug(DmJS kSvL$$}[5-k3UʺG`n&ZF*M)&@! +u_TtQ5zբW6j|`B۝B/.3ࢡYe8hsU )Xw/<$0mUӹ}f?deFs1;$R "X)%Tm,լjuX . <8(|Pez#WcaBj+VV,lF81 jDžAY*>ݓ_w_1Lt$x!Rxy|k\=/Gl voNjf.1!nrn&NK o8|e EwK .﷚MzQ&.}Z=g%wI;zߌ̼H%߱c6w=k{׽f?J*"=+PYDuXKu`BoDu'LRQ1x^ 9?Pԙ bm ]80 Y`فmR) $ 5Z!IK2;k:d\np'9ظۥK8ޒM5Bn.1΂˒F4 8LtAK!8. #Ʉ w4葤[wcΟuib̅+w1lcdaP}t +V1˃lrw- OOV!G=#L< v0.rH=q5ǵaiߐ Ux;%ъ+3nqAI_JmIo uRmUba%QXxYN|T=αgETG#w^9ab,r1k6%?l;=̵ yic"+GҨŮe;[3Nۨ7ZIt ̥YM-`nbJ.N^Hd4|u/xP)hAm1 P~6g|C$b9.e2yF.Qs,&$Pʆ XSv-h ֱksנFo8K bTDx҃<+OǴAR0`)8 _{G_G?t@+6{MW( ( 1kH4%\'#ݕ@IC!DjԍCp {)5%:)lƝd1vɬ*vatfg1sf4'Z|bq= ?UK薼;\B^" Gj^0ҞԔs/*ʷXu`yV-g߄bіim5gֶ2~6F J\6e l[*'dOD`ilOO&bi!i[Ca& o|ak 9Zz^Yjш +Cm+-Z#ôӑhzCSROeX+CQ5t_}(>n)_oFU0 ZPVTH‚rLl0(O\ 97pQIOQrkCo9- y 97RdP6VҼ8uPO L[K\a-M<bV0f+-<c5Y]ؿBovo6ʵ YsJV4U\~4p\aҥMPKM5 v !YtZ9܍Q39kfH"K Y3x<;h[[3 i 5uN.G9fA&tW/?-sm}BQEgvJ*jL:( BN uu,;v9{[FZfZD&HKiM_oc#fvYCi:X/kpR#e>GG.P A+%ukGwJ>b !jGE$O[0>Ü|8: )y]9PO'b>U:La/!m0 sͅAk2$M`۶)zgrp EBWD ? `ghOrWy@ً@Q>/{y⬳9ގ:$+:A5p; &\7UWf-⺣;u^›,N|]K.!{V552~z8l頭}| =v` V4Okj&͘k]2Vd8n>4xgMB^-: S9Zׯa$ޥ~B$*ʬay^h>yukNMUU8B!2z7WdRJqAd'&z?ogwՖM|md纺I:Ùl8t;-J۟:&LWIռ bI(:9%/L96'%ᢛhhYn#B2[?_5fBgf̞Q~7 M2Ԥg?'4!_\erE:'nӯoP\Ew.e['GreSDIJc/E| ԣ:5l;mQӂiQncYf]N-TyCэ%$F#0æ[?m= Jz/`̃%YMD{覅Ub`SJV˜K3hH'c$pkPwNNR.h06s(De0M6yƒ61,~WJkwH_O/!䨦wir_`$?B(o_1otU`do7g=+Mqs(K:~c sΎzR/=A |F0Ö\TS 66(?};AS Yo~Mhm!OL  ," lh\ХN>f,tz$B 7SW[DF?E =3D; 0zy92jq׺5lA[A-"5 m3j^lIʵDys"UrLy sJCMlG gU|KΞΟg2Qt\^0*Ơ48~{s$Xg$$B} -*A[X C5u ׏y6pŏli<[N ) ޞZelZ&`r%9RG`mzDTLm#4=P3zc[._{t!{gz_ mmKNnaɹ7ܧɽ{wR [ raY\ Ѹ[U_s4 `kۑs 7s#v}XkȹGL17Ҿbj),oveH{P⋬ߞ%1Vguw?k mEaǰao Jюzq~z),ty*NEE;/KH~T=!ʺd!T˷oM7x|ʘ#H[kVTڮg~&0+CGܙ~ع53!\QM'Nh]==5roy²^HɆ[_ZRA!3d|4[F nl Ql+|Ly4xfzʿRc=v!nG}g/fj]"䰼q}7ׇnR춊Cb܊\ݿQSf.l8 `X|00#nMy*Oí$߁J#*$O%TC0Qg+,-dHEc.ؚOoK 3nZ٭~G%=|`! &?~dw* /쳈HKO$8|lдDkX=Gǚ[ ~$b?P֡ki1*]Z6Q£Ef^sӲy@?~  Jm)CO'?0xxr5'cJ?jE \h H wIZ#[D/8vE&[5|J`!ȎRZx|OZ堧U#ӆMį'ݭir~NOy0h(]y}Td8[ڑj+.OEt6EEs Uж, ц*;גpSi@%e'cb)9/T]qeĹJ?4MJ'rD-/wWrS_5&Ӎ8^%25X"7q̤j:Wi3 70TCO4TWGYc}E!TW15hmq\ag!Ы\qSxJ"A aK!"&Hl=8i`ghI=HGř9Uj*ZxbHo𳕠}lzP$WGHퟪk Đw2"ФH\[CES߼zʭ J N;VA}25~U^=q3ب=>4P')UMP1(O_ ۭ]Qe'!&9ؠ\B4Ynz+򒊃l~!?Nxq8љj[Wqgİ_㪊6:Zo}^|0c)jIQ.A [>"Q «Z QBgu@)~؈fda0 9v*fޯAUk/+~!8:ksa^HEDgH?L ?&"3ݘ÷1؇lh~Rs^8{ 1?҇\4h[l3=;?<>W?õյc|Їv{'SQ3dmg ~cA6WBk$f$;& 7%|O ݧbmv<.SB푌RXRf=d6G- g B*fSDo;K8bL*tˬfR(-V%npM?r% : W(>|F抝 ?\x)##dt&&mY))? cSS+ kSpNJ,3l^ҕUWU sǪatgfn@эa15j+RlieG!%yRߙf:y<HpT?Ж_[ #\kAv{ x]TwҚ 2{̥,\-ܬ^ {$g%U8mcCa\@k\K0l1njKWM% sѓ'`-pMU]X&MfKl!i2C$.h@0Udt:ʶ\Y3Z8lu!yOvu:|SN_8uG`$(YweKm*qIAQ(l탌hڑ /,bc>(Q$R>Fsl5#xj7,{Qo oe7a\C-1~"{պ~Όʶ'6z+x;tK 7;<| <uHy|q5~VPA؎quQ=<ccp9PaiQ;I 4z+b?JЅYѕ2Tj90V0:vR{hw3:XNevdZC>+SNgaoeǿ :?}1)P7cwFYUԦbRZK$cb=qɞ[@^K.1|]x(Ysv4l[LnB'5 kI .yP1hcsؗ?W-ޔ`".A͗"wԪyujR˺co':p+UI)jSv/A'iŜP|RLzzqtr}tp$2S R&׽'OLZO\lưY>4I"şf<"/@:Q|zCC G6| K3l,5xWg,C gY:"u对47u)pПN#tYMy{y:R BnXWpx!pM]Ɇ. ao)E&sGT*.٦%y:.z⪄oIsCC,U~V.G/IӬxb]-A4ZN2PX@89zK9[ :vku2".S Q[FD46[KM-՛=byt 4@H @~@ 5xFͺՙc݆<*t6^DZS'7 ~0lUܿqY\88It?QW疱˼eo-X+D@wd]Ӂ&2lf0!lLo 4aF6_o 6 )=ػύb=[INʨD@_(\<\tm; z5h:AByZ)b[F&ˋSt^w!1wdGg Pvdš?zf8yrb~XJi czPI:BGhO{8j30e6+S(8r<5enr't&g :+L:Jm߶wTe^¬Z^n{(9nVPqd&p W[;Ͱߘ1;nmk॔ڲɣJoQO;Qz͵V$v΁ܢqġJ]2\%Esm i."|da9K9:}">'QŇSnwvY&1SL7{ΆjsQ%Z=;qTM+ψKXqR \rХ,=>Ȉ0" k M$HN%0^,,FcͰPGgOjUd 3x%Lj*ӌuYaivRC\[Q[0/[ $ř8[q4]y7`RK-G}Bݵ~+Н]<sBg?l"#f<3zVHwoF<9>GQb? K'*cDi,6RۦH%RN +NCc]G *+ DB@N#l!BDg LFL?|jwdYXqC KēpBO$dfHUb)'y4b p(p?]J 0(!0.p> AbzcZGEu $p1L3cZ?@f}| }Q_uɜS ]^~oYo|mRddo<.l43]MqjUY4`DIipi8mţJw9?#pb}vZ\jEUo0v|L?Yк\Jº_K_~^Sîo+C}0q+Zc@02pI7 \# C~uF'as'F܋v{8`6@0`uݟSHē\ȉsrkGK|@Pzk;6 0O9ȄUS1WFXVj DC9RC:1/fD#EZәWh)rw&3GY8&SyNIm[⦩ ~.sri*)Y!GjVjWXP]LLk6Ui De'DH[zr'bi,V,D|nXp+x؜⮩q,d<-:y&tZy:daQ֝AqVG<[g!6*5#( ۖ* ynk'+*~*m\Z܆~:~O^+-ݲWP0a{TW^3c&sBΥ^wgvڐ n, XU\CP6{A\Ե)\TS/ОXgGW#u(bR %rpYC#>yE6lc]*,B$9}/R5ְ(XyBFw6Xy4R̝$ojkb$5;jP%hJ9yh]aHh*fbֆhGf%4|Y@ȋSdI@O+]w YR07s\ "r24R|,~mN)q:Pik̒wRZ~l܏Xü0'ۃ,r eq \ vW в JTVi(]-^.wY i+}=]4KTQNVϩG⋦snTANXS(f|Z«l^5كm(+[zÌa9nVX[{-B,/?&6{ݳTĒ=nƕ1 ^e_QJJ1w'׺.{8wKM_q8Fa'. qBa/NH)1aAO943pcG֮1xPӇ0ݒKBZS0Y0b'/zBz߿{BuE"tw]/ n(m ]jAcNxR3pt +#jsCjk jK "R_ޟ*t󋫨W,/}፳t6fmCj3Yq7࿭3 c4J_O;뙲߼ī^NZsۊAȀEmI=4lwO0,jC/i屽"8 / _n;bҸ2<7IfzsG#Nud"9 CZh~k@ \#=sLj~Pi9s?H/#="޻6(5)bWtxԽdT_1dՃ@W['h~'Z&cf=*V#:M΄T ܋ۆAa:H$x܃a&-|b_ؒ?7n'߳oE +0 %cw`ۇT_L3gĶߣHtL)_;.6~K/+MϛlU3OV^?cN1m`+F<&\Cƀ?WJڡVk N Ļ`_.pm=$7D :?4Rn$Dbjc0Z)KBCy'}O]yxsNȗo|LL/3ۮ oe (hA9cbcֳL(N[$G~G!RNыƃu Vk #Sj`u޹M}6ٱ8=lu.ar݊941ž3_pkjE=6 _0=𓼉#l'RE% ]Tf 0>bqp~"|\cznhY/dO]%b[olRNĩNYp2Yfuh ǃZ*M<1N1&RjW̛;uO뢌 y`uuQQf@QYnJD-#UCY υ7~[EKS%.HHq1Od6gnXIØd(#df`8wY)i##CطZ-NAII$%a0[mQ% zbe^c[ &*?} H(^/䨻|aÛ-B,"ާP,b=_VGR9=ܵ"1©-g^pB:Swvbuo6\`]X׊Z! }8Ja/@BL>5avf =Oc->*2,uC{h0eURTUBYy$adYh|\T8b*6I]~xXE}o#ӌd;j1;1 z;!VaM!#:wg|Hp_á|q~8yn]h0::s|Sg:N/̱ze|*7l}DFu_R8d:%YHܲ3&ry+K:R#.D/G7elr`\i#^m:0t^7vNMlDdYs>pdfq#?9]Yd?3+2 ͻ'$(sWKΞk>V(O7BH1[RHbTSgh|@% P  0N̙`>P#]>042,` YF&?TwXxP0XVTСO9\1}\fnIe5 54;<Mds;2=ZgnGNڿ9Ʉƛų-׫ɾw͋KNLuۧ.d3~5d0d*|-4e/Ԑ33qHR3!`EWkߞi#0 q5^5_'i ;Xۊv/!u*yfy D޺}]Dj}_voRZ0:>SqS3*-G&9l@Aұ B8)_xAC #d]3&)0'{δoQ 6=\vn١tgmvlr*!.<[M\]~a`k&(/*7qvpl_M,Z* %Pf3 w>"h)!k)dǫP0z]SGuA V~XYaYbi>Kh5 Ub#gG[-E iMU\؀17 ?\}n)M+|< n_*/.jDV+!/>ЄeyWep%o骟2s6VCC }knkupuBd[.fwceE%baE#qq\;y㱭[zM0脑P&Z0/חoPwxg9΂g]3hf١4Spu6nx5fENg}lDh2&Fs\`09 2X^6"+xe_>Ma FVPFGè?uM\d!m!Y<ARp ĺ=#;jF|MWc '~f;|k[3K4 YDjiqpe"ђc` =iDOp7A W6]`WEDt ;+RGt;sՔ@^Oj69c܅!@U.(Cܰ[$w蹲+C~9ɝ|`8 DGԴUt&SJGHQɊf/(cG1{4>b%X7SSyYCug >LgP~"TfJ~}x0%iDqT1xGP ƥZj CfeJ1Wm>=6UK6<Ȅߕ e(E[K8l(ӕ@$S>dUQ(&L{]d*V ȴ" ri6!^h|N(&D,덗?J{#{~{hh8a~'ZDzù}fi(jIEK㯻(7@?g^K^7Q[yšM>#vlUt[0?nkNhJǒ*ejNCNWۢFm2FInRX#bC[ԋD%<3w`V(ӬXa9pZwH!ͮ Ṃ :?`b`LLX{.LZvqY`uAXU%>+8ivڤ׺z=mbxV>ѹG;U\&΀/JKُ}m֭IIEZj-IZ-_w + )4=,5xOF1["jDhM^^9痖+t@Aw 7*d+n܋|Ⱦ\Tk/la>scB+\VsW;MU׹#W#O.5bۅ:~,fqVxgBܷ8unReK:!P߻۳g/L?p `(AR ?7 [3*Mڽ8*0(N?>#tD4 P KD(\=ѽ g7iXws?)f(ZWˋyðKw"6܍,-z^SPT6zoZy(Vp_uNwPٛH5 `4Ǟ,+Yb!pAn 9@=JRDc:7KVOjQRݖu{Ma&rAr7ԉW2}f~dt[0~#;a}ϧo4dNYk`śPQNB8ס\>Yow\U''e\&yEQmݙ/~PI)1V`j[ft+3bG&^>X+?1Ð+: 9ƗFSa4^??Z hoj;2~##^<SS : Lf`J:REL?.R~aJH3=Q G>OzȽZh۸|"96;X)xvNkr}ѕ&3si.B+w9lxxEwʤk) }ă)6̀QeiJ?*۔_[B[FJHnNw̕q:f. *0nzXr dXjA 9cHKHUG[b,c[L׭+-Skco n&`O2L6c-[Ub>ڌe'1/ "}2Uv•1Oy%vw˄f%uHX~BVei#W>Fz]u@:OK go$QQv* Î.AM<6F/֐QUQsrD(e6ͷg/"Wեrk)z>OB.և}/|,s0=cǞJJ-+ K*/ U2J8<@N%+cgA+G*ғڐSgy\k}+!!K@v! X*^xN󣹑cn :kjdGuQY*p_ Oz 2 'W&UkD%=/O,mՔKmؠk!i]jty3WטKBש|uGVqtCmun:Z̅p n{x{f;.f},i!TT\5R՗9ݿ@4͉*ŲUoXж%>a@E~e]m^^CpCXI5KǍ1" :wau)Y=iIX%Ǯ;io]ԪQIa$QDZ.sůQVlOޝqd՟\VgFoSWVWx)ָf/ΐF#T T:uy^(q~Fm8TXڊ26V Fb'!_P DTH޿ol *)!D|rK*Qb3D3/Ԕ?lB7#"Z1Υld kR ~S]H)PL^…ʘYHLfW5/Z{FKbnUEju>IQ-)qI.&:KVʶ]sJu @gWA zaܦ%JapvX~K*R*!$5Cj ytzۤ= _kҮN K;N X RS]t(GN~ ?J {=W/jsSτ|PygØ=a~RCE$ʔ)TŨ2Y]HZeot풖@ͷ΅9?(S @;^&L~e{ */E3k)VL~'yiߋjTfGZ~u0c"Ha؈]PNb3#ey0ڪhһNw1ھGw zOJN'^]:syq{FXXP MQ`*ƇE&QV2m$ џ%{$>ʭ*)$ 7(~ UcB2$\f;_j休J/YOup8aKZŃYt4z/QWo2 PC@ ~(}<ͻoj8 \U-9K.+`M Q @0.W*+3O-*5ٴɰ{c;GD#fH9yV`r{*UhNgqQU9BBY+}sبq>_Du߾I̸2|Hi>C56HtQC=]-ˠo]))#UNTK-W2I׈AV3KIйjr#&ow_*r+^\x Xlt7ʄeci;t{ z{)ޣ)K74每l/lդ'59ޡ2;.*&k5 \(]f:¢f)jU^!36!./]$?ݸ݅te#cǣL&sfrnGƏ%ZæcABI*wpx߲\%j5Eǵ'ˋQ?1ĕyMTO2gcVJ^[_ʥ/ rCɗFk|^k3Tw@0prTa d`I ,7N-s {n$ʕN<44Anv888kSLsLs@ 5A (#(alʵaFY}z"x4ljS6E!}󇢿Ak1]y䶵󘤻&38"Bd hdHJ/ >t+Gk冖@gm}o=DzYkK\~LQN#,="ul}蚏UO/͔\M)B$#rS@ڜoYV 'B=W(0 n?[‚JDf mޗ 8X71V^oVC&!={#ϜiZzMWР 9l9d4M B3S/'XmCY7eZfn|"e ȃG[F\$[0 E і!'5#G}4?b\qGXIJo. ( FiۚzmI\Xq!{cq2`A}rpbJ3^]ͣ7zqSobJHq,ȮD A!J?`i7^A<վڗWC\9vr1:.`XYR2,G؀>uo2$M(_،L|<b }rzK~=r3P(OF,{b lBUW=9Sqd;⺺H P'>+XKkCDcc2[My[}w\)u ˜yOz(Ÿcol up,tB%;̻+h]ֆ XofL<ĩoL7(~~4Jr᭄3Nm@E_{Egw 220VȒq4죛O@V\ֲ@tW vİ1tXy`'%w@2 L\%Hf'm=ٲljgJ*F-¶斀cr䨽Th\*bE|& #^li~HvD!_ wyoϛ,GϺ%Xfx]c,$wHk!dj! WюkɆ|(b:P:0 6G/_Fhjʃb_NdJ7hu"~hE^%~U["ϓ Qui .Ìa0 #fX7x`^*4ʌk]z1^v)8- ~ZLJQB U9s>EkD*+~1v}"帒Mb#lǢXy׮GKr, 2+٥iD$U-Y*26q؆"oc69|QBS :"E<󬷇PuyњP6bm<[ G/Òө &,!9C m`Z^@9qZ#A*MX\7%WDž S6>贩` -M³ē'x/:p1.C2Zxur+Ss(X^iepSҜ$$\P`dc(1[Z];Owy:kH$^9I")R)CtRuE\A+>%iA݄z^$jy 2v]n:-K~3lj]3׏ 0q RbLbonzQN;xZ@.UNsq&-k%ż=XG馳,Y1NBCFVUU ? xR?{j$&l\u\($ڈf5GB3V}QffWj[)#J̻#\~]^mfG< ca85M3_.۠hܜeL+X^ҊxȶtE[rǸ>)G0&B h L8E3wG; :60,.hFQ8\@6kd9Jas"ZH2)a$tD97S JXW{/ywvՀY0s+Mۺ0әe-aZ-5J K+A Hum'ŞBQ3J&BFp ;K`;9vf4O""ci{&:6ȕSE,/0jh0YXx]TJm.qaaۙWe = sE(7RՕ+g|jֵ–gP"4/ZZ,FK0MS0sYIT_-≕ΜkQ}^::2Ol`oԔL`Η0v^~Cԯ3׈XJO&aw2J FeveHEB9'ۏ,{Eu4ڶRa"7E*Q5d;T j {Θ=|2$Z'duэ7II틗\Fn2S=s^O=%fԮ$olz/MfJk;#6w^S.9=yxpx)xL%Q_q_E?2/9yng7VZo޻kq7_ 3sv~f̻9v"8<I%u+׶.q`d]>`ONf'+`'3`s؍nk`'hmӍY cEtftɛCDb#I*ł}y-nV1 {j|[zG_x uausUԃ!w&7Fd`= +R9e몞^+qi, t92Ә zin45K562X7nJdDaTN{I΃Lы7 gMLԼ!߬Y9=왃y2r=6|i(/Ʒ'mn&rhs>WX>M Yz\a)=/K)J\0X;խwel'|]}ޭQj6t۝ղá:?pi}8VȵP+d-n+ |P)~ {g',^-p#Ꟍer#<}?FTe+0jK~eaVz95oL'π /2|yըOө o7{::ԛi 7憺ǣb;?*kC?'Ý9D;4S/f1|T>@vp}wPrͭ4􍋲1cvt~,tJ Cr.`2B)" T:}j;4=5tYjinQo Zimzxas`b'M6kpUO?Ͽ^Q::7+;qQ}@o^>tUw~jeo}ܽV~\&T_Qp<V6i++d%<i}V0t d-J\;If엟fVXOm+]{Kw>!bC㺥3wiʓG&ĎD QvZ$?8 Տ~ý B 9npCpg8@'8H0y˥iofn.Lw m hè`Gc"Nio 69,9e*r^S`i5Xִ|dz:4?;`9XxSv{ =zSt_~!~ [4˖+f1j4$PhF૒$³^*޸'Q7W56tpXvF򀸀4A#p+\i뱚E5t6W]<7{7>5i Ţv}yϮ% ]NhA R8~xڻ#V03rO3VZf=X|[iHe qHv lۘ?DI5r[ܐߏWJ:k?Wܟ[Jn 'vgփ9M3骋H77ƟJTK-:_;ӊm,8(bw,K !;њù͙fo,%`#;n94Gm.yOY-ݤ^>(WN1vbeBq#X˜rrw~&LEόj`I ,rsǴߏ=E XL8LD!ξImi^dLtbvEߟڷ" ':E,b,o9(3]SƑ#V󵂚[)50fmp(VĩcєOBC9z9qEfgFb`Au6CH7/ra>j¤4@A!W$ZpI )R,cR҃&Vp iJ E!fFJo.: Pՙu0 ܙ 'sxOȣGzF{UފJ?9?2JG 'Ѫ;V3w~axO]4TўXlZQ'ic0@wqt%70vgc^|rZafOh,x4BNږ`f͈iRz a܇,A bdg~*;7fĴJNgӁ@šlq̈|hIιA0`*n|Nv&ζ=T,FjG=DQ 3w1G\S_*32@ҖM[)m5ׇمy˃{n楌wZюbԡI.JeY}h#Wy3IZnp!\9fpW.SC\9L%z%rQ˵ꃟ՚IjUikg>cq9W# Z׺"{B%f|%2)PU>5Ă3AM9ҙ]PE5"sV|n']}}#OȹQ8\@y)J)jvayiKZL]^K "qP`Hi p۴{zyܟU\}L|d k&<.$4Z{C3u9U8;i# -bV%qspMn46vZ_9Zy%Gy}R˼VP(P܋'q?F/ҽ7}K8,^eܪ`#VL]1'iP_C]r.KET|nZwk p}l1(i0Yup1M;5gèwv{]bHi;Fc퓄 jbNϡݏO:Ư,dmhc)) Bz|slVב*yj{c&EGQ*HwwjUk .QBN \c~NOCxlu~Ed!,!i:oR?t:7Q<ȁ~fsY,#/GBj9WۇurdT{05ՙ{Aш-PsJ$mpeM=K 0v&&O?] v[VK[= 5#rJ>M5F( I@9.i=_~⹒bk  Q`".U#0b{*t*D529mF0-Fg/y/m~(_:X[ Ƌ[Of0958U1W١ѓw XG&E d ػ ,Zj1hqD/[gk54O=ߍ q'0IF##brSABk|f#!&q 'G|6W6ibFq&Ax0 Q/rwkw("WZEU& 9Lx^xp\RE: UlW"@(7w&3PD^8EVPI-q܁A69Wr4ޛetZAέ맍P8,)*cys{ (SpքM*s ˾mN4ɑ&haKީ!]V@@6E[RUzK}40h,؉Lל-Ab3a]1v1.T aEӰe~zߨ7 :~ԫ*XvMU,,$< ŧ{Q?bqaf'㞚IB-y]>@86BВߟ}:s : %@q$R{Sͱ!eO胬\6MVO4z*^ӻwAy C-}m8Ӂv`W5Ѭ>/ wBoiUO1~KF^cnoAŇU&&-FmV $F>q>mvYȷк1rf$csjθW p;u"~B4?EL0| q>'98W%V\R܏vsօ7Iw;jV+7zl;Z[o~6D]C9?yp/[/X Ȧ\{Pr!z+i#wH\BJZkJj6LVTt"KRi}fUJɗT+M PBǬ,ZU2YY ╍uHVi}0jfJqL `U N7q@m޳2yD &>_WL:ۆSJIQ/u˻o=`axmD?sA&zS(Px)& QY' owg_׮Fff#7Ӵ[I?$ HFT6}g{缅 "+~RkS/SɗIgbٌ$,y.J DWdJthOL KZ-rPh>þw}$tf0 ,^g3|A}LN-DΆ%) H i&$-^ 4z"x ꥀ%[&VLŃE9FJHMPLs}^z4 ;B4kw%I9x<;9&6}t|1PqBƞ!,nbW Ϋ~|-|l5JJR9+UZ|6ꆅ`YhjAҝ1^#4GWu>W<$E2>8ӳSc(E{UxtFOr__ե@n}y*ny}Hmp[v2HEehs/maӘ% 4۸dNgX`ϩO>Do+ZveF~d"p9б|od *˪Z]n]}o{u s;l+}E 1"d[x0N,TۭJhwz`Owˋ!Mj Ȭv+){d؄wwfoWR+}Qā!YF@?nd xUHۼ}4&`[g@'DZ0AMEq$_{+5\l%Niv8$ O|Vj n >VQ:{h|E  $r/7~1e4ұIy RK4*+*?;ɰc[sƓi<8(y.&JHíCčљBT2wD93Dmw92h .2߭߭HӼ1~j_gRuOTt[@8&ǿ循^ǏF/a1TQ5cMrQqtWU\־ ML$NGL̤Դdٓ=9]ܯ7j 輷sH ΐOM㵅NuU_j?徇iY8fj/OYDZoғˆXfgG}FlHM.O]ϫ>QÏϟزs~@%KJT?d{:3XBߋ)j_z17Ç=l/Ijt+M`=}o\ڤfcHIy A;ϒREmY}CP`1i9_R>U*e8H6YcFUvk N.*{5D09nfr4>]tҊY"!yEvB 0\VPvQkgһ;m,%NiU*my~n.i=x 2UD7#L{$E*jCJw8B& ]u7i56~'36&Yp5.V jk~?ˬDmyU!1m|ZVDd9[=6&lRR}b]g*Ipz&IúF& /{Ѽxz |E+'o5yXXmkesh[gkU>cGpznW9 ] HgsMddIab):Ǧ FRj(Wqf5bET[[i\e:jˈ aA!*Eȑ|JIYDۥ05\J8P`2WM64nk-2XZ4e y8122ƍVEaz&||ͫ6cfZmVA5=׏&ve^oxOp.`?ˆ|\*sbqX]Aϲm{yGNS< rI2ϟ,GxHtlS*#y sWkIt`⊐7Xl˕ +1N(eX=UtZbegYi kC}`2ls8qNK2z9UϿ_ $-,{[Zӊ_)2ߴ̸]vLEqEg^ 3aAfunN ADF`n|{'ck~9YU1QAyKUhw pgh5~*s46k'[۴Wi}8.wf_`2Nut ܄nB _KAVBn= d'se<8g yLITȸJ` a.is,Xti6›/_̣pD`/ 6ʄʢ'*=6{#y<o,A,=XV[_MKMo5`qeI_OV*i3dܺ#*YPu$jO'J&>GJ6;*7-W޸DVPHӾ߃`p2d?.so܁4ʯ [_#NXɿҔ|o ;8&R^pd/4$Vvɪ;"=|Tb^z];`/w{uoO3kYIV*S#m%Ch=#aEBR:;Ϳŕs=ittvr99Qt%`XY[3OԘ CrEū*D;dM&՘;Va̵PC|dI3/5DS6/Qരv\/ɐp;M_l\l =JvM&8fϙ4`:Q Bԏ6n8Rъa/糯'{X&RٯOc4_U>o/|oZoPY& i( SBu[Ô9w߸Xh+@ЏS}Uze }x- TK˰R%5ڗ )ldYCS0TI8Uvչ dx?XV9Fc*2 4햳G bK"tx2h 2Pq473٢ǂFW8,Nc~T)]|?y8֫Xjؔ$ZthʣBk訃E?M6BћlNq"7ywb\a8CXwiOg]c K`u.?4?zc u!ɕ忠#_i7`]%O:9fQ8TS.DJ':uHϨXDSt>YzƁݽݖ}*H-s^R4^FE{i ɰ_5}\QP|y4YK#P~9N4ɔ|کb,T v+ULiL+7|.2m03?L. >C*]MNeQxe({4ȱlJ_R=㛮`虍j2I"Y΢ɫ#xuTL7gBl/:|6d|Bc:u Ndf'$":-': ûE`[mHII]pWρq*c*ۊ8ZEPK8&^#sy=^<6V}-sUoKpϮzPam  y!r35PȽη#Q@O0Ԯ~,]rȔ翲bDwt.vo@|iZ#U#J-Q<U?I4wѱ宋Ԛz_2kS–k!a1#6vHϛUm>JN,"h#fXf PVQ>LwFO! ͬz?jROx|*:=?1βk)FYڣ*/ Ǡ<7]~ X|CoZK-^7oWk$uBxD@bt'jЍʐ+7c11{?o#})?=VNgpP`NW$HG!dNI_jOfj"y|-)a+5nJ=*=ӆ6zުk)Ie#g$ b7*K[.ЃךEaF136*͗zY~j_mX7%ڃ JqFK/0Qik?o!yI\B, /X郇P:Ngu3{5"uje7z A`Ѿ! iy)Gλ9Qx7ع̘"V:x%ˁa R*i'׋"2k$.DB4UN q^XkhmQcHq5!yGg #HM&Cnp]['<  ?'j=7j_AI̸iNR )k YAY_iςŸt$6 Dr'A#dо3>pMɻ1FpY` s2e NޤAK[L0J=;4.A[^-F[͠&*KJ/X5 1,7?O~v׵^}m+z>6cg]աExKdO*rYrUpPam.7*;Y YY1!T+B2Px.m1y`H,iЁh *Do=]ӇiK<[1dzug.&Hʼ|(*jcbQzj8qˏcX |gUk B|6yW*;?Bv Pa7>%"Jd;`BA9m |ޫ28K 4F@vJﳛF]~]C٦/J[<5|Z9.C5 kG,lZЮƳfmVk4ft>k䣱zũ8)74i^3;N'ȯ)zlLwS+SlѸT0@;ֶ\@;Ks}h>l.Y2u㖹PIRPA+"9Wy>e5'|-vhG+2l]# ( }r&{ W߰hu./c-6ev&4a@~y%9MUMX k۟=X,K,ي_6_gA ETp#ѣm+]Cy-_)"0pW[gtaՕפb`\hq{ n;?T&AZ$6 gÙc(Dچa5;"_\cA)+R z^fLmݗY _]aUza7\vP_*BY˓Y11TT)=`Q҅Tܹǰ’`ԝzF]vZNuv(/YX1bV˅cx(k}J 3{_=?P",䋜 q5xצG" L߃g(!>b9y&%to]/kE'8Q3gpk=`acGݎώEXbJL7&-WP@sXґp^~@}j}9C#YUP@7S+ե9e}Ui͵C4!l1c:v9LZ޹.:޺̦t2㎇S /'f:7+K5[e{~bTT!gQP\ ze*] {ѮXL)T抴NK FORYLl R ʟ6{ۀnMh{y)zao2м"mt5ʾxp9d/SatV,=@w{.xS Vbi^ :ʡˣ:6ZiUSطua`I7CYR^rLk~RbHJC=Uѵ27*lƞ(*jNЗPUHGU)$CKt1+y$Yth+0[bRը<AXfήߵӠc D*TS>fS3޲ګCY>5śJ*=8- (a5'Imp=%r.O.L}XB0b8ARߪ FbNYb͆-;8ZT{_?o>| P`!Bst˓zoP͠$USwPI/rݎQ7]7&L*$p}wuρOK l@H DBLBX"J `qxDPitpy|P$Her+*F&j3rmj^,2iَaDc4ˋLOq!6hOw!!PD1X;5I24DA[2Tpiȕ CIdEtôl bSTjae݆\  $VY@ 8D(z 茅 G &n\"3]Nl)1/7ߋ3\šҲr>VOTUwةs_RE">@bW"W)&:$gCp?({g6vBR%1i"-o-6`c,TYW=^Atyidqjcָڗ+أECO"\7Hf%5ISL&U`HS%6^IZá s7ypĭ jFmQO1:/ؤf@}L~ot/4;2F&M}؈Yf~ EJ=i VD;Qn jLNBW:+'nZ)Ү!Bpe w}8Q"w%b=Q".Zg8s zP4$>F9[( I';q@1 TU<7G"Β-j^F2"l܈nCQ390•,*EP'ڥ[@yTKnkVPP3B2Ԙh+&ځdGw|"Y< HYd;5biS^ +V4uґSH*x*@-$F%(sSkEׯ6 iN e%"|E"L(dU(DP&\g"L(dU3&I2W$+B*"L(dUYwi^OzOF=1Ow6<:~!]SzM\\U]I]$߭yn (=Әaxq= cTREPޏSd3Oʐ}Z ɫZؚ|щOm4}X缓ɶIp*%"L(d~1cf zm 4v5ۯܝv 69p&ɊP3~!Y}2$ex>DP&\jZ+?IP iOkY~|g!qiN} ݳ" $Y& .!گO[϶2T8a~tԎTꡪ[oEUP;ܾ\^p[~PݕȂrXmAi5|]1i7)YUFA D)Bi25BLA rWIs6H2{&"BbҦxn0+`J ٩0fTV6dv:^ {nPm7K0@p  h ((i4DlFFm|ըU?E%~i)5m8W&;,K ?0pl,o_9]uAI23$'Klq%OzJ-)g׍}MWT8_@Wٕ3"xU\dZ.*/ E(pׅ@$[O|yIƿd inc/fonts/OpenSans-Medium.ttf000060400000375634147177152050012160 0ustar00 GDEFȱ`GPOSo7uL9GSUB홗8OS/2,k`STAT_@@Zcmap8lcvt =B,0fpgmZogasp#|glyfa,O@head4Yx6hhea k$hmtx6Yloca$HTPmaxpPl nameO,post&'jprep{@  rr++23|/01A#34632#"&\/M87NN78M L??LJDDr+2201A#!#S&&H&&29@   ?3?39/333233233301A!!#!#!5!!5!3!3!!!=SSQM>*RQQR=uǒVV9QQ9u"$,5(@..(, - %#/333/393301E5&&'5.5466753&&'6654&&''wGIiVdx~mQ?GNdnk+_O~B[.(Zw& "5,dcfT*"&o(Zk VG1A1`)B.3F3\g '3"@(." r  r+22/2?+2201A2#"&546"32654&%#2#"&546"32654&IEEIKIHmթ+IDDIKJIxJh%0<+@70& - r r1r+2++29/9901A26673!'#"&&54667.54663267"6654&ro[w4C iP'>ktJ`0O.`Db3|v>QlKCtkcKcJA^[ߡ6R-_ju66kwGeN)QdEnL7TRExG@xQJWS r+01A#S&&R5 r+/01S473#&RAfA^fA1?#z0x;>! r/+01A#654'3!Ag_AB`gA3w"7<${Sz@    /2901A%'%7&ﲯ'zq#aY`>$qc,  /33301A!!#!5!3kj aN /201e#>7 7B!'! IJPHMG}/201S5!MϮ  r+201w4632#"&M78NN87MrL??LJDD r?+01A#!J`2  r r+2+201A#"&5463232654&#"26uj`ױi8~hh88}jj}7ݲeQQ @  r r++22/301a#4667'39%g5YQ&1B`.@ r r+233+201a!5>54&#"'>32!.2nJodVl;dl]tϞo]rxID2Q0`vuo Y$.@ $,r r+2+29/39901A#"&'532654&&##5326654&#"'6632N[xuZ[bZ{N{L}k2cQec\p&*.3Vm4AvOgq!6">X*m @ r r++29/333301A##!533!4>7#mRk/kJJ;2[RG(V%|#!#@r r+2+29/333301A2#"&'5326654&#"'!!66@yrEJajV=.^8"%ne‹v((+5Bg 9mi8"1@))# r r+2+29/33301S4>32&&#"3>32#".2654&#"i%Y,k#&^/Z ^YhrӒlL}\K$Jppڥ^ 1P/iȏxQġNu=?kAT5@ r r++2301a!5!L_1.<@+6# r/r+2+2901A2#"&&54667.546632654&&''">54&I~sKNZXyڒsTRGuEuʬIT"UxA&lCrGDm?PsXc'*ldza]{ek&(fZpQhmEhS" $WolhaFaGGcDbg^."1@))#r  r+2+29/33301A#"&'53267##"&&546632"326654..%Y+p$&b/[ \]~htԐmK {^K$JpGۥ^ 0P0iȎxQ;Mv>>kAf r r+2+201w4632#"&4632#"&M78NN87MM78NN87MrL??LJDDM??MJBBAf r /9+201e#>74632#"&t8A!(" M79MM97MHJPHM??MJBBc-/22901e5-6 kl$ /3201S5!5!lHMlc-/32901S5c 6?ekSU+@ ##) r r+2+23/01A54667>54&#"'66324632#"& MDJW'}q`KGV{:mM@EK:6NN6:K9Mqc6r EE .5/32/323+222301A#"&'##"&546632326654$#"3267#"$546$3232677&&#"+Y[Xp 'hnȉ[4F0>T,^y^[xBNf[pg M*f|8_WcFHaҮwi!( fFfhl6$&0TCv _+@ rr+2+9/3901a!#3.'Tà.+N MDeX^)[OQ%@ rr+2+29/39901S! #!32654&##!2654&&#>vVZQ~CUX NpaOtosexLm:|r  r+2+201A"3267#"$546$32&&4q|Biԡ`WTxג\nXLIOԅ# Qm/*!2Z rr+2+201A#!!24&&##3 ZoFzw @  r r+2+29/301a!!!!!!5ChM  @  rr++29/301a#!!!!4B|4!@ ! r r+2+29/301A!#"$54$32&&#"3267!$sʡTx]JNel[6 /'(PR.)#1/ @  rr+2+29/301a#!#3!3//]b rr++01s3J_t r/2+01Q"&'53266535P J*8\6at ,l`q]@ rr+2+2901a##366733i467E  "DJT1ml--lo2c)@$)rr+2+22901A#.'#3>73>7c~     J%VUDCTW'_,[[U&'Y\Z)u*\\T$2t|<v @  rr+2+2901a##33~;a`:m9@@ rr++2901A3#3Np/GP @ rr+23+2301a!5!5!!Prmr/3+201A!!!!m3= rr++01S#"J3r+2/301W!!5!!32ÛHLr+2901S3#Hl^0wH/301A!5!w{R!  /]9901A#.'5<JQ!%ZZJ!.qj&PYQ\a(#@%%  r rr+2++9/33301A2#'##"&&54$%754&#"'663265Qʐ'.d^dYsgUH@Nj1"(6qeXR$%@r r rr+233+233++01A36632#"&'##"32654&t -oɈ-&m8B~"He_BVmbr r+2+201E"&&546632&&#"3267f}Z5<8:jFEeY<:zz$"]\( mD$%@ rr r r+233+233++01E"323&&53#'#'26754&#"(U]  ɟ! ](#.L0p*0O.m'b@   rr+2+29/301A2!3267#"&&546"!.[niXStzޕz 8qb{r('&#[N!(@r r r++2+23901A!##57546632&&#"!ɻVsEs*4"T/WSMa=LN pqM?c/?K-@" @@ 99))Fr0r+2+2239/3929901A"&5467&&5467&&546632!#&'332%26654&&##"2654&#"u,?EEWje@:|$/0+,'J5遭X9pRFh:onpnkqrgS4=Y*$pwX w&h>;&$ȓ4`B32#4&#"#t #gI\txr:T3b!:M'T2[ r r++201A#2#"&546tf0EE01CCNN8??99??8@  rr+2+201S"&'5326534632#"&23U!@(CTCC10EE01C JddRd?88??99Y @r   r r++29+01A36673##sM`F.u1b"x'vu r r++01a#3ub'(@$%! r!rr r+22+++23301A2#4&#"#4&&#"#33>32366pkj0^Hg{7ɟ !e|E|( 5b/Ws:Y~N9L'Z\]Y[b@r r r+233+2+01A2#4&#"#33>Ͽtxɟ #lb2N:N'mnb r r+2+201A#".546632326654&&#"nGxpJ|砘Aki@@l)ՓMMՈbb~`b(%@rr "" rr+233+233++01A2#"&&'##33>"326654&oɇU[  ʥ [*j;8n^}=b-K+'g)>81Q0S| _f{lCb$%@rrr r+233+233++01A467##"4632373266754&#"z -oʆ/l<(b&JeeIyR|#:b@ r rr+233++01A2&&#"#33>F?@tX2ʢ "ab0[TNn]J]\SN@ r r r++233+201A#'##"&&5332665S "lK[svs;N9L&TK[5#N @  r r++29901a336673]- 0\NoA23@FO*@")r* r+2+22901e.'##33>733>73.  ͗ ڳ @'^^QQ_`'M:|n'MUPb,mj&"l<A ,N @  rr+2+2901A33##4jQ%N@ r r+2+2901S336673#"&'5326677 ,$'oh0I?"?[A2N1]W*3KziQ 1Z<J~N @ r r+23+2301a!5!5!!~DI23%@  r%/2+29/39901A.54&>54663ĉY9oQQo9]Eb4noql3bFCi4EU'&TF6iC%PAfz zfAO$//01A3#㟟G%@ r/2+29/39901S5>54675&&54&&'53"GEa4nnom3bEY9pQQp9]$OA.gz {e/BO%BiFU''TEhDcG-]@  /33/322/301A&&#"566323267#"&)Hd/933|J=vZJc-;}20|K55#53466oID@Nkwj)B&>s0g%$!g0r=GsCDsFHtEEtv,@   r ?+29/332233301A33!!!#!5!5!533H]f)*j /2/301A3#3#㟟*v6E@/!3:'<8#&YvSg#&lN& )V:(;;'(Uxm2MD&YB2QG%Z.   /33301A4632#"&%4632#"&.<++==++<;++>>++;u733765567337655dD.B@ "9 r(/ r+22+2201E"$&546$32"&546632&&#"32672>54.#"ToptpaA992b.~}1t41hgc_犊^]pqpp#цv z_ꌅd_댆c? '@$$ r+22/992301A2#'#"&&54667754&#"'663265uf(uLBc5InlO?4j118btQ:0a\wy@]/;-]EG]1(?7i%?51.`NPs $@    /329233301S%P\_0QRQRc) /33/01A#!5) MG}dD *>#@ 5!r + r+22+22901A!2##32654&##"$&546$32'2>54.#"<c@̇mR[T[koptpc_犊^]aquaQELCpqppm_ꌅd_댆c/301A!5! lKr+2201A"&&546632'2654&#"bSRdbTT`YacW\`_KP^_RQ_^PfTWggWTfc.@   /23/3333301s5!!!#!5!3cikj3a3Tx w?32301A!57>54&#"'6632!MS F<8c5Q>\4iNTxK`N,;?-+i4?sBpsI+E)@  x#w?229/39901A2#"&'532654&##532654&#"'66]WEV_K>C@d^jivqhWL=;i7L>~dPilPw"(OECEwN=:=*$f-8R!  /]9901A#5>7KZZ% OL!QYP&jq.\N!@  r rr+2++23333/01A#'##"&'##332665\ !XuKPt&vxt9N7M(4.K[1:I[~5xj /2/39/301A####"&&54663!j|}L'}foDž7jA `ڵ^>WZ  /29901A#"&'532654&'73"<B@GcUV/0O0erx'034 c ,GPT @ x w?901A#4667'%3eM"EA+IfA   r+22/301A#"&5463232654&#"ưaQU_^VU^^WjRpswwssusNs @   /32901A'7'7_U]]R`_Q\]R`_Q\=%6@" r  r+2/9+2/9/9333301a34667'%35!533#35467]u2eMs` :JJ"EA+HfpC?,j1` , -&@++# r  r+2/9+23301s34>7'%357>54&#"'6632!^]2eMMS!H;8c4Q=[5hNJJ43.+HfxK`N,;?-+i4?sBpsI/J-8A?@1::44/>772.. r'( !!r+2/229/399+2/9/9333301a3"&'532654&##532654&#"'66325!533#35467m^K>DAc_kjuphXL=`VEV`5sa 9J:"'NFCDxN=:=*$e.8~eOi kPxpC?,j1` 6wr^+@ ##)r /3+23}/01A3267#"&54667>55#"&54632n MDJX&~p_KGW|:nKBCK:6NN6:K9Lrb754&#"#46632L:UU: RJGg8aza7$^j4kc#SJSb*8TS8oK|I|ՈtHhOA=%.=1.avSpI" 'ZN1GH.4WX8AYC@L7QQ+cViOE\!&DC /r+01\!&Dvo /r+01\ &DJ 5r+01\&DQp :r+01\&Dj >2r+01\&DO )V+44\b1=E3@ A%,r!229 r/>>r+23+299//3+233301A2!3267#"&&'#"&&54667754&#"'66326632665"!4&&j7eTSm^|*1qnc\nݦudQG@Mh}+9eTSKu 3jb{ߖt('gLIh7HppRJze/#)5T\T]qeXRCc[Mmb&Fzom'!&HC &r+01m'!&Hvv &r+01m' &HJ ,r+01m'&Hj 5)r+01!&C r+01L!&v: r+01| &JX r+019&j  r+01lj$4!@%$!  - r/+29/9301A7#"&&5466327&&''7&&'"32654.E:O`L{硔wؐIv[ ~SN)[/kABj$Js I*ssZ餾xw3'pLu~7OocUž:hR0[&QQ 'r+01mn!&RC 'r+01mn!&Rv 'r+01mn &RJ -r+01mn&RQ 2r+01mn&Rj *6r+01c. /22201S5!"&54632"&54632c1CC1/CC/1CC1/CCq=BE88EB==BE88EB=mn"-5@&& r' **  r+233333+2333301A#"&''7&&5327&&#"4&'3266n}L8SxZ@FL7NzW>E!U4dTT2i@)"!tR|KЅ)%#nRxIˁJ{0WӿEv.bS!&XC  r+01S!&Xv  r+01S &XJ  r+01S&Xj' -! r+01%!&\v< %r+01*!@ rrr '' r+23+++2301A#"&&'##33>324&#"3266ndžV\  [WΉ_|=*,I-BD8E$e0P0ȹ#`%&\j 3'r+01+&$L i r+01\t&DL +r+01+a&$Mi r+01\&DM -r+014+&$Pq\4a&DPc|&&v1i &r+01m!&Fvq $r+01|&&JOi ,r+01m &FJ *r+01|X&&NEi &r+01m&FN $r+01|&&KNi r+01m &FK r+01Z&'K,i r+01m&G4 1V+47Zm,*@ r'  ?23?33+?9/33301E"323&&55!5!533##'#'26754&#"(U^  eɛ! \(.M/"s(o/0O.Ծ&(Li r+01m't&HL "r+01a&(Mi r+01m'&HM $r+01X&(Ni r+01m'&HN &r+014&(PBm4'b-5)@#&1 & r.r+2+29/3333301E3267#"&5466772!3267#"&&546"!.#0+!4=*kn;[1QZ#ȐniXStzޕz 8q./ } k]:m]"BdR&{r('&#[N&(Ki r+01m' &HK r+01|4&*Ji . r+01? &JJ[ R{V+4|4a&*Mi & r+01?&JMx P{V+4|4X&*Nwi ( r+01?&JNP RV+4|;4&*q7? &6"J r+01/&+JDi r+01[&KJ[ !V+4'@  rr+2+29/32223301s#5353!533##!!5!//3]T["#@! "r r r+2+2+9/33301A!!3>32#4&#"##535tf "gJ\txr:ɛ3a!:M(U\\ϑS&,Q]i V+4&Q; r+01a&,Li V+4Et&L r+01wa&,Mi V+4c&Mz r+01d4&,P<4&LPX&,Ngi  V+4t&,-W&LM _t&-Jmi  r+01| &JX  r+01;&.q;Y&Nq=YN@ r r+2+2901A##336678[3yNsNM2> &/vQi r+01L&Ov: r+01; &/qo;&Oq&/4 V+4&O4F V+4 &/Nb|&ONo  @  r r+2+901s'737!aOP{9ky;4 @  r r++901s'737dPwQ6>r%ZQKb&1v<i  r+01[!&Qv r+01;b&1q;[b&Qqb&1KYi  r+01[ &QK r+01'Qtb!@  rr/2++2901A"&'532667##33.536T!P.=b;ct  *cU-D0CRW\b$!@rr rr+2+++23301A"&'532654&#"#33>32+0M:#;Ntvr<ɟ #jJ[A JdRZN:N'TdR|&2Li #r+01mnt&RL #r+01|a&2Mi %r+01mn&RM %r+01|&2Ri '4r+01mn!&RR '4r+01|(-@%"" r  rr&r+23+2+29/3+2301A2!!!!!!#"$54$"3267&&4i-(+Q,j4ב&vq8b̜9m'(i M  SQOԆ;k>`$3;-@!%%74r,,  r+2323+239/32301A2!3267#"&'#"&546632>"326654&&%"!.snlVSsB?Їz垂=(sD?hh>?w 6p`zߘr('&#omlppkFb3ƅ]\\ [L&5vi r+01:!&Uv r+01;&5q;:b&Uq&5Ki r+01X &UK4 r+01f&6vpi 7r+01e!&Vv 2r+01f&6Ji =r+01e &VJ7 7r+01f&6z@eb&Vzf&6Ki 0r+01e &VK4 +r+01;]&7qB$;H&Wq]&7Ki r+01$&W4`]!@  rr++9/3332301a!5!!5!!!!*EEC(β2r$H%@r r+2+2333301S5!267#"&&5#5773!!5x+X "q;ZWG|?Y+d >n]J]\+S&8Q"i  r+01S&XQ  r+01+&8Lji  r+01St&XL  r+01+a&8M\i  r+01S&XM  r+01+&8Oi V+44S&XOK V+44+&8Ri ( r+01x!&XR) , r+014+)@)r$$  r+2/3233+201E3267#"&546677# 53326652+!2=*lm@`0?U*mι~M;5 } ojB~h Cna^N'Z[s4[N&XPc&:Ji 7r+01F &ZJx 7r+01&<Ji r+01% &\J[ $r+01H&<ji r+01GP&=v~i r+01J~!&]v r+01GPX&=Ni r+01J~&]N" r+01GP&=Ki r+01J~ &]K+ r+01 r r++201A"#46632&&"UX[oGj)2 Szhr`J %#@ !!  r/2+29/333301A2&&#"!!#"&'53265#575466;Fm(0"N-TN Lp*P>"OPR _r>yN  Xt`?}E/*7&@ 0077%/33/3/??9/9301c&&54632#!!.'2654&#"5>73 +1dc1+ ؝ٟ  J4?@32@=+B=AQS#Z>hvug>Z3NT#@@7l<76<<65> RU%>D?\(4AM4@%% r CMMIGG)5/<r+2222/333?+9/32301A2#'##"&&54$%754&#"'663265"32654&'2#"&546#5>7Qʐ'.d^dYsgUH@Naj1"(6qeXRd=45>>54=j5aDivuifu' LMFH&vi r+01\!&v M,r+01|&vOi 8r+01mn!&v 5r+01f;&6qe;b&VqR$ @   /]3901A#&&'#5>7%[d&6u66r6&aZ -qk'"c77a$(kp-R$ @  /]223901A.'536673NZb%6u36u6&d[.nk'$c88d#'jo.Rt /]301A!5tR /]3201A#"&'332667Sdy5Z=6Z;UI89:5R; /]301S2#"&546/EE/2CC8??99??8R  /2201A"&54632'2654&#"6eebc2@B00B;vhfvueiwl=54==45=R4 /3201W3267#"&546670, 4>*kn;[1fFK./ } k]:m\ @pRO@   /]33/2/201S>3232673#".#"R%=Q0-SLH"+6o {a,QLI$,5AdD##.#9=$-$9=RO! @ /]33322301A#5>7##5>7OBST#qEBBST#qDA!QYQ'ko.QYQ'ko.&l /2201A5>73 9E$&^gc)1;   #@   /33301A#5>72#"&546!2#"&546%=I&_!+88++88);;)-77+jn1*jo.3765567337655673 5&$ SMfi'(S'+SK',S&&2_S'<HSW&u]S&T@ /V+444+$%rr++201A!#~*@ rr+299+901A!5 .'! y{=1jc&&cg.(GP=/+|$@  !r r+2+29/301A!5#"&&54$323265#"MVS/,c͟`d>allR1,.@ r r+2+901A#.'# $ $J5tp-.ps4[0b1G+ @  rr+2+29/301s5!5!5!Gb|2rr+2+201s!#!RFJw3Jb'@  r r+233+9933301s55!!""&'663!J'!XUJMW]7<f!*!@"r# ! r+223+22301A#5.54>75>54&&y@÷=C򯞽S\ØYS˴fÞadbn–X^ou`bto];o@ rr++229/33301A##".53332665>µ54&&!gBxv[T./T]vzBhvܛRA$ǘAQ醜uWH&,ji r+01H&<ji r+01ml&}S* 4r+01Vl&S -r+01[l&SK r+01l&S r+01&T(6*r+01ma 3'@rr$,,0 r+2323+233+01e266754&#""32366733267#"&'#Wk;gy3 !2$% '.SgYUʤ'WU%T .OoF6 Kc0O/0)@))**r!! rr+2+239+9/39901A2#"&'#466"32654&&##532654&zxݛqCʁPOC]TfdQWĹg&"5c:{&.f>yxy+N@   rr++29901A#466733>7+j -/G,#(NSG;S@4w$ u1Gkl$3@"%1)- rr+2+2901A2&&#"#"&&54667.546326654&YTQc]W8zb{X蜕mzKr?ڲQoH^cHA+,9Q80NS5Avsk͑Ä#,bxL6[WKNlVb,@,,&r  r+2+29/39901A#"3267#"&54675&&546632&&#"3jCGXsEBjbmr|tRFD`{|(R<=M$4 !)zz }baA)%*LIVKmv)@ & r/+9933301E#>54&&'.54>7#!5!P2#<%"ce]^}Yt8 ,Oimπ\syq<ɟ #lbTFZN:N'l\! @  r r+2+29/301A# 463 2!"!\f߶fݲ V xcb Nr r+2+01A3267#"&&5mNO-^ r:^SN]\ = YNp!-@(  r r r++2+2901c'&&#"5>323267#"&&'.'#3%SU"7/3lZ)U$(# */9P9 52_XIrG29 &P<#ONG?F\NwN@  r r+2+9901S33653#'# s;ON(rm$yJkv<%@!!0 r+2333/9/39901S46675.54667##5!#"33#"#>54&&'.kOPEd5NW X]'8=VP{URhm8O.#:" ef_dh GmM[zL%KsMhlLZeh3D[;WC/c]%-'hmnbR N@ r r r+2++2301e267#"&5!##57!#3R3tGj6 UYJ`D9lb"@r r r+233++201A#"&'##46632%"32654&ls֔U: wߚz8O(0*(S ~12mvb&@ r+2/901A2&&#"#>54&&'.546T?=m8P-#:$"dd[n<b#!sID\uOtqbʠX:N@ r r+2+23301A!3267#"&&5!57\cS/_#!s@a^ܝNkZ ;fYJNr r+2+201E"&&5332654&'3xUɉ" [~Scmva)!@r" r r+223+223+01A4632#.54">54&&CM\Z_dx?Tj^4a\gfۏU U† % z©(cy hx]mW&"@ r r+2/3+92301S233267#"&&'#&&#"566H[A5P0>-.B/WtM ئE2)CW8nSD;K$ A{XmROO !@rr rr++223++2/01A>54&'3#.53wZ%!"!Xh _| %t%֑PrN0#@##0r )) r+22333+29/01A#"&'##"&&546673326653326654'u)5Zv# !t[5)@=tiCT(*T?Hc4=AN_ld]]dl`CxO6Uw>[| &j &r+01&j -!r+01mnl&RS !r+01l&S# r+01rl&S 1r+01H&(ji !r+01r !@rr r+2++239/301E"&'53266554&#!#!5!!!20X#J,.U8q< "^Xrk)·&`vi r+01|#@ r  r+2+29/301A"!!3267#"$546$32&&ChM >C|ve]Vwϒ] ZONw<|/O]xp("@   rr+22+22901A333###C?<<= Vb.@ #+r r+2+29/39901A#"&'532654&##5326654&#"'>32@ă[>D׿ZV_>nq_m&*,z>qNisE8,F(]q@ r r+2+2901S333#4>7##ƽ 1tpXJ"6zsYLq&3i r+01 @   rr+2+2901a##33n<<@ r rr++2+201a#!#"&'532667667!C!"Pm$G7 9D+ !&)4kRe YZ@,0/+|2mw3|&]7@ r  r+2+29901A#"&'53266733>7*>9j++c4JhK!| Ma /aL6.000fr;w @ r r+33+201e#!3!3ˮ@ rr++29/33301a##"&5332673x{zruT+2Juw+) @ rr+23+2201a!3!3!3134w9@  r r+333+2201e#!3!3!39P)*ͮ , @ rr+2+29/301a!5!32!'32654&&##g(mҬSzly]l- @ r r+22+29/301s332!'32654&&##3lȪPxly鬀]k,YJ @ r r+2+9/301s332!'32654&&##pWxly]l-A#@  rr+2+29/301A"'6632#"&'532>7!5!.dKM[xVY]d|ECHz0"*/i %D{mx>'!@ $r r r r+2+++29/301A#"$'!#3!6$3232654&#"Q V [ZZ\ݩk8^ \@ r r+2+29/3901A#.54$!!##"33~KS oPW^~JW4nY\aDpe"2,@.**# r r+223+29}/333301S4676673>32#".26654&#"pbЦ{|=y/Y~G dYcvEXFzU`E{O%, f*U8xݘ|ZKId'`UUN#@   r r+2+29/39901A#!!24&#!!264&#!3260vck]Ơzl } ju~6dv{t_SN6zYOP8GGI_Nr r++201A!#_NUN%N@   ?2333?301A3#!#367#!XYv@ ?dDNT"}1Qem'bH#N @   r r+22+22901A###33C-.BN//8Fb/@""!! r)r+2+29/39901A2#"&&'5326654&&##532654&#"'66zjp`DnBiեPu,FoTOFkw|yWQCYbB_cv @lQ\W "4#PA7!<[\!:")E9/$k C;oN@ r  r+22+2901A#467####!oOTN5k3u3k=fN^rN @   r r+2+29/301A!3#!#u5N;NmnbRZNr r+2+201A#!#ZNWNbSmbF+N@ r r++2301A!#!5!U%N\k&%@r  r rr+++223+22301A#.54667>54&UvMMvvLG"  fuvf & gu ,N[N @ r  r+33+201A#!3!33l#ɜNURIN@  r r++29/33301A32673##"&5[gadTWzNr`[:15CN @ r  r+23+2201A!3!3!NNUU8N@ r   r+333+2201A3#!3!3!5NRNUU)N@  r r+2+29/301A!2#!!5!!2654&B$b]ǠBvNAGhhTS`[IN @ r r+22+29/301s3!2#%32654&##3]ZszfNAGhhTRa\IN_N @  r r+2+9/301A!2#!34&#!!26u2a]Ĝ !z$pGhhTN\ISCb@ r r+2+29/301E"&'532667!5!&&#"'6632r`?AXfT >8832326654&&#"Nvۘ| |Њy:|dc|:;{cc|;)tN;p_^\\N@ r  r+2+29/3901s#.5463!##33!"8BrF޳xthL^R[[bam'&Hj 5)r+01\/)@'#'r rr+2++/339/33301A"&'532654&#"##5353!!3>322.K7 8Kuur;˛ "hJ[@ Kb'\я2a":M(TfR_!&v4 r+01mb @ r r+2+29/301E"&&546632&&#"!!3267~V@;=xu"GjrM' ebVL9&j  r+01M lN(@! r r" r+2+2+29/301A32#!!#"&'532>7#32654&듿^[ŞY<[Z$9")F:.%LrNAGhhTk D;S`[IN#@ r  r+23+29/33301A32#!!#3!#32654&]ZßT)sN?FhhTN=S`[I[E!&vw r+01%&\3 "r+01fN @ r  r+22+201a!3!3!#-~(NU(rr++301A!#!(i/lr r++301A!#!l (MN=c&:CAi 0r+01F!&ZC 1r+01c&:vi 0r+01F!&ZvZ 1r+01cH&:jdi ?3r+01F&Zj @4r+01&<Ci r+01%!&\C $r+01R{/201S5!R\ҩR{/201S5!R\ҩR{:K /3201A!5!5!5!KOO:~[ r+901S'>73' 8B!)! IHNGZ  r+901A#>7K8C!IJ:}6A'7\   r+301S#.'7 !)!C8GMJI @  r+222301A#'>7##'>7(" 9C"(" 7B"NGIINGII @   r+223301A#>7##>79B!)" 9B!JJMGJJ:}6A  '7 @  //9/33301A%#53%10H01[ _w'@  //99//33333301A%%#553%%B[0/V))V/0[)~~i /301S46632#"&&=iBBi==iBBi=^r33s][s66r&';\ : '3?K,@@4F: r(." r  r+22/2?+22+2201A2#"&546"32654&%#2#"&546"32654&%2#"&546"32654&IEEIKIHmթ+IDDIKJIJDDJKIIxJT" r+01A3#]Tr+2201A3!3  Ps</901SP\0QRNs:/901S']\]R`_& r?+01A#]JpL@  /2/233301A2#4&#"#3366|KNoYg"zsROPzs\44O$ @ r ?+29/322301s#53!!!!!!+=?"IO),@ %%"!! r+2?339/33322301A2&&#"!!!!!!5>5#535#535466qGCDOhxqo"?.CY.\.!&rNrLK|Xf" .-@% r,--*.  r /+29/3/3333+201A ####32654&3#3267#"&&5#5778՝=T9<>#O_?Pt?B_JՅ۔jLO =fUL8y6+@300'* # rr+2+29/32233301A2&&#"!!!!3267#"&&'#53&&5467#53>fRM32!3267&&#"yy]^,\EH0x&je/#֊B/L{o)LL(OG.<#8D.@93'?-  r  r+2/9+2/22901s34667'%32654&''"&54667&&546326654&#"^[1fMQPUL,<OR*I-?FvuU@Pc:GE?>ELJJ"EA+HfH97M /<&8Iwr9T?']MmtnnLc!#lTrB61::15B+G-;T`9@45COU[I<.< r(' !!r+2/229/399+2/22901a3"&'532654&##532654&#"'66322654&''"&54667&&546326654&#"A^K>C@d^jivqhWL=;i7L>aWEV_ QOTM+<OR+I-?FuuU@Od:FE?>EMJ:"'NFCDxN=:=*$e.8~eOi kPx-H97M /<&8Iwr9T?']MmtnnLc!#lTrB61::15BNJ"0IU=@ )*8DJP>1#1 r r+2/229/3333+2/22901a3"&'532654&#"'!!66322654&''"&54667&&546326654&#"?^C.77[kh`.KI"<$QOTM,<OS+I-?FuuU@Od:GF?>EMJ8!'OVLS(}/G98L /<'8Hxq9U>(\NlunoLc #mTqB62::24BU0 0<-@+17%  r r+2/33+2/22901s3!5!2654&''"&5467&&546326654&#"^];iQOTL,<OS]C?FuuU@Pc;FD??DKJJlH97M /<&8IwrUk#']MmtnnLc!#lTrB61::15B[>&6@4''/ rr+2+29/33301A2#"&&54>32665.#"5>"32>7&&}d+-^̄D$L|tT)ۜc.&*|c.&!*|g@ @  r?2+2901a3' *=S=)/! /]3201A#"&&'33267 WN `k^o fJHioNSj~  /9901A#5>7 0; q (mp0LUP!w;q t  /3201A#5>7"0?% #mt,(lq/T @  xw?39/333301A##5!533!5467s :pC,j1` DC@ xw?329/333301A!6632#"&'532654&#"'m<$D/67[kg`/JH"~!'PUMR':Txw?3301S!5!^;iTl2D'3@ '.! x(w?22901A2#"&&54667&&54632654&'"6654&muU@OddI+I-?F[,<OOQOTM>EM::GFnnLc!#lTrm^{B.$*/;J1%&4^0  %1}o0oo/mmmmmmoo;mmJoooo/yhI\ii\\hhCS1B :EPZb" "+% * f$2re]T!-@ !%++//9/999301A 5467>54&#"663232654&#"TV*C;N'9yp.RD7?>5DLCQ<8SS84/TbC,".:/:G5=qP;H??HL==z &KV  r+01Z!;G.@ #CC4#4#4- r</2+299/}/33333301A23##".546654&#"'663232654&'&$&5466".htQAؖpY% # 3.)m>_W bouP͋N}UUaٳ :Tk!Rڈ8p9d~D4e[!.$ fR.fn;U{6vxXTRLKyHfn8@rr r+2++901A>7>32&&#"#3J"HG@?Q7 4 !7%MYY$N-2A! ">(a/N4-@((r $$ r. r+2+233+22339/01A##"&'##"&54667!57!32655332654&&-Zu"#t3 ^1skb\,U?jq+NJPqd]]dPIWKEPwUw>O&0vi  r+01!&Pv /!r+01+&$SD\a&DS/ V+44n;  |/3201A"&54632'2654&#"Re~fac2@C/2@:vggvveivl=46<<64=|+@ (r! r+2+299201A#"&&54$32>533265#"TR/T26y~+*b͠_cݩllRpeOsH1Vz 2mE)@ ' r r+2+299201A#"&532>53326654&&#"n}蟕nB:>@pX "@kk??m))IDQvH_k@[]^\@ r r+2+993/201A>53# 5332665+=D 0Tcyμ~I MyPLjI'SZn")@r  r r++233+993/201A#'##"&&5332653>5 0Ta #jJ[sv7&&'3367< Vw(SHA}f? Pm5 $'Be9GpF OGNg2f#HJ&$bdшt"R$@   rr+2+9/322301a!5!53!!32!'32654&&##A2gnͻSBϥly鬀]j-'!@ rr+233+29/301A!!!2#!#535!!2654&_&]Ƞw'٢លhTS`[I0*'@ rrr$ r+2+++29/33301E"$'!#3!>72&&#"!!3267w٘ FjqVLK_i{L TAzsc\V7_[4+$532&&#"!!3267 ݊Y997>bI JdX@<mN:a&EgrL'{ #@  r r+23+9/93301A#####!'.*QPm EPK HffFOMCGDN #@  r r+23+9/93301A######!'.Ƚin}  98 N,,N!HG"MH 0@  r ?333+29/9333301A#####!#3!!'.;PrmFIG HaaahBGG"DEAXN.@  r  ?333+29/9333301A#####!#3!#!'.ff׽n}  3 4 NN7ɃMOv"KG!&@!  r?33+29/333301A#.'##>75!Qc{^$Ѕ?i[\h=Ԍ?Y\kLZ ]t7\j/T/j\LV`: 큳\N &@  r ?33+29/333301A#.'##>75!ctH~w5RFJR2y~ HvaNf N|UACM# "NDSS}Nif#&?@""%##&  r?333?+9/33333333301A#.'##667!#3!5!hd{]$̇BiZ[j?ӓ7%XwMZ \t7`h+V0iZLNj[߁[N#&:@""%##&  r ?333+9/33333333301A#.'##667!#3!5!IcuG~w6RFGU3y)ĽNf L|UABM# "MCS/PN=]f:GWZ=@$ /@@7/== +/RTWNNG r+22322/3/39/993993301A2&&#"326632&&#"#"&&546676654&##5326654&#"'667.'53>r$5 *1l-™Fۗnr'HbR}q?SajT;tUGXȪǺ[yW`Mq"SO1w4(Yi wXD`p>3"/8G{MU{Gu>qNisE85M)YS!m60`@hS[;@$ /BB7/?? +/SUXOH r+22222/3/39/993993301A2&&#"326632&&#"#"&&54667>54&&##532654&#"'667.'53>#5 ).b+wp_CmCdٮeg$J\Hyj1FO\/.yLv:KaKFjw}xQQC?zEEC1m9&YjS xK;lcw ?iQ\V/ 1.ErDMxG$M?ot|"@ r r+2+29/301A#"&&54$322667!"!&&VS/,[ig hǘl ݩllRy㜜zrԔmnb@  r r+2+29/301A#"&5322667!"!.n}蟕aEF__ G))NmmN*fH^@ r rr++9+201A"#3>7>32&&.=1J! -Sta+G17r[OBla2&NRZ0T cY@  r rr+2++901A2&&#"#33667>3&-"b' $CbY#D3N=O~%-Diy3^&q i $1r+01c!&r | "/r+01| !?&@?()":3-r"rr r+2+2++?3901A#"&&54$3232654&#"%336673#"&'5326677_M꟡JVSSWh .''of2I>#?[B2ݩllR0\W*3J}iQ 1Z<mb&R\|*8'@!$$$ r1.++ r+233+33301E"&'.54$766326632>54'#"&'J7G ْI G54GJ֋HD2/EzQG03DzSSv38|9;--;˗}83 ,$%+#(,''+阙m3'@%"r.1+11  r+333+23301A#"&'.54766324&&'#"&'663266gŊ @47> m>41@ m2fP;46; yqrz :42;yq)20/5"2''4ii)()*ʠ)#%&|S)kC@#Lf rU\r #:3riIFFCGGCC* r+23/333+222/233+2+201A54>3233#".#"56654.54632"$546632&&#"3267332654.#"'6632#"&'%BY5;psM\q^,76O;=):1=F=sI}O=L,j".54632&&#"32673326654&#"'6632#"&'#?X6Iԉ%^h6199(0`~%TGJQ24&]qi 7r+01'<&^ 4r+01{ @  rr+2/+201A2&&#"3267#".546$NrZMKbvDi߰5j.͘n4` /*#1PՅ ZG愦nmb@  rrr+2++201A2&&#"3267#.5466T<:;'66&&'#667%&&''&&'&&'5#'>7vCK<]-ms^-ms6BJMUIMN C#^( 62@.l,/.k-](Q3su5UJ!' '.B-k-^64]63A-l2' B#LOUI.mr5CJ;J<]EP '-]( LUJ3su5wUl''@#   r r+23+2992201A#4667##3333"&&'332673Х `L al]o Ww"<4M?/GjoNSjgJi%'@! r r+33+2992201A#4667#333"&&'332673AՉʎN bj^p Wh+hb N,gc(}TXHilQSjfJ- @r?3+9/333201A!!32!!#535#32654&&?riWk{R]j-f @?33/3/9/33301A!!!2#!#535!!2654&|;%b^ɠwGhhTS`[I7@   r r++29/33333333301A'###! 3267'76654&##domp2pB$Aav|28w?Y  W!mQb29@ r r r,++-**'' r+2323233333+++2301E"&&'##33>32'"3267'76654&U[ ʥ [WYPmr{!LRj;8n(zxy)'-K+)n%C81Q0GX S{!_Y2h. @   rr++29/33301A!!!##53u]͖&| gN @   r r++29/33301A!!!##53gWəNȜ.Ҝ&@  rr++2/39/33301A"#!!6632#"&'532>54&&L/m`m+~=[Qt`>>~GY\/sr  VR@{rm "N!#@!r rr+2++29/33301A!6632#"&'532654&#"#t#N'ỳIv6.wA~G N|w!@Nw?(@ r  r+233+22901A3####33u@=<<lN(@ r  r+233/+22901A3####33C[ҽl-.BNh//8V4b&kmF4b&kwX!@   r r+23+2901A3###3Ņn<<}N@  r  r+33+2901A##333d/l/Ng#@   rr+2+299//901A#3##33yyqn <<EN#@    r r+2+299//901A#%3##3c_/hX/N#@  rr+2+22901S5!##33#'n`<<E)@r  rr+233+29+01A!!3###535u`/ʝf/я  @   rr+2+22901A##!5!wn<<N @   r r+2+22901A##!5!/N/w@  r r+33+29/301A#!#3!335.w]b0N@  r  r+33+29/301A#!#3!33o5ȾN;T{ @ r r+2+239/301s3!!!#!/b]N @ r r+2+239/301s3!!!#!5%N;ŠRC)#@"(&)r$(r/3+2+29/33301A6632#"&'532>54.#"#!#1|8ZPub?>~GV]0C{g-m#vcVS@|pt7  N#%@" #r" r r+2+2+29/33301A6632#"&'532654&#"#!#5C szGr3,o>u@ N$xw!AUN|=N,@B::%r1.. rK/3333+23+29}/301A3267#"&'#"&&54$32&&#"3267.54>324&&#">Gr>M,'F49\G3CWC|%6b2ph2sЌ,4M*7eSie(N:,C.)F."6654&&R7[!,H(Ai- 6EO`XPpM8:G'I:,iLu;y*<D2>M8b wa @vxOK}5  +%՚Tf1^Ca-(h@]1|4&&k+m4b&Fkw] @ r r+3+2301A#!5!!3CGCw+N @  r r+2+2301A!3##!5N<%N@  rr++2901A#336673wR3 /RPK22MT%@  r r+2+9/33333301a!5!533!!5np4P.D7%N!@  rr++29/9933301A!!#!5!33667%ST/ 1NSNS==TKw @  r r+23+2901A##333Uw~;a`:rwm9@ qN @   r  r+23+2901A##333lQ4jnw@ r r+33+22301A!!5!!!33f34w+N!@   rr/++3323301A!!5!!!33XMɿRw!@ rr+2+29/33301A3###"&533267x{zruT+2Juw+)N@  r r+2+29/301A3###"&533267IWzgadTNT5Cr`[:13@   rr++29/3/3333/3301A##".5333667GLyp{@yLCJQ) .,ZbJuwY'?N/@   r r++29/3/3333/301A##5#"&533667?6m@t  bat;p8N#6p_Z" 1$@ rr++29/33301S36632#4&#"#wsyrt,1"vw+)E[K*l)2%@$$//  r*r+2+29/3333/01A2!32667#"$'#"&5467333>"!4&~ q֟`yr"`'/%@##++  r(r+2+29/3333/01A2!3267#".'"&&5467333>"!4&&.nrXStwP[A 57}z %9u`zߘr''&#Cƃ0bK'F9/4d\M*vl,5)@!!((22  r-r+2+239/3333/01A2!32667#&&'#"&5467333>"!4&~ q֟`yr"`)1(@ --) ' *r+2?339/3333/01E.'"&&5467333>32!3267#"!4&&zf[A 57ЀnrXG\Uz %9uؖ0bK'F9/4gzߘr''" C\M,&32i r+01#&3  r+01:+)@*''"+%r$r/3++29/3333301A6232#"&'532>54.#"#3667  [Tu`??NT`4Oj@q,,a0UQ힥R>xto4 37w6 WN!#@r r r+2++29/33301e#"&'5326654&&#"#33W}}Lm0.iAQ~HWw+\%/Bx!UT PNqw!@  r rr+2+2+201e3##!#"&'532667667!C!"Pm$G7 9D+ !&)4kRe YZ@, N@r r r+2+2+201e3##!#"&'532>7! ԉȃ<[[!:")E9.$k D9/@ rr /3++29/301A#"&'53265!#3!/b>=N.]b rN@r r r+2++29/301A#"&'53267!#3!rnyJo1.m=r{3NԼn#N;w!@   r r+33+29/301e3##!#3!3/.̵]bHN!@r r+33+29/301s3!33##!5֊ȃN;Tw"@  r?3+29/33301a##3#"&5332673Ļx{zruw>+2Juw+)IN"@ r ?3+29/33301A##3#"&533267IWzgadTN"=5Cr`[:1wi%@   r r+223+2901a##!3!3##4>7#A8'% -'hla"Yw#ek_DN#@ r  r+333+2901e##467####!!DȄOT5k3u3k=fN^T,+&$3Ni r+01\&D3 -r+01+H&$j<i (r+01\&Dj >2r+01\b&(3(i r+01m'&H3 $r+01%@ ""  r r+2+29/301A"5>32#"$55!.2667!d<;r[U1 rqr P/+jꬬiTEwoҗof!bsH&ji ;/ r+01f!&sj 5)r+01H&j!i 'r+01#&j ' r+01VbH&ji D8+r+01F&j E9r+01E?%@ r r+2+9/3333301A#"&'5326654&&##5!5y]`gQb“w% ɀp&*.3C}WVq8$N#@ r r+2+9/333301A#"&'5326654&&##5!58{yJLppSasN tˎ~'"$4QajFq&Li r+01t&L# r+01qH&ji +r+01&jS (r+01|H&2ji 6*r+01mn&Rj *6r+01|omnbp|1&ojR 8,r+01mn&pj 5) r+01A1&jR 9-r+01C&jj 5)r+01&Li r+01%t&\L r+01H&jEi 3'r+01%&\j 3'r+01&RFi %2r+01%!&\R %2r+01H&j^i ) r+01I&j )r+01w @  rr+2+201A!3##t^N @  r r+2+201A!3##^NNH&ji /#r+01&j /#r+01.Z&l _gN"@ r ?32+29/33301A"&'5326655##53!!!!3*'C5 ,əW6l_  2'ҜȜ]}@Z $@r  r+232+2901A"&'5326655##333)H4 .p~;a`:u7rZ 7-m9@XG _eN#@r   ?332+2901A"&'5326655##333p(C4 ,n6l_  2'Q4je]}@!@  rr+2+29/333301S!33!!##!}1xa_w5~Ua:[m ,N%@    rr+2+29/9933301S!33!!##!rXTj4Qv; @  r r+2+9/301a $5466333%3#"pz|R{w\J7rXwmDGu+#@r( r r+2+2+99//301A32653#"&'#"&&54>33#"3265nhcnx+0hAٗyT;uUwnfwuWMIZccw@_5xbUq8xWk&3+@&r!''r-- r r+2+23+9/33+01A32653#"&&'#"323&&5"326754&'[zld6hab~O&i[S{X  舆{}y~'ea/,T94U2$.L0"q&Ⱥ!?5#@&&%% r.r+2+299//39901A232653#".'4.##5326654&#"'>prR2SbF:T.~'db0)PxOEW)IXKJ%"&(?w( @ !r+2?39/39901A23##4.##5326654&#"'>(s8qo̍WzKg9Zk@bA BvMhuG0*D(O_`& @  r+2?39/39901A23##4&&##532654&#"'66ykn\Bk@Dj}uSLDX`B`bt @kR6>S)HWJM'"&(<.@ .r% r r+2+2+29/01A32653#"&&5!#"&'532667667glji߾zjg  Pl$F6 9D* !&)wky(OH7d W]B) YN(@'r! r r+2+2+29/01A32653#".5!#"&'532>7!cnec4f`aj8<[[!:")E9.$}vr~(eb0/af4k D9o%@rrr r+2++99//3+01A32653#"&&'!#3!fkje۽zhWxmw(O*]bN%@  r r rr++2++99//301A!332653#".55!#ueldd3fa_k8N;0wr~'eb00afoN|#@ #r r+2+29/301A!#"$54$32&&#"32665!UZFƦN]KMtvmۦN}b`PQ3+#7t|mb"@ "r r+2+29/301A!#"$&54$32&&#"32665!<ʎxQB?bWuCXL}ɎL-'0dKW @ r r+2+9/3301A!32653#"&&5!5TCjlkjzkL|xmy(O+N@ r r+2+9/3301A!32653#".5!5fmff5ha_k9Nxrx+eb0/ag6iw/@(' rr+2+29/39901A2&&#"33#"32667#"&&54675.5466l@fTzXS7!3(C3 ,<[\!:")E9/$5l_  2'k C;K]}@+&$\a&D+&$XR r+01\&DX .r+01+&$cR oV+44\n&Dc 1V+44+&$dR oV+44&Dd 5V+44+I&$eR  oV+44\=&De 6V+44+e&$fR oV+44\&Df /V+44+&$'Ji +r+01\ &D'J 6r+01+&$gR oV+44\&Dg ,V+44+&$hR oV+44\&Dh ,V+44+X&$iR oV+44\&Di ,V+44+a&$jR oV+44\&Dj ,V+44+a&$'Mi r+01\&D'M -r+01&(m'b&H&(XR r+01m'&HX %r+01S&(Qi r+01m'&HQx r+01&(cR (r+01m&Hc <(r+018&(dR uV+44/'&Hd ,}V+44UI&(eR uV+44mF&He -}V+44e&(fR uV+44m'&Hf &}V+44&('Ji %r+01m' &H'J -r+01&,XR r+01w&X} r+01&,&L||&2mnb&R|&2XR &r+01mn&RX &r+01|&2c}R =)r+01m&Rc =)r+01|&2d}R -^V+44@n&Rd -}V+44|I&2e{R .^V+44mn&Re .}V+44|e&2f{R '^V+44mn&Rf '}V+44|&2'Jki :r+01mn &R'J :r+01|&TvKi 3r+01mE!&Uv 1 r+01|&TCi 2r+01mE!&UC 0 r+01|&TXR 1r+01mE&UX / r+01|S&TQMi =r+01mE&UQ ; r+01|&TmE&U+&8VSN&X+&8XSR  r+01S&XX  r+01&Vvi 'r+01!&Wv *r+01&VCwi &r+01!&WC )r+01&VX\R %r+01&WX (r+01S&VQi 1r+01&WQ 4r+01&V]&W&<%N&\&<XR r+01%&\Xt #r+01S&<Qxi r+01%&\Q= /r+01m&B / r+01_#@@  /]399901A#&&'#5>73'6673#o3m35k3p#NKKM#Q); +n6n#U11U#&X^..^X&0[@:i+x#@@  /2/92201A5>73#&&''&&'53c"MM KL#p4j54m39m, <('X^--^X'#U11U#+i:@[2_(-@%""&@  /3/3392992301A#&&'#5>7%2#'6654&#"566 KM#o3m35k3p#NK[hI7[ ?<3-' ,.^X&#U11U#&X^.EJ:> L~"! [^+%@++#(   /3/92/222/01A#&&'#5>7#".#"#66323267 MP$h7n54q5i#QN0S:'IC?), a dU)KC>)+ -[U'"Q11Q"&U\-@e9&/3`'11d @   /32/2|/3201A#"&'332677#5667 rgXPn CH$f$=􁚖V*+ |}P55P(@c9&/4`|&11'4{  /3/301W4&'7#"&'5326LE@ipf#@3&28u@.V^m }0Z /3201S"&'5326655#53(H6 .7sZ 7-XG]&7zd$H&Wz|4&2P,m4nb&RPx|4&2'LiPA #r+01m4nt&R'LPx #r+01f!b@  rr+2+29/301A2#"&&55!&&#"566!326{ޖnhYS7rX{b{r&(&#XZN~X#'2]v2V+44X1 @  /222/33/301A56673&&54632#l5AK%uq;4-;&8?:G*hk. zd7F/0# #5)C  xw?3201A"&54632'2654&#"jRLLROKJC,D,@  'xw?229/33301A2&&#"36632#"&&54>"32654&GB#o8lSyL_`V(c6Q,'N9I[P PW*=]KWeUB)@$0[:[XJU%D+@ $$ xw?229/33301A2#"&'532667##"&546"326654&&]_W(a!I?+o}8 gQF\NP6P-&MVeU TT(@XVJY(@#7Y6&{@ !V+4444&|@ V+4444&z@ %V+4444&|@ V+4444&@ (V+4444&@ "V+4444&@ ,V+4444&@ &dV+4444q&@rr/2?++23301A"&'5326654&#"#33>326Q N-6^:F͠" 'V{:kq  )h]mʋBc7j۩:ng2tb (#@ rr r+2++2339/01E"&&55332654&#"#33>32ܲ~OtF͠! 'W{{wRɯmʋ~Bc7j۩(W %1%@ +&& /33/232/3301A"&'332673"&54632!"&546325>73 u iXOoy+99+*;;X*99*+::,)EH%˖{I9?Cy5462264554622645 ?E'#KEW %1+@ 0&@*,,  /33/322/323301A#"&'332672#"&546!2#"&546#.'5 u iXOot*;;*+99+::+*99(-h#JDy{I9?C2645546226455462'E? EK#f'@  '! /33/33301A!52#"&546!2#"&546#5>7s*;;*+99+::+*99=EI$g,)x2645546226455462$JE ?E'f '@ " /33/33301A.'535!"&54632!"&54632#JD),tj +99+*;;X*99*+::EJ$'E? ֕5462264554622645 @    /33232301A#'##'##'5N&./&/.&L.ffff.!&II!Q&IL!@&IO!&I'IL! &I'IOy+&@' r!r+2+29/9933?01A2#"&'532654&##5.#"#466͂}nmlOOWo(OsNwKVjeq#),0~94F%ZsY(&@ r r+2+/93/301S233267#"&&'#&&#"566O`B!n!27&5 J+WmQ-7I%<77! F5pV#i\LR Gv@_[ ' @ r+2?39/39901S! #!#32654&##!2654&&# @wT_IJxVV Qk^9tqtkPm8 &/z V+4b&1z= %V+44+&$P4&(Pdd4&,P V+44+&8PRt (@ r  ?3333+233301a!57'5!tު"v/k0vv0/8 r r+2+01E"&'5326653Ip*0k;8\7b,m`"];t&Ci r+01R&vi r+01&Ji r+01:H&j i !r+01S&Qi r+01.&Li r+01 a&Mi r+01R4t&PR4t&PcRtX&Ni r+01RtR&-8&Ji  r+01Rt&XR r+01Rt&}' SRt:H&j i !r+01Rt:H&j i !r+018RttN r r++01a#3tNtN rr+2+01S"&'53265323U!@(CTC JddR~mWmD &6k :r+01I&Oz= V+4[b&QzV+4\4a3>2@;;!544)((! r-r/2+2?+9/333333301A"&5466732672#'##"&&54$%754&#"'663265ojnGm8f:R+1*"3=Iʐ'.d^dYsgUH@Nj1"(6qeXRm4'b&HPb<4&LP4SN-$@-r#r(( r ?+23333++01A"&546673267#'##"&&5332665mm "lK[svs;4k]>ug*3`Z/./ } 9L&TK[5mDb"3#@** r rr##r+23++2+2301A2373#"&'532655467##""32>554&&+o; mwRSu 7q[}AOsH#@bUTl"$(.*WXU+  5_,Z^.TmD &J Ar+01mD&M 8r+01mD&N :r+01+%@''$r r /22+2+232301E"&54673265#57546632&&#"!!% A1:BUrEs*4"T/WRF 9,@BP`a=LN pqMoQkl!/@ " ) rr+2+2901A#"&&54667.5466$32654&&7Ӟ>fa蛔]tAqF_@Q^I(=9):A3?rmҚ}##KdIStQ6>ZwadRtp;@ |} {?323301S36632#4&#"#"uG~KNpX;35sROPzsp;@  |} {?3901S366773##23V,F:-Fp; }{?01W#3p;z&%@ |{?332/3333301A2#4&#"#4&#"#33>32366wzFDbVFECQ#gAQ-Po "zr~ONNmiNN6hL[".6785p;@  |{?32/33301A2#4&#"#3366|KNoYg"zsROPzs\44p"#@ |{?2/33333301A2#"&'##3366"32654&ЂSikh9gWUl[[Zܫ:(>_,?cpov~ppB/H)@ &"| {?32901E#"&'532654&&'.54632&&#"HKm,/};UJLEE`3zBr5*/c3CG"NBA`4 `ej 2*&&2E8U[\(#$"1G/f@  |{?3333301E267#"&5#57733#i9J&Xzcg/P:o \ Xwu8,]87qc #@   yr/2+2901s466766736676653#r ]B  0(_CLM:dY,,>0 dX(R{2,KV07;f7W @ zr ?23+201s5!4&'&&#"566323Xib_?(2gHRc==Q mlD4DO.6 &@  ! z r+2?399?01W"&'732676654&#"5632#'#A&=!K|'3K&P0^\Kk#2) 3*s E?+oCQ` "*X0#C)0,   yr/+2301a467667!5!c%M2P+o3V(0%;lr @  zr ?+23/?01a4&'&&#"56676632!3^_I.Dћ1^-O5r==R :lk P>+[9yu  yr ?+01s3 K%   yr ?+2301s467667!5!"3(" Z9.E3:(_*?#Rr @  zr ?+223?01s6676632#4&'&&#"=,[Gs=>Q eeB*+sHO?*]:ypo 6@ %zr yr r+2++201E"&'&&'&&5332676654&'&&#"56632F54Y!*(11"lEIn#6%#0'tD&;G52N " fE7\CRц>,150EwvD71"]@ĹeGZ)!!i yr+2/301S3ˈ@i$g zr/+201A4&'&&'&#"56676632*L}-R&IF*,_3j8/"!W7/6 E7C'F`CE8%zr r+2+201E"&'5326766766554&'&&#"56676632bG$gv8>a! / *.*Q32'267>54&'&&#"jeKo"#H5\IQ9:X oMlJn#!'C8!]4/G%PL+-#m7&_Gfo3&($nIIoWAj->62-K4 "U;26? @  yr/+2901W5%6673>73?9ǚpSR 65'?+Q]8' a,r7P9TN /@ %zr/+29/3301A4&'&&#"'"&'&&54676676632,+&rGF%#',+F+&!%\4-3A6K"9}DQ82R%'r97/--(e9In E>6^]63#$^?N~jb J@ ())9zr r+2+29/301E"&&''532676676654&'&&'&&#"'&&'&&'&&54676632\?yg$+^\Di"&,A4B%Jo"+3,%J*& %8b*'B!!M@IdV9.M%'/+$c81w  -&*E/Q2S?Ac('t?Co#=&2Kl5?='&[:ǸM=V @  yr/+2901A366766532FO/.$yOmHm^`4'> ^L0 @  yr/233+29901s5!36673T[DR8FR   %C'VJr *MF!(J%.R$v @  yr+233///01a445467>7!5!3   <2TR]+1TWV_T ,q  zr/+201a4&'&&#"56632ca8 )sy2[?~>=R nmO?+[9yW| (@ yr/2+93301s36676673"#!267673#m;;l$*+ >?8pHG56 @23\EV 32*2UHE@J4rUU*& 0 /@  $$zr/2+23/01W"&'532655>32#4&'&#"4+-ED$H#fA]_*7H ec-K#S/,&k X[  M<%Y5tpm :`(9#W|&#!r )yr+01W| &$o )yr+01W|&'!5l#$r 4yr+01W| &'!5l$o 4yr+01qc &gqUc &fqc &!W &!G6 &!G, &!RGr &!Gu &!G% &!H &!Gi &!8$g&!RHE&!^H:&!@Gdi &!Go &!AHjm &!gGTN &!Djb &!aL0 &! &!TF,q &!RGW| &!5l0 &!Du& yr+01!Cx8!v&j JF Q6tLyNMevN; *jO!Rj KF! %@  /]3/2233301A#.'5##.'5 >Cp"SQB=Cp"TPB!.ok'QYQ.ok'QYQX=" | /301A"&546320DD02DD9>@88@>91z%R4P<<@ /301A4632.=K,*5L@\?>@ /301A56654.54632>>rO;<):2X5YA$=/-`s[Ntq6W?$G2#."$/$ N  |/32/301W"&54632"&54632#%%#$&&$#%%#$&&(&'))'&()&&))%')T ".: @ /55#))|/3323333301E"&546323"54632"&54632!"&54632'"&54632#%%#$&&H%$#&&$%'"$&&o#%%#$%%$#%%#$%%)&'))'&)O'))'&)('(')&&)('&))&&))&'))'&)%@  |/3333301E5!"&54632'"&54632i#%&"$'&%#%&"$'&WW('(')&&))''()'&)%@ |/333301C5#5!#"&54632'"&54632g,$%%$$&&$$%%$$&&`WWZ('&))&&))'&))&')J |/301G"54632H&"&&'O'()&&)   |/33301W"&54632!"&54632$%%$#''"%&!%%%(&(()'%)('(')&&)  #@  |/333201C"&546327"&54632!"&54632$%%$$&&m$%%$#''"%&!%%%('&))&&)(''))'&))''()&')E7 |/301G5!qWWGg /01C5#5!#-ngXX~K /201C"54632H%$$''~N((*&&(N /201S"&54632#%%#$''(''()&&) # |/2/2/01G"&54632"&54632"&54632#%'!$%%x#%%#%&&z#&&#%&&(&(()'&()'&))&&*)''()&')N /201S"54632H%#$''N'()&%)..p /01C30^.BN /201S"54632H%#$''O'()&&)J /201C"&54632#%&"&&'(''()&&)P|/3301C5#5!#4|J~ŞRR)wPm{3t+us7Dm8,~x:m92}:%yrDr r+2+201A#"&&54632324&#"D6v~y:`ֲj8~ij~6ݲeeP"&-r @  r r++22/301a4667'3:%f5YQ&1BJM@ r r+233+201s5>54&#"'>32!MnJneUl;ek]tОo]rxID2Q0`vuo U -@  $+ ?3?39/39901A#"&'5326654&&##5326654&#"'6632xvZ\aIZ{N|rKcRep&*.3C}VVm4AvOgqF3>X-p @   ??9/9333301a!533#4667#Q;zJ;BiT"']%x!!@ ?3?39/333301A2#"&'5326654&#"'!!66-_8!$oe‹v((+5Bg 9nrA"1@ ))# ?3?39/3301S4>32&&#"3>32#".2654&'&r%Y.j#&]0\ ]YitӐmK|\L$Jppڥ^ 1P/iȏxQġNv=?kA ?33?01s!5!KtE0>@ ()18 ?2?3901E"&&54667.546632'26654&&''>54&#"`sSSGuEu|rK}NYXyږ_EJU"Ty@AhCm@pkCr]{ek&(fZpQPsXc'*ldza>kA)9wPJ{3Jt+;uJ7D98,:x:J92::%:ylOdr r+2+201E"&546632'2654&#"Zmsߢ||>QҁȦ"d   r/+22301a#4667'3>'b4dZ$7DT d@ r/333+201a!5>54&&#"'6632! Jj95hNWRghbGezJd]>;T-CDYQOf]{E<j-@  $+r /3+29/39901A#"&'532654&&##5326654&#"'6632D_}WNf[}{}e^keWYZ \^g*)(7Tk34q\gm8;HH.od @r  ?3333+2201e##!533!4667#o]b>*"{_32#".2654&#&o\.^/*`8u )kIdpӕ~~?􂒈PU'JmmFi >V,kˏ{^JwDAj@*Nr+23/01S!5!6~_1/=@,7$ r0r+2+2901A2#"&&54667.5466326654&&'">54&IsKNZXyڒsTRGuEuʬAb_EBpUxA&lCrGClAPsXc'*ldza]{ek&(fZpQEl=7 1@$p }(mq0#ms,=4N&PN&t_/)Ge>o,Ra=+I"W3S  5 n  ` 7 a  & A V p  ^ !W8o7rA sJ[C?Xi %o1WvDVhz)<N`r!4g  2k#7  / A T !!#!Z!!!!" ""m""""""""###'#9#K#]#o####$$$)$;$M$_$k$$$%%%+%=%O%b%n%%%%&!&4&F&Y&j&}&&&&&&&&'' '?'Q'c'n'z'''''((()(5(A(S(e(q(())!)3)E)X)k)*4*F*X*d*p********+++ +++=+I+w++++,,,$,8,L,_,r,,,,---)-;-M-_-q---..n./ //0/B/M/X////0 070a000131?1H1U1b1o1{11111122 222g2o2w2222223383@3H3334.4A4T4e4v4445 5h556I667747<7778-858k88969f99:;::::;;;1;D;;;;;<< 4>g>y>>>>>>?? ??Q?Y?a???@@6@o@@A9AsA{AB(B?BwBBC C;CLCrCCCDD"D*D2DODWDDDEE+EXEEEF:FFFG(G:GzGGGGGH9HAHSHdHHHHHHIII,I>IPIaIrIzIIIIIJ*J]JfJJJJKKKKKKLLALoLMMMN>NNNO/OPVPQiQQQRR%RHRRRS"S.S:SdSSSSTTDT_TTTTTTTTTTTTTTUUV VVVW/WAWSW_WtWWXHXXYYY%Y7YIYYZ;Z{Z[ [`[[\>\\]A]^>^^^_5_z__` ```a apb*bbbc8crcdZde?eeffdffg gjggh3h?hKh|hhii?ixiiij*jSj|jkkll"l.lRlul}llmmNmmmnnMnno ooqop0ppppqqXqqrrGrurrssXsssssssst ttftnttttttu"ueuwuuuuuuuuvvv.v@vRvevwvvvvvwww(w4wvwxxAx|xxyyjyz#znz{ {Y{{||b||}!})}}}}}~ ~~2~F~Z~n~~~~~~~&:Nbv';Ocwˀ݀1CVi}́ 1CUgy͂߂'9K]oÃՃ L:s>eӆ*2HOe{ӈGOZ)5AQaVi|ލ(:M_qʍ܍+3;Mrz0k2p 8R֞ %.7@IR[dˠWԡ+E '09BKT]Cz5BJRZbjrzȥѥڥ&GPn[ckB]0_< w&Q b(V+2u\hsRs>eSc NM&``Y*|iT_^&&Aclc,r-8|t2|WF_CH%B|B|dfwyG3HscR\mmm!c  e ml\e$#]L %J 3f Gc(Hwfv.d?4PcMdmlc3+cR=x& PA4N=[,\/6------|ttttWWWW7%B|B|B|B|B|B|(\\\\\\\mmmmm    lmmmmmcm%%-\-\-\|m|m|m|mm7mtmtmtmtmtm|c|c|c|cW W W Wd <W@F_ eeC C C CKC %%%%B|mB|mB|m|k\\\dfedfedfedfew$w$w$y]%GJGJGJ.\\B|mdfevRvRR;RRpRRRR 7 &)-8>*tGB|WH%rGB|JwfoBIWmVm4kVmleqpkmbmmms3_rm_rt>0|dfWWF_-8> tV55HB||wfYs Am \p%m(FAAW mm+%kL "G[OCmme    W%Sy]y]y]%RRRGss As{Awa \TwTPN?pOIe8u$^+! BIf<+NU[* Bcd%t ccccg~wtD:2V&TTT s) H-\nV|mht5mAf2u'ena :o3E|m2C2C |m|BmJ|Mwf2u'0{ml++z-E. Za_VF{W#e  .d6| m|mw+%%1 +$*d"*d"W(  8kMW-\-\\tmff(VFE$5A5AB|mE|mE|mAC%%%FOE. , L vm8u4k7?J$?zO &^"|&m]+iV -\-\-\--\-\-\-\-\-\-\-\tmtmtmtmt8/tmtmtmW wW B|mB|mB|mB|@B|mB|mB|mV|mV|mV|mV|mV|mhhhhh%%%m_x_^ddd\'w$B|mB|mfX),%%WWff!!!!!;,C%-tWdR_8;R:. RRR R_8RRR:R:_8R  sm I\m <mmmm~kR?ppbpp?p5pBqKW\6,"GK$E:d]qoj?Tj L,W60WWWWqqqKW\6,"G$E:dqojTjL,W60"x X"1R<?QY EGP)P3+D,:2%r-nMU-xrtd)P3+D,:2%lN"`TT<.uoL*_\`mEmm]mGmmbmUmCmMmD)P3+D,:2%MOO<<HHHH_f  o = 4 s332@ (GOOGH ` ~01ac7Y #(  OP\_?M   " & 0 3 : < D p z  !!!! !"!&!.!^""""""""+"H"`"e%ʧS6<>ADK 12bd7Y#& PQ]`>M   & 0 2 9 < D p t | !!!! !"!&!.![""""""""+"H"`"d%ʧS*8>@CF~ ZHyu`{xYM geb^Qyj h(;,us N$!WhX_HL|dHI#$t   5\78x9:yhidfkegmb@J~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSQPONMLKJIHGF( , C#Ce -, C#C -,CCe -,O+ @QX!KRXED!!Y#!@%E%EadcRXED!!YY-,CC -,KS#KQZX E`D!!Y-,KTX E`D!!Y-,KS#KQZX8!!Y-,KTX8!!Y-,CTXF+!!!!Y-,CTXG+!!!Y-,CTXH+!!!!Y-,CTXI+!!!Y-,# Pd%TX@%TXCYO+Y#b+#!#XeY-, !T`C-, !T`C-, GC bcW#bcWZX `fYH-,%%%S5#x%%` c %#bPX!`# %#bRX#!a!#! YY` c#!-,B#Q@SZX TXC`BY$QX @TXC`B$TX C`BKKRXC`BY@TXC`BY@cTXC`BY@cTXC`BY&QX@cTX@C`BY@cTXC`BY(QX@cTXC`BYYYYYYYCTX@ @@ @  CTX@   CRX@ @CRX@ @CRX@ @@ YYY@U@cUZX  YYYBBBBB-,EN+#O+ @QX!KQX%EN+`Y#KQX%E dc@SXN+`!Y!YYD-, P X#e#YpECKCQZX@O+Y#a&`+XCY#XeY#:-,%Ic#F`O+#%%I%cV `b`+% FF` ca:-,%%>> #eB #B%%?? #eB#BCTXE#E ic#b @PXgfYa c@#a#BB!!Y-, EN+D-,KQ@O+P[X EN+ D @&acaN+D!#!EN+ #DDY-,KQ@O+P[XE @ac`#!EYN+D-,#E E#a d@Q% S#@QZZ@O+TZX d#d#SX@@a ca cYYcN+`D-,-,-, C#Ce -, C#C -,%cf% b`#b-,%c `f% b`#b-,%cg% b`#b-,%cf `% b`#b-,#JN+-,#JN+-,#J#Ed%d%adCRX! dYN+#PXeY-,#J#Ed%d%adCRX! dYN+#PXeY-, %JN+;-, %JN+;-,%%g+;-,%%h+;-,%F%F`%.%%& PX!jlY+%F%F`ab #:# #:-,%G%G`%Gca%%Ic#%Jc Xb!Y&F`FF` ca-,&%%&n+ #:# #:-,# TX!%N+P `Y `` QX!! QX! fa@#a%P%%PZX %aSX!Y!YTX fae#!!!YYYN+-,%%JSX#Y%F fa &&I&&p+#ae ` fa ae-,%F PX!N+E#!Yae%;-,& b c#a ]`+% 9X]&cV`+#!  F N+#a#! IN+Y;-,] %cV`+%%&m+]%`+%%%%o+]&cV`+ RXP+%%%%%q+8R%RZX%%I%%I` @RX!RX TX%%%%I8%%%%I8YYYYY!!!!!-,] %cV`+%%%% % % %%n+8%%&m+%%&m+P+%%%q+%%%8 %%%q+`%%%e8%%` @SX!@a#@a#PX@`#@`#YY%%&8%%8 RX%%I%%I` @RX!RX%%%% % %I8%%%% % %%q+8%%%%%q+8%%8YYY!!!!!!!!-,%%%% PX!ehY+d%%%%I c% cQ%T[X!!#! c% ca S+c%%%&JPXeY& F#F& F#F#H#H #H#H #H#H##8 #8Y-,# c#c`d@cPX8 g=<;r:9O7@6^43O10+)(O(\'-&%@%\$1#"!g @\2[87[2[87[>Z1U1UYY 2 U2U YYU 2 U2U_UY YYYo 2U2UYY@@T+KRK P[%S@QZUZ[XYBKSXBYCQXYBs++++ss+s+++++++s++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Kqmkz:xHzqmzkz:q}x~Hyz 8&     4    ( F * ( B< >~ < " 4 N  ` l        `    Copyright 2020 The Open Sans Project Authors (https://github.com/googlefonts/opensans)Open Sans MediumRegular3.000;GOOG;OpenSans-MediumVersion 3.000OpenSans-MediumOpen Sans is a trademark of Google and may be registered in certain jurisdictions.Monotype Imaging Inc.Monotype Design TeamDesigned by Monotype design team.http://www.google.com/get/noto/http://www.monotype.com/studioThis Font Software is licensed under the SIL Open Font License, Version 1.1. This license is available with a FAQ at: https://scripts.sil.org/OFLhttp://scripts.sil.org/OFLOpen SansMediumOpenSansRomanWeightWidthNormalItalicRoman2t  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`a  bcdefghjikmlnoqprsutvwxzy{}|~    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}NULLCRuni00A0uni00AD overscoreuni00B2uni00B3uni00B5uni00B9AmacronamacronAbreveabreveAogonekaogonek Ccircumflex ccircumflexCdotcdotDcarondcaronDcroatEmacronemacronEbreveebreve Edotaccent edotaccentEogonekeogonekEcaronecaron Gcircumflex gcircumflexGdotgdotuni0122uni0123 Hcircumflex hcircumflexHbarhbarItildeitildeImacronimacronIbreveibreveIogonekiogonekIJij Jcircumflex jcircumflexuni0136uni0137 kgreenlandicLacutelacuteuni013Buni013CLcaronlcaronLdotldotNacutenacuteuni0145uni0146Ncaronncaron napostropheEngengOmacronomacronObreveobreve Ohungarumlaut ohungarumlautRacuteracuteuni0156uni0157RcaronrcaronSacutesacute Scircumflex scircumflexuni021Auni021BTcarontcaronTbartbarUtildeutildeUmacronumacronUbreveubreveUringuring Uhungarumlaut uhungarumlautUogonekuogonek Wcircumflex wcircumflex Ycircumflex ycircumflexZacutezacute Zdotaccent zdotaccentlongs Aringacute aringacuteAEacuteaeacute Oslashacute oslashacuteuni0218uni0219tonos dieresistonos Alphatonos anoteleia EpsilontonosEtatonos Iotatonos Omicrontonos Upsilontonos OmegatonosiotadieresistonosAlphaBetaGammauni0394EpsilonZetaEtaThetaIotaKappaLambdaMuNuXiOmicronPiRhoSigmaTauUpsilonPhiChiPsiuni03A9 IotadieresisUpsilondieresis alphatonos epsilontonosetatonos iotatonosupsilondieresistonosalphabetagammadeltaepsilonzetaetathetaiotakappalambdauni03BCnuxiomicronrhouni03C2sigmatauupsilonphichipsiomega iotadieresisupsilondieresis omicrontonos upsilontonos omegatonosuni0401uni0402uni0403uni0404uni0405uni0406uni0407uni0408uni0409uni040Auni040Buni040Cuni040Euni040Funi0410uni0411uni0412uni0413uni0414uni0415uni0416uni0417uni0418uni0419uni041Auni041Buni041Cuni041Duni041Euni041Funi0420uni0421uni0422uni0423uni0424uni0425uni0426uni0427uni0428uni0429uni042Auni042Buni042Cuni042Duni042Euni042Funi0430uni0431uni0432uni0433uni0434uni0435uni0436uni0437uni0438uni0439uni043Auni043Buni043Cuni043Duni043Euni043Funi0440uni0441uni0442uni0443uni0444uni0445uni0446uni0447uni0448uni0449uni044Auni044Buni044Cuni044Duni044Euni044Funi0451uni0452uni0453uni0454uni0455uni0456uni0457uni0458uni0459uni045Auni045Buni045Cuni045Euni045Funi0490uni0491WgravewgraveWacutewacute Wdieresis wdieresisYgraveygraveuni2015 underscoredbl quotereversedminutesecond exclamdbluni207F afii08941pesetaEurouni2105uni2113uni2116uni2126 estimated oneeighth threeeighths fiveeighths seveneighthsuni2206 cyrillicbrevecaroncommaaccentuni0326commaaccentrotateuni2074uni2075uni2077uni2078uni2000uni2001uni2002uni2003uni2004uni2005uni2006uni2007uni2008uni2009uni200Auni200BuniFEFFuniFFFCuniFFFDuni01F0uni02BCuni03D1uni03D2uni03D6uni1E3Euni1E3Funi1E00uni1E01uni02F3OhornohornUhornuhornhookuni0400uni040Duni0450uni045Duni0460uni0461uni0462uni0463uni0464uni0465uni0466uni0467uni0468uni0469uni046Auni046Buni046Cuni046Duni046Euni046Funi0470uni0471uni0472uni0473uni0474uni0475uni0476uni0477uni0478uni0479uni047Auni047Buni047Cuni047Duni047Euni047Funi0480uni0481uni0482uni0488uni0489uni048Auni048Buni048Cuni048Duni048Euni048Funi0492uni0493uni0494uni0495uni0496uni0497uni0498uni0499uni049Auni049Buni049Cuni049Duni049Euni049Funi04A0uni04A1uni04A2uni04A3uni04A4uni04A5uni04A6uni04A7uni04A8uni04A9uni04AAuni04ABuni04ACuni04ADuni04AEuni04AFuni04B0uni04B1uni04B2uni04B3uni04B4uni04B5uni04B6uni04B7uni04B8uni04B9uni04BAuni04BBuni04BCuni04BDuni04BEuni04BFuni04C0uni04C1uni04C2uni04C3uni04C4uni04C5uni04C6uni04C7uni04C8uni04C9uni04CAuni04CBuni04CCuni04CDuni04CEuni04CFuni04D0uni04D1uni04D2uni04D3uni04D4uni04D5uni04D6uni04D7uni04D8uni04D9uni04DAuni04DBuni04DCuni04DDuni04DEuni04DFuni04E0uni04E1uni04E2uni04E3uni04E4uni04E5uni04E6uni04E7uni04E8uni04E9uni04EAuni04EBuni04ECuni04EDuni04EEuni04EFuni04F0uni04F1uni04F2uni04F3uni04F4uni04F5uni04F6uni04F7uni04F8uni04F9uni04FAuni04FBuni04FCuni04FDuni04FEuni04FFuni0500uni0501uni0502uni0503uni0504uni0505uni0506uni0507uni0508uni0509uni050Auni050Buni050Cuni050Duni050Euni050Funi0510uni0511uni0512uni0513uni1EA0uni1EA1uni1EA2uni1EA3uni1EA4uni1EA5uni1EA6uni1EA7uni1EA8uni1EA9uni1EAAuni1EABuni1EACuni1EADuni1EAEuni1EAFuni1EB0uni1EB1uni1EB2uni1EB3uni1EB4uni1EB5uni1EB6uni1EB7uni1EB8uni1EB9uni1EBAuni1EBBuni1EBCuni1EBDuni1EBEuni1EBFuni1EC0uni1EC1uni1EC2uni1EC3uni1EC4uni1EC5uni1EC6uni1EC7uni1EC8uni1EC9uni1ECAuni1ECBuni1ECCuni1ECDuni1ECEuni1ECFuni1ED0uni1ED1uni1ED2uni1ED3uni1ED4uni1ED5uni1ED6uni1ED7uni1ED8uni1ED9uni1EDAuni1EDBuni1EDCuni1EDDuni1EDEuni1EDFuni1EE0uni1EE1uni1EE2uni1EE3uni1EE4uni1EE5uni1EE6uni1EE7uni1EE8uni1EE9uni1EEAuni1EEBuni1EECuni1EEDuni1EEEuni1EEFuni1EF0uni1EF1uni1EF4uni1EF5uni1EF6uni1EF7uni1EF8uni1EF9uni20ABcircumflexacutecombcircumflexgravecombcircumflexhookcombcircumflextildecombbreveacutecombbrevegravecomb brevehookcombbrevetildecombcyrillichookleftcyrillicbighookUCuni0162uni0163uni01EAuni01EBuni01ECuni01EDuni0259 hookabovecombuni1F4Duni1FDEuni2070uni2076uni2079uni03B9030803040300uni03B9030803040301uni03B9030803060300uni03B9030803060301uni03C5030803040300uni03C5030803040301uni03C5030803060300uni03C5030803060301Eng.alt1Eng.alt2Eng.alt3uni030103060308uni030003060308uni030103040308uni030003040308cyrillic_otmarkf_ff_f_if_f_luni1E9EuniA7B3uniA7B4uni013B.loclMAHuni0145.loclMAHAogonek.loclNAVEogonek.loclNAVIogonek.loclNAVUogonek.loclNAVI.saltJ.salt Igrave.salt Iacute.saltIcircumflex.saltIdieresis.salt Itilde.salt Imacron.salt Ibreve.salt Iogonek.saltIogonek_loclNAV.saltIdotaccent.saltIJ.saltJcircumflex.salt uni1EC8.salt uni1ECA.saltIotatonos.salt Iota.saltIotadieresis.salt uni0406.salt uni0407.salt uni0408.salt uni04C0.saltuni0237uniA7B5uniAB53 uni0123.altuni013C.loclMAHuni0146.loclMAHaogonek.loclNAVeogonek.loclNAViogonek.loclNAVuogonek.loclNAVg.saltgcircumflex.salt gbreve.salt gdot.salt florin.ss03uni0431.loclSRB uni04CF.saltuni2095uni2096uni2097uni2098uni2099uni209Auni209Buni209Cuni05D0uni05D1uni05D2uni05D3uni05D4uni05D5uni05D6uni05D7uni05D8uni05D9uni05DAuni05DBuni05DCuni05DDuni05DEuni05DFuni05E0uni05E1uni05E2uni05E3uni05E4uni05E5uni05E6uni05E7uni05E8uni05E9uni05EAuniFB2AuniFB2BuniFB2CuniFB2DuniFB2EuniFB2FuniFB30uniFB31uniFB32uniFB33uniFB34uniFB35uniFB36uniFB38uniFB39uniFB3AuniFB3BuniFB3CuniFB3EuniFB40uniFB41uniFB43uniFB44uniFB46uniFB47uniFB48uniFB49uniFB4AuniFB4B gravecomb acutecombuni0302 tildecombuni0304uni0306uni0307uni0308uni030Auni030Buni030Cuni030Funi0312 dotbelowcombuni0327uni0328uni0485uni0486uni0483uni0484uni05B0uni05B1uni05B2uni05B3uni05B4uni05B5uni05B6uni05B7uni05B8uni05B9uni05BAuni05BBuni05BCuni05BDuni05C1uni05C2uni05C7 zero.dnomone.dnomtwo.dnom three.dnom four.dnom five.dnomsix.dnom seven.dnom eight.dnom nine.dnomzero.lfone.lftwo.lfthree.lffour.lffive.lfsix.lfseven.lfeight.lfnine.lf zero.numrone.numrtwo.numr three.numr four.numr five.numrsix.numr seven.numr eight.numr nine.numrzero.osfone.osftwo.osf three.osffour.osffive.osfsix.osf seven.osf eight.osfnine.osf zero.slash zero.tosfone.tosftwo.tosf three.tosf four.tosf five.tosfsix.tosf seven.tosf eight.tosf nine.tosfuni2080uni2081uni2082uni2083uni2084uni2085uni2086uni2087uni2088uni2089uni05BEuni207Duni208Duni207Euni208Euni207Auni207Cuni208Auni208Cuni2215uni20AAuni2120afii10103dotlessafii10105dotless commaaccent2iogonekdotlessuni1ECBdotless \7$=D]ll||ISTUUWXZeguw55JJMMORTWYv}~1335amsttuuvvz%oprs4\5 "%STttvv #" 8@HRmarkRmkmkZDFLTTcyrlTgrekThebrTlatnT8<@B4,V .8B48Bj!!!!!!r!x!~!5ttvv ST55ttvv%5 "%STttvv !$!*!0!6!D""J&&PV\bh&"Vn$x$~t"1z&(1h$0/&&0"#%%0&11*62(--00$l$r2/41& -. /   " ( . 4 : @* R F2.(2 L2.4 L"b* R"2 X ^ d( j2:(\"13 p v'' |+ 2L"# (&(, 03 2:4 2 %( '2 00 # 1 1/1 1,j1 1 ,|+8!(1(1/1%1!!!$$/$///! /-/!-$#1#1!1!1(0!$&!*!0!6/4!6/4/ /4!42.24"D"J"P"V(4$x"\"b"h%8*"n1"t2""z"""1"2"1"2"1"2"$#(\1h"2:""$"(\""1h1n2:("1/13"/"3$/$3"""""#"#"""## ####"%#((,#:%#@(,%#.(#:%#@(,0#F0#L#R&#X30&03#^1#d4#j1#p4#v1#|4#1#4#1#41#2:2@#(#(#0#0$0#$r###$r###$r#######$$/4$ ,|$,$-$$2%$$(&$*$0$6$<+&*l$B+z$H$N$T$Z.\$`1D11$$f1-&R--11$$l$r&&$0/$x$~$4D&(1h$$$0/$&&&&$$0&00$&&--))$$$$0$&$.$% $1D$1V$&$$$$$%%3..%%%% %&4%,%21D%8*%>%V%D%J%P%V%\%b13%h%n%t%z%%%%+P%%1V+%%%%))%%%1D%1V%3%1V%%%1&(&.%&R+h%%%&& &&&&"&(&.&4*&:-`&&@11&F&L&+2-&R&X&^11&d,&j-&p-&v-&|*&&&(&&0/&&&&+8&0&&-`&&--&&&-r&&&&''' -'2'-6''$'*)42/4'03'6'<'B( 'H'N/+,'T,'Z-'`-'f*'l'r'x'~+,+213''''1&''00'''2*''1V'''''''-'''.''(((/(V((( *,(&(,2.(2(842.4(>(D(J(P(V(\(b*(h0(n(t(z((((((((((((((((0-f0(4(((((1(2(0-$131(2:4(1(-(/)-) ))))")().)4):)@)F)L*)R)X)^)d)j)p)v++**)|)))))))))))0-$12)4)))4))))))+h)*** ****$***04*6*<+*B-*H-*N*T*Z*`*f*l*r*x*~-*********************+,++++,+2++++ ,+&+,+2+8+>+D0+J+P+V00+\+b00+\+b+h+n-+t+z+++++.+,.-r.4D,.-r.J.P++.J++++,+,+++++++++,, ,,,,",(,.,4,:,@,F,L,R,X,^1,d/4,j1,p/4,v,|,,,1,/1\,,1&,,,1&,,,,,-,,,,,,,-,---- --/-*30-$12--$-*2-0-6-<.-B-`-H0-N-`-T0-Z-`-f0-l-r-x1V-~------------------2---....... .&.,.2.8.>.D.J.P.V.\.b.h.n.t.z........1......1/@2/L.1./4.1./4.1./4.1./4.1./4//@/ /L/1//4/1//4/1/"/4/(1/./4/:/@/F/L1///R1/X//^1/d//j1/p//j1/p//v1/|//1///////42./0/10///3///3///3///3///3///000$0 0000$0 0000$00000$0*00060<0B0H10N2:0T0Z10`40f00l00f00l00r00x00~00000000000000000000000011111111 1&1,12181D181D1>1D1>1D1J1V1J1V1P1V1P1V1\1b1h1n1t1z111111112v2|111112|12|12|22|12|12|12|2v12v112|1112|2v22 22v2|22|2v2|22|2v2|44442R2d22"2(2.242:2@2F2d2L2R2d2X2d2^2d2j42p2v2|342222222222224b4P2224P2224P22222234P33 34P333$3*4V4\303363<3B3H3N3T3Z3`3f3l3r3x3~334P333333333334333333333444444 484&4,42484>4D4J4P4V4\4b4h4n4t4z44444444444444;4V\>hL:@FBHNTV\bhnPHNTZ`fy1 y v! !@@WNPNN NNNNNNNvNNN3NNNNjKNbUO^RKb ,,""";N;Pqo*N0N~y'dN@N%_N'Y'N#NNn'N3NNH'N NN4N#NNNNdb }R R"R&HpE!EENG!llnoNyEt4  W ~~oKtoaKoWKg4;;a;W1;1;1t1Q%;2;(g;;(;; NN"anN!;N; E!E ;;;;JRta!4/ N U!UWU ZJE!"n!;;$~Ucv::LL!!)NH~l4lllx~N ~NNkvNe!(!N2N9!N9N9vNmNmNvNxN:N:JN/Nxnlxl/l/oHyE%twzz wz\0*p;@@w--::x77iZNZNeNeNNIN]N] N NNN$NkNNN!NbNbN^N^BNBK!NgNgN,!N**/!H/-N M!EoK!!<N<'  .N.ONRN@N@bbGThDDN"!"lNlNlwrreuuy#1N1 wFNFf4N4wMNM,N,#2NwVV|N| N 4G4;wNNwFwNwNvNxRNR wyNyN wNw{N{w'N'EHENoKGNHGxHxfHWWNtH"H"1"n1tH!H{$$wNtHt((##ZN_ZFNF_ff'Nyy([ENEw>N>~N~NNNg4NZvNv_EEIEeEE EXEaEEaEEoKoRKoKoIKoeK`ogK `"n"n"In"e$n"$n k+!++R+++Ne4!44R444NNNNNNRN;;JH"nN"$4ntk4;NG~xx{qtog?h8dddRddad4dWtddnndHENE4`44Ne4hNNh hhadd+O'O'O  OO*O*&OO(OOOWOcOOEOO(OO O  (OFOkOkliOii(OxOxI[OeOefMOO(FOF OvOvYOOWOOV:[O"O24N=F: ! z*DFLT2cyrl>grek6hebr:latnN'\dLllt|V` $,4<D aaltccmpccmpccmpccmpccmpdnomfracliga lnum&locl,locl2locl8locl>loclDloclJloclPloclVlocl\numrbonumhordnnpnumtsaltss01ss02zss03ss04subssupstnumzero0XMKD SRB dAPPHCAT IPPHMAH MOL HNAV vROM  ^b,PNLJ@>dB "    !$%& #$%     &' ;} $ ( H  HI#$l|l|4hropsVrZH@.(  jnrvz~ L         dfhw{tu78x9:yiN0123456789DEFGHIJKLM0OPQRSTUVWXOPQRSTUVWXDEFGHIJKLMegjYZ[\]^_`abk0v"0>LZh$*06<BHNTZ`flrx~`Jl|l|HIops#$&'()*+,-./AFN~DM:C/O:B(.4dnx mn_s~$2DR$D2RbdfhjlnprJ&/rtvxz|~LM55tt 34OX 09DM 09   Q  KNOPQSVW,-Yfv24defghjikrDEFGHIJKLM0O1P2Q3R4S5T6U7V8W9X0D1E2F3G4H5I6J7K8L9M{'1;PZt(2<Q[u)3=R\7*4>S]8+5?T^x,6@U_9-7AV`:.8BWay/9CXbw&0:NOY  QQ  09DMOX&J$,-2DJKLMNOPRSVW 34Y_fsv~245mn:;<=>?@ABCyOy/ILOILIOIy/yO }|{z~!!!!!!!!! 34opqLrL $(,28DHLRX,wdthwghtitaldinc/fonts/OpenSans-Medium.woff000060400000235244147177152050012314 0ustar00wOFF:FFTM:h/GDEFc[GPOS|! LU5GSUB,1OS/2U`ecmap xYDcvt @=B,fpgmZgasp#glyf"NRwhead564hhea!$ hmtxh ֶ_6 locamaxp lnameIّpost'nQqprep0{xc`d```fpڶ^S~u}хCGoɇu5ζ&{o"s?QV=i[- οb[qZrI56t j)?2Wm,ynqq$ F#4إ.NmPxX ߝOOXh.+LU0v[el|Y9dsR UA[<rЦzQFإ`.,Vw),w7a:Ays?XàV1.I.ݛvs3o|}}MqOO{9J=n9Gkp&'{?vX1@Xj6*b[ }Y.dCcX'ofqvJ o۰bRM(ЩB"Z廡?х1I &ؿDW F;9緾E'Qa}vRw`۳g]\$w>vɷk0]7IJ{{{00"2͒C؅.~lކ(K1E&A{ޅQSw`wI&Waބmu=(&mSR"L]5BmR se,|Й^q꩐1ZfyIbD:1("S;b`i<x[PUU:\: 2-3-o$ Ҹ#TNiV$X"i `8fALc>49_lj,:[\[3{g? C0TN/1v6\]]FQ!E?1Yr7%)$Y#keZߺQ)wWx{x'f$^PcT*SijRUZTSժܾ(_OL_o/403Œ4xkN1fi֣YAWpf058/0\rqvE7CⒶač;mGSdvw{<&moTRjΨ}*WAh{ۿ9hm'898[ӵOmsr:;'vRC1z'Tz.T*  CKC}>evh^4VjVUdZyVeeZV`YV5 t\߭s&1Sx-c 0tq#>8=| NM i*e<1^%5_NgYz#{I)XNf3E'x *N#b:|Yneʯ\%j6 BVRE[xZޢyw١;N#_E(/ D!b(CMxW[oR{U6v)U#!ڵ.ҮRSr/&ӋQumL oyY~ȏP3]]%9g9sn3nO:oxr7/?O?ƣ M~{ww;lkscF6kE+Z5--VGhRK5P #wk'j9;U*xmzӑN1X`VOlmF-nd3\SvNљ = /7hJ9؜xd[XA \AUX'-Ӟo#4C1nxٞҭ7a?OL?Q|ȹ*ybЍD8x'ŬԑpyON^/pf^lgA/K۲[jh™ 5&(ii,x]$dXc CB ѫYl8 i$S`;6`yl)4τbX aÞ _cU}Ӱ-' XY5t&NNy J`М0<ۧ+}`௿Xgi7qάAЦk"M<{miGb8{m5-B #teiOiBM4WsPt @;TcK'rჴ$b`a{: $N-=H!\>MȰ:CS\6:Y4̆zX]+SEQ$U.yS7MTaJũD&< iaZIRXZ}=Z:$I(u*R .*].j?~a.rT;^:.5' Ў")TT: {_ = D:IOznj7-$m áZ 3FuV.˒_ZQp Nm7ykWd2b02U1_7_}d)D!hl'R)IY7t>e iGA;W6`Ql~Gߠaf ҶN}Вn ݪxp*@.rN}(miuЇ(cB|PzMf;T>qPH]D$ Zd!d\iujz g5Zg™%>- yyލ FfV){Ow -a*z6ƪ:PTZ:î0ĺEp/mfU2b92=|^٨ae\QI;}JS?*:XG3Ō#23p)Bϛ0׊U1+Us"ފi%E:?7c*{y~'`B{S]ۼhYU}yZӹS^#@RN,KC(AT{p~sVi mU+.r4uH_c,CcD[us={@;b+&'YMKΛ2.6o]TgHNCG7lՃFV[vjt˛^ i>Ԅ=O\ń}$q%PO Rԝ| iM؏|@gpW; h,P॓.TW3K=94~k!\_I&yxmKSA{&Cx$b@ 82&QG_QZI|7J**6PT3f?%? Xeu{snmάu%ks)kc-M!CX=Ox?e7ӄ:U)B5<ϴ:j&LZxP$84hH,%`vKQ.^Ix`zp-/%ϪT}6r~x;Yz8tU9o[iFT]cs1N[IF͛Cm>3|)H(PÂ"uL|}P^MF,藷\&vip>I-xuL҉p"82#CED~ ȯ8#)]F<##C"-73OǡD`s9k9k5s9s9Z{| AA`4֎eP:n@o>:C1l~W]0 ͉Y8[eIIɺ'?s͹ৈdO!1aB!Fo3?"H iOyἽ3333g|I~4?sqyr<oʌz{wtRPY/Ȟ'=?s~74 B3B^X(/<,MŁ= 9Fa0q$f^RT(J%QlbeV;QW/֖*JuvaqLׄ,8-e2IX6GqxZ,>G`AM0|0aL"&h!a8q#HINҒ^R4I#'mȕdOo+g7J>HaRFbX(c9{:e򕊤QTLS#$uUN.7;ʓK4>-MehmN/3BkVz/=LOҧ `Zˈ2& 5FBT!hhpW*Jh%[VE2TMWZڮ:b"jh5\ͯT˫jkuzzfձ,/+Zfl;N% {gqr8HiX9^NgʅqQ\<p%\95qmw1xyf0/ɛ-]]@^P_]H_8|&_okV ?,֠k45͋ȋ . Kj.. rp^Q+<#㢈&dQR',:\pbH,b)ř+9WWzDhP&,cUUUեڼZMm6} qM~xm:].QR[Ϭ7+[`z$W"%׏)VjU'闆a!0ݰذXm yYL, ȶ~fy痺_o8ooXo7MSM77oʱ[[[vx\T+VGh5nnn)J@R);ߝ;+w6[ZD--ɖȻ5w5ww*PiTF1jڮQgr}~+::k~p4MFyy

yjZMM&iSmdtۢ:N~݊z^7~}X? i `7D s8[4BBcb\w9{HG?X2U[S)Ttvtvf:w:͹fYhVGGGG ܢ,3 <<^BBuOh6-bv].S+5kk.+voOO:&as;GƱu ')q*FpoC…s\RWes]W5w>!neVN UyF{*{=gOgmO֏ӓ'cO2O ,Pւ2lt`SSSӭ^FwYao99~lڿf уA`096~@ B 6H AyP#\p)1BP~x!q1҄:B lh!Z|[xxo7",l!8C!Րyw(143<= ;7z4'2(GѾTt!݋~1NLZb-ұ|,ی8*Ncy///^$_$DKBHD"H&3×ʗ/w7MR-)m#eKRH*OͤޥG##c#ۯhܴ*=NϥN:>H{ {|x \x@T8|維,ۗKoK X) X) "v,{D`&1ՊI^{^K|3s.k`̞9sΙY$}3EzMf#Ȉ&B%$Y:-k b~$%cޕa  $z|nQ&@iH{9~c! 7 ?{ " ||NVbLPH lKEcQwwMeAup J4/ tJ:ݥw; U"* $&DR~dg9hȇV5BAڟ/-7 2$r`"EN\U;yca: bj?"%2/"ԱFRj#($ީ1T? ', F4FEdb@ !m3m$tr׸]Oh̟Z4z0z` ?Aj U}o*7Ex*ݥِ*lEt4d"BjbG9+\xejY1۾tEf5hWI[u(vDkw|ZDakVb5oR^ԹlX‚\ ;ڞ-6Zv)2=࠷()9-@_arjaajrᏆOAt`{6~CGџBS_$@lvI՛Dݴ߿''Osp~ h@Op~5P wv~x>"X.4F&fo}IOs\)ϳsj$M0M` ,P/xJ F̜An{BkCӒ҆c3k2Fʨh  ËSC<2s!aV͐a,&ey{t"\mh sJ0$؄U!/z4 d)FޚF v:O޷i.`/G(Ӥ7L=xz3 Z@*y8gwZymηU/;Lۧ ƿ@\4E,. >Zl&~m@x;kDbMdT_Sp3g9?yx/rbr/|. —V9+hlR WS!'Qޢ/r!pWbԽC΃=+e.-VHIA)orbLp" P9\1W`qFh%ooһ?~^Unq}Ok${\EKN 3u jĔW~#,<}2is\! {5wKA䡸+I^JI&smQ}GJ7/ "_]۳w DãwO@gS_k,PU\z6\pL!'m22$0L#'Gd,`S=`iEc?}יSNY!V=ԾPaEތ-6Һ¢Y0BJ0F >ǭ&@  תrBuB806:( r֒a`w t^vbIM;k|-(;˺}5M1PJBAMNK\v^1#iooZh)}eRfM9#Wi]9c еR*W8q9ˣC"+U miU0Qݯ:#y7n(x)/j$M"*-KxFD,#^~>s}Lwo_Vq?L=ONHHl$uXܙ( Cb _#x>[0#: aBT aAD!6Qa~J]>`B)BB`Q,*YglQ-.L827? Qj{=4HaB5rZW6;Y^>2z8Ϗ{%d Aln4x#?rrU>cW#=I݇NRꍴk1}˜2,2q 9 ~j {o׽}r ;ȯ9_90!p6' F3Z .X= Mʴ#|0؀meҏ:[Ea6AHw=jwcwI5k:Y}QF,qP% &3AK^Yc̺Oc}HU}O}EWD(aE2?lf D|qD§U&3L N`=Y|z8zҪ7O{®ѝ' / 2FtX..pch[$9iLɶX> uRV mBl NjSke66"g}ՅȂtZMDPQEDI/ˌ+rӸ8Yn-. <>b5~deobh;L@)/CD 3jg0p2U n:9y :1Čiu/4vmFjW}s+/k?S& G0PImJ&"FOJ &T)(eDcO 9 B[#+^įrq`kjf|)zXS88;bGrշ̐ͲD)yC&&&D(?h,_g]K;ИҧZ9[nv#@Lfmg 5 1P+w\T(m,iFIFBH2%&?`Yyˣ77'Ō.ԹB\uUG#5B"q |KfEf珮 ?k7苛1īrop,>1&{ԴugLo^?ilS[96<試G0Rf_Ԭ#/gzojK7%LGf&j:~;ʢashFȧCͧAihaii!V\kiHw]ƘVh.;O[Q~:$v2?sfEZJ6L*׳Brcrl~~l\^]t,]dgfg@y[i1,%ჼ4~ϸk'2h +ɋRiD[KDSNZPV F21+us[X.+d>R"Jd(?rk:ߢg6l_-3, 4)oӌ(uc )ܯf"j 5VBSJkS_Kz!40`.^V_zl)o'ϟ,-2]?13K\8e?B>39mɅtaqc]d CT*xPB AB̦ۼ(ݼjCJ+2;ut8W)D0U Y~{p6zϷ5]^Q0}ۿlY^?mպa&2l; 7]Xt⢅'y=ͅ:\T L(tZOOQ{ٛIn q7l/w%7{K˗-J'SLZ>㾸ҷ4jhyJŦ+}eO~vw0m yGUtP=m#vFIHR%X=KEQeCeQsF~qsANӰ88v*N )-X:iοsJ7]/ * ˆ  ldFz<-coV/kDeV[~.1?8G8jI 'k`~A8U!J,}3rv[vZ d! ޺@RBQ WHLA3 g$3f<=4Q<ug;棧ŴG&w$檪bOB i󧛽 G#k{#Be9^ -C* ( ˤ6-` 5p[pq]`G܇ *;iJ0l/aǍ&ۻq-___B qq8: 8sCb\-:l\_0}FKM~ׅMM+Ƞ9 z\\3o ܮip|Ԯ| 9* O\PRCeTcR5%B b_:6*}A| $z g*"ADn",z&_X $cyy<:[a"<@PcA oZ")Q GS.!=}ijݚ+&KSf35:H<ϯ<5{HrSsӮ~a0ܯEMCUmh~2BA}Վ!^v Ar=ʩI)yvƅ!g\]Xn޿1KӮ07cF6/z>Ww*6V_zl@^A(~~:Po.R,+QьD-'-1wRGQICR9KBOD7z"3_uc3gĭ7."ff%z΀n0eР[خˌAAeSbcOY~_kԜߐ - T)T*969\,ù">X OMn?AϗwA8/\ES]Wpv@8E eߣj^ƛƂO3@:G.̛־ߨUDC-ceQqdRŽќ f& D{ x`yu~0-M66~Җc2~zܘօ맇N:ukyÒ&5 yg3RL!c[K,54O1*-4=:1p@{ln|`8FH%GvAq]$8)<:#""33""tGDdeED3-$''}{^CD7;UJB1{ݎH硶^Ӓ,M;8&ţh{Z袕~564~\zrG+kI:e'kjʯ|kmM9hnDo:xf0߹^ާw}KH=ķ;>;qVw~sH6%%3`$j& R #Lё /7M :kXnmMg'ťtԴVW0fᬕ1Q*h:4;sO0f'aFW; = Z&3u%.׸oHu4 0H?Fgw=wqu~2.qKAN9ye}K} &>Gm5T Nyq"B9MXAzhlR=*6|YʈR1Q&Oޕ!!3Zn/o,)/+_1:sYLOnqbĀ{f'AgnfFYFQC)Nxn%qU/vJBgE2&klXl˄յ+&P5~}IUFtL.=epZTGImU$"`?2"Z_*[KWMYPed'6j`H&U͆Vs~Wdķ3Rj6T,ٞ0h'XM}1tBQdzvTĴ͹MC66%'o9+Һ8aN2vJAA\mt]eXU7u2ӧ%Z˾pi:a>C.L pnu0dA^n27.3`0O֨-;3nf49-]GMyxVpgSq0b8f-!ƍֶTmO. MZ]`Cw^:L69/u7+P*7|*TbZ?̼:dW#Lx V۩j>sZp &bEʜlZ]uPQKcbrM6Zl$H"!#2p}U"0ls98\*$E-^ /n"=s4!_uxPϿ\<@{ aq`=l;%|5Nl^W̉G5j4]ǎtnj=yV3_u)heRFĂFY>kxn$wpzTzL㋹ Hf+gf*h$CWSZns+$4;mC*(Ee ,*qΤ T i5񈴚m}?h7II茎,p[3x򫽛WBu(r 8|sL¦{}ciӇy97l5#GWMJ!|$ RPx:4/QT!L#<tJ|'61c31cSSC=2fs"QqJDAp4QÒ6 T7Z=zč= ')wAȂ9H+Jy 8|hz[P14bb/ǩo-%B2𘾗-h&9i8y~H5P3[Ph$.JBnF^-*D/(E.AܓpsmJ7=.sOsS\<W~ӏih5m. ~y 1+FcBA=ȘP?2fsoR8?/ A&X7ȪI%XT4CAno Q`p1PN5Rx(MqOπFҙ1\<2s_t1,Ne&&ŁR .Lܸ5!΢dHAwzg>;vѴrT0W]0~5,+{BhrV˜e&yT=|y.0Q]۫CEAzaަ y%闑Ǵ>x#cc #c;4;1o|%Bz'/KazIJ68Rd3Ƴ,!de9'qV c{&k~m]*+(N@._-ΞL2@Yƪ}f^bO^5x k H=mx~Ӥ%CGVK:fG[[kk 25ym%`ӆIJJ0+TVѳӢ(HFCQMi71B\67cc ߷1<-y;ib O)e1SMWm'þeG|ԒXL7\]41?ģ阶e<Q6o8@yc)ف?2#a Px!3pI>Eh/RB[;ᦚ#bbݻ))sW7]+u Q^7$Di"G*%b\XW;Ohqya=}{-I)mg? [\4wtV~o|82a&rNǕO[a%úƖCJl^6yh[/Fۏ 5!q8Ә~nνȘ6́1#cc ϯ?8f(ۯ8J+ &X9zpO!D]aʹP!ԳGLwSS5tQK*(y$KFN'$ï-`RD4/vD,1.^}kE:Z>j1.kű3Nn؟ѹĉ-lqڹJ9L}LjN8UDcxΟN8U)~O=>gYM1@kj9Y;o 8Ŀ=Ph?z-sF6Xw1˷~D~z _cZ(h}QIiH<@SW;Tw8:Ty?gxp<''.ݏད g̸Z "̪5U*8=% ٢|xG>>aDCxRAR,2FT3]_?DHbY}eZce:wb ۏTݘViV0D | ֿp63 h7P%SSa8Xx8UmΈGqOd#p~ A81ڿ?sn*K)A2~.GB7а ww]RL(.0zD_1O[A<$obs$VhĠj J%t'_9J/A5T*' c71eǷV#*@tka+H4RMcsTܠ/zsh;,2eYӎ]X -ƴБgW+_pZ48#yJHGH#ɫ>ɕ]scaUa~XqB⑏X^yXU8 aA?p\-߅qs1^~\x Kɂj5/N,Eo`Lu8?xb ?CnIgIoq.ºVsr4 _>\ u Xr@+c]tl: {84\:هG5͙cZP7wv*F6J$u)[ )\9x{nϺ7 C{X `]O/Dž[h3q1]8^}  cྕiZ w\:}b~}=6@_x1Vzo}#VFXU$H"P݂kQ6OGpyYOm"~J:݁TbIANqdRV +ufyK6/舅Ozz:/)s8R*ry9 0:?o3b$˼cf8fj7:ׂQL/4:Ҧ Ɏ[Ieљ5M1-fv<_{kQȟkGOG}b@L+=JΏY!PeP(|DV꼞H`养(~|,[fJ/jiȸ_fLyNU}!egnaïa= P;1M|uz:e_Ior X?O'*|lq.ۜrNh3n}?h6e TIl")6"m!|]J4OgapG:aZj?EF!{Y) @ȷ'gޝhܖ3bP駠3÷yVt `}/ʢ'@188e"~"&2RT(](4GH㳭!fG:!J2|񥣮5=> Fn^nn˷|x{d6ص&{ԩKGgoDOvۥ @{GSۯutWV_yBs[a8YNax:zp.9ec)z_?`,7iy;ca]sW?E Iu|?=e倃br '8'#(ɞdSDwNV|+`:{?/c^OOσOrAQcķx7ϛ*̻+\^h'=ܡTJYƽ2"D/Bw`o':v/x >\E==ېp7PUԫ5Q=^3(%JDmɣȈ D8j@ o\7a q˔KOyS=O'*g88N8sEha?gr?79aMCy < sUwcY'֟s°}t{| ;IZ Ro\HwL[x\c73:!+{d8h\@3qaF]©lc{p Α_ Αq2xA2RB0](.8zh+g|,+^ v/7y=0[Ѝ |*|+[7^x~y8cpe= u1Y#pp*>O|n8M䯬?݄~rX4'GY~hƠRfT UOxP[D0a*FB!]X]^p|qi҃6􁍡EQeE@)|V7oeUnJ%Rű"bLv7p;u_c-)k [P)< "'. ܎{~RQm[3#r3߫rKM7^㲦Κ5s**3yY*А:%# Y W_NC V/68X燚0Ҽ!%dsub+;% ѡ\:ޛWP{ jڊ:oMO˶N\V;04Ǭ32Lk5m,`{ +t86k%o( _>pF>m1!w Hgu)j8^lvH;اgf_B]|~wB]|u<|t_>uȖyLf!s(0qXfS=;Q {0E^x/uS[z5ljK\i!dJzU[vQ j,oGy&p|Mƨ==*B ĠC PKt,1P3$%lpfqlTIn# LTL`2ER3 J.'  geuS,ܸ^29_QUe~]9֨)[i9~L[>/'Yb>$JɤE 'W\ɋٯN:iZkCf2( }}4} k}FK!3n;}ԱКsgR> |Vsa-}ĴgE"ODR A2?l;>Be `?"q-dB]'~?}݄np= G%w[Ukde_l\gr<ߦ\N}&zY6"Wg Yuy qCHlg"jN#5o>  '[c 0[eMIftk҉(SIZqZ F/^_q^ e(12=nA])aՐE1R({ˡ bZn 4sz"ectyMk3w7HI_$̞FM3C7OhЏKdIT#Elλo+|*D=x4L\'YRiMmu-q#E>77Av/O{:;!`G%}7'ϳzm UB F )II\;?ękd̄'FIL2p0g >Sc Dv^zZۘ Z*|=) ɷ0+-xsayL潿(ڐ)ѽ:k)0{v-=)BG!(%y5D OQovTɓw55ډ;:Hi#ޫ<Mý KwHz()*9@nw gd77C-A{RϜ!:E֜>8ˁb3U^d'i݂;}U%qOR}A&gcx^כJ&$) gK!i !f @pu LicFz8CBR$9>C?'HLϟڟ¿gazAߖdnqF\M ALRMd .%۶dre ߾onuï_̼Ϳ\i_+̭_N~yO5'Ľ/Li0*=[o=='Q7wBK||2T<3Ncs[t2虒~o,~+P ZGnʝ:_Trl > 9gMfa:uswp%h]QF,s9,} 1Oc>ĺgC9 esOl.`8mg2yq7]MA`jYC,xEFBx3i"tQ'%>σ$G/N_rx~ب?RKh}%Gtׯ<yಀ赇s3&L<6vx ߃PK?ƢXNhmj?]f$,ϸsX*>ok~BugջstjۇfʻU#:|rwٶ7>d)K_hMPs)X"p)6yӑ4 siuclYӵS;:[Xܡ?9cڕ9#SSbJst>Ys}φ"kچlOҕZ2chѶc|DI[*Y{Y,fd!^2oВ1^^WjmoydM?\+$#0(!ic؅UszKT/ >lȨg2J]`| W&lb(g&^wd1Щ%K:[SF0eNZ]Yuʱ-)o#oָ4ṕ*otڣ΍>yw:IS{WRIT.\Bzb*}#nH \|wɇk Σ+5ϙ<{:Ɲnwv j5=wOQ3@ Q uO,8f~^k*)9JrO< W} ܀;^3֋B.KM޵$XGUҪ6E*+ҝ̭yh,]h/ΓEYU nz?q2A. )-\c|@ǧH|F D%td`NchX>. Tz1 ro/(=D{tc!F j)d`ix M;lH} zRމ:}n%fDܼ<ޤBmAs\>C?;:ܶeRRbh(Xւ]5{wMQPLb'4eܻˢ&X;s̙3gΜ;Ḏfq^^V\Ɩ$u"N)Ek@ 2f`+uɌ.ףӰ%e}X3s^ؿK~O#kdĿjihd+' gՙFZcJķބoȮ F|jZB(l lz&ΆwƎ8mJY_>܇9RmspL4CМՐ8PԛQ+qxy;$~~Df[o\b\8zt_5]gK;%߫tA3^*ٸxy>b/>k>FRrcSk. Z"(]5XJt18{w^Nv} kkfC:lX1 VZvC>y{ i &Pr'Dv7lV[<2CVROƗz&}x3W+4 S2~]k»޹ ~Y=u9igɇlwv׈ EpzZ3}ګM$z IMgCKYB&؇?qOؠ2fmXLWwC; [-p jr> Kmh p8z/zV}C-PsI](dvHMPxdRiL,;`נF 88L< Emt~+6Poneޣ LQʥG(>W^Y@Hir#NupR˷Hk2$sv^+ XLQ^Јј8֫Υ[5.@꛰-SbnoѿCBĢp{Q:|,cL)L+[h _5&zҧɷ]{WSU;d}S[H ;ǟbhԡÅC.. uc%$xڥ3=8Š Q}^A.޻m^\r|ÅF0PU[~@2O!.M: RTaa/oĢk,OIp53BTr$(ηߙքJ-'zh ld0>ycnvx,c׶ewwڼDž/]~ْ[/x?NlspN4ח Ce.&\k{@&Hdc ̟}͖n}2χ}0yJyB:hg.kr{NǃAɝn2/W XT}صcfccug.?p'~%Ň9Gǧ]׉} z}q& OrrM\_->@U{I kdW[D T ## !1+QTDE:gvzDD4V o6W_ټ>g2zɏȽhù87/[ 0_$5$- D$cէꁫdJ2zi%&wpc]xx3G UEBp 11ȰCZa:!S@DRi `u3&x;νq3xvpi~$gšC.7ld3|垊\k'4DcDbM]IR*).`ӈ"$ϮH:R!u__b#ޤ=va9Z(r<6{|I5wcBӦM(7>)CX+s\k!'ݏXx͑v/Z"gXly>"R_1_9_; sAƅt+30 7t~E*zYʋhSATa*($TcamX?Q1%Rz&FBJhu썀;\r̝{.F^V׏U| 2Nt4@W1sBG FJFν*sTLДn#8?̐ D"/zYORȦ5;FmbaĽi!?7nC iD"}&Ui7n?uqgK= ȥ5*qI]5E/xMG5OO[6>;&t7'bˮFK.:d4IYm.B%/Dۚ"4; ػ͈<nj_h^<.QV}nBçg"{ȇ ?BC{]@V`oLmΥIo>P؋(_<gRF%;lSns l?w;fnGShc{:.{D]o6ooǖ=Uv`;n}Ee/1ptB?{ 8䒱(ٵ&_ӿ\΅e+u׎x VU,nTA M`%?]oᱦ&z#}yrƺ/w}ÆIdGAC@Īm7yxӰy98 eKI5K:ӈڧ )aT= }a)0%M=x@9s}nt}&eL--Ht&4Cs77SH FVk4J,fK*e%flMsСs@:Z hYU@7*?9#(g© ^Ö/1t?6M2-;} 6vN ՞>^+dLxg;;Ja? C|~HMl4*1I)+QmX3`&&M @* n=ϲ?zѶ$g@oT*g;7 vj$:]=n?9 \<}СArͱ_5bCe9.v%GX4S7xΟg'o)*2ͅ'x=,P] C'ݻ+%~EձIU)Ft9X=h }׳NלXx',sYՈ5a+h;{ g5-bJXV-P+p[ *F wCCٙiGn p h>ABij`~3ۯR2rxXǚЈ ` #@myczHLѻZcM;^yjs0m4:P\C@ӫ!uKdñ"@ئzA"vGɠsj3%v,p41xU^}板2u22o~7Mڴkkqu^n{#WLF`[V%ġh6՘6xcMY *Op㲇3? [=㍥k>nư3eM:tFu,>aֆx~ܳŴO3KlRPy[&i6r`UΟlx)' 9wB4UQ*}{ 'pO@!0jQTȗ7/"S_&9@zpFImf9< 9`㼬=rEJ:^@zc Mڮ(תq7q_Ei vL  H0QH~OS!VBĦ^_=%Ci7I]8)4`OPQ k},n6zO6)~>Q$_AT$݇ Z#ԥZC=cmD6̛?tc`>A̜~aU6spSێ.{eaȾМeǴX88l ֓ߓ'!IAlW~h5a[d+ azrj35d]o)Hg}6u#7_Ջ9[>QskJQєnPAAI8C"uQn;ޞp 2u\ruGefSuxAՇzNMz GAC soT#aٓ99rAJu׭nt<$h K!~sQ"V"Q*ZF'$^"bQTP }7obghCؼҋtZztWЛU]?͜pt9P{"lQ 7}In'?9kȦfR0L@'O}xe.A|[dfw<^e$ [\+g@" 7Z3Uj |ϗςy n#h:8(E.9od p V_dPAŨo65ѧ`sY$X/x}IxxTN)sKFё=u8,?LTz!]塓 f]ICSPdž`6z_C/ ΫPEW:(CBh$4=e#c NШt߄yLz/+..3ݏtQN?@V 1.3vՖwb8 DD3GXZO;uMv^1k^335q~; =|oo^pb© .:;>$hUR]Jdy5Hq|ߎ~7=Z3x۸\1B2xQsFk渂E}pE&/STQfߐڴv̷89ĕRT=M-/O[i%]*HN?p\4䚿%[[9nP~mGLJֿQIKt>./],QV9y:tXTQ>+qS8{Қu~2M^uk^`hx3v<ѱhJÄemҷ{0&0YXqW?_̤ضs')۠1O!љ|GJ')1%q鎊'?pK: I(/]yFOOCr9/~r-5'fͨИB5aVVWR6 ohk-v [jyqLFbidz_X$39CNA *>$oP'{[vKc^d;ByI%y11y6kPlk_AE[߱o'?paKJKϮ^s޿fT"hTߔkɫ`L~ĺStlؿ,ڶ=zCOd''M=WĿIa+"5=I Ky *gD_HVT!tQ7b֥n|H"H,c^\hMyURVL嚶crB']=ϟS$:j--;ٖ ~YqqYk68_iȰذu?lX"cm:!c=?Յ5&#>)&)I.! X8>!C"LiI pqjΈKe\j{(MIޮ}\C:1ͫ]Jrjx:jLɉ ƕ &[)mUjܹAP%<"K7JHK)#E*OơF8v_P- b>JG+ *qgHn9K%Vڅ@tۄ P;\Uޡ<5k܄E޺+MOcJr%tΙ?n,ٖS;*dvY|s F'5%klE|ߙ=rFv^2] 9ٵ Ia,',1lih\hV8p+,] <\S>&u ˁۣ0Z~ߓ(-d#V*$_?`]BI%l;wp3y)ie--x:ML(οt[S =uŠ7/ gBȠ̸qjV, o33ڏiXmRrA|i;unkU0crd.I/m3g᣻`Wwft~Q1?LJ- C*ou]뀚zu#Ӓ2A&h|fVZs{tII:mB-tZΡg,3#]=n!Oz:2Q0HB+$D;WD:Vz2uT|I|({ ,I=ֿd2/x`1Ǧg.!zwVئw;ke-ɮ]UPfd~ ^[\Z~v/rU$gMl<)@.M ' '/.'%D)^2:jPǀ_b-ĝ^bqz1 'b,1L[j||b-,ވ,g?k}tFSR&¶с"Lp,aa霄VVhN}VVl]Fufa6oGkUyF{q.Emjd.9əAY%r9cTMRs,6 :JЊC,9خ]]I7hcSR*ޒVQ^bҩNT)5Y>veWMY  AHu!" tCCj$E”|IZWnPRA|"kugٌ6o'sê܏JFKĆ#F5g7 ~wAYjTs6˫sl-&C2y=[2{/m8lT!uܷ}*ˇv. 5ƒ3080}1BК?Y } J~kMk.O'{W;ɣ ֡^XfWUѹbV[#D㟖6'ď~c0)ύn0`UWxYMqRfhWC',}s%ZGj~Yn{ p~e/` Q*>:"[X#t ahZ|W?tBXvFmcvfS^椬ﯱ<#a~9Ń!5ʯHˎ&4)O!8^_r`ŨťF&O9\5Cp{p XO (~7lO<}l?w'O!'\L/خҩՀeF3y1dl۲Om%f,xonذl_o_ݪNhfO>K1stng||4FI cY\$BZ4O} Qhy)B@[MZs8y\M`zgX{33ʲu֖_Py9_,;loHm Ey"1MKTe6k%11qѬ,;&xl5,9~gE9OE9j /Nڸ/P\1!F΢31FMe]5&ۓz&/WY^ytI$˷%oyEh v_ 7l>0HじnsN158Ȅ"ţHy]`9:^n'!ka8iz)q9q^&ĩx!ZFO;O?i jش->nV%SGrr{yM2vp  ;<F&511rrKM ιM-Up}iǶjf9볙\z"w+s86p'B`)眩M]'׵⡳A#t}ϺS!7&@;$y$'nTh ^b?2VBK$^bfmާM,}pۓČ'+;q|,qe=yfC4!1(RBF ^- $vᵚE‘8/ <,mxDPK~^?k*}I{]#\N2e1d\ $EM g *mwv'ƞR#4p,h5p+d '8Iz@R#" ^26\T:I[hͩWNJoͫrѓ6U;WC%C3SE?j=5Z25d6mLS6#!@A<DJNB[q|䓝OyP=>ۍZ -o)#ˑHFb ^\gƸVw3X'p0)d8۶+UxN'9FJs*+1Z"ËjyW\O/~Phuc*9oˣv.) hzC'?8`j;#$ XJ )BXW R: _2}pUTɥ$jկ}Lr]ɦGK5/uqjV#7J*}Eы vym-}dbCݐCapF@lp6U`c0MIإ{Wt4js,S}W lg-v].p瓲s3JbDݺSCd);JTJ"$ƄM/Q-;缳7J?du\K#\[${̙'T ü슳8c! ]v PkpfxwlX@QPs&>{yR T "U{ܴz3ڶ?yz=yEt''y-ܮU ťdoRAu¢qC@* >~ =N3sOc09 TZQ)qOM udjǠpX  s{qP;)Rtp,ݒ79G=*خAxhuf? ۧ΃>_ì/0C8ȆU|LyC`d'sR2S] %35S`1\_% , ؓN(58@`o*z"'^G7~ V6B_[zO".l s78<)9,YrۦbbHxf}4"x650ͿlBМCpFUI  X:t6o{dms1hfIXOS#3GgS׫7ojJIt׸2nıyg2 ^BL 'P\Ώ7qd#3}4 ;9~+q4?J~/V G_s塱P vh4`ʔRR Ԯ҄Ըi1XR=8brQטVk(*_i21k\ Ԓ6q H CmJ8{u!BjM#*8} >kqm"N?t:ͳ+n\#/"{_tˏ| d氰SrMyw ƻ ĠQAV&&-2&A|4+'g}w^kv\Q͑/az^.sU.(rx~o{hbڶ_9;?;GT?0b1 ej#3ɴ+V|ڄQ0u8U챝=}KM{|2tn3Wᙓ\YփKn4'lkuKdX*!!ɾfs=&{4.>)vH"8sOGN9=q)-. |UTe.kf@_#w(Xͭy=O&z}Le3ߜYX_ݾ.eb߽ &j^[S|B[Do@g8oBG%}^`ځ&hsm|Xt?նo=; sx+ @ɑl}R/SS<'%wo wFu<Ψo-\ht+u\lre{QIt%*8$Uu\쪜3yƷ+}|Ι|6| +InA%QW!Pu1ؤtljlmh{cN,_7\'\8\B.\;=9l>..Q(R)OmsC.K{j="dn1QvAE60zR`X&!BstnzJѹ`3p:MFrI Hccios:d^qi4F9Ofd^$)irȼCkW p뉣ݾ`13$fH+8-AW۾;pf9F#k6?)gf)Sg>z;D:ɠ2ZJUz8~pQB4|ǥw_j|@s7`l8`#d!t\:HJ!UCeMl&iTvr]‘\WWDBRgm$O'4G4G z=0/[WN-+'vӌy-?rːc0|h,P'sPH C\YfH ׆^sݟŸfI25q J?Qꋠw^~ K몇r=$v%mV[9k[.˧ݶ@-@ՀҖտm]br_6XˎH|!üiCK!)ж )3ǹj+O\ZGӾ>>@ڡz7R, 0w7`#YKk:z.{θ e/FtA=6ZfhGtͼC#vAE+3T0a/ t5ZEhRLb'Rz2/Rx&Bt I k  ^7e  ͜ m}rjJ)$FVZ|y{ mp[i*Sma;:-~ ƷC}%!wzV2b/9ܗ^{G_ %'iM myύ|$l=27_|7 ִ A&u PSs#`vq؉fմO]Te/癁tn*HX,5%c|=׆7@ϕ_2M mJekQByLɞ'"9&mѦǚ6m_NAj6Ҕl]AHـvrɈ &6h1nڅٖ6IDGu1R}=t.{%J|WaC߹'yQiLzLIȑ#$igq&me̳Ӡ}mօ:\`(q]x4Z:8څpgJK>o47 2$)>u g  Lz5sIg>`K8 r"QLm_)c+ !x0e3:wodoV+J*d8y74-&> ?h~ Ntvƾ^'ݝ~1}Qn=ܑຒ>'!Y /vDU"Fp[8|\ȁ# 9tLwI<8w=ڰz&6'TM|X6tOs>3 uY6*n!VkTj 8tqq&DBM(U,H WUr\͌VL֐6rY%/V_NkV2oMOOfN?k« I흙'a񅉡#灷޹{RD8sT-7(D|~$$O[SgiӺ7]X $fq[fG|m53&2"c1^]7h~H^P\pF6JQydǐ&P$c$ڷc+ 5iף/JpĹ<AHx2 U$Q գ+: o2]GVrȆ,?{ȚYLv+} [ٹ]Ys,\21ǔNeQmО֌x#???Vj!lW.s WWf?8ϗm?bk=/=5#'yaLclB__DK+$MJ׳O2zL7otԖ̜Tc 'GZ7\[KY"+a$x싑Jt#,Cj`'ViH<_{UiWG2`2*{, lKs#*[7zj %W2˻l޹mׇ݂yɏ(6 Ѐ Q;XʑĴJ$*w)Jі֧T(ėdG}?% r)t'791<`Rq  !6p~)b:df$YW5V8 ^/:Hތ,qZ icz^\C+.m:oסOk~@\MgLB| -%}t?᪉wf=:]$_9#qr4ϘR;u*,3~ _ҏ\X2/q/T"VU[Uu'u!6΄;781._7Nb57Yz{kO!ujOUBRxYf#W[i}aڲ}/t{|t2}~ݳŬK]<6{s1W#ׯj}W o*}ch>;vȐ[텣'imOH)w7W'xye;AH=Yo!Yu'܋ٰ~ȫ'S=6w-u*TP-^Y%)BH%e(LxZ-aa_##QQֈ**""**]p;Am#ZT;gz%(S` >΢LA9nl% "9Kx%"lX0><yqO V^DZ'S"SK:ue  P&-pue13i?AEzhh7<66W9y/Yа5=9@$gUtOZ\0AvL=p|^$gK ѤD+ fKWW͋L^5˦^Cd/QDG*S;; Qi-WPk$ ֘I<[ffP}+]8MiBTU#|9!gXͶ=>ڒ_'ȥ9^)/fl>s\bFK!*Qاc >Jt<0T5!y>Z}7k{! ({mbxVMZ1_Á48alH4 4V90pOonIW27RNN/ګ]fZ"Qr=rc*22>ߊ`Y#`Эp}S>/~;R# Y`1^ P/g9x|vڙ#EY\NV%.Np/OmNlŞ ksr{a>!:fB9V*1EhhXdw7m~0~9|C>ա\E|\Ys $靝祦DGKJ u%-ܒhQ7gNM. ꔾPdͅt~USnlRjbw&7uLObٽg5ޟ3HAQ!!g}P愥TB$9^V{}>Di# *R dV`<yGΌ/st ۨ g-ILФI%;$xSz@ODf17R_Az־uUJ'"O ւU FL2DG=-Ϩ3zvKCQ딡~]#۝~ =fypH9 OmY. ;bNH2 NjR$DaLkPTyYH8_9gCݏdo}>ɵK,pqدɎ鿧 BM1qx3S53w[ #UAl:QiMB*Q1@"U +ck}8W:ksl1)3Mr؜Q!r1T΢)}zCHD)#$s}E˻m]LJD||2mx@?0[wFUl ߹e{o6eS7ɦoMF*i$B@lAJB &{)*'*~T3sn6c'sϜ9s̙8ed(E{7%%bFbܾN*z^} 'G qnxԺF)wgmKk7B(7.l*PjD"82ξ2- A;5HD:rnXHAZi MeCTcIo.(2vhB4<5j %<РEE:Gnny81.gc$]ѕo%ݗ>8/(&BHFrbD o[(=hHq )on6ba,bȔQ~Jñ&F*E}F&ߩXכ{Gw)|4C.J a0k=Zs.OR!aFSdaX4GYJSUL 6mk.$B[S "aOEe m*n08Hk1 #S!wS( [swy8w N}֜ADgvoNpqg`%2د8 &/߭-~BEp^-$`Pdnsf3,ҹ9Is k:o٩OߟzzEZ̞~Ej c-V4x6U{sآӡ|y}]pNsI]7-cf W5kU 7j%@y@(by ̃w>NUS 71đB񓉹Y(0jT'zŴ)A"ߗ}eYɻ pޏ KX,}j" P o-VExeۛ55 @st ܣc}%AAmj7r 5zP;fʠ1;@9D#/"*?/8솅MI:֖R2Y lHy@$ȼugPKu($Qjshy/:GO)A_gq>yN܄cRH34/tw֤,߱ߋxO3_Rŵ(by'a Ɠ'1%҆ x<0XO&M(S3rdYCC0.S|C ܒ0p\!"$20MxyZ7-G |}'_ ށn\{חnS;ufs/<ĩN/*{l[ɕ{̕mQ3 {ߞn ;iт@J1GSdW.]=(Nt3;C*&LQ0ϣ]pxn8A]HoNN8\TA.(jKl {<>!A|<񉊜wy|ї!͉>}Ǘ|N|<>Q_ 5N|Ny(>4oy뷎@s)۬m=x^I0N:G{K҇(''8 X>|ݟЇes^ЦՃh^ߝHe-1^խ~x=k^k!b_g :Xp~ ש!?MD 7ص_ʁ#a=o <]}đj>u ՒCt,µbYcC!>ɘA|W`s>x\mp~7 bS<Qίy|z/۝ ŇpnY<db~oCr%`9dڈDc9f>#&sjg4'ԓ\]%_e<|b_brT,ռ<;+1!;Sb:yy sÉf>Ì7cM,9|=˃FYX5/r#wg!>3=7ߜcgzj^LCyr;89K,ռ̾y3x=-!<x}ٺrpLOƃx@Isît ^9 O{~uh=k1|/t_C8.<^O~/x}{6 ~ x&ذ|UMIف~JQUj *3HJ%{ WC%F|F➠. ^;szZ|TO΢?L=T 49Z-y||0sQ/3&0]@x:I}oU=zF6BG8^Z@ l*U2p>#$dg)@q8(ɂJ?Mo6{ԏ7*cC>[^Pj4ւ9OjԫE9Yώ>YG|sFT¨DN X5EyCS{Og]z0"zyztÉzTe.i@ɀd9_pC6|~ITJ%O ^|xF .4PrEN /m:)'9_vH"/6(3܇;d*Gmp| ؠ M> !K,~Teo(1'oz|Q 1 P"DavI1jPF`{1쳠0XPG}/6@|fv&JLJUb Ƌ=5]=82Աc7@mX  l/X=lǴ|MQ? (紌o8m99mmKWC]Wb i{]Bh@hH?\BCABx&+Ne`oDX,Rl@7L- ec}ʫqYqȧ#56wx'ć#رwM7./*)*:o"o۷}]v˶ݺK+?~/|Ꮻwڽgg+fۯt/ܺڝv_;>A%#d Ή(9Kb*{~1D3~Q;q;!\Bx>|VLb1h`s&[6TfDpr@1 P؅pP}xvuُ(J;Hk_yekzd{W! Uc0xzRF6Z-@' L]LZv#y+͉˓&Ol6 ^]-Zӻv׺SE*N1FRyiH*I l!T4Yq\uP | %.| <9dgʈ9OnjTrRXi*K)++Fg[԰dŭϯas¬A1uukwpC@: MA>¨{A#FaoOG Eq <[e&/ 処Oq V4|.4" t/D!Wڢ3@]o> >[84muW M2TG9,!#uǨ,_o !˛V5mj8 ^N_;w^t|<$| WyqI'] ƎY͖-܂xYsNۮ  OpW{X|N0 p @*7\GM^twfmMP"%FN!E^2抿=S,z L\],<xi(';m Jc8-% 1*¾̰\r4xrg.gކ|@" S&,,>E-.(1=i $i7ziz~قܼuftM1厎~ y;:`Ow+lg(KZwyߺ&yp{A ѭ#(o+b\Fڤ_ * _#'`0cf\ߓ{nxxT;|3^>MY3aNb;7,6rn 'c5:I\n=J6H#d2ό]"!\41@AQ9 x.y1aŰ7YXcJv-/:d)?M?UEJH?q-<==L$Ŗ#\'S(u[* \s-6\G(%4NV O_7hnS |jH3ln)[265gZkwznln\հ.~mnAoy"ܖoA3~HWDc0Sy 5oÙ|v* ơcK->Gx9*0egzrY֫|ǔOn԰5qRT2e!ϟ;r3Goo;>={K=Ka]8p:c/@FFD&OƆ<<)PBgnHh Gڑ햕(bz{5I?=PW~\6miӺ 'KpO ,Vh QHaB\N]+lf6e\aGM7FbN/c;*of|o?=w'^Q [p-tDrK:"L  /d 4_k=&z/!>nniz$=JRX/pvoR(X;Cq[bs{ä>/ǃȃ-ȃ("&Q%(=l&htSrA.@]nVCr<TO,]n6kimIkƮ<2n~Up73;c4 ͛]M'VMc'C ((H@ɯAM“󊙊X#Eźٴvv&o9?&fa&n],nCQ ]AWP^ReĖX0d*-o0kv悔RƜnJ.tzJM>l̩-Ǝ1RSy9rݵ{P"b`O)EyZwRX\BJ0O%_%hz7b\[6,/++_~_/b'Zv5Hbpͅ@Ϫ0t:,\h;Hy(8r/$%bQ.^?/t >:TSs[ʺ m'ȭoNۥϷ ?ytyUU&\1gUھy ;6nDlosYo7z'o 9]tʲw{,-{?zӟ`|E "I@g]3ۓ4 b9d0]?O=zϡRsN=z-b:_ u\cO'WSi.8UBR IQB'm|pԠ;ӗe?.?P y 5xMVZ-t$jT:g8<԰^dآj)]Z7fKvƖ1JWlJڸ䰽:vBQUYȒҌ1֒1G>9ujuͣm:n+j&UZS?f!dTP~]Ac]7:V++?hdIՖIRoϜXBzHje4Jee{w/r-&MHB#'UQ* < P,)ܻf=:oʄB7yod gWjdRɈ}UGr4xv 4J!u pv bqC}DH&#-Nfd8^^c3€G~J~f|~B{ cBPr|J7Sd`h/iՁ ~ˇ5rF9,o xLu8bdGe%6Y}pz6)s5aZ-k$/KD]RyYhimKwɴH_aKئ!L87X%4jNyǡHt5TQ K+ 0eEa\tÑc_=[f3ϾXW++WM^b#eRfL1پ>#D >_H"SW(!8t nuW…'A1>q܅@A*!9@ؐ_ |66n6_G(M*a` >_'0^׶Pl: M&'|l䄁ewD5& ox8|5ë0!88ه/r= `ǕB/<܊c5!?|,Bo|l'q{>>< ۏ<|,;Sn3uY}51tg`8!^v@8<y2 P \2F;dpcY(|O) (:t'Mz+wDlH(Nͯk[D8{O2bzڀjU1h?PP F!_`R aFe)rpQs ܻy(C.R.̦XDu-]xnZ)sEWu'ee&zW'^)7eƛ.}&0:՜Z1"[UXDߢ>x B}A!)h 07ulM}"ybŚ#e͓; k ״ kd?e,iPcrbƤOj5 ZUvL)[3ȥ мnϓIRy5yLV1#R:e7G.l"t(>N@4𣁃dh `49!r삺bxTwܰn=$]M}kA7& (ƽ`jʭ(@vMu*ψ2vr/7q^~i$LL3W2X\ĩ-cMll3dTctt㨐1uV]j[lGƪ!zd2. x9;ĠSo >IqZ|{B|eYJG-iTcTT(嵈T. T  4xh^ՂZ.)n QkܫB0W8g r쨛T$d[M2HӅUS3e > UGSFȯ_HklUFDP??X-)Z\4r/\ LXIIS'+)ÄTSQnOXXLkT]IX[~:"ᆫH:M#B Igxp uX @k-"h⨊  A>̯ mMϮ *5c3>\Ѹt{`IH~'ef1걲C}҂[EG֪1zCni\npZDy;"~z ԤPP7y @7,5]9NŐ#hSYJn!zd8RzG6mt&"Y%4HD"BE68/!e  E<JD,ib\EΪ$/X}k۴ Fw7ym 3ϋg >3B797.Ym/|Z&G{o wm;ߓwCOJH~V M @ j%~@[Cm:*l<{Җ5p4%n exmnuUrW!x-7>rO‡6_DyMJLxKAR+}ˢSX}pص=bSMM.MjN<rZ?:ڟ:u8..l39{=*z=E('z9g S׹ p)P gZ~|HiԳg$tھ~l_[LCP6t/O6'­p={wrP{y#BB Z9.ϋuMu3I>-rIeMh$cqAp{nEWOpߔa/1Cp>ڄt*xSE$rW~rEj5f;M]R_4Y0{"0!Ii 4p3rݕцm'X&,҃AeA!8HoҟP0gq}oح (<|u_doB3/D2gOGe8'@Kzf ]0Ҏ` 1|<ܿ.:4U0V+Q;6F.<ԪӴH0_*5t I*%JOΰrx,3=9f֬<}eVx-U.39->ڸ޺Ԟt7iOC4x)ړFh]&V66 ȵuO6.xR`(ogʀ \cv(׸ .8VTSo0pm.rMux4G\4w\<8>kga~3*$\ 7Q#/>"(ON]Ї_=. c@@*M'<Fz?2 z$*(źIh]QMCbX-?UZ92\WT8=,AnP=-D&g >ii aR:]hSpG\g9VVp`G4񂂓\* dgԂ U!L H xkb͎Bkٛ }߶\?tHɓbfH*:]'"iGND cׇ& [GUm@8s06g|9o ۏ5ǣP%((Ay*_%㜳~f*"utFŅ'|2i%%O׽5kim̉*Kc^lN) ~zy^ҷT7[s[ RM\Di\ђdZ2 AH,$C4 #:I:cF;sf'w^hTowSNFY;cT 2  .,t=r̊UOW?,H~}.ypoHmjMO ]E`ু;G?|kVL6H`6 W˜g!*cBP?:=7'HGh&;65k#U~;S"~*kNE3plFʣemRʹ÷ۗwnSDaF=xE쩥w`(#Kɾ+sфc~}×Ȟ>2~Pq { |H KͶdmxwwh,_4bFe=S7fck2vG鱰ɓT7k5@.րA\Bp<,bf,5a=Tk`>k"~"OS Xr?n QX aǨ\9zD51`36 pI$īfP*Dʎg=x98s{wl_}A"닭wYG EX;i 6hӸe67S c ')+50qXAνb|84+\Zyoo.ո#R-yppK`7'7~F ,<6(oI\eLY3|R|hKn| U qH_/;?.κ<ݻq0Q8]yMOc^ı(b% M#,h@ Pqw:C^I;<(6k|2r\YYݓ1>~CqzC (2w,cPg1C#bG,EL++.˂C/OsK#n 4>;owX1`f߲/aԜ75-/ c^4)úl6mé'NX>fʊ]ZLS֏؝EF,ʟA^)h7qac <'H2<\ ݏۭu`C̛ܞÂ!s } {9=2(/6听nFI:zct߼emu֯[]'Օ]c/v޾d .} RD p)2:.ڟ\vdHm8q'~ ]a睅MqgRM _@`Xs5&glNIT6XI_>?`E+I>h7dUG]Y䄆s_~t;~YPЦAg8?^c`?-n:qdO0 G;9=k'n9z̝k݅[21wvv+_8{ G_8v!ul>~Mpx0U!J -OdV54LLrNB odQ宒1HuzE>x\Ӣ5jfg)p(ȝ2TV@M/`٭g1PvQX{-`âr:F'@̨Xx Q;>] &.}?KY'V,XY\ n}^$sþ=*7~A{?>r&u''oo$7uw}T-Ķkl@9':>O (1PndrA5.wgT<? }΅ioDK}+x>Ϋ' ͠?o```%>QHN6XW?hZ |uhOcGW$ĝƃ8}j Gwj=5xTAoUi4Ep!kZ>rᎸ#!qPqp8!_츶 *v7ͼٙ!{Pyς ^K|# _/zFpn/m ^Kߠ*~;7ʟoчկVuv/tMZ!j# W`Ym Dp:?^_ V0\B7}]Iߤ/*? EW7gLzp z\Z&W]Z'dhD)H.5Qt چ CV tC }rf6KK{Tǝ(K! Yjp'49P V<~LČ&ym6i_HgeVB:(\Vmٽz=I]=3'$}n2gxǐ@4r㴀9l`S' x5ާ#`JpQh4};z8u?b;ö)gSDg:{띂IqZgdT!2&X,9quRc~}r+jqҹVEQQBsu,VhZ:IӹU]S=dYp3 @QO83UMfdUs%ifֻ)ޖ.V?6M2u#Ht9wWiZ'9I\:qpiǖ:;\ЭwDp8,;l:f?t_ c>ߺ"NUY2F|tpqIMueS2/3CJuZ oZ`xA"[;k\~tI2,:x}!yh` 1r~'oc8ʵA(DaYs0V;V9ZYU*l].w<µWgl"|h~xmxֆ8q̐ZҮ,LIMBزDR {23323㽷gG_?;;s9;gvv$97fw`VR2@Dèj4FKв-O+ЊLЪNkКMкOІmLЦmNh jǏC.E)FqJЖmMжmOIJQ2 FiD;dBSi'Fi4v]iF'ͦ(φ.C0NOp: hnCnat7ӑ |QPH$1ziz>.zZo$z^(KEGT2]@ڛSF紈bڇ}6@:-C0>#(>cUz^7Mzޥ>D>OST>O3L>s\>|!_%|)_Ɨ? | _|7| ʷ|w|??ʏ?O ?o~_e~_s5~7-~w=~?#?O3/+o?_#?/+ƿUDH4J f.#EF(-cd,#r +J"j!kZ#zl Fl"f-UB8JTbl)[ֲl+%#Yx m2QvIL)2Uvi2]fH,3eUfn!{lK2G:S %#E+$R̗*}/5Y e,%+r(r*r)Gr+r('r*r)gr+@.bD.r\!WU/Zk:^n&Yn[6];.[{>_!yXG1y\')yZg9y^-/ȋ,ȫ.oț-Ȼ/ȇ|,ȧ|._ȗ|-ȷOQ~U~{LmFmaڬuHuetY]NtE]IWUtU]MW5tM]Kut]]O tCH7MtSL7qjHQG]jL-u+Zmu;^Ҵf49M':Iw:EN:M mםu,Mw=tO{i^hvjA[{suWZVO t.źD}u?_ =XC0=\#(=Zc8=^O$=YOS4=]3,=[sQMt3=Lt]Ez!CEt^z^+JJW5z^ zޤ7-zަzޥw=zާ>D?>>Ot>s[_3E:΢o%Nsr:Nv}Y_W5} }Sҷ}WP?ҏT? RүVw?Oo2lĨ14&34fi1#(3ڌ1c2fYYެ`V4+*fUYݬa4k:f]Yl`64&fS܌3[V2a1qML$̖f+lk3ۛIɘəfi3fL6STflf]̮fn0{f/7sL4eM)f)^S63mY`EfYb1I$=V.&[ʂBR-304udoZ)76&T @J0)ouDXv Ft,Mo:Cc#鴒|ZH!Y]P^4@6fB #u#t{ P8 Pעń9mRgHS\DlƴwE6QsGLc]j>DX˼jP.˝ŎIZI6R f^ɿϓmr]+DžF'Ve{je~OAn- ›bë2rJOܝzKZJ}q%W.Bsc,jeȈuobqy?@jG5Dn#^-jqd_՗15d̺>.w/g2|T^2h6*)=jۃc?ڨI(F>fZ'X,&?h6%V{}=֮,/P&Ĭ"BGwNsϷkps0ughGT*s* k')h xwrNTYQp7WʕBW JÓ=lΗ+Ro+z# )E?l)n[ilѫVC2Ba|7o;p3Kfx ;{O9yٱ&kK =ESi^| ѩ=EM{}EI&Zz47P~a @7s: ||%~h 4Yü Rd*-,*zϜ >Tt/ ^+6T;RGgK~jV6K˄aM&ub84MBS44Bm;!C?~f`v;!C? >O' ~0&? ~0a?~#cAur"Gԉ?~|||||| >V]Oo? ~|N(QG? ~(QG?~ 1c?~ 1c?~8q7n8qp&M7n p;~ 'O N$I'O? ~$I'O?~ ||8ZqRI?~ )O? ~4iO? ~4iO?>%뒓?~*~ 3gπ?~,Ygς? ~,xu.]? ~9sρ?~9sρ?g.}뾋uźbwX].}뾋uźbwX].}뾋uźb~.懛a~.懋b~.懋b~.惋"]䫋|u.EWfڣ?W"_]䫋|u.EW"_]䫋|u.EWk(kӐU~iqfӸLͷ0 ,.IM¯}z:PƠqh竧ih:YM?~ )SO?~ )SO? ~4iO? ~4iπ?~ 3gπ?~ 3gς? ~,Ygς _gς? ~\qWYs@ρ>]C9(ívxuQh &IhjY+wb;sNi5K:{`} 6ux_^-6ЇCbC }11z"fn{7n8qp$'? IO0nw 5/yB)Up#돧߇F }|R.==-=]vK7Vea@~&cISnDfw5xk.e,=MA 4 Y_ah@]h&Fǁ_¿/\־r ȎbTv9;޼j[gW-ܖ]a9{WwnpoofC n lqȠ8^l:fR@@^xzFR L~s.4\oEK_ zar|AQnRYݖnJo:/ƕ*lqLPytvHmHƶq}^'2-C96𢃺v m ~a9fm;Avk!}+/$ѱm̠lv^}!V_ҭ6#XchC&:X!rmt໇?{=mev*բwZm:PiB&K ʸrwGFB{fxJ {z}E^@fXE8l F5z/u5}={}u3OBe\V>7gߴ}9YiBP1`T|>f au|~ܷoR3@>%0|o ߴX'|TPϲ‚ͷ }xQ* pqnB(;R(,{tt xMj`sωF5TyhZ݋CI1hnC"@݁pAEba̠.{[{ǝ>jXcHm*J{]>>l߾$nHDO hy+:hZ`6]mLKLm+<\4S*WS+f(ެxFn"Ң+9LPq1-FL(^:H4A'G:Ioѻt@2}9y p1zM10a͐N#GyaNy+nO3ȉ\6*TKuTO Ȟmfڈ,tN{>}@?Ӈ1]K$cȣ<^Ws y/q)>o'd;q;L), M,e+>"[kiuS=L2 :/UNb.RdmWs#ds/2ww!c|'g&b91OOcEJ2`*Sȉص*Dk5F}in ~3NfviAQrV6Ϣv0ϡ8v+hI4bՃy=2d^@LO !s-Kw#se*C3e;0KZ\ li.v`tI'0W0RX-}N`1$lA`HwnWݡۦۡyw*1ծiyڄ_  ˅yB&#=9e p\VfY,S18}.3Z\20)h琉-zkhg.Žڤl<\)r0ދkUs0N אnX/۝kǵ+S|k=o+O1݉^xi GT`?v+I"ݒi]")GrH{0b9?  h5E4B6^rT]\k\>kk%OKv>t>r::v>s& 67 os퐏`Uxqzb'񤞆͢|#Te}OB֔iBm>G>&ЍmA{'уlv?_;TD%s̼h#i3n1ϚQyL7w4}OFyoMػ:Mctg5~sxHkkdcV~!m/6c?_5Z8"~3^fkpO޶dOefB>nXhS򹍞"ی׷yʌAJJVkupsۥEvHItH2ΤwgqJN ˀDdоJmgv {[;Z:2sSC!k]̯`ooH |M)UVn3f -^WW{-rW_*#SJrn]h/}bUdީ!xݜ}Ty3`FLOLwOOcr0„`a !b A #,!b-&X1GfYAdr0Y"s0F!`ت )Zg=k޺u~Uuki}jn谑c57̙3 -7cڔ9ڈΝ׬SsG3/_ƓyBO> e "|hWw=K4⿠FT_:4l4_ޫiQҦPk5mzikBij:ۑwN@n:tJ[6*[o[?[6 68DffB=m[l[f[%Kal{Ӷjmm?!Qq3KB]ݰuK[Os!ͭP@s *\j5yLxISuBkBݴkzivTȞG6>>j}}}PK+k`[ghj}}'{a?b~~Zs+]jh-[`TWQԾToվj!ǩN:~j nU)ww@V*Qe%aTc&R=M5Ͻj{9jZ MT[ۨr>@u}]) Tרnv(uw1t9JpQc&tL1jN|EKVvZױꍎT;vR:qꝎT;Q]BuRӛjN"UC<#<3C#aE>[#au>D6Vvu}\Nȕwhg47v?g6̦~fSh??lg6/3WM̦7ɿOO'gI4)\*TC40$@ *P 0FM̦f , l i@4p,l8`6 \0MZ47Hւd-`(lMÃ̦Af ipf48?l\d6 27M[̦Af`W4x$l<d6 2MB/;DB!_"T_ht&_hF_hqV_h}6 q5j.t(\xЙWsK!B7B\ͅan0 / p)L#/<>LS/<;L /&3i򗾔&if_!C2C2;2L)3,32#XˌLL232 3ڌ))%-#r22fNe/ ˙kAIVgfAY[֑DdCD6dgGefg'gggfŘggefHgde7fffgwfŨfGb,'bW׳rbrsr91Z9{ΕRBnhNLntn\nbNGnFnVnnܲܪK9˽ۜ{3[nW+Wܹ9s'sg]qŝsŝA~`<<|jX1y]\LKE_/fw_q_d "+^-bw_i`ZK(RTV"1%WT"K4DJKJ䯴DJJ_+++["%W\"e%r}_V&eOeW_yT''SM/2+/*2++eW^&=.eW~Lʧ|LbTzWi*;B* *2B**2B**te1ղ T!u+fUvUH]eUVH]d \Jw'I:vNR$uհΑXtsj'W7;\عu$k:7Qm$kou}dMӍWvo~ c~-}`>r|~ }(~ _r0,_@mYa\(/E֦eh,55ϟ!?w Uf!jJ6t+J9sʂZzf.ڽiM!aS,a42Z;(gs76ʟ骄fhU(X 5߄ECQQka A/z9н(pmƃ;UoHG KpסEو-"e#kU⪟*-kZr=ֆ6,V%}z'`Oʂ!=PU,@m,ze?Ek*=@(*g >RӟzdQ0x} S?W2yؑ%̹b"oxXܞ} U01߯U2>C睉K(LI?R*kwgUk #9ǰUT'olboI0iD~NQ vK*+U^dّ۪)tw- \-Zh*GE[Ycɬ$_aF||׵sM6V3URsRDGM&ʚ6-] 2P?$9ED~ʮ?=fF< o`u_F=i_akv ̳Z j Huݔ?Dl*R}Zϭ1[&5;"վdEH 1sZ@z`h U+sbDQh5 A1&{ծ5_ Q}[]+ozʧ3r%g$ʮV46Yi=e(C[[L53~f}cRw7,C#7Qb|յ#b+@dc0bM[?HbW?@{/3i3_h޽w/X |\xWjhI@Q\{>:C*z| K{='KF?ݻg4Ц;ZӜZ|L41mxdHvͽs<1Cg>wP,xϚ;x]п~VV +q>ا[ι}%4@T&qm}5ֵ [ר3v` 4f]@j®x識J? ;Ω?sEEƔ `>s0|L}:ֺ1M' /๞_fg8*} SІբe|& ]ڞTj@9(ߨS ^|dy mPe5j}h@ ǎ}mX-gNuPg;[{:a.[>=1 4ݪ C8_kSOʲ˘ce=㞜hƟ\h=eoEn_fD2b|1ݸoS/ɛ~cQsV;*N37O? d 6~E 1þ[0 wY C{$j_SK`W{^i?Wz[Pgڿw|-VNJ3a'˲_R[m{j_l[ieĖϲW]i UsW ~7igMG{3K>vpj}{:j^tfk>K%5;UL{Q:AܡVcld{sU+kvә/X}ƴŎp`NTk p8υōtcWZ`Wh9%U)׫he#mNEcdQz^_@!K6"!G[v?Ts?yx5`~fSB{Ÿ4ҮJؗ ]ZT Uq*aT%ڰfk?i&G7kOS*U¾TEe(ud;eMߪJBͰ,W%,Tr=}Uz_ݷK}'Tzf|KVWa˟ S#[_cz۪}oAJؿcJu0SSXΪqֿ gtQjDی Z3 {+,>>EuZkA۰W95;:Î82jCjm~'̲Ne_~&G&S=+jQoT{z0ճTgǛ7Moyzo?շ!RW߆fL?I8e跪#}Z͎~ֳNvFjAힷ$߫_=;]>Wy:v+Ϸ?2٧hhl{l}>fǸЎ~KKRWaǸWe,:`B{>~d_gNЅtA2W\uǼWיcjvy_el٪v%6Vѯ~6Kp֯~jӸmTwx7ew`RSa",3Г)Wo¤5jƻ|?,C{ gֽrw{>nbg9*M~'Kgȹ > c ٚUh}\3¶Vh7imۗ0: 5YPjs,u(癮z >YBo_S.M^ͽ% C((y[\unQ~\+AwػA,>Sd씥5ن;KZ&ɿ޹~WGk}: h9f>Z6P"aT}#[xS==uX~ZCv1|>x᝗}-R菾b Z[YCӂ3bjkM#둹CM_MW~YfS,>h#>bסgt8$''>1SƚE#=3^`..SE] 8Af""Yobr)%F{FF~Mvɾ\Wo˷(GDoS\r=&wQ}oO[DyZ<-!e7#1xm6U{\jK"LHo_NK]@UQ9Q?/lhBLz5_ԉvu`vW,a%fΦ~5$b5Amߚ&.w_W_]#߸ouͼ_,?j$w&Qinc/fonts/OpenSans-Medium.woff2000060400000164534147177152050012401 0ustar00wOF2\>l`?STATZv|   j6$N dj [HȑnIyLvJbxZm\V]q|p8{[X*WM,qEՈ'Qq[Op(z?6pB2TbQ0Q=hR%CIXi~] l L ge2wY:uɶ *93^fZ}p pN$GRd{meTJj5<q;rsiAb$uH]UZBP%yF$2Ъ2mfA~fd7gyvh(C+dɾeW Pa永*C5Wu|ǿ܅ȤڨJeU9U}S`zfjF-`ѥ"ѢD "mۀu|޿d&9$ rGu@?u= i\b\ &*cwuY:FY=^'~Dz`!I8HZ_ַڅFiHdZ oY'f!CX@ڵ}Ap-S^Ѥls `MRK$?,n}f}T}j'7}P3h(q,%~p-"ʕWʕ+E!\WDD\BͅwBb^ "D BDml2?v(/̾7e7\Vݡ (0ئHg58bK9#TFEPBj&`\72>q9"f{EBت-~R} Of% W*(ի99Ъc4,չ5g~!8Wg$z'7l(t7ΝGTTwoك~'X [sO.=O(dȩ L3ĭ4HI@N h p@8u$լVĿ!/3 o%bȕ-oHj,MujP`UR~'#Oe3\?,H R~ET4ۓr2r>:9Ŋ_~m3++Q hKvfkYew_2QUU  #* Mt88!Ef?f+iEqog;YfnO]+˙RRɮ\ҝR|sG*9V!pV]<}2čyOqG#QPlٿ7wu` ᚗ0??aXpG?`A$L'"R@sU+^ `&<ܲW#c>LJ t}9ئ s="e:(gRmX`B3aF0"aEYDD?|JsUU5"""|g'itecC^ǘZMs+' rɏpѱ"c+xF'A=dwO 7uL̘ph@bĀd)P R 9 d"o@|䣏 A>ĠAq ?S@ k A:$'a,6@O\2>)(iY`cZA<%g%J ij*Ӡ5_mVz++&i4 IQ(٩FȩIuqGYpXq/P@ e,~8D /(;a7C1l ]ͽt_"A,P Ob89G %>w M05uVջi2!% ЖU#ܕ {bޖoSP)DrIavLYmY@{P2 !a( c18mi`4agIuV6 JrҋVtSu%w-}w:o݇fأ ^ʊ^$Obzw< 8/F(Fn␨`YJ4I>fq%`aᒍ}73aJx1{`QtlEa4wI"C\7)gPAU3u!1hؑ\ĆOb%])eLs ||CEIvB1{(B<)J)e#k *$dθ(HH!2Q/[>X@`;:u`J%=T*@W"gtl!Hj 9!<RI3V )r!%/ZB !hk{iAlmҘgʰ,Qʚr^~u{J׋rbĢ>+b}/+Wa%\5TRtKsȂTɖBN-]9jVUXEX*P6d׈Ex9(E=%T,JTDMh SRu $A퉂)Eq\-ZrJx#jUj)~g+[ղ:+H[vY%GMS_(}үnn+;y<UIok4]_SESZ*aIRY^jU߱W;L H^I;=kjz.GO*]cX< KbnO(C:VnGxO݌$ !E#F9R9,bgNھD'J敍%Ԗ険z UٖaÏ-T2 u@ 7岆AhV̈1͈PFG 2 JFsG~vpFQ篫Ͼ9A64E/i| `&sYUl q| &BTp2c&pL%ɥhnf~9klug|q2 KXbx2lhذݶDAakIq7.q$B%OR2Ǿ=Tۏl1h[(~2Qʑhmdؿ:W='r`'8>m* ;w & A=տ6봒0)@>\NQɶ/ gS`sBEW<݃ =|/ddc;2KALl;lװZn@ԣgkFn:x#~"Qu_X;7w7߼ӾGL&xtWz7;(i¸q%p^J85pפZ][9Us$?`?o^4^͒2.jo_t&~W~U$x՗Bs"P79R؃fo^+|'W aZ|lx&~Q*'Gt,E#hK>ڇ .|/KԿF>51vR-( ۲MIl˯M qN,Mh_CY=]|,Tν1Ju~%ḼoTh'u pvt` vkCzDϖ7-j դg:/KW[oOƐԶ8dSTtCd*R#:=-RϜ0ӌB׹qrQѶ8\0s*G3Rj 2+,'E)TI&X޲v qiT НLƞf1 V̤@bހ<̣KD96\}cx)]˗Alhe\7&ZJ1ሜ1BKK^Wxcp.][qeNl%Wsuϴ99 Җeܟr>܊+jW$2]Q?VcKYqo{>͑?NYB#2ťV}(e{ܷSzi"r}>fBIK}LD8X=q rhM<iZc{{TZP31*0_F3ӗ~WY!%]Ơ`R'ϊ{[in]n3燡VܰJqxQ#9< }z#O8k# gsNr8*v0F@a;F`K3mXpE9 fJonVܪ6P \!cDS;)Lg5Vur? ֏Xm"\MT)>WZ8Ena3monp,~n}v}f5K N؋O>i#3ҙ ~hqFO( ޛ3o^:HTVwD],=\X1^;,p|Pȅ>J3ԭ`h0\B\)Pz}!|ߥs3 jԴ`C4s 6"o(1董ښB_^^9pkB$ej[ι*G A1MKӛ@Ӹ֠;xNŻlC!F&; :K.}MŠ1Uט`dAd%3`wtZur-Xa$T~ݥy1}_1O bb-I$]%墔1T6:aͶupDÆ TA@ EדlF@SL<81t C5iWͳgw6DCRdLsAo#=1NʒD *vq~KTpw~b]Y#TQoKjJd[ xYDVuLjm2]M.1b=x9a/~vړ~RHEmp&ؕfD#m#SYrzz(@\cƧ8ӆwx"\K"s戬8jա64a7ҹw.vWs3(Yc#0e5%Sք O;3)Oz3O"4g#AS"_330^K51CiE*,Y/nyq(,4\Zr/\:~Q/' (K[F@JЂF-j]Mq3/EMZV`qDM:y֜Bʃ[hBQ4 QDф&&s`fG''* aw,_ ~fQZq~3.=r_ Т->"7-kylJTa2 NL3V!>L욃?I%Y=HH]z o~P1ialm=Md|LTjDMPL2;-cDaa IIˤA|YPĥWĉ4/+)%W'AG#P"1NĒH9ލia/oT ~Kr.wTQuGF'S&oLyP='U[NĽRy->(#ge9-TgJU=ӵ~ g)!yZt*"HgL'[tz?!T\k+i7C$b܆ Ǫ!cpJ$=khݔC's20^l'G\oK\OfdFBBl@ :F65gQy'AeP i{׃`3X߼_ d"oN[0>Q!)O⡩\6>,?`Ppa8 芯 jpPu:z_ijtB'C  :}cwd5mJv& o=O+-xjY5꜎|-k3/dq7aMQsSe@Mgpr(iY9y=kPqs;W<|+qߨ؟rww7~CdŬ/ ($,bƬ*@USAY,#:I.xn <{ͻ-\}0X@$F> -=#3 ;7/\/&][N=R.Q_`KfjCs[g$2VnAq[@!D[Jezmv[˂2I  HDrDT 24Xw>tc1ک'p " b Ph#/xkk԰-.B:dg*Tj*qno4*b7c.5JfMַ7 t\ !dDw}t+nl ȠUTSC-Ye |ߠ}AMnC.|(: DG cJߏPgι#rdJDZ5"UiD5# Z&d=X&0of(o4<q qWq q7_Z :J7$t J\m!)}/eq Kx-ӜKDV*ݞYme1+L ^Qy]TC1=vlk#RpQB ~x2'? !|@a=;##֙ƒ@odQ2l@؜CD$3?M6C]0NW E(%k$$ed) $21ko2SY᮪Ū$>ƌC_fd#ĮuD(d,q&`\ys9\lQHZsx ?o36=S=KҢ^s#y ݆!s>x`L%Y] -t!c ΰUm|žq^J2YǗX ^7G`gkCX4* h0tQ$K5AA/oIa*ɣ)&|>M KB`u@GVe/:ZX09aF!u16˧YKy3o("!RTNP;Iks  &潒WW1_~SKd ry (  % Tj:@#),hlvA`g@L {!v3  !Y,!_u-]Zש4#}럔5@PQAD7~tu5\i@Q|yҟowk.r3>,-4e(O]?6l o3ƝH Da-TфzD (ڍRP2G  '|p$  f,ɓe s e] ߹$pA% EPAm(Mvk67|Jyh̜Ҏ*8UZhBcab'^Y=+oEnfG&퀦 "|J^QtLSj4^5 !MA$eNi6 uVioU*'2XN;phƮ+%X>Mb[S ׺GA#/,!U[qyNn.mx4`$X4h]]ϺO^[y zӲ5|R4dC\ޕ 1>`fC+Boy!S ]yDRuq=%&)yчW, `z-l-O8(d2 b:&9Rn0^Ke\ɊI"(g rP,U)4 `ְpnvӢ;:4 T34i;Q#V O~Y"LFn.t;:zɸ*zvTR̜Oւȇ{@0\2>O~e$@wZR]LoG:Wx)2XYq !4,JwjĜFP}{Jʥ ^ c6!x?UYVaK\ϲu53\bhFVemT'TT*)/i9+҅jBk Á1"yiJhƂkqݾ䥪 ~h0 ɢ˦t_`J/QT]"PτѬWܱ~(B;U>JK .<6 &q@jQVP"CTk`|/T(Âe= MUnQ92UYt{"s!!Ӌ"A/[zeal9eۭ.5,NL#L~ ٭8n(<ЕIɞ9&M>djgw݀Rեg;_yJh~gYn vTuӊ[8<} Q8邯%[ffM 8d]٫USy9Uq}[CXt0| 30g;"įSpVK95LW7 ]-*?R4lBClsђ5a1b_E8ްcl5@&DYsuBqD㲠m"I. p@g=m o{v40k|: @w|% 3xTC4^vN-kH?ϹT (sQy2,'oӊpdGӅ_}. hkBqԗ3fɰRK ёE<;W)[DМmҼRL%fsSʶ'A`Pn2Y1Y0 0=a>N -HbyXSF9iކ 6$ycX M'~ c7}_3isK,F(?ļڱ$G3D : @! I 5k%cnAQfCm/j^,WRې:_! ѹDr#~=g)/]L t54ΐLtuf %aLΉڃ0Z/Cièiƒ1:xD@7E"jhL=q<7Mxߌş~ٟllՊ e KA43&$whbڰZ7ͺ^6kә.5%h՛3'޴];7o<{5<-L@3RgV͜1} 1B_.F`)w~6>cSF MH]Du>o75slEL1eWe 32 es0N8pqiu1®|~_^. ]:ǜE`ŕO 5N\:c)ʰ -N]a_OqAmpQ>8L//Er> 8B}Çj_pIs!o7BAD;6(n Y0I}6Rt)R XnR)šu,>% >! \evX:"I7K25,PjXf<8N02_!ȕ12Rƪ}}B#mϹisaS\8] Ũ2[) AAWet'H\#@w{{ߢ,itGh58X*q e_ˋ6A1QFxrB3 p%.Tt>x+\Fಀ^ ;uIbdn#uW"T`Tr١:3$:q؜G=V,V)^T @{˯APĶGҙ | p$K`OUV8G~IXUT /٘ؓ[M5/c, 7jJl9dV>joJwA>Ίor)?|E9Bg[HԊ\z4x|ŴKH|B^mN4b!*$^D{;qҗI2CD_s=i# <ߢsq 1@^ '7]7<8:N|eG[>'cs~Ζrk,ǵ]tI;2IM괹wMbOxNZɭtRl튦8:j*+vY)91w^`ݘYp Aݓy* i%t"H-xL6){xxr5EL- }SE$2G0IMMȊ-.q幫'?6,M+!&Zz@ DҔl*rޭ;/]qNc(a|Ϸ"OBm %=ᐥ}ؘn:ipgr`v "*B@ %f懪St{ CuKpJ6y8h4UE#>EX(0= [lDr7 |ܕŊ }ҚwX;%N3YƬIԹ O\JY*IO9cfg4%I1$g0>ZH'pj?012%ʚge[<B#:ਣݣ98$fw;^ AEWN+M np OutŪ+"py#OdLfmn~&_i#~Jk rCt+pnF/8RT|-Ͻ-TWۮl^Y-Q 5Mњtiz< z[Ct3P \Yb`eX(zCx %Lin!9x}E~`ue|Y0I \Y=2De_Q^M.NZvd 3i ;'8:'Z_ 즯;iaYj}>,dh"sWfS$Ƀk,|GgE ƸΡK4 #B*BQύ5 "M-.o<Ί־1_HHQZcp)rnox(5Tj(I̜|j^FuO&U<i@WA9ڈs;:`pr>0&`['b`4|g;k|#PQ3)~K-ϴ}rK^ϰ10z/DB8m֏j`jZ2+ pqnh>*@lg"X=^n' \W>֥GDL);IK}1* swQES9JW"5\EQMeXu]!֕eʂxf*Kkc[gS|UԌ.ռډ[4 (G=b>p[C*ƌ~ a5c͖~RXIBհa/]A]`oxD4Lxڝ.ZҖ|qK^xxIpdm5~j=<! vT0=&#ͩKC׭!3R-g<3z'(=4``.}p\,~TЅ[p%9so lI`+5TIv 1߬f/lw-7)U7#'eF%'גh qT;5J!z@h"1(D1#:Ňotc1% GԐ`;B),#U%d͊=RoD~ K{@ dUx.1owڌB/$7G7d< o~1WIrTT[`%ٓC [-m吵rkkt J yrt{)߰ml-ΚH%?V)B ,_G߬qzʚڻuHB37&_>*oXFr@WC&"RxAcĝ+Glm|J31%3d X`" ӄ^EPR8,aE8r[<#;EhmZ]4\(uE>rN=k>K{*њP.,Ufͣ)Pq-~~+9hfB6K,Udٱm P#dΎJ\eͦ]T^?>8=>8:cTV1 3$w8RK!'ca`#p7ҧ!H1 ߫~Jron<}ڈK`qWqypX OR&e rqq[JIJ[*;Dyͬt*}y!FͷZm C-4j{a{x-7-ہkrn( < Jhi^A9wIuU2!W.x n|%8(ˡI2.w)#gJL$ >ctqȈ瓉rrIKt—!@(rP,v+5^g䡾' rI'Y&(퓇Nɷ+ z0b@JB*w3>̗2"qo~gx.:w[ Zh΋pE[;̷=,d"!H3*kJOv9-\wɈ崌2$|t@Rzz/ 7[2ׯc6paZzЙKp'ҝ^5zh&ho4<5*@vH6SRn68w bWoHD{OpS#_P[B&1wέ-OoF oSrqB:`LHY$#~vǿzp `JA] LXž2O.=F~u`,GQBK?FzT1U ][u xX Vf`< B+fccɌԌKLu{[G}SEuJSl0Y,\V:SeQ~ݟl.~§D;Ozt=4;zԒwKbGq[T:){\kŠLةF!]wK<|zmFWëpTApg'=;2n 35%o+vL"28"|!ۓtU2T4~:uc_W+t[x>vSGmc97g)F?{V1~y$5CErRsNvP7l<l.Ps$ o@^ltZ[yNzp $,ڢDmWܩMţPAt C';3% ȏR<|h4eI7_m_wE…w3"m :z /\Ȧ-Nmh+6Z$rbY1AkZ""~eQ_mR;7NXum!~ zYdY'(L&6קDW@ȟy ] &en>,->(}s8QVH|%|ᔣSZI[3Mڗ(46v<<6$0r*bƿ S͑CKiX*9j׮֪I=Xp̘r7L`.->9̴88DOg@.͑v#JLkL7v0xQ_YW.Pڤy88'.ZI@f]~ DI FDq?o˪4~=囑>=0Mpl\I,취 _GŻ=p;5'[zrAi\XDOojo0Tf!|1H'n6;S\Lg^mܠfDHq Oell\Jd /P9VLydrD^yxx˨ULwzͺoE&4zgT׀cj՛9`d?ɷ1cJ֒t[ޕ$FOA^T h^:sI2JM7U(nbyim|Ptq8q^o7(اmv0#yӪ<&y>͍p-d9Y0t}SV6FbMDd*dA|5#(:ۼOH-d\0)?|?BLiPLN;RsuJ*jOrߵ_wLV&i [C7}L[k/+W`gH U#(nSn|i!'bw Mȳ* >y?7z7E֡g{6k/^/yT9hskBUXSlR$stѧF&;\( 7VKh0%+/]}.9T!g2}"95MW4;qeopwSYAen[b=82AѴfYx'SO`%9nmr|~Bon Zg ={ib6)^}N{b=(O [|X#!Ai WBCWimDf}[4 _/Z+~G婨Ov_ 4r]V׽O~YаSc>正J0QM̨dD}ݸkj5jj;ݕw;JNx2^}t5Z>FRL\ʋ3H-{E8rpalyqپ#mCG\/y-e<ڝyh㻴S'_}5nFnrfK~:[TdsW-FW7ί7 -z=;\%Gmp9yu&kg%=5W}fw%N[8.[~Cz7?xG V`u%}U.ثf/1)ljp{ķ63ﻀY3O>ۇ/c@wL0ef .y(YI4 ccWWkcзg~.}/#- s?9q1kg%m_f!_:#{SՃx`eKqћǙ\"+YVcvWy/[qR<ѝZlJQ͂ⅇEip<('R)m%hc6@?arNɮO$ >:<4829F);oU {[>xPI 7v;Gmn>Xh:qaHmlgތ={3ͅS_Jx"gi[g\D"[GS{S_ݷK}{`|l2 Y3k>K1y^ZFO9&Zd߬MGbN=H=]EB,mWW|#u-H !.uLtb֙ c%;֦<֐֕ xHlCj=T-Zˍk,շŝ51;0lLJ 66,>cm~6IZpn稥ϼ8lBގߏZR 2jڰQٳks١uFN[>=[.>QCgz X ʜ*`y!\!>+ z͉ +Z&_ޡ5_m?9R[i/V3ۨAn6-)5)k(ͱ5^{s J#w"gǥ]@KLzV?fOgc|3*g*εmhƌ':4-kl!Z&{x[^L2Rn\j- ="h>6(# Ci.pR>KZ#ԊvYJ|%3/*?_/V(>|4`΀" ^~T|p`I&f: +Һx}MC$?IQ D8>o-4RjiW\\lCqasZRMM2h`(ۢ-%,Ł=3tт(ppimmx YZHx7UKStɟl|)ˆVo)iaH(έQ냉T1 MraIQz,lh:v8[-2W`T儣"PW㨑ywTn;5RBrȼ6mPS.EX+`%hU"-9bٸu_ [ @TD @!%q N8VKI4znD{kKlЎ plP`vo#l=$h&W* i |SﮖJcۥCW-˅pm ٻ@FnNO5(N=u·CskHns{=4%)jt!4u_K {7ii؏>,~ҜzAO"ףB F'b )$4KmǴ%D5`:׾twBMIV6ZL-^X+0㠿X/Id@dT;_Jw|\nEyJЮ$uqsa>dBC-H|?zb >Zj`क़+1bNٚ &H(R[8ɉ(Im=͟w Mzel궓4fVB ,W>gaǧs[ _R+E(x7mݯx\bA x*ZDqwXKG aV:_B;*hX(*: 8M)fLu33:>:[{EQ\DGR<:/YSGeEj e @8t K)TVgF&p\f`;33lf9|I_ !`(FMVrإ߾tgezӂpɉ 2CqR\?CGjzq"}RyS`,jFBǡŁV8RNaXeqIGK$&%(`ILfTj3w;䀻zXaEp 02nJҌ(;9Mh*-jL=YƏ{/7U3叹zb]CSQ Dr, x{͋uc,urǫA2!j>`2-gfp 9E<}2%cıǕqu0ēnQ7[_mƓHwu8\ID͒cߓzJP\ffb2lq풿1xBr\.5mn`G ) /o[a(i QsJu By y*Wug]x5!Lc#%o ]@D_^BFLy4 *oO7z (d)4t j9p6#5q5%w_NT'"e~A G쁓Nݬ}n}HYvƽ;9|8lVNXp&,9TVK@A 冐28ޏ6BHԈx59J0ѭ_ ;>,'Z[6bd ,},jȩmaˡs#^'9Y1.gŶ<]BÔZ"C,)Ǣbl4+%XD2"ՃUX~2ioU[A5%1~WR82)0F'qP6fj!5'Wg7+?Au`)H!$~}$2&$5 #;kOrdǺqNB.V=w ߞR1C!]Ի#, :W T֭5*276V#:MNQ]P=rpj>x'ru5E؈BǙVT4%B6M֑_-룙W ;Y|JS1%FOWNU%fY98h`g(nbg^LhX="w<|_BVՌ>=zygܭɊ7 5uwk;2/1-MJm\ݙId0r}F?*/1 ZB(&njւ50om=bLM#F k-„5lCIki+dȾ&eMMjWk}rJi\W/`gIc]$v{CB3|\ܳ7"Oυb^j>g@;UǥƦ:Jt /4Et{2RىU4X$7;œ [Y긌>X'hVJ#ᱣQ-x>T=Mѭ^)kKpZ܁\gs-&&-OF_1žr`r&܌Y_2+t,nijk &x/ix c{oQu~N+)ᩃ-\G|8?ވh豭q׸abD;qRhS :%/~{b ޔowڪv2;1]۶I)}b,*H^hՌw j} Mq?BoPKЌ}[|#$@mwe^;CTzHveYö=!I{\0aŽ1Es&G?xH?%V/)lI_i1~99xlHAy^s׭CHj7P5B#`7!1%0GZ OuPNFC [ĝҢ5矽13U-/d%$-rr, Y It {:K cMz<@N|;lj _(TBD) +KӇ2l.Tԯ*ݗޗJ~0:ydh݂0@ڴKl h@q~ kt> wZsbв,89NMX˵з.{:3[9٠*#?mT/݉X0 denO+U(,>?C2iEzFcrTZ!_6J{ڷ5v) !wbd Ơo/XX Ykz#̲H6\j=\H[9x3'oU?cR_~)MNPM,#pGv}^$9?t:B6pQ3~X_c8O+q?h\J_uۈ%DDo: +qdt \ܽYy0S|G*Z"*ۮIrF7z^aee>okw }&B[#>]1kЬթ6&WĘ H[:mlҜFOHܛ\* vQVtROGjPLN4*xђ>u6&NZ 2i)ב^Pb~׷:&J9 "8웪()($!dʣç6v eL qWui80CǫvIaWt9q+ܾPFabrm#.-@f0utЀF*HGN|+dgQ&O:| I~#OKz^Mgf 5R\7o‘(*BNe&F>Gg H$>Im9SPJIe]?BWɻ?Ҙ'vVݡg2+b8T @P+NdNbkbT^>#"Qs*xTt86.%EAd4z70,(U).M9T]eb|BaS^Ar&he0LaB}:QQq)G;9On#0Ff#/3ڣz!vCPRS<bH.~~>Du)Bձ`bC;7U\MϲRJfC5EG6֯z.< U'A1fK.ԩ=a^Latz~vaV۷F)Kaf=/x[9rҿmc,ݦC D-U~TBu5|e@Q 0^ ~<|6ew1K/t᩼yyyj  پyI3:rD_m{i_U"/%㓃Ƀ$J#(\#2F2 fIE # _ۇ}ABDY_a~u5)/ty?GёK46,vb6 IycD@d$'ƲTVbl"#`k2k%[:sݏ [oދ* >UXL(55{%gkH]5I5Lpv0_Iv@Tq9L*%3|(;OBIFďԏLY"P,!qlZ C)Ȃ rlB9o/RЈ(1;%- P\^+c,bě?H}Q <8PKD%g\9I)*:p,`(ʞ#6Vr[ re4JF'FcN~O zq@?'~!Rz=( A|5fEmc*E;AAc!Y?DDaMt$2LԔтTӓ7s,WFYNle#QbRˏ*72Y/do8Jn(YI3Y2OTz6|%nr 6Ndѻ0"UJ ]^*V12!8$#&)Ĕ"/TYJ-k&"'Lw~iKO=#vl/\El Y.l\[/YE+sm}l1"T"'|B **ѻoxc) D?fy$~wr20N͡1>wi}2j~fx#bTwu%hHG~X@Q %HXf:l ;˹sғP,>f/q׭Y{nݛlHѕ沋\c2۩5n+K@giTU#T$oėɜFlb`G[T[Dk XK ʑKR3%;C& EΡ!fP6l\F.YTԔD Tu`$kF@$2B7)X5 M<<`ieʤ-6jrWG6;ݔ%31aE^< @FB4ޘftt1Ś,6 `ȵ4gkP, fh.LWABvv ޾d:Dp^ߔ}I_qITnq^PK#66XNG1hd]~*u -dCq2Y=dV\2@r5my\xez@ҳM`q0ˉg:iP/0Xq >a*/nd_0rEq=9axcߚ$GhD(ǭm]\::,,s+ss]CXD9W;¿}Z.S2W:ÿYd͚EϝIJQ6zh:8K#}xh *A ՇAivx!.(@gǯ*;}uPx(#\q<6H/>tR/.-%窢phY_nJqUgVwӖn6\5JvvćS-bGcI$++ī E2d)LR|&\OI=J}ەoY#_56la%)izba~pE g\Y+q֧SZہ*3H) s :*|9ɑgU{9.0" )N>h˝~ʒ<ьKT VX EAEuӈip~!6P#&xB1 44:/N՘#хҗBࠐIj8#Ѫ:AvN8Pz3%:n /@IɳNc$ $e,z>AzXQ!'Y6)āmY9\im=)pnJcwt.류vb î,.oVXSY4,KE0CvpT]M}`]\4[Ǵ"J4+ǎ'As3ӱZg- mT2QItܼ//T>8XMllvVK:O9\sڕ`; sSPB/JF6AD=%!7"-5=ZA&Pk]\xZ~eL iz?00[O8/;Z0/G-7Zx ~Zkz VN"fO,|2I'K1htNkPMK~ݐ~+d9]D3?¿'X1hπP2]WzN{|^uKTCU[yBFn~œm үٶi@j4%6| QK=qmmr)eweƣ3N_;|ߔWGm.1 _)+BgzDVVs ˸iWvMQc~"o8/-yynmmk k hDz`7v{ɭJ(Bgqu+KlTERp';DtѣYo\g=wvCuJԺP$S'u5`<3cU #Iwy߯% WNG [~ Q#ڿ-܁hV֏c?(Y?9!>nj*6q4Z_=w02(ΉIѧdmllg`x? )Y~3C- A>4{cń}~CՏIז[Jzv~%h':hWF6z? v}QG βg:&Z@u3 pf% щ>9Us#hPKS9bUYsĖa\uhĈj:1͡= ywv y|3{u- v41KPBxmm%BݻlPFf>|t&l̛POv{2g0h0A[v&@`Zfx}m@`l/}DbKb4Df֒W_𩳮>D|3=id ."đ9'p7$޾+~#I{ݿ2Q)+rzS;Xs7(Ы |C=n*qri^XO?R7t8[i#v#| >:ܐqi0xpDmN:?++ramG=4!hlΒs2K"Wj+"OE:sA蹁ǖt2?GUbui Q(G߆zU)eBOokܐO7jt\w@UHԂ0򵀉= 2w0[AʯU~ Gw1 WUЃL~Tc auvW;߀_&Zm+fcg R<`fRQ?ZO5lY|;CXH0!*4CW`_rMm!s PnJArيW_ȩӭde7 ȓ/[w|O#7Jdk]M?[PkR-xazUYX:4vFgSكݑzIVD +mux6#> JT@3|Y~l\GZ 6ܠxD7J#Ba#5 ˋ啨)?H;L)?p4JMI94cy*v79‡tJ2LÁ\"+8@M+pzDO\,96XV-]dl}wRR9Evc_&zۥ*cÉh߷[|gTs6{v\-k:4mUTP%s<%CeHI̼ Ӻz^&Œ ߚ ѹk]kl >.Yd7災-E 7dzZ+g'#,52 bJ~0,? +x$31(EؔF?j^V;fWʌ"o_X+51VVF/S.Y&886:Z<+?AN=aW^( Ӷi8d.YE_dːKa_mzE/.i{-uޱ(cL!V*yhnVi*P@YAթ1mf^;We݇s)m3xܥ@~hqq49t![l^tn%uN0k{q8(/4#:~+F;|<]1F NM_cH0% ]7D [5RC;"5 ,X~&D (3!! .a Zi1'b.;|E4[sBۤ^ Ps2zR:NC/ gofEcwB Ǐ"Γ J83@8/3z Wߪ$=}OFBZ/IK)\eX`޵oo`}\AѬ`lI3S .R)QχCn'>\bEњ,-ׁ{ۅMm@?ZYOFҩ * 766ⷧF="IN[*73H"@5/>uv϶rBQrU ]f3 t-OX}Gϧ2p`)ˍW$= 4֢LߏDQYu}%Rpo Ѵxp+S@>~41q5yDMFB=sU w'Oq~%,h-˗c[P#ލ$L'͘yL}0)yX) :#4=Q4Io F]q[(oe5޸6_*aͽ5`9wʦϞHMg]Kv;s ֱY`BW6erOKsLe?9.63@2<z|wd+>v ĚH a,׻'.S LG'OA@Ni5)?Zm;iRԜ[E,r8`̇a|U" 6 /:|5!r !skD&) ЇZx>8A䮳B[.uWW蓜dej ܍$fSXae'̏U}H^ok3+)N 0RIxv-o4Cq9j"ݏp)r-T_a1 re Jz⠾a²nNL3"3ݻлhѽ5"K{[DdYm4\P)+xe{!zTiAFURr (5 Nc`Q2LLϗ9Py+Vm5Vw7Oy{)D[]sMA?RÑ#dKfҫ=v[\ec@$ zI 9enF|;pfQ[K4)2 3=\0 ~gt,G5fE_lCcK6T-8##ְ8`6O!nh)%GeL,>7!k3ˉkP_XS!r`˩3B."_ŅO ÍGcNO?ͨK[wg|\YI!_x`U&X OsMgo.8Xmji89 LLN[RAIlKa-n/wNh=l=N#dO j:[D/T'"*䣑:qnF- ڄ/lpWUWu[^1V!9d {bAݏQѲ׾i t5qHfɭ,hhߏrG_ o!yeuŸQHշ=U(؁Y&W*u֭PnayԋTj~wԑrmb#5Ԥxi~(S㡗Oߍ^ nHd"h߻E{H /^ ZHO2 hol=<~֯߱|bE6Q((*RN~{h/NMmσȆ'?(VJBUD u?$Rf--_=|".q/R{FͷYfw6y:L/#$BNץyzݗ;+w3*=dX5ʽnl6ʎ%84+^TN`y$ Tzد\XW.2ɬq7F} \D7䝿u̹,+1X4IG:|;6d1Q!f*Nx{ӡ^xQo,i x=˅BhJPwL^>.P~1q_iM84;tں\7_ye0HykWKmx;7V|TsPvAЇ!@1`YPґ」<W?ׅE*? 4Wdqx盟Uյ!) Se,0mڎ^!9/ԥ[`cSK rBef:v(ƙhXez:|o賏]#%;c\o=Kn;۴[ΰNwߎ οx8ݷ["a+`,[k c)o@;Ӏ}4P`9j%3yM#cC -hi^J$RfPY] M o.~>acdQ-ZbNE 3Ϯs^1.eBf`K`` `ތUF]L+[ao5\2mzq&dkThրޥ0('ko$߂ ,FHaLd#x7Z[Mrz{`m̭ y)`_qȁbUM3\p`xbc42Kl,!1-Nk70=1&ߜi^?a1{ā؁ὐ>M,lE83wqB[fݘ3y mI n|+rhB>͔b>Sx P<&$9Ev5U>G(( D_2 LJj(hֆ4v\\T/XRȏ6j<Ժ/u+ŧtĈ75lE1Vp֭ sﰱUO_]v':gX(.|{d>Rmaw,N媷.,ޭH-~U-IO>$Z'xFmC>U]R̰]wN=Mibvz@cK^!t?ZP ky,#\?%i!@ j ^{;kU}ߣU =k`/S4n޸\<˄̥juf&[a m sn 荴dquJi9^;Ed\g@A\80`PۼEi?+Яa=Ə98v/7mvRM s`^GuFd $L`Os~?7X=:ES /6qۂk틭67]㹵# ?' xÎ b>??VUq/++ R si$6Oizw!he bǿ:k%'-[[US|7mhsY1o?[Ske7{wgwރNNsm3Z<,͵y]{/V=CX{ʶR;Ԁa}MA&N k%vDcgZsq+,i'nj3x;N$/@c--j+SїzSnGz~X &A#ZC0Sn2C_P(g! HW~ˆZVJb[HvQ&ӭPc&ҀjJi7B-3}ϑMJ{ߨG/g‹ÆʅA mT%v;\V)5>k'N> !rvs` 6m<~`'5B?IR cY͜# ~ҽC>f|_1f#ɽ7iW# @KRXdCm9\7Ip]t8vLYО;[mh'f #B{Lug Ăww(j2IW֜ #ǡOY)= 8`*>i׋U#>t|?-hu0 (` ev:G1'*#B0>dhz4uwʑ^}ώܙut_qt̒NRHay.CУ'nZxڝ쫛t8/$-s(_F$vm( &:x,2ZfV\5m:,۩Ǽh6!;K2y#‡zFB=zRǓ;9ؗɨP:{SrKXXLgT w? ܨff05;5QӚ/jR*0\ nhG'O<(("ӜkY6th^҉G7([>zgo ۄz~D11gsS]8 MFWC^(AJw^~JBxgw"HtCS ~{e%WjyҢT%sQO&bu*/*$jX 8[nMVb X.X|% %.fXRLttU0k!Ƕ¢تQ157v-uHxݷwl`3aThC~΋Oꭷ&z̍:~oe;Y0KdCM20`;B>gD;ٓT!;Ȁ+uؓ!Eb̋趱G w ]0)̩bi^m^~íl )dZٚa,_JMbֱ:CPqTWu1Y.n} m~Cn } ,UbrwIaXxbϽtXWP_ }k!T Յj$PQq#ێ:QVzUJh\ahyh~(^YSA5ɋgO0J#*=4z{nSh"\KƀٯdвL5,C8^@4޽}Y>]^l@ǿqֶO=}A&Cؓ-ԷKM[A*ߥX0;Cĝe8"dG=l?V=Gn3qOXH($M(5S_OB'iZEU& 9 rle-t<_VK|}XΩwCOeU!E~L y>3$^ls0FUWUk$ _^Gʹd8ʜ-etZp24 3g'K2'PD]ct:=@?4nS GM@!Wk9TPAH&36A@ ^N 1enU눱:q\ڻ{RNx?E!tPLi.vq'UJL…Iػ~~z7CU,wzLE$@!- /Mkl8 `X䙸 !@fEP-}pn-jfSgSB$У0a J2^ _^k+xL F$5!UzP!qlk|"3T*)?E炥1ޒs8>^.>$*c hQc4M)X8ۋ¨=ζP\u6 )w*^%xûw ;_!Ɩ{5Di f`3D]y<'lZy[fʎymX.e">z]4FBfp  NzY&U Y\1ږT0*h :ef r›+W'$Wٍ@"ʊK@z8u5E}Lwrc՜fi_TnrcR6S Y_b >w/Hx'KȝcD2soCi k5s}:s5lw#|fa %xmW,04vX|c&Ơï'l'rϯ֭(hy̾9?luOmJ ϧҪB_WF:tvp+F cźY^:?Wp9EҘ[W3vefٶLi`މ\[:-+`B>nyt,qY.YFlpWNurvJB0|pRo?(~rMSsTga?!MC C"#v;BR' @ ?DJxP^g] ˀc1o9EpD@#J }A\Sə4J CR\A4*۲[L,TR<~xL46[)XXԆՓڥ Ng]z9pciX< ?0k7;c t\Fʓ{+ɪP&HiQNj)wڬ3WN˟ú IBIV55XWEXX…I:%2f)l8<;67/2R9t?Fq`" o"4\"i|3i95&wif3_N&ֵRx<٨q`&'pK-r?<,4cDSӢ~_Ea};\>#>8򻧉цs-6)?!Mp>H͎Ni| Q?B$&;csxNė4xi =P1%yn)qFYbnN:ߠMTm: 0v.rx\.! R?]dmEAt 0Uџa. W>Q#7LkWt}ԚRcI˓;Z 7 hwl\zI[E|i<n%rR oSa?s*QNb% /nUC0M\(t࿝L]nKW:@K]ÇL7q2IJv2gӠΗH`De8hQv&٠`g*0saZq2L4 {y20GB0pE+8*ṳ,I؃{!$ h04fqqaLz[ \)Iq_=Ou'&_΋_Ƅ%aVsV2KrE|PFM4IZj$ypCܦI3{dL$,!Y`fKr8!)'6웗Jh;c=N.Z"=ϑ3FitE&ÖdFgX3"kߞc9F7v[8!viFŬ__@#+"HcsuOSfk6 !w=><'^r.L ?s] J*9 qfQmeEnKw&kq<:Xb?ophQIF0(\O9gHxC̔-Jϝ 2HFw3pK;!wJ8=;߈dS慅}d 0sޏWZqqDj(&n>m|ޗ{pq>w Rܾ'PYE8ﳧ۝H~KvsBH[OJU9ofE؟=QAXd R7Eq ntƬ@}á[5Auĥm~}iLϞصXaȭ׃bxܓ(Yč3!pp1؏?N\Ļhư/&C yTn!$։{ݽ^Ŕ B#Kz7{єZ]Q[X +Þַۚ7>{JdÒTBlh1|<:SB.W @[8 G/{֋٬X|<]y!cȾjKԎ)m?(@83M6nmU ?׉7_>~G[Dq ֌Q69̯">Ǯy_z<\_~X4z*> I Ӑ#3gr{jw/>zoq9?IC1Vb>4xk-DH8y"N~7 q>T]ű!_H Z߼oo\)xH@<e_|/]ϫi2}X/^_2Y[\2<]q JO%?L;e5:s~/~ _{}7}B_vMK&Zm>p̗UK]0XGߙ?6Y2f^AԝIu؂[i`#X3)s%q[ශhoP:{LbA%fTuon;iT Uwá \Vy圥i9`9=m>F2\[4O$@õ1^J\9M2 ,ybf-ƻ\) _c#ɷ@}6[JڟnAAWF>*Ub&{"K!=!?yMp H)൙Ѱ,}pݮIЙ- |YyvJ#ݚٖW281S'_X5 rjEa]g{"?IX$~ a^Ȗ{Epw |@2 K6g7Ϟ T8)%+G?RWY[szㅠ(%͢ "?4`L RZn25K7Ζ P.H#my»eىq}d- $3$i3.h)9h:PC#ɕ!K1|AwE?α@޵>NU˄6RᑹoG;hnGK9Ҹ7;O;G{"8v/UP m[B }_=6tY* 2W:SG}4X/r?aK0@ 4q;NFlYa4ŔF?Lms/Za&C }(L%95){۬xߢA˖SaiUI)/R*~ ]`5eZ1QfIS$Il|qnrgBl/9|ˤ}Cc:vM9iK2HGt|^4d* c`[6'ęd.z+sqO*9ZWERk.8&(]q;%- 3r9^hō(R>Jvm98:ҳ+/d[[x2-%p|85T {( oGgqtЦW*-Ssy˜Eo-s=Tpau ǠWpp:,՚Kҍ(VOPB\H}X~ڍ>BLzC3HX}Tѩ)qE]4-._1, oB%\@:_Jy}q]z&XR׎#w/kM i ,U[7Z^B`}~ _Ǯ5] s @G74 dRbkJ^,Ȯ'ŷ^tdXLv(n!IF,>][#z:Cd T%% Ny9I߀*6Z=^!O,4d5<T 0jb쳃z|c>C!\70wL>s C5ܖDZ6)֯||B55VHՁckွvgc34)/T17=lz,1OƢõt Mrjtcjyˣ^MZ~X}9^@f@e Яzi1lyKxJ%qߡWC\Xbz'`‰6Q)m^a<';Y 2iY13 K%q+oOڴy+VeGŖnf1l8TMB5xV6eO/ѳdʒyL,01A^œcw\s,O3^c1nn;n]JubՊLNuhϺ-N a۬ڱrI+x}]&Š+x7)zsލ|'#8zMjRaYXښ>A۵PROA@8NToL%`;T0~H,z]gYN4֢ ) zz#@|["ĸ^r; m&KV}޳A4Wp>S<0Baf@>MO͗}KC(uWKlq ]5OO3,}uZ B>:͞:.sLš%ZCgTV R_uǞ'U9M?틕`YY^E~ɥUP#wpgAl`AoKFR.qL唅K'M0h i7`f,Í2OB1Cq%Сa%j_t5 ☪a}K0+=ݍL جdԫTБ<@ [my fM8dhMu>TH;b"*k<#U.Om F28a; E,B&LU!3J6`4kX &sӂ ʀ.] W6qBړ7$KĜtN:d4VSHC_U4B͞B !PD\և+K@K3߶M.b.il*:zX!HtjRβ>]n@8`hSL[e(O2&k`ADV^ "΄3E IK*v&رL64.G͘OH$DǜC!p,58׳ ?kh0ycJ`I:!2ޠ^*8.Z_Wtu$$&Le`]V i B~ knoZ/iA]v w>du{u^nD~gnNU#$8Ι=uWB%= "8,ț%t.__i1D0<,N7+{ ;Pn)G]9 |> +-Ah3#N勩-UHUq% ,Դ;R%N_I~J$ {{pU#~̰En.S 8Pв{ÿ%y® @?nZvJu{ްwg_7-vP, Iq+v~|7ʱMXuQ=XmuJ~VvR`ٕ` +n l^뼋. q hDVEr;@({4. BTX(t B;k lRB؝9e^DAđ4S+!c*TY 8Y]~Eg08ى,kMGeM)2TY¾4"$-qFSE=}6"wLqCJfnm~c["|rS6*4|N;vy|NkQ|8\p/3^[, e{T").L" s 5,lg@y ?^!1Jb R] F0$Q/8h=Ă͊DQq;,|FUTFr]= 1u$ؑZlI k Cp*0nή4Ӡcԁj}|)3^5B-"2k.wLT32ȉ%# 2>_߽Ze+VYaӖm;v:pȱΜpʵ{" ƪut v>| PPt+RFJT)jPOQYP}8_#m|q4*XSBrǜi3fsϼcm<"|Q(ŊCD $K*{2er@s:ʑ'ߪ50$BbxjQ1qf6cpDPaBg0Ylo**) 44[;G@DBFAECx\bJ#WTw)]LYIHȥ'NA)TВ<+U\JU{I29+{Q ( @,O T4t Lf6vN.n^>~A!aQ1q IvH+(*)1X@$)Td9\_ %R\ FNo0MGWϚu6 MLU2@U ӲG'&gf  RRkI]TDSRJPƧtV?]\Z^A_][llRߦA‘)d #($E3, $+e;a'ieU7m?ƓlX֛nNͰ/PNo0p‘h,Hҙl._(4r JjaZz~FqfyQ0qut{kp4Lgk`h2[6r{D%$ed 8 DBid9\UTRVQUShhji 0 #(4$2J3,6 "D*+*Fo`hdlbjfnaiemckgZ!PD1Xa|,رﺤy`Q/B*2!ofovJIJ6J\*Ŏ&-FҳŦ*Y䌟 tΉEf?2j 6-^|' 1iIa"NO[B*2gi=Jy\ʄ~(zƂAu@x{ jR3VH^% "FhDTL aMOSIC(M'%b!J?"tR$y cO&q!6Nn „2.:%ʸJ"L(B*m[0 Nn&q!6%NK >⣾6x4 ec4hvAsq?!{{;|n󄬸$ h]%ߗ[ht:1@,@Y9mg^ld"Y;#OGPWrkŅOM5~kG<¦ԡ0<ʸj"oSR)TŻU.4@&YjU/#{ľjðw\ ZI Л „2.:uʸJ6"!6.ZMRJ)RS%0 Nn „2.:ʸJv"L(B*maBRic^ʸJ\ „2.:E7&b8!bTPdTb8!bTPdTb8!bTPdTb8!bTPdTpBLTɨ^X"fKy1Ni2-H0`P e""'>"@pO .$F|8PCv#cLf2չ۸5=*_SR{`X%wB8õ,JˎD+  r/+01A#654'3 Ag`ABagA3w"7<${Y @    /2901A%'%7&'ss'YdYE'sg(  /33301A!!#!5!3ddXSz /201e#>7m 7A!|(! IIPHRBp/201S5!Rܔ  r+201w4632#"&D13FF31DhF;;FE?? r?+01A#!Jg+  r r+2+201A#"&5463232654&#"+6ti_Ԯh>qq?>ss=ݲeQQ @  r r++22/301a#4667'3Ϣ6(W ;UG% -!q1e#@ r r+233+201a!5>54&#"'>32!#BmNxiUY:Yk\ond|HBp1L,^xtm\.@ $,r r+2+29/39901A#"&'532654&&##5326654&#"'6632L\wtZ[dȲcwWNp8TPab[o%+-3_u7FWoy 8%r>Z,l @ r r++29/333301A##!533!4>7#lۢ=1=SS+7YMF"(Y#!#@r r+2+29/333301A2#"&'5326654&#"'!!663yrCIbo]>0T8%&x~eu((,4Gn 7Gt0"1@))# r r+2+29/33301S4>32&&#"3>32#".2654&#"t%X-h"%_0^ `[ipϏkJ숤dR'Pzq٤] 2Q0hƍwRS~ABtF],@ r r++2301a!5!"Xg).<@+6# r/r+2+2901A2#"&&54667.546632654&&''">54&HoMO^Xw֐qVTIyGqžL_$\D>Ab r /9+201e#>74632#"&\8A ~(# D15DD51DHIOHH;;HD>>g)/22901e5)>_ܔs /3201S5!5!sVZgg)/32901S5g>Ks$_V<+@ ##) r r+2+23/01A54667>54&#"'66324632#"& KCN[(zcG:Rv!F;;FE??vGAO)@ILL%>r EE .5/32/323+222301A#"&'##"&546632326654$#"3267#"$546$323267&&#"+XY]n &kkÅY2M7C[0`zYXڃwAKj^tm S-g:_VlJOgϬwm%' lKiln6"%/TD| b @ rr+2+9/3901a!#3.']<8i 0DgRX)QE3%@ rr+2+29/39901S! #!!2654&##!2654&&#A|[`T} 0âIUX Po_C~y}nݙSv?}r  r+2+201A"3267#"$546$32&&9yHsbRPyՕ]oSDF5Sދ!Rm,) /Q rr+2+201A#!!24&##3 QsB./}m* @  r r+2+29/301a!!!!!!.|_' @  rr++29/301a#!!!!r.|]}8!@ ! r r+2+29/301A!#"$54$32&&#"3267!9sǢSz^AQhvc:;'&QR-)#2 @  rr+2+29/301a#!#3!3Oor rr++01s3ȪJ\j r/2+01C"&'5326653 2L J+8^8[ ,j]_Y@ rr+2+2901a##36673񜪪9x;nj'ABrr+2+01s3!Ȫj@  rr+22+2901a##333#4667#K)vHd@JAu+?@   r r+2+29901a###33.53?1}I8#@O} r r+2+201A#"&&54$323265#"VS-)tj۩hkݩllR?f @   r r++29/301A ####326654&F=ݠnğ^]I7V! "TJ=:jb..ck;E)@$)rr+2+22901A#.'#3>73>7Ey    |  J*UM;:LV,)k.YTP&'UXZ-n/\WO#1lv? @  rr+2+2901a##33uo;mo<|GGy@ rr++2901A3#3=/NE @ rr+23+2301a!5!5!!E )bkr/3+201A!!!!k;# rr++01S#"J3r+2/301W!!5!!3#:P%Dr+2901S3#P`ݕ%dH/301A!5!w{R!  /]9901A#.'5GO!q$UTD!.qk&PYQ^Z(#@%%  r rr+2++9/33301A2#'##"&&54$%754&#"'663265Iľy .d_dY zoVF3JHͨr^Z32#4&#"#U "iKY}z?/(Q":O)T6]h r r++201A#2#"&546UU);;)+99HH58766785h@  rr+2+201S"&'5326534632#"&+3L@(DT@9+);;)+9 Ld dLa8558766$ @r   r r++29+01A36673##TQlG}(s,f,zsV r r++01a#3V\'(@$%! r!rr r+22+++23301A2#4&#"#4&&#"#33>32366Usq3eMm; !d|F}& 6\2ƅYv;ZH9N(]__]A\@r r r+233+2+01A2#4&#"#33>Ȥ} #l\6H:O)r`\ r r+2+201A#".546632326654&&#"`FvnIz㝖}FsrFFt&ԒMMԇjj„hs\(%@rr "" rr+233+233++01A2#"&&'##33>"326654&pˊW^   \>r@=wfC\.N.'n)>22S1X dnŀq4\$%@rrr r+233+233++01A467##"46632373266754&#" .p͉/tA'f%LfgJ`W#&\@ r rr+233++01A2&&#"#33>!HBBuX2"`\5cUH=e<gt\*@' r  r+2+2901A#"&'532654&&'.54632&&#"tiÇs?Ca3xjiScK8DPs{9~ggQ,iH$!!6\O-EA'(Or['!(LB3B:'&Qs F@ r r+2+233901e267#"&&5#5773!!)Vg1WUBdA_t =QA{gf8H@ r r r++233+201A#'##"&&53326658 "lLY|z@H9N'T>\AH @  r r++29901a336673`4  8_HiD22CJ*@")r* r+2+22901e.'##33>733>73+ ̻Ҭ ʳ~)OI??JQ)H]' H @  rr+2+2901A33##! ˼1ZAH@ r r+2+2901S336673#"&'5326677$4#&ef/H?">[B<H8g^,2U{eQ /Z>PoH @ r r+23+2301a!5!5!!oY^nX{9%@  r%/2+29/39901A.54&>54663|_8nQQn8dwJi7jnph6iKGk2GW('VG4kF*VDh~ ~iDU(w//01A3#싋C%@ r/2+29/39901S5>54675&&54&&'53"CJh7kmoi6hK|_8oQQo8d)UD/i~ ~h0EV)FlHW((VFjGgQ)S@  /33/322/301A&&#"566323267#"&*Gb/932{I>uXI`-;~20zJ7wP}bd{˥ `[" }괷DD#%@  rr+2+9/3333301A2&&#"!!!!5>55#53466oF<=Sy~`(A&=^5e/"/ToCDx[1|]y#3J@#!(((  000    ?3/223333332233333301S467'766327'#"&''7&&7326654&&#")"\1xB@t2\!+'%Z0v@Bz/[")I}LN~JJ~MM}I?w1Z#''#Z0wA@y1Y"''$Y1w@M}IJ}LN~KK~p,@   r ?+29/332233301A3!!!!#!5!5!5!3Hy\;Ţ<`{{{{w /2/301A3#3#싋z6E@/!3IQq@-t@w,umiR:j64U;}>`)e~'oUz''D>)>:%%WtTh#%mP$'\>*>=('Twl5PE(_F6TJ&`6k  /33301A4632#"&%4632#"&64&'55'&44%&66&%4r2..211112..2111dD.B@ "9 r(/ r+22+2201E"$&546$32"&546632&&#"32672>54.#"ToptpaB982b/2s41hgd_댌_^ppqp&Ѕu tz`퍆e`퍆eDn'@$$ r+22/992301A2#'#"&&54667754&#"'663265h['rM@_3FmpU>7g.+4b|Z>5h]nw>W+9,ZCD\2/E8_!@:51cSOz $@    /329233301S%OTwwYuu,DEDEg$/33/01A#!5$RBpdD *>#@ 5!r + r+22+22901A!2##32654&##"$&546$32'2>54.#"?c@ϊoS_X\moptpd_댌_^}aqudRFMDppqpf`퍆e`퍆e/301A!5! u[r+2201A"&&546632'2654&#"`QOb_RR]bbe_eba[N\]OO]\NrmX\mm\Xmg*@   /23/3333301s5!!!#!5!3gbddX2Tsx w?32301A!57>54&#"'6632!sRX!NB=g5CQ_K=D>lgwlwwhaU@@o7D>~bTjiSwy $WKLEjRCA@+#Y-6R!  /]9901A#5>7ETU$o LH!QYP&kq.CH!@  r rr+2++23333/01A#'##"&'##332665C "^}QVy(|=H6M)6.GY54<]Az] /2/39/301A####"&&54663!]opN%}enƅ*SE aٴ^FKb /29901A#"&'532654&'738<KPkSYo62Q0ami,472 p *FLT @ x w?901A#4667'%4mB 6$?=*M^C  r+22/301A#"&5463232654&#"aN\ff]\fe^oQny}}yxzxMz @   /32901A'7'7ttYouuVhEb`DhhEb`DhB%6@" r  r+2/9+2/9/9333301a34667'%35!533#!5467nF4mB ng  =JJ6$?=*L^bDr?,n1^",-&@++# r  r+2/9+23301s34>7'%357>54&#"'6632!o&3mB RX"PA>f5B;U8jMJJ61.-*L^hPfR/BG/)Y2772.. r'( !!r+2/229/399+2/9/9333301a3"&'532654&##532654&#"'66325!533#!5467doJ=D>lgxlwwhaU@@n8D>^X>P`55#"&54632QKCN\'ycG:Rw!.F;;FE?? &$C)o r+01 &$vo r+01 &$Jo r+01 L&$Qo $r+01 A&$j4o (r+01  &$OT+@    rr+23+99//332301a!!#!!!!!!#ް+RMs0'}&&z&(Co r+01&(vo r+01&(Jo r+01A&(j!o !r+01&,Co r+01I&,vbo r+01o&,J|o r+01;A&,jo r+01:Q@   r r+2+29/33301A2#!#53#!!3 4&Ct/. *'}?L&1Q<o  r+01}&2Co 'r+01}&2vXo (r+01}&2Jo -r+01}L&2QRo 2r+01}A&2jo 6*r+01  $@    /3/3/3/901A'7^a_cac`aa`ab`c}%09@*--r)) ""  r+233333+23333301A#"&''7&54$3274&'326%&&#"VvJftn[Z-kKbsj]c87_8[h'446Ukݩl33LdR3.ObᶆLL(-M&(&8Co  r+01&8v&o  r+01&8JMo ! r+01A&8jo ) r+01y&<vxo r+01g@    rr++99//3301A###33 326654&##g<ߣ" \^I=o<@ .9r4 r r+2++201A#"&'532654&&'.54>54&#"#46632:UU:OJHj9^qa6%]j6tg%UGSb*8TS8sMLtʁkGfNBA(0=10bwSpG# &cT5NK.6XY8AYD@O8XR+g[YJC^!&DC /r+01^!&Dvt /r+01^ &DJ 5r+01^&DQm :r+01^&Dj >2r+01^&DO )V+44^}\1=E3@ A%,r!229 r/>>r+23+299//3+233301A2!3267#"&&'#"&&54667754&#"'66326632665"!6&&Ӆf;dQRe`y(-okdZoߧ~lQF4Jd'5m[ZPy 6p\|ޒi&%%"7kNIl;FmmSGq1#~'5Ze[fvl^ZHlcRr\&Fz^r!&HC &r+01r!&Hv &r+01r &HJ ,r+01r&Hj 5)r+01!&C r+01$!&v= r+01V &Jc r+01&j  r+01q[$4!@%$!  - r/+29/9301A7#"&&5466327&&''7&&'"32654.D:H_Ox⟒~vבKz_ YG+`1sGGr'P}J+fwY䥾xߘw6)yQh9TuhY>oW2A&QQ 'r+01r`!&RC 'r+01r`!&Rv 'r+01r` &RJ -r+01r`&RQ 2r+01r`&Rj *6r+01g* /22201S5!"&54632"&54632g.>>.,>>,.>>.,>>o9=A44A=99=@44@=9r`"-5@&& r' **  r+233333+2333301A#"&''7&&5327&&#"4&'3266`{O9Xma=CN8Upa324&#"3266spʉX^  ]ZgC'.M/EH73b1Q1$e&\j 3'r+01 &$Lo r+01^a&DL +r+01 V&$Mo r+01^&DM -r+01> &$Pp^>Z&DPa}&&vCo &r+01r!&Fv $r+01}&&Jio ,r+01r &FJ *r+01}Q&&NVo &r+01r&FN $r+01}&&Kfo r+01r &FK r+01Q&'K>o r+01rp&G4 1V+4:Qr,*@ r'  ?23?33+?9/33301E"323&&55!5!533##'#'26554&#"5W_ E^=.N0l$}}#1P/ &(Lo r+01ra&HL "r+01V&(Mo r+01r&HM $r+01Q&(No r+01r&HN &r+01>&(POr>\-5)@#&1 & r.r+2+29/3333301E3267#"&5466772!3267#"&&546"!.2-!19'ie:X,PY#j hVSowّD;x/1 l dZ:m]!@cU"|ߕg&%%"bS&(Ko r+01r &HK r+01}8&*Jo . r+01/ &JJn R{V+4}8V&*Mo & r+01/&JM P{V+4}8Q&*No ( r+01/&JN\ RV+4};8&*qB/ &6J r+01&+JVo r+01A&KJe !V+4'@  rr+2+29/32223301s#5353!533##!!5!ȪȪ5OGA"#@! "r r r+2+2+9/33301A!!3>32#4&#"##535UG "iLY}z?~(O":O*UZ]~L&,Q[o V+4p&Q7 r+01J&,Lo V+4-a&L r+01UV&,Mo V+4A&M r+01X>&,P1>|&LPQ&,Nko  V+4&,-<m&LM\i&-Jvo  r+01V &Jc  r+01;&.q;$&Nq+$H@ r r+2+2901A##33667a-H|HR/7&/vUo r+01$&Ov= r+01;&/qp;}&Oq&/4 V+4&O4$ V+4&/NTnr&ONX @  r r+2+901s'73%!kC!D>qjMx2 @  r r++901s'737nDFTEps"I]pA?&1v>o  r+01A!&Qv r+01;?&1q;A\&Qq?&1Kao  r+01A &QK r+01'Q?!@  rr/2++2901A"&'532665##33.532O P-8b?\ *h[)H[-HUVC\$!@rr rr+2+++23301A"&'532654&#"#33>32%1D;$>O|yA #iKY?~ Ldr\H:O)TdL}&2Lo #r+01r`a&RL #r+01}V&2Mo %r+01r`&RM %r+01}&2Ro '4r+01r`!&RR '4r+01}(-@%"" r  rr&r+23+2+29/3+2301A2!!!!!!#"$54$"3267&&4a-5\,b4Փ'큽{=kު8f()b ' SPRތvp*Z$3;-@!%%74r,,  r+2323+239/32301A2!3267#"&'#"&&546632>"326654&&%"!4&&rikSSl><ӌ}x:&q@CpoCD .8uZ{ޕg&%%"zwv{|tLk9ьcbbcQ&5vo r+01&!&Uv! r+01;&5q};&\&Uq &5Ko r+016 &UKC r+01i&6vo 7r+01gt!&Vv$ 2r+01i&6Jo =r+01gt &VJJ 7r+01i&6z/gt\&Vzi&6Ko 0r+01gt &VKF +r+01;S&7q@ ;F&WqS&7Ko r+01 &W47S!@  rr++9/3332301a!5!!5!!!!;5A39_ F%@r r+2+2333301S5!267#"&&5#5773!!0_~)Vg1WUBdA_>6 =QA{gfL&8Q&o  r+018&XQ  r+01&8Lmo  r+018a&XL  r+01V&8Mjo  r+018&XM  r+01&8Oo V+448&XOF V+44&8Ro ( r+01L!&XR( , r+01>)@)r$$  r+2/3233+201E3267#"&546677# 53326653-!09'jdA^+v5 l igA~hCmaaN&Mas>JH&XPE&:Jo 7r+01 &ZJ} 7r+01y&<Jo r+01 &\Jb $r+01yA&<jo r+01NE&=vo r+01Po!&]v r+01NEQ&=No r+01Po&]N- r+01NE&=Ko r+01Po &]K= r+01 r r++201A"#46632&&YcXm=a'* SqaM %#@ !!  r/2+29/333301A2&&#"!!#"&'53265#575466A>h')"R,]WMj(IA"XRO f2F  _yP8G*7&@ 0077%/33/3/??9/9301c&&54632#!!.'2654&#"5>732:|aa:2  C6CC64D@ C>>LO#_EesreC`(n*AJ#86/C@:9>>99A"WZ'BGC^(4AM4@%% r CMMIGG)5/<r+2222/333?+9/32301A2#'##"&&54$%754&#"'663265"32654&'2#"&546#5>7Iľy .d_dY zoVF3JHͨr^4D?94BD2@e;ab||o/xD>Z7Zd'v6r66o6r&aY -ql'#f77e$(lp-R @  /]223901A.'536673LZa%r6s26r6v'dZ.nk'%g88g%'kn.Ra /]301A!5aR /]3201A#"&'332667M`h2X>7X8QyD|8:;5R /]301S2#"&546);;)+9958766785R  /2201A"&54632'2654&#"/a|{b_a5CE32E>rfdrrbgs`A77@@77AR> /3201W3267#"&546672.!0:'ie:X,\FK/1 l dZ:m\@pR9@   /]33/2/201S>3232673#".#"R"8M/.TLG!05b p_,RLI#14<^B#%/%;@u%/%;?R$! @ /]33322301A#5>7##5>7$>MO"`D@>MO"`C@!QYQ'kp.QYQ'kp.q /2201A5>73 8F"&`he*/9  #@   /33301A#5>72#"&546!2#"&546?J%Q# &33&&33$66$(11+ko0*jo/.211112..211112. &$S]by'(S'+S',S&2US'<5S8&uFS&T@ /V+444 $%rr++201A!#u%}@ rr+299+901A!5 .'$ !fhN 75>54&&x@񱨵=BXaɛ^X˴hĝ_bdoÕWcx~e.h|ya;o@ rr++229/33301A##".533>5=𳦳<^Ɯ\n“UCVk!UfVO'@r  r+23233+201A"!5!.54$32!!5>54&&jGwZV+,U[vGl7}衎[D)˝CZ|;A&,jo r+01yA&<jo r+01rq&}S# 4r+01Yq&S -r+01Aq&SB r+01q&S r+01o&T#6*r+01r\ 3'@rr$,,0 r+2323+233+01e266554&#""32366733267#"&'#Os@z4   2%% $+L_ YvZ֊'XV&T .KQF8z Ld0P00)@))**r!! rr+2+239+9/39901A2#"&'#466"32654&&##532654&wwޝuE}܊WUIiYpn[Wȹf(#5d?(0lD  H@   rr++29901A#466733>7 l -/C,#!(HTG4QT7Cytk͑ň%-avLI_^PTsY\,@,,&r  r+2+29/39901A#"3267#"&54675&&546632&&#"3ΒjFMUpD>|ޏd^nkxtQ>C^,XBDT&4 )zy {a^C'%(TP]Qrq)@ & r/+9933301E#>54&&'.54>7#!5!M2!:#$klY` [~B.Rph;ZXA+`\$ 3*kt}Wt~>?YA\@r rr r+23+++01A2#4&#"#33>Y|xA #l\TJ\H:O)qI! @  r r+2+29/301A#"46322!"!Idڱdحx  ycc11$Hr r+2+01A3267#"&&5LOU+^j3ZNHgf ; $HJ!-@(  r r r++2+2901c'&&#"5>323267#"&&'.'# 9"OV$7*/e|U)i$# #'0F3 9 8[bFr &0|  H:$STLCLCHwH@  r r+2+9901Q33653#+' @OH,{v& Qpq<%@!!0 r+2333/9/39901S46675.54667##5!#"33#"#>54&&'.pQNEd6TSO]/C8XS~[Wni|7L-!7 #mn[hh HpObN'OyRmrS]in6AX:WA-_\%1+fr`\RH@ r r r+2++2301e267#"&5!##57!#.D/lq$ߖF6t CK@54&&'.546Q947}D;i}7M,!7"$llWm<\!zRAX;X=,_\& 2+Ev}rH @  r r+2+23301A#"&&546$3!!32654&&'#"]sᦗz PbDt(M7C~vOvhשZ=H@ r r+2+23301A!3267#"&&5!57Tl[-_ l;_]ٖHyd } :M@oHr r+2+201E"&&5332654&'3pS!YzQdrJ\)!@r" r r+223+223+01A4632#.54">54&&CM^`e|_vBZnd:fSYdߑY o ' yħj iő^NP&"@ r r+2/3+92301S233267#"&&'#&&#"566@R<?W0@0.:)WpJ αC3#<P7iM`@S) @yU`FPW !@rr rr++223++2/01A>54&'3#.53Y{a" cfi gÓ~ %u ܚTsH0#@##0r )) r+22333+29/01A#"&'##"&&546673326653326654'C*6Vr! p|Y6*@=|jEY+.Y?Ih8=AH^k`[[`k_F{O:Wy@]&j &r+01o&j! -!r+01r`q&RS !r+01oq&S r+01sq&S 1r+01A&(j!o !r+01A !@rr r+2++239/301E"&'53266554&#!#!5!!!2/RE.2^>z7 (g^zw ^&`vo r+01}#@ r  r+2+29/301A"!!3267#"$546$32&&ApR 'FfUPtґ] TEJ5@zϏK!Sl0)%.i6r,;A&,jo r+01\j-)&0@'r0r r+2+29/3+201W"&'532667667!32!!!%32654&&###D9 >I+"&)j LYv bVG,jy YûCgct2X#@rr+23+29/33301s3!332!!!%32654&&##Ȫk~.YunjyNct2A@r r+2+9/32301A!!2#4&#!#!5 ԩtv^{t&vo r+01z&38o "r+01  @ rr+23+201a!#!3!3 2<~ $w @ rr+2+29/301s!!32!'32654&&##[OaƥP(h{ᒋct2%` J@ r ?2333+201A3#!#367! !pKgA  >awB~?]`|r("@   rr+22+22901A333###VĽ44Q<<;O;.@ #+r r+2+29/39901A#"&'532654&##5326654&#"'>32wZ>Dː_VR:hn_l%+,C{Ts|G8t*E)]M@ r r+2+2901S333#4>7##ʟ. Ѽ0qlXJC5wpY0Mz&3o r+01 @   rr+2+2901a##33`y<:@ r rr++2+201a#!#"&'532667667!ت& ""Mh#E9 ?I+ "&) pTg eRD .j0+}2 mf3}&S7@ r  r+2+29901A#"&'53266733>7$>:c'(]4MnT&̺g܌^ /gU@')((7ir; @ r r+33+201e#!3!3猪~@ rr++29/33301a##"&5332673éuҀݪ{x^*4Dy{-*w @ rr+23+2201a!3!3!3wQWX @  r r+333+2201e#!3!3!3 _JK~ @ rr+2+29/301a!5!32!%32654&&##dgT kw璋ct2 @ r r+22+29/301s332!%32654&&##3ȪfSުkw瑌cs1NJ @ r r+2+9/301s3!2!%!2654&&#!ȪkZkw璋ct2?#@  rr+2+29/301A"'6632#"&'532>7!5!.eEFUrTTUdˊI- N5. ),k#JІtC'!@ $r r r r+2+++29/301A#"$'!#3!6$3232654&#"QicΠbaΣdݩk?P#.G@ r r+2+29/3901A#.54$!!##"33qPUyVc]Jc8xa^ZDvR"2,@.**# r r+223+29}/333301S4676$73>32#".26654&#"vZ}?z/U{G hZ`{ޖtC_K[fJK%#3 rȘ,V9{ޕ{ZPMj*fZ;H#@   r r+2+29/39901A#!!24&#!!264&#!!26x_gZ(vh!r5gswz^RH5xaVUFNMNHHr r++201A!#HHEH'oH@   ?2333?301A3#!#367!!ҝV^|@ CnIHE{6Ufr\HH @   r r+22+22901A###338 !7H,,3C\/@""!! r)r+2+29/39901A2#"&&'5326654&&##532654&#"'66{bl_CmAd̜Mp*FmTOFjyyZP;V\C\cvCmQ\T "4'WGAU)P_RQ%"&&dH@ r  r+2+29901A3#4667#MV̛HO?GA da`Hd &3P r+01 H @  r r+2+2901A3##3.'H,H H@ r r r++2+201a#!#"&'532>7!=[Y0 -K=0%m~K=4H@ r  r+22+2901A#467####34bgH,[..[2<H_H @   r r+2+29/301A!3#!#VcH4Hr`\REHr r+2+201A#!#EHGHs\Sr\F)H@ r r++2301A!#!5!qEH\pG&%@r  r rr+++223+22301A#.54667>54&,񩢣OP~~OD$  jj T l}' H[H @ r  r+33+201A#!3!33ڢwE{HEC,H@  r r++29/33301A32673##"&5@qlhW\|Hvgb@7;DmH @ r  r+23+2201A!3!3!mBHHEE H@ r   r+333+2201A3#!3!3!lMHCyHEE&H@  r r+2+29/301A!2#!!5!!2654&&=^Z"68HxFffRHeOYA\@ r r+2+29/301E"&'532667!5!&&#"'6632b];>Xp[* ;8.:Rꃊ$R}!#tɿ}0\&!@ #r r r r+2+++29/301A#"&&'!#3!>32326654&&#"0s֕w ݦ%x̊u?lk?@kk@&xH4redcc"H@ r  r+2+29/3901s#.5463!#!3!!"32.-B7 :K|y@k "jKY>{ LbN]||'O#:O*TeLH!&v8 r+01r\ @ r r+2+29/301E"&&546632&&#"!!3267yꃉS:19;mS *NpZ=:xx Lq{T$gt\VhL&j  r+01hM IH(@! r r" r+2+2+29/301A!2#!!#"&'532>7#32654& YYc=[W/ -K>0&.}H73' 8B!z)" IHMGA  r+901A#>728B!zII9~6Ah'7D   r+301S#.'7 "){!C8GLII @  r+222301A#'>7##'>7)" 9C")" 7B"MGIIMGII @   r+223301A#>7##>78B!}*" 9B!xJILGJI9~6A '7 @  //9/33301A%#53%/-M-/`_y'@  //99//33333301A%%#553%%7_-,Y''Y,-_&(W /301S46632#"&&8a==a88a==a8Wi00jVTk22j&'f '3?K,@@4F: r(." r  r+22/2?+22+2201A2#"&546"32654&%#2#"&546"32654&%2#"&546"32654&QLLQTRQIՒ+kQLLQTRQmRLLRSRQwbJxxxP r+01A3#ZoPfr+2201A3!3 0   Oz/901SOTww,DEMz/901S'VuhhEb`S& r?+01A#nJrL@  /2/233301A2#4&#"#3366kQTv`lW"zsTRR|v_47^# @ r ?+29/322301a#53!!!!!!I@|*|FF),@ %%"!! r+2?339/33322301A2&&#"!!!!!!5>5#535#535466pD;@Ssdb$?+C]1U-!'~|~\|M Md~|k .-@% r,--*.  r /+29/3/3333+201A ####32654&3#3267#"&&5#577 7~њ@U6ľ8BOV=Kk::_HՀIQS | =z]MC4u6+@300'* # rr+2+29/32233301A2&&#"!!!!3267#"&&'#53&&5465#53>fRF9PNdFAisO@>a-/22ff|).|yZ&%~|$/|6%@0#*#r  r+2/22+2/2201A##"&5463232654&#""&546632&&#"3267Փ+Ta]VS`aTʕ]e5f&!%W'pnlm5b('hJklmV{He{vvwep#-"@ +'r r+23/+2901e2673#"&&555667466324&#"66vLi dGcTT/b04`-;evdqR@@M7navmQE qVPۣ1lz,`ahYNC%1&@,&  r ?2/+2/99/32201s33.53##!5!"&&54632'2654&#"żK0XMXN[TS\[VU=42JJ67PpPppxstrrtsx+@ r+2/323393301A33#467###!#5!#̮zf4/b4#UXihhOufH"@ " r r+2+29/301E"&54>32!3267&&#"yy]^,\EH0x&je/#֊B/L{o)LL(OG.>8D.@93'?-  r  r+2/9+2/22901s34667'%32654&''"&54667&&546326654&#"o-2nB XV[S0A VY*I.BErqUAS`AMNDDMTJJ6$?=*L^L=>88H%-;T`9@45COU[I<.< r(' !!r+2/229/399+2/22901a3"&'532654&##532654&#"'66322654&''"&54667&&546326654&#"1oK=D>lgwlwwhaU@@o7D>^Y>Q_YU[S/A!VY*J.BEqqVASaAMNDDMUJ:y!#VLLEjRCA@+#X.6bSjhSw"L=>88HH"0IU=@ )*8DJP>1#1 r r+2/229/3333+2/22901a3"&'532654&#"'!!66322654&''"&54667&&546326654&#"*otC,88_one4M=!=$YU[S0A!VZ*J.BEqqVASaANODDMUJ7!&U[QY'i %L=>88H^ 0<-@+17%  r r+2/33+2/22901s3!5!2654&''"&5467&&546326654&#"o`6W~YUZS0A VZ\EBEqqVAS`AMMDELSJJs^L=>88He2&6@4''/ rr+2+29/33301A2#"&&54>32665.#"5>"32>7&&ya*,]ɂC$Lzq]->{]=5"[g$^Y+]gSfDzUr{uniNQZJ1Z,#cMmbcVw%}a!r/2+201S!#!Z[ J @ r /23+993301S55!!!Jy>Di4jg*/201S5!g%@ r+/9/9301E#5!3PYu- &2'@-*$ 0?3333/393301A#"&'#"&&5466326632&&#"326%4&#"326-JY[A>XXLKYV@;_b4nGS`\XDpTbRCn73pFRaVVjtjpP^XTishqe[oROp]`Sm\db^n r/2+201S"&'5326546632&&#"%JA"`SNd!E< ?M" oK  $B!  /]3201A#"&&'33267 S}K `l`n  eECgnPTju  /9901A#5>7u .;[ 'or.LUQ!;}q}  /3201A#5>7}$ /A% "nu,&os-T @  xw?39/333301A##5!533!5467n =!bD,n1^">B@ xw?329/333301A!6632#"&'532654&#"'b=$C.87_pme6L88HG:8>T #'+/37;?CGS_ox'@,, 9955!!?3333?333301S!#%5!#533!5353!5!!5!5!#3#35!#35!35!#35#3#3#"&5463232654&#"%32##32654&##32654&#"'532653T/0momImmmm0oowoooommsBEG@@GEBno.,->m^{B.$*/;J1%&4^0  %1}o0oo/mmmmmmoo;mmJoooo/yhI\ii\\hhCS1B 9EPZb" "+% * f$2re]T!-@ !%++//9/999301A 5467>54&#"663232654&#"TV*C;N'9yp.RD7?>5DLCQ<8SS84/TbC,".:/:G5=qP;H??HL==S &K`  r+01A !;G.@ #CC4#4#4- r</2+299/}/33333301A23##".546654&#"'663232654&'&$&5466".Dn~QBЍiV%&!3$#_4aQfq|ǓJt]Zh =Yr!P܌8p:eF9oc#0& vhP/ku>]9qyUP]RP~Imu<@rr r+2++901A>7>32&&#"#39#KJB=M4, 9%NZZ%!Q-1B"$A*d/|H4-@((r $$ r. r+2+233+22339/01A##"&'##"&54667!57!32655332654&&|#3Wq!"o!:%8!9#{ldd1Z?kx0HOUm`[[`UMJAGUÚwWy@Uj&0vo  r+01!&Pv /!r+01 &$S4^Z&DS/ V+44u5  |/3201A"&54632'2654&#"Ra|{b_a5CF24C=redttbgr`@79??97@}b+@ (r! r+2+299201A#"&&54$32>533265#"UR,U8:t}//vi۪fjݩllRrfOvJ}/X@r)@ ' r r+2+299201A#"&&532>53326654&&#"`{㝒mA;<>eL"%EstEEu&(JDQvH^fA_cdbx@ r r+2+993/201A>53# 5332665AE -O|ZuݫȆN L|SIgF&Kar")@r  r r++233+993/201A#'##"&&5332653>5 -NyX "jKY|@BHjF 9N'T@?z N|Ps@  /]29901A#'6654&#"56632s^I h MWM;78'yMUo 111$d[&(Co r+01M&Co r+01r!&HC &r+01d!&C= r+014+@ *r% r+2+93301E& '33667.'3363 #.'TvK C`l2 1  Cfx:T~H]}3cZJ Z}Ƚk:T,G?s(T]'J(@(#  r r+2+93301A#.'#&&'33>7&&'3367 Yu*UI@{d@ Ut9 #%Fm>LzM JHRf2i#GI%8edƇu+[$@   rr+2+9/322301a!5!53!!32!'32654&&##WC\h°USԏkw瑌bs2'!@ rr+233+29/301A!!!2#!#535!!2654&]A[›!3'ߋŜfRYfdN%*'@ rrr$ r+2+++29/33301E"$'!#3!>72&&#"!!3267xڕkgpQDGbqP=E|cTP=Q]3)#4BwϑK!\'&@r r ! r+2?+9/333+201E"&&'!#3!>32&&#"!!3267 ѧ1ދS707;lQ OnX<8oH3f!KqzT$\ #@  r r+23+9/93301A#####!'.\왛\Q PXX JZZAHH<=?jH #@  r r+23+9/93301A######!'.ͪrxūi ??HHt!?B$(I?a 0@  r ?333+29/9333301A#####!#3!!'.[픚TQQOT JTTTt;=A$ =;;H.@  r  ?333+29/9333301A#####!#3!#!'.B̩rr̪ڣci =>HH.tEM&(G>!&@!  r?33+29/333301A#.##"#>75!*Y\#CujisA=Zday~ [s6bm+A,lb;U`8~9 H &@  r ?33+29/333301A#.##"#>75!}p|H ;^SV^7!H}n$Hd MUJHR#"SHQSN hd#&?@""%##&  r?333?+9/33333333301A#.##"#667!#3!5!gy~ [s6gj'C-l_;WmL~7H#&:@""%##&  r ?333+9/33333333301A#.##"#667!#3!5!(p|G ;^ST`9-8%Hd L~UJGQ#"RGQ4U H6fd@O7Z=@$ /@@7/== +/RTWNNG r+22322/3/39/993993301A2&&#"326632&&#"#"&&546676654&##5326654&#"'667.'53>W 2 &1o/›B֕rv*KgTuCVgma@n{VBXĢʽ͏_|WSLo"ROz2z4(Xe mYDŒ`o>!5#1;!CtIPsB}C{Ts|G8t4M)WR!m71]={M[;@$ /BB7/?? +/SUXOH r+22222/3/39/993993301A2&&#"326632&&#"#"&&54667>54&&##532654&#"'667.'53>2 &0g.zp_CnCbϢil&I]Hu1DO[1/}Is6GcQFjyxQP;@yEFEy2n8'XfMnP>kcwAjP\S1"0/Cj;EmC&TFAS'P^RQ$#$%OJ$d81Z:ot}"@ r r+2+29/301A#"&&54$322667!"!&VS-)bn,mդr ݩllR}r`\@  r r+2+29/301A#"&&5322667!"!.`{㝒} lJlKj M&(WxxWZoPF@ r rr++9+201A"#3>7>32&&0@5X$ .Qr`#?06;|dCDpc2&PV^3Q >T@  r rr+2++901A2&&#"#33667>' %.%g ) !#B]T%L;H"S~ +Eiv/F&q o $1r+01>!&r b "/r+01} !?&@?()":3-r"rr r+2+2++?3901A#"&&54$3232654&#"%336673#"&'5326677MO昜K^×[[_r$  6'&fe1H=#>[C<ݩllR 6f^,2TeQ /Z>r\&R\}(8'@!$$$ r1.++ r+233+33301E"&'.54$766326632>54'#"&'E6G גJ G53G LӇ HC4/EXF/4C[Zt18|98..8˗}81-&',2'.''-r3'@%"r.1+11  r+333+23301A#"&'.54766324&&'#"&'663266e =46; k;53> i7rY :13: ~~ :20< |&1-,4 "3((5qn("#)Ԯ)!"&~@)kC@#Lf rU\r #:3riIFFCGGCC* r+23/333+222/233+2+201A54>3233#".#"56654.54632"&546632&&#"3267332654.#"'6632#"&' '3*7A5j޼}HyO=A/k".54632&&#"32673326654&#"'6632#"&'6B6jN;=&18'66&&'#667%&&''&&'&&'5#'>7wBK<\-ms\,ms6AJLUILO C#\( 63?.l,..k-\(Q3su5UJ!( &.A-k-\74[73@-l2' B#LOUI-mr5BJ;J<[DP '-\( NUJ3su5_''@#   r r+23+2992201A#4667##3333"&&'332673 λ.ėI bl_o T~C:22@+BhnOSjeE %'@! r r+33+2992201A#4667#333"&&'332673퀤̞V̹K ck_p Sy(`Z^Hj*^[(ERCgnPTjeE,w @r?3+9/333201A!!32!!#535#32654&&rFno}ݾZizbߌbs2R @?33/3/9/33301A!!!2#!#535!!2654&_'@^\Û 1FffRYfdNs7@   r r++29/33333333301A'###! 3267'76654&##shsuc4tF-N%hj32'"3267'76654&W^  ]Z]Tqc#RFr@=w0xh~21.N.,r >22S1FN X!d N6x.  @   rr++29/33301A!!!##53 hWwJH @   r r++29/33301A!!!##53J [H&@  rr++2/39/33301A"#!!6632#"&'532>54&&3.s M]'|:ROx[;?}G^a1u  \RB|t H!#@!r rr+2++29/33301A!6632#"&'532654&#"#U#N(yt}Ms2/vF#O#H zv# 'H(@ r  r+233+22901A3####33۹eRĽ44;~<<H(@ r  r+233/+22901A3####338s` !7HXy,,3O>;&k\C>\&k*!@   r r+23+2901A3###3yңu`:~<?H@  r  r+33+2901A##333Xط'z,HV#@   rr+2+299//901A#3##33ouuq`y#5<: H#@    r r+2+299//901A#%3##3I{`'iR,H@  rr+2+22901S5!##33`yp<: )@r  rr+233+29+01A!!3###535Vmط'|W,| t @   rr+2+22901A##!5!Yy`:<&H @   r r+2+22901A##!5!' H,@  r r+33+29/301A#!#3!33%~OoH@  r  r+33+29/301A#!#3!33ZcyH4Ej @ r r+2+239/301s3!!!#!ȪoOH @ r r+2+239/301s3!!!#!cH4̉A&)#@"(&)r$(r/3+2+29/33301A6632#"&'532>54.#"#!#'u7RNx^}<>~F]a1=ws0w C_\SCz|A H#%@" #r" r r+2+2+29/33301A6632#"&'532654&#"#!##L$lvIn.,kB{ MާH& uv# *EH}=N,@B::%r1.. rK/3333+23+29}/301A3267#"&'#"&&54$32&&#"3267.54>324&&#">GvF R2&G06_G2DWDt%-f2yq6yݖ6:R*7eQib-X@2K3-P4Fc53  5/iY SDh}=d߾sZ6cSd7-r\7E+@8?,/ r"")r+2/33+22339/301A2&&#"3267&&5466323267#"&'#"&&54>"6654&&K9Q$G(Dw$6 >OQ[XLtQB :D#I:+hKr;w/B!M7CT=\  xl B{{NL~9 *%ՙR8iLk.,pIh7}>&&k&r>\&FkS @ r r+3+2301A#!5!!33C3~{)H @  r r+2+2301A!3##!5Hyy<H@  rr++2901A#336673RT7 3SKP22Rry%@  r r+2+9/33333301a!5!533!!20f3#;H!@  rr++29/9933301A!!#!5!33667UV"3 6"HlHZAA\f @  r r+23+2901A##333"!4y w[>Uݠٟ .p ;; ehxFuʹb$+5j)C<#46WD}-Z'/%@##++  r(r+2+29/3333/01A2!3267#".'.5467333>"!4&&j tVSnvLWx=  87x F;{Z|ޔg%%%"EɃ1aJ%@:!27dcR8?,5)@!!((22  r-r+2+239/3333/01A2!32667#&&'#"&5467333>"!4y w[>QƆ .p ;; dhxFuͳg$&u$j)C<#46WD}-Z)1(@ --) ' *r+2?339/3333/01E.'.5467333>32!3267#"!4&&}eWx=  87|j tVI\E F;{ ޙ1aJ%@:!27h|ޔg%%"KcRr,z&3o r+01 &3  r+01+)@*''"+%r$r/3++29/3333301A6232#"&'532>54.#"#3667QSx[=?QYe6KuIv*/i3WXꓧQB||z= .8|8 (H!#@r r r+2++29/33301e#"&'5326654&&#"#33(zzIo/.nCVJ[|%])5=w$\V ;Hp!@  r rr+2+2+201e3##!#"&'532667667!–ž& ""Mh#E9 ?I+ "&)~ pTg eRD . H@r r r+2+2+201e3##!#"&'532>7!㸇=[X0 -K<0% ymK;@ rr /3++29/301A#"&'53265!#3!a}<=Jߋ)Oo _H@r r r+2++29/301A#"&'53265!#3!_hrIm,+j@w|aHm$H4!@   r r+33+29/301e3##!#3!3ęŸ~OoH!@r r+33+29/301s3!33##!cH4Ey"@  r?3+29/33301a##3#"&5332673îuҀݪ{x*4Dy{-*,H"@ r ?3+29/33301A##3#"&533267,\|qlhWH^;Dvgb@7,%@   r r+223+2901a##3333##4>7#K—ġ'_bY!T@~"[`XH#@ r  r+333+2901e##467####33쇪bgލy,[..[2<HEr, z&$3>o r+01^ &D3 -r+01 A&$j4o (r+01^&Dj >2r+01^}\z&(3)o r+01r &H3 $r+01x^%@ ""  r r+2+29/301A"5>32#"$55!.2667!Z@;hZT{3 wxw S7%"jꬫjODJy榤yj \sx^A&jto ;/ r+01j &sj 5)r+01A&jo 'r+01&j ' r+01O;A&jo D8+r+01C&j E9r+01I1%@ r r+2+9/3333301A#"&'5326654&&##5!5+w[^iYhǑR ˀo%+.3F_^y;ޘH#@ r r+2+9/333301A#"&'5326654&&##5!5u3熃xCDvlZisHykǓ}&! 5TktEtM&Lo r+01da&L r+01MA&jo +r+01d&jH (r+01}A&2jo 6*r+01r`&Rj *6r+01}or`\p}$&ojR 8,r+01r`&pj 5) r+01?$&jR 9-r+01A&j[ 5)r+01&Lo r+01a&\L r+01A&jDo 3'r+01&\j 3'r+01&RIo %2r+01!&\R %2r+01A&jbo ) r+01,&j )r+01  @  rr+2+201A!3## hz~FH @  r r+2+201A!3##FHyHA&jo /#r+01v&j /#r+01.q &lqJH"@ r ?32+29/33301A"&'5326655##53!!!!3%>5, [2fq 1%Tu=q$@r  r+232+2901A"&'5326655##333&>4+cuo;mo<1eq 1%|GGTu='q;H#@r   ?332+2901A"&'5326655##333U%>5,Z˼! 22eq 1%A1ZPTu=!@  rr+2+29/333301S!33!!##!3tmnq9uoNhIH|' H%@    rr+2+29/9933301S!33!!##!v! f˼buZ- A~. @  r r+2+9/301a &5466333%3#"kփSyxkJ%@|[r5G}m+#@r( r r+2+2+99//301A32653#"&'#"&&54>33#"3265xngx},1hAڙY@_||r|w[QL__cu>n;hZy=_p&3+@&r!''r-- r r+2+23+9/33+01A32653#"&&'#"323&&5"326754&^sl3b^fK'fgU}Y Δ6ca02[=9\7#.M1k# L{5#@&&%% r.r+2+299//39901A232653#".'4.##5326654&#"'>kqR7Y>woм\l:8lfąZyNU7]j[eJjC}&/cmOpG!E~Ts|H5r*E)O\3%@&&%%% r-r+2+299//39901A232653#".'.##532654&#"'66vbiYCc;/`Onm/_`^a4Adw{sON7Q\C\cv ?dHA^37cb0*S{QDV)P_RQ%"&&L( @ !r+2?39/39901A23##4.##5326654&#"'>.n=wnӌ^RU8]j~GhC E~Tq~I4r*E)OZ& @  r+2?39/39901A23##4&&##532654&#"'66ycl\Bk?Dj|tTJ=UZC]bs BlRy0BX,O^QT'"&&.@ .r% r r+2+2+29/01A32653#"&&5!#"&'532667667osprӶteI  Mg#D7 ?I*"')ʇx&OJ9f cVG+ ,H(@'r! r r+2+2+29/01A32653#".5!#"&'532>7!iukj0`]^d4=[X0 -K<0% u~8cb10beEmK;[%@rrr r+2++99//3+01A32653#"&&5!#3!prqoжtd'̇z}&O7OoH%@  r r rr++2++99//301A!332653#".55!#VKkvhm/_^]d4H486cb11bdwH}#@ #r r+2+29/301A!#"$54$32&&#"32665!_:G̣Ox\APit嫠VxY[QR0*$3y׍r\"@ "r r+2+29/301A!#"&&54$32&&#"32665!>„yP9AebzHBFŇE,'0iˆOc@ r r+2+9/3301A!32653#"&&5!5H2usquַug@cz~&O)H@ r r+2+9/3301A!32653#".5!5mukn1a^\e5H~4+& ""Mh#E9 ?I+ "&)1fq 1% pTg eRD .Tu= q|H(@!r r# ?32+2+201A"&'5326655#!#"&'532>7!3%>4,=[Y0 -K=0%1eq 1%m~K=9Tu= &$^Z&D &$XR r+01^&DX .r+01 &$cR oV+44^>&Dc 1V+44 &$dR oV+44-&Dd 5V+44 I&$eR  oV+44^&De 6V+44 b&$fR oV+44^&Df /V+44 &$'Jo +r+01^ &D'J 6r+01 &$gR oV+44^&Dg ,V+44 &$hR oV+44^&Dh ,V+44 X&$iR oV+44^&Di ,V+44 \&$jR oV+44^ &Dj ,V+44 V&$'Mo r+01^&D'M{ -r+01&(r\&H&(XR r+01r&HX %r+01L&(Qo r+01r&HQ{ r+01j&(cR (r+01rX&Hc <(r+01\&(dR uV+44I&Hd ,}V+44=I&(eR uV+44r$&He -}V+44b&(fR uV+44r&Hf &}V+44&('Jo %r+01r &H'J -r+01&,XR r+01w&Xr r+01&,~i&Lf}&2r`\&R}&2XR &r+01r`&RX &r+01}&2czR =)r+01rq&Rc =)r+01}&2dzR -^V+44``&Rd -}V+44}I&2exR .^V+44r`&Re .}V+44}b&2fwR '^V+44r`&Rf '}V+44}&2'Jo :r+01r` &R'J :r+01}b&TvXo 3r+01r!&Uv 1 r+01}b&TCo 2r+01r!&UC 0 r+01}b&TXR 1r+01r&UX / r+01}bL&TQRo =r+01r&UQ ; r+01}b&Tzr&U&8H8H&X&8XOR  r+018&XX  r+01x&Vv&o 'r+01!&Wv *r+01x&VCo &r+01!&WC )r+01x&VXYR %r+01&WX (r+01xL&VQ o 1r+01&WQ 4r+01x&VQ&Wy&<H&\dy&<XR r+01&\Xd #r+01yL&<Qqo r+01&\Q5 /r+01r&B / r+01p#@@  /]399901A#&&'#5>73'6673#^3m35k3_#NLKN#O)9 +i5`#V11V#&V\--\V&2Z@:i+#@@  /2/92201A5>73#&&''&&'53t"NM KM#`4j54l4j9g, :(&V\--\V&#V11V#+i:@[3p(-@%""&@  /3/3392992301A#&&'#5>72#'6654&#"566KN#^3m35k3_#NLv[dK6O 7#".#"#66323267 LN#\5k54o3\"OM/O6%FB?)- X `P&HC>), -\U&#T11T#&U\-@c7'15_|(24u @   /32/2|/3201A#"&'332677#5667 fcXOk !BG$]'<z}U59Q&KB2\@u @   /322|/3201A#"&'33267%#.'5 fcXPj 9([#HBz}U58R@\2BK&u #@  /233|/29901A#"&'332672#'6654&#"566 fcXPj [aJ5O ;>7,( +z}U58R%DG:; -^ $#Lg &@ &#@  /32222201A#"&'33267#".#"#66323267 fcXPj /O6%GB?),X `Q&HC>), y|T35R,?a7(15_x'230>n  /3/301W4&'7#"&'5326LDu5+2eq 1%Tu=S&7zQ F&Wz}>&2P2r>`\&RP}>&2'LoPN #r+01r>`a&R'LP #r+01j \@  rr+2+29/301A2#"&&55!&&#"566!326wٓjgWS:y^\|g%&$"aaSsX'2<v2V+44p/ @  /222/33/301A56673&&54632#y6?J&pi7/+:&5A"32654&FG&o:qUyK]]V'a;Y1+V>PcXr V\,<^JUgTM,E'5b>a`P\#D+@ $$ xw?229/33301A2#"&'532667##"&546"326654&&U\W'_#HB1p~9 jSLdTX:Y2*USgUt [X(An^\Qa+E'=`8&o@ !V+4444&o@ V+4444&m@ %V+4444&o@ V+4444o&@ (V+4444o&@ "V+4444o&@ ,V+4444o&@ &dV+4444{&@rr/2?++23301A"&'5326654&#"#33>324M O.6a=J %T|7f{ )dXūnʉAd9k۪%c`/? (#@ rr r+2++2339/01E"&&55332654&#"#33>32Э{TzîJ %~U|w{YװūnʉAd9k۪,_ %1%@ +&& /33/232/3301A"&'332673"&54632!"&546325>73jeXMmn&44&&66W%44%&55-)DH%NjpD06>p113..311113..311!>D)%JD_ %1+@ 0&@*,,  /33/322/323301A#"&'332672#"&546!2#"&546#.'5jeXMmy&66&&44&55&%44)-^$ICppD06>.311113..311113.)D>!DJ%k'@  '! /33/33301A!52#"&546!2#"&546#5>7l&66&&44&55&%440DH%^-)g.311113..311113.%JD!>D)k '@ " /33/33301A.'535!"&54632!"&54632$IC)-V&44&&66W%44%&55DJ%)D>!ˈ113..311113..311 @    /33232301A#'##'##'5L ..!.. J ffff &II&IL&IO&I'ILb&I'IObW+&@' r!r+2+29/9933?01A2#"&'532654&##5.#"#466ۆ| ځtj߰kNO[v>QxS}OxQddq#)+1}S5K)asK&@ r r+2+/93/301S233267#"&&'#&&#"566EU<|"$36%1J&Q`I0 I#761?.bNkJSY!~ DueX\  ' @ r+2?39/39901S! #!#!2654&##!2654&&#D~XgIѪ(RWVTh\,~|~vӔXv<&/z V+4?&1z0 %V+4> &$P>&(PkX>&,P V+4>&8PWQ (@ r  ?3333+233301a!57'5!Qc#%cc%X#8 r r+2+01E"&'5326653Gn)1m;9^8[-k]BʊYLQ&Co r+01Ww&vo r+01 &Jo r+01:oA&jo !r+01L&Qo r+01)&Lo r+01&V&Mo r+01W>Q&PW>Q&P]WQQ&No r+01W&-8&Jo  r+01WQ&XR r+01WQ&C'SWQ:oA&jo !r+01WQ:oA&jo !r+018WQUH r r++01a#3UHUH rr+2+01S"&'532653+3L@(DT@ Ld dL~NPr5 &6e :r+01A&Oz% V+4A\&QzV+4^>Z3>2@;;!544)((! r-r/2+2?+9/333333301A"&5466732672#'##"&&54$%754&#"'663265aheHm6\=U-3,"09@ľy .d_dY zoVF3JHͨr^>dZIt'8fe9/1l \&HPm1>|&LP>8H-$@-r#r(( r ?+23333++01A"&546673267#'##"&&5332665je9_9@Z/3,!1: "lLY|z@>dZ:oc' 1\Y//1l  9N'T>\Ar5\"3#@** r rr##r+23++2+2301A2373#"&'532655467##""32>554&&6q; hרxMMv7ubFW|M%D\UUk$#(.0[XW( 5f0aa1Yr5 &J Ar+01r5&M 8r+01r5&N :r+01+%@''$r r /22+2+232301E"&54673265#57546632&&#"!!F3=EQp?i(+"U,_Z={x/ DDSgP7IR {PegOp]!/@ " ) rr+2+2901A#"&&54667.5466$32654&&'У32366wvxkKIh]kKJGV&lWAQ.Pn#{r}QPPokPP7jM]".8998r;@  |{?32/33301A2#4&#"#3366kQTv`lW"zsTRR|v_47r"#@ |{?2/33333301A2#"&'##3366"32654&UmlYjGo_\uccb٪<*Bb-ATwv}ttC/?)@ &"| {?32901E#"&'532654&&'.54632&&#"?Km)+z>]S!ODEc6wAp1$-d4JP%RCBb5^b\ 70)'0D7SZO.'(#1E/e@  |{?3333301E267#"&5#57733#X7C Uwef+A=M Vt0'N}>=qB #@   yr/2+2901s466766736676653#q !![@ 8/^A<$Y>i^-*: "pe(U2*IZ6>Bo:R@ zr ?23+201s5!4&'&&#"566323Stli@)/cJHd=>R vpH8>F)1&@  ! z r+2?399?01W"&'732676654&#"5632#'#A&=!N(4R#N/XXDc!/( 0+uKE.tFUf  )U#&@,0,   yr/+2301a467667!5!j&@2T,6[ '{2&>ka@  zr ?+23/?01a4&'&&#"56676632!3iiK0?͗/Z*P0q>>R Nup P?(V5kW  yr ?+01s3 >   yr ?+2301s467667!5!"0%! V6,B|.6%Y*?"'a@  zr ?+223?01s6676632#4&'&&#" 8+]Bs>>R nmE-.~PO@'W6kxrx6@ %zr yr r+2++201E"&'&&'&&5332676654&'&&#"56632F46Y '%54%tKNv%;(&5*}H)7F|46S !cD6`EP͂@.470J{yJ94 cEL}fGZ) !K yr+2/301S3y8_"O zr/+201A4&'&&'&#"56676632".O~.R&HB)*\2f8.!!]:16 E7C'F_DFs8%zr r+2+201E"&'5326766766554&'&&#"56676632\G!es6Ag#"3.1-U;w> 8')_5f8.B.E  $L'(o>n;56 E7C'/is@V?5S>'6 @ yr ?+3301a!3!_L_t Z zr ?2+201s6676632%!4&'&&'&&#" 8*^Cu@:N_"#I.G/.~OK<$U3]AWcH5@%$ 4..zryr ?++2333?301s6654&'.'&&'336676632!5!4&'.#"cZ  M''ICn+1G""5E,@r#!5\5" /-  (E<!"7 8XMw''&;!!dO  yr/+01S4&&'&&'3  ]@y6  u>u" zr ?2+201s5!6654&'&&#"56632u 1 (T-&Y4:V -  7j4z0M 8 #Z52qg!3n^#<@ 11zr$ r+2+23301E"'&&'&&5466775>32'267>54&'&&#"eeIk!%K8\FR95RmLjNv%%+J>#b64M(VQ01%u8'`Fev4()#iEJqXAj,=820N5"X>28<t @  yr/+2901W5%6673>73< ;Ҧx^\ 66+G0SZ6( t.z3T=xY=/@ %zr/+29/3301A4&'&&#"'"&'&&5467667663210(yKK)&*//L/[3+0@5M!7wAN62Q&'r=5312+nNπnQJ@ ())9zr r+2+29/301E"&&''532676676654&'&&'&&#"'&&'&&'&&54676632V=sb%)ZXJr%'/ G9E'Mw$08/(!P/7a)&@ !OAHaS8-K&(-)!Z43{ 2*,J-U3YCDc*!+CIx&!~=&2Il5=;&%X8OςN;Vo @  yr/+2901A36676653:JU,+"sL{8sh^4'A[O @  yr/233+29901s5!36673SiGb7P]   %F)UP{(JE!(J%0W%sd @  yr+233///01a445467>7!5!3# Դ` 3VSb-AxTY[fZ,^ zr/+201a4&'&&#"56632lk9 'tx.Y=x>>R vqO@(V5kR^ (@ yr/2+93301s36676673"#!267673#m=Cz(//  <=8uML56 B56b@N 9/9]/҆GDP1sWX*!(h/@  $$zr/2+23/01W"&'532655>32#4&'&#".&+HJ$H$e:\|[*:K nl.N%[6,$c^b=  N>#U2gwq7\&:"R^&# )yr+01L^ &$ )yr+01Ra&'!w# 4yr+01P^ &'!w$ 4yr+01q"B &ZqXB &XqB &!R&!yQ1&!Q, &!YQa&!|QW &!Q &!R&!QK &!@"O&!WRFs&!^R6&!<QcH&!qQu&!VRn^&!`QY=&!=nQ&!YO &! &!GP,^&!OQR^ &!w(h&!OW& yr+01!C!v.Q J^Q,aL8MxfNLj%O!RP K]! %@  /]3/2233301A#.'5##.'5?D`"OM>>D_#PL>!.pk'QYQ.pk'QYQaF:{ /301A"&54632*::*+::678558767z[>P @/8 /301A4632.@D7,2&;=Nk69G(&2H?WD18 /301A56654.5463216iN;=&3+7B7W?H2&(GW4 /3|01A#"&5463!6632# (/1()2+-1*)",2414)//12#*Z? /23/301A2#4&#"##532>X7V;xC/.euUNsq6P6K1#/#y$.$ L  |/32/301W"&54632"&54632!##!#$$#!##!#$$'&&((&&'(&&((%'( M ".: @ /55#))|/3323333301E"&546323"54632"&54632!"&54632"&54632"##""$$E#""$$"#$!#$$o!##!####!##!###(&&((&&(N&((&&(''''(&&(''&((&&((&&((&&( @  |/3333301E5!"&54632"&54632g"#$!"%$#"#$!"%$RR''''(&&((&''(&&( @ |/333301C5#5!#"&54632"&54632f*"##"#$$#"##"#$$hRR^''&((&&((&&((&&( F |/301G"54632D#!$$$N&((&&("  |/33301W"&54632!"&54632"##""%%!#$ ###'&''(&%('''&(%&(" #@  |/333201C"&54632"&54632!"&54632 "##"#$$n"##""%%!#$ ### ''&((&&(''&((&&((&''(&&(F= |/301G5!mRRHo /01C5#5!#+koSS}G /201C"54632D#"#$$}M''(&&'L /201S"&54632!##!#%%'&''(&&'( # |/2/2/01G"&54632"&54632"&54632!#$ ###u"##"#$$w"##"#$$'&''(&&'('&((&&)('&((&'(L /201S"54632D#!#%%M''(&%(6-r /01C30]6<L /201S"54632D#!#%%M''(&&'F /201C"&54632""#!$$$'&''(&&'S|/3301C5#5!#6wm8)}x:m94|:#ys7r r+2+201A#"&&54632324&#"76t{w:_ӯh㑩>ss=ݲeeP/43I @  r r++22/301a4667'37(W ;UG% -!q1JO @ r r+233+201s5>54&#"'>32!OmNwjTY:Zj\pnd|HBp1L,^xtmW-@  $+ ?3?39/39901A#"&'5326654&&##5326654&#"'6632觉wtZ[dNcwWvSTPao%+-3H\_u7FWoyE8r>Z0p @   ??9/9333301a!533#4667#<ۡ@PS+It\%(d#~!!@ ?3?39/333301A2#"&'5326654&#"'!!66-xsCIbo]?/U8$%y~eu((,4Gn 7Hs/"1@ ))# ?3?39/3301S4>32&&#"3>32#".2654&'&s%X.g"%^0_ `[iqώkI쇤dR'Ozq٤] 2Q0hƍwRSABtF ?33?01s!5!Xz:0>@ ()18 ?2?3901E"&&54667.546632'26654&&''>54&#"^qUUJxGq|nMO]Xv֔fJL`$\CFqJwE|uJ}]{el%(f[oQPqYc'+ld{`BvOIoX$ &]vNJuBLkKjpqjLiKf#"1@ ))#  ?3?39/3301A#"&'53267##"&&546632"26654.#%Y+n#%d0_ a\hsЍkIfQ'PzG٥\ 0Q1hƌxRXQ}BBsG):wLJ{2Jst%;uJ7>88):x:J94;:#:yp=^r r+2+201E"&546632'2654&#"Sjpڟzy<󡚝Q~nj*f^   r/+22301a#4667'3f?)R6g[#8q:U^@ r/333+201a!5>54&&#"'6632!]k:9qTWSXg߃{`Hd!LgcD@[1BEsWMNd]{F;_-@  $+r /3+29/39901A#"&'532654&&##5326654&#"'6632B]頀PJk`~ccqjXLVق\\g-'&9Yq66ydow:32#".2654&'&v[/\-)^7z *oKenϓ~{=쏞W]*QwmFi >X.kɍz`PHCrF!Hr+23/01S!5!B jg)/=@,7$ r0r+2+2901A2#"&&54667.5466326654&&'">54&HoMO^Xw֐qVTIyGqFjeKIy\Dqq?>ss=ZkjԲeQQH^D^Em_^F K_GA^H`HITJBHK!LLF ^M)twLc{2sut%uui7>c8)sx:c94r:#wyRB /201S5!RP  /01S473#&Pb[adcbXehm眘pbPdd={  /01A#654'3{dYdceb[bionh=d{fHf  /3333301A5#53533#%dddHfF /2201S5!5!HccddHfBhHfi%@r r+233|/+223}/01s!2#4&&#!3!26653#!̐]E]՚hG]ȣCq̇|iJBAKhxq=3@:"63& ))0)r+22/322/3/3/901A33#467###"&'532654&'.54632&&#"̭ze:n%)p=QUTS2eCw7n 0A$[#}'ps-"mu,3>~H&PmH&jt_/)Ge=n+Q`<*H!V3S  5 m  _ 5 _  $ ? T n  [ S 3j2m <nEV>;Te {!k-Sr@Rdv%8J\n 1d /h 4  - ? R !!!!X!!!!"""k"}"""""""###%#7#I#[#m####$$$&$8$J$\$h$$$%%%(%;%M%`%l%}%%%&&2&D&W&h&{&&&&&&&&&''<'N'`'k'w'''''((('(3(?(Q(c(o(() ))0)B)U)h)*1*C*U*a*m********++++(+:+F+t+++++,,!,5,I,\,o,,,,---&-8-J-\-n---..k./ //-/?/J/U////0040^000101<1E1R1_1l1x11111112222d2l2t2222222353=3E3334-4@4S4d4u4445 5f556G667 71797778*828h88929b99:6:z:::; ;;,;?;;;;;;<<^<<<<===Q=Y=a===>/>b>t>>>>>>>?? ?L?T?\????@1@j@@A6ApAxAB&B=BuB}BC C9CJCpCCCDDD'D/DLDTDDDEE(EUEEEF8FFFG(G:GzGGGGGH9HAHSHdHHHHHHIII,I>IPIaIrIzIIIIIJ*J]JfJJJJKKKKKKLLALpLMMMN?NNNO0OPWPQjQQQRR&RIRRRS$S0SOʒ[ؓWєGPY?v1>FNV^fnv~ĥ֥ͥߥ"CLjW_gB!_< w&Q b0+4fo\R\>hYgSRge\,t]ggAgsgt,v+ }r!}<&\-29}9}cihcyN3P8Rr^rr~rX4hrqEg 30'P9eCgDyez6dDOgRdmug2%8R=zLCMB%,:!t5 }rrrr<<<<:9}9}9}9}9}9}yr^r^r^r^r^r^^r~r~r~r~rqrrrrrgrr^r^r^ }r }r }r }rr:rr~rr~rr~rr~rr~r}X}X}X}X<<<<X1<b &\44-----i9}r9}r9}rf}pEE}Ecigcigcigcigh h h c3yyNPNPNPr^^9}rcigERERRRlRbRRRvR +)%rN9}<2hC9}Hhy`iao?O<yrYr pYrq4HTpr5rrr[ 1sr1sr)}ci<<&\{+)y rO29} }h`iAK} ?b.r^vs'~rC" rr)p0'.&%An"~rsrg "7xc3c3c3yRRRF[[A[EAy9 ^fP9PgOgM0r^F&4"p&?Of>%H^e% Jgd%u ggggl>:4VTTT[ 2hr^u?}r.Mr~rR4@'f_cyW @ao <}r }r}3r'~.wR4@'|rm++11,3.t.<8OCK["4z &5yv6}r }rh)yyY')8H-8H-<q =D<r^r^^r~rx~jx~jOCI9}r<}r<}r ?A4s%3.tV'0'~r(}$p/LfOL4O I }r1)nY r^r^r^r-r^r^r^r^r^r^r^r^r~rr~rr~rr~rr\~Ir~rr~rr~r<w<9}r9}r9}r9}`9}r9}r9}r?}r?}r?}r?}r?}r.M.M.M.M.Myyyrppiuuug0h 9}r9}r~jup))#__kkbff"-r<XWG8LW :)&WWWWG8WWW:W:G8W[rAr^~r1rrrrGpW0rrQrr0r.rzCq/R>1 , >"F6cdrun<YnuO,R(RLRPqqq/R>1 , "F6crunYnuO,R(%a:7[@DWZ""FH(S)L2%>):4#sv3jOW0~szf)L2%>):4#p$*PUC;.{yv8!gbg\H\\_\K\\`\T\B\L\F)L2%>):4#RPP==HHHHHnqt3 4 s332@ (GOOGH ` ~01ac7Y #(  OP\_?M   " & 0 3 : < D p z  !!!! !"!&!.!^""""""""+"H"`"e%ʧS6<>ADK 12bd7Y#& PQ]`>M   & 0 2 9 < D p t | !!!! !"!&!.![""""""""+"H"`"d%ʧS*8>@CF~ ZHyu`{xYM geb^Qyj h(;,us N$!WhX_HL|dHI#$t   5\78x9:yhidfkegmb@J~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSQPONMLKJIHGF( , C#Ce -, C#C -,CCe -,O+ @QX!KRXED!!Y#!@%E%EadcRXED!!YY-,CC -,KS#KQZX E`D!!Y-,KTX E`D!!Y-,KS#KQZX8!!Y-,KTX8!!Y-,CTXF+!!!!Y-,CTXG+!!!Y-,CTXH+!!!!Y-,CTXI+!!!Y-,# Pd%TX@%TXCYO+Y#b+#!#XeY-, !T`C-, !T`C-, GC bcW#bcWZX `fYH-,%%%S5#x%%` c %#bPX!`# %#bRX#!a!#! YY` c#!-,B#Q@SZX TXC`BY$QX @TXC`B$TX C`BKKRXC`BY@TXC`BY@cTXC`BY@cTXC`BY&QX@cTX@C`BY@cTXC`BY(QX@cTXC`BYYYYYYYCTX@ @@ @  CTX@   CRX@ @CRX@ @CRX@ @@ YYY@U@cUZX  YYYBBBBB-,EN+#O+ @QX!KQX%EN+`Y#KQX%E dc@SXN+`!Y!YYD-, P X#e#YpECKCQZX@O+Y#a&`+XCY#XeY#:-,%Ic#F`O+#%%I%cV `b`+% FF` ca:-,%%>> #eB #B%%?? #eB#BCTXE#E ic#b @PXgfYa c@#a#BB!!Y-, EN+D-,KQ@O+P[X EN+ D @&acaN+D!#!EN+ #DDY-,KQ@O+P[XE @ac`#!EYN+D-,#E E#a d@Q% S#@QZZ@O+TZX d#d#SX@@a ca cYYcN+`D-,-,-, C#Ce -, C#C -,%cf% b`#b-,%c `f% b`#b-,%cg% b`#b-,%cf `% b`#b-,#JN+-,#JN+-,#J#Ed%d%adCRX! dYN+#PXeY-,#J#Ed%d%adCRX! dYN+#PXeY-, %JN+;-, %JN+;-,%%g+;-,%%h+;-,%F%F`%.%%& PX!jlY+%F%F`ab #:# #:-,%G%G`%Gca%%Ic#%Jc Xb!Y&F`FF` ca-,&%%&n+ #:# #:-,# TX!%N+P `Y `` QX!! QX! fa@#a%P%%PZX %aSX!Y!YTX fae#!!!YYYN+-,%%JSX#Y%F fa &&I&&p+#ae ` fa ae-,%F PX!N+E#!Yae%;-,& b c#a ]`+% 9X]&cV`+#!  F N+#a#! IN+Y;-,] %cV`+%%&m+]%`+%%%%o+]&cV`+ RXP+%%%%%q+8R%RZX%%I%%I` @RX!RX TX%%%%I8%%%%I8YYYYY!!!!!-,] %cV`+%%%% % % %%n+8%%&m+%%&m+P+%%%q+%%%8 %%%q+`%%%e8%%` @SX!@a#@a#PX@`#@`#YY%%&8%%8 RX%%I%%I` @RX!RX%%%% % %I8%%%% % %%q+8%%%%%q+8%%8YYY!!!!!!!!-,%%%% PX!ehY+d%%%%I c% cQ%T[X!!#! c% ca S+c%%%&JPXeY& F#F& F#F#H#H #H#H #H#H##8 #8Y-,# c#c`d@cPX8 g=<;r:9O7@6^43O10+)(O(\'-&%@%\$1#"!g @\2[87[2[87[>Z1U1UYY 2 U2U YYU 2 U2U_UY YYYo 2U2UYY@@T+KRK P[%S@QZUZ[XYBKSXBYCQXYBs++++ss+s+++++++s++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Hqmkz:xHzqmzkz:q}x~Hyz 8    6 " $  > ^ * (, BT > < " 42 f           Copyright 2020 The Open Sans Project Authors (https://github.com/googlefonts/opensans)Open SansRegular3.000;GOOG;OpenSans-RegularOpen Sans RegularVersion 3.000OpenSans-RegularOpen Sans is a trademark of Google and may be registered in certain jurisdictions.Monotype Imaging Inc.Monotype Design TeamDesigned by Monotype design team.http://www.google.com/get/noto/http://www.monotype.com/studioThis Font Software is licensed under the SIL Open Font License, Version 1.1. This license is available with a FAQ at: https://scripts.sil.org/OFLhttp://scripts.sil.org/OFLOpenSansRomanWeightWidthNormalItalicRoman2t  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`a  bcdefghjikmlnoqprsutvwxzy{}|~    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}NULLCRuni00A0uni00AD overscoreuni00B2uni00B3uni00B5uni00B9AmacronamacronAbreveabreveAogonekaogonek Ccircumflex ccircumflexCdotcdotDcarondcaronDcroatEmacronemacronEbreveebreve Edotaccent edotaccentEogonekeogonekEcaronecaron Gcircumflex gcircumflexGdotgdotuni0122uni0123 Hcircumflex hcircumflexHbarhbarItildeitildeImacronimacronIbreveibreveIogonekiogonekIJij Jcircumflex jcircumflexuni0136uni0137 kgreenlandicLacutelacuteuni013Buni013CLcaronlcaronLdotldotNacutenacuteuni0145uni0146Ncaronncaron napostropheEngengOmacronomacronObreveobreve Ohungarumlaut ohungarumlautRacuteracuteuni0156uni0157RcaronrcaronSacutesacute Scircumflex scircumflexuni021Auni021BTcarontcaronTbartbarUtildeutildeUmacronumacronUbreveubreveUringuring Uhungarumlaut uhungarumlautUogonekuogonek Wcircumflex wcircumflex Ycircumflex ycircumflexZacutezacute Zdotaccent zdotaccentlongs Aringacute aringacuteAEacuteaeacute Oslashacute oslashacuteuni0218uni0219tonos dieresistonos Alphatonos anoteleia EpsilontonosEtatonos Iotatonos Omicrontonos Upsilontonos OmegatonosiotadieresistonosAlphaBetaGammauni0394EpsilonZetaEtaThetaIotaKappaLambdaMuNuXiOmicronPiRhoSigmaTauUpsilonPhiChiPsiuni03A9 IotadieresisUpsilondieresis alphatonos epsilontonosetatonos iotatonosupsilondieresistonosalphabetagammadeltaepsilonzetaetathetaiotakappalambdauni03BCnuxiomicronrhouni03C2sigmatauupsilonphichipsiomega iotadieresisupsilondieresis omicrontonos upsilontonos omegatonosuni0401uni0402uni0403uni0404uni0405uni0406uni0407uni0408uni0409uni040Auni040Buni040Cuni040Euni040Funi0410uni0411uni0412uni0413uni0414uni0415uni0416uni0417uni0418uni0419uni041Auni041Buni041Cuni041Duni041Euni041Funi0420uni0421uni0422uni0423uni0424uni0425uni0426uni0427uni0428uni0429uni042Auni042Buni042Cuni042Duni042Euni042Funi0430uni0431uni0432uni0433uni0434uni0435uni0436uni0437uni0438uni0439uni043Auni043Buni043Cuni043Duni043Euni043Funi0440uni0441uni0442uni0443uni0444uni0445uni0446uni0447uni0448uni0449uni044Auni044Buni044Cuni044Duni044Euni044Funi0451uni0452uni0453uni0454uni0455uni0456uni0457uni0458uni0459uni045Auni045Buni045Cuni045Euni045Funi0490uni0491WgravewgraveWacutewacute Wdieresis wdieresisYgraveygraveuni2015 underscoredbl quotereversedminutesecond exclamdbluni207F afii08941pesetaEurouni2105uni2113uni2116uni2126 estimated oneeighth threeeighths fiveeighths seveneighthsuni2206 cyrillicbrevecaroncommaaccentuni0326commaaccentrotateuni2074uni2075uni2077uni2078uni2000uni2001uni2002uni2003uni2004uni2005uni2006uni2007uni2008uni2009uni200Auni200BuniFEFFuniFFFCuniFFFDuni01F0uni02BCuni03D1uni03D2uni03D6uni1E3Euni1E3Funi1E00uni1E01uni02F3OhornohornUhornuhornhookuni0400uni040Duni0450uni045Duni0460uni0461uni0462uni0463uni0464uni0465uni0466uni0467uni0468uni0469uni046Auni046Buni046Cuni046Duni046Euni046Funi0470uni0471uni0472uni0473uni0474uni0475uni0476uni0477uni0478uni0479uni047Auni047Buni047Cuni047Duni047Euni047Funi0480uni0481uni0482uni0488uni0489uni048Auni048Buni048Cuni048Duni048Euni048Funi0492uni0493uni0494uni0495uni0496uni0497uni0498uni0499uni049Auni049Buni049Cuni049Duni049Euni049Funi04A0uni04A1uni04A2uni04A3uni04A4uni04A5uni04A6uni04A7uni04A8uni04A9uni04AAuni04ABuni04ACuni04ADuni04AEuni04AFuni04B0uni04B1uni04B2uni04B3uni04B4uni04B5uni04B6uni04B7uni04B8uni04B9uni04BAuni04BBuni04BCuni04BDuni04BEuni04BFuni04C0uni04C1uni04C2uni04C3uni04C4uni04C5uni04C6uni04C7uni04C8uni04C9uni04CAuni04CBuni04CCuni04CDuni04CEuni04CFuni04D0uni04D1uni04D2uni04D3uni04D4uni04D5uni04D6uni04D7uni04D8uni04D9uni04DAuni04DBuni04DCuni04DDuni04DEuni04DFuni04E0uni04E1uni04E2uni04E3uni04E4uni04E5uni04E6uni04E7uni04E8uni04E9uni04EAuni04EBuni04ECuni04EDuni04EEuni04EFuni04F0uni04F1uni04F2uni04F3uni04F4uni04F5uni04F6uni04F7uni04F8uni04F9uni04FAuni04FBuni04FCuni04FDuni04FEuni04FFuni0500uni0501uni0502uni0503uni0504uni0505uni0506uni0507uni0508uni0509uni050Auni050Buni050Cuni050Duni050Euni050Funi0510uni0511uni0512uni0513uni1EA0uni1EA1uni1EA2uni1EA3uni1EA4uni1EA5uni1EA6uni1EA7uni1EA8uni1EA9uni1EAAuni1EABuni1EACuni1EADuni1EAEuni1EAFuni1EB0uni1EB1uni1EB2uni1EB3uni1EB4uni1EB5uni1EB6uni1EB7uni1EB8uni1EB9uni1EBAuni1EBBuni1EBCuni1EBDuni1EBEuni1EBFuni1EC0uni1EC1uni1EC2uni1EC3uni1EC4uni1EC5uni1EC6uni1EC7uni1EC8uni1EC9uni1ECAuni1ECBuni1ECCuni1ECDuni1ECEuni1ECFuni1ED0uni1ED1uni1ED2uni1ED3uni1ED4uni1ED5uni1ED6uni1ED7uni1ED8uni1ED9uni1EDAuni1EDBuni1EDCuni1EDDuni1EDEuni1EDFuni1EE0uni1EE1uni1EE2uni1EE3uni1EE4uni1EE5uni1EE6uni1EE7uni1EE8uni1EE9uni1EEAuni1EEBuni1EECuni1EEDuni1EEEuni1EEFuni1EF0uni1EF1uni1EF4uni1EF5uni1EF6uni1EF7uni1EF8uni1EF9uni20ABcircumflexacutecombcircumflexgravecombcircumflexhookcombcircumflextildecombbreveacutecombbrevegravecomb brevehookcombbrevetildecombcyrillichookleftcyrillicbighookUCuni0162uni0163uni01EAuni01EBuni01ECuni01EDuni0259 hookabovecombuni1F4Duni1FDEuni2070uni2076uni2079uni03B9030803040300uni03B9030803040301uni03B9030803060300uni03B9030803060301uni03C5030803040300uni03C5030803040301uni03C5030803060300uni03C5030803060301Eng.alt1Eng.alt2Eng.alt3uni030103060308uni030003060308uni030103040308uni030003040308cyrillic_otmarkf_ff_f_if_f_luni1E9EuniA7B3uniA7B4uni013B.loclMAHuni0145.loclMAHAogonek.loclNAVEogonek.loclNAVIogonek.loclNAVUogonek.loclNAVI.saltJ.salt Igrave.salt Iacute.saltIcircumflex.saltIdieresis.salt Itilde.salt Imacron.salt Ibreve.salt Iogonek.saltIogonek_loclNAV.saltIdotaccent.saltIJ.saltJcircumflex.salt uni1EC8.salt uni1ECA.saltIotatonos.salt Iota.saltIotadieresis.salt uni0406.salt uni0407.salt uni0408.salt uni04C0.saltuni0237uniA7B5uniAB53 uni0123.altuni013C.loclMAHuni0146.loclMAHaogonek.loclNAVeogonek.loclNAViogonek.loclNAVuogonek.loclNAVg.saltgcircumflex.salt gbreve.salt gdot.salt florin.ss03uni0431.loclSRB uni04CF.saltuni2095uni2096uni2097uni2098uni2099uni209Auni209Buni209Cuni05D0uni05D1uni05D2uni05D3uni05D4uni05D5uni05D6uni05D7uni05D8uni05D9uni05DAuni05DBuni05DCuni05DDuni05DEuni05DFuni05E0uni05E1uni05E2uni05E3uni05E4uni05E5uni05E6uni05E7uni05E8uni05E9uni05EAuniFB2AuniFB2BuniFB2CuniFB2DuniFB2EuniFB2FuniFB30uniFB31uniFB32uniFB33uniFB34uniFB35uniFB36uniFB38uniFB39uniFB3AuniFB3BuniFB3CuniFB3EuniFB40uniFB41uniFB43uniFB44uniFB46uniFB47uniFB48uniFB49uniFB4AuniFB4B gravecomb acutecombuni0302 tildecombuni0304uni0306uni0307uni0308uni030Auni030Buni030Cuni030Funi0312 dotbelowcombuni0327uni0328uni0485uni0486uni0483uni0484uni05B0uni05B1uni05B2uni05B3uni05B4uni05B5uni05B6uni05B7uni05B8uni05B9uni05BAuni05BBuni05BCuni05BDuni05C1uni05C2uni05C7 zero.dnomone.dnomtwo.dnom three.dnom four.dnom five.dnomsix.dnom seven.dnom eight.dnom nine.dnomzero.lfone.lftwo.lfthree.lffour.lffive.lfsix.lfseven.lfeight.lfnine.lf zero.numrone.numrtwo.numr three.numr four.numr five.numrsix.numr seven.numr eight.numr nine.numrzero.osfone.osftwo.osf three.osffour.osffive.osfsix.osf seven.osf eight.osfnine.osf zero.slash zero.tosfone.tosftwo.tosf three.tosf four.tosf five.tosfsix.tosf seven.tosf eight.tosf nine.tosfuni2080uni2081uni2082uni2083uni2084uni2085uni2086uni2087uni2088uni2089uni05BEuni207Duni208Duni207Euni208Euni207Auni207Cuni208Auni208Cuni2215uni20AAuni2120afii10103dotlessafii10105dotless commaaccent2iogonekdotlessuni1ECBdotless \7$=D]ll||ISTUUWXZeguw55JJMMORTWYv}~1335amsttuuvvz%oprs4\5 "%STttvv #" 8@HRmarkRmkmkZDFLTTcyrlTgrekThebrTlatnT8<@B4,V .8B48Bj!!!!!!r!x!~!5ttvv ST55ttvv%5 "%STttvv !$!*!0!6!%D""J&j'PV\bh%"Vn$x.2t"z&z&4(D0$18/j&F&L18".2%%0l&X11 1h).&d-x060Z$r%1..*'$--  1/    " ( . 4 :" @ F1' L142 L"*N R"" X ^ d(P j1'"01 p v+' |) 1"# *'3 0x#L 1/" (, '<2 0B0f # 1 1.1 1+1 1 ,*!(t1(t1/"1%1!!!$$/j$/j/v/j! /j,/j$,#1 #1 !1 !1 (20Z!&L!$!*!0.!0...!6.+.!<.!B,*!H(/(//(/'/!N4P!N4P(84P'4P!T$#X'$ 1$ 1/1!Z1,10,#/#/"/!`/,0f!f),0f!l1!r..1..!x!~11!&R!'$!&R!'$!&R!'$!&R!'$!!--!!!!!1!/!1!/!1!/1011/"1/(/!"!"!""""'"" &j"&",'"24P"84P">4P11"D"J"P"V(842$x"""\.>*N"b&"h""z"n""t"z&"""z&"""z&"""$#'0"1""$"'""001'"0/j01"/j"1$/j$ 1"4J""".2"# """"".2## #%#3#(%#.3%#'#"#(%#.30l#40x#:#@&X#F#L0l&X0x#L#R1 #X/#^1 #d/#j1 #p/#v1 #|/#1 #/1#11#.#(,#0Z#0f$0Z#%###%###%#######*~#.#,$,$,$ ,%$'$11$$$$*$0$6$<$B$H$N$T$Z011$$`$f& &$r$l11$$r%&j'$18/j$x.2$~,&4(D0$1,$18/j$&:&@&F&L%$0l&X060Z$)@)F&d-x)@)F$/j$$0Z$$$.D$'$0$0$$$(n$$$$$3T.>.D$$%'%%%4>0.>*N%% %&%,-f%2%8%>01%D%J(b%P%V%\1'%b%h)0+%n*0%t%z)L)R%%'0%0%1%0%%%1%,4%&)%%%%%%%%%%,4(t3~%,&:%11%%&2& &*T&11&,F1,p18,&",&(3~&.4&4(D&j'18/j&:&@&F&L*&R0l&X&^,)@)F&d-x&j&p&v-&|&&&&&&-0&4 &,&&&*~1.&&&&))&&1/&,R&,d&,&,-f*B''' '*x*~01+'+'*'$*'*0B0f'0'6'<2'B'H'N-'T'Z'T'Z'`'f'l-<'r'x'~2''+n''/''')'2'31''4P142'''''''*B'0f'''((((.((,(.((,( .(&(,(20Z,0f(84206(>(D(J(P1(V1(\18,(b(h1(n12(t1(z,(/(,(((((((((((((((0Z((((()) 4 ))))")().)4):)@)F)L)R18,0,-Z2)X)j)^2)d)j)p)v)|)))))))))))))))))-B*N-N))))))*** ,j****$***0*6-0*<*B13~*H*N*T*Z*`3~++*x*f*l*r*x*~*******,****0l***060Z**060Z**-Z*****++++++ +-+&3+-+>+,+2+8+>+D+J+P+V,F+\,R+b+h+n+t+z++1++++++++++++++++1+.+1+.+,, ,,1,/,",4,(0,.,4,:0,@,F,L,R,X,p,^,d,j,p,v,|,,,,,,,,,/j,118,0,,,,,,,,2,,,0f,,,0f,,,0f--- ----N-$-*-0-6-<-B-H-N-T-Z-`-f-l-r-x-~2-0---------------------...... .&.,.2.82.>.D.J.P.V.\1.1..b1.h..n1.t..n1.t..z1...1.......1...1...1...1......1/1/..1./.1./.1./.1.//1/ //1///"//(/./44P1/:18/|0//@/j/F1/L/j/R1/L/j/R1/X/j/^1/d/j/p1/v/|/////0///0///0///0////1/1//1 ///0 /0/0 /0/0 0000 0000$0*00060<0B0f0H0Z0N0f0T0Z0`0f0l0r0x0~1800000000000000000000000000000000000111111 111&1,12181>11>11D1111J11P11V111\11\1b11h1n1t111z1111111111114>4P4>42111111111111111111112111122 2222"2:2(2.242:2@2F2L3222R32X2^2d32j2p2v2|2223222322222223r222322222333 33333$3*303r363<3B3H3N3T3Z33`3f3l3r3x3~33333333333333333333333444444 4&4,4>4P4>424>484>4D;>/fp! !88YHPHHHHHHHHHpHHH3HHHHiSH`JJZ0Ib :?3:vPkH#Hos$UH3H KILt$&$HHHj$HHFn$HHH HHHHrH^\w K KKAi~~9!99HB!gjts9a> K! PK K uuqEaqUEqPE>>U>P7>7;v-a/;b;;;t;t H}HUjHx!x;H;x E!E 3;;31KttaUttt!> = R!RPR JJ9zs!j!;;surrffRRj5E )=AxqqqqsxHgn H HfqH^!^!$!$zHz+qHiHqH.2HHsjqsqqqAmEyyssm`yi3N!!&&l11bbLHLNHNHHH JHJH{BHyHy`HHH H\H\HQHQ8Et!HHZHZHtt! }H}!A= !9iHdq E!!!H!' H :HHH#H#UUOO{00 H ! VHVH_ ``ppsHsH HU>H>.H.HqHHHHvHv H >KHB>3HHy-H-ooHwHwhHHH]y 8H8 S{H{ HoHoHy9 A9zzsHsqyE ?HA?]A]UAUUH a A A$jj$yayAyy!AooeAeqHqyyq+H+qOOHr7V3H3HiHi  HHHWHqQHQq99I9b99 9X9\9 9U99qEqKEqEqIEqbEaqE ajjIjb j j er!rKrrHrXtX!KH==H==K=331FjH >jae>0H?Y\sr{qe5bVVVKVVUV>VPhhVVHHVA9H9>EHa>>tHX>_HsH_ __aVVWJWDJJJJJ_J  JJ%JJ JJ]JdJCJJ%JwJwwJ%J\JfJfg]J]]%JqJqCZ_J_`MJJ%7J7 JhJhNJJUJJ@%]JJ+ >H  />,gdd z*DFLT2cyrl>grek6hebr:latnN'\dLllt|V` $,4<D aaltccmpccmpccmpccmpccmpdnomfracliga lnum&locl,locl2locl8locl>loclDloclJloclPloclVlocl\numrbonumhordnnpnumtsaltss01ss02zss03ss04subssupstnumzero0XMKD SRB dAPPHCAT IPPHMAH MOL HNAV vROM  ^b,PNLJ@>dB "    !$%& #$%     &' ;} $ ( H  HI#$l|l|4hropsVrZH@.(  jnrvz~ L         dfhw{tu78x9:yiN0123456789DEFGHIJKLM0OPQRSTUVWXOPQRSTUVWXDEFGHIJKLMegjYZ[\]^_`abk0v"0>LZh$*06<BHNTZ`flrx~`Jl|l|HIops#$&'()*+,-./AFN~DM:C/O:B(.4dnx mn_s~$2DR$D2RbdfhjlnprJ&/rtvxz|~LM55tt 34OX 09DM 09   Q  KNOPQSVW,-Yfv24defghjikrDEFGHIJKLM0O1P2Q3R4S5T6U7V8W9X0D1E2F3G4H5I6J7K8L9M{'1;PZt(2<Q[u)3=R\7*4>S]8+5?T^x,6@U_9-7AV`:.8BWay/9CXbw&0:NOY  QQ  09DMOX&J$,-2DJKLMNOPRSVW 34Y_fsv~245mn:;<=>?@ABCyOy/ILOILIOIy/yO }|{z~!!!!!!!!! 34opqLrL $(,28DHLRX,wdthwghtital"dinc/fonts/OpenSans-Regular.woff000060400000234630147177152050012473 0ustar00wOFF9PFFTM9|"GDEFc[GPOS\!L -GSUB,1OS/2U`MNcmap tYDcvt <=?,fpgm Zgasp#glyf"[R}head564hhea!$ hmtxh VBlocaҌmaxp lname4post'nQqprep,{xc`d```fpjvB9+<2f,-i%p{Ϲ%W2;ͷg>7a~vSi2Q J=#Ttr'kJ Xu';u@)eN'ʈ! b)3?A!XwL_}1UIe-O fY~b[ E̻1%FF 3~BXokaQNDe{(ع?{>7WalnVSB#@Dozahr1>ΗdC˘T'!`#zq>B>/e?ps `ȇ.u!)?[cCGCX;>ʶc({ٌ$Ȟrufސ 1(HQoB;njF,6n9HۢHTy/H5k?sSX;~l?pZɳa<-Do sֵC[ڪ%\cwIg9]N}9X$1K7RfЅwz8DED1M qA[ߦ^b-sX W)]L胱Ҧo: ~("F)K̵bSZ W;NWy8wKf#Ju$l7kG5R^Ej2ξ&`ܹğjgw=.5GnwI.^iUlu;LnŜ-yNj?@G T7/{;28Á^w%& nSUZ5qn_HT& ^D&kwA2y`MO>,0+j3^cO^: \"m"ȳȃ`܀\8Yy!%n L(ü )_y[>d}iָDdZº49_lj,:[\[3{g? C0TN/1v6\]]FQ!E?1Yr7%)$Y#keZߺQ)wWx{x'f$^PcT*SijRUZTSժܾ(_OL_o/403Œ4xkN1fi֣YAWpf058/0\rqvE7CⒶač;mGSdvw{<&moTRjΨ}*WAh{ۿ9hm'898[ӵOmsr:;'vRC1z'Tz.T*  CKC}>evh^4VjVUdZyVeeZV`YV5 t\߭s&1Sx-c 0tq#>8=| NM i*e<1^%5_NgYz#{I)XNf3E'x *N#b:|Yneʯ\%j6 BVRE[xZޢyw١;N#_E(/ D!b(CMxW[oR{U6v)U#!ڵ.ҮRSr/&ӋQumL oyY~ȏP3]]%9g9sn3nO:oxr7/?O?ƣ M~{ww;lkscF6kE+Z5--VGhRK5P #wk'j9;U*xmzӑN1X`VOlmF-nd3\SvNљ = /7hJ9؜xd[XA \AUX'-Ӟo#4C1nxٞҭ7a?OL?Q|ȹ*ybЍD8x'ŬԑpyON^/pf^lgA/K۲[jh™ 5&(ii,x]$dXc CB ѫYl8 i$S`;6`yl)4τbX aÞ _cU}Ӱ-' XY5t&NNy J`М0<ۧ+}`௿Xgi7qάAЦk"M<{miGb8{m5-B #teiOiBM4WsPt @;TcK'rჴ$b`a{: $N-=H!\>MȰ:CS\6:Y4̆zX]+SEQ$U.yS7MTaJũD&< iaZIRXZ}=Z:$I(u*R .*].j?~a.rT;^:.5' Ў")TT: {_ = D:IOznj7-$m áZ 3FuV.˒_ZQp Nm7ykWd2b02U1_7_}d)D!hl'R)IY7t>e iGA;W6`Ql~Gߠaf ҶN}Вn ݪxp*@.rN}(miuЇ(cB|PzMf;T>qPH]D$ Zd!d\iujz g5Zg™%>- yyލ FfV){Ow -a*z6ƪ:PTZ:î0ĺEp/mfU2b92=|^٨ae\QI;}JS?*:XG3Ō#23p)Bϛ0׊U1+Us"ފi%E:?7c*{y~'`B{S]ۼhYU}yZӹS^#@RN,KC(AT{p~sVi mU+.r4uH_c,CcD[us={@;b+&'YMKΛ2.6o]TgHNCG7lՃFV[vjt˛^ i>Ԅ=O\ń}$q%PO Rԝ| iM؏|@gpW; h,P॓.TW3K=94~k!\_I&yxmKSA{&Cx$b@ 82&QG_QZI|7J**6PT3f?%? Xeu{snmάu%ks)kc-M!CX=Ox?e7ӄ:U)B5<ϴ:j&LZx cccA |: .CǁB6g%'w0Ɓ&NԜP;J |$$p\R!wT)BExӈE5ߛO !H>Ҁvti[(Jvggg2yy y𳴳g]g/cӟ>wT@+ds ϟ_;e8z0(j G I抁bkhD|Z#H0J3 cf1+%Z D^b(.-*J[K2T (k(X(bX!hyNyA9\\.+וq(pRKҸ}|||^7 ~g $<-Kdvh$zQbDCF!HR4KZ&m>r>DfyVC6ߒEP(6J?C QeTP*t _TBFErr2Yr5ҩ|jUFUSMT/5H.PW4@4K5Gڗ*AUKUWYVMW-V%UzKw?VӪ{W7wk59ZqVQ5jwj"FCp1bM?LS 2'o esffC1FY`8bY,,)e`Y kJl:UlfOku:xNQ;8#tp+'zm}~B !npEEŞK|7[x%K|oS,xu}Y9qy7A# F] W`W:xD \aHV zQhzoWWWWCW ꆉkkz\K\ˊ".>4ٍƎFy81ӄj4uuuu1T/&8%Nć-ͣ͛---S-?~4ъhmj f~S-su{IB$SwMMͥvB[[i%GJt;{?Iu*: E=7nneBAQ Y󥫨Kݕ˽pw9ZE=ʽ{{( bN~%_٦T(<=p>X|p©ZUnR7[tG7h5V ]S4 ]H4JQ3iBYͲfKjZЊZ֮i[ڌCCÍXGc/[gm="?Uk׵^Zw}okyvkh7D Ǣ~EIÓԓ##8aL-[TiRx@>; L,$> |5Rl0!yŜ2g-KbY$dLX,kZiViZ>kܺhݴX6md6ds|mζbKٲv=Nsvh =eHAspBGCuǴcёt'ʉqҝ|)u&u;A z;X?(Fr\(et]C!|:Zsr;/xxQztzgƳ L,lg>,yzx~Ux߽@M]MacXG1|<h?_N3B@ ` E`?Gn^EHc 6( Fqx۸j<_φ7)s'c@eau /tx?#nDD}#ld!;9%-Dkh"2rQL)c1ycX,6-R7L OLM"'Is;MLO.MOAHST5xU"A P@Mo `Jѵ'ΟvrxBQUeh670υT=v \*↛&uQfULM|`iCLMfn2Bo"DUnvS F(nŧGBtEbB>jtĄ`еk';(/,)*IELۺkǦm ~5:tCσCG9xhyM "%OU8Ɉ(̦ wj>r-  $'Ag- BɆJσA笛43kqF6n_y)3nVQYS׎o;͵i ũKn0mA^?fn.otLA_/ [6W]$8Nqp7Yo7JAQOmXZk 2/q^>om>`I!<%G"&Ϋ1C Lf7 v,Iwy {@g\NKY !'| F"2n2VJ1Pe`P!zF-:$5`7[ :Lkj:a^(rm:a'ae(Ra3&PP;(Z_Ճ(J \ s )vi-bBrRd`*9ðPfQEcry%> 9hl`L'=CIdH:c]4nWV9'5EB ],P T!Ȼ'HG  y?wƦe>@{XCʹ ͪb4*$2ĒtD>ޔw?/-kfZnYԴz0iNŸp'~{r:Xpծ/O]%X|G2X 1P'|\>"'(h_e@Jo//. >CB}6E r[i^f]Á3W,[bKRχP'\^uwNXȄfv>qK&oㆊ!>WADJӱFw;D F$"s@@l&gmA!ձޫjVk4 vW\4j>9Jt^c񅱓_]E{?`!+g@UBEB*aHrnD/:J @Y%(㿭 Ѿ R9# 0WF r8-DBqVPDYwܝ5z}ɰyCgrumVW,v [<2nV;ƛ"w/8SSybC&װMk( vK-55S6z:oJ7Exȩݥِ*tlEtHHi }*ͿvuŒ4nَa[&n-v|R&4-'>i)zߠMi(bMaIq^! Za=|NXSsr, ;ڞVey\dLTi9rUJFbmQ>a璿8'@7:ʝ<Xd`ըV uWJ8\ ;qkWh? 绝 =&ph05v nҊP߅SKЄ` i \͍~E ²4@.)A.(XB& {9Q)xqa>t`W4sSCⲳQM)*2&7G$]:Plr{_3w({9KdDU=,?_P6IvøF'Uz߂iIo]FbM>K@~܏nq&Ĝ%?_Y?/;=mXx|`$u;!]Ɲ%D=s$M9Jz8xe."'۪2lOL :ԡ3jX%TbAi}lՆ@Zi^#¸k 24^$rq5[J}6bJ{++ʔRQV\2[4Ӿɓmsӱm\uM, y;[VA*uޕM_;V4ϸV̡;Y9]yek@}}FdH{HCJh )G J""5?CNYf?` \Ѓ`9(/+hlR SS"GQMEv3mn,  z$`;Tڟ@m̤@:.x;ee$Ifw0b z~{mP2 M>ӻbWƯ!9{)~%(z!*|1~ _ pٹA1E12H~ Z 3{N>LSm"8}|s0FlF=z+%`*¸L8C8Wp8qY|O`^DJUʑq%rMRYJUgx@XrKPXN3p`"8T o^Ԗ4p5WLK}2"xxJ Up5 cY=ki-KI^!orbp"< f%@5ӊiYJy0kr{V<`Ʋ9xS##$j\ıT~}sA +/Ŕ},hݰ)ƥ[T H&/¸K]rʦc$]@F/RH*@]S?:tx!צOt>E/p'{N7D>7CzH$2i,! ՀQe90W~a0־PuN%WMV4vnm"n^j_(A0"F| i]aѬƨA^yݕ7kwA7'@H“*\\8O"6g]r*{0X:tw@w3ݛotߺSP/@yV(MdKQ67ZⲫEDu4 Dǎ?I*޲0fsgn+d{wVy8TUҬ smkgFPc(o/s<2\=bbAD̔'x\UFŐF"(Ƃ~\uK3$& y(x)Ϋ%M"H xFx/y+//?'5 Oxψ 7jO4Qg1\~#*F >\z_vi0ZkJπ 8.:z42Ol3z$r>W@Mڟ[( 2Y->uC#Cʔzw#S?irQ@tjVQP>P:"c`ȞpشQҲQԚ1c qS[ au14"]LQ "v5ri/,7lV>y<9>Iyj7" Eʯ݌0Ay0yK~ҳ:Cee$5"foļGNgbpj{$.^ owok}3siXgN9Kp#wg_#6R9dгϜ/@/aBDl(N< 8g0CWVŢ"C, ċ&eZi> lVsGjgO=]qws~$Z^]-k:Yu^F,qP% &5BKC KKԬ!zִPOQ~Ϫznc ?"0ZUZMd6Zj">8"SJ&$I0@BK˪w(u/o3ǜw}Vy{]wPaxNřmACWEӫ݋u X DU#lZMZi;_VȌtJ)"(P BDnG5m܃Z7k~'X s1o"%\[mfVcX}C : H;ypF3O .:9q˽o-z2.>~Y665yf^7xֽ-щzJMAdҀVdSk<=]J %ha֙5-2{gL[U-޿KP,dOn{B|'qӃ~7*fW7>v⥆tb%$ S.DGuDh,]{}]F]84ygv|wSn2  ?:ʍАΐϝڕwm-u1%gEeг6QR5R"0*B'zhgcq@I3zuTNJte2eP|i tb8eYljjx8EXa̼3*t +-瘀ޠ#c4| F<`ѩ$"͎=zZ݅v$ hh}L%/Lnnl[C"C]%O:$S=6Ҵ`-'΀rM<6Q%}oiPYOdJiF4eS-)}?n1aA KN'V7m쩥tԑaՕ^?--ȡWJ$Dz%}:-hftťwxQ*JS_9x_./¦tNFI蚜<1lhNgmsNN#O+1ggگNz}٥x;&8'PXRnd6ˋxԎ9}$ףsPo^FI҉+:,5Vr+3+o_ڢGFfs6~o|qڲk.|YmZLU֊P#T9٬"P/۫{s^flt}Đx?-;d͘ˌ~ *ˆ ld Z!~CX,+Dv8qRY: $hg9 Y2h:KdѲG,#9>"DX)V4LϼP2uʓ_lxJQM ROU"l 6zLAxyomK KBA2 e$OA+DG\s׫=-W^>[eĬZ'q暇'#u~=Hrqxt>=0zfМI^9Fr}yР Y ļ4A='떡eR֏}G :^x_ns7/q i\20lS$du O͍`]dرZLWA`_H:aĘ\o]zeApu)")%~yLNKDR)dY4c?Lvu뫔]W+OM;7'aqT -W&0$>4& # 9h-F۩ߍX3dhLxyYv%&9+ָ 8aWN2vJAA/Yn)>rzY-'5Oon\[j6$gYֲ,+fSx 3}/B _/6+Hj==A>>:Elnr M{Ac'GqKƤ:w(PG b G'"jƞM9}]E[״rd耎s[_\{:2~v93Ϋ*b q"PFkTRVpV<,`J`7 H&հgS((3c|W;P%ʰLLmKTHEG~jƶ@l?(y A[LH$'GSTb6x`!IL■ˀ̮*̩G>8k s-=73%˲j}geTQj_?`T}eIKꊧE[>?H䚩" n0E675>CK i Y/נ,Dp+j>J73ȣ  Z(݄z '6BPPl/߉{̘polpoG;/1p5HcΆ(?8Ԁ {9(kKqjS/Ò69 =uzč]j9ѧ'Իd=p ` {-]{ o^U .1ݽ'h=D/bʢS-AjV/9NHד) w.ҁ~ySSͪݘR95iҡuRJS65h?ҥѿ8rHFX@غΡ'KGN*+O(ϲEL>ټLW\c ]sx^nDz&|cP, ׹V:R8y 'hMD$$} DZ " ezK 6$Rd3ij,)X,CJ|;,}Du1.7]s (8[8`O#/w~nςxc`h{ VuS?0@Qrى 4G7:㬔e5J&uYJYYmȽUS_,MWJWs 6&-Cnk ȋX5WϾ|ɏ}©yw OOo-;g7_4tõx QLC<-?FcZOn<&1o cx" H;dݏ$Y>EhRB\;p[Zry]Kt)|'ׯ\5HHJ:ؚ`mE&F{VoP.0PQl&__T$0@"5 }% &QA8rg_*XZ6vp&aAY=/ywCjy"9d!! ,,yXKV%>,7ۗN`~x+i'G:@x8cy~? lnx*a4 '`vI{R-Brd*8gB훊⵷ګH>p&Eco~dΣg&$MLgD*;דKq9/0;\ ~ W~kzl"\֊cW]GdUhH*@k \rMwQ-J4TNU4x!putaoRm'UV=RCF7B'AM'݅6G Jz=GXR<7נ_vQcyaaA ZkKXL/`؂sI|w# U*81W.Xui am>G@e;GPQeUջ%}ށ2򰪖"X~Og`a)XP/r:ESu`&sKWrקҹ|}:ۿ>t~:%~[-"bAx=0SsS\2;˵[\o4|j~2EϦ;N,#|Lc9 nSkA <(J(ԥRB:n9;JiW^6n8yRК(5XOr௅2^S1>^<t?qB׍.a~c 1ᾕA>twnpܝEJ3i. @:>Sx(+wAz _Ib[0qJ@҆t{Z WeTJoq-.Υ:݃T`I @Iof+rn%ٍMT}Xe{K~{# }Rvowd XygНq e\J K]̫WGBt.BW31K4Pw%NtnOKbݥ%7Q*j|oਨKK8-oLG_;6`\Բ\JtD_B"/\+B4RUvD-/Kh,o`KyHS:w,O_켽CV-8f_)9gE| tC=nKߒsXG'~N '8:T#p"`=21,)G]bEP|uhk/plVzsr|ehQ4 eL{xdAlHBt#kw7]'$YI/tԸ O~glk^bO웶x-YE-o_yg`Nuff#ns'Sc|uҍ+>שP1c<۵;X$ ×Dwib/q8ǼP|ȟS̻ΛuCTdb C~6 'ٯO]0&y:ga8(>}N:`9EO瓠_1ӡLx.ro Yyb ms2wMea+(Bh"D|zcOp)t"A*Z˶mZ{5G^^:ZMV20 $JRw)^]$Ҳd IDߙa>>3GXG2#p>(8N8ğp>(|Lop0G ḟ'&gsV gR$ N~cV߃OXN// Dža|y΂rhpt@TJep0%k2wPQXoij}FUAE~ =>$4”I'2gԲoY<:_ ΓqTzH#|g !6^yG avy6Q>ǂqu|VU/p2g{ļWGYzk](=׳GȯKSN˵<;G>}ϑ>6QQ07O՘K͌Ցe<x U?kTrO$] #Js7z:-?86HsRL y){s9GwãDYtp.藱AW֬~.!b[p*1M o%OJ̈́2>~Qbp1h,c ΫU*zkxȫ4%dT7'@2ԪV{Z1&=qmQ:j6ඎȵ  ͨ$$u.OjO?}+iLV)EII Y@LҒ_`ΞdY tr3gF'%)F 2S- B4fI9dh'\gNA lH5a#F :4<1fASԬ;_.a︂Z]hQVDK/Sd['-[KyV%8H,_2-BA+rRb@^XY d6̒\"b-չ0eVcG༄pqC.j4=gc!`W (Ue7Z~bj.nkM6g[ѦMjAW'vA)eo#YGG#| W38"c*+w׹3V//(т1b9 'P Xl2"&$!6Q^XY? ?T5f}z#C>QN' r7V1j=@Tyq"etA5YV eU4~i./sm|OneK,\)\io\ɉOl6~Ikrjzzjʭ8k^-~bq'黠 |W??zO೺ ޣ?L-|V-݀'|Vŵzw3bb"se{q_3 (oyO0s\ _+- 㹳(o䃯yw!V%4j'neYD:8K *aQY-J8Yqy 񫥮+nכqջT| w I6(e\KP֟i?qb?ᏼ/QCsb(^,~Y1+|D 5R,Ұgd)9A]КbVoȞrhX﯒n*޷915y! cP9~/سi Sb ;hgN3 wQo='iIV ?gfKwQ%aKCQ²Pd{HnfB[[spy "A8wGw~3?zȘGObГd0,e9toO Exychoe.j)5=h$$ςp?ken5=}SlScbLYOqЗK?_"D0Š"I:[ޒ}!R0]j_G}?[Sq[ h'?>o9zH9i#]<L*p'RP-w,l7kP0sWl2ܛiDf# W&EvkԆ.̮֭.YX }%Ǩ< <nf۠Ng+q_ 4}\XdUS2HF Bp0'J $If6|Q7Typ]dZZ .YSr\g ?WS*{R6TjpwC2u~ht-\Pb29Q3Zojw@b˩~]?xZY;^Us,'' nk[Pg-O`螷-w_+=ӱgHG?jYDp9Qq;A1(T63T` ͋Z3Fu>#*k[ͻv9,xvO9s|oqOo9t /kM 3?fY&}Ҟa{L_n{[k ZJ)A8asMkL5h7=0O?yWmQ$”wK^:;tЉC慳 Df_!q,<@AG\c(t#m;Yoa[˦ g?ҒSGV8ّF>ȟTh 䴬3? īo")?̘-/j.`vw{;ua4g$> 0<GlI:xfIxb\~0ʙl7[G>ܲY0b϶N{޲$F e~[ WG.7i-є٭ 6ڵEMoxO/껫CZ.eZ;~Afvh""'Myre߳C氯?4 MG9 OM0 gZpj|"؋kjS,.%#.a|7t >.}F4q{c{f&cޟ/u~y n|ˬG[pfd=ZӦwF83lREpۤa%k(7-t8S ua҈עi^װy!GXŦм`p~d|>\7taVa@OL*1RU4X>FB׬PPӳrG7WփU;s:a ن+r60|dػN1 KV"o$>H"F$X*D (/h$ T\|$U!sA'dw𼻴m+;jnd 7pZpiperj->{p/~qWÙ"J[Ry^Q1 />:t獢AGVz8O8=L%ϝrB#(ąNr^l3>8#3wm#g(?uCK,JOnjHw 10bCiOܣWÅC.) ce$xޭsphN4[;:\kثwH냂@B{8]!#.Z#].đ6`ɥaI6k|t߬QnV*cVΛ ĥ`s^{YՋwGx4R Xo=Ir1|ثcgc jo WƢ1g9;`s@y浲nǹtK6/c]wR[W&䋁 {.멾GT[}.쩠Y kDŽ=Fʦ}AF7qk\d`$ace1ڔi(aKCxn6":B7ֿۄ A!ڐen^|v,VNg@[{7N<poݾPP{#g /A$͆w Ckn+Z }^r_'"~ǽ M/ >;HO O{{m({ p<m4jFo= }kTJ$U< ˪ α&w~;|`ξog?'2( k/uDGOG?vS( ?Oy虯HoTy&*%׭"y#Ehbvj[*`Iة(\:g6d>Ю#u^ o/3?o߽|ω1HY_7Ikk{hlH, vI@x9w/+2<3i`y%Zֳ処u_:6_~L_ţ~ %t@ C;㣫(6Q Fyժ r#4T*j-2gx_JӮz_v{EN_yC ѼgKY&$$8XL`<&K肬?bQu{/k !1[|YmXJ;n>;n;Sa[ ݸ=v떮+_68kf|aP0ivkerf9:>%~ BחIAL'pf9Z$]r2OZ+h'Q~9Rc7ȭeJUpOp{75n{_{CG2.[ȝŭba+r"T_DFbe?hCpE㜅HuMk*53F.|گ?P"њwvy(@~I31>~%]AzaH'8~!DJ!ң:\U[i }.dHuq|۱?￝?Qv#dy7N2H {`aʊd*K{i=b߾a˿׸}&6^;rF)۫}"Qb 9%Uw^q"hTo˟][|] yh&36̊ ˘6QqJ@:g[W ELSnwN?5jŝU]o"ײ3\zRv_<|fluv[抭3/|/ٶVg:FREu,Nv mX:x4@$˾{}o¯Φ&0^ _{m~8oxo"N< AZ"p q ; 7Hu~E8h1ȎhF>VW1HOJX$ W>h/6xoHzI5>x؍IʚL'!EYhJy;tj;%)>>`4ȜvG#2?;,hMu0@fFdhz棁jlg_R lyVK?X[_[T|c1V{oAע.F5(Dk݀?r5}YN]@6A#9$vAxx@c;Y? " b~` N ޙunM?mg 𵫘3ryKْ9# Ez—z;D㊧mbwJ-Y\_TS뵼X,2tWRyQz̨Ĩ2`ρ v`;lVLJؒB`>\N˗ eOc"n-}$rFkd,t֓Q(%S<@ 8ɤ,5 :apcŖxޣy!/m~O 2BXA64g2yDAU8}םmLuwwU^\wQMs]2|U/C j,7L;dS!<`[DZq+ +<:ZbEper^/7^g ;@I Mf=Ĉ| sEzgByF*d=$^.&rMl8NI32 G gW LZn# C"?{Ԗ+V,G)pJK3WsN! >{N(- p7yB@!YJC}qW2z\PA%92@3 mXn^ 30U$5/f%Uz;!aj|Fj=JR鿃b G64x 4ps0snO/WWJ 66z/6b KҜ Q;v ~%PqH7$hKd"K ̕BV7 bތR氀`y ZQDwU&^XJ &*iw:vO+|b}/ܳPvѮk0|^kc/k4eՄ]fʚOh&_p}BXZΜ1VS@GF[uٹkM;P!C`5YIv A mtXV;gu@˓-Ihlj iyԼfxŚ6zm9+ec3RlDi]ݪj'Ms8MGij|}kE=OGݬ6r5L[뢜Bd*x(گ.|p~ t*gW [%@߮ {-Lja`_b{te2D l1N6&j,VF{ $%v ؽf]8ejqM8GN1UB@ʕ1{Ǘo~v"G 7Mfqk|7eBHN±(\,>q9}`X?כ?SxèXw`Ԅ !鳧k'"s(\Z$}[+y8ց7 c_){C?:F$k;-NET"S8`2$9^jw|?Vف8 BhrǼJ۫pTrL)/Q k: /VR5"XN{H4[J% l*]li91KgH\`yS.4@x{o2wzluS&FHŠCq@Vѳ &(T# +J 8C *nS篿}ٽ{;^W?k~KZ(;T<㶨BCٰ0ʪgϠZ@{<[t/W@@.ԂM%[2ӑ9خyoU YGT{5`PrYVkM:R+T!OW\?l޹ ~{2$Qd V0愷Lz!YZMj܉q l+Oos\*d NW' C}k0o$3}ӳxݡyd!!vk4 /_@ؿlx% K̉Ct<S*lw(й3[^~k.Q 55ڿBߟp~؏kT:Z~lҼ5ӆL)񓢻-YRҥ%"%yڮ3eY=rsߢ56]׸tN}s mESbzʹ)'7hđ }ҶY\1^O°&b/Dl#3EN>{ O6_]۱c.c/._j*Jd9(~XPvJACw_7a^-Isu^G9:)}()n+"qV2 /=<6vqJ/G;@~ޝx H ledWzw˴}Tͧjr/n3-Bp&`׃L '>2pA+GkAeK2AGp@ie uPr|TaK')o7/±UtξAb"SdOT!)>7#~}HޠIțC;e@^lѥK=ǎ$/@<$o5JLCCv\޻޾;[G_T޶FEō_zNn QU1c֏N) qVvzRï5c*ۥ(=W%[ɓsw8X&1v^*FJ]ͳ|,,툴GF2T“St!ts%[?D6(CH%#oFxŒb՚7v[UqXsv䊡 -аA%藞(?=3%\}P^^ JJ } rgKV 1B 5&)&&1h}㱍>4 ?5EE V')%!%E)# X8>aIr48ZF|L\*coQIV,5\Odzk::j.\ھzE5 ֔vipƦlǧc#qw;=ՅwL8j"Uvx pZ;EE ,cdT©G)x[i C A5;Z]BVQ-RaE- 4 4OMOy@:ε\/?;e iz'F4(Z5TBXtgtΘ+;mKB _hXq^X&?7=vm)kjzO/6Cct׾kW.-Kj?py$= ӥc`М8 02)r3əg7@8dO-" dLo7~yui_Nմc\/%w'1vcDb=_nTjs%/06Ee33 $V,*Y׺ݗ:, K^w_ZvǓSݰUub8CtyU>({wëP[ ;ǹQ3ZIQp(1Eerl~/{"8ނAǹᵆ pQD:xޠ+)Hhp; Z8pP9IV7z-10$OFXgs.F x0BT}FpEIa{$%]=ڞkbwCqltpd M5b .-} 80qKhaJxPḱycjŤ -T-έ4Z2B ꮆL66ittENB QNTo\%7z3e=d=r d2ۼF1.뙖Yמ. me;y;5f$QyndbCc&rujGT1l :O+Ñ7#''ߢОo%AŐhlƤHL.P!t>´<##aأzr9$ VIs 9/iR椤C }د]3_X&:ODևd5 CpNDĨ̝øaSOzn}w<:&1pn.ᵲa$AN[Mx̠0hi㩿/`T2 !AGIUKK䬢}ÿ/ͻfwWvIæ*ㆵR{Ͻˎw^9nJ~F,17j9#?-\ct64% zϏVO0i:~w/1􀻗V@fwwNȉæ)`.} vxyXs%:Le4z+NS棳O#: g@DzZ S#Br ޝ%EK5Ooݻ?vwf^Fs3BFRl)o&wnI,3pUǰmK?_ൽbfۻ`]}&HYs=o"bE} !Nw3!L`!j5XVT AR8/!-/- tFfLU =c܌f]i ț[N$7aY/eU*zor?q};ݸN'τJup5vQQ.!!1> AVՊFJLYɴq:p6{HO8xOcKѶ ?W|eAɳV=uۉCr^1졛oɛ a=ܞXw G]2 Q2Z&ӈW_zf&˺}OY~E?J\(7ۈ3'(ZFp @kP$ Ar%KH?-r!fO0b u `.EC̗Obn\meJ QɾK<8T%$&!t%'Y摘0mwv'ƝJNf ( >AK+<)\ G8?'|Z,J(h@F׆N믓.5ּ*zjU=5 8dXѾ8_g *NJDָ_|05Oxf[i_2㰹uxr }Oth}u촭[,E ̓Ğ`<*NȔJ$`jYq_Ù `&0n& g^|;ω8OŘJ Eq3ј8ޘUWcD&l'n0ÏS(Tz2v:Fcye%]埵˞ބC42넵#WI>ұ 2AS1RkN5æ&>zۃ%"}=nqZH|m^h[͖ilG66c&s<iE#c˿82-r5l4t ?,JS}_{w+_]3k33F7̦͗E]dbCےHa.Y @\?6`$kV.)( GL V!Xޡ=28.gGf(s{][1̾ᶎ]]:&~SOS!gfA=U5_=$zؿpl\ew-ywG)\5ĽIO:.yXR;tT0zd__"ؠp Fb,,iE zLg!\-jb Yho۱|kR=AC YG(u.@1}lI}}l0W럂 ( A5:Z`=@rj+'=o[&ڶ\a?<A3]DjjS)ytw7ݢFR\j4{< /Ox`)X~8f:Ogo;`Qs@` z"R.1xGԑA1-?_5/A.\ARjf0mUʷBA}h^?'{Tۀ6>K.E41* lѰ N=gga'8ٰy KtػKd9}y˩Ru_̾2xy˯.|:rvO~ 7H^H`5 *ؑͫ=V ddNƁI͡fɂPzp6@{ 쁷q;ݹހD73]BnhL&dWV-2t`mgkmg2%؇'.gD:qgJv'5 $FFrklqlb.zr[flV08PPt /d,q/IF\_gvUV@C) )iHPzO9oG+4IVTdpC׏kS$g^WqEHˮF qV}'gZ?eٍ:Bbl9C%cm63!WUXVښDk?iX}eWɞ;:s׀~̺^׃8'GZ)deZYOCeg˫?<΍ Q+_[ Rwtf?j#7vT::9 Dń(q/NR}_^qXuo_+M7?j$߁fcݝujrҔKU<[54%㛥9m9ڍhT0#^a =};I FN{0MqGPO\W4{ph/hA %d!&C^(yJ&k-~2T,$eSwjW>>N:f2/b _ϴ {q` 4jUpH+NlMY\hY)gQk/ . 9>Ⱥ-0WHIq$: ޒX?#;lYO&gW{56Ϡ?Lo<&9$R}aLGא51/XSB_qkgagDp]hxLVPvI ihT۴j="dnRnhD6r[&'!)`:l \' uD"$f#޴tLCۘf.bPiFE֎`!E!MNE{B 8u!W<@t$x+dZ,{r[^<<͠sqژa#;˸ (e.FT Waϡy$I1ZP řlF ]?02p6-d= hz*F!{ %{kSCr芄HM6"vvITˌ eH.eOq$WI̦V 7BsHsPRȷUIoP5sZ*c0|DfRx(c?$샖Wk@e {w>R|N%.q֨ݖ˄W'_pgjuuHuh`ЉyKy;6;P-,}@d PҶ& H[}&1!6xώX?.Y mh#X)?V ;6wEmBCm4Big[ PéG:;HX[n~Oʆ+o)w~+ܩyyjTž$Wъas6hf5j'6=R#ÏV<'XCs^(I__:bKzlɂhǎ=gn*IS"Nuil<0)ǕZZzB,zFqmˁ0}x{d¨6s.@q&PdI|>Yib[wI[6M:/ mghe1贶%侵RJV?  Ƚʯ/?r!Q֦-@҉UPBk2D 6uunH1\):dH K|%bGh?b0Et:8(Fj4MB~!@R[ʟO'1jI&NĹn=4 VkPNL ~)FsCgbFL9r3'@ҫz`gZxN`߀1.?Um]wcqԧ\lR:A8BpT>'m{kʵ-9x.g)^BeC68lx_cN_5M`('er$0(ѥm@I,[sό4ļ#tY5a[ڣKgm*[^xJcIf wnUʾe1Qxqu0rƔD{ :H[@*h3SgL4}~Ѱl ZU!=uveu7h#bH^;g A{?imVUSkGP&A1%웈ŴdZK q}&bT >c`h/K}̔Tj)y~晎GycΓkAf3`yjj=J)t'8 !jD gËqMЍҼD,CoV+7"%eĖQhCJ퐰z% 1j- ȶFw,w!}_}CWotm?_:5Y>Q <6ncm?Hqs%wѭez{i>O^{c{vctE/'`uo] #hCA0XJ^;+K'TS$!q^CM2=t:Lq'9)O9Tf;6ӰY~HڜA閛PGwVkPɮT~9pFF:XSTL,vSճ(j;$#+53.j#,JDB*錈Z 3HLJt:_czc{ AbbZz# T[*z}@Nsqψ{DDE:KKRϸG'SFPyBJVk6S5 48[&݉/Z?*0fs&~^/-})-[4TQ1JI)N[5Yd]_zIrbhyV#F9mV /i Gƒ(4(-P>*7}@Av$vB'}*OyoloJ@KQKue 2|TJTL=3iSԖbEGD1h?ֵ\An<Ӵm٠޽=a:E~'Κ V,eT Ese{20|Y!>п0]pV[.[@eV`[`e>/N˹+;~o GL >w5r:#T(#1fY. ٞfB 1//U@s; iѾ"jpY3'r%mCɨڜ QQϚ8ڎdkIVHnQ\P)-;QStdB0wCyS= ?;8f:"@#2h{!>ܴD94zh9Zaፑb H}G$Np/IMVg4e01iaNFLf eG˰<Afo G(zTWS%Ř;=M YT18<&XzZfEeF/(1YB32;FvXj ^zwѶIi}9G:qj,1Nj˗ą;Aw4',=Ǡ_ǑB fög#٩pJ}V0OX|,$! FHocpX!)¤hk%s\1glIFnbPY3^y0VS0Qog~(@^[V&.y%4.c(,1zFFXgK&$Ϟ³b↥9d iCB Ei ;5Ԕ3 UjgO ؘ/,WH&(f=oCBa8^{BE ]8J2 _ygB=di;oCrm$(':J\"++Tww6 X7oF.u< XFKP8-*Rf2&%ġ>ReIw[E#jvZ#fd9 drZY{k4hZ0%bb0s{tɦG(ѩC[h7w2[ Oѯc v4;<7ѷ3rAb'JҨ 40<*8yrC݋f(JT6!V?"LM\5t玷S1am)E u.RcVs0+Va0VM~fҚCBŝbb̽b8]3^탸ϾS` XE^l3BI6tF%Z Ehl !A60c%#&yGZhhwu _Qf4>k"||nOHK Y;l\ oEb+7ޘ<חןs T!$x9fu05&䕝 _A~2pQ t\sXso9˓\ )Ӄx;=u.hH(zt*̤$x|qRYkKHp^!85u5 4*ܿ/J/Ooo7T5m #7`EםD֣庒2gӳj4w/Ww(+po9vΛsܓ{"+ C.v,pȲJ,a+a3p|U֨(:|g%RhIܥxFJv(Hk=:~q"-KIM<;Я _w ^u2#S$Y dikϐ׻^Z&<2D7cݠ}]U;Yb7r y;QfʨA9@YDҸF61/pb`-սUɓ2鉶MUn*JJ%YrquW{MN3 ͢vtwAa詄o/7}"xwp=5‰(M'Gv+'b(\k:Ou:c|+دd ߆b0Z.UQ6Ɠ'0((wd0j!e'ڛC<=xzȩ<d8u/$ݪqaj/5bus' Fg2aDMmvf$42q |}P ˇցn?\sן`k[>=7ɅWx~!Hs/)YzDkŃ T㓫Va @ƥ$nRHI=? qܡ1rE Ш\`^'[_\n_ѭvmbG:9;} ]H/v^x\t܁wz+|&Xhw7'>1"0mn;݋%ׁ<8ݡw o1^Q|Ce,>4oa[E|@|d46{q.zKq9L+ЩNaA{G_=oX?WmGՎ;Р])}Ѽ0_:楖$bw5ҽ-Yz|Ag>bg ??75NGo#mxx@q ˗nD_ ^yBQ*TS';* ?^zAX09 ~B(#H^~,'bn ,'tbYa_CLCO6xO6pxBsˎtvn7)%8ƃ?8+~8[~!Ocw_ئktɷ<{ލWh}6@\WXOiT3ud/>Iɑ!JyFBބM-J%KO6nZTo y\wI 7;eПzֆΜ.lˌvKY|D%mh#_ FR J< dQ,'r2yCS7db\zd2!ч-O(%JXkEnLbMHzN{ĂAzg38|8zU,qy]cI+,ch@3BD-&w;=Y=bϕljzTU.׀Dscsu >K>E7{JΧ+^|xF h|L*i|sRUBfsBL}P@*U2}:{?|؇!̇reRK/,;~47s91!ǼYJh/7H R.aqJjRLCY)5=dy:; ":;"7[6 XJȕǸ1/t*Ad{wdx6;*fzȓ[{>!oܗxL;T# 9-%[BG )1D򻩳ZKĴ@>9L|"~ ԤתP~9okċ0V"D ɲ`YT^^R1ŵv͞LqA&`?w>e)TлT؜v>ul ?dJ1ڿ>_>_'O<}S ~_n|'O>r'{@>Q'IBt=Ob:*0vNfv"E'wBZo⢀+| Ť':,E t 'Yz1BP~i2r.l|,|/N+N-g \ל 7:ς7=pP+x$ON8BCdC[7Sm(CUG!Ty}ˊQDs޷CcY :zɣ*%//A2XD0&}8W3j8uj@}&yo3vl~(I1pz5|hn7ҨLrK>˪=/?2n5ޝiϬ&ԞO>2~cdZR s-_3.63O+Tvb߂6Tf1=޹>Z@Q;%w}NPdŧlIkjOUFͨ`rAiC˷U +;j_r渆j̟d8?P.2=$s> mZpsdwU;#blr;&u&5{jH O F B.4"4u*(??'4/23hiTd2&o7+6)ܦ6yKkI)OM)k'z$'a3¹ǾKaM+=g[lWn;qSO4N2-Kb\[JV:!"2&}5^KvVg ^}>,ۜZa"I5E a| 6VQ L[}x k"Eg'v`uBB^IH_֌7&֟}FhQ%XÿD5T7hh@}o7żϧCb-/N"#.dT`IcM +hpqv;ݵښ9!gZ'O>OChpU)b9M(xb4={8WS\nTk9W Mһ;ANM6C?rJDm ;cX>+IPX +E.܄a@Ά6:`i䀡~]KvX,c; a[0#|v a[#L a1/637 lV5MIB p 8y&6 C+.2woP+qq1/PГ۷ {\&Gƚй 1`*8r79H\XqjLw71tiʏi@c->֕Cs`^^TܗZ? ď">*Z㓹s_-qMDlJo/u\~cOHpY.!᣺̙\3gR^NyAmFqdQk\nt.93;BDz$&%%:Br/ArOn&̘/}/ 6LJUtL蕳?ҹ:<<Ӟ[}5e"έ3~-93f4N<  5KWo?=ǏXtHO? mJ-[0f잋|'Z1Na*z_L߽jRkHⴚCaVyсyE)3┵ :u?!+ĬwJ()TGz]t6I;bOMp @J\P"D^ pdlS㠤"%NWJ=޿ifXƛo.wa ;2-M.6XiP(h':; )DGs(2wq9zyN'0@ކ۴Iu3<e}lYuon&YenB||stkH"¦5I:#"z7X"_}opu P#0/ k;z,gϐnJ+ԹN|P2sק8|88|zȶȻ}\nqT+Q.'4yVD]OOrEPź#[*M> 95v} w;~)~ㆄgVhϼtAϼuH%6o/9 &Dr9AxkC.3fT_قR5^8%?ཻ*mfċ,f;MHj6SȼҒ[S#|jc'䕔['$ F[}X*LOrLl:$^GfFa#`Vyh{rԺ3$N^px ~_#y P_vv1 D|⻷HwRrvs. #{0m3G>7W>+fo G:x^z9V 3/tmz!PDz'F>i mo}G}%! @\}Jތy$Ytze2P)15}Tp G GɪX,kѫpKsF_SC$ t1>m@OXQ^U_^@h.:vv9SOW;gU;z &ȋ<L#?p]PP#J:T)6n|aSIQ)`3 qhW>`؉‹jL9*Mo2iUjvw7חl Yik+ӊ?B6˒a(<tya%{.2[ϰ+"7E\;xay \ 6 McҢ-Ԡ^>>Zv`1?&eoOO[jrhօ3b'XN.t00]iUW*]o@ w+mAw/,I0yH(C)fiKj{)K)Q5$AڒMqUk+jf[̼\%~{iAٓ=xZ.ZpAr Z~aFy7Kqd p-8 Ex,KSCsJߪD~qJ> (ȅ$h I81@Q`L^*3l"^V>,(̐4۔pIQI\]јEfв >hBo3 _D~xpV_= /H C&}a-ykj-OJQ+11n;2<0eP'.$bמ'W3I¥ 2ggþÆ%1% Nø1ס2ś=Y_P (2mV#ca0|vYG"&eo^Pq]n?JfLWG3#&M~24g8$v0&*]$%j$W9 } ە>hkZ^ƤyqOCVĆ@m `/sW#ZV1ks:u hxa|ܔ˙O^\(ԼՐUz-^?)Ov: ߋ?Ogn2cA$kN{8';ENQ8nߟߋ V ;xV'?gzc#?y|Fh1H Soǣ07)ߑnO:-r b'ܶc$Ū/G䴑/v&Ӈ!+(p!¿m !}% 1-'{|Y>¿pag` 1/&* ? P @Tba!g^B)"S0B&[ÅFо !7}n/Am Bb #+şP, ɑ3:Y>(;"/ 1Cxفp!F0Qy2 G.B2FRn9?Q<F #,HtbZ.)n Q̓'B0WWjwo! 'ųHY&e~E; i )Л i6KFl0o>O/VIX9A}":A_܏N>ȗD bdcuܜvku@aZ M2}B"dӼC¥/eѥF]P6#777&Ѻ2{"7wF#\)A{-Vw~q6K$p/Kvl2eFEWOfN`9ŗxeqI7A2u16?}z\rZ%=& !8MbcQ+_Rpqb)7m1:IAZ{puNg5>rvsGwEš'u_q⠨KKFqZћ!3 ?"WH- =U6 > -{xXEX$rHˡH "!a>Y7'@%"ƊQ\h;WxQEEcqr1Wg-H\⩈0mWWraχ뀖nO,tKm(/` ~vL|?h/~0MIN5 6aU8]mFZGۚƶ}rg~cvO/h`O*y[7ѶV7m⻤% `^Rm{P:S/$\'c'' UGtީ5>b{o&-˶![/<5dlj-g]c(FվzP%-'9LgHV@R@y%J/ztĴ`ٞ?k鰇ߒS1;wB}l>1~&׳~7u<,(HJF#ezy!p9S~dYy&tHscKNU@o6PI"=z'q?V=j=7|jF!">֭{^0_11IFi VH&t{hC_TlBL:nY`Oa`FnbK-R)#(H,TF;2?j!rsLuW uDc_^QrQ\g{`k#v&0׃9^M% Yڐ/ƊcĒգ)0)w6]\%;K$894B@\ gIԓ{} #}4cNM\fٻ-W崅DKM6j6?RGhNmz-ک96jnrlGy$T[FhS3>n#wjg܎bͅ6#k`9KCsķAsG>罆U Hm7?{eg_Sb|=m>sNcWr&u÷*٬hN)be2$ >/6#U*q c)\D3$5}jy鳃§O %~=:]U2|(!w):*zɪM>st K z!@b[z;È>o} 5e hm)}V?=c魽[?ztYNWV i>t&=;e O͌{ntgɳkL9qڣ&0xz%|܁3Dn°n ]N]6Cq {Z0q,>Z .8 u9-g:̞ᒈU!sQŠ2>*e,I'rŒ yػC<9k}*WWEs~] p~B6 JƘ m]*3S&3pTè[*1M6qe9&Ú}; \s׊L' )pgKأ.EВ;&on9\Z5ϷT]!6>ػjbڳ=_] F ?1* Z{/Sj")zVvo_V^g6|{d-ӌۯB[g1c24$*ÕnacCyjwjZAQ,'jom}5;+} u+OԑםwμG4k _`qуg6.9_:saan{E,f~s&hɟ=I16;g3S*aך|1=?06*wq0hjYo4wis9f,6-rV8Z*Q/nQϔ?3K33uL&0/{+'y&sX Gv1{3Mia 3 Dr‡=ļ ,>; 8`̋ }k`¾J[%S1&S]nHtv&K~e_X_p}<xכ˸a?yOLؗP]RO#v$CCޜm$Ϫ2j}t!~\3A\>D%"kN oC5`ל䤎ҩK*f}jcu7rk!֌,[UtfvԂ[k6.; yHKDjzt?vw3 ˿~ɢsL;;ѯ.s̓EZ w~^ ~?{=hdmؐΛ`l wll?c[5@qnkxbhҵ  2}CuE'A!=~@EPd۸==~}.5s's&w0]μ?7~>O*>'2zEFFFp3@:Ƒm#x 'h0mQUnJX4ph]q[4 s7q/98Sk!xTOoEk;I6E@+!\jNRqHRʖ%#MwޱffkpD9p oW{="zQ_h;0 mEGWadѽ׀7h'+Mzr/-z]#[t x>~mgwڳңwK6B&QmO?sVG~pvOI5ڋ xDI"'--0mگ~mzV>;e] x'ګ.=,9iӔ )h@Rα#va#):z MW)X3~<-SWޢ4]+!.rXӆ=QaCe.Β܊F_ɾhc=3E/Q=:K;[pќ5eHzw2+ Z~21=Y?Im >Ɠ9M^_xu _tKх4V\pT-%RX 4@1Ug[MxppmG}|$ ۦ+kqإ(+LQb})ZEbLEO #3e42*}i\0ʦP/ ί^#ДK gP9:n:=J2godxe,/ ђ iUs`wٸLkw6]u|8go*A2CTZjtWeJCt D^ed2KuBh_3,b^(QH+R~@ ÷o@0 Ԭ]6H)YpS6<${2̝YWb)ո L€,H}ءx8`9!V?3 &F8ӗn52T}?4FQz㔍;c1 A,,&j ,<}%w,f;g%n"Ωxmxֆ8q̐ZҮ,LIMBزDR {23323㽷gG_?;;s9;gvv$97fw`VR2@Dèj4FKв-O+ЊLЪNkКMкOІmLЦmNh jǏC.E)FqJЖmMжmOIJQ2 FiD;dBSi'Fi4v]iF'ͦ(φ.C0NOp: hnCnat7ӑ |QPH$1ziz>.zZo$z^(KEGT2]@ڛSF紈bڇ}6@:-C0>#(>cUz^7Mzޥ>D>OST>O3L>s\>|!_%|)_Ɨ? | _|7| ʷ|w|??ʏ?O ?o~_e~_s5~7-~w=~?#?O3/+o?_#?/+ƿUDH4J f.#EF(-cd,#r +J"j!kZ#zl Fl"f-UB8JTbl)[ֲl+%#Yx m2QvIL)2Uvi2]fH,3eUfn!{lK2G:S %#E+$R̗*}/5Y e,%+r(r*r)Gr+r('r*r)gr+@.bD.r\!WU/Zk:^n&Yn[6];.[{>_!yXG1y\')yZg9y^-/ȋ,ȫ.oț-Ȼ/ȇ|,ȧ|._ȗ|-ȷOQ~U~{LmFmaڬuHuetY]NtE]IWUtU]MW5tM]Kut]]O tCH7MtSL7qjHQG]jL-u+Zmu;^Ҵf49M':Iw:EN:M mםu,Mw=tO{i^hvjA[{suWZVO t.źD}u?_ =XC0=\#(=Zc8=^O$=YOS4=]3,=[sQMt3=Lt]Ez!CEt^z^+JJW5z^ zޤ7-zަzޥw=zާ>D?>>Ot>s[_3E:΢o%Nsr:Nv}Y_W5} }Sҷ}WP?ҏT? RүVw?Oo2lĨ14&34fi1#(3ڌ1c2fYYެ`V4+*fUYݬa4k:f]Yl`64&fS܌3[V2a1qML$̖f+lk3ۛIɘəfi3fL6STflf]̮fn0{f/7sL4eM)f)^S63mY`EfYb1I$=V.&[ʂBR-304udoZ)76&T @J0)ouDXv Ft,Mo:Cc#鴒|ZH!Y]P^4@6fB #u#t{ P8 Pעń9mRgHS\DlƴwE6QsGLc]j>DX˼jP.˝ŎIZI6R f^ɿϓmr]+DžF'Ve{je~OAn- ›bë2rJOܝzKZJ}q%W.Bsc,jeȈuobqy?@jG5Dn#^-jqd_՗15d̺>.w/g2|T^2h6*)=jۃc?ڨI(F>fZ'X,&?h6%V{}=֮,/P&Ĭ"BGwNsϷkps0ughGT*s* k')h xwrNTYQp7WʕBW JÓ=lΗ+Ro+z# )E?l)n[ilѫVC2Ba|7o;p3Kfx ;{O9yٱ&kK =ESi^| ѩ=EM{}EI&Zz47P~a @7s: ||%~h 4Yü Rd*-,*zϜ >Tt/ ^+6T;RGgK~jV6K˄aM&ub84MBS44Bm;!C?~f`v;!C? >O' ~0&? ~0a?~#cAur"Gԉ?~|||||| >V]Oo? ~|N(QG? ~(QG?~ 1c?~ 1c?~8q7n8qp&M7n p;~ 'O N$I'O? ~$I'O?~ ||8ZqRI?~ )O? ~4iO? ~4iO?>%뒓?~*~ 3gπ?~,Ygς? ~,xu.]? ~9sρ?~9sρ?g.}뾋uźbwX].}뾋uźbwX].}뾋uźb~.懛a~.懋b~.懋b~.惋"]䫋|u.EWfڣ?W"_]䫋|u.EW"_]䫋|u.EWk(kӐU~iqfӸLͷ0 ,.IM¯}z:PƠqh竧ih:YM?~ )SO?~ )SO? ~4iO? ~4iπ?~ 3gπ?~ 3gς? ~,Ygς _gς? ~\qWYs@ρ>]C9(ívxuQh &IhjY+wb;sNi5K:{`} 6ux_^-6ЇCbC }11z"fn{7n8qp$'? IO0nw 5/yB)Up#돧߇F }|R.==-=]vK7Vea@~&cISnDfw5xk.e,=MA 4 Y_ah@]h&Fǁ_¿/\־r ȎbTv9;޼j[gW-ܖ]a9{WwnpoofC n lqȠ8^l:fR@@^xzFR L~s.4\oEK_ zar|AQnRYݖnJo:/ƕ*lqLPytvHmHƶq}^'2-C96𢃺v m ~a9fm;Avk!}+/$ѱm̠lv^}!V_ҭ6#XchC&:X!rmt໇?{=mev*բwZm:PiB&K ʸrwGFB{fxJ {z}E^@fXE8l F5z/u5}={}u3OBe\V>7gߴ}9YiBP1`T|>f au|~ܷoR3@>%0|o ߴX'|TPϲ‚ͷ }xQ* pqnB(;R(,{tt xMj`sωF5TyhZ݋CI1hnC"@݁pAEba̠.{[{ǝ>jXcHm*J{]>>l߾$nHDO hy+:hZ`6]mLKLm+<\4S*WS+f(ެxFn"Ң+9LPq1-FL(^:H4A'G:Ioѻt@2}9y p1zM10a͐N#GyaNy+nO3ȉ\6*TKuTO Ȟmfڈ,tN{>}@?Ӈ1]K$cȣ<^Ws y/q)>o'd;q;L), M,e+>"[kiuS=L2 :/UNb.RdmWs#ds/2ww!c|'g&b91OOcEJ2`*Sȉص*Dk5F}in ~3NfviAQrV6Ϣv0ϡ8v+hI4bՃy=2d^@LO !s-Kw#se*C3e;0KZ\ li.v`tI'0W0RX-}N`1$lA`HwnWݡۦۡyw*1ծiyڄ_  ˅yB&#=9e p\VfY,S18}.3Z\20)h琉-zkhg.Žڤl<\)r0ދkUs0N אnX/۝kǵ+S|k=o+O1݉^xi GT`?v+I"ݒi]")GrH{0b9?  h5E4B6^rT]\k\>kk%OKv>t>r::v>s& 67 os퐏`Uxqzb'񤞆͢|#Te}OB֔iBm>G>&ЍmA{'уlv?_;TD%s̼h#i3n1ϚQyL7w4}OFyoMػ:Mctg5~sxHkkdcV~!m/6c?_5Z8"~3^fkpO޶dOefB>nXhS򹍞"ی׷yʌAJJVkupsۥEvHItH2ΤwgqJN ˀDdоJmgv {[;Z:2sSC!k]̯`ooH |M)UVn3f -^WW{-rW_*#SJrn]h/}bUdީ!xݜ}ŝ鞁 rYD$t K pH A  ; ˲úY*ᲄ%r8(׋9,8A "A%\nշ=@9뜮zꩧOկgtMzh3vf5?{hhiN 8*rj7nhe|ُh GYDZmQ]#ޯj5ޑ_PC[}ɶcޝZOӺus-[ZjuݺP/m{nP{׽PݑP}uk6Q+[w[/[_6%A6QXdxl3lsۖV ƶ<Ͷmv@n{vꄭvv^K+N[{W?_JC U?jbfϭ_~y}; ~GnxֿuXI/_]JfwPA{ܞba o}}*tl<"WW[ghj%N=v!q)?_ZdDkЫa@nh7 j 5a&4L0jN ˨V6ZFSzoo&a>&a!!{EIF_dPEFF_dBEE_dNEG_deEG_dsE^!鈐\5J/:0J-QF_%Q%)Q%хQ]%ѵQ%Q%уQ=%ѓQ=%Qb/3Fbc/我X0Fb M͋m폑ءؙ]ص8wx8/x2N/>2N/>-Ns/8N+/>N/r_8xG_J%  hID4AK OĸKLIK,LKMĦKlOKLKLĹK\N$ɞI$IG%I&_rH%G'_rR%'_r^%&_ru%7&_rk%w&_r%%_x%$_b%_{_ʞ")o)")򗚐"i)򗚓")Z")ڜ"S/7ER_h:R/u>ERWR/mMt4KL -i:ԥiZz\zbzJZ^\kӂ`(;/}0-INKL ^җӂ623##3L6#8 ɌȌΈ<3/(4#tfuf]fcFKqW33eeĽϜʜɈ;ݜݖ-+w@3[Yθ'Tgqg/e9v8q /\c9tH58ܨWr9q 77ܒr966Qmq #ܾro並qM;.w!5]*yw/繺ˏsuD55]~vP&uʤ|AuLʗʤFz~mԵH][H5mx7m8iM6n-immmdmC&-mdmGYkF4xfHխA>)CjKO8@Bw % " r =_Hr&pV|{'p~Y^/^/}wg?:rnC,Έc꼸 },Ͳ]%n߀=mCjN_(׵|gyєֹӘgɯ^5 Q)(<viH'!F?CUi#~ yBT g$(<);J8Mq׶C'EG3H_)5wM=`4F~YONپy7eZW[[Ǽ-JՓydĐ'fNiZC﹵ߙ/[Pִ1kf~^,2 1r67fcqձk1з0jSk\e:X¹1|)ۘnG6WKPp z(Y,gqӺx9SuM+#,5xCqaD>28p'GmlY]5| Z;VǒE|{QQ}aUލTvDܴ`wLuY36_$sͽ@O7|޴rSǚes ?ԿԼ蛲 CϚ{M+zyz}7+@\@xh _EWQtOpldžg9|FΆ1֦Uvr0:v>1ȏv36ojoҪ "'ЪCB;0iǴ7\]G΀1z>kh蕫o~cO@^A"ϷȓDkiuM*f5X `كQ_i9iȴV5YƣQvv>< .PǢ>6ـ2^Q,Sk_S&o#?!4W;r??FBB@P#?B7&S+vL$5H;xKL4Yym>4.o@?qO@l7Xg,ڐ-_Ἵ/Sϡ<'٘3Q$ܯIf_XLD*>"Z1wJ]r;{c'cԿ37F>?:.eeWy_ P>_uܰ"XEյ'Е؂f_ 70|POQQ9,MZ5FO6 :7~bْh }>GC?{ύ(@imhuK:NX{q)UcF#ÿ ?P^VuմghYr1B9Y{_7g EOV|nc1銉c ~i=P~?l{_5vjL[&}5OЯWXպ>*$_C~8/bq7n)EA\;d~V]rݕOI͹=Loby,21Z֢*-}gc}g5{<>Fwث=y,)mn3jGJJ1 YjQmR]1Gŵca|;֡i}/}|S06tT _k UΓ*UqK#SkVWo76%8_RkhCWUzއTEoCw㌋U.F}T=RKS)u}*?%LU)y>}*_o8] *UsU~rTJC˟R3ljQ{Px iy~eN/U}jmm)T:Z觺YS%ڭRN{Ժ!vS⑿w _^W~3Zum]&rG+W룞>`^E+&>WgLBPVUЕs+q+|[B}"gLzG=B^D}^6?e648F?W?cU}y^[HVF)xLj.VTa31Wꮗ}ԺzZcYHSvSyn&]2aU-g]V%c%xGXf4y]K ZnTHD!c*7vzL}K;jbM4=5?槷 ͣ4ݯ fHĴ*-6hemGW۫uhӴ篴3];+~ViiZ7ڧg{gg]Y}>_P_]?nO~ FF(m?Ì0~d,?2 3Q%j-qKh$-ƫ;7N㐵3NX֠[kĚ1޷9uuu'jyf#kcg22Mk_]'ơ|]mC>|P!>rW^g(wmm=ⶈ>P|ŧE|ߥŧ(>9p%>"Q|IYB/,\, ]xk ߤױ;{V#Qot[;Y45ߋՇ~}I./Hu8{Ej*~_"%Ӛ<_*ˤ\|ƥK㎀hӢEh=k#fQZo6PˣTu-rsпv!Ͽ4ʰ*â>d=+rY =? {bS}>b j[[BuSCk4N ~_ujr_5oi}SRoʿko5sM/eVrW)>}ħ. tOP|qf"${LD*Fo2)X &U #7L4CҚ&gq5JXʻ{;n/7%7$+=q6\ʝq_Vvc~"!7õQ8m6E{XjK"LHN^QsLf_o/cΚ_o m&fhIT_x"}䝮MUKj%zl^5}$ R{)"ǝZ?5Mtw}'rG|+oş¿"Yrw&Qinc/fonts/OpenSans-Regular.woff2000060400000164064147177152050012560 0ustar00wOF24\>t`?STAT^v|   j6$N Fj [Ǒm{/"6iW!clW6v* Iz$Yĸkv ރ-"JhG/miMa1 )dn΄'JJ; $@Q0ؙqZIJ#9; uۖٽYIQS0R8{ZZl; tLΝNlzY0R-׋{Cdlw$ˎcm;{RB )'P>;!L.k-`cXI&& gpx#[ͯ1]J7+|>dYvVZK'^!KfԼmAyE2M_wso3-h~\0kJ~2Cy >{8~{{s{/J̑DJ B$f}U4!,]tN{kZͩHd2@FFn bl%RJb66O:}C͈-ɖ^ meM6}/IϿ;w?[n%-$I[?r--I$Ir-I$[Gr-Yd9X7JC< 4]n7ͯ+ʅs`}g)[UMtcT$)JPJj5 cHrG}53v0Ip}4qU~N'2Fe ,*֜?0+b`蘂QF"a"-H X5+uF-dv.]vw_s6 ҹQQQ,p/kd2yWKK.OjphU.rk - j!œ9>h~d5",73U@GHe$$?yOa:+ԝhnM7;0@ nMSWk @0T m%%j*Qv.FVq5 ԧI= Br=T;+՗0kPҮp:>3ÌdpuI)C`uo% mom{Q +R.:Sj٪0!m[$\_~Ca4cv{/ V'OJ',(ќ'M[+Z'bCx@YXMo~ OHX`,0 cM4L8FUW*twU? @ Ůn0_@\祉`HHkNO'p蟍7sZ퀋"e eYo,Q; >N8s2'܂/$1h;r.j:}H99AJ,QlwAr0;R+! LLߠյ +zGtGD/ /McrXHA+`# ÿ#dt#wG돬?4>%>#@ݑhbp0O1 M)M݋UNa0&@@rGfls/4r8A2t|RC"˯t3=^^9,N>T5щ % Y]O5H9{J&A6;03?8#Xs ܿ/Fy yGYeDX%|kC絿 !\D!ۏuӢ9ld"6d K {rBªn=o'@h%5xt1v71P3uCaŕ"6:[آZiozۻ%66QVY5N>sDIK;/ 3%2yXD 6!z|"F#6n!@(rQ;˾0W0Dx]kpq΢ʸIv%z\0a|_ivnU_m|`c(St qpD! V!k qY^)ZL"WTF]Ϩ&}AlIWUc=#: AAw ҇=qI=i;Os(FCt]Xz!xn=L%a) d)tv8nP5{P݃G4#3drc"9[|v9}M`,Kcg5'\^TfsWyu{`2k򍣢( 1^`8諘<6ۙ4d{~";d$w~USF7ߖZLYrt#!Uuq"k@t͡@LbXYù ť^KBriK`@400c\O=AT>-CY,s2iIRJ]6|w{xQ:8 ]Iyōv•C$;^Ѫ@#2y ׼iJB9*AK_5_ЊcNu2mzN-2_&1izivhOq?KeAQڳ{zg;ۃJOhӳZ녽ZJ ,|ۼ-OT_ѫ6!!):FH){}RjR#5(_YaV mb)P[@B/a!@O-;Ü": .V7~w~ط<}|{a";NjgEL_ UVC'V) 0! Np,n  q \&%݀-.s>/MI Q;#פJZ0!Pc-ta=ۃ>Fi*Ͷ-OHtۑ}/t,*ASF şl\x\kG{ 㤎~SzuꁞvZ.W69/<+p٧pȭ`P( ŤyVYW]I*}d*O^^*4 ⃋%%ɤn\sz;/'.Oh&[r\LR%Sgg#\EZ߲c;"PuU]0yL7.ǒG^Y(]'(rUSmGv4谞DY3 H׀߾Y鷝 8>tcXL y~N>nW{K٠*;:>5WQՙ(eV_mlӎYlp sa{jo=oSG뉿=T=٥.jJ]و:o=]G8n {.W*?Vе~>Q/.}EHu?op;!F@F ZMRTd, w!p_hg""d23̟)f*scN|$@$ϫ2KE@ )䆴?$vG?8Q*[y'e˥ݸfQ[2]m2~sMݿ!9Wј+x`E[h:r1XF W!Q+ =y| ]B} wJv#SL=? ~&&A,RHH?拹6ۯwtl&uv>-:u&6?U+&W 1rnj0֋k]gcOn<`nU쾧:}`^i+Ԍ͸[HSS޶$] jQgq-"v^++aL> Wƍo R3\uH*g[Ic~(}nOƤ3VV@.7zN[Wa-HQg88<$PH#@i(p]g8@|n7 Lꎠxy:4=xn[w?˝et1V#7lF%).w(MF]c BLrxһN)@-5 5NK˨' :( $⹬=@ZAYhS5x `Dv}_cժ#gW=6G6H{T>0q׀.RPSZf4q`Řh3|h(W%lo x'/*H c'yEmakxtm5Be Ǟ7%D TȄQT8 %G?6 `zR'XP_7f=!v/=fI@ 0WzFDŽb*5m5o2aJ)M-U;<"2T5dy γx)Q) }#4?tm]lԼ U}6>|(¬.#S"B{NEZNm\T -[E=ygĮ щ~P0vĐA`t>jGF{s Z_gY~F.&BTf{Pxz@Ǐ{0EЉұM%E*IY!:ؗ]38_VsN+\ҙ Kaf eF Sq\;4kr9d B{xaxG.؏:2{ԻY1;pk.ٹFV뼾=Mڰjx j6:{NРFy8}}N!;fERV0=&(~6lWy-j֤Hu藚njRt+jz/kLḅ=r,,4T JD;ؕk[bGDg}Y}ɠG\j6K 3R3}W݂HB#R;{ȣcD`cw߭M)krip=Sb!G(",2oIib&.PaE GEQ'ůZ25.2Ȟϡ@ՆZF}A\sIrBUxM$̶mDC"gAai4p^U6,#A܃Wׅfz)!ݖqPWՋ 5`>nvC߈:B)E- GJvo+oU\f~ٰf˻뺡>Cj)]Z5wn)'Y5nYMRF֯FnCu7pns_M1!&An }upqZg>.&aT!U7uܧqǏN{5ޭ ߯qQ>t49C[z{ϞNWƆ`BȩȽgq;B4e/ %eL:Hؘ=(jbF:7k9No4ٜs.|:;Gˆ :I87E+X&3#[BOG@R:5y/w[p}ko ??s;xlXR<^foۚvYkWn'05L~8,/́=O=ST1a{5|cۧ;C ݕX \h`ُMc0J1JP҄ @W{nWyUW}Rzʟ9ӲzfϜ9[[kXJE2-U)~oD]0)-iKGғꚮ\ le' iI &'9Erѕ-yS^B[>ȘvY .}0- +kFl6Nɲzf!'b'd'O|(fqi@!\3"$"!R9Ȉz[m#>/}V).BUkP}e1A4͵樝u,`!.HUm{tjUԗ+RT&ui@vbsJZ6:\cB'|L0RM$uBJTQ16j2~/Ďb_}! kpI@^D,ydɩdR9*5j+)>yn%]z =IW4$}}04sC킎7 C uLO!+)fFR8F#% žiNWa<,Ē6>{߱cM))++b|o|;FD1lcebcʄb…Åq xDp|b$papdpyBCǐ%gEܔzд/ ]a0R A/\4h/\,"q*' '$55\!4hO(F"JhT$1P$/F)'BaN&-4AfJBQ6QNZIacPTh 9(W{8jB!]NrgXjtdX$N{ H()rSjRƸt6GG|0 ΗBw)8tXxqB]z1I#1$&GDGzFe&SRR6ԛ6=f=rΉO/??70} Ngx LMNLN=&7mRvM>L~S'?ɽtTӣwxhG>SK &Np3/tb }-x5 ~ C~2wк`IU612V\F>oZ8"0Oz>m]im,,M?ymh4{ˋv٨{3X_4)Lyb "E9iA|LKՊ6i470偣A}k|A}FO~]R*NM9`msA PiAM{q2,]rd#2$:1D}T&%ub^~zx LIG%cI'lXhw7 pb4|T[K<_40rr?&;,;2ψf=0 &Ns9{R,$O ǒ}N?ε{ 1뾬ysA Et#X *Zd`%FXY"JJ>ᑁ65SWe (Hu-7m-H)'w! Bf"u>X'hrʣt!v&Jx|4F;` 9׿K&nPϤd s WZmXĕUVp'5p0M f U4.jsO x&}k2 P7g`٬X+3T_䖍gWwlVIYID{/y{ Sdy) MB|huPd/g%͹Ҽ:}SQw=#1Q5I9G0c'󸂞 '6zhJDG豲4t+Tk +;*jv?vI%HΆ[]7@5u,?%$O9r\ *7&E;t6Ud UҶ<~0 "O&5jIw*.FB&UKWD[/ƹ"ު,=v8,!+U>Kgthyђ +S/4 ,Q*z H9P/~ *(˸'E-W[ Jr Nrf^$v_$e:^mاArv32wXWM4ϔY/xM\ 9ϯV$ 6tuVl5 J,2voקEˮN(]7xlt NWijeyM(dD^ٚ?u5&lRiu$c/z ~qgN ;+y2)Ȏej}JGH aa8!`ʕ{{u8 @^h4ÍrՏȰc¸/SnoSHԑWQA Rd0*:Ǽ>kH-7~Ѷ{wvKpa/yx%[T scy$:W??k$D]*hr_z7s3! 09.̓T4$z$qG)L%B54So'+2o!"҆ozs3| fd%$h1t1с.:ol lNx`,n/FGO@A1p@2F@27e "jHa7#%l8XBbWYD5bei]x*4nqr;}@`[\e!õIqID<ijqLIlB8t x.'ˈspi!BoQa! zW՚`Y>)>\++q|*~=AjVZ=/6XN>xEN[!sŚj$!$rGƣbfHLe1^nzA㓁97QNd}~åP~ !8f/-kOт88PGJ5 op ?KNn@Qf}m'j^u q}_/HHtj q{zn1/]UL x%uQUΐtqf0F~0Xɷ}i{6C|qHf09"DTr{_z?Fizwf:>[W 2-,zhLJkP׭b!oyk=Ƥ=:\hl TQUċ07|l7l&FS,,zG8j 2#PÙU5g̶Pc AY RFm6<}}y?/DS =LYD-e.%3ok{m5) qӶ"{Iޫ2_v߅/Ъ_,Ŝ껹Էf?/eXv*%Fؕ?>9:'4{=-9  oa7oXD mqm M/エ+E,nwK;4?>n:Ťji.#sy8wh!`͟/PPbjs-&%B>4z)Qu}\A4l fV8[ x~4BN>*Cs$ @Y "w h^2Òoe GH![E% XSJD'ΣCi1+RX](WDc2y!BkeE 9.JO9k,3r>Nc)>&r؜ e~e]K UBꖕRi w2tQ8ŎnZAnDd!PŊ(֖_H̞}4K!wk=W m_,3O [>⫔kj cf80È+$l'(dyNtyIVy?iQu?lXqK$;ͬ2BD 3RpD=ۘR0[匆}dx|NhY,Q7a:Bv"a+o3 Rod"Zˢ?A>md!18A>AP4p%J 3bE2O$w!yMbfЯN8P "=ֻm ,#E?qSN6-ŬOܡ9t/ڐU:Fɘ )PEZ";AZJDS9SnsU.RX:O3 zl-Czx/ =8x|qp.$qڴ5ul>͚Vě)㐼CK pG1f=J1T:)JCVjt 'V$.~9]8{!_^##21=h= 4[M`gb$luP8i3N8t!$ !b#6u|C{ggٯ#{,ˁNYg N>)pG#@D Z6BDDNB9LĝZ͇08YdݙV g~wb?fX`ݝR){MX,2(pi3dnf+%2 ="j쟂6mz[%vfEK$vKXISvI1?Qz?tYVX)ޢ)iHrc$=[0dd?'.+(0n kfګ(ANP HRX&N>ڹ2Sx ew%,>W"m0lƭ?B&萲`@XxȽcN{2V~ '08 ~3> 'U-m ]ގc u\dk>K1;` XJ j`7EfJ:T!yaz ꦙC".n>*JPr6f.HzD[$΄&!ޔ޻ b|ZE|HD{pŰME6p4@Ppt [W+gR.vVcyj&\ΐYb=Oـ=`就;~ܢ#d*艁F{a$O 9m!8=ţ. ,S]qPȁ{RXeoܔ]&jj9y {X`KqoE1/FT E݋gwk..; vOƨD׆ ie*-X(TH;ty JdM ߠ,ZM_b`6XX]M&N\%VOΙ;0 V=0gHȤ=N8l6Qx^jA)Sʿ]DMcmoB߿zA F= >9,TqK5U򮍥+oUXςyyms\!Hr6 ^r$AOs^c=ʪ z% !s\T[b iR,^S ]}ɓVB(*B6֐v|=N{p5hBIV0g3-K|sD9灥I\`8n x 0c\`$1&F Eivæ[epQT<=ȝWC(g2!9ռ!oEC-+<@5VAMLqj'` [1/A!9J'R<=A(4Fd`MG ػ"izxyne>m ZWR4DUP!S\+SUs}̉Y! %ZhZ R9 zVyxnz)zȒB,DSbы>R[E87`ɝw`"WU!Jɭ *LPJnZq [i#>,QOԱ%Ae*:V6QHD!a uBxA.pj21 [߰v/28#%"[8ǚ 5~ {ͻΐo[Z_-&Nt֔E$3BGJ 4FzYS#X^fvnz]~md'ԨtohN,g|H<"BDKI]?C ;bYLIE3HM~zEݱӕ&&׷%-&7܆ k;. :Yfqp 8)Jj icivVWԙ 0V/ g'2#ʞeYvC\ \ԅ+M7$*ZLΐ͆icpqˈg5-5If.)/)DlŸ9lfdԾăo!Y$ 6:e>V  i3|xFܱWWZմ$Ԝb%Q2|2ǎlxLĦpJَ}lxf XcǔL+(j"(C1#}/K2hA4+OHocycA|K?-BgLnN,h-9R:H(1R6 ʜlt:'VtۮӛmLxC6POoȠBoXt+n,k]՗!X3=W^//@n6򯒽XwUʵ َOsN(`" ʓGZ9{#T1F>_pɆ51Z[+4a5y*iAb1bqůIUqA1q/뾥TJ&<8y/1}'п?_ݨye߼d'"[lgh:dfJ\.oL>_ E>fcWhv̹.7bj?< "8O<m*lm-&R EDN9R1͖Ѐ?-'JF8ckaiD]"r/! Z)2B칶5~J#,̛9F\̲'(,Uß=X(zD="ĵLJy٨OT TVR~",q1#>>BtLզ#רfpS8FH8쁓zܸ&4RC,&~ Pt23Rlb!-d4{CBZ7tW._n?/ Kc[=ӻaK=2]X򰐱A&`<٬M.4YS ܇K<| l7d 2XdI.6ɓ1YZ[D^3qN"Z0EMZ! q$I#,7\5ALGv O*p-R1|ch_[t)䊐Mm61! ؕ='Hf1I _Jق@uLݲ?@Of,D!B-]x3?R0Ƹ&w뢦Xɡ Ll)Djx;bôMinJVvj-txӐsfkt$h=ɚSjҨb` .%;|<5nIWb%< U-ef>'k ^@NeF#zV! ȃ/+n>βuAZ _"E™ a/ӕ3nfT*gdg-)aNMr3 j1B5V{[RU74;OΗFb Ԉ(n h^P9\%W~Pbʍ=!>g_uB| l)#Яi)DZ4.^+h<,*JMc kLlrExY_٬#GK(WM^ e#A`b@l%)̡K YSH)4tA 89t'g]ђHf"~-54+jmv,fCTgKyKw0cs7Wtu{FNNbFSi  M'$J?|7Xn]_5p +)'7\ ?c|o76y۠yN(PmRI?-b{0"Grʉ,wXݓV/ie戄|b)}cQϮ a,vNpN_*T!証H K1A ! —N$Kp^D@IŽ eN0]-QU8`ozV86lX&n*2 "5d|UM3HÓBIb89tP:\L{sm>hV& e՚kt2ta.lb`}`=o*cC* *[^?|XWV?9*~,sҚ}=bMz:4NWH27y8f"[pIZN (U:*n.X'b)db6nH#aUus?9"kN~&bǽkμK/O" yK,CE)F/hDe01ddKˑ[ft`VZ4XA}3$;cK8晉4*-* to\~ -rGuzZUEY\ښ!y'ysVѻ}E`AuAv( IHtTNp2d4;OX)SutIo]}ժJ?TP-!M_M`#N7R VMqq}9j\=L6i=q-!aJۚ=) b@F}n|$k}sΌNqԌ˳@D?yb,ٝzܟϱ̽8y42h#hk9HRV`c41[6BkpEAy7,Ò,=GBopb#М3fF)?OD 1 4 [[ ^m<ұB>v}gIMNВt@%z{X Bx Jv;`%G󻠵Gs3%ZS: g^EE'9VO57~8d,3OdZfB6{Ҍ+{γE*w?j+Dgҡ S{A) Yf)L˖јi [ϘeɠʲN6 j \G8>ngy 9mȅjN &#`9u j3-)> Av| ]w3fc{p:Pb t/":X:ItF0uzFWl9(|v~J-d.p MA*ͪu$"8L% eC9̢X 8K?ǥ /5*%+@sOj74>MeаE O֒Q}z]TbsIH jԿ R9IN?LbI3<-W+_SQj΃'ez.[ 8'(zoϾptiʒ,[5I=SXAPEf>%)+&-V%T5m^J&%~r"X4qdOq''e` 捇DkYȋXIhwq3q2 T1iб.賋+(@;i/v\?M'}Ц{n GL[$7["nfm\ĚMZ܍er]!maY?SDnݗvYow @<>@4j9='^.< ^0&L/;UZ$ }'+f!?`Z]QQG,c@RqYF`=̤wq C?hk1?cXc;;*Ox1Քh?ߑ7vo{aNg?HP٫hyO%7u7(r𲫸28x=Kց}voϚK%QI(TPG6yܯo y}{"?o}3<;xfeuR/su?jſb8AME,H[%$C9W[]Vo'$ zc33PW#Ἳmh#?GC譒>6\>ުk%9Uw\0-Ud5 k:I#q֓"yo|\1,=B%{@#*g/:gؚ=7x<6Y7㔭 |:5˛y;T[t.I?s=-շvoڄ,(\|@yodni.#X9j׬A~UyL`UALQ$ċsG=x _|.FM AbwG)c;_@g9Y"W?<}3W͍ٔGY2NޑH}dre a=6gDW̅L-ځ+~EF ߆zMYe%Y}bKMGD@>?o\&5rw-2^Xy/SQ`OĤbnkm^>])W>x˕㼳pj9kNXXKeQlp]$ EeOtb~?c{/ce4[jȅ2mX5ej&rM;1A.^Фi \(% Z6 ;a.)lUm\rj psc:uφJ[f쁑:3z菳SgZjRĸH~n>.3뿁(U<4@p/&>QK7B,Ϩ\EC?HT>6KCc9rbO%S3ɑ0= rbNT۫/7dPR(ޒ6)SO_ ? č.%vg3hrd!&?+0:~sF\^9HX "$v"~H`{ _\#p-4 spf #gl=B.sMaY+Wj|nBN| y/iCZ-q͜ʙmD3,UO}S^[j meh~+ż.B}+:bTjˡBST1bNtZLSÑWr-&|oj*O .%WWA]8uj To͆ ^ L6D^Ϝa'~E{=MMR}\avS:El_'@sQnGB--џ#JxxvلHv+Ɛ&5SC 8_dEX^^L x5K]W|KZ2F 4qrCvdw\NksLS#y1.4?i 3 vl:uD]\oi>REDجWͰ9_,d,h5鶆`[a5A/ܳ( MU!PuBxD/ރ iI2jXK&۔ɴdfIYs6IiLٵ˰1Hj(>f] @kzFIK 20-ARL%%,hĨڄ L-r!Z|HsI^Ĉ U&G KⷚE5, ?W`Ph.&FŵaҐ(&^ByHEOX; U|e sݓ\wP9Y҃J?l@wy-P`ƷvbwAEE|;n<{=Dһ\vtU/D.Iɦ9#Z&X{ @$E`ɸ82O Eĝ5x(!Ai4U4<꽫jQűaP|j >h7Y-dpeTeyi6| r$ ьC޼AC@l!#&RgkMJ*  Q c)\%äȏ iqJs\x >b1ki8fоPɐLEFJHyT+^@p J~=;"I2={\U0aVhϰafda6CXs,[N=޻띫J؇XBQ~4V'#)IWMvdgcscp[_r eS}]NA%{ ̓ATtBOJo.f+%f֊GQ%T@Y,w`EiԊuO@xz>LDH to 3;$כC&é}[QA}ZbIJG| ĵ%:W(5;[).JQ1 $qQԲ %%%,q$7`8d_o[uXe22HĎxj . b̴ٸ.V+T[׬Ft8F44ק'Z\XrRI,~i[2- Zvf?pw9uބvs,NQ'BEC\oJnSHCP^ޱWtJp%$R#!+.#PX#.SXkGds#>*CJ2"V.O$b(Kܖ!g\l\ʚ4n*&w--Tq>^s@͍bQg1]:ԉ6l5gӤ$XXX][ vK4\S6e(GZjw4FNa gj XMq\|EGMϘe{ju+p(uN5wE g0bxFڼ?2 ?O#1  f0Ndÿ**״/q:әljqԢzyl]E:73e|g#"ۓӮ(X@&YTGS(BSƻ[ i)9PY\[Rc. rX_/G?lYD1XG\rtC}\T,IM7VhԤ\_yO'շzxKH~4EBSғ(ix,5-))|HqKκFf3x4J nN IIX2ɱΠ$]Bbh5tL".wjTcrqf 5r}VVN\-D_TyDk~ 3e IFLiUqrz&TQ' 2+]P'h(mAThrq@KO0IQ|cxeK8k+fpYw] @7pq:Ohz dy\a${Pǧ]U.W)E,|PМ.OӚiL5˯EGhiuzQþ fI1{~Cv~ְ,E DƊ7Gw,wl@ܒ6hUK\v?&$W%6(B+6-4Fzl V]I|,tȫ Yut"NCCQ|Nd9$ xidcHYB-fa hWYK**eD,NP/S6i^u蹙ty^TX\ zT'o}G!œ$R"B㈻ҲM*t.o H)U@IV]:jR @uR.--bjZ,lSi `bvcEpk^փg3<Ϧۙ:O'Jhw]BLDZLj|\J7i_.99Ho߁4zԦzġi)WnW@?u&G(O/Ty%(npdz/&&vnڍ0e#9Ǫ/9(X|qDWhUrr?} XS}+g#OίIf;PVՃVOy1ڢhs#:8?'Z <܋LɝPN1{ă<@W\"up pG6Ɗ[|gTP#<%tD ;k,t 9?kNxI.lvi7^⮟{$!>șJ3=r:![Sg̜ΪJf5RR|JVI,nӆ= z ~WiDK_{׊r-U\st7opKpnLqI!3pk,dEJWIuX^#eutV`n0t  o/cT4'-f,M d.ctui You7N_L}\-#MdN$|΍: N޼!Y˯G۽C#D[ "WbϤΝP0JՀKlH"i6='+OhH߲)\^m\D`digtqkxb_hd - .}V! %9G[CΠw|#X58Ko|{ RndPr]~c"8iq$t]oӹvxW/dɏ}Ce'Ν(ʜ9y9|vO*޴܃M=ʸOrGt%+gi}Jƹ-D4pZci[fysg}C#݃1 ּz̑fg?} $`C43us`@3GHh>t62#dZK@ܒ) J7{;|[Zlcښ*aBGO&T[ӊ3׀e6!@b(rMEb`&SXΆI|^xr6ykxRsV'ĢnJtXlyvm+77 *r3U;֣rSV4h _WA.JO"+XuPS׵ ?dtK&%"Btօd܏H5;TTh㈚u#FO geƅNzubh5?YK+c @nƼYbJEԼyʺ* y؜_,o q4y}[([D{)pubx8ֲ }LvOo2HĭvO+0Q:>h q+u_1[i# :%N ~Jf:WJvKL:MsEE96pq[cx0EZBBSKvf7QN9CfbC|%x) K$̛S^ˌ +i[f[v ["~{9 3MMb#'U];V{-Kνjjs޼HNoiGT_ܦ'kB#f묂qzfe% 555%8g^[.5.:(lhdy6oۍfG}M_%9'pv}IX&Iא ӎG7lW~sCЩϾNӀ@pʶ8kn~&%+sUZ؛:w *%+$#9Fq1DjLn7a)@@9vDKm:,xu~,$UJ,'$#)bl"CRgZ a\倞-nrQ$)Q{ Gv= e˃ϥlxh!h.N,:{~eDJwr2WEn;a7CU,ftsC6I9ȧ7BԽ}GPny9zg`9'(t`By=DM+hz! 2ךwzXW̒SՃmK>5 LtR^A'|CGOq.>Sba!bS^D²*G~c-%:kpn,~3JK+m^oDc&MHePTJ ߓ) &L(51U@03=BO9WPrU TC=!rJ}v99k>6\ ivB9eQ0-!ѭԤ%U\3c[r$Qb7+dht1SnQ%;8']L$7dJ]jZWMi _i@dFtTB ڡUsa8fvE)ٞMDGS:tؔp.dhPh0rCSrќ4mzZ,[2wZm;t&&kG|.ٞ? t^99sޠ<Ù!8pcWpQj90xGr' (QwQCu ~c;oya?PfuikFr2@Kj83jh zǤ_@v{!HH鬨>-  }b+xBjGt )'eyJ}ȶg”chVMhV=/O[E`2@UEe(%h+.}պs\]e 7pu&ƻ& >J)8L.7F&$ Ff =tBg-gԚ+gS͵Cv*O4dpt8עlw/gt8,A⃴^,wXecy%S;l?x@ ЂABgISZnFL0ϫ+2*~Qqm6# [mêᱛဘ8OhyAcG[ij|4ԶN0g>_N#.lQ6`߲*`'.>%۬fl^'- 2^b3?^m^W@pL{K .'x{61pBn䴊μfGL4/65=GJ$̡S{$EiԔ-!OӹA&2[kwx.J/V rE)?,45+Y<0kNVLYt=Cݕ=YlN4PImh^vg^usHT&*2{-] 3٬Pwe t,)?b+*i5ztjYy@a0$|.vI< =  'u6vJOMpm=֣ҷb-L*枓 V[BPNWUR`t)Egy.P io8bqeit%.QV"O$&J^Nމ4n7u8Feϭ@9\ڿ 0($Ru1[w~kvaBK~asFf0G}52̒&Q[Wn0=•@Ǒ2&EmQyg'B{@}R"d)4Zph%ﶵ=%"d,hښl$2y(T=_wq ֔A&bhH8렂*# AgVr;E|:PuAQٝ1iZb1 SUpOS wLLr50}L6f؅y,Cꗽ.K!M2ye8@ lYOs?^o{FlB&\x ghͳgH_F8:dW9 HVc"WM~jCojo\O @VA]WٺSdi vjp[2+  SsxEjCKzF&s|_e׍Js._Ez|@8l,cK)gnҰ&IL< <:ӒПON奈1"yA9\!$URA }ce90'<C6HuOB7<xew8_ϣ9rnkV4'm/V(ϕ]0';12+K/+Sf486|͕ݴpVt˺oiNJ)9>fd MZp0 S' YջiGahW(7՟KJc00Ze}T9A*Ms8BV x|E4V *Arҧ(<@U\|ʹ|Ae2*]*') JtDP/^@xC >M.Տ!c*G]m ۫MPLj$5SwO;ns2DI,LmyiAmcg-G-s3՞*8ONɒOY|!<ٽ1l=7-FEz]Kj+Gz3]xUF fB76g*ÂsF  =-g.Fp`TҮ48&jȆ:IF3 .R.c?")Su;=5Ia"iH/+eƋ+Ed]1,Sx+nLW, *>$gPXןy[pI6d Fx_uܢJ0R$IK!JoO. 2ꧠ\>TFi``/R'Ed2cpvEd9EM& "Ls)($ ݟr-;'2\\7P(f$3|gQ>UW^6HףqLh9V*Mc{VHA _oPӫFn^-tAF59"sM)9(_ḶAZ":sAulr[h|rB$} P1Y'?/-zN"Y-ڈÓc#f 9Ci+<ۣk>zKؔnosmDxJw:7~(MwN(`̭\HH>6ުq׭PJv<2EhiDAF#A hNny մf\spUfQ$N9 jn.mR y<"N ϕ<21 q=qׄmhG[.LB\-WyRsk#П}?);A|(^cӮu>޶/q@KݮL [nsMM(h'Px @HǢ+T *ujKP@=@]ϭwה)&º.]VV5QJMO׳qWJ:-w ^WPba{ ppZE͛ǤɭvSY O#eaxWrUא }Ii*Afmز簉h,K>W[Dh/E?\9%*ݎSͻ \*sLPu2|@uCSf鮲]]D1d0=ޫZu(tLN$Gid8A Mf|J6 Q=z./%IE(RQ}MpF*EQ;A aqY9.7͕|+7 $8J ] 8H{JrOb:;8+F ;;K>T,t!q)]ђ2+ Q0fD3Aȉm%>t @@^ez. ƴZ\8w# C~hF#v\DR5P,6bjuI- *<:H(xXp;7]`S2ʲkGk‡TA:u c~!lWgNkMiYiSC~6苩k9%(VI喣mP>˨,-.{!# J]!Ʉ-zȫ-.?ϭjM35*3#t㒿BcجM[r:FQ(mmiW6JU"|\ EG2cʻ(G7|e.IkUzT0mt/S64^ݬUJ7v-9K6FwW4,vDw)̪ =4',Irr1/kDӶ:zQ(퐻u%pJç杻g*E.DNM%LG{n `|6f0o]qSҫP6vꅛ K Ƒx y W*5NC_ZvOSM4{cϬ%Bi(>^{VkVtneW'_5"_`Y3&Z(h LWhP6KϺ#8;L)tmm>ØI?z1B /hɥ)چI(0:l)w祜cfA >a?=)%/U; ֓Ԁs5æg8it^RH$Ǝ>3WW\!|jxe7GYпgm/$,ƍ)JK;#ocGERS}|h*YAƢK? x'1h(R929K/@Eb}֓()* q+é. p'd)G ٸk{7kPw*}7I4)٩R4Kh3pORpiV0ut!@Gƭmkx,) Wݤ3pQƢ*4jc3^SqChgqFd*D{oRt͇E`^6ŕTAL[7%FKc r;]_2 $ | >lMzU;wz\vgdzcz\9. ٻ07ɜW[oʊvw}eϷG' 2u3R'k6+`"a\4)!],XK%-LE =-xGվp?/w.:pvlA%­S`P\ur,CD{r}S}}ľzw 8Û7;SIeE.is~xn4N0tqK› " f@4+b*@]pDy@}(˳-a[Y8P_G%yA]BN\U,U^Z|֠@vltkc_r fv]VV919yb M4SniyZǦBbBZ*B=~P(4Z@b=ee߉rS5N?'w";v{εoZE 74nlK9F#ьRPx<[@W"O&hݬx<}{Jr } :*QFLM,viw_yj^&j$6]4ఌM>ۋ6j\GnqVZ3L~pk覐EPhSRϴn}\TM6įuelU>|^ϰZokp fp ;z}|bHʣeqنMVa.m;1PH{$}d K vZ_-N R壦Xૉ[Õ$߲zͭEF:y:)h,].e<~2ZXbOom}(|˳W!'UY%sρDi1Aʼn|^bpK2զW;*`iuueACR.5vdD-"=j* ;웶ivZIS|D^A| H !Bt͜ygҫL"/TY̒DJ5Ylz?ݯx-߭u#׸L \(E٤R8e֛T֖2ꈀ"K/ԑ t"P=.r \vj`L@Sh r>m=CNN. `/)RR{@` q'D!9-WJ2#Hw]~v0 r7&I.'971C3R@A*w6H 9&N34v3"&r86'qkKNv4t7]￧i$|O8#M $y8Vn%:!lR\MȊզ`rBt:=%RgbӬ.ĢAl<ؼ{FQSΑk<m]zW\.E|m\o9'niz+˃Rk,>z DBBT Y:wgdϛlu|wz֊ u>N\~^P҉^x7\+>v~:vyۅy9PQKWYj2/nH^HRj!I(8o7b?ds4<-z=yS5,Y⸭*8S@ss:nP0>Au^L(u ӆ3M}gg\s/vmiëDuf么MK|^fC̎vrͺ .4@뚣W ,U!Svgz=☈p .+/b]^e<i|*ndcj`0845UnjD<ڀ~E,$}&VԤr@r.}1>Êvi Ze&30kq(38]ntei27nU at`TE-G;rtXrGL#7x;@ c NE)ƁLyU-mK1 8RnPqNh'9<95wlia ];:S|EIQ0<=cezsgq33c^t@%{K$>YD4F8QB5J+34w."ϳ`C`dCqloKC6}Eţp㣺c6J*g|4o׽bnG]qu 5|ᰓgW1:ztŹ1 iܮӭ@C {3x0Y#9M£aq\b'+>^ı';-ש̽~efrZ-j9D,UC[;rh# ^nyovN>;Ik+2̋=lf&ӇQMij9{?aKJ<$c}R#}h!q>0’hV  Z ߅Q&]&QLM2uRY/*gG:8880 (LRm(r6*S3dM?.4bxoOSnɯm0958WL/ q˫ ?S{6i#ЖX _ΎAT}xߖyoտmNO{ⴴmȹ:wÐD.{} ݭ|d|ٚIwLmrfGcz ;Ä]DdZNȸ$M_ Eq!#IdUv7]tRq.Dsޞ9BV'A6ݸ/vηvrdvI }10U2spCΉڛqdȁENN[#ڹt i$Ȁ=Y*!wl(tyߺ}P\;Gups[ĭT׍ իc}|` ^FDg{xx#/O3 _Bw1('djڬx_ %k/=f"D }j@!@a%)(9 5bVIk[(e(xxgn@B.dR.B\se{c4I{-8BW{i" vndX K~Ԅtw(dsKIX{$ 4zk*]K XE7B7`Z]Jb-rz|H/nPǴw=jbifM[`h :qJJ;†raPԚGɅgrQneDmhMs_~iz+gf*-7mјch9g7R'C~*KKy•woNo)tqЊ?"!z/TÄe ¤wMEm7sZNAоK90AوL493s{al?0^iUl์ޏ\SHuE|q*eWlvEV9ftHYO>^ɥYe(Cˠ=He$~Fﲪfƾ.8ZGji7nsyZvOӐb!}!f9+a>HCEPuq4 -x-OZAns|sOL2+_-y*%Os*$֌Z_5bLxV23}>Ar@kA;[I%3AN\J:ues<Ҡ&.Qe*0'cL~Wͨm@ƌ̸d^a7 R65Kڵ댶1 R6Z&X 6دܝ!5oUFoMcЊZx+GKs? _Z5Sl%qhPvaKu̮%4~j]]d3?Am3+ơAMڅ_",!X/YqI;7+Z!l:cI0`)s݈mmOγڢI'ݙxw~r+*eҾ]'[{}J qUૹX.}\kj&o2sxcouגȯi˜59 kDZEӥW b)W}A{{eJ.yL;Ԏ72*놬L"mGr%txL?49bLvᅜ {Jffm+l9߭31/D.>< -ѧ{^Ⳉ1]H79_-ڠ^3(LZn=~od&l7c 4k'w8j]ˣNNP}|& .`O3FZ4zpvF8jHp02_h6WK$ j{;3%bpyY E$nc/z82t'ڳ=ȯ9jW]/ L{̔<իW=ツa2.-9WWʄ^AV *qx&9C"\]輲oՉBڋ xNg2Q]uDbߙ)ܫ+3dl%x{B92e;X .2lW]*/ェd` x_5}y<)9M4bfaDޥcD1ZudH]ݒJf#}pc):_%;[}vrف6ɧ[DpW,g,3X.亲yGy7FoHDAY Nmؔ,q:PKFf̮?M:էiٲt`ep%k1iFU"tVX50,*Y|v}*NQniyΗ*yf3$B6]0VL'%c|?:pj ?e1|hoR=ʣMx5w)}up"+#6k~: 3 +~=څrXd{тMDSc*m@Po50_e1Q co쀍DL{J☲ T $APA}j9Oksb7& 69%ސ,wiN !v_=y<((bXX8f%)n6`s+6>\ZÌceBb;SEYe9D3H[n vB/3Zg/2aF_5jߎ~;,Ր+pOq@*̸P PUpϼ-ݖA4hZѫ GOi.@+h+[g0:ۛj+.6Eg zK96My0(m7fiiP$qdlCPD)bAɎbyAR($HPe ^`] kp6NCsL2j[7)UvEMj' tz=Y!TF%ƎV:%dGbPbHI7}8Zp|jb(/DS ctʠH dv}AE y~N3M$Ba*횚ho &5A +JKb nm8Dq|8Ez<6)m-- %;40 V 9*cf(4$-}-?}t|/Kr֙oLLaMs>`5:W>R|Qj7S#B–яm7& E-$܅&F9jtnXIAe9hW% Y~skՎa?:+F,Bd BnggMEҀm>slϬS0KPVh j N:Z6 ֩y˺4{}U$#uD?͋A{szO71w4N%]ZCsk*.3(JMB2[+ѵDbQH8,ԤǙ(t G+xY']Yw*3[x(AБxYٽX$s5hE BN=| ^~ q.?6wn񗜾[8-yۉq[Z4xcsăm@(e S y7ZnO'p~'1XDaghDʮ;G'f }HdI !lYNAv6m>;ALh3ysۢkLHM|=Dʝ;-aX@s [ڪ3ܹ u*lАW=dCZu0A2S_v_|~BScϙt6H$꟣ϐ *!$o6Q5Tso`M?+ brVHI}6O Fxن{) B kA "_=UR 8 *tk YHN?6@rZYZ;$TQRYq֝G vGl͇-ҸwoV+b@hFpbm2桦hԐ.o.[኷;/Tt@z)4uxBR҃jjLBcC0sYaP&Ι䫳P&dS]i]0 bklgq~އn bA|eS)X/f:rf+C2T04."ˁ@˥ujtxkVpJo$%Rs} O7[8V}jZ2&(lL{C].TGlxGYDal딫vxp>|PT+2{`≙ ȱ d,z.Dh NEv K*\Ƕ5- KnǨֲy\~Dc'ms\ nf,5s;CGD]F _#g̴-Br9S: #Laӕs$J=AD\82_$!\1yJh­t)VZϮ.C%2)}qpL E`BXYY9kb"η./yktIt nb=6j֗7@ __I &q\.rF uBWeesOq{<1̀qP8H,m~d}ctzgj_2"d&uÁi4SK_ș` $u9҇>+gjucҗJ󕍬 }crm @ѫ36;0Y@&7XuPʘv?9]@\v|$y=-kV9C;"d(573M7A os> 8IˊxY.- |&κ|i v#djl_ E"Щp)Z4tAywq/( Ehǭ˫[~[9(ɦл{mKa {l}BuaD U 甇[f gjn.#RJFz 2@3Q[ZJTƪ1k|,q[rX!N0=}ܮٓ˒53&&mW~+{/^}L"v/?O_>䋑pDyo.ﰤv}NA&ds.06ᣒf"ZV`Mw,OuJB"`7f[2jg5pk_;S־r] !sI"?i{VoBou.ɗRG_LYL҉Ai"`E$]t!Z2orldѺ=^}+tYnb'*MB c*k,fg5]tV` ?z?𴭿|҈>q;"J@f 䧟~_=Υjl >@kn3ÅPYO]`x0`wL֑KMюϚpC.ϷG%蓆le1a~ױi ԳLp/!ÃxRe?~$\U"꽷~wxzN\Wq2{u{gMwۙy> RPT]G ߉4_YeT!;?)jIo^_7˨ei.w.^~! ѷcuׂ E!Γ$沔l[:bT#X gFwOkJ+@{ e$0 M9rT#O*1;T./Iy4p[pZr?@d "4ڐ{Ifq4E9ETfY<.唱[h0!4OJHP$D@UJ'z#ȆlPLJJb^E`!{ؕjañI@SIGb54z#Fi,̗#Lf&rұtt_(2`Z꽉q<14>k[c8qGYXxSz)əC'Oipg!>)<3NF[j61 *&v*4UYeP"H#bRqFQVYSAe%c) y^ZnR#űlc!RˏC^ "_c_guDC$"($[t{~\k]4`]nA* 2&:8໶ -8O0uӞ℡=g'H3} 6YVBc,rz>{3+ 9V-–4BI sf)r!2N`]{:$E6 EK;ڡ7ec3=oZ$~cy`{'} ^8%$ߒ/zSp64#w lcv

A8)c3^u iE3~0.vSgdhgKv-eV3d`}>5d2 DԺ+ 0Z}U3^v9*8n}Rm闁?|N߰/^|onT\AMv)iB*~!~@EЏǚߞ{tEx.7h:a@-PWskבOTD}өAX$/du%6r Mgb(->_x(0wowE+|l^,pCLqj7!jà3{h0>:^?CLA= ƅ"'c@5_"e|CuSC,x^C$~ Rf&)R wMwl}%]:%;S?Cxn9*z#G|b;c_eew~O[[&jp=1Z Z$4$Agq49nZM[bdG(!?H ,3|_|K{&Dzs\=艀+=5.sj?ciogRM;yh?e) xSnC,Kp(?6r9>y9NR pMa@4K)zῌ/s~?Ktra~vW U칷. v+;]j2UĪBۨm@>gD cL=tU%XJ-@鴱2J Vj;M5H.hU O&k30Le6bSiN( a;쪻@;@SHjz۵x[Fd\ w`Myϻ[q yatK C,ugH]Xu|v޻<Pb/Mup$#ؑ;NKКkJf5~-R:~+0uNy\} t=VO,BWw+t1q Y_I??| pHA]CvZuF9S' 3:HrZGvᆣZ=ЎȖI^BGU@kAiDVP+ڀ1U7ɛd55l!ƠV{?wF\GhbEZ^:,:;4Wwt:ߨ!ui7!`Z}N$Tur V_fzZW zŦlmBJe}'x2+T*jR\B@/g-sO*rE=&)ۙt,=9w :z11TƮ2".O/<_i>Kb_)vP{,?1u LU_e"AgRj Ũ{uHq PWڎǼpebȗq$+,?S^GS:_d3Դ]R`uܚ_f,S +)\eZ(H&.T==yR _}cwJ!ٞ>Ei^|)iҖ |}:9׋([Oc}ŶE[[ 5kݲuJpdD.%* +F3!>!^1 kQA’`]Ů0†ZǶrX4;h3 wiNÈP]dCrP!:^BO|`_q$7/L/H@{hH2FSSjy w Qu7'cwYxQkX =:I@߸}_!'ӣL$0 As$ف4a; aϋ]ܓML{  0VI@@7I¹jQL96͢Gٲ6tTֽke*USUjs4^4)SȾڴ\(X2A/ j۞zT)z x]FL !?u2F U/ *kb׸eU+N&Ħl͇d{&TA!kMUS??:Ty aTO;TS睊"[rU'B'y 8˼b֐*iAn=TODWHpZՕE6eOYQjI2`?0 %ULGO4Uidċdkueb:lXVL~]P"AmHf!wMXOxZi$%gxRr\$U%L͉G/q`@ -Y>(wg#O:-Yp[@A hٚVz+Ėu:FaPpEQ+V8 $IN4aQ'V,|2+"2QPy:,/fRLgRI8Uݴ]lw$m.|?Ёqq5[Nq|zv~qybO&Y:_,:(n_^eۑB0^NͰ/n`$Fv?ON/.8ۻǧ $a& aB4/u?Ku>ĔKm]`Vt=^BX"J#($E3,\SȐ9QЀf"6=k|  "ߒHOY%V$k`hd a@LB653G$R*W(1w HVhG'gW7wO/oH DBLBX"JZ FS3s K+k[;{G'gP$HerRhuzI  K+k[;{G'gW7QU jaZz>AIEY!L(B*muv0Nnq^~`8cLv\y~F1j$I3%j~i^| "> @,OdJ{G2{\.Ffk-,m(G'g_a&Rs{X?fzJ|):\ãL+8jD0b8Abuj576˔q@ 88aeׂ@ \|QHZs nDnB1P 6x0ۈ =`UHȕh8j(7.eT۳8o0h4+Q0H?l9O6I-`}[$ ѭzݷ7Ix1,G6"_%*@I U)ObESP{htr4qEx}E=su )TRSQ'2rʽ>x͗LTvmj_,ԻJ4tg^Z}$ H>~O']6=.كM4]YP!$NaN2j: M{[rf4B\ &FIj(P>a9BʞuLv<헵_YWz(7Aa:h[h ˟v:]DЮљ* jp(ՙ,iv}d*EZ5*-u~ǔ}hbdinҧ?$ EPƅT8EʸJ"L(B*m[0 Nn „2.:UDPƅT8K ͊Kti87IG@겆[NS?~GXsGc~4La鈅˽h?~"5t|fPRv䤍ȱT/4} 3b\LՆOis92iOW>պj:vs h|N +4r|B! A&W(ip\z"A&WTw6[O?v4)tpR/^pP""U=DV~غL.1_Cw2h茆oêPzQ4'm;@ 33nrB>g<}}Ԑ8ᛲ]o;?&Zx`A Iol滯 R9sԔ&}( =@XOh)~}ӄpE{TE71lj2@](·=!6elg ^@gGeK12 ]b&]gHh (Gƾv7Rz@Sf& D_T@6Uz p#я2vya9KRRu_m;p°PN S(id er~WWzyM/o'e\(mr!ĸqt')ëvʸJlџx:& .?TD0a3gG^4=Ol'=2)7DXA)Ql\4P zUQ@km*._yNWrAVLVLNwL^*{d"m' XqU VLjzpVLg wH=B=#G6 1"C&ש1Pr 4h`ƀFk ςqHBH }ew8tpߥn{րo^d%+6Yyc 7 To_&WIymm^qzCZ~v.Gčӂ_jNN&-Eğ?~R[~+\$*EOe7Sgk!q5%_@dlM/,|inc/fonts/OpenSans-SemiBold.ttf000060400000375264147177152050012435 0ustar00 GDEFȱ`GPOS^d8GSUB홗POS/2,k`STAT^A=XZcmap8l cvt =D,8fpgmZpgasp#glyf,7,OHhead4Y6hhea k$hmtxs)Yloca=OpPmaxpPt name4post&('jprep{@  rr++23|/01A#!4632#"&s0U>=VV=>URCCRPGGr+2201A#!#l('p''19@   ?3?39/333233233301A!!####5!!5!33333#8QROM9'PPQP9h]]ZZl.$,5(@..(, - %#/333/393301E5&&'5.5466753&&'6654&&'|LMjTgzoVIKLzm`^'SD:P($Ow)!$:w1jcfV+&&(\p M>*:.9$:(,>.S '3"@(." r  r+22/2?+2201A2#"&546"32654&%#2#"&546"32654&A==ABA@+A==AC@@裸J裸a%0<+@70& - r r1r+2++29/9901A26673!'#"&&54667.54663267"6654&uq`Y1@nT)Ӕ>dwG\2J'd:T-se9GgC7 r/+01A#654'37@h^@A_h@2x"8<%{Ln@    /2901A%'%7(©"y(m iOh7!m~`1  /33301A!!#!5!3pq+lI /201e#>78B"'! HJQGHL/201S5!H  r+201w4632#"&U==WW==U|RCCRPGG r?+01A#!JY:  r r+2+201A#"&54632326654&&#":7vjaڴk 1r__r32r``q1ܱfQQ{z}} @  r r++22/301a#4667'3="v/^Z)6T\:@ r r+233+201a!5>54&#"'>32!:"{nEzd_V=nm^xpVjmKE4V3cuvr U..@ $,r r+2+29/39901A#"&'532654&&##5326654&#"'6632P[zw[]^QEzxJyf.qShc]r&*.2yNd2=lH^i"4>V(o @ r r++29/333301A##!533!4>7#ogR.AAJk-]VI(S't)!#@r r+2+29/333301A2#"&'5326654&#"'!!66MxsHK`fO<-g7 $deÍx((*5<|_~ =^@"1@))# r r+2+29/33301S4>32&&#"3>32#".2654&#"^%Z,n$'].X ZVguהmNr{{T~E"Dfoڦ_ 2N/kʐxPᕚ}Hn9:vc<J>@ r r++2301a!5!> ΡX:.<@+6# r/r+2+2901A2#"&&54667.546632654&&''">54&IxI|MVY}ޔtPQErCz͕GwH Np=a}=h?=c;}OsYc&*mb{a^zel%)gYrP`|zd@bM! !ShV_Y?ZAA[@X_U8"1@))#r  r+2+29/33301A#"&'532667##"&&546632"326654.8%[+q$&_/W X]~gvؒnNox|V}E!DgGڧ^  0O/jˏyO}Gn9;vb=k r r+2+201w4632#"&4632#"&U==WW==UU==WW==U|RCCRPGGSDDSOGG@k r /9+201e#>74632#"&9B!'" $U=>VV>=UHJPGSDDSOGG`1/22901e51/#wf+ /3201S5!5!f;Aq`1/32901S5`#/2XwPn+@ ##) r r+2+23/01A54667>54&#"'66324632#"&"PDFS%sh\OS[Հ8mM?CU>U?Jna57PQ6UY4'2=ƢYk;2IJ4.RCCRPGGnNAO)@ILL%>r EE .5/32/323+222301A#"&'##"&546632326654$#"3267#"$546$3232677&&#",Z\Tp (fpό]6>*8M(Z yb]yCPdVn` F(dy7_XZBA[կx!e)aAcdj5%'0TAzp [I@ rr+2+9/3901a!#!.'Jя  4 jDd_c")eXp%@ rr+2+29/39901S! #!32654&##32654&&# ;pRUM~=uTW Lqb[jfh\0oDd7zr  r+2+201A"3267#"$546$32&&/ir<`Ė]^Ywّ\n[TLL$# Rm1-$4c rr+2+201A#!!24&&##3 cjJq۠ͪ q @  r r+2+29/301a!!!!!!<'Ls5 @  rr++29/301a#!!!!:&8z0!@ ! r r+2+29/301A!#"$54$32&&#"3267!"sˠTw]TJczbѦSt1"&*QQ/)#0 yA @  rr+2+29/301a#!#3!3A^lV rr++01s3Jbi r/2+01S"&'5326653 7S J*7Z5hi  *nda@ rr+2+2901a!#3667!9,Z-uE6l6rr+2+01s3!m@  rr+22+2901a##!3!#4667#7[ QPK)JqJ.C*=@   r r+2+29901a!##!3.'34 %;Hy3Bz r r+2+201A#"$&54$3232665#"UT1.\Z\ݩllQ# @   r r++29/301A ####326654&i;۠qR_L5t_|z%@ "r r+399+201A!"#"$&54$3232665#"X\  T1.\Z\ݫ3IlQ# @ r r+2+29/3901A2!###32654&[yPJ\ldyJ"|yjd /@,($r  r+2+2901A#"&&'5326654&&'.546632&&#" P5Yr]{74! 5Jl(rt--tr))@$)rr+2+22901A!.'!3>73>7   Jl X\ML[Y")_`[%&]aZ$_%\`Z$1~7Y @  rr+2+2901a!!!!; TR9W*9@ rr++2901A!#!^[/@[ @ rr+23+2301a!5!5!![/E̤or/3+201A!!!!o,b rr++01S#"J3r+2/301W!!5!!3+@Tr+2901S3#@xWJjH/301A!5!jnŃR=!  /]9901A#.'5`NT &^aQ!.pj&QYQZh(#@%%  r rr+2++9/33301A2#'##"&&546%754&#"'663265Zק-/d^cZkaSJLQ0bPzhPzǺghr r+2+201E"&&54632&&#"3267f|c8F=;a?@~\[@?zz'"V~zU,#$#gS$%@ rr r r+233+233++01E"323&&53#'#'26754&#"T~[  * [}|x!$-L/u20M.ͷg;h@   rr+2+29/301A2!3267#"&&546"!.arjZSx~o 5khz~)('$SH$B@r r r++2+23901A!##57546632&&#"!뵵YtL~+="T0PK `qEMI d`KNi/?K-@" @@ 99))Fr0r+2+2239/3929901A"&5467&&5467&&546632!#&'332%26654&&##"2654&#"w-AFFWifċG= 2/$&&K6{V6lPAd7gdgecggfU4>X)%qxY #&a95!!ͥ0Y=6:)N7LR^qgpprpequ@r r r+233+2+01A3>32#4&#"# #fH_jok}6y=t :K&U.Y| r r++201A#2#"&546w6OO68MMSS:GF;;FG:@  rr+2+201S"&'5326534632#"&94^ "@)AUGM86OO68M HeeXfG::GF;; @r   r r++29+01A3667!!#I!RE3y5#^#l$q r r++01a#3h'(@$%! r!rr r+22+++23301A2#4&#"#4&&#"#33>32366bd{+XCas2! "e|C|*4h,~Tq9X|S:K%WYZVuh@r r r+233+2+01A2#4&#"#33>jo}! $kh.ƼS:K&g|h r r+2+201A#".546632326654&&#"|HzrL죙;|bb|::|c,֓MM֊y[[yyYh(%@rr "" rr+233+233++01A2#"&&'##33>"326654&oDŽT|X ! Yau53wfVq8h,G*(a(=>/P/Mt!{Y^vgSh$%@rrr r+233+233++01A467##"4632373266754&#"g -nDŽ0 dx6z(^'Ic!cHLs$ͶOh@ r rr+233++01A2&&#"#33>B=?rX2 !bh)S|RS;b;ch*@' r  r+2+2901A#"&'532654&&'.54632&&#"j˓tJOXtf)okiJfWJKN[_.qecN13=pT*@")r* r+2+22901e.'#!33>7!3>731   &lsbbtn'S8v&S[QI&ss&"u9&PS @  rr+2+2901A!!!!  6{aHS@ r r+2+2901S!36673#"&'5326677 %%)wh2J@"?\@'S+SP(4AxlO 2[:hDS @ r r+23+2301a!5!5!!/4 ,%@  r%/2+29/39901A.54&춹4663ʖT:pRRp:V@\0qpqp0\@@f7DR&%SC9g? I?cv wc?I //01A3#ڳK%@ r/2+29/39901S5>54675&&54&&'523"K?[1ropq0[@T:pRRp:VI?-cw vc.?I @gDS%&RCf@`=1g@  /33/322/301A&&#"566323267#"&(If/9~32}L=v]Je-;}21|MV :RDDROGG#"/33/3301A&&#"3267#5.546675W6E@;b@A\\G;|Lcg}ˡ%!U~Q%!첼KW#%@  rr+2+9/3333301A2&&#"!!!!5>55#535466oKMAI^ot+C%;W0n/")gvNh?@lTXu#3J@#!(((  000    ?3/223333332233333301S467'766327'#"&''7&&7326654&&#"#x.p:;j0y$! v-m;j@Ak??kA@j>;m.w"! u-o<;n/u! u/l;@j=>i@Bj??j},@   r ?+29/332233301A33!!!#5!5!5!533HAnt!   /2/301A3#3#ڳFr6E@/!354.#"Toqtoa@9:2a-|z1t31gga]䇇]\prpp чw ]芃c^苇`:'@$$ r+22/992301A2#'#"&&54667754&#"'663265q)wKEf7LmjK>3k56;ckH6*[[ǁzBc3<.^HJ^0 :7 s)@..*[JQl# $@    /329233301S%Qce5^^^^`/+/33/01A#!5/+yHLdD *>#@ 5!r + r+22+22901A!2##32654&##"$&546$32'2>54.#"8 b?ɄjRWP[hoqtoa]䇇]\apt^RCKBprppu]芃c^苇`/301A!5! c: r+2201A"&&546632'2654&#"dVUeeWWdR^`PR_^:Sa`TTaaS`PS``SP``2@   /23/3333301s5!!!#!5!3`opqLl5Tx w?32301A!57>54&#"'6632!HN?52_5_>b2fO}TF[I)47,,y5BuAnrI0E)@  x#w?229/39901A2#"&'532654&##532654&#"'66fUK[`K?CD[V^gsihOD98a8U>}fMg oMx $+G?;CK639(&s.:R=!  /]9901A#5>7=R`^&!QO!QYQ&jp.vS!@  r rr+2++23333/01A#'##"&'##332665v# SmFIn$lpk|4S7L(3,O]-?XY|'vv /2/39/301A####"&&54663!vJ)}foɅC< `ڸ^7cR /29901A#"&'532654&'73&@H4=ZXT).M0jv  $+.6 V .ITT @ x w?901A#4667'%1]X KE-Eo>  r+22/301A#"&5463232654&#"ϳaSOWVONWVPfSqoqqonnmPl" @   /32901A'7'7"f:dQ^_^^PQ^_^^P85%6@" r  r+2/9+2/9/9333301a34667'%35!533#35467#M2]Wx~~Y 7JJ JF-Eo}Č?+f1b-B-&@++# r  r+2/9+23301a34>7'%357>54&#"'6632!M1]WHO@43_5^>a3fO}JJ670-EoF[I)48-,y5BuAnrI>l-8A?@1::44/>772.. r'( !!r+2/229/399+2/9/9333301a3"&'532654&##532654&#"'66325!533#35467vMJ?CC[W_ftiiNC:8a8T>bTL[a/x~~Z 6J: %*F@;CJ739(&s.:~fLg nMxƳ}Č?+f1b6w^+@ ##)r /3+23}/01A3267#"&54667>55#"&54632"ODFT%tg]OT[Ԃ9mM@BS@;WW;@S?Ioa66PQ7TZ5'1>ƣXk<2HJ4/BRDDROHHI&$C d r+01I&$vd r+01I&$Jd r+01IY&$Qd $r+01IO&$jDd (r+01I &$Ofm+@    rr+23+99//332301a!!#!!!!!!#5B5yjs5z&&z,&(Cd r+01&(vd r+01&(Jd r+01O&(jd !r+01&,Czd r+01&,vid r+01&,Jfd r+01sO&,jd r+015c@   r r+2+29/33301A2#!#53#!!3 4&&Kr1ϣso~IZ qY&1QFd  r+01z&2Cd 'r+01z&2v?d (r+01z&2JVd -r+01zY&2QHd 2r+01zO&2jd 6*r+01  $@    /3/3/3/901A'7{Gz|E~F{}G}GG~z%09@*--r)) ""  r+233333+23333301A#"&''7&54$3274&'3266%&&#"UlG`d`^1hH[a_b)(/uIZ((L.tG\ݩl**\d#Q+(\b޶pC oDQ <&8C^d  r+01<&8vd  r+01<&8J)d ! r+01<O&8jd ) r+01&<vwd r+01@    rr++99//3301A###33 326654&##:ٞ'xN^L"5v`z<@ .9r4 r r+2++201A#"&'532654&&'.54>54&#"#46632~:UU:"VKEe6db8"_k2b_ SKTb*8TS8jKwF⏍|JjP?;!.;2-^vRqK !'QH-AC.3VX7@YD>K4LP+`PxSGZ!&DC /r+01Z!&Dvj /r+01Z!&DJ 5r+01Z&DQs :r+01Z&Dj >2r+01Z&DO )V+44Zh1=E3@ A%,r!229 r/>>r+23+299//3+233301A2!3267#"&&'#"&&54667754&#"'66326632665"!4&&p4dWSt^,5sob^nۣl\QIKQly1;|]MMxEo 2chz)('$2cJHd3IsrPMhZ.#+6NSNSl^RK>zZTHgh&Fzg;!&HC &r+01g;!&Hvk &r+01g;!&HJ ,r+01g;&Hj 5)r+01!&C r+01s!&v6 r+01!&JM r+01V&j  r+01gz$4!@%$!  - r/+29/9301A7#"&&5466327&&''7&&'"32654.F9VbJ룘x؏HrV!sMV'V-c};;}b!DjI)pZx᝞v1%eGx4Ij^P7bM,u&QQ 'r+01g|!&RC 'r+01g|!&Rv 'r+01g|!&RJ -r+01g|&RQ 2r+01g|&Rj *6r+01`2 /22201S5!"&54632"&54632`3II32II23II32IIytAFK;;KFA@FK;;KF@g|"-5@&& r' **  r+233333+2333301A#"&''7&&5327&&#"4&'3266|G~7NRCII8FN@GK,1|H)b|:,oZtK҈*"dZlI΂Bn+.ķ;g([m!&XC  r+01m!&Xv  r+01m!&XJ  r+01m&Xj+ -! r+01H!&\v< %r+01*!@ rrr '' r+23+++2301A#"&&'##33>324&#"3266mĄT~Z  ZT~zwVq8,*E+?A9V(i0N/鼽#YH&\j 3'r+01I&$Ld r+01Z&DL +r+01Im&$Md r+01Z &DM -r+01)I&$PsZ)(h&DPfz&&vd &r+01g!&Fvb $r+01z&&J6d ,r+01g!&FJy *r+01z_&&N3d &r+01g&FNu $r+01z&&K5d r+01g!&FKx r+01c&'Kd r+01g&G4* 1V+45cg,*@ r'  ?23?33+?9/33301E"323&&55!5!533##'#'26754&#"S~\  {웛) Z~|w,L0&z,[;0M.°&(Ld r+01g;&HL "r+01m&(Md r+01g; &HM $r+01_&(Nd r+01g;&HN &r+01)&(P5g);h-5)@#&1 & r.r+2+29/3333301E3267#"&5466772!3267#"&&546"!.10( 8B,nv;`5Q[%ДrjZSx~o 5k,-  s_;m]"DeQ+z~)('$SH&(Kd r+01g;!&HK r+01z0&*Jgd . r+01N!&JJG R{V+4z0m&*Md & r+01N &JMh P{V+4z0_&*Ndd ( r+01N&JND RV+4z;0&*q+N!&6&J r+01A&+J2d r+01u&KJP !V+4'@  rr+2+29/32223301s#5353!533##!!5!^^1ݨl` u"#@! "r r r+2+2+9/33301A!!3>32#4&#"##535z#fI~^jok}6뜜h=s!:L&U_vY| ĢY&,Q`d V+4&Q@ r+01x&,Ld V+4^&L r+01m&,Md V+4 &Ms r+01p)&,PG)&LP_&,Ndd  V+4i&,-q&LM;bi&-Jdd  r+01!&JM  r+01;&.q;&NqNS@ r r+2+2901A!#33667oT9dSkSH6#F"&/vNd r+01s&Ov6 r+01;&/qo;&Oq9&/4 V+4&O4g V+4&/Np&ON @  r r+2+901s'737!XZ]m3mEQ @  r r++901s'737[Zf]8r'lD}T&1v;d  r+01u!&Qv r+01;&1q$;uh&Qq&1KRd  r+01u!&QK r+01)'Qi!@  rr/2++2901A"&'532667##!3.539Y#Q.Ba8 %hi  (^O1?4=PXvh$!@rr rr+2+++23301A"&'532654&#"#33>3210U8#8Lkmk~6"$jH^D He1{zY}S:K&UeXz&2Ld #r+01g|&RL #r+01zm&2M{d %r+01g| &RM %r+01z&2Rd '4r+01g!&RR '4r+01z(-@%"" r  rr&r+23+2+29/3+2301A2!!!!!!#"$54$"3267&&5q-<"H,q5ِ%lg3Z:r''p s5 TPKʀfSg$3;-@!%%74r,,  r+2323+239/32301A2!3267#"&'#"&546632>"326654&&%"!4&&utnZTyEA΂||@+tH9za`x99zo 5kgy~)('$ccbdf`@X.}WW|VTG &5vd r+01O!&Uv r+01; &5q;Oh&Uq &5Kd r+01xz!&UK& r+01d &6v_d 7r+01c!&Vv 2r+01d &6Jwd =r+01c!&VJ# 7r+01d &6zPch&Vz)d &6Kvd 0r+01c!&VK" +r+01;f&7qD(;I&Wqf&7Krd r+01(&W4f!@  rr++9/3332301a!5!!5!!!!THS{W(I%@r r+2+2333301S5!267#"&&5#5773!!9.Z%'|C^XM=T ?SiSTR<Y&8Qd  r+01m&XQ  r+01<&8Lhd  r+01m&XL  r+01<m&8MNd  r+01m &XM  r+01<&8Od V+44m&XOP V+44<&8Rd ( r+01!&XR* , r+01)<)@)r$$  r+2/3233+201E3267#"&546677# 53326652( 6A-nv?c4BW*rvG95  wkCh!Cob\N'gSr)mS&XP&:Jd 7r+01p!&ZJt 7r+01&<Jd r+01H!&\JT $r+01O&<jd r+01@[&=vpd r+01D!&]v r+01@[_&=Nd r+01D&]N r+01@[&=Kd r+01D!&]K r+01  r r++201A"#46632&&1ON\sOt*8"Qa_`^G %#@ !!  r/2+29/333301A2&&#"3##"&'53265#5754665Mt)9 K-MDKv,X;"ENU Z_lJrU RorEnDL*7&@ 0077%/33/3/??9/9301c&&54632#!!.'2654&#"5>7!$'hf*$Ŋ "! R3:=00<95B=EUV#T8jyxj7Un<hZ`"HK>8438832:MP";@;Z(4AM4@%% r CMMIGG)5/<r+2222/333?+9/32301A2#'##"&&546%754&#"'663265"32654&'2#"&546#5>7Zק-/d^cZkaSJLQ0bPz/>85.=>-Cl@fiq.B=h7V&6y56u5&bZ!.pk&"_77^#'jp.RU!@  /]223901A.'536673O&5w45y6&c[.oj'$_77`#&ko.R /]301A!5R  /]3201A#"&'332667Zi7]<3]? ZM8885R\ /]301S2#"&5467NN78MM:GF;;FG:R,  /2201A"&54632'2654&#"=hidf/=>..>7xkixxglyv;21::12;R)! /3201E3267#"&546670(!7B,nv;_6pEM,-  s_;m]!!AnRd@   /]33/2/201S>3232673#".#"R(AU2,QMI"'7{ d*QLJ#(7 FiG$"-"8;#,"8:Rz! @ /]33322301A#5>7##5>7zFYZ$FCFYZ$EC!PZQ'jo.PZQ'jo.4h /2201A5>73 9E$%^ea)2= #@   /33301A#5>72#"&546!2#"&546-=H%m /??/0==!.@@.2<<,hm3)jo-7<::::<77<::::<7^&$S#=jY'(S  '+S ~',S ;&2iS '<[S v&utS&T@ /V+444I$%)rr++201A!#)/@ rr+299+901A!5 .'k  ҋ,&a]\`%(@[=A+z$@  !r r+2+29/301A!5#"$&54$3232665#"DUT1.\Z\LollQ#,.@ r r+2+901A#.'## "J-wv+,vv-n01K2 @  rr+2+29/301s5!5!5!KVz2#rr+2+201s!#!c{J3Kj'@  r r+233+9933301s55!!"&&'663!K+"TQIJ= f7<c=!*!@"r# ! r+223+22301A#5.54>75>54&&{@=CNVUN˴b bd_m–XYfm[5\lgX;nB@ rr++229/33301A##".533>5B@޷>VއZ {ǎMGNw!~C7B}C'@r  r+23233+201A"!5!.54$32!!5>54&&"b7Kh -.M+"(SSF;SF4}$ v7-f{$3@"%1)- rr+2+2901A2&&#"#"&&54667.546326654&_`U`YO9{`zT젗kvFpAHeA{W[~C@.,9J3,KP3Arsk͒~#*czL!W{O|EHd|Th,@,,&r  r+2+29/39901A#"3267# &54675&&546632&&#"3 iAA~[wEFƂodlwtTNGbxw&J84F#5 !*{z be?+%-CCPDg{)@ & r/+9933301E#>54&&'.54>7#!5!R2$?&\]b^yXj.$}*Kcq;?YD0g_#)$niݵLlp4E^uh@r rr r+23+++01A2#4&#"#33>}^ipj~6! $khUBY}S:K&gp @  r r+2+29/301A# 463 2!"!&pig & wcb  Sr r+2+01A3267#"&&5LH/^%%yBaXSTR >S!-@(  r r r++2+2901c'&&#"5>323267#"&&'.'#.&YT 628s`)A)-$26A[= 1-~cNMr=D ,X?l#JHB=?vSw:S@  r r+2+9901S33653# # gz5MS&he!s Bf{<%@!!0 r+2333/9/39901S46675.54667##5!#"33#"#>54&&'.fMQEc5H[%`]!,AVKyONbq:R0$=%]^cai FjJVsK$GlIagE~X`d/F]54&&'.546WEFAAAqr:R0$=&]]_p<h&"ky@H`=ZD2jb$)&Hup{gT @  r r+2+23301A#"&&546$3!!32654&&'#"y쭝낔Mf;}d"C0;uNek\V7S@ r r+2+23301A!3267#"&&5!57dZL/_(&zEd_S\R >MfSSr r+2+201E"&&5332654&'3W$\Ubgf)!@r" r r+223+223+01A4632#.54">54&&CNYTXšjޝ{ >MfX/[dtg،Q 9Ņ # {<]q e|m[_&"@ r r+2/3+92301S233267#"&&'#&&#"566QdDp+H.=*/!H5YwQ H10 K_:sY&7C A~[lz^OG !@rr rr++223++2/01A>54&'3#.53tR'"$#ߤMi W{ %t)чLjpS0#@##0r )) r+22333+29/01A#"&'##"&&546673326653326654'(4]z# #z_3)@=lhBO#&O>G_0=AS`li^^il`@uP0Tt=Yt&j &r+01&j -!r+01g|h&RS !r+01h&S) r+01ph&S 1r+01O&(jd !r+01 !@rr r+2++239/301E"&'53266554&#!#!5!!!2 2]#&O**L1fxAuURi_;Ƹ)&`vd r+01z#@ r  r+2+29/301A"!!3267#"$546$32&&FbxH V?tode\y̔_`ZS7nhow>$# Rm3-&4d 6,sO&,jd r+01bi- f&0@'r0r r+2+29/3+201W"&'532667>7!32!!!%32654&&##&H73?+ &)q SxPq_ Ld<(n}R@bsYc(#@rr+23+29/33301s3!332!!!%32654&&##0~q yPq_Un}ksYc(@r r+2+9/32301A!!2#4&#!#!5G']nŹj]< &vd r+01 &3Td "r+01l# @ rr+23+201a!#!3!3#CGlI$ @ rr+2+29/301s!!32!'32654&&##|tp׹Py|m~sYc(%)` l@ r ?2333+201A3#!#367! !:qBvbE 9Tg9|lay@[sp( "@   rr+22+22901A333!#!/,<<? Z.@ #+r r+2+29/39901A#"&'532654&##5326654&#"'>32dŞʆŏ\?Eľ֮V~VmCsv`n')+y|r8hH_kD7.F(]@ r r+2+2901S33!#4>7#! 2xrYJ6~vZh&3d r+01  @   rr+2+2901a!#3! N<>  @ r rr++2+201a#!#"&'532667667! `  !Sq&H74?* &)WgPb Mb;)0A+z2#m3z&f7 @ r  r+2+29901A#"&'532667!3>7 /=š8p/-i4IaCY  2e.[B-+577:c=r;l @ r r+33+201e#!3!3@ rr++29/33301a##"&5332673{wqhqJ+1õPqs)' @ rr+23+2201a!3!3!3lg@  r r+333+2201e#!3!3!3g@ E @ rr+2+29/301a!5!32!'32654&&##jQt߾Rro|sYc(A @ r r+22+29/301s332!'32654&&##3r஡Mqo|sYb(cJ @ r r+2+9/301s332!'32654&&##u¡Tso|sYc(D#@  rr+2+29/301A"'6632#"&'532>7!5!.dPT`~X~_ecrxAZAq3#-1h #%32#".26654&#"ijvz 9w/^H `XexHPuAoNZArR%& [)R7tܛ~ZD}F]#[PoS#@   r r+2+29/39901A#!!24&##3264&##326Kufm_ͥ |p}xpbitw7`y~p_US6|RHK*A?CvSr r++201A!#vSfS"zS@   ?2333?301A3#!#367#!0ZTq? :[?Scz7!7|8k9zGS;S @   r r+2+29/301A!3#!#SC"Sg|hRoSr r+2+201A#!#oSgShSghF,S@ r r++2301A!#!5!fHS\f&%@r  r rr+++223+22301A#.54667>54&߲lJImlIJ   clmb  clPS[zS @ r  r+33+201A#!3!33czSfbfS@  r r++29/33301A32673##"&5v\V`RSySoXV4,1BS @ r  r+23+2201A!3!3!SSff{gS@ r   r+333+2201A3#!3!3!ǠSbSff=S@  r r+2+29/301A!2#!!5!!2654&^ e_ͥNmxSFGkiUMYSDS @ r r+22+29/301s332#'32654&##3ߜb^ȢjytRSFGkiUMYSESvS @  r r+2+9/301A!2#!34&#!!26f`ˣ|s iGkiUSSEMFh@ r r+2+29/301E"&'532667!5!&&#"'6632cADX[L B8B=^ꆄ!)Cl#+mlh&!@ #r r r r+2+++29/301A#"&&'##33>32326654&&#"lyՀӋ} 5r[[q55r[Zr5,pޤ"SCm|XX}|WWS@ r  r+2+29/3901a!.5463!##33#"5?mD~mi`O]WTWJ[g;&Hj 5)r+01 v/)@'#'r rr+2++/339/33301A"&'532654&#"##5353!!3>326.U6!6Jmkj~6윜h #fH^C Hd{zY| ši=s!:L&UeXv!&v0 r+01gh @ r r+2+29/301E"&&546632&&#"!!3267WFDC=Y|F B{Z^HAxr$ AbiF(!!chVLV&j  r+01MS(@! r r" r+2+2+29/301A32#!##"&'532>7#32654&̚a]ɣO;[\*B(%?6-$ihxSFGkiUh =7MYSDS#@ r  r+23+29/33301A32#!!#3!#32654&2ʛb\ɣKRhwSEFkiU SDMYSD u!&v r+01H%&\3 "r+01{S @ r  r+22+201a!3!3!#+}Sf{Err++301A!#!Ek2r r++301A!#! `S9&:C.d 0r+01p!&ZC 1r+01&:vd 0r+01p!&Zv] 1r+01O&:jid ?3r+01p&Zj @4r+01&<Cd r+01H!&\C $r+01R/201S5!R\ȽR/201S5!R\ȽR7L /3201A!5!5!5!LPP7s r+901S'>73' 9B"(! IIOGs  r+901A#>7d9B"IJ;}5A'7t   r+301A#.'7 !(!C9FOJI @  r+222301A#'>7##'>7(! 9C"(! 8C"OGIIOGII @   r+223301A#>7##>79B"(" 9B"IJOFIJ;}5A; '7 @  //9/33301A%#53%32B23V_u'@  //99//33333301A%%#5753%%NU21R++R12U* ||| /301S46632#"&&BqGFrCCrFGqBez88zeb|99{&'-WS | '3?K,@@4F: r(." r  r+22/2?+22+2201A2#"&546"32654&%#2#"&546"32654&%2#"&546"32654&A==ABA@+A==AC@@A==ABA@裸J裸裸WA r+01A3#`Wr+2201A3!3  Ql]/901SQc5^^Pl\/901S'dPQ^_^& ~ r?+01A#LJmL@  /2/233301A2#4&#"#3366zEHiQw#ytOMNwq[43A% @ r ?+29/322301s#53!!!!!!㢢B1> QҗLX),@ %%"!! r+2?339/33322301A2&&#"!!!!!!5>5#535#535466rJLGL^k} @2CV*d."%fv?gMJqJ_d .-@% r,--*.  r /+29/3/3333+201A ####32654&3#3267#"&&5#577:ڟ;8U<@;'M iBU|CI`K|{GK >o\U;|6+@300'* # rr+2+29/32233301A2&&#"!!!!3267#"&&'#53&&5465#53>ePT?HFsY=-x^fO><`,+*+VU #&dH""z棗#& c6%@0#*#r  r+2/22+2/2201A##"&5463232654&#""&546632&&#"3267+ ITPJHRTI]f6k,,)V&^ZX[9e(%gJguthirrGHshgnM#-"@ +'r r+23/+2901e2673#"&&555667466324&#"66|D[IveZ*`12^+JqeF58A/qlcmwYP  jLО:_qPVZL6%1&@,&  r ?2/+2/99/32201s!3.53!#!5!"&&54632'2654&#"T    C]R\TQJIRRKK38Jo78$SqSroklkklko!+@ r+2/323393301A33#467###!#5!#ɵi//a0"SVfkkCufH"@ " r r+2+29/301E"&54>32!3267&&#"yy]^,\EH0x&je/#֊B/L{o)LL(OG.;Q8D.@93'?-  r  r+2/9+2/22901a34667'%32654&''"&54667&&546326654&#"M0^WIIMF(7HK+H,Kf4?<:7=DJJ JF-Eo)C52G,7#5Cr8S>'`MmtooLc!#iTr'<3*66*1=0v-;T`9@45COU[I<.< r(' !!r+2/229/399+2/22901a3"&'532654&##532654&#"'66322654&''"&54667&&546326654&#"PMK?CD[V^gsihOD98a8U>bUK[`Kg4?<:7=DJ: %*F@;CJ739(&s.:~fLg nMx9C52G,7#5Cr8S>'`MmtooLc!#iTr'<3*66*1=T~"0IU=@ )*8DJP>1#1 r r+2/229/3333+2/22901a3"&'532654&#"'!!66322654&''"&54667&&546326654&#"TME/57Vgc[&IT";$8JHMF(7GL+I,Kg4@=:7=DJ8!(IQHL ):C52G+7#5Cr8S>'`MmtooLc!#iTr(<3*66*1=M[ 0<-@+17%  r r+2/33+2/22901s3 !5!2654&''"&5467&&546326654&#"MZByJIMF(7HK]BKf3@<:8326654&&#"5>"32>7&&g,.`φF$N~wK~&;mK/!&% /]3201A#"&&'33267 [P `k\o %gPMjoMRjt  /9901A#5>7070?$!%mq,)jo2T @  xw?39/333301A##5!533!5467x 7}C̺+f1bIC@ xw?329/333301A!6632#"&'532654&#"'y;$E057Vgb['IT#!'IPHM);Txw?3301S!5!ZBzTזz 1B'3@ '.! x(w?22901A2#"&&54667&&54632654&'"6654&uyU>KghK+I,'`Mmt,7#5CC52G6*1=<3*6T #'+/37;?CGS_ox'@,, 9955!!?3333?333301S!#%5!#533!5353!5!!5!5!#3#35!#35!35!#35#3#3#"&5463232654&#"%32##32654&##32654&#"'532653T/0momImmmm0oowoooommsBEG@@GEBno.,->m^{B.$*/;J1%&4^0  %1}o0oo/mmmmmmoo;mmJoooo/yhI\ii\\hhCS1C :EPZb" "+% * f$2re]T!-@ !%++//9/999301A 5467>54&#"663232654&#"TV*C;N'9yp.RD7?>5DLCQ<8SS84/TbC,".:/:G5=qP;H??HL==!&KM  r+01s6 ;G.@ #CC4#4#4- r</2+299/}/33333301A23##".546654&#"'6632326654&'&$&5466".{QAw[& !48/{G]] ^lnK͊RKQYʨ 7Od Rׅ:p9b{C.[S-! &cT,bh6Nqw3{vZWIEEuG`g5@rr r+2++901A>7>32&&#"#!["DD>AU:#< #6%MXX#K|-2A  <%_/%$S4-@((r $$ r. r+2+233+22339/01A##"&'##"54667!57!32655332654&&$(^z$$y++li`T'P>ij&SFKui^^iKEeSBIxTt=I&0vd  r+01!&Pv /!r+01I&$STZh&DS/ V+44gB  |/3201A"&54632'2654&#"Qhhef/=>..=6xjizyhkyv:239932:z+@ (r! r+2+299201A#"$&54$32>5332665#"US2U+2''[Y\ݩllQncOrE2Tu$gs)@ ' r r+2+299201A#"&532>53326654&&#"|죗nD8?Dzd :}bc{::|c,*HDPvGaq>W}WX}|V@ r r+2+993/201A>53# 5332665<:B2Yk}vEMxLNnK'ZRl")@r  r r++233+993/201A#'##"&&5332653>52Zk #kH~^io}:BNpK9K%UZƻ&wOyK@  /]29901A#'6654&#"56632XM LF;/"=M,M][ 2+)#  f&(Cd r+01&Cd r+01g;!&HC &r+01!&C# r+010J+@ *r% r+2+93301E& '33667.'3363 #.'VxH :S_. 1  7Vj7 Kj:X.YQCYķeEQHGts0KRI'jT(@(#  r r+2+93301A#.'#&&'33>7&&'3367j Tx'QGBg@ Kf1 %*=]4Be? TEK4h!3e#JL&^dۉtH $@   rr+2+9/322301a!5!53!!32!'32654&&##,"qsذRx2ʺo|sXc( '!@ rr+233+29/301A!!!2#!#535!!2654&b `ͦl}'ԸiUMYSD<*'@ rrr$ r+2+++29/33301E"$'!#3!>32&&#"!!3267vؚ !ls[TP\atG l?qkbc[1mY5,%77jdl}C$# h'&@r r ! r+2?+9/333+201E"&&'!#3!>32&&#"!!3267 ܉_;C7BXxA F~YYCAlܩ#SC]*!?}]kC)! #@  r r+23+9/93301A#####!'.TFրE! ;I> GqqKVRKPIS #@  r r+23+9/93301A######!'.`dё  22 "S;;S QL{xPR 0@  r ?333+29/9333301A#####!#3!!'.qE| ;D; Gnnn[GQN KOHS.@  r  ?333+29/9333301A#####!#3!#!'.ZZz  )* S%%$S@UR_fNP !&@!  r?33+29/333301A#.'##>75!xmo`%<\NN]:BXySu:^u8Vg2h2fW]W`< S &@  r ?33+29/333301A#.'##>75!VlH{o0E9=H-p{InU(SgM{S9=I"!J>VS{Njg#&?@""%##&  r?333?+9/33333333301A#.'##667!#3!5!no`%>\MN^;4#s;_u8Ye0i2gU]DhjЄS#&:@""%##&  r ?333+9/33333333301A#.'##667!#3!5!iVlH|o0F9V*J SDUg5?wZ=@$ /@@7/== +/RTWNNG r+22322/3/39/993993301A2&&#"326632&&#"#"&&546676654&##5326654&#"'667.'53>(8 -1h,Jkl%E\P{n:Q\gF7yUKVͱŶԭVwVnPs!TO0u4'Yn XD`r?0#+7LQYLw}o8hH_kD75M*ZT!m61bCUY[;@$ /BB7/?? +/SUXOH r+22222/3/39/993993301A2&&#"326632&&#"#"&&54667>54&&##532654&#"'667.'53>;'7 +-](tq_CmBg`b"J[Ina1GO]-.vMy?O^EFktvyPRJ<{GCB/l9'ZnY F9ldw =hR\Y-2,GzLWL"G87G"APDD%"$ $LG"e:0aAnBtz"@ r r+2+29/301A#"$&54$322667!"!&&UT1.Uc cgYݩllQoϑoIhg|h@  r r+2+29/301A#"&5322667!"!.|죗XtABvV* Bt,*EbbE]Av@ r rr++9+201A"!3>7>32&&,:.< ,Txa3O24hP[@h_3&MOT.W  ]@  r rr+2++901A2&&#"!33667>?'+]%$Fg] !=)SXI).Ch}6v&q d $1r+01!&r  "/r+01z !?&@?()":3-r"rr r+2+2++?3901A#"&&54$32326654&&#"%336673#"&'5326677rLJNKKO^ %')xh3J>#?[A'ݩllQ*RP(4AzlO 2[:hg h&R\z-8'@!$$$ r1.++ r+233+33301E"&'.54$766326632>54'#"&'P8I ےIH64GJَJD2.EqIH/3FqKKx59{:=--=̗|95?+"#*ݐ'*&&*ܐގg3'@%"r.1+11  r+333+23301A#"&'.54766324&&'#"&'663266kɍ B58A q @30B q+[G<79<jcem964:me,3445!1%%2ad+.., (&''{g)kC@#Lf rU\r #:3riIFFCGGCC* r+23/333+222/233+2+201A54>3233#".#"56654.54632"$546632&&#"32673326654.#"'6632#"&'*H\2;ptNbn[+33=<; +!A9BJF|IʁO".54632&&#"32673326654&#"'6632#"&'BKD|R;;!* @!;ptMcnZ,32*H\uCrЋPz2W,Q(lo%Gf@;]. ?E)Vw>pm'P,Y3zPrvݜr:;,NBd@G_Id-|ˆGh&"TQ?Gяrkt  //9901A%%'%7%7x FCzB CEttE?tcv* )7ESao@ IW-;le&/3/3901A6632#&&#"6632#&&#"6632#&&#"6632#&&#"6632#&&#"6632#&&#"6632#&&#"6632#&&#"]efblNL4=B5efblNL4=BeeckML4=AefblNM3=BhefblNL4=B7efblNL4=BuefalNL3=BdfckML4=AYhkV9!<%YhkV9!'66&&'#667%&&''&&'&&'5#'>7uDJ<_.ms_-nr6CJMUILO D#^( 63A.m,0.k-_(P3tu4UJ"( &/B.k-_73^72B-l3' C#LOUI-nr5DJ;J<^DP (-_( KUJ3tu4lx''@#   r r+23+2992201A#4667#!33!!"&&'332673  .P ak[p [l>5i?3MkoLQjgP{%%'@! r r+33+2992201A#4667!3!3"&&'332673D-Q ak[q [{0-qi!S-ol(Xc^MjkQRjgP. @r?3+9/333201A!!32!!#535#32654&&9ǠwbUn~Bɫ+sXc(z @?33/3/9/33301A!!!2#!#535!!2654&P f`Φm|GkiUMYSD7@   r r++29/33333333301A'###! 3267'76654&##`lg~0l?!3Zt(,v@a |_`F|h29@ r r r,++-**'' r+2323233333+++2301E"&&'##33>32'"3267'76654&T|X " Z~TULgvF^au53wf!{t,G*'i*F>/P/Hb Mt!{Ye.W/- @   rr++29/33301A!!!##53-cMo~ S @   r r++29/33301A!!!##53T디S>¶,&@  rr++2/39/33301A"#!!6632#"&'532>54&&e/hs}/@eTrdA?~HTV,pT / PS=ugd DS!#@!r rr+2++29/33301A!6632#"&'532654&#"#$M&}ԁGy9-w=u@S}w ZSl(@ r  r+233+22901A3###!33-?<<{S(@ r  r+233/+22901A3###!33DNDx;;NSx22=Z)&k}I)h&kl!@   r r+23+2901A!###3 N><{S@  r  r+33+2901A##3!3q#6V{2Sw #@   rr+2+299//901e#3!#3!~~pN <>S#@    r r+2+299//901A#%!!#3}^6#g]2S& @  rr+2+22901S5!!#3!&3MQ<> )@r  rr+233+29+01A!!!!##535T6#읝u2š @   rr+2+22901A!#!5!j:N> <3S @   r r+2+22901A!#!5! 6"?S2l-@  r r+33+29/301A#!#3!33F]llV{`S@  r  r+33+29/301A#!#3!33{"SCc @ r r+2+239/301s3!!!#!9^VlS @ r r+2+239/301s3!!!#!KSCd"`)#@"(&)r$(r/3+2+29/33301A6632#"&'532>54.#"#!#;8aSrfA>GOY.I\)c%f PS>tgg-  S#%@" #r" r r+2+2+29/33301A6632#"&'532654&#"#!#L:y~Ev8-q:q24S#{w XfSz=N,@B::%r1.. rK/3333+23+29}/301A3267#"&'#"&&54$32&&#"3267.54>324&&#">Hl7H&(F8=3CWC%=]2i`.mĂ#/I)7eUhi"E4';(#>&4P/ҕ-   30iY LЃv7dzu8^Է^J+PnDZ{,&|gh7E+@8?,/ r"")r+2/33+22339/301A2&&#"3267&&5466323267#"&'#"&54>"6654&&Y5e#3J(u?{[%."!4& kʕf8XШ729%h[l@-ͻUn&8+A-ͅr2U!D!,5T8mgg'/%@##++  r(r+2+29/3333/01A2!3267#".'.5467333>"!.?sq\TywƑU_F 25Մq 6ogz~()'$Aā/bM(M8+0eSHk,5)@!!((22  r-r+2+239/3333/01A2!32667#&&'#"&5467333>"!4& kʕf8O͓729%h[l@-ͺWn&8&:zr2U!D!,5T8mg{g)1(@ --) ' *r+2?339/3333/01E.'.5467333>32!3267#"!.xg_F 25ԅsq\F\eq 6oґ/bM(M8+0gz~()"!;SH, &3Ld r+01k%&3  r+01a+)@*''"+%r$r/3++29/3333301A2232#"&'532>54.#"#3667  eVqeB?MM[1S_9k.)Y-SHR9pme+ 76r6 S!#@r r r+2++29/33301e#"&'5326654&&#"#3!րOj0-d?MxFRs0[ (H{M|Q eS q l!@  r rr+2+2+201e!!#!#"&'532667667! `  !Sq&H74?* &)WgPb Mb;){(S@r r r+2+2+201e3##!#"&'532>7!6;[])B(%?5-#i <6A@ rr /3++29/301A#"&'53265!#3!AbB>S]lV S@r r r+2++29/301A#"&'53267!#3!uʀKr50q:mzS̸p!"SClJ!@   r r+33+29/301e!!#!#3!3A ]lV{xS!@r r+33+29/301s3!33##!SCc"l"@  r?3+29/33301a##3#"&5332673{wqhqley+1õPqs)'zfS"@ r ?3+29/33301A##3#"&533267fSy\V`RSz<1BoXV4,l%@   r r+223+2901a##!3!!!#4>7#7[ QPK)pvj"q6%nvf={S#@ r  r+333+2901e##467####!!H<A?x>|8k9zGS;c,I&$3^d r+01Z%&D3 -r+01IO&$jDd (r+01Z&Dj >2r+01Zh!&(3&d r+01g;%&H3 $r+01%@ ""  r r+2+29/301A"5>32#"$55!.2667!mÞ8<} \W/ kjzk M'94!kꫭiWFocda5hsO&jd ;/ r+01a5&sj 5)r+01 O&j4d 'r+01k&j ' r+01ZO&jd D8+r+01I&j E9r+01AN%@ r r+2+9/3333301A#"&'5326654&&##5!5+{^beK\: ŀr&*/2?tPMi5+S#@ r r+2+9/333301A#"&'5326654&&##5!5=rzQSjtJWuS/|ωހ'%'3OX_F&Ld r+01&L, r+01O&jd +r+01&j^ (r+01zO&2jd 6*r+01g|&Rj *6r+01zog|hpz=&ojR 8,r+01g|&pj 5) r+01D=&jR 9-r+01F&jy 5)r+01 &Ld r+01H&\L r+01 O&jEd 3'r+01H&\j 3'r+01 &RCd %2r+01H!&\R %2r+01O&jZd ) r+01f&j )r+01l/ @  rr+2+201A!3##/{uS @  r r+2+201A!3##uSSAO&j#d /#r+01&j /#r+01/C-&l MS"@ r ?32+29/33301A"&'5326655##53!!!!3P+H4 -씔T:tM  3)¶eCCA$@r  r+232+2901A"&'5326655#!!!3+R4! 2}; TR9d33#"3265db`cs*.hBזqpP8iKoq_Yqt#THFTečbzCO1n]Pi2eNf&3+@&r!''r-- r r+2+23+9/33+01A32653#"&&'#"323&&5"326754&6Wod\:ne]|S $lNQyX  ~yytqvipw}fb/'L71M- %-L/%x)Ǽ 35#@&&%% r.r+2+299//39901A232653#".54.##5326654&#"'>tsR-N9h_hs<0cgLxqAx8WmYb8W<r|*5jm>_A!?oFajE,*C'Dh3%@&&%%% r-r+2+299//39901A232653#".'.##532654&#"'66upn\Hf9)UEb\8ledo=C\psMNIXhAadw =`E3J)v|fb/(NuMEX*AQDD%"%+3l$( @ !r+2?39/39901A23##4.##5326654&#"'>!x4lpŎPwEx:Wm:\>!?oF`kF+*C'O{g& @  r+2?39/39901A23##4&&##532654&#"'66yso^Ck@DkwwQOK[gAbdu >iS;;N&APDE&"%+Z.@ .r% r r+2+2+29/01A32653#"&&5!#"&'532667>7_edaƀp Sq&H64?* ')h]s{*OqD6b Ld<(S(@'r! r r+2+2+29/01A32653#".5!#"&'532>7!]fa[9ldcp=;[])B(%?5-#|gcv|fb0.`i"i <6%@rrr r+2++99//3+01A32653#"&&5!#3!]cc\~nzi`r|*OlVS%@  r r rr++2++99//301A!332653#".55!#]d^[8kcbp<SC)hbw|fb0/`hf"Sz#@ #r r+2+29/301A!#"$54$32&&#"3266'!J{FL_VJȀlfѡGjdQQ6,#:nlgh"@ "r r+2+29/301A!#"$&54$32&&#"32665!.:ҘxQJ<^Mp?mQz͗R/&0awGzL)@ r r+2+9/3301A!32653#"&&5!5aRaddaŀpZi`r|*Or,S@ r r+2+9/3301A!32653#".5!5^g`]9mdcr=Sids}fb0.`h$c/@(' rr+2+29/39901A2&&#"33#"32667#"$&54675.5466qCqTxTU>[햿˶eU}"?.5Af`Hg7u|{w*'(kXbk^Th C/@(r r* ?32+2+201A"&'5326655#!#"&'532667667!3*S5 !1`  !Sq&H74?* &)W7!3*H4!,73'6673#3l45k3"MKKM"T)= +s8|#U00U#&[`--`[&/ZA:i+T#@@  /2/92201A5>73#&&''&&'53R"MK JM"3j64l39r- =(&[`--`[&#U00U#+i:A[/O(-@%""&@  /3/3392992301A#&&'#5>7%2#'6654&#"566KM"3l45k3"MK]jF9g A9.-' --`[&#U00U#&[`-GK:A G{"gR+%@++#(   /3/92/222/01A#&&'#5>7#".#"#66323267 MR%u9p55s7t#RP1W?(KE?*+ k f\+MD>** .[U&!O00O!%U\.!Ag;%-2b%/0S @   /32/2|/3201A#"&'332677#5667 ~kXRp EI#p!>UEJP#KE.d:S @   /322|/3201A#"&'33267'#.'5 ~kXRp <"o"JDUEJP:d.EK#S #@  /233|/29901A#"&'332672#'6654&#"566 ~kXRp YbC0] :0+$) /UEJPCF;< +f ZP &@ &#@  /32222201A#"&'33267#".#"#66323267 lVTo 1V?)KE?*+ k f\,MD>)+ L87M$Af;%-2b$0/)  /3/301W4&'7#"&'5326MECiwj(D8%17rA2}V`t  -C /3201S"&'5326655#53*S5! 2"32654&H> n~6iPxMbbX*e2H'"F4BSH KR)<[MYcT8&; ,T5TPDN'D+@ $$ xw?229/33301A2#"&'532667##"&546"326654&&ecX)eI;%p{6 eO}@SFI1I'!FWcU MO&@RNDR&; 0S2&@ !V+4444&@ V+4444&@ %V+4444&@ V+4444&@ (V+4444&@ "V+4444&@ ,V+4444&@ &dV+4444g5&@rr/2?++23301A"&'5326654&#"#33>328T K,6\7B')Yz=qg  )kamʌBa5i٪Oxo4i )(#@ rr r+2++2339/01E"&&55332654&#"#33>32KnB& )Yy~!uKmʌgBa5i٪&N %1%@ +&& /33/232/3301A"&'332673"&54632!"&546325>73 lXQq 0==00@@Y0==0/@@,(EJ#ϢMBHG8696696886966968AF%#JFN %1+@ 0&@*,,  /33/322/323301A#"&'332672#"&546!2#"&546#.'5 lXQq n0@@00==/@@/0==)+p#JEMBHG6968869669688696%FAFJ#a'@  '! /33/33301A!52#"&546!2#"&546#5>7y0@@00==/@@/0==KEJ#q+(6968869669688696"KFAF%a '@ " /33/33301A.'535!"&54632!"&54632"KE(,g~0==00@@Y0==0/@@FK"%FAᣣ8696696886966968 @    /33232301A#'##'##'5O,00,/0+M2@;;!544)((! r-r/2+2?+9/333333301A"&5466732672#'##"&&546%754&#"'663265~nvGm8q8N)/(!8BPק-/d^cZkaSJLQ0bPz)s_P|1!>qk8,-  ?554&& l; swWZu8l Us;IiC :{hTSn!$*,#SWS- 4Y~(SZ+OgS!&J Ar+01gS &M 8r+01gS&N :r+01+%@''$r r /22+2+232301E"&54673265#57546632&&#"!!C >.6@YtL~+="T0PJ P(D8&=?NWcqEMI d`KvSf{!/@ " ) rr+2+2901A#"&&54667.5466$32654&&G֚Be{_흖_jpmӚ{" IgKTwS7'Wj[\Mm;@ |} {?323301A36632#4&#"# "rF{EHiQ%E33sOMNxpm;@  |} {?3901A366773##0ܯ3U=H!9$Dm; }{?01E#3m;&%@ |{?332/3333301A2#4&#"#4&#"#33>32366y|@A[P@A?J!wBP,Po "ysNLMleLM5gJZ#,4673m;@  |{?32/33301A2#4&#"#3366zEHiQw#ytOMNwq[43m"#@ |{?2/33333301A2#"&'##3366"32654&߀Re}g+_OMdTRR୪9%;]+>shhpv|lkw@/Q)@ &"| {?32901E#"&'532654&&'.54632&&#"QLm039KCHFE]0}Bu901b2;>JB@^3bhz+%"$3G8X\j" !2H/g@  |{?3333301E267#"&5#57733#y:P,\|bj2`6_ k Y{e?2l31j #@   yr/2+2901s4667667!6676653!s ^D (!`E [?8]U*.BJ XM)Nu4-MQ+/6\4\9 @ zr ?23+201s5!4&'&&#"566323]^WV>'5lF\a;=Q fg  @0 KW4;< &@  ! z r+2?399?01W"&'732676654&#"5632#'#A%> Iw'1F(R2e_St$6)! 5(r >:)h@NZ #-[="E'.,   yr/+2301a467667!5!\%Z1N+^0S(.":l @  zr ?+23/?01a4&'&&#"56676632!3TTG-IԞ2b0M9s==Q$xdg P>.`>  yr ?+01s3 WK   yr ?+2301s467667!5!#6+$ ]=.I7>+e+>$} @  zr ?+223?01s6676632#4&'&&#"B-ZKu==Q]\='(hAN?-b@xjk 6@ %zr yr r+2++201E"&'&&'&&5332676654&'&&#"56632E52Z"-)--!b@Dg 0#!*#l@$ ?H6/H""!hH8XATՋ}:+.3/Atq?30$W#.-  %D <!)$9!<^ӻrEj#-"7DW  yr/+01S4&&'&&'3 EE}1  zDi " zr ?2+201s5!6654&'&&#"56632i ,'Q/&]7Nj$#0  -Z-K*EJ)!S06wl"4e| #<@ 11zr$ r+2+23301E"'&&'&&5466775>32'267>54&'&&#"oeNq$"D3]LP9>_!pNoEg ";4V2*B!KG'( f4'_Gfh1$%%sNHkXAh,?61+wH3 "S枂916A @  yr/+2901W576673>73A7gIqH 55#8&Oa;% L;)j:Lz5P^ /@ %zr/+29/3301A4&'&&#"'&&'&&54676676632p&%%lABu"%*'@'-%0]6/4A6I#_%) :0?$Fi'.)#C&.%09c+)D!#M>KiX;.O%&2,&mb%#j9>f =&2Lk5A>''\7!5!3     0SPY(!TUPWN&,  zr/+201a4&'&&#"56632YX8 *tz5]B=>P xfiO?.`>\ (@ yr/2+93301s36676673"#!267673#m:2_$( @@9jyBB46 =//}UK^ I ,$,M`|C>Cy|7rRQ}),$8 /@  $$zr/2+23/01W"&'532655>32#4&'&#";!//B?$G$iF^d)5C \Z,H!J)-)q PV  M;%]8xhj =d+8#\&#1Z )yr+01\ &$U )yr+01\&'!La#3Z 4yr+01\ &'!La$U 4yr+01j &ujR &tj &!\9 &!=< &!=, &!K= &!= &!>K &!> &!> &!1' &!M>D &!_>?&!D>e &!>i &!->e| &!n>P^ &!Kes &!iHO &!  &!a=, &!U>\ &!La8 &!9& yr+01!CoZ!v!J.Q@Lpd MR|N*9jO!R!K/! %@  /]3/2233301A#.'5##.'5=C"VVD463-174%2XW /23/301A2#&&#"##532>X2\H)8.,\obNup5^J(C3"-"$/$P  |/32/301W"&54632"&54632%''%&''&%''%&'')'&**&')*'&++%'+\ ".: @ /55#))|/3323333301A"&546323"54632"&54632!"&54632'"&54632%((%$))L'%%))%')#&((o$(($&''&$(($&'')''**'')P'*+&'))(((*&'*)''**&'*)''**'')+@  |/3333301E5!"&54632'"&54632j%')#%)(&%')#%)(]])(((*&'*)')(*'')+@ |/333301C5#5!#"&54632'"&54632i-%''%&((&%''%&((X]]V)''**&'*)''**'')N |/301G"54632K'%&))P'*+&&*  |/33301W"&54632!"&54632%((%%**%')#%(()'()+&&*)(((+%'* #@  |/333201C"&546327"&54632!"&54632%((%&((k%((%%**%')#%(()''**&'*(('*+&'))')(*'')D1 |/301G5!u]]G^ /01C5#5!#.p^]]N /201C"54632L(%&()P')*&')Q /201S"&54632$''$&**)'')*&') # |/2/2/01C"&54632"&54632"&54632%')#%('{%((%&((}%''%&)))'((*&')*'&++&&+)('*+&'*Q /201S"54632K'%&)*P()+&&*'0n /01C31a'GQ /201S"54632L'%&))P')*&')N /201C"&54632%&'%&)))'')*&')L|/3301C5#5!#2YVV)wTm{5t0us7Im8.~x;m91:'ypQr r+2+201A#"&&54632324&&#"Q7vz;aٵk tu2r``q1ܱffQ}}& @  r r++22/301a4667'3=#v/^Z)6TJL)@ r r+233+201s5>54&#"'>32!LznFzd_U=nm^ypVjmKE4V3cuvr S,-@  $+ ?3?39/39901A#"&'5326654&&##5326654&#"'6632zv[\_zCPEzwpDrShr&*.2>sQNd2=lH^iG->V*q @   ??9/9333301a!533#4667#f5AJ<_K'V&r'!!@ ?3?39/333301A2#"&'5326654&#"'!!66KxsHK`fO<,h7 $deÍx((*5<|_~ =pR"1@ ))# ?3?39/3301S4>32&&#"3>32#".2654&'"p%Z,m$&].X ZVguהmNqz{T~E"Cgoڦ_ 2N/kʐxPᕚ}Hn9:vc< ?33?01s!5!> ΡnO0>@ ()18 ?2?3901E"&&54667.546632'26654&&''>54&#"auQRFrC{|wH|MVX|ޘZz>FwINp=g^zel%)gYrPOsYc&*mb{a8cC@bM! !ShC@c9A\@X__Y?ZAaD"1@ ))#  ?3?39/3301A#"&'532667##"&&546632"326654.D%[+p%'_/Y X]~gwؒnNpy|U~E"DfGڧ^ 0O/jˏyO}Gm9;vb=)8wTJ{5Jt0;uJ7I98.:x;J918:':yh`jr r+2+201E"&54632'2654&#"apv~~@PӃj   r/+22301a#4667'3=&sg1aZ$6ORj@ r/333+201a!5>54&&#"'6632!8}j~81`GXPwj핂eFfZHaW96L)CC[UQh^zC<u-@  $+r /3+29/39901A#"&'532654&&##5326654&#"'6632Fb{`SaV{wyfXf_Vf_\ah(*+5{Pd02jT`c79JH.vj @r  ?3333+2201e##!533!4667#vmK?( yqQ9je/#a;7q'S!!@r/3+29/333301A2#"&'5326654&#"'!!66HwvI\eeQ:@b7!5i/`q*(-332#".2654&'&g^.`1,b8p 'g~Gdr֘~Bw|wJ~M$EcmGg w=T+m̐{]ϚDo@>x`:4Sr+23/01S!5!+ʑX:/=@,7$ r0r+2+2901A2#"&&54667.5466326654&&'">54&IxI|MVY}ޔtPQErCz͕nE>v_8Y:$@ !r r+2+2901A'#"&54632326654&&#">}{7vjaڴk 1r__r32r``q1o~~fQQ{z}}C;jDsjEZY#jFCuG\jHdSIV7JD)SKM/LB)jM)vwTc{5vt0uui7Ic8.tx;c91u:'vyHOM /201S5!HON-  /01S473#&N]^_^]_]^mrޛrgNdd;-  /01A#654'3_\a]^_^]ms%!ql;dfH  /3333301A5#53533#"ڃwwHL /2201S5!5!H77wwwwHVhHi'%@r r+233|/+223}/01s!2#4&&#!3!26653#! aC_eEcس|ߕMqDBmEq=W=3@:"63& ))0)r+22/322/3/3/901A33#467###"&'532654&'.54632&&#"ɴ~i>w$-v:HTDS?a6|71?#}*ko2%lq,H)S&PzS&t_/*Hd=n)O]9 &DS .N  0 i [  2 \ # > S m  [ T5l5qA tL]F@Yj&p2XxFXj|+>Pbt#6i!3k#7  / A T !!#!Z!!!!" ""n""""""""###'#9#K#]#n####$$$($:$L$^$j$$$%%%*%<%N%a%m%~%%%& &3&E&X&i&|&&&&&&&&&' '>'P'b'm'y'''''(((((4(@(R(d(p(()) )2)D)W)j)*2*D*V*b*n********++++)+;+G+u+++++,,",6,J,],p,,,,---'-9-K-]-o---..l./ //./@/K/V////0050_000111=1F1S1`1m1y11111122222d2l2t2222222363>3F3334-4@4S4d4u4445 5g556I667747<7778-858k88969f99:;::::;;;1;D;;;;;<< 4>h>z>>>>>>?? ??S?[?c???@@8@q@@A9AtA|AB(B?BvB~BC CIPIaIrIzIIIIIJ*J]JfJJJJKKKKKKLL@LnLMMMN=NNNO/OPVPQiQQQRR%RHRRRS"S.S:SdSSSSTTDT_TTTTTTTTTTTTTTUUV VVVW0WBWTW`WuWWXHXXYYY%Y7YIYYZ;Z{Z[ [_[[\<\\]>]^;^^^_3_y__` ```a anb'bbbc6cpcdXde?eeffeffg!gkggh4h@hLh}hhiiCi}iijj/jXjjkkll'l3lWlzlllmmUmmmnnTnnoooyop8ppppqq`qqrrOr~rrssbsssssssttt%tptxttttttu,uouuuuuuuuvvv%v8vJv\vovvvvvvw ww2w>wwxxOxxxyywyz/zzz{{d{{|)|l||},}4}}}}~~~(~<~P~d~x~~~~~~0DXl 1EYmՀ);M`sÁׁ);M_q˂ׂ 1CUgy̓߃VD}Hodž݆4bL`-IH1Y\U(t^JXU11@`f`-nJFzwCzqfbY_DLzLzfd@3@fRZggg$o;;;ggtc*(FhHD,gK`4Kugr'd:rQ`Hdmc`50R=v1T >rPH8->6JJJJJJHzwwwwqqqq5DLzLzLzLzLzLzVZZZZZZZggggg;;;;gggggg`gHHJZJZJZzgzgzgzgg5 gwgwgwgwgwgzozozozo q;q;q;qp;Gqvfb;Y;Y;Y;Y~Y;DDDDLzgLzgLzgzftttxfdcfdcfdcfdc*(*(*(H@D@D@DKZHZLzgfdcRR#RdRR~RRRR_1>?JFS/w@Lzq_D}KLzKcnECqg"Tg&Qf"Tggfggg  g^pgpw(SDzfdqqfb (! JFS w#ZUU! _Lzz cq-Dy1Zi"go(ImmP.gg,HfhB pyFg gc;;; H-oHRRRHA--Au S"WWQP>~MmAL;tc&M0&!ECf;0TMP/ :`d%s/````btlhI;1V1TTT;d]%_JZgmz)gwUgmy0'd - }/ 35(n^Mzg`u`u z gzQgn{lwy0'Dzgk**.V/ Z(I#!& 8]7z+gzg,LLr( ,]((q#o4 ; o qJZJZHZwg3a3a#oZ(IAJ+UmUmLzgMzgMzg-DF H H H YyV/ ghmgHmCf?3DL3O %7t9z4g,c"T 7JZJZJZJJZJZJZJZJZJZJZJZwgwgwgwgwwgwgwgq;vq;LzgLzgLzgLz LzgLzgLzgmz)gmz)gmz)gmz)gmz)gHHH gOTORSSSP*(LzgLzga@).'DNNaa$ $ $$$T=YDJwqpMw9*M94MMMIMw9MMM9M9w9M;;&g;PZg;GggggfMMmmtmmMm<m@jg\{<5,$<oW$'D? >e,WqieAPe:H,\X8\\\\jjjg\{<5,$<o'D?>eqiePeH,\X8<o|O *H8:KXDGL)T50I.;1'p&rLS*rp,na)T50I.;1'hyqRd<.qga4XUY}C}s}Y}C}}d}V}D}M}B)T50I.;1'HNN;;HHHHQW;;i;H 4 sX332@ (GOOGH ` ~01ac7Y #(  OP\_?M   " & 0 3 : < D p z  !!!! !"!&!.!^""""""""+"H"`"e%ʧS6<>ADK 12bd7Y#& PQ]`>M   & 0 2 9 < D p t | !!!! !"!&!.![""""""""+"H"`"d%ʧS*8>@CF~ ZHyu`{xYM geb^Qyj h(;,us N$!WhX_HL|dHI#$t   5\78x9:yhidfkegmb@J~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSQPONMLKJIHGF( , C#Ce -, C#C -,CCe -,O+ @QX!KRXED!!Y#!@%E%EadcRXED!!YY-,CC -,KS#KQZX E`D!!Y-,KTX E`D!!Y-,KS#KQZX8!!Y-,KTX8!!Y-,CTXF+!!!!Y-,CTXG+!!!Y-,CTXH+!!!!Y-,CTXI+!!!Y-,# Pd%TX@%TXCYO+Y#b+#!#XeY-, !T`C-, !T`C-, GC bcW#bcWZX `fYH-,%%%S5#x%%` c %#bPX!`# %#bRX#!a!#! YY` c#!-,B#Q@SZX TXC`BY$QX @TXC`B$TX C`BKKRXC`BY@TXC`BY@cTXC`BY@cTXC`BY&QX@cTX@C`BY@cTXC`BY(QX@cTXC`BYYYYYYYCTX@ @@ @  CTX@   CRX@ @CRX@ @CRX@ @@ YYY@U@cUZX  YYYBBBBB-,EN+#O+ @QX!KQX%EN+`Y#KQX%E dc@SXN+`!Y!YYD-, P X#e#YpECKCQZX@O+Y#a&`+XCY#XeY#:-,%Ic#F`O+#%%I%cV `b`+% FF` ca:-,%%>> #eB #B%%?? #eB#BCTXE#E ic#b @PXgfYa c@#a#BB!!Y-, EN+D-,KQ@O+P[X EN+ D @&acaN+D!#!EN+ #DDY-,KQ@O+P[XE @ac`#!EYN+D-,#E E#a d@Q% S#@QZZ@O+TZX d#d#SX@@a ca cYYcN+`D-,-,-, C#Ce -, C#C -,%cf% b`#b-,%c `f% b`#b-,%cg% b`#b-,%cf `% b`#b-,#JN+-,#JN+-,#J#Ed%d%adCRX! dYN+#PXeY-,#J#Ed%d%adCRX! dYN+#PXeY-, %JN+;-, %JN+;-,%%g+;-,%%h+;-,%F%F`%.%%& PX!jlY+%F%F`ab #:# #:-,%G%G`%Gca%%Ic#%Jc Xb!Y&F`FF` ca-,&%%&n+ #:# #:-,# TX!%N+P `Y `` QX!! QX! fa@#a%P%%PZX %aSX!Y!YTX fae#!!!YYYN+-,%%JSX#Y%F fa &&I&&p+#ae ` fa ae-,%F PX!N+E#!Yae%;-,& b c#a ]`+% 9X]&cV`+#!  F N+#a#! IN+Y;-,] %cV`+%%&m+]%`+%%%%o+]&cV`+ RXP+%%%%%q+8R%RZX%%I%%I` @RX!RX TX%%%%I8%%%%I8YYYYY!!!!!-,] %cV`+%%%% % % %%n+8%%&m+%%&m+P+%%%q+%%%8 %%%q+`%%%e8%%` @SX!@a#@a#PX@`#@`#YY%%&8%%8 RX%%I%%I` @RX!RX%%%% % %I8%%%% % %%q+8%%%%%q+8%%8YYY!!!!!!!!-,%%%% PX!ehY+d%%%%I c% cQ%T[X!!#! c% ca S+c%%%&JPXeY& F#F& F#F#H#H #H#H #H#H##8 #8Y-,# c#c`d@cPX8 g=<;r:9O7@6^43O10+)(O(\'-&%@%\$1#"!g @\2[87[2[87[>Z1U1UYY 2 U2U YYU 2 U2U_UY YYYo 2U2UYY@@T+KRK P[%S@QZUZ[XYBKSXBYCQXYBs++++ss+s+++++++s++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Mqmkz:xHzqmzkz:q}x~Hyz 8&  $  8 $  "0 R * (  BH > < " 4& Z l |     l      Copyright 2020 The Open Sans Project Authors (https://github.com/googlefonts/opensans)Open Sans SemiBoldRegular3.000;GOOG;OpenSans-SemiBoldVersion 3.000OpenSans-SemiBoldOpen Sans is a trademark of Google and may be registered in certain jurisdictions.Monotype Imaging Inc.Monotype Design TeamDesigned by Monotype design team.http://www.google.com/get/noto/http://www.monotype.com/studioThis Font Software is licensed under the SIL Open Font License, Version 1.1. This license is available with a FAQ at: https://scripts.sil.org/OFLhttp://scripts.sil.org/OFLOpen SansSemiBoldOpenSansRomanWeightWidthNormalItalicRoman2t  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`a  bcdefghjikmlnoqprsutvwxzy{}|~    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}NULLCRuni00A0uni00AD overscoreuni00B2uni00B3uni00B5uni00B9AmacronamacronAbreveabreveAogonekaogonek Ccircumflex ccircumflexCdotcdotDcarondcaronDcroatEmacronemacronEbreveebreve Edotaccent edotaccentEogonekeogonekEcaronecaron Gcircumflex gcircumflexGdotgdotuni0122uni0123 Hcircumflex hcircumflexHbarhbarItildeitildeImacronimacronIbreveibreveIogonekiogonekIJij Jcircumflex jcircumflexuni0136uni0137 kgreenlandicLacutelacuteuni013Buni013CLcaronlcaronLdotldotNacutenacuteuni0145uni0146Ncaronncaron napostropheEngengOmacronomacronObreveobreve Ohungarumlaut ohungarumlautRacuteracuteuni0156uni0157RcaronrcaronSacutesacute Scircumflex scircumflexuni021Auni021BTcarontcaronTbartbarUtildeutildeUmacronumacronUbreveubreveUringuring Uhungarumlaut uhungarumlautUogonekuogonek Wcircumflex wcircumflex Ycircumflex ycircumflexZacutezacute Zdotaccent zdotaccentlongs Aringacute aringacuteAEacuteaeacute Oslashacute oslashacuteuni0218uni0219tonos dieresistonos Alphatonos anoteleia EpsilontonosEtatonos Iotatonos Omicrontonos Upsilontonos OmegatonosiotadieresistonosAlphaBetaGammauni0394EpsilonZetaEtaThetaIotaKappaLambdaMuNuXiOmicronPiRhoSigmaTauUpsilonPhiChiPsiuni03A9 IotadieresisUpsilondieresis alphatonos epsilontonosetatonos iotatonosupsilondieresistonosalphabetagammadeltaepsilonzetaetathetaiotakappalambdauni03BCnuxiomicronrhouni03C2sigmatauupsilonphichipsiomega iotadieresisupsilondieresis omicrontonos upsilontonos omegatonosuni0401uni0402uni0403uni0404uni0405uni0406uni0407uni0408uni0409uni040Auni040Buni040Cuni040Euni040Funi0410uni0411uni0412uni0413uni0414uni0415uni0416uni0417uni0418uni0419uni041Auni041Buni041Cuni041Duni041Euni041Funi0420uni0421uni0422uni0423uni0424uni0425uni0426uni0427uni0428uni0429uni042Auni042Buni042Cuni042Duni042Euni042Funi0430uni0431uni0432uni0433uni0434uni0435uni0436uni0437uni0438uni0439uni043Auni043Buni043Cuni043Duni043Euni043Funi0440uni0441uni0442uni0443uni0444uni0445uni0446uni0447uni0448uni0449uni044Auni044Buni044Cuni044Duni044Euni044Funi0451uni0452uni0453uni0454uni0455uni0456uni0457uni0458uni0459uni045Auni045Buni045Cuni045Euni045Funi0490uni0491WgravewgraveWacutewacute Wdieresis wdieresisYgraveygraveuni2015 underscoredbl quotereversedminutesecond exclamdbluni207F afii08941pesetaEurouni2105uni2113uni2116uni2126 estimated oneeighth threeeighths fiveeighths seveneighthsuni2206 cyrillicbrevecaroncommaaccentuni0326commaaccentrotateuni2074uni2075uni2077uni2078uni2000uni2001uni2002uni2003uni2004uni2005uni2006uni2007uni2008uni2009uni200Auni200BuniFEFFuniFFFCuniFFFDuni01F0uni02BCuni03D1uni03D2uni03D6uni1E3Euni1E3Funi1E00uni1E01uni02F3OhornohornUhornuhornhookuni0400uni040Duni0450uni045Duni0460uni0461uni0462uni0463uni0464uni0465uni0466uni0467uni0468uni0469uni046Auni046Buni046Cuni046Duni046Euni046Funi0470uni0471uni0472uni0473uni0474uni0475uni0476uni0477uni0478uni0479uni047Auni047Buni047Cuni047Duni047Euni047Funi0480uni0481uni0482uni0488uni0489uni048Auni048Buni048Cuni048Duni048Euni048Funi0492uni0493uni0494uni0495uni0496uni0497uni0498uni0499uni049Auni049Buni049Cuni049Duni049Euni049Funi04A0uni04A1uni04A2uni04A3uni04A4uni04A5uni04A6uni04A7uni04A8uni04A9uni04AAuni04ABuni04ACuni04ADuni04AEuni04AFuni04B0uni04B1uni04B2uni04B3uni04B4uni04B5uni04B6uni04B7uni04B8uni04B9uni04BAuni04BBuni04BCuni04BDuni04BEuni04BFuni04C0uni04C1uni04C2uni04C3uni04C4uni04C5uni04C6uni04C7uni04C8uni04C9uni04CAuni04CBuni04CCuni04CDuni04CEuni04CFuni04D0uni04D1uni04D2uni04D3uni04D4uni04D5uni04D6uni04D7uni04D8uni04D9uni04DAuni04DBuni04DCuni04DDuni04DEuni04DFuni04E0uni04E1uni04E2uni04E3uni04E4uni04E5uni04E6uni04E7uni04E8uni04E9uni04EAuni04EBuni04ECuni04EDuni04EEuni04EFuni04F0uni04F1uni04F2uni04F3uni04F4uni04F5uni04F6uni04F7uni04F8uni04F9uni04FAuni04FBuni04FCuni04FDuni04FEuni04FFuni0500uni0501uni0502uni0503uni0504uni0505uni0506uni0507uni0508uni0509uni050Auni050Buni050Cuni050Duni050Euni050Funi0510uni0511uni0512uni0513uni1EA0uni1EA1uni1EA2uni1EA3uni1EA4uni1EA5uni1EA6uni1EA7uni1EA8uni1EA9uni1EAAuni1EABuni1EACuni1EADuni1EAEuni1EAFuni1EB0uni1EB1uni1EB2uni1EB3uni1EB4uni1EB5uni1EB6uni1EB7uni1EB8uni1EB9uni1EBAuni1EBBuni1EBCuni1EBDuni1EBEuni1EBFuni1EC0uni1EC1uni1EC2uni1EC3uni1EC4uni1EC5uni1EC6uni1EC7uni1EC8uni1EC9uni1ECAuni1ECBuni1ECCuni1ECDuni1ECEuni1ECFuni1ED0uni1ED1uni1ED2uni1ED3uni1ED4uni1ED5uni1ED6uni1ED7uni1ED8uni1ED9uni1EDAuni1EDBuni1EDCuni1EDDuni1EDEuni1EDFuni1EE0uni1EE1uni1EE2uni1EE3uni1EE4uni1EE5uni1EE6uni1EE7uni1EE8uni1EE9uni1EEAuni1EEBuni1EECuni1EEDuni1EEEuni1EEFuni1EF0uni1EF1uni1EF4uni1EF5uni1EF6uni1EF7uni1EF8uni1EF9uni20ABcircumflexacutecombcircumflexgravecombcircumflexhookcombcircumflextildecombbreveacutecombbrevegravecomb brevehookcombbrevetildecombcyrillichookleftcyrillicbighookUCuni0162uni0163uni01EAuni01EBuni01ECuni01EDuni0259 hookabovecombuni1F4Duni1FDEuni2070uni2076uni2079uni03B9030803040300uni03B9030803040301uni03B9030803060300uni03B9030803060301uni03C5030803040300uni03C5030803040301uni03C5030803060300uni03C5030803060301Eng.alt1Eng.alt2Eng.alt3uni030103060308uni030003060308uni030103040308uni030003040308cyrillic_otmarkf_ff_f_if_f_luni1E9EuniA7B3uniA7B4uni013B.loclMAHuni0145.loclMAHAogonek.loclNAVEogonek.loclNAVIogonek.loclNAVUogonek.loclNAVI.saltJ.salt Igrave.salt Iacute.saltIcircumflex.saltIdieresis.salt Itilde.salt Imacron.salt Ibreve.salt Iogonek.saltIogonek_loclNAV.saltIdotaccent.saltIJ.saltJcircumflex.salt uni1EC8.salt uni1ECA.saltIotatonos.salt Iota.saltIotadieresis.salt uni0406.salt uni0407.salt uni0408.salt uni04C0.saltuni0237uniA7B5uniAB53 uni0123.altuni013C.loclMAHuni0146.loclMAHaogonek.loclNAVeogonek.loclNAViogonek.loclNAVuogonek.loclNAVg.saltgcircumflex.salt gbreve.salt gdot.salt florin.ss03uni0431.loclSRB uni04CF.saltuni2095uni2096uni2097uni2098uni2099uni209Auni209Buni209Cuni05D0uni05D1uni05D2uni05D3uni05D4uni05D5uni05D6uni05D7uni05D8uni05D9uni05DAuni05DBuni05DCuni05DDuni05DEuni05DFuni05E0uni05E1uni05E2uni05E3uni05E4uni05E5uni05E6uni05E7uni05E8uni05E9uni05EAuniFB2AuniFB2BuniFB2CuniFB2DuniFB2EuniFB2FuniFB30uniFB31uniFB32uniFB33uniFB34uniFB35uniFB36uniFB38uniFB39uniFB3AuniFB3BuniFB3CuniFB3EuniFB40uniFB41uniFB43uniFB44uniFB46uniFB47uniFB48uniFB49uniFB4AuniFB4B gravecomb acutecombuni0302 tildecombuni0304uni0306uni0307uni0308uni030Auni030Buni030Cuni030Funi0312 dotbelowcombuni0327uni0328uni0485uni0486uni0483uni0484uni05B0uni05B1uni05B2uni05B3uni05B4uni05B5uni05B6uni05B7uni05B8uni05B9uni05BAuni05BBuni05BCuni05BDuni05C1uni05C2uni05C7 zero.dnomone.dnomtwo.dnom three.dnom four.dnom five.dnomsix.dnom seven.dnom eight.dnom nine.dnomzero.lfone.lftwo.lfthree.lffour.lffive.lfsix.lfseven.lfeight.lfnine.lf zero.numrone.numrtwo.numr three.numr four.numr five.numrsix.numr seven.numr eight.numr nine.numrzero.osfone.osftwo.osf three.osffour.osffive.osfsix.osf seven.osf eight.osfnine.osf zero.slash zero.tosfone.tosftwo.tosf three.tosf four.tosf five.tosfsix.tosf seven.tosf eight.tosf nine.tosfuni2080uni2081uni2082uni2083uni2084uni2085uni2086uni2087uni2088uni2089uni05BEuni207Duni208Duni207Euni208Euni207Auni207Cuni208Auni208Cuni2215uni20AAuni2120afii10103dotlessafii10105dotless commaaccent2iogonekdotlessuni1ECBdotless \7$=D]ll||ISTUUWXZeguw55JJMMORTWYv}~1335amsttuuvvz%oprs4\5 "%STttvv #" 8@HRmarkRmkmkZDFLTTcyrlTgrekThebrTlatnT8<@B4,V .8B48Bj!!!!!!r!x!~!5ttvv ST55ttvv%5 "%STttvv !$!*!0!6!!+D%%JPV\b%2"h#(n%2">* t%,z0H$/.%%/""%&%,& /%00#'f%,//#0~0.*),, 0.b    " ( . 4! : @1' F13 F" ) L"D" R X ^' d1'*"h/. j p&p&v v) |1&&" && /" 1/@ 'r (, // #F' -0r-0r-0r 0r+J0r 0r +\* .h0~.h0~.h0~%0~-~-!$......!.+.! , #0#0#0!0'x/!%!!$.t..t..t..8.+P.!*.!0+h*!6.t.b.t.b.t.b+P.b'~3'~3'~3'3!<2"'*......!B.,.!H1h#"/@#"/@#"/@!N/@,L/!T),@/!Z0r!..0r..!`!f00!x%!~)!x%!~)!l%!r)!x%!~)!!,,-~-!,d!0~!.b!0~..b!0~!.b0x!01.h0~.t.b!+!+!+!!!%!!%!!'*!3!3"311""","'~3#"" "&$x)",">"2"%2"8"D"%2">"D"%2">"D"%2">"D""V$#"'*0H"J1"P"V$#"'*"\"b0H0N1&"h/./."n."t....."z"""""""""&""""""%,"&"%,"&%&"&""%,"&/"/""%""/%/""0"/@"0"/@#0# /@#0#/@#0#"/@0#(11'T'f'Z'r'x/,L/$ /#:0~#@#F#.0~#4#F#:0~#@#F#L#R#X#^#d#j#p.#v+\#|+h., .1h%&#&########+#&###0$0l0r$(% %n%t) )0x0~$#0~%%$/.#(##%,0H$##/.$%3r%%##/%//$/v/d%,(t(z0H$$$ /$-$-$$`$$0$$*06*~-$0*$6$<$B$H$N2--$T$$Z$`$f3$l$r0$$x)$~$$$))$$/.$$1 $$$$$($$06*Z$0$$(($%$0$$06$.%06%%%0~%V%\%%t(% %&%,%2%8%>%D%J%P%V%\,F2^%b2^%%h0l0r,,0)%n%t*%z0x0~*N+%+%+%+%2^*%%,%%/.%3r%%* %/%(2^/v/d%,+z%*6,X%%%(%%%,%'*&,& (2&&0.&.&0~&"&&(&.0.b&4+&:+&@+&F+&L)&R.&X&^),/.&d&j&p&v*)&|&//&&(,//"&,d&&&&&&&,&0~&,(&&*&+P.b'$&&&&&&&1''313' ''''$'*'0)'6/))'<'B'H'N'T'f'Z'r'T'f'Z'r'`'f'l'r'x/,L/'~3'',''0l'0'/, ''0'1/@.h0~'+.t.b'+''+8''''''''(((((( (&(,(2(8(>*~06(D(J(P(V(\(b(h(n(t(z((/, /1h)(((((((((((((((((((((()) ))),)",)().)4):)@)F)L)R)X)^)d)j)p)v)|)))2^)))2^))))))))))*f)),)))))**2v* ***/*$***0//++//++*6*<*B*H*N*T*Z*`*f*l*r*x+,X*~06+,X*********+*+*************++++++ +&+,+2+8+>+D0r+t.+J0r+P.+V+\+b+h+n0~+t.b+z+-0+++0+++++++++++++++++++++.,./, /1h,, ,1h,,,",(,.2^,4/,:2^,@/,F2^,L/,R,X,^,d,j,p,v,|,,,,,,,,,,-0,,,,,,,,,,,--- ----$-*-0-6-<-B-H-N-T3-Z-`-f-l-r-x-~-----------0l.0. -0r.,.-0r.D.-0r.D.-0r.P.-0r.\.-..t. -0r-.-0r-.-0r-.-0r...... 0x.n0.z.&0~.,.b.20~.8.b.>0~.D.b.>0~.D.b.J0~.P.b.V0~.\.b.h.n.t.z.31././............................/ .../ .../ ..// ////"0/(1/./40/:/@/F/d/L/p/F/d/L/p/R/d/X/p/^/d/j/p/v/|//////////////////////////000 000$00$00$00$0*060*06000600060<0B0H0N0T0Z0`0f0l0r0x0~001V1\000001\01\01\01\01\01\01\1V01V001\0001\1V0001V1\01\1V1\01\1V1\33331,1>000111111 1>1&1,1>121>181>1D1J1P1V1\1b1h1n1t1z111111111121113N1113N11111113N1123N2 222332"22(2.242:2@2F2L2R2X2^2d2j2p2v2|2222222222223 222222222333 333363$3*30363<3B3H3N3T3Z3`3f3l3r3x3~3333333333333;z)Z`BlP>DJFLRXZ`flTLRX^dp2' }!!!HH VSPSSCS'SSSSSSS}SSS3SSSke`Ubtb"::"=.6''#\C{grAS>S~*sSN)S*tT!g**S?SSs*SKSSI*SS!SDS]S?SSSjiY #Y'Y,OvRSKqstS~)_LL!mRmlm_Ri)99l9_9+;!5 Ys ;$K;5m;m#;;#?S?S'ls S;;F!C;;CdYl !)W_W!jJR!;;40&W@@SS#)^OhOhh&h})S)<SqSl 5 &SKSN!NS{SqS{S}SFcSIS&}sh}hIhGmOF5 il*lpA<vC} l99N=pS{S{z4SSS%gSpS(S(SS S wSSS7SiSSjSjL! S S"tStSG!%%88D!ODD^!]!RrSn+!V'##NSNeSf=S=%%^S^nn?ZUYY002S;!;SS+x+l%{ttkkzz~S~,DSD lqSq{ww)S)llSl{GSG)KSl{SeeS S)LSK)Cl S {l^S^{lS{lSzS"k"S"{8%kSk lS{S 88lS{lSzlVSV{ORSmR% OOO88wOwZZ&S&++O+'O'='s=%O%%!O--lS{O==,,CSMCaM~~5S5_WSWlaSa{SSSSxxOS  CSMJiRXRfRRlzR RzmRmYRmRmJRmiR`mizR!`z"z's's'Js'i)sp')zs!pz7!77Y777zSzzrzrQ!QQYQQQzSz^^z%S^%^Y^%CCdI'sS'))sp)FSO&&}}g##imiJoSssYssls)s_isszsOR)RS`)")Sr)qSSq!q qa;sssUsU6U6U$UUO?U?,UU+UUUPUbUUH#UU+UUUU+!UU0UqUqruUuu+ UUN]UlUlmMUU+UUU UUeU U YUUlPYU'U&9&)S&z2KMG7 z*DFLT2cyrl>grek6hebr:latnN'\dLllt|V` $,4<D aaltccmpccmpccmpccmpccmpdnomfracliga lnum&locl,locl2locl8locl>loclDloclJloclPloclVlocl\numrbonumhordnnpnumtsaltss01ss02zss03ss04subssupstnumzero0XMKD SRB dAPPHCAT IPPHMAH MOL HNAV vROM  ^b,PNLJ@>dB "    !$%& #$%     &' ;} $ ( H  HI#$l|l|4hropsVrZH@.(  jnrvz~ L         dfhw{tu78x9:yiN0123456789DEFGHIJKLM0OPQRSTUVWXOPQRSTUVWXDEFGHIJKLMegjYZ[\]^_`abk0v"0>LZh$*06<BHNTZ`flrx~`Jl|l|HIops#$&'()*+,-./AFN~DM:C/O:B(.4dnx mn_s~$2DR$D2RbdfhjlnprJ&/rtvxz|~LM55tt 34OX 09DM 09   Q  KNOPQSVW,-Yfv24defghjikrDEFGHIJKLM0O1P2Q3R4S5T6U7V8W9X0D1E2F3G4H5I6J7K8L9M{'1;PZt(2<Q[u)3=R\7*4>S]8+5?T^x,6@U_9-7AV`:.8BWay/9CXbw&0:NOY  QQ  09DMOX&J$,-2DJKLMNOPRSVW 34Y_fsv~245mn:;<=>?@ABCyOy/ILOILIOIy/yO }|{z~!!!!!!!!! 34opqLrL $(,28DHLRX,wdthwghtitaldXinc/fonts/OpenSans-SemiBold.woff000060400000234470147177152050012572 0ustar00wOFF98FFTM9EcGDEFc[GPOSX LaGSUB,1OS/2U`|cmap tYDcvt <=D,fpgm Zgasp#glyf"%Rp=Ihead564hhea!$ Ihmtxh ).locajmaxp lnameB post'nQqprep,{xc`d```fp-ˊ$7K#ȅH2W fxc`d`Kw_A.Q2`)Vv_/Jxc`ajraf:`4 <`` djxS7|6 !xX pU]s}I  |$B*[B (QюӐ #HBWlth5i-NLߐ@;$kw3<@3f{ι^usѨA+K(З(t OLTͱ't̰e;Е}b0QNbEpmZwv' N9/#yion/Z흠/-jLxp]/ma|A96pSEͭ>;&u1?C 3U~+̽7 >5wfgSĺNjZ;ϗ7gɍh41JH0V cLtӆ#7|*~[Ƴ>Ҧ n=D|R.Sx61#~KI}݋ ^w.~vs癸.$6Qü=7G,E~h?"χlC1p*R >6V;D=C#/پD|s"|~t Yu Џ#I'2ؓDw;[U@M|.7ɷCqZ,f=7MWؘܷ["y9C*Au6BC[P5JHQypܾ#ڛLnZ%Ͱ틜'Z\z[ݙ^M'917S-U7h^.Ā 9~@gҟ9gvё[$st#8{#IooC'tOk1c Ɔm*g_7\Gx{v;zH'Ig9i+) ]B jqzX4O[Y:qRi_SAw6xUS`# Xr<lpݞ$0둜og'}9?^O@ 曞xZx/1K1q&ΉP?'>w聊QC{8O+.{65G=#ƻ0}Cߙ#Z1L}=fr~y>N#7rOX~S?2;hׅjuDG?rCsz+,ߒxx {M^;+q($90Cfbc"A͹%%D'&~_gi P"gw*IGfM6w x9Y臫*sӃ6 Mĩ(CDLbwH}e3Kc4&1H3'+m݃x*0SbmP,Yj SLu.kl *T&/cs_!Uyon~ 1Fd#Ax#Bg0ȰsP/Ewo$TN]~y'=O!=xM] :a3}Pix#s}#uڈY9 y]bރKb]]]-S?5gVQMq;jz'Z~}@1FBk] rbyVlfmx0DA <ZKe#⴩r l%ߚqѱƢ&ȱi[ &QYq~{|mj<Ԋ;̝ͽwa{74߸Tǰ>s %B.SJ1l/kz9Xykj׸Fvg}=xI2b1xPn极Гlga?Px[PUU:\: 2-3-o$ Ҹ#TNiV$X"i `8fALc>49_lj,:[\[3{g? C0TN/1v6\]]FQ!E?1Yr7%)$Y#keZߺQ)wWx{x'f$^PcT*SijRUZTSժܾ(_OL_o/403Œ4xkN1fi֣YAWpf058/0\rqvE7CⒶač;mGSdvw{<&moTRjΨ}*WAh{ۿ9hm'898[ӵOmsr:;'vRC1z'Tz.T*  CKC}>evh^4VjVUdZyVeeZV`YV5 t\߭s&1Sx-c 0tq#>8=| NM i*e<1^%5_NgYz#{I)XNf3E'x *N#b:|Yneʯ\%j6 BVRE[xZޢyw١;N#_E(/ D!b(CMxW[oR{U6v)U#!ڵ.ҮRSr/&ӋQumL oyY~ȏP3]]%9g9sn3nO:oxr7/?O?ƣ M~{ww;lkscF6kE+Z5--VGhRK5P #wk'j9;U*xmzӑN1X`VOlmF-nd3\SvNљ = /7hJ9؜xd[XA \AUX'-Ӟo#4C1nxٞҭ7a?OL?Q|ȹ*ybЍD8x'ŬԑpyON^/pf^lgA/K۲[jh™ 5&(ii,x]$dXc CB ѫYl8 i$S`;6`yl)4τbX aÞ _cU}Ӱ-' XY5t&NNy J`М0<ۧ+}`௿Xgi7qάAЦk"M<{miGb8{m5-B #teiOiBM4WsPt @;TcK'rჴ$b`a{: $N-=H!\>MȰ:CS\6:Y4̆zX]+SEQ$U.yS7MTaJũD&< iaZIRXZ}=Z:$I(u*R .*].j?~a.rT;^:.5' Ў")TT: {_ = D:IOznj7-$m áZ 3FuV.˒_ZQp Nm7ykWd2b02U1_7_}d)D!hl'R)IY7t>e iGA;W6`Ql~Gߠaf ҶN}Вn ݪxp*@.rN}(miuЇ(cB|PzMf;T>qPH]D$ Zd!d\iujz g5Zg™%>- yyލ FfV){Ow -a*z6ƪ:PTZ:î0ĺEp/mfU2b92=|^٨ae\QI;}JS?*:XG3Ō#23p)Bϛ0׊U1+Us"ފi%E:?7c*{y~'`B{S]ۼhYU}yZӹS^#@RN,KC(AT{p~sVi mU+.r4uH_c,CcD[us={@;b+&'YMKΛ2.6o]TgHNCG7lՃFV[vjt˛^ i>Ԅ=O\ń}$q%PO Rԝ| iM؏|@gpW; h,P॓.TW3K=94~k!\_I&yxmKSA{&Cx$b@ 82&QG_QZI|7J**6PT3f?%? Xeu{snmάu%ks)kc-M!CX=Ox?e7ӄ:U)B5<ϴ:j&LZx8=vz@4]&ϐδ;³8^x>_=G>g<=L/;_w|J1>ؾtan&:S9Hh輸t KK3Ljb b ++GY,YV8+ ͦfWdes&rܾPXj H1RlCA8r./5Gcy0 "(CQe|I~c1 Eh@,( * Ab(.FQb&1q*ff`X"aX-֊uc)l** Boh$81N38n7[x-ގoN@AHzB0MX 6 ?0"!:Cq7wzHU^[,ŊVCœTD$I"$HN$EI]2%J$92yDPR_)1 LKVKvK b,KJҍ2h<~GSKZr~f}t?I7s׸ O!zGy4x Ϯ' fHA.(ԂtAp %p x%^QG5}G@Àag 40589p4I uG|_oaO@v@Cph[ X l~S`NOOOOfB!eH2! CP44>g|f}}|<Esapw84<6<9m81# 5ᗊ/hEf#bd9يE#ɑjbD0"Ex}@G7_ʲe,KG`Q *H,(6@T5I5FMK.w&&1$~gvY11͛[$u 3p&\RD"'$-DxQejJLFW kӎҴ"ò D&|a)tgm(~ƐMM)#R{c ~œ$< _" VV;bLPHu SImRw;2IZ8ƀ=2Q&&$>zlؓ!>o XQ#E]V$)5rWv}g˕}ܗ Q "x"!tbZ(@D6Aw.#GxSEq 1ޤS i,ҪA|R)@m~9ᅓ% g[7QIS]\<`~JQHYwPG)4;aemRTx9 6d)|6 R\$)!Qp9Cwnbn2BL*+!W`F[h?mlg.&cB|\P 0͟ ߹/ٶ/3--Ze*|}/=2?޻/wgu֯_n ᎍ'jk:~ T"aX"ī %T*㦂Ǩc\#X l~)!?tTe1:)2`B6X/Aw_УG9 Y@.{%> w ^!ip5~ @$2ĝ1w#҆ٵ,z23 D!(xzQ6?Byۉh',H]H@>WY 9&# @$μ?'w'XKUdTWO%yJq0C0q>sg~3wO'BkʤRVN[90h z 8``M?{:]YK^@X}H:ʛЙeR5c$ -&ăt ?+ N'MXpN'nY:/moL|J8 :^[:aR~RS3f7O~Qp(^^PD0\"T&!^sHcA<}聅onmkZ͖/~ծpB5KPQƥ-o5Tٝ^zsOs+”u'9Br?bf~  HMW6ۿ h5Qfɽ 2Q׺Ȋ\`cL6ppwwu%'mq;Pf}h#PnYt@y~ir?_;d~#߭QkǾrg!!kT+O#oǭ;cTB|uzjUh+kq8 7:L.<>M2)Y;B:+zj ? > |s;݆Ճct8ACOzez+z|unѣ}c (Bi$hBPM~b5PwEF^Md{}p}} PE0 3,7E%kHqG>KT~P@7yL|bЄ_7]5}b17/.`Ibr`MdCP&UNY$ #yX!{ X L몣 0KSԢ>`bߌ([aI!뺉=9ѲeJO5,y>Ⱥ~bDU׍,YkKokޡ1ԝʄK/]~Z38("(w{uʮΟD]P@\z!-"Jw 2z= ^("[m}Rҗ[.J=E+Fns;ҍKPO8搈5//[-xdY! 6KmO:evZ~vźIڲ̩=Kp:B U>~hA.f~ӀDP<nN|;=._FDHG=#LkEuuM wQ0rv}* %ARmA AP^J`<Hc=EDY#.@Fa *Hi|q gg%ygj_c?((`Ы%xZZu06)AMJeMLG]?0$K8uOȶ1o|1)m8FLᐭ>~yae];ɮa'oџwHf1ǡq("8T@O!ѣH8[?%7ϰ~ИvBq "xjKI̩p2;Z@RҢSlJ,rY b"cD\B{`(ݠkFD|U>LW?ɣ{f_{'SxK42pm|:~>urwqZĐ@ ySD :sEӴ:WCěxK[ H䐥!S \I\Jq'׸%@wAԦ{FqŲ۟o<Zc`sk_mv範 %prCU:K$2% `eHBU`P1pyo;?[,Ұ-̩o߯:O55~zU{o[=xPB yz2R[H-|}]⾗j$o5qA.s*PiLfX*gbI8l@v,㷖ye'm{mɜ}u>2z9.>:P7ECV* w,rZ ]@p{"!:yJC?Ꟗ>uݬ)(;0`Bb-/3b2ýV^q90"8<"'8y zH#?DEhaAsANO+so;y!i(8\9܏ʈwiTLy\;ܿ<:|hA̩[Jpj3 ^HH,$'0((Bwqc{~ g=C,##[Bu& E P(ĺ9G : \J`%k|(]:_֙"W#)৿J%(5ZYuQ2"W/oB|־Ъ1eTUKbOFaRpa[u24"L2#[uoT0 .a=@>&/YFY ]/@b ,EZ ~<~Cyۺ[%)vJ?b@Ngapܪ˟~M~kYȮW[{l.M'g1Ew}rI ϯ*{K~*1'?~f{ s" gAqIy? q:Mʰ fpEC{:5jʄ z }[u E#`Ve> !YhEGhOѫ 9 0'LdG-^Ft1 bVu'=;V݋nvD2&ư7BB%( Lˊ,77~zGZ0JF() {tx!A^WZr?Lԧ|fSr….P=7,ax)0W_=wӗmxB:`%ٓe Rfq8L]zx'>$Ǭb_0@Yݿ-{sR9Oǵ~}WCC h:KY^ܑ!qZf+tE#J5F2V',Ĉ|ɓM/_S]Ԏم++4u(Fp.`z<D>iv~lrrh( Ԉ,1x*t+-sL@׊!(gT|F <`qIDk:fEf8b|})AOb Ox%] Ef%.>P0sٵ~6%0 AcCzOr7n3*-!5tpb0rjÔ))cs?3 /z {gwf4I<" E6Eav2Էz0i✄PZҦ ?E7oԑ6=8 IlaeiZJo%Tg`݃Y C$$O`ʠ@~^̹`XJ y.2@SO>q~mq/L\ҜO=n)gj%\3kԐV0@Ya){Hn:(D(04㑫XeøNH,o4F.|3[Hg"F tL`Ç/x2Lu^F@Ջ,,tܥ|̄7ήU<^CQo+xPSbYc;mj;;G5<8AI`䑇ڬRG*+u/3kaP$7A A~w}R;砙&.]g⍐ V> d=6srm9ˮZ../h{˿;>ImiKIi]Xu4ѽhQ7qpyᖖF6nB=f-*E&,ZwwYfeЫ7\5;?6],i臗2QcfēYSq \Aa!cB46}KtQ­|u6b*,ZTC*p"T ϔhRU-a;k/Lj=du dΎy-28@tl `۴ o>u-oPC0o o`zs`xƸUai|xOalhq0t[5B۾g:ؕE-{&r< F cY!Ln!^4q.՟ipyUԱ/ &m, LM HN +UnKhQ}xR\pBBHPq3/!ɟ\>UZ3d"B$vzk( t0e* n˪8rӮ {J~L喱u Y<ǭ s ed]*9 khn>Tlg-tIg sV>4qno+Ϧ9 v~*!2i.~>Y)%aR 0L8kuoM@pSBY\6B]~lx[5ѣJm+2lm9͝tywCs_ ?v!Ьi4>2BAʡ ɟm5 Bi@'4ȧ&yB~a&H1.L܈?0ёӃehE17=d3I{{!>&"lhBB<]u:?_OgrD:>>D%Oq9Ψ))btz\9)ߔ3K`Μ117_pSzrUqǏ7mHxAY5RH~$]]1[C-qi 5s/҉#珰ńϸ |d2d !ϫ |㾢Jc&[[4,u@ο4̊57yQ]`C͸uCN'L͊mOVL-1eȤ_ 2 (J JL -m1,- ;y8K0CSvAqY$8)<LLvvLL44KL~X!;ʻ"_d)e q&p㖑/e|֢s@FTWJ0(TnMSo s~yArqLd%M <<ŋ>X1z7.Snͮ@}2&]7?ږzh;]Uvقo^<:\y$"u5J \rKё*9)=7MO [dgĂM&䧛&'pvbNBXy9sm^+׿/2'2z)~ӼC% c +ø %i5B,D,f()!bI5nuvI@ c(=} <p/X62^vVW={^": Gg}'1|(חG­cmT5Drr"\AHp#%M*=K9 ܇k$ {e{M]0lDQ> K;LqvɰOxc@օf3 =7LOoT %tp&< )%qUl%/8=źƪM5 ,s%_, Kh1#s%woSblrW|#gE.NNho{ h{oUpIC}vun9>qie#K6FpL)eҀ+\ȇZ2'jD&! >8Iy&Uܵ@2{̻pOݐLR@lb03 Q{7>}t˘uŜjȈ!GΟ=tLKSNm!xZAL0xjg}4Ek 2fN#kIGuVSw+%=C0wL8|P] q4r89xfS5YD -ZCW8 &TG9K wβv-8yrb O\tMɹ׸\Pىoc:1xz\=5mxqcԟi&3?A)̘23>W#q 7! tq0 0kD@e$#!4Уlq$\jl4ʝηl\0<;ŝq70h.wm>|pE7^aj:hb-2X/B;F{<k셫:Z!o]\uBP.xrPJT07DN1U5]!֓3r7],BDMS?b:`8C:G/>=5tVk>~ ;tz5Bzz/o)W=H1ͤ 1pC3c4[ކzKB.YR$ brC̺XO ! ubHG4eݗ^y p#_J\y`~w999(ğb}~,J8C- %=O=;L_c<ưfbу6h!rE\@r:MDx\S8H#b4.CTe"Y"MfNOL⣬hY&q1APe 7kmuWhfG~q-Cز?6UmצRlm.1ԙr7Nl.bEʢ {.UfU%i\P UoA;3 '_AwL3}D4ӟўƇ:iGP.a81 ):dg4'<3e8f} ׅm5SUר^L~݉dVևvGoLg}|%D 9:+QWL(ΪpB8#1c ƴ#7Qb=ۥ DqήTCX@P2L {Hٻ8 sVIkӢ⹣d[f?ܶļljcŗ%p1A廎4Ws•_;K0 | E #,7gyjS>%.ݑ`وT\jv1U*_ߠX//WJ$D׷}|@XP/˦bcB>#&Lmhy_[#"ejӴIc2Zhb;ߏ%WL !y#Wv)|jXp&T gHp*a8E©é"E_8 @1#\*Ri ?֣ ~ "4,g`|LLH.F[ޅ7WpL+2k<,u$-шNBH5P9;FTPz *PݑftzJr o]V}ʅsta+OX4RIaU۠/zsXZE"Zaoϝ{R;߾uyu׸iWYș,ozA1HqtWC:B ^ 83C|iUѽBX{`}UbPAb{#w-_yX݋yXbгwp;pB̳ a=xSP97c|x|:+0sWuR8eb]螯[DDS[a|T-"x=5x,hgyb΅^uб2qiTT5ԥFԍŬI*%^l+秛p;#@])/&r[rV$h~t+z!/U,C1 Pne$>DWZGwKTpo(n_mvCT z ~K=n@ (I(VHN.zou5BDxU$H"P݂kR6QǠ#ˎ={w~3mD>23\6[=k(!ÔLB.QU^va}[{V lmmĮK;4[:{1z[, }WxeSѝqv}bW>o^ {&g^h#/y]!P(cp Tvn<îG2W9֒X `+vwpd>KkLu_Br;%1"pY,B]-ê`N=}b}h噑qDtnn ];pگQL$;hy_6 }>I&Mxp_0aAN7v٭ͱ/ ?k#m6jAW۰./0 ޾XG >l '/K>缣sq9Z'8Ξ{ |/an{(f@"J)Bla)W%_YnDُ:$(@9OYϐOɜSYRKpL./En寺qBjEtYRGdDDHJW!B ̑/beZ{AzI/մ UfƆ[=',+9ܲ;7m7WYsVOnSݜJnZ&OZ߻o?{kkkpѽ<2ҥsq`U% #{(菣||K֩!xGcqmdX$ GwgBq?vl0. 1`8InUNw5HaϹz8c J[uIB~?~L0_폳&c' 磄4?N& Zb!7ls{m^B8]pzS)eY(Z:߅o^蓠gԐqߒnFc] w(TcV+] :Q=nd QJG%="v>yaJ2||=GXCy!G`}"q3pTO0p>O9y?p;jpq:Mϙ^êF<ǹ'?9Po3Y'!Z °}pu>q }9D(: %-j* J=q!m4)_x^ny;Ofq =>J9Yݲjm…iZp~t`Zy=#|G a0f:ޣD=\U|Mw^>#y8CˍޘQO <_TV| W%!1*oN |./U ctY3p@Hc_pgSJBq Ck?ƕdG6dzXPfLUJz=<5| /s$ f^/Q(d8 Cګ }g/Y84̈>ك/^<*s)j<ѕg=\!(k^dO^sK=d_覂N`PF|EnO" ӤC=5AF?}5;P; F#W{{pW/mtq/6]zZKvMcɍB##t>&l]fUN.j,Y|[C⏑xDIGDmw`!e2pVh$eNMlt)zBh1 Oꢙc^꛾itFv}矽  *xxRB &QDqԚs}G.9uŹ@;x|u]94l[# W#Y@wDY //Va-%2vj?.ǨeYqNJ%R11"atFl7pu_-)c Q)< ꗇl ;n+zH*fJI?M K ճ$iBKOI0[K˪sӕ`CR))dL U>E m9U.3'$ 8AsiVaaA:fwGot(nFBkn;ӓ#KϟλNЉL1Sĺ쉭-Ʒ[AA>'p(xD9ZlsB"I71 !.$cB k4/BS~\e=:|>T> "(C4qlҷO@no̢z# taPHߖjY ljA\cq2z:zẖ|mB.Z YïӃ 3@PY=_Y&u@-q[d ]?Գ6hGBK|Œj:-=**=Q8J] 5SA,; nZ-_T6 D8~PR I)|}jIP;,u RezjU U0g`bevջx  '%5KAҹ]:nqcW,w%-zy֖q[fMO0tw?kat;D.Ϛ3 g=u+YӃ¸+=,*P#cl|o+*a6beܻÄq24Hfy;g]?e6 ~s?/5}AUajM³ypNl4M{˽#]YͿFF8i:Xֶ}azj" W5-ki"~; #cZV>jY+WCqK9(k*%-'pcH}e׏=1n=tBS^OhT$"rg /azܷYR w ~{o-y#Ew oЏoOߓ^AgLR-0;ɏw=}f,H5M\d?; &lC$c- iPG̩[O]NFaJde9J9W|s@vwN_?>,%~c>`J&pLǰ|=Iw E=t<$_Cn`}?ZSׯ7<53ʎ'=z2T*(@{_ߙ{7-UFΚ1sfdd? 0MVQ<2ܣiUWn+Wz7 7o_'KoܰXEGڀ*OanKtsO]~\ܿ>جd2HN Rΰ0KzT(6|Ss:畻6t]"@7EqNw(=gOq1jܦ17 7jJ?:7bJNr_Xm+Re j^L& \Ө{@]ztkҲ6cKO,|჏17O0ʎ/躝&]8>-gFm!oZ;}_W.ě=Y'ꍲnZ-+uζ[FcO͉ u/Oc3!LUl_O~z5ߔ_e)oU pvꫳW~,@%v]7_bAd:۸#3BY|}2Tl?ⳮroN}],`\oź ̨xa`c`=*0Ӻu~W0 q*/~Ywu7ˠ3vlx2.GUga<vŹ8t?1c8\]ګ ccp֭ݏ=XY܇|Bٓ=ۇN3T> a|6W}p!Ztnnb1; "A9 咸i"tQ*%>Ӄ$f%[^4)z%g/19P" 3MT84d\ŹqxwR:<7rվbnEv>y5уq_]H➩1(%.^,@Pi[9|,ޟP{]uoζ]ids+kE윴C-Z10 #wtŢ5{>nQ=>',Uũ i2(&]gĖ#ON4NӺfWa]1fg>qhRE.dC蜣O NÏzڟ^;oިsH)C~PȟpSi X>~|WM?"}IO3|NJN1ӱzY ̧DOo=`P{r=~t8׍B>KsMci .ȉ l?fHZ2L%?֥o]F1@+bhOpcHǬ"U vrY'`k(ȑU<:g|4DW4/A1&M{:dB#=4<; XU:rn`1s1[,] x (bdh4wO[afGfb[[HЗR%O=5A[iŸ`IO,nhX/bqcӀn w [/?3Ժ1NN*Z!lm }R(|#")zL}ٵ9+O;;{eǐk.Lm@ZoE 1{I'NwXāAcdY] 7{Dutwn ,, ,d)" XP;bGQvl{bLl)FSl1MyHMbL.{x6ݙ3gΜ9siRL>pow`F|tc쌼 k':i-(߱5OռS.b;qʈDֿCނvޝ_-%#G9{p;nW?–>fDk˼d{7F-z'A!-ԋ#=y5ypLtmሽ7ٲsޗ"=>ddm5b o#45(zޅ]fUdϖPո@޽v]ǎDXdzVkIA).n!l"aMʉ Lr#|<Rʘޅ=?20$ *5FZfнLBKtSy;@ޣzF#TWhE*";h)wtE|| } (07Uز +W4. f*`:ޒ]DDt. Ar:+QbcrV%*6Fv/GJϪ#-BYiGc҂*ί]T:.}i{+/}wuϖ 9Rգ C/ySJA krNCwɣo/ޟqΟpvA.Um)&s/ B$(ĚVI`Z>94g%T;M%)?Ze ^2[Mwe8f݄\rO@hdyЎ6d:b) +Q>0wnQkbYoJxFe4s(Q3|Su͈ =9O=Ͼst5pָs޻#ţAƟFtvl+eSjbaeʽOpŪ6)Y^6Koմ:PO+uVQY,}> xmHqhBԫ ŸQ ;E.z[jhQ!}S݇C=R5>Mˍ#euKj$dͰ6o d;4}^ߝdͬ!ߝVST}sB$:1:._̭$LYtq[ɉ: -Z ٪hYyRhL*o&zVSf!;.D'%av7DVdŒ^p}U\{Oz8 ʤ*7E*?NHtdpls)FA%Be'ߧ"%W> ňnj_QʻO.i09fnEçtNc.NjW _r|=wy6!{rY7%NjB f3`fʊEMIUHÃo}䩚U^'xB̾'>u(ov+S{3pnDZCϓsP1- #v6:-24=ti!?9 Ϲ0_mr;/%z{|B=c+&ds c*\ Yhr_x?Ϸ`ٺĢ'dtooۛAV`xSN疮:Y˟M{ f_֧=E<Å1ӀFC+A6E4zx'HlG,mn΢y=@P3/T,ޱ:F0*ӄH[+bNjó/;53UԆL&p8@ݰӿ4UgҰ‰9V6IJ%݋V]8ySk{ٹ&[?i6>wtϊa+⶙c=:t8/2\" B9xRHWD`G{Če;~ !| >췿 Sjx$ljC4SҌ ȑT@n=00z$hzxл[=Y}6g!6hq=e ҙ^7"McH?1oTs. @Oo7ufflVmG$◙6ZghrŢTi7 ,`^Oo B,+ 6N1SvZRϒ[]c2RYYbƟf5f[HfK%_Cm "P#;ÛjT)b&'\UV7_+`$$ -Bå g~./Toiø/uz7u`o`m8ݠzajO\=|7 b=:Dsx^˅Is`Ѣy&Y٘ssa5A.X dcv4W`ElX˪ZˆTarY0u`!{{޽[Œh %P|تvN"b;V Y8Zg?˓oP'P^RL-WFR ^jžva7m8b!{ gu4Gzt56o鸞V3(ܬě2ݠOGl)z z7Jx r-Zc `ע^]Yp; `w=C}⢡!MT?4z-b7]܂ lGRI/~JiG utD"^IȜQ)}#ZOr- |BF ?|k~/*Vp[|a 39^ -XYuNѐq ¹X&uR=Q(XQQ4Uk|HIv({Ԛg|cGuڇwe`Ưg{tt!rW>n[tz~8p߾2&z m=jli .%W 6_I :~ <9l=\2uW(ZzGA^}Aab/d2L 1+j,XF{ Cd$ pdt7v̜;*U8G}~P*uA,P3k4{;Z [xrg?c*ɇ]qn˄Z7c95Z,.o{TN+O\=-`o?٢r*R*o?s-L.@5y"'m=;zeQ!aV}%F XםQH¨w`=A'BeݼY.hC0kZ~ڔ/ަ#Lb}|ռnvYd,vM#z7g) @kҡSJm.Eڼ(:͔^ְ.?/W͛),"Ԁo`8E,;ķ:"3Kyo$$Tv)."{"aBTHҳzu [V18jjuFxʞ 3l8d' !{JĚIt2 0>ۦ+')ZT|f1.c鿙~GIߣ GnKg~&ի;'+ɻ$pPGoL{z; N}4 ?'D8qqCB(R|(zGG;*WvJ3, f~TW^opK;tiUTO]GJg@?[eA(>O֓@cDT TMM/xLW1hD%wT Dk`́p ~ܞ7}zʕW%gQ?,"s.7shBIniB=aQcEH0 r@=llٜóл{^~RRq+Ϭ a(iL|"_ > -G_OC IycQMVs5;=%3u8?蟞VTf#V?7ܓaS==.\KʢE\ 8Z2C@#'5w}=V}lm 27=_9o.hq+΍]^#Lqкĺ*AWH]D!K,dHe6Ɖ Jb^t/{tRW)CAܹ;k5ŝ;iҧg]J; d`'+& ywurݮLTUD5eز=Μ\S=nD;nJզ׫YܤU5F-aRSzD1B2Ѕ~_\{K6CUh acnᛷu^,My(Jʳ4 D= > },consކ|^b}c d(>w#C"ڐs H)nCBt:sȵZ:)\95-Cĵc2A:t8nº!Q~ok;۽n noF.0X7h3*V[ԑ}ax!mDža菉a8/1}a ¬r?i47| eFMeY)!Gѹ| )Mƌ: 'Ds3An^r:4i EL #2-IE9Ft[F8vKu&x-iN8}z\i%_{G[Qv AzD<+'>3qd4瓅 |RWeF~4|?tfQͶ~]G4 ?EssQWR+A1PD EzU0K rB#Ó̠e|zۭ[G%#zmqz5Y)0TkNH0 $(iy3BDdYZNJ8[Oyӷ[VG,9>@yTQU˧؁]ٲx}Ɨ0ѫ`ʔ4W*n>'!ʬoӓKӶg|&ϛ uA rܴ'.Kqz2Z +| T9&/Mo-7W[Y~݋"HM_F?aϵ6L]@9"fڏa;ڪcw"1iks5hQaѪ &o<4uF3=;1},׀\%e/&未7-1,5s& uw~WDtl1x~)q=F*"v"*Sc^4@'c^糔-g0 02\[@vH$XWD[oeg+[( |QpD [SK@(-PHM&6P%hÄ#!A=B~eޏXC)On^)\:lBaʊRnT7iSSVhOn YRޣ X- I6x>6=mMJ` I5}{%mL*mϝn,ϫ.+6-?ר|U m.e+`ܿA&mfɵH<ǝv4k 60  +Fn]Y4P(ee~&-(fgrΧ*:ְH<]d+cKِB? ?TT9\SZrcbl6D;<$yn/ۂEUCHCCv" pi#Ȋt̊Gu+SDY?m{ܝ휹fV?_.Y67m0W?]ſS˳,,U: Ğ||d5ΎvD##*XiUt!t]w_ۖ7D'A,$)}h-|1s~+x`jt_vs9mۄ;wEW:2}cv3Y#~IʙoBɝsb>7|u;: ND%Gp$Dn vgL-$1{~a6@}23HhJǥo֝.Mp{ͥSB$fV^~psR?iMCY,e@<T2Ons:),-T/*j>Nc-S`WK;t0$ÉɹA[Ixт[Ծ 0g6<aܩV4 [๹6oB QG浩Hṅ}8U][]/wxf'tk*1d#j1gɑ""2s\|xG/.~+嫆JqSgfF=‹s{@zd.#~F/K u>Sif1]EcBgQx2;YcBH"Y$cCzx~jsGw{O>NAV˺ɺG/r#F67Ĝ_5O޶1Jz?jlameQcǟsJ!+}@)w6JFL{+u2(?#FEʺy Xq X!2\(ɉ([oПd.ƭ+G\L~JMjt08ޓQy?,Z'M*s9FInS~ҸƔ1a-)i_ #L1%*MtYnTsjmvLN!0j3[: 0p:&1p0o1c wʦBd 9CezQE{M O W" QŽ>H Z{K^*&xsgH7P&m;U*H1tlD'816Io]f5ؼ;dl;k16?8;GQf4&-2\NFCzCbaz#y DD∦X9#~]]T!F:,SkF;q'c~ýA%ƌѓJO$fe5Fc!>T# 7+, @|kOu{;}ǿ>;lw4ނ¥fky u:Z|*jqBe(w[A)|9!o~Mxo %6|?!A<Сqf^0Xzl*0!U e?#D5%0teZkT3/:w}pulq?9&acwꍼCS_poC;>h,QH,R*g 2(5ĸ8 FՌNJt暖PҿA/QKӟϮEu^ﮣꦆ :%vOwhg.lkJvO%&oW ۮT3/ly?ܘDB6)51T ݰޱmHc5*vVJߓ;ǬzZŭ!lm$<4Ob%OH1г`'~:)Tw=zDV -{M#4EBȁ^ݍٲi\< >8{K sayZd(VO{8dwsdpp~vk+Iuy~~˞Ks0ǖ,Wo8ze֠A9SYv@tzm`ppǬJ bpZ@ Ȓ=,Ἆ3LYdP^h=ȷlv ӂCpeH.hX-[Dzb,*uGh,@43)fq9[z?KD);~6JyOP 3h*ЀQ4W`kJgӟ '6 Uad)l?cq\/_C|*KHܻ#O/RO2eU$b}\II?_R|quyc*C+£F[qRbʂ$pGd#fѐ4eAW $Wi h P!SZ$+ s̡'V* VQhxF R)jUG=D5ҳA!CkRH098<--sC)G0D*@#حdo#qdN**w{cTk)ǽ58;d3):&fɖ,zk,7^8Ab>JmQg:CuùAQv*)ɬtaYLE9CHM*Z\͹S}\5뺛 ^7e3Q{jJAs|vL[ǣ^eq<B[RX%$Ixa䙻MƁK͡fPzp7O2#ij#s9;< ?$#>BѼ|h-F#x=@zC&dn^~iL?ǒr-8/H:qgJ~qd%7Ro#ecӃ)w^j5&qrNxy%KNd(<_ ¼'NA1*Hv2<:>. FcflFPj5IU bvqGm4G_;Qi$C{+hpI+CoG0&W7hC]^qQEz&{`VO{OЁ42)\-/!`HS= bTd+SJG} ; k ɠQhB. +MfAclyX)eސe:|km<w%xI|x}'C^[=7>nm(E%cCCx3_SybOkMB I^{hK3{1ue*թF֬VȘfCľ̟iHVS:$>eʓV-&:[kJqx&AXgTD64NTqV2nupOiAO??ʟe.򛗢?fԽΟO]m WpmD<J&`}"஀BO:$)bL,,{XoJƹ\pFG3tD B }JjO'+lyrqܹ%%s[:98kl>ˊz[ħש?ffx2]rVQ<[CL{+|Z''|v]W$h"%\WVJe\_ [Ѿ݂=w/ oo ^+UA ".Uw Y~L_)WxSjކzC[ݵCyԱ 8%yDHgZ&Shqqzȵ+,)͵ _E? f?G2]Պ:Jhn?"L"<֢GwhJE%tcdrqO?jx jGH4OilqL|?]{B>yp H##) i`(*c0fJő>8 Ie(^1\,6>P '0R.؉SD4~ v`2Q㧎7wDɬ3+@U:8>(28z䒅$O01=D"{kQI]g"5(Zԗ.CUSHfL"v`\"!W.՗+S$4.ÿB7d9q"B}_?\L!7Jʵe~W u}4o5"`EQZ D\fHƽuu>T/{m6Y11g*o+ahc[#`/?m9W-ym/)D4@+Eļy,mdB{[lM@U4Җ+e bغU󹌴סu|  i/#,|V7q@HHG ~yp+a< f~>h؏v:pȻ;}f+>\':ɥ%ӟ;!:⡉P{0#Hi=zG͘Q s|YQ[;=f xλ- 5]:WԻ.w/)z 7װp@8)ZÙ$yv'I /OVë#sFs U="+Lb:Ozi1$^B[V\FH[NkkBP_9H=Q+/=ܗ^{__ 5yH[YmLҖV|n%(`Q仉MynH~2+O|)0q5!'xQeOgRKwj),E(zZ{8ZBAų%/͏fH}R;('|)˽ރWk։Phdҳz2dI12z6;W P \CmOHr0ywg>)t; 'yT)..#Nl$6zX'ƨRAx!P@|ՏoS ! `İ!qIzټf֣L᳃L/B+zU^Z5@mݽVS+ y\T|58\P*P/DZBEJk \WW?c3N1nݕ#u6տcFP5j3cܵ0ui2rdWV%Y(J5=_>v|Ү-jp+U&Mu3t]4PkOpWPa G`npdc N^V!㵀6J$JO Rn}3p&Oo2qY ۻp;wV5!f nZtI%{urO39v,/6_\ =7"cpd\fYV;noލ65 =!J)r'9z!klCpbĠ;>lĶP'zcM%!F XⲄDYe>kWwDo.әYok]WbYǷ4ҙATnOƖ~?zĤ*: p&4{5ƥ T`#v2 a!iwa:OH $5/l*{]q{-*kӕO}t"=QN5s5+fkuΛe~농=8jJ5)_AsLi1',Pܺo* /طlV!PU c/,~v p>E$n4شmA8Fe@rz:,JK'6_7'{{oGDERM]]QQ\0!2&&+ b]8+Ġđߣ8@G`0<`JbAS;]ƥ;"s-UEFCzlOF{rd٨:uh IwZf=^GL#VC tNb4vp%7ݕ)n-y:[>8uwË_DONr48*ODAL#pHyzEo `h J) ѝ?lLȮn<(o,D F0DidZ)A:% 4hxxg1ӇR,ɚ5'UiL1J/Wh/ YCJ% i׸14WQf ׇrg"=cg1l4%as0t#far:1f Ζb HG$Nrq/aKLs@K+*cY,rAO3Vrpg47c أj=%Wp9h1'dOpr|'ç.IO[aTx3Ds3""Uŭma!{}]Rv|;95S8e ۶ G8pQ\l; 9a)͋ !i/DlM2;%? M\4pJR+H,>qȂ[^qY:J,uw wOQ}.+4Mksӂt2qT2Cۻ iIokJw&W_WIz E>F K ;)v6<<$A`[3;_kD'm3g56{p-&-^54jk %OnOe6E#95Ik@TpS[hmP/ў1ΐĠ@kfh#b C"o䂲2NJU e&P&UrrrgR[T*VdFr#̈́X3'k|҂ѠN4 D:S4ZJ#S8 WhWРαӪ#ҰT"]3 b-n QIW"Du!XʅwC-3QL􄕕j"m!̊cj78nGmQm>q]:bG\w<1ȒV5^FFEMV~OWmI}5Us۲lm,e)˲,}ZaY;`%j{k4F%XR}itcgfeQ? =;̙3gΜ{ʊ=XBBI'>G?ǫF8/~(>B HFf 9+l6&cPc _O@Ö֒Œ"CZx%w/._2#?;̰S=yų^*w ͐p>(h4:ϥܹ DN mv)F~y3BQ&)_%Ŝ/%ĐveFBM{|RztT>94- eln+9 ;?ܔ[qix=2= ["3 &&Ohw3Hvn/FC~b77FZ +d4## 9e.3Rg O o2OS3b9)4: ʧgFa|zΘ@i(qaCrLYޜ!Z/?v;/1|ZhCHHw TaOYY'?1V6{,նlL2e}zZ\%ǟ<| )3GQ g ʵ蕝PNsE45EW ?-k_ZɌV#ejUC "v@Q4u* SX7r5|;Q+fHA<@9Dl`l + wfOaC|L㈺b}iB9C*}ƣj0;ɒ/xJYY6"XE;ۓ${٣ ȣE`/k?_C{?Gfhbvl8:Nrիdwzԉ|~ ,$"o u0`O۟x{xtM^&y<^t7]kqao bMr; -"L: B-n(],>f+Ȅ:Y>|E0 זrj3U\VVL*V7 ꞚW:K. ŚW̞> 'J{ 4Ə W.y/zA'>Q)y[-{.<1$#;E yp=vpEv vK;|}^|w|(uGskfݣ<8x|~DZx}yòĿv4x É4LCx t!q G|C]Oĺ9SoM0?S;}𼴹楁 BFs_5k^PE:Hr5y܎$b?g 6^Q|S>[5`wqF~1:'B%LÑQ>u"P}t,uRYc">jLW/9m!&%|~}!Zz/9*~|T^Q:>+S>/Ri_x_|hz;}UX|Ʉ^ zZ ,'q Pbf6 ,' m11ٻX>x9 )ૅv%Xky;a:yW`v`:ky./=.,ّF÷v}~|wL[/ert zDž~|\z\LrX#ȡ>S_|hް& &^`,a _ 2뷌nǾY/3 ׄ*Fm9)b<$<7xmN

m9Pɾҟ<caaGK6TUnM 0fdӟ(Do( u\rA=Whd؇KogD8 Y;s- oyQ pV,BS||?.ly_APb[ ʊ+STE%yJ*.rVe$g>g@FyA:$|zoi%؝~- ӽT‰s@qi"\*y#ԇJ9sȱҽ{K|=KVS /><9QfpBzrez~W2eZ~(s 5^K>|P@*U0]>>x ~'(iuDryPV$ؑyCebwڋ[Y5'$yzRavKjTTL2CY(#;h>{ %~oWz @oķ[6Yb`)Z-WP/`SӭTQ!UFcԒ@-w(C"E7ubС{3wp?d<<~CJ+wM-* ?nOKkґ>hKw8jW ר%"7[w$0"(#bZkRa J 5{_N̍NDl8.|K?9) @w ۵wOn/;_^?+T]vpVrOؾg֭kWo߾z֓k֭]nڵ+2'o]O8 =#z'~t;" vԿp;\}">! Rmhg;j9HS7g)d8"Њ #p7@n; 6p] zw|>uzVLbp7 ʟq4s%n>2< Ri#Db8nrYr)#H*|sRbEZNgrY={? n?}z=ׯ[z5!?b_:e-_jV͠1tZ]ǣWG/qЌ=](T&Zt<2~1 -_BP!<D[:Ų*l2{7HH>yϤ"pa';\">-M%{~i}l; G$8G{CY%Rg'ݻ׻By{;*\ * 4?W5{uʖCFN,6&U{ҲAY_^1#O3Cbjk 9(_'$k>l mqyd;wxC]|(??V_1zahtkxtakA%TB#2I9jsZ,$&HKDj`qqiqE!ߒdf?<|0ƶ:VVcjhQTCr~~rbtD%dk},Q)XLp.@Y$T  ?|6wb yhg .4NˆFW[sx$Ĥ/d5ґgzҊֵ\5h@Ap60_LyR򂣜!H R[4 vmѵkdf}լq7}C3.z[=jΚݬYxwn6=F5+hQZX8-J!P߰qS}el[7qZA*yH5\IdHQF%X8bKs}Cz<}6 7o-Fпj2< XNވx8738_?xͳ|< s_wq`cŀYSIl+Dr_/3" u͹?H 9R)"`C5,MP)`qߣ.X wU. >{Ӽ+v`AٳU=BvBZl7 &C<Vaz$!Ck0Bѡ' ͯy>U Rj+?yGcb&L)Ij%[f$C9O$ K*`| wXN|[ {ಃtͿpK@X/s}{o'0()3ynC_Ѫ(!Р `r߹8lf3!C䭷& eNfkUz$>yU1Us򊉣REy\sB/AO^&̜D^};iȻ% VoOq` R@CCn:QHRNk뎮A<(f<(5U3hGӍL_7icǪ8a?WVD'2B e};S9h}@_!˽tJ+k )b4teWŌhtJJOasN[ <qt x{21N~L)DǔL@v7ݻ<2.FZ}!r{(s 5ƪPeP^'{Ht|96wU_;S<^#RP&cK|7J#"tM>m!8y%8@ݐl䐔#U5N^bn0rmNڦ]m Hrz-bOGE 3q6z84.=Udþ_41+` q9)(9^g(mT𔏙oNY? #3&TSwAAz}rT]*:~sG7,;ͅT)Z1)bb"7 >:ʟm?ṕgNl1}8 <ڹXVO:I\rTIש%B*oYBzE$/ȃ؞ ZEd ¯F;maK.)!!tǞ}vA~7lu`Xŧd-@/O]q*grnQʫp}j #d52[H{AkFlӰL`$?ՀPvω{Eh1bu>_5jXZ2hPYdFˊUiWwKɩk֤vSn;&NM俙Ef M{Iđ"\N:M9xΌ7Q 3ނ%ta3~$|pgBe0̐矿4޸=(~'gVX̌չ) ;ĄS򺢡] ={nk AwO9UOMM:O=Zk K+K)cՓ7pԄRx_$}IvcDEP dIoKFNusZ &L`S>ԕ$I6c8>WGBĬ]IJ;ޣR+'U !Tsm/4lhϫ1F8~Oo?zٰk}P8r]>`| =^^ ^ʙ݌xPzw4PkݓP+.۾/w3`MN٘c+r2'..wCJ }"Wğw/*҄Ͼyy0y $j&T))9^GQY2[ A @ϸ4,0|?;s@.wXUEUsŹnh6nleڜ5-K֖ o:Be[)5l~`pʝ{!یQ%iqǔz&U^ťq!j7XBxEuP#2U9 JԨȗ`v`=?['ۥ5/l~8meYŌnYV8`z]rsi7tpʴiϏ/;r`L0iڒ菵*k ]"/8/es8evCp D癟SFVHg\xf,"Fb21X@;RIUd(5=뺓Ơ1&#+>K3*'k>J֒{fGGJe^:_%# 2dMAz =v҃}µA]łOJBK.ߊwgxlH7A"ҵqSgyZj7&3BW`X`HFtR OO/mN jEqGT ?7Mzdű!> qN&<%pGp.@v|~V2@>մPZ=izoþ|\z/s G^W[^~|_[y/-SBCz }X۽^gmco8l;I1g$3Tr?_/@C"Bq'gb~|ZVR2"ul#rakgOµ$ozH#'4Svў y쩜}x6YAFyA/Uj 7BKj!S,Nln~ ,N=@pԽtx~y>\(]9꥿\v0X)m%·1h[p=rPˣEtAr\D+em7)[.ġɎp{㳳V0 bZ>1ʋR%yELKIO9v~FPC?ڪ QLJ[bbVr5? j0>X;oPwdGM#gh)Ǣ'ap%)ca ?]aA ^ڄ7T&=E$r˫4Y7ԪzM/ OaTmt]gϷ-+a&}hy I&x?@bo$cY(U/"b|Vr+, UcF]߳~I@k9#se]H$Di* &LX$>|8>u` s Y5cr/D@1Œ@ "]vxmz-@#yHrݫhf5ӡSsdp 3U YSfMMiЧ)x_yԢ MhVZ>-UiU;9S'z+=dlڵ۳J6L;X1%ް7:~a'6 *[M8ky bxg\Pvmy, ?"‹|QR:Ypc"褙c27ӔAy`ay64nhm1ڔzsQO/3{>lAЧ&L/[7TTĦxZܔWq@&F!-,ARd\YIE C&^Y׌2GھWHje.ZX2.?$c.=zͽ]?{=*frCpߐj H0#E/W#=s946iAs)iۉ8:J6(&Jcm!~&be2$|ra_PYuן{%<+ʉK>ܰ}GgW)wjcG"TCȑS *[}LTv|mz.QOP?1ED*$6@{kiY5RaToI?>ڒdܣKnn}&5 J?/f# foXSI9_^ꔶtRZV3:nRY5~ɶ'9az,32<6=`C,+c-‡bX|>@egV` Ө{ L3< 8+kN4̙"HNR"sQɠ=J W =0uKݝg3>w vWH55MM ?}˜1O`373ooZc6hP2O6WS.Yϐ46 }:lnԦ.]jt$V`l +C5.+㌺􂖼Oz}TOZq;yY5eϚ & <:cmJF}VC>cMK¢D-aA&~xo ~cKvn.h5eO[ߦǮ?$9u[x{q9bqE{r<8FASTM@G=% >OcPp(W3 _!kߒ4<$pO~Ǩ{J/r/4x",48#yApmg' <h/^”^)*e4{ὓ^/.{i̚]cƦ? E}-_̎WTrVGei6;z ヘ7ទ”>>!H&c) >#brISuOv(-,>CEҠ^jV sk淒ܽC|Q"] Vmrv_[ 'gOOx=Vʐ$EJ]!sb<ۻmIp|%㡍E9-=|4o&\ 7#Z$H"kT5>;1pB[gwT ^=Mu9JLΚӘ5*sި9gGhlfZUmڰ#ãִ=|"mdB/WͷL'_7:qXn]?,Vk狑>ro zDH>oCSF鷇 mɚIgW Gt ?*Zxھ10_Wǿrs*w фglA[#4epYJjS> !l3jOf7}@)`}@!,̀,>nKF}}@g0ͫyX&z!y -PX w'oy)3~j޲YPPѪ,8/{Pߏ<SOOV1:n~#-G^/4UΚ3fХcݲ~|Gle57wu%:yܪQ/$i4}LrA$f**l ؽJy;{d(*7{5sPG{G ͙a*6:yyū>񙯗x~wmXnmI%HsKmdjTĕXKV*U y2F"A(ЮClVDDh4Lh&e2UPô-T 7)!%mSՍ7|ݎ/Wu,_Y5nX{np^f̚\AZ3Xn-ee{2zN%k Ը7|6ctdtKkbqŃ_tdf-7sGܥכ<=KS~8կ6G;0o_I930a_0P$-CO,|jeЪx:פvc;>3윋,ovgаN56,i &';s?c8Ӿ>sgnykyxooy$ŸaPwn/Cπg o~n>S+s-Je~+K?<8蛄LjV(wgtgA0$8>"K`|*r @f2jDĩ1oq?\;8肣; xToU;i(!xDNJPQQ$:}}Yog{#p‰?9' q@ Nb;)RW7?vfh+*~ .Q-Bp \hT\5zU[2]Bo|ޯTߥ*gѻ_7՚5ڬ&xVޠ&" *+x8%%Z .' t~DUZ\K-.)|V>|>|%x5ت!xTN ޠ2=#C#RN 4 GvE'hhʀ@/`c>[o3=jkGuX)P V<~Ďym6@HgfV͹;u0v[=pnd8qq7FlL3900B2D$JWzWPO :!ck@}ͥG7<7Nh8OJUsѩmb2Ş612!CXz_ BUf^ekMqXs=,4$"gwߗE&*T.#= e7 H éi8N:RI:w!q(;̂s7p4(:c( xU7iu< $q#s-c#7mgD+qnF NhA<{Su$*88$s<᫾0$b'IbkiZ3Pg~Q~ؒ7[]SnbsS6S4[S{a-Θ !>|;H\d~g[ۯ Dh1Z-ݗn\ V?#^u"t0QFM\I>V$cE:W{.V.+ rwĖGua5&^my2rnni-Vx#5ts]-!xmxֆ8q̐ZҮ,LIMBزDR {23323㽷gG_?;;s9;gvv$97fw`VR2@Dèj4FKв-O+ЊLЪNkКMкOІmLЦmNh jǏC.E)FqJЖmMжmOIJQ2 FiD;dBSi'Fi4v]iF'ͦ(φ.C0NOp: hnCnat7ӑ |QPH$1ziz>.zZo$z^(KEGT2]@ڛSF紈bڇ}6@:-C0>#(>cUz^7Mzޥ>D>OST>O3L>s\>|!_%|)_Ɨ? | _|7| ʷ|w|??ʏ?O ?o~_e~_s5~7-~w=~?#?O3/+o?_#?/+ƿUDH4J f.#EF(-cd,#r +J"j!kZ#zl Fl"f-UB8JTbl)[ֲl+%#Yx m2QvIL)2Uvi2]fH,3eUfn!{lK2G:S %#E+$R̗*}/5Y e,%+r(r*r)Gr+r('r*r)gr+@.bD.r\!WU/Zk:^n&Yn[6];.[{>_!yXG1y\')yZg9y^-/ȋ,ȫ.oț-Ȼ/ȇ|,ȧ|._ȗ|-ȷOQ~U~{LmFmaڬuHuetY]NtE]IWUtU]MW5tM]Kut]]O tCH7MtSL7qjHQG]jL-u+Zmu;^Ҵf49M':Iw:EN:M mםu,Mw=tO{i^hvjA[{suWZVO t.źD}u?_ =XC0=\#(=Zc8=^O$=YOS4=]3,=[sQMt3=Lt]Ez!CEt^z^+JJW5z^ zޤ7-zަzޥw=zާ>D?>>Ot>s[_3E:΢o%Nsr:Nv}Y_W5} }Sҷ}WP?ҏT? RүVw?Oo2lĨ14&34fi1#(3ڌ1c2fYYެ`V4+*fUYݬa4k:f]Yl`64&fS܌3[V2a1qML$̖f+lk3ۛIɘəfi3fL6STflf]̮fn0{f/7sL4eM)f)^S63mY`EfYb1I$=V.&[ʂBR-304udoZ)76&T @J0)ouDXv Ft,Mo:Cc#鴒|ZH!Y]P^4@6fB #u#t{ P8 Pעń9mRgHS\DlƴwE6QsGLc]j>DX˼jP.˝ŎIZI6R f^ɿϓmr]+DžF'Ve{je~OAn- ›bë2rJOܝzKZJ}q%W.Bsc,jeȈuobqy?@jG5Dn#^-jqd_՗15d̺>.w/g2|T^2h6*)=jۃc?ڨI(F>fZ'X,&?h6%V{}=֮,/P&Ĭ"BGwNsϷkps0ughGT*s* k')h xwrNTYQp7WʕBW JÓ=lΗ+Ro+z# )E?l)n[ilѫVC2Ba|7o;p3Kfx ;{O9yٱ&kK =ESi^| ѩ=EM{}EI&Zz47P~a @7s: ||%~h 4Yü Rd*-,*zϜ >Tt/ ^+6T;RGgK~jV6K˄aM&ub84MBS44Bm;!C?~f`v;!C? >O' ~0&? ~0a?~#cAur"Gԉ?~|||||| >V]Oo? ~|N(QG? ~(QG?~ 1c?~ 1c?~8q7n8qp&M7n p;~ 'O N$I'O? ~$I'O?~ ||8ZqRI?~ )O? ~4iO? ~4iO?>%뒓?~*~ 3gπ?~,Ygς? ~,xu.]? ~9sρ?~9sρ?g.}뾋uźbwX].}뾋uźbwX].}뾋uźb~.懛a~.懋b~.懋b~.惋"]䫋|u.EWfڣ?W"_]䫋|u.EW"_]䫋|u.EWk(kӐU~iqfӸLͷ0 ,.IM¯}z:PƠqh竧ih:YM?~ )SO?~ )SO? ~4iO? ~4iπ?~ 3gπ?~ 3gς? ~,Ygς _gς? ~\qWYs@ρ>]C9(ívxuQh &IhjY+wb;sNi5K:{`} 6ux_^-6ЇCbC }11z"fn{7n8qp$'? IO0nw 5/yB)Up#돧߇F }|R.==-=]vK7Vea@~&cISnDfw5xk.e,=MA 4 Y_ah@]h&Fǁ_¿/\־r ȎbTv9;޼j[gW-ܖ]a9{WwnpoofC n lqȠ8^l:fR@@^xzFR L~s.4\oEK_ zar|AQnRYݖnJo:/ƕ*lqLPytvHmHƶq}^'2-C96𢃺v m ~a9fm;Avk!}+/$ѱm̠lv^}!V_ҭ6#XchC&:X!rmt໇?{=mev*բwZm:PiB&K ʸrwGFB{fxJ {z}E^@fXE8l F5z/u5}={}u3OBe\V>7gߴ}9YiBP1`T|>f au|~ܷoR3@>%0|o ߴX'|TPϲ‚ͷ }xQ* pqnB(;R(,{tt xMj`sωF5TyhZ݋CI1hnC"@݁pAEba̠.{[{ǝ>jXcHm*J{]>>l߾$nHDO hy+:hZ`6]mLKLm+<\4S*WS+f(ެxFn"Ң+9LPq1-FL(^:H4A'G:Ioѻt@2}9y p1zM10a͐N#GyaNy+nO3ȉ\6*TKuTO Ȟmfڈ,tN{>}@?Ӈ1]K$cȣ<^Ws y/q)>o'd;q;L), M,e+>"[kiuS=L2 :/UNb.RdmWs#ds/2ww!c|'g&b91OOcEJ2`*Sȉص*Dk5F}in ~3NfviAQrV6Ϣv0ϡ8v+hI4bՃy=2d^@LO !s-Kw#se*C3e;0KZ\ li.v`tI'0W0RX-}N`1$lA`HwnWݡۦۡyw*1ծiyڄ_  ˅yB&#=9e p\VfY,S18}.3Z\20)h琉-zkhg.Žڤl<\)r0ދkUs0N אnX/۝kǵ+S|k=o+O1݉^xi GT`?v+I"ݒi]")GrH{0b9?  h5E4B6^rT]\k\>kk%OKv>t>r::v>s& 67 os퐏`Uxqzb'񤞆͢|#Te}OB֔iBm>G>&ЍmA{'уlv?_;TD%s̼h#i3n1ϚQyL7w4}OFyoMػ:Mctg5~sxHkkdcV~!m/6c?_5Z8"~3^fkpO޶dOefB>nXhS򹍞"ی׷yʌAJJVkupsۥEvHItH2ΤwgqJN ˀDdоJmgv {[;Z:2sSC!k]̯`ooH |M)UVn3f -^WW{-rW_*#SJrn]h/}bUdީ!xݜ{T՝9UDB~!H0`DH TH c8 KaK ED$H{(8?^˷vޟi5]Ӵ~ZB>bߘۦcZvj7GYEN 6L,߆fyi*{DV ljA*wZzwkm[@^vqmGP+kW׮zvSmB}ڃGמ= ur5mFz6嵅mImmMmm:9yP mKlږ ʶƶۛPml{޵:j;a;m;'E[uB V\篋Bu#F׍5nFlu-[YjBm{nu{ށ:Pwɺ3u. uծ٫gode;n=nBO7>T}}}P+᭶ɾž jˎkozGz{=[G׏WOY?j^B%R-_E~Ն7oUj_TR?Mu"Օn 6 @৊6 #F70jFlTR-kXA*TޢѰjo;TSk8Iu<եJ5jTQ iQ9T8UL5q ՄTjkKq1UGT+WSm|jSm;ߦxHqSg.4^0ru q ;\T^G*S w ) yX X   ] C8 s N9:ɟs9u?gI9I3$EN\$N'sw?f'sp?^'sp?1'sq?%'si."!.rȟ+"FȟkȟE\ \".Z"M.".sw?sr?s]k"M}_SMk7&oS ^Si8QMhB5i&՜yT P=۴jUuMlJi՞}T6:tt9MWJ5kH5yUCs39Jn.RhM5y"T۩7/ZڼjEs'ի66ozyT4:|d͗(T2r-YrH1-&Lzjn-TϷZݲMT[ZQlze?#T[NQm@uRnݗjjNr{$UMܣɟ{P=&Un^&7ϽM{OPv?E7sw{ȟy{y8y=oooooooooMxm&i#MT}wG|~Z*@?WS0?7ɕ?'WO$̿O~_'a~jj?j?j?jj\Md-0$@Y \MWWWW@[i`Ai#42464)4-4jj8j8jj$A =H &/8&Sa&k!#/⍐H2B"#/2.B"S"/23B""/$B"#/&B""/5B""//B""/r"B""/r%B((6G_4%bEGG_tbEgD_=J/,JQ]%Q%ѽQ=%cQ=%KQb/?FbCb/我X0Fb؄MX[_#Fb+c/6Fbb/-Fb]1##1;# 1'q=N8'/>%N3/>/NK/>dLuFeAD&gAfdfLfBF~fZL[FyfAfq##z:2:6#7)%-#z5ӕy;?#2s$s]]'Y߲۳qgdξ;{4{t;,wwܹ~9rsr9r\jDOr9rs?-1~[c jn=rv?Ƚ.w83]dgtD\W?3~?ȻyZ>AuLˤJZԵ[I]kH5ut+7[iMk{+w7ZdT[duw+YtcCv5U΃~SU+/+o# lE8,=i(-ԃZy9YZO 1jW 'OBCx\:_fيe}Ѝ*N}MH[wp_+P|\e)gSj?FC@zUV™4C>HFktg.FSU ;_5\/N '=цoC 5b[4OB0m ]#N֣ԣ/t[E ZAp,nR6JG߯,rZ^r-V@^P)>Zչ»z]1J;g9޽׵|\zF"=;7Q\\mHZU wHcȣ)Sh:\,RdY="eK?ȱߧgAO2&ݯG[@ ӈz倽;豽wj&A9jlZd~5*'^U~)zl ɘ_͠z3t{]u٤7^|}>GP3T'h -Ƃuם̯DM/Ɠ({zGL{g*픾X9 CC^W}=7i՟U;_{E9fV|99>|̹ 25p_L5czMX՜oiqgǒ8PV\QkI3Z-xLY]6m1e=ūʷL}=)]_u{YAj㋕UL}V t[]/[g@v7//汎y̿|@=*mopgg>[ӳY$Ej=R̊m&wt[*ȳ-}~ Mjʈ]3H:޿]~0"?` s~V폰~h!LFk튏JLfga+"-`ڇB +M78&2&2&~2&~2=0ur~q(+OU}WA#GЯ@uUo?q=i-W)+h7B))|RO= K)|n2S4麗T3e/:UwM.HҭuwTЃ7B?%5F,W} ɼEdW`؂w[0fOMU!e3ׅmv̘Ժ /c ũx( _U.*qӹg~Bw}Rzsj h @$SQraɶNcpfo VW_jYkjU^j,  1b:Fĺi|_P9s+%|Oe$z»n%JD1{4>k,a ~9deX#K2?6fM~j4B_m]}턏3{Hk !g;oqU:|3Xs jD6vPE,{A?ݽP)a$Tï ^he qgiF9_"46I0Cbq7Цe`5RGSdxeSԊVmGKnzyf#ZU=G3,9 vP)rbϪXgL<Q 󵠿~)#-Z@ ?^S$ST5*e~.OQ#sV #?2`Zq0V9Q"ZTFIfdv5<weO/zOAB=`K/цovພ> dy`7n5*Ό3C=m,V17dSUe<^[jЌDM~v )5bY;48oCLi5zK%JiQk9և,BRQZGXmq/=1%{vw e}؇.u(|SQ~u{ B@uF7Aw, (w?VqUXN;)|޳=\Ļ껉:&ߍ/ ȟD_𗩹WޣBpnA KĬeUbE}cӍ)f8ʙe*gi-;RV,!FJ+|nO>؇9GWkd[ٰxpS8asX~oٚcD\G~5"}56qZWc)%WW.C*vC;d~ %̙%oӶIxŕ3})h`}-o ~-[ps]Qk5W5w"'0*yA/ħw +}=HG˽p*Vũt 17XpVB9PBmULE~T >cHP'1n**E9}Ęֵ#TzCv8JOϪH%VZ;*^(_gJq( (gQ7U kഩTi/cjs(GWTܭJjVGJ9%bf"wdx(ZzOR[⴨FiĠ0c.vwlb}p "U)f<>h5L?/r:*Q߂TS9'ʯ6uLLu{ 1eji\I'U|{{_},S*>ڭJ=IJj&v˷$ JT—ϗ?7}ꣾG@}2&5?_?'~oX>*ާLzW+mj׍Y_8tx=~˷oN1ҋϪUn* ̐Uf}Gz5㛿`hͥɽAm6GD'uh/jqS{U+kk.6S;)~Z;%~Vhϋ}m~'~^]~/~^>?k?蓴п]ӟis ]kn}%~zAfV_4dγ~]x JX;\όZ+68e\Z&r<'iH>o(wXiC<^OH|]Zhkx[},^~j):]/-^KT<]^Y2WShk&ٻϣuh5VI& QTJk%"4vOqZ>pN6!?yJYovcHWR{;Oz`{U p%lXŻ7.N.߽qOEZqsMCת˯jD|_ˆA4*,U> 5+rX?1ʰeXZCv1"`jh\8sUVO-,q `6| OyK3(4ySMOʿߧ|YѦx]uCuKuq ԇM=t`Pj`?STATZv|   j6$N tj [Ƒn{GެnsĤLPs4U*)G2{ $ ӻUn$D.]қ)jN+&"0Z1Xq˜גQ,QCA]K#R+n!˖q`08㈊eGpޚ'To8׵>m5/38T׍V]S>-$899kD)=~X)ZpVʬ뗜s3IDK QEbwp{k#/ :LPEmQ=ͬ/ws,wf?2/ޝ!Y\ }G{g-cAh1b3^,=p/`nP!ҹQc0ƠG1R2$lT҄ OXr//HX祐=fO9&vYZJCAxp9IO,Qvew@te%NUUY"2'UM7}eQ#D @16z 0RE" @#yQw}Z]8`;Iނ mW%ob:C4 ˔S)T](UJK;c^9rst# ޺[kh #ˆ˹Qm:"r>]V Q1Dĕ ]h(qʕ++q-ʕ+W2\+q2D+\/qsj?'fޓdI)68bF)b^g "D !℈ml4\lm \{3 r{s_jFdNpg5'",-XjڵD$Ju2Lff;iz_uQ'"^+##L_dDJ1iQw^a+pRV?@-zc=əeOkC+v ; 9:vJ~z]Y-l<*uӒSݥitL_`Oo>xF"N,?Җÿ;(8PtRIwOJ\T9='8rQz\,xۇa.7!h}S0PՕ_/ªR*G#[7$oT]6`e$2LpĐiaX9eOah[ #S csXRZgX2{r0]1<4Ónx7_ ZAB$B N Bړ]q[<D$Ls⒈7KR qq-?JDL22?}I L~zNҽnf-YG $jm:p |}Tւ& Bёd6 ,._F, $?⿉o $\KaZ ~ɦԿ\y~nq_)x7zkoQC p=`Br p"$P :pFgPߨ|MqP-oJ.D7弹e:_n`ںttET+p|GJ0 |1Z](zրjnd&ƼfjXu`.̍'U < _g\Uo_CXߨ<괒>/B67S0@2bN땘`KqBOg+̯bM"ODW3kxS SLQѧ@C:µϢ3ZWe[TiC,sCT#_<,7k:&!$@.(;}M[pfDa$Wp-ԧp6Qd M 2Q jf__~p,{?Ja>nޏrv8Ow}R׹tq;K3b}|i]6cɆЈ5j IWK3Jv9zuڎzAz^{] *+nF/1xNy\ZJ[">,B/dWа=03Ll֩6XP(7v2@+ PH0H|W,ϐ M~rdo y'Zp\Zgs}%ْIS!V?Miq46Xִ FeLO-{_,nVQL*rQ*] W%J\C%J-Y{u\/^PoF`RIBrM\_/)O]uM >t0 *4 oӇ{|D_4x"h9t9%Xw$ʠIwze_ ͭ:Œw_w`oQYϕ~/(0IYhLe&yS5Z݌Ӝj.T4 fnh/ja>Y3*ixْhg ^ÙtZ9k˴]NiZI&Rn/j^ifȍVt^>PZN~ >K_ 2cb]ote޷ז@7%/7PjcӦG+,C+gg +Ў'ق =b6XhN8r1v3d^F(Ř1hU,iEJr} zd ?='G [Ct~1R~Pt;{ ݽi?9=!Q  *x qѹE0 j~5{"1-פhX:]A[kJ̎>`n}"w8:p(*l(u%;$#2g!T6yPҒOZJuMOHŻSm񽭿:Oݟ*Jh*x<7@YCE_ qFor0Mt-xMі̐ggN'\٪@SҤrxl@pS^srQBkj2RHI a^%i&`ԟ$jA.ZC"4o)FKD5spoɈpGۡW)z ~ AOGR\ͫ#["Z9105J`Awҷ]a'f$/:[ 㛴 K.*n}\D{ҭ $GQ8G L;27MKuJPLWGv-y=],We:VMMJHv<GU`gVe]3}p[¾}!pĕ0dge)2kS$^8 GG1-Ԑ|()ZKUVX'~%Lx\=;Ctrޥ//8ShF!1[ݿa[eέ7@5SUà5/m ['Vm[cWeEWa6]n/g+ Eރ FiGdD|,pDZ Ut -8:PxU=p:ppoQȸ Yxd%%]?4]74I]~jC"[DZ6={%=_~ȃqDU_ (_C]Ai2) G:.."j>/W=5hҞWB O>ˍvwnr4QG4k|OLu8OwCL>7y&<bIN^WvrmY#Swa1[%#Q74YsVap@xW8>DHpFպo$9qPӄ'QV` S0#l6ܟD]A6j7w(1tR)B S\lSK:t`Y"pF7?0O3⎞;Be/bE@%;|\G#^ǘBu}`aOGe?$^*OUvTg9q9l:WXz[a0v9? |Mz3.nb_J4%6BoTg<6v}|7Z\+V:IDc V;Cc"y)-J4h@G&9pAH32}Ww/*!-W"P2XED`R Xe Xca_`e%S0N2,s0dE`\eM`eC"Pʅ ̅ɞ !)G.JN\9\b1r&asl-6"&&=8c$)ei ,7($%^P4JZҕ<e'>5{]Z֮2BMTKKLBCA~^ըUJ\&EBYL:J!< HOcrH\")Gc 72OU -U/Io F\Ѵ{4F#J(:Yy;}1Z 1 dj6[4]i8v RR#JT: IZMj![ "RfC'SNz΍ usEC$lD֘Qϫ#x^sRZ>L{H`IBқw7å+r<E,B#.@|p+Jjp§r1"X{ѻ*$brAk,dj&K4`e*j(z~ K2.Ϧ# Xqida"x#E('gL, GۈgINF|;W/1NJ?ϭcUw#Ndo.E\>h=2?#6+EYU8mf2"^DO~l!HZ5Y?swнeV(OZ&rhel~]ԴQjCUjզFX9ik{SPds/ӢY.-$@U^FY3-Gd!i^{F@m.LXpSZ,ȬBs;+*ؐ>/ cR{$_IVKǎi%CKF:T"h@IIOZ \^cC x{ eTDrK^Aj}4E53iIoLnf؃6SYr9Yzl>]5 9C m8`t+UXsXaFAcٹc6NUŸ xLZHR$0?qMD9:+ɍ-'?dG!,J:ns'MH/]yiQm.bփᮈpq(&"lȀ/C)0.'UMz-D9x_c-Pͼlj Ij%& Y;*6 ,/n&SuVm\7)*43n'geaApɞxwrB _}aF "5uK6=|EeJG]]toQ Kj@@'U!wk 5n%rݝu P_ ~ .ؖ7K’_/nryga'+/biKhcH3lhy+ʯ'}HATi2&rZ=pcj <` 7)dIU5u*ΏyS";ΙK9 -VѤ lڬ`Lt| Ɯ=vX(Wuq&5Ϙ j96O kf/ʫwhRљb46C"T6Ֆy` ~_LjMΏB&2 H(r%v먰dd`*(kv i{VBя.9_ml6N`'*(Oh/PGKyljpkQDQ}!԰mP7Ƥ$ _#Pk Zo,HMdUQ?\j6Dn~ ABK9􇺄eqEGu|| njO>j9dD7?JV@@'ZIU[6jO BRKtL3^&Zؽ,# ' GyT~r,#΀QCJ $,W""#.֛Z60ܝŵB.<1䉘hlr&Ա&*E=}ցhM’bjV9(`QU3~c=(Q:lj+rvRz3覍:NڇC/Q̙#x<y+Ƀ0]]I8Te҉gxRd/P<]יI? W,RsV+KQ409}^*<-Q۾`&C֖ /`WsyU|lנ[3fn8Mi,lh$HȦW t4M=3%b;TI W,oQ]ҐYz6:|h].c{?r_Ñk-)KK?ReWy0C44"˾mUFNy/r=~ Jb~W~O0$ep3#-ͫ2=$CB26[)\HR hi RhmCx>ҴD]y`F}a|&/ϜLh:$뷀%eHyb3!QPy)O" Ŧ'ZqF=s9*R`͸׈+6+ҕDL׏ig^DA=cF/=D 6HgTԘUW{@W={60R5ֽ:wFtݾaMcy )F׫rMYDf%8h?ZqC Rfz]5 =pZ'o ` Cq"=$EEk՝h麶vhK[CK-pZZ"H̥xM&i ?* C")JWFי/$)d|<'}5Snoa@m]v%A3Ucc:A$*K'LҤy|DPWJ=N4894F5{m]cjJ>8J6XuYc+,POKS2zW9c~;*~4t%|Hb1xjf mj$H#L-gvrqy|[^ ^dݺ<~"#L~!ǑAU  !1`G 7,;[fLwҠBr;egY‡:FcMNusj/6k_hQJ յ ˷8-|Rp=>T:7)ՂrůN^-6ܙ48sN.UV;=)ԱLr~3ݔ<BR&̈,7ZbL&-tG*rXf+cp{4Orjl,ACӈg(NOk 5tZ6ʡ OdMP:G2$լC!dgɳK\!Pm`d\J4 d?4k FjaY\4 )d6gaܙudFnF3K/U[o"&ad i߼0x4g9)δ.uɏ%obrT8 ؚ+]mLX(%?otVO2Ei+ I]ẗrCȔ×][+?:lg1vD2h i!",I 8U-P86pKXWz\e8X]4>#ŤW,r ;S^7x)7ȎkkziLg#*с鹭طKU,xbV_pO _,Sֳ-/47JgY"O2pVZEQbG[PюK]tz}NZf 1;ĮW}n  fVI`i ڥWBpS$ JTB*>H #=nlˣg EvS*f@XE+ ֶB$ Vx^}4X'9*Ѷxن`%P;9BΧ$3~K80|fEWBS섎#!ŒjQ;/ѶpY5.Pʮ6> AlČikyyf :)1_`8Dnxﯹw汇KW}5Iֻ9^QB?P.zPH fcC*䭺n{D8!u\ c Wls;HQ鴩ӣ[#W %1IR8uzC7mrPkra%E~g?9I7UǥNf{zՙnm$ȓ!jk"8=7U1#V[]5Uٛ RiNxINX'!Tq.0%| H5V(P)^HszHˎEԫSoY} XIfi¤HQ:XE5Â=32$1c;kQF5zKs*qsxaLEAFVmYa2ɓ4ːX:V"X6SO Ed <xJPЇ:Kcj亖*T@)FEH5I#O,J &l=˜֜7/W×y퀨 kPeKM)_r }2#%G>nlD"@#wzFs q cJMgҦRr5`E;_k|Oɠ՞ MH o91p8í2\ l&/+*νč(1v$o6Z5"`ަ ʻְ+!qBk[ϭ,0Pm\{-{#kQ/Ԫeb}%ڟvdJsk^B|mB<~TP즔TMΨ x_ȖFq۠ǖ0 zEBFoqnT$nWһ%#(aG=wDrf13БJ_W+/low>5RuS/84n gD]U`;&FsrlYcBs+iWۛZ{?v*//Y @Tbw`9>y W{X!pw!""/|02,cMphpDhIcqh%thlrh$@%Zѧ"E7t}jՎ rsPN^mrZnЛk*Fn%Q:0jz[ܬlܫ|JRJj ٢t&[/whv#xy^Ky]`PM0NFd$r$,ڂ ^Rf#py~.Z{#;RNy870w:ѡ\7tcQ`?oDITZQJ"Ţ3T%ݳ!(0@~sO9f|@}alߩVa)U{`~4ERk=eb 0 +z@'|e_wEH*1 >Efc 0ȍ?! 'ܤo9rt|tqQ1 P+W{0jy3u>e}n˭_ _?'c~TqӦ23DRf89H>$Tmǭ>p}ɭ:PrJ<4p 8 %/簈X\X(eg`D'_Bb;YM/-R.mW(y"wW$BAw5{P(*Idi#tTW{d= JNOЃ W^~EX#BeH9r '@qdʢd"oUgaK6mU҅J:.oϹ?2{$Rn=-&yJةmE2vvd4{]'y2)484Jq-0XjR-kYy'c eb$'0fHQ)b+Veٞ vyNn|U"@1ɔI^ 75>\u|;kзV^3)v]<'u-'|њq4nⷷ;k"T| GX3P证fX1? S=[]9ˆ[%PrrI/Be[pL3P\*BHf]RUۆo)7C丛p<IM,{#\LR{Nn4]ة5Dn{{ [uhYl`; h K\MWfoCd V*mFfҵ'$܆u(jԠ֜ j/`LM|COOj&6UjFG ݉N (uL|] PBsQ:UƊi~fv)ݨ7e<7O*qW&z窪HzяqRge]b:U"&$;;86!mqC'|ƃrqȫ&uj9k6ˆI*F'̰}w?Q&V0sn0\Ykh}-7TYrl!j B;8{FBSg1k?xv{$/\FAʱ$:F"YIQ04g|p*mÚBA=L9`:qDc%E:c}qGPKy'FN( 9@J2*.WCud O!|߿hڍaoZ;1zo5p{.f!zূ}Es20\ M[bx,sNV%4(:*=t&.ǠaυK^[_MQ.?\PJS1){N:97#9 ]Ճ,3w A5_ q 6Ds9U8\rBX?G󌖞s,t)\}A q@G٭}thn|CP~dWRt1ϑh&`] jVG \|p,|c,\Mjs'_TUwW|xx^0FY~$4L6]30 6zb"e*9eR&d {s0~( Xr[ ڮ_[;J g8{c8>šl12Yh8]/lU9>Xe4Faw,)d|ﺣy.}9yC|X&DMs/ c``b1qڰl2ֿbH$IKŏ뼨-]W#Kٺ{:Ђyo rF˜B-Sx_tGOܘN~ M0'ӮLϠ^FL8Ækhs+;1<2jY/HqB(}^[fܸt[yZ""^oۨWS˦5cf1{g9eHj9)Z$Caui]KҸ7!14w!S ƏI6ٍzy}=Yy ,N z%kGь\Wv#fE(d6# t&Tx8 hI>W>Xd#8oFozv)9:hl7/OƃgxR"I'}« Op;%圾JԶވSv)Vw'$y3@FC{UR|oc eH2s̀!_c3Fv#v,k,!u{\{#]rx3r& Z#, FPA026ow!OVZެdyd G }|AWtŮH\r2y:zn\QʸGN9Hc{URlos5eH 4s嚬ϊ~ I-֭Ϭv3?R*Iri=Rg;#;g({u譣}7C?R~?GAh!S P;0PAm6vPڤTXT2MAy鋞̰ͫqCcTQnӃ""P#[GsY,Jssp]όx LAN/5J_^65荌W9L"i=-"P⧋k٭ůBsc;[qUGTg+jӕQ2/AYu層n xyW+!5$KYoa'}vEoVs̳$Y?Nsg?Bܟ$Ȁ*:ca2bKd`I`W$N)\~쭶h˴u7ouZR +h2?v6r| 9.:sE䘱S沕Y \Xj6 K3̇d0dPz%s%_7eCX|3?J!h¥h*h֢|Paj^{i/1px^;FRR+# lxB5l$:N:r-Q[!sOKJ'|6=rWV>^Qm<7uPʷLk:u1IZjLe3u#t_Yv9W㠁 ̋,H.N ZMsy#14q&PlV1a**t6:}uEieM"9yHGWGL 5T-B%EKE4D{5*V3)*2 UHd"L僼6TTU^+c*`ǪB *+߹%Wı}4Hk{y E@3ƕԂ&yB/O >?HQqfX$ªh*}M_<9!#6) AaLgރ4FX6Q8d׶*sfv2r1^xK方18 jNb QPG9{M V#9L\kJ=e(&O9Od-OH_LWkL$5FDSxV™2_]Ŏ"ag"n >IJ[q^wM5x΄.AܥXnVkA| \V:vGbI4+ްV憯,]w~=dgE>`{̈́%ЄJ"$vscJ!Գ98 OlzMb/M6mZ:SY:qsŘO }#ȖoIkJMI1AivkJ\aCbC-ͩ)AռԽEo0EoD1-(X>%# Jbat7D<Xݭ~fc].T1thRAi+}Ξ艮'ᐿ fm ]ضDř/:S֯t1C"7€V*Y4'̓%'}&ϾT:PxQfP:AD4^qca$TyO$)k֞B7J'>[^cd[|+}:ԀsLCdm@ߺj<υGRd9I ٗ3PH(ں#cGΟTqغE,1{Q 8t4e^p *E[D9ѹ>U>ȷQEE&yxm(6+9~pͦ8'^detEeA: Q%oU4Ƕy҈F KB s >6o/uhb&s[9P' bCOZRQXc~ 7eO %ChwCo^f)ہkʃ 9m=Jkwr 31C.P9Stn*SᥘE5D|Eq̙-.a1F_Oޤ { ؒJ9bJC/' 4k].:o- aj-sKrU1(kzjOXh:m7;pAȵ>qH9en@#̔ˍ(gVjla#\tN/9@OET(W!N -ɶfߙ~՟||9Yl.Ù~o^XopB9Tr˒ K"Qz&A({r9xϛIyl9x {-uˆ@$uC 5errGdԇ'J Dg|]B]O)Ri mj^M 4NIj*_2oUDG5T '`v,;/;G'9zah#>qa/?vCOr./ >2q%H2EXu'IN~1ܬG%"q]X{:$ʙzW@~$9ѭJoA11P9EK󵫰&+3b> ĕ Yo˂[$$,2P­۬okTG̸ʶ7:kwW"Y][eKڸު~:CpLoՒauCu:&P FstO=|=Ny|i$@HNUThyjpؙ@Y<<μLR] 4bxW H|F>A##>8biT=hx!k+Kb۠US$4/'LB2l퀑h*s%( !-iG5}C%«iR&@)}0lyLgH鎃uAŐ&G5 ڔTKS$ kzۗ. QS~φxlDge;3\(x|+Z-J\ZQ^6; |4pA@eotHA<Z `jjИP)wҠ.FW[4AewG\p)+ A>}%Wv%C >S]b=[ƺxf>}o'5IΖՍ bԋQF?6`2PIR>EI+\D޴桒!48 of!TH,Fڶ87o%t z_ x\&guƞ|D#gI!Lk#bLlra9a~"."!NpKyRnw%<<Ibdry6*_.rm6yN5ѸzNؓp~cK֩t ǵuw^lB97N+j\FwWƖ"zlP#P%c54U#( $'OD끝38WB&dgp/l/Apw@Q\҈R6 4icoFue[}&%FK3] ML$ߓ,sEX\F毎j zs-w }̆`K"XV&<2Pkp]̩&"Na.Wd?q{%ۭ~Hj h!4 mu;K Unkڝn1%?l,j(EeZ4(+PinO^m! XAb 33Kjg6ddQk]?XlVhYd{)>`0,q ln~Zߖ"I@nq뛣faSCc{I0R1b'\7Cz|?*s|qc$i<)c;'(܇{bLNkm6;Go4Իe%/l.X>9bx߾J :r 2T;I'!"1H2ڇ>tVHR,H2# ۫ 24>]Z"z8=y|>--/Q(nN! u%A`Hh5GfVP0b ^(e26Yf^&}?'Zn:xU$QgG/w22H"bj lj;.1y?km=@3Ѽ}ܴ/B qڽ}++LgcD ߯=qys#Ldl1 =?,9QåGn"8`5&m-ZX$Ȩb}ywOݱ-K^%; e,w-kcp@!f5ۑvmq'z##y0qkG{{]4k;gs6DV*9CI̝?.^HNDTJ̔|DQhеʳ\xuqΉ* /L.=Hj$ozg ؊,ziޠN Q9BZx[4jBd08yW6J4n#VG:PfZ3"1[)X(*M8δC2:+>#;72gѺkלu1VUU,bsTb]] 4ƫ ^d:/t+; %:T.a_uUOD&26-g8gMz,*RmFLE}rqW:c/z;L0v)&D7tpv&RkL1{lr|W.yra0X):թ8~ՐLq*Ѱ\xq>lnSYn(Ȭ@f) 6B/$E"WѪ&>ib)Qx$XLh\`gne:{44>%WB=z . PD, ])QT7µmU1ZQhI|sCɂ9& 㩆%m ]y4ۯ@QaեwGaX(absfdQgSքټ P*}~β>IjQx7/K%_hx_ r[l3[11EhjOGoG-P4p<sI6[pFsy(JLf\p)jhpF%KNiI o)Q\&9Ԍ8`hD͂[Z3ZdZpA-ɯ*3G)2?$v[=-R]@x{'v%|q  H^fg2DK ~UlW{Ftߓ,\sM k<5&+7p@} B΀/mCN=`>B tU@,W[86n.eC ֧[8r7G)uMirs_厤=`a3ط(>mF-䤇gK% pgsd?oAȷ1{YLJ:<^G^B!C {*^3Ct%HF7WƘOir7( Lլ6eGߝO7Y>aחs# :DaVJrn\Np?B7r;oN}e,/t{ֻd$o_-S_ˣ38GsFM0#-Oof$1'E(4qSSv; ED5)ς퐛$W򙽯Ύ5#!E/÷*S+P4@elϫ1'5 Q qk .QѮu;gjjx4AcX[Y~Hh,rӆקn؝ =(Ga@FՒwWbhtő4Z+*qG4:zלTe`'~d\<If^X^2Մ9;߽ 9;و;eSː!@L複gRR1t53˗< k$z2t檒EVgÊ.S0 PK(_eO"&"` Q)eQrXD6UeFf"{-.Q;ԎOwit|@7iVGyYtN~Fx͟J/Y,Kפwٛ?>*jzzG&/-?C AjG~k P ;ؐ{ЭQ(- wHkoZEJqjZmIʌszOL,5!"XN$$ZQ$v9k=˦7;g" D8L S. WX.Q&᙮)lQe/9f)׿nxkΗo[= Y/MVܲ6%DT6UوԌnFwK~]T=湷i8UZ&~Hg&RaM ˎT?UNi{:+}#M(UY|s9mm=eY##{m,D1X"ft1kL<_. ,ia ^TAzUu8)rgƨ=3U#50^(V!вux:Ui#559|F|SjNd8Ż$A:@V+7iPS V?7Y'nߖ>8Rh+ʲ,/1|Bay7p;b1d,C}(3FBg8v& fV]7)Fskv4prxH-Glg\dwFyw.$!͔h%b9ƃYl؟̥;BuP7fz ,Ȓ)6]馦+ f7@L QZU/,[Fxyҁ3y5Ο:t5ЍWDa8NH*hpֳy:T!6lɮo˗L˱41o/b0Z2Y5293ߙOL .NWDS“-'Cgk@/ɂ5`N.EUy^N;.O"YևWb{|Y46/-Ŭ蠖IkX K׷|R~)hZ 6Ga]_;ٓ5c ۣ=FX!l KIPa {I\{kܮ.}-+I4pT4 G!4/*( |+xBqTFQ@I(S(Pq%fG-JH- g=Dn=2Fk@n '' #pʯNYo/?Arn9S.DIYß8? ylo؟ SJ0̦:7~ 8wa.DX2oP1=bt5tYl1lw{;B1׸xc75>*5kKjhV2ԔaCcsuDZ}`&+ۦvOi-Ԛ:w"c._,'iVµƬ 7hHeydA87F4f\"NU:mHױ0JVɍx?wKˎXHȡZ TP8cq*_*+1nS85FJ-2PŀRvD=-:pra(_"P '߼*(NT ܼMh=׏A)X$zP.y:JxfNZrSz 7/>7P_Rw;f߷jૉa40U,I,V0x^`v(3˼춠Btܬ8Gu\>L E9TYs0x~&~#[Y':)f:Cnf5m.(/1ڻbMFRߛ#0lK.I =A@ƕbrN s$/HͭeVFy7]DuFmhӘWk265~B[햛0l-I@QP dC;~ޥ,NhAJd_î< ϥb%HxT;N^cZg kE &fBT;x]"U[~(*"'Aؙ*,>6)εwkסV;v*#F#h}n86zԸA nOn%{߸H0Nt| g.yOXcF#w&HK)H ܍ B ÛN 'n7 mӝtƦ9"Gb#>>(ԏ OEOՓ/`|Mwה@`Y.c X* GebSy/^[Dt-|™mciXbizb)"G'q'ɏEE؋ﴅE+uaĒXNZCm kB&|Jݵwn<~'hr&~r<K5VKqECoH`;ȥm?R_p4Yk!:ߡZx֪O,=!in<˳SǓ@;iW*'LkԵ ǼdkmrдOJϿe#gp?\!7!//R9c|K'R+jcg0.fs9,h^-oGw$kQI1( WA_ }0@ʣV PvÆu/pv([5lc';_. jG"\Ser";y!PR1Q3'Xī( F$ 'Z-q y6$.;0Qgz7.u B431r(eFZh7E1E#k8fI=*32 Qd@υR(axr> ?rF +x:N>N(X+8\An6a/ը(bז@t{ ZTĴ?Oo"%{|YIS1\gy2fG_Ԩo~:0\8rm} AQWT˫֤z\G'9Ɩ5 Z{gkl`igui5-'#:9nouC#Vv/ ؾ%;kJCg."^ |jSqǼaAezGߗxm/k贼Ο}v>ILC餛Z,޷m7廬d4djzV`ә'I9j-x%?n[5 3k{)ۙ& [y5:P/%3!^TKz,ZGu%!")H.1j ST5 }1&9h+<8~QfpUu_TVo4*wP[Nq 6և rݠ\##ۀ6!a|߃*En}R2\mĢtՅ̉s"Hp30v&ko=lUH-k!NjQ;w@P Lz$86'Td nPf2:v3Q_Xi*9<:ڿ=(./F 4p.kb ctdWsMG)<Ɣ~eR7\g_[Kd)]K8RvVZ Dw(QViAk[_mPQğFe1CU2'bgLǖ>+œo : Ң~<*>pTT%;nua/'˔ynpUR & UؤK欍zNB/L6=6;2^06vrK(Fkgq:S%h-ո3Ņixc-y4a16+h4}GՁȱS2G1 m(.-5o za_R 14a C-;3~a~"Me QbiUC\7"bntV;/Y+u>.qfCڃ6]o|svP-p{piӉߗy$bu| 敀4 Y[x7Pbq&XWe5DIDC o}sh ˙r;g땫XScIƕsiMtum~5T9Wֱ/as54frr_crkohw"T6NKXXuϐ bIp=qOe'5h-G҄s"$KcA8%C#ד=U>1Z>kbj)ذ|:x߰ys`B`u ~cJw`=Gs$>'Kʙlw$FtsƼ WinքL&B S|:zR</[vE/9v]*~Yeu?KBo+ҧ#ʿ!/ 9n?<6@wOFyasW.G{;roN,|bBTq蓍#Ifa(j[Tċ#Bs+.27RGM ݳJeH(.J1Ϭ2G%md2w_%zώsdrdoAɡg"i% wLs)YgBjn/$pw 50` s1>QX*jyv:Q#՟mCyEk>O l>eU&xgRمkE; aCcQ^D &.RGM!bOE \`~ABcƪmЬxJ%iv1y#d_+YS<']FyUAY+23VFLC3v!)SI'#'ߞuOl?8Qg/\.;"'?f]CaKHR(-a_qH> n1nȋ?{_QR}fńLUV9 z;0@&UdE{[LY,% %:KZU$nҰ'9j^G!)Ǹ?oSsbLQUsz}5twxK7MP=R:6Rw~)HJ?&,ntuؘ{vhI* %n-Fm~H8 ބ$o?a$'sEm Nf*C2|q\6; JC12Oea3C@;v?jbq m,4\jGSdP*eY3eF0(mAL]$m$!BKSu}]Ía;Q;p%;r560\}Vbp=/G`26y:~w}F c{XK*g,)&B84G=D훑E;W'#ҏXᖎpLuEYYI^$RJ>gv⊦OyӋ+wzB(~r'KZi|>{ȻF~ULc{+[ݏs>⬘c-𶡂`&m'%.@a L(tn5Bw|QfpdU]gjM_P8<@ō۪rEA3ʘ< T*U K&&-3hh"| 9&xR7^z0 Ȥ1/ dRiNVTLA/>!/|9HacR2 H( :!cAzXOoyV(ZK)+/ɣ:T]Fޖ츨@OLfVf4׃p!GLQ&KBxI;W:g7]MC<_! xsiJs:qU=;+&N*0P(pHuח>Fcafy%&xMKm^Ȁ tP?W&bZcʛEoAJx$ gך;w0=I &S`)2*-hu/޴_kR99肱^(qߴ}aiFO1u`;]nCk<6ū%J=l;|󕜊+U^|Dl%*P$b. pZ2\g4|=2%+e/##J}⨜ջ\![͓M*Jm^57'a7RF%[`4D즏eڣ{f-~N թŵ&Bc8sZerQmxA%A_RKQ1qw3J ś*+mIl!5_-kgj$*C>jRg4a+0R:zR !utH!R78Mnf^UO/ ݱ܂?Hl¥9avDZ(u'!J[r̻8m!8D9 ZTWVMŠoDҰ%VP59i\8blU ]\b{26l[l.촙5x׊e6vȿ@+~gsǥˉ_|>E^o} H4ϥYƗu :P@C06&bc #~#42L9?_59JL5U$ZT<7+Lͫt+Ÿb&h!wB˦w9*$"cW8).yv(MD޹uaufYT)3ӟ1Mu,-bJ@a7m$rk Fy=!2Gꪒ!ɧ{*a̺"<`J'xp[H*ПnH/.21x^B—J&K~\kDž!ΉTO5Smc .w "߶2XLZ\lkH2 zC&*GiHί$ & i@GF ?Z(Y 3$=@f;cg0hv xCB'1 (&UƁQϷNON<M]"gG^E?Tvr^&̾BiRDņvI%*0Y-XZajYY"%#o#ZQ5+?O`cO+RS>+A+CZ"[܌HKVPB= gaLR8< \p3x;Dm!GoEk|$٣F]_FpXfSL:P154) G΀U09;tXe.UjRc3IG//O ϙ YէJ0ˌ #X!РPT IWG SJ<-<(("O GPBimHi;ޅJ 4YRC/(ϺH(ƇN) ZS@<ĭkr1"$0D>"+(a̭.2JJLu?Tb@.I#Jf`)PUhZgs u(m'w:r1 9 2LJ ;P,JQEI?@ֈvMWW.yBL XM7+"eJ0Y g(46kt<sy\wA35B }M#qi4aZCxYN8N s 8Wh"N*妝|"b jL᥅%ru91>L3yz;#d_GEKuPbuL(v.kpa . -/#NW3ȃJ&} 23U?FP9#7pk_r=Rمiq=EN5}2,_aF:'=WOK'dMN9l+Rf#*V`WtzA ±NK Fbvs@mnoť`@xyF";[R ZsL%7ۿp&ս#s~?-V6=3ƳdHJ}8 kb 5Gzj c^VT9 2F=wa1g+^>L,w勪h>nH0u$fo O` Ng/WbUJaDck/^oDoWJ9ixC)<-!/` H2&!;IE8ՀA%0ծ(1FTt-FQ8})0 u֐T2<&jDA$@ d9UɈF|N1FXw1$4=zsΈH V43K;El%F 8\*mJq4 ÒL3C?qHn7vF΍:tlc#C}j||<4R^<ĜזĂ$T{޶q\تo2!(iuŇyB+WyΨ*M=W^!|oqDȬmLSx$[jVcU {MՓe̬M `E{ܱ /IP՚[uu$U"JE }NѺY$`Ճa+aVrΨj( 7r4ՠvl jwx$z `;`eG2٠-(!)· g Go8|d>>9%T&$t ׭ uqhuKPJz<3a%>=z[d\Xep8ly$LK&Qɹ G&1V-é4UsJ1z|zWCu2܏nk@īwfqEGpr 'Hy>E\Ieڤ{R@orߴLN" ҷtȶ&1`ftϏ9BMzn9<\/hW`>##)3/oh)MFUoƥ4GGrA>ꇝg꠬NCh|'Ft^ ǜ#1"Qi'l1>ؒx|?Xhn4Z)Q-MDuT2VGejFf@[t ڂHq@p7O"(캟\C ֲ˙ f9f9c9 f9f9Ǜ2J#!PcZœ澋sB"~0zĊD1%a1*P=#15HGތU,,,E{T^ՈCyrh^R,r``E1GZsᴏu4q !..)q8!.:qdv7%{bԚƧHt> y@q v@R"1gzgnkqRgiCgr۲lύ?De_i[SBafl:jGaJx(dw@]jI>[Iz+Z8C`״">WoH'#%a{̏ơUǾVE~Q1ǔUmxnوwkn ?}dFw]j Qwu0*:ٱ%2k~Ź*SkӐ>|idywM8l0a? YF?m'~g}o `P(r6mWnjOe?mS +HKBzܦ )Khj fMzËn1"H'Ӽ UeFï&cÖ<uzeFeCH4U/&| gzN♒okd;-|M-:ҪVҥg ukDȟ̕B5yqVv_ҹ)8fGVS#{|-9wl_7X 4*v^) }PQÍ(&;LZ:9X>j YښJ5hgj`a6P,P3$`Ҹj 筐9k7wMljWHhڑB]j5wl?=X彐Z K&Uke/#TyYHpȔkV[U?{EnN_Hp`Ll٘>9/l8`CM%OJ3m7M?U 4&WGgc5FsjF]Q_ W/Aӝ+ڹڱrSbz੣}6s 6(oc;!˦+z NŌXBO̜ F;r>]-&cʮcWф|)tMNޒO/\ߤ;r ܷL!/Oft6ԇl}o 2wx`lFM1 A%TA_P"1$/NIemZDq rI[3mm45 b{0So \oAF26iQL}p/1@c+Ý[`iLRdh I!N N$;B8rh':Lr+]N "wME]k-d OtEr@A'he{I'laZ)i֬}DX1Wߟ̎!_:Zr⎆a~Oq[.8J>惚Yq *5gp`1?mhÂ`Ðui o<{U#+X<83Prڸ_0u% !OlUDy$}'qxS:zʫ7<f2=ñ[z鐻ֈ.ɉ?3 fAиAھ=-zC{wzMta0xjױԢi:YZ1jғdVAsW_VVUDYtiaeri0LT0:3\61 8*ZV2}ё-9GUיoT2 LSA,K<$?)t?{p Lguk~}aH1&6.8q4w|vdFYT[vU<3v)U8i*wHS],V b_PzBB]:QB97aqA Hx\DL &![ a%ւA"})Y,׌[9eS! E2*s1:)4WHj>tݙϻ"ATSȧf&hM6fRs.:fà9A9% W`uϐ ,%y}B S2^o;}s/]!844bёT4UvFOG[zHhy\T 2J<Ƴ cJi_0Q9R@5=4c~%5@r]n3.ah#\2ʍ \)-τjx`A 4}v\Q4'lwc#{u|Aٜ-!Sv {\BСj>ƻ>u{PoKX7ڜEz30} VR2)̅fHnmTecb4GN"(kaILjE.C΀'ƭ0Q0ˁS:%^|gR=,9Z#NArUJUJxJ$#aVw,47RɥԴqɶi9(@٥xDZ,t4BA>C}$b>{з5&36QVN96.Ě-~tUU65G+ uSq8ْsl r4c&:+Mr$`u.xw.S;y=o ^ ! -ZZyH/eO?sʳsKOYWbc5zyv&6Op.zW,TNbҺ*Ƣeٖ{?bA81}zU˶-V`zӆCanc󳸃ls81Ǝ}LiQv Y YⷎBkE׶<&[y ֹyA:o!ܭqUӨuT;FgUZC!@K (uCp[Kn{wI"KEB2%Ҧʑ˟E2$SR[9*`v{e3[)7ՃzRAIbȋ_{N>9k!=SylG B[`^è~KG諜_D'{οҾ=grN 5ֽ c=i65d5҃uS-{4=^=wjڄ§^(8mi4I8m1/o촴8vT@źiY hiy|bF{}bApWf%U='7+=ZaـW6d{Zb ц_`\ۇH6hc`mNDoι.w!gĿCSz4آr#[g!cmc c>*'Rf% ,r?SoF9C3E4l ":pk#Ta  7r~vS 0\s,U^'{'J1)QTu c~; x*wƅ#1^NJ y,n4GO vjӬ ~JPD=V˱k+_0|cOJӵi1@:<>?}ԙ< 4-3S㵷77 F B¿oO#XHb]o5p֭=#"{8 FױK`EIy`xJ gw.L鿔U[+d,gHaܹ&ߘp4eJB$p4s@Xr"ɼ?bYΖ F$;H,@%_DH>y4q _2jY$i|vJckCfᡄp򜴽O;6%ht#SLHGι@M[px1G] 5^W_ !ώlpѫ(8[t^,.tp7nSo=Iɿ 9ͼl,(\Ⱥ(%۪m {0'o T $ϋ4UVKVoLZ+-\.}oy._/9bAkT8[xYKM@\Fi4iK9Kʤ{Vc,ZNB$Jay(ܭ sjVstO4»J]st4U@hLDsQht޴ i0ɷvgdži__yRx{CXc|GpgżYE+ BbQHTȺ꤬2eKLr"⮬J$!@LN~ѽE|7 UbgILonZ9o]뀥lU4ΥK.J)x݂*m^TU*ivYdqps{K]f `(ޏǖp#L5/X\NJ؄ĸEA(9-:['"rN7Z ]Ja_NFT1]d%ޒ:ϖ"AٜaxL6Wdgg..mW<ϯx'q<Dd|Y]UV Ƽ,oC^#[̹h39oLI% xrmxYη#:B#BVǤ`orNiFt/o&8$2Ag:αړDxYU{%&;'B9zJ6*zJ@. Vxs,CWFU^J [{=d,}s <;Ue}&{W|}b#hfW) wyiPF,CB髝U2Y=;6hVOߐO6‹Czo̗0oFDP7ܘ5v=V#c;=Z%:2p0cq_fOP1~P'扻J) 9E558j !$։~r vb!&зX˔"\3Gwb{u=ƮOikm/gYKtAMPfUkVAdJ̚@go_1%MUTmZ65Fg DJU>o3 +׹69jEBZ4`fz z&9P_z8 u\Dv-N)H6YeNgŝgbp7=Xg̵L5Igi6"us)fj0<j˨*Z3UoQbg9,?ѬT=)i ;v֊n$L #)l^(p$tNP؍ L#~|) Yg@1-i\vZM}$tmx28P'R"!J 6F+ctfۄu]+޿cTsFz"Yr0mdK /OMqK,|@4 6,cB>,ҡe]dckI nYX (1:ut^RܜuOƃBuABsq[yt6^]Hf/eiK2j!lHk8S}39>iiv&E1#L{vEn (Xn#mu)$-ss}5#=3]i=ŝ:V+Jl޴zfn\]GM WJGSZm>6W^,\Gtnݗlvλ&pNS.6ajӖD{}r׶uU Y'n0 '0 -0K𖮎8b;=YVUDL?stA%1G_˂F ak^n*Bq)$M^ DB/X'nMr_z UrV+7۶^R7|;/Tt#N[Ry^P8DF˟۹[#*k2.0.9EGQDp?"{ 2haVbE^6]摢*.N‚wRs] bd܅PL1%0,- fҝtV HNLEiϕcv@-akN z(1s=X%ڃ!cwKQCfA74QP&Uj[)bء!v Φiίh-X\"kwCiqsZ WWgq:Rt#}SuOKFE`C/#y^>>Jy:s:/9t 1^ ?3Og>EJ%ϣgxK^xUWœ ;O Ω UR#CgS+`E-ڀVV򿴼[.l=8V5)G0@(bfy=1!hQ]XY41 ċ#u5MS9rgvb^,Mm[_$P1jaոuӓ!W2| hZҭYv}NfAܫf_-R0B{'ʱ_e,W–TiŰèWZ UagCmP/iY}~*|òeҵA"1J m"6Ҕݰ[T>5ܥo~;\onĤkm`yCWЉxoNfmc"ZCiP-BD,g$xydD銃ڕf%OYW\\RjuDРoo?ۡW@0mCRާ 4qp{[8[v"' n+$G{Qs.=,[KFDFi??O/xz|MhNi (7GdC9ٙUֆr'm~ Iz/~7uWob2>|oųq"/SQg#3,v53)4Pg=9~wɔB꿥kb %SxL,:3b&d6C_lK$uiU)|t>FY1P$jA 8M>?E}b6sv: :i[P]S˳~ؒUTDuI9#gׂn~N,u_`ȁn*&}2<0q#C?s!i6%-{?hY q= !MNF*9 Gz6!@:o:df@wmal5Nqo0}\Jq2R:hgƝ8:z'}X KtΡ 5;tz:dy`ױ>{O ĵyD Xʎ'FlKqAWY;oo.~]Dj ck]|شeRq)6ERx^5LG*$CA8C2hUҎ(!IM,}qh܇ԛiv4F=aWۨSS C;jg|V+QAyNP7yH9^/MM(?r5~~%$sw :?t 1:a1M K__s:0[& Gf|Nk.?M VM@.ֆf"߄$вXEc7I&l7{1+0MCdZ^J0܁ qlTlrGoŊw-FDBP%16D>BR$o PmpLN[JqEu*[" sG oleugp(nB(\vmD:ƿEYժȿt/`aW%E}H (/=+nB"( U$$I>նǠ@vE}#SUI14qU-hשkC^}#h Hch`‰>Q)oԾ8>D-&GXhz('s`lv(GӷE +kC5Oe* Mɮ^6g{0FHٔVQmCJsJf;E*ҔB9a?gl_[ʨunk2Z?0;G&[觃dZLՑgؘq@hP4at6 |VJ2SLTo5(X?aeML*r#:^ hdN0%es]ed t0332sze$W*yjZlJ@>^nA ϟ3Pα0Fm=!eu`Va3WdEuDb"C] Wc4oWZ! tzj}Vo:%$#$ vD`AXt-mgGm6Ïw2D-N7v>-ހ.\KM@ Pƴ`jSގf_n(%3΄D ̧guO;':آLax*e+=8'%)b_~2)eWExD9ʋ5õl¢{3K)Qѳ%/譗=+yJ2tؐl+^t u$+4 EVO.ױf ;6?y{FA106f4 K!u3I~͂fLI'IӆpNqO=QGS0+=3PgFxhR>^;+uI|ؐ7u_&57/ļm `Yv|5t:5mĬٱ@Z +҃~=G+zhw_|H#]B ]rWO;rr%= BjdY?RG,1$s?1K-"bZ(n$c]1`֭JFr>%T]O+ j ?{J`EdžEo3%mpOA$/u)yW5/KHJ![b#7Дi_>JIwd?<@KhYㅱQ(خ)굪v3g4 )GZcfTAnMk553erqҴ2֮c^MIfI(VLF'6[#4&6Jd^@vSҴ^[}lT`pċ$X9jՠTp"/1zt^R]QIp"XΫ-ƞ\O<߼KÙ8BTY$,Ö!W7&̡,C:t ~!C;A:n!^o@WH!ߴsD N[H55flLG-ǀU(7IGp>Ir5/W<;IsP")eVxRcbOQ/bL -z|֞Zu=G7l!SzD2CjPlaǰ! ]y_*ZL*5(zT*Mt9yDQ) ?%'pgAx0҇ځc! ;qBK#'`%I]c0ZR'6o n7>.<'@U0!%p"$hK$Hɤ)F:2\u_gM1|~!2a 7ZXk)X63uZnE&n  /OxheuSPrV=nGٴ;K(oʒG/AB1)V¬TrũdQFvSkzoQf #*G!*)JA +*Ҫ(mln`XBIetZ:zr  $ BQ"L &_-8\_ %R\T5ZPh2[Zmwptr.7(Uj^ӫ*B1X@$)Td9\_ ܹI-N$)Td9\_ %R\TF&j;.50-!m)Iiَ2mƬ9TIYEU 3H & EiqYvٽ\9)j[ѕ8VVjUWsu~[ӵ\u\X̵̷g@ap`qxDPitpy|P$HerRhuzdX;8:9Bap`qxDPitpy|P$HerE%eU5u M-m]=}C#cS3s K+k[A1H"S4:bs< EbT&W(UjlqM7LKHqAj *jZ:zL1kURVQU$bs<@(K(V7[P 0 #(4$2J3,6 "D*+*F&MD,O :ZmaY9ӫpc6xpe :~^C#cS|&?ֵGBLBX"vNүIB7Mffw8]kaZBڎ RD1Ͷ*ۆ(6eb#% Lfj8tj>bd]Z_җZEh19UҎUqXQX9R:A$$A3. YWިS^y3jTlҸ_)q0jVGNV}+P!X@NKӡ:{+#,R ["V.e5)X$W`"~⮳I@MvQҪ+*[5! ҆TobhYc[*N H;aBRi"L(B*m[0 Nn „2.:ʸJVaBRi㜐9c8ts| ?RۛLIh6Ud6,Jvv0=z>gY >xdpf)1Sd/;+9nX7X.b9nj5B㬹ˁ/>rdxPʸj_xVK=;b&[SE|g_~aJ.ɞRu8١I:! „2.:uʸJ6"!69=tIRJ)rC"L(B*m0 Nn „2.:]ʸJDPƅTX' „2.:DPƅTX'M $RfXNf'HHera9E|! A"i]pT&S0$H29Ͱ"!$R ܕͱۿ>ܮpiѨ iiԮPiRu hZX`y=NwS]ɠAG4\`++~ً-n}@ڌb'mBKt6ef}iiD+3K+9}qx^k# uD=psoF[)ݨL05Ξ/(ooOh~w} g(EeT<Gxlbx6pڔf{ ~'we`cǔ%!ޭ;{rk%uZD̂DSl0aO=bG7@_doxP\٦۲l,dlMe^2~Nsa%ʏXwTJ B*}r?0,`'H4æd %R~1/gBsfzM M7TLn39N')'778aBRi zJ|os\FeNüigm(hnICyXgxx*/4@}R `RIC 6v\cn\++"-=1)@EI5xsʸ8N'ꌙw$9k^>J>"QLk>߯=$oB7_.iPgl;EZQ%`C:yYtjЪb(4}P7 D)Y{  `e{3/HfPֆ*Vs׳hvٿíÌg->I4lU_&up)ĶQBizPjIoh RzT[8wk4|$J3pVeY|N72|"}ު inc/fonts/TitilliumWeb-Black.ttf000060400000140260147177152050012621 0ustar00DSIGFFTMeRXGDEFt GPOSKGSUB?z3EOS/2kɂ`cmaphu gaspPglyf8l headv`6hheaT$hmtx& loca.~ maxpGx nameV)postX preph mz;_< ̏u2'|9m|rgD@XKX^/ UKWN@ m|m  M" && FF&,! d&& &*&+&#&&&&1& & & &L&;&W_% k$AaWdiB VGN9U!&Sy.X(N- 9:(f2 B)]B4::ps A# "i"g&="&)&!&'E!SU_p&U<&}&,^+^!A&B Ah^apr+r%%%%$$&zzNc- - - - - - ' ((((B44444&+4AAAA"9"- - - :%(%(%(%(%(k2 k2 k2 k2 BB$$$$$Aa)4BBBB444v\ipipipBBBB s  s  r AAAAAA N"N999s- r; 4B s AA,ZPA% &   - (4N"N"0$   $y3lbb^^ ^^^*^ ^^^^,^!^^^^)^ ^&P)&(&& &8&>&I&=&;&;&@& l   .""FFU!Shh+AZAA%?,ZS^^^+^!^ ^^^*^ ^&^^^,^!^^^^)^ ^dA`@ ~17>H~    " & 0 : D p y !"!&"""""""+"H"`"e% 49AJ    & 0 9 D p t !"!&"""""""+"H"`"d%A)ofbIFEDA80'\Y~{srkh\@)&    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`adqdeifwok~ujrgvMl{cn:m|gb \]ab^_3k}ijex`chEKpGHIyLJF(Z&Db.b~,^pNh2HTt:Z":L\nDl  & > J p 6 V t . d & L ^ 0 N ^  <Jf~$j$H~,Hd(Z<V6ZX>N@f2d@b0\"Nx(T|LhB|  j !&!|!!!""0"V"j"~""""###:#`######$$$$>$V$t$$$$%%B%j%%%&&>&j&&&''>'Z'''((R(())X)))**6*P*x**+ +.+Z+++, ,4,`,,,--&-F-d-----.&.X../"/T///00<0N0`0t0000011<1b11122d223"3>3Z333333344(4>4T4p4~44455 5D5^55556*6N6`66667*7<7v7778*8Z8p888889 9Z9z999999::*:L:t::::; ;L;x;;;;;;;<$>P>d>>??p???@@@D@p@@@@A 353'3V '33'3- f  37#737#73733733#3##7#3797574>:789> >qP{{{{PqqqrPP$(&"#5&/73264&'.546753~mF@wx>tX `4cvz>Y`   -VuhII \gdRR %62"&6"26462"&6"264,@=>>@=>>; QPQQUeQPQQUe '267' &5467&54654"27'Q.4]; !A.Yւ66$=k]$|@3a;8}77YrNV)R!!-Z = '3- >#&'&46?3*%? 2|:;oH76664&/3#6)*%? 2:;oH76T'''7'777e&}NNUVNM&f_)bAk66lAc)^, 753533##5, 3 Og(GV75!*353/, 6  &"264. v"rss  * P 99:"*#'7<m7+)576707>54&#"'6236W*&H< h32&"3242'" #&rluR'`2Wo%ph!/""mpN&  .'a15!'51İ=. $2 5467.5464'#33654#/-4"&1+ ( "Z$uDAFAACA:Q]2- 7267#"&4632#"/77274&#"'" #&rluQ(`2Wo%ph!/""mpN&   .'a35353  3 53 Og(pL%5%~% +ݗ;95!5!;P᪪W'55F~ ݞ#&4>4&#"'6253%3M!Y >?qiJE$7T/B' %^%9C"'#"&5325326=4."37#".>3227&=&"b6FSob;- OqfZ80(Cb0p-C{&);~55u O50RQd;(#KB%,  4y j. "8) #!#'#3'_T&c$bMMS !2)#3264&'#3264&/*1%66#$34?D=G n?k9%".54632&"37jx5{Hb#R(*/ ?Ǔ 5@~)!2&+3276CX%@))4< 3!!3#!9< 3!#3#lP".54632&"375#'P{F3&&y%$7"'Zz^ G2q !5##3353b33b&#52>765&0%a%< b.% H\i %#3373#'(KkuQ)33>93!!####Y4+c :9 bYR 33353##b6264&" &6 !i j!NKJIKmU %##!2'3264&+%+%#-ns&\ b "&6 '264&"LR`Pb l%g!!g% rxPwW MLKMY %##!2#24+?9JB'173g<d8"&"#"&/73254&'.54632QA@&' b45e_* 1G<|j  ]jd 5!## ώg2653 &5DώIVspZ!33Z4/bL333333!'UO -2J! "LVbcS 73#'#=N䑈;=쏏A]^!#5373?A4% 5!3!55ώ!B#3!B@@h/,25!!53!@8.9L'#3z;?Ґ9e(G05!(N-f3#N+Ӧ #"&/"&46?54#"'632275 N:0>ZfnH*[[!mr?D"V  #Q=  #"$%0) 2#"/36254&#cv@-B", xX/"2&"37#"&6 ETgF `WjrOw)s #'#"&535"375&72nXQ N# ,Q,732? &6 '4&",dd'u~ *#yrvcz_##5354632"3 Hd1BRPDDlV   $)$-5&5467&546?&46327##"'2"7254&#'264&"\P$$Qs!6/ nS!(M 2**Y$82 % &QlI Fg  S((+3#3632#54#F%mW&)rW3353$533'>0fH>(PiL$ ") 3#3373#'#-HN/33NF3#362632#54##54#B)GOuV!+ %'--}aBa+3#3632#54#?/lV$+'uW%  &264&" ..}||$a$$a=*2#"/#36254&#dj\ew,1, ~ 'X/"> "4632#5"375&Ɓ=-B", | H_X/"f 3#363"?+"6/< &"#"&/7254.54632|ZHmq?r|aGukrQOIR  INfR b]37#"&=#53533 -V.]P''QDhMhdd%3#5#"&5337E@2jT,%{-""333!$ "U>  33333!'!  31> 7373#'#bc((YV(!=" 3333#7VU$ w?>D 5!3!57Ù:6í÷zX#"&'&54654'565'476763! -ui4 ,, &*>A[.Q3//-b&*Vx  R$& "$3"evX#7'467.574&'52#5>V! -ui5 ,, &*?@[.iQ4./-b&)Vx  R#' =m$"&"'>232?:&7 J:'1,  , [ #5#V)O5.46753&#"37s\bm32&"3#37!5_>>9Q1ZJGW%]vy<)K_5*<'!627'"''7&47'7264'&":<;+<--<+;<:8+8//8+N5N-0<+;;;;+;/,8+7<<8+4NN6533733#3##5#535'0Pp%)vPh~~+<*<><<>!$3#3#!uz==*4&"#"&/73254.47&'&5463264'&"[$B}Z-<('#6,Q+v0+, \ =$  @+*-  &D4!% |a  , /53!53/>'6&462264&"&4632'&#"32?#zz{;=G'#$y{HEV%KR {N"'#"546?54#'62'275%$-n?>/GF , {\1! R,3gN_  ] '57'57OrrrrJJJ#5!5ȡ>"6&462264&"#32#'#'324#|z{A`4>)d"#x;3]+n]OO<35!<G3}462"6264&}SSS3 نSSR! , 753533##5!!,2TTGGQ+4!57>7654#'63203-7 #.UBA  lp2  gw   !?#5324#'632#"/72764RM(_K(VMKO0?C2f$c0>"!H8 e!-3#mӦ3#'#337;* ,.!- ##5#"&463!-Fcc/Ҏ̐]753͕hf #"/73254&+53+;?@A-& I"#n4N p,)#5'7)S$s"R{R2"&4264&"[KKL!BBBy0, b ?'7?'7rrnrrTJJJ #5'7%5#5733573#)S$`/c6Ns"Rg@;0b7Iq0 )%#5'7!57>7654#'63203/lS$7 #.UBA  l@s"Rbp2  gw   +2!5#5733573#%#5324#'632#"/727646Nw/RM(_K(VMKO0?C20b7Iq0@f$c0>"!H8 e!:74676?332?"&#5%3M!Y >?qip JE$7T/B' %^aQ 3#!#'#3'"_T&c$Q7bMMQ #!#'#3'3#_T&c$imbMMiQ #!#'#3/73#'_T&c$ep bMMለ>>v #!#'#3'"&#"'>232?_T&c$84k (B;f .bMM "j' kY #!#'#3'753!53_T&c$ bMMᐐ24323#'##3&3'24>K57|&c$*=`/1bMM++a!5##!!3#!5#n ;%MM>Y 3!!3#!53!539<ɐQ333#"bQEQ333#mbQFQ 3373#'ep bɈ>>JY 3353!53]bɐ 53!2#!$&+3#3276&v%@)77)4232?84k (B;f .b "j' kQ6264&" &6 3#!i j!N"KJIKmKQ6264&" &6 3#!i j!NhmKJIKmKQ6264&" &6 %73#'!i j!N ep KJIKmÈ>>v"6264&" &6 &"&#"'>232?!i j!N84k (B;f .KJIKm "j' kY6264&" &6 %53!53!i j!NءKJIKmÐ  7''7'~|{~{~~{{~~z67&637+264&"S]U2!i j! 6S~*,GR)0KJIK`Q2653 &573#HҌ"IVtpgQ2653 &573#DώmIVsp`Q2653 &5?3#'HҌmep IVtp+>>gY2653 &5%53!53Dώ=IVsp+^Q !#5373 3#?AĮm4O %##332'3264&+"""Nj(M-&$/HHF6t%] '3#46 #"/73254.4>54"D~Nz/UkhNN=&"s'L^+ŐjOV1&*,>EeW ,2K,= #'"&/"&46?54#"'6322753# N:0>ZfnH*[[!mr?D"+V  #Q=  #"$%0F #'"&/"&46?54#"'6322753# N:0>ZfnH*[[!mr?D" mV  #Q=  #"$%0F #*"&/"&46?54#"'63227573#' N:0>ZfnH*[[!mr?D"[f V  #Q=  #"$%0HH #5"&/"&46?54#"'632275"&#"'>232? N:0>ZfnH*[[!mr?D"4k *?;f .V  #Q=  #"$%0, t(+ u #'+"&/"&46?54#"'63227553!53 N:0>ZfnH*[[!mr?D"AV  #Q=  #"$%0 #+/"&/"&46?54#"'632275462"624 N:0>ZfnH*[[!mr?D"\H{IG} =V  #Q=  #"$%0d11b3x++ "(/%32?"'#"5476?54#"'62632'4&"275-ce&.fY!#D*ZW ~(/M +"#""K$'  #rvcz%0%#"/73254&+5.632&"37h;?@A-& lSrETgF VS"#n4N [ ysO732? &6 '4&"3#,dd'u~ *+#yrvcz732? &6 '4&"3#,dd'u~ *m#yrvcz732? &6 '4&"'73#',dd'u~ *[f #yrvczHH732? &6 '4&"753!53,dd'u~ *=#yrvcz333#+Ӧ>333#mӦ< 3373#'[f -HHF 3353!53Z/#"&462&''7&'7"325&>+mxxn 9?C-7V6'`-YTnwL"YY, n3K++!3#3632#54#6"&#"'>232??/lV$+4k *?;f .'uW, t(+ u%  &264&"3# ..+}||$a$$a%  &264&"3# ..m}||$a$$a%  &264&"73#' ..[f }||$a$$aaHH%!  &264&""&#"'>232? ..4k *?;f .}||$a$$aW, t(+ u%  &264&"53!53 ..@}||$a$$ac+  !!75353+0T6M''7&546327&264&"##>* )7666@/.. >,l?p}H q@t|$a$$a%3#5#"&53373#E@2jT,+%{-"%3#5#"&53373#E@2jT,`m%{-"%3#5#"&533773#'E@2jT,[f %{-"sHH%3#5#"&533753!53E@2jT, %{-"u=" 3333#73#VU$ w?m>DӦ=)632#"/#254&#C%j\ew. , ~ X/"=" 3333#753!53VU$ w?4>D/Q #!#'#3/5!_T&c$AbMMለ #'"&/"&46?54#"'6322755! N:0>ZfnH*[[!mr?D"yGV  #Q=  #"$%0h #!#'#3'6"&5727_T&c$JJtNtbMMUA -- A #+"&/"&46?54#"'632275 5727 N:0>ZfnH*[[!mr?D"tNtV  #Q=  #"$%0 -- %"547'##!#373':_3. 1&c$t@'MMc5h $%,"547'"&46?54#"'63237275Z>ZfnH*[[!mr?D  3. 1"tN-#Q=  #"$j13hi%0Q%".54632&"373#jx5{Hb#R(*/m ?Ǔ 5@2&"37#"&673# ETgF `WjrmOw)sͦQ%".54632&"3773#'jx5{Hb#R(*/fep ?Ǔ 5@ >>2&"37#"&6'73#' ETgF `WjrI[f Ow)s'HHX%".54632&"3753jx5{Hb#R(*/ ?Ǔ 5@ 2&"37#"&6753 ETgF `WjrOw)s-P%".54632&"37'373jx5{Hb#R(*/e p ?Ǔ 5@ >>2&"37#"&67'373 ETgF `Wjr[ fOw)s'HH~P)!2&+3276'373CX%@))4e p<׈>>%73'#'#"&535"375&E>72nXQ N# ,Q, 53!2#!$&+3#3276&v%@)77)4*$!"547#"&6 !32?374&"*u~ ,dd'J. 1*t5&yrvc#@#hP 3!!3#!'373e p9<Ȉ>>732? &6 '4&"/373,dd'u~ *.[ f#yrvczHHPQ#".54632&"375#'73#'P{F3&&y%$7"ep 'Zz^ G2?>> $)$-5<&5467&546?&46327##"'2"7254&#'264&"'73#'\P$$Qs!6/ nS!(M 2**x[f Y$82 % &QlI Fg  S((HHPh&".54632&"375#'"&5727P{F3&&y%$7"AJtNt'Zz^ G2>UA -- A $)$-5=&5467&546?&46327##"'2"7254&#'264&"6 5727\P$$Qs!6/ nS!(M 2**tNtY$82 % &QlI Fg  S(( -- P[ ".54632&"375#'53P{F3&&y%$7"'Zz^ G28 $)$-59&5467&546?&46327##"'2"7254&#'264&"'53\P$$Qs!6/ nS!(M 2**&Y$82 % &QlI Fg  S((P 73".54632&"375#'>䵮{F3&&y%$7"'Zz^ G2 $) (19#7&5467&546?&46327##"'2"7254&#'264&">P$$Qs!6/ nS!(M 2** 2Y$82 % &QlI Fg  S((qQ !5##335373#' ep bɈ>>+3#3632#54#73#'F%mW&)[f rWHH53533533##5##35#胃لAAAA'22+3##53533#632#54#((==F%mW&)!k&&k,rWIv33"&#"'>232?(84k (B;f /b "j' kC33"&#"'>232? 4k *?;f .#, t(+ u3Q335!AbɈ,335!G32h 33"&5727JtNtbUA -- A) 33 5727-tNt$ -- #33#37#"5479. 1W<b64ht?*$"54733753sD5. 1tD*3h[3353Ѻb™33oQ#52>765'73#'&0%a%< >$< 73'>73#'0fH>?[f BPiL$ " HHi73#3373#'>J(KkuQ)73#3373#'#>X-HN/Q )333#>sm4333#mN 73!33>>733>N 73!33>>>733$>V:N 373!557"JJ>%%]0 37#557)''%%Q 33353##3#mbQ+3#3632#54#3#?/lV$+'m'uW733353##>b+73#3632#54#>Y?/lV$+'uWP 33353##'373e pbȈ>>+3#3632#54#/373?/lV$+7[ f'uWHH33353'>5#  -jH>bg-#""5$+%54##3632'>K$+?/lV0fH>BW'uiL$ "Q6264&" &6 %5!!i j!N!AKJIKmÈ%  &264&"5! ..zG}||$a$$agh6264&" &6 &"&5727!i j!NJtNtKJIKmUA -- A%  &264&" 5727 ..tNt}||$a$$aX -- Q6264&" &6 3#73#!i j!N'YYKJIKmK%  &264&"3#73# ..yYY}||$a$$a e#3#3!#"&633&#"eﳳrOuz) G( := ~ >=^J9 N%%32?"'#"&62632264&"%4&"#,dd')/i.+d ..+#,,|}00rvc$a$$aiYQ %##!2#3#24+?9JBm173g<Qf 3#363"3#?+"6m/< Y %##!2#7324+?9JB>%173g<hf73#363">>?+"6/< YP %##!2#'37324+?9JB{e pD173g<Ȉ>>f 3#363"'373?+"6[ f/< HH8Q"&&"#"&/73254&'.54632%3#QA@&' b45e_*m 1G<|j  ]jd&"#"&/7254.54632%3#|ZHmq?r|aGukrQmOIR  INfR8Q")&"#"&/73254&'.54632%73#'QA@&' b45e_*Nep  1G<|j  ]jd8>>"&"#"&/7254.54632%73#'|ZHmq?r|aGukrQu[f OIR  INfRAHH85#"/73254&+5&/73254&'.54632&"+u;?@A-& bM b45e_*QA "#n4N [ ]jd 1G<|j-#"/73254&+5&/7254.54632&"L;?@A-& S9|aGukrQ|ZHlo"#n4N Z INfRIR8P")&"#"&/73254&'.54632%'373QA@&' b45e_*e p 1G<|j  ]jd7>>"&"#"&/7254.54632%'373|ZHmq?r|aGukrQ[ fOIR  INfRAHH #"/73254&+5##5!##z;?@A-& OP"#n4N eώ! k]'#"/73254&+5.=#53533#370;?@A-& 61''QQ -S."#n4N _ PSddh P5!##7'373 e pώ>>  7337#"&=#535337; -V.]P''QhMhdd 5!#3##5#535 ////ώ b]3#37#"&=#535#53533@@ -V.]P%%''QY"iMh&i"ddgv"2653 &5$"&#"'>232?Dώ84k (B;f /IVspJ "j' k%"3#5#"&5337"&#"'>232?E@2jT,B4k *?;f -%{-"i, t(+ ugQ2653 &575!DώAIVsp+%3#5#"&53375!E@2jT,G%{-"ygh2653 &5$"&5727Dώ|JtNtIVsp*UA -- A%3#5#"&5337 5727E@2jT,ytNt%{-"j -- g~2653 &56432#&24Dώ>KI@=IVsp /`1u++%3#5#"&5337462"624E@2jT,H{IG} =%{-"d11b3x++gQ2653 &573#73#DώxYYIVsp%3#5#"&53373#73#E@2jT,YY%{-"$g"547.5326533716[WDei1. 1t;*roIVxu11h%%"5475#"&53373#37F@2jT,3. 1tF*%{-"?5hQ333333!' 73#'UO -2J! "ep LVbcɈ>>  33333!'!73#'  3ϖ[f 1>-HH^Q!#537373#'?Aep 4>>=" 3333#773#'VU$ w?[f >D-HH^Y !#5373 53!53?A[4%Q 5!3!553#.mώp 5!3!573#Ù:m6í÷%X 5!3!55'53/ώ菏 5!3!57'53Ù:6í÷%P 5!3!55/373&e pώ>> 5!3!57/373Ù:[ f6í÷HH=r##'5267#537>3"3rVA_4BEHY1SFgL FF_dO O4323#'##3&3#3'24>K57:mm&c$*=`/1bMM'++ #+/3"&/"&46?54#"'632275462"6243# N:0>ZfnH*[[!mr?D"`H{IG} =YmV  #Q=  #"$%0d11b3x++aQ!5##!!3#!5#3#n ;%ymMM* )7666@/ms.. >,l?p}H q@t|{$a$$a8&73&"#"&/73254&'.54632>ƍQA@&' b45e_* 1G<|j  ]jd73&"#"&/7254.54632>|ZHmq?r|aGukrQSIR  INfR  735!##>彽 b]7337#"&=#53533F>) -V.]P''QHhMhdd-N73#'[f -HH-J'373F[ f-HH,$l 5727ltNt$ -- P3 53P3 462"624H{IG} =Pd11b3x++$"546?37X=J. 1t-C @#h%#"&#"'>232??4k *?;f -#, t(+ u /3#73#*YYզ##56?327;"&' =,Q_1"F "l'#   ! ?[Q333333!' 3#UO -2J! "v"LVbcQ  33333!'!3#  3ϝ+1>ӦQ333333!' 3#UO -2J! "'mLVbcQ  33333!'!3#  3m1>ӦY333333!'53!53UO -2J! "?LVbcɐ  33333!'!53!53  3\1>/ #*<"&/"&46?54#"'63227573#'6"&#"'>232? N:0>ZfnH*[[!mr?D"[f s4k *?;f .V  #Q=  #"$%0HH, t(+ u9 #!#'#3'6"&57273#_T&c$JJtNt+bMMUA -- A.732? &6 '4&"'73#'6"&#"'>232?,dd'u~ *[f p4k *?;f -#yrvczHH, t(+ u%(  &264&"73#'6"&#"'>232? ..[f p4k *?;f -}||$a$$aaHH, t(+ u^Q !#53733#?A"4=" 3333#73#VU$ w?+>DӦ^!#5373"&#"'>226??A4k *?;f)4, t(+ u=" 3333#7"&#"'>232?VU$ w?4k *?;f .>D#, t(+ u`75!`75!#K3K 3 Kl #!#KK333KZK 333 KZKl= 53533##≉&Ʋ> 5#535#53533#3#≉±qƲqƱ3F7!3Q 353353353EE %-662"&6"26462"&6"264>2"&6"264,@=>>@=>>@=>>; QPQQUeQPQQUe.QPQQUeO'57OrrJT?'7rrPJR'p/@O62"&6"264.GDEFDZYZZ qU R5#5733573#6N0b7Iq0K#632#"/7324#'7=!H7.544'#2'364"LP"0B0.)  %*=&$#T3o$$&g / ,H#"&5432#"/726'274&#"CCRIVL/? FG  ?D_Z` p8O62"&6"264.GDEF)ZYZZ qU)#5'7)S$s"R,5)57>7654#'63203.7 #.UBA  lp2  gw   !?7#5324#'632#"/72764RM(_K(VMKO0?C2f$c0>"!H8 e!S35#5733573#6N0b7Iq0J#632#"/7324#'7<!H7.544'#2'364"LP"0B0.)  %*=&$#T3o$$&g / ,H7#"&5432#"/726'274&#"CCRIVL0> FG  ?D_Z` p8"53>32&"3#3#37#"&'#535 Af"Qs+ +2hkz o<(o<>)K-#53###373#5#'pG)XRg)-fR"7&5OO9Ǯ(!73.546323#5>4&"#(DX,Fc ʹbIM(eae::b2#"&463.#"'6"327&}|u|wlI%=Uh]/=ww +&" 5d9%t 3!3 aCn'm*K! ###5!#3B.1L. !!!!5鸺kȪ,(>X75!>5!3#?ty h~-#7"&4632632#"'"3267.24#"HGGHcFHaHHIIaFFW** ))** ((~qq[[rqZZ"....I="#'52765>30 ?^D ?^hK hK = #$"&"'>232?&"&"'>232?:&7 J:#5E:&7 J:#5 ,  , ,  , ;53733#3##7#537;''1()2LL7PP7;- %!53'5% 'Bz"@- 75-5573j*ܢֿ1 "zBo1' 33'7'#랞m6677DP$ 73'>0fH>BPiL$ "|3O|( 662"264& zyvN!!I! j(r|1--1F #'7F;=<  )57>4&"'6327_.>x6/92t'" 8I)$724+5324#"'632"'q1~}$%\_.2%s|  S! ;'UV7#533533##q΄400M}>XXM 724#"'!#632"'zB+%o ml 5 A$P\  &632&"632'254#"ymhRo Q&3`g_;9$#  L` 5!'²c.G "&547&462%254'#74"36Fz<2pp2?qipJE$7T/B' %^a75!75!753 #5#V>#&'&46?3*%? 2:;oH766>4&/3#6)*%? 2 ;:oG67!B#3!B@@h25!!53!@NX#"&'&54654'565'476763! -ui4 ,, &*>A[.Q3//-b&*Vx  R$& Y#7'467.574&'52#5>W! -ui4 ,, &*>A[.Q3//-b&*Vx  R$& +?Q3#+"QZwQ3#mQUQ73#'ep Ɉ>>QP'373Ie pȈ>>%v"&#"'>232?w84k (B;f . "j' kY53!53ɐ?Q5!?AɈ,lh "&5727"JtNtUA -- A~ 432#&24>KI@=/`1u++Q3#73#/YYQSX53SɏO62"&6"264.GDEFDZYZZ qU)#5'7)S$s"R+4!57>7654#'63203-7 #.UBA  lp2  gw   !?#5324#'632#"/72764RM(_K(VMKO0?C2f$c0>"!H8 e! R5#5733573#6N0b7Iq0K#632#"/7324#'7=!H7.544'#2'364"LP"0B0.)  %*=&$#T3o$$&g / ,H#"&5432#"/726'274&#"CCRIVL/? FG  ?D_Z` p8'+4675373#5&'#7."264.53iD1$D20*bzD-D)90  * /.J<= Lj&r 65@X$ 99:"((a9C"'#"&5325326=4."37#".>3227&=&"b6FSob;- OqfZ80(Cb0p-C{&)w~55u O50RQd;(#KB%,  4y j. "8)EO>2"&6"264.GDEFxZYZZ qU=)%#5'7)S$s"R,=5!57>7654#'63203.7 #.UBA  lp2  gw   !=?#5324#'632#"/72764RM(_K(VMKO0?C2.f$c0>"!H8 e!=S5#5733573#6N0b7Iq0=J%#632#"/7324#'7<!H7.544'#2'364"LP"0B0.)  %*=&$#T3o$$&g / ,=H#"&5432#"/726'274&#"CCRIVL/? FG 2 ?D_Z` p8G75!*ӵ$"546?37X=5. 1t-C 3h~ ~;    &  : & v! $   4   )Copyright (c) 2009-2011 by Accademia di Belle Arti di Urbino and students of MA course of Visual design. Some rights reserved.Titillium WebBlack1.002;UKWN;TitilliumWeb-BlackTitillium Web BlackVersion 1.002;PS 35.000;hotconv 1.0.70;makeotf.lib2.5.55311TitilliumWeb-BlackThis Font Software is licensed under the SIL Open Font License, Version 1.1. This license is available with a FAQ at: http://scripts.sil.org/OFLhttp://scripts.sil.org/OFLCopyright (c) 2009-2011 by Accademia di Belle Arti di Urbino and students of MA course of Visual design. Some rights reserved.Titillium Web BlackRegular1.002;UKWN;TitilliumWeb-BlackVersion 1.002;PS 35.000;hotconv 1.0.70;makeotf.lib2.5.55311TitilliumWeb-BlackThis Font Software is licensed under the SIL Open Font License, Version 1.1. This license is available with a FAQ at: http://scripts.sil.org/OFLhttp://scripts.sil.org/OFLTitillium WebBlack  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghjikmlnoqprsutvwxzy{}|~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~uni00A0AmacronamacronAbreveabreveAogonekaogonek Ccircumflex ccircumflex Cdotaccent cdotaccentDcarondcaronDcroatEmacronemacronEbreveebreve Edotaccent edotaccentEogonekeogonekEcaronecaron Gcircumflex gcircumflex Gdotaccent gdotaccent Gcommaaccent gcommaaccent Hcircumflex hcircumflexHbarhbarItildeitildeImacronimacronIbreveibreveIogonekiogonek Jcircumflex jcircumflex Kcommaaccent kcommaaccentLacutelacute Lcommaaccent lcommaaccentLcaronlcaronNacutenacute Ncommaaccent ncommaaccentNcaronncaronEngengOmacronomacronObreveobreve Ohungarumlaut ohungarumlautRacuteracute Rcommaaccent rcommaaccentRcaronrcaronSacutesacute Scircumflex scircumflexTcedillatcedillaTcarontcaronTbartbarUtildeutildeUmacronumacronUbreveubreveUringuring Uhungarumlaut uhungarumlautUogonekuogonek Wcircumflex wcircumflex Ycircumflex ycircumflexZacutezacute Zdotaccent zdotaccent Aringacute aringacuteAEacuteaeacute Oslashacute oslashacute Scommaaccent scommaaccent Tcommaaccent tcommaaccentWgravewgraveWacutewacute Wdieresis wdieresisuni1EABuni1EB0uni1EC5uni1ED7Ygraveygraveuni1EF8uni1EF9 zerosuperior foursuperior fivesuperior sixsuperior sevensuperior eightsuperior ninesuperior zeroinferior oneinferior twoinferior threeinferior fourinferior fiveinferior sixinferior seveninferior eightinferior nineinferiorEurodotlessj commaaccentCR zero.pnumone.pnumtwo.pnum three.pnum four.pnum five.pnumsix.pnum seven.pnum eight.pnum nine.pnumquestiondown.cap endash.cap emdash.capperiodcentered.capexclamdown.cap parenleft.capparenright.capbracketleft.capbracketright.cap braceleft.capbraceright.cap grave.cap acute.capcircumflex.cap caron.cap tilde.cap dieresis.cap macron.cap breve.capring.caphungarumlaut.cap dotaccent.cap zero.numrone.numrtwo.numr three.numr four.numr five.numrsix.numr seven.numr eight.numr nine.numr zero.slashat.cap zero.dnomone.dnomtwo.dnom three.dnom four.dnom five.dnomsix.dnom seven.dnom eight.dnom nine.dnom hyphen.cap ogonek.capmȔ,n̏u 4NDFLTlatncpspkern$  $%&'()*+,-./0123456789:;<=   !#%')+-/13468;=?ACNPRXaP&Hn~<n  F>6d,V ( & X , v  6 d 8 "<*2H^dd(fl*DjfD 6X~ 79< _ #$-9;< FGHRTV1 *i! &*2DFGHIM+QRTVWXYZ\]^",",#. $-FGHJRTV[%4% $79:;<[ 79:<Y\^_"$&*2< DFGHIJQRSTVWXYZ[\]/%79<<! "&*2789:<?FGHIJRTWXYZ\`o^_~ $79:;<?[`   &*2J2 ( $-79:;<=?@[`~ &*2J. ' $&*-2<DFGHJRTV (71"'i $79< !  $<$$&*26@FGHIJRTWXYZ\`o ;4& @^i "&*2789:<?IJWXYZ\o^_~ $-79:;<=?@[`~+ "$&*-26789:;<=?@DFGHIJRTVXZ[]`i~ $79;<?H $79;<[  $ #$&*-2<DFGHJRTVX]%5-%ij $-<% - #$&*-26DFGHIJQRSTVWXYZ[\]C<.&ij$&*-2DFGHJQRSTVX]6/!( " &*267?@ DFGHIJRTWXYZ\` o JC4- @i  ? " #$&*-267 ? @ DFGHIJQRSTVWXYZ[\]`o N G92 ^ij  &*2J*#&*2<FGHM7RTXYZ\"# , % $ &*2789:<FGHM#RTWXYZ\ @_ "79:<?IJRTWXYZ\~ "$79:;<?@YZ[\`~9<?R~ "79:<?YZ[\~$9 ;<H 9<?FGHRT~*29<?DFGHJRTVi~x "79:<?YZ\~ "$79:;<?@IYZ[\`~ "$79:;<?@IYZ[\`~79:<?~ $-9;<?@`~ $79:;<?J[`~79<?~ 9:<?~ $-9;<?@DFGHJRTV`~ $-9;<?@FGHJRT`~ &*29<?DFGHJRTVi~ $-9;<?@DFGHJRTV`~79:<?~&*29;< FGHM9RTWXYZ\#$". ' %M( 9<M.$-;<O&*26789:<DEFGHIM5RTVWXYZ\$@ !@%`&%% ,@%`&-%% "$-79:;<=?@Y[\`~ "79:;<?IJWYZ[\o^_~ ?@"`#   "@_`_~ $ / ( 8",?-@,_`-o ^_~# $-79:;<=?@[`~" " @ `   @ `+"#  % %"'?@)_`*_~  @`   "?@`~   " ?@` '@)`+!*+   "@_`_~   "789):;)</=?@E K L M O Y\_ ` ^_ '/ : % ,"5?5@6DE9FGHI JK9L:M:O9RTVWYZ [\_%`8_i~&y  v"?@EIWKLMOW\_y`oDYR_gsGCf^?_h~p$-<FGHRT,% #$*-29;<DFGHJRTV 92$i79< 79;<[_ $-<* $79;<&*2.$ &*2< "#  &*29;< $% $-79;<=a #$%&'()*,-./2356789:;<=>?DEFHIJNOQRSTUVWXYZ[\]^_`cox @^_ij~ 8bDFLTlatncasefraclocl$&.60B :ABCDj2lzstmnopqrlzstmnopqrlzstmnopqrlzstmnopqrlzstmnopqrs| ((stzzlr}hhkks|Y  >@^`cx\] uvtswxyz{|stzzlrinc/fonts/TitilliumWeb-Black.woff000060400000061164147177152050012772 0ustar00wOFFbtFFTMbXnCGDEFQ'GPOSRTKGSUBQ()?z3EOS/2P`kɂcmaphugaspQglyf ; 8headl66hhea!$hmtx8 &locad.~maxp GnameGxNo@postJ6 prep\hi_< ̏,n̏u|9xc`d``WVt62`<Z.xc`d``<L@ `>Zxc`ffna`e``b```Ќq @>1#0K\ 9ƟL xMhUs4icdh$M-dN@ERRh] ""Bхb7݆.i)?0@bv|0 v|s{ιZV3-C*MZZ bm'UddOn+A7t&Uo;>BTox#'T5X<6W$AK}̓8!|[!lwh}]h[נuh:Ή~f3sk篰c6{,{<'SV)Tv =y 6i)$7R|.9Wh=n&;>OU Wumݺz> p~v10'`c^ ~1v]{Rkt{>I)Myv Y1--r,[e&o`pyAͮm( ^j{B-:l3 cg4ESi9=4СmBP u;;NSrN:qNU|->nSٞdO'DyZ?߻_3c|{o iG%?nʟ~kMJ5H jR jSS4!14nhIsQ-hI85-hO:E':Ӆt;=I417}R@< $2$I!4`0a g#h0q'L&0Qqgs#(9iNq2q\"q[ܤے#C&2 'H yYe~YAVL֕S|ZQ~*+hEN1xV):e.{hAȁ Hl`%+qeANl*/*ʥʫ=U[YQ_yI5kUSӾӞj:.[uS5 ]= EpC0k _qxaM)g3m.M=4 =SN:KTC*q|铚#GΡ=`.9/(L$B~? ϥqY@/ /x| . #+8(+)j+ AEѕUz5km Nhߋs.q*Mb6)+)AAWQ@yEzdB8qbSꌺo;,+i˘ | kF Tshȼ)>}ڒhj x zӷk!3q霛F++| poͅﯮUswR4)W%%- ohj[S˕eM俠}S_{9y>+4#X+V.xkf5Y+N/UMbcJu“6G[-H;a˩Vu(Q9FaleX=fsk#RL{<*Eqѵ/G5{N R.S^QJ6^kWRmOċn?ûQk+A~ *^UFI5+*!x 7 ZV!VMdohrH$0:o\k**wu"G/7(7@ X ?s)ې{j)'\YFCgÜw<Oڹ ӯFԶ?mJ Y/l3ll3r"ۢJ TR#9sΒRSDԾ^qӎQ<ܵnNV>|;7qJw=gkƛf;W3ٯx'C`E4XSTȏ+V M2=UfՔntٛ_a_vZ=)]K d9 }嬉O7Lsz<֡3.ے~E%# s}WL vKZ~hJW xo?΀;kD3)o.3e5D;od޳?O@a7+Y_e4;'yo:Z/*`o@qI C0^ABtd}YHND@>W;_,d!<58<ZtcVpCzvMYur49A1늒^㾺(Nkr醥KePE5RʋSX!j2rc] 8/&K,ø׍{:Ri1d k{LCienǕnzafekkۧZOz6τ*/-E *@ CӄJ&o=݅)Vն(>vvSyo+afvF ބh_m @_Mdw>Y!23@J_EMYQJ3SywmLsuPҵػJ4PJ'1ؔ?i!p#\AKNnM& U`wwMG4 =H+eG(푭w sw+ŇďDX&x8;Lxw7?g8Y&g]L/M?4Յ?FW:Y#cv D*pyqGoK۸׿ٸmIrL֊k3#^]ĤRZKݽo,U+lGk.q?6"%/z> /]/D3 0W\_ VSJINQ`7qn%"Rk ]<f~ )[[s}qͼ>70x'A-bMD9>P!,.gh|+]ոnA_Cxo%/KV-!z񌴦luTAWN{@voYhVm[Q}O?ьeJ:qdy$(@ȝՊ{o㐹*2o؀9)U[[}2'mVGM,AMhЖ1%MwOv8&SG_w 4Cp!NGxp͌j"U}{~- y7O:&,_.ٙgq*u; d^KͩKzWUmWX7q-棓ZVֻj4CR*)2j-9J5= > [֊>=tHB,v%#b"f^?>)qȆ93ףGI?>`Fo#{VTn(!rGhAkkY;~$W2P3+>P9ksC@FxhI/L?]pWV{mŗh#s5f=tW?AoXNox-&Fl8qSv}?ti_+QO7=ٽ Sc#P+mB`P} hSk[")F]qE`߈V־Q܈8&j7 n)5%rnz^T=3):U" toF;dPXηԹg mϾMJ*;fleQVNoUm6HȬ{2 vӖI5iؾu qj={OSTF7K("|.g%]@-\{!-%ۍ~{nZ~zܳ؄Q ->%9osCNE7C[z뤕δ%\)[y`(6`M!9csr2ݐ^} g% 'h:kL0קjZN24YW?.VvohyVL`3Wf6;rw} [(hg}T!^AK8+ גӒ>T)4^SlzaN@|)V2.WjI))ty˿]Ѣ3Nu߸ %TT2}``.Y/}lR\ϿjDbK4sYPJ=;Y}/7Oxal6]G%4CnÇu7}ÆEX^&))+dzO V[Y7{YbnQG~j ]7aW*YG0YfKWx˃A} BzNE󦦖xkz,ae`()) C7JoQ%PX(_3΃%k'aO$|_%e{> žӬ4[%c CejSyq1/˛"HWͭF_Ģq<շ[Guzo[2}~uIz؜]k9>dF~=rS{='W#' -";u+5vE&UrC— 2x|~B]*ERuzפХغ_-%>>==E鵾N/kR tl,LN$2K|L)7K\ a]k7D&*0]s?7>UY;="XJe[sZΖ]?тg/{vxc' Cx>󃒒ȺnD .,$[@^|@Ĭ ̜kkkJRWޛɸp}`E7W90NP nB=Z{IdO^+[2[ZZ[/??;)ϓ90~ͭQ j;(w};]3ѣ{4݆';(,rOcxNqAemEzE¤>N׵|$',wyҾ`xK=sþ|IAƄ7XlLi=Nqh]=}hL-$aNT-fAasZ __?rA9l &TI'EsC&V6߽PY:o>J9[ JuT7nd_L斱X&6ʟZSOOojjΘL `H ?TVۏ%@#y]S*݄3U>?g1gH ,*L h#[:o`2gU@)2B@BQ qȦ{B{R{L¯EQؑ AH*$ !2$H4d9\,SmZ.|̲'z':J'x"<^}<ɞu,2bL+vx\}0)ڄ4q_6g\VK1Z5O?C#5%/Z˶wh+zuBX&/HK@KCeCj4Ul;PDch~Di:biƮSzՎ- BjXvآDӝF(:OC~Gdy%Έy[KW=z]uĝIyO <f1*4;GB.׉Iy%+RPMڙnBjZ= FܭxhtctQdmivضQtHBt0$ϰvSCsdٱJcIpƣ($ղ 8#fgD|3`8mfcQhHR5ۛ6B7 9$Z҂81/kJND%(}$Y6hʥHp$xAe "ڑGP(cئwnBCpWZ**R-޻495s>_ _cwGй%j$CFK&bG!':B'qRR&@G?Km&(h᯿w94Mgnޱ&Kf#pAH7?PGl0e~rh>8q3ɞ8NVxS, s@V8yԕE,7wGcL ]s/ MRxmqJf`,>K{؅xK6Kq@?} m9oj|#Ƣm۸0o/[/MiRU ]}i 2걐 #wjRvNm}n׽p l@% d2^R!A 43C/7QsCv(:ISf4DIRU"rXsseաG)lĄC+LcՅ;0oQ*$.פ%$hDQq q1v[=0 ŖJBۻIغ1&<4)asHX٪Su ܗPxn#A%gY2q<K J/.K'वG0_X.db'EHgKUHV^R~q)fxKKۥ%z?=eMy.#Ch>wƦO5ħ?'Y#\>Ty5x}y"C'\ZlB7oHeP\_<& xF,Ͽ>Y^reH Z0V_Sx gQUʊlS"E).[wck%C7\v1 mP@߭Kpɷщ= GIu!VJ$mkDp\SQ'1χ10od}kntDRmbb=wd1z8\zKr(`WTP%~ bO߲==s$饐iF<"~rB%m2z>Щ<0l-ԚŎ{_{D'V=cNNȞAퟵh]e7veCiX ѴmyLלZ2N}Qt~K45Q>l糴oPwŰx"Q.*P+ǣi'>#kxY.ղ3gN&趩^XtY(h_gU0Py?ri??,\D ("jo[? 2C&sZ),aa,'1rb}[Ph1O={ ye0X2TG%H} #Ol5H:/'E5(Z_L 2]<!Oi![5LSi~s,"P!tXs:[߂C@_-CF ȳL1ܾQ%HC9TAK,$;>̊ 380C)s 9փM\nN.Xh\ҧ:adސ|!0aX!̀0XjPA|A;.Cx>Vl%x4' QtqMlqBO (+n"NG^]Z:&/\E]0n,9LSv%Ѩ4|u|u%I%`vλu.( yAYK)_ޖqg59xFϳsɦ˜"[Ӊm<Ě噅 ]PYi2R!DG43Z8Vy=2=džz4l=&K\/)'ɸ4n*W*_io~t>%J(" ֒5/.<3 Mt>:{wMjѡ]3y߄ Ehg3sb}IѯsztL@>ݥ3NFlOdF(HE"9F:H.wfqĤw3pg90PWW%_Lan Cn.l][ qA[&4ΕsS9-mE9;c޳_ձp_*S6&ʹ;SqGF~PNF%EGydA1 Yx.*'aAӰB&DY"0FsdNIbtw#&VL,]z>>!Ԗ˧艙+|mamfɁ[I9$omj[lcX֞ÉlOMz"d],GUٮDAnZ)8R?lj4".^\ހ"HVVfM1ziiz^H,):qɛSQ] 7XT 1~%l7qawUM`m]Zfژ1~􂬏Qn9v b+w wqjVxe!qǁ+Re!A%>j.}/SIOu !.pQ5a͞?%pguyy}20>~u:Iz~5)!>N%Y1iy&9fRF1stȓ;nBwmF ZbpcD 7* ;h2d%|DK\_cG?ap :6t3eO̒Baa]<9d4&ҔW"rJ3T6>]CjeFst'+$L*ڑQ1-cgVP( 61a)֏|E ؼ,H'r'Dx [٭r{ ZɌ%^xbĢ"*D2:A~γUzƖ]b?\kIA_ lEW)Y=ԸRWNwcv ˃+H[,7.T73fwRBjr;REn)FJhwZ V7_6(PbAYО=ˡu=iAORg*10}"1:j^F3c#mU{2|+}"Zxv:ɉ/Z$0|a!?o76KLݾ)GJt3Yl(;dPL҈Pk,< mbmݷ@UKNxVPƓ^Ԛ5GD+>^iҳ>Rc 9EYYG'uEJq҈gn}-T{)]{Z.^YÿuOWqwCmWw'A9>H灑s -y&F> _E^YLz;늎@z9&=5Oɺ5 v%^#8b!>Q=f2KGA,}cy]䣸>1 If _"_B~wW kVK&TcuYEIጡ`teLC^3'm2jMi8EU]|1IƙB Řt3yo0SVéM;)Y 5Ҿd{ZBU) zUZʝoe8=Kw Z]qZvjOA¯.-Gx&gڔ5Zu!ӿVh>gvEM}^z73 ]eP!KjIugvj{->_~[dœ rxZsZ/ىt; {:?h8p9^Sj]c~Y?Z Ƃ[;=;CI>Z>BI '\@B2?&K&tO$I1'wiubAs侫6=yʦ9I:u2r i6t]՚i&>)*זMUR]h"jbr+$.zhްoM+4_!ԵY|QD<R 6+W6lBަJX--fe\ ȝyUq`>q_n {8%|&|DZ[ zE[t>JwV SFZy+x?>T fy,Z+ךC߄~؁9S )b=_(eq[{q1A\v&:{7t񫧟E|95݃ Q.SBhlՠ= '/y+?Cp#kS?.@IO/;OAkO5ӃMKf*ow>rvL]?~l}}>cgLy( k6.欑#g1kܒQ\~'^N{) H\di&Nzi/AAbR)7%)0K5v;ys]}ߨӹ3ND`l }V72A/Q޲[5wUoM:OpOc J. }p.pSًW1zP )YܿlgwxI":hE(`’7OGJxw|Ųg ﺲ.zf.Z黳)aO#< txxA5g!~q lf{}ĥY0cٔA%ڔ{c&/]5=GJٗhmVmcefz>{ CK?@^4SSX;"ݤ`9cX`Q+ |3_֙?,575iPO_ zbi ZdxMGU,AvI,Z9tpP:_#p)rf AY{`ȘmY9ĴU?+؛Y3XȺ:;Cwd|wǎ}ψx#rFt{s;ڷ^q)w{'6T%s;Qfe>RKvvԓEܱ;o2C!t}5 $LvN4\C;in[C\>ji==3agkBcJ,hrqQ7F.HiR2> ETyt}cQ;Xa. p*c:%_1jᙥR_@kQTO I4.!{IrND_r$\΃y!Br(O29A >@| ??-ӴSG@i.a%E^N(FhLWYZN/_i2{u-!}dPU?sv*|ba99til<7|;d;LDa;!7Īz'E5^':C^UѥL{萄 }Q;U!tMFt `a>xaB|Qը/k *%GUsuzD00I{GYZ3cG}/ч#'ToC~Dݑv9s;Dt7ڠV߯)Dܢzkt5C?_a2 K7icE`npDh#+6֣;lMF?q]s=}oK 4)RIPNw)zFXLtIPAfx) +3@RaIp΀jd!g2Yx@xϰVC.na THT*{Mm1{"d*Ȃu!5R^)V i̞,u4b)T%2 쉲% aa\Z;om\5QU}10a1qF j$a21S1 8 hA+Ct8Ghcqũ8 +q)8g܄p&)?g0=X_ ~܊$nC;8<x/Y<%:2^KY ^k|30::Q@,tBlF7BЋp ,v0;<, Fe9`%ccsɡ܀8r#nM)7nɭ5܎sȝ8;s u=8{>1XxyNAL5w)Nb'S8x0xq-ilvq<'pO]a9=q2<܌5XO\Sx*Oĕ\Ňc|Op5IS|٨cUUɪh-ӈj #vKMB4ifMCtF5nBG^%^Y1m-]h6y[fԺkv47~Ôj($TJFS 0R; lHT]il@uiP  bCJlrfG%DItz5׬G7%O iZڱE$/!>-_/OF^A2TUCW5tC(lџgjT39jSk0QITߦp_+ܷI4Xs茊%^ޒ=mDZT-sjU9ʡVǟUMHjFv=M愣h;RC#3Ԍ}*gʾMz*Th2P|yS,xs%aڲE6[BE[F(Ŋ~aN%VW)vldڨWZ4>aEKXi;L*lĊzO?O] z6gEnEroP;v WAP#Ty c宙yQ,ΌNy@MS'oT]m$$$գ\1*O*QTPɆrDM#cvZW02סh񄹦f' u.F^t, SqDP-e0$L)BfX{,3Xw_z%+iYI<#<Qeb23B)#$UFDi\=͌hTKuգb^WuyL]b+'?ʣ+ֵ xM/Qϙi'6Fb¬D Ƅ4:ZA'[VK>= f7 |dG[BXb; (^ #Jg;L 8p1$8&0m2dUH8.2\`&|(}Uv1]s 6;Ĉj 9^%>?q\.ƿ8w,F؆T4]縐krTgYv΄e<go|=ox;ZaD.u4!yO\Fx}{pT'$ / TT’I"Tn9&ǥOe@2()a1B,$5Y+*T^5EU*UjPZժj:]թ u:K-VKTZw9B]ZWGcq]=TOEQov/=c݇pά֜ks9ɜ줭^ ^/7E+/s,;,~8R+W\ruI;,)k.{쭲r_חo-F m}&\A+!! ~q÷k@NuHV=Rme:*uV|<+%˭ZqY5\kai':^F(RIK L)2y\Ռ$-GR+xBr 1$ezlJFXHQ6_vr>Dd*QSPjIJ< `YXV?e5\ZdF;9Awba/Jd,5BZv?Y C~)H]Ǽ 6͛}ؒƎl/!5`U!JPb킥e(Rݰ4ObS LŐ3hIV d!b4,(IKcꆛ10G VTa3Q,[ٱSAbp# ( UTYPEE 4ס(V!.SNp2Vb;ln#h=V<6llBlG v+vp{O;~렒: 3>tF zt~0d Ϡ70.DlG0wiaُ'- -)D5:aFzLa:L .A[Ɇ^,Q2$&hM>њde 8빂h ,Tv"4zDseCɏ"'?Jx3YߏpلK:rV|5w;DL‰O am.5|@Yhh.PM֔z*C9N]p[o߯qeA<FA{1uDeJ hY;Q!Gx2zl04lh}y2'=fL| T8ނalPوf޵Xax +WUmĥk]c\t]ꪯNjko[m5pZgHCRjy*;}t9.V7b&?K3qB/ǃx(C;Y<%RؗwdiIe @9KJK%űoAnP2 (N, AХA7$F@4=Ut(b޺3 Iρ+T/Zh G QN]AZ=I|c@{?KN)n28 'V&MMQ%Y 2/1ꉋz↛>5.:HYi<ūݠ0}Y(/X Q,xbKǿcMkcM=XbJ>y:,>&C߬}Ժ^Dd9vU^yNUbz0 "ދEXNwh|$V# EH0=ivLtݎ_=ƱsR̗23=U{ډ =ZB'T ]1(#T1a*#3M j|Jr Igr(a/#39%&D^`KKT Ui)C֟~G:q$;Y:n@LiRݫ$=hitW]!_Aj7RSTɣH@gwlJGtb&';tfun9U[1)B_ #s õ J$fͅC)D7  nGY;ˈ;M63coY"d̪qwfs;.ֲdn ^Ǫ^G1.*jէt$|w!i$| I9H>S_ۨ [aGKL9LOQǃᓘm'80TA]Qc=$nSu=4M\m4&g=W>}bBaHl4UgܙG1H!VR_'ٯ=Y\.mMfGDD!k"}n1wmH'!iXc>$uGژ71CdX'ӱ 7L+$f$L1'bfdZ3&&ٖ0q:' ڤ"#5ϙgTFaI3b4pȽ3u:tNzrNqgSM5lwg:lj:՜T6sX]Jg.+m!oKL2QYx:5T:3s {Ul%ı$%qa #Nuh|hƢsgcΗ9dJ 8 93SC':[&iYjLj͛ԝ|}TOV9혙4 >,y#0+Dg>kn iyin}Z/XYOO;Si=;jΑ,gdmL:Qԋ\T%UXR͌xk sB-S[U5Z9S`u\G߬VdOp]NV+!ajѥZLTX=b@zXf&~k#OON1QI>fE.3xZv4V)Rp0rJyS#!H1aǃL/UT&mR~VbU# >#y2|$NЯJ?sTAF9j\Id7~'D}9j<|̻3_?WyI𹛳SLA«9j-h$"h պЩA"4֠RWӭàr3sR'# DCN5vbʞksru!p) jQ 0A,TOʨ5gpurCu.tz\|B7=d +o?'"|L$ uGטWX*W}_{ljvt|&ښi%VpZ%K%]el&r&qY G7c2._ImV[UjU=R)?.մ2̏,n̏uinc/fonts/TitilliumWeb-Black.woff2000060400000041624147177152050013053 0ustar00wOF2CC0?FFTM `6 q 6$  ) ضݪJr$BSB̨qPdT;+ EU YL- y4dE=QՉˤk1L V_,EPIܟܒ;Rok!YYYYm(v ˵bb\[T̛ dIWvK|HrZʪ;VL: ax`@zcE+F56"JB:%,()Xٜ✇DȘ<wgx)TVGE21]&\t0v{5ӑc'YD涾H;@V|ii~DI,- *>xouJĶn6s8λW®wTtAhmn4hW :5b^0  Bkv`('UF~:f\ZYJЉ2ح~ T ?񛪴9 %I\IS0\`ݕ۴J ]OPLQi̛7X{lyыwsڀ{3Y'>W+2WUjLߧLѦ|Rz)u1/`) BiV.sIs;7M.WJPma AA(Q9g]&)zZwVn; R8Dn1B!BLU4H!;8(PX `#͎\NW.1 e Q9 T)t/O;=sQ_Oq˚) b3y YMع 2gvkcd@@D1"%\x)m!\jcʸJ|)k|`4-V?|;?/.]u+ݟuP$4 r8(QB-:3ďKBx߀AFsA6w.̳rI>o<>Lw@#ec5Q}~( ͓JHc10+X Na_qu</7ǷT >"Kt +O$)tt#ǐe!@QPQ6ʤj10isK/d2tLL1 л"`+&wVH(t-9 7ȷb7ҎʫC+L5gBu!`dF IF’$/+L%WԢ=Kjf4V.uJݠ_^cu1.\p#iH;BeUo)+Ռz\.F681ڍyw&x^[܎:)Li/J{kH{cS {G Q\*TFjQ|t5'ZvSVz~e96 F̝Yʄ:NMn'rY63T!S{]XN"ݟO܆ήI: WH-Exl%tqVֳ0#1X[N8m+aJpeAi4eM2=S1=O /9Kua2bVp.ԎmHz$%v"qo#~U baIYp6Y].x|Se6O] p oav=4#Cm\AUPgͿƁ[ۼ;QH_5ݲ@I IGYs.#HeJaqh=IH1W*GSo>9N֙ͥ`.X~xؙ g4cOKt̻u=SS#aJc*fztp4tXzWH'?NrU P8rΈlm(\tGr!B<&*:kݍ>fC 3q:o~jvH&@'YhUqC>BQ)=}M8"!]_ؚP t8PAkj/^j~h,t c6arWgRK}U/ӿKRqCuG߷?Ƌ4Q] `mH$Iأ0ss&yEʅhԛyax0X@?f@'+WgԦV22TcmhrdAXFZVsoP:t("H(spiT~pB.&'G~jXn@:Ftx㒩}}jVἨ)x )vD:! ykt2#iCb XN=Wi?o|SD\ ÅΠ#/Ǎ r؁hr[₥J׍OhSM!e8+x)\* 279w} dܟDmwz#P y*-UAhN+R}=4mj0˰[M0HKhfI Ww KT ! hay$D Py=_y'#@ &dث\ :S)qzQ;6JdgX/p ;u}5 gDd:EKб4rJ,Rc´'4aNZQrtyX(eO=kEyt꫻ ? &4Zh+쨎N]6e% 3RRPm)zí/:GvhX6gBPA@- V9,Đu"& wHX.+]yKkӘ6n t{ʆ-a";n3Ň1,:a`*!B$ Z& ׹flfDt!YTƢ%i/qHdmg EZPȡf6+1؉;cU$| 9} d"!cJoYC?&|z>ؤ3l뇗*W3;TcTs|T@OD҉Gԧcd,h 8;VM^ Kتȟ:.깪宎`ƈ@㼜jZKܗĀub 2U\*lj S`B^;:J6oZs%E=@BU!07,,Л2 ӎ 3e;f ջRdFl":t/P:@Th6>v }fZh&5iRn&*7")$D6)RB=I⌻uVnB-2A84I #`ԡÐs$%8pč;O^_@AWPa"UYa#N8iʴxOWl!BۧXn}:Q#Y-갹[cŋ@qhd(c02E?MОm)I$RQEȊ5 b f$/CfIH& Ӣ7J 㑝!] P/K"0B'7Ē`(,2'a 7R">E ,2eȑ+O\9"зN@iUIZV{VPC!1`~Ds>_ /m$sIp[c0X2̪ͮdeMb}d)l:ŖgslS ;Ǯes0y<^$Ogɫ;ȇG+r]`!H9Am0*12>l*fk1s&tb#+\tyGwU^+g֍ҍuuuuuhGQH, \+^+XXK_KX[ ^q.'.ck%TI2WdRɠc`"CPkZspEy\_ut4f:I:N2cάyr9,U()Lj e_U뭪+Rʸ.Q+g\%S5"W+,.BIP$޾yXna"U^cs82w?p}>d˹9p,/N@ ?j[!{Cj1ZEY6k+ @څ"!ĸ0IBpb(EQ^[Fcí-B<./1h^M,iit-4 ;Yۮ-Q[5I,Kg"*f=qtDNj5޹QPz -g7xLv$Q=xr -2;gtvh%U<+n.FHˣ)SHՊmT=:GHfp>(##"$uH>zB ʥ%Lc!1QIg vাf|\!)E:onDRK] ͇G[Uݵk92 ]r6=J%%o4!FITj^\L,C}l|I$NҤ0NkSY-ءϑӼXαJ(DP6^>%V-ϧR //Qm ,Bljpj7vҰ`#aڼ y>#|';7seTƸOR#K< MAChc"0}C"CX{ |0(CvjGkJHcY"6=YQh@)%xIA%"ga<(lKE ffam?e?1*T&sQ[ٟ%P\ I]#=fd›-+EYjpa` YJ H5Ғ]cks+$=1U>A54{^%ӻ2w2,:dynac]cѝxzOJ?1 TnwMEt;NL@z{G|R37nD}K 6ht If~_#,E4͸_zcIz;X'?S`@B1[za]X %!@+xT㒭oΣ=5~^ئ.z!3pVeG"z5j/tַg&Lohe8w av&_K3&۬h\2V '2lkWGY[kmN mjqpˆ'TlC%)3L+/8X(]%ٛlOMuGd:HIt vԢ40N@M~i= >4%^*"ϮHޡ$ +effL?o˔)*_Gȡr,q/3RG067]Lf*;D H<2h~N]v`?iÄ2yG&Orj_7-B@dl1Rz`y)X(-f(6P/WsM|=֚5 Oq~h#V[iAicmܚoV3z;Ϛ3߸e!i7ȣ힕VQ?yt Wg0tuwϧOW1YbsAm "DVVxŎ&/\Y_i,>jÂAo.f j|HryO =6 3H!BIhOVGf|:Q>~YX?ҫd,X͊[$ȕPk x*-&f偅WV$881W.˗!GLbc(#Tk )-LL7PfnhíL^WlC5ŔeKpfc$؝}4h7O{In>*2-)sC ";{[$ er{SW̌53tӋ쨌=SIFTqs;]-;z  =2ۑ o8Uսt ! 6z|\GVϨ޷`ޞ+AɱB#z CDx\@ji(#耀rMzƒZm4^`gRw&d]c19 5 "wB :阜_Qai!eycr/եhs~#70cT[SQcqTM腲4gI2W).4_]󈄾n9õ?M`Dj|m;f'0V v[[9`Q='#.=%EO(ve|RSՇO1/LGM9F1|1:3Pi;y [-P QƖ3#1/BXTltQTĞؒ<ȋ}M〹5 T__ ?o 97%lnsXBfcE>)ᙥbgƞ<.S4xܒ՚~ᔔmpKo uw>Z v`;*1[CG37Hr#rxր+.(fx;JA1 5#/ε W?:$D ַ4xZi[M:)'@`٠_Y,u|)7KR3A"n;z[8iӛ-woMok/kk$i1d4 y/<'|.: F[s7*36}9 ()(oUǏŪFWIӁsIp{'.OJ_V@5 q4]9{t_ aMGNň57 lt ;=*_U^@ȅ1$=^9zT$"B)/ܟ#OV\+`mD6yXo%?E{̃=Wi͌u%~{G%XV !1ɡB2@xٞ>!;x. /U9Rьh֌VhGDtZFӢxh9g#>jUL̙į]-iSw-msƣBmsZJ)zx#0̘K($"Tcrg.Ґxސ?07`]gD7NHq3j僨`ɭ$ ;L%zYaĺ ( -&3!݃<q˔˰Dͽ.qQ(y`M7>*ySr,D>rWFZ6m͒DDzܨ,ߟ?)z/E cp񞚁7N桗 W \ˊIar$Lcz;$V 8OWozI;py|Tq#wP6rujR$903}-M {7Vd^y`2pO EH!|g N# bʬ5mޛ#3NKG'}nrbod9vnnGz܀GoT_G/eȚƻu͑Z@cP%?o""WUx^O{I$<,%Yw?U$QHh6K" r}-kFtħ$Vܕ49H="?Uo|Q7hS}lwɕ7g1.CbT('zBɧnn>'3.EIRm2E--^pQX-IS٠<7(XZV嗚Hv-9w}Òxnn zC^#Yv1dT h~ORpT/uΓϗ 371o Ia@E1."c+ ΙPeuɨSE?˛ꕑN -9`_[oH/E} %EyE%rB񢃽q=Vcx欇'HwW/p7&34ILN =s\x'Q*Ҏ}/r66 ] t[2NQ5|ZjQx"7?_Wr[h8Wb'e%r!GXn_oMF1ovG܊1=gɍ԰' fѪR$=-j&{ #trJs0(GќSpn#ºP/moAćäF&I@{k7'i5)n8yE?Jm)T/K7H[v~'C\]uyebۦĮʰkDteqUN>,_hXje@ð5Y$ 6TVKy,Sl(jBhw[3 .[Vxg;'v0czSFX3"IQq혣0撁qK08ҟ)r.+`ҿabqr uΧN‹5?֫x׈[ A:aeNN΁+ ~|{fLD\/q>:zbDJ-4>؏E_\6޵sutF\^x&U X:v]SW`#\FKO< {mU>bzXF9)1 `>n=v2f=_y7btacxSSRw0S s޸:-&rn9*wTܻxw7-y>!. -q-Y ̹LܚrgxNbZ1^'Ex$/F<ܺ"X]%+N˿V˕0^c<^Cg54@hq^)L;4־0iM ӯdu|UEɨLR@l6%S"aWEPn}l`mL: 8<֑uya^$ gh:.FpqbeS!f[w(2p&qA^&r]<LL.;nL+N&jiG-h]Z=_byΣ΋zqE!tw?[d>Z[8} /H?H UWW9!Gcŝ5ٮ{[\RU)k;]Eʍqr#9aHw&QXrft?h-6?,0藖rb bQqXv}D;[*Rsam1Q^oǧD_X2F?L!k9k"J'@}5&Jx'rPw]ijX>7?Snx0_^eի>pDIҽ3ǡ{ [^?XP[r5BT5 i7wtT`d%et " & ײ$l,|8+bZ& kNj~TQƩݹV?/<<2dNpvĜ|JX32|AFNcn-8T`z.!6>(>CcmmGK`a@q ]] 3X9x,)D&NO@A zQHUb 6`O'?\gS&wݫxVȥ™ysN_? hf GSFCCCt G ;<=@|C^x^^(µa1eA=-F3\`{ze 2t!B4)n)Rd+q}Mބ>'et4ߢTTcڮ~&>|X'7-xo@YھfIg7Fhj8&h^gHz6ޠ|8!} kNKƥ//$ S_XKym9O\nGAM gc{ lRmp\bLô: $ hB-fڠoP7О t ZAJw{bgC2Eb-x-p3io/iSkpgy :UKɀ?f~i@l 4` :  I5X9L*IAӇYh*b7_+{UgB ij]iij Nڱ&H'2g,m-3mt*FM^z#1XFLD8͒5_H8XRTad!̙g7U1=H C,3~U%gE[$=ܚ , &c:f.%Vd'd#d#KÀ >q aA&; YWM7:}럿}%H(H4eȒ)[W)PЙJywN:CbBBW( IB @  B4T4tىI6y )RƣBZ+4hҢM.= <3aʌ9 |X7e:lq⬱;韸qo>| P=,JxC";_h1b{CY_D˪׻=*'.CRn黱"J1Ӯ32uE\~eUTZZu5hԤY qD^fa:t:[v:u֣WʡC;b¤9L1kμSN;sλ`E\Ε,jznfr+s'w2>I3E"rIHH=+ZvujU^9AES7-ԂɚHUHpCWф֒YUzEXy95ڏl |iݒdvPhapw>+z%R8R8V>Y.d0'}r'eOi_yF}gg" q׆94nVޅ0t~RV!zO_ SĶeE[} :ip̢wY>4"xȈ1gy϶l`LꯉD nepxP_W{0DחKsK(77L]*zRntP-p` T*5U@ODzʼn~'U۳}%\dRԕ-N6I'6Mvz^Rb١6]sn=јŽ(ߥa;LokfM.mn&wĄRoJaXK B,]2onA!K#Xb)Q  J98`cmaphu gaspglyflhead$6hheaT$hmtx_b<9 locax maxpBx namewpost[ preph j_< ̏u2' #Zm|^ ,#?@XKX^,UKWN m|m  MD70040#84&4(028800J0A090(020#0E0080B0:0X&ZaJ/~J*JJc-JJ.QJJZJJ,MJ,lJ % D[9 -)cD c#0l`  >&%&%e %)>>>DG>)>$ >&t>$l)9)i Ci$0=;0X0K00E% .*Y(09. 002 0?W8 ([7$1$ZZZZZZg /*J*J*J*JJ,,,,,08,DDDD-TJc>&%%%%7&)>$$$$$02$)9)9)9)9 >ZZZ/&/&/&/&~J&%&*J%*J%*J%*J%*J%c-%c-%c-%c-%J)>) J>.OJJ)JJyD}J)>J)J)>J(=,$,$,$.B$lJt0lJtlJt %$ %$ %$ %$l mD)9D)9D)9D)9D)9E)9--))))))0,Zh -$ % l    C   0X%$-f9Z9#)#),d8M>(>6      0P0(00,000>000c0;090B0I0,) ,$%)(#j;^;8C4&4cDc#ij$          C  0$   8`@ ~17>H~    " & 0 : D p y !"!&"""""""+"H"`"e% 49AJ    & 0 9 D p t !"!&"""""""+"H"`"d%A)ofbIFEDA80'\Y~{srkh\@)&    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`adqdeifwok~ujrgvMl{cn:m|gb \]ab^_3k}ijex`chEKpGHIyLJF(R(Hj(Zt"Pbv4P~4@Tn~8j|$4FZhv"Jl  & X v ( J j ~   J j j ~  $ 6  * b p  <HfxR|Dx2Th|8`@bBN&^"6Jbz<fBl .P,r$Nv6hB^@r X !!R!t!!!""8"L"`"~"""""##>#`######$$$4$T$|$$$%%.%T%z%%&&.&\&&&''<'Z'''((T(())P))))***H*z***+(+Z+++,,B,t,,,- -,-N-l----..T../(/j//00,0T0f0x000001 181^11112$2233F3d33334444*4>4R4f4|444555"525T5n55566(6J6\6|666777N7t7778*8B8Z8x88889*9J9f99999999::B:\:::;;0;Z;h;v;;;;;;<( >>V>~>>? ?2?P?v????@ @F@RD353'3D R7e#'3#'3^vv %##5##5#535#53533533#3#5# `tht````tht```hp~pp~~~4~*"(.%+&57&/77.546;73&'%74&'6~fJJ2 OCgVxi J>4 I>hK+Z#Qhkvt h XLca j!O "2"6264&"2"6264&"}Ib  b  ?ݶHHݶHH#$-62>7'#"&5467.5267'>54"opj2;$Nc(0/!?8'3<&#.4676?30.$ ">?h^5p4W#64&/3$ "=/.p2i.MDDqd(e#''7'773{&I)g/if.e'K&{xyO;NI?Iyz2 753533##52xxxx32Z{8`G75!8(zz835387 v*:2 &&"26r4{56z4k7cdbbJ#'7?l\gA)57>4&#"'632!TK;1-CObi@TsuMR]& kJlMh9!62#"/73254&+532654#">\hM0)kvW` pLg5+!3cEN|$W38=khiX%,r8"G( !5!533533#@裘??miQxm2!632#"&/73264&#"'>8vl.u#$yQ14,(C3Rxpz f4a, e#&#"7632"&632"32654fKB'qr|NY/3p04hpX50^E5!'5E{$ &2#"5467.54254'#"3654چ,,&q',*;X54#"'6534adkU#"'&'#"&63253326=4& 37#"&'&46 27&=&#"a`G- PD^]Wh#)  Z:s>z1&4*4!1$ 8uz (Nk u .5kv$F{ :II 3!#'#3zEEX{{6CJ6!2#!#32654#324J jj")-+ti~~-+\z{NU_9CH@c`$0R/%".54632&"27jf:oVqc87] *\|^śn#b[JP !#3264.+3276/Xr?=t7;2[[K"%Usy_+ qD8H&J 3!!3#!J.xvxJ 3!!3#Jxx-+%53#"&632&"375eƏYw|]l$x>:[Sxrk $a^J[ !##333XJ33JX 52653($aFx)/mLJA 3#373#Ԋ\pr\ ! J)33}J333####JxxXJk 3333##J 0X0,`6264&" &6 ;<<'6lipphJ6 %##32'3254&+Dp{og25owv?7,d` "&6 '&264&"F~6iS~Z s;<< iM;xhppJB 7#!2#'>4&+3ԊdaO,030~?v}uu}K3#33v-X33333# #TzzTkk22X 0 73#'#~ę~Fb,!#33\ҙ}}k) 5!!!55)>0xxZxwD@#3#@ssxxh %7tr 14#53#53#suxxx9 '#3mqr9[`E !!`TIr4%fWJ!"&'#"546?54&#'6232?5 3=HKVYkkU81&-Xe#PC]Pn k> 2#"/362654#"0iap+r&@C.T($.sq lAT &2&#"37#"&64QO&E--Ftk8oadj;=k}{&#5#"&63257&#"2F3mVgh 97+Q$SD!~}  NB%632?#"&532!74&"/,]Is]qf ڬ&_')cx ]f3#3632#4&#"ĆE7dL-'' $v{ ?= >3353> 4 73'>53?Gk5-$#fa6c"/H> 3#3?3#'Ć3ce7r D33DD>!3#3632632#4&#"#4&#"ĆE1Q,\LcM* .,'& (//s~ @=K'J=>3#3632#4&#"ĆD9dL-)& (v{ @=$2 4264&"j4j))j)||HFF>.3632#"/"32654>A1e`jy!& W%& -:+'yqZDR&. "&632#5"32?&i`o=b$@C/U(% % s)p ;ET >c 3367>TLQ:52$&"#"/7264.4632|c'DB^ |a#%LlU;f!w'BJp&>QT#37#"&=#53533S{LC#ZB;;{kQmr93#5#"&5332?eH5hH.,'  (sJ6333#PTx~ 33333# #=LL=_99~x 2 373#'#7PQQP. 333#7#[[7^~:) 5!3!5)s|xxxxzE.574'565'467)GF+*o[pp[q+@?6=@u"&rNZyIhD_Lr"C.3Cr$zY7'467.574&'55>m+FG)+q[pp[o*7u@=6?!"rL_DhIyZNr&=N$"&"'63232?8&7 ?<%3, k4, k;L#5#̐ RX;5&753&"37nOOe34?t'(Kh ei d1r2d mK"3#37!535#5354632&M4|EQJ@@PVC@D'A5rprr;hKh$"''7&47'7627'&264&"EZ(I\HH\H([(I\II\IxF33F37I\H)Y)I\II\I([(H\I[3F33F,533733#3##5#535:\{zY#pp-pp-E.3#3#E%B~&2&"#"/7264.5467&5432654.qj&6>2gr8c lk/2D(,@TO/ 92%*:G,.aVl9-?G#O LC2 T:53353XT.U!6&462264&""&4632&"37˝zz{};=G' #4#CyHF V$K*9q"&'"&54?54#'62275_ D/ *d8C,FK/  R ;3_K1((" '57'57mmmm?KV`KV`9hf!#5!9xf.U"6&462264&"#32#/324#˝|z{B`4>)d"#x];3]+n]OOU5!Udd462"&264&"SSS)D++DۆSSRD**D+2 53533##5!!2xx4xllxddx!#57654#'623I.%LIj2&^Z;%c .W-!2#'7254+5324#'6y#vy=>B@TD!Y57i]U[ 4)7(fsJ?.3#5#"'#332?kH5+,'  (:-#!###"&463!#>rTfhTK$6mor8M7538#"/73254+53;:5,#&&5&$n9Nj& #5'7j/1j JK(:| 2#"264&"ө::Y JH71 %'55/55m߮mK`VK`  #5'75#5733733#j/1j_5wG'v4[  JKx#]#XZZ_# #5'7#57654#'623j/1j_5wI.%LIj2&^ JKx#]Z;%c .W-$!+2#'7254+5324#'65#5733733#y#vy=>B@TDA5wG'v4[ !Y57i]U[ x#]#XZZ_#@&4>=332?#5~adkU232?zEEN4 *?;z +X{{6C. `(. aI 3!#'#3'53353zEEĀVX{{6CƄIO#'##&54623&3264&VVEE3  j{{!;CCC%& >!5##!!3#!3z.Ptt.5/$#"/73254+5.632&"27{;:5+$&&|[oVqc87]^`&$n9N_ sn#b[qJ 3!!3#!%J.!xvxj]OJ 3!!3#!7J.)xvxGjxOJ 3!!3#!73#'J.gu14xvx88J 3!!3#!53353J.yVxvx 33%J!Xj]O,337J)XGjxOO 3373#'Ju14X88: 3353353JVXS!5332+%4.'&+3#32766Xr?=tZv C[[K#%&Wuza,M+22 &)Jk 3333##"&#"'>232?J 4 *?;z +0X0. `(. a,`6264&" &6 %;<<'6l!lipphj]O,`6264&" &6 7;<<'6G)lipphjxO,`6264&" &6 73#';<<'6'u14lipph`88,`!6264&" &6 "&#"'>232?;<<'64 *?;z +lipphY. `(. a,`6264&" &6 53353;<<'6;Vlipph_8 7''7'TUUٍUUT,`*!"''7&546327&#264'F1/:b:X:+=dAU<Q; }1|NԵ +RѳHp1s0i2DJ 7253 &53% !ww>}uu} j]ODJ 7253 &53'7)ww>}uu}ŸjxODJ 7253 &53'73#'Gu14ww>}uu}U88DJ 7253 &53'533532Vww>}uu}T, !#33 7\ҙ}})k4jxOJ8%2654+##332C36ioppp}?9kcby>L(3#462#"/73254.4>4&"Ćkr+X 5[o6La%P8$X(k* fXJS62'=;:eKk &8Cf8$*#(!%"&'#"546?54&#'6232?5% 3=HKVYkkU81&-Xe#PC]Pn kfWJ!%"&'#"546?54&#'6232?57 3=HKVYkkU81&-(Xe#PC]Pn kfsJ!("&'#"546?54&#'6232?573#' 3=HKVYkkU81&-~T{..Xe#PC]Pn khCC!4"&'#"546?54&#'6232?5"&#"'>232? 3=HKVYkkU81&-98-\ % =-] *Xe#PC]Pn k"$K%$ L!%)"&'#"546?54&#'6232?553353 3=HKVYkkU81&-XXe#PC]Pn kx!)1"&'#"546?54&#'6232?5&462&264&" 3=HKVYkkU81&-`CCcDD^((Xe#PC]Pn k-CcDDcC(("+1$32?"'"&46?54&#"'62632!'32?34&".-Dbs3TLWWlHU +4Q چZ8)(1'_&&h0 %WEu%%^J]05 5,.&%#"/73254+5.632&#"37?;:5+$&&WMdo4QO&E--Fta9&$n9N` ~{j;=k%632?#"&532!74&"%/,]Is]qf ڬ&_')cx ]f fWJC73#(fsJ@ % 3#73#'>k~T{.. DCC( 3#53353>nX T&##"54632.''7&'77"3265&{xmm>3(,6L.>yX`6)+]892qXhv/CVL3 ^ @L=+iXc>&337>320#4&""&#"'>232?>?dL\,8-\% =-] * v{ @=k"$K%$ L$2 4264&"%j4j))j) ||HFFCfWJ$2 4264&"7j4j))j)8(||HFFfsJ$2 4264&"73#'j4j))j)Q~T{..||HFFCC$"2 4264&""&#"'>232?j4j))j)8-\% =-] *||HFF"$K%$ L$2 4264&"53353j4j))j)OX||HFF2 535!53Մׄ`xx$_27#"''7&546264''" (Q)^")P+Yj|5)d 5) db;fg<|fH"'F 93#5#"&5332?%eH5hH.,'  (sJ6sfWJ9#5#"&50327'7>hH`.(  sJ6vfsJ9#5#"&50327%73#'>hH`.~T{..  sJ6vPCC9#5#"&50327'53353>hH`.X  sJ6v`. 333#7#7[[7^(~:fsJ>. %2654#"2#"/#36 :+T($-?iajy!& @hDS sq. 333#7#53353[[7^:[Su14xrk $a^ 88%"+/6"&547&54?&46327'#"'254&/24"'73#'yH% Ds_+*Kfm "?~\$:ZJ~T{..R:[S"7#y]\yxrk $a^ DSSD%"+/;"&547&54?&46327'#"'254&/24"273"&'3yH% Ds_+*Kfm "?~\$:Z^8eUUe!R:[Sxrk $a^ %"+/3"&547&54?&46327'#"'254&/24"753yH% Ds_+*Kfm "?~\$:ZR:[S7yxrk $a^%1&/3#7"&547&54?&46327'#"'254&/24"Z.7"yH% Ds_+*Kfm "?~\$:Z1;R3#3632#4&#"73#'ĆE7dL-'' Y~T{..$v{ ?= vCC53533533####35#;BBtNNNNtTT 53533#632#4&#"# 2E7dL-'' t44t8$v{ ?= N33"&#"'>232?J'4 *?;z +X. `(. a.3#"&#"'>232?>8-\ % =-] * k"$K%$ L@p335!J[Xbb3#5!>L Udd[332673"&'3Jq"7#y]\yXu DSSD%3#273"&'3>C8eUUe! BA\\A#(3337"&547J+ * ;[=DX2!_ 4,B6(3337"&54753>+ * ;[=F  2!_ 4,C54J3353JX>33> d 5265373#'($au14Fx)/mLC88- 73'>73#'?Gk5-$d~T{..#fa6c"/XCCJA 3#373#3#ԊZpr\!7y  73#3?3#' .7U3ce77r J )337})jxO)M337D(D]fsJJ 3#!33̂7y/}M7333#D7yDMJ #!33͂}ND3#3/7yDD )5'7373}*AkcAZKGFZs} 35'737w3At?A#ZQZ,ZZJk 3333##7J )0X0GjxO>337>320#4&"7>?dL\,2( v{ @=fsJJk3#333##+7y M70X073#3632#4&#" .7UD9dL-)& 7(v{ @=Jk 3333##'373J M410X088>3#3632#4&#"7'373ĆD9dL-)& #~{..{(v{ @=ΗCCJ,k3333#526=##J au($Y 0=mLx)0=3#3632'>54#"ÆR/]OCo32!264&"%34&".-Dbs-0jj|:NK4 j))j)B'^(&hDD%,-$^SDCCv5,/JB 7#!2#'&+3267ԊdaO\30~10)?:<jxO0c 33677>TLQ:(52fsJJB73#!2#'>4&+3.7xdaO,030~?v7y.TLQ:M752JB 7#!2#'>4&+3'373ԊdaO,030~c41?vTLQ:A~{..{52DCC% $"#"/73254&'.54632&7m6PiNq$Gj1It_|lJr$ )QfsJ% '"#"/73254&'.54632&%73#'m6PiNq$Gj1It_|lJr$ u14Q^CC%1#"/73254+5&/73254&'.54632&#"w;:5,#&&Lh!Gj1It_|lJr$ :m6PkY&$n9N]kX $![QfdmH "@Qn $-#"/73254+5&/7264.4632&"@;:5+% &&?H|a#%LlU;f!|c'D&$n9N_p&>Qo'BJ% '"#"/73254&'.54632&/373m6PiNq$Gj1It_|lJr$ j41Q^CCT)#"/73254+53.=#53533#37"';:5,#&&-(;;{{LCS&$n9NjROrrk # 5!##7'373  41.zz.ϕ88#37#"&=#535337#T{LC#ZB;;{zsQmy5!#3##5#535.zzttT#3#37#"&=#535#53533S{__LC#ZB;;{zEdsQmdEyDJ 7253 &536"&#"'>232?4 *?;z ,ww>}uu}N. `(. a9&#5#"&503276"&#"'>232?>hH`.88-\% =-] *  sJ6vw"$K%$ LDJp 7253 &53'5!1[ww>}uu}fbb9#5#"&50327'5!>hH`.  sJ6vaddDJ 7253 &5362673"&'3@"7#y]\yww>}uu} DSSD9#5#"&50327'273"&'3>hH`.Q8eUUe!  sJ6vBA\\A#DJ 7253 &53$"&462264&"VVV{ 6 6ww>}uu}vCCvCk&&9##5#"&50327.462&264&">hH`.CCcDD^('  sJ6vCcDDcC((DJ 7253 &53?%7CtNCtNww>}uu}_*%*92#5#"&50327'7%7>hH`.9um}um}  sJ6vCABE(K725337"&547.535 * ;[=5qqww>$-B_ 4,<1tv9( 337"&547#5#"&5332?e' * ;[=J N.iG/5 +!_ 4,B6!rL5 33333# #73#'TzzTkk|u1422X8833333# #73#'=LL=_99d~T{..~x 2DCC,!#3373#'\ҙ}}u14kꕕ88. 333#7#73#'[[7^9~T{..~:DCC, !#33 53353\ҙ}}Vk鄄) 5!!!557)>)0xxZxwjxO) !3!5#7)s)(xxxfsJ) 5!!!55'53)>~0xxZxwχ) !3!5#753)svxxx) 5!!!55/373)>s410xxZxw͕88) 5!3!5/373)s9~{..{|xxxxȗCC,#"/5325#5354632&"3#AOY3*@366?S$7,<yy/gP nBrkQ m&rI!#'##&54623 7;>4&"VVEE)B  6!i{{#;CCCujxOj&%!)15"&'#"546?54&#'6232?5&462&264&"'7 3=HKVYkkU81&-mCCcDD^('}(Xe#PC]Pn k-CcDDcC((fsJ ?!5##!!3#!37z.P)tt.5jxO"+15$32?"'"&46?54&#"'62632!'32?34&"7.-Dbs3TLWWlHU +4Q چZ8)(1'_&(&h0 %WEu%%^J]05 5,.1fsJ-a!%"''7&546327&#264'7G1/:b:X9,=dAU<Q;) }1|NԵ +RѳHp1s0i2jxO$%27#"''7&546'7264'"7"& (Q)^")P+Yj(s5)d5) _ db;fg<|fsJ2H"(F %$3#"#"/73254&'.54632&ׂ7yrm6PiNq$Gj1It_|lJr$ MsH "@QTknkX $![Qfdm3#&"#"/7264.46327y|c'DB^ |a#%LlU;f!M'BJp&>Q  3#5!##߂7yMezz.T3##37#"&=#5353317yP{LC#ZB;;{MkQmrD:73#'~T{..DCCD>'373j~{..{DCC=4 273"&'38eUUe!BA\\A#C,53C, &462&264&"WCCcDD^(( CcDDcC((( %37"&46?: * ;[=)/D_ 4PAI>"&#"'>232?$8-\ % =-] *k"$K%$ L3|27%7um}um}tCAB%5##"56;2?3".@U )@V3,2)FM, ~ m n r )933333# #%TzzTkk!22Xj]O33333# #%=LL=_99ґ~x 2fWJ33333# #7TzzTkkѴ)22XGjxO33333# #7=LL=_99҄(~x 2fsJ33333# #53353TzzTkkяV22X33333# #53353=LL=_99aX~x 2Tu!(;"&'#"546?54&#'6232?573#'6"&#"'>232? 3=HKVYkkU81&-~T{..8-\% =-] *Xe#PC]Pn kJCC"$K%$ LFZ 3!#'#32673"&'3'%zCAO"7#y]\y`Ntt3: DSSDfWJ%u1632?#"&532!74&"73#'6"&#"'>232?.-Dbs]qf ڬ'^'L~T{..8-\% =-] *&hx ^g5,.3CC"$K%$ L$u)2 4264&"73#'6"&#"'>232?j4j))j)J~T{..8-\% =-] *||HFFxCC"$K%$ L, !#33 %\ҙ}}Ц!kj]O. 333#7#%[[7^~:fWJ"!#373"&#"'>232?UЙ{zG8-\ ) =-] *'t"$K%$L. 333#7#"&#"'>232?[[3Z8-\ % =-] *p;k"$K%$ L9-C!!9 Cr9!C!!9Cr##70U)73)/U73/Uu##7##70UQ0U)73373)/VR/U~su7#7!#70U%0Uu 53533## r rr7,5#535#53533#3#Grrrrdd^|73dd8 3533533538oo2 '"2642""2264&""2264&"  I    PHH?w#mHH#mHH('57mm?KV`6!7'55mK` '5wx#  !2"&4"264&J?>>!LII !@]5#5733733#'v4[ #XZZ_##632#"/724#'7|]v.68>N Zco U   !632#"54632&""24|62C4=L 6B= #4k=YZ Wk"*53'75_y[ie   !#42"&546?&254'#6"365 @?h&  %$  YZ& %9009"m   !#"54632#"/72'"374f@7>LII !@]7#5'7j/1j JK#57654#'623I.%LIj2&^dZ;%c .W-72#'7254+5324#'6y#vy=>B@TDY57i]U[  5#5733733#'v4[ d#XZZ_#7#632#"/724#'7|]v.68>N Zco U   7632#"54632&""24x62C4=L 6B= #h4k=YZ Wk"*753'75_y[kie   $742"&546?&254'#6"365  @?h&  %$  YZ# %9009"m  7#"54632#"/72'"374f@732&"3#3#27"&'#535>owMtX8 8|cep@7cfubk(8fBf-# m`gfBPKT53##5373#5#'P)Xg)-fR"7&5OO9Ǯ(!73.'&546 3#5>54&"#4P ' pp.P1%z%'i DR[L rc18tVVt8%%c2#"54632.#"'6"3265&yxri=28I MUb\[87&ȲjtiO g-|]h, )53#3(|{Zh,NL ###5!#Oq5944xxL!!!!5b x]xSB>775!>xx~; 5333#\ f@x8'gy 7"32632#"''"3267&24#"K))KK'(7$$ $$yVNNMMp8pp8c9 #"/72654632&"Y49BS!6 < n%^jR n&;-#"&"'>232?"&"'>232?9'7 K7'3D9'7 K7'3 , k!, k, k!, k9:5373#3#'7#5379Dh2^&?h-T&'y)qyWy)fyWB  %5%5![[16yt~xxI %55!5Y[[Q1~tyxx, 33'7'#O^^__DPr 73'>?Gk5-$#fa6c"/73.7)2"&$"264vssj11j1{oo @;; K#'7K}. cMey,)57>4&"'6323oN7/K$^xO:ISm[79: r=K3:$62#"/72654+53254#",sa@OnYJc!n|N@ADV9CR%#Nr %n+(!5!533533# ~zz}))RZHrrxR%!632#"/7254#"' ,/bhmgPi#~R!2cCR\r*2-)"632"&632&"3254 gD4}jeYD lD#0^ZfOX}z h _925!'5okn[(%2"&5467&4254&'#6"3654j@vv($@q<8|L$,<,E(3%IIII09(2 '&)#7265#"54632#"/77327&#"-2 $5n[yeY< MO* P%"g6/PY|g 1Y&4>=332?#5{adkU?h^5p4W4&/3#6z/.$ ">?h^5p4WD@ #3#@ss xxh# 53#53#sxxxE.574'565'467)GF+*o[pp[q+^?6=@u"&rNZyIhD_Lr"$Y7'467.574&'55>n)GF+*o[pp[q+M?6=@u"&rNZyIhD_Lr" .%2!j]O&7)GjxO73#'u1488S'373X4188Y"&#"'>232?4 *?;z ,. `(. a,53353*VBp5![bbW 2673"&'3_"7#y]\yu DSSDS+O"&462264&"+VVV{ 6 6 vCCvCk&&p7%7CtNCtN*%*C53C o 2"&4"264&J?>>LII !@]z#5'7j/1j JKz#57654#'623I.%LIj2&^zZ;%c .W-o2#'7254+5324#'6y#vy=>B@TDY57i]U[ z5#5733733#'v4[ z#XZZ_#s#632#"/724#'7|]v.68>N Zco U  o632#"54632&""24z62C4=L 6B= #F4k=YZ Wk"*p53'75_y[Iie  o $42"&546?&254'#6"365  @?h&  %$  dYZ# %9009"m  o #"54632#"/72'"374f@7#"'&'#"&63253326=4& 37#"&'&46 27&=&#"a`G- PD^]Wh#)  Z:s>z1&4*4!1$ 8uz (Nk u .5kv$F{ :I  C2"&4"264&J?>>CLII !@]8#5'7j/1j8 JKC!#57654#'623I.%LIj2&^Z;%c .W-C2#'7254+5324#'6y#vy=>B@TDCY57i]U[  835#5733733#'v4[ #XZZ_#8#632#"/724#'7|]v.68>N 8Zco U   C7632#"54632&""24x62C4=L 6B= #4k=YZ Wk"*8753'75_y[ie   C#742"&546?&254'#6"365 @?h&  %$  YZ& %9009"m   C7#"54632#"/72'"374f@7?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghjikmlnoqprsutvwxzy{}|~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~uni00A0AmacronamacronAbreveabreveAogonekaogonek Ccircumflex ccircumflex Cdotaccent cdotaccentDcarondcaronDcroatEmacronemacronEbreveebreve Edotaccent edotaccentEogonekeogonekEcaronecaron Gcircumflex gcircumflex Gdotaccent gdotaccent Gcommaaccent gcommaaccent Hcircumflex hcircumflexHbarhbarItildeitildeImacronimacronIbreveibreveIogonekiogonek Jcircumflex jcircumflex Kcommaaccent kcommaaccentLacutelacute Lcommaaccent lcommaaccentLcaronlcaronNacutenacute Ncommaaccent ncommaaccentNcaronncaronEngengOmacronomacronObreveobreve Ohungarumlaut ohungarumlautRacuteracute Rcommaaccent rcommaaccentRcaronrcaronSacutesacute Scircumflex scircumflexTcedillatcedillaTcarontcaronTbartbarUtildeutildeUmacronumacronUbreveubreveUringuring Uhungarumlaut uhungarumlautUogonekuogonek Wcircumflex wcircumflex Ycircumflex ycircumflexZacutezacute Zdotaccent zdotaccent Aringacute aringacuteAEacuteaeacute Oslashacute oslashacute Scommaaccent scommaaccent Tcommaaccent tcommaaccentWgravewgraveWacutewacute Wdieresis wdieresisuni1EABuni1EB0uni1EC5uni1ED7Ygraveygraveuni1EF8uni1EF9 zerosuperior foursuperior fivesuperior sixsuperior sevensuperior eightsuperior ninesuperior zeroinferior oneinferior twoinferior threeinferior fourinferior fiveinferior sixinferior seveninferior eightinferior nineinferiorEurodotlessj commaaccentCRDLE zero.pnumone.pnumtwo.pnum three.pnum four.pnum five.pnumsix.pnum seven.pnum eight.pnum nine.pnumquestiondown.cap endash.cap emdash.capperiodcentered.capexclamdown.cap parenleft.capparenright.capbracketleft.capbracketright.cap braceleft.capbraceright.cap grave.cap acute.capcircumflex.cap caron.cap tilde.cap dieresis.cap macron.cap breve.capring.caphungarumlaut.cap dotaccent.cap zero.numrone.numrtwo.numr three.numr four.numr five.numrsix.numr seven.numr eight.numr nine.numr zero.slashat.cap zero.dnomone.dnomtwo.dnom three.dnom four.dnom five.dnomsix.dnom seven.dnom eight.dnom nine.dnom hyphen.capmȔ,n̏u 4NDFLTlatncpspkern&0  $%&'()*+,-./0123456789:;<=   !#%')+-/13468;=?ACNPRX.5tt(>(d  " @ @ N \ @ @ jBp&4Rhhh.8 "r @ @## @ jjjj#$%&&&<&jh'(&     (D    (  "R "R "R "R @h(h(()) @)2 @ @)T)n \  )(D  @h @h @h @h            * .jjjjjjB    .BBB>>++(++(,,l,,,,,,,--&-@-n-n-|-.`.-n #  79:<!/13CNPRXZ_b&*24DFGHIMPQRSTUVXYZ\^&     $&(*,.02<>?@BOQSTVWY[J$-7 FGHJRTV5(.    ! ";=@BC UVW[9IY 9;IY[$&*-24DFGHJPQRSTUVXYZ\]+-      $&(*,.02579;<=>?@BOQSTUVWY[9<13XZ "9?IYo~$9;<?@J13;=UXZ IY,#  9;?@`* $-DFGHIJPQRSTUVXZ[\];.1''  $&(*,.02579;<=>@BOQSTUVWY[\]`cg9?IY II IY/3# 9?IYo~ 9;?@`8 $-9;<?@D` 13;<=>TUXZ`cg9;? 9;IY[  #IY[D7:0 0 $(T[I #$&*-246DFGHIJPQRSTUVXYZ[\]m|98*     $&(*,.02579;<=>?@ABOQSTUVWY[\]`cgij 65'&*24DFGHIJPQRSTUWXYZ\m7 >*$      "$&(*,.02<>?@DOQSTVWY[\]i #IY[o>F1$, Y[IY)r&*24DFGHIM RTWXYZ\^0&       "$&(*,.02<>?@DOQSTVWY[n &*246789:<FHIRWYZ\      !"#%')+-/0123?@ACDNOPQRSVWXYZ[_b "9?Y~ "9;?@Y[`~9? "9;?Y`~G$-< FHRm D,;0'%  1 3 ;=@UVWX Z \]`cgi9?M "9?Y~9?x "9;?@Y[`~ 9;?~ ;?@` 9;?@Y`~9?k $-79;<=?@DFGHJRTV`m  !13468;<=>@BCTUVWXZ\]`cgi 9;?@`979<?FGHJRTm  !13@CVWXZ\]i9;?@`9?l&*24DFGHMRTXYZ\^-%     $&(*,.02<>?@OQSTVWY[ @` 7<!13CXZ9$-<13;=UXZO9;I[$%&'()*+,./0123456789:;<=DEFGHIKLMNOPQRSTUVWXYZ[\]      !"#$%&'()*+,-./0123456789;<=>?@ABCDNOPQRSTUVWXYZ[I)(%I2 $-79:;<=?@`!/13468;=CNPRUXZ`cg> 789:;<?@IJWYZ[\o !"#%')+-/0123CDNOPQRSXYZ[^_ab~(   1";?1@6EKLMNO_`30 _b~$ !"~    -""?@`~ c $%'()+,-./013579:;<=?@Y[\`!/123468;=CNPRUXYZ[ "9?IM,Yoc~ "9?MY~  0"/?.@.IY[_ `-  9~M *  II  "'?@"`!~ I$ " ?  " ?@`I .,*  %"!~ 79:<?IYo!/13CNPRXZ^_ab~f "? @ EFGHI JKLMNORTWYZ[\`m    "02@DOQSVWY[\]^`acgi'$  #+ .  #+ . $-- #;=U ?@` ?? ?@` ?@` ?@` ?@` ?@``cg ?@` ?@` 79<!13CXZ9;&*24.   ?&*24)   ?&*24(   ?<13XZ   #? D`(ccEmmFooGxxH||IJb9;DNc ij ~~"#01234 l*$ 333-u"" &#$%&'() &&&&((    # # # $ $ $ $ % & & & & & &'()))  $ %'''(( ! !  !""!# ! """"               !!""""""!####         ) $$&(*2 48::<=DFHHJK NN"PX#ZZ,\]-mm/||01HNZ`y!9;DNcij 8bDFLTlatncasefraclocl$&.60B :ABCDj2lzstmnopqrlzstmnopqrlzstmnopqrlzstmnopqrlzstmnopqrs| ((stzzlr}hhkks|Y  >@^`cx\] uvtswxyz{|stzzlrinc/fonts/TitilliumWeb-Bold.woff000060400000073520147177152050012635 0ustar00wOFFwPFFTMw4sr;{GDEFSt'GPOST"tEϚtGSUBS)?3NOS/2P`k>cmapȒZgaspSlglyf =headl66hhea$hmtx4 _b<9loca~xmaxp BnameJ$cpostM45 [prephhF_< ̏,n̏u #Zxc`d``W$+aQf {rxc`d``<`L@ `>5Uxc`fŴ)B311  pČ0Nw·,jXr[&0R LA &xKh]E3'Ooomny$^\CX#b$ XS%>Kܹq pQp#b\(..MTVZ@2c_w朙{fw -4A_S@~-ks5n*$ e߃~.a3f4f^_CG5OiUaBQtQ3 ٤ h}IGUcM];+qP5O<,6YlktϪa=d{%Mga9`{Ƚ̳E u9nI% u:k|AZ]bC~k½QDk=1:¾'_oW}%jU?-ȞW0pp8lC\7c&Z6bqx,Ƶa>ߊM1؈^k$Vlϔ8ll]cZW鱻5zFx-j\ql6/a{svYnx[ ўeu}j4wKW8^ͳ7ḳ#wӶ9[ȿmRDc~ ҘL5Mf@Cpv>6(A7a/;=NsО\\{z$7ؿ4yJz?}V1c2= 6O݉ _厧9ZTKm~SӋc_<vc]/"|׬B_b|U/;Oٗ>L>sӟ| ) xoOQ?-E]u{QnVv̠--]سFY+HHHD~4*z}Hě>9>yP9Z!:#Z&'4c(թG"dDKhi4><63͋U,5˭ + "e:+* }Fiw ˞9ZP Q7^j|Kl۰*>yTS}AMjGmPW]O҈4)h?-GkLڨشUtBWѝBOzћ> % d5D+a 'HUoьdXr<$&Stu&M s%^\.C ia^Xn [[wUD2襨*ڢ.Yx|b!qQ<%.ߊďLH%mɽ^siY.=~>YN6-CYKv+GVyN>kU%@0H YGZȓ¬ %5Ş*zatGBߡJrTYQQ*;*7ռT=U갺RWJj&4+f%mMmi$nQw}{5k !g( Qo䍓7Ɩd6eM3צSӝ1y-Ê[Ge붵mmmʶa;%}ܾj߷ucq9;.5s5\MWSa,;6U:v`]mu{}r!܊xu{POS,x / zǼޖO}E߲owGJu_?_BN yE@s79?0 v@'h AbpzpoQ~@MR+NSԏbC㡥^"3Ç(2yE"QJt' ޡQMh1cLb0b۱#KYγK&bq2OAo݄.M%3(MqempG3?/_ߒHKd)YK&T/Lt9Od迪x}|TU;Mf'ie&IH#3R %NPB(&0@P ]QQW/ZwuQW]_]WX׆=y{{i bs=Ͻq 'p*;z`ꮿ&أGT|9<Kl oT\ư/>2\2qfAve/Yo' ׷_؏7[[;⿎["L+l>agrBSpYe0 Q]eHǿ[Uiÿ+%?Nۺ 6]̤Z]+bJ4Qt ⩴MP9-Ι3jo39ub}N#""Nʿ/$WqiiR?ʿѹ='\ p\f)U*p fO9]V^եCŴ+a:ͼMu4o,WMvTbdaųfYW,2/Ve+ dM\ O+ʬ&\)<ÝiF(VY<@"Np=̅" m m&[UՆ%Yd|?Dj0;Kpi9g. :M(}3ƒ\L})1wc()5<!26//{*y ro3)3,q IIxv:K69=%]KZ[¯oTOY{zT_ ?]~>3?s\.8\UPb1`umzB&|.NvRj5AγD iWNhE8eKD 7V%L_^(u-ﭮ^~+N9yk}džxT.qTiax9joWn0gS]L[(?FL6=srg!]ut岆Qֵۿټ95KDJmakM#);J^-`:Fñ?7ߗfPYxhr)8Gy$Q*XJ-ю(=;%?rڟbւų(/7g*_<ɚ٦ٳKFəj2Od'Fw*B'aT.[5ha~t֪;zn|兎8{Tƶnx\NMcx3¦{Y;!1}A<ʌ]܇3.`&M8شr{>n3(.gtĀ>ۑ ğ!Llaђ{]4O97 13aUωuX_f#0x`»Ylyz{V>x$1bT0&m0,,JoIjOߖ:cD^5SrcrMeYˬ)ъƣG ~Oʪ*du+!:c7K*qg( vTբ)qfT6[plAjryZ͹jwTLltFMāuǪz~Ŗ0mI&z +~:CE$]5[*-#<қώ쟽iOA-Gyeb9@NԙVYRQmm܂+į |ւ=&XPVWd!> ܃W'\JS![n3,X@^VnXshZŒkJ]ϋ2yK%V9?q2%D2k4Z,)儢O>Y`\*l T^kJ8K:L}=<#k(k]^އF>['s_ϝ~<kE倥/sU[:RZ/#p|cx? T;-)Pfwmm;:!h}QrRiM*SMYnsye_mj4v ;h0S#"acnJ^1mkS:NGzo&$g|?"Gw~xb|,t>N@8Yglru!j!]#mg: ? R]]bS|U@|!BOM%"d?O)]<%n aj;)jK)9EEj*cb?@}1:rqW]c.DH:f!we?Z)ĒrsrynfGPmw1\CofZUF/]֝im.H);˿l[_aOʺ̎/&Fy=%9G+[891 #R0nM$2m H.zKj):䰩wkUYBCa2}mTѺWFPl^dξq匊epU\U:xeGTu-ۜN緑ƹ. $T RmFeiTE{8Ϸzs>N!\KdMFETRqq|k )9vRK逫 *Y fSGY!FS^B  ;+{*w.8[Vv%!oM| %3.ѣvT*#QԮؿ¥nsvell5 򳲎]zvT\XwxY،깯 ~hGcBqG;Ubu8V*w0nf;eMl3@'cso8ȁ960w(p; +uD<u*;ŝN1C!=$R L`DZsk,_Wt;KǬl/=YNgqRQ|F ~K6/\43>l:,zy.xx:`3(xӡ?p$E;Cr73ר@-bZ2`vۿў{6=tʖʱHDmoQ~?cʔ00(M$z703D4js9T8,늢nͿFs >:%?UQa_ jUCRq9D+3&xmm@e[0TV>z_{uݿZxnK 27Zted",V)hS4aFi\_9,k=%Uqܖ{/Qju=;A}^^y7ODmğ$rJ :t4f0y0Y$TS+D*0u~F3l(s mgwyc*iT.yNȜШ]+)bg5GPaa}9[?FI퀞Ѡ&(Z̤<^_//1D7?@4k'^7\Wթu:4d?Aڪk:rHir$$Qs'4 (wc%aZ].L$CH7op|M0_Ȩo`|V{-l3HRr$>s̨OKGrW归mu*Gf/lN;|c!Q@=;Ly1=1ĬȠl__\^Oi `)+H3J7#$NE4HGQߗ)aSۼIν}p4m]~pnp#V~uop/.CJK}`JarX d{Ēm1bSu=Qs/ėD,+Uf-InC\>D@R>8g$*32!2+jkFyѐm@y Pş`f:vZVj3| : X?5 ?ʯ"9Uq~jKnBѕ%;YaQ >XM00|Ƹ'+@՛O0VqʥC:-=ٻc)g(q߻+^_.$K(pxK|H\2'h"9;@ ̻yk4Fcy뱉I8/A5|zş< 1>_s ~)aH*~LByFkJƶΏPGQť6`NHpgQ>'lwhɕ֦9>].& ;N֎.|k W5c:&0/W+XvHBʖ8B2[~L> "r@s|ɬ.bN.ʁľJ༔G02N?p`ƾ}3_\w`Ƶz-F{xtѝ( ?+y)!Gcam풺I99CS@[R7' eB@qMP -Z[D/zU& )`'~[XP8_8YV$uW^sCSinN_[XYT|kYwS%Å SQO9 'hWų&Ma.*FmMlO9>w<i2'b"( eÕG(" ?O CLe=xT91sB3 Ltp6m^~Ja8:ϑht*/n\6҅$,QnZG9)ȑQld%Knq&IAB&s:,phSVU5a9W; g/t7Ư-{֍ʢęi5*V^bXDY%$;Ns&&lڥN$̹,M񗥗R"#ur3^!9ϯd{;0IV'A%ҟ|-+`?(˰v{0,>রx3oQ`!(`u* is{L$NjI->&g4 ^~Ʒh]NxU|{',ܹhWq,AcztI{kkͮ2h"SRr)5wrޜ͎er#7ZW<$\|ı{e˜k3i~ \ -5eQQGG*0B4ĊtڪqaGThxd0^/fdK?/'K6{< gI ]($FDи7CL@X#MY[2gi RbHQAEBi7RQ-Hɿ&;9Ga$nljR:BF+_dh ^/IUV׫>M2G2)Fy4\X@,~scBtn0ouFFbݴiu|KX/I%;ֵ(XO\ƃS:gqtsVٳOl.5)/:(TS OuGZmaI&F?9?aRg4DÌJkȌ]â++G+*NV $gJ_޺mϡv20+M%z-޽kgtoqaE.d4f'T!o-obx}bpa0vw VRhFj!ۆFr+Rv`O1Cwȸl4x߀aSqp봆#2 Uw˂D].t8o_6R=elW`W YseyyOwITˢĢ#JH҃BdKZ'GK bHnӀO.<8ZY# XZ>c`׎9wt3CWw(f>uy!2O\Z;0*{G@@Ub"kG ?Z5O96:X/>o-_8\IC?- Eut 0 4T*ȖJ191@lvL\y|B $qnD/ # ڙ$ J? ѨGP`8V ^z*6ev`>CN(W˻]˻]*~9]|gTb 2lF#⣄qw(D-=쿜":$x73ۥ@|EjިC300oXlޠ2_8wh*L^(p{',ke_$XӡbPJK7aN~s$ׯ6J'10;i}`paV jF'bA9}:5RoHo?zK}rn^d}j^Gj% ­z Qk YP{EX["nBzH5 "{>Ax5hCsD=&Zө#$ۈ; Ҋz,9ܧqlTZ5 z#cmqOdr^ヘGAo˜hQ ?DYT߻MWIzh-<}BùyZpOE tJۀ5@P+yyON9worv_lG6hJE߮^- 7{{:(HHuxWh@`*oS$ʤL+.@`?ǹ0q!u ҡojH&rQ(gΏ LU 6t+ROS׹# d<^ Lռck>!Le̛CY OQXRFJF ޻d}?c?ӴwDf!?Mj^\e]=r)ԗ$ڣ5hJ>KNIR7"ZBO߄JS$r^;]'Ƌ!ɷ[;KFwBqOG㿠4F>dY [>[\s~P&859@||J#V\ o 9Ys=QX)S0~Z4oRͣR|u[d ac|:CX⨵DyO҃5qO$^ @܀;]y@\}5 }4WogT0kOo{i͍ scZ 36"okyjsLfz. ߲j\a 40才yWm8Wz?O3,8M{Õp\i^^Lw!<4`} F"VHsf_J W[II %Ia5uu?/pkko/}T=i!lN-%-%sЕ7+&=$MT$YI,]#B@qx|r1$߅s L7j}:VQ2&Pyӹys#OR(hhK 8dhd҈4RjY/ϸv2r'\ZAOxj(cnl2 tC/L6qnMί:=#Y>5MCϑ:4':_ŐsJL6SHYUmJ3/'$i3P47NɴVM{ Ň*4F ʎahTKO"VC5nS&/t$Kfg{ ]qug[v}Iﺚ=+o n?]난t.uOKP:wJR웞UCcN5zhMD*욿HtI狜`=Q;] w=SVSj XDc߾ޝ; ?J1! xѾ-:ш@-H %XF~lޯzLCjBUp8CԹs* * !ͭ#d:\M14LHxN>" N$|#>A]ej|lV? T$EbuJ@%dUiyZh6T+cڙgܾ)ÙCݍk-#&|COt5E!oao5L~ 7P FqlxafhwU$Y~xɶw{ore=+aWOf {pcZ4 F0ֈbZe 5O0, V>zb኱ncQC߈1<hgv0FGB PSN咂^smml!pH<q#N;yIf!Ino\Xy%@ |[u %η E.nQf>h|j9cr1b6*5r}`B1k)v\HG㻃'y>ouݻ>8)1?ǔ8cJ։ϰ$3)*//Bdxσ9ͼ@> Ncf1>i饃0rY=-˥'ju-)F΄)Tt*GS*t ˺unGF?;i2S3_3WlL2-bC6:@Yo/ư^wgr>$_9FF":׷78%fP t}qI)B+ibVxYatRʝeND#$yIn(ZhVJF +Ѥ eDXGn>"4HD+smW@|%; $@cWpAX7q#@v<3 'oB;I.9 z@"d AUGG\*sD|Fp |&(3<eF۩jϿ*9oj yJ>%u>Sos.X~ϧ:BGp"ڈ\93˧7yw#>AdÍ޲WƇԶR/qno…Nx;lFPހ+p84GhY03 J1I32r53&RrLȏ_Ģ@!.$;s|f#gɽjPX R%& x=)ebg  k/|$SX`h5v*M H ,UHRAeݬ!tl?JY)Ipg(:+ҩ07+|ᅴoDDve($'D{\><+l_<"nou9&S]!QI9 4`y R/VX!pHo]AUW(D{'Dq;!+?LA7YyF3cM>++q=0e%ȼ¥y1BR|q 1?DA7_q6ϏWjBsP)LW_̮_;g8t q<K=7lHr%~~EpTZ2]pAO'ρpQdSH'c>?z:ntįd sxN‹RV0 )7o!3vt>dWtdmDR }70{{µ|L-5-?@/3ͿLwag`|51#'Цz>lxN"+Z?b?'E8Ԗ jdһb`Y[\4T15WWDž'Zcbs,نtpn!&::f6:&&Ʊ"6p Մj-:5#)iVWFn,PZޏ1l]v#Mo\ voz#t>g,jO'1δ&CHm!eć7of58u0_^ 7ؒc+n+_%\?b1z]fKQ8FƹJPC2f1PӤ3Ιd8^wa/ok$T&%>Ęqߑ zԯJȜ 5T^sՄJ/~ͧѥKthj\dنI9F-+0Ǭ2.\l:Nl=3j%AXlO>;˦\1ig];xzq{>ݝAX+ᲆtЛK&GX3:(4'Zݓm^_Q6=\R|[3ח^‘ilYfvֲ${ݵbJ3&6"Om}r$MDqy쌽|4xmB^koʼn=|<љar`^|SPP*4XfzZB=w6,.HN-(MObo 84> ÜCi%jEbaԴLg"c.iM!߯V[ZTp -_Np{ՅUq]mMn-[sv>{<§m꽩?8'_ع{VQtx|?\a$?߻_zoJw\O_Ub U.t?tу'͟Y`\;K׈ݷHrٳo39X|ƐHhXZb d˒ݸuV\V ď׬**`@s_Ö ߢ KB>TJ^?;l*jȚ5UV"Sw^$Djh`*ݒd{xQͤsdWoN󚚑u3ࢶvjމ(1{u^N@/CߺgKn&'kT=?[L}~H7iE[W-¬zdjM?쬍z܄g´P o<ߡُg4hQ,4!fy]ﶼֶm霺uq&8,I@\O5w‚2GzaK'z'TIg3KYEO $pLג;mIJLƜNNQ1+D>ޗٳ?԰9ćmƤH?)ޢQ3_ q- R%+LO 4fxfusF'MO6-w)boY)-wn8s[\-~ x?s_s+ސwXACgW =ҍ!ޯ 5BT=LB=Lf|&=wM>,ynѨ;#_{#h/{/`M/@!=ەd#  FYH>gY<7Ҽ;rr.0B :3r퉠7!9 Cs$#5ßR?AL/ȟ:ѐ:@_ gD qv"ޤACķoWߦ{?!%o"ɻ7QW]&:o/#Jx#6]!E3*!ei'i_!< T9"l%fCXj  )91 L>YX4M}xF]9U H7b}y^Ɇ ,V'zqiԬrxȽ,{'<, Qʹ\*>u-yhS3Qfєlݲ|ȅ^+L٥V͚O\rdH+J;)h7rrCh:59U}#t-:6clͰ9F` 7V`$Fa[lvN`Wj{bxLDIb2Hb jPP阁D#pD3ZЊ6vYC0sq(8Wp>I8 2\p8?' q V]q~q3Hld4)G܋97'q܏3)mLq*8lL1>a#xd3[6vYC8sy(4V2CNf)>5Q#|q>|Oi>u :YMeQMa$a"I&ͬi0V֭S̋Xīj2°Ԧ5/eFA_) TA!*UJ$M2HJebu!QِRl@uiP|#2bByr%^>Cs#Ro~'IDW5覇+iҎ-"y _~?5FepjT-F6d=5L cd5)5Na+ҬZns۬Z ZTTQB%4bWEF 'VnK(o6d{jSrԆn6Ս#apLәm&!=!>+J<2[/jv/ѤB9h&S 5TkŜf[.ְaО4w= ڕ ]X+{16pJšq kGfD} >N ,:M+i:V#V{x,gsvdF$sFn(vOpsH%Uĸ  S0`ˬpXhʃjjR1݆Sp)⊓J*ғ3Ws)?FQ)E9z:$6E[7cIkUȸ_:\-s񎆈t^+ %5Kyi˗ҲdA^.aہC;AL~hҥtS y%wcPcޝz7W peEH-#"<-BEH!"䡬!ogD UZ$^UU=*U~^U駪JJGYUsB? xJAIBJ$h V6&WE_lۼV<;NKf? bGMx(~~vwvQkܰ0tȢ'1Y!Shos(B\f-s.驲A6!~r01 r-<~q\._c-8!L%κ5؀cYr]g²g|+>wy-l#@^'{)%"r+NJC*d0yPn2ڔ*%\If}BQȷ2M )U2KΒR-52GΖ2Ozs,Er,e, NK{^@ OrL~.ȃ<,G+yT7<)쐝KȇSL*:9*si4IXb#6iwR5L"5\P#(5FSjTT5]TlUVuZSKj'uZ֨ZzRmRO3Yz^#jNLWy_ z!9.yB)RcuwoR-OV#/QF=cLlK*\VRvNmpGʿñiC)?8 L:4ȤʲV_L~KQPO?곇~`EA/1j~JzS3cƌ3n}9f+-^ҘQqR`KNT=STmT:xkZ77UƬVϕo~-.ɳ')`yфШ qm;GjzkvB뢬|SΊ8pZơUUo~W/TP][]3fy?i~;X zeyU&f_o_%"!QG| ",rDzXURk28Ky/s5`-1uw ,Us /)+=K.lRv5^\Rv%rׯB^k:u#>G/14x< σ߁/%2x_#Z - & hm3}B.{{"!?BGd\C|? jGi84 )U⵩<0 üVYY,B##KgPc*AF `U 怹^\R/.([N[Qv9׮Wu\kvQ7KpR湏*5H ZҋaUhe-rW;wF/bX.bX.bXF^Ű\ Ű\ Ű\Lޣ`'^y'Zp1<A#HC1C1܆rZnSRΔR59EF%^,E\8k 2sWO0=ZR@i,NW|s׮~Sq)jq5?Es"XxRKsqsN֩:uXa:zrLFlFjjl,ZEScjjjG G q]O6b:ᛍf$ IX70!0!0!0!73'GO$#aH5F| 5k5aR=LIZZZksa",FV7>qpNI| q8]3̊ׄOs#b,3٠٠DoýL˼6 }uU?aj0"Ԍrj2p- p- p- pgFqmdI{dEDO]Cq[EԳpDžiďm*eX-[}he`9{=|l4z;3Hd)34Z 1=[ŵ5|W!B-MD )E_QE_QE_Qـ999999H09d#I>>>>`L.>b(>`(>`(>w>D_s9s9FkFkFqz%e&kk~c[[[1|+oVJ[ |+ou[.·RV >E-NE-r~Ձ_uWߢ_9_FM`_ I ^ ei>7VF Sc9׋86YAl @_SHCo=<㏾?/nQ;PӆV|?)XFmvΘr2\Nwa KmXjRڰԦuI,T0Յ.Luajv FoX; !If;.K<Xj.rMDفEv`0#JgC(ZadNKxΥ\xa\}fdzɿShw+u{}bt{kw-i οA sFg}h.|> :8 {~8_Clcë5c^/qUK jbԪohg08O )YhbT@j$F5zUOĨbTH"(hz8AJFRcхEJx4@Ker/3>3>3033C0330330335+5#55+Xg `]Y ,Xim0(LLfe|_}+r1쮦j)jsVI-[X%EmB{Xt=S{0m +X7ecX5U}O'&{6^/+` x mܳ9߃܋r?8 j,[#[#[#[#bI1wRۍbj2r r*st0A 8;mXKJ1ܿWSrA~RkW˥\okmX0nQ~ Ç'Y&N#g:!Gnb2^ۿ3+%fZK};Q+IfyxR^ h)I+m\o22na٩\BvyscD&rr,%N—pɩ]npl0}iMz/=- & hg vs!pԂ# k9:%N'IpTdZXWC`Ǔ-$v:F&; Lv2{04ۨs͞Dqcr!OUϫڮew~6 QX6h" e2!9Ϭ)mDz&?Nim9 5b-f-FU#b3Y*wuf_zPCE~SSp)Of(G2$cTւu_?v"Û8Û8Û8}q#Ǚ-:-:-:-:-:-:-:TNeTNeTƟ%2(2(2(p)ά p*2p*2p+2p+2p+{~%VneVneq][%u1/lj9YKX._/@^\NEs1 ;7p2 'p2eWzEz7q`Y--%O,s*uݛ_<84PLq\pu>H[b1wԃF|H]bbAw@'L̽zKу6bv 4qvRZ83eSd;c6~>f',F($I;qf83d2 g捐fm4kYDtk]hF6ڵydMzwmwmEl,bcY5άgV3ez/6lf8VaXfc-owZ99owXflelelXfL2C&qZ-r89,TzW_%3#b:z8AxSoML=\ •Cnc}KVF,ombE,E"Y" Ƅh&~Xa-M6>ljѾM6D4'v# +og'1u>YfFV9l03\ud#"쮅' d| Ϝ'._Ruʾ.` Εuȫ{2f| (t$7qNsz]S~3sx<6oW_>3~OMOӧg9<O|^W`3xąfV-]w.EH?&yۑ1A͒~h뎈뎈~1CϐE"u @D jʼn.1%R8C]Kt.1%BR(l70bh𾶮So5ր yW 7~߄_ƚ;m2¼g29ka&w.> Άs\G>Er35Ó ~V!#b"ڏ|.:;k=; 7,oYnNs]{?ZnX?EܗߵGZk9:,|ܷ6h]Mg!\/`ه glDR~ojp9ʮr p=y#c=o>%Q2(g%z2j7+Jй*7Mۧm]4HuD#4W E-2,*0.[e*3F{9~EvKLL7w"w{`H }{;Aļ?+XNL"Jzk(vcvX!/gtf{.6o{19cVuX,g&Y6Ld{͎2|sД͑1f>?c\ txzynEi ?mGdL)1?GfgAAI޿Aտ}%o_q\*.*yL-9NU,TK %jUԙSCI5U=1W=1O=1_ñ@8GJl&E'F|bGNއMSzM^ȫڼ$V"iw/ᅉ!^KnӴ嚿Nqb%vSz>q_?m}yi'ݩW3sg)u;pNn>-i]n!eS{91Wyo맵{xG<캒Jjf~.m,2=> nmSɬgYF=>QYT}Of~F!ZDυLG3E gu!5ݾ~nKjg[rLٿv߶VXUml0}ZݟI|3t/ 㥝ci( dPQAVxNݚsHzy]ø2E]3C(ɘGԱ]Pf/wE}rŔ>c6z ϴۍk.Gi a4a('vAƫ1?#cmߚܥ&Of?^Sh5Xݗ+4Oƚgb4Ʈcx%9rz9eD_㨔UuckrDw6;xsNyTcWd+uDz^>_r<(6Cp<,#d8~mST򖚬z?P@9%'I?IFubS̏,n̏uinc/fonts/TitilliumWeb-Bold.woff2000060400000050610147177152050012712 0ustar00wOF2QQ$?FFTM `6  6$  w #GPvY]kXA(& ?!!2 ԬB5*++ ;Q AZIT/$(rLꏚLPb&^]11hS'q8)>x`nzGӜ-բ|EhоE`Gͩ?>_n0܈Gn8~~;+ON<HTwK[ Ef$;e̲f١aDFȸ1ӭomnMn}ܘ&M{q$B Q%B{ig׉1E׉f@w+Xy/X À\2[{d8Ae[.Uٿ*o CR)f|ϻ cjeVcr1r\6$X f !QP9 Ly!j9?U42&;v|GqS!a б5ˊ%N m}Q[s< l|"k7lL2.Q`tfVHT~,.{T %AZ@  RH$%˔x1V!EyMR墩\)F"e}3pr.d!y{125qT/Fnbە1; TyIY1 WCo߱D rQKh@9 ˬKsG1FaJ}{k6hc|dH1B]+t35v#S1FzKYdX_R4Gm,3"63j7ZmW@ ӳRDF'_0`wݬPUmPG0粇yC\иs'/|/K 6 Bj! I (Ɋiَa'kga\?|;)4  B$ @pYYd9sK3|?V -%\j٭MԪꪯdu CflrӥKì7KB'~؎ 1=p#+3͌gVm'ˆ4V۬Y}%Hx?9,c&'/nUݍ|e_"k 2eKuc=d_'CVܜBnB< e&zq[s%Bhgdi$VE};dF#!$|}X'rj%#/!({͗uH1ݪd=6@|qo 7B~j_Fm4o:z[if<7zTHq[bKrNá HWtXqAy^MҞ`? 0*z\b&IcrU< =1ji֥[O '%,iȰ42([\V֬ۼ^q_rHteX}R)9qAI%-AȤ9ㄠ }#9 Euflrv |d>zA"d.Юf"{7 Hȝi"hѪzZJű.x:HOB ece6(geQڰu*4"m3EJNXPRl9gx}3t*;-z>vRź^9lЄ"fޘ|뗱/CXS03X+H#1R8~d^Y S\G`0 a&S$aZ"" bI0 1j,a yXU+kQʺ ~>U%4]ێ60$INc\bߎ/y~jQD\5wh@XQ rXYLHl4vB+$P,4UdxAFddE@%dLP*6[J 9dkcFM.;C,=BQr@kRw~?Zz咩挧yhv6εzަ_fErCBSuo1mg,m9SQX5) ZdZc YYf`.."eO-{ \TƓIo+:Sl˜HR/:F<qT#c{g^jkXhZbdl)*\ tNFn=W%pbIבMeȰˌ¼EѪmشuPzza3c̖HozqQ2!ed!PNEqbJqq aqgq'q%0uaW$(A N;EhUtnj,_=a"}1XW$edeFa^vy^{NYVm8x:J/I2 1j,30oӅr+!qc$s:D7mt 0vBbJs~MH"Gs W??QPkr#_4;잋U/%ue46A/ZlqL|'еm8^ڲw%ʊ'z-H˞]Z"r(:դYKZm[; q/|(",2b,3Phy[[94ʱL!D t%IbDy]:ݟyk49ՙ0"$p^˝>_5]}5<zP9 *Cqf ׭TE>Z@V{ǹIhtN y3SCUVtJ2}sW+1BVUUUթj"֢UvB((#]o"IR2 0bL2Eh4 ?!DJN[PR)`e\>GPT%<zGEtb84t.#zL4en_{ 6 _+,Iy(X,++3B)_LMt'X dIN7g,߮? 1OfBӕ"g{ºjxHYڷ67<B!!)7'q⟓!yCBB/$jevEc~V)^̭Ձi ҤTt3: 8t@+0a`m 0N)jGDB4*Q0`kQwxuZͩq>r>0 d|ͯc@ "TXDH o#k-ΰ.F.2] 攘$$K*Mz2d*Y);9z[{ N[q,| "!WW&7rmwu}<WxMW9M@ԪSAci"5kѪht 2bN t\V4RD/oޣuv}9vtq'7/ߖ9A$>H)i,?U `gQ7gd)*֬ۀ4tG7s)>wN6:GI(uQZt M+50F?dū/dƒ0!KLKg8MKgA땱-+Q F קZ2\UA0=.MBH  SJ!mbP{Ch5aDz:e^ko֩^zZZ05zSFWx?Eea\Xap5>$r>[٩.s}3:$/>TaRbrIDJ**B' WK;E٦[uxuzͬ {Е/οg49RbݘC3(&HέcxBRvp3X ƛ1_~9iڈQI!<$u+J+Y)rws+eRSne26k΂%o'}k9pdn^qIPT"̵Axa0a&&m s[۾J_9d +an' '^sͳ$f5 (Ⱜ7{9'46\rWNpكs/ PG+Goj[?C~%Yg1pqz/>7NUS^y]Z5Dx;/Oyy3ֲꮳ`kVGD.;fa% ,T!]$9j#Kd)d9ˍ+? *J,rW"C ,Ȅy QK4mˬ7۴v~&:^>=zVs14slawIDzL]aݑNO)޹+Qܢň\LK3\ r cSY-(I$IAՔHLTFgaOƴRe5}wׄ!N#wZ2xROL~E7'x,}3ǫfZ>hv!ۿ&gb0 L+Ws^?}tزgІ>Zŏn+A 1FB\o`=5+8.B."8{N8lF0jEA @ɀa/O*AʳG/cT!:EESbh}q,!0bGr֞[/2@&"OC-NM_x}]|$;g`DB/KNaZ3bht2+4pG5Xd-dan10Aze0ϖRna($жڊ^^mIGךycq[&BV\^vP,1/x}jBޠc8>+."o{)V1̚:iڦv{K;~ Gld2H(b.ɧ#P{V"~9~c<;ӷ2\;9+3z|>DW> [! G >Ic p/-uhy̔Ok0uHq1+5){p1Acl&N>0=Iw8ݞO)qaO6 8ݝA֦Őg#0M7ZKwr:oj~ [ޠQ D}$!%WE G l CgSOXaP B[uuαa<N8(1A5; i rXY @q)R Od-6ge@K^fm@`>Vv$g|Hk _GQdjh,Ap V(EE#Mah=kqX}fNa{l3YaSpVZfȲ6w3U35;! U9IxY*bkѪ!H s PĥҶ KI]R|֊;J+ Ua'IP8ّRM{1m|o|LtǾď5/BrV䖽yquY3̻p;]{ةO즺 QRp5IpDWR퉕7d"PǨ FT BE:Y[j*JYu5֕󒈢VuDrtPDXB7C*Rf4ҢZA`i@r@h;n)Q{; on|q+$VQydW[]էMWC5s㲟C#pVե `-G˦qYYE uص;;ɋ\Ÿ򝝵QX[KX;La3Dΰb.FQfq[X8-uZ紱8Slk' KˮF 8j]E)"A;˜;ImԮn}ÝJsM۩W.Mi_['6N̛h((g{V}yssϹݞ1i|(e2@:꓂C󏬩mrpr];x.Ik{/Rh1bťc_)RI!Sl9DrWP^z [buZo 6bavcpAu܉FReꭡTE->=#S5En[B=*4qDTĩTX.[x47Wt’2ugs ZhT[nePu1GW|A ā Vt.8ӱ$M D˶JTSb&Ĉg8G4"X$娬mG\ʐ $-ؖO DCƥ@ĊNv`͸5D}k yU`椼%d ]D,9Cvt@cQ(7DZ#xF"k:av!cCϘ l0PƂ,eCd2-ێȐ?egzmN+ a&#XL4e ui& SlFV=xԞaVcy%mco%P_]%#ft}~WOdY7p98i,Je[sG4yG*#D `),yƟܖqah#fCyxBj ~|ٙi2ȧW7]uN+;:X-"1WN>v0iY`TF"Jg2HV-V9TwXHz~<"[yJt NtrUOȠjI-~D@. ^ ~dD"/v\̚ű:ExQ@gU;(d*{~]avZ&rN]f6oƪ/I9%Ŕ ![7ٟMvL=S6(NR(VI-k1e±^ 9>FoLFQuQD*؃ɄRC-'tN0%t+h; &jk@EQFgY^-*i4CwR3v/w ps0ߗOmTo@[5t2q{|ؑE1)v"bjS=jq(Q720^sekh=b-;T[J?ز6"Y4kцl8g-n(|\q{9x=FH1l=QR'`@Umv(snhF˵|FȒ6l>MTSA" !vє5Fe*Q3M*5I{d|(:J5Uxh5]bq^4꣦VLV0R|P3{5%˱jesf%:E]DTqps.g%]uj05Q6\2hpmpq/RZ$R%ʵm ֱ@:EY""+OüyӞ(NPQvsWľ~[J/;E864@0C:|@k#AT~DeBFyݍ03[Y])jP,kBKCؔHU(Qnn̥>dxm/ԞK퉗43xƨL RrCNãU6l۠th4NR$Dx2q g鍩!{Tnlu/{AN`mu.&jɄ|ЕV{m䏐W4%yORiPVauZ#:Fm?yH@L wlA+su˱e #$ںh.Su LTq=~Jwmg=b=M^vV`)hv9_2bG ӪN3VǏi8V2H1*`0uV:|7_.$(.taFrv,YR^' Mpf?`dXDPIY{s601)Zn,[.5j&*Sw@4E.mҫ8=|P?S?Ln$v!o{oL@B͂uM,5[y ^Y֤e)͒}]=ܢ&/v63a8*D]˜0"|9ǜvˆ;,^`>1 nT@ ߁ I@J˺s]|mbN#hG]9^?Zz8&Wg6<pTH8Ʋǯ2d5wUQGWj!&F@f03N\GImzt.k gvIѩL83)qN`{S =dWaퟸBMTblr‹X:RN, ,}$#S~bF3EgɐM `@;mk@ j'.1Tx A ι2 ~g}[N$*E,A;NS{h}P)oh! uѩ폼?A?YU5>=' 5d;$ L+ 4(/Re ye.z 7N g) ./URb=4#f]qtUO]!# 42;sJ9Lg7g9Wع07:伨BV 3Y| ЗsǼK& ]t-"e:0g5\>{m4 `2v.ZԖTp;߹F!#۰z+z^-tYגpo[sVb+:ke~D(H᫳ vZ;fRwC` Zؔ*.5ݟ`ʽ5yz')iB 31i\O{Ypl"2UȊ'YzKy5uB{ij7Mm0YϮWll)M>i%!Vk Wc xbju+^NpWnwS0'}~= hV|6H ,IjZ^߄pWm]thY+eV*jCmT -}~mS6x?BVH#`-cF/9:gR G§5'[)!Ai)%w]zskG?S2-9JI l}nUVҠ^&ݧk9NM4dt–;լ)+Z/YQp8Vh̃Z,Ȋqf}9w9Pcy, wt!zBJ$,MF_Ē?>t3sсA7oJZ2&øf*L 2i ?7>]h1cG5Q"D s IѵNsU].d[ ¨[3R/*9wV|+~ftM5Zеed JbiZE|NjnnٮݾM 7@@Z7޺u?۶uh]Q^+n| (j+k,4|= kD (ūpQL})<'\!* CȔxiУ[#J-J|݉{v 1 ׆WC.V*<5fnl|WtgL!IRphYTFU9ݸ'{p]wbśi^ Ըih+ дQwAFБ}#.A5?Gy܀^mlMol#|oHKZhfyO^c`_3[+H@Ms7{@+ܖ2X1wёE;;v 'uoGz„v}8ǹ%8##Qdܵ ZV8TsvIyR`d~Q oa( 5Fl=Td!LRod)Po=}pNn6GufL]@$_py}gcuiӲ;UlѰ1q[n+u-W-[Ym ,we6@-kҭT-!jwξɿW|X,[k=WOM}Z>Lk/ Y欮۪j\(Ȃ*÷)9yThucmbci2MVP7>_Y(w"#{J җ;QƏzԏ[ xICפ >~a˭d߂kh/X-[d-X2?_}!c-NZ*mJYѼY~dA9I|e؂얄B$U XW:\OJN/o'V[pnE4v5J*5, ji4xэ3mXЧl+EPV6% Mn(ʌf&C ?{MF1b *G\ҐB4Xu;X*eExJsR7$BF:SƵI1~ħ|S5r<ũTXie>h9۾6assې> 9qHj`D t-? gziYt"#d_{KJ@qԃsxnP"]}RN=%={+V0\,{]9y1\I&5dS=f=JAZBG/tpi>Z'y1cyJ;?>**e_h~gdzO= t=ɦXI`C]ת5~`e^Ѥȉ, ]]\JvtGWTQDr`UpL!5@AQZOFY`NIkﭟ~즻BIzޕ?=a^ҲesgI^tNO`!ڭD]wFQ֎BǾ! me8Dm"S#-"a5T~ Bݑ+iUDK8V$J?^neI~Њ!%D4R5k+;]y_Z%OB%F*p5**AѾ6Ee*v+ly9j?CuMT?fv&ZLZl岾jiu ŒfmI#)hz8;'[sn 0c Aϳ϶%IzѹԮl:6Sb3[}` SV t:ӝ@o}x{a9!d5 G^R6XX~O)L;83aquq3xmwq[gxhC|}ކ.9SSK=H$x^ĂFhھ`JKV7 i?@=țӘp@ˮAC%-[>+ء#J ݢB=si(Q)Vg B;|N\R]-13WLꚺ9q"sM\km-+DT*(YB3 TQqIY fQϻזϧaL]skrRڼ8uq# FP SLF_X瘹T,i0\fgǓdг.3"UٜR9f̌̄#6)}M )y8Uyэ(/aU)4oK)*$aIJ78fynPA ]LF*;|IpDX t**WJ XXݐU[㸬2;ܖ >~lEeϤY +F~IrֽR)"@D*p |2T yQgDn߻M'n;]δ5kZ3$ٖ^<4ֽ,;xSq834*lM;Sp|jMvt^8Z7x'T@HB"͟w\覢 r͸aKS"VyK2m\PZv}]":p|v&$4'\φOz$;”G#9&¬}F(l;,oeDFARmȯ}ö.d:7,!Zv+MHC;\+FF|VЦ\r%s`أ)x$]ן C=C:}jsτS6vس^lYjRC/j7M/i^Աa7j۝JTHnx(]䖆Ղ}5\5 K S*>զaՖ{ΔBοF ƭQݛ>b+ۘӛe̓;ՋE]Vc,NNb8#PWz#\(0aav-[z^k 1 |ӗ'Xi|s4sVOtB[Z)Ц bi9V2QwR#ͥT[uIZSGynGc¡LWٟo*i$n}zZizA?2~1tx:+N(_R!+,_U݊,;џn5Z]wJfѠN Z$8xʣkzzx|ur=I9~SUS?.E*KNs*Ѭt*gQ-X:mGAMͣեv +0dC|̦-P_B*=qF{wslC&au٨ ӆ"+ԙd\嶺M2B*1p~kz0t& LlJ@ذz ~Anow蛨?ᱪnxòmǍsB&o !yD(!4i8rN2[hN8{DL rry+KC-'JYin\2'&2 7 uGCEs|T(=ʋ\跨%ټՌXm:x~tYjB;h5 LsfӮ7gїT&KO 'aG]MYhɳ޼wkVX'n+#XcWHh|TZonb>{s~4O0{c㓠q˼߹<'$'!όz';p!YDK9D4ђ3q׭V,qp΃X,ϤL;scVpJ<g4uqg;1ŠpgO$/I39cF<#E;=cj0>AM*p>MW5c*J,+ L˸e!=AOHؗ/ŻƳ&qmV?LXWM-L@+;8.4GZ9FPU?hE!pѕB*n^t|#OaCLFiց78o Z͆  ;9:Osjs}f0iĚѼfOGA =@zX&ƛ`z7xf-81EM}dMyҹEAo* "l+dSgW&MaJWV.]U\zDdr>pHcun f-#1^ҔUbi_l5h`2IMY7M-%-GOQO8J}^A9,o~GW{66[:c!jmOI7Xk}hɕ1h4g?,k2b ~}m'}gܑwҏvٝM\VW:u^}ݽzg 'sI_|ϷFhƣ ZwnMMB~3C}էopp@iu&l-W9ж"[.px3%?:~@5?%mڊU b-%(q"*BQ  hvMц("F#W`%=$L"K0FC;pxC"鴮|8Ѓ ܒl{hwjs6h*0, 7aCS0Y rV4|`5QNS'H]`DP'7@BdLE 8( ;1<[}且rD ;{ԑĂİ@)|dBYm)8pn/[w2Ia}31#|[5w]T s7{'S~md4+BD#%P_Avͺ `7cd)anUa<@K!BvBձͣ.hxˁB9o?4R tv׎U=/Ԫu"?8CyWB}ns&=ω18 oL7q/Z[a _%߸ 1b˱e* n20S$cj$4.#X< F(^J !O6hfٶQ5zBVm:v,d6΅e%㯘)maTxv ̔5,d 3YS3 {v  $w4-.1RHrkhsWLM_B"_pGxҰ aKS)X}|9)D b&fxiYY /ueݯdyyʸs=pO;j߆PN9dQ7}'K}qMi-?Ɍ~R+گOLxZ0?]@bZ@P'P HTL9 IN iީ?FHFf%zM:*Ub{2dԂgl"6JQk,:у r*URj*j4@NfM[U60-w:ܞXc864#C߮5kK|R.WD1X@$)T*={FH.d?[qkY_UO/ .iOL2}PCCϥUY#!d !"1|TOS46Psܡ*0=4004 0HT=#.?<,) WWWWWWi 4)O)O)O)O    O111110>1IIII%UOSB""""""",****"/("B*****0i*====BW"W"W" 4, 4, 4, 4,Oq++)O*)O*)O*)O*)O*e2 *e2 *e2 *e2 *O"B"      OB(EO&O.OOKH^O"BO"2O"BO"B1*1*1*3L*jOi8jOijOi*(*(*(*(f hI=I=I=I=I=I=%%*)*)*)0*W"j"2**& fI0"U**%n=b=*/9*/1i=I!7*7; " 0U000$0000$0@000`0>0<0B0H00.z0* -..(p>d>= K!+!XIX&ef% %I#0*"=`@ ~17>H~    " & 0 : D p y !"!&"""""""+"H"`"e% 49AJ    & 0 9 D p t !"!&"""""""+"H"`"d%A)ofbIFEDA80'\Y~{srkh\@)&    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`adqdeifwok~ujrgvMl{cn:m|gb \]ab^_3k}ijex`chEKpGHIyLJF(R .Ln,d~*\nD`(@L`z&Hx"4DVjx0Xx  4 @ p  > ^ ~ $ 2 b  B T  6 F ~ >Zf0t @f0Rt.V~*d *f$xTNbvDjJr8Z|0^(V|.\,d8j 8 !,!\!!""."V"~""""# #*#N#`#l####$$$4$F$^$r$$$$%%4%V%%%%&&H&x&&''D'n''''( (V((()B))))*2*N*t***+(+H+p+++,4,\,,,--<-\-~----..8.X..//B//00N00000011$1@1d1z11122>2h223$3t3334(4Z4h4v4444444555255555566<6N666667&7>7`7777848V888899909v999::.:H:^:l:l:l::::; ;4;b;v;;< <<(<4>>2>Z>t>>>? ?6?\???@@.@F@h@@@AAJ353'3Juj t D<O#'3#'3I_i`j%##5##5#535#53533533#3#5#f_~_ffff_~_fff~[[[;%%+%+&57&/77.46;73&'%74&'6wf@@< OBhVug@ G;eN)7w%/mhgtq V R\VL%&"& # 42"&6264&"42"&6264&>޴7'#"&5467.5267'>54"{gb@Qzi#w>q!nBvFN'0P2-U-5+sPQR/y]zSmGb.4jhS[->1(!<2z104)L='3@j+#.46?3/g,8g"??k_=>V#>4&/3" g 5/g,m2j2WEDte.k~#''7'773~'>)i(kh'g(@'~z{O3OJ6K{|4 753533##54bbbb|730xP{=h?75!=+cc=353=u 7 ` #@2"&$"26|}}B?A?q@miiX#'7o3ldSC)57>4&#"'632!WJ<:B>Kah?Q*_LVg,XHjK;%62#"&/73654&'#53264&#"B]e 5/is-l nTx>3%?70OT U\(@;BieVi02]=W*( !5!533533#Q׮{pHHvUCav8!632#"&/73264&#"'DBuk-r"" vT:@8-Q3Fbpx T@v4_) &"7632"&5!23264&"aNH1|y KW;?>o0bXlpU@r9I5!'5Ih0d%2#"5467.54 54'#74"36܃%33/q.2/&lT`QF`J[U<= !E=dZCH#C8T|giE\\<##"727#"&4632#"/72?&#"L.lrm}zKW ae9<9@VgvWB9m=5353=uuu/ѐ$73#53TxPX)u|@  %5%&fy|pZ=g5!5!=J-bbbbV -55|f|oZp!#&54>54#"'63253!f!X&b j#"&/"&63253276=4& 37#"&'&463 27&=&#"\]-? X_Xl(.l *"\8s\g |Zkk\ON !#324&+327>a~~c! Wy1ab|nI%TO 3!!!!!OAa`bO 3!!!!Oaa2)53#"&632&"3275f%vyXn#yGCfI$boXlo OV !!#3!3oo(p($SO33OoS 526535'nZGb 7;kFO6 3#373#ooff-O)3!oO333####OptS2O_ 3333##OoKSL1^626&" &6 CEF?|}4|Vt||שjO3 %##32%3254&+Joux:>v|`F@1i^"&6 '&26&"H{}4|3:TgYCEF kx'0as||O< 7#!2#'74+326opqzcjv<8ڒ4{E*"#"/73254.4632&3#33tڨt2Sw33333# #ubbuvuKMS% ' 3# #u|uKb !#33Kp}|&m* 5!!!55*>>=Lak2ajI2#3#2{{aZah%7_^ (*&53#53&{aa%<'#3|}r^<XcR!!cTQ]@'eGN"""'#"546?54&#"'6232?5V/PQQT#"@` mQE=28ZS%%LD $( MOB 2#"/36264&#"+g[l/f"lEP5-3007ss WKI,2&#"37#"&65HO&L42Oue3r]bVDHW{w+ #5#"&63257&#"2lI=b[ek$N<3e/f<%v~ ( \G*%7#"&532!274&"rXoa4/p3ZQz N>:J;>GR##535463&"3l::>Ol1Ai] kP Y'4]*%1:#"&5467&54?&546327'#"'3254&/264&#"rn$(! Hl\,+Sci%GwX8Dy+@b,b+,1\D>R%53-+kZT X#/bK"%>`#E'Z++\+YB3#3632#4&#"mmJ?dIm"700%q QDB3353Bmmm Iss 73'>53ClEh+F&lb^5Q,7xssB 3#3?3#'mm>vz{zAgH33Hm<B 3#363262#4&#"#4&#"mlG;W([Jl!4-4l 62+*11o QDlYDB3#3632#4&#"mlIAdIl#63/*q QD*2"&264&"gdd.11PLLB) 3632#"'"32654BlEJ[<:LS#37#"&=#53533O%RC#U?@@l=(W Nl]=3#5#"&5332?qllI>gFm76- *oZ>333#r` doi 33333# #kO_p_NljNNis W 373#'#7tbcttcbt) 333#7#kjjlk5'467*CB+&4kYn95Yl5'?}?8=@u+/\OZyMU 1'^M\,H)3Hle%}R7'467.574&'75>+BC*'5lY59nYk4&6u@=8?}+,\M^'1 UMyZO\/@J$"&"'63232?7&5 >:#5 3 X43 WBG#5#uj t D]@5.54753&#"37[Z[XO+D77Gx0)Nnfn lp S:7S rM&"3#37!535#5354632I[HQOBBJT;A4 )64][]]9mN*%"''7&47'7627&264&"s+a+GKHHKG+a+HKHHKP::P:VHKG(d+HKHHKH+a+GK:P::P $533733#3##5#535':p||no-\ \-\\-J)3#3#Jllll+S&1&"#"/73254.'.5467&5432>4.om/:C/%6b l7m2ZYI),BM#l#(#K%:A SXK#?F$N M%I 38 _#53353hih_rrrr4P 6&462264&"2&"37"&46͙햖{|}e&)$;D u8:uB H#[(EIH/La"&'"&54?54#'6232?5J7) 0`4rL.|FB$! ' D7/X?/= 4** '57'57ttttJS^oQnS^oQ=n_!#5!=b_4P"6&462264&"#32#/324#Κ햖}{}8P}r0T%+)*/uc5d&+pcYYa5! aRR462"&264&"QQQ-J//JQQPJ..J/4 53533##5!!4bb8bssbppb #57654#'623O0*OCf0 1mKG)P -T/* 2#'7254+532654#'6r")qv;K#BA #WA V5;cMH K @7"e^NH)3#5#"'#332?|llI>'mm 46- *J6%!###"&463!#U^RhiSJ4P/jl]=R753=u##"/73254&+53871&' ")/+"f4A e+#5'7X8)i&>I.Me   6264&".7|@AV$T#$R<* %'55/55tѓtSnQo^SnQo #5'75#5733733#X8)ic/wK4b=/ M&>Iwa)IYYO) #5'7#57654#'623X8)if/wO0*OCf0 1m&>IwaKG)P -T/*) -2#'7254+532654#'65#5733733#r")qv;K#BA #WA?/wL4b=/ M V5;cMH K wa)IYYO) <4>=332?#"&#5 !f!X&b j232?ݪp%%UTK0~ ' 54{ (SP[2! N"2! OD 33#'!3'53353ݪp%%UThihSP[rrrrDP#'!#&54623&264&"p%%oNuNUTV 8!!8&h&6??[,,=!5##!!!!!3*qd@bkikJQ4$#"/73254&+5.632&"27}871&' ")~]lYkZ@>\\^+"f4A [ pZkk\O 3!!!!!'OAa`bgLRO 3!!!!!7OA#a`bDgaRO 3!!!!!73#'OAt^t@Aa`bCCO 3!!!!!53353OAhiha`brrrr33'OoSgLR 337Oo#SDgaR9 3373#'Oo^t@ASCC# 3353353OohihSrrrrQ5332+%4&+3#327><;:?a}}d  $j'W-u{2b$CwmjI%RO_ 3333##"&#"'>232?Oo0~ ' 54{ ) KSL 2! N"2! O1^626&" &6 'CEF?|}4|xVt||שjgLR1^626&" &6 7CEF?|}4|W#Vt||שjgaR1^626&" &6 73#'CEF?|}4|6^t@AVt||שjkCC1^"626&" &6 "&#"'>232?CEF?|}4|0~ ' 54{ (Vt||שjl2! N"2! O1^626&" &6 53353CEF?|}4|NhihVt||שjrrrrr>! 7''7'DEFӖEEE1^%!"''7&546327&#26'HX{F'`C {'|Kߵ}#Pڶb|7 t;TIA 7 53"&537'p~p"ۅ0yooygLRIA 7 53"&5357p~p#ۅ0yooyЗgaRIA 7 53"&53'73#'p~p)^t@Aۅ0yooy[CCIA 7 53"&53'53353p~phihۅ0yooybrrrr  !#33 7Kp}|շ#&m*gaRO4%264&+##332I==<>oowJ=lliwB7)3#462#"/73254&'.4>4&"mdh)T!7\n9@\/[#@C4$S,w.fUGQ55&>>:ePX E ;[2#8*6""&"'#"546?54&#"'6232?5'V/PQQT#"@` mQE=28ZS%%LD $( MOeGN""&"'#"546?54&#"'6232?57V/PQQT#"@` mQE=28"ZS%%LD $( MOe^N"")"'#"546?54&#"'6232?573#'V/PQQT#"@` mQE=28}Ef::ZS%%LD $( MO`LL""6"'#"546?54&#"'6232?5"&#"'7>232?V/PQQT#"@` mQE=28(3*a'  4+a ) ZS%%LD $( MO ( ? ( @""&*"'#"546?54&#"'6232?553353V/PQQT#"@` mQE=28hihZS%%LD $( MOvrrrr""*2"'#"546?54&#"'6232?5&462&264&V/PQQT#"@` mQE=28s@@^AAD+ZS%%LD $( MO)?_@A^?++""+1%7"'#"&46?54&#"'62632!2267&5%34&"s2V^FIU\u# KT '1d4M-ZsE%0o3^U2 &TB !`44O<7/HD:<,&#"/73254&+5.632&#"37#;871&' ")XIbo5HO&L42Oud3+"f4A \ { wVDHW*%7#"&532!274&"'rXoa4/p3ZQz N>:J;>GeGN*%7#"&532!274&"7rXoa4/p3"ZQz N>:J;>Gge^N*%7#"&532!274&"73#'rXoa4/p34}Ef::ZQz N>:J;>G)LL*%7#"&532!274&"53353rXoa4/p33hihZQz N>:J;>G?rrrr33'Bm eGN"073#""mme^NL  3#73#'Bmmn}Ef:: ILL 3#53353Bmmjhih _rrrr(##"&4632.''7&'77"3267&yrpvmi@>38|-U,HpQb.47tC>Cy[qv7Q S?9NB?F5~exB'337>320#4&""&#"'7>232?BlEdIl#p73*a '  4+a ( q QD|u ( ? ( @*2"&264&"'gdd.11 PLLKeGN*2"&264&"7gdd.11"PLLe^N*2"&264&"73#'gdd.114}Ef::PLLLL*#2"&264&""&#"'7>232?gdd.113*a '  4+a (PLL ( ? ( @*2"&264&"53353gdd.11-hihPLLrrrri 75353353iDElnMMnvv*^!27#"''7&546264'"& &)D*\d{&+C,YgxC.y@1w ee7ii9RP%RL#)=3#5#"&5332?'qllI>gFm76- *oZ>|eGN=#5#"&50327'7lCgFms6"  oZ>e^N=#5#"&50327%73#'lCgFms6}Ef::  oZ>ULL=#5#"&50327'53353lCgFms6hih  oZ>krrrr) 333#7#7kjjlk\g# |Zkk\OgaR,2&#"37#"&6'75HO&L42Oue3r]b "VDHW{we^N4"&632&"2773#'5klYkZ@>\g^t@A |Zkk\CC,2&#"37#"&6'73#'5HO&L42Oue3r]bL}Ef::VDHW{wJLL4{"&632&"27535klYkZ@>\gl |Zkk\rr,2&#"37#"&67535HO&L42Oue3r]b:lVDHW{wDrr4"&632&"27'3735klYkZ@>\guA?u |Zkk\BB,2&#"37#"&67'3735HO&L42Oue3r]b?}f;:fVDHW{wJKKON !#324&+327>'373a~~c! ކuA?uWy1ab|nI%TBB+3#'#5#"&63257&#"2@j5`;lI=b[ek$N<3e/f<%v~ ( \GQ5332+%4&+3#327><;:?a}}d  $j'W-u{2b$CwmjI%R+5!3#5#"&63257&#"27lI=b[ek$N<3e/fn^<%v~ |( \GOl 3!!!!!5!OA~La`bQQ*%7#"&532!274&"5!rXoa4/p3"ZQz N>:J;>GARRO 3!!!!!2673"&'3OA)@)cZZca`bu$$ANNA*"%7#"&532!274&"2673"&'3rXoa4/p3$'A&TSTTZQz N>:J;>G()!?VV?O 3!!!!!53OAla`brr*%7#"&532!274&"53rXoa4/p32lZQz N>:J;>G#rrO,3!!!!!#37"&547OA(- 5S9Da`b=O 2+<;*, &37"&47#"&532!32?4&"Z- 5S9;oa4=QK @/p3ZO 2a9z N>:Q9XJ;>GO 3!!!!!'373OAuA?ua`bBB*%7#"&532!274&"'373rXoa4/p3C}f;:fZQz N>:J;>G)KK2)53#"&632&"327573#'f%vybd#yGCfI$ֆ^t@AboXlo CC*%1:A#"&5467&54?&546327'#"'3254&/264&#"'73#'rn$(! Hl\,+Sci%GwX8Dy+@b,b+,1\2}Ef::D>R%53-+kZT X#/bK"%>`#E'Z++\+YLL2)$53#"&632&"32752673"&'3f%vyXn#yGCfI$)@)cZZcboXlo o$$ANNA*%1:F#"&5467&54?&546327'#"'3254&/264&#"2673"&'3rn$(! Hl\,+Sci%GwX8Dy+@b,b+,1\''A&TSTTD>R%53-+kZT X#/bK"%>`#E'Z++\+Yf()!?VV?2)53#"&632&"327553f%vyXn#yGCfI$lboXlo rr*%1:>#"&5467&54?&546327'#"'3254&/264&#"753rn$(! Hl\,+Sci%GwX8Dy+@b,b+,1\7lD>R%53-+kZT X#/bK"%>`#E'Z++\+Yrr2)53#"&632&"32753#f%vyXn#yGCfI$j5aboXlo *()5>#7#"&5467&54?&546327'#"'3254&/264&#"I,i4rn$(! Hl\,+Sci%GwX8Dy+@b,b+,1\(>R%53-+kZT X#/bK"%>`#E'Z++\+YOV !!#3!373#'oo(pG^t@A($SCCB3#3632#4&#"73#'mmJ?dIm"700?}Ef::%q QDpLL5353!533##!#!5!Bo(pIIpoo(______(ff 53533#632#4&#"# 7mJ?dIm"700m)^==^O%q QDx):33"&#"'>232?Oo00~ ' 54{ (S 2! N"2! O3#"&#"'7>232?Bmm3*a'  4+a )  u ( ? ( @/l335!OoLSQQ3#5!BmmV aRRB332673"&'3Oos)@)cZZcSu$$ANNA3#2673"&'3Bmm'A&TSTT ()!?VV?,3337"&547Oo/. 5T9GS: O 2+?8,3337"&54753Bm+. 5S9I m 5!O 2+=:IssO3353OonlSrrB33Bm [ 5265373#'5'nZ^t@AGb 7;kFNCC 73'>73#'ClEh+F&j}Ef::b^5Q,8wLLO6 3#373#3#oodf?j5`,&73#3?3#'&+j5)mm>vz{zA,gO )3!7o#gaR.<337Hm"<Ve^NO 3#!3!j5aoM,333#Hmpj5a320#4&"7BlEdIl#p7" q QD|e^NO_3#333##6i4aoM,KSL273#3632#4&#"2+j5mlIAdIl#63/,*q QDO_ 3333##'373OokuA?uKSLBBB3#3632#4&#"7'373mlIAdIl#63/=}f;:f*q QDŒKKO6_3333#526=##OoZq5'OK:kFb 7LB 3#3632'>54&#"llT9_KAi0G'"1*:&{d]4Z(5:LL1^l626&" &6 5!CEF?|}4|ALVt||שj~QQ*2"&264&"5!gdd.11PLLRR1^626&" &6 2673"&'3CEF?|}4|)@)cZZcVt||שj$$ANNA*2"&264&"2673"&'3gdd.11-'A&TSTTPLL()!?VV?1^626&" &6 7%7CEF?|}4|cZldYkVt||שjn'#'*2"&264&"7%7gdd.11vUUPLLѨ9783d)".54632!!!!!27&#"dVHg9t;D>OR^DA +^}^ kj jj*%$%7#"'"&6262!2$264&"34&"rXq,-eg,/i4/.3}2O/o4^UNN[[ptO<7LMMMJ3E9=O< 7#!2#'74+3267opqzcjv<8#ڒ4{EgaR8X 33677BlUUV=w"<7m e^NO<73#!2#'74+326+j4opqzcjv<8 ڒ4{EX3#367Bj4a+lUUV=M,<7m O< 7#!2#'74+326'373opqzcjv<8̆uA?uڒ4{EoBBX 3367'373BlUUV=$}f;:f<7m IKK*""#"/73254.4632&'7J[<:Le^N*%"#"/73254.4632&'73#'J[<:LaLL*0#"/73254&+5&/73254.4632&#"p871&' ")Ig! G|8`ykMi# :M *%"#"/73254.4632&/373J[<:LaKKS(#37#"&=#53533#"/73254&+53O%RC#U?@@ls871&' ")/=(W Nl]"f4A e+ 5!##7'373 p uA?uJccJBB#37#"&=#535337#5P%QC#U@@@mi=(] Okb5!#3###535pJcc^^T#3#37#"&=#535#53533Ppp%RC#U?))@@l[R#=(] Nl5R[bIA 7 53"&536"&#"'>232?p~p0~ ' 54{ ) ۅ0yooy\2! N"2! O='#5#"&503276"&#"'7>232?lCgFms6%3*a'  4+a )   oZ> ( ? ( @IAl 7 53"&53'5!p~pLۅ0yooynQQ=#5#"&50327'5!lCgFms6  oZ>mRRIA 7 53"&5362673"&'3p~pF)@)cZZcۅ0yooy$$ANNA=#5#"&50327&2673"&'3lCgFms6'A&TSTT  oZ>()!?VV?IA 7 53"&53$"&462264&"p~pNuNNuw 8!!8ۅ0yooyl??l?_,,=##5#"&50327.462&264&lCgFms6@@^AAD+  oZ>?_@A^?++IA 7 53"&53?%7p~pcZldYkۅ0yooy^'#'=#5#"&50327'7%7lCgFms6DUU  oZ>~978I,A7 5337"&47.53p=- 5S98wwpۅ0$7"O 2a6ov=,337"&547#5#"&5332?ql1- 5T9LN9gFm7'9 8$O 2+=:%oZ>w33333# #73#'ubbuvuu^t@AKMS%CC33333# #73#'kO_p_NljNN\}Ef::is WILL !#33 73#'Kp}|^t@A&mCC) 333#7#73#'kjjlk>=#Lak2ajgaR) !3!5#?)s6"aaa2e^N* 5!!!55'53*>>=lLak2ajrr) !3!5#753)slaaa2rr* 5!!!55/373*>>=uA?uLak2ajBB) 5!3!5/373)sS}f;:faaaa2KK*#"/5325#5354632&"3#0JT$4?=::-C2fPZW]%f]Y)0-]D  #'!#&4623 7;>4&"p%%oNuNUT#7 !8&g]??[UgaRh,+""*26"'#"546?54&#"'6232?5&462&264&'7V/PQQT#"@` mQE=28~@@^AAD+"ZS%%LD $( MO)?_@A^?++e^N>!5##!!!!!3'7*qd@b#kikJQgaR""+15%7"'#"&46?54&#"'62632!2267&5%34&"7s2V^FIU\u# KT '1d4M-ZsE%0o3"^U2 &TB !`44O<7/HD:<%e^N2_!%"''7&546327&#26'7I=.9P:]}=3:R>X{F'`Cl# {'|Kߵ}#Pڶb|7 t;TgaR*%27#"''7&546264'7"& &)D*\d{&+C,YgxC.ys"l@1w ee7ii9RP%6e^NL#)*"3#"#"/73254.4632&j5a^J[<:L  3#5!##j5apMvccJS3##37#"&=#53533Yj5a"%RC#U?@@lM=(W Nl]I+73#'}Ef::ILLI.'373j}f;:fIKKC( 2673"&'3D'A&TSTT()!?VV?IC53IlCrr&462&264&S@@^AAD+?_@A^?++, 37"&46?4- 5S9(U@ZO 2K@ 9U0"&#"'7>232?3*a '  4+a (u ( ? ( @;k7%7UUr978%5##"56;2?3".Qtm#/>T=+:.>E* i Y Z '\ ':w33333# #'ubbuvuKMS%gLR33333# #'kO_p_NljNNis WeGNw33333# #7ubbuvu#KMS%DgaR33333# #7kO_p_NljNN"is We^Nw33333# #53353ubbuvuhihKMS%rrrr33333# #53353kO_p_NljNN`hihis W_rrrr"b")="'#"546?54&#"'6232?573#'6"&#"'7>232?V/PQQT#"@` mQE=28}Ef::3*a '  4+a (ZS%%LD $( MOBLL ( ? ( @AM 33#'!32673"&'3''ݧp(%SQ^)@)cZZcRLNU$$ANNAeGN*b2%7#"&532!274&"73#'6"&#"'7>232?rXoajh40o32}Ef::3*a'  4+a ) ^Uz ptO<7D:232?gdd.111}Ef::3*a '  4+a (PLLLL ( ? ( @  !#33 'Kp}|՜&mgLR) 333#7#'kjjlk232?Eo||O3*a'  4+a ) )s (? ( @) 333#7#"&#"'7>232?kjjlk9S3*a '  4+a (v6u ( ? ( @=19!!= 9]=%9!!=9]*#7-rL/73/-rL987396$9qq*t#7##7t-rLX-rL/{73373/-rLZ-rLSs7#7!#7-rL-rLs 53533##m]]] 15#535#53533#3#̛lI]]]]igc73ig= 353353353=uuu!* "*2264& 42"&"2&264&42"&6264&'>޴%%KLJJ%%h#"5#5733733#4b=/ M)IYYO)"'73#632#"/724A ǁ]q-38I\K. cn G : 632#"54632&#""24o" g@3}=G9<-!= h5 UDB@ W'$ 7/-7&#    27#"&4632#"/76274#"y-14>;w;E'/0!"-6h;VQ I~ >#>2"&6&"26===~>%%KLJJ%%h#""7#5'7X8)i&>I #57654#'623O0*OCf0 1mdKG)P -T/*72#'7254+532654#'6r")qv;K#BA #WAV5;cMH K 5#5733733#4b=/ Md)IYYO)7"'73#632#"/724A ǁ]q-38IK. cn G :7632#"54632&#""24k" g@3}=G6<-!=b h5 UDB@W'$ 7/-7&#   27#"&4632#"/76274#"x-14>;w;E)-0! -6h;VQ I~ ># #53>32&"!!!!27#"&'#53&=>nvMpQB  B`cYtn?9mTuiW9ETOT@5XgnT#UKV~53##5373#5#'U4JY48XE021;CC3IJ0$73.'&54623#5>54&"#1c" #ii$ c 1,,-T@"ZSXVL ]Q<6|aa|6+,Q$2#"&4632.#"'6&"326uspvqfD7@P NU87rA?ϰqtya U/mD:p0 )53#30nT@%T ###5!#do<?@@aa$T !!!!5$qbMaz`M@,75!@bb{9 5333#l nݮsYb9jy/7"&4632>32#"&''"3267.24#"ADC@)::)@C(96// //   yWX*00*WT*/2'#*  `> #"/72654632&"MKE3?AO6"B cSZ&0SnUZ,6>>#"&"'63232?"&"'63226?7&6 >;$5 F7&6 >;(4  3 X43 W3 X43 W<*5373#3#'7#537ClEh+F&b^5Q,873,j5.62"&$&"26.sqqrT9{:;y:{zopHIDD4#'74e& SRv0)57>4&#"'6323|G53>|rM8CpYq5I9ugxdSA*6k/: :GOX~y &(E5!'5dXYpsv.'2"&5467&54254&'#74"3>\hKpq+(HZ#$F$!ȽFC$4&KFFI39%IQB !99 (7265#"54632#"/7&32?&#"6;2BkYR> O-#=% b.,RAAOYU$y%74>=332?#"&#5!f!X&b j2L]LictCFP/!/2Q-$JS!Mk>2W!!> W]>&W!!>W]=53=uK#5#uj t D+ #.46?3/g,8g"??k_=>V4&/3#6~/g,8g"??k_=>VI2 #3#2{{ aZah& 53#53&{aa@.574'5>5'467*CB+&4kYn95Yl5']}?8=@u+/\OZyMU 1'^M\,%R7'467.574&'5'>*CB+&4kYn95Yl5'O}?8=@u+/\OZyMU 1'^M\, ',gLR7#DgaR%73#'%^t@ACCA'373]uA?uBB I"&#"'>232?0~ ' 54{ )  2! N"2! O53353!hihrrrr4l5!LQQB 2673"&'3K)@)cZZcu$$ANNAv`"&462264&"NuNNuw 8!!8!l??l?_,,j7%7cZldYk '#'I53Ilrrp62"&6&"26===~>%%qKLJJ%%h#"z#5'7X8)i&>Iz#57654#'623O0*OCf0 1mzKG)P -T/*p2#'7254+532654#'6r")qv;K#BA #WAV5;cMH K z5#5733733#4b=/ Mz)IYYO)r"'73#632#"/724A ǁ]q-38IK. cn G :p632#"54632&#""24m" g@3}=G6<-!=@ h5 UDB@W'$ 7/-7&#   p27#"&4632#"/76274#"{-14>;w;E'/0!-6h;VQ I~ ># 532"&$"26A|}}B?A?eeq@mii*J2>#"&/"&63253276=4& 37#"&'&463 27&=&#"\]-? X_Xl(.l *"\8s2"&6&"26===~>%%KLJJ%%h#"8#5'7X8)i8&>IB3#57654#'623O0*OCf0 1mKG)P -T/*B2#'7254+532654#'6r")qv;K#BA #WABV5;cMH K 835#5733733#4b=/ M)IYYO)87"'73#632#"/724A ǁ]q-38I~K. cn G :B7632#"54632&#""24k" g@3}=G6<-!= h5 UDB@BW'$ 7/-7&#   B727#"&4632#"/76274#"y-14>;w;E'/0!D-6h;VQ I~ >#=h]75!=+cc~ ~ ;   ,  @ , v9 *   4 - GCopyright (c) 2009-2011 by Accademia di Belle Arti di Urbino and students of MA course of Visual design. Some rights reserved.Titillium WebSemiBold1.002;UKWN;TitilliumWeb-SemiBoldTitillium Web SemiBoldVersion 1.002;PS 57.000;hotconv 1.0.70;makeotf.lib2.5.55311TitilliumWeb-SemiBoldThis Font Software is licensed under the SIL Open Font License, Version 1.1. This license is available with a FAQ at: http://scripts.sil.org/OFLhttp://scripts.sil.org/OFLCopyright (c) 2009-2011 by Accademia di Belle Arti di Urbino and students of MA course of Visual design. Some rights reserved.Titillium Web SemiBoldRegular1.002;UKWN;TitilliumWeb-SemiBoldVersion 1.002;PS 57.000;hotconv 1.0.70;makeotf.lib2.5.55311TitilliumWeb-SemiBoldThis Font Software is licensed under the SIL Open Font License, Version 1.1. This license is available with a FAQ at: http://scripts.sil.org/OFLhttp://scripts.sil.org/OFLTitillium WebSemiBold  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghjikmlnoqprsutvwxzy{}|~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~uni00A0AmacronamacronAbreveabreveAogonekaogonek Ccircumflex ccircumflex Cdotaccent cdotaccentDcarondcaronDcroatEmacronemacronEbreveebreve Edotaccent edotaccentEogonekeogonekEcaronecaron Gcircumflex gcircumflex Gdotaccent gdotaccent Gcommaaccent gcommaaccent Hcircumflex hcircumflexHbarhbarItildeitildeImacronimacronIbreveibreveIogonekiogonek Jcircumflex jcircumflex Kcommaaccent kcommaaccentLacutelacute Lcommaaccent lcommaaccentLcaronlcaronNacutenacute Ncommaaccent ncommaaccentNcaronncaronEngengOmacronomacronObreveobreve Ohungarumlaut ohungarumlautRacuteracute Rcommaaccent rcommaaccentRcaronrcaronSacutesacute Scircumflex scircumflexTcedillatcedillaTcarontcaronTbartbarUtildeutildeUmacronumacronUbreveubreveUringuring Uhungarumlaut uhungarumlautUogonekuogonek Wcircumflex wcircumflex Ycircumflex ycircumflexZacutezacute Zdotaccent zdotaccent Aringacute aringacuteAEacuteaeacute Oslashacute oslashacute Scommaaccent scommaaccent Tcommaaccent tcommaaccentWgravewgraveWacutewacute Wdieresis wdieresisuni1EABuni1EB0uni1EC5uni1ED7Ygraveygraveuni1EF8uni1EF9 zerosuperior foursuperior fivesuperior sixsuperior sevensuperior eightsuperior ninesuperior zeroinferior oneinferior twoinferior threeinferior fourinferior fiveinferior sixinferior seveninferior eightinferior nineinferiorEurodotlessj commaaccentCRDLE zero.pnumone.pnumtwo.pnum three.pnum four.pnum five.pnumsix.pnum seven.pnum eight.pnum nine.pnumquestiondown.cap endash.cap emdash.capperiodcentered.capexclamdown.cap parenleft.capparenright.capbracketleft.capbracketright.cap braceleft.capbraceright.cap grave.cap acute.capcircumflex.cap caron.cap tilde.cap dieresis.cap macron.cap breve.capring.caphungarumlaut.cap dotaccent.cap zero.numrone.numrtwo.numr three.numr four.numr five.numrsix.numr seven.numr eight.numr nine.numr zero.slashat.cap zero.dnomone.dnomtwo.dnom three.dnom four.dnom five.dnomsix.dnom seven.dnom eight.dnom nine.dnom hyphen.capmȔ,ȍu 4NDFLTlatncpspkern&:  $%&'()*+,-./0123456789:;<=   !#%')+-/13468;=?ACNPRX86vv.\  @ > d88N\88LD Rlvll:T^  !!#####$r$$       > > > > >88(( 8()vRvvvvl*+Z+p+^^^^^^   -H- R R R R - l >v >v >v-v >v8.(.B.\..8...8l//\:TT/<-T8888^^^ >vL/L1h !!!  >v^L v^  ..1111#$22j222233303j334@4@4N468l4@ # G &*24789:<WYZ\    !"#%')+-/0123?CDNOPQRSXYZ[_b&*24DFGHIMPQRSTUVXYZ\^     $&(*,.02<>?@BOQSTVWY[@`N$-7=FGHJRTV'"   !"468;=@BCUVW[9IY 9;IY[$&*-24DFGHJPQRSTUVXYZ\]*$      $&(*,.02579;<=>?@BOQSTUVWY[9-79<!13CXZ "9?@IY`o~'"$-79;<?@J`!13;=CUXZ IYo'  "9;?@` Y'$&*-246DFGHIJPQRSTUVWXYZ[\]9"()      "$&(*,.02579;<=>?@ABDOQSTUVWY[\]`cg 9?IY II IYo0)! "9?@IY`ox~ "9;?@`A $-9;<=?@D`m 13468;<=>TUXZ\]`cgi 9;?@` 9;IY[ #IY[oE)34%$ $(T[I  #$&*-246DFGHIJPQRSTUVXYZ[\]mo|8-)     $&(*,.02579;<=>?@ABOQSTUVWY[\]`cgij 3'%&*24DFGHIJPQRSTUWXYZ\mo8 3(%      "$&(*,.02<>?@DOQSTVWY[\]i! #IY[o?;/"-  Y[ IYo( $&*246DFGHIMPQRSTUVWXYZ[\]^,      "$&(*,.02579;<=>?@ABDOQSTUVWY[n &*246789:<FHIRWYZ\      !"#%')+-/0123?@ACDNOPQRSVWXYZ[_b "9?@Y`~ "9;?@Y[`~"9?@`  "9;?@Y`~W $-7;<=FGHRTm|H!,*/  !13468;=@CUVWXZ\]`cgij9?M "9?@Y`~"9?@`x "9;?@Y[`~ "9;?@`~ ;?@` "9;?@Y`~9?@`l "$-79;<=?@DFGHJRTV`m  !13468;<=>@BCTUVWXZ\]`cgi "9;?@`;79<?@FGHJRT`m  !13@CVWXZ\]i "9;?@`"9?@` $&*246DFGHIMPQRSTUVWXYZ[\]^*      "$&(*,.02579;<=>?@ABDOQSTUVWY[  @` 79<!13CXZ9 $-79;<=!13468;=CUXZ O9;IY[$%&'()*+,-./0123456789:;<=DEFGHIKLMNOPQRSTUVWXYZ[\]      !"#$%&'()*+,-./0123456789;<=>?@ABCDNOPQRSTUVWXYZ[II4 "$-79:;<=?@`!/13468;=CNPRUXZ`cg~B "-789:;<?@IJWYZ[\`o !"#%')+-/0123CDNOPQRSXYZ[^_ab~(   $"2?/@0EKLMNO _`.  * _b~ " ~    !"?@` ~j "$%'()+,-./013579:;<=?@Y[\`!/123468;=CNPRUXYZ[`cg~ "9?@IM5Y`oc ~ "9?@MY`~  ,".?1@$IY[_ `#  9~ MY' II   "'?#@` ~ I "?   "?@` IMM I"!  " ~ " "79:<?@IY`ox!/13CNPRXZ^_ab~h " ? @E FGHIJK L M N ORTWYZ [\`m|       "0 2@DO Q S VWY[\]^`acgij "9;?@M`~$   #'"  #'" $-! ;=U ?@` ?@` ?@`  ?@`\]  ?@`x\] ?@` ?@` ?@`\]`cg ?@` ?@`(&*2479:<   !/13?CNPRXZ9;&*24"   ?u$%&'()*+,./012345689:<   #%')+-/13;=?ANPRUXZu$%&'()*+,./012345689:<    #%')+-/13;=?ANPRUXZ$-<13;=UXZ  #? D`)ccFmmGooHxxI||JKc9;DNc ij!~~#$12345 D-$ 000*~yumy%%""   !)&'()*+,  !!!!!!))))++      ! ! ! & & & ' ' ' ' ( ) ) ) ) ) )*+,,, ! ' (***!++#$"#$"         !""!#   ! """"           ! ! " " " " "" ! # # # #                $$&(*2 48::<=DHJX!ZZ0\]1mm3||45LRbh!9;DNcij  8bDFLTlatncasefraclocl$&.60B :ABCDj2lzstmnopqrlzstmnopqrlzstmnopqrlzstmnopqrlzstmnopqrs| ((stzzlr}hhkks|Y  >@^`cx\] uvtswxyz{|stzzlrinc/fonts/TitilliumWeb-SemiBold.woff000060400000077010147177152050013451 0ustar00wOFF~FFTM}nEGDEFTd'GPOSU(<O^qGSUBT)?3NOS/2N`jZcmaphugaspT\glyf >$QZheadl66hhea$hmtx4 V2Dploca ̌maxp JnameJW ]6postN$5 [prephU_< ̏,ȍu &Mxc`d``W$S+`Qc {xc`d``<L@ `>]xc`f!4c &#0K\ 9/Lk xKhUƿ{1jtN&63I$&Qi R'ʈ6@55h+ [whօ|u!P+%B|4Vkܹ aL5לswιܤGIj>-z4} 3?jw賓YBuiP<0 av (3$sMnWGۿIYM&X.?נoVʟ!&o(GoӠք;]Շ^\F[U}/wO)S^Ae-+3nhA7&Hf%0upm]z5ta3+bA rKt(߁yA= a:jw Fs7c 'WBloSl[.p Ƴ'x ^ϢA8x K_]cgE} [9ȹ effƻ堛ŮS7y1uFjfച݋|VVWKAǵڦVOQ䘶Zn7s-7̯~YK5hdY?Yk9v*1|~IW>socF 5yzMvo%8='U-]lqCȪ-"z;iME#r>~[OaOQφ-z {-nU|;{-.BP u;;NSrN:qNU|->nSٞdO'DyZ?߻_3c|{o iG%?nʟ~kMJ5H jR jSS4!14nhIsQ-hI85-hO:E':Ӆt;=I417}R@< $2$I!4`0a g#h0q'L&0Qqgs#(9iNq2q\"q[ܤےҗ|-?=] p\ X>(#^QKQAct^WC wj,dh9 p-dHfdfEf)3)y <,FV"^*,fEv=g;*DGecbX1vkĚq$l|=ވ?% *N$^^L'$dcN+0.Mp 5x7i~ ?_o !aXVc*T.DP!qR\+g3?e8ux`TU8}L d2Lz̤'LMBz@ PLH(H@Abqu,u׶*ݢkBϽɛ$I ޹{_su=s<8æ6n/l}خ]ߠ'jx\1z5I!Ŧ/T8%A}O>>o x%sɨ3:Fl:3lb+ߐ? oXx/Yx 7Lَ&hVf˜\zW.;#MW-$d/;Él\QQ^ o_5oxehbJм>yQBIlxdz Oq\0| s|0 40S#5pd ٩:fF'xxʬR&]QE(uU555Cs &SZt0{gC.E9ZR_\zD ;"_m2*EaGzʛSF5+0s{9m9ю;9W۬J ɵjYS:MHOMz:6-_dhW|i)>%aqY _r*UYl;bbVFd'$$4L߿?,)w=rûQ]RBRl%jCܔkU7cFuF.G\XⲸ.҆o)M_eY^nن~8OTߢ!9:>\iC=G=G<;cX0.Ӝ-gΰ9pU|rJPKsC5r5SJǏq178Anb]kPEקHm1W] K誙sSb9ڈ٣{wtXCmʕ LjIrNaհB)2K) muq;=7G3# wWwx7'Â5FiM*Fڙ*DSGݐ:%*("C/l?84ыB>xCy8P 爒H\Ʀ1ZREC&G5m'Zі={.Mޛ`kR7c*5l1t؛PP*Kf{iwUzO>U2So| e; -_؏Nj8Aàh.8R^z_~7-#_[3Dpkˆ4M5m 7o7g!HWT'*Jm[ӺQj!pXuԩ:& ~Fp%/φʞU7{?'t g9+ ʇ0M4CZl]6l۾YU+jӐDQ}hV Nj'LU)Xxwpt]|XxsO25 %k \lje4R3][MOav0TkO=Jx-| #Kv,gcұ#hS(s0mE+h.D>Ȧ,VtCQl|5 oT@G ;eBd+>9>ZsҾ {>.|{g0Ʉ==~$LE;\lŜ_-}m+/5Rܒ{¦6wV juVƴy_d*aaSgpҥ:lŰȳ.8a鱭=byЉ;B ._ .|K`oil1c{t;v G[i􄈻W<&loi~= Nգ2&-8 R'ͣw^{-oџt BDd921*JQ n>ͽֳYt Yl=ͯbG1&%r Z45?`SZ [7t3&TZ4i5#[>T嗨]8`-*T'.{\)jǜ;O-(-C8I+ &$*hBkƁ ]4?/oNFCG?Qb-B-&ӭ <; 告0V%~ƒ4#S#ihrҼ G-??҅<ׅ% Ԫyg=?> $pk>9ꨉ j27حMrڮRDM-(f#0R`⡠w.5@ԁ1sז,\ޟ֨VۖύǙ6mSSv"4%-)C rJʆh}oo(*Uސ u.Fa5R7th·5:G"6@Dd=.**mriq}B/ו?'lؓA?!ti\H>h27PILth*w,@?} RTfCgX:-=5>ݙ:7.*4kcpKA訐재iw59mUVGkl2"*]bLa!ET2Z@Z >bg:4cʖ\Lkvb\ z?!u@r``u8yǓH 9*UY3n Գќ›%NtIO0*p57l9?'T-T]:~3̒CY:ґnЗs%]Arh[ޕuF'R^W/I&U+J*DMGWݗ}6?ZGN%:U@kҕ3\a+@TK"CлR:yf풔e; ;)wa#xnߤ]|{С<:˨s?_<5x<n%>՚ 믅+A{WAي\"9@ Mnq">[YU4(W: .ZV.);:6Nj:rAAd{2#lv8}=0~KA#ەYUJ( fpy:lkV65{iSےfoh 8jhi`Pф&LvڍҢF:4Mn%͏^= tdkG޵=A]a O ;w/srsωq=s+0"x_/<񑭏.7g(ҦkqՊႢ}y_܊?Z4.LẄ}25n-bAA5[b'*Q飿օ+cJچ~RcC0\kWe)Av21F\Qu+y_GJeV}[#=#<CA>tJ :?4 R4Xv>es淚22|)%|9"]gp7$+ Eq{\f^JyC`yGsuN]^^}#uuy];΢/@F`C[34tXtO!rLctz7g6UȏK6NʈU i͋mtqDױaC淃k k6(++D+*yM! q5Sb^J #4dF{ЍN3T<{-duI#Ăb7?e<6""b371ўEʹz[P}tw>(Uq,BHqFO,;דm`&.pM3[t, ɪ)˳ &%d Kkh9/R"Ae4Gcxyi4ahb8:#Q){Lͷ.b?o3s)>a\'Q0X%l.Yo4򄍨R{OI^( Q%ޘ4zIwFퟞ^)N܄a'zo+{| d3)_׾qZưhd=;?ḁxaGf>w Ja {h8;R7]`~o~k:{• s'٭q)+r^((6tŋ.^_^!WWUqcPXI)Œ~>Xa55Q3&Ge>k8wy3ƣp}{2Xs(WQcҨ!v={Q. qN]pmw^JAjj>aN]oH4;ʞ!#ܖ2_2\SF>GM(sKx4gQ=/G>ӏP3-B!_V"`([}׶.ysL-  "8Y"0Yp, _m-i ظ0^pq%t1p3$~ R&%,ş>=)FXt芲W]uY:![=(j~_k/=v,ZRtw{c|Y|5ny~Qak`͇ue&‹?H'[qP=@(7>.F`6"Oxo""KE߀^IĆh.no}3nћl.&#ĺ!J-Zjz٨$-|4)+SԵuhnig&dYR)[,#}0rq9{F.t$|ԳOZC?Ә T=Fm`H1DoqOH;}}@d0; vn$q %Pv>pz|`>!K+E}F~ɌEp&( {dy 2GO:j~ڒ+vw.,ch6 E FS6, ֺtsUFktWr}PgBcy=%!{c.֮hpbKKωn8}՘P餴WH|NrLyT"9jl[n4 :v9MYr:EEbdߠ88 ((2#b@.FڳgRvdžE&LJG2}NF-qMw'f7%8drsL:).UTT'$d%$LSFEe%f%:oeO؁f \rN)l%7d#{K랰[4sؘRߚtA˴e>d dz#жo[[T*CSRRC%Qv] =Ϋ bیMoSh=2Lg ߂6C9+{.&^R(AvbW8gDFaHuGNalgƏQ&*IO2r"I/=G\ARSF%+htrxN #xW2>.R_!N%) FҒX<^?]u98A<=7(Lx(,@x^?n6"GG!Inџ}v%|~koVϞ yIݏE Z2x)E*%)DKMl!u"` HE{INPgEFNSIA%~I.ј2̟yEɞ,ؔYtYty $O)4 s"\g˵G:fX9p``FKu`5o7J">:6ϋQ NT_o1 wՇN&ӺN15Ŗ$wScP\d0[l>XQ*:n^C6%V46VslaLl[.EY`r=tĴͨӶ=-n#oXQUa#Cwv*:+RzC"<%j>/$"Q8e&l܂- Lq:.晅+ sVcꕅGD uMa֬0e /f$_/к@j2r^l];C>Y2')6Heh>#y`{S ~|8Uǿc/obF'ɯ@}D~KgoߥҾf8cfM3GUl +< ŸN<8oD.#|U- ϣӔD#Yǯ_'o?лኲǓjbǣZu珧g}ډF'$LT a>P$C}\7C'4CM3R3:AF).s,>.ɟ&+?`_a*@qx^{d',KqTsłВ캇f$T kˀ[skx"d'}$Yp}j(8Y*̸Uriu<קg͛W@t}疰 _f"+F\Qn'+c2ӽ'!SU=iNj6M!ZKs`̢ J=)&"1^KpLHmεB^oF]ʽ,d_JA2|Q"wk|Tag׃$NI<N=˼NCN]%\)\<UR:GzbV{>D'\% X L Ã\hH|ǯ!E&U~5 Ip^^ rNDC aCQ^Jrj|+qpRJ.9RF8]ta9hBC5Gmv~q'^:X|m$G}$E! K D1$+~?rAtt1[/D%Ӌo(/X>Ց$1Wa0?p _r}%7ywI x"a `~'nsC"I6ĩ=ܛlT_uePU9Z gAE)LC)+}f JVCԥ 78!שu3Qk|H|EAwc٨['&FބZ?&?R+=eQ+YL_򕧳 _̵m7$ѣ}¡MŮٳ]gQX""T =[~$OA@Ը< ;yHULJ׍Tz]%SY,N=~|g@szTFR#wg1|fS)>J~y S? 2_ }A_NL$Q$AǨT+OV#=[˜c NԵqr*NԹ Q7uȰĕdwMX,x[E݆zG91mis'ك^[0؀N>1xݢG>+gjdВJ!ڕs."eW-ϴ)5S38p!"_|0Q#'f$zXHG952;N"}y''Z%3Ѻ9uh_7Dݯ@kVs>A=6_%:J:asGu5|'T$؃IQ#N= Ёn |zѵt6gc?Hkj )G~k-DQhoP+*N~H} \>4$'#*v\#Ţ혻zgvro|хOw8G""qJg&xelGOr3YQ,V~'!-9_1jsyq4^3ez/UDh;!}LRT:oy7X\`=776ol>.+s- ٤\fAgrPҘbB>ȆX6 o2ge,[L:5!,?"VmIQd>K{09^RUK:vMz%ba 0\"Uȱ\[%6=A=$S&;+x_0"hXk?qug(]iyyKm*(BmFa$/Pv0R_*1i$f=%A.F4Օ(|:LX9aUX 䡚i GϥLXO$& kT艓xNIuP{`Y'u3"l @QGDžTc% 4oa']>|_{U4TH/PEԯĖNT_RV)2Ҥo7M{{oG;kCHNz >ۯ596w>7l갠YEuw0jPkrc!02tn0uemkɬȠ⤜-.wr߼`^_X gP[?'9g ~j#_H/Ge^]4:'ơR>5lKip}[u6u>e~R\y9dsp1)-$i.vk83tspl4{gXT1$l q~׼PVMZQdkNdkgɁFM 87֟wێu7 հ5i̷ַ;b<9Kbʿ_@"s8p^]eQu܏<ϝ3Η=1"Ơo;x'kRٺR7 onXdJ:.M960o5]cX~$͌/obM=P|+ 5kJѡCT6v7`&F0{(03(T+Z/]~ޘM厈蕫[#dmۀZI?TX] 3َC=GFns:#(nB9qҠTcЛ[rXҴ9/*冎.y )Α箬fo'QjBڊ2ڃ¥ygV[ږ' V]8Dɧ IP!'V׊GD &7[qg*We8>|yw٧|ӇtO> GO!w=Q›c4[νFٜx]9zrlU<qOyr_|>t6c-z,}.ӳFo@퇑V`crS\>袌zgB^>N1%ټ0:>&}&H igT_喽7\14]߾i&ˢwRcYb,ϚR8yXٕ}|E΅ ӵ&^杵pKEhǖ }SSTu57ݕh_~%jk2wGD{W Fv?X; 8gƫPvwqyb.t ݢ7WdO;Nv5u=kڛ:R/\9-mqsM5*EĔ:x߽YwW/iEnnz4Wxn˖%x%tf]{e)!vRGovׯ0LR۵8ǮiҢ3}M.)/*#Q*'uUtNsm*-WnZR Êf%Ծ EnN7Ϡ2 PA 1-{Yt`.mg6eAhy@j EѾtW!FT<۹>1)~5Y5ofDŽIh4U\?sfPgLhLNOM>YXa}]0GICdD5SAxCtkRmh"Xbfϭ=д`GUp[GiQ&F$Z~Y&kklm5'kV7ט} [|Ɏ.|?YYJ@Sy|%Èw1gO9;w,ew,dynCd/{{;c澇svlWd|ߍ ndaŇaegT;~+J9y{F/ݳa܀pq:\=o<?ޏ}*['8|?Gqt5̓fb{ovxB|2XX*g·Zw\N\@u]*뽓!uU*y>㑝i1ABy\SeQy7h~ ;k8-S}pS[_Q>;Jĸ "~!8'?B:{ ?$yOㇼF&ᙟ~{ ~~ޟ^ٙhy(p 90 9ւľ]lMC_\~2}!F; |!F Y8 !k㞳/d{?KhK!5/dK`_z29v17bsm{nrtIn/{nܪ@ A:"7: d{WQlΕg>WU pݧ2>%zwݧcLt6=B0 3%)D諄ıڿWY=? B]_~ZJvxSn7=pɡaIcwF,@%N>sw)-RXRr $9 r z#G))Ƃḇ""83Dt;ڠOܢ?n xnNPw7V; xޯ}ozC7`־pD[ћ[p~ xZ?ܡE]7G9 zй&yMJHӌΩ!E*..%Xiۣ).9 *H;>$Z P r&g $>=Ëm9T{K㣯)y^dIzХGzvިIiN~Ip)gqo(^8yTj;+u^O%~m-]默gbC玁K^j8;}[0Io1Wr<İgjS??.@Յ] 够z -awh`pɜ} v @2|k3HR,x^a[J=LKRaWɂ *aϔ-Y ǥ7jfMlTfsxWEx\U/9[xmTgxU=$ +V1ؗd @lLv_v΄R, ;lذgu}9羹{-AY??2c0"B q$0C1 a8aclM6͹5=v ;c$v(ƮP{`O^ ~@$1 5E Q)TLCMhF ZцЎ1 qa8G`4U8'>\pX ,y?L\S0X3~/X@g# O9G'^x p^Kx9|q*BG 01ݰPу/Ћ~Hp7cq7e,`Fe߬dc Pøs}n 7&ܔqs߸Vܚp[vܞ;pGĝ9p~ǫ]9c;!xND}/<2ILq28ilt?>f#83sgx8j``'s.gMvs^xom.."m:^]{»3ROJ=r,IEx_G"!EH?I"\<5hTīGUUżϫ*TUIUU(\_wNȱ GⲺ xJAIBJ$h V6&WE_lۼV<;NKf? bGMx(~~vwvQkܰ0tȢ'1Y!Shos(B\f-s.驲A6!~r01 r-<~q\._c-8!L%κ5؀cYr]g²g|+>wy-l#@^'+E???P y߷[!QjP9" D U:Oxj|b>1QLq*Nt1Cl1֜.gyb8K, bG+Vjj_VN^AQ< şğ#QxB<)O/)>+wpC8"څ./",CEREVt KӴ!ZVi%pmv6Rժ Z֠MҦhSi m6GhgkjiK2Z)imMhvȻ+oc]C&``y.ϋ )>XRZQVQ6mIӶPٶU嗔*oidw[.:Z][껪wfn9ʚQl7UX7JJm,)wucQۖU;jFM Ν|_(7}鉲yշ:c|V\)1cᴍ3!1fS7ʫj/W恁ӑ&?vCީj=Wk'KvCE]57g#ga13 fϾmُ09CT͙99欝{ےȼCY> V\W5Q$6uDl5ibL |[Q &Z]T0gZ<|]eEB q ߯z\5G $x < rvy|Og`pC08bui`u@a 0 LS40Êh3Yl+.byq|)r2k)}icoL/b5Sz%F蕘Xl%VP\`ą؋TVJ\  {5ǯ[ z--n:z.F=b\L<5σo`փ`ߛ-6 w ӖԻӮݔ)3=/_q__o4f\yGO\VJCA(b0+cZ1[-ÖSVZ8H`27i`:i%zZ[h%E;ee\<&6CA18x>`hiVP '2./^=(|q{*pX Xc?Fc?Fc?Vx|ŏPG`'O |} 4p7hS\S~y>qm(jp[/ʴD`X`p޹=2Wj_n'-G."(Qrq$Α?j[ڟ>1)},h h"*DeOD8'2u.J?Q+.ҏg\DA *DeBWR=^ V5?$'bDlq"6NDNDNDNxڅ]xڅ]xڅOˍxivivivA"6H  b0aAÄ&W'z0E&aM ћ...."z0%QX7 "H"KhCA(,I.":\DtFh?' v6FD $DtI":#yø&\'0ڈ$Q$ʓD `  ] :aW v}=Guo'g|bkrk嘔fּhem>xkk'N復Nj 픪e% Vjrk)?;Ain:ho=x/}_^^˾d r**jľBk_ScO!U0d( )RQ}qvm[(ƊjS+wS;zz_##'a+n#1k DLqXLftvT:d??DhCm*վJ)wX9עvDbhDC{s}ϥj@#L4D#L4D#L4D#L4@# 4@# 4@# 4@#hDa4"L/̧Bat"Nщ0:F'DQt"N$щ$<:aatD'脉N EDat"NpɏNɏNpʏNʏ୑xJĨ>5EA"^E0ы0zaaD/EAm4*w2v v, [ D0 NӁ#It$Б\#|#:b#as2_'1AOI=I'INvj4$O+]dFQ0d|߯0~%x6ȽCäV0߶$DLjJ-S ~AWךo}̵qD^_rGw[jk*^SBi!ΎqYa8sPCH[FhFC9⳩q@Yj;8g%eU>(X5Y&Kd,Q%j_^U`۳݀Yn`0T.]]]` Y@xĻ&݊wݭ,#Ezh;sRAVɾJkե d{1Hscc̙wK̛艋}Y;ə{O#jB sNL$6_pb<8X|^h$v[{}6bf;;>( 7+}JڋVf՝A"x}/^o{)_pxЀ72MO-Π6;OsnحF;W^؍{c7zEhqAI-NY@~E߬{*pX Xr⿘e7F貛ޘG_W/E]vntٍ.@r 7v[9[]v |F]Nntٍ.e7F]v@&u.L ^"F^tً.{eǹ0P EDD@h%D@+ ZDa"h%ZV"0` Xoxb,(qqlolooloqq9nNXS8d!;;[ggݪ=9O|b0%QrN[S^q=|_2$LL3ڵ,ZZȱc :FT,R5dhA%Rf3#쬈5;ޑHu"鷌1SA)ښoΜ*ދ=QYaG]۾nZ%#<,yj]Y3Цp (jF 3}С/ܮ0ZPj8ƕՍ[Ώδv9e=k{q7 SPj\J-SOҌPO"1#1#1BhZ fQ3ͨfL3j5ӌi))R7[mlPvv'vv7>/WZi_ j jjHӥj જ[d2`F/]pw:ւ8܍8܍0JoQ* Ax#\ό\Nc-hX \8\nmp .oW[{ϤG<^,jC7t\.V̎J]k)/e o` >/Wk @3hQs$o99xtї.+̍>G.ȕS6'Oҽ;Vr# r4єR3̚AFc5^5]e9f1N F9( 1Ձ9f3z3  dA YAh -A%H\+X_`7':ܥI:u#(*jAjΕcBx6|?v M KS/}ˠo-d|12GO;NÈ0NG\G;oP]ڦzr ='a')jSit 09>;{: Lk+6zd="G3z"N+}KpX .(sJUX|NĽ.&;sK?qN{󄦝oAC|hm1c2c2c2cJCϨtÃnx A7эvthG7+*x l2؄}co`3r`;Sviyqx?Ҏѐv4ď!~4]|Iۿ5v/}&wfl E_~mѱ֋a6 ap${2O&)lf& {kY4lvv(6[-$Ƈ1ba%Rplv)w;; ;MD?NƎVaR[mP+:3./:3u:3//z3y:30/3 ;׳"\GDzt=:O<)zCC> lC fl{)Vοa9yZՎ>;Htz:yӳb|nUܑ\7af~ƈV">Fg"#|T^)sJOv0̠%gsETwePf)`rk){=XA/ ~vuiZaUF| q;_R |f-[A'Y4H*i#';O[$x < rvrn+p6|*ɝz|[ie+NɄK&<27RF3#ܽ.Rm)66(ьy3[r4yFcgU1nbX\1Sy忁K` R73|W[Lj^`zȞVH- 0Q1\%NjEv(nwYs71;R1uKhh5WBq `҄I5k`'` N`t 0sL  Ñ7ڌ^ `a ` ` zo(w?-=#x<2JN𥉉"bRx ϢY;ng,zErM΢Y8g`ɿ ڛEwhn͢Yt6f,ښE7hf׃p |LȜMItvDgLσp3/p2AtTt2sVJhr}VNͥo*JIS4ZԥbB=ij-./O_?oG7Snhc QEA 9_9wX ^oa01s~mD[hk5mTW׮e;<&kssZR\ K9{ r~r[ \^{^i/[f>-GFs g'gyxAdxO G`&]OQa ab _Q% 6 U`?+Vo7[ml۩=ʼO |& ZA ܠ x>!1r(w=[Zxz_t&Q2[$C\f5:MԷ1[??hWE\דL^~I5o%EV"<[a#['9+ΩwJ˷ڊ8c$3;a{%ކY VjRyZꨥJIz/@SR JU>Ͼuڞ:RVwj]}UgSm+VtP)T"fٛUy]zCGm^ ]\=MjM\ձR5~G!ԗ96W%lI7$߬6^"Uejk~zP\i~XgVVoߓ{Zgd!W0(օj~xho~` }27Gs W wk0;}|o{^X!NR{8ِɕ}dD&IFd'ddE&IFddDzR=K߂;pB>xADA3<3:3830) deXcK2̲dQ^M;^ j8^ :^ :^x5Wx5Wx5Woi'::챽*>'i«!«j5{u z5MK߯y5I\=W^^O1j T.Q$ZIs^cKc/Ot.<х'Dr)bǺ.!\uQs5l<>BfBc@UkxFrRe|qN /.bX_(b3'ߣM Sh Ś-nJiiul ڃZ ,9 lsmlsNy#_YNb1q]X +nV X{Lj\VCGOBz8ϰ0u[IAjPۏS x1aH>dubqΊzKw''^Szg$eہ|ϙIro1+jkXV Wo5ԓ&zIimjb<9jRGlqҫ!%,9&@^4dǾZrް[;^w]jFzz~ǩ5lv~uwfe}xGb䚽Fk+ٌ~ovvhm>pD>wOMVjO{n${9iEkooZEqԧ|Dw{SRNpV 6k/w.ޏpckj2qW^{(ݱf/J)CnU@K(g_{h.uގ>{.zx9O?#kT=f!sW'f}t6wRϑﻳ9!ԴLɫҍ[Fid03e3Nufs֫.=@hEz(^8ՒεBFO W zGQcҺO[uj 8Ҥ赧_DGMXڝQJx^gD(nxۻȿڥy!38zbĭAz6K%so RNWc1Ч/Ԟ-w= j<8oPw|#qJ{ϧz?(y֓'`Y(ԧ"!jŢp>Ϲ'1)F.B,j869eؔJY9Ϙ;!gw-׆oT]?n]TxYl_>fWjܞOc±8]3Oj*rja]|K QQ*`'m,l)U܄P=[,\>}I/?#{Z޳=rPio*Js[ uݛ(g+4F-mtސmQ?c Py>6 3Hs7_rrאu <? x)N3F_%J)QR=OJhN#>:ͦ\1^>m?rUb.fF1KIQsJ8]<.֊KijbX&6&Sm6A|i2)0t%}c"{oSz mzZVxqq ݷSA?>;kot=F~c~hN`q I)i.{խGUM>nSVz 5i֢Uv:uѫOxdT4t Lf[dŚ [v9p'zlzϾz"XD< yHM,RxeUTWSo /l1iU#D9JԦ\1͖[nL MXx 'osO*r&Vt(:FbzcB2n08[)99v(M=w+ЯЙƭ>)2kndB:v@;,ᶂCfGϛ_%'~O,i |A5 P0}lS$&6q. muRx{(YwTB#5 fk<|ZLͱ]M05b&94+t> oG΃VVZ2AKfnTu:P]hh_fD$fgdeesWF\F\FR)UΩdׁAAAAvӖўёљѕѓAjdh@aafn1f>! 2ɦ4ab!29(\rQF'HL̑b!dMev۱ln֮NwrΌ`Ȏ)S*2UD mtѵg#vvj<OqEsőH+\de%o}jl!$4`Cl B  Pě (&/X92Rw6|bAC4 N7$4L>>Jjywö蒊pņH񡍶{6&=WV8?V9 O>0H_ꤡpT+]U7G:'ӄ ˁ#,tD&Ыr5{=B)J: ޜN2o0!ap6:tS2 *z1X8J4ë‡DML6S\&P%u_&?/@ 5vڳfb 3[4e%v 0!PIrj&beǀ6қ}!M0#`tE [!r&Uk*4[l?Mupt)Ӏj[\yl#87twش'5>@$(#>J{ףn#5=k]enirFBO#|6p$RrpZzXN:OTQ}x"a{F,!6ҿ+OI)*>lK::6k/8 Eb!aIUTM}}4_> 蚄)pI⤂;lp .s_{QH8z_t6ZBT7SV\6#B['&ݹɷlvd'nHxg!~ـM]_˿(..hH1 fgSV=}:P0X`XPl:lDM:Lv' :un-B> q,`!fp^#B-)ڋY pp/D@UTSo7`h`'*\q+3SA6e̯[.0!ĥL5,(av)ZJn:ҡS"H(hň`ba-]Aq\%u$hg%=# 88.C8ooJY0'$*Mn!piM=#3+{9ᮨO<%t 0u8'"UکEwkPo)GRia;FȢ +vqjT:*;a;Vp;4ߝ|>WxYB#bCĒtTBFL,l<|B"{q@ @OV۬{+)Ƃ$$glϯuxAL ;9\F9y*)b8&BG8E rڬ@iIsP»w`U`Wr6w>/o!76%[Z2 uJr6ͧ6~\`8*tWz>"|W+[(袜qVSX#dv6\'/B"%RPE }0\`!,[:6wV.KrS.\| $ %DN*2rU]W[3E74 ;'6:A]ecņb$25<8{ŕ`3 ƌZnfvv* iit6#]f2TK[ͧoc.pR.CRF,l˒Z~ Mر:i I$ɳ %4$##3exL4Y$ QRQGKȜ}\=oUd8®ԋ؛˶-X2 TEbda*p)@m9eE>QgK p֌F>23Y=FFqV046NMD&hY`lպٵ8•[$/9)ynab"84/KJ)e5k`-`tҥ8RJ)eh0Mxim^+Jy iʠ"uBnJjHؗTWζғy@A` I8aJZDQ$Bv/ o/1&MQ)ͥ 6v=ȶXFADiv]ߧ@)LEURtWJ t5kШI=jZ}Rէ@768 \ 0 0Aa#fd,ëB"5Yeʴ% 0 ð@H]g_|TffnaruwaeT5T A-:O@ŏ3B蓚!"䔉MTj;ڵH Fn.YXط+2Νo_ǟTa5rb3 B M0Ni! @U?tzOP[¯hDWZqZi[X ,U( p2*t"}"Oy%FԀyfT9XMjhE?rLvކ浠jQ6)qm9{UR Y>9qKv;d[. LW nN L,lroN-d]:yޜZBN-8IsP\h*JXk(ƌgb0?I^Z?~P`_Kaʌ9 5 ZIaq t4"p2xPGaQ DsNH)h2A,DI-FOMVJBj)ͮ+J<aH(hAuZԩנQf-Z `ERIK2[e-YfÑGx깗^7[[g_Ε:vcnv+wnq3z=ϻeYesT䠆"6th3+@r)DӿSC8TQL6|!=׍zѼ8$Q/{GBĪ3]_9CvY1fȁCJ(ҧԋs=u"䮗 jGG*t[n=c0h\x 4;-.9 {v-X%( ,`dP4 u1)k|*iq|\Ϗ903Vu@,d'g bx"!zT$C]70׹z 3,aIUዀD;}} ߡgd6g!,[n v;L1gZaksv}4xL;yC ]>[Ogb3/۪pSz z՝]Xs sp9Z.@yn?ę_xaH(h9kZGiS_ZL.lO7_ƂcyҞq,vB|>@gi!uchIy:y.,, U3:TUWm>Mk$Vl|h=';j *VI V/3P|*/-`K;eNjh9 N ԺX䚀<̫݊鋒g?q"?~sK׋2Ղ22\ N.D'N%\K,J*~yϊ9ZM6ԩנQf-Z+ }ǁ!IF L5hɊ5_l; <O=뾍zϾ._bs' P%eҠuONVJ4pzM[:ֱTUU/傪cn|Яn / nItK A0 p)8bNhvQHWGT4qb8Q;IکNu PU2:v'xڧ]tKWW'm:;uP[=@^PLD*ע.o)q P@k_:eSQB^Rhi_?ىXs1vu N_7 bx ʑgi FHLu0@ $VH=Hg7c릕{9yEV(L ߱u?'/gj،ō--ôRj^ˠEKI*FTae}GƏ,zn-E}ʓbA 4Ex', ̮&kޖ}okÉ c]cz 3rȳV9T'jFlhf XXH};vϣA(&eCZUQbਯ+v~\l Y[Sw賾,=C4pj Dzɕ@yS0 <5cGUZsۅ6OwӡJ߸-"#\pOўuEec㞷qC5w7kx +L h`9^L' Dwك`oCHݒ>‡‡Ap1㠽U$d|AIp@틆*C `'\O0ۇoN lL!Ya2kM" 'yO'\2e1c 59{eEQb+&9Rh5mXwhi0#%q4( b[Mf  Qm}2 S@5f U*- `CWM}戰1昶Мm!?Z3`I8}iʤ wZE@9gBr qW{$sV&\`eܐmA^[FէfM!Îqcx%;_d}hC{Cv~$:]ꇻkLuu㔃UX!@#^^ȫ 5_ϐ  *!H B@8G\R>}2NB}R4苩xN $:O ԫ[ލPgm(2t4* _tQH_ԝ$MU&@p]^cL5elD45h@|d猲~Wb ßu;Pu{+ CT8I}x{@l- 1b_:V l.p39P$aku,XM֪_\G`/Tw&d5Kz&5, a|S^mnƀO[%>r2bӦ0m/cm&y@|PAփ?gm6j5jFQhhҝKL 8B+85a0]rBO(z}(n_9#]Cg&06eӶOĉ%gpmfJ4|VZ-9?&,4zNq:u@B頀{bѤ<ˇ D~g_0w7ݹfEW`C.ΗiܸfTh$l kY]+j# Dp`>H' ld֢UhMK XܴԽКJPS#VU`9v2ba$yڋ?vJdxk!CJ111޸ =h5ꔵ|=˻c]6ě?x)\턓0هe_Ȗyle(B?͈rvύȹzBS^a/?ujajIhrDep.Q;uPCCw 8d]~m pHׂzP1{PpxQ"-y*Sh!s>`{R5jǯq;uRlH.߷Ha9|)譯 P=)V Bn*A!긑 4x."1i*fK[3AςGB8Mars ؁(|봽0GyBFY~y \uYy2X:cl1'd.3w!mSwv])ꀸAK<:nziƁzg4CE0< 8٦Qbʼ4k|Gg91) gx ;/e&54{xgr,>mΤs,FJ`n;dEza7kh%cEqEx I Eo)  #i. sa djV?*뵼~^>Ohe*j{M)ӻ&xҟ,Ԥ٥^hC % +eh52H1'C- ø(|sJ<J97c3qfhzy5x#cײFJ͆,ˏ:v W7g)?gϝ3]fRhfJ7E^bGA`r:C{M$~,PHP+E  ,*埍IRRY + {WP $pr`CJp$|ki,g4RC?LJMO쐾s0uq}qXzwxT(AH++HYVa1Kd?v8Q *'*KwGi)(v}4g{'7TnhMrx:Tв﹗qD|[]:N>j|mOi#1i X`AW #!"M;?mw"yqzR@#RzpURKP6i*T Nj躒>wY /ǂ((t޼GsSUkVens&5JF!Yi|L뽡vOr]XݎMXġ9K:͟}v/[eWbbAK02nCNvvXp(=Y` u0kiR=B}RPůc:q2hsJbcnB6%ŽƄ`hS#פ{!I{`EmГ 8Kz/ X&N8S9Diә,:Oh3h4y}P WqDʬ!=F(Nv s)H*Bu/ga^]5>!Nkz4a"lthlE! 1W1(n"/O룥QgTPwipO(L[H.|fI_H>^6…6b_XaAɽ>Y[oe y,9q@2B(8Tp:0O\X+mCYCUW*D`L%2+CitXPy UKl(wUMJ۹0oe+,L6 EC#}FEGlJ|1A0%9L#t`_/prv9ϜgA/3ʋ#(T;.Bޜ 6@AӞf\I؎ |&R8*wŎ׳x\,F zkk Fs~,1 @HCp@PcOcPg5qrȍmaDs`%4*60^fUR1s HE x/~] UEUdsqI)ju"r!) ҫ(G,Jh8i{n L_ k6"F}"FPL%c8L9Ӹo#{\L& nhڪXjc0Ɯ&wwz*lt* ofq>( Bi|?us?~u1uh[>̻0r?SgCl]mKoS@͋˘y#uُFJ=  uGU̜uGPMt"i թ<+Ts4=s+Ԥ|nZȕ' A[E`h2²Ơ*[*kIz;U,?C6m+xan;8`T=핟ջ{F~34IãWd5P{9'7HTsy~{w"~ˠi ~;PURb6xd1^ڐFE=TcsC{v*?/i]Le=N. 5ǧ]SEwl6q{@ txo}n盶rRIUA\!iy LJz.e㨙vh! sftY)jGNJpdAlߤH,TajZ[ Dڸ00!},Dhd}bR=*G)<㘍ZdA쩃c[TJKжfE|ߥ쿫(S+6RSS@ܙqMqR0z"|ԶpU-Vl}3`\0Vq fS(F5UA[&lm KJf~>&f"%(.8[Ͷվ]DR/QK9 m [)gKum4oV@?^`TJ)].:vPe3]0=U*\ m1ĄFp$gv`nҤ7LbYEM <Ϭ\CjEyPW6M*3x^ßӦ5Bl]ׇ0E_Q`뚻Ӹ18l66M"T@TxVh-= ;~1>>W:o"fhYtgRWz~#e;hG.,2lVڧm=ZÊ8\O l?(~,@l [Ӗ$hOɏPI*|@h6t3Kjµzj6O^`~Fmow,ps M'7)^{|gOkZyB4-* #T{ ݮ ilPU '6pJ[viy#/v%:uQok-C8Ru2R=rAkLkwTYOBvNMCmp=GKmp)D qu)Mމ,;֭jtINVeLX~n="Wݳ5.r2].dQ+-ju?Z3÷^U 5og7 J''I8p{z+꿷7c[no0$`E\AA WXf Y `@ROEEa a׻[%.N_y OLlb?WdA*HKE ^_V OT }@0StdV=%0cY.Є8=Y OAL Ҿ)qVf)C\$KLgȒ=*IprձJ 7[Bč֩0BRµZ5 +><~~Flq7kg@o]yBD,DzaHetr"AQIiA'7K>a766<``Aya'osa:oȔHH0)eT#ŢV\3>y;19$?]ӺĄR0CΈd -3'P*Ikbx+,||4&)n0CΈ]8NZN46?gcOj6z'pv~v:H"gKh\jgTRkӚ3=In)µ T7k3en/0;h=YDxGq޺J5j[=+̖?w`ݻ>\/Y@{`:"=ʭe$RyY\{JE,u^K_˛#@ /goowc֢ݡizoy b~gZU#LJr}j %e )q_ a.dMB{G4|`TUpr_7k^/[GZ:ڦw헡A °QIs8` QY!;e\2s:s7iYE߻ ~/YDuK{灖FAj%-Գ$iK9iLV c鏦w4?IIoH~F$1 K }%{Բ/iT']拻IcUy~ H,-䈰x S@H(79,V0NU?Z򌫺K(@{}ta+SWjX$A.\W@Z\$qBF{Â2aTPa |%*Q& }21c^-w? /_ϲjSgg$3k(?_*VEvI&ib".|s/}W{/fgk.Š0UYٞ)U ܖIAGt}Vn'UlZ~|J%;Arυ S7\iP{U'Q~ؼV7uf!b`w  C\):^I "k\z2~AZN"ě_&4hŭGjE lΑm(B:Z'T`/ > aP$Ĉ4C+K-z͖pKzo ˖rhZ'Cf"8dW5_xCj1&;XϮsJ.xR}T$m}~pYLG3v)0oEr9)߃JV<{ցQ9秾LENzS~~ Q'#lc2k%s10_B,ͷ_$ȅ?)H:'(`t9w&yUEZ򫡄Q%D1Ks$!B72cn9%# =x.1bs/Y7qף#w-*%n6lfZTe96_c>=J?絙Hh„̄6 tePuMg:o{OYͩ}̃b1=<#X_6)1DG|Q~i)2lH?%%Ą5Mtځ1?*|ؘ2!z;>IL@Dnaw.wuC k}|&)2NgƗPrrrUR,^3\0qȨ`lVYB'3B Aq(9g U]sK8E&雀'ziX6Ejtwya,>br9uer3cBsڝJduEGU%Z熮G^Yg;"5>aD 3H\rR{JL\2"/%45ʊ Bs{?}.A[E ѾX^DBmt{%^tuڢKا p|8ڻ9ñ(,we}ap)5>l!rRd ypv\eH}38~bqH djiĻMfx1)\%'_3^/;mtԱZ310nRP\3mXT=ϸb{×xf"D?kaDzQ "97u)M u%%4~k.[ ''äOa0MҰJJJ4wUV<&;M>ܶc'pajsrBjV5C9߫K]:9金J 1,~P2 i f2L;!;ŀr;j.csx˅/R`ݻ\ O 3zX&+@lf.FA] +ͻ@vϤnIr.CGJ)>}ti]g5|ÜD}i5~۩׆"RT'grʒeE.%ywX+NApi4+%!nab1Y'$i6FIk_۷ ȶCg AvI)X耦dDI[e%Ī"P*QǁTLu:'` ]}B#gTLOȩh&RsOAۗ=l\% Cf6nEqhmKkƩFOpF" SqNA's;iʦӌ =׊m WLYtVWL.R %Hb^_.(f|SBM!i^7!G8V̘^Ux;w-w0hة]sdَй DՒ@Y'ҕQ]=}Kz-*Ogi] ͻ}2U[_E֯ .1ZovjryK.qWba0q|gki-=R:|lQ] {N9ۏt?TJ*KQ d3d@iW P͘Ǥzϫ=;VmTRWD+RQ*)ϙ}ݩwx})x[=o+$&>vlU%Y ,NmePH5t1FUomd9fЮnXbe֯Z"CjLJ̐ nlnh4hгEfmuS1,`PK.K+ y9@ #$Lr:B"BJu\M5b v"aw4I9 )lr[8RZ%WL o $ fITo0+u*'D!o[}2 *9)Mئ\QҼK,"$Ā' ٜW0EeE ZsqqVٳ`_B`k8bucS=!N#gaɅ3!]^y8uz!lX?Vq'1D"3ܤYymw%i9zkdԡ~?קsrHU}6 3{n4Ŋ|eYi9y 1ϿjK;_P8K߫)V ZekovpsMb; _Dٛծ+Vh6[wN (m+K*HbV 1u="Dzs$eN311*ss&|u<[ y1uvEJ3shH =IY Ne=GQ?\T;YYdbw sD0ai6 ۚL#vuQ`TgP @'MQtmiV'{4&oU `2vң 3ܡV)Hu &ľ9l&ϓU3.?ƠMPh}ͻ\gsIБ(ҬJ)* I\_TmfI /sgH=6Jx&R-iچblit5\/qsG' =5EF)f2L4.1NmnȚm(B\Pru$ޜ(XTz2K N`b?&C,&@W^3X gk,}O^rK6S\j ~G zIP8BѲT/PͦSf̪<ӟCA8{^_C"uxA.^&7 v&\hfd0HF됊<$ǐ5Y2iVd)9q7)(زPCX"|2 ҡH?mf{LfiD8i&}Ҁ& ˸dET4QFmE3ib^{qMc,|v(\Hټyn?=(fD敖"m]pe@]}X[Qk%Xh )a[ƅfAL_!#d^:ZpjaX=Cx55"& AhԴMazF,ob]м;0_PiΧ([8UT^_cY7C|fz9߆g~}; j$\Yg+knYkT4tk``dba֨ɋk̦݁Sixl=p%S4zWf0a4[).{5n=jz7`PLWMW&v !PRj58xDjIH;OԑS#~AEMC hnڳaӖ]kvG&_joZXBk_ .0 aSԽ8耝@U.0 aDWӚhinc/images/blank.png000060400000000137147177152050010365 0ustar00PNG  IHDR%VPLTEtRNS@f IDATc`5IENDB`inc/images/checkcross.png000060400000003075147177152050011431 0ustar00PNG  IHDR||$PLTEF,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,qJ1Ļ`IU=vR:ZCjUƾzhSwcp\vca(tRNSF%g.a0щ]7*yd1zIDATh޴R@$MFD}:";/ReMM4M7?X[Hf' I0v.xrLڙQGWek.=ldϾ+A)Y:g;0عH>_LS6ʟ˒BJq;V+H$~\.;֤%&YgZ/ck[71rO/' 4\ヅZV× P]H])o>{St葏ovީJG}zU5VYsh.C{Pf>[m ] 6EpҪ j iRw;l.qBk>CKx<Ixv̘C`l߻AiΫ EY/^ڢ*dmT2'eq|R=>$E7d?W5dEc_|nC2h4>&FC;a/l D-$Cڑ!$?S دH^ִxP FnBkY<{ַ2$ my[W_@;~ɓ꼭?AG]y[_T\uҩxu]y[_@qj6^qٲWPR듏wٯ[,+ֱ$$M2 I[ȴosu6q>ɸnئO1% ۴pl]Pu\6#}=\f쮝@hYݼM-'V„By[` VBmA[.g2 !2$7{U(Ͻ?6(C D },l q a3ߙcN׳n=\;_8o GO-/\FEԴpy-XU TgcіaR/4L&tit܁=@ƈh0*X.E%>BQ$S(Df8pIdEp@jB>,@HQ ) SCa ~So6_Ee~390͸{um^maqY̒Zm 'Biά*t=f4fz-i*Ό?$_m>mC>li^-Pu﷘R-jo+XAx+.x_!IdTȘBL01 )|Xo8 ~ PIENDB`inc/images/checkinfo.png000060400000000740147177152050011227 0ustar00PNG  IHDR||$BPLTEUBUBUBUBUBUBUBUBUBUBUBUBUBUBUBUBUBUBUBUBUB"AtRNS:fs]L9*Y7IDATx JQa;s^lK>Zkr:{3O=s{9=  ={&Uvڵk׮LD{&=ўhD)Ml`S"6E)Ml`S"ؔ6ms,vP_hQ}Mo6}|ΡVtMߗtl`.ش)6gg؜asv6gg؜asv 6Mbsv6gg؜asv6gg؜`.ش)6gg؜asv6gg؜asv 6٭Z=dIENDB`inc/images/checkmark.png000060400000003733147177152050011233 0ustar00PNG  IHDR||$PLTEUBUBUBUBUBUBUBUBUBUBUBUBUBUBUBUBUBUBUBUCUBUBUBUBUBUBUBUBUBUBUBUBUBUB[HUBUBUBUBo_‰UB|mfU~UBUBUBUB]K~oΡUBUBĎݽUBФwhwYFUBxiƒn]Ǖm]}nteծծfUݿUBrbUBΡcR`NYFԭvfm]۹հȕ̯Цtp`l[hWfUƹֱҪǔŏl\[I|mܽٵ{lwhjY؞Ɠx}[ NtRNS.꽁(z7#c]0 `Gٓg̩FE汏h;6 ӴspbMID/ɢIDATxśSID.Q}5f읽K ^ψ&jV}Wo |+OKg;!΁!RYNhMnX:sKdEXaz&!&^b~i>O$铢uu:\ps="{+L wX+:.bC_H=$ 6n58 ဟd)2'p [s%i{uG> 滲تy݃Dś$k[܄%䒄,th ^UǺ&\KXR46U0M`am0ÄvK`RujOGiOwK"zW t;:/ailk> =NcrVװT0B,A6bɰ6Ⱥ}dSf-,-Ff-9;G3yK y" 8VЊG\1#Q0$drvrdQ]aw421ޫu$$1 &@L,iSgyP%5'>N("`rkOz f[͢`m: `-s Řj]Hv.?{rtfwΟZol !ش؍7 E7nE)׎nCn|$K NjP$׆_ϧq!4@*錭"%?]vKͫ")0zRI"Ba`=+B# z S  n(rcm 20@n7@Mjع0>=Xj#5Gd"^IJ4j,i2zn(v9BNCsN㗆̞^\nx]3|Q<rË+r6)WdŁLE1^7,/+nX(mܰUq" _ϭ]Das̞p-y9ܙ w~5 9-sj M[R<3_suWvwm eж6l跪\Zܪb}5h1ڞT. =!66f!Lj-isxK휨lo8r4`4`5-w7r4B>"De7Z?b0L\!j!Uĸ*TVP;L0m$;lfKT@DIéN^um]%,[|&3ASK_ x/fGYpLo_YQ bgr|XZl<OxOsvNaIENDB`inc/images/checknotice.png000060400000003341147177152050011555 0ustar00PNG  IHDR||$PLTE+$+$+$+$+$+$+$+$+$+$+$+$+$+$+$+$+$+$+$+$+$+$+$+$+$+$+$+$+$+$+$+$+$+$+$+$+$+$TOA;<682xtGAqmIC0)C=[VKFRMc^}ieb]-&|xCU5&tRNS/F$ga)ѻy]7x0NvYIDATh޴։rQ7 $iU A jޅ\f4LO/m˱(׋kYD:ГJ'<%9S2,Jj*KHas-DLX)srRp3a5<>Oѭ`ǿSpS Э*m^$d`ɬϗy3gQNUxмۯzuyƩ}N}UU3?SQ{x :;oy~^ݰ2'ЇJNr{ΰ ab}fK+dv5ړ>12'H^ra*^Cc^l\Ht F&Cv 8QsJ7U GԝG)TFBtE^P!x8z^DJaW\ GCn}ckvJΫ+o͗v̸ lj{I85f89 #mMEKeE=({|Ʈv8W6JKᇣM˪ӳo,Mġ~D;.&.-C,&CZv+bӏkJ(_zЦt-UC+h[t-r&cͺM4S-]PPzAՒ#Sڇ1]Ʉ1&M%T>Q%-鱢uӧTR1fPjJ08tʚ8iy CھA--qqo5eC랶/PNײY5m&]MhjM6Mׇȉ wtͺXI_W[LWZ=>AJWJ҅ZҵQozhݽ٭$EQx*BP]EYECAD ŜofqY?[y=d6 fh@!c"ᐁo^,6/xS :-0͝ <&Fܡ}F}>FWq/)LF܅z:Wh0{}DC\R<>Fr)D(*D#"2Ds ks QELl0CHq&BaV&€ ȡ& ?= _oyp[4Kq4ڂG6yPr_U%FK: 'Ar_O,HY}%mg+72т2P+TO+m^VUlnQ7.CѺyrdx`:_+VH\MʶJ F'ζ>w2.N5(uU+]knÚ/z京u-ƚm#IENDB`inc/images/checkwarn.png000060400000003356147177152050011251 0ustar00PNG  IHDR||$PLTEF,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,V@_IfTT<ǿjTƼsw[DJ1wbR9o[zbL|mvfN7kQ+tRNS(0gG.yaѻ]7# ٨Edۇ ^IDATh޴׉v@I@V -jV{IE(-u?.Q?';!eyI;U,|6 WZmY emVJfaf9SvuY|U&QK`i}$e'g1"+cC6olSa{eg&JsTL:BghtF=ZḀ߯#qM+?ӁƐ9T:Y6T{)K*(3'b]8:8h9Ԅ>=9c̖82J(4-cE{'Gl{z,c9g٣DžPs3\@kDPgټݪuxюeOX?3})ԺwS6\Ae/zMS-詚=NezꔱWmA]q7>7( 2!/XW1! ${DaIL^`>{#/%_&+jS6,%DCf9_ !clc>,l>$I=ED~JtH%}D1Z@J` G>YhFv!>gHR76$t"Cq@RDLE @R7 H\$"˟\ &I(y[dRŸb՟2@mp0l  V85SCS/\ ȑF\Ql =$w b <{؂e @^4*N*4 CINI9 ff#i#i&mn 10s=i* ӲiQ_䘂p}Y_bY UIWFgPũ*c.&8A+-Ɯ$Z]):ց:IENDB`inc/images/flags.sprite.png000060400000223071147177152050011703 0ustar00PNG  IHDRϰ&IDATx^uU]XT1~]!$ \]X;yz@ý_n-ַӝ5kGu4)JЀZҝקLyCikk:\eec#:E{6~qm<|2m g'a!ފO$' e~[Q PqHx傑D0#!"!.@yɴ%"q`h }4сZ[Is)+I:Mۏ 0h cL*>gӡFj(+ERb!Ƚ4]Wg5X\řO ؉t3-s񹃸5>HKm>ttJo`s5KDbq%y[Qt]wDBYe ( |Sb}\GR!A'v1#%|\&`+ n(QFk\>V(xxZ͚5k[5x {.yypA'+uPq)w{ъ)VV(S7z4oV=-Z ծ H$1Ne H#7!NJsanu /Nu~dqh5ϧC#{lq׺tǥQ:\ψMdc\IB8$1MQԷljPV>∼wƹaM'u9:m!yih1r :eA_ I&H^zmt|LԵ9w>jb5~B55@\3c+=hV]\〫D$z~ݠ x F0B?R*bU5^L>/s|Ձi7q-cCzrڤE hw|#-tھ?>#EqnL[}_ h_ZįYZC~>#,sGBח +d}Z W&>79 ߏf*b禍9;.F$E#MZ濵[.[\5!8w)R2!7\p=\a"ض\o6\,L>Dzeb t׃;B^<.|{Gk8Ep6≄T|x=&8//v=;P bXI3~[퉕{VeBK9?^4uM Q`6>|Euj&.R'鯧M{jr#Mv>0Xm v8fc`%(/"XϞ1cnѦ6.#>wN8Bt,ob~W񕆃v̻cf1{a#SgsY;ͤE@mgϷك.*0~l#*tK<U-e"RDۑ[{. TIPLv tI`h n+R =[̩~~b/aHx *Nw΃K ؿE;_F„Y".9P6,zN"O Z̋*x.v3vSxCZX{hQ|*3~!bV-(;4Z**pU ; )˷b粥^CR׳KN݆Q| #qsʨt(5Gw~m 9D7L^sٝ zl9?ㄢTU-4v:|x:k yx|:~?-"vt#~-"/Zk.iG7Jzr$گ?K︃3 TPHƭO͎ |iQ(| ϓųJXȣFZ/aŤÏ^Ҏ|L^~]/ѓװ6`þQ>{+)n~ߙHJ5JCC}aO{kx.MeevHb+4y"P_X}ߎ|i9g4w˸uC? 1\qE7M ]f㻛0o:D678rŀϱ ݳ;0e 5O`ȴtx5rwܕ[bګp|As:Nɾm}}:v_$K`жAK@4R&}Cxc1YqtbX H[VڊmIKQ?u1XE)mGIac=)TϖGeo $:he_ENFC$Xhl\Vg4@`q^wމ޽i~dwrênҤFtPwPnD$%d {->_\H$/F#q<^$LN'Z>ĉ oN

8\\lY/ ׆t;q9,o=PD[Ʋqz~]Eۼ-vGq> }&/]< W+J}h/5۲^nTˆbQ@ rѺ7W*8vA$)4d.H%ZX'F_^Q9NHH|!ץ'/^i]@D=i|9j- hTm6#=K@rgQ,5 8ȖmNB3pI~db1(ؐوw*' ֎{ 06ږ? 搈CJ"QH/$:/M$֫7jѺ;kCIg|"Nݕ+/*b l_z ؃ Di&h h)?P5w=4㑝XɈ#X/jɐ?tvAQV6mh3D DP:< ,A.Iϧd"b kڊĀj9twXaN86KDK7KDe B[\S~ob"yuDD2+z!8w)o>Лn8|.(/H[h8LҜތ56\>mLKtFZi/3  ٙau?1$JJ>XUuW7 B'|"={qeeL|`?#mT;xI-h]}cC,nMЩׯyuS--=E(=(+i3EF~- U >:Ok9YwUUa^ =`G$! BtED;Pqt t)W(ڠtM}i\x7q {nW]0᥆&]0LQk۠Uw,Qp"V"_ 镹z HXʊgu |h$Nl(BEL('^PP,=V\ @QQQpv^Ͽ`}Av3^qEפItKJAR+Xo އ=ȃ\?EŽ5*q[~![&9.>yyN8?ttpTWWlW&Q˓(.Cq61"'N  F#ߏ(LlUD1qf4]o}' HK[Q*ySk]?MĆZ}^#ً7\Ñ[}LI# ]vsaXЎcX%Cu0"0~IJc\㯫. |r|lc>Z<{I[uW}/[Z|;%~Rf@9 tdZg1~ z ظ;;3oZ[mEZ1sΗmCR㘢3i,`+S?Dђyh\+S~Fޏbҭ `>o:L2W CJ|?82tFvzTҧm5r/։1yWfW²,$wI`4kG/YH.x)qI ˉ.DGl `|!lq$rڗT'u(٦crV5 h|'gD$,6#$gtVޱk?)6]h@ sC|?;Ɉ7>w\WHe^(]A>;,87zpdK|#jq]ܺo+JnKREmV6ޡb.g.zZ۝#bE?TE[ Nm&eߍ;9kaJ>p^_ad

,S܌WxU%DKYDn!p`f̀{ô4g}dįl,aVlAMG>t9GWT#+vHAĐ~#qs yqq 8=߻p$ Ai=[V77ȩgM=PWM{O\fk c0j1^54n:N^q|S uj-FH(ZDm8}gŴ)Gr̹՜vrf2򉨔!qʕcM~s59s [t\PV41F8è4)n3vSmt*E$Rܠi~_.eY584RR)g,_>-~p~qW p:wR~wo!pePEmH1:=^ (ީVALTh!R m%qnͮmxYib@C a0yTC8Nn/:3ߪ.ŝ{<|K]o[v X@іGa p 6>L Ds'b<֋沗<&RJS[& pIw#O牷 8!ip+g#v].(FP~q,ThHrM( eu3@=G^XԮho{?\)8\ۃ{P1y?P!%ƭxx?V13d3s/f͚ly mnMYrY;?2KcK#2PAG4bTͩ2S*hy#/Z-_)y.ݤ_{޵<|.@F775wuI?vy W~:{oJа`Kkk RXB CAG&0$;g@(p]zkZ2a_:* b939r$*T c_Do8Oǚ8;~Lu6{\QχQh%q>yQbV߈N UMإ;P&6er E[@Gӹ]NrT^p.jBJ?gweOx"ѮJ _M;sIs+.W=$c ^6<{._Zˆ4@P,iGbQe^dz=mʗCâdh:SɰW#9 Xi 1S޿:|n ɘg7 )E}r~[lцegC%cC6pfwm߉<8h*3_J 5x!$|\hMHyDcu\4^_PFm_ঠ?Lʆ3.:YI٨܌f@'y0u2]0^/sɣ<ݮ׿=N>vy'M Dݳ 0ѡi݄UmTu9WGSB3 *y T_[$kZNHLhyK16ͲzŲkDBʨ:Rl)\\y/b{}/)凔_U֤]*{;G4}wIXxh_O_j:Hb'IiP|%u7+  )̏ ) јSB+Y6e Ȱu䌉%Z$ږh/Lv j=;#@$%t^*@Y[_7w><X)@"wֺЛ0J+sAI W Q 1k7T~KL|(m@,+8xa7cVm|rN&T]jߧvF֬;~Ezs6Un:4W!u |Pyop0@ 4L׫~͔mmŬ TCEi H+0lL:g18\_Ci tJqIJ=qni! oXF?#.# bAZghh__lK4  *AKvþ It62>ܼB n:(U0f%KikV( s(4}C 0̶[Ltϟzb7OZ*y 4aYA[Ur{Xއ.{5_.{mT\ˠwۙ n(ƌ\'4|d5c@kXWk`ni[/Lfi"M.1Lʊm" PxgY o\sͿ]7_%\WtmQ:y8kZQ> Πy]u 5қ(Z[q4K!FT%HN >rx a` R ac i;Y/`OjN{-58s2Rf!z]OI{=;T eTR[(/Jm|,T:(PDҡ31P`OYSSya@JA' 2ИA::)CQmD"ϷQi6<|m3vF)6V(UIvwUA7_` WHO>^NrӻsJ VkXIBzDcϦ_I!NBsٝˁf[ -<Ѣ|ї | o|&1 Mb@>z*cv C ,\(q-@ .j= B{)(oQeU{l+-Ph^~90G⧦MvGĆ\rmPsS8:' VEIjk!gز坶j"9E(Ods.rq6c9qrndea3(vt(㣖zО^M~Rt&ZE'='k}tGlK-J.K?D6bNZAR dnʓ!`(qd#9d@uAqAY;>G#l@ ϋi]}/Goٚx8 J#=T$fAB-7NϿKV#dJ.s#fel%jwȡm|=-͎$i^%4 pˁ`&a|&=FT9'L!ͻƈKn_#I}3Йk+-NV^[kqΣ;pܠDZW1w!"6d˚QnE{:_1~O<{9>m /9䟒fBhv(4@ǻ|:?e)W;b.B'EAv({(1CH[`y ƷXkMtyH+%Kt^@ȁ }76|{/-6[ϟJ# {>+SJaäyͰꍩWM!Jr N0H$ݓO))(Ds_z{8BKȭ#݁;T xu0CoŃsVsZw~B'Xv+"`3||90\E$ZRCx?Zqͫg>+vqgáPdDάػ(e>Oꛒ:gE7?o@qycXo7 Vf2A83++kSώ#ԖG5.Ӧָyr*1c B75CBa{]Lk׺GR8*5 ?5 ϣCkRU~,^bav]OUYG&S@LK7~Ȗ$ l["1ᅬyQ)'%dzP\\J\VJ&-i˩bu{.MmItfykRШx<0RlV/^Bd*1֮_uljE\A)&b=HwRݒi=SQ2 1w4l#Da3rnƵѾx|63̢EPd8x j (@LJp0&Zط8m&uIݙ%A8ŊKg:khaeÉY%V3SDrG|_%ώ;EElR鿩'OIB;pI]>p Xsm<&]# 1lC-OMo OYϢmի3Ya-+9s7γOᄳPTEإ=(&Y㷽/f}@#@a۝sۭğ|Ƴ`R`<A!f[@ҩB<wsQ Zpx]_ 5~wP L8(ܒP,rr,QFǻѱ \5TUa]E!*]| `%߹Oc*:}} >wZ(GDkkf2u5a{ ]W,WqbRMƀmGz>MN"#m? .ut`CmA#amm1| \=#φw&+b2.M qv,eK<DPmBaH1z+ek XY5 a{VAG.栚PZ_4V@CNWuyB n8oCiUSRc()N>ka(@'x> B!˓ ŀo)e uܜw>z%ǬّW`tEEhg>JMSge Ϻ\^B[&[u4 :H]#摝3SYg릧$3]߀X!Ļl**V%`9rҜiXm%n >1\yu⥃ 3 P5{p%U?wwK#$uGw'XXrc7[6u/:/ŢRG74biw`R]?.g  G!iF>mi-7V&Zo2_W[E`ĭ9+F>' F(ޙAGg#Ip 7A"\_ yA|<cj?0Bvc)VehbYNd}}wգu(:~7^qy&{F>Q {4 kA?}3)VPaU}{2EAGi) FcG$O;'r,Kik/YT ':H:x4nKYU(H纺ݛuR/Zk hQRD4Hy?$4 Y8 `3k>'n>zco ώ\>l>\߸Pk)ì|Ss]YR(F 6% >)vVu@_r/D<{ (T+/6"Ä0I5ľU :)? ` &c_IcHYKwOѧRso=JZ@ז% סe6;?޽~P*sIlBiL_ 7N>cfk hĬ )?Ffd"~]Ѻ ^-|-OI"!IIĭ?ڍ[ v؁|0u? ]!NI!V\(6V ;e9r0&F~}]N=YS=/\ۦ9 ΥJ9[8 K & Tph5nඝ(8܌kƤ+j 'ă~[H7⏼/^߾k2ҍσ؎WdCay!т_0&aZZ0W]%yxmK$ҠN?>'҂8Z016|֕Hy9."{)|aO}vZ m_vC\ GLJ:X"8-]\PS8gG; 9ջs`~{ %[])DXՌiLRza Ô?vcy~79TŤ5L6YqJK 1l(XܾIđ j%ݩFAzdW̘1680ǰy?CW ni!ܫ׍jfF xWt9}Tm~t VtQ\ }5t`N{S>$a~s9ޒH`|oq1~- -DGfʕw{<+6"H5q MɀF@t^}/o3_MdwGԵ\E)&*,wU\tBq-˾?+~`jMpR\ %gXs 9\~MKzImԲMT=q*y  (<rkÆ!gk$LW_ӼVCO֙#+#O?(c Όhe%R{/ (:D9HPIq7g"=|iS_ǵ]BzY/ M- 3(HB;M||0lwib0a9z?7X gD#w_$Do/fFBA4{.…) I_ӉV:<ޖx[6e u/cqb 8Lww9>^{A p˻Ȑq;NӦAqXAI?E ۅGB 7zrJ/R~I :JIר >ov4N˗ӳg ?m4F$K.MEe;aP#:}՜ <_\=j{RCgc[p`#FEt!\ivYO 6P -w[ ;w6*VPZK MBQDGNE% .TU]mDžg{>/C_9߱k 95=SLJp 6Wb(t '1 t i~@ng X?e7mLj2[MV(sfYY->J{KQSYϡO|t^G ֻ7ZA`Y3UON&IoJGETyl<:+$`JG)::6?w'x*7М,0NUlJD5bAwON\p?f]-@.*~cjYn| g ΆR+2Lux?+2ߧӒ߃ _Gv,8hh8E;=yEi@]z/\,"~:뮻^~cf6".~` npMmm@p?p &76dz׀]Kf4(gǩʿgGP͟=|K9P\q5:pFXg\F_CYarbvŞdazJY+7D >l8tsY\NO_ޜS.ڟ31]]R]KIR>*"a1lSHя<}utg D|8㼞Kq}nUZ~N.BY yE F1Vv[z%~ **W]U1jR0".f=zV_} N0 wA=hK {8:/ǩ+>=9C6/7IݪNwب=#^r' 8\\EFqlOM46Цᔕc w%[b/0ͨo2o޼ͿǁЪzT+)k_3|:P8aYsEi!Qg- A(=mଃ{uLhߓ +`2TM c;(m߇7kͲ++[AQHH p5-z3ovƔtC|ܶ9- ;HO;AdYSsK@9s6$q4e9 ْU |?c0Y(_ՙ cw9'+_vPQyʫn"~pem+8M{o2wg7|bL^\KVnGpޙ@CQ34cص'j|]..otZ~H λ/o;gƍL%9(jZ[79N&zBk)(lbG|V1F1㧤,)vc_Eb(Q8 ^ %rEƒǤvXrSׅU@Ujhj{~~ɜ{fsߦ(Qp}`cR0PޭĩmQd  J~s=W;k< 0KvSyb eYFaa.Ř{WVXݫ n\rQ?Q !88li:[{h!mpU{ a.YuQEbaSCN7.F%p\ ш!˜q>ƃv4]^mxɥ;BiQ!M HemEvލƭ@# ^7XѽN"~E.nOM0eV4uMu cyrFe+sx8爽nx=^753VK@Qu_*P0eٷԱEhkh +7庸ʗ˩3({t!44 {fJoONp]zʻ+Y`x{+-/U҈XJC>:m 'nyN'BT`/^:{FѶ%u ~ 7M\"!"Em}v4FHUQ\7_jyz9G 9j%rT{?RgX2w bv"U/3H8ўAe Ӎ% ٭k|Ь᥂ZZl8{pKb J?Y@'Jz'`"- PVi{3ĩ,bBh^ 8nAŃH, FpCD +:7ރ!8ؗr|cMNU|o:?хpȉn@_gD8[~.*K#ㆂy hCzPaVC T lWOyh}u-~7叺>sEKrf_5HRv7 l)d/׻g?3n{!# `<@[ZPj](}"_:ީ!cE£G.P,3DvO*_!xv7?_T}&MCUZ˄Cz~ n{ T\\+ ,#[*_pqb6Lޚ<|'F`vdt='&Ø-쬪@*pBq,8 ~p.=ܕ6lzx}pȳ1vj_o4ֲc_kYF߂^[teaoXohZVy=;E|Lg42`z~U‹'W,V$+Ӏڲo`ߗ|3sk:"J2l{(۞%pDp=線="Lf)1F3c`SDDHza?_w1Ǝ2N; ]\tҏC`==lyC<Ǭ}]?aItYZ4ZZV V0h0X#52BMiWa'$pPY91_WeBWu NHWP`$h;ePK~%G;̩ʭ^>6QzL`qolKaE'в,zȓLKlGu;`u5u =Xx"κkc@<7j>'ƠG϶O" w ^;ǽb/5q>APrmTV/=x5J _*%rVr&u@T#6'-=|,M]،d=%r;K;~V#ƀ:5j@i)* VAzuBaߏ{NjIƟ@[»CoΊ](ew{"x~j"Ͻ*yw SS&ڋNڳ{eĞ}0;scnY{Vc@;pQ(v+t9̣W\8u!U.o4ZPI qCIǒ|~QG9^z{_ˈ-U3  Ptm( ,M X[K'1x\#BG!|,{"}xݬ|nY]Hx.7z,To|67ו=;4`Rϼk8 iC;8:+a#:фpA ߊͬla5h\ 57tï@->+JqqmI;ֳ)KN|kZSvĂ6=ʼn; o|;rWg@I]OxDg&4W)|Ǻ@XD0Q> Z:S.?qX‘¼\VY㵧i+xc~7f8Jyi{~#/ݏ P*8c\{m1Ie6M >=@qS#\@i!V=~*A®W ,Ə۵n(p x }X܋?79R"[qT!=j}YYP܍ ӷ=  4,'j@ J4Zix;PJzEP"qG",q(h_;w&]8BdH]ӣО4|=@*M"\(m(.$a>^Gi.F6vJclU2L8ޛ?.kRD5V$ܳЧ%zyORL`Cw]o;ƻ)/1p usIr;שqGꔣ^N2++߃Z8hcҤBoz]P`f}fϨk3a]ٿ?*;2,aix6i^WfBQ랅'v-YbBV@a3Yy#P`?=^*z˳׀vv}p3-NZ)+ .@C PPZZ?.Z(;KeuBQ?` Ab\Ȑ:Pf}  (aEQGfBQ0~-ZhcOp9 qB]W# ?YQJ6l#cx ; !;m`ђzrL.k_g'㠥ƍ6|A\2;o k"j{wܐrYYF8^Ş :B5<ŗ"X@3I:/k 1R~o-땟+(|4q|A}2|O2Y(0{Kj bҤ6+'L|j.<JJ;?2v=;pc"ޜ15.7߳N,J e޺" EQM:_Eϐ o1fZ&lypYp 5RRV\b5i7cnK:B~Ͳ2KOٳwf"ֲ ߷PXߓJ ~T7T6 )x<L[YCkPpG}p{N3/ڑG'D<gA+Z ʇ87b ¡{9_O_5 ^;X>Iο(L@ԡ LW5®Gr&Еò.< AVfL:+0m)ȧ/JtV`[^"M 䴵 V"ZX@vظiQnyWW(pŲU &"0tk 񒺮&{o^g:XIՊz=7_5-Tf%Մz_|][1w߅:4+q+JG16.m 01wvǷ%Z# .o9[JZy+UnʯQ8ս}CԝGnspv?[IhcHk@VoPisS\:'о4dA}ͣcܯ6h+ se~rPP'3=]6 q Wڈޡ6ZrXeB2W αV~k6|?𸙌*/Ox +:^; mЅyh,(>v*fTr+*^b J/0hSr'!p:71+JA1f";ڌ}w+.X|IAxI!EP;~v(fGǛoAR8ًhm$JoZNž5Y 8i#_rKo-G84lρ`JN =K>H!`shЀΖ/jeA@I)FZٕÒ60;crp0F\9nO;S A5䝖JÆ#y!r\)#ţc4' ካ^㚫l6!Y$vA2ZFcVh ǀ]!US_|7OaR &hhD>*I)Pb@Rj(1'^Hiɏ.MB3K;Mu4A4`,ϻ:9g.~ Vsq6뀕SWEؠ|+v.[J5>/u=$zkoшÞQ|p-={95~:1A1?zeGc\N;5+3ٰB0Ψ0} 2XQ /??>RPVF5װj&@c *.X?>pQ#N0 ^|:&)28Otz` N.o Ol| /7v@T^%E3K0/´P\x0 +>/t} h SR˛~u>,CD <%(v;(_ZA((KA#'OqRSУ+W\_"Tj҈F(YMOWy|7<.#t`uDC.zrѩ xwk06}6ߜOAIiJCv)Ʈd{ɋ9Y\~Iǭ ʛɊut\w);]y;PVVTyLky6|̅Baȳ= j%|(ES퉠@ 5.fa7 KkV}Ʒt۴m0|^r%\?TgͿ4d0D:ڞ՗ rl.%WEy!tΜSw6=SUe޼US~ym[@WV@ (+Dw{ gW^9"Ж߫=Zb.[P~=H/Sy e=Žkoׯ3dQGچdž7)lRh}v[Q7Df_*8J0{^< }y >.xTnpa~F{R0?|hqZWԓqyҫ_3f{?#Niq ~$t :;&mb;x(A+@Uy<(?T-R=" R %Xi)fM0m ?`=ha!iWkX$ࡻ fprn~tЂE7$H1_~٥Rd/#3) _SF #"fVj<S"PI.)t O BL$}E_Da;F*[p?fL(x?ªڶ jՙT:O'0zY"nosetSVYqXsk&p3Y&gar Г,L$Oj_ӿ?ohpӮ m=,R^Pde O^+,ﺺ:4& UUa;_w##0ƞ |?0|OIΝE~KmktFrATzYo<內Е.n4E> ?=ĪU8W_M|bvKm'0?d ǽ%ެyQkC^p:oEiGbKmO|j@ޘςeH-\ו#8-ZYaP!\𴢦jЍ?~KvK8Zӵm;F^~Ev(O@*p,wPbxLL9)d~Uܦ4xHIQ"a4 %a?聮 6/+]ѾOT`L>m>ޤ^nGeYmKD 98`*Dx:Dbdwq2YucKHMo,NU˞並*pf %-ȏJg!3e>'w;]u[(WtY窩X_硫@O<}1S^?g!U|;iu$>;r)[3l`ϻ_J!E;oba:A,LsqvϲoȞt@`EK|~}i -@g#i=?}ȯ @KnNXc]"Y6)ܹGF 3 R<;@!@:`@9T̈́80hJ,{x a஻ح#fފd7^on @nf"3YRP ~LF ұ)wF;Pҫ2%#SeJp;Kأ N ݎ6!*N_m~ͨtk-m ^~rBa*Nnŵ j*Ǻ`bPnXe{-@4wPTĖէǝ^Vg>\X=/XHsp-m?: ( *mR3)Y3 {$8WO#:4n|vhoL\{`ҡZa>>`4}NG.oV.Q[gf1)VL` x/m`hX(V8F֊6:v0&[sUx{ DNic깾O1U,oZ"淋cH#^X(zfR[uڈFOk`EݼOQ~W\ sK0nfG3!{kqiԬEӦ|PryxZjC8>T_~G>eP`cEkxDKfY;=@(/ByY7*gw B@OKiG \u"Vg= \ ZV[-7С:( F Us1_%/CY|{.Eh tl4 > [Pi'xI1v`v`bhhOvx89ꉄg"Nf /x|zyj*'X E#f?]V +V%oT KWuZ@LR[l;73a@_v5oyL$FۍD: \iq'3Jygaj>!VznZX$JE.:VCV(|=/vsbK΄t`" "{P3?"ወuSKV'Uec0'"h6tOw HNȳ$~yvL k{:me&`ick{@ك5(KϧlFu J%}Haa!k,y}FHϯ(Hv C!?o6T~5RC]",gEJr*xà'$HLaATUnja̱c(S+eY2jku,l_H^,\B]^/)SЇsV6#;I(X6_Ѯ׷m|{!퍷f؏QA}.N`>PNl=XdE}9tWF%|'VEwy<˳xh{|EZZA3]r {1瞋;P$$ E٥Eo>{Nl-~$Hƿb zȜ(%.RZ(@wuwI+KW)L[w p kIxATP>5^j(C 6 m8iƯDn(оEW%^PDŇHy` "88ä) H$:t ~׏AH$à<{Z [ŌEl^Lk/cY.CvͷLr{&|+ lsdgDč+Ǒ$8pգG *2y F``rc +KK7xR=tv9_^1y.Fs U*@{ꐃ#uFO(J8Ш{l2w^y\VJ?B:0_|1{PT :VHl=?iJJE-L6mrؠ7B(@C+ rweWhd~SZZ~ ^wP_,le7 kYg~kRg-2CV0aql+/KNyL%?Zӻek6%TDQ/bkۻO^f`2 i#Z%3O:mEr~Z#P'D;yms% :Z199j/b8#[ɂ_W.MߎOq=eH_pwz4ȭũD@y/9GŜz*f„PԶC`EZ dh8l3k ܖ=L6W[xhsahx^>$_{ۖrv0 u^C J}5ˉqU͋茀O JN ,czT,mfGD ]+S>5(śb+{/}#<|n|N?Ko|mblc@:D妼> ^Ca-lmggӁS[57I? v F~(^F_t9Owx-:{\z(N=ȣo˼wTq.1OiD"c'rIXޒxlY}r^w]1K佲+ue9yxVW2gΕh+2m|ъz0~. ,DҎfܕ|%P_/”m@XTÒtAG}?$mk(2PS.-g~֐5^A>E,^NFYxO z87dcĈ\r%456$ Ǩ/~G;\]BϞ=;n1- pf̼y}1 @]fj?^ȵ҆Ni^z{dvKjҷg_8(՛Pv4ԙ41>:lrs)xo+<\qF1#<^OS#!Ok=s鯋?*l ؞IZ?Zt$qPBU`Z Wa8 - K U$:@h6v-m;Hcve`0aŕIR+ @-|{hnj((#`E;7̤=(hM`0/ۇHVTb@VV( glɡ `ec'9az2}F#yTWz'կlݜ޸՛^ũ'vp{Z(rMRWg"xBR+A5=$nHm|8hU[fb Yg (p)ϝF/Vȍ}蛯njC -ˎW0U).[8g=}FlɗƢ2#_Dg?K"|~CV?'ur֚XU!n[[nLG`LHBF@Esَ=D7-Geܹ̿L}Ixi 3u=g},";c&:?0q %ߘ[|3*HUեߒQ:נܭ3R [͚WZS#@<@V1bps@g' uuk%@#ցE߀qȾΊ|NIHьpPM21"֟\9@a]8B8Rn Ax)K*+kZēB Zߏ/QUߵ(smr7`v6ۧndv.{~&W!77ϩ-5~PH .0,bִ%2 gma1]ttQ=؎'JY<@˰lO+WHQ% ,H'Hd?'B4@?>7$M j(Jp Y ʻK}@bGcPtLMMb02Ǎ{VێiPJ8cK{vXzmaJ4;Ź̞=f6dʿ&LqI1m&$75`-, ZֵBQz?fUVKrı7q=z_YzS+h c ݳ.5^ @ʻ0|#os$H0q")~>e ^R^,lo8i %+-|s%+ X&gd]qIi<z^8Ssgƍ$[Plf lXly0 K .Q7@Wkkf+k<8u]  ׸7$pt@ \y)|zRA~GB(pvqµ ; O59H -)hǩ˜t(i)?sX9O\9唳ePǏ B<ze *0`w)kkgF>SZ[уcG*Aԯ\{KiYCӋud| pt$,e/ǯNHgH͉LDhM+܊2aRh6gՆx;9KF݄:^#dlGoHo'oX@lH=sp5aU[ѶY:-"WbJ(OQR]΍f,@$B_pn%ЮIFfF! vϑAqU1gxhc~  .**؇ x 1VUM6C8, xpp{KџТK0!>ӣG\L]@V#r(p^U/^8v%zU0-=hIʶ:x~ݜiצ٘@DR#F`&MVUg)lb3GWcy'+bӫWr1߈>Zw;ȉ}n,nOht<ۇү?G\`x"=j] %<Γ:bw쐩`͈ϙCk18,=rl@7d@9#@pZ;]3 0 n m.țKC䐍ɒXG:NVyYmƺc+D&]0k`D=x#|V)ȿpY ٖ;S/*+P!~kp1lRi.O?F8މBjU #Oya YsѻЪQ.` 9\uRoe{kNùΣhGUI .r[(`bX~[9D;5O" w(Üv+\x1_V(R*xJϸ4(f{툁Vϧ+w=).Y]m*v1+=}hC;} `"ڲŋ0gMk#7dX޴|mKp^JξNs?Nt|Ljd-D-){ULN;c=g].M/|\եKlxe4_eQŹ* Wx<|2}=}t1W P~>_$4dSXU?#ʿ/BByܲE'rt P+(5YS8l/{2-'Fߞ4f㧟]>/L~'IyqT|Gi0(ԫ)L#AO.ezߘ},m?7RfOϊ(Eʊ, 1"@1/5kdьْa=ds1&9̹g dRU 2.1`?i$AvC7Pk{"ƷdO/lbJ<ᡗ =b)+&T\L{*-o_J(gosOoj=>|gԋmDp76Ǯy;{J`D,j]]v[r3hy8|W6 `zd^X[8ovO>cy+dՕ._Q>5f BX!7=fiTիWSXOsEYӃx[4n=?kkU0dpBa}cQ$&P#?~_:yͩK56pmKb9VMPm泱ϻT4rZt1WR"+-Wb~jNEa0xevVƂ 2xGec4M; GD(JN$Ŋ:v,(BX>`{.}p1>} aMh]} 譵![C. P ZMp6r m扱xx2"}ڧpQ" WD}zn߶˺xrroesx-3up+M\r|1_pi[u[tvK-2<%uXHryD]fߓ:56_\bVegUƖ_=M5!CH\=)`L 2oѰ!L?醴Cw݇nՌ1vlec4h!obXҾ.saGY 0]^oI]R,t&TXHO.ҐxE_jSD.`Ⱦ9*Ѽ)G*`lh[q9_XU.5%"+`ܔY, }X1`2 X=A]4Y ;3ON4VzU5TS[ɜ>R`Lj )FC8/%.yx{v&~._2OsZY Ku]+d*hIeeq,i:l(9߶̑<۸_ ;~@EE\&kMyx  S[@W߅Cv'=Wwy}qC7K/ALlo _O2QHc|nz;65i:=xnÂ9CSr ,|=?@ u)xʿ.8p`=l-kķSs=^ zCO3vkW 1Ht]{>E|km塒yf)NOa,*7wmc&@sLQ5L@uPPT0Rǁ#9pQ"RgZNٰxnP;0}caכi (sܘj _+0[n2'7r-^z{j*z`(Y># l8 *ݡ 2(+ :)Ac?@\G=t,]?a"hs>F9 AI={9SlٔO_M%d HVa0A<} ٮ.2P! @C{{g`:(JHnVTF} ?n?_+~hn(rؚH*:Hr\<|Czm# ..7+/ⰓFz}Ԗ2/eB&&;uY7  ;NM:+O{RJ1Y~e59 _zkA¬4ٚ_[^'wb !'M#qo\?VxL.IpqBHlv9!7Q$= O˧lBN"$MR c975=FoHL,=zU@SjQ9uhl%7l m-0ZEkb\^!![Xׇ5[ iN?gO-/idʎ@|m##+u,Q _TfF?{Z=ʒKm"m3ނ&斀hb4ȕך/iMg:6 -2-~R?5z4})eαڰ~QRy8'l (}/SP?"Z : kiS࿸4y9TQiw{bgLٌO׃!e^8+F`>8A*G>SrmI}lqh"Vg2nbRnp}r|ˇߐȉ )2ģֈx>zXVUDIMYSԁtHt$Ht(+X49C%r1;l?Ͽ. yRi~=4DE45 QFKeFO:Ɗ>@' qqAa씖X%TNʉӲ*k_0 X-.MA$Q`YiM6¡vB@>Eh .F1BO/Dt<:(HO.Qt6&xĕ |9X_]>;9 VN ]^< spd}i;6X^1a"IgŜ9u!b-W}BLz%:kK(J~ߘcG~ F*Sh|k ? թsIꎕ>l{Oϥw+ޠY:%^?رho_m#$V{KX>}:tYj]%@c>)5xm\kqt8f`E ݷ'{og~@H ƧaO.fφeV/XR Pȍ X€RH6(Rg`Q+fOG,Ri0}.$.fap1$e;'yG'bWv}-~:5CrC:]/qƳ hBxaլ!j%(dz w ؓrYEZSÚn`-C[AYK[CD>scOeYzo)h_hcXkXp6W͒,F!Wte}KEX=5+2Cb׽8{* ÖZ,;Ԣ#u?֧F6WQ[NHdsJ`x0,d`0 `3{F?N_w8+e@Y #wlzb1m. *$|Meau6w)-̕ >^ q_O<b:cCᶇHpW (FfDRF;V5It%uz0"{N!C,VK2#AN0;Fz9ah *v ..G~_4-Ư]-ң_ɟgrrzvT UR:G۝urwL?BZxE-Y!7+r[h_]}O< %m7@6@ǥ3ד0e^VV\Q/3 Mm-on*H;-S.ԪFt0!.] 2>|.T:ʇH0\cGG`RMm\ɓDw=>~Av;hf'0CYҘyMz<.ӡ`LB.3oHI)XH$ߞ肁[xtXeGfMwa| )U0@qZ2&tb^ 4۰p\wY ȐM1 [E>" wJ՛I/ÉGL SL|+;tOmb[@x"֭+rӔ)-#IEI{VGrrX2il<|7|3_GyQ)-dL(6bS( (zBԟql:ScWo X p2i AQL?? eٞNApvxPǀ" JkCԘP;nV˶Yk gwsN*e9 ~߲Uػp=V24aޓl|XݤXt(CAyH ȓM?Xn -1a_ 6ܶ5~v(5̡me)%Y>=7>Z gX*eSzοD6]d$BtLaƣ{k2FNC*FO* 9-D4E"7dsϥuBdu_o\.%p0*gw/OhcNCV*e!e_R=lPddBѵ3EjOK%?7q4@'ԁ `:hmhE"?}+P-gC4~;R L]q>9#cAhȗάM$=L! rGp60 ]S#\sq.怤8_`´ZVj!l;$vOݘgEwQD,:.T uGd+`[ +,AI'rQ Œk=ƹ!'}︑eH|Q@01ZON>L|#Nk8Y]U9[q֫dsK&*qء.֟F|vE34̲vcDс_A뗶7 _DHȺ# Ak[-,@klN41%'G!;yݬșJJK]<cdx]% 4>eW AWD"n>e ?4EϞOZ ]7 --Lv7bM|?y,͝xRj@Xa`y>)_Dͤ~1):LcK-b `ae{ؚO yacޤh5ly{ˀ#nTk 0fAMaE 9x 9aJj)H0drb="+TÅ3Q١]Dך๠,d:RSb 8Jb:IQI Wr|-_i߱=Ѹ _߮ ۍP@AY+0_)55WD#ي@wn&\ p-ǘVc=,Z{ oC 餪73Yn=Up93CvȬmyN.pQGEI4nZʱ͂B,Ӟ,!S0W>\|t8{]iVw621tVl8Ѡk>zqpvʮdPD[#cڷ.\KӘWvZ{׵Id흘t- Zj 3I'w_/$.]Vҥ<9+S24B~eWx:dՁ|gfN .w&VLw돜I_d08op,(uS}.āE]~%]>YGg00OǑ.j2gn@jgL'@U@ezUN2 k+;2rsv(h돻W`) fo7_CЋ0i-R!+h?Fl҃+N{h4BY,';z:oqch4epV9]5y-=#DP&njpu$km0{d4 ! oLvm<:IJ1Zx3DY4Fz{)MRΔcaSH%;` xJO%RDXeeYSc!X(aXa eu ہqu!힃;0xDW8!(: ed!)I?]h#qPYѷc.y(w0ffIc Ce<]{nً[m\w{_ X zEB@r^;/(=~2FBV'Fs>֏E~ս(:T\5I:dVC ~H$B4m4 P`.p{Z1`@L[9-3Ba 6oHtViH3ކ!){`qqwZ2W// ҡGAc%yi1 U|3aXO>ts.(g-} d^v'z(Fo +K5R).&7'ΪB!c FlUM^Bb?9TEXe@{1 ML(!;Jwǁ!J6gLrhaR*,Wg ?ON:G[5+,Uk:)u>|58Q7p1ŕYTBІBQ:U=*JP^ۨG91x}s`{^ݓwrq DșSF䧯Bl۝`bVxalM^yӀ׼ hM7<\ҲV(nѹle Cv"h3u<@-'%OYҷ.9-ݖՙ V=2x"oۓrg6Vim R= rh`#\[p4p0'0rwo\4z$7 ޽[k2r^gr_[lI:,H1bQ{ܜnzv,<wP n|}crIDhůCvaQ'BƊmp^pԯ),Jx&(=hhԇ}BdQǕ-Jĝ?_qjmwSۗo;+qx0 .smApctp޿Ofa*ܨq/pp!3\p@s0z C8НnO؊(]qxq;\xs.)g7uimWU `xi6Y\2Jy(CrU!C(UtuyPpW 䠋.mwŎϹ_q%DkN ZkQ{0GD{cА .`C{YMH@{2y=f{"iZ$_WpRPlY?ۅmsхvBLw o|2 R&|`CAHAﺢ1Im ++n++<ɞ/~F6Y*hUR HW3ci;o~:m7fIA.ϭܽ=3Vb6Z4A`8ͤX$kN8pʻqA; TB:;iǝGNO8 hvm'Ww8`&\;61?.l~ާQq-T6Zd^ڹ!yi=kS[>j0Oߊ@mre nڹ/ 9(o(Qo Qg"(XXw]_k{ïb=g#J{mD /QI8.%[ԈJ4`Wn=5{9V8jwzܘ-6w#lU}pʼfr< `9tssr j6K o{~ e >v l*XG$T,]߁6{c PP1ʲr"p` ik"'OzylϽˆ%uc);UL}W=mt6O=(֘E7q6"bf_į,оf|i-E9ĢVv%#D*ـ^%Ds6x_ԦW9.?X:㋓\塴˹C=v|[1T;KPf_="WicYpqK$M,␎ `VGc xSNbɏh'%8\[/N<KckDPA,VEgP8pb$'{f1m6ٝ.Oysh:T[J*FHdƟ~-򉗓#tn"N554v7byP@EQ\z}̯_{`n拆Ps=#7!Imnňnyr"ӻOْ˼%{y\Oz\cM].Xx7W*1׊Ҹiomqד{SW_SCyqİioP "2 {fnb6>6a|8v-'>ncIKP}D L/@≡)S|<;T6Pc06rw>8FkA ƤФ b9NQ1mOkD]q"6?w<Յ~z6,-VD }yG1yH.\)n3u&RV<:e[ ?fqq3xϊT@v(_Is-tVuC}qH8pAzr$gƟ~-r#AmA-mgK>cj4[.ʤC1q-3,opWV W|:ٱ{3ĩz*KhldZs.y)H4%.Nsycr%u+1G@4O _s;ev n(nk?s9!$b`v1G;Oy`E].;c*Iv9ҫ',#@T >Aa%hTLeu&8-!-M?O|garBDa L$p!wS~'z= U)8SAO1H9&?%‘ [#tqjLiа&Sf}Ain)Bq~JLVцۦ#C!L" j?fTlɉ{dfcaQkզ| 0-UޔFf? ȷ\euzc[(icJ@۳NN2C0y%{^3:ߊ PxϦ ~ JۏlDoƲ&+݀>Wt-mZ%>[&"W2zuqWY(c8Kcl縶ZʪuZ} ZBؐ4̵pɍ"\"]n:WxE8g.4VL ( (30֋ն1c, SaXa3tstWmP.JD֔.q@qepOI( ?ϥ&ydBxUrb2b |f=%UrsqcLbVUsF_~ ᐗm[u=6kntZE ݁+*I= lqQ ١ԁZ 4P?ֿH qn:{GV`Ckw-n,b,Ah+':3FwⰚ^WɯM۫-uwUm[)n`ǖL!mYqM#VzE2 ^|13++QX{Lw! ȵwgBP@1P&yf2Cƪma>S#E]1 \Zrxʁ|?{+[ Bk5e1@ALrоXmy( ĨCPdxb&SP?n v\5BTl-i-6ue ( m3[1tt|K e+XvZY2 ,NS+W/[fȢs4Wa u; X? 8cXf GNG)ѽ{.,֋0=ߣ!j69~K =rpIӞByN$ˡ FNj-8ѲRfnVo.[ƠZKyry%uJJ;?wɒ-ۭTĭB;_f&@=PvgY-1rRk> "5J9")wlHRJ\{I>?ro9?!//{wp/ALo 7PYķߌ %e%s;MW2PF}D~WW%|5p|%+yE2Hj`ZH8XFouKvVǟ^jUUa0s/,HU[X2Q `)%MJ.?r{`uH7ƨ+6PZؼ8F<0CTHo/vg=2YmgY0 [bAjl +)&ΙȊ5+d/}.# @v(%Ltdff;hCkH~l{8{ch{d{G)E13")=/@"E<^yE<ԩ?S<ƭZ@ڡb&IxpfYYmѠkh|5+nnBF)#Vo٠ P)@],B)ztdm"#|Cx^l@e(jhѩKK}b-?A= 'n8]-0:o|G;%$O>BbC[֞ՊHn5v0"QƅPyn^UP"S&STY%Ao\ 慆j- (sc';X@[U4((ŵ&݂AoByv({(KN Qģ9/~@s9x<. p;;u97)'y$usk=^ O^W)<;TXdf&Ÿ`1;') }Qx\aJpAXʵStR:$y ظvc9n;@6(@0%^t(䈧5l)syi8^~u },)jB/)"W]3K;S= W>zO2\Ԃ~8NV}U R)#(z>qls?CŎ샷7{ߧ;bVp֙Th1zN #k)$NMlԢ/\3MY βzy?m7X띀Qk'1D/;"ʊefa;.0bM.Z5 KI47wvLWW|AyȐ!7N3).ctz\v=:?xY{3 `mϮlyЙ,h]@16eEsP 2b`{z6FOs8*\'r-, le# 9KϽ,\c~tYC0x iӥ5%qS?5yQ` #{:asV-,][A)0hy95ѥ{F@).gv/k O}R> )&2~<Ѷ'/{j^^sE⡞)ӝ$|oXS_A (_P52i(TN1Vcmdy `E^CVWc<ĂiyI3Xs`k3hO#3?ydS\YR# @,Can!C2 )n.ziRV @B9á0JHiP`Q]5py%/mtm4bTEj X2Ūa?U½;a索JmEʏG-|}[A#tywTW. _'v[OA8 a|eE#AvgH^% lMB<<Lt'YƷ??%ZVb|zXt'?GaБuСwh }ke5e=)-PhИ" HY h"H6T{Oج">3rAR@L \@ Stp5^ÉO,˚5(,##=+:oXylCG{:Eo!P !3DY{}tu ;ߧ57SO**PkEز}cmu5nwdӟ1dsͳ'sRBڡ> Zwtd/;94{tf0@rDS (R*Yx7X6rd&LzEc!Y+1.{"td&^:9k^D㭙Pʀ 7Pmn/}.!^`76R&-K8 yl)={/zqz◳#6g?w 1nk2a)YwLPt x@Wz H.n^X?(taggZr{({tgǧ4T,M"nIo<`!Gh yl(3݁?g#Y1۾ظ})JKq5)WN+!r/zÜ9h XEŏnUߣG? @qXt,Ɲo""P(;-ڞh,3#pJ)ƪ*}( E 䖡9hc#;s_d|qW(_揝^4 yڲp?nXoCDyWERcjK{ R 98x(~Z)%tV6uF:w|@Alʪ;Ph eev( V-Br3١0~ 7??4 ^uFi߂,Z++xCv N%( &zR&Mo5QM^W&R;b@bQo_6OI{PfcL(\!Ax8F+|Ǹ|xTGS^ރN0|2}w.]].N 2+.@ZF/\J[MYC,nO-(4(KZx1$7oocɒ<71^'lJIYbUC/(CQeE l0c\e~}痳[s'ӿ'q:6eOazH8l/n%APҍ DaTb8vr>o$e KgP^Q71z1lC2 V m7"\2cQMl*F}A0 mmDX:|`!qo1fKAxiW[~΀ (Σc`~mɒ%E.PRLjr{PX9wR V[a|? >?M<^rtG<|_w1 /Z'7RGPtw*b!cP\C)?CɻF%4u07] P]0< rۈwz<ގ:.ZhCHK!x"ƭ/zo=?hZ[zr O>js!j$6'zk PŅ.u;6XFB_~@Q1̣me^HlGxKsj` 6*PR%95Գ5pX mHI {uξ}`Jyut|>*-rLfwn2ˁ& o ·`ՋyyY*1fcObZbV(&}j 4.7Neإv c<dRVZA]YV-`Y}1ϼ52n'Er ϥ BۚI)(lvל>?t,k~4qyPQ=7WHI+,~xՕ_ xh'oAŦ)LmP&q$"ϞsQ95?'?yoľ?Ѣ}xk!eFp],]YVh;LS݇~y.8;0|DE@<.cFd `c$lxO'u}/"=:cH!) DoS,j Џ^hE (4#0kހצa&PXvc'(ke z5 R׍?~ ˄  9C)Q?_"/72FaNN'x]+qCHHgc4 "WFE+?L( JgŎdgVJF|o?#m[iqE^:>*=V!PpJp:3d0uJWZظ3Д@r9C{@ gw:~PC_ǀLt3Z ![X2nf_;"0fSu!@f 2`M:\4xU'#ňC:bgZov@u4C 8@)*/+qWtGRqU q}_SN(4=cÈD^-̿իSi'x<ĕ^i@ZOaS3*\vxx\nkf3jk%$3RxSxF@ !Ind- mkA'23sO js2VZ5` o?nw8/P֊o&ppc*@+!IM{.)[e!Е@O4Kn7Й#N:N:i6{U̵ֳrK<. #KG U'~dQG2sٲnB![1 >%ʉTWqA}y>b ^iḆùH./ Bci ׍w ywIXiac{@ ˎo)(-~5v,}!⋄qikز~-biYn"|O\-tvC^i=-eeC3asC(^іT{wWƮNe"bR"rzZ7Vk6N%)V`mxR&CD-fB\xB8 m;Fei4~XyPhװ)]n%dKE쳖gA σ>M.'N F*@R'ܷ/+ПNeI/u HvVZ&lZUM bH7:$}!n?uJsWYck>=p)=@5w@}ˮ[6ؑ[觺gO=;X޳Pм3zxuaQZ*J#\u,v#rQ.C ;4*Ƿ *R{}ߣy`4]2`< >X(o<gZgBq=I\9 t@3PO8pe߱C;m8ov.;VBX!wIׂ򿓛҅\ONm-B"bm-F]K| 3oK&„q-ۗrٕrB^x›o6y1q8-6t).l% KB@ F!I,ppp(gg=fZr||զi~Njx=s*b,U,+Z^{\GK27qtD*Mۻ?jG'/mN@_޷~{;s= (V.B/w>y7̯[NϏUKnGq (/t',]熑wpKx-sNM0=w`xsyPR9+eVl,[Ay˜D1Wyq-\z#ɃëW6ʴ{'LNoS<>X=RV1~_ت<з`8aC}y\{sg>+HIoIJԹsұ ,%e,_e?f,]Z9Ҽ.eo4 7υn棏թpWt0t:ڷ.`~'5Z)+*UƯ}[gƯA-Ctd')ZAyk+*,{ɵFƣ,[8wKmaZIBmcAGgy7F.%"G`ob L_\N5I IXaf',p1;j|42, Fi AVُѧ*BA|[]Ũ7d|]s #(8<DnZ)NVaRTI()9t r6—_ƹW¦V~)]. Yp~@(!q.8 )2Ge3Iwc΄}d.s_%oWq^/E{W!8I2Jk*PqPBK +ֆ>%u73d<wpbdseST))wˈ m*Pi q Ż]sJ6S F/͌1n lڞC}K;6ozj>`?SGY:ߚ~cZ4~n?:VRr0>:~P0q%Ͻ=8v8\C *bS;ssAE|h䐧uSДL_| a[,rwqJQx(GBIL0@D4(PhQj>oYt}K4 /Aly_<8_BZWʀf,`B, D/ڤ"I0ԡP̈0p{;~g|{N[Ԁ*mGR~P`١(ֆgi6 ӧ4~kscNJvt6R+FE,]kNh0v44,&bYu.{Be)F7}CEKy5Q;w(Re/D6bAf(a?2]+w#%| g+n٧72֜55b_<;Mq@))Hjbx= v]\oiƟ1p0 C\|,ފJic{PBrs EM7^Fz nRHfCT@ &d-e\Y6 xP`';xEk .`\MUxZl5m_(9OkeNGA~|V)@7~` :_N\ hZsCa a{KĈ|e)sHiwUV4LG7`9{wWsZog De?biE0x󷁎ɄVAYy Pu@Ӯ$t20c`FV5Zp4K(uffB a[X2JiKOn?NnI>=%`eN("Su3"{:#\V-S˖Ӗ )j{? =HemSM/ZRFBY:spm\6҈P:GగZ2/]U_KKkC}\z6!AaмuW3~,ǁ1kͿ@˺߼zoMF䴂 Oi0NՅ@( .9ZJ-ZSC˟+NPPtA No2' Њ:p|j 1 20VOynKJHbO~spV!+rCVg(WLc% es_sb+o([w^$fφvt_\Q'|f,h]z-C}F{7yg;XE)c.z| ɩ6λm,_ R6ߕ߇0_8 цKnKҲCS1j"0=LpnʴoL`pP~ZIR d1ɖdA)+\ъB~5mDcK~;ױ_ 8?jUANYb<k 'ro~];3 O .{ U#S;(^I;ӽ57&b|/-Cen\EG:b ID"O;K.bh5Uih>CV_p9+hNJAEeuZӖf}9Ø)Rc(Dړr./-KjțSNl8-T;%[F+o,j3ՀZ2m@:,v&[I |=+;t}QSGӫ8TWȑJo&Diʩg}a03%i/]Lȫ\><2z̾]bDoPݳyq7SWh~YrN:^}Lu@ۢ K7o"F?n0w~Or+.ɂ%&һ {=lɯ#o2!.t)#_\z)PѬ]twGf=<<<>~ 2"Ң#6-:'bs`2y#:tCVw6Vb6 @[k/*_p>g]Ǽa eH +E5$ѯ^ N^4W({UZĜx"͓ObΕXsA޽0o#-lPMyh m^E鬷!#6,^{[0 SsŧcXv/Ƹ|TNJa@8 f tj]QRȔ)݄ 4FP^C#>Hϗ `1$<4 >^1;#i5>}CBa(? KAqw+W<6 ˳cCxݍt~}]3͖G h*1i۠%4nDùTBpڗ]Peڱ;"$yNh^|@Wz=q)4LG?1,LKP_3ŋ{(%ݳO~a,Y=Jݷo1 peѨOW(_lg<{-T`ARZW[0]pMV(#=2/FEEo8/bI9{GNϰP9hks~h_)l|*:r91#C=#/𣄮t by; ^`Fykz^31w o[r%YQqF!e:5Hz`>cʮ? V^@ݛo}aD"\u,2_/?vZ':2X/ӵ@Aw/{e4͒Ue ~_xq=xheTΫઠO1b zlrq =IkϢ ףSص2ůgyzsXP`1{c>sŘ>CFe!6UCxux'x|LE).:aT`%+]~-0ʀTķ W>/ڟ/5 u߈3dX߿ JsL:ma|].+@v1)l0.o4jg^cgqn'!@"=@ke N@U} @@<%B%=8nss/w=hk_^N/S[`M؋< ZPW_9-K8d5,Y `UW{Pd> Z@yY[ҷbm\y{8H ozmv@;f\Z[$.śo͖S#{# ·!U[W_L!Q4e1DB}x-MGNG\+PQBRY<j"xi@ ea 4)6#N|y8$:XtRkjj,Az ݍQ [p0Zq]-OYV|l@z}?W~J8=%b| Z؏ 'cG:h@^zTo76^?|0f6!}q2~Y(6g)<]cE+,L{o!tai J.ZPܯ:|ˊlBStStw=v W1fiHWW@oMv+z3ű=k =t܊s۲ښjy+*0 #~f;+G }"Mi<ˀն2|a:0vxq.poA^ m~4ű>T \+ZBU[_uJ&PR$4tি}P_JNVt6R ؓyM \xNkkɂ4ee! E,ml&b zI)p1ZI:'} >&pGQ.(g@jv(tP''+uww ZeE*c}q2sⱱwvϙ#)y2ӯmNcD?w,ƕ4=x#-h($`$*{]ɆVr=?K/Y34t֍S[@G>#?hJʊܷn5f :WJer%}AY<BwD+kweySr}~PӃJ_g#0ob +.7܀g m˓q[̝;W2O>⋿o$x:(cY<l e}`sT 2_y ۮ.zDEPwXiVkF*k|d*(^|dZdx4 z)T*Lrˍ~`)&%n߮{_)O/+2fvߢ?_ְLjy57`=ӌ2] <-~g8fg߄8vGK9](5hw?ĢR^Z؍4Ɩo<s~IOmmW]u7n!C*Y38 |KkAQ6A C [r%5?$mntFF2]Jq 3Fǻ0F.yoV_YˎN<_,d9$io㐚U'Ղܴ *p?Fmr,\e4^{֘?Ǵ;|~#WϟO}}=_x!Qq'@";z4NG$uXL7u#^`='l12gO8~իeQcક[fYe} eLIVX]qM ,cmď_tڕWSw O#֩xFɟwǯ+кmNX*9OxNxώo/Jq`M BG;r2PD(4:) }<Ս [eptF$GSSW1em\<_#F H!u%C7 5<{qrd8[-wrTy)tluuBHCI,KZ$Lf >,~ܹDܖv.b%t!vLiID-@ܨw` se5]:0L8%7Ǐ8naN/¨{/$W^^{xchUww_1딸Iyg3xB.956Dk-xBwB+wߟ*ӧ~.qkD#r9,ݎzlxP&vM{`V<Ml 8 xj,i[qA1ޡk䐿ϕ-I {Yt$%fΗ_xë {U{+<~wӆee}>#t 3Sz/fu-$ 0W3xnDҕT>S) X÷+~JZ~Ӎ?aԇY,\! 7ʆCv`4* >q<.11`WL{)>`?,M=/<mǩ}6 5bBײjjfr?##,Qڬ@dpsϥhPL(nᚉ1Æa:;1V=rm矙spM13Zi+;XVa5ue1V<5ZE'VASB` A Ƙ :eWfnzJ tC4\>[1#x|?\Hg\y@,I)矯#/Of1$÷ߎ#.+͙!9>bZbv>Imt+ 'ڿMzo+_ C’2Ei(}rPFx{Ku9$3[(Kۙ4i?#\|T>6ӕ;z]LdXRKT"9KTć W>+=u)P_9^Ǻ?`NxԖ)(xOxBͩ{}L% <V&Le^?\?<:eϽcP*Vϳ|}qȑhwi2/n^n?WDz@M)vߢLK iI}gZ0A 0?? ,9r'W\>;\];?A bK4Tn"{SL"mZ`V5|;g:UDmLzR_ؼ8eE8(*7&.Ya1W6NB?BcǶbgYOs ;y"oއI:(,$LOi xK_)ƉX+hwPƴ˖-1m< 3dA IpDXgxϕ\;oɰ&W^ɓwށ4o.+x+1}K~1 }sr~إ; M|>eB(:~hqž.+ry`@o.3pB>]#7Mׁ\"Y`طN d>Bཋd~<-#o<۽{4`Ӏ4" ,i7d͵/, 6;(ޖVۺ;Ӈ%DB$꼣=6.݈v ڥR\ X8lS>}(͋p r*h`{+)ԢNJ-i]%wSX8jGb^x +q9ySP7X즮t0p=Ë)ou"l)4P8DegJsc)Js^ G,U3aHPf"PtC[(cZW^6_9ىd1`::Ho z5^K/ϓF _y%NWfߗh)s'rS\~?pPU|:Ԡr]?cc*hkSa \@+Xio'ǰPxkI-Ȼ[RQ/lG38Æ~Z?bti Z^q55 ”&eT5ם ? K>|W\B]q V+-:xљoEfq[Gq7Ѽpe5%hCyJ#}8hOr8x̄ 򝈼oKemX369lBʲj+%4W(ŷtpG6.a<\[E wW(#u\6ݚ{ߦ8ǮTLZ2 y/+vV2gܸWo.J.4(`%;Q"s>x[97c;yJKaU7oK*r4OZ߸m@IYGOtrɷz44z.]9o3r2׈`1Aa5/pX 8>!r$?4ʫm*EB)1DRbz1b$zmg }:NxhiHxt+1~>+#gL 6B{@ڊ&8DRs2HYz*7+1'MBWT@I:ï3cgxCۃ\z\mQ?g8ւS/ҽ߿`8tEnn 55;mr}v>SVoL~ +JcEݮAm}^mI~ ~ [n%#dR'O0fw33w[H*a3D)xX&#7Qx/\{ަ@ 4oIPp6|z闰P`aJg\ ({zpw?N.ΜW^u8pJ12B5@q@m-pH kZV|:CijYvPR\|u:/+Qر3_}{ns."r fDk ՁjH#=)1f h7>?q]‰ɻw{\f^DQ֏5I 6?T ʼu[g+t3o@S+@fߣdhnm$dK@e)?^F Mgnf,P6(b7-exW ę^"` z61B(C`̹?t40`}Y4f *!<ϒb7I0egreuN?\PZ74(˛;?ڮg~񦕊e,\hZ߸!NzǬxHVx9 ~p&p8(ƛIL#T|1nDKNGu 8*:fŪ\XI'([(͋.3|&"<@s= :.é|~#;x(Ѳr՛^ mrU2,zk 8Aѣm?-د`Ĉ:~u) K V? nt%@䙕J狖9?CAq 'w. eVF"g- 2a"M6?s BGKBsH*}㣍ep:Z,U }-AMP<56[Q"K<|c=xɷ@H2^0 $n<;,> n]Ut#ԯ`ȺXu7)Jt7y7IkkC4i ~Rx^gK_n?Usc1q#1Bʻ"'/4hcdi6NSZZJN<& a|Vt0.l 4I#~fw?oM?q"?YE;O{D]゚*y_&|oOSM 9.&5rsE4aop]喍Y|ʫyX}p}Pn71plM^|cee3YI}t%eSbʒrJv(,QiQQpuXF%h)bI}5fcd1{&]S.ѥ+ѻSSG_S9䰆fFqz]y%.%C/gCdI#G-t1gNx %:lPVA(FLgZ֬0h yZA[mٓ93 M6nc{>+vEy,'-_4~:0s_>>I]#?88.M㥳6 ȵӏ~5ۻ7LNԽ.~R ~..b٪pZ})7>FLىĢiVkBkJ)̍br1'u[v(q}:]o`Kn-_u>rij(+b0|`.9Z9N9,k#-؅P&sλnJ%k/]Śf-6R|Ñqնw0'+>9Svb 7Fr f5BN(̪ɻI7|-!ޕJ]WK_}|E 6 g*?b"%ZPtĞRY~g#cx!afI8H)^}g3b,JDNT4^p㬧P;N۫~;"/}Kk=lKcB'GF1"G݃ycϡi9%S/~M٪ 0\/ aI&)o7Cip˖2~8$.QJ(H(&F瘺gs]8l9Ob1#'UOnZc͠AhDP})sO 6`={X8nė2یxKy?|qna\.@?{;l][{n T@:||?`k B!g2zYרr÷9P-M7 ͼ| 1xI ZkB]xz#$ۆ#R)١R!lԹIȄwb#Oz%ƯӸM8|uXTO=SLgi]t|rt.(P], u'e˘}yId PoիYpa+zR* 'e p(,xCɗ`yo,aX\`eV_|P9xn7}q=܌X(#PhFg^n)=0I$9:Ph8 U )(eaه+^R,3&=-naqj^y9u  1TiҴa7f]÷û  )b6҇iJpY(e%:`*n @mAߏ֖VJJ'7dZȆC7$~pCa[őeJ7?BL>[ҵ>Bl^YP"N,A)X 3c.zr^_Xעm^v9I2NVɬ_ a#Gq0y餚Y]X3XguVZЕLvs ܴPrb"PRҠOo zn=7>y5+Mz͵-ybu!Oʁc4b1}k‰@GFu#a / p6pfIENDB`inc/images/index.html000060400000000046147177152050010564 0ustar00 inc/images/mainlogo.png000060400000020273147177152050011106 0ustar00PNG  IHDR "PLTELiq"""""""""""""""%"""""""""""""""""""""%""""""%"""%%%%%%%%%%$%%$%$~$%$~~%$%%$%%%%$$$%%$~$%%%%%%$$$~~%$}}%%$z{%$z{$$%$xz$%$$%%%$$%$$%$$~~%%%$z{%$%$$${|%$$y{$%%%$$$$%$$$$~}$~~$x{%$$%$$%$$%%$$$$$%$}}%$$wz$$$%$vy$$~"""%$$$$$$$$$$$$$$$%$%%%$$%%%$%$$%%%$%%%%%%%%%%%$$$$$$$$$%%$$~%%%%$~%$~~%%%${|$$}}%%%%%%%$$||$$y{$xzԑatRNS `@Р0p@P `p0P  @@ @0p0@@p``@`PPࠀ࠰`P0ЀpPP```аphȅή pHYs%%IR$IDATxS33 I3AAf{w}v<όf2t+د"$'99e'IIݫJ       Bol!5ncNΘV؉Ch^&t?IДo :Ma- (d=@)c$t R(Y%tqc0)Ah &?$4,:Ji`NhcgmY^1=΁3r2w#C?iڸ<.C?pppǒ1c-0WzACm:u%lʱDD{Q.ZKvMFzWpى> u$t$<S S~~E 9:J`=v=/zg ɝ4ib`zxb8~40ӫe55d,$#GKX :@1~]᫞siXM~Mz%$v`LCf 1t"Y1C_B@܅A7<ԳLC)vLÇj0 gq_iv@_XbnغI(bx駟zhJcU,~=a} Zj/Nv2#Y+B. 1K3X)w~CZWe/05 ɼ7!J1g0y (L hAo'_ DC4P 3`O;Ʀ0Т%ŵ >\J9@ o[۪opRĐjb 9¸wPOͼ10; CvQy=Cv|ֺuL Hx{pY4%J.b@g,V>I00z#`Z/1u)9E1 9ozuok18e|1 A m.0dx-ZG" F "¸KˎcRW T>aE z[%]u1/ҡJR^&;t[tzځÄ"*gLh5Rm1J)襵^$Qb3rrb1`*C!XW/ >YTIp@uf}sLDj/|4!Ljf z$J \#4NV5tђ1@Se1P̽^S抡`jy~ɕ|VĠ8ʢG@n#M"Єb(w-?+KW-]U4g"s* 4h1O-ATWP4 pz5`5&ŐPDǢb XBS\&5U?^N@+:˕TW !mK$J p:S }-ϼh _rD gQ?bϵ(: Q~FĀx_+^z%IbN }aHwJ)?)Ӡnwq$&bO0^1E Rp 1 X`"tpL{*#C {G JOzW 2hj$-=*Ԍ5hg`i1|cU ]N8XpaY =0P^tLjd݉=/L1eGi] bIFb(JxqIQ \9?C ixgҺRJŐJ饐Fh=wR#Z[-O!p Ql/NF%'ႏgAU{xĀ:14G eӰ͗^8z5tb ~f\:|Rt1 {8\?ʦ^hp18 _ vKh 1/?&f4fW?KzLJW{1}xd'~p56_YbzgMBi1W߯Āچ6^iLL|E/}@r֘%gCeM=0|x5tbmՅq[C G;߼07 ~1:]b[k3!rŁE<>] 9_6m}k.8S"#F1 ~AP Xglγ^ş~J?@֫EĞemh/4$`F8ߝYGOB֙!2ͰH3E_NS0p\&f Ma={>>=`^q! 3,J7H5 |W;+.. +d׸b|cu"lg Vm@[~|{b[;xOŀy!9uV⮍Bn(kb,[MLPn軏*7cp_ex{L1Z`;N1@H l)"N^ѭy&hpt.]z᝛/9bӻ9_ t (b a hu$$KhXШ+ wG8(b<S E_fsOrPZC>U3ET 䝝Pq^ bA‰P-Rl`;M}W5aOUxF~p"BN2ބW^vP MY-ȓWL|7n:>3X9bEF<=W~}fօx@yU7ܩK%ԢcL; 3H߬=|48jܽ*lW1+2L}<+.S?p{}tk=zMSn|;ru`nO9TXKK # u*c>b +цz/%cқsȳҠoҚm3yEa,*]3M6 5p`iŐ%5hnsf A^@ 0}-'z_ mrM&QgY0`&o Yә{>tL?UCHm .A1 3 4c`._hG 3  cS)HpfSc%Z4g,71\Y9-ܖ4 Պ48c;4}iXQ1L`,!CՃeաVc\K ZY⎥QSSݻiW_W1%Kvlc>11 5޲@AD3K",D ˶a)Z:ls+YVpE{+K>W_W1K94J-XPٖJ"wP6\G޷\2|-ɜ.¯K=ߕdۂ V}p9G[^ 혆[iӫуھLU.nufɹƥj[ЍCkW'Z "~ P]PrUQXA0̋p4W Cӫ;cxz5C;&13~옆WU14`&F0ӫ[_/ZpjWwӫtTAXK~M%[Pfn^}ߛ^W+ңŬuӫ+$XqUN N^#Dғ^(_# AH(wp `Ӱ˛^zh#e 2K'LYB"iXJs!%`MTWo9Kց̺nW=\ց0B!t        BsJ6b"թIENDB`inc/images/pluginlogo.png000060400000020273147177152050011460 0ustar00PNG  IHDR "PLTELiq"""""""""""""""%"""""""""""""""""""""%""""""%"""%%%%%%%%%%$%%$%$~$%$~~%$%%$%%%%$$$%%$~$%%%%%%$$$~~%$}}%%$z{%$z{$$%$xz$%$$%%%$$%$$%$$~~%%%$z{%$%$$${|%$$y{$%%%$$$$%$$$$~}$~~$x{%$$%$$%$$%%$$$$$%$}}%$$wz$$$%$vy$$~"""%$$$$$$$$$$$$$$$%$%%%$$%%%$%$$%%%$%%%%%%%%%%%$$$$$$$$$%%$$~%%%%$~%$~~%%%${|$$}}%%%%%%%$$||$$y{$xzԑatRNS `@Р0p@P `p0P  @@ @0p0@@p``@`PPࠀ࠰`P0ЀpPP```аphȅή pHYs%%IR$IDATxS33 I3AAf{w}v<όf2t+د"$'99e'IIݫJ       Bol!5ncNΘV؉Ch^&t?IДo :Ma- (d=@)c$t R(Y%tqc0)Ah &?$4,:Ji`NhcgmY^1=΁3r2w#C?iڸ<.C?pppǒ1c-0WzACm:u%lʱDD{Q.ZKvMFzWpى> u$t$<S S~~E 9:J`=v=/zg ɝ4ib`zxb8~40ӫe55d,$#GKX :@1~]᫞siXM~Mz%$v`LCf 1t"Y1C_B@܅A7<ԳLC)vLÇj0 gq_iv@_XbnغI(bx駟zhJcU,~=a} Zj/Nv2#Y+B. 1K3X)w~CZWe/05 ɼ7!J1g0y (L hAo'_ DC4P 3`O;Ʀ0Т%ŵ >\J9@ o[۪opRĐjb 9¸wPOͼ10; CvQy=Cv|ֺuL Hx{pY4%J.b@g,V>I00z#`Z/1u)9E1 9ozuok18e|1 A m.0dx-ZG" F "¸KˎcRW T>aE z[%]u1/ҡJR^&;t[tzځÄ"*gLh5Rm1J)襵^$Qb3rrb1`*C!XW/ >YTIp@uf}sLDj/|4!Ljf z$J \#4NV5tђ1@Se1P̽^S抡`jy~ɕ|VĠ8ʢG@n#M"Єb(w-?+KW-]U4g"s* 4h1O-ATWP4 pz5`5&ŐPDǢb XBS\&5U?^N@+:˕TW !mK$J p:S }-ϼh _rD gQ?bϵ(: Q~FĀx_+^z%IbN }aHwJ)?)Ӡnwq$&bO0^1E Rp 1 X`"tpL{*#C {G JOzW 2hj$-=*Ԍ5hg`i1|cU ]N8XpaY =0P^tLjd݉=/L1eGi] bIFb(JxqIQ \9?C ixgҺRJŐJ饐Fh=wR#Z[-O!p Ql/NF%'ႏgAU{xĀ:14G eӰ͗^8z5tb ~f\:|Rt1 {8\?ʦ^hp18 _ vKh 1/?&f4fW?KzLJW{1}xd'~p56_YbzgMBi1W߯Āچ6^iLL|E/}@r֘%gCeM=0|x5tbmՅq[C G;߼07 ~1:]b[k3!rŁE<>] 9_6m}k.8S"#F1 ~AP Xglγ^ş~J?@֫EĞemh/4$`F8ߝYGOB֙!2ͰH3E_NS0p\&f Ma={>>=`^q! 3,J7H5 |W;+.. +d׸b|cu"lg Vm@[~|{b[;xOŀy!9uV⮍Bn(kb,[MLPn軏*7cp_ex{L1Z`;N1@H l)"N^ѭy&hpt.]z᝛/9bӻ9_ t (b a hu$$KhXШ+ wG8(b<S E_fsOrPZC>U3ET 䝝Pq^ bA‰P-Rl`;M}W5aOUxF~p"BN2ބW^vP MY-ȓWL|7n:>3X9bEF<=W~}fօx@yU7ܩK%ԢcL; 3H߬=|48jܽ*lW1+2L}<+.S?p{}tk=zMSn|;ru`nO9TXKK # u*c>b +цz/%cқsȳҠoҚm3yEa,*]3M6 5p`iŐ%5hnsf A^@ 0}-'z_ mrM&QgY0`&o Yә{>tL?UCHm .A1 3 4c`._hG 3  cS)HpfSc%Z4g,71\Y9-ܖ4 Պ48c;4}iXQ1L`,!CՃeաVc\K ZY⎥QSSݻiW_W1%Kvlc>11 5޲@AD3K",D ˶a)Z:ls+YVpE{+K>W_W1K94J-XPٖJ"wP6\G޷\2|-ɜ.¯K=ߕdۂ V}p9G[^ 혆[iӫуھLU.nufɹƥj[ЍCkW'Z "~ P]PrUQXA0̋p4W Cӫ;cxz5C;&13~옆WU14`&F0ӫ[_/ZpjWwӫtTAXK~M%[Pfn^}ߛ^W+ңŬuӫ+$XqUN N^#Dғ^(_# AH(wp `Ӱ˛^zh#e 2K'LYB"iXJs!%`MTWo9Kց̺nW=\ց0B!t        BsJ6b"թIENDB`inc/js/index.html000060400000000046147177152050007733 0ustar00 inc/js/scripts.js000060400000012313147177152050007763 0ustar00/* global jQuery */ /* jshint ignore:start */ function sucuriscanAlertClose(id) { var element = document.getElementById('sucuriscan-alert-' + id); element.parentNode.removeChild(element); } /* jshint ignore:end */ jQuery(document).ready(function($) { $('.sucuriscan-container').on('click', '.sucuriscan-modal-button', function(event) { event.preventDefault(); var modalid = $(this).data('modalid'); $('div.' + modalid + '-modal').removeClass('sucuriscan-hidden'); }); $('.sucuriscan-container').on('click', '.sucuriscan-overlay, .sucuriscan-modal-close', function(event) { event.preventDefault(); $('.sucuriscan-overlay').addClass('sucuriscan-hidden'); $('.sucuriscan-modal').addClass('sucuriscan-hidden'); }); $('.sucuriscan-container').on('click', '.sucuriscan-show-more', function(event) { event.preventDefault(); var button = $(this); var target = button.attr('data-target'); var status = button.attr('data-status'); if (status === 'more') { button.attr('data-status', 'less'); $(target).removeClass('sucuriscan-hidden'); button.find('.sucuriscan-show-more-title').html('Show Less Info'); } else { button.attr('data-status', 'more'); $(target).addClass('sucuriscan-hidden'); button.find('.sucuriscan-show-more-title').html('Show More Info'); } }); if ($('.sucuriscan-tabs').length) { var hiddenState = 'sucuriscan-hidden'; var visibleState = 'sucuriscan-visible'; var activeState = 'sucuriscan-tab-active'; var locationHash = location.href.split('#')[1]; $('.sucuriscan-container').on('click', '.sucuriscan-tabs-buttons a', function(event) { event.preventDefault(); var button = $(this); var uniqueid = button.attr('href').split('#')[1]; if (!uniqueid) { return; } var container = $('.sucuriscan-tabs-containers > #sucuriscan-tabs-' + uniqueid); if (!container.length) { return; } var rawurl = location.href.replace(location.hash, ''); var newurl = rawurl + '#' + uniqueid; window.history.pushState({}, document.title, newurl); $('.sucuriscan-tabs-buttons a').removeClass(activeState); $('.sucuriscan-tabs-containers > div').addClass(hiddenState); button.addClass(activeState); container.addClass(visibleState); container.removeClass(hiddenState); }); $('.sucuriscan-tabs-containers > div').addClass(hiddenState); if (locationHash !== undefined) { $('.sucuriscan-tabs-buttons a').each(function(e, button) { var buttonHash = $(button) .attr('href') .split('#')[1]; if (buttonHash === locationHash) { $(button).trigger('click'); } }); } else { $('.sucuriscan-tabs-buttons li:first-child a').trigger('click'); } } $('.sucuriscan-container').on('mouseover', '.sucuriscan-tooltip', function() { var element = $(this); var content = element.attr('content'); if (!content) { return; } /* create instance of tooltip container */ var tooltip = $('

', { class: 'sucuriscan-tooltip-object' }); if (element.attr('tooltip-width')) { var customWidth = element.attr('tooltip-width'); tooltip.css('width', customWidth); } /* interpret HTML code as is; careful with XSS */ if (element.attr('tooltip-html') === 'true') { tooltip.html(content); } else { tooltip.text(content); } element.append(tooltip); var arrowHeight = 10; /* border width */ var tooltipHeight = tooltip.outerHeight(); tooltip.css('top', (tooltipHeight + arrowHeight) * -1); var elementWidth = element.outerWidth(); var tooltipWidth = tooltip.outerWidth(); if (elementWidth === tooltipWidth) { tooltip.css('left', 0); } else if (elementWidth > tooltipWidth) { tooltip.css('left', (elementWidth - tooltipWidth) / 2); } else if (elementWidth < tooltipWidth) { tooltip.css('left', (tooltipWidth - elementWidth) / 2 * -1); } }); $('.sucuriscan-container').on('mouseout', '.sucuriscan-tooltip', function() { $(this) .find('.sucuriscan-tooltip-object') .remove(); }); $('.sucuriscan-container').on('click', 'button.sucuriscan-show-section', function(event) { event.preventDefault(); var button = $(this); var current = button.text(); var onText = button.attr('on'); var offText = button.attr('off'); var section = button.attr('section'); if (current === onText) { $('#' + section).removeClass('sucuriscan-hidden'); button.html(offText); } else { $('#' + section).addClass('sucuriscan-hidden'); button.html(onText); } }); }); inc/tpl/auditlogs-filter.snippet.tpl000060400000000204147177152050013575 0ustar00inc/tpl/auditlogs-filters.snippet.tpl000060400000000625147177152050013767 0ustar00
%%%SUCURI.AuditLog.Filters%%%
inc/tpl/auditlogs.html.tpl000060400000023135147177152050011604 0ustar00
inc/tpl/auditlogs.snippet.tpl000060400000003275147177152050012325 0ustar00 %%%SUCURI.AuditLog.Date%%%
%%SUCURI.AuditLog.Time%%
%%SUCURI.AuditLog.Username%% %%SUCURI.AuditLog.Message%%
%%%SUCURI.AuditLog.Extra%%%
IP: %%SUCURI.AuditLog.Address%%
inc/tpl/base.html.tpl000060400000004521147177152050010521 0ustar00

%%%SUCURI.GenerateAPIKey.Modal%%%
%%%SUCURI.PageContent%%%
inc/tpl/dashboard.html.tpl000060400000006610147177152050011537 0ustar00 %%%SUCURI.Integrity%%%
%%%SUCURI.AuditLogs%%%
%%%SUCURI.SiteCheck.iFramesContent%%%
%%%SUCURI.SiteCheck.ScriptsContent%%%
%%%SUCURI.SiteCheck.Malware%%% %%%SUCURI.SiteCheck.Blocklist%%% %%%SUCURI.SiteCheck.Recommendations%%% %%%SUCURI.WordPress.Recommendations%%%
inc/tpl/firewall-auditlogs.html.tpl000060400000006426147177152050013413 0ustar00

{{Firewall Audit Logs}}

{{The firewall logs every request involved in an attack and separates them from the legitimate requests. You can analyze the data from the latest entries in the logs using this tool and take action either enabling the advanced features of the IDS (Intrusion Detection System) from the Firewall Dashboard and/or blocking IP addresses and URL paths directly from the Firewall Audit Trails page.}}

{{Non-blocked requests are hidden from the logs, this is intentional.}}

{{Firewall Audit Logs}}
{{Loading...}}
inc/tpl/firewall-auditlogs.snippet.tpl000060400000003727147177152050014132 0ustar00
%%SUCURI.AccessLog.RemoteAddr%% (%%SUCURI.AccessLog.RequestCountryName%%)
{{Date/Time:}} %%SUCURI.AccessLog.RequestDate%% %%SUCURI.AccessLog.RequestTime%% %%SUCURI.AccessLog.RequestTimezone%%
{{Signature:}} %%SUCURI.AccessLog.SucuriBlockCode%% (%%SUCURI.AccessLog.SucuriBlockReason%%)
{{Request:}} %%SUCURI.AccessLog.HttpProtocol%% %%SUCURI.AccessLog.RequestMethod%% %%SUCURI.AccessLog.HttpStatus%% %%SUCURI.AccessLog.HttpStatusTitle%%
{{U-Agent:}} %%SUCURI.AccessLog.HttpUserAgent%%
{{Target:}} %%SUCURI.AccessLog.ResourcePath%%
{{Referer:}} %%SUCURI.AccessLog.HttpReferer%%
inc/tpl/firewall-clearcache.html.tpl000060400000014614147177152050013470 0ustar00

{{Clear Cache}}

{{The firewall offers multiple options to configure the cache level applied to your website. You can either enable the full cache which is the recommended setting, or you can set the cache level to minimal which will keep the pages static for a couple of minutes, or force the usage of the website headers (only for advanced users), or in extreme cases where you do not need the cache you can simply disable it. Find more information about it in the Sucuri Knowledge Base website.}}

{{Note that the firewall has special caching rules for Images, CSS, PDF, TXT, JavaScript, media files and a few more extensions that are stored on our edge. The only way to flush the cache for these files is by clearing the firewall’s cache completely (for the whole website). Due to our caching of JavaScript and CSS files, often, as is best practice, the use of versioning during development will ensure updates going live as expected. This is done by adding a query string such as ?ver=1.2.3 and incrementing on each update.}}

{{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. — WikiPedia - Web Cache}}

Clear Cache by Path

This option allows you to clear the cache for an individual page, post, or other path. Enter the URL you wish to clear and then click the Clear Cache button.

This functionality will not clear static content. (i.e. .jpg or .css)

Clear Cache Globally

This option allows you to purge all of your page and files cache at once.

You can select the checkbox below to clear your website cache globally every time a save is made on your WordPress website.

inc/tpl/firewall.html.tpl000060400000001754147177152050011421 0ustar00
%%%SUCURI.Firewall.Settings%%%
%%%SUCURI.Firewall.AuditLogs%%%
%%%SUCURI.Firewall.IPAccess%%%
%%%SUCURI.Firewall.ClearCache%%%
inc/tpl/firewall-ipaccess.html.tpl000060400000010456147177152050013210 0ustar00

{{IP Address Access}}

{{This tool allows you to add one or more IP addresses to the blocklist and stop them from accessing your website.}}

{{To delete an IP from the blocklist you can use the form below or you can log into the Firewall dashboard.}}

{{IP Address}}  
{{Loading...}}
inc/tpl/firewall-settings.html.tpl000060400000014057147177152050013257 0ustar00

{{Firewall Settings}}

{{A powerful Web Application Firewall and Intrusion Detection System for any WordPress user and many other platforms. This page will help you to configure and monitor your site through the Sucuri Firewall. Once enabled, our firewall will act as a shield, protecting your site from attacks and preventing malware infections and reinfections. It will block SQL injection attempts, brute force attacks, XSS, RFI, backdoors and many other threats against your site.}}

{{Add your Firewall API key in the form below to start communicating with the firewall API service.}}

{{Firewall API Key:}} *******************************************************
Options

{{Name}} {{Value}}
{{Loading...}}

{{[1] More information about the Sucuri Firewall, features and pricing.
[2] Instructions and videos in the official Knowledge Base site.
[3] Sign up for a new account and start protecting your site.}}

inc/tpl/index.html000060400000000046147177152050010116 0ustar00 inc/tpl/integrity-correct.html.tpl000060400000002416147177152050013265 0ustar00

{{WordPress Integrity}}

{{We inspect your WordPress installation and look for modifications on the core files as provided by WordPress.org. Files located in the root directory, wp-admin and wp-includes will be compared against the files distributed with v%%SUCURI.WordPressVersion%%; all files with inconsistencies will be listed here. Any changes might indicate a hack.}}

{{All Core WordPress Files Are Correct}}

{{We have not identified additional files, deleted files, or relevant changes to the core files in your WordPress installation. If you are experiencing other malware issues, please use a Server Side Scanner.}}

{{Review False Positives}}

%%%SUCURI.SiteCheck.Details%%%
inc/tpl/integrity-diff-utility.html.tpl000060400000003224147177152050014233 0ustar00
%%%SUCURI.DiffUtility.Modal%%%
inc/tpl/integrity.html.tpl000060400000006110147177152050011621 0ustar00

{{WordPress Integrity}}

{{We inspect your WordPress installation and look for modifications on the core files as provided by WordPress.org. Files located in the root directory, wp-admin and wp-includes will be compared against the files distributed with v%%SUCURI.WordPressVersion%%; all files with inconsistencies will be listed here. Any changes might indicate a hack.}}

{{Loading...}}

inc/tpl/integrity-incorrect.html.tpl000060400000025227147177152050013621 0ustar00

{{WordPress Integrity}}

{{We inspect your WordPress installation and look for modifications on the core files as provided by WordPress.org. Files located in the root directory, wp-admin and wp-includes will be compared against the files distributed with v%%SUCURI.WordPressVersion%%; all files with inconsistencies will be listed here. Any changes might indicate a hack.}}

{{Core WordPress Files Were Modified}}

{{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 Server Side Scanner.}}

{{Review False Positives}}

%%%SUCURI.SiteCheck.Details%%% %%%SUCURI.Integrity.DiffUtility%%%
%%%SUCURI.Integrity.List%%%
{{WordPress Integrity (%%SUCURI.Integrity.ListCount%%)}}
  {{File Size}} {{Modified At}} {{File Path}}
    %%%SUCURI.Integrity.Pagination%%%

inc/tpl/integrity-incorrect.snippet.tpl000060400000010324147177152050014327 0ustar00 %%SUCURI.Integrity.StatusType%% %%SUCURI.Integrity.FileSizeHuman%% %%SUCURI.Integrity.ModifiedAt%% %%SUCURI.Integrity.FilePath%% inc/tpl/integrity-notification.html.tpl000060400000002504147177152050014310 0ustar00

{{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 Server Side Scanner.}}

%%%SUCURI.Integrity.List%%%
{{WordPress Integrity (%%SUCURI.Integrity.ListCount%%)}}
  {{Status}} {{File Size}} {{Modified At}} {{File Path}}

{{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.}}

inc/tpl/lastlogins-admins.html.tpl000060400000001537147177152050013243 0ustar00

{{Successful Logins (admins)}}

{{Here you can see a list of all the successful logins of accounts with admin privileges.}}

%%%SUCURI.AdminUsers.List%%%
{{Username}} {{Registration}} {{Newest To Oldest}}  
inc/tpl/lastlogins-admins-lastlogin.snippet.tpl000060400000000317147177152050015746 0ustar00 %%SUCURI.AdminUsers.RemoteAddr%% %%SUCURI.AdminUsers.Datetime%% inc/tpl/lastlogins-admins.snippet.tpl000060400000001556147177152050013762 0ustar00 %%SUCURI.AdminUsers.Username%% %%SUCURI.AdminUsers.RegisteredAt%%
{{no data available}}
%%%SUCURI.AdminUsers.LastLogins%%%
{{IP Address}} {{Date/Time}}
{{Edit User Profile}} inc/tpl/lastlogins-all.html.tpl000060400000003611147177152050012533 0ustar00

{{Successful Logins (all)}}

{{Here you can see a list of all the successful user logins.}}

%%%SUCURI.UserList%%%
{{Successful Logins (all)}}
{{Username}} {{IP Address}} {{Hostname}} {{Date/Time}}  
{{no data available}}
    %%%SUCURI.UserList.Pagination%%%
inc/tpl/lastlogins-all.snippet.tpl000060400000000745147177152050013256 0ustar00 %%SUCURI.UserList.Displayname%% (%%SUCURI.UserList.Username%%) %%SUCURI.UserList.RemoteAddr%% %%SUCURI.UserList.Hostname%% %%SUCURI.UserList.Datetime%% {{Edit}} inc/tpl/lastlogins-failedlogins.html.tpl000060400000005300147177152050014420 0ustar00

{{Failed logins}}

{{This information will be used to determine if your site is being victim of Password Guessing Brute Force Attacks. These logs will be accumulated and the plugin will send a report via email if there are more than %%SUCURI.FailedLogins.MaxFailedLogins%% failed login attempts during the same hour, you can change this number from here. NOTE: Some "Two-Factor Authentication" plugins do not follow the same rules that WordPress have to report failed login attempts, so you may not see all the attempts in this panel if you have one of these plugins installed.}}

%%%SUCURI.FailedLogins.List%%%
{{Username}} {{IP Address}} {{Date/Time}} {{Web Browser}}
{{no data available}}
    %%%SUCURI.FailedLogins.PaginationLinks%%%
inc/tpl/lastlogins-failedlogins.snippet.tpl000060400000000516147177152050015142 0ustar00 %%SUCURI.FailedLogins.Username%% %%SUCURI.FailedLogins.RemoteAddr%% %%SUCURI.FailedLogins.Datetime%%
%%SUCURI.FailedLogins.UserAgent%%
inc/tpl/lastlogins.html.tpl000060400000002052147177152050011763 0ustar00
%%%SUCURI.LastLogins.AllUsers%%%
%%%SUCURI.LastLogins.Admins%%%
%%%SUCURI.LoggedInUsers%%%
%%%SUCURI.FailedLogins%%%
inc/tpl/lastlogins-loggedin.html.tpl000060400000001563147177152050013557 0ustar00

{{Logged-in Users}}

{{Here you can see a list of the users that are currently logged-in.}}

%%%SUCURI.LoggedInUsers.List%%%
{{Logged-in Users}}
{{ID}} {{Username}} {{Last Activity}} {{Registered}} {{IP Address}}  
inc/tpl/lastlogins-loggedin.snippet.tpl000060400000000760147177152050014273 0ustar00 %%SUCURI.LoggedInUsers.Id%% %%SUCURI.LoggedInUsers.UserLogin%% %%SUCURI.LoggedInUsers.LastActivity%% %%SUCURI.LoggedInUsers.Registered%% %%SUCURI.LoggedInUsers.RemoteAddr%% {{Edit User Profile}} inc/tpl/modalwindow.html.tpl000060400000001025147177152050012127 0ustar00

%%SUCURI.Title%%

×
%%%SUCURI.Content%%%
inc/tpl/notification-admin.html.tpl000060400000000450147177152050013360 0ustar00
×

%%%SUCURI.AlertMessage%%%

inc/tpl/notification-pretty.html.tpl000060400000004101147177152050013614 0ustar00
Sucuri, Inc. %%SUCURI.TemplateTitle%%

Information:

{{Website:}} %%SUCURI.Website%%
{{IP Address:}} %%SUCURI.RemoteAddress%%
{{Reverse IP:}} %%SUCURI.ReverseAddress%%
{{Date/Time:}} %%SUCURI.Time%%
%%SUCURI.User%%

{{Message:}}

%%%SUCURI.Message%%%

inc/tpl/notification-simple.html.tpl000060400000000321147177152050013556 0ustar00 Event: %%SUCURI.Subject%% Website: http://%%SUCURI.Website%% IP Address: %%SUCURI.RemoteAddress%% Reverse IP: %%SUCURI.ReverseAddress%% Date/Time: %%SUCURI.Time%% %%SUCURI.User%% Message: %%SUCURI.Message%% inc/tpl/register-site.html.tpl000060400000005341147177152050012376 0ustar00

{{An API key is required to activate some additional tools available in this plugin. The keys are free and you can virtually generate an unlimited number of them as long as the domain name and email address are unique. The key is used to authenticate the HTTP requests sent by the plugin to an API service managed by Sucuri Inc.}}

{{If you experience issues generating the API key you can request one by sending the domain name and email address that you want to use to info@sucuri.net. Note that generating a key for a website that is not facing the Internet is not possible because the API service needs to validate that the domain name exists.}}

{{Enable DNS Lookups On Startup}}

inc/tpl/settings-alerts-bruteforce.html.tpl000060400000002503147177152050015073 0ustar00

{{Password Guessing Brute Force Attacks}}

{{Password guessing brute force attacks are very common against web sites and web servers. They are one of the most common vectors used to compromise web sites. The process is very simple and the attackers basically try multiple combinations of usernames and passwords until they find one that works. Once they get in, they can compromise the web site with malware, spam , phishing or anything else they want.}}

inc/tpl/settings-alerts-events.html.tpl000060400000003324147177152050014241 0ustar00

{{Security Alerts}}

{{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.}}

%%%SUCURI.Alerts.Events%%%
{{Event}}
inc/tpl/settings-alerts-events.snippet.tpl000060400000000502147177152050014752 0ustar00 %%%SUCURI.Event.Label%%% inc/tpl/settings-alerts-ignore-posts.html.tpl000060400000007261147177152050015372 0ustar00

{{Post-Type Alerts}}

{{It seems that you disabled the email alerts for new site content, this panel is intended to provide a way to ignore specific events in your site and with that the alerts reported to your email. Since you have deactivated the new site content alerts, this panel will be disabled too.}}

{{This is a list of registered Post Types. You will receive an email alert when a custom page or post associated to any of these types is created or updated. If you don’t want to receive one or more of these alerts, feel free to uncheck the boxes in the table below. If you are receiving alerts for post types that are not listed in this table, it may be because there is an add-on that that is generating a custom post-type on runtime, you will have to find out by yourself what is the unique ID of that post-type and type it in the form below. The plugin will do its best to ignore these alerts as long as the unique ID is valid.}}



%%%SUCURI.PostTypes.List%%%
{{Post Type}} {{Post Type ID}} {{Ignored At (optional)}}
inc/tpl/settings-alerts-ignore-posts.snippet.tpl000060400000000646147177152050016110 0ustar00 %%SUCURI.PostTypes.Title%% %%SUCURI.PostTypes.UniqueID%% %%SUCURI.PostTypes.IgnoredAt%% inc/tpl/settings-alerts-perhour.html.tpl000060400000002045147177152050014420 0ustar00

{{Alerts Per Hour}}

{{Configure the maximum number of email alerts per hour. If the number is exceeded and the plugin detects more events during the same hour, it will still log the events into the audit logs but will not send the email alerts. Be careful with this as you will miss important information.}}

inc/tpl/settings-alerts-recipients.html.tpl000060400000003760147177152050015106 0ustar00

{{Alerts Recipient}}

{{By default, the plugin will send the email alerts to the primary admin account, the same account created during the installation of WordPress in your web server. You can add more people to the list, they will receive a copy of the same security alerts.}}

%%%SUCURI.Alerts.Recipients%%%
{{E-mail}}
inc/tpl/settings-alerts-recipients.snippet.tpl000060400000000377147177152050015625 0ustar00 %%SUCURI.Recipient.Email%% inc/tpl/settings-alerts-subject.html.tpl000060400000002664147177152050014402 0ustar00

{{Alert Subject}}

{{Format of the subject for the email alerts, by default the plugin will use the website name and the event identifier that is being reported, you can use this panel to include the IP address of the user that triggered the event and some additional data. You can create filters in your email client creating a custom email subject using the pseudo-tags shown below.}}

    %%%SUCURI.Alerts.Subject%%%
inc/tpl/settings-alerts-subject.snippet.tpl000060400000000334147177152050015110 0ustar00
  • inc/tpl/settings-alerts-trustedips.html.tpl000060400000004742147177152050015150 0ustar00

    {{Trusted IP Addresses}}

    {{If you are working in a LAN (Local Area Network) you may want to include the IP addresses of all the nodes in the subnet, this will force the plugin to stop sending email alerts about actions executed from trusted IP addresses. Use the CIDR (Classless Inter Domain Routing) format to specify ranges of IP addresses (only 8, 16, and 24).}}


    %%%SUCURI.TrustedIPs.List%%%
    {{IP Address}} {{CIDR Format}} {{IP Added At}}
    {{no data available}}
    inc/tpl/settings-alerts-trustedips.snippet.tpl000060400000000632147177152050015660 0ustar00 %%SUCURI.TrustIP.RemoteAddr%% %%SUCURI.TrustIP.CIDRFormat%% %%SUCURI.TrustIP.AddedAt%% inc/tpl/settings-apirecovery.html.tpl000060400000002455147177152050014001 0ustar00

    {{If this operation was successful you will receive a message in the email used during the registration of the API key (usually the email of the main admin user). This message contains the key in plain text, copy and paste the key in the form field below. The plugin will verify the authenticity of the key sending an initial HTTP request to the API service, if this fails the key will be removed automatically and you will have to start the process all over again.}}

    {{There are cases where this operation may fail, an example would be when the email address is not associated with the domain anymore, this happens when the base URL changes (from www to none or viceversa). If you are having issues recovering the key please send an email explaining the situation to info@sucuri.net}}

    inc/tpl/settings-apiregistered.html.tpl000060400000002074147177152050014275 0ustar00

    {{Congratulations! The rest of the features available in the plugin have been enabled. This product is designed to supplement existing security products. It’s not a silver bullet for your security needs, but it’ll give you greater security awareness and better posture, all with the intent of reducing risk.}}

    {{Your website has been granted a new API key and it was associated to the email address that you chose during the registration process. You can use the same email to recover the key if you happen to lose it sometime. We encourage you to check the rest of the settings page and configure the plugin to your own needs.}}

    {{Dashboard}} {{Settings}}
    inc/tpl/settings-apiservice-checksums.html.tpl000060400000003070147177152050015560 0ustar00

    {{WordPress Checksums API}}

    {{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 development version of the code.}}

    {{WordPress Checksums API}} — %%SUCURI.ChecksumsAPI%%
    inc/tpl/settings-apiservice-proxy.html.tpl000060400000002224147177152050014754 0ustar00

    {{API Communication via Proxy}}

    {{All the HTTP requests used to communicate with the API service are being sent using the WordPress built-in functions, so (almost) all its official features are inherited, this is useful if you need to pass these HTTP requests through a proxy. According to the official documentation you have to add some constants to the main configuration file: WP_PROXY_HOST, WP_PROXY_PORT, WP_PROXY_USERNAME, WP_PROXY_PASSWORD.}}

    {{HTTP Proxy Hostname}}: %%SUCURI.APIProxy.Host%%
    {{HTTP Proxy Port num}}: %%SUCURI.APIProxy.Port%%
    {{HTTP Proxy Username}}: %%SUCURI.APIProxy.Username%%
    {{HTTP Proxy Password}}: %%SUCURI.APIProxy.PasswordText%%
    inc/tpl/settings-apiservice-status.html.tpl000060400000003555147177152050015126 0ustar00

    {{API Service Communication}}

    {{Once the API key is generated and the SUCURISCAN_API_URL configuration value is set, the plugin will communicate with your remote API service that will act as a safe data storage for the audit logs generated when the website triggers certain events that the plugin monitors. If the website is hacked the attacker will not have access to these logs and that way you can investigate what was modified (for malware infaction) and/or how the malicious person was able to gain access to the website.}}

    {{The API service is disabled. Consider enabling the Log Exporter to keep the monitoring working. Otherwise, an attacker may execute an action that will not be registered in the security logs and you will not have a way to identify such an event while investigating the incident.}}

    {{API Service Communication}} — %%SUCURI.ApiStatus.Status%% — %%SUCURI.ApiStatus.ServiceURL%%
    inc/tpl/settings-general-datastorage.html.tpl000060400000004106147177152050015355 0ustar00

    {{Data Storage}}

    {{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 (one level up the document root) please define a constant in the "wp-config.php" file named "SUCURI_DATA_STORAGE" with the absolute path to the new directory.}}

    %%SUCURI.Storage.Path%%
    %%%SUCURI.Storage.Files%%%
    {{File Path}} {{File Size}} {{Status}} {{Writable}}

    inc/tpl/settings-general-datastorage.snippet.tpl000060400000006475147177152050016106 0ustar00 %%SUCURI.Storage.Filepath%% %%SUCURI.Storage.Filesize%% %%SUCURI.Storage.Exists%% %%SUCURI.Storage.IsWritable%% inc/tpl/settings-general-importexport.html.tpl000060400000003237147177152050015637 0ustar00

    {{Import & Export Settings}}

    {{Copy the JSON-encoded data from the box below, go to your other websites and click the "Import" button in the settings page. The plugin will start using the same settings from this website. Notice that some options are omitted as they contain values specific to this website. To import the settings from another website into this one, replace the JSON-encoded data in the box below with the JSON-encoded data exported from the other website, then click the button "Import". Notice that some options will not be imported to reduce the security risk of writing arbitrary data into the disk.}}

    inc/tpl/settings-general-ipdiscoverer.html.tpl000060400000004677147177152050015572 0ustar00

    {{IP Address Discoverer}}

    {{IP address discoverer will use DNS lookups to automatically detect if the website is behind the Sucuri Firewall, in which case it will modify the global server variable Remote-Addr to set the real IP of the website’s visitors. This check runs on every WordPress init action and that is why it may slow down your website as some hosting providers rely on slow DNS servers which makes the operation take more time than it should.}}

    {{IP Address Discoverer}} — %%SUCURI.DnsLookupsStatus%%
    {{Sucuri Firewall}} — %%SUCURI.IsUsingFirewall%%
    {{Website:}} %%SUCURI.WebsiteURL%%
    {{Top Level Domain:}} %%SUCURI.TopLevelDomain%%
    {{Hostname:}} %%SUCURI.WebsiteHostName%%
    {{IP Address (Hostname):}} %%SUCURI.WebsiteHostAddress%%
    {{IP Address (Username):}} %%SUCURI.RemoteAddress%% (%%SUCURI.RemoteAddressHeader%%)
    inc/tpl/settings-general-resetoptions.html.tpl000060400000002311147177152050015611 0ustar00

    {{Reset Security Logs, Hardening and Settings}}

    {{This action will trigger the deactivation / uninstallation process of the plugin. All local security logs, hardening and settings will be deleted. Notice that the security logs stored in the API service will not be deleted, this is to prevent tampering from a malicious user. You can request a new API key if you want to start from scratch.}}

    inc/tpl/settings-general-reverseproxy.html.tpl000060400000003123147177152050015632 0ustar00

    {{Reverse Proxy}}

    {{The event monitor uses the API address of the origin of the request to track the actions. The plugin uses two methods to retrieve this: the main method uses the global server variable Remote-Addr available in most modern web servers, and an alternative method uses custom HTTP headers (which are unsafe by default). You should not worry about this option unless you know what a reverse proxy is. Services like the Sucuri Firewall — once active — force the network traffic to pass through them to filter any security threat that may affect the original server. A side effect of this is that the real IP address is no longer available in the global server variable Remote-Addr but in a custom HTTP header with a name provided by the service.}}

    {{Reverse Proxy}} — %%SUCURI.ReverseProxyStatus%%
    inc/tpl/settings-general-selfhosting.html.tpl000060400000003470147177152050015407 0ustar00

    {{Log Exporter}}

    {{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 (we recommend OSSEC). That will give visibility from within WordPress to complement your log monitoring infrastructure. NOTE: 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.}}

    {{Log Exporter}} — %%SUCURI.SelfHosting.Status%%
    %%SUCURI.SelfHosting.Fpath%%
    inc/tpl/settings-general-timezone.html.tpl000060400000002506147177152050014713 0ustar00

    {{Timezone Override}}

    {{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.}}

    (%%SUCURI.Timezone.Example%%)
    inc/tpl/settings-hardening-allowlist-phpfiles.html.tpl000060400000005540147177152050017226 0ustar00

    {{Allow Blocked PHP Files}}

    {{After you apply the hardening in either the includes, content, and/or uploads directories, the plugin will add a rule in the access control file to deny access to any PHP file located in these folders. This is a good precaution in case an attacker is able to upload a shell script. With a few exceptions the "index.php" file is the only one that should be publicly accessible, however many theme/plugin developers decide to use these folders to process some operations. In this case applying the hardening may break their functionality.}}


    %%%SUCURI.HardeningAllowlist.List%%%
    {{File Path}} {{Directory}} {{Pattern}}
    {{no data available}}
    inc/tpl/settings-hardening-allowlist-phpfiles.snippet.tpl000060400000000577147177152050017751 0ustar00 %%SUCURI.HardeningAllowlist.File%% %%SUCURI.HardeningAllowlist.Folder%% %%SUCURI.HardeningAllowlist.Regexp%% inc/tpl/settings-hardening-options.snippet.tpl000060400000006331147177152050015614 0ustar00
    %%SUCURI.Hardening.Title%%
    inc/tpl/settings-headers-cache.html.tpl000060400000042167147177152050014131 0ustar00

    {{Cache Control Header Options}}

    {{Please enable site caching on your WAF to use these settings. If you are a Sucuri client and require assistance, please {{create a ticket}} and reach out to the firewall team for support.}}

    {{Here you can see all the cache options available.}}

    %%%SUCURI.CacheOptions.Options%%%
    {{Option}} {{max-age}} {{s-maxage}} {{stale-if-error}} {{stale-while-revalidate}} {{Pagination factor}} {{Old age multiplier}}  
    {{No options available}}

    {{Cache Control Header}}%%SUCURI.CacheOptions.Status%%
    {{WordPress by default does not come with cache control headers, used by WAFs and CDNs that are useful to both improve performance and reduce bandwidth and other resources demand on the hosting server. }}

    inc/tpl/settings-headers-cache-option.snippet.tpl000060400000012456147177152050016153 0ustar00 %%SUCURI.name%% %%SUCURI.maxAge%% %%SUCURI.sMaxAge%% %%SUCURI.staleIfError%% %%SUCURI.staleWhileRevalidate%% %%SUCURI.paginationFactor%% Edit inc/tpl/settings.html.tpl000060400000007343147177152050011454 0ustar00
    %%%SUCURI.Settings.General.DataStorage%%% %%%SUCURI.Settings.General.SelfHosting%%% %%%SUCURI.Settings.General.ReverseProxy%%% %%%SUCURI.Settings.General.IPDiscoverer%%% %%%SUCURI.Settings.General.Timezone%%% %%%SUCURI.Settings.General.ImportExport%%% %%%SUCURI.Settings.General.ResetOptions%%%
    %%%SUCURI.Settings.Scanner.Cronjobs%%% %%%SUCURI.Settings.Scanner.IntegrityDiffUtility%%% %%%SUCURI.Settings.Scanner.IntegrityCache%%% %%%SUCURI.Settings.Scanner.IgnoreFolders%%%

    {{Hardening Options}}

    %%%SUCURI.Settings.Hardening.Firewall%%% %%%SUCURI.Settings.Hardening.WPVersion%%% %%%SUCURI.Settings.Hardening.RemoveGenerator%%% %%%SUCURI.Settings.Hardening.NginxPHPFPM%%% %%%SUCURI.Settings.Hardening.WPUploads%%% %%%SUCURI.Settings.Hardening.WPContent%%% %%%SUCURI.Settings.Hardening.WPIncludes%%% %%%SUCURI.Settings.Hardening.Readme%%% %%%SUCURI.Settings.Hardening.AdminUser%%% %%%SUCURI.Settings.Hardening.FileEditor%%% %%%SUCURI.Settings.Hardening.SecKeyUpdater%%%
    %%%SUCURI.Settings.Hardening.AllowlistPHPFiles%%%
    %%%SUCURI.Settings.Posthack.SecurityKeys%%% %%%SUCURI.Settings.Posthack.ResetPassword%%% %%%SUCURI.Settings.Posthack.ResetPlugins%%% %%%SUCURI.Settings.Posthack.AvailableUpdates%%%
    %%%SUCURI.Settings.Alerts.Recipients%%% %%%SUCURI.Settings.Alerts.TrustedIPs%%% %%%SUCURI.Settings.Alerts.Subject%%% %%%SUCURI.Settings.Alerts.PerHour%%% %%%SUCURI.Settings.Alerts.BruteForce%%% %%%SUCURI.Settings.Alerts.Events%%% %%%SUCURI.Settings.Alerts.IgnorePosts%%%
    %%%SUCURI.Settings.Headers.Cache%%%
    %%%SUCURI.Settings.APIService.Status%%% %%%SUCURI.Settings.APIService.Proxy%%% %%%SUCURI.Settings.SiteCheck.Target%%% %%%SUCURI.Settings.APIService.Checksums%%%
    %%%SUCURI.Settings.Webinfo.Details%%% %%%SUCURI.Settings.Webinfo.HTAccess%%%
    inc/tpl/settings-posthack-available-updates-alert.html.tpl000060400000001255147177152050017750 0ustar00

    {{WordPress has a big user base in the public Internet, which brings interest to attackers to find vulnerabilities in the code, 3rd-party extensions, and themes that other companies develop. You should keep every piece of code installed in your website updated to prevent attacks as soon as disclosed vulnerabilities are patched.}}

    %%%SUCURI.AvailableUpdates.Content%%%
    {{Name}} {{Version}} {{Update}} {{Tested With}}  
    inc/tpl/settings-posthack-available-updates.html.tpl000060400000003216147177152050016642 0ustar00

    {{Available Plugin and Theme Updates}}

    {{WordPress has a big user base in the public Internet, which brings interest to attackers to find vulnerabilities in the code, 3rd-party extensions, and themes that other companies develop. You should keep every piece of code installed in your website updated to prevent attacks as soon as disclosed vulnerabilities are patched.}}

    {{Name}} {{Version}} {{Update}} {{Tested With}}  
    {{Loading...}}
    inc/tpl/settings-posthack-available-updates.snippet.tpl000060400000001052147177152050017354 0ustar00 %%SUCURI.Update.Extension%% %%SUCURI.Update.Version%% %%SUCURI.Update.NewVersion%% %%SUCURI.Update.TestedWith%% {{Download}} inc/tpl/settings-posthack-reset-password-alert.html.tpl000060400000001056147177152050017346 0ustar00 {{WordPress has invalidated the password for your account %%SUCURI.ResetPassword.UserName%% at %%SUCURI.ResetPassword.Website%%. The change has been requested by one of the admins in this website for security reasons. You can set a new password at — %%%SUCURI.ResetPassword.ResetURL%%% —.}} inc/tpl/settings-posthack-reset-password.html.tpl000060400000005433147177152050016244 0ustar00

    {{Reset User Password}}

    {{Select users from the list in order to change their passwords, terminate their sessions and email them a password reset link. Please be aware that the plugin will change the passwords before sending the emails, meaning that if your web server is unable to send emails, your users will be locked out of the site.}}

    %%%SUCURI.ResetPassword.UserList%%%
    {{Username}} {{E-mail}} {{Registered}} {{Roles}}
      %%%SUCURI.ResetPassword.PaginationLinks%%%
    inc/tpl/settings-posthack-reset-password.snippet.tpl000060400000001150147177152050016752 0ustar00 %%SUCURI.ResetPassword.Username%% %%SUCURI.ResetPassword.Email%% %%SUCURI.ResetPassword.Registered%% %%SUCURI.ResetPassword.Roles%% inc/tpl/settings-posthack-reset-plugins.html.tpl000060400000007234147177152050016064 0ustar00

    {{Reset Installed Plugins}}

    {{In case you suspect having an infection in your site, or after you got rid of a malicious code, it’s recommended to reinstall all the plugins installed in your site, including the ones you are not using. Notice that premium plugins will not be automatically reinstalled to prevent backward compatibility issues and problems with licenses.}}

    {{The information shown here is cached for %%SUCURI.ResetPlugin.CacheLifeTime%% seconds. This is necessary to reduce the quantity of HTTP requests sent to the WordPress servers and the bandwidth of your site. Currently there is no option to recreate this cache.}}

    {{WARNING! This procedure can break your website. The reset will not affect the database nor the settings of each plugin, but depending on how they were written the reset action might break them. Be sure to create a backup of the plugins directory before the execution of this tool.}}

    {{Name}} {{Version}} {{Type}} {{Status}}
    {{Loading...}}
    inc/tpl/settings-posthack-reset-plugins.snippet.tpl000060400000001524147177152050016576 0ustar00 %%SUCURI.ResetPlugin.Plugin%% %%SUCURI.ResetPlugin.Version%% %%SUCURI.ResetPlugin.Type%% %%SUCURI.ResetPlugin.Status%% inc/tpl/settings-posthack-security-keys.html.tpl000060400000006560147177152050016104 0ustar00

    {{Update Secret Keys}}

    {{The secret or security keys are a list of constants added to your site to ensure better encryption of information stored in the user’s cookies. A secret key makes your site harder to hack by adding random elements to the password. You do not have to remember the keys, just write a random, complicated, and long string in the wp-config.php file. You can change these keys at any point in time. Changing them will invalidate all existing cookies, forcing all logged in users to login again.}}

    {{Your current session will expire once the form is submitted.}}

    %%%SUCURI.SecurityKeys.List%%%
    {{Status}} {{Name}} {{Value}}

    {{Automatic Secret Keys Updater}} — %%SUCURI.SecurityKeys.AutoStatus%%
    {{Changing the Secret Keys frequently will decrease the chances of misuse of sessions left open on unprotected devices.}}

    inc/tpl/settings-posthack-security-keys.snippet.tpl000060400000000355147177152050016616 0ustar00 %%SUCURI.SecurityKey.KeyStatusText%% %%SUCURI.SecurityKey.KeyName%% %%SUCURI.SecurityKey.KeyValue%% inc/tpl/settings-scanner-cronjobs.html.tpl000060400000007322147177152050014715 0ustar00

    {{Scheduled Tasks}}

    {{The plugin scans your entire website looking for changes which are later reported via the API in the audit logs page. By default the scanner runs daily but you can change the frequency to meet your requirements. Notice that scanning your project files too frequently may affect the performance of your website. Be sure to have enough server resources before changing this option. The memory limit and maximum execution time are two of the PHP options that your server will set to stop your website from consuming too much resources.}}

    {{The scanner uses the PHP SPL library and the Filesystem Iterator class to scan the directory tree where your website is located in the server. This library is only available on PHP 5 >= 5.3.0 — OR — PHP 7; if you have an older version of PHP the plugin will not work as expected. Please ask your hosting provider to advise you on this matter.}}

    {{Scheduled tasks are rules registered in your database by a plugin, theme, or the base system itself; they are used to automatically execute actions defined in the code every certain amount of time. A good use of these rules is to generate backup files of your site, execute a security scanner, or remove unused elements like drafts. Note: Scheduled tasks can be re-installed by any plugin/theme automatically.}}

    {{Name}} {{Schedule}} {{Next Due}} {{Arguments}}
    {{Loading...}}
    inc/tpl/settings-scanner-cronjobs.snippet.tpl000060400000000677147177152050015441 0ustar00 %%SUCURI.Cronjob.Hook%% %%SUCURI.Cronjob.Schedule%% %%SUCURI.Cronjob.NextTime%% (%%SUCURI.Cronjob.NextTimeHuman%%) %%SUCURI.Cronjob.Arguments%% inc/tpl/settings-scanner-ignore-folders.html.tpl000060400000004241147177152050016012 0ustar00

    {{Ignore Files And Folders During The Scans}}

    {{Use this tool to select the files and/or folders that are too heavy for the scanner to process. These are usually folders with images, media files like videos and audios, backups and — in general — anything that is not code-related. Ignoring these files or folders will reduce the memory consumption of the PHP script.}}


    %%%SUCURI.IgnoreScan.List%%%
    {{File Path}} {{Status}}
    inc/tpl/settings-scanner-ignore-folders.snippet.tpl000060400000000474147177152050016534 0ustar00 %%SUCURI.IgnoreScan.Directory%% %%SUCURI.IgnoreScan.IgnoredAt%% inc/tpl/settings-scanner-integrity-cache.html.tpl000060400000003541147177152050016154 0ustar00

    {{WordPress Integrity (False Positives)}}

    {{Since the scanner doesn’t read the files during the execution of the integrity check, it is possible to find false positives. Files listed here have been marked as false positives and will be ignored by the scanner in subsequent scans.}}

    %%%SUCURI.IgnoredFiles%%%
    {{Reason}} {{Ignored At}} {{File Path}}
    {{no data available}}

    inc/tpl/settings-scanner-integrity-cache.snippet.tpl000060400000000760147177152050016672 0ustar00 %%SUCURI.StatusType%% %%SUCURI.IgnoredAt%% %%SUCURI.FilePath%% inc/tpl/settings-scanner-integrity-diff-utility.html.tpl000060400000002370147177152050017521 0ustar00

    {{WordPress Integrity Diff Utility}}

    {{If your server allows the execution of system commands, you can configure the plugin to use the Unix Diff Utility 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.}}

    {{WordPress Integrity Diff Utility}} — %%SUCURI.DiffUtility.Status%%
    inc/tpl/settings-webinfo-details.html.tpl000060400000000516147177152050014521 0ustar00

    {{Environment Variables}}

    %%%SUCURI.ServerInfo.Variables%%%
    inc/tpl/settings-webinfo-details.snippet.tpl000060400000000257147177152050015241 0ustar00 %%SUCURI.ServerInfo.Title%% %%SUCURI.ServerInfo.Value%% inc/tpl/settings-webinfo-htaccess.html.tpl000060400000004126147177152050014672 0ustar00

    {{Access File Integrity}}

    {{The .htaccess file is a distributed configuration file, and is how the Apache web server handles configuration changes on a per-directory basis. WordPress uses this file to manipulate how Apache serves files from its root directory and subdirectories thereof; most notably, it modifies this file to be able to handle pretty permalinks.}}

    {{Htaccess file found in}} %%SUCURI.HTAccess.Fpath%%

    {{Your website has no .htaccess file or it was not found in the default location.}}

    {{Your web server does not support .htaccess files.}}

    {{The main .htaccess file in your site has the standard rules for a WordPress installation. You can customize it to improve the performance and change the behaviour of the redirections for pages and posts in your site. To get more information visit the official documentation at Codex WordPress - Creating and editing (.htaccess)}}

    {{Codex WordPress HTAccess}}

    inc/tpl/sitecheck-blocklist.html.tpl000060400000000412147177152050013530 0ustar00

    %%SUCURI.Blocklist.Title%%

      %%%SUCURI.Blocklist.Content%%%
    inc/tpl/sitecheck-blocklist.snippet.tpl000060400000000261147177152050014250 0ustar00
  • %%SUCURI.Blocklist.Service%%
  • inc/tpl/sitecheck-details.html.tpl000060400000000566147177152050013201 0ustar00
      %%%SUCURI.SiteCheck.Metadata%%%
    {{This information will be updated %%SUCURI.SiteCheck.Lifetime%%}} — {{Refresh Malware Scan}}
    inc/tpl/sitecheck-details.snippet.tpl000060400000000247147177152050013713 0ustar00
  • %%SUCURI.SiteCheck.Title%%: %%SUCURI.SiteCheck.Value%%
  • inc/tpl/sitecheck-malware.html.tpl000060400000005302147177152050013175 0ustar00

    %%SUCURI.Malware.Title%%

    {{Get 20% Off On Malware Cleanup}}

    Reach out to our suppor team to get 20% off on malware cleanup.

    • {{No malicious JavaScript}}
    • {{No malicious iFrames}}
    • {{No suspicious redirections}}
    • {{No blackhat SEO spam}}
    • {{No anomaly detection}}
      %%%SUCURI.Malware.Content%%%
    {{Get 20% Off On Malware Cleanup}}

    {{This is a free website security scanner. Some types of malware and security issues cannot be detected by this scanner. If no issues are detected but you suspect a problem still exists, sign up for a complete and in depth website scan with malware cleanup.}}

    {{The Sucuri Security Plugin's automated scanner has detected malware in your WordPress environment.}}

    {{Log in to the Sucuri Platform dashboard for a complete scan of your website files and guaranteed malware removal. You can sign up here if you don't have an account yet.}}

    inc/tpl/sitecheck-malware.snippet.tpl000060400000000664147177152050013721 0ustar00
  • %%SUCURI.Malware.MalwareType%%

    %%SUCURI.Malware.AlertMessage%% %%SUCURI.Malware.InfectedURL%%

    ({{Hover to see the Payload}})

  • inc/tpl/sitecheck-recommendations.html.tpl000060400000000425147177152050014735 0ustar00

    {{Recommendations}}

      %%%SUCURI.Recommendations.Content%%%
    inc/tpl/sitecheck-recommendations.snippet.tpl000060400000000365147177152050015456 0ustar00
  • %%SUCURI.Recommendations.Title%%
    %%SUCURI.Recommendations.Value%%
  • inc/tpl/sitecheck-target.html.tpl000060400000003210147177152050013027 0ustar00

    {{Malware Scan Target}}

    {{The remote malware scanner provided by the plugin is powered by Sucuri SiteCheck, 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.}}

    inc/tpl/wordpress-recommendations.html.tpl000060400000000541147177152050015022 0ustar00

    {{WordPress Security Recommendations}}

      %%%SUCURI.WordPress.Recommendations.Content%%%
    inc/tpl/wordpress-recommendations.snippet.tpl000060400000000263147177152050015541 0ustar00
  • %%SUCURI.WordPress.Recommendations.Title%%
    %%SUCURI.WordPress.Recommendations.Value%%
  • inc/index.html000060400000000046147177152050007317 0ustar00 lang/sucuri-scanner.pot000060400000272557147177152050011201 0ustar00# Copyright (C) 2024 Sucuri Inc. # This file is distributed under the GPL v2 or later. msgid "" msgstr "" "Project-Id-Version: Sucuri Security - Auditing, Malware Scanner and Hardening 1.9.6\n" "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/sucuri-wordpress-plugin\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "POT-Creation-Date: 2024-10-08T04:57:05+00:00\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "X-Generator: WP-CLI 2.11.0\n" "X-Domain: sucuri-scanner\n" #. Plugin Name of the plugin #: sucuri.php msgid "Sucuri Security - Auditing, Malware Scanner and Hardening" msgstr "" #. Plugin URI of the plugin #: sucuri.php msgid "https://wordpress.sucuri.net/" msgstr "" #. Description of the plugin #: sucuri.php msgid "The Sucuri plugin provides the website owner the best Activity Auditing, SiteCheck Remote Malware Scanning, Effective Security Hardening and Post-Hack features. SiteCheck will check for malware, spam, blocklisting and other security issues like .htaccess redirects, hidden eval code, etc. The best thing about it is it's completely free." msgstr "" #. Author of the plugin #: sucuri.php msgid "Sucuri Inc." msgstr "" #. Author URI of the plugin #: sucuri.php msgid "https://sucuri.net/" msgstr "" #: src/api.lib.php:91 msgid "URL is invalid" msgstr "" #: src/api.lib.php:95 msgid "Only GET and POST methods allowed" msgstr "" #: src/api.lib.php:182 msgid "Invalid API key format" msgstr "" #: src/api.lib.php:188 msgid "API key was successfully set: %s" msgstr "" #: src/api.lib.php:284 msgid "Unknown error, there is no information" msgstr "" #: src/api.lib.php:324 msgid "Invalid email format or the host is missing MX records." msgstr "" #: src/api.lib.php:359 msgid "API key was generated and set" msgstr "" #: src/api.lib.php:361 msgid "API key successfully generated and saved." msgstr "" #: src/api.lib.php:389 msgid "API key recovery for domain: %s" msgstr "" #: src/api.lib.php:492 msgid "All Time" msgstr "" #: src/api.lib.php:496 #: src/auditlogs.lib.php:392 msgid "Today" msgstr "" #: src/api.lib.php:500 msgid "Yesterday" msgstr "" #: src/api.lib.php:504 msgid "This Week" msgstr "" #: src/api.lib.php:508 msgid "Last 7 Days" msgstr "" #: src/api.lib.php:512 msgid "Last Week" msgstr "" #: src/api.lib.php:516 msgid "Last 14 Days" msgstr "" #: src/api.lib.php:520 msgid "This Month" msgstr "" #: src/api.lib.php:524 msgid "Last 30 Days" msgstr "" #: src/api.lib.php:528 msgid "Last Month" msgstr "" #: src/api.lib.php:532 msgid "This Year" msgstr "" #: src/api.lib.php:536 msgid "Last Year" msgstr "" #: src/api.lib.php:540 msgid "Custom" msgstr "" #: src/api.lib.php:548 msgid "All Posts" msgstr "" #: src/api.lib.php:552 #: src/api.lib.php:584 msgid "Created" msgstr "" #: src/api.lib.php:556 msgid "Updated" msgstr "" #: src/api.lib.php:560 #: src/api.lib.php:592 msgid "Deleted" msgstr "" #: src/api.lib.php:566 msgid "All Logins" msgstr "" #: src/api.lib.php:570 msgid "Failed" msgstr "" #: src/api.lib.php:574 msgid "Succeeded" msgstr "" #: src/api.lib.php:580 #: src/strings.php:167 msgid "All Users" msgstr "" #: src/api.lib.php:588 msgid "Edited" msgstr "" #: src/api.lib.php:598 msgid "All Plugins" msgstr "" #: src/api.lib.php:602 msgid "Installed" msgstr "" #: src/api.lib.php:606 msgid "Activated" msgstr "" #: src/api.lib.php:610 msgid "Deactivated" msgstr "" #: src/api.lib.php:918 msgid "WP Engine PHP Compatibility Checker: %s (created post #%d as cache)" msgstr "" #: src/api.lib.php:1261 #: src/api.lib.php:1266 msgid "WordPress version is not supported anymore" msgstr "" #: src/auditlogs.lib.php:199 msgid "API is not available; using local queue" msgstr "" #: src/auditlogs.lib.php:201 msgid "API %s secs" msgstr "" #: src/auditlogs.lib.php:247 msgid "There are no logs." msgstr "" #: src/auditlogs.lib.php:303 msgid "status has been changed" msgstr "" #: src/base.lib.php:60 msgid "Error:" msgstr "" #: src/base.lib.php:60 msgid "Info:" msgstr "" #: src/cache.lib.php:401 #: src/cache.lib.php:424 #: src/cache.lib.php:465 #: src/cache.lib.php:482 msgid "Invalid cache key name" msgstr "" #: src/cron.lib.php:49 msgid "Automatic update of security keys failed. WordPress configuration file was not found or new keys could not be created." msgstr "" #: src/cron.lib.php:51 msgid "Automatic update of security keys succeeded." msgstr "" #: src/cron.lib.php:53 msgid "Automatic update of security keys failed. Something went wrong!" msgstr "" #: src/event.lib.php:89 msgid "%s (every %d seconds)" msgstr "" #: src/event.lib.php:95 msgid "Never (no execution)" msgstr "" #: src/event.lib.php:214 #: src/event.lib.php:264 msgid "API key is not available" msgstr "" #: src/event.lib.php:222 msgid "WordPress version was already reported" msgstr "" #: src/event.lib.php:225 msgid "WordPress version detected %s" msgstr "" #: src/event.lib.php:268 msgid "Scanner ran a couple of minutes ago" msgstr "" #: src/event.lib.php:300 msgid "Event identifier cannot be empty" msgstr "" #: src/event.lib.php:468 #: src/event.lib.php:472 msgid "Info" msgstr "" #: src/event.lib.php:470 msgid "Debug" msgstr "" #: src/event.lib.php:471 msgid "Notice" msgstr "" #: src/event.lib.php:473 msgid "Warning" msgstr "" #: src/event.lib.php:474 msgid "Error" msgstr "" #: src/event.lib.php:475 msgid "Critical" msgstr "" #: src/event.lib.php:605 msgid "" "

    \n" "\n" "Explanation: Someone failed to login to your site. If you are getting too many of these messages, it is likely your site is under a password guessing brute-force attack [1]. You can disable the failed login alerts from here [2]. Alternatively, you can consider to install a firewall between your website and your visitors to filter out these and other attacks, take a look at Sucuri Firewall [3].

    \n" "\n" "[1] https://kb.sucuri.net/definitions/attacks/brute-force/password-guessing
    \n" "[2] %s
    \n" "[3] https://sucuri.net/website-firewall/
    \n" "" msgstr "" #: src/event.lib.php:747 msgid "Password Change" msgstr "" #: src/event.lib.php:916 msgid "%s cannot be deleted." msgstr "" #: src/event.lib.php:928 #: src/event.lib.php:934 msgid "%s was deleted." msgstr "" #: src/fileinfo.lib.php:291 msgid "No files were found" msgstr "" #: src/fileinfo.lib.php:349 msgid "Directory does not exists" msgstr "" #: src/fileinfo.lib.php:353 msgid "Cannot delete content directory" msgstr "" #: src/fileinfo.lib.php:359 msgid "Cannot delete uploads directory" msgstr "" #: src/firewall.lib.php:161 msgid "Firewall API key was successfully saved" msgstr "" #: src/firewall.lib.php:172 msgid "Firewall API key was successfully removed" msgstr "" #: src/firewall.lib.php:204 msgid "enabled (recommended)" msgstr "" #: src/firewall.lib.php:205 msgid "site caching (using your site headers)" msgstr "" #: src/firewall.lib.php:206 msgid "minimal (only for a few minutes)" msgstr "" #: src/firewall.lib.php:207 msgid "caching disabled (use with caution)" msgstr "" #: src/firewall.lib.php:253 #: src/firewall.lib.php:349 #: src/firewall.lib.php:567 #: src/firewall.lib.php:602 #: src/firewall.lib.php:643 #: src/firewall.lib.php:740 msgid "Firewall API key was not found." msgstr "" #: src/firewall.lib.php:385 msgid "no data available." msgstr "" #: src/firewall.lib.php:443 msgid "Anonymous" msgstr "" #: src/firewall.lib.php:488 msgid "January" msgstr "" #: src/firewall.lib.php:489 msgid "February" msgstr "" #: src/firewall.lib.php:490 msgid "March" msgstr "" #: src/firewall.lib.php:491 msgid "April" msgstr "" #: src/firewall.lib.php:492 msgid "May" msgstr "" #: src/firewall.lib.php:493 msgid "June" msgstr "" #: src/firewall.lib.php:494 msgid "July" msgstr "" #: src/firewall.lib.php:495 msgid "August" msgstr "" #: src/firewall.lib.php:496 msgid "September" msgstr "" #: src/firewall.lib.php:497 msgid "October" msgstr "" #: src/firewall.lib.php:498 msgid "November" msgstr "" #: src/firewall.lib.php:499 msgid "December" msgstr "" #: src/firewall.lib.php:610 msgid "Failure connecting to the API service; try again." msgstr "" #: src/firewall.lib.php:617 msgid "IP has been added to the blocklist: %s" msgstr "" #: src/firewall.lib.php:656 msgid "IP has been removed from the blocklist: %s" msgstr "" #: src/globals.php:90 #: src/strings.php:39 #: src/strings.php:327 msgid "Dashboard" msgstr "" #: src/globals.php:91 #: src/strings.php:40 msgid "Firewall (WAF)" msgstr "" #: src/globals.php:92 msgid "Last Logins" msgstr "" #: src/globals.php:93 #: src/strings.php:41 #: src/strings.php:106 #: src/strings.php:328 msgid "Settings" msgstr "" #: src/globals.php:114 #: src/globals.php:115 #: src/strings.php:35 msgid "Sucuri Security" msgstr "" #: src/hardening.lib.php:121 msgid "Directory is not usable" msgstr "" #: src/hardening.lib.php:125 #: src/hardening.lib.php:325 msgid "Access control file is not supported" msgstr "" #: src/hardening.lib.php:161 msgid "Directory is not hardened" msgstr "" #: src/hardening.lib.php:331 msgid "Access control file does not exists" msgstr "" #: src/hardening.lib.php:335 msgid "Access control file is not writable" msgstr "" #: src/hardening.lib.php:342 msgid "File is already in the allowlist" msgstr "" #: src/hardening.lib.php:375 msgid "Cannot remove file from the allowlist; no permissions." msgstr "" #: src/hook.lib.php:68 msgid "Media file added; ID: %s; name: %s; type: %s" msgstr "" #: src/hook.lib.php:82 #: src/hook.lib.php:108 #: src/hook.lib.php:193 #: src/hook.lib.php:1007 #: src/hook.lib.php:1018 #: src/hook.lib.php:1048 #: src/settings-general.php:315 #: src/settings-general.php:316 #: src/settings-general.php:317 #: src/settings-general.php:318 #: src/settings-general.php:319 #: src/settings-webinfo.php:40 msgid "unknown" msgstr "" #: src/hook.lib.php:83 #: src/hook.lib.php:109 #: src/hook.lib.php:1008 #: src/hook.lib.php:1019 #: src/hook.lib.php:1049 msgid "user@domain.com" msgstr "" #: src/hook.lib.php:91 msgid "User added to website; user_id: %s; role: %s; blog_id: %s; name: %s; email: %s" msgstr "" #: src/hook.lib.php:117 msgid "User removed from website; user_id: %s; blog_id: %s; name: %s; email: %s" msgstr "" #: src/hook.lib.php:134 #: src/hook.lib.php:225 #: src/hook.lib.php:292 #: src/hook.lib.php:404 #: src/hook.lib.php:530 #: src/hook.lib.php:746 #: src/hook.lib.php:772 #: src/hook.lib.php:873 #: src/hook.lib.php:917 #: src/lastlogins-failed.php:251 msgid "Unknown" msgstr "" #: src/hook.lib.php:136 msgid "Category created; ID: %s; name: %s" msgstr "" #: src/hook.lib.php:150 msgid "WordPress updated to version: %s" msgstr "" #: src/hook.lib.php:175 msgid "Bookmark link added; ID: %s; name: %s; url: %s; target: %s" msgstr "" #: src/hook.lib.php:205 msgid "Bookmark link edited; ID: %s; name: %s; url: %s; target: %s" msgstr "" #: src/hook.lib.php:226 msgid "User authentication failed: %s" msgstr "" #: src/hook.lib.php:279 msgid "Attempt to reset password by attacking WP/2.8.3 bug" msgstr "" #: src/hook.lib.php:293 msgid "User authentication succeeded: %s" msgstr "" #: src/hook.lib.php:322 msgid "" "The value of the option %s was changed from '%s' to '%s'.
    \n" "" msgstr "" #: src/hook.lib.php:328 msgid "%s: from '%s' to '%s'," msgstr "" #: src/hook.lib.php:337 msgid "Common" msgstr "" #: src/hook.lib.php:341 msgid "Global" msgstr "" #: src/hook.lib.php:355 msgid "%s settings changed" msgstr "" #: src/hook.lib.php:358 msgid "%s: (multiple entries): %s" msgstr "" #: src/hook.lib.php:416 msgid "Plugin %s: %s (v%s; %s%s)" msgstr "" #: src/hook.lib.php:478 msgid "Plugins deleted: (multiple entries):" msgstr "" #: src/hook.lib.php:480 msgid "Plugin deleted:" msgstr "" #: src/hook.lib.php:506 msgid "Plugin editor used in: %s" msgstr "" #: src/hook.lib.php:531 msgid "Plugin installed: %s" msgstr "" #: src/hook.lib.php:591 msgid "Plugins updated: (multiple entries):" msgstr "" #: src/hook.lib.php:593 msgid "Plugin updated:" msgstr "" #: src/hook.lib.php:662 msgid "Post deleted: (multiple entries): %s" msgstr "" #: src/hook.lib.php:676 msgid "Ignore corrupted post data" msgstr "" #: src/hook.lib.php:681 msgid "Skip events for equal transitions" msgstr "" #: src/hook.lib.php:705 msgid "Skip events for postman-smtp alerts" msgstr "" #: src/hook.lib.php:710 msgid "Skip events for ignored post-types" msgstr "" #: src/hook.lib.php:716 msgid "Skip events for ignored post transitions" msgstr "" #: src/hook.lib.php:722 msgid "ID: %s" msgstr "" #: src/hook.lib.php:723 msgid "Old status: %s" msgstr "" #: src/hook.lib.php:724 msgid "New status: %s" msgstr "" #: src/hook.lib.php:727 msgid "Title: %s" msgstr "" #: src/hook.lib.php:730 msgid "%s status has been changed" msgstr "" #: src/hook.lib.php:756 msgid "Post moved to trash; ID: %s; name: %s; status: %s" msgstr "" #: src/hook.lib.php:773 msgid "Publication" msgstr "" #: src/hook.lib.php:791 msgid "%s was %s; ID: %s; name: %s" msgstr "" #: src/hook.lib.php:856 msgid "Password retrieval attempt: %s" msgstr "" #: src/hook.lib.php:875 msgid "Theme deleted: %s" msgstr "" #: src/hook.lib.php:898 msgid "Theme editor used in: %s/%s" msgstr "" #: src/hook.lib.php:919 msgid "Theme installed: %s" msgstr "" #: src/hook.lib.php:934 msgid "Theme activated: %s" msgstr "" #: src/hook.lib.php:976 msgid "Themes updated: (multiple entries):" msgstr "" #: src/hook.lib.php:978 msgid "Theme updated:" msgstr "" #: src/hook.lib.php:997 msgid "User account deleted; ID: %d" msgstr "" #: src/hook.lib.php:1028 msgid "User account edited; ID: %s; name: %s; old_name: %s; email: %s; old_email: %s; roles: %s; old_roles: %s" msgstr "" #: src/hook.lib.php:1060 msgid "User account created; ID: %s; name: %s; email: %s; roles: %s" msgstr "" #: src/hook.lib.php:1103 msgid "Widget %s (%s) %s %s (#%d; size %dx%d)" msgstr "" #: src/integrity.lib.php:113 #: src/settings-general.php:46 #: src/settings-general.php:501 #: src/settings-posthack.php:58 msgid "You need to confirm that you understand the risk of this operation." msgstr "" #: src/integrity.lib.php:119 msgid "Requested action is not supported." msgstr "" #: src/integrity.lib.php:129 msgid "Core file restored" msgstr "" #: src/integrity.lib.php:130 msgid "Non-core file deleted" msgstr "" #: src/integrity.lib.php:131 msgid "Core file marked as fixed" msgstr "" #: src/integrity.lib.php:136 msgid "Nothing was selected from the list." msgstr "" #: src/integrity.lib.php:229 msgid "Server is not fast enough to process this action; maximum execution time reached" msgstr "" #: src/integrity.lib.php:236 msgid "Only %d out of %d files were processed." msgstr "" #: src/integrity.lib.php:245 msgid "%d out of %d files were successfully processed." msgstr "" #: src/integrity.lib.php:390 msgid "The plugin has no permission to delete this file because it was created by a different system user who has more privileges than your account. Please use FTP to delete it." msgstr "" #: src/integrity.lib.php:393 msgid "The plugin has no permission to restore this file because it was modified by a different system user who has more privileges than your account. Please use FTP to restore it." msgstr "" #: src/integrity.lib.php:396 msgid "The plugin has no permission to restore this file because its directory is owned by a different system user who has more privileges than your account. Please use FTP to restore it." msgstr "" #: src/integrity.lib.php:494 #: src/strings.php:536 #: src/strings.php:539 msgid "WordPress Integrity Diff Utility" msgstr "" #: src/interface.lib.php:190 msgid "The plugin requires PHP 5 >= 5.3.0 - OR - PHP 7" msgstr "" #: src/interface.lib.php:198 msgid "Storage is not writable: %s" msgstr "" #: src/interface.lib.php:240 msgid "Do you want to get vulnerability disclosures? Subscribe to our newsletter here" msgstr "" #: src/interface.lib.php:253 msgid "Access denied; cannot manage options" msgstr "" #: src/interface.lib.php:254 msgid "Access denied by %s" msgstr "" #: src/interface.lib.php:274 msgid "Nonce is invalid" msgstr "" #: src/interface.lib.php:275 msgid "WordPress CSRF verification failed. The submitted form is missing an important unique code that prevents the execution of automated malicious scanners. Go back and try again. If you did not submit a form, this error message could be an indication of an incompatibility between this plugin and another add-on; one of them is inserting data into the global POST variable when the HTTP request is coming via GET. Disable them one by one (while reloading this page) to find the culprit." msgstr "" #: src/lastlogins-failed.php:349 #: src/lastlogins-failed.php:373 #: src/strings.php:175 #: src/strings.php:188 #: src/strings.php:202 #: src/strings.php:214 #: src/strings.php:457 msgid "Username" msgstr "" #: src/lastlogins-failed.php:350 #: src/lastlogins-failed.php:374 msgid "Password" msgstr "" #: src/lastlogins-failed.php:351 #: src/lastlogins-failed.php:375 #: src/strings.php:89 #: src/strings.php:181 #: src/strings.php:189 #: src/strings.php:203 #: src/strings.php:217 #: src/strings.php:308 msgid "IP Address" msgstr "" #: src/lastlogins-failed.php:352 #: src/lastlogins-failed.php:376 msgid "Attempt Timestamp" msgstr "" #: src/lastlogins-failed.php:353 #: src/lastlogins-failed.php:377 msgid "Attempt Date/Time" msgstr "" #: src/lastlogins.php:129 msgid "Last-logins data file is not writable: %s" msgstr "" #: src/lastlogins.php:305 msgid "Invalid last-logins storage file" msgstr "" #: src/lastlogins.php:312 msgid "No last-logins data is available" msgstr "" #: src/lastlogins.php:456 msgid "Last login was at %s from %s (%s) view all logs" msgstr "" #: src/mail.lib.php:80 msgid "Maximum number of emails per hour reached" msgstr "" #: src/mail.lib.php:189 msgid "User: %s (%s)" msgstr "" #: src/mail.lib.php:215 msgid "Sucuri Alert" msgstr "" #: src/option.lib.php:120 msgid "Front Page" msgstr "" #: src/option.lib.php:131 msgid "Posts" msgstr "" #: src/option.lib.php:142 msgid "Pages" msgstr "" #: src/option.lib.php:153 msgid "Main Index" msgstr "" #: src/option.lib.php:164 msgid "Categories" msgstr "" #: src/option.lib.php:175 msgid "Tags" msgstr "" #: src/option.lib.php:186 msgid "Authors" msgstr "" #: src/option.lib.php:197 msgid "Archives" msgstr "" #: src/option.lib.php:208 msgid "Feeds" msgstr "" #: src/option.lib.php:219 msgid "Attachment Pages" msgstr "" #: src/option.lib.php:230 msgid "Search Results" msgstr "" #: src/option.lib.php:241 msgid "404 Not Found" msgstr "" #: src/option.lib.php:252 msgid "Redirects" msgstr "" #: src/option.lib.php:263 msgid "Woocommerce Products" msgstr "" #: src/option.lib.php:274 msgid "Woocommerce Categories" msgstr "" #: src/option.lib.php:316 #: src/settings-alerts.php:214 #: src/settings-alerts.php:215 #: src/settings-alerts.php:216 msgid "Sucuri Alert, %s, %s, %s" msgstr "" #: src/pagehandler.php:44 msgid "iFrames" msgstr "" #: src/pagehandler.php:45 msgid "Links" msgstr "" #: src/pagehandler.php:46 msgid "Scripts" msgstr "" #: src/pagehandler.php:47 #: src/pagehandler.php:48 #: src/pagehandler.php:49 #: src/strings.php:26 #: src/strings.php:55 #: src/strings.php:67 #: src/strings.php:81 #: src/strings.php:121 #: src/strings.php:164 #: src/strings.php:442 #: src/strings.php:453 #: src/strings.php:465 #: src/strings.php:508 msgid "Loading..." msgstr "" #: src/pagehandler.php:100 msgid "Last-Logins logs were successfully reset." msgstr "" #: src/pagehandler.php:102 msgid "Could not reset the last-logins data file." msgstr "" #: src/settings-alerts.php:56 msgid "The email alerts will be sent to: %s" msgstr "" #: src/settings-alerts.php:59 msgid "The email alerts will be sent to: %s" msgstr "" #: src/settings-alerts.php:63 msgid "Email format not supported." msgstr "" #: src/settings-alerts.php:82 msgid "These emails will stop receiving alerts: %s" msgstr "" #: src/settings-alerts.php:85 msgid "These emails will stop receiving alerts: %s" msgstr "" #: src/settings-alerts.php:96 msgid "Test Email Alert" msgstr "" #: src/settings-alerts.php:97 msgid "Test email alert sent at %s" msgstr "" #: src/settings-alerts.php:102 msgid "A test alert was sent to your email, check your inbox" msgstr "" #: src/settings-alerts.php:104 msgid "An error occurred sending email - please check your server mail configuration." msgstr "" #: src/settings-alerts.php:151 msgid "The IP specified address was already added." msgstr "" #: src/settings-alerts.php:153 msgid "IP has been trusted: %s" msgstr "" #: src/settings-alerts.php:154 msgid "Events generated from this IP will be ignored: %s" msgstr "" #: src/settings-alerts.php:156 msgid "The IP address could not be added to the trusted list" msgstr "" #: src/settings-alerts.php:169 msgid "The selected IP addresses were successfully deleted." msgstr "" #: src/settings-alerts.php:178 msgid "n/a" msgstr "" #: src/settings-alerts.php:213 #: src/settings-alerts.php:217 #: src/settings-alerts.php:218 msgid "Sucuri Alert, %s, %s" msgstr "" #: src/settings-alerts.php:219 msgid "Sucuri Alert, %s" msgstr "" #: src/settings-alerts.php:247 msgid "Invalid characters in the email subject." msgstr "" #: src/settings-alerts.php:255 msgid "Email subject set to %s" msgstr "" #: src/settings-alerts.php:260 msgid "The email subject has been successfully updated" msgstr "" #: src/settings-alerts.php:309 msgid "Maximum 5 per hour" msgstr "" #: src/settings-alerts.php:310 msgid "Maximum 10 per hour" msgstr "" #: src/settings-alerts.php:311 msgid "Maximum 20 per hour" msgstr "" #: src/settings-alerts.php:312 msgid "Maximum 40 per hour" msgstr "" #: src/settings-alerts.php:313 msgid "Maximum 80 per hour" msgstr "" #: src/settings-alerts.php:314 msgid "Maximum 160 per hour" msgstr "" #: src/settings-alerts.php:315 msgid "Unlimited alerts per hour" msgstr "" #: src/settings-alerts.php:325 msgid "Maximum alerts per hour set to %s" msgstr "" #: src/settings-alerts.php:330 msgid "The maximum number of alerts per hour has been updated" msgstr "" #: src/settings-alerts.php:332 msgid "Error updating the maximum number of alerts per hour" msgstr "" #: src/settings-alerts.php:356 msgid "30 failed logins per hour" msgstr "" #: src/settings-alerts.php:357 msgid "60 failed logins per hour" msgstr "" #: src/settings-alerts.php:358 msgid "120 failed logins per hour" msgstr "" #: src/settings-alerts.php:359 msgid "240 failed logins per hour" msgstr "" #: src/settings-alerts.php:360 msgid "480 failed logins per hour" msgstr "" #: src/settings-alerts.php:369 msgid "Consider brute-force attack after %s failed logins per hour" msgstr "" #: src/settings-alerts.php:374 msgid "The plugin will assume that your website is under a brute-force attack after %s failed logins are detected during the same hour" msgstr "" #: src/settings-alerts.php:376 msgid "Invalid number of failed logins per hour" msgstr "" #: src/settings-alerts.php:401 msgid "Receive email alerts for changes in the settings of the plugin" msgstr "" #: src/settings-alerts.php:402 msgid "Receive email alerts in HTML (there may be issues with some mail services)" msgstr "" #: src/settings-alerts.php:403 msgid "Use WordPress functions to send mails (uncheck to use native PHP functions)" msgstr "" #: src/settings-alerts.php:404 msgid "Allow redirection after login to report the last-login information" msgstr "" #: src/settings-alerts.php:405 msgid "Receive email alerts for core integrity checks" msgstr "" #: src/settings-alerts.php:406 msgid "Receive email alerts for available updates" msgstr "" #: src/settings-alerts.php:407 msgid "Receive email alerts for new user registration" msgstr "" #: src/settings-alerts.php:408 msgid "Receive email alerts for successful login attempts" msgstr "" #: src/settings-alerts.php:409 msgid "Receive email alerts for failed login attempts (you may receive tons of emails)" msgstr "" #: src/settings-alerts.php:410 msgid "Receive email alerts for password guessing attacks (summary of failed logins per hour)" msgstr "" #: src/settings-alerts.php:411 msgid "Receive email alerts for changes in the post status (configure from Ignore Posts Changes)" msgstr "" #: src/settings-alerts.php:412 msgid "Receive email alerts when the WordPress version is updated" msgstr "" #: src/settings-alerts.php:413 msgid "Receive email alerts when your website settings are updated" msgstr "" #: src/settings-alerts.php:414 msgid "Receive email alerts when a file is modified with theme/plugin editor" msgstr "" #: src/settings-alerts.php:415 msgid "Receive email alerts when a plugin is installed" msgstr "" #: src/settings-alerts.php:416 msgid "Receive email alerts when a plugin is activated" msgstr "" #: src/settings-alerts.php:417 msgid "Receive email alerts when a plugin is deactivated" msgstr "" #: src/settings-alerts.php:418 msgid "Receive email alerts when a plugin is updated" msgstr "" #: src/settings-alerts.php:419 msgid "Receive email alerts when a plugin is deleted" msgstr "" #: src/settings-alerts.php:420 msgid "Receive email alerts when a widget is added to a sidebar" msgstr "" #: src/settings-alerts.php:421 msgid "Receive email alerts when a widget is deleted from a sidebar" msgstr "" #: src/settings-alerts.php:422 msgid "Receive email alerts when a theme is installed" msgstr "" #: src/settings-alerts.php:423 msgid "Receive email alerts when a theme is activated" msgstr "" #: src/settings-alerts.php:424 msgid "Receive email alerts when a theme is updated" msgstr "" #: src/settings-alerts.php:425 msgid "Receive email alerts when a theme is deleted" msgstr "" #: src/settings-alerts.php:469 msgid "A total of %s alert events were changed" msgstr "" #: src/settings-alerts.php:473 msgid "The alert settings have been updated" msgstr "" #: src/settings-alerts.php:547 msgid "Only lowercase letters, numbers, underscores and hyphens are allowed. Post Types cannot exceed 20 characters as well." msgstr "" #: src/settings-alerts.php:549 msgid "The post-type is already being ignored (duplicate)." msgstr "" #: src/settings-alerts.php:553 msgid "Post-type has been successfully ignored." msgstr "" #: src/settings-alerts.php:555 msgid "Changes in %s post-type will be ignored" msgstr "" #: src/settings-alerts.php:570 msgid "List of monitored post-types has been updated." msgstr "" #: src/settings-alerts.php:572 msgid "List of monitored post-types has been updated" msgstr "" #: src/settings-alerts.php:579 #: src/settings-scanner.php:179 #: src/settings-scanner.php:239 #: src/strings.php:47 #: src/strings.php:180 #: src/strings.php:192 #: src/strings.php:206 #: src/strings.php:311 #: src/strings.php:423 #: src/strings.php:532 msgid "no data available" msgstr "" #: src/settings-apiservice.php:43 msgid "The status of the API service could not be enabled because the required SUCURISCAN_API_URL configuration was not found." msgstr "" #: src/settings-apiservice.php:46 msgid "API service communication was %s" msgstr "" #: src/settings-apiservice.php:51 msgid "The status of the API service has been changed" msgstr "" #: src/settings-apiservice.php:60 #: src/settings-general.php:211 #: src/settings-general.php:277 #: src/settings-general.php:324 #: src/settings-headers.php:126 #: src/settings-integrity.php:80 #: src/strings.php:618 msgid "Enabled" msgstr "" #: src/settings-apiservice.php:61 #: src/settings-general.php:212 #: src/settings-general.php:278 #: src/settings-general.php:325 #: src/settings-integrity.php:81 msgid "Disable" msgstr "" #: src/settings-apiservice.php:69 #: src/settings-general.php:254 #: src/settings-general.php:298 #: src/settings-general.php:359 #: src/settings-headers.php:126 #: src/strings.php:619 msgid "Disabled" msgstr "" #: src/settings-apiservice.php:70 #: src/settings-general.php:255 #: src/settings-general.php:299 #: src/settings-general.php:360 msgid "Enable" msgstr "" #: src/settings-apiservice.php:83 msgid "NONE" msgstr "" #: src/settings-apiservice.php:143 #: src/settings-apiservice.php:150 msgid "Core integrity API changed: %s" msgstr "" #: src/settings-apiservice.php:146 #: src/settings-apiservice.php:153 msgid "The URL to retrieve the WordPress checksums has been changed" msgstr "" #: src/settings-general.php:38 #: src/settings-general.php:44 msgid "Local security logs, hardening and settings were deleted" msgstr "" #: src/settings-general.php:63 msgid "Directory used to store the plugin settings, cache and system logs" msgstr "" #: src/settings-general.php:64 msgid "Cache to store the system logs obtained from the API service; expires after %s seconds." msgstr "" #: src/settings-general.php:65 msgid "Local queue to store the most recent logs before they are sent to the remote API service." msgstr "" #: src/settings-general.php:66 msgid "Deprecated on 1.8.12; it was used to store a list of blocked user names." msgstr "" #: src/settings-general.php:67 msgid "Stores the data for every failed login attempt. The data is moved to \"oldfailedlogins\" every hour during a brute force password attack." msgstr "" #: src/settings-general.php:68 msgid "Temporarily stores data to complement the logs during destructive operations like deleting a post, page, comment, etc." msgstr "" #: src/settings-general.php:69 msgid "Stores a list of files and folders chosen by the user to be ignored by the file system scanner." msgstr "" #: src/settings-general.php:70 msgid "Stores a list of files marked as fixed by the user via the WordPress Integrity tool." msgstr "" #: src/settings-general.php:71 msgid "Stores the data associated to every successful user login. The data never expires; manually delete if the file is too large." msgstr "" #: src/settings-general.php:72 msgid "Stores the data for every failed login attempt after the plugin sends a report about a brute force password attack via email." msgstr "" #: src/settings-general.php:73 msgid "Cache to store the data associated to the installed plugins listed in the Post-Hack page. Expires after %s seconds." msgstr "" #: src/settings-general.php:74 msgid "Stores all the options used to configure the functionality and behavior of the plugin." msgstr "" #: src/settings-general.php:75 msgid "Cache to store the result of the malware scanner. Expires after %s seconds, reset at any time to force a re-scan." msgstr "" #: src/settings-general.php:76 msgid "Stores a list of IP addresses trusted by the plugin, events triggered by one of these IPs will not be reported to the remote monitoring API service." msgstr "" #: src/settings-general.php:111 msgid "%s were deleted." msgstr "" #: src/settings-general.php:118 msgid "%d out of %d files have been deleted." msgstr "" #: src/settings-general.php:136 #: src/settings-posthack.php:368 msgid "Not Writable" msgstr "" #: src/settings-general.php:137 msgid "Does Not Exist" msgstr "" #: src/settings-general.php:143 msgid "Exists" msgstr "" #: src/settings-general.php:149 #: src/strings.php:364 msgid "Writable" msgstr "" #: src/settings-general.php:223 msgid "Log exporter was disabled" msgstr "" #: src/settings-general.php:229 msgid "The log exporter feature has been disabled" msgstr "" #: src/settings-general.php:231 msgid "File should not be publicly accessible." msgstr "" #: src/settings-general.php:233 msgid "File already exists and will not be overwritten." msgstr "" #: src/settings-general.php:235 msgid "File parent directory is not writable." msgstr "" #: src/settings-general.php:239 msgid "Log exporter file path was correctly set" msgstr "" #: src/settings-general.php:245 msgid "The log exporter feature has been enabled and the data file was successfully set." msgstr "" #: src/settings-general.php:321 msgid "INVALID" msgstr "" #: src/settings-general.php:339 msgid "DNS lookups for reverse proxy detection %s" msgstr "" #: src/settings-general.php:344 msgid "The status of the DNS lookups for the reverse proxy detection has been changed" msgstr "" #: src/settings-general.php:492 msgid "%d out of %d option have been successfully imported" msgstr "" #: src/settings-general.php:498 msgid "Data is incorrectly encoded" msgstr "" #: src/settings-general.php:556 msgid "Timezone override will use %s" msgstr "" #: src/settings-general.php:561 msgid "The timezone for the date and time in the audit logs has been changed" msgstr "" #: src/settings-hardening.php:100 msgid "The firewall is a premium service that you need purchase at - Sucuri Firewall" msgstr "" #: src/settings-hardening.php:108 msgid "Enable Website Firewall Protection" msgstr "" #: src/settings-hardening.php:109 msgid "A WAF is a protection layer for your web site, blocking all sort of attacks (brute force attempts, DDoS, SQL injections, etc) and helping it remain malware and blocklist free. This test checks if your site is using Sucuri Firewall to protect your site." msgstr "" #: src/settings-hardening.php:116 #: src/settings-hardening.php:277 #: src/settings-hardening.php:339 #: src/settings-hardening.php:414 #: src/settings-hardening.php:458 #: src/settings-hardening.php:501 #: src/settings-hardening.php:616 #: src/settings-hardening.php:669 msgid "Apply Hardening" msgstr "" #: src/settings-hardening.php:120 #: src/settings-hardening.php:176 #: src/settings-hardening.php:269 #: src/settings-hardening.php:273 #: src/settings-hardening.php:331 #: src/settings-hardening.php:335 #: src/settings-hardening.php:406 #: src/settings-hardening.php:410 #: src/settings-hardening.php:461 #: src/settings-hardening.php:497 #: src/settings-hardening.php:612 #: src/settings-hardening.php:674 msgid "Revert Hardening" msgstr "" #: src/settings-hardening.php:145 msgid "Check Updates Now" msgstr "" #: src/settings-hardening.php:146 msgid "Verify WordPress Version" msgstr "" #: src/settings-hardening.php:147 msgid "Why keep your site updated? WordPress is an open-source project which means that with every update the details of the changes made to the source code are made public, if there were security fixes then someone with malicious intent can use this information to attack any site that has not been upgraded." msgstr "" #: src/settings-hardening.php:154 msgid "WordPress Update Available" msgstr "" #: src/settings-hardening.php:174 msgid "Remove WordPress Version" msgstr "" #: src/settings-hardening.php:178 msgid "It checks if your WordPress version is being leaked to the public via a HTML meta-tag. Many web vulnerability scanners use this to determine which version of the code is running in your website. They use this to find disclosed vulnerabilities associated to this version number. A vulnerability scanner can still guess which version of WordPress is installed by comparing the checksum of some static files." msgstr "" #: src/settings-hardening.php:201 msgid "Read the official WordPress guidelines to learn how to restrict access to PHP files in sensitive directories - Nginx Global Restrictions For WordPress" msgstr "" #: src/settings-hardening.php:208 msgid "Block of Certain PHP Files" msgstr "" #: src/settings-hardening.php:211 msgid "Check Hardening" msgstr "" #: src/settings-hardening.php:212 #: src/settings-hardening.php:261 #: src/settings-hardening.php:323 #: src/settings-hardening.php:398 msgid "Block the execution of PHP files in sensitive directories. Be careful while applying this hardening option as there are many plugins and theme which rely on the ability to execute PHP files in the content directory to generate images or save temporary data. Use the \"Add PHP Files to the Allowlist\" tool to add exceptions to individual files." msgstr "" #: src/settings-hardening.php:242 #: src/settings-hardening.php:243 msgid "Hardening applied to the uploads directory" msgstr "" #: src/settings-hardening.php:245 #: src/settings-hardening.php:307 #: src/settings-hardening.php:380 msgid "Error hardening directory, check the permissions." msgstr "" #: src/settings-hardening.php:253 #: src/settings-hardening.php:254 msgid "Hardening reverted in the uploads directory" msgstr "" #: src/settings-hardening.php:256 #: src/settings-hardening.php:318 #: src/settings-hardening.php:393 msgid "Access file is not writable, check the permissions." msgstr "" #: src/settings-hardening.php:260 msgid "Block PHP Files in Uploads Directory" msgstr "" #: src/settings-hardening.php:304 #: src/settings-hardening.php:305 msgid "Hardening applied to the content directory" msgstr "" #: src/settings-hardening.php:315 #: src/settings-hardening.php:316 msgid "Hardening reverted in the content directory" msgstr "" #: src/settings-hardening.php:322 msgid "Block PHP Files in WP-CONTENT Directory" msgstr "" #: src/settings-hardening.php:371 #: src/settings-hardening.php:375 msgid "Hardening applied to the library directory" msgstr "" #: src/settings-hardening.php:390 #: src/settings-hardening.php:391 msgid "Hardening reverted in the library directory" msgstr "" #: src/settings-hardening.php:397 msgid "Block PHP Files in WP-INCLUDES Directory" msgstr "" #: src/settings-hardening.php:434 msgid "Cannot delete %s/readme.html" msgstr "" #: src/settings-hardening.php:438 #: src/settings-hardening.php:442 msgid "Hardening applied to the readme.html file" msgstr "" #: src/settings-hardening.php:449 msgid "Avoid Information Leakage" msgstr "" #: src/settings-hardening.php:450 msgid "Checks if the WordPress README file still exists in the website. The information in this file can be used by malicious users to pin-point which disclosed vulnerabilities are associated to the website. Be aware that WordPress recreates this file automatically with every update." msgstr "" #: src/settings-hardening.php:488 msgid "Verify Default Admin Account" msgstr "" #: src/settings-hardening.php:489 msgid "Check if the primary user account still uses the name \"admin\". This allows malicious users to easily identify which account has the highest privileges to target an attack." msgstr "" #: src/settings-hardening.php:521 #: src/settings-hardening.php:562 msgid "WordPress configuration file was not found." msgstr "" #: src/settings-hardening.php:523 #: src/settings-hardening.php:564 #: src/settings-posthack.php:76 msgid "WordPress configuration file is not writable." msgstr "" #: src/settings-hardening.php:550 #: src/settings-hardening.php:554 msgid "Hardening applied to the plugin and theme editor" msgstr "" #: src/settings-hardening.php:582 msgid "File Editor was not disabled using this tool. You must scan your project for a constant defined as DISALLOW_FILE_EDIT, then either delete it or set its value to False. Any plugin/theme can disable the file editor, so it is impossible to determine the origin of the constant." msgstr "" #: src/settings-hardening.php:591 #: src/settings-hardening.php:595 msgid "Hardening reverted in the plugin and theme editor" msgstr "" #: src/settings-hardening.php:603 msgid "Disable Plugin and Theme Editor" msgstr "" #: src/settings-hardening.php:604 msgid "Disables the theme and plugin editors to prevent unwanted modifications to the code. If you are having problems reverting this please open the wp-config.php file and delete the line with the constant DISALLOW_FILE_EDIT." msgstr "" #: src/settings-hardening.php:639 msgid "Automatic Secret Keys Updater enabled. The default frequency is \"Weekly\", but you can change the frequency on Settings -> Post-Hack -> Update Secret Keys section." msgstr "" #: src/settings-hardening.php:643 #: src/settings-posthack.php:158 #: src/settings-posthack.php:159 msgid "Automatic Secret Keys Updater enabled." msgstr "" #: src/settings-hardening.php:645 #: src/settings-hardening.php:655 #: src/settings-posthack.php:150 #: src/settings-posthack.php:161 msgid "Something went wrong." msgstr "" #: src/settings-hardening.php:652 #: src/settings-hardening.php:653 #: src/settings-posthack.php:147 #: src/settings-posthack.php:148 msgid "Automatic Secret Keys Updater disabled." msgstr "" #: src/settings-hardening.php:661 msgid "Activate Automatic Secret Keys Updater" msgstr "" #: src/settings-hardening.php:662 msgid "Changing the Secret Keys will invalidate all existing cookies, forcing all logged in users to login again. Doing this frequently will decrease the chances of misuse of sessions left open on unprotected devices." msgstr "" #: src/settings-hardening.php:716 msgid "The file has been allowed" msgstr "" #: src/settings-hardening.php:721 msgid "Specified folder is not hardened by this plugin" msgstr "" #: src/settings-hardening.php:748 msgid "Some files could not be removed" msgstr "" #: src/settings-hardening.php:750 msgid "Selected files have been removed" msgstr "" #: src/settings-headers.php:46 msgid "disabled" msgstr "" #: src/settings-headers.php:47 msgid "static" msgstr "" #: src/settings-headers.php:48 msgid "occasional" msgstr "" #: src/settings-headers.php:49 msgid "frequent" msgstr "" #: src/settings-headers.php:50 msgid "busy" msgstr "" #: src/settings-headers.php:51 msgid "custom" msgstr "" #: src/settings-headers.php:87 msgid "Cache-Control header was deactivated." msgstr "" #: src/settings-headers.php:89 msgid "Cache-Control header was activated." msgstr "" #: src/settings-headers.php:92 msgid "Invalid cache control mode selected." msgstr "" #: src/settings-integrity.php:65 msgid "Your hosting provider has blocked the execution of external commands." msgstr "" #: src/settings-integrity.php:68 msgid "Integrity diff utility has been %s" msgstr "" #: src/settings-integrity.php:73 msgid "The status of the integrity diff utility has been changed" msgstr "" #: src/settings-integrity.php:112 msgid "Core files that will not be ignored anymore: (multiple entries): %s" msgstr "" #: src/settings-integrity.php:114 msgid "The selected files have been successfully processed." msgstr "" #: src/settings-posthack.php:63 msgid "WordPress configuration file was not found or new keys could not be created." msgstr "" #: src/settings-posthack.php:65 msgid "Generate new security keys (success)" msgstr "" #: src/settings-posthack.php:66 msgid "Secret keys updated successfully (summary of the operation bellow)." msgstr "" #: src/settings-posthack.php:69 msgid "Old Security Keys" msgstr "" #: src/settings-posthack.php:72 msgid "New Security Keys" msgstr "" #: src/settings-posthack.php:75 msgid "Generate new security keys (failure)" msgstr "" #: src/settings-posthack.php:140 msgid "No frequency selected for the automatic secret key updater." msgstr "" #: src/settings-posthack.php:263 msgid "Password changed for user #%d" msgstr "" #: src/settings-posthack.php:358 msgid "not installed" msgstr "" #: src/settings-posthack.php:365 msgid "Plugin is Premium" msgstr "" #: src/settings-posthack.php:371 msgid "Missing Library" msgstr "" #: src/settings-posthack.php:381 msgid "Cannot Download" msgstr "" #: src/settings-posthack.php:384 msgid "Cannot Backup" msgstr "" #: src/settings-posthack.php:397 msgid "Cannot Install" msgstr "" #: src/settings-posthack.php:406 msgid "Installed v%s" msgstr "" #: src/settings-posthack.php:480 msgid "Newest WordPress" msgstr "" #: src/settings-posthack.php:518 msgid "There are no updates available." msgstr "" #: src/settings-scanner.php:68 msgid "%d tasks has been scheduled to run in the next ten seconds." msgstr "" #: src/settings-scanner.php:74 msgid "Force execution of scheduled tasks: (multiple entries): %s" msgstr "" #: src/settings-scanner.php:86 msgid "%d scheduled tasks have been removed." msgstr "" #: src/settings-scanner.php:92 msgid "Delete scheduled tasks: (multiple entries): %s" msgstr "" #: src/settings-scanner.php:103 msgid "%d tasks has been re-scheduled to run %s." msgstr "" #: src/settings-scanner.php:110 msgid "Re-configure scheduled tasks %s: (multiple entries): %s" msgstr "" #: src/settings-scanner.php:122 msgid "No scheduled tasks were selected from the list." msgstr "" #: src/settings-scanner.php:131 msgid "Execute Now (in +10 seconds)" msgstr "" #: src/settings-scanner.php:207 #: src/settings-scanner.php:216 msgid "Selected files have been successfully processed." msgstr "" #: src/settings-scanner.php:208 msgid "This directory will not be scanned: %s" msgstr "" #: src/settings-scanner.php:218 msgid "Directories will be scanned: (multiple entries): " msgstr "" #: src/settings-webinfo.php:39 msgid "not active" msgstr "" #: src/settings-webinfo.php:52 msgid "active" msgstr "" #: src/sitecheck.lib.php:178 msgid "PHP Version: %s" msgstr "" #: src/sitecheck.lib.php:179 msgid "Version: %s" msgstr "" #: src/sitecheck.lib.php:191 msgid "Hosting: %s" msgstr "" #: src/sitecheck.lib.php:197 msgid "CMS: %s" msgstr "" #: src/sitecheck.lib.php:275 #: src/sitecheck.lib.php:292 msgid "Site is not Clean" msgstr "" #: src/sitecheck.lib.php:331 msgid "Not blocklisted" msgstr "" #: src/sitecheck.lib.php:356 msgid "In the blocklist" msgstr "" #: src/sitecheck.lib.php:410 msgid "iFrames: %d" msgstr "" #: src/sitecheck.lib.php:425 msgid "Links: %d" msgstr "" #: src/sitecheck.lib.php:446 msgid "Scripts: %d" msgstr "" #: src/strings.php:27 msgid "Total logs in the queue:" msgstr "" #: src/strings.php:28 msgid "Maximum execution time:" msgstr "" #: src/strings.php:29 msgid "Successfully sent to the API:" msgstr "" #: src/strings.php:30 msgid "Total request timeouts (failures):" msgstr "" #: src/strings.php:31 msgid "Total execution time:" msgstr "" #: src/strings.php:32 msgid "Send Logs" msgstr "" #: src/strings.php:36 msgid "WP Plugin" msgstr "" #: src/strings.php:37 msgid "Review" msgstr "" #: src/strings.php:38 #: src/template.lib.php:136 msgid "Generate API Key" msgstr "" #: src/strings.php:42 msgid "Copyright" msgstr "" #: src/strings.php:43 msgid "Sucuri Inc. All Rights Reserved." msgstr "" #: src/strings.php:44 msgid "Help & More" msgstr "" #: src/strings.php:48 #: src/strings.php:107 msgid "Audit Logs" msgstr "" #: src/strings.php:51 msgid "Firewall Audit Logs" msgstr "" #: src/strings.php:52 msgid "The firewall logs every request involved in an attack and separates them from the legitimate requests. You can analyze the data from the latest entries in the logs using this tool and take action either enabling the advanced features of the IDS (Intrusion Detection System) from the Firewall Dashboard and/or blocking IP addresses and URL paths directly from the Firewall Audit Trails page." msgstr "" #: src/strings.php:54 msgid "Non-blocked requests are hidden from the logs, this is intentional." msgstr "" #: src/strings.php:56 #: src/strings.php:80 #: src/strings.php:145 #: src/strings.php:241 #: src/strings.php:248 #: src/strings.php:256 #: src/strings.php:266 #: src/strings.php:279 #: src/strings.php:287 #: src/strings.php:298 #: src/strings.php:306 #: src/strings.php:320 #: src/strings.php:336 #: src/strings.php:372 #: src/strings.php:392 #: src/strings.php:404 #: src/strings.php:411 #: src/strings.php:418 #: src/strings.php:461 #: src/strings.php:477 #: src/strings.php:493 #: src/strings.php:510 #: src/strings.php:518 #: src/strings.php:596 msgid "Submit" msgstr "" #: src/strings.php:59 #: src/strings.php:224 msgid "Date/Time:" msgstr "" #: src/strings.php:60 msgid "Signature:" msgstr "" #: src/strings.php:61 msgid "Request:" msgstr "" #: src/strings.php:62 msgid "U-Agent:" msgstr "" #: src/strings.php:63 msgid "Target:" msgstr "" #: src/strings.php:64 msgid "Referer:" msgstr "" #: src/strings.php:68 msgid "Clear cache when a post or page is updated (Loading...)" msgstr "" #: src/strings.php:69 msgid "Clear cache when a post or page is updated" msgstr "" #: src/strings.php:70 #: src/strings.php:109 msgid "Clear Cache" msgstr "" #: src/strings.php:71 msgid "The firewall offers multiple options to configure the cache level applied to your website. You can either enable the full cache which is the recommended setting, or you can set the cache level to minimal which will keep the pages static for a couple of minutes, or force the usage of the website headers (only for advanced users), or in extreme cases where you do not need the cache you can simply disable it. Find more information about it in the Sucuri Knowledge Base website." msgstr "" #: src/strings.php:73 msgid "Note that the firewall has special caching rules for Images, CSS, PDF, TXT, JavaScript, media files and a few more extensions that are stored on our edge. The only way to flush the cache for these files is by clearing the firewall’s cache completely (for the whole website). Due to our caching of JavaScript and CSS files, often, as is best practice, the use of versioning during development will ensure updates going live as expected. This is done by adding a query string such as ?ver=1.2.3 and incrementing on each update." msgstr "" #: src/strings.php:75 msgid "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. — WikiPedia - Web Cache" msgstr "" #: src/strings.php:79 #: src/strings.php:98 #: src/strings.php:290 #: src/strings.php:312 #: src/strings.php:365 #: src/strings.php:424 msgid "Delete" msgstr "" #: src/strings.php:82 msgid "IP Address Access" msgstr "" #: src/strings.php:83 msgid "This tool allows you to add one or more IP addresses to the blocklist and stop them from accessing your website." msgstr "" #: src/strings.php:85 msgid "To delete an IP from the blocklist you can use the form below or you can log into the Firewall dashboard." msgstr "" #: src/strings.php:87 msgid "Add IP to the Blocklist:" msgstr "" #: src/strings.php:88 msgid "e.g. 192.168.1.54" msgstr "" #: src/strings.php:92 msgid "Firewall Settings" msgstr "" #: src/strings.php:93 msgid "A powerful Web Application Firewall and Intrusion Detection System for any WordPress user and many other platforms. This page will help you to configure and monitor your site through the Sucuri Firewall. Once enabled, our firewall will act as a shield, protecting your site from attacks and preventing malware infections and reinfections. It will block SQL injection attempts, brute force attacks, XSS, RFI, backdoors and many other threats against your site." msgstr "" #: src/strings.php:95 msgid "Add your Firewall API key in the form below to start communicating with the firewall API service." msgstr "" #: src/strings.php:97 msgid "Firewall API Key:" msgstr "" #: src/strings.php:99 msgid "Save" msgstr "" #: src/strings.php:100 #: src/strings.php:429 #: src/strings.php:438 #: src/strings.php:473 #: src/strings.php:485 #: src/strings.php:504 msgid "Name" msgstr "" #: src/strings.php:101 #: src/strings.php:486 msgid "Value" msgstr "" #: src/strings.php:102 msgid "[1] More information about the Sucuri Firewall, features and pricing.
    [2] Instructions and videos in the official Knowledge Base site.
    [3] Sign up for a new account and start protecting your site." msgstr "" #: src/strings.php:108 msgid "IP Access" msgstr "" #: src/strings.php:112 #: src/strings.php:126 #: src/strings.php:161 msgid "WordPress Integrity" msgstr "" #: src/strings.php:113 #: src/strings.php:127 #: src/strings.php:162 msgid "We inspect your WordPress installation and look for modifications on the core files as provided by WordPress.org. Files located in the root directory, wp-admin and wp-includes will be compared against the files distributed with v%%SUCURI.WordPressVersion%%; all files with inconsistencies will be listed here. Any changes might indicate a hack." msgstr "" #: src/strings.php:115 msgid "All Core WordPress Files Are Correct" msgstr "" #: src/strings.php:116 msgid "We have not identified additional files, deleted files, or relevant changes to the core files in your WordPress installation. If you are experiencing other malware issues, please use a Server Side Scanner." msgstr "" #: src/strings.php:118 #: src/strings.php:132 msgid "Review False Positives" msgstr "" #: src/strings.php:122 msgid "Lines with a minus sign as the prefix (here in red) show the original code. Lines with a plus sign as the prefix (here in green) show the modified code. You can read more about the DIFF format from the WikiPedia article about the Unix Diff Utility." msgstr "" #: src/strings.php:129 msgid "Core WordPress Files Were Modified" msgstr "" #: src/strings.php:130 #: src/strings.php:150 msgid "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 Server Side Scanner." msgstr "" #: src/strings.php:133 #: src/strings.php:152 msgid "WordPress Integrity (%%SUCURI.Integrity.ListCount%%)" msgstr "" #: src/strings.php:134 msgid "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 advised to restore the original content immediately." msgstr "" #: src/strings.php:136 #: src/strings.php:254 #: src/strings.php:269 #: src/strings.php:288 #: src/strings.php:307 #: src/strings.php:360 #: src/strings.php:419 #: src/strings.php:456 #: src/strings.php:472 #: src/strings.php:503 #: src/strings.php:519 #: src/strings.php:528 msgid "Select All" msgstr "" #: src/strings.php:137 #: src/strings.php:154 #: src/strings.php:362 msgid "File Size" msgstr "" #: src/strings.php:138 #: src/strings.php:155 msgid "Modified At" msgstr "" #: src/strings.php:139 #: src/strings.php:156 #: src/strings.php:361 #: src/strings.php:420 #: src/strings.php:520 #: src/strings.php:531 msgid "File Path" msgstr "" #: src/strings.php:140 #: src/strings.php:371 #: src/strings.php:391 #: src/strings.php:487 msgid "I understand that this operation cannot be reverted." msgstr "" #: src/strings.php:141 #: src/strings.php:509 msgid "Action:" msgstr "" #: src/strings.php:142 msgid "Mark as Fixed" msgstr "" #: src/strings.php:143 msgid "Restore File" msgstr "" #: src/strings.php:144 msgid "Delete File" msgstr "" #: src/strings.php:146 #: src/strings.php:157 msgid "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." msgstr "" #: src/strings.php:153 #: src/strings.php:363 #: src/strings.php:476 #: src/strings.php:484 #: src/strings.php:521 msgid "Status" msgstr "" #: src/strings.php:168 msgid "Admins" msgstr "" #: src/strings.php:169 msgid "Logged-in Users" msgstr "" #: src/strings.php:170 msgid "Failed Logins" msgstr "" #: src/strings.php:173 msgid "Successful Logins (admins)" msgstr "" #: src/strings.php:174 msgid "Here you can see a list of all the successful logins of accounts with admin privileges." msgstr "" #: src/strings.php:176 msgid "Registration" msgstr "" #: src/strings.php:177 msgid "Newest To Oldest" msgstr "" #: src/strings.php:182 #: src/strings.php:191 #: src/strings.php:204 msgid "Date/Time" msgstr "" #: src/strings.php:183 #: src/strings.php:220 msgid "Edit User Profile" msgstr "" #: src/strings.php:186 msgid "Successful Logins (all)" msgstr "" #: src/strings.php:187 msgid "Here you can see a list of all the successful user logins." msgstr "" #: src/strings.php:190 msgid "Hostname" msgstr "" #: src/strings.php:193 msgid "Delete All Successful Logins" msgstr "" #: src/strings.php:196 #: src/strings.php:622 #: src/strings.php:627 msgid "Edit" msgstr "" #: src/strings.php:199 msgid "Failed logins" msgstr "" #: src/strings.php:200 msgid "This information will be used to determine if your site is being victim of Password Guessing Brute Force Attacks. These logs will be accumulated and the plugin will send a report via email if there are more than %%SUCURI.FailedLogins.MaxFailedLogins%% failed login attempts during the same hour, you can change this number from here. NOTE: Some \"Two-Factor Authentication\" plugins do not follow the same rules that WordPress have to report failed login attempts, so you may not see all the attempts in this panel if you have one of these plugins installed." msgstr "" #: src/strings.php:205 msgid "Web Browser" msgstr "" #: src/strings.php:207 msgid "Block" msgstr "" #: src/strings.php:208 msgid "Delete All Failed Logins" msgstr "" #: src/strings.php:211 msgid "Logged-in Users}" msgstr "" #: src/strings.php:212 msgid "Here you can see a list of the users that are currently logged-in." msgstr "" #: src/strings.php:213 msgid "ID" msgstr "" #: src/strings.php:215 msgid "Last Activity" msgstr "" #: src/strings.php:216 #: src/strings.php:459 msgid "Registered" msgstr "" #: src/strings.php:221 #: src/strings.php:232 #: src/strings.php:381 msgid "Website:" msgstr "" #: src/strings.php:222 #: src/strings.php:304 msgid "IP Address:" msgstr "" #: src/strings.php:223 msgid "Reverse IP:" msgstr "" #: src/strings.php:225 msgid "Message:" msgstr "" #: src/strings.php:228 msgid "An API key is required to activate some additional tools available in this plugin. The keys are free and you can virtually generate an unlimited number of them as long as the domain name and email address are unique. The key is used to authenticate the HTTP requests sent by the plugin to an API service managed by Sucuri Inc." msgstr "" #: src/strings.php:230 msgid "If you experience issues generating the API key you can request one by sending the domain name and email address that you want to use to info@sucuri.net. Note that generating a key for a website that is not facing the Internet is not possible because the API service needs to validate that the domain name exists." msgstr "" #: src/strings.php:233 #: src/strings.php:285 msgid "E-mail:" msgstr "" #: src/strings.php:234 msgid "DNS Lookups" msgstr "" #: src/strings.php:235 msgid "Check the box if your website is behind a known firewall service, this guarantees that the IP address of your visitors will be detected correctly for the security logs. You can change this later from the settings." msgstr "" #: src/strings.php:237 msgid "Enable DNS Lookups On Startup" msgstr "" #: src/strings.php:238 msgid "I agree to the Terms of Service." msgstr "" #: src/strings.php:239 msgid "I have read and understand the Privacy Policy." msgstr "" #: src/strings.php:244 msgid "Password Guessing Brute Force Attacks" msgstr "" #: src/strings.php:245 msgid "Password guessing brute force attacks are very common against web sites and web servers. They are one of the most common vectors used to compromise web sites. The process is very simple and the attackers basically try multiple combinations of usernames and passwords until they find one that works. Once they get in, they can compromise the web site with malware, spam , phishing or anything else they want." msgstr "" #: src/strings.php:247 msgid "Consider Brute-Force Attack After:" msgstr "" #: src/strings.php:251 msgid "Security Alerts" msgstr "" #: src/strings.php:252 msgid "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." msgstr "" #: src/strings.php:255 msgid "Event" msgstr "" #: src/strings.php:259 msgid "Post-Type Alerts" msgstr "" #: src/strings.php:260 msgid "It seems that you disabled the email alerts for new site content, this panel is intended to provide a way to ignore specific events in your site and with that the alerts reported to your email. Since you have deactivated the new site content alerts, this panel will be disabled too." msgstr "" #: src/strings.php:262 msgid "This is a list of registered Post Types. You will receive an email alert when a custom page or post associated to any of these types is created or updated. If you don’t want to receive one or more of these alerts, feel free to uncheck the boxes in the table below. If you are receiving alerts for post types that are not listed in this table, it may be because there is an add-on that that is generating a custom post-type on runtime, you will have to find out by yourself what is the unique ID of that post-type and type it in the form below. The plugin will do its best to ignore these alerts as long as the unique ID is valid." msgstr "" #: src/strings.php:264 msgid "Stop Alerts For This Post-Type:" msgstr "" #: src/strings.php:265 msgid "e.g. unique_post_type_id" msgstr "" #: src/strings.php:267 msgid "Show Post-Types Table" msgstr "" #: src/strings.php:268 msgid "Hide Post-Types Table" msgstr "" #: src/strings.php:270 msgid "Post Type" msgstr "" #: src/strings.php:271 msgid "Post Type ID" msgstr "" #: src/strings.php:272 msgid "Ignored At (optional)" msgstr "" #: src/strings.php:275 msgid "Alerts Per Hour" msgstr "" #: src/strings.php:276 msgid "Configure the maximum number of email alerts per hour. If the number is exceeded and the plugin detects more events during the same hour, it will still log the events into the audit logs but will not send the email alerts. Be careful with this as you will miss important information." msgstr "" #: src/strings.php:278 msgid "Maximum Alerts Per Hour:" msgstr "" #: src/strings.php:282 msgid "Alerts Recipient" msgstr "" #: src/strings.php:283 msgid "By default, the plugin will send the email alerts to the primary admin account, the same account created during the installation of WordPress in your web server. You can add more people to the list, they will receive a copy of the same security alerts." msgstr "" #: src/strings.php:286 msgid "e.g. user@example.com" msgstr "" #: src/strings.php:289 #: src/strings.php:458 msgid "E-mail" msgstr "" #: src/strings.php:291 msgid "Test Alerts" msgstr "" #: src/strings.php:294 msgid "Alert Subject" msgstr "" #: src/strings.php:295 msgid "Format of the subject for the email alerts, by default the plugin will use the website name and the event identifier that is being reported, you can use this panel to include the IP address of the user that triggered the event and some additional data. You can create filters in your email client creating a custom email subject using the pseudo-tags shown below." msgstr "" #: src/strings.php:297 msgid "Custom Format" msgstr "" #: src/strings.php:301 msgid "Trusted IP Addresses" msgstr "" #: src/strings.php:302 msgid "If you are working in a LAN (Local Area Network) you may want to include the IP addresses of all the nodes in the subnet, this will force the plugin to stop sending email alerts about actions executed from trusted IP addresses. Use the CIDR (Classless Inter Domain Routing) format to specify ranges of IP addresses (only 8, 16, and 24)." msgstr "" #: src/strings.php:305 msgid "e.g. 182.120.56.0/24" msgstr "" #: src/strings.php:309 msgid "CIDR Format" msgstr "" #: src/strings.php:310 msgid "IP Added At" msgstr "" #: src/strings.php:315 msgid "If this operation was successful you will receive a message in the email used during the registration of the API key (usually the email of the main admin user). This message contains the key in plain text, copy and paste the key in the form field below. The plugin will verify the authenticity of the key sending an initial HTTP request to the API service, if this fails the key will be removed automatically and you will have to start the process all over again." msgstr "" #: src/strings.php:317 msgid "There are cases where this operation may fail, an example would be when the email address is not associated with the domain anymore, this happens when the base URL changes (from www to none or viceversa). If you are having issues recovering the key please send an email explaining the situation to info@sucuri.net" msgstr "" #: src/strings.php:319 msgid "API Key:" msgstr "" #: src/strings.php:323 msgid "Congratulations! The rest of the features available in the plugin have been enabled. This product is designed to supplement existing security products. It’s not a silver bullet for your security needs, but it’ll give you greater security awareness and better posture, all with the intent of reducing risk." msgstr "" #: src/strings.php:325 msgid "Your website has been granted a new API key and it was associated to the email address that you chose during the registration process. You can use the same email to recover the key if you happen to lose it sometime. We encourage you to check the rest of the settings page and configure the plugin to your own needs." msgstr "" #: src/strings.php:331 #: src/strings.php:334 msgid "WordPress Checksums API" msgstr "" #: src/strings.php:332 msgid "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 development version of the code." msgstr "" #: src/strings.php:335 msgid "e.g. URL — or — user/repo" msgstr "" #: src/strings.php:339 msgid "API Communication via Proxy" msgstr "" #: src/strings.php:340 msgid "All the HTTP requests used to communicate with the API service are being sent using the WordPress built-in functions, so (almost) all its official features are inherited, this is useful if you need to pass these HTTP requests through a proxy. According to the official documentation you have to add some constants to the main configuration file: WP_PROXY_HOST, WP_PROXY_PORT, WP_PROXY_USERNAME, WP_PROXY_PASSWORD." msgstr "" #: src/strings.php:342 msgid "HTTP Proxy Hostname" msgstr "" #: src/strings.php:343 msgid "HTTP Proxy Port num" msgstr "" #: src/strings.php:344 msgid "HTTP Proxy Username" msgstr "" #: src/strings.php:345 msgid "HTTP Proxy Password" msgstr "" #: src/strings.php:348 #: src/strings.php:562 msgid "API Service Communication" msgstr "" #: src/strings.php:349 msgid "Once the API key is generate the plugin will communicate with a remote API service that will act as a safe data storage for the audit logs generated when the website triggers certain events that the plugin monitors. If the website is hacked the attacker will not have access to these logs and that way you can investigate what was modified (for malware infaction) and/or how the malicious person was able to gain access to the website." msgstr "" #: src/strings.php:351 msgid "Disabling the API service communication will stop the event monitoring, consider to enable the Log Exporter to keep the monitoring working while the HTTP requests are ignored, otherwise an attacker may execute an action that will not be registered in the security logs and you will not have a way to investigate the attack in the future." msgstr "" #: src/strings.php:353 msgid "Are you a developer? You may be interested in our API. Feel free to use the URL shown below to access the latest 50 entries in your security log, change the value for the parameter l=N if you need more. Be aware that the API doesn’t provides an offset parameter, so if you have the intention to query specific sections of the log you will need to wrap the HTTP request around your own cache mechanism. We DO NOT take feature requests for the API, this is a semi-private service tailored for the specific needs of the plugin and not intended to be used by 3rd-party apps, we may change the behavior of each API endpoint without previous notice, use it at your own risk." msgstr "" #: src/strings.php:357 msgid "Data Storage" msgstr "" #: src/strings.php:358 msgid "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 (one level up the document root) please define a constant in the \"wp-config.php\" file named \"SUCURI_DATA_STORAGE\" with the absolute path to the new directory." msgstr "" #: src/strings.php:368 msgid "Import & Export Settings" msgstr "" #: src/strings.php:369 msgid "Copy the JSON-encoded data from the box below, go to your other websites and click the \"Import\" button in the settings page. The plugin will start using the same settings from this website. Notice that some options are omitted as they contain values specific to this website. To import the settings from another website into this one, replace the JSON-encoded data in the box below with the JSON-encoded data exported from the other website, then click the button \"Import\". Notice that some options will not be imported to reduce the security risk of writing arbitrary data into the disk." msgstr "" #: src/strings.php:375 msgid "IP Address Discoverer" msgstr "" #: src/strings.php:376 msgid "IP address discoverer will use DNS lookups to automatically detect if the website is behind the Sucuri Firewall, in which case it will modify the global server variable Remote-Addr to set the real IP of the website’s visitors. This check runs on every WordPress init action and that is why it may slow down your website as some hosting providers rely on slow DNS servers which makes the operation take more time than it should." msgstr "" #: src/strings.php:378 msgid "HTTP Header:" msgstr "" #: src/strings.php:379 msgid "Proceed" msgstr "" #: src/strings.php:380 msgid "Sucuri Firewall" msgstr "" #: src/strings.php:382 msgid "Top Level Domain:" msgstr "" #: src/strings.php:383 msgid "Hostname:" msgstr "" #: src/strings.php:384 msgid "IP Address (Hostname):" msgstr "" #: src/strings.php:385 msgid "IP Address (Username):" msgstr "" #: src/strings.php:388 msgid "Reset Security Logs, Hardening and Settings" msgstr "" #: src/strings.php:389 msgid "This action will trigger the deactivation / uninstallation process of the plugin. All local security logs, hardening and settings will be deleted. Notice that the security logs stored in the API service will not be deleted, this is to prevent tampering from a malicious user. You can request a new API key if you want to start from scratch." msgstr "" #: src/strings.php:395 msgid "Reverse Proxy" msgstr "" #: src/strings.php:396 msgid "The event monitor uses the API address of the origin of the request to track the actions. The plugin uses two methods to retrieve this: the main method uses the global server variable Remote-Addr available in most modern web servers, and an alternative method uses custom HTTP headers (which are unsafe by default). You should not worry about this option unless you know what a reverse proxy is. Services like the Sucuri Firewall — once active — force the network traffic to pass through them to filter any security threat that may affect the original server. A side effect of this is that the real IP address is no longer available in the global server variable Remote-Addr but in a custom HTTP header with a name provided by the service." msgstr "" #: src/strings.php:400 msgid "Log Exporter" msgstr "" #: src/strings.php:401 msgid "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 (we recommend OSSEC). That will give visibility from within WordPress to complement your log monitoring infrastructure. NOTE: 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." msgstr "" #: src/strings.php:403 #: src/strings.php:417 msgid "File Path:" msgstr "" #: src/strings.php:407 msgid "Timezone Override" msgstr "" #: src/strings.php:408 msgid "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." msgstr "" #: src/strings.php:410 msgid "Timezone:" msgstr "" #: src/strings.php:414 msgid "Allow Blocked PHP Files" msgstr "" #: src/strings.php:415 msgid "After you apply the hardening in either the includes, content, and/or uploads directories, the plugin will add a rule in the access control file to deny access to any PHP file located in these folders. This is a good precaution in case an attacker is able to upload a shell script. With a few exceptions the \"index.php\" file is the only one that should be publicly accessible, however many theme/plugin developers decide to use these folders to process some operations. In this case applying the hardening may break their functionality." msgstr "" #: src/strings.php:421 msgid "Directory" msgstr "" #: src/strings.php:422 msgid "Pattern" msgstr "" #: src/strings.php:427 #: src/strings.php:436 msgid "WordPress has a big user base in the public Internet, which brings interest to attackers to find vulnerabilities in the code, 3rd-party extensions, and themes that other companies develop. You should keep every piece of code installed in your website updated to prevent attacks as soon as disclosed vulnerabilities are patched." msgstr "" #: src/strings.php:430 #: src/strings.php:439 #: src/strings.php:474 msgid "Version" msgstr "" #: src/strings.php:431 #: src/strings.php:440 #: src/strings.php:621 msgid "Update" msgstr "" #: src/strings.php:432 #: src/strings.php:441 msgid "Tested With" msgstr "" #: src/strings.php:435 msgid "Available Plugin and Theme Updates" msgstr "" #: src/strings.php:445 msgid "Download" msgstr "" #: src/strings.php:448 msgid "WordPress has invalidated the password for your account %%SUCURI.ResetPassword.UserName%% at %%SUCURI.ResetPassword.Website%%. The change has been requested by one of the admins in this website for security reasons. You can set a new password at — %%%SUCURI.ResetPassword.ResetURL%%% —." msgstr "" #: src/strings.php:452 msgid "Reset User Password" msgstr "" #: src/strings.php:454 msgid "Select users from the list in order to change their passwords, terminate their sessions and email them a password reset link. Please be aware that the plugin will change the passwords before sending the emails, meaning that if your web server is unable to send emails, your users will be locked out of the site." msgstr "" #: src/strings.php:460 msgid "Roles" msgstr "" #: src/strings.php:464 msgid "Reset Installed Plugins" msgstr "" #: src/strings.php:466 msgid "In case you suspect having an infection in your site, or after you got rid of a malicious code, it’s recommended to reinstall all the plugins installed in your site, including the ones you are not using. Notice that premium plugins will not be automatically reinstalled to prevent backward compatibility issues and problems with licenses." msgstr "" #: src/strings.php:468 msgid "The information shown here is cached for %%SUCURI.ResetPlugin.CacheLifeTime%% seconds. This is necessary to reduce the quantity of HTTP requests sent to the WordPress servers and the bandwidth of your site. Currently there is no option to recreate this cache." msgstr "" #: src/strings.php:470 msgid "WARNING! This procedure can break your website. The reset will not affect the database nor the settings of each plugin, but depending on how they were written the reset action might break them. Be sure to create a backup of the plugins directory before the execution of this tool." msgstr "" #: src/strings.php:475 msgid "Type" msgstr "" #: src/strings.php:480 msgid "Update Secret Keys" msgstr "" #: src/strings.php:481 msgid "The secret or security keys are a list of constants added to your site to ensure better encryption of information stored in the user’s cookies. A secret key makes your site harder to hack by adding random elements to the password. You do not have to remember the keys, just write a random, complicated, and long string in the wp-config.php file. You can change these keys at any point in time. Changing them will invalidate all existing cookies, forcing all logged in users to login again." msgstr "" #: src/strings.php:483 msgid "Your current session will expire once the form is submitted." msgstr "" #: src/strings.php:488 msgid "Generate New Security Keys" msgstr "" #: src/strings.php:489 msgid "Automatic Secret Keys Updater" msgstr "" #: src/strings.php:490 msgid "Changing the Secret Keys frequently will decrease the chances of misuse of sessions left open on unprotected devices." msgstr "" #: src/strings.php:492 msgid "Frequency:" msgstr "" #: src/strings.php:496 msgid "Scheduled Tasks" msgstr "" #: src/strings.php:497 msgid "The plugin scans your entire website looking for changes which are later reported via the API in the audit logs page. By default the scanner runs daily but you can change the frequency to meet your requirements. Notice that scanning your project files too frequently may affect the performance of your website. Be sure to have enough server resources before changing this option. The memory limit and maximum execution time are two of the PHP options that your server will set to stop your website from consuming too much resources." msgstr "" #: src/strings.php:499 msgid "The scanner uses the PHP SPL library and the Filesystem Iterator class to scan the directory tree where your website is located in the server. This library is only available on PHP 5 >= 5.3.0 — OR — PHP 7; if you have an older version of PHP the plugin will not work as expected. Please ask your hosting provider to advise you on this matter." msgstr "" #: src/strings.php:501 msgid "Scheduled tasks are rules registered in your database by a plugin, theme, or the base system itself; they are used to automatically execute actions defined in the code every certain amount of time. A good use of these rules is to generate backup files of your site, execute a security scanner, or remove unused elements like drafts. Note: Scheduled tasks can be re-installed by any plugin/theme automatically." msgstr "" #: src/strings.php:505 msgid "Schedule" msgstr "" #: src/strings.php:506 msgid "Next Due" msgstr "" #: src/strings.php:507 msgid "Arguments" msgstr "" #: src/strings.php:513 msgid "Ignore Files And Folders During The Scans" msgstr "" #: src/strings.php:514 msgid "Use this tool to select the files and/or folders that are too heavy for the scanner to process. These are usually folders with images, media files like videos and audios, backups and — in general — anything that is not code-related. Ignoring these files or folders will reduce the memory consumption of the PHP script." msgstr "" #: src/strings.php:516 msgid "Ignore a file or directory:" msgstr "" #: src/strings.php:517 msgid "e.g. /private/directory/" msgstr "" #: src/strings.php:522 msgid "Unignore Selected Directories" msgstr "" #: src/strings.php:525 msgid "WordPress Integrity (False Positives)" msgstr "" #: src/strings.php:526 msgid "Since the scanner doesn’t read the files during the execution of the integrity check, it is possible to find false positives. Files listed here have been marked as false positives and will be ignored by the scanner in subsequent scans." msgstr "" #: src/strings.php:529 msgid "Reason" msgstr "" #: src/strings.php:530 msgid "Ignored At" msgstr "" #: src/strings.php:533 msgid "Stop Ignoring the Selected Files" msgstr "" #: src/strings.php:537 msgid "If your server allows the execution of system commands, you can configure the plugin to use the Unix Diff Utility 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." msgstr "" #: src/strings.php:542 msgid "Environment Variables" msgstr "" #: src/strings.php:545 msgid "Access File Integrity" msgstr "" #: src/strings.php:546 msgid "The .htaccess file is a distributed configuration file, and is how the Apache web server handles configuration changes on a per-directory basis. WordPress uses this file to manipulate how Apache serves files from its root directory and subdirectories thereof; most notably, it modifies this file to be able to handle pretty permalinks." msgstr "" #: src/strings.php:548 msgid "Htaccess file found in" msgstr "" #: src/strings.php:549 msgid "Your website has no .htaccess file or it was not found in the default location." msgstr "" #: src/strings.php:551 msgid "Your web server does not support .htaccess files." msgstr "" #: src/strings.php:552 msgid "The main .htaccess file in your site has the standard rules for a WordPress installation. You can customize it to improve the performance and change the behaviour of the redirections for pages and posts in your site. To get more information visit the official documentation at Codex WordPress - Creating and editing (.htaccess)" msgstr "" #: src/strings.php:554 msgid "Codex WordPress HTAccess" msgstr "" #: src/strings.php:557 msgid "General Settings" msgstr "" #: src/strings.php:558 msgid "Scanner" msgstr "" #: src/strings.php:559 msgid "Hardening" msgstr "" #: src/strings.php:560 msgid "Post-Hack" msgstr "" #: src/strings.php:561 msgid "Alerts" msgstr "" #: src/strings.php:563 msgid "Website Info" msgstr "" #: src/strings.php:564 msgid "Hardening Options" msgstr "" #: src/strings.php:567 msgid "This information will be updated %%SUCURI.SiteCheck.Lifetime%%" msgstr "" #: src/strings.php:568 msgid "Refresh Malware Scan" msgstr "" #: src/strings.php:571 msgid "Request Malware Cleanup" msgstr "" #: src/strings.php:572 msgid "No malicious JavaScript" msgstr "" #: src/strings.php:573 msgid "No malicious iFrames" msgstr "" #: src/strings.php:574 msgid "No suspicious redirections" msgstr "" #: src/strings.php:575 msgid "No blackhat SEO spam" msgstr "" #: src/strings.php:576 msgid "No anomaly detection" msgstr "" #: src/strings.php:577 msgid "This is a free website security scanner. Some types of malware and security issues cannot be detected by this scanner. If no issues are detected but you suspect a problem still exists, sign up for a complete and in depth website scan with malware cleanup." msgstr "" #: src/strings.php:579 msgid "The Sucuri Security Plugin's automated scanner has detected malware in your WordPress environment." msgstr "" #: src/strings.php:581 msgid "Log in to the Sucuri Platform dashboard for a complete scan of your website files and guaranteed malware removal. You can sign up here if you don't have an account yet." msgstr "" #: src/strings.php:585 msgid "Hover to see the Payload" msgstr "" #: src/strings.php:588 msgid "Recommendations" msgstr "" #: src/strings.php:591 #: src/strings.php:594 msgid "Malware Scan Target" msgstr "" #: src/strings.php:592 msgid "The remote malware scanner provided by the plugin is powered by Sucuri SiteCheck, 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." msgstr "" #: src/strings.php:595 msgid "Malware Scan Target:" msgstr "" #: src/strings.php:599 msgid "WordPress Security Recommendations" msgstr "" #: src/strings.php:602 msgid "The max-age setting tells your browser how long, in seconds, it can keep a copy of a web page before it needs to check for a new version. This is the basic setting needed to make caching work on most devices." msgstr "" #: src/strings.php:604 msgid "The s-maxage setting tells shared caches, like those used by multiple visitors or devices (such as CDNs or web accelerators), how long they can keep a copy of a web page. It allows you to control how often these shared caches update their content compared to private caches." msgstr "" #: src/strings.php:606 msgid "The stale-if-error setting allows a cached page to be served even after it has expired if the original web server returns an error. This helps keep your website available by showing an older version of the page instead of an error message. You need to set a private or shared cache duration to use this option, and it can be set for hours or days." msgstr "" #: src/strings.php:608 msgid "The stale-while-revalidate setting lets shared caches serve an old version of a web page while they update the cached copy in the background. This improves loading times because visitors don’t have to wait for the updated content. Like stale-if-error, it requires a private or shared cache duration, and can be used together with stale-if-error. This setting is useful for ensuring quick page loads while keeping content reasonably fresh." msgstr "" #: src/strings.php:610 msgid "When this option is set, older pages will be cached for longer than newer pages (determined by page number). The configured pagination factor is added to the main maxage and s-maxage options. This allows less popular archives to be served as stale for longer." msgstr "" #: src/strings.php:612 msgid "When this option is set, the max-age and s-maxage values will be multiplied by the number of years since the last edit or comment (the Last Modified time). This allows posts that were published a long time ago to be cached longer than newer posts." msgstr "" #: src/strings.php:614 msgid "Here you can see all the cache options available." msgstr "" #: src/strings.php:615 msgid "Option" msgstr "" #: src/strings.php:616 msgid "No options available" msgstr "" #: src/strings.php:617 msgid "Cache Control Header" msgstr "" #: src/strings.php:620 msgid "Mode:" msgstr "" #: src/strings.php:623 msgid "Please enable site caching on your WAF to use these settings. If you are a Sucuri client and require assistance, please {{create a ticket}} and reach out to the firewall team for support." msgstr "" #: src/template.lib.php:277 msgid "Invalid template type" msgstr "" #: src/wordpress-recommendations.lib.php:54 msgid "Implement an SSL Certificate" msgstr "" #: src/wordpress-recommendations.lib.php:54 msgid "SSL certificates help protect the integrity of the data in transit between the host (web server or firewall) and the client (web browser)." msgstr "" #: src/wordpress-recommendations.lib.php:57 msgid "Upgrade PHP to a supported version" msgstr "" #: src/wordpress-recommendations.lib.php:57 msgid "The PHP version you are using no longer receives security support and could be exposed to unpatched security vulnerabilities." msgstr "" #: src/wordpress-recommendations.lib.php:60 msgid "Missing WordPress Salt & Security Keys" msgstr "" #: src/wordpress-recommendations.lib.php:60 msgid "Consider using WordPress Salt & Security Keys to add an extra layer of protection to the session cookies and credentials." msgstr "" #: src/wordpress-recommendations.lib.php:63 msgid "WordPress Salt & Security Keys should be updated" msgstr "" #: src/wordpress-recommendations.lib.php:63 msgid "Updating WordPress Salt & Security Keys after a compromise and on a regular basis, at least once a year, reduces the risks of session hijacking." msgstr "" #: src/wordpress-recommendations.lib.php:66 msgid "Admin/Administrator username still exists" msgstr "" #: src/wordpress-recommendations.lib.php:66 msgid "Using a unique username and removing the default admin/administrator account make it more difficult for attackers to brute force your WordPress." msgstr "" #: src/wordpress-recommendations.lib.php:69 msgid "Use super admin account only when needed" msgstr "" #: src/wordpress-recommendations.lib.php:69 msgid "Create an Editor account instead of always using the super-admin to reduce the damage in case of session hijacking." msgstr "" #: src/wordpress-recommendations.lib.php:72 msgid "Remove unwanted/unused extensions" msgstr "" #: src/wordpress-recommendations.lib.php:72 msgid "Keeping unwanted themes and plugins increases the chance of a compromise, even if they are disabled." msgstr "" #: src/wordpress-recommendations.lib.php:75 msgid "Decrease the number of plugins" msgstr "" #: src/wordpress-recommendations.lib.php:75 msgid "The greater the number of plugins installed, the greater the risk of infection and performance issues." msgstr "" #: src/wordpress-recommendations.lib.php:78 msgid "Disable file editing" msgstr "" #: src/wordpress-recommendations.lib.php:78 msgid "Using \"DISALLOW_FILE_EDIT\" helps prevent an attacker from changing your files through WordPress backend." msgstr "" #: src/wordpress-recommendations.lib.php:81 msgid "Disable WordPress debug mode" msgstr "" #: src/wordpress-recommendations.lib.php:81 msgid "When \"WP_DEBUG\" is set to true, it will cause all PHP errors, notices and warnings to be displayed which can expose sensitive information." msgstr "" #: src/wordpress-recommendations.lib.php:84 msgid "Prevent PHP direct execution on sensitive directories" msgstr "" #: src/wordpress-recommendations.lib.php:84 msgid "Directories such as \"wp-content\" and \"wp-includes\" are generally not intended to be accessed by any user, consider hardening them via Sucuri Security -> Settings -> Hardening." msgstr "" #: src/wordpress-recommendations.lib.php:226 msgid "Your WordPress install is following the security best practices." msgstr "" #: sucuri.php:330 msgid "Sucuri plugin has been uninstalled" msgstr "" src/api.lib.php000060400000137002147177152050007372 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Plugin API library. * * When used in the context of web development, an API is typically defined as a * set of Hypertext Transfer Protocol (HTTP) request messages, along with a * definition of the structure of response messages, which is usually in an * Extensible Markup Language (XML) or JavaScript Object Notation (JSON) format. * While "web API" historically has been virtually synonymous for web service, * the recent trend (so-called Web 2.0) has been moving away from Simple Object * Access Protocol (SOAP) based web services and service-oriented architecture * (SOA) towards more direct representational state transfer (REST) style web * resources and resource-oriented architecture (ROA). Part of this trend is * related to the Semantic Web movement toward Resource Description Framework * (RDF), a concept to promote web-based ontology engineering technologies. Web * APIs allow the combination of multiple APIs into new applications known as * mashups. * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ class SucuriScanAPI extends SucuriScanOption { /** * Alternative to the built-in PHP method http_build_query. * * Some PHP installations with different encoding or with different language * (German for example) might produce an unwanted behavior when building an * URL, because of this we decided to write our own URL query builder to * keep control of the output. * * @param array $params May be an array or object containing properties. * @return string Returns a URL-encoded string. */ private static function buildQuery($params = array()) { $trail = ''; foreach ($params as $param => $value) { $value = urlencode($value); $trail .= sprintf('&%s=%s', $param, $value); } return substr($trail, 1); } /** * Sends a HTTP request via WordPress WP_HTTP class. * * @suppress PhanNonClassMethodCall * @see https://secure.php.net/manual/en/book.curl.php * @see https://developer.wordpress.org/reference/classes/wp_http/request/ * * @param string $url The target URL where the request will be sent. * @param string $method HTTP method that will be used to send the request. * @param array $params Parameters for the request defined in an associative array. * @param array $args Request arguments like the timeout, headers, cookies, etc. * @return mixed HTTP response, JSON-decoded array, or false on failure. */ public static function apiCall($url = '', $method = 'GET', $params = array(), $args = array()) { if (!$url) { return self::throwException(__('URL is invalid', 'sucuri-scanner')); } if ($method !== 'GET' && $method !== 'POST') { return self::throwException(__('Only GET and POST methods allowed', 'sucuri-scanner')); } $res = null; $timeout = SUCURISCAN_MAX_REQUEST_TIMEOUT; $args = is_array($args) ? $args : array(); if (isset($args['timeout'])) { $timeout = (int)$args['timeout']; } /* include request arguments */ $args['method'] = $method; $args['timeout'] = $timeout; $args['redirection'] = 5; $args['httpversion'] = '1.1'; $args['blocking'] = true; $args['sslverify'] = true; /* separate hardcoded query parameters */ if (empty($params) && strpos($url, '?')) { $parts = @parse_url($url); if (array_key_exists('query', $parts)) { $portions = explode('&', $parts['query']); $url = str_replace('?' . $parts['query'], '', $url); foreach ($portions as $portion) { $bits = explode('=', $portion, 2); $params[$bits[0]] = $bits[1]; } } } /* include current timestamp for trackability */ if (!array_key_exists('time', $params)) { $params['time'] = time(); } /* support HTTP GET requests */ if ($method === 'GET') { $args['body'] = null; $url .= '?' . self::buildQuery($params); $res = wp_remote_get($url, $args); } /* support HTTP POST requests */ if ($method === 'POST') { if (array_key_exists('a', $params)) { /* include action to increase visibility */ $url .= '?a=' . $params['a']; } $args['body'] = $params; $res = wp_remote_post($url, $args); } if (is_wp_error($res)) { return self::throwException($res->get_error_message()); } /* try to return a JSON-encode object */ $data = @json_decode($res['body'], true); return $data ? $data : $res['body']; } /** * Check whether the plugin API key is valid or not. * * @param string $api_key An unique string to identify this installation. * @return bool True if the API key is valid, false otherwise. */ private static function isValidKey($api_key = '') { return (bool)@preg_match('/^[a-z0-9]{32}$/', $api_key); } /** * Store the API key locally. * * @param string $api_key An unique string of characters to identify this installation. * @param bool $validate Whether the format of the key should be validated before store it. * @return bool Either true or false if the key was saved successfully or not respectively. */ public static function setPluginKey($api_key = '', $validate = false) { if ($validate && !self::isValidKey($api_key)) { return SucuriScanInterface::error(__('Invalid API key format', 'sucuri-scanner')); } if (!empty($api_key)) { SucuriScanEvent::notifyEvent( 'plugin_change', sprintf(__('API key was successfully set: %s', 'sucuri-scanner'), $api_key) ); } return self::updateOption(':api_key', $api_key); } /** * Retrieve the API key from the local storage. * * @return string|bool The API key or false if it does not exists. */ public static function getPluginKey() { $api_key = self::getOption(':api_key'); if (is_string($api_key) && self::isValidKey($api_key)) { return $api_key; } return false; } /** * Call an action from the remote API interface of our WordPress service. * * @param string $method HTTP method that will be used to send the request. * @param array $params Parameters for the request defined in an associative array of key-value. * @param bool $send_api_key Whether the API key should be added to the request parameters or not. * @param array $args Request arguments like the timeout, redirections, headers, cookies, etc. * @return array|bool Response object after the HTTP request is executed. */ public static function apiCallWordpress($method = 'GET', $params = array(), $send_api_key = true, $args = array()) { if (!SucuriScan::issetScanApiUrl()) { return false; } $params[SUCURISCAN_API_VERSION] = 1; $params['p'] = 'wordpress'; if ($send_api_key) { $api_key = self::getPluginKey(); if (!$api_key) { return false; } $params['k'] = $api_key; } return self::apiCall(SUCURISCAN_API_URL, $method, $params, $args); } /** * Determine whether an API response was successful or not by checking the * expected generic variables and types, in case of an error a notification * will appears in the administrator panel explaining the result of the * operation. * * For failures in the HTTP response: * * Log file not found: means that the API key used to execute the request is * not associated to the website, this may indicate that either the key was * invalidated by an administrator of the service or that the API key was * custom generated with invalid data. * * Wrong API key: means that the TLD of the origin of the request is not the * domain used to generate the API key in the first place, or that the email * address of the site administrator was changed so the data is not valid * anymore. * * @param array $res HTTP response after API endpoint execution. * @return bool False if the API call failed, true otherwise. */ public static function handleResponse($res = array()) { if (!$res || getenv('SUCURISCAN_NO_API_HANDLE')) { return false; } if (is_array($res) && array_key_exists('status', $res) && intval($res['status']) === 1 ) { return true; } if (is_string($res) && !empty($res)) { return SucuriScanInterface::error($res); } if (!is_array($res) || !isset($res['messages']) || empty($res['messages']) ) { return SucuriScanInterface::error(__('Unknown error, there is no information', 'sucuri-scanner')); } $msg = implode(".\x20", $res['messages']); $raw = $msg; /* Keep a copy of the original message. */ // Special response for invalid API keys. if (stripos($raw, 'log file not found') !== false) { $key = SucuriScanOption::getOption(':api_key'); $msg .= '; this generally happens when you use an invalid API key,' . ' or when the connection with the API service suddently closes.'; SucuriScanEvent::reportCriticalEvent($msg); } // Special response for invalid firewall API keys. if (stripos($raw, 'wrong api key') !== false) { $key = SucuriScanOption::getOption(':cloudproxy_apikey'); $key = SucuriScan::escape($key); $msg .= sprintf('; invalid firewall API key: %s', $key); SucuriScanOption::setRevProxy('disable', true); SucuriScanOption::setAddrHeader('REMOTE_ADDR', true); return SucuriScanInterface::error($msg); } // Stop SSL peer verification on connection failures. if (stripos($raw, 'no alternative certificate') || stripos($raw, 'error setting certificate') || stripos($raw, 'SSL connect error') ) { $msg .= '. The website seems to be using an old version of the Ope' . 'nSSL library or the CURL extension was compiled without support' . ' for the algorithm used in the certificate installed in the API' . ' service. Contact your hosting provider to fix this issue.'; } // Check if the MX records as missing for API registration. if (strpos($raw, 'Invalid email') !== false) { $msg = __('Invalid email format or the host is missing MX records.', 'sucuri-scanner'); } return SucuriScanInterface::error($msg); } /** * Send a request to the API to register this site. * * @param string $email Optional email address for the registration. * @return bool True if the API key was generated, false otherwise. */ public static function registerSite($email = '') { if (!is_string($email) || empty($email)) { $email = self::getSiteEmail(); } $res = self::apiCallWordpress( 'POST', array( 'e' => $email, 's' => self::getDomain(), 'a' => 'register_site', ), false ); if (!self::handleResponse($res)) { return false; } self::setPluginKey($res['output']['api_key']); SucuriScanEvent::installScheduledTask(); SucuriScanEvent::notifyEvent('plugin_change', __('API key was generated and set', 'sucuri-scanner')); return SucuriScanInterface::info(__('API key successfully generated and saved.', 'sucuri-scanner')); } /** * Send a request to recover a previously registered API key. * * @return bool True if the API key was sent to the admin email, false otherwise. */ public static function recoverKey() { $domain = self::getDomain(); $res = self::apiCallWordpress( 'GET', array( 'e' => self::getSiteEmail(), 's' => $domain, 'a' => 'recover_key', ), false ); if (!self::handleResponse($res)) { return false; } SucuriScanEvent::notifyEvent( 'plugin_change', sprintf(__('API key recovery for domain: %s', 'sucuri-scanner'), $domain) ); return SucuriScanInterface::info($res['output']['message']); } /** * Retrieve the event logs registered by the API service. * * @param int $lines Maximum number of logs to return. * @param array $filters Filters to apply to the logs. * @return array|bool The data structure with the logs. */ public static function getAuditLogs($lines = 50, $filters = array()) { if (SucuriScanOption::isDisabled(':api_service') || SucuriScan::issetScanApiUrl()) { return self::parseAuditLogs(array()); } $res = self::apiCallWordpress( 'GET', array( 'a' => 'get_logs', 'l' => $lines, ) ); if (!self::handleResponse($res)) { return false; } return self::parseAuditLogs($res, $filters); } /** * Returns the security logs from the system queue. * In case the logs comes from the queue, set key "from_queue" to true, * as the parse function later will need to prevent timezone conflicts. * * @return array The data structure with the logs. */ public static function getAuditLogsFromQueue($filters = array()) { $auditlogs = array(); $cache = new SucuriScanCache('auditqueue'); $events = $cache->getAll(); if (is_array($events) && !empty($events)) { $events = array_reverse($events); foreach ($events as $micro => $message) { if (!is_string($message)) { /* incompatible JSON data */ continue; } $offset = strpos($micro, '_'); $time = substr($micro, 0, $offset); $auditlogs[] = sprintf( '%s %s : %s', SucuriScan::datetime($time, 'Y-m-d H:i:s'), SucuriScan::getSiteEmail(), $message ); } } $res = array( 'status' => 1, 'action' => 'get_logs', 'request_time' => time(), 'verbose' => 0, 'output' => array_reverse($auditlogs), 'total_entries' => count($auditlogs), 'from_queue' => '1', ); return self::parseAuditLogs($res, $filters); } /** * Retrieves the available filters for the audit logs. * * @return array An associative array containing the filters for the auditlogs. */ public static function getFilters() { $format = 'Y-m-d'; $today = strtotime('today'); $yesterday = strtotime('yesterday'); $thisWeek = strtotime('monday this week'); $last7Days = strtotime('-7 days'); $lastWeek = strtotime('monday last week'); $last14Days = strtotime('-14 days'); $thisMonth = strtotime('first day of this month'); $last30Days = strtotime('-30 days'); $lastMonth = strtotime('first day of last month'); $thisYear = strtotime('first day of January this year'); $lastYear = strtotime('first day of January last year'); return array( 'time' => array( 'all time' => array( 'label' => __('All Time', 'sucuri-scanner'), 'date' => null, ), 'today' => array( 'label' => __('Today', 'sucuri-scanner'), 'date' => SucuriScan::datetime($today, $format), ), 'yesterday' => array( 'label' => __('Yesterday', 'sucuri-scanner'), 'date' => SucuriScan::datetime($yesterday, $format), ), 'this week' => array( 'label' => __('This Week', 'sucuri-scanner'), 'date' => SucuriScan::datetime($thisWeek, $format), ), 'last 7 days' => array( 'label' => __('Last 7 Days', 'sucuri-scanner'), 'date' => SucuriScan::datetime($last7Days, $format), ), 'last week' => array( 'label' => __('Last Week', 'sucuri-scanner'), 'date' => SucuriScan::datetime($lastWeek, $format), ), 'last 14 days' => array( 'label' => __('Last 14 Days', 'sucuri-scanner'), 'date' => SucuriScan::datetime($last14Days, $format), ), 'this month' => array( 'label' => __('This Month', 'sucuri-scanner'), 'date' => SucuriScan::datetime($thisMonth, $format), ), 'last 30 days' => array( 'label' => __('Last 30 Days', 'sucuri-scanner'), 'date' => SucuriScan::datetime($last30Days, $format), ), 'last month' => array( 'label' => __('Last Month', 'sucuri-scanner'), 'date' => SucuriScan::datetime($lastMonth, $format), ), 'this year' => array( 'label' => __('This Year', 'sucuri-scanner'), 'date' => SucuriScan::datetime($thisYear, $format), ), 'last year' => array( 'label' => __('Last Year', 'sucuri-scanner'), 'date' => SucuriScan::datetime($lastYear, $format), ), 'custom' => array( 'label' => __('Custom', 'sucuri-scanner'), 'date' => null, ), ), 'startDate' => '', 'endDate' => '', 'posts' => array( 'all posts' => array( 'label' => __('All Posts', 'sucuri-scanner'), 'value' => null, ), 'created' => array( 'label' => __('Created', 'sucuri-scanner'), 'value' => 'Post was created', ), 'updated' => array( 'label' => __('Updated', 'sucuri-scanner'), 'value' => 'Post was updated', ), 'deleted' => array( 'label' => __('Deleted', 'sucuri-scanner'), 'value' => 'Post moved to trash', ), ), 'logins' => array( 'all logins' => array( 'label' => __('All Logins', 'sucuri-scanner'), 'value' => '', ), 'failed' => array( 'label' => __('Failed', 'sucuri-scanner'), 'value' => 'authentication failed', ), 'succeeded' => array( 'label' => __('Succeeded', 'sucuri-scanner'), 'value' => 'authentication succeeded', ), ), 'users' => array( 'all users' => array( 'label' => __('All Users', 'sucuri-scanner'), 'value' => '', ), 'created' => array( 'label' => __('Created', 'sucuri-scanner'), 'value' => 'User account created', ), 'edited' => array( 'label' => __('Edited', 'sucuri-scanner'), 'value' => 'User account edited', ), 'deleted' => array( 'label' => __('Deleted', 'sucuri-scanner'), 'value' => 'User account deleted', ), ), 'plugins' => array( 'all plugins' => array( 'label' => __('All Plugins', 'sucuri-scanner'), 'value' => '', ), 'installed' => array( 'label' => __('Installed', 'sucuri-scanner'), 'value' => 'Plugin installed', ), 'activated' => array( 'label' => __('Activated', 'sucuri-scanner'), 'value' => 'Plugin activated', ), 'deactivated' => array( 'label' => __('Deactivated', 'sucuri-scanner'), 'value' => 'Plugin deactivated', ), ), ); } /** * Filters a log entry based on the frontend filters provided. * Returns true if the log matches the time filter (if applied) and any of the other filters. * * @param array $log The log entry to be filtered. * @param array $frontend_filters The filters applied from the frontend. * * @return bool True if the log passes the filters, false otherwise. */ private static function filterAuditLog($log, $frontend_filters) { $filters = self::getFilters(); // Check the time filter first if (isset($frontend_filters['time']) && $frontend_filters['time'] !== 'all time') { if (!self::filterByTime($log['date'], $frontend_filters)) { return false; } } $other_filters = $frontend_filters; unset($other_filters['time'], $other_filters['startDate'], $other_filters['endDate']); if (empty($other_filters)) { return true; } // Check if the log matches any of the other filters foreach ($other_filters as $active_filter => $value_filter) { if (isset($filters[$active_filter][$value_filter])) { $search_term = $filters[$active_filter][$value_filter]['value']; if (strpos($log['message'], $search_term) !== false) { return true; // Log matches one of the filters } } } return false; } /** * Checks if a log entry matches the specified time filter. * * @param array $log_date The date of the log. * @param array $frontend_filters The filters applied from the frontend. * * @return bool True if the log matches the time filter, false otherwise. */ private static function filterByTime($log_date, $frontend_filters) { $filters = self::getFilters(); $today = strtotime('today'); $time_option = $frontend_filters['time']; $filter_date = SucuriScan::datetime($today, 'Y-m-d'); if (isset($filters['time'][$time_option]['date'])) { $filter_date = $filters['time'][$time_option]['date']; } switch ($time_option) { case 'today': case 'yesterday': return $log_date === $filter_date; case 'last week': $endDate = strtotime('sunday last week'); $endDate = SucuriScan::datetime($endDate, 'Y-m-d'); return $log_date >= $filter_date && $log_date <= $endDate; case 'last month': $endDate = strtotime('last day of last month'); $endDate = SucuriScan::datetime($endDate, 'Y-m-d'); return $log_date >= $filter_date && $log_date <= $endDate; case 'last year': $endDate = strtotime('last day of December last year'); $endDate = SucuriScan::datetime($endDate, 'Y-m-d'); return $log_date >= $filter_date && $log_date <= $endDate; case 'this week': case 'last 7 days': case 'last 14 days': case 'this month': case 'last 30 days': case 'this year': return $log_date >= $filter_date; case 'custom': $startDate = strtotime($frontend_filters['startDate']); $startDate = SucuriScan::datetime($startDate, 'Y-m-d'); $endDate = strtotime($frontend_filters['endDate']); $endDate = SucuriScan::datetime($endDate, 'Y-m-d'); return $log_date >= $startDate && $log_date <= $endDate; default: // Unrecognized time option; don't consider it a match. return false; } } /** * Reads, parses and extracts relevant data from the security logs. * * @param array $res JSON-decoded logs. * @return array|null Full data extracted from the logs. */ private static function parseAuditLogs($res, $filters = array()) { if (!is_array($res) || !isset($res['output'])) { return null; } $res['output_data'] = array(); foreach ((array)@$res['output'] as $log) { /* YYYY-MM-dd HH:ii:ss EMAIL : MESSAGE: (multiple entries): a,b,c */ if (strpos($log, "\x20:\x20") === false) { continue; /* ignore; invalid format */ } $log_data = array( 'event' => 'notice', 'date' => '', 'time' => '', 'datetime' => '', 'timestamp' => 0, 'account' => '', 'username' => 'system', 'remote_addr' => '127.0.0.1', 'message' => '', 'file_list' => false, 'file_list_count' => 0, ); list($left, $right) = explode("\x20:\x20", $log, 2); $dateAndEmail = explode("\x20", $left, 3); /* set basic information */ $log_data['message'] = $right; $log_data['account'] = $dateAndEmail[2]; /** * When the audit logs comes from the queue, it's necessary to convert * the logs using the correct timezone before parsing to avoid issues. * First, use timezone override feature if set on the plugin settings, * convert it properly as the syntax must be compatible with php strtotime, * otherwise use WordPress timezone or offset with a quick fix only for UTC * as by default it would be set as "0" instead of "UTC". */ $tz_override = SucuriScanOption::getOption(':timezone'); if (empty($tz_override)) { $wpTimezone = get_option('timezone_string'); if (empty($wpTimezone)) { $wpTimezone = get_option('gmt_offset'); } /* set wpTimezone to UTC if was previously unset */ if ($wpTimezone == "0") { $wpTimezone = "UTC"; } } else { $tz_override_replace_from = array(".", "UTC"); $tz_override_replace_to = array(":", ""); $wpTimezone = str_replace($tz_override_replace_from, $tz_override_replace_to, $tz_override); } /** * When the audit logs comes from the audit logs server, it will * be using EDT timezone, however due to the seasonal nature of the * EDT timzeone, here we will be using America/New_York when and only * when the audit logs comes from the audit logs server, cause when * it comes from the queue, wpTimezone var will be used. */ if (array_key_exists('from_queue', $res)) { $datetime = sprintf('%s %s %s', $dateAndEmail[0], $dateAndEmail[1], $wpTimezone); } else { $datetime = sprintf('%s %s America/New_York', $dateAndEmail[0], $dateAndEmail[1]); } $log_data['timestamp'] = strtotime($datetime); $log_data['datetime'] = SucuriScan::datetime($log_data['timestamp'], 'Y-m-d H:i:s'); $log_data['date'] = SucuriScan::datetime($log_data['timestamp'], 'Y-m-d'); $log_data['time'] = SucuriScan::datetime($log_data['timestamp'], 'H:i:s'); /* extract more information from the generic audit logs */ $log_data['message'] = str_replace('
    ', ";\x20", $log_data['message']); $eventTypes = self::getAuditEventTypes(); $eventTypes = array_keys($eventTypes); /* LEVEL: USERNAME, IP; MESSAGE */ if (strpos($log_data['message'], ":\x20") && strpos($log_data['message'], ";\x20")) { $offset = strpos($log_data['message'], ":\x20"); $level = substr($log_data['message'], 0, $offset); $log_data['event'] = strtolower($level); /* ignore; invalid event type */ if (!in_array($log_data['event'], $eventTypes)) { continue; } /* extract the IP address */ $log_data['message'] = substr($log_data['message'], $offset + 2); $offset = strpos($log_data['message'], ";\x20"); $log_data['remote_addr'] = substr($log_data['message'], 0, $offset); /* extract the username */ if (strpos($log_data['remote_addr'], ",\x20")) { $index = strpos($log_data['remote_addr'], ",\x20"); $log_data['username'] = substr($log_data['remote_addr'], 0, $index); $log_data['remote_addr'] = substr($log_data['remote_addr'], $index + 2); } /* fix old user authentication logs for backward compatibility */ $log_data['message'] = substr($log_data['message'], $offset + 2); $log_data['message'] = str_replace( 'logged in', 'authentication succeeded', $log_data['message'] ); /* extract the username of a successful/failed login */ if (strpos($log_data['message'], "User authentication\x20") === 0) { $offset = strpos($log_data['message'], ":\x20"); $username = substr($log_data['message'], $offset + 2); if (strpos($username, ';') !== false) { $username = substr($username, 0, strpos($username, ';')); } $log_data['username'] = $username; } } /* extract more information from the special formatted logs */ if (strpos($log_data['message'], "(multiple entries):\x20")) { $offset = strpos($log_data['message'], "(multiple entries):\x20"); $message = substr($log_data['message'], 0, $offset + 19); $entries = substr($log_data['message'], $offset + 20); $log_data['message'] = $message; $entries = str_replace(', new size', '; new size', $entries); $entries = str_replace(",\x20", ";\x20", $entries); $log_data['file_list'] = explode(',', $entries); $log_data['file_list_count'] = count($log_data['file_list']); } /* extract additional details from the message */ if (strpos($log_data['message'], '; details:')) { $idx = strpos($log_data['message'], '; details:'); $message = substr($log_data['message'], 0, $idx); $details = substr($log_data['message'], $idx + 11); $log_data['message'] = $message . ' (details):'; $log_data['file_list'] = explode(',', $details); $log_data['file_list_count'] = count($log_data['file_list']); } $log_data = self::getLogsHotfix($log_data); // Based on filters, evaluate if should skip. if (self::filterAuditLog($log_data, $filters) === false) { continue; } if ($log_data) { $res['output_data'][] = $log_data; } } return $res; } /** * Modifies some of the security logs to detail the information. * * @param array $data Valid security log data structure. * @return array|bool Modified security log. */ private static function getLogsHotfix($data) { /** * PHP Compatibility Checker * * The WP Engine PHP Compatibility Checker can be used by any WordPress * website on any web host to check PHP version compatibility. This * plugin will lint theme and plugin code inside your WordPress file * system and give you back a report of compatibility issues for you to * fix. * * @see https://wordpress.org/plugins/php-compatibility-checker/ */ if (isset($data['message']) && strpos($data['message'], 'Wpephpcompat_jobs') === 0) { $offset = strpos($data['message'], "ID:\x20"); $id = substr($data['message'], $offset + 4); $id = substr($id, 0, strpos($id, ';')); $offset = strpos($data['message'], "name:\x20"); $name = substr($data['message'], $offset + 6); $data['message'] = sprintf( __('WP Engine PHP Compatibility Checker: %s (created post #%d as cache)', 'sucuri-scanner'), $name, /* plugin or theme name */ $id /* unique post or page identifier */ ); } return $data; } /** * Get a list of valid audit event types with their respective colors. * * @return array Valid audit event types with their colors. */ public static function getAuditEventTypes() { return array( 'critical' => '#000000', 'debug' => '#c690ec', 'error' => '#f27d7d', 'info' => '#5bc0de', 'notice' => '#428bca', 'warning' => '#f0ad4e', ); } /** * Parse the event logs with multiple entries. * * @param string $event_log Event log that will be processed. * @return string|array List of parts of the event log. */ public static function parseMultipleEntries($event_log = '') { $pattern = "\x20(multiple entries):\x20"; if (strpos($event_log, $pattern)) { return explode(',', str_replace($pattern, ',', $event_log)); } return $event_log; } /** * Send a request to the API to store and analyze the file's hashes of the site. * This will be the core of the monitoring tools and will enhance the * information of the audit logs alerting the administrator of suspicious * changes in the system. * * @param string $hashes The information gathered after the scanning of the site's files. * @return bool True if the hashes were stored, false otherwise. */ public static function sendHashes($hashes = '') { if (empty($hashes)) { return false; } $params = array('a' => 'send_hashes', 'h' => $hashes); $res = self::apiCallWordpress('POST', $params); return self::handleResponse($res); } /** * Generates a new set of WordPress security keys. * * @return array New set of WordPress security keys. */ public static function getNewSecretKeys() { $new_keys = array(); $pattern = self::secretKeyPattern(); $res = self::apiCall('https://api.wordpress.org/secret-key/1.1/salt/', 'GET'); if ($res && @preg_match_all($pattern, $res, $match)) { foreach ($match[1] as $key => $value) { $new_keys[$value] = $match[3][$key]; } } return $new_keys; } /** * Returns the URL for the WordPress checksums API service. * * @return string URL for the WordPress checksums API. */ public static function checksumAPI() { $url = 'https://api.wordpress.org/core/checksums/1.0/?version={version}&locale={locale}'; $custom = SucuriScanOption::getOption(':checksum_api'); if ($custom) { $url = sprintf( 'https://api.github.com/repos/%s/git/trees/master?recursive=1', $custom /* expect: username/repository */ ); } $url = str_replace('{version}', SucuriScan::siteVersion(), $url); $url = str_replace('{locale}', get_locale(), $url); return $url; } /** * Returns the name of the hash to use in the integrity tool * * By default, the plugin will use MD5 to hash the content of the specified * file, however, if the core integrity tool is using a custom URL, and this * URL is pointing to GitHub API, then we will assume that the checksum that * comes from this service is using SHA1. * * @return string Hash to use in the integrity tool. */ public static function checksumAlgorithm() { return strpos(self::checksumAPI(), '//api.github.com') ? 'sha1' : 'md5'; } /** * Calculates the md5/sha1 hash of a given file. * * When the user decides to configure the integrity tool to use the checksum * from a GitHub repository the plugin will have to use the SHA1 algorithm * instead of MD5 (which is what WordPress uses in their API). For this, we * will have to calculate the GIT hash object of the file which is basically * the merge of the text "blob" a single white space, the length of the text * a null byte and then the text in itself (content of the file). * * Example: * * - Input: "hello world\n" * - GIT (object): "blob 16\u0000hello world\n" * - GIT (shaobj): "3b18e512dba79e4c8300dd08aeb37f8e728b8dad" * * @see https://git-scm.com/book/en/v2/Git-Internals-Git-Objects#_object_storage * * @param string $algorithm Either md5 or sha1. * @param string $filename Absolute path to the given file. * @return string Hash of the given file. */ public static function checksum($algorithm, $filename) { if ($algorithm === 'sha1') { $content = SucuriScanFileInfo::fileContent($filename); return @sha1("blob\x20" . strlen($content) . "\x00" . $content); } return @md5_file($filename); } /** * Returns the checksum of all the files of the current WordPress version. * * The webmaster can change this URL using an option form the settings page. * This allows them to control which repository will be used to check the * integrity of the installation. * * For example, projectnami.org offers an option to use Microsoft SQL Server * instead of MySQL has a different set of files and even with the same * filenames many of them have been modified to support the new database * engine, since the checksums are different than the official ones the * number of false positives will increase. This option allows the webmaster * to point the plugin to a different URL where the new checksums for this * project will be retrieved. * * If the custom API is part of GitHub infrastructure, the plugin will try * to build the expected JSON object from the output, if it fails it will * pass the unmodified response to the rest of the code and try to analyze * the integrity of the installation with that information. * * @see Release Archive https://wordpress.org/download/release-archive/ * @see https://api.github.com/repos/user/repo/git/trees/master?recursive=1 * * @return array|bool Checksums of the WordPress installation. */ public static function getOfficialChecksums() { $url = self::checksumAPI(); $version = SucuriScan::siteVersion(); $res = self::apiCall($url, 'GET', array()); if (is_array($res) && array_key_exists('sha', $res) && array_key_exists('url', $res) && array_key_exists('tree', $res) && strpos($url, '//api.github.com') ) { $checksums = array(); foreach ($res['tree'] as $meta) { $checksums[$meta['path']] = $meta['sha']; } $res = array('checksums' => array($version => $checksums)); } if (!isset($res['checksums'])) { return false; } /* checksums for a specific version */ if (isset($res['checksums'][$version])) { return $res['checksums'][$version]; } return $res['checksums']; } /** * Returns the metadata of all the installed plugins. * * @see https://developer.wordpress.org/reference/functions/is_plugin_active/ * * @return array List of plugins with associated metadata. */ public static function getPlugins() { $cache = new SucuriScanCache('plugindata'); $cached_data = $cache->get('plugins', SUCURISCAN_GET_PLUGINS_LIFETIME, 'array'); /* use cache data instead of API */ if ($cached_data) { return $cached_data; } // Get the plugin's basic information from WordPress transient data. $plugins = get_plugins(); $wp_market = 'https://wordpress.org/plugins/%s/'; $pattern = '/^http(s)?:\/\/wordpress\.org\/plugins\/(.*)\/$/'; // Loop through each plugin data and complement its information with more attributes. foreach ($plugins as $path => $plugin_data) { // Default values for the plugin extra attributes. $repository = ''; $repository_name = ''; $is_free_plugin = false; /** * Extract the information of the plugin which includes the repository name, * repository URL, and if the source code of the plugin is publicly released or * not, in this last case if the source code of the plugin is not hosted in the * official WordPress server it means that it is premium and is being * distributed by an independent developer. */ if (isset($plugin_data['PluginURI']) && strpos($plugin_data['PluginURI'], '.org/plugins/') && strpos($plugin_data['PluginURI'], '://wordpress.org/') ) { $is_free_plugin = true; $repository = $plugin_data['PluginURI']; $offset = strpos($plugin_data['PluginURI'], '/plugins/'); $repository_name = substr($plugin_data['PluginURI'], $offset + 9); if (strpos($repository_name, '/') !== false) { $offset = strpos($repository_name, '/'); $repository_name = substr($repository_name, 0, $offset); } } else { $delimiter = strpos($path, '/') ? '/' : '.'; $parts = explode($delimiter, $path, 2); $possible_repository = sprintf($wp_market, $parts[0]); $resp = wp_remote_head($possible_repository); if (!is_wp_error($resp) && $resp['response']['code'] == 200) { $repository = $possible_repository; $repository_name = $parts[0]; $is_free_plugin = true; } } // Complement the plugin's information with these attributes. $plugins[$path]['Repository'] = $repository; $plugins[$path]['RepositoryName'] = $repository_name; $plugins[$path]['InstallationPath'] = sprintf('%s/%s', WP_PLUGIN_DIR, $repository_name); $plugins[$path]['PluginType'] = ($is_free_plugin ? 'free' : 'premium'); $plugins[$path]['IsPluginInstalled'] = is_dir($plugins[$path]['InstallationPath']); $plugins[$path]['IsPluginActive'] = is_plugin_active($path); $plugins[$path]['IsFreePlugin'] = $is_free_plugin; } /* cache data for future usage */ $cache->add('plugins', $plugins); return $plugins; } /** * Retrieve plugin installer pages from WordPress Plugins API. * * It is possible for a plugin to override the Plugin API result with three * filters. Assume this is for plugins, which can extend on the Plugin Info to * offer more choices. This is very powerful and must be used with care, when * overriding the filters. * * The first filter, 'plugins_api_args', is for the args and gives the action as * the second parameter. The hook for 'plugins_api_args' must ensure that an * object is returned. * * The second filter, 'plugins_api', is the result that would be returned. * * @param string $plugin Frienly name of the plugin. * @return array|bool Object on success, WP_Error on failure. */ public static function getRemotePluginData($plugin = '') { $resp = self::apiCall('https://api.wordpress.org/plugins/info/1.0/' . $plugin . '.json', 'GET'); return ($resp === 'null') ? false : $resp; } /** * Retrieve a specific file from the official WordPress subversion repository, * the content of the file is determined by the tags defined using the site * version specified. Only official core files are allowed to fetch. * * @see https://core.svn.wordpress.org/ * @see https://i18n.svn.wordpress.org/ * @see https://core.svn.wordpress.org/tags/VERSION_NUMBER/ * * @param string $filename Relative path of a core file. * @return string|bool Original code for the core file, false otherwise. */ public static function getOriginalCoreFile($filename) { $version = self::siteVersion(); $url = 'https://core.svn.wordpress.org/tags/{version}/{filename}'; $custom = SucuriScanOption::getOption(':checksum_api'); if ($custom) { $url = sprintf( 'https://raw.githubusercontent.com/%s/master/{filename}', $custom /* expect: username/repository */ ); } $url = str_replace('{version}', $version, $url); $url = str_replace('{filename}', $filename, $url); $resp = self::apiCall($url, 'GET'); if (strpos($resp, '404 Not Found') !== false) { /* not found comes from the official WordPress API */ return self::throwException(__('WordPress version is not supported anymore', 'sucuri-scanner')); } if (strpos($resp, '400: Invalid request') !== false) { /* invalid request comes from the unofficial GitHub API */ return self::throwException(__('WordPress version is not supported anymore', 'sucuri-scanner')); } return $resp ? $resp : false; } } src/auditlogs.lib.php000060400000033626147177152050010623 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Lists the logs collected by the API service. * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ class SucuriScanAuditLogs { /** * Print a HTML code with the content of the logs audited by the remote Sucuri * API service, this page is part of the monitoring tool. * * @return string HTML with the audit logs page. */ public static function pageAuditLogs() { $params = array(); $params['AuditLogs.Lifetime'] = SUCURISCAN_AUDITLOGS_LIFETIME; return SucuriScanTemplate::getSection('auditlogs', $params); } /** * Generates the HTML snippet for the audit log filters. * * This method constructs the HTML code for the audit log filters, including * select dropdowns for various filter options and date input fields for custom date ranges. * * @param array $frontend_filter The currently applied filters from the frontend. * * @return string The HTML code containing the filters. */ private static function getFiltersSnippet($frontend_filter) { $filters_snippet = ''; $filters = SucuriScanAPI::getFilters(); foreach ($filters as $filter => $options) { $filter_options = ''; if ($filter === 'startDate' || $filter === 'endDate') { $date = isset($frontend_filter[$filter]) ? $frontend_filter[$filter] : ''; $filters_snippet .= ''; continue; } foreach ($options as $value => $option) { $label = $option['label']; $selected = (isset($frontend_filter[$filter]) && $frontend_filter[$filter] === $value) ? ' selected' : ''; $filter_options .= ''; } $option_data = array( 'AuditLog.FilterName' => esc_attr($filter), 'AuditLog.FilterOptions' => $filter_options, ); $filters_snippet .= SucuriScanTemplate::getSnippet('auditlogs-filter', $option_data); } $filters_data = array( 'AuditLog.Filters' => $filters_snippet, ); return SucuriScanTemplate::getSnippet('auditlogs-filters', $filters_data); } /** * Gets the security logs from the API service. * * To reduce the amount of queries to the API this method will cache the logs * for a short period of time enough to give the service a rest. Once the * cache expires the method will communicate with the API once again to get * a fresh copy of the new logs. The cache is skipped when the user clicks * around the pagination. * * Additionally, if the API key has not been added but the website owner has * enabled the security log exporter, the method will retrieve the logs from * the local server with the limitation that only the latest entries in the * file will be processed. * * @codeCoverageIgnore - Notice that there is a test case that covers this * code, but since the WP-Send-JSON method uses die() to stop any further * output it means that XDebug cannot cover the next line, leaving a report * with a missing line in the coverage. Since the test case takes care of * the functionality of this code we will assume that it is fully covered. * * @return void */ public static function ajaxAuditLogs() { if (SucuriScanRequest::post('form_action') !== 'get_audit_logs') { return; } $response = array(); $response['count'] = 0; $response['status'] = ''; $response['content'] = ''; $response['queueSize'] = 0; $response['pagination'] = ''; $response['selfhosting'] = false; $response['filters'] = ''; $response['filtersStatus'] = ''; /* initialize the values for the pagination */ $maxPerPage = SUCURISCAN_AUDITLOGS_PER_PAGE; $pageNumber = SucuriScanTemplate::pageNumber(); $logsLimit = ($pageNumber * $maxPerPage); /* Initialize filter values */ $filters = array(); if (SucuriScanRequest::get('time')) { $filters['time'] = SucuriScanRequest::get('time'); if ($filters['time'] === 'custom') { $filters['startDate'] = SucuriScanRequest::get('startDate'); $filters['endDate'] = SucuriScanRequest::get('endDate'); } } $filter_keys = array('posts', 'logins', 'users', 'plugins'); foreach ($filter_keys as $key) { if (SucuriScanRequest::get($key)) { $filters[$key] = SucuriScanRequest::get($key); } } if (!empty($filters)) { $response['filtersStatus'] = 'active'; } $response['filters'] = self::getFiltersSnippet($filters); /* Get data from the cache if possible. */ $errors = ''; /* no errors so far */ $cache = new SucuriScanCache('auditlogs'); $auditlogs = $cache->get('response', SUCURISCAN_AUDITLOGS_LIFETIME, 'array'); $cacheTheResponse = false; /* cache if the data comes from the API */ /* API call if cache is invalid. */ if (!$auditlogs || $pageNumber !== 1) { ob_start(); $start = microtime(true); $cacheTheResponse = true; $auditlogs = SucuriScanAPI::getAuditLogs($logsLimit, $filters); $errors = ob_get_contents(); /* capture errors */ $duration = microtime(true) - $start; ob_end_clean(); /* report latency in the API calls */ if (!is_array($auditlogs)) { $response['status'] = __('API is not available; using local queue', 'sucuri-scanner'); } else { $response['status'] = sprintf(__('API %s secs', 'sucuri-scanner'), round($duration, 4)); } } /* stop everything and report errors */ if (!empty($errors)) { $response['content'] .= $errors; } /* Cache the data for some time. */ if ($cacheTheResponse && $auditlogs && empty($errors)) { $cache->add('response', $auditlogs); } /* merge the logs from the queue system */ $queuelogs = SucuriScanAPI::getAuditLogsFromQueue($filters); if (is_array($queuelogs) && !empty($queuelogs)) { if (!$auditlogs || empty($auditlogs)) { $auditlogs = $queuelogs; } else { $auditlogs['output'] = array_merge( $queuelogs['output'], @$auditlogs['output'] ); $auditlogs['output_data'] = array_merge( $queuelogs['output_data'], @$auditlogs['output_data'] ); if (isset($auditlogs['total_entries'])) { $auditlogs['total_entries'] = $auditlogs['total_entries'] + $queuelogs['total_entries']; } else { $auditlogs['total_entries'] = $queuelogs['total_entries']; } } } if (!is_array($auditlogs) || !isset($auditlogs['output_data']) || !isset($auditlogs['total_entries']) || !is_array($auditlogs['output_data']) || !is_numeric($auditlogs['total_entries']) || empty($auditlogs['output_data']) ) { $response['content'] = __('There are no logs.', 'sucuri-scanner'); wp_send_json($response, 200); return; } $counter_i = 0; $previousDate = ''; $outdata = (array)$auditlogs['output_data']; $todaysDate = SucuriScan::datetime(null, 'M d, Y'); $iterator_start = ($pageNumber - 1) * $maxPerPage; $total_items = count($outdata); usort($outdata, array('SucuriScanAuditLogs', 'sortByDate')); for ($i = $iterator_start; $i < $total_items; $i++) { if ($counter_i > $maxPerPage) { break; } if (!isset($outdata[$i])) { continue; } $audit_log = (array)$outdata[$i]; if (strpos($audit_log['message'], ";\x20password:")) { $idx = strpos($audit_log['message'], ";\x20password:"); $audit_log['message'] = substr($audit_log['message'], 0, $idx); } $snippet_data = array( 'AuditLog.Event' => $audit_log['event'], 'AuditLog.Time' => SucuriScan::datetime($audit_log['timestamp'], 'H:i'), 'AuditLog.Date' => SucuriScan::datetime($audit_log['timestamp'], 'M d, Y'), 'AuditLog.Username' => $audit_log['username'], 'AuditLog.Address' => $audit_log['remote_addr'], 'AuditLog.Message' => $audit_log['message'], 'AuditLog.Extra' => '', ); $date_data = self::getAuditLogDate($snippet_data['AuditLog.Date'], $previousDate, $todaysDate); $snippet_data['AuditLog.Date'] = $date_data['date']; $previousDate = $date_data['previousDate']; /* print every file_list information item in a separate table */ if ($audit_log['file_list']) { $snippet_data['AuditLog.Extra'] .= '
      '; foreach ($audit_log['file_list'] as $log_extra) { $snippet_data['AuditLog.Extra'] .= '
    • ' . SucuriScan::escape($log_extra) . '
    • '; } $snippet_data['AuditLog.Extra'] .= '
    '; } /* simplify the details of events with low metadata */ if (strpos($audit_log['message'], __('status has been changed', 'sucuri-scanner'))) { $snippet_data['AuditLog.Extra'] = implode(",\x20", $audit_log['file_list']); } $response['content'] .= SucuriScanTemplate::getSnippet('auditlogs', $snippet_data); $counter_i += 1; } $response['count'] = $counter_i; if ($total_items > 1) { $maxpages = ceil($total_items / $maxPerPage); if ($maxpages > SUCURISCAN_MAX_PAGINATION_BUTTONS) { $maxpages = SUCURISCAN_MAX_PAGINATION_BUTTONS; } if ($maxpages > 1) { $response['pagination'] = SucuriScanTemplate::pagination( SucuriScanTemplate::getUrl(), ($maxPerPage * $maxpages), $maxPerPage, $filters ); } } $response['queueSize'] = $auditlogs['total_entries']; wp_send_json($response, 200); } /** * Send the logs from the queue to the API. * * @codeCoverageIgnore - Notice that there is a test case that covers this * code, but since the WP-Send-JSON method uses die() to stop any further * output it means that XDebug cannot cover the next line, leaving a report * with a missing line in the coverage. Since the test case takes care of * the functionality of this code we will assume that it is fully covered. * * @return void */ public static function ajaxAuditLogsSendLogs() { if (SucuriScanRequest::post('form_action') !== 'auditlogs_send_logs') { return; } /* blocking; might take a while */ wp_send_json(SucuriScanEvent::sendLogsFromQueue(), 200); } /** * Sort the audit logs by date. * * Considering that the logs from the API service will be merged with the * logs from the local queue system to complement the information until the * queue is emptied, we will have to sort the entries in the list to keep * the dates in sync. * * @param array $a Data associated to a single log. * @param array $b Data associated to another log. * @return int Comparison between the dates of both logs. */ public static function sortByDate($a, $b) { if ($a['timestamp'] === $b['timestamp']) { return 0; } return ($a['timestamp'] > $b['timestamp']) ? -1 : 1; } /** * @param array $snippet_data * @param mixed $previousDate * @param mixed $todaysDate * @return array */ public static function getAuditLogDate($date = '', $previousDate = '', $todaysDate = '') { // Since we're iterating over the logs, we need to keep track of the // previous date to determine if we need to print the date again. // This serves as a visual separator between the logs. if ($date === $previousDate) { $date = ''; } elseif ($date === $todaysDate) { $previousDate = $date; $date = __('Today', 'sucuri-scanner'); } else { $previousDate = $date; } if (!empty($date)) { $date = '
    ' . $date . '
    '; } return array( 'date' => $date, 'previousDate' => $previousDate, ); } } src/base.lib.php000060400000067600147177152050007541 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Miscellaneous library. * * Multiple and generic methods that will be used through out the code of other * libraries extending from this and methods defined in other files, be aware of * the hierarchy and check the other libraries for duplicated methods. * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ class SucuriScan { /** * Throw generic exception instead of silent failure for unit-tests. * * @throws Exception * * @param string $message Error or information message. * @param string $type Either info or error. * @return bool False all the time. */ public static function throwException($message, $type = 'error') { if (defined('SUCURISCAN_THROW_EXCEPTIONS') && SUCURISCAN_THROW_EXCEPTIONS === true && is_string($message) ) { $code = ($type === 'error' ? 157 : 333); $message = str_replace( SUCURISCAN_ADMIN_NOTICE_PREFIX, ($type === 'error' ? __('Error:', 'sucuri-scanner') : __('Info:', 'sucuri-scanner')), $message ); /* throw catchable errors via tests */ throw new Exception($message, $code); } return false; /* for backward compatibility */ } /** * Return name of a variable with the plugin's prefix (if needed). * * To facilitate the development, you can prefix the name of the key in the * request (when accessing it) with a single colon, this method will auto- * matically replace that character with the unique plugin ID. * * @param string $name Text with optional colon prefix. * @return string Real variable name. */ public static function varPrefix($name = '') { if (!empty($name) && $name[0] === ':') { return sprintf( '%s_%s', SUCURISCAN, substr($name, 1) ); } return $name; } /** * Gets the value of a configuration option. * * @param string $property The configuration option name. * @param bool $raw Return the original value from the php.ini file. * @return string Value of the option as a string on success. */ public static function iniGet($property = '', $raw = false) { $ini_value = ini_get($property); if ($raw) { return $ini_value; } $default = array( 'error_log' => 'error_log', 'safe_mode' => 'not active', 'memory_limit' => '128M', 'upload_max_filesize' => '2M', 'post_max_size' => '8M', 'max_execution_time' => '30', 'max_input_time' => '-1', ); if ($ini_value === false) { $ini_value = 'unknown'; } elseif (empty($ini_value) || $ini_value === null) { if (array_key_exists($property, $default)) { $ini_value = $default[$property]; } else { $ini_value = 'not active'; } } if ($property == 'error_log') { $ini_value = basename($ini_value); } return $ini_value; } /** * Encodes the less-than, greater-than, ampersand, double quote and single * quote characters, will never double encode entities. * * @see https://developer.wordpress.org/reference/functions/esc_attr/ * * @param string $text The text which is to be encoded. * @return string The encoded text with HTML entities. */ public static function escape($text = '') { return esc_attr($text); } /** * Translate a given number in bytes to a human readable file size using the * a approximate value in Kylo, Mega, Giga, etc. * * @see https://www.php.net/manual/en/function.filesize.php#106569 * * @param int $bytes Integer representing a file size in bytes. * @param int $decimals How many decimals should be returned. * @return string Human readable representation of the given number. */ public static function humanFileSize($bytes = 0, $decimals = 2) { $sz = 'BKMGTP'; $factor = (int) floor((strlen((string) $bytes) - 1) / 3); $number = $bytes / pow(1024, $factor); $result = sprintf("%.{$decimals}f", $number) . @$sz[$factor]; $zeroes = '.' . str_repeat('0', $decimals); $result = str_replace($zeroes, '', $result); return $result; } /** * Returns the human version of the time difference. * * If the timestamp is in the past in comparison with the current time, it * will return a string in the form of "X time ago". If the timestamp is in * the future in comparison with the current time, it will return a string * in the form of "in X time". If the timestamp is the same as the current * time it will return "right now". * * @param int $time Unix timestamp. * @return string Different between timestamp and current time. */ public static function humanTime($time = 0) { if (!is_numeric($time)) { return 'N/A'; } $now = time(); if ($time === $now) { return 'right now'; } $result = ''; $template = ''; $diff = $now - $time; $groups = array( 31536000 => 'year', 2592000 => 'month', 86400 => 'day', 3600 => 'hour', 60 => 'minute', 1 => 'second', ); if ($time < $now) { $template = '%d %s ago'; } else { $template = 'in %d %s'; } foreach ($groups as $secs => $label) { $distance = abs($diff / $secs); if ($distance >= 1) { $plural = (round($distance) == 1) ? '' : 's'; $result = sprintf( $template, round($distance), $label . $plural ); break; } } return $result; } /** * Check if the admin init hook must not be intercepted. * * @return bool True if the admin init hook must not be intercepted. */ public static function noAdminInit() { return (bool) ( defined('SUCURISCAN_ADMIN_INIT') && SUCURISCAN_ADMIN_INIT === false ); } /** * Check if the admin init hook must be intercepted. * * @return bool True if the admin init hook must be intercepted. */ public static function runAdminInit() { return (bool) (self::noAdminInit() === false); } /** * Fix the deliminar of a resource path. * * In Windows based system the directory separator is a back slash which * differs from what other file systems use. To keep consistency during the * unit-tests we have decided to replace any non forward slash with it. * * @param string $path Directory path to fix. * @return string Fixed file path. */ public static function fixPath($path = '') { $new = str_replace(DIRECTORY_SEPARATOR, '/', $path); $new = rtrim($new, '/'); /* purge right side. */ return empty($new) ? '/' : $new; } /** * Returns the full path to a specific directory or file. * * @param string $path Path that needs to be completed. * @return string Full path including the base directory. */ public static function dataStorePath($path = '') { $folder = WP_CONTENT_DIR . '/uploads/sucuri'; /* custom path no matter its existence */ if (defined('SUCURI_DATA_STORAGE')) { $folder = SUCURI_DATA_STORAGE; } $fullpath = self::fixPath($folder . '/' . $path); $fullpath = str_replace('//', '/', $fullpath); $fullpath = rtrim($fullpath, '/'); return $fullpath; } /** * Check whether the current site is working as a multi-site instance. * * @return bool Either TRUE or FALSE in case WordPress is being used as a multi-site instance. */ public static function isMultiSite() { return (bool) (function_exists('is_multisite') && is_multisite()); } /** * Returns an URL from the admin dashboard. * * @param string $url Optional trailing of the URL. * @return string Full valid URL from the admin dashboard. */ public static function adminURL($url = '') { if (self::isMultiSite()) { // @codeCoverageIgnoreStart return network_admin_url($url); // @codeCoverageIgnoreEnd } return admin_url($url); } /** * Find and retrieve the current version of WordPress installed. * * @return string The version number of WordPress installed. */ public static function siteVersion() { if (isset($GLOBALS['wp_version'])) { return self::escape($GLOBALS['wp_version']); } $wp_version = ''; $filename = ABSPATH . '/' . WPINC . '/version.php'; $lines = SucuriScanFileInfo::fileLines($filename); foreach ($lines as $line) { if (strpos($line, '$wp_version') === 0) { $version = str_replace("\x20", '', $line); $index = strpos($version, "'"); $version = substr($version, $index + 1); $index = strpos($version, "'"); $version = substr($version, 0, $index); $wp_version = $version; break; } } return self::escape($wp_version); } /** * Find and retrieve the absolute path of the WordPress configuration file. * * @return string|bool Absolute path of the WordPress configuration file. */ public static function getConfigPath() { $filename = ABSPATH . '/wp-config.php'; /* check one directory up */ if (!file_exists($filename)) { $filename = ABSPATH . '/../wp-config.php'; } return @realpath($filename); } /** * Find and retrieve the absolute path of the main WordPress htaccess file. * * @return string Absolute path of the main WordPress htaccess file. */ public static function getHtaccessPath() { $result = ''; $base_dirs = array( rtrim(ABSPATH, '/'), dirname(ABSPATH), dirname(dirname(ABSPATH)), ); foreach ($base_dirs as $base_dir) { $htaccess_path = sprintf('%s/.htaccess', $base_dir); if (file_exists($htaccess_path)) { $result = $htaccess_path; break; } } return $result; } /** * Get the pattern of the definition related with a WordPress secret key. * * @return string Secret key definition pattern. */ public static function secretKeyPattern() { return '/define\(\s*\'([A-Z_]+)\',(\s*)\'(.+)\'\s*\);/'; } /** * Execute the plugin' scheduled tasks. * * @return void */ public static function runScheduledTask() { SucuriScanEvent::filesystemScan(); SucuriScanEvent::reportSiteVersion(); SucuriScanIntegrity::getIntegrityStatus(true); SucuriScanSettingsPosthack::availableUpdatesContent(true); SucuriScanEvent::sendLogsFromQueue(); /* blocking; keep at the end */ } /** * List of allowed HTTP headers to retrieve the real IP. * * Once the DNS lookups are enabled to discover the real IP address of the * visitors the user may choose the HTTP header that will be used by default to * retrieve the real IP address of each HTTP request, generally they do not need * to set this but in rare cases the hosting provider may have a load balancer * that can interfere in the process, in which case they will have to explicitly * specify the main HTTP header. This is a list of the allowed headers that the * user can choose. * * @param bool $with_keys Return the array with its values are keys. * @return array Allowed HTTP headers to retrieve real IP. */ public static function allowedHttpHeaders($with_keys = false) { $allowed = array( /* Sucuri custom HTTP headers */ 'HTTP_X_SUCURI_CLIENTIP', /* CloudFlare custom HTTP headers */ 'HTTP_CF_CONNECTING_IP', /* Real visitor IP. */ 'HTTP_CF_IPCOUNTRY', /* Country of visitor. */ 'HTTP_CF_RAY', /* https://support.cloudflare.com/entries/23046742-w. */ 'HTTP_CF_VISITOR', /* Determine if HTTP or HTTPS. */ /* Possible HTTP headers */ 'HTTP_X_REAL_IP', 'HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'SUCURI_RIP', 'REMOTE_ADDR', ); if ($with_keys === true) { $verbose = array(); foreach ($allowed as $header) { $verbose[$header] = $header; } return $verbose; } return $allowed; } /** * List HTTP headers ordered. * * The list of HTTP headers is ordered per relevancy, and having the main * HTTP header as the first entry, this guarantees that the IP address of * the visitors will be retrieved from the HTTP header chosen by the user * first and fallback to the other alternatives if available. * * @return array Ordered allowed HTTP headers. */ private static function orderedHttpHeaders() { $ordered = array(); $allowed = self::allowedHttpHeaders(); $addr_header = SucuriScanOption::getOption(':addr_header'); $ordered[] = $addr_header; foreach ($allowed as $header) { if (!in_array($header, $ordered)) { $ordered[] = $header; } } return $ordered; } /** * Retrieve the real ip address of the user in the current request. * * @param bool $with_header Return HTTP header where the IP address was found. * @return string Real IP address of the user in the current request. */ public static function getRemoteAddr($with_header = false) { $remote_addr = false; $header_used = 'unknown'; $headers = self::orderedHttpHeaders(); foreach ($headers as $header) { if (array_key_exists($header, $_SERVER) && self::isValidIP($_SERVER[$header]) ) { $remote_addr = $_SERVER[$header]; $header_used = $header; break; } } if (!$remote_addr || $remote_addr === '::1') { $remote_addr = '127.0.0.1'; } if ($with_header) { return $header_used; } return $remote_addr; } /** * Return the HTTP header used to retrieve the remote address. * * @return string The HTTP header used to retrieve the remote address. */ public static function getRemoteAddrHeader() { return self::getRemoteAddr(true); } /** * Retrieve the user-agent from the current request. * * @return string The user-agent from the current request. */ public static function getUserAgent() { if (isset($_SERVER['HTTP_USER_AGENT'])) { return self::escape($_SERVER['HTTP_USER_AGENT']); } return 'Mozilla/5.0 (KHTML, like Gecko) Safari/537.36'; } /** * Get the clean version of the current domain. * * @see https://developer.wordpress.org/reference/functions/get_site_url/ * * @param bool $return_tld Returns the top-level domain instead. * @return string The domain of the current site. */ public static function getDomain($return_tld = false) { $site_url = get_site_url(); $pattern = '/([fhtps]+:\/\/)?([^:\/]+)(:[0-9:]+)?(\/.*)?/'; $replacement = ($return_tld === true) ? '$2' : '$2$3$4'; $domain_name = @preg_replace($pattern, $replacement, $site_url); return $domain_name; } /** * Get top-level domain (TLD) of the website. * * @return string Top-level domain (TLD) of the website. */ public static function getTopLevelDomain() { return self::getDomain(true); } /** * Check whether reverse proxy servers must be supported. * * @return bool TRUE if reverse proxies must be supported, FALSE otherwise. */ public static function supportReverseProxy() { return SucuriScanOption::isEnabled(':revproxy'); } /** * Checks the existence of the HTTP_X_SUCURI_CLIENTIP header in the request headers * * Once active, the Sucuri Firewall sends custom headers to the server with information * about the original request. * * @return boolean True if the website is being reached with our HTTP_X_SUCURI_CLIENTIP header. */ private static function hasSucuriClientIPHeader() { return array_key_exists('HTTP_X_SUCURI_CLIENTIP', $_SERVER); } /** * Checks whether the site is behind the firewall network. * * @param bool $verbose Return array with HTTP and HOST information. * @return array|bool True if the firewall is in use, false otherwise. */ public static function isBehindFirewall($verbose = false) { if (!$verbose) { return (bool) self::hasSucuriClientIPHeader(); } $http_host = self::getTopLevelDomain(); $host_by_addr = @gethostbyname($http_host); $host_by_name = @gethostbyaddr($host_by_addr); return array( 'status' => self::hasSucuriClientIPHeader(), 'http_host' => self::getTopLevelDomain(), 'host_name' => $host_by_name, 'host_addr' => $host_by_addr, ); } /** * Get the email address set by the administrator to receive the alerts * sent by the plugin, if the email is missing the WordPress email address is * chosen by default. * * @return string The administrator email address. */ public static function getSiteEmail() { $email = get_option('admin_email'); if (self::isValidEmail($email)) { return $email; } return 'noreply@example.org'; } /** * Get user data by field and data. * * @see https://developer.wordpress.org/reference/functions/get_user_by/ * * @param int $identifier User account identifier. * @return array WordPress user object with data. */ public static function getUserByID($identifier = 0) { return get_user_by('id', $identifier); } /** * Retrieve a list of all admin user accounts. * * @see https://developer.wordpress.org/reference/functions/get_users/ * * @return array|bool List of admin users, false otherwise. */ public static function getAdminUsers() { return get_users(array('role' => 'administrator')); } /** * Get a list of user emails that can be used to generate an API key for this * website. Only accounts with the status in zero will be returned, the status * field in the users table is officially deprecated but some 3rd-party plugins * still use it to check if the account was activated by the owner of the email, * a value different than zero generally means that the email was not verified * successfully. * * @return array List of user identifiers and email addresses. */ public static function getUsersForAPIKey() { $valid_users = array(); $users = self::getAdminUsers(); if ($users !== false) { foreach ($users as $user) { if ($user->user_status === '0') { $valid_users[$user->ID] = sprintf( '%s - %s', $user->user_login, $user->user_email ); } } } return $valid_users; } /** * Retrieve the date in localized format, based on timestamp. * * If the locale specifies the locale month and weekday, then the locale will * take over the format for the date. If it isn't, then the date format string * will be used instead. * * @param null|string|int $timestamp Unix timestamp. * @param string $format Optional format for the date and time. * @return string The date, translated if locale specifies it. */ public static function datetime($timestamp = null, $format = null) { $diff = 0; /* use server time */ $tz = SucuriScanOption::getOption(':timezone'); $length = strlen($tz); /* example: UTC+12.75 */ if ($timestamp === null) { $timestamp = time(); } if ($length === 9 && substr($tz, 0, 3) === 'UTC' && ($tz[3] === '-' || $tz[3] === '+') && $tz[6] === '.' ) { $hour = (float) substr($tz, 4); $sign = ($tz[3] === '-') ? -1 : +1; $diff = ($hour * $sign); } else { /* reset; value seems to be corrupt */ SucuriScanOption::deleteOption(':timezone'); } if ($format === null) { $format = sprintf( "%s\x20%s", SucuriScanOption::getOption('date_format'), SucuriScanOption::getOption('time_format') ); } return date($format, (intval($timestamp) + ($diff * 3600))); } /** * Check whether an IP address has a valid format or not. * * @param string $remote_addr The host IP address. * @return bool Whether the IP address specified is valid or not. */ public static function isValidIP($remote_addr = '') { return (bool) @filter_var($remote_addr, FILTER_VALIDATE_IP); } /** * Check whether an IP address is formatted as CIDR or not. * * @param string $remote_addr The supposed ip address that will be checked. * @return bool Either TRUE or FALSE if the ip address specified is valid or not. */ public static function isValidCIDR($remote_addr = '') { if (!is_string($remote_addr)) { return false; } if (preg_match('/^([0-9\.]{7,15})\/(8|16|24)$/', $remote_addr, $match)) { return self::isValidIP($match[1]); } return false; } /** * Separate the parts of an IP address. * * @param string $remote_addr The supposed ip address that will be formatted. * @return array|bool Clean address, CIDR range, and CIDR format; FALSE otherwise. */ public static function getIPInfo($remote_addr = '') { if ($remote_addr) { $ip_parts = explode('/', $remote_addr); if (isset($ip_parts[0]) && self::isValidIP($ip_parts[0])) { $addr_info = array(); $addr_info['remote_addr'] = $ip_parts[0]; $addr_info['cidr_range'] = isset($ip_parts[1]) ? $ip_parts[1] : '32'; $addr_info['cidr_format'] = $addr_info['remote_addr'] . '/' . $addr_info['cidr_range']; return $addr_info; } } return false; } /** * Validate email address. * * This use the native PHP method filter_var which is available in PHP >= * 5.2.0 if it is not found in the interpreter this method will sue regular * expressions to check whether the email address passed is valid or not. * * @see https://www.php.net/manual/en/function.filter-var.php * * @param string $email The string that will be validated as an email address. * @return bool TRUE if the email address passed to the method is valid, FALSE if not. */ public static function isValidEmail($email = '') { return (bool) @filter_var($email, FILTER_VALIDATE_EMAIL); } /** * Cut a long text to the length specified, and append suspensive points at the end. * * @param string $text String of characters that will be cut. * @param int $length Maximum length of the returned string, default is 10. * @return string Short version of the text specified. */ public static function excerpt($text = '', $length = 10) { $text_length = strlen($text); if ($text_length > $length) { return substr($text, 0, $length) . '...'; } return $text; } /** * Check whether an list is a multidimensional array or not. * * @param array $list An array or multidimensional array of different values. * @return bool TRUE if the list is multidimensional, FALSE otherwise. */ public static function isMultiList($list = array()) { if (empty($list)) { return false; } $status = false; foreach ((array) $list as $item) { if (is_array($item)) { $status = true; break; } } return $status; } /** * Join array elements with a string no matter if it is multidimensional. * * @param string $separator Character that will act as a separator, default to an empty string. * @param array $list The array of strings to implode. * @return string String of all the items in the list, with the separator between them. */ public static function implode($separator = '', $list = array()) { if (!is_array($list)) { return 'INVALID_ARGS'; } if (self::isMultiList($list)) { $pieces = array(); foreach ($list as $items) { $pieces[] = @implode($separator, $items); } return '(' . implode('), (', $pieces) . ')'; } return implode($separator, $list); } /** * Check whether the site is running over the Nginx web server. * * @return bool TRUE if the site is running over Nginx, FALSE otherwise. */ public static function isNginxServer() { return (bool) (stripos(@$_SERVER['SERVER_SOFTWARE'], 'nginx') !== false); } /** * Check whether the site is running over the Nginx web server. * * @return bool TRUE if the site is running over Nginx, FALSE otherwise. */ public static function isIISServer() { return (bool) (stripos(@$_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== false); } /** * Returns the md5 hash representing the content of a file. * * @param string $file Relative path to the file. * @return string Seven first characters in the hash of the file. */ public static function fileVersion($file = '') { return substr(md5_file(SUCURISCAN_PLUGIN_PATH . '/' . $file), 0, 7); } public static function issetScanApiUrl() { return defined('SUCURISCAN_API_URL') && !empty(SUCURISCAN_API_URL); } } src/cachecontrol.lib.php000060400000022531147177152050011265 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Cache-Control library. * * We use this library to set the cache control headers based on the user's * settings. The cache control headers are used to control how the browser * and proxies cache the content of the website. * * Please enable site caching on your WAF to use these settings. * * Please note that this is an advanced feature, and we took some inspiration * from another WordPress plugin called "cache-control", which hasn't been updated * in a long time. We've made some improvements and added some new features, * but we still want to give credit to the original author. * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ class SucuriScanCacheHeaders extends SucuriScan { protected function getCacheControlStaleFactor($factor, $maxAge) { if (is_paged() && is_int($factor) && $factor > 0) { $multiplier = get_query_var('paged') - 1; if ($multiplier > 0) { $factoredMaxAge = $factor * $multiplier; if ($factoredMaxAge >= ($maxAge * 10)) { return $maxAge * 10; } return $factoredMaxAge; } } return 0; } protected function getFuturePostMaxTime($maxTimeFuture) { $futurePostQuery = new WP_Query(array( 'post_status' => 'future', 'posts_per_page' => 1, 'orderby' => 'date', 'order' => 'ASC', 'ignore_sticky_posts' => 1 )); if ($futurePostQuery->have_posts()) { $localNowTime = intval(current_time('timestamp', 0)); while ($futurePostQuery->have_posts()) { $futurePostQuery->the_post(); $localFutureTime = get_the_time('U'); if (($localNowTime + $maxTimeFuture) > $localFutureTime) { $maxTimeFuture = $localFutureTime - $localNowTime + rand(2, 32); } } wp_reset_postdata(); } return $maxTimeFuture; } protected function getCacheDirectives($maxAge, $sMaxAge, $staleError, $staleRevalidate) { $directive = ""; if (!empty($maxAge) && is_int($maxAge) && $maxAge > 0) { $directive = "max-age=$maxAge"; } if (!empty($sMaxAge) && is_int($sMaxAge) && $sMaxAge > 0 && $sMaxAge != $maxAge) { if ($directive != "") { $directive = "public"; } $directive .= ", s-maxage=$sMaxAge"; } // Append RFC 5861 headers only if the request is cacheable if ($directive != "") { if (!empty($staleError) && is_int($staleError) && $staleError > 0) { $directive .= ", stale-if-error=$staleError"; } if (!empty($staleRevalidate) && is_int($staleRevalidate) && $staleRevalidate > 0) { $directive .= ", stale-while-revalidate=$staleRevalidate"; } $directive = apply_filters('cache_control_cache_directive', $directive); return $directive; } // Request isn't cacheable return "no-cache, no-store, must-revalidate"; } protected function getCacheDirectiveFromOption($optionName) { $cacheOptions = SucuriScanOption::getOption(':headers_cache_control_options'); $option = $cacheOptions[$optionName]; $maxAge = intval($option['max_age']); $sMaxAge = intval($option['s_maxage']); $staleError = intval($option['stale_if_error']); $staleRevalidate = intval($option['stale_while_revalidate']); // Dynamically shorten caching time when a scheduled post is imminent if (!in_array($optionName, array('attachment_pages', 'dates', 'pages', 'singles', '404_not_found'))) { $maxAge = $this->getFuturePostMaxTime($maxAge); $sMaxAge = $this->getFuturePostMaxTime($sMaxAge); } if (is_paged() && isset($option['paged'])) { $pageFactor = intval(get_option('cache_control_' . $option['id'] . '_paged', $option['paged'])); $maxAge += $this->getCacheControlStaleFactor($pageFactor, $maxAge); $sMaxAge += $this->getCacheControlStaleFactor($pageFactor, $sMaxAge); } if ($optionName == 'singles') { $dateNow = new DateTime(); $dateModified = new DateTime(get_the_modified_date('c')); $lastComment = get_comments(array( 'post_id' => get_the_ID(), 'number' => 1, 'include_unapproved' => 1, 'orderby' => 'comment_date' )); if ($lastComment != null) { $lastCommentDate = new DateTime($lastComment[0]->comment_date); $dateModified = max(array($dateModified, $lastCommentDate)); } $dateDiff = $dateNow->diff($dateModified); $monthsStale = $dateDiff->m + ($dateDiff->y * 12); if ($monthsStale > 0) { $maxAge = intval($maxAge * (($monthsStale + 12) / 12)); $sMaxAge = intval($sMaxAge * (($monthsStale + 12) / 12)); } } return $this->getCacheDirectives($maxAge, $sMaxAge, $staleError, $staleRevalidate); } protected function isNoCacheable() { global $wp_query; $nonCacheable = is_preview() || is_user_logged_in() || is_trackback() || is_admin(); // Requires post password, and post has been unlocked. if (!$nonCacheable && isset($wp_query->posts) && count($wp_query->posts) >= 1 && !empty($wp_query->posts[0]->post_password) && !post_password_required()) { $nonCacheable = true; } elseif (!$nonCacheable && function_exists('is_woocommerce')) { $nonCacheable = is_cart() || is_checkout() || is_account_page(); } return $nonCacheable; } protected function isWooCommerceInstalled() { return in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins'))); } protected function selectCacheDirective() { if ($this->isNoCacheable()) { return $this->getCacheDirectives(false, false, false, false); } elseif (is_feed()) { return $this->getCacheDirectiveFromOption('feeds'); } elseif (is_front_page() && !is_paged()) { return $this->getCacheDirectiveFromOption('front_page'); } elseif (is_single()) { return $this->getCacheDirectiveFromOption('posts'); } elseif (is_page()) { return $this->getCacheDirectiveFromOption('pages'); } elseif (is_home()) { return $this->getCacheDirectiveFromOption('main_index'); } elseif (is_category()) { return $this->getCacheDirectiveFromOption('categories'); } elseif (is_tag()) { return $this->getCacheDirectiveFromOption('tags'); } elseif (is_author()) { return $this->getCacheDirectiveFromOption('authors'); } elseif (is_attachment()) { return $this->getCacheDirectiveFromOption('attachment_pages'); } elseif (is_search()) { return $this->getCacheDirectiveFromOption('search_results'); } elseif (is_404()) { return $this->getCacheDirectiveFromOption('404_not_found'); } elseif (is_date()) { if ((is_year() && strcmp(get_the_time('Y'), date('Y')) < 0) || (is_month() && strcmp(get_the_time('Y-m'), date('Y-m')) < 0) || ((is_day() || is_time()) && strcmp(get_the_time('Y-m-d'), date('Y-m-d')) < 0)) { return $this->getCacheDirectiveFromOption('dates'); } else { return $this->getCacheDirectiveFromOption('home'); } } elseif ($this->isWooCommerceInstalled()) { if (function_exists('is_product') && is_product()) { return $this->getCacheDirectiveFromOption('woocommerce_product'); } elseif (function_exists('is_product_category') && is_product_category()) { return $this->getCacheDirectiveFromOption('woocommerce_category'); } } return $this->getCacheDirectives(false, false, false, false); } protected function mergeHttpHeader($directives) { if (!empty($directives)) { header("Cache-Control: $directives", true); } } public function setCacheHeaders() { if (headers_sent()) { // Headers are already sent; nothing to do here. return; } $header = $this->selectCacheDirective(); $this->mergeHttpHeader($header); } } src/cache.lib.php000060400000040234147177152050007664 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * File-based cache library. * * WP_Object_Cache [1] is WordPress' class for caching data which may be * computationally expensive to regenerate, such as the result of complex * database queries. However the object cache is non-persistent. This means that * data stored in the cache resides in memory only and only for the duration of * the request. Cached data will not be stored persistently across page loads * unless of the installation of a 3party persistent caching plugin [2]. * * [1] https://codex.wordpress.org/Class_Reference/WP_Object_Cache * [2] https://codex.wordpress.org/Class_Reference/WP_Object_Cache#Persistent_Caching * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ class SucuriScanCache extends SucuriScan { /** * The unique name (or identifier) of the file with the data. * * The file should be located in the same folder where the dynamic data * generated by the plugin is stored, and using the following format [1], it * most be a PHP file because it is expected to have an exit point in the first * line of the file causing it to stop the execution if a unauthorized user * tries to access it directly. * * [1] /public/data/sucuri-DATASTORE.php * * @var string */ private $datastore; /** * The full path of the datastore file. * * @var string */ private $datastore_path; /** * Whether the datastore file is usable or not. * * This variable will only be TRUE if the datastore file specified exists, is * writable and readable, in any other case it will always be FALSE. * * @var bool */ private $usable_datastore; /** * Initializes the cache library. * * @param string $datastore Name of the storage file. * @param bool $auto_create Forces the creation of the storage file. * @return void */ public function __construct($datastore = '', $auto_create = true) { $this->datastore = $datastore; $this->datastore_path = $this->datastoreFilePath($auto_create); $this->usable_datastore = (bool) $this->datastore_path; } /** * Default attributes for every datastore file. * * @return array Default attributes for every datastore file. */ public function datastoreDefaultInfo() { $attrs = array( 'datastore' => $this->datastore, 'created_on' => time(), 'updated_on' => time(), ); return $attrs; } /** * Default content of every datastore file. * * @param array $finfo Rainbow table with the key names and decoded values. * @return string Default content of every datastore file. */ private function datastoreInfo($finfo = array()) { $attrs = $this->datastoreDefaultInfo(); $info_is_available = (bool) isset($finfo['info']); $info = " $attr_value) { if ($info_is_available && $attr_name != 'updated_on' && isset($finfo['info'][$attr_name]) ) { $attr_value = $finfo['info'][$attr_name]; } $info .= sprintf("// %s=%s;\n", $attr_name, $attr_value); } $info .= "exit(0);\n"; $info .= "?>\n"; return $info; } /** * Check if the datastore file exists, if it's writable and readable by the same * user running the server, in case that it does not exists the method will * tries to create it by itself with the right permissions to use it. * * @param bool $auto_create Create the file is it does not exists. * @return string|bool Absolute path to the storage file, false otherwise. */ private function datastoreFilePath($auto_create = false) { if (!$this->datastore) { return false; } $filename = $this->dataStorePath('sucuri-' . $this->datastore . '.php'); $directory = dirname($filename); /* create directory if necessary */ if (!file_exists($directory)) { @mkdir($directory, 0755, true); } if (!file_exists($filename) && is_writable($directory) && $auto_create) { @file_put_contents($filename, $this->datastoreInfo()); } return $filename; } /** * Check whether a key has a valid name or not. * * WARNING: Instead of using a regular expression to match the format of the * key we will use a primitive string transformation technique to reduce the * execution time, regular expressions are significantly slow. * * @param string $key Unique name for the data. * @return bool True if the key is valid, false otherwise. */ private function validKeyName($key = '') { $result = true; $length = strlen($key); $allowed = array( /* preg_match('/^([0-9a-zA-Z_]+)$/', $key) */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '_', ); for ($i = 0; $i < $length; $i++) { if (!in_array($key[$i], $allowed)) { $result = false; break; } } return $result; } /** * Update the content of the datastore file with the new entries. * * @param array $finfo Rainbow table with the key names and decoded values. * @return bool TRUE if the operation finished successfully, FALSE otherwise. */ private function saveNewEntries($finfo = array()) { if (!$finfo) { return false; } $metadata = $this->datastoreInfo($finfo); if (@file_put_contents($this->datastore_path, $metadata)) { foreach ($finfo['entries'] as $key => $data) { $line = sprintf("%s:%s\n", $key, json_encode($data)); @file_put_contents($this->datastore_path, $line, FILE_APPEND); } } return true; } /** * Retrieve and parse the cache file and generate a hash table with the keys * and decoded data as the values of each entry. Duplicated key names will * be merged automatically. * * @param bool $assoc Force object to array conversion. * @param bool $onlyInfo Returns the cache headers and no content. * @return array Rainbow table with the key names and decoded values. */ private function getDatastoreContent($assoc = false, $onlyInfo = false) { $object = array(); $object['info'] = array(); $object['entries'] = array(); if (($fh = @fopen($this->datastore_path, 'r')) === false) { return $object; } while (($line = fgets($fh)) !== false) { $line = trim($line); if (!$line) { continue; } if (strpos($line, "//\x20") === 0 && strpos($line, '=') !== false && $line[strlen($line) - 1] === ';' ) { $section = substr($line, 3, -1); list($header, $value) = explode('=', $section, 2); $object['info'][$header] = $value; continue; } // skip content if ($onlyInfo) { continue; } if (strpos($line, ':') !== false) { list($keyname, $value) = explode(':', $line, 2); $object['entries'][$keyname] = @json_decode($value, $assoc); } } fclose($fh); return $object; } /** * Retrieve the headers of the datastore file. * * Each datastore file has a list of attributes at the beginning of the it with * information like the creation and last update time. If you are extending the * functionality of these headers please refer to the method that contains the * default attributes and their values [1]. * * [1] SucuriScanCache::datastoreDefaultInfo() * * @return array|bool Default content of every datastore file. */ public function getDatastoreInfo() { $finfo = $this->getDatastoreContent(false, true); if (empty($finfo['info'])) { return false; } $finfo['info']['fpath'] = $this->datastore_path; if (!isset($finfo['info']['created_on'])) { $finfo['info']['created_on'] = time(); } if (!isset($finfo['info']['updated_on'])) { $finfo['info']['updated_on'] = time(); } return $finfo['info']; } /** * Returns the Unix timestamp when the cache was created. * * @return int Unix timestamp when the cache was created. */ public function createdAt() { $info = $this->getDatastoreInfo(); return (int) $info['created_on']; } /** * Returns the Unix timestamp when the cache was updated. * * @return int Unix timestamp when the cache was updated. */ public function updatedAt() { $info = $this->getDatastoreInfo(); return (int) $info['updated_on']; } /** * Get the total number of unique entries in the datastore file. * * @param array $finfo Rainbow table with the key names and decoded values. * @return int Total number of unique entries found in the datastore file. */ public function getCount($finfo = null) { if (!is_array($finfo)) { $finfo = $this->getDatastoreContent(); } return count($finfo['entries']); } /** * Check whether the last update time of the datastore file has surpassed the * lifetime specified for a key name. This method is the only one related with * the caching process, any others besides this are just methods used to handle * the data inside those files. * * @param int $lifetime Life time of the key in the datastore file. * @param array $finfo Rainbow table with the key names and decoded values. * @return bool TRUE if the life time of the data has expired, FALSE otherwise. */ public function dataHasExpired($lifetime = 0, $finfo = null) { if (!is_array($finfo)) { $meta = $this->getDatastoreInfo(); $finfo = array('info' => $meta); } if ($lifetime > 0 && !empty($finfo['info'])) { $diff_time = time() - intval($finfo['info']['updated_on']); if ($diff_time >= $lifetime) { return true; } } return false; } /** * JSON-encode the data and store it in the datastore file identifying it with * the key name, the data will be added to the file even if the key is * duplicated, but when getting the value of the same key later again it will * return only the value of the first occurrence found in the file. * * @param string $key Unique name for the data. * @param mixed $data Data to associate to the key. * @return bool True if the data was cached, false otherwise. */ public function add($key = '', $data = '') { return $this->set($key, $data); } /** * Update the data of all the key names matching the one specified. * * @param string $key Unique name for the data. * @param mixed $data Data to associate to the key. * @return bool True if the cache data was updated, false otherwise. */ public function set($key = '', $data = '') { if (!$this->validKeyName($key)) { return self::throwException(__('Invalid cache key name', 'sucuri-scanner')); } $finfo = $this->getDatastoreInfo(); if (empty($finfo['fpath'])) { return false; } $line = sprintf("%s:%s\n", $key, json_encode($data)); return (bool) @file_put_contents($finfo['fpath'], $line, FILE_APPEND); } /** * Retrieve the first occurrence of the key found in the datastore file. * * @param string $key Unique name for the data. * @param int $lifetime Seconds before the data expires. * @param string $assoc Force data to be converted to an array. * @return mixed Data associated to the key. */ public function get($key = '', $lifetime = 0, $assoc = '') { if (!$this->validKeyName($key)) { return self::throwException(__('Invalid cache key name', 'sucuri-scanner')); } $finfo = $this->getDatastoreContent($assoc === 'array'); if ($this->dataHasExpired($lifetime, $finfo) || !array_key_exists($key, $finfo['entries']) ) { return false; } return @$finfo['entries'][$key]; } /** * Retrieve all the entries found in the datastore file. * * @param int $lifetime Life time of the key in the datastore file. * @param string $assoc Force data to be converted to an array. * @return mixed All the entries stored in the cache file. */ public function getAll($lifetime = 0, $assoc = '') { $finfo = $this->getDatastoreContent($assoc === 'array'); if ($this->dataHasExpired($lifetime, $finfo)) { return false; } return $finfo['entries']; } /** * Check whether a specific key exists in the datastore file. * * @param string $key Unique name for the data. * @return bool True if the data exists, false otherwise. */ public function exists($key = '') { if (!$this->validKeyName($key)) { return self::throwException(__('Invalid cache key name', 'sucuri-scanner')); } $finfo = $this->getDatastoreContent(true); return array_key_exists($key, $finfo['entries']); } /** * Delete any entry from the datastore file matching the key name specified. * * @param string $key Unique name for the data. * @return bool True if the data was deleted, false otherwise. */ public function delete($key = '') { if (!$this->validKeyName($key)) { return self::throwException(__('Invalid cache key name', 'sucuri-scanner')); } $finfo = $this->getDatastoreContent(true); if (!array_key_exists($key, $finfo['entries'])) { return true; } unset($finfo['entries'][$key]); return $this->saveNewEntries($finfo); } /** * Replaces the entire content of the cache file. * * @param array $entries New data for the cache. * @return bool True if the cache was replaced. */ public function override($entries = array()) { return $this->saveNewEntries( array( 'info' => $this->getDatastoreInfo(), 'entries' => $entries, ) ); } /** * Remove all the entries from the datastore file. * * @return bool True, unless the cache file is not writable. */ public function flush() { $filename = 'sucuri-' . $this->datastore . '.php'; return @unlink($this->dataStorePath($filename)); } } src/cli.lib.php000060400000011461147177152050007370 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Manage Sucuri API registration. * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ class SucuriScanCLI extends WP_CLI_Command { /** * Register and connect to the Sucuri API. * * ## OPTIONS * * [] * : Sucuri API key to register with. * * ## EXAMPLES * * # New registration * wp sucuri register * API key: 99e656abef7a123d1cffe73f91ba63702 * Success: The API key for your site was successfully generated and saved. * * # Existing key registration * wp sucuri register 99e656abef7a123d1cffe73f91ba63702 * Success: The API key for your site was successfully saved. * * # Registration recovery * wp sucuri register * Warning: We already have an API key created for this site. It has been sent to the email admin@example.com for recovery. * * @param array $args Arguments from the command line interface. * @return void */ public function register($args) { list($api_key) = $args; ob_start(); $registered = $api_key ? SucuriScanAPI::setPluginKey($api_key, true) : SucuriScanAPI::registerSite(); $output = ob_get_clean(); preg_match_all('/

    SUCURI:<\/b>(.+)<\/p>/', $output, $matches); $message = isset($matches[1][0]) ? trim(strip_tags($matches[1][0])) : 'An unknown error occurred during registration.'; if (! $registered) { WP_CLI::error($message); } if ($registered && $api_key) { WP_CLI::success('The API key for your site was successfully saved.'); return; } $api_key = SucuriScanAPI::getPluginKey(); WP_CLI::line("API key: $api_key"); WP_CLI::success($message); } /** * Manage which files are included in Sucuri integrity checks. * * ## OPTIONS * * * : The action to be taken (ignore or unignore). * * * : Relative path to a file. * * [--reason=] * : Why the file should be ignored from integrity checks. * --- * default: added * options: * - added * - modified * - removed * --- * * ## EXAMPLES * * # Ignore a file * wp sucuri integrity ignore wp-admin/install.php --reason=removed * Success: 'wp-admin/install.php' file successfully ignored. * * # Unignore a file * wp sucuri integrity unignore foo.php * Success: 'foo.php' file successfully unignored. * * @param array $args Arguments from the command line interface. * @param array $assoc_args Associative arguments from the command line interface. * @return void */ public function integrity($args, $assoc_args) { list($action, $file_path) = $args; $allowed_actions = array('ignore', 'unignore'); if (! in_array($action, $allowed_actions, true)) { WP_CLI::error("Requested action '{$action}' is not supported."); } $allowed_reasons = array('added', 'modified', 'removed'); $file_status = WP_CLI\Utils\get_flag_value( $assoc_args, 'reason', $default = 'added' ); if (! in_array($file_status, $allowed_reasons, true)) { WP_CLI::error("Specified reason '{$file_status}' is not supported."); } $cache = new SucuriScanCache('integrity'); $cache_key = md5($file_path); if ('ignore' === $action) { $cache->add( $cache_key, array( 'file_path' => $file_path, 'file_status' => $file_status, 'ignored_at' => time(), ) ); WP_CLI::success("'{$file_path}' file successfully ignored."); } if ('unignore' === $action) { $cache->delete($cache_key); WP_CLI::success("'{$file_path}' file successfully unignored."); } } } WP_CLI::add_command('sucuri', 'SucuriScanCLI'); src/command.lib.php000060400000014305147177152050010237 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Class to process files and folders. * * Here are implemented the methods needed to open, scan, read, create files * and folders using the built-in PHP class SplFileInfo. The SplFileInfo class * offers a high-level object oriented interface to information for an individual * file. * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ class SucuriScanCommand extends SucuriScan { /** * Check if the system was configured to allow the execution of certain shell * commands. In this specific case, we want to know if the generic exec method * is enabled or not to allow the execution of system programs. * * @return bool True if the exec method is enabled, false otherwise. */ private static function canExecuteCommands() { $disabled = self::iniGet('disable_functions', true); $methods = explode(',', $disabled); return !in_array('exec', $methods); } /** * Checks if an external command exists or not. * * @param string $cmd Name of the external command. * @return bool True if the command exists, false otherwise. */ public static function exists($cmd) { $err = 255; $out = array(); if (self::canExecuteCommands()) { $command = sprintf('command -v %s 1>/dev/null', escapeshellarg($cmd)); @exec($command, $out, $err); /* ignore output and capture errors */ } if ($err !== 0) { return self::throwException('Command ' . $cmd . ' does not exist'); } return true; } /** * Compares two files line by line. * * @param string $a File path of the original file. * @param string $b File path of the modified file. * @return array Line-by-line changes (if any). */ public static function diff($a, $b) { $out = array(); if (self::exists('diff')) { @exec( sprintf( 'diff -u -- %s %s 2> /dev/null', escapeshellarg($a), escapeshellarg($b) ), $out, $err ); } return $out; } /** * Generates the HTML code with the diff output. * * The method takes the relative path of a core WordPress file, then tries * to download a fresh copy of such file from the official WordPress API. If * the download succeeds the method will write the content of this file into * a temporary resource. Then it will use the Unix diff utility to find all * the differences between the original code and the one present in the site. * * If there are differences, the method will write the HTML code to report * them in the dashboard. Some basic CSS classes will be attached to some of * the elements in the code to facilitate the styling of the diff report. * * @param string $filepath Relative path to the core WordPress file. * @return string|bool HTML code with the diff report, false on failure. */ public static function diffHTML($filepath) { $checksums = SucuriScanAPI::getOfficialChecksums(); if (!$checksums) { return SucuriScanInterface::error('Unsupported WordPress version.'); } if (!array_key_exists($filepath, $checksums)) { return SucuriScanInterface::error('Not an official WordPress file.'); } $output = ''; /* initialize empty with no differences */ $a = tempnam(sys_get_temp_dir(), SUCURISCAN . '-integrity-'); $b = tempnam(sys_get_temp_dir(), SUCURISCAN . '-integrity-'); $handle = @fopen($a, 'w'); if ($handle) { @fwrite($handle, SucuriScanAPI::getOriginalCoreFile($filepath)); @copy(ABSPATH . '/' . $filepath, $b); $output = self::diff($a, $b); @fclose($handle); } @unlink($a); /* delete original file */ @unlink($b); /* delete modified file */ if (!is_array($output) || empty($output)) { return SucuriScanInterface::error('There are no differences.'); } $response = "

      \n"; foreach ($output as $key => $line) { $number = $key + 1; /* line number */ $cssclass = SUCURISCAN . '-diff-line'; $cssclass .= "\x20" . SUCURISCAN . '-diff-line' . $number; if ($number === 1) { $line = sprintf('--- %s (ORIGINAL)', $filepath); $cssclass .= "\x20" . SUCURISCAN . '-diff-header'; } elseif ($number === 2) { $line = sprintf('+++ %s (MODIFIED)', $filepath); $cssclass .= "\x20" . SUCURISCAN . '-diff-header'; } elseif ($number === 3) { $cssclass .= "\x20" . SUCURISCAN . '-diff-header'; } elseif ($line === '') { /* do not touch empty lines */ } elseif ($line[0] === '-') { $cssclass .= "\x20" . SUCURISCAN . '-diff-minus'; } elseif ($line[0] === '+') { $cssclass .= "\x20" . SUCURISCAN . '-diff-plus'; } $response .= sprintf( "
    • %s
    • \n", $cssclass, /* include external CSS styling */ SucuriScan::escape($line) /* clean user input */ ); } $response .= "
    \n"; return $response; } } src/cron.lib.php000060400000003470147177152050007563 0ustar00 * @copyright 2010-2019 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Class to process Sucuri custom cronjobs. * * Here are implemented the cronjob methods used by the plugin. * * Remember: methods must be static and their name must match the cron hook. * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Northon Torga * @copyright 2010-2019 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ class SucuriScanCrons extends SucuriScan { /** * Update secret keys. */ public static function sucuriscan_autoseckeyupdater() { $wpconfig_process = SucuriScanEvent::setNewConfigKeys(); if (!$wpconfig_process) { SucuriScanEvent::reportNoticeEvent(__('Automatic update of security keys failed. WordPress configuration file was not found or new keys could not be created.', 'sucuri-scanner')); } elseif ($wpconfig_process['updated']) { SucuriScanEvent::reportNoticeEvent(__('Automatic update of security keys succeeded.', 'sucuri-scanner')); } else { SucuriScanEvent::reportNoticeEvent(__('Automatic update of security keys failed. Something went wrong!', 'sucuri-scanner')); } } } src/event.lib.php000060400000077651147177152050007757 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * System events, reports and actions. * * An event is an action or occurrence detected by the program that may be * handled by the program. Typically events are handled synchronously with the * program flow, that is, the program has one or more dedicated places where * events are handled, frequently an event loop. Typical sources of events * include the user; another source is a hardware device such as a timer. Any * program can trigger its own custom set of events as well, e.g. to communicate * the completion of a task. A computer program that changes its behavior in * response to events is said to be event-driven, often with the goal of being * interactive. * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ class SucuriScanEvent extends SucuriScan { /** * Creates a cronjob to run the file system scanner. * * Right after a fresh installation of the plugin, it will create a cronjob * that will execute the first scan in the next five minutes. This scan will * set the base-line for the file monitor through the API service. When a new * scan is execute the API will compare the checksum from the previous file * list with the checksum of the new file list, if there are differences we * will assume that someone or something modified one or more files and send * an email alsert about the incident. * * @return void */ public static function installScheduledTask() { $task_name = 'sucuriscan_scheduled_scan'; if (!wp_next_scheduled($task_name)) { wp_schedule_event(time() + 10, 'daily', $task_name); } } /** * Returns a list of available cronjob frequencies. * * This method will return not only the default WordPress cronjob frequencies * but also the custom ones defined by 3rd-party plugins or themes. It will * also add an additional option to allow the website owners to disable the * schedule tasks from the settings page. * * @see https://developer.wordpress.org/reference/functions/wp_get_schedules/ * * @return array List of available cronjob frequencies. */ public static function availableSchedules() { $schedules = array(); $jobs = wp_get_schedules(); foreach ($jobs as $unique => $info) { $schedules[$unique] = sprintf( __('%s (every %d seconds)', 'sucuri-scanner'), $info['display'], $info['interval'] ); } $schedules['_oneoff'] = __('Never (no execution)', 'sucuri-scanner'); return $schedules; } /** * Returns a list of active cronjobs. * * This method will return not only the default WordPress cronjobs but also * the custom ones defined by 3rd-party plugins or themes. * * @see https://developer.wordpress.org/reference/functions/_get_cron_array/ * * @return array List of available cronjobs. */ public static function activeSchedules() { $activeCrons = array(); foreach ((array) _get_cron_array() as $timestamp => $cronhooks) { foreach ((array) $cronhooks as $hook => $events) { foreach ((array) $events as $key => $event) { if (empty($event['args'])) { $event['args'] = array('[]'); } $activeCrons[$hook] = array( 'schedule' => $event['schedule'], 'nextTime' => SucuriScan::datetime($timestamp), 'nextTimeHuman' => SucuriScan::humanTime($timestamp), 'arguments' => json_encode($event['args']), ); } } } return $activeCrons; } /** * Creates the cronjob weekly, monthly and quarterly frequencies. * * A few Sucuri services require additional cronjob frequencies that are not * available on WordPress by default. This function will add these schedules * frequency if they were not yet register by any a 3rd party extension. * * @return void */ public static function additionalSchedulesFrequencies($schedules) { if (!defined('MONTH_IN_SECONDS')) { define('MONTH_IN_SECONDS', 30 * DAY_IN_SECONDS); } if (!isset($schedules['weekly'])) { $schedules['weekly'] = array( 'display' => __('Weekly', 'sucuriscan'), 'interval' => WEEK_IN_SECONDS, ); } if (!isset($schedules['monthly'])) { $schedules['monthly'] = array( 'display' => __('Monthly', 'sucuriscan'), 'interval' => MONTH_IN_SECONDS, ); } if (!isset($schedules['quarterly'])) { $schedules['quarterly'] = array( 'display' => __('Quarterly', 'sucuriscan'), 'interval' => 3 * MONTH_IN_SECONDS, ); } return $schedules; } /** * Creates a cronjob. * * @return bool True if the cronjob is correctly created. */ public static function addScheduledTask($hookName, $frequency) { // Return false if schedule frequency does not exist. if (!in_array($frequency, array_keys(self::availableSchedules()))) { return false; } // Remove cron first if already exists. if (wp_next_scheduled($hookName)) { self::deleteScheduledTask($hookName); } // Add cron job hook. wp_schedule_event(time() + 10, $frequency, $hookName); return true; } /** * Deletes a cronjob. * * @return bool True if the cronjob is correctly removed. */ public static function deleteScheduledTask($hookName) { // Return false if task does not exist. if (!wp_next_scheduled($hookName)) { return false; } // Remove cron job hook. wp_clear_scheduled_hook($hookName); return true; } /** * Reports the WordPress version number to the API. * * @return bool True if the version number was reported, false otherwise. */ public static function reportSiteVersion() { if (!SucuriScanAPI::getPluginKey()) { return self::throwException(__('API key is not available', 'sucuri-scanner')); } $wp_version = self::siteVersion(); $reported_version = SucuriScanOption::getOption(':site_version'); /* use simple comparison to leverage casting */ if ($reported_version == $wp_version) { return self::throwException(__('WordPress version was already reported', 'sucuri-scanner')); } SucuriScanEvent::reportInfoEvent(sprintf(__('WordPress version detected %s', 'sucuri-scanner'), $wp_version)); return SucuriScanOption::updateOption(':site_version', $wp_version); } /** * Decides if the file system scanner can run or not. * * @param bool $force_scan Force the execution of the scanner. * @return bool True if the scanner can run, false otherwise. */ private static function runFileScanner($force_scan = false) { if ($force_scan) { return SucuriScanOption::updateOption(':runtime', time()); } $current_time = time(); $runtime = (int) SucuriScanOption::getOption(':runtime'); $diff = abs($current_time - $runtime); if ($diff < SUCURISCAN_SCANNER_FREQUENCY) { return false; } return SucuriScanOption::updateOption(':runtime', $current_time); } /** * Gather all the checksums (aka. file hashes) of this site, send them, and * analyze them using the Sucuri Monitoring service, this will generate the * audit logs for this site and be part of the integrity checks. * * @param bool $force_scan Whether the filesystem scan was forced by an administrator user or not. * @return bool True if the filesystem scan was successful, false otherwise. */ public static function filesystemScan($force_scan = false) { if (!SucuriScanAPI::getPluginKey()) { return self::throwException(__('API key is not available', 'sucuri-scanner')); } if (!self::runFileScanner($force_scan)) { return self::throwException(__('Scanner ran a couple of minutes ago', 'sucuri-scanner')); } $fifo = new SucuriScanFileInfo(); $signatures = $fifo->getDirectoryTreeMd5(ABSPATH); SucuriScanOption::updateOption(':runtime', time()); return SucuriScanAPI::sendHashes($signatures); } /** * Sends information of a security event to the API. * * If the website owner has enabled the security log exporter, this method * will also write the information about the security event to that file. * This allows to integrate with different monitoring systems like OSSEC or * OpenVAS. * * If the communication with the API is enabled, it will also send all the * security logs collected on previous executions of the method that resulted * in a failure. However, this procedure depends on the ability of the plugin * to write the log into the queue when the previous request failed. * * @param string $message Information about the event. * @param string|int $timestamp Time when the event was triggered. * @param int $timeout Maximum time in seconds to connect to the API. * @return bool True if the event was logged, false otherwise. */ private static function sendLogToAPI($message = '', $timestamp = '', $timeout = 1) { if (empty($message)) { return self::throwException(__('Event identifier cannot be empty', 'sucuri-scanner')); } $params = array(); $params['a'] = 'send_log'; $params['m'] = $message; $params['time'] = $timestamp; $args = array('timeout' => $timeout); $resp = SucuriScanAPI::apiCallWordpress('POST', $params, true, $args); return (bool) ( is_array($resp) && array_key_exists('status', $resp) && intval($resp['status']) === 1 ); } /** * Sends the event message to a local queue system. * * Note: The method is public to facilitate the execution of some unit-tests * but it could be private and be mocked by the test bootstrap script. Take * this in consideration during the static analysis of the code. * * @param string $message Information about the security event. * @return bool True if the operation succeeded, false otherwise. */ public static function sendLogToQueue($message = '') { /* create storage directory if necessary */ SucuriScanInterface::createStorageFolder(); /** * Self-hosted Monitor. * * Send a copy of the event log to a local file, this will allow the * administrator of the server to integrate the events monitored by the * plugin with a 3rd-party service like OSSEC or similar. More info in * the Self-Hosting panel located in the plugin' settings page. */ if (function_exists('sucuriscan_selfhosting_fpath')) { $monitor_fpath = sucuriscan_selfhosting_fpath(); if ($monitor_fpath !== false) { $local_event = sprintf( "%s WordPressAudit %s %s : %s\n", SucuriScan::datetime(null, 'Y-m-d H:i:s'), SucuriScan::getTopLevelDomain(), SucuriScanOption::getOption(':account'), $message ); @file_put_contents( $monitor_fpath, $local_event, FILE_APPEND ); } } $cache = new SucuriScanCache('auditqueue'); $key = str_replace('.', '_', microtime(true)); $written = $cache->add($key, $message); return true; } /** * Sends all the events from the queue to the API. * * @return array|bool Information about the dequeue process. */ public static function sendLogsFromQueue() { if (SucuriScanOption::isDisabled(':api_service') || !defined('SUCURISCAN_API_URL') || empty(SUCURISCAN_API_URL)) { return false; } $cache = new SucuriScanCache('auditqueue'); $finfo = $cache->getDatastoreInfo(); $events = $cache->getAll(); if (!$events) { return false; } $result = array( 'maxtime' => -1, 'ttllogs' => 0, 'success' => 0, 'failure' => 0, 'elapsed' => 0, ); /** * Send logs to the API with a limit. * * We will use the maximum execution time setting to limit the number of * logs that the plugin will try to send to the API service before the * server times out. In a regular installation, the limit is set to 30 * seconds, since the timeout for the HTTP request is 5 seconds we will * instruct the plugin to wait (30 secs - 5 secs) and an additional one * second to spare processing, so in a regular installation the plugin * will try to send as much logs as possible to the API service in less * than 25 seconds. */ $maxtime = (int) SucuriScan::iniGet('max_execution_time'); $timeout = ($maxtime > 1) ? ($maxtime - 6) : 30; /* record some statistics */ $startTime = microtime(true); $result['maxtime'] = $maxtime; $result['ttllogs'] = count($events); foreach ($events as $keyname => $message) { $offset = strpos($keyname, '_'); $timestamp = substr($keyname, 0, $offset); $status = self::sendLogToAPI($message, $timestamp); /* skip; API is busy */ if ($status !== true) { $result['failure']++; continue; } /* dequeue event message */ unset($events[$keyname]); $result['success']++; /* avoid gateway timeout; max execution time */ $elapsedTime = (microtime(true) - $startTime); if ($elapsedTime >= $timeout) { break; } } $result['elapsed'] = round(microtime(true) - $startTime, 4); $cache->override($events); return $result; } /** * Generates an audit event log (to be sent later). * * @param int $severity Importance of the event that will be reported. * @param string $message The explanation of the event. * @return bool True if the event was logged, false otherwise. */ private static function reportEvent($severity = 0, $message = '') { if (!function_exists('wp_get_current_user')) { return; } $user = wp_get_current_user(); $remote_ip = self::getRemoteAddr(); $username = false; // Identify current user in session. if ($user instanceof WP_User && isset($user->user_login) && !empty($user->user_login) ) { $username = sprintf("\x20%s,", $user->user_login); } $severity = intval($severity); $severity_name = __('Info', 'sucuri-scanner'); $severities = array( /* 0 */ __('Debug', 'sucuri-scanner'), /* 1 */ __('Notice', 'sucuri-scanner'), /* 2 */ __('Info', 'sucuri-scanner'), /* 3 */ __('Warning', 'sucuri-scanner'), /* 4 */ __('Error', 'sucuri-scanner'), /* 5 */ __('Critical', 'sucuri-scanner'), ); if (isset($severities[$severity])) { $severity_name = $severities[$severity]; } /* remove unnecessary characters */ $message = strip_tags($message); $message = str_replace("\r", '', $message); $message = str_replace("\n", '', $message); $message = str_replace("\t", '', $message); return self::sendLogToQueue( sprintf( '%s:%s %s; %s', $severity_name, $username, $remote_ip, $message ) ); } /** * Reports a debug event on the website. * * @param string $message Text witht the explanation of the event or action performed. * @return bool Either true or false depending on the success of the operation. */ public static function reportDebugEvent($message = '') { return self::reportEvent(0, $message); } /** * Reports a notice event on the website. * * @param string $message Text witht the explanation of the event or action performed. * @return bool Either true or false depending on the success of the operation. */ public static function reportNoticeEvent($message = '') { return self::reportEvent(1, $message); } /** * Reports a info event on the website. * * @param string $message Text witht the explanation of the event or action performed. * @return bool Either true or false depending on the success of the operation. */ public static function reportInfoEvent($message = '') { return self::reportEvent(2, $message); } /** * Reports a warning event on the website. * * @param string $message Text witht the explanation of the event or action performed. * @return bool Either true or false depending on the success of the operation. */ public static function reportWarningEvent($message = '') { return self::reportEvent(3, $message); } /** * Reports a error event on the website. * * @param string $message Text witht the explanation of the event or action performed. * @return bool Either true or false depending on the success of the operation. */ public static function reportErrorEvent($message = '') { return self::reportEvent(4, $message); } /** * Reports a critical event on the website. * * @param string $message Text witht the explanation of the event or action performed. * @return bool Either true or false depending on the success of the operation. */ public static function reportCriticalEvent($message = '') { return self::reportEvent(5, $message); } /** * Send a notification to the administrator of the specified events, only if * the administrator accepted to receive alerts for this type of events. * * @param string $event The name of the event that was triggered. * @param string $content Body of the email that will be sent to the administrator. * @return bool True if the email was apparently sent, false otherwise. */ public static function notifyEvent($event = '', $content = '') { $email_params = array(); $email = SucuriScanOption::getOption(':notify_to'); $notify = SucuriScanOption::getOption(':notify_' . $event); /** * Skip if the IP address is trusted. * * Ignore event if the website owner has the IP address of the current * user in session in the allowlist. This is useful if the administrator is * working in an office and they want to allow every person in the office * (aka. the same LAN) to execute any task without triggering a security * alert. */ if (self::isTrustedIP()) { $notify = 'disabled'; } /* skip if alerts for this event are disabled */ if ($notify !== 'enabled') { return false; } switch ($event) { case 'post_publication': $event = 'post_update'; break; case 'failed_login': $settings_url = SucuriScanTemplate::getUrl('settings'); $content .= "\n" . sprintf( __("

    \n\nExplanation: Someone failed to login to your site. If you are getting too many of these messages, it is likely your site is under a password guessing brute-force attack [1]. You can disable the failed login alerts from here [2]. Alternatively, you can consider to install a firewall between your website and your visitors to filter out these and other attacks, take a look at Sucuri Firewall [3].

    \n\n[1] https://kb.sucuri.net/definitions/attacks/brute-force/password-guessing
    \n[2] %s
    \n[3] https://sucuri.net/website-firewall/
    \n", 'sucuri-scanner'), $settings_url, $settings_url ); break; case 'bruteforce_attack': $email_params['Force'] = true; break; case 'scan_checksums': $event = 'core_integrity_checks'; $email_params['Force'] = true; $email_params['ForceHTML'] = true; break; case 'available_updates': $email_params['Force'] = true; $email_params['ForceHTML'] = true; } $title = ucwords(str_replace('_', "\x20", $event)); return SucuriScanMail::sendMail( $email, $title, $content, $email_params ); } /** * Check whether an IP address is being trusted or not. * * @param string $addr The supposed ip address that will be checked. * @return bool True if the user IP is trusted, false otherwise. */ public static function isTrustedIP($addr = '') { if (!$addr) { $addr = SucuriScan::getRemoteAddr(); } $cache = new SucuriScanCache('trustip', false); $trusted_ips = $cache->getAll(); if (!is_array($trusted_ips) || empty($trusted_ips)) { return false; } /* check if exact IP address match is in the allowlist */ if (array_key_exists(md5($addr), $trusted_ips)) { return true; } $is_trusted_ip = false; /* check if the CIDR in range 32 of this IP is trusted. */ foreach ($trusted_ips as $cache_key => $ip_info) { $ip_parts = explode('.', $ip_info->remote_addr); $ip_pattern = false; // Generate the regular expression for a specific CIDR range. switch ($ip_info->cidr_range) { case 24: $ip_pattern = sprintf( '/^%d\.%d\.%d\.[0-9]{1,3}$/', intval($ip_parts[0]), intval($ip_parts[1]), intval($ip_parts[2]) ); break; case 16: $ip_pattern = sprintf( '/^%d\.%d\.[0-9]{1,3}\.[0-9]{1,3}$/', intval($ip_parts[0]), intval($ip_parts[1]) ); break; case 8: $ip_pattern = sprintf( '/^%d\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', intval($ip_parts[0]) ); break; } if ($ip_pattern && preg_match($ip_pattern, $addr)) { $is_trusted_ip = true; break; } } return $is_trusted_ip; } /** * Generate and set a new password for a specific user not in session. * * @param int $user_id User account identifier. * @return bool True if the process exit clean, false otherwise. */ public static function setNewPassword($user_id = 0) { $user = get_userdata($user_id); if (!($user instanceof WP_User)) { return false; } /* invalidates the password for the given user */ $new_password = wp_generate_password(15, true, false); wp_set_password($new_password, $user_id); $website = SucuriScan::getDomain(); $user_login = $user->user_login; $display_name = $user->display_name; $key = self::GetPasswordResetKey($user); if (is_wp_error($key)) { return false; } $reset_password_url = network_site_url("wp-login.php?action=rp&key=$key&login=" . rawurlencode($user_login), 'https' ); $message = SucuriScanTemplate::getSection( 'settings-posthack-reset-password-alert', array( 'ResetPassword.UserName' => $user_login, 'ResetPassword.DisplayName' => $display_name, 'ResetPassword.ResetURL' => $reset_password_url, 'ResetPassword.Website' => $website, ) ); /* Skip per hour alert limit and force text/html content-type */ $data_set = array('Force' => true, 'ForceHTML' => true); $sent = SucuriScanMail::sendMail( $user->user_email, __('Password Change', 'sucuri-scanner'), $message, $data_set ); return true; } /** * Gets a new password reset key. * * @since 1.8.25 * * @param WP_User $user WP_User object. * @return string|WP_Error Returns a password reset key as a string, WP_Error otherwise. */ private static function GetPasswordResetKey($user) { global $wp_hasher; $key_error = new WP_Error('no_password_reset'); if (!($user instanceof WP_User)) { return $key_error; } /** * As of version 1.8.25 of this plugin, we still support WordPress version 3.6 and up * and for that reason we can't take advantage of the native function get_password_reset_key * (https://developer.wordpress.org/reference/functions/get_password_reset_key/), introduced in * WordPress 4.4. * * When we drop support for versions prior to WordPress 4.4, we can use get_password_reset_key * instead of this function. */ if (version_compare(SucuriScan::siteVersion(), '4.4', '>=') && function_exists('get_password_reset_key') ) { $key = get_password_reset_key($user); return $key; } if (is_multisite() && is_user_spammy($user)) { return $key_error; } // Generate something random for a password reset key. $key = wp_generate_password(20, false); if (empty($wp_hasher)) { require_once ABSPATH . WPINC . '/class-phpass.php'; $wp_hasher = PasswordHash(8, true); } $hashed = time() . ':' . $wp_hasher->HashPassword($key); $key_saved = wp_update_user( array( 'ID' => $user->ID, 'user_activation_key' => $hashed, ) ); if (is_wp_error($key_saved)) { return $key_saved; } return $key; } /** * Changes the WordPress secret keys. * * Modify the WordPress configuration file to define new secret keys from a * new randomly generated list of strings from the official WordPress API. * The result of the operation will be either False in case of error, or an * array containing multiple indexes explaining the modification, among them * you will find the old and new keys. * * @return array|bool Array with the old and new keys, false otherwise. */ public static function setNewConfigKeys() { $new_wpconfig = ''; $config_path = self::getConfigPath(); if (!$config_path) { return false; } $pattern = self::secretKeyPattern(); $define_tpl = "define('%s',%s'%s');"; $content = SucuriScanFileInfo::fileContent($config_path); $config_lines = explode("\n", $content); /* maintain new lines */ $new_keys = SucuriScanAPI::getNewSecretKeys(); if (!$new_keys) { return false; } $new_keys_string = ''; $old_keys_string = ''; $old_keys = array(); if ($config_lines && $new_keys) { foreach ($config_lines as $config_line) { if (@preg_match($pattern, $config_line, $match)) { $key_name = $match[1]; if (array_key_exists($key_name, $new_keys)) { $white_spaces = $match[2]; $old_keys[$key_name] = $match[3]; $config_line = sprintf( $define_tpl, $key_name, $white_spaces, $new_keys[$key_name] ); $old_keys_string .= sprintf( $define_tpl . "\n", $key_name, $white_spaces, $old_keys[$key_name] ); $new_keys_string .= $config_line . "\n"; } } $new_wpconfig .= $config_line . "\n"; } } $resp = array( 'updated' => is_writable($config_path), 'old_keys' => $old_keys, 'old_keys_string' => $old_keys_string, 'new_keys' => $new_keys, 'new_keys_string' => $new_keys_string, 'new_wpconfig' => $new_wpconfig, ); if ($resp['updated']) { @file_put_contents($config_path, $new_wpconfig, LOCK_EX); } return $resp; } /** * Clear last logins or failed login logs. * * This can also be done via Sucuri Security -> Settings -> Data Storage, * however to improve the user experience, a button on Last Logins and on * Failed logins sections was added and it triggers the removal of * sucuri/sucuri-lastlogins.php and sucuri/sucuri-failedlogins.php. * * @param string $filename Name of the file to be deleted. * * @return HTML Message with the delete action outcome. */ public static function clearLastLogs($filename) { // Get the complete path of the file. $filepath = SucuriScan::dataStorePath($filename); // Do not proceed if not possible. if (!is_writable(dirname($filepath)) || is_dir($filepath)) { return SucuriScanInterface::error( sprintf( __('%s cannot be deleted.', 'sucuri-scanner'), $filename ) ); } // Delete $filepath. @unlink($filepath); // Register on audit logs and return result. SucuriScanEvent::reportInfoEvent( sprintf( __('%s was deleted.', 'sucuri-scanner'), $filename ) ); return SucuriScanInterface::info( sprintf( __('%s was deleted.', 'sucuri-scanner'), $filename ) ); } } src/fileinfo.lib.php000060400000035751147177152050010424 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Class to process files and folders. * * Here are implemented the methods needed to open, scan, read, create files * and folders using the built-in PHP class SplFileInfo. The SplFileInfo class * offers a high-level object oriented interface to information for an individual * file. * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ class SucuriScanFileInfo extends SucuriScan { /** * Whether the list of files that can be ignored from the filesystem scan will * be used to return the directory tree, this should be disabled when scanning a * directory without the need to filter the items in the list. * * @var bool */ public $ignore_files; /** * Whether the list of folders that can be ignored from the filesystem scan will * be used to return the directory tree, this should be disabled when scanning a * path without the need to filter the items in the list. * * @var bool */ public $ignore_directories; /** * A list of ignored directory paths, these folders will be skipped during the * execution of the file system scans, and any sub-directory or files inside * these paths will be ignored too. * * @see SucuriScanFSScanner.getIgnoredDirectories() * @var array */ private $ignored_directories; /** * Whether the filesystem scanner should run recursively or not. * * @var bool */ public $run_recursively; /** * Whether the directory paths must be skipped or not. * * This is useful to retrieve the full list of resources inside a parent * directory, one case where this option can be set as True is when a folder is * required to be deleted recursively, considering that by default the folders * are ignored and that a folder may be empty some times there could be issues * because the deletion will not reach these resources. * * @var bool */ public $skip_directories; /** * Class constructor. */ public function __construct() { $this->ignore_files = true; $this->ignore_directories = true; $this->ignored_directories = array(); $this->skip_directories = true; $this->run_recursively = true; } /** * Checks if the file scanner is usable. * * @link https://www.php.net/manual/en/class.splfileobject.php * * @return bool True if PHP class "SplFileObject" is available. */ public static function isSplAvailable() { return (bool) ( class_exists('SplFileObject') && class_exists('FilesystemIterator') && class_exists('RecursiveIteratorIterator') && class_exists('RecursiveDirectoryIterator') ); } /** * Ignores a file if the extension is not supported. * * Note: This is an approach that is intentionally naive. * * @param string $path Path to the file. * @return True if the file must be ignored. */ private function ignoreFile($path) { return (bool) ( $this->ignore_files && strpos($path, '.js') === false && strpos($path, '.css') === false && strpos($path, '.txt') === false && strpos($path, '.htm') === false && strpos($path, '.php') === false && strpos($path, '.ini') === false && strpos($path, '.htaccess') === false ); } /** * Ignores a folder if the extension is not supported. * * Note: This is an approach that is intentionally naive. * * @param string $path Path to the folder. * @return True if the folder must be ignored. */ private function ignoreFolder($path) { $content = basename(WP_CONTENT_DIR); return (bool) ($this->ignore_directories && ( strpos($path, '/.hg') !== false || strpos($path, '/.git') !== false || strpos($path, '/.svn') !== false || strpos($path, $content . '/backup') !== false || strpos($path, $content . '/cache') !== false || strpos($path, $content . '/uploads') !== false || strpos($path, $content . '/w3tc') !== false )); } /** * Ignores files specified by the admins. * * @param string $path Path to the file or directory. * @return bool True if the path has to be ignored. */ private function isIgnoredPath($path) { $shouldBeIgnored = false; if (is_array($this->ignored_directories) && isset($this->ignored_directories['directories']) && !empty($this->ignored_directories['directories']) ) { foreach ($this->ignored_directories['directories'] as $ignored) { if (strpos($path, $ignored) !== false) { $shouldBeIgnored = true; break; } } } return $shouldBeIgnored; } /** * Reads a directory and retrieves all its files. * * @see http://www.php.net/manual/en/class.recursivedirectoryiterator.php * @see http://php.net/manual/en/class.recursivedirectoryiterator.php * @see http://php.net/manual/en/class.filesystemiterator.php * @see http://php.net/manual/en/class.directoryiterator.php * @see http://php.net/manual/en/class.splfileinfo.php * * @param string $directory Where to execute the scanner. * @param string $filterby Either "file" or "directory". * @return array List of files in the specified directory. */ public function getDirectoryTree($directory = '', $filterby = 'file') { $files = array(); if (is_dir($directory) && self::isSplAvailable()) { $objects = array(); $this->ignored_directories = SucuriScanFSScanner::getIgnoredDirectories(); // @codeCoverageIgnoreStart try { if ($this->run_recursively) { $flags = FilesystemIterator::KEY_AS_PATHNAME; $flags |= FilesystemIterator::CURRENT_AS_FILEINFO; $flags |= FilesystemIterator::SKIP_DOTS; $flags |= FilesystemIterator::UNIX_PATHS; $objects = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($directory, $flags), RecursiveIteratorIterator::SELF_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD ); } else { $objects = new DirectoryIterator($directory); } } catch (RuntimeException $exception) { /* ignore failure */ } // @codeCoverageIgnoreEnd foreach ($objects as $fifo) { $filepath = $fifo->getRealPath(); /* check files and directories */ if ($this->isIgnoredPath($filepath)) { continue; } try { /* check only files */ if ($fifo->isFile() && $filterby === 'file' && !$this->ignoreFile($filepath) && !$this->ignoreFolder($filepath) ) { $files[] = $filepath; continue; } /* check only directories */ if ($fifo->isDir() && $filterby === 'directory' && !$this->ignoreFolder($filepath) ) { $files[] = $filepath; continue; } } catch (RuntimeException $e) { SucuriScanEvent::reportCriticalEvent($e->getMessage()); } } sort($files); } return array_map(array('SucuriScan', 'fixPath'), $files); } /** * Retrieve a long text string with signatures of all the files contained * in the main and subdirectories of the folder specified, also the filesize * and md5sum of that file. Some folders and files will be ignored depending * on some rules defined by the developer. * * @param string $directory Where to execute the scanner. * @param bool $as_array Return the file list as an array. * @return array|string|bool List of files in this project. */ public function getDirectoryTreeMd5($directory = '', $as_array = false) { $signatures = ''; $abspath = self::fixPath(ABSPATH); $files = $this->getDirectoryTree($directory); if ($as_array) { $signatures = array(); } if (!$files) { return self::throwException(__('No files were found', 'sucuri-scanner')); } sort($files); /* sort file list alphabetically */ foreach ($files as $filepath) { /* silence errors when file is not readable */ $file_checksum = @md5_file($filepath); $filesize = @filesize($filepath); if ($as_array) { $basename = $filepath; if (strlen($abspath . '/') > 1) { /* convert absolute path into relative path */ $basename = str_replace($abspath . '/', '', $filepath); } $signatures[$basename] = array( 'filepath' => $filepath, 'checksum' => $file_checksum, 'filesize' => $filesize, 'created_at' => @filectime($filepath), 'modified_at' => @filemtime($filepath), ); } else { $filepath = str_replace($abspath, $abspath . '/', $filepath); $signatures .= $file_checksum . $filesize . "\x20" . $filepath . "\n"; } } return $signatures; } /** * Retrieves a list of unique directory paths. * * @param string $directory Directory path to scan. * @return array A list of unique directory paths. */ public function getDirectoriesOnly($directory = '') { $tree = $this->getDirectoryTree($directory, 'directory'); return array_merge(array($directory), $tree); } /** * Deletes a directory recursively. * * @param string $directory Path of the existing directory that will be removed. * @return bool TRUE if all the files and folder inside the directory were removed. */ public function removeDirectoryTree($directory = '') { $directory = realpath($directory); if (!is_dir($directory)) { return self::throwException(__('Directory does not exists', 'sucuri-scanner')); } if ($directory === WP_CONTENT_DIR) { return self::throwException(__('Cannot delete content directory', 'sucuri-scanner')); } $upload_dir = wp_upload_dir(); if ($directory === $upload_dir['basedir']) { return self::throwException(__('Cannot delete uploads directory', 'sucuri-scanner')); } /* force complete scan */ $this->ignore_files = false; $this->skip_directories = false; $this->ignore_directories = false; /* delete all the regular files and symbolic links */ $dir_tree = $this->getDirectoryTree($directory, 'file'); if (is_array($dir_tree) && !empty($dir_tree)) { foreach ($dir_tree as $filename) { if (is_file($filename) || is_link($filename)) { @unlink($filename); } } } /* delete directories starting from the deepest level */ $dir_tree = $this->getDirectoryTree($directory, 'directory'); if (is_array($dir_tree) && !empty($dir_tree)) { $dir_tree = array_unique($dir_tree); usort($dir_tree, array('SucuriScanFileInfo', 'sortByLength')); foreach ($dir_tree as $dir_path) { @rmdir($dir_path); } } @rmdir($directory); /* attempt to delete parent */ /* check if we deleted all the files and sub-directories */ return (bool) !($this->getDirectoryTree($directory)); } /** * Evaluates the difference between the length of two strings. * * @param string $a First string of characters that will be measured. * @param string $b Second string of characters that will be measured. * @return int The difference in length between the two strings. */ public static function sortByLength($a, $b) { return strlen($b) - strlen($a); } /** * Returns the content of a file. * * If the file does not exists or is not readable the method will return * false. Make sure that you double check this with a condition using triple * equals in order to avoid ambiguous results when the file exists, is * readable, but is empty. * * @param string $path Relative or absolute path of the file. * @return string Content of the file, false if not accessible. */ public static function fileContent($path = '') { return (string) (is_readable($path) ? @file_get_contents($path) : ''); } /** * Returns the lines of a file as an array, it will automatically remove the * new line characters from the end of each line, and skip empty lines from * the list. * * @param string $filepath Path to the file. * @return array An array where each element is a line in the file. */ public static function fileLines($filepath = '') { return @file($filepath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); } /** * Tells whether the filename is a directory, symbolic link, or file. * * @param string $path Path to the file. * @return string Type of resource: dir, link, file. */ public static function getResourceType($path = '') { if (is_dir($path)) { return 'dir'; } if (is_link($path)) { return 'link'; } if (is_file($path)) { return 'file'; } return 'unknown'; } } src/firewall.lib.php000060400000063372147177152050010436 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Defines methods to interact with Sucuri Firewall's API service. * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ class SucuriScanFirewall extends SucuriScanAPI { /** * Check whether the firewall API key is valid or not. * * @param string $api_key The firewall API key. * @param bool $return_match Whether the parts of the API key must be returned or not. * @return array|bool True if the API key specified is valid, false otherwise. */ public static function isValidKey($api_key = '', $return_match = false) { $pattern = '/^([a-z0-9]{32})\/([a-z0-9]{32})$/'; if ($api_key && preg_match($pattern, $api_key, $match)) { return $return_match ? $match : true; } return false; } /** * Check and return the API key for the plugin. * * In this plugin the key is a pair of two strings concatenated by a single * slash, the first part of it is in fact the key and the second part is the * unique identifier of the site in the remote server. * * @return array|bool false if the key is invalid or not present, an array otherwise. */ public static function getKey() { $option_name = ':cloudproxy_apikey'; $api_key = self::getOption($option_name); // Check the validity of the API key. $match = self::isValidKey($api_key, true); if ($match) { return array( 'string' => $match[1].'/'.$match[2], 'k' => $match[1], 's' => $match[2], ); } return false; } /** * Call an action from the remote API interface of our firewall service. * * @param string $method HTTP method that will be used to send the request. * @param array $params HTTP request parameters (key-value array). * @return array|bool HTTP response object. */ public static function apiCallFirewall($method = 'GET', $params = array()) { $send_request = (bool) (isset($params['k']) && isset($params['s'])); if (!$send_request) { $api_key = self::getKey(); if ($api_key) { $send_request = true; $params['k'] = $api_key['k']; $params['s'] = $api_key['s']; } } if ($send_request) { unset($params['string']); $params[SUCURISCAN_CLOUDPROXY_API_VERSION] = 1; return self::apiCall(SUCURISCAN_CLOUDPROXY_API, $method, $params); } return false; } /** * Retrieve the public settings of the account associated with the API keys * registered by the administrator of the site. This method will send a HTTP * request to the remote API service and process its response, when successful * it will return an array/object containing the public attributes of the site. * * @param array|bool $api_key The firewall API key. * @return array|bool A hash with the settings of a firewall account. */ public static function settings($api_key = false) { $params = array('a' => 'show_settings'); if ($api_key) { $params = array_merge($params, $api_key); } $response = self::apiCallFirewall('GET', $params); return self::handleResponse($response) ? $response['output'] : false; } /** * Generate the HTML code for the firewall settings panel. * * @codeCoverageIgnore * * @return string The parsed-content of the firewall settings panel. */ public static function settingsPage() { $params = array( 'Firewall.APIKey' => '', 'Firewall.APIKeyVisibility' => 'hidden', 'Firewall.APIKeyFormVisibility' => 'visible', ); if (SucuriScanInterface::checkNonce()) { // Add and/or Update the Sucuri WAF API Key (do it before anything else). $option_name = ':cloudproxy_apikey'; $api_key = SucuriScanRequest::post($option_name); if ($api_key !== false) { $api_key = trim($api_key); if (self::isValidKey($api_key)) { SucuriScanOption::updateOption($option_name, $api_key); SucuriScanInterface::info(__('Firewall API key was successfully saved', 'sucuri-scanner')); SucuriScanOption::setRevProxy('enable'); SucuriScanOption::setAddrHeader('HTTP_X_SUCURI_CLIENTIP'); } else { SucuriScanInterface::error('Invalid firewall API key'); } } // Delete the firewall API key from the plugin. if (SucuriScanRequest::post(':delete_wafkey') !== false) { SucuriScanOption::deleteOption($option_name); SucuriScanInterface::info(__('Firewall API key was successfully removed', 'sucuri-scanner')); SucuriScanOption::setRevProxy('disable'); SucuriScanOption::setAddrHeader('REMOTE_ADDR'); } } $api_key = self::getKey(); if ($api_key && array_key_exists('string', $api_key)) { $params['Firewall.APIKeyVisibility'] = 'visible'; $params['Firewall.APIKeyFormVisibility'] = 'hidden'; $params['Firewall.APIKey'] = $api_key['string']; } return SucuriScanTemplate::getSection('firewall-settings', $params); } /** * Converts the value of some of the firewall settings into a human-readable * text, for example changing numbers or variable names into a more explicit * text so the administrator can understand the meaning of these settings. * * @param array $settings A hash with the settings of a firewall account. * @return array The explained version of the firewall settings. */ public static function settingsExplanation($settings = array()) { if (!is_array($settings)) { return array(); } $cache_modes = array( 'docache' => __('enabled (recommended)', 'sucuri-scanner'), 'sitecache' => __('site caching (using your site headers)', 'sucuri-scanner'), 'nocache' => __('minimal (only for a few minutes)', 'sucuri-scanner'), 'nocacheatall' => __('caching disabled (use with caution)', 'sucuri-scanner'), ); foreach ($settings as $keyname => $value) { if ($keyname == 'proxy_active') { $settings[$keyname] = ($value === 1) ? 'active' : 'not active'; continue; } if ($keyname == 'cache_mode') { if (array_key_exists($value, $cache_modes)) { $settings[$keyname] = $cache_modes[$value]; } else { $settings[$keyname] = 'unknown'; } continue; } } return $settings; } /** * Returns the public firewall settings. * * @codeCoverageIgnore * * @return void */ public static function getSettingsAjax() { if (SucuriScanRequest::post('form_action') !== 'firewall_settings') { return; } $response = array(); $response['ok'] = false; $api_key = self::getKey(); ob_start(); $settings = self::settings($api_key); $error = ob_get_clean(); if (!$settings) { if (empty($error)) { ob_start(); SucuriScanInterface::error(__('Firewall API key was not found.', 'sucuri-scanner')); $response['error'] = ob_get_clean(); } else { $response['error'] = $error; } wp_send_json($response, 200); } $response['ok'] = true; $response['settings'] = self::settingsExplanation($settings); unset($response['settings']['whitelist_list']); unset($response['settings']['blacklist_list']); wp_send_json($response, 200); } /** * Retrieve the audit logs of the account associated with the API keys * registered b the administrator of the site. This method will send a HTTP * request to the remote API service and process its response, when successful * it will return an array/object containing a list of requests blocked by our * firewall. * * By default the logs that will be retrieved are from today, if you need to see * the logs of previous days you will need to add a new parameter to the request * URL named "date" with format yyyy-mm-dd. * * @param array|string $api_key The firewall API key. * @param string $date Retrieve the data from this date. * @param string $query Filter the data to match this query. * @param int $limit Retrieve this maximum of data. * @param int $offset Retrieve the data from this point. * @return array|bool Objects with details of each blocked request. */ public static function auditlogs($api_key, $date = '', $query = '', $limit = 10, $offset = 0) { $params = array( 'a' => 'audit_trails', 'date' => $date, 'query' => $query, 'limit' => $limit, 'offset' => $offset, ); if (is_array($api_key)) { $params = array_merge($params, $api_key); } $response = self::apiCallFirewall('GET', $params); return self::handleResponse($response) ? $response['output'] : false; } /** * Generate the HTML code for the firewall logs panel. * * @return string The parsed-content of the firewall logs panel. */ public static function auditlogsPage() { $params = array(); /* logs are available after 24 hours */ $date = SucuriScan::datetime(strtotime('-1 day'), 'Y-m-d'); $params['AuditLogs.DateYears'] = self::dates('years', $date); $params['AuditLogs.DateMonths'] = self::dates('months', $date); $params['AuditLogs.DateDays'] = self::dates('days', $date); return SucuriScanTemplate::getSection('firewall-auditlogs', $params); } /** * Returns the security logs from the Firewall API. * * The API allows to filter the logs by day and by user input. This operation * depends on the availability of the Firewall API key, if the website owner has * not signed up for the Firewall service then they will not have access to this * feature. The plugin will display a warning in this case. * * @codeCoverageIgnore * * @return void */ public static function auditlogsAjax() { if (SucuriScanRequest::post('form_action') !== 'get_firewall_logs') { return; } $response = ''; $api_key = self::getKey(); if (!$api_key) { ob_start(); SucuriScanInterface::error(__('Firewall API key was not found.', 'sucuri-scanner')); $response = ob_get_clean(); wp_send_json($response, 200); } $query = SucuriScanRequest::post(':query'); $month = SucuriScanRequest::post(':month'); $year = SucuriScanRequest::post(':year'); $day = SucuriScanRequest::post(':day'); $limit = 50; $offset = 1; if ($year && $month && $day) { $date = sprintf('%s-%s-%s', $year, $month, $day); } else { $date = SucuriScan::datetime(null, 'Y-m-d'); } ob_start(); $auditlogs = self::auditlogs( $api_key, $date, /* Retrieve the data from this date. */ $query, /* Filter the data to match this query. */ $limit, /* Retrieve this maximum of data. */ $offset /* Retrieve the data from this point. */ ); $error = ob_get_clean(); if (!$auditlogs && !empty($error)) { wp_send_json($error, 200); } if ($auditlogs && array_key_exists('total_lines', $auditlogs)) { $response = self::auditlogsEntries($auditlogs['access_logs']); if (empty($response)) { $response = '' . __('no data available.', 'sucuri-scanner') . ''; } } wp_send_json($response, 200); } /** * Returns the security logs from the firewall in HTML. * * @param array $entries Security logs retrieved from the Firewall API. * @return string HTML with the information from the logs. */ public static function auditlogsEntries($entries = array()) { if (!is_array($entries) || empty($entries)) { return ''; /* empty response */ } $output = ''; $attributes = array( 'remote_addr', 'request_date', 'request_time', 'request_timezone', 'request_method', 'resource_path', 'http_protocol', 'http_status', 'http_status_title', 'http_referer', 'http_user_agent', 'sucuri_block_code', 'sucuri_block_reason', 'request_country_name', 'request_country_code', ); foreach ($entries as $entry) { if (array_key_exists('is_usable', $entry) && $entry['is_usable']) { $data_set = array(); foreach ($attributes as $attr) { /* generate variable name for the template pseudo-tags */ $keyname = str_replace('_', "\x20", $attr); $keyname = ucwords($keyname); $keyname = str_replace("\x20", '', $keyname); $keyname = 'AccessLog.' . $keyname; /* assign and escape variable value before rendering */ $data_set[$keyname] = isset($entry[$attr]) ? $entry[$attr] : ''; /* special cases to convert value to readable data */ if ($attr == 'resource_path' && $data_set[$keyname] == '/') { $data_set[$keyname] = '/ (root of the website)'; } elseif ($attr == 'http_referer' && $data_set[$keyname] == '-') { $data_set[$keyname] = '- (no referer)'; } elseif ($attr == 'request_country_name' && $data_set[$keyname] == '') { $data_set[$keyname] = __('Anonymous', 'sucuri-scanner'); } } $output .= SucuriScanTemplate::getSnippet('firewall-auditlogs', $data_set); } } return $output; } /** * Get a list of years, months or days depending of the type specified. * * @param string $type Either years, months or days. * @param string $date Year, month and day selected from the request. * @param bool $in_html Whether the list should be converted to a HTML select options or not. * @return array|string Either an array with the expected values, or a HTML code. */ public static function dates($type = '', $date = '', $in_html = true) { $options = array(); $selected = ''; $pattern = '/^([0-9]{4})\-([0-9]{2})\-([0-9]{2})$/'; $s_year = ''; $s_month = ''; $s_day = ''; if (@preg_match($pattern, $date, $date_m)) { $s_year = $date_m[1]; $s_month = $date_m[2]; $s_day = $date_m[3]; } switch ($type) { case 'years': $selected = $s_year; $current_year = (int) SucuriScan::datetime(null, 'Y'); $max_years = 5; /* Maximum number of years to keep the logs. */ $options = range(($current_year - $max_years), $current_year); break; case 'months': $selected = $s_month; $options = array( '01' => __('January', 'sucuri-scanner'), '02' => __('February', 'sucuri-scanner'), '03' => __('March', 'sucuri-scanner'), '04' => __('April', 'sucuri-scanner'), '05' => __('May', 'sucuri-scanner'), '06' => __('June', 'sucuri-scanner'), '07' => __('July', 'sucuri-scanner'), '08' => __('August', 'sucuri-scanner'), '09' => __('September', 'sucuri-scanner'), '10' => __('October', 'sucuri-scanner'), '11' => __('November', 'sucuri-scanner'), '12' => __('December', 'sucuri-scanner'), ); break; case 'days': $options = range(1, 31); $selected = $s_day; break; } if ($in_html) { $html_options = ''; foreach ($options as $key => $value) { if (is_numeric($value)) { $value = str_pad($value, 2, '0', STR_PAD_LEFT); } if ($type != 'months') { $key = $value; } $selected_tag = ( $key == $selected ) ? 'selected="selected"' : ''; $html_options .= sprintf('', $key, $selected_tag, $value); } return $html_options; } return $options; } /** * Generate the HTML code for the firewall IP access panel. * * @return string The parsed-content of the firewall IP access panel. */ public static function ipAccessPage() { $params = array(); return SucuriScanTemplate::getSection('firewall-ipaccess', $params); } /** * Returns the IP addresses in the blocklist and allowlist. * * @codeCoverageIgnore * * @return void */ public static function ipAccessAjax() { if (SucuriScanRequest::post('form_action') !== 'firewall_ipaccess') { return; } $response = array(); $response['ok'] = false; $api_key = self::getKey(); ob_start(); $settings = self::settings($api_key); $error = ob_get_clean(); if (!$settings) { if (empty($error)) { ob_start(); SucuriScanInterface::error(__('Firewall API key was not found.', 'sucuri-scanner')); $response['error'] = ob_get_clean(); } else { $response['error'] = $error; } wp_send_json($response, 200); } $response['ok'] = true; $response['allowlist'] = $settings['whitelist_list']; $response['blocklist'] = $settings['blacklist_list']; wp_send_json($response, 200); } /** * Blocklists an IP address. * * @codeCoverageIgnore * * @return void */ public static function blocklistAjax() { if (SucuriScanRequest::post('form_action') !== 'firewall_blocklist') { return; } $response = array(); $response['ok'] = false; $params = self::getKey(); if (!$params) { ob_start(); SucuriScanInterface::error(__('Firewall API key was not found.', 'sucuri-scanner')); $response['msg'] = ob_get_clean(); wp_send_json($response, 200); } $params['a'] = 'blacklist_ip'; $params['ip'] = SucuriScanRequest::post('ip'); $out = self::apiCallFirewall('POST', $params); $response['msg'] = __('Failure connecting to the API service; try again.', 'sucuri-scanner'); if ($out && !empty($out['messages'])) { $response['ok'] = (bool) ($out['status'] == 1); $response['msg'] = implode(";\x20", $out['messages']); if ($out['status'] == 1) { SucuriScanEvent::reportInfoEvent(sprintf(__('IP has been added to the blocklist: %s', 'sucuri-scanner'), $params['ip'])); } } wp_send_json($response, 200); } /** * Deletes an IP address from the blocklist. * * @codeCoverageIgnore * * @return void */ public static function deblocklistAjax() { if (SucuriScanRequest::post('form_action') !== 'firewall_deblocklist') { return; } $response = array(); $params = self::getKey(); if (!$params) { ob_start(); $response['ok'] = false; SucuriScanInterface::error(__('Firewall API key was not found.', 'sucuri-scanner')); $response['error'] = ob_get_clean(); wp_send_json($response, 200); } $params['a'] = 'delete_blacklist_ip'; $params['ip'] = SucuriScanRequest::post('ip'); $out = self::apiCallFirewall('POST', $params); $response['ok'] = (bool) ($out['status'] == 1); $response['msg'] = implode(";\x20", $out['messages']); if ($out['status'] == 1) { SucuriScanEvent::reportInfoEvent(sprintf(__('IP has been removed from the blocklist: %s', 'sucuri-scanner'), $params['ip'])); } wp_send_json($response, 200); } /** * Flush the cache of the site(s) associated with the API key. * * @param array|bool $api_key The firewall API key. * @return string|bool Message explaining the result of the operation. */ public static function clearCache($api_key = false, $path = '') { $params = array('a' => 'clear_cache'); $path = ltrim(trim($path), '/'); if ($path) { $params['file'] = $path; } if (is_array($api_key)) { $params = array_merge($params, $api_key); } $response = self::apiCallFirewall('GET', $params); return self::handleResponse($response) ? $response : false; } /** * Generate the HTML code for the firewall clear cache panel. * * @codeCoverageIgnore * * @return string The parsed-content of the firewall clear cache panel. */ public static function clearCachePage() { $params = array(); $params['FirewallAutoClearCache'] = 'data-status="disabled"'; if (self::shouldAutoClearCache()) { $params['FirewallAutoClearCache'] = 'checked="checked"'; } return SucuriScanTemplate::getSection('firewall-clearcache', $params); } /** * Clear the firewall cache if necessary. * * Every time a page or post is modified and saved into the database the * plugin will send a HTTP request to the firewall API service and except * that, if the API key is valid, the cache is reset. Notice that the cache * of certain files is going to stay as it is due to the configuration on the * edge of the servers. * * @return void */ public static function clearCacheHook() { if (self::shouldAutoClearCache()) { ob_start(); self::clearCache(); $error = ob_get_clean(); } } /** * Requests a cache flush to the firewall service. * * @codeCoverageIgnore * * @return void */ public static function clearCacheAjax() { if (SucuriScanRequest::post('form_action') !== 'firewall_clear_cache') { return; } ob_start(); SucuriScanInterface::error(__('Firewall API key was not found.', 'sucuri-scanner')); $response = ob_get_clean(); $api_key = self::getKey(); if ($api_key) { $path = SucuriScanRequest::post('path'); $res = self::clearCache($api_key, $path); if (is_array($res) && isset($res['messages'])) { $response = sprintf( '

    %s

    ', ($res['status'] == 1) ? 'success' : 'error', implode('
    ', $res['messages']) ); } } wp_send_json($response, 200); } /** * Configures the status of the automatic cache flush. * * @codeCoverageIgnore * * @return void */ public static function clearAutoCacheAjax() { if (SucuriScanRequest::post('form_action') !== 'firewall_auto_clear_cache') { return; } $response = array(); if (SucuriScanRequest::post('auto_clear_cache') === 'enable') { $response['ok'] = SucuriScanOption::updateOption(':auto_clear_cache', 'enabled'); $response['status'] = 'enabled'; } else { $response['ok'] = SucuriScanOption::deleteOption(':auto_clear_cache'); $response['status'] = 'disabled'; } wp_send_json($response, 200); } /** * Returns true if the plugin should flush the firewall cache. * * @return bool True if the plugin should flush the firewall cache. */ private static function shouldAutoClearCache() { return (bool) ( defined('SUCURI_CLEAR_CACHE_ON_PUBLISH') || SucuriScanOption::isEnabled(':auto_clear_cache') ); } } src/fsscanner.lib.php000060400000010314147177152050010577 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * File System Scanner * * The File System Scanner component performs full and incremental scans over a * file system folder, maintaining a snapshot of the filesystem and comparing it * with the current content to establish what content has been updated. Updated * content is then submitted to the remote server and it is stored for future * analysis. * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ class SucuriScanFSScanner extends SucuriScan { /** * Retrieve the last time when the filesystem scan was ran. * * @param bool $format Whether the timestamp must be formatted as date/time or not. * @return string The timestamp of the runtime, or an string with the date/time. */ public static function getFilesystemRuntime($format = false) { $runtime = SucuriScanOption::getOption(':runtime'); if ($runtime > 0) { if ($format) { return SucuriScan::datetime($runtime); } return $runtime; } return 'Unknown'; } /** * Add a new directory path to the list of ignored paths. * * @param string $path The (full) absolute path of a directory. * @return bool TRUE if the directory path was added to the list, FALSE otherwise. */ public static function ignoreDirectory($path = '') { $cache = new SucuriScanCache('ignorescanning'); $resource_type = SucuriScanFileInfo::getResourceType($path); $cache_value = array( 'directory_path' => $path, 'ignored_at' => time(), 'resource_type' => $resource_type, ); return $cache->add(md5($path), $cache_value); } /** * Remove a directory path from the list of ignored paths. * * @param string $path The (full) absolute path of a directory. * @return bool TRUE if the directory path was removed to the list, FALSE otherwise. */ public static function unignoreDirectory($path = '') { $cache = new SucuriScanCache('ignorescanning'); return $cache->delete(md5($path)); } /** * Returns a list of ignored directories. * *
      *
    • raw: Contains the raw data from the local cache.
    • *
    • checksums: Contains the md5 of all the directories.
    • *
    • directories: Contains a list of directories.
    • *
    • ignored_at_list: Contains a list of timestamps.
    • *
    * * @return array List of ignored directories. */ public static function getIgnoredDirectories() { $response = array( 'raw' => array(), 'checksums' => array(), 'directories' => array(), 'ignored_at_list' => array(), ); $cache = new SucuriScanCache('ignorescanning'); $cache_lifetime = 0; // It is not necessary to expire this cache. $entries = $cache->getAll($cache_lifetime, 'array'); if ($entries) { $response['raw'] = $entries; foreach ($entries as $checksum => $data) { if (isset($data['directory_path']) && isset($data['ignored_at'])) { $response['checksums'][] = $checksum; $response['directories'][] = $data['directory_path']; $response['ignored_at_list'][] = $data['ignored_at']; } } } return $response; } } src/globals.php000060400000020724147177152050007501 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Plugin's global variables. * * These variables will be defined globally to allow the inclusion in multiple * methods and classes defined in the libraries loaded by this plugin. The * conditional will act as a container helping in the readability of the code * considering the total number of lines that this file will have. */ if (defined('SUCURISCAN')) { /** * Define the prefix for some actions and filters that rely in the differen- * tiation of the type of site where the extension is being used. There are * a few differences between a single site installation that must be * correctly defined when the extension is in a different environment, for * example, in a multisite installation. * * @var string */ $sucuriscan_action_prefix = SucuriScan::isMultiSite() ? 'network_' : ''; /** * Remove the WordPress generator meta-tag from the source code. */ remove_action('wp_head', 'wp_generator'); /** * Run a specific method defined in the plugin's code to locate every * directory and file, collect their checksum and file size, and send this * information to the Sucuri API service where a security and integrity scan * will be performed against the hashes provided and the official versions. */ add_action('sucuriscan_scheduled_scan', 'SucuriScan::runScheduledTask'); /** * Initialize the execute of the main plugin's functions. * * This will load the menu options in the WordPress administrator panel, and * execute the bootstrap method of the plugin. */ add_action('init', 'SucuriScanInterface::initialize', 1); add_action('admin_enqueue_scripts', 'SucuriScanInterface::enqueueScripts', 1); if (SucuriScan::runAdminInit()) { add_action('admin_init', 'SucuriScanInterface::handleOldPlugins'); add_action('admin_init', 'SucuriScanInterface::createStorageFolder'); } /** * Add cronjob weekly, monthly and quarterly frequencies. */ add_filter('cron_schedules', 'SucuriScanEvent::additionalSchedulesFrequencies'); /** * Hook the sucuriscan_autoseckeyupdater cron job. */ add_action('sucuriscan_autoseckeyupdater', 'SucuriScanCrons::sucuriscan_autoseckeyupdater'); /** * List an associative array with the sub-pages of this plugin. * * @return array List of sub-pages of this plugin. */ function sucuriscanMainPages() { return array( 'sucuriscan' => __('Dashboard', 'sucuri-scanner'), 'sucuriscan_firewall' => __('Firewall (WAF)', 'sucuri-scanner'), 'sucuriscan_lastlogins' => __('Last Logins', 'sucuri-scanner'), 'sucuriscan_settings' => __('Settings', 'sucuri-scanner'), ); } if (function_exists('add_action')) { /** * Display extension menu and submenu items in the correct interface. * For single site installations the menu items can be displayed * normally as always but for multisite installations the menu items * must be available only in the network panel and hidden in the * administration panel of the subsites. * * @codeCoverageIgnore * * @return void */ function sucuriscanAddMenuPage() { $pages = sucuriscanMainPages(); add_menu_page( __('Sucuri Security', 'sucuri-scanner'), __('Sucuri Security', 'sucuri-scanner'), 'manage_options', 'sucuriscan', 'sucuriscan_page', 'data:image/svg+xml;base64,' . base64_encode('') ); foreach ($pages as $sub_page_func => $sub_page_title) { add_submenu_page( 'sucuriscan', $sub_page_title, $sub_page_title, 'manage_options', $sub_page_func, $sub_page_func . '_page' ); } } /* Attach HTTP request handlers for the internal plugin pages */ add_action($sucuriscan_action_prefix . 'admin_menu', 'sucuriscanAddMenuPage'); /* Attach HTTP request handlers for the AJAX requests */ add_action('wp_ajax_sucuriscan_ajax', 'sucuriscan_ajax'); } /** * Function call interceptors. * * Define the names for the hooks that will intercept specific method calls in * the admin interface and parts of the external site, an event report will be * sent to the API service and an email notification to the administrator of the * site. * * @see Class SucuriScanHook */ if (class_exists('SucuriScanHook')) { add_action('activated_plugin', 'SucuriScanHook::hookPluginActivate', 50, 2); add_action('add_attachment', 'SucuriScanHook::hookAttachmentAdd', 50, 5); add_action('add_link', 'SucuriScanHook::hookLinkAdd', 50, 5); add_action('add_user_to_blog', 'SucuriScanHook::hookAddUserToBlog', 50, 4); add_action('before_delete_post', 'SucuriScanHook::hookPostBeforeDelete', 50, 5); add_action('create_category', 'SucuriScanHook::hookCategoryCreate', 50, 5); add_action('deactivated_plugin', 'SucuriScanHook::hookPluginDeactivate', 50, 2); add_action('delete_post', 'SucuriScanHook::hookPostDelete', 50, 5); add_action('delete_user', 'SucuriScanHook::hookUserDelete', 50, 5); add_action('edit_link', 'SucuriScanHook::hookLinkEdit', 50, 5); add_action('login_form_resetpass', 'SucuriScanHook::hookLoginFormResetpass', 50, 5); add_action('profile_update', 'SucuriScanHook::hookProfileUpdate', 50, 5); add_action('publish_page', 'SucuriScanHook::hookPublishPage', 50, 5); add_action('publish_phone', 'SucuriScanHook::hookPublishPhone', 50, 5); add_action('publish_post', 'SucuriScanHook::hookPublishPost', 50, 5); add_action('remove_user_from_blog', 'SucuriScanHook::hookRemoveUserFromBlog', 50, 2); add_action('retrieve_password', 'SucuriScanHook::hookRetrievePassword', 50, 5); add_action('switch_theme', 'SucuriScanHook::hookThemeSwitch', 50, 5); add_action('transition_post_status', 'SucuriScanHook::hookPostStatus', 50, 3); add_action('user_register', 'SucuriScanHook::hookUserRegister', 50, 5); add_action('wp_login', 'SucuriScanHook::hookLoginSuccess', 50, 5); add_action('wp_login_failed', 'SucuriScanHook::hookLoginFailure', 50, 5); add_action('wp_trash_post', 'SucuriScanHook::hookPostTrash', 50, 5); add_action('xmlrpc_publish_post', 'SucuriScanHook::hookPublishPostXMLRPC', 50, 5); if (SucuriScan::runAdminInit()) { add_action('_core_updated_successfully', 'SucuriScanHook::hookCoreUpdate'); add_action('admin_init', 'SucuriScanHook::hookOptionsManagement'); add_action('deleted_plugin', 'SucuriScanHook::hookPluginDelete'); add_action('admin_init', 'SucuriScanHook::hookPluginEditor'); add_action('admin_init', 'SucuriScanHook::hookPluginInstall'); add_action('admin_init', 'SucuriScanHook::hookPluginUpdate'); add_action('admin_init', 'SucuriScanHook::hookThemeDelete'); add_action('admin_init', 'SucuriScanHook::hookThemeEditor'); add_action('admin_init', 'SucuriScanHook::hookThemeInstall'); add_action('admin_init', 'SucuriScanHook::hookThemeUpdate'); add_action('admin_init', 'SucuriScanHook::hookWidgetAdd'); add_action('admin_init', 'SucuriScanHook::hookWidgetDelete'); } } } src/hardening.lib.php000060400000044576147177152050010575 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Project hardening library. * * In computing, hardening is usually the process of securing a system by * reducing its surface of vulnerability. A system has a larger vulnerability * surface the more functions it fulfills; in principle a single-method system * is more secure than a multipurpose one. Reducing available vectors of attack * typically includes the removal of unnecessary software, unnecessary usernames * or logins and the disabling or removal of unnecessary services. * * There are various methods of hardening Unix and Linux systems. This may * involve, among other measures, applying a patch to the kernel such as Exec * Shield or PaX; closing open network ports; and setting up intrusion-detection * systems, firewalls and intrusion-prevention systems. There are also hardening * scripts and tools like Bastille Linux, JASS for Solaris systems and * Apache/PHP Hardener that can, for example, deactivate unneeded features in * configuration files or perform various other protective measures. * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ class SucuriScanHardening extends SucuriScan { /* * This method is used to extract the folder and relative path (from one of the allowed folders) * given a full path and a list of allowed folders. * * @param string $fullPath Full path to the file. * @param array $allowed_folders List of allowed folders. * * @return array|false Array with the root directory and relative path * or null if the file is not in an allowed folder. */ public static function getFolderAndFilePath($path = '', $allowed_folders = array()) { $best_match = false; foreach ($allowed_folders as $base_directory) { if (strpos($path, $base_directory . DIRECTORY_SEPARATOR) === 0) { if ($best_match === false || substr_count( $base_directory, DIRECTORY_SEPARATOR ) > substr_count($best_match['base_directory'], DIRECTORY_SEPARATOR)) { $relative_path = str_replace($base_directory . DIRECTORY_SEPARATOR, '', $path); $best_match = array( 'base_directory' => $base_directory, 'relative_path' => $relative_path ); } } } return $best_match; } /** * Returns a list of access control rules for the Apache web server that can be * used to deny and allow certain files to be accessed by certain network nodes. * Currently supports Apache 2.2 and 2.4 and denies access to all PHP files with * any mixed extension case. * * @return array List of access control rules. */ private static function getRules() { return array( '', ' ', ' Order allow,deny', ' Deny from all', ' ', ' ', ' Require all denied', ' ', '', ); } /** * Adds some rules to an existing access control file (or creates it if does not * exists) to deny access to all files with certain extension in any mixed case. * The permissions to modify the file are checked before anything else, this * method is self-contained. * * @param string $directory Valid directory path where to place the access rules. * @return bool True if the rules are successfully added, false otherwise. */ public static function hardenDirectory($directory = '') { if (!is_dir($directory) || !is_writable($directory)) { return self::throwException(__('Directory is not usable', 'sucuri-scanner')); } if (SucuriScan::isNginxServer() || SucuriScan::isIISServer()) { return self::throwException(__('Access control file is not supported', 'sucuri-scanner')); } $fhandle = false; $target = self::htaccess($directory); if (file_exists($target)) { self::fixPreviousHardening($directory); $fhandle = @fopen($target, 'a'); } else { $fhandle = @fopen($target, 'w'); } if (!$fhandle) { return false; } $deny_rules = self::getRules(); $rules_text = implode("\n", $deny_rules); $written = @fwrite($fhandle, "\n" . $rules_text . "\n"); @fclose($fhandle); return (bool)($written !== false); } /** * Deletes some rules from an existing access control file to allow access to * all files with certain extension in any mixed case. The file is truncated if * after the operation its size is equals to zero. * * @param string $directory Valid directory path where to access rules are. * @return bool True if the rules are successfully deleted, false otherwise. */ public static function unhardenDirectory($directory = '') { if (!self::isHardened($directory)) { return self::throwException(__('Directory is not hardened', 'sucuri-scanner')); } $fpath = self::htaccess($directory); $content = SucuriScanFileInfo::fileContent($fpath); $deny_rules = self::getRules(); $rules_text = implode("\n", $deny_rules); $content = str_replace($rules_text, '', $content); $written = @file_put_contents($fpath, $content); $trimmed = trim($content); if (!filesize($fpath) || empty($trimmed)) { @unlink($fpath); } return (bool)($written !== false); } /** * Remove the hardening applied in previous versions. * * @param string $directory Valid directory path. * @return bool True if the access control file was fixed. */ private static function fixPreviousHardening($directory = '') { $fpath = self::htaccess($directory); $content = SucuriScanFileInfo::fileContent($fpath); $rules = "\ndeny from all\n"; /* no previous hardening rules exist */ if (strpos($content, $rules) === false) { return true; } $content = str_replace($rules, '', $content); $written = @file_put_contents($fpath, $content); return (bool)($written !== false); } /** * Check whether a directory is hardened or not. * * @param string $directory Valid directory path. * @return bool True if the directory is hardened, false otherwise. */ public static function isHardened($directory = '') { if (!is_dir($directory)) { return false; } $fpath = self::htaccess($directory); $content = SucuriScanFileInfo::fileContent($fpath); $deny_rules = self::getRules(); $rules_text = implode("\n", $deny_rules); return (bool)(strpos($content, $rules_text) !== false); } /** * Returns the path to the Apache access control file. * * @param string $folder Folder where the htaccess file is supposed to be. * @return string Path to the htaccess file in the specified folder. */ private static function htaccess($folder = '') { if (!function_exists('get_home_path')) { require_once ABSPATH . 'wp-admin/includes/file.php'; } $folder = str_replace(get_home_path(), '', $folder); $bpath = rtrim(get_home_path(), DIRECTORY_SEPARATOR); return $bpath . '/' . $folder . '/.htaccess'; } /** * Generates Apache access control rules for a file. * * Assuming that the directory hosting the specified file is hardened, this * method will generate the necessary rules to allowlist such file so anyone * can send a direct request to it. The method will generate both the rules * for Apache 2.4. * * Please note that since v1.9.5 we allow relatives paths to be used in the * REQUEST_URI condition. This is useful when the file is located in a subfolder * of the folder being hardened. * * @param string $filepath File path to be ignored by the hardening. * @param string $folder Folder hosting the specified file. * * @return string Access control rules to allowlist the file. */ private static function allowlistRule($filepath = '', $folder = '') { $filepath = str_replace(array('<', '>', '..'), '', $filepath); $relative_folder = str_replace(ABSPATH, '/', $folder); $relative_folder = '/' . ltrim($relative_folder, '/'); $path = sprintf( "\n" . " \n" . " \n" . " Allow from all\n" . " \n" . " \n" . " Require all granted\n" . " \n" . " \n" . "\n", basename($filepath), rtrim($relative_folder, '/'), ltrim($filepath, '/') ); return $path; } /** * Generates Apache access control rules for a file (legacy). * * Assuming that the directory hosting the specified file is hardened, this * method will generate the necessary rules to allowlist such file so anyone * can send a direct request to it. The method will generate both the rules * for Apache 2.4 and a compatibility conditional for older versions. * * @param string $filepath File to be ignored by the hardening. * @return string Access control rules to allowlist the file. */ private static function allowlistRuleLegacy($filepath = '', $folder = '') { $filepath = str_replace(array('<', '>', '..'), '', $filepath); return sprintf( "\n" . " \n" . " Allow from all\n" . " \n" . " \n" . " Require all granted\n" . " \n" . "", basename($filepath) ); } /** * Adds file in the specified folder to the allowlist. * * If the website owner has applied the hardening to the folder where the * specified file is located, all the requests sent directly to the file * will be blocked by the web server using its access control module. An * admin can ignore this hardening in one or more files if direct access to * it is required, as is the case with some 3rd-party plugins and themes. * * @param string $filepath File to be ignored by the hardening. * @param string $folder Folder hosting the specified file. * @return bool True if the file has been added to the allowlist, false otherwise. */ public static function allow($filepath = '', $folder = '') { if (SucuriScan::isNginxServer() || SucuriScan::isIISServer()) { throw new Exception(__('Access control file is not supported', 'sucuri-scanner')); } $htaccess = self::htaccess($folder); if (!file_exists($htaccess)) { throw new Exception(__('Access control file does not exists', 'sucuri-scanner')); } if (!is_writable($htaccess)) { throw new Exception(__('Access control file is not writable', 'sucuri-scanner')); } $rules = self::allowlistRule($filepath, $folder); $content = SucuriScanFileInfo::fileContent($htaccess); if (strpos($content, $rules) !== false) { throw new Exception(__('File is already in the allowlist', 'sucuri-scanner')); } return (bool)@file_put_contents( $htaccess, "\n" . self::allowlistRule($filepath, $folder), FILE_APPEND ); } /** * Blocks a file in the specified folder. * * If the website owner has applied the hardening to the folder where the * specified file is located, all the requests sent directly to the file * will be blocked by the web server using its access control module. If an * admin has added a file to the allowlist in this folder because a 3rd-party plugin or * theme required it, they can decide to remove this file from the allowlist using this * method which is executed by one of the tools in the settings page. * * @param string $filepath File to stop ignoring from the hardening. * @param string $folder Folder hosting the specified file. * @param bool $is_legacy Whether to use the legacy allowlist rule. * * @return bool True if the file has been removed from the allowlist, false otherwise. */ public static function removeFromAllowlist($filepath = '', $folder = '', $is_legacy = false) { $rules = self::allowlistRule($filepath, $folder); $htaccess = self::htaccess($folder); $content = SucuriScanFileInfo::fileContent($htaccess); if (!$content || !is_writable($htaccess)) { return self::throwException(__('Cannot remove file from the allowlist; no permissions.', 'sucuri-scanner')); } if ($is_legacy) { $rules = self::allowlistRuleLegacy($filepath, $folder); } $content = str_replace($rules, '', $content); $content = rtrim($content) . "\n"; return (bool)@file_put_contents($htaccess, $content); } /* * This method is used to get the list of files in the allowlist in a folder. * This returns the list of files with both the old and new patterns. * * @param string $content Content of the .htaccess file. * * @return array List of files in the allowlist. */ private static function getFiles($content = '') { preg_match_all('//', $content, $matches); return isset($matches[1]) ? $matches[1] : array(); } /* * This method is used to get the list of all files with new pattern in the .htaccess file * introduced in version 1.9.5. This pattern is based on the relative URL from the root directory * that the user selected. * * @param string $content Content of the .htaccess file. * * @return array List of files with new pattern in the .htaccess file. */ private static function getFilesWithNewPattern($content = '', $folder = '') { preg_match_all('/m#\^(\S+\/(\S+))\$\#/', $content, $new_matches, PREG_SET_ORDER, 0); $files_with_new_pattern = array(); if (empty($new_matches)) { return array(); } foreach ($new_matches as $match) { $uri = $match[0]; if (empty($uri)) { continue; } $cleaned_uri = str_replace(array('m#^', '$#'), '', $uri); $relative_folder_uri = str_replace(ABSPATH, '', $folder); $relative_path = str_replace($relative_folder_uri, '', $cleaned_uri); $relative_path = ltrim($relative_path, '/'); $files_with_new_pattern[] = array( 'file' => basename($cleaned_uri), 'relative_path' => $relative_path, ); } return $files_with_new_pattern; } /* This method is used to build the allowlist from the list of files and files with new pattern. * * @param array $files List of files in the allowlist. * @param array $filesWithNewPattern List of files with new pattern in the .htaccess file. * * @return array List of files in the allowlist. */ private static function buildAllowlist($files = array(), $files_with_new_pattern = array()) { if (empty($files)) { return array(); } $allowlist = array(); $processed_files = array(); foreach ($files as $file) { $wildcard_pattern = true; $relative_path = ''; // If this file is found in $files_with_new_pattern, it should not be marked as a wildcard pattern foreach ($files_with_new_pattern as $file_new_pattern) { if ($file_new_pattern['file'] === $file) { if (isset($processed_files[$file])) { continue; } $wildcard_pattern = false; $relative_path = $file_new_pattern['relative_path']; break; } } $processed_files[$file] = true; $allowlist[] = array( 'file' => $file, 'relative_path' => $relative_path ?: $file, 'wildcard_pattern' => $wildcard_pattern, ); } return $allowlist; } /** * Returns a list of files in the allowlist in folder. * * @param string $folder Directory to scan for files in the allowlist. * @return array List of files in the allowlist. Each file is an array with the keys: * - file: The name of the file. * - relative_path: The relative path of the file. * - wildcard_pattern: Whether the file is a wildcard pattern. */ public static function getAllowlist($folder = '') { $htaccess = self::htaccess($folder); $content = SucuriScanFileInfo::fileContent($htaccess); $files = self::getFiles($content); $files_with_new_pattern = self::getFilesWithNewPattern($content, $folder); $allowlist = self::buildAllowlist($files, $files_with_new_pattern); return $allowlist; } } src/hook.lib.php000060400000114351147177152050007563 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Function call interceptors. * * The term hooking covers a range of techniques used to alter or augment the * behavior of an operating system, of applications, or of other software * components by intercepting method calls or messages or events passed * between software components. Code that handles such intercepted methods, * events or messages is called a "hook". * * Hooking is used for many purposes, including debugging and extending * functionality. Examples might include intercepting keyboard or mouse event * messages before they reach an application, or intercepting operating system * calls in order to monitor behavior or modify the method of an application * or other component; it is also widely used in benchmarking programs. * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ class SucuriScanHook extends SucuriScanEvent { /** * Send to Sucuri servers an alert notifying that an attachment was added to a post. * * @param int $id The post identifier. * @return void */ public static function hookAttachmentAdd($id = 0) { $title = 'unknown'; $mime_type = 'unknown'; $data = get_post($id); if ($data) { $id = $data->ID; $title = $data->post_title; $mime_type = $data->post_mime_type; } $message = sprintf(__('Media file added; ID: %s; name: %s; type: %s', 'sucuri-scanner'), $id, $title, $mime_type); self::reportNoticeEvent($message); self::notifyEvent('post_publication', $message); } /** * Send and alert notifying that a user was added to a blog. * * @param int $user_id User ID. * @param string $role User role. * @param int $blog_id Blog ID. */ public static function hookAddUserToBlog($user_id, $role, $blog_id) { $title = __('unknown', 'sucuri-scanner'); $email = __('user@domain.com', 'sucuri-scanner'); $data = get_userdata($user_id); if ($data) { $title = $data->user_login; $email = $data->user_email; } $message = sprintf(__('User added to website; user_id: %s; role: %s; blog_id: %s; name: %s; email: %s', 'sucuri-scanner'), $user_id, $role, $blog_id, $title, $email ); self::reportWarningEvent($message); } /** * Send and alert notifying that a user was removed from a blog. * * @param int $user_id User ID. * @param int $blog_id Blog ID. */ public static function hookRemoveUserFromBlog($user_id, $blog_id) { $title = __('unknown', 'sucuri-scanner'); $email = __('user@domain.com', 'sucuri-scanner'); $data = get_userdata($user_id); if ($data) { $title = $data->user_login; $email = $data->user_email; } $message = sprintf(__('User removed from website; user_id: %s; blog_id: %s; name: %s; email: %s', 'sucuri-scanner'), $user_id, $blog_id, $title, $email ); self::reportWarningEvent($message); } /** * Send an alert notifying that a category was created. * * @param int $id The identifier of the category created. * @return void */ public static function hookCategoryCreate($id = 0) { $title = ( is_int($id) ? get_cat_name($id) : __('Unknown', 'sucuri-scanner') ); $message = sprintf(__('Category created; ID: %s; name: %s', 'sucuri-scanner'), $id, $title); self::reportNoticeEvent($message); self::notifyEvent('post_publication', $message); } /** * Detects when the core files are updated. * * @param string $wp_version The current WordPress version. * @return void */ public static function hookCoreUpdate($wp_version='') { // WordPress core has been successfully updated $message = sprintf(__('WordPress updated to version: %s', 'sucuri-scanner'), $wp_version); self::reportCriticalEvent($message); self::notifyEvent('website_updated', $message); } /** * Send an alert notifying that a new link was added to the bookmarks. * * @param int $id Identifier of the new link created; * @return void */ public static function hookLinkAdd($id = 0) { $title = 'unknown'; $target = '_none'; $url = 'undefined/url'; $data = get_bookmark($id); if ($data) { $title = $data->link_name; $target = $data->link_target; $url = $data->link_url; } $message = sprintf( __('Bookmark link added; ID: %s; name: %s; url: %s; target: %s', 'sucuri-scanner'), $id, $title, $url, $target ); self::reportWarningEvent($message); self::notifyEvent('post_publication', $message); } /** * Send an alert notifying that a new link was added to the bookmarks. * * @param int $id Identifier of the new link created; * @return void */ public static function hookLinkEdit($id = 0) { $title = __('unknown', 'sucuri-scanner'); $target = '_none'; $url = 'undefined/url'; $data = get_bookmark($id); if ($data) { $title = $data->link_name; $target = $data->link_target; $url = $data->link_url; } $message = sprintf( __('Bookmark link edited; ID: %s; name: %s; url: %s; target: %s', 'sucuri-scanner'), $id, $title, $url, $target ); self::reportWarningEvent($message); self::notifyEvent('post_publication', $message); } /** * Send an alert notifying that an attempt to login into the * administration panel failed. * * @param string $title The name of the user account involved in the transaction. * @return void */ public static function hookLoginFailure($title = '') { $password = SucuriScanRequest::post('pwd'); $title = empty($title) ? __('Unknown', 'sucuri-scanner') : sanitize_user($title, true); $message = sprintf(__('User authentication failed: %s', 'sucuri-scanner'), $title); sucuriscan_log_failed_login($title); self::reportErrorEvent($message); self::notifyEvent('failed_login', $message); /* report brute-force attack if necessary */ $logins = sucuriscan_get_failed_logins(); if (is_array($logins) && !empty($logins)) { $max_time = 3600; /* report logins in the last hour */ $maximum = SucuriScanOption::getOption(':maximum_failed_logins'); if ($logins['diff_time'] <= $max_time && $logins['count'] >= $maximum) { /** * Report brute-force attack with latest failed logins. * * If the time passed is within the hour, and the quantity * of failed logins registered in the datastore file is * bigger than the maximum quantity of failed logins allowed * per hour (value configured by the administrator in the * settings page), then send an email notification reporting * the event and specifying that it may be a brute-force * attack against the login page. */ sucuriscan_report_failed_logins($logins); } elseif ($logins['diff_time'] > $max_time) { /** * Reset old failed login logs. * * If there time passed is superior to the hour, then reset the * content of the datastore file containing the failed logins so * far, any entry in that file will not be considered as part of * a brute-force attack (if it exists) because the time passed * between the first and last login attempt is big enough to * mitigate the attack. */ sucuriscan_reset_failed_logins(); } } } /** * Detects usage of the password reset form. * * @return void */ public static function hookLoginFormResetpass() { // Detecting WordPress 2.8.3 vulnerability - $key is array. if (isset($_GET['key']) && is_array($_GET['key'])) { self::reportCriticalEvent(__('Attempt to reset password by attacking WP/2.8.3 bug', 'sucuri-scanner')); } } /** * Send an alert notifying that an attempt to login into the * administration panel was successful. * * @param string $title User account involved in the transaction. * @return void */ public static function hookLoginSuccess($title = '') { $title = empty($title) ? __('Unknown', 'sucuri-scanner') : $title; $message = sprintf(__('User authentication succeeded: %s', 'sucuri-scanner'), $title); self::reportNoticeEvent($message); self::notifyEvent('success_login', $message); } /** * Detects changes in the website settings. * * The plugin will monitor all the requests in the general settings page. It * will compare the value sent with the form with the value in the database * and if there are differences will send an email alert notifying the admin * about the changes. * * @return void */ public static function hookOptionsManagement() { /* detect any Wordpress settings modification */ if (current_user_can('manage_options') && SucuriScanOption::checkOptionsNonce()) { /* compare settings in the database with the modified ones */ $options_changed = SucuriScanOption::whatOptionsWereChanged($_POST); $options_changed_str = ''; $options_changed_simple = ''; $options_changed_count = 0; /* determine which options were modified */ foreach ($options_changed['original'] as $option_name => $option_value) { $options_changed_count += 1; $options_changed_str .= sprintf( __("The value of the option %s was changed from '%s' to '%s'.
    \n", 'sucuri-scanner'), self::escape($option_name), self::escape($option_value), self::escape($options_changed['changed'][ $option_name ]) ); $options_changed_simple .= sprintf( __("%s: from '%s' to '%s',", 'sucuri-scanner'), self::escape($option_name), self::escape($option_value), self::escape($options_changed['changed'][ $option_name ]) ); } /* identify the origin of the request */ $option_page = isset($_POST['option_page']) ? $_POST['option_page'] : 'options'; $page_referer = __('Common', 'sucuri-scanner'); switch ($option_page) { case 'options': $page_referer = __('Global', 'sucuri-scanner'); break; case 'discussion': /* no_break */ case 'general': /* no_break */ case 'media': /* no_break */ case 'permalink': /* no_break */ case 'reading': /* no_break */ case 'writing': /* no_break */ $page_referer = ucwords($option_page); break; } if ($options_changed_count) { $message = sprintf(__('%s settings changed', 'sucuri-scanner'), $page_referer); self::reportErrorEvent( sprintf( __('%s: (multiple entries): %s', 'sucuri-scanner'), $message, rtrim($options_changed_simple, ',') ) ); self::notifyEvent('settings_updated', $message . "
    \n" . $options_changed_str); } } } /** * Sends an alert with information about a plugin that has been activated. * * @param string $plugin Name of the plugin. * @param string $network_activation Whether the activation was global or not. * @return void */ public static function hookPluginActivate($plugin = '', $network_activation = '') { self::hookPluginChanges('activated', $plugin, $network_activation); } /** * Detects whether a plugin has been activated or deactivated. * * This method will send an email alert notifying the website owners about * activations or deactivations of the plugins. Notice that this only works * if the plugin was affected by a programmatic task. The method will not be * able to detect a deactivation if the plugin has been deleted via FTP or * SSH or any file manager available in the hosting panel. * * @param string $action Activated or deactivated. * @param string $plugin Short name of the plugin file. * @param string $network Whether the action is global or not. * @return void */ private static function hookPluginChanges($action, $plugin = '', $network = '') { $filename = WP_PLUGIN_DIR . '/' . $plugin; /* ignore non-existing plugins */ if (!file_exists($filename)) { return; } $info = get_plugin_data($filename); $name = __('Unknown', 'sucuri-scanner'); $version = '0.0.0'; if (!empty($info['Name'])) { $name = $info['Name']; } if (!empty($info['Version'])) { $version = $info['Version']; } $message = sprintf( __('Plugin %s: %s (v%s; %s%s)', 'sucuri-scanner'), $action, /* activated or deactivated */ self::escape($info['Name']), self::escape($info['Version']), self::escape($plugin), ($network ? '; network' : '') ); self::reportWarningEvent($message); self::notifyEvent('plugin_' . $action, $message); } /** * Sends an alert with information about a plugin that has been deactivated. * * @param string $plugin Name of the plugin. * @param string $network_activation Whether the deactivation was global or not. * @return void */ public static function hookPluginDeactivate($plugin = '', $network_activation = '') { self::hookPluginChanges('deactivated', $plugin, $network_activation); } /** * Detects when a plugin is deleted. * * @return void */ public static function hookPluginDelete() { // Plugin deletion request. if (current_user_can('delete_plugins') && SucuriScanRequest::post('action', 'delete-selected') && SucuriScanRequest::post('verify-delete', '1') ) { $plugin_list = SucuriScanRequest::post('checked', '_array'); $items_affected = array(); foreach ((array) $plugin_list as $plugin) { $filename = WP_PLUGIN_DIR . '/' . $plugin; if (!file_exists($filename)) { continue; } $plugin_info = get_plugin_data($filename); if (!empty($plugin_info['Name']) && !empty($plugin_info['Version']) ) { $items_affected[] = sprintf( '%s (v%s; %s)', self::escape($plugin_info['Name']), self::escape($plugin_info['Version']), self::escape($plugin) ); } } // Report deleted plugins at once. if (!empty($items_affected)) { if (count($items_affected) > 1) { $message = __('Plugins deleted: (multiple entries):', 'sucuri-scanner'); } else { $message = __('Plugin deleted:', 'sucuri-scanner'); } $message .= "\x20" . @implode(',', $items_affected); self::reportWarningEvent($message); self::notifyEvent('plugin_deleted', $message); } } } /** * Detects when the plugin editor is used. * * @return void */ public static function hookPluginEditor() { // Plugin editor request. if (current_user_can('edit_plugins') && SucuriScanRequest::post('action', 'update') && SucuriScanRequest::post('plugin', '.+') && SucuriScanRequest::post('file', '.+') && strpos($_SERVER['SCRIPT_NAME'], 'plugin-editor.php') !== false ) { $filename = SucuriScanRequest::post('file'); $message = sprintf(__('Plugin editor used in: %s', 'sucuri-scanner'), SucuriScan::escape($filename)); self::reportErrorEvent($message); self::notifyEvent('theme_editor', $message); } } /** * Detects when a plugin is uploaded or installed. * * @return void */ public static function hookPluginInstall() { // Plugin installation request. if (current_user_can('install_plugins') && SucuriScanRequest::getOrPost('action', '(install|upload)-plugin') && check_ajax_referer( 'updates', false, false ) ) { $plugin = SucuriScanRequest::getOrPost('plugin', '.+'); if (isset($_FILES['pluginzip'])) { $plugin = $_FILES['pluginzip']['name']; } $plugin = $plugin ? $plugin : __('Unknown', 'sucuri-scanner'); $message = sprintf(__('Plugin installed: %s', 'sucuri-scanner'), self::escape($plugin)); self::reportWarningEvent($message); self::notifyEvent('plugin_installed', $message); } } /** * Detects when a plugin is updated or upgraded. * * @return void */ public static function hookPluginUpdate() { // Plugin update request. $plugin_update_actions = '(upgrade-plugin|do-plugin-upgrade|update-selected)'; if (!current_user_can('update_plugins')) { return; } if (SucuriScanRequest::getOrPost('action', $plugin_update_actions) || SucuriScanRequest::getOrPost('action2', $plugin_update_actions) ) { if (!check_ajax_referer( 'updates', false, false )) { return; } $plugin_list = array(); $items_affected = array(); if (SucuriScanRequest::get('plugin', '.+') && strpos($_SERVER['SCRIPT_NAME'], 'wp-admin/update.php') !== false ) { $plugin_list[] = SucuriScanRequest::get('plugin', '.+'); } elseif (isset($_POST['checked']) && is_array($_POST['checked']) && !empty($_POST['checked']) ) { $plugin_list = SucuriScanRequest::post('checked', '_array'); } foreach ($plugin_list as $plugin) { $plugin_info = get_plugin_data(WP_PLUGIN_DIR . '/' . $plugin); if (!empty($plugin_info['Name']) && !empty($plugin_info['Version']) ) { $items_affected[] = sprintf( '%s (v%s; %s)', self::escape($plugin_info['Name']), self::escape($plugin_info['Version']), self::escape($plugin) ); } } // Report updated plugins at once. if (!empty($items_affected)) { if (count($items_affected) > 1) { $message = __('Plugins updated: (multiple entries):', 'sucuri-scanner'); } else { $message = __('Plugin updated:', 'sucuri-scanner'); } $message .= "\x20" . @implode(',', $items_affected); self::reportWarningEvent($message); self::notifyEvent('plugin_updated', $message); } } } /** * Every time a post or page is deleted WordPress triggers an action called * delete_post, this action is caught by the event monitor. However, at this * point the page or post has already been deleted, which means we cannot * send enough information about the event to the API. To fix this, we will * also monitor the before_delete_post action which is triggered before the * post is deleted but after the user has executed the action. * * We will store some information related to the post in a temporary data * structure. Then, when the delete_post action is triggered we will extract * this informaiton to send it to the API. We will delete the temporary data * after the operation has succeeded. * * @param int $id The identifier of the post deleted. * @return void */ public static function hookPostBeforeDelete($id = 0) { $data = get_post($id); if (!$data) { return; } $out = array(); /* data to cache */ $cache = new SucuriScanCache('hookdata'); $out['id'] = $data->ID; $out['author'] = $data->post_author; $out['type'] = $data->post_type; $out['status'] = $data->post_status; $out['inserted'] = $data->post_date; $out['modified'] = $data->post_modified; $out['guid'] = $data->guid; $out['title'] = empty($data->post_title) ? '(empty)' : $data->post_title; $cache->add('post_' . $id, $out); } /** * Send an alert notifying that a post was deleted. * * @param int $id The identifier of the post deleted. * @return void */ public static function hookPostDelete($id = 0) { $pieces = array(); $cache = new SucuriScanCache('hookdata'); $data = $cache->get('post_' . $id); $data = $data ? $data : array('id' => $id); foreach ($data as $keyname => $value) { $pieces[] = sprintf('Post %s: %s', $keyname, $value); } $cache->delete('post_' . $id); $entries = implode(',', $pieces); /* merge all entries together */ self::reportWarningEvent(sprintf(__('Post deleted: (multiple entries): %s', 'sucuri-scanner'), $entries)); } /** * Sends an alert for transitions between post statuses. * * @param string $new New post status. * @param string $old Old post status. * @param mixed $post Post data. * @return void */ public static function hookPostStatus($new = '', $old = '', $post = null) { if (!property_exists($post, 'ID')) { return self::throwException(__('Ignore corrupted post data', 'sucuri-scanner')); } /* ignore; the same */ if ($old === $new) { return self::throwException(__('Skip events for equal transitions', 'sucuri-scanner')); } $post_type = 'post'; /* either post or page */ if (property_exists($post, 'post_type')) { $post_type = $post->post_type; } if ($post_type === 'postman_sent_mail') { /** * Stop infinite loop sending the email alerts. * * The plugin detects changes in the posts, there are some other * plugins that intercept PHPMailer and create a post object that is * later used to send the real message to the users. This object is * also detected by our plugin and is considered an additional event * that must be reported, so after the first execution the operation * falls into an infinite loop. * * @date 30 June, 2017 * @see https://wordpress.org/plugins/postman-smtp/ * @see https://wordpress.org/support/topic/unable-to-access-wordpress-dashboard-after-update-to-1-8-7/ */ return self::throwException(__('Skip events for postman-smtp alerts', 'sucuri-scanner')); } /* check if email alerts are disabled for this type */ if (SucuriScanOption::isIgnoredEvent($post_type)) { return self::throwException(__('Skip events for ignored post-types', 'sucuri-scanner')); } /* check if email alerts are disabled for this transition */ $custom_type = sprintf('from_%s_to_%s', $old, $new); if (SucuriScanOption::isIgnoredEvent($custom_type)) { return self::throwException(__('Skip events for ignored post transitions', 'sucuri-scanner')); } $pieces = array(); $post_type = ucwords($post_type); $pieces[] = sprintf(__('ID: %s', 'sucuri-scanner'), self::escape($post->ID)); $pieces[] = sprintf(__('Old status: %s', 'sucuri-scanner'), self::escape($old)); $pieces[] = sprintf(__('New status: %s', 'sucuri-scanner'), self::escape($new)); if (property_exists($post, 'post_title')) { $pieces[] = sprintf(__('Title: %s', 'sucuri-scanner'), self::escape($post->post_title)); } $message = sprintf(__('%s status has been changed', 'sucuri-scanner'), self::escape($post_type)); $message .= "; details:\x20"; $message .= implode(',', $pieces); self::reportNoticeEvent($message); self::notifyEvent('post_publication', $message); } /** * Send an alert notifying that a post was moved to the trash. * * @param int $id The identifier of the trashed post. * @return void */ public static function hookPostTrash($id = 0) { $title = __('Unknown', 'sucuri-scanner'); $status = 'none'; $data = get_post($id); if ($data) { $title = $data->post_title; $status = $data->post_status; } $message = sprintf( __('Post moved to trash; ID: %s; name: %s; status: %s', 'sucuri-scanner'), $id, $title, $status ); self::reportWarningEvent($message); } /** * Send an alert notifying that a post or page is created or updated. * * @param int $id The identifier of the post or page published. * @return void */ private static function hookPublish($id = 0) { $title = __('Unknown', 'sucuri-scanner'); $p_type = __('Publication', 'sucuri-scanner'); $action = 'published'; $data = get_post($id); if ($data) { $title = $data->post_title; $p_type = ucwords($data->post_type); $action = 'updated'; /* new posts have the same creation and modification dates */ if ($data->post_date === $data->post_modified) { $action = 'created'; } SucuriScanFirewall::clearCacheHook(); } $message = sprintf( __('%s was %s; ID: %s; name: %s', 'sucuri-scanner'), self::escape($p_type), self::escape($action), intval($id), self::escape($title) ); self::reportNoticeEvent($message); self::notifyEvent('post_publication', $message); } /** * Detects when a page is created or updated. * * @param int $id The identifier of the post or page published. * @return void */ public static function hookPublishPage($id = 0) { self::hookPublish($id); } /** * Detects when a post is created or updated via email. * * @param int $id The identifier of the post or page published. * @return void */ public static function hookPublishPhone($id = 0) { self::hookPublish($id); } /** * Detects when a post is created or updated. * * @param int $id The identifier of the post or page published. * @return void */ public static function hookPublishPost($id = 0) { self::hookPublish($id); } /** * Detects when a post is created or updated via XML-RPC. * * @param int $id The identifier of the post or page published. * @return void */ public static function hookPublishPostXMLRPC($id = 0) { self::hookPublish($id); } /** * Send an alert notifying that an attempt to retrieve the password * of an user account was tried. * * @param string $title The name of the user account involved in the trasaction. * @return void */ public static function hookRetrievePassword($title = '') { $title = empty($title) ? 'unknown' : $title; self::reportErrorEvent(sprintf(__('Password retrieval attempt: %s', 'sucuri-scanner'), $title)); } /** * Detects when a theme is deleted. * * @return void */ public static function hookThemeDelete() { // Theme deletion request. if (current_user_can('delete_themes') && SucuriScanRequest::getOrPost('action', 'delete') && SucuriScanRequest::getOrPost('stylesheet', '.+') && check_ajax_referer( 'updates', false, false ) ) { $theme = SucuriScanRequest::getOrPost('stylesheet', '.+'); $theme = $theme ? $theme : __('Unknown', 'sucuri-scanner'); $message = sprintf(__('Theme deleted: %s', 'sucuri-scanner'), self::escape($theme)); self::reportWarningEvent($message); self::notifyEvent('theme_deleted', $message); } } /** * Detects when the theme editor is used. * * @return void */ public static function hookThemeEditor() { // Theme editor request. if (current_user_can('edit_themes') && SucuriScanRequest::post('action', 'update') && SucuriScanRequest::post('theme', '.+') && SucuriScanRequest::post('file', '.+') && strpos($_SERVER['SCRIPT_NAME'], 'theme-editor.php') !== false && check_ajax_referer( 'updates', false, false ) ) { $theme_name = SucuriScanRequest::post('theme'); $filename = SucuriScanRequest::post('file'); $message = sprintf(__('Theme editor used in: %s/%s', 'sucuri-scanner'), SucuriScan::escape($theme_name), SucuriScan::escape($filename)); self::reportErrorEvent($message); self::notifyEvent('theme_editor', $message); } } /** * Detects when a theme is installed. * * @return void */ public static function hookThemeInstall() { // Theme installation request. if (current_user_can('install_themes') && SucuriScanRequest::get('action', 'install-theme') && check_ajax_referer( 'updates', false, false ) ) { $theme = SucuriScanRequest::get('theme', '.+'); $theme = $theme ? $theme : __('Unknown', 'sucuri-scanner'); $message = sprintf(__('Theme installed: %s', 'sucuri-scanner'), self::escape($theme)); self::reportWarningEvent($message); self::notifyEvent('theme_installed', $message); } } /** * Send an alert notifying that the theme of the site was changed. * * @param string $title The name of the new theme selected to used through out the site. * @return void */ public static function hookThemeSwitch($title = '') { $title = empty($title) ? 'unknown' : $title; $message = sprintf(__('Theme activated: %s', 'sucuri-scanner'), $title); self::reportWarningEvent($message); self::notifyEvent('theme_activated', $message); } /** * Detects when a theme is automatically or manually updated. * * @return void */ public static function hookThemeUpdate() { // Theme update request. if (current_user_can('update_themes') && SucuriScanRequest::get('action', '(upgrade-theme|do-theme-upgrade)') && SucuriScanRequest::post('checked', '_array') && check_ajax_referer( 'updates', false, false ) ) { $themes = SucuriScanRequest::post('checked', '_array'); $items_affected = array(); foreach ((array) $themes as $theme) { $theme_info = wp_get_theme($theme); $theme_name = ucwords($theme); $theme_version = '0.0'; if ($theme_info->exists()) { $theme_name = $theme_info->get('Name'); $theme_version = $theme_info->get('Version'); } $items_affected[] = sprintf( '%s (v%s; %s)', self::escape($theme_name), self::escape($theme_version), self::escape($theme) ); } // Report updated themes at once. if (is_array($items_affected) && !empty($items_affected)) { if (count($items_affected) > 1) { $message = __('Themes updated: (multiple entries):', 'sucuri-scanner'); } else { $message = __('Theme updated:', 'sucuri-scanner'); } $message .= "\x20" . implode(',', $items_affected); self::reportWarningEvent($message); self::notifyEvent('theme_updated', $message); } } } /** * Send an alert notifying that a user account was deleted. * * @param int $id The identifier of the user account deleted. * @return void */ public static function hookUserDelete($id = 0) { self::reportWarningEvent(sprintf(__('User account deleted; ID: %d', 'sucuri-scanner'), $id)); } /** * Send an alert notifying that a user was edited. * @param int $id The identifier of the edited user account * @param object $old_user_data Object containing user's data prior to update. */ public static function hookProfileUpdate($id = 0, $old_user_data = false) { $title = __('unknown', 'sucuri-scanner'); $email = __('user@domain.com', 'sucuri-scanner'); $roles = 'none'; $data = get_userdata($id); if ($data) { $title = $data->user_login; $email = $data->user_email; $roles = @implode(', ', $data->roles); } $old_title = __('unknown', 'sucuri-scanner'); $old_email = __('user@domain.com', 'sucuri-scanner'); $old_roles = 'none'; if($old_user_data) { $old_title = $old_user_data->user_login; $old_email = $old_user_data->user_email; $old_roles = @implode(', ', $old_user_data->roles); } $message = sprintf(__('User account edited; ID: %s; name: %s; old_name: %s; email: %s; old_email: %s; roles: %s; old_roles: %s', 'sucuri-scanner'), $id, $title, $old_title, $email, $old_email, $roles, $old_roles ); self::reportWarningEvent($message); } /** * Send an alert notifying that a new user account was created. * * @param int $id The identifier of the new user account created. * @return void */ public static function hookUserRegister($id = 0) { $title = __('unknown', 'sucuri-scanner'); $email = __('user@domain.com', 'sucuri-scanner'); $roles = 'none'; $data = get_userdata($id); if ($data) { $title = $data->user_login; $email = $data->user_email; $roles = @implode(', ', $data->roles); } $message = sprintf( __('User account created; ID: %s; name: %s; email: %s; roles: %s', 'sucuri-scanner'), $id, $title, $email, $roles ); self::reportWarningEvent($message); self::notifyEvent('user_registration', $message); } /** * Detects when a widget is added. * * @return void */ public static function hookWidgetAdd() { self::hookWidgetChanges(); } /** * Detects when a widget is added or deleted * * @return void */ private static function hookWidgetChanges() { // Widget addition or deletion. if (current_user_can('edit_theme_options') && SucuriScanRequest::post('action', 'save-widget') && SucuriScanRequest::post('id_base') !== false && SucuriScanRequest::post('sidebar') !== false && check_ajax_referer( 'save-sidebar-widgets', 'savewidgets', false ) ) { if (SucuriScanRequest::post('delete_widget', '1')) { $action_d = 'deleted'; $action_text = 'deleted from'; } else { $action_d = 'added'; $action_text = 'added to'; } $message = sprintf( __('Widget %s (%s) %s %s (#%d; size %dx%d)', 'sucuri-scanner'), SucuriScanRequest::post('id_base'), SucuriScanRequest::post('widget-id'), $action_text, SucuriScanRequest::post('sidebar'), SucuriScanRequest::post('widget_number'), SucuriScanRequest::post('widget-width'), SucuriScanRequest::post('widget-height') ); self::reportWarningEvent($message); self::notifyEvent('widget_' . $action_d, $message); } } /** * Detects when a widget is deleted. * * @return void */ public static function hookWidgetDelete() { self::hookWidgetChanges(); } } src/index.html000060400000000046147177152050007335 0ustar00 src/installer-skin-legacy.lib.php000060400000003121147177152050013014 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Plugin Installer Skin for WordPress Plugin Installer before WP 5.3. * * This is used by the post-hack utility to disregard the installation * process when the website owner decides to reset one or more plugins. * Without this WordPress will flush the buffer of the re-installation * process immediately and we will not be able to disregard these logs * after the operation has finished. * * @codeCoverageIgnore * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ class SucuriScanPluginInstallerSkin extends Plugin_Installer_Skin { /** * Reports the progress of the plugin installation. * * @param string $string Message to display in administration message. * * @return void */ public function feedback($string) { /* do not do anything */ } }src/installer-skin.lib.php000060400000004550147177152050011561 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } if (class_exists('SucuriScanInterface') && class_exists('SucuriScanRequest')) { if (SucuriScanRequest::post('form_action') == 'reset_plugin') { include_once ABSPATH . '/wp-admin/includes/class-wp-upgrader.php'; include_once ABSPATH . '/wp-admin/includes/plugin-install.php'; if (version_compare(SucuriScan::siteVersion(), '5.3', '<')) { include_once 'installer-skin-legacy.lib.php'; return; } /** * Plugin Installer Skin for WordPress Plugin Installer. * * This is used by the post-hack utility to disregard the installation * process when the website owner decides to reset one or more plugins. * Without this WordPress will flush the buffer of the re-installation * process immediately and we will not be able to disregard these logs * after the operation has finished. * * @codeCoverageIgnore * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ class SucuriScanPluginInstallerSkin extends Plugin_Installer_Skin { /** * Reports the progress of the plugin installation. * * @param string $string Message to display in administration message. * @param mixed ...$args Optional text replacements. * * @return void */ public function feedback($string, ...$args) { /* do not do anything */ } } } } src/integrity.lib.php000060400000071572147177152050010650 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Checks the integrity of the WordPress installation. * * This tool finds changes in the standard WordPress installation. Files located * in the root directory, wp-admin and wp-includes will be compared against the * files distributed with the current WordPress version; all files with * inconsistencies will be listed here. * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ class SucuriScanIntegrity { /** * Compare the md5sum of the core files in the current site with the hashes hosted * remotely in Sucuri servers. These hashes are updated every time a new version * of WordPress is released. If the "Send Email" parameter is set the method will * send a notification to the administrator with a list of files that were added, * modified and/or deleted so far. * * @return string HTML code with a list of files that were affected. */ public static function pageIntegrity() { $params = array(); self::pageIntegritySubmission(); return SucuriScanTemplate::getSection('integrity', $params); } /** * Returns a JSON-encoded object with the WordPress integrity status. * * The plugin gets the checksum of all the files installed in the server that * are also part of a normal WordPress package. Then, it communicates with * a WordPress API service to retrieve the official checksums of the files * distributed with the package with the same version installed in the site. * * For any file found in the site that is not part of a normal installation * the plugin will report it as ADDED, for any file that is missing from the * installation but part of the official WordPress package, the plugin will * report it as DELETED, and for every file found in the site that is also * part of a normal installation, it will report it as MODIFIED if there are * differences in their checksums. * * @codeCoverageIgnore - Notice that there is a test case that covers this * code, but since the WP-Send-JSON method uses die() to stop any further * output it means that XDebug cannot cover the next line, leaving a report * with a missing line in the coverage. Since the test case takes care of * the functionality of this code we will assume that it is fully covered. * * @return void */ public static function ajaxIntegrity() { if (SucuriScanRequest::post('form_action') !== 'check_wordpress_integrity') { return; } wp_send_json(self::getIntegrityStatus(), 200); } /** * Mark as fixed, restore or delete flagged integrity files. * * Process the HTTP requests sent by the form submissions originated in the * integrity page, all forms must have a nonce field that will be checked * against the one generated in the template render function. * * @return void */ private static function pageIntegritySubmission() { /* restore, remove, mark as fixed the core files */ $action = SucuriScanRequest::post(':integrity_action'); if ($action === false || !SucuriScanInterface::checkNonce()) { return; /* skip if the action or nonce is invalid */ } /* skip if the user didn't confirm the operation */ if (SucuriScanRequest::post(':process_form') != 1) { return SucuriScanInterface::error(__('You need to confirm that you understand the risk of this operation.', 'sucuri-scanner')); } /* skip if the requested action is not currently supported */ if ($action !== 'fixed' && $action !== 'delete' && $action !== 'restore') { return SucuriScanInterface::error(__('Requested action is not supported.', 'sucuri-scanner')); } /* process the HTTP request */ $cache = new SucuriScanCache('integrity'); $core_files = SucuriScanRequest::post(':integrity', '_array'); $files_selected = count($core_files); $files_affected = array(); $files_processed = 0; $action_titles = array( 'restore' => __('Core file restored', 'sucuri-scanner'), 'delete' => __('Non-core file deleted', 'sucuri-scanner'), 'fixed' => __('Core file marked as fixed', 'sucuri-scanner'), ); /* skip if no files were selected */ if (!$core_files) { return SucuriScanInterface::error(__('Nothing was selected from the list.', 'sucuri-scanner')); } /* process files until the maximum execution time is reached */ $startTime = microtime(true); $displayTimeoutAlert = false; $maxtime = (int)SucuriScan::iniGet('max_execution_time'); $timeout = ($maxtime > 1) ? ($maxtime - 6) : 30; foreach ((array)$core_files as $file_meta) { if (strpos($file_meta, '@') === false) { continue; } /* avoid gateway timeout; max execution time */ $elapsedTime = (microtime(true) - $startTime); if ($elapsedTime >= $timeout) { $displayTimeoutAlert = true; break; } @list($status_type, $file_path) = explode('@', $file_meta, 2); if (!$file_path || !$status_type) { continue; } $full_path = ABSPATH . '/' . $file_path; if ($action === 'fixed' && ($status_type === 'added' || $status_type === 'removed' || $status_type === 'modified')) { $cache_key = md5($file_path); $cache_value = array( 'file_path' => $file_path, 'file_status' => $status_type, 'ignored_at' => time(), ); if ($cache->add($cache_key, $cache_value)) { $files_affected[] = $full_path; $files_processed++; } continue; } if ($action === 'restore' && ($status_type === 'removed' || $status_type === 'modified')) { $content = SucuriScanAPI::getOriginalCoreFile($file_path); if ($content) { $basedir = dirname($full_path); if (!file_exists($basedir)) { @mkdir($basedir, 0755, true); } if (@file_put_contents($full_path, $content)) { $files_affected[] = $full_path; $files_processed++; } } continue; } if ($action === 'delete' && $status_type === 'added') { if (@unlink($full_path)) { $files_affected[] = $full_path; $files_processed++; } continue; } } /* report files affected as a single event */ if (!empty($files_affected)) { $message = $action_titles[$action] . ':'; $message .= count($files_affected) > 1 ? "\x20(multiple entries):\x20" : ''; $message .= @implode(',', $files_affected); switch ($action) { case 'restore': SucuriScanEvent::reportInfoEvent($message); break; case 'delete': SucuriScanEvent::reportNoticeEvent($message); break; case 'fixed': SucuriScanEvent::reportWarningEvent($message); break; } } if ($displayTimeoutAlert) { SucuriScanInterface::error(__('Server is not fast enough to process this action; maximum execution time reached', 'sucuri-scanner')); } if ($files_processed != $files_selected) { return SucuriScanInterface::error( sprintf( __('Only %d out of %d files were processed.', 'sucuri-scanner'), $files_processed, $files_selected ) ); } return SucuriScanInterface::info( sprintf( __('%d out of %d files were successfully processed.', 'sucuri-scanner'), $files_processed, $files_selected ) ); } public static function getTotalAffectedFiles($latest_hashes, $ignored_files) { $affected_files = 0; if ($latest_hashes) { foreach ($latest_hashes as $list_type => $file_list) { if ($list_type == 'stable' || empty($file_list)) { continue; } foreach ($file_list as $file_info) { $file_path = $file_info['filepath']; if ($ignored_files /* skip files marked as fixed */ && array_key_exists(md5($file_path), $ignored_files) ) { continue; } $affected_files += 1; } } } return $affected_files; } /** * Checks if the WordPress integrity is correct or not. * * For any file found in the site that is not part of a normal installation * the plugin will report it as ADDED, for any file that is missing from the * installation but part of the official WordPress package, the plugin will * report it as DELETED, and for every file found in the site that is also * part of a normal installation, it will report it as MODIFIED if there are * differences in their checksums. * * The website owner will receive an email alert with this information. * * @param bool $send_email Send an email alert to the admins. * @return string|bool HTML with information about the integrity. */ public static function getIntegrityStatus($send_email = false) { $params = array(); /* initialize the values for the pagination */ $maxPerPage = SUCURISCAN_INTEGRITY_FILES_PER_PAGE; $pageNumber = SucuriScanTemplate::pageNumber(); if (isset($_POST['files_per_page'])) { $filesPerPage = intval(SucuriScanRequest::post('files_per_page')); if ($filesPerPage > 0) { $maxPerPage = $filesPerPage; } } $params['Version'] = SucuriScan::siteVersion(); $params['Integrity.List'] = ''; $params['Integrity.ListCount'] = 0; $params['Integrity.RemoteChecksumsURL'] = ''; $params['Integrity.BadVisibility'] = 'hidden'; $params['Integrity.GoodVisibility'] = 'hidden'; $params['Integrity.FailureVisibility'] = 'visible'; $params['Integrity.FalsePositivesVisibility'] = 'hidden'; $params['Integrity.DiffUtility'] = ''; $params['Integrity.Pagination'] = ''; $params['Integrity.PaginationVisibility'] = 'hidden'; $params['Integrity.Items'] = ''; $itemsToLoad = array( 15, 50, 200, 1000 ); foreach ($itemsToLoad as $items) { $params['Integrity.Items'] .= sprintf('', $items, ucfirst($items)); } // Check if there are added, removed, or modified files. $cache = new SucuriScanCache('integrity'); $ignored_files = $cache->getAll(); $latest_hashes = self::checkIntegrityIntegrity(); $affected_files = self::getTotalAffectedFiles($latest_hashes, $ignored_files); $params['Integrity.RemoteChecksumsURL'] = SucuriScanAPI::checksumAPI(); if ($latest_hashes) { $counter = 0; $processed_files = 0; $params['Integrity.BadVisibility'] = 'hidden'; $params['Integrity.GoodVisibility'] = 'visible'; $params['Integrity.FailureVisibility'] = 'hidden'; $iterator_start = ($pageNumber - 1) * $maxPerPage; foreach ($latest_hashes as $list_type => $file_list) { if ($list_type == 'stable' || empty($file_list)) { continue; } foreach ($file_list as $file_info) { $file_path = $file_info['filepath']; $full_filepath = sprintf('%s/%s', rtrim(ABSPATH, '/'), $file_path); if ($ignored_files /* skip files marked as fixed */ && array_key_exists(md5($file_path), $ignored_files) ) { $params['Integrity.FalsePositivesVisibility'] = 'visible'; continue; } // Pagination conditions if ($counter < $iterator_start) { $counter++; continue; } if ($processed_files >= $maxPerPage) { break; } // Add extra information to the file list. $file_size = @filesize($full_filepath); $file_size_human = ''; /* empty */ /* error message if the file cannot be fixed */ $error = ''; $visibility = 'hidden'; if ($file_info['is_fixable'] !== true) { $visibility = 'visible'; if ($list_type === 'added') { $error = __('The plugin has no permission to delete this file because it was created by a different system user who has more privileges than your account. Please use FTP to delete it.', 'sucuri-scanner'); } elseif ($list_type === 'modified') { $error = __('The plugin has no permission to restore this file because it was modified by a different system user who has more privileges than your account. Please use FTP to restore it.', 'sucuri-scanner'); } elseif ($list_type === 'removed') { $error = __('The plugin has no permission to restore this file because its directory is owned by a different system user who has more privileges than your account. Please use FTP to restore it.', 'sucuri-scanner'); } } // Pretty-print the file size in human-readable form. if ($file_size !== false) { $file_size_human = SucuriScan::humanFileSize($file_size); } $modified_at = $file_info['modified_at'] ? SucuriScan::datetime($file_info['modified_at']) : ''; // Generate the HTML code from the snippet template for this file. $params['Integrity.List'] .= SucuriScanTemplate::getSnippet( 'integrity-incorrect', array( 'Integrity.StatusType' => $list_type, 'Integrity.FilePath' => $file_path, 'Integrity.FileSize' => $file_size, 'Integrity.FileSizeHuman' => $file_size_human, 'Integrity.FileSizeNumber' => number_format($file_size), 'Integrity.ModifiedAt' => $modified_at, 'Integrity.ErrorVisibility' => $visibility, 'Integrity.ErrorMessage' => $error, ) ); $processed_files++; $counter++; } } if ($counter > 0) { $params['Integrity.ListCount'] = $affected_files; $params['Integrity.BadVisibility'] = 'visible'; $params['Integrity.GoodVisibility'] = 'hidden'; } } if ($send_email === true) { if ($affected_files > 0) { return SucuriScanEvent::notifyEvent( 'scan_checksums', /* send alert with a list of affected files */ SucuriScanTemplate::getSection('integrity-notification', $params) ); } return false; } ob_start(); $details = SucuriScanSiteCheck::details(); $errors = ob_get_clean(); /* capture possible errors */ $params['SiteCheck.Details'] = empty($errors) ? $details : '
    ' . $errors; $params['Integrity.DiffUtility'] = SucuriScanIntegrity::diffUtility(); if ($affected_files > 1) { $maxpages = ceil($affected_files / $maxPerPage); if ($maxpages > 1) { $params['Integrity.PaginationVisibility'] = 'visible'; $params['Integrity.Pagination'] = SucuriScanTemplate::pagination( SucuriScanTemplate::getUrl(), $affected_files, $maxPerPage ); } } $params['Integrity.Items'] = str_replace('option value="' . $maxPerPage . '"', 'option value="' . $maxPerPage . '" selected', $params['Integrity.Items']); $template = ($affected_files === 0) ? 'correct' : 'incorrect'; return SucuriScanTemplate::getSection('integrity-' . $template, $params); } /** * Setups the page to allow the execution of the diff utility. * * This method will write the modal window and the JavaScript code that will * allow the admin to send an Ajax request to inspect the difference between * a file that is currently installed in the website and the original code * distributed with the official WordPress package. * * @return string HTML and JavaScript code for the diff utility. */ public static function diffUtility() { if (!SucuriScanOption::isEnabled(':diff_utility')) { return ''; /* empty page */ } $params = array(); $params['DiffUtility.Modal'] = SucuriScanTemplate::getModal( 'none', array( 'Title' => __('WordPress Integrity Diff Utility', 'sucuri-scanner'), 'Content' => '' /* empty */, 'Identifier' => 'diff-utility', 'Visibility' => 'hidden', ) ); return SucuriScanTemplate::getSection('integrity-diff-utility', $params); } /** * Returns the output of the diff utility. * * Some errors will be reported if the admin requests to see the differences * in a file that is not part of the official WordPress distribution. Also, * if the file does not exists it will be useless to see the differences * because obviously the content of the file will all be missing. The plugin * will thrown an exception in this case too. * * @codeCoverageIgnore - Notice that there is a test case that covers this * code, but since the WP-Send-JSON method uses die() to stop any further * output it means that XDebug cannot cover the next line, leaving a report * with a missing line in the coverage. Since the test case takes care of * the functionality of this code we will assume that it is fully covered. * * @return void */ public static function ajaxIntegrityDiffUtility() { if (SucuriScanRequest::post('form_action') !== 'integrity_diff_utility') { return; } ob_start(); $filename = SucuriScanRequest::post('filepath'); echo SucuriScanCommand::diffHTML($filename); $response = ob_get_clean(); wp_send_json($response, 200); } /** * Retrieve a list of md5sum and last modification time of all the files in the * folder specified. This is a recursive function. * * @param string $dir The base path where the scanning will start. * @param bool $recursive Either TRUE or FALSE if the scan should be performed recursively. * @return array List of arrays containing the md5sum and last modification time of the files found. */ private static function integrityTree($dir = './', $recursive = false) { $file_info = new SucuriScanFileInfo(); $file_info->ignore_files = false; $file_info->ignore_directories = false; $file_info->run_recursively = $recursive; $tree = $file_info->getDirectoryTreeMd5($dir, true); return !$tree ? array() : $tree; } /** * Check whether the core WordPress files where modified, removed or if any file * was added to the core folders. This method returns an associative array with * these keys: * *
      *
    • modified: Files with a different checksum according to the official WordPress archives,
    • *
    • stable: Files with the same checksums as the official files,
    • *
    • removed: Official files which are not present in the local project,
    • *
    • added: Files present in the local project but not in the official WordPress packages.
    • *
    * * @return array|bool Associative array with these keys: modified, stable, removed, added. */ private static function checkIntegrityIntegrity() { $base_content_dir = ''; $latest_hashes = SucuriScanAPI::getOfficialChecksums(); if (defined('WP_CONTENT_DIR')) { $base_content_dir = basename(rtrim(WP_CONTENT_DIR, '/')); } // @codeCoverageIgnoreStart if (!$latest_hashes) { return false; } // @codeCoverageIgnoreEnd $output = array( 'added' => array(), 'removed' => array(), 'modified' => array(), 'stable' => array(), ); // Get current filesystem tree. $wp_top_hashes = self::integrityTree(ABSPATH, false); $wp_admin_hashes = self::integrityTree(ABSPATH . 'wp-admin', true); $wp_includes_hashes = self::integrityTree(ABSPATH . 'wp-includes', true); $wp_core_hashes = array_merge($wp_top_hashes, $wp_admin_hashes, $wp_includes_hashes); $checksumAlgorithm = SucuriScanAPI::checksumAlgorithm(); // Compare remote and local checksums and search removed files. foreach ($latest_hashes as $file_path => $remote) { if (self::ignoreIntegrityFilepath($file_path)) { continue; } $full_filepath = sprintf('%s/%s', ABSPATH, $file_path); // @codeCoverageIgnoreStart if (!file_exists($full_filepath) && defined('WP_CONTENT_DIR') && strpos($file_path, 'wp-content') !== false ) { /* patch for custom content directory path */ $file_path = str_replace('wp-content', $base_content_dir, $file_path); $dir_content_dir = dirname(rtrim(WP_CONTENT_DIR, '/')); $full_filepath = sprintf('%s/%s', $dir_content_dir, $file_path); } // @codeCoverageIgnoreEnd // Check whether the official file exists or not. if (file_exists($full_filepath)) { /* skip folders; cannot calculate a hash easily */ if (is_dir($full_filepath)) { $output['stable'][] = array( 'filepath' => $file_path, 'is_fixable' => false, 'modified_at' => 0, ); continue; } $local = SucuriScanAPI::checksum($checksumAlgorithm, $full_filepath); if ($local !== false && $local === $remote) { $output['stable'][] = array( 'filepath' => $file_path, 'is_fixable' => false, 'modified_at' => 0, ); } else { $modified_at = @filemtime($full_filepath); $is_fixable = (bool)is_writable($full_filepath); $output['modified'][] = array( 'filepath' => $file_path, 'is_fixable' => $is_fixable, 'modified_at' => $modified_at, ); } } else { $is_fixable = is_writable(dirname($full_filepath)); $output['removed'][] = array( 'filepath' => $file_path, 'is_fixable' => $is_fixable, 'modified_at' => 0, ); } } // Search added files (files not common in a normal wordpress installation). foreach ($wp_core_hashes as $file_path => $extra_info) { $file_path = str_replace(DIRECTORY_SEPARATOR, '/', $file_path); $file_path = @preg_replace('/^\.\/(.*)/', '$1', $file_path); if (self::ignoreIntegrityFilepath($file_path)) { continue; } if (!array_key_exists($file_path, $latest_hashes)) { $full_filepath = ABSPATH . '/' . $file_path; $modified_at = @filemtime($full_filepath); $is_fixable = (bool)is_writable($full_filepath); $output['added'][] = array( 'filepath' => $file_path, 'is_fixable' => $is_fixable, 'modified_at' => $modified_at, ); } } sort($output['added']); sort($output['removed']); sort($output['modified']); return $output; } /** * Ignore irrelevant files and directories from the integrity checking. * * @param string $path File path that will be compared. * @return bool True if the file should be ignored, false otherwise. */ private static function ignoreIntegrityFilepath($path = '') { $irrelevant = array( 'php.ini', '.htaccess', '.htpasswd', '.ftpquota', 'wp-includes/.htaccess', 'wp-admin/setup-config.php', 'wp-tests-config.php', 'wp-config.php', 'sitemap.xml', 'sitemap.xml.gz', 'readme.html', 'error_log', 'wp-pass.php', 'wp-rss.php', 'wp-feed.php', 'wp-register.php', 'wp-atom.php', 'wp-commentsrss2.php', 'wp-rss2.php', 'wp-rdf.php', '404.php', '503.php', '500.php', '500.shtml', '400.shtml', '401.shtml', '402.shtml', '403.shtml', '404.shtml', '405.shtml', '406.shtml', '407.shtml', '408.shtml', '409.shtml', 'healthcheck.html', ); /** * Ignore i18n files. * * Sites with i18n have differences compared with the official English * version of the project, basically they have files with new variables * specifying the language that will be used in the admin panel, site * options, and emails. */ if (@$GLOBALS['wp_local_package'] != 'en_US') { $irrelevant[] = 'wp-includes/version.php'; $irrelevant[] = 'wp-config-sample.php'; } if (in_array($path, $irrelevant)) { return true; } /* use regular expressions */ $ignore = false; $irrelevant = array( '^sucuri_[0-9a-z\-]+\.php$', '^sucuri-[0-9a-z\-]+\.php$', '^\S+-sucuri-db-dump-gzip-[0-9]{10}-[0-9a-z]{32}\.gz$', '^\.sucuri-sss-resume-[0-9a-z]{32}\.php$', '^([^\/]*)\.(pdf|css|txt|jpg|gif|png|jpeg)$', '^wp-content\/(themes|plugins)\/.+', '^google[0-9a-z]{16}\.html$', '^pinterest-[0-9a-z]{5}\.html$', '^wp-content\/languages\/.+\.mo$', '^wp-content\/languages\/.+\.po$', '^wp-content\/languages\/.+\.json$', '\.ico$', ); foreach ($irrelevant as $pattern) { if (@preg_match('/' . $pattern . '/', $path)) { $ignore = true; break; } } return $ignore; } } src/interface.lib.php000060400000027731147177152050010570 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Plugin initializer. * * Define all the required variables, script, styles, and basic functions needed * when the site is loaded, not even the administrator panel but also the front * page, some bug-fixes will/are applied here for sites behind a proxy, and * sites with old versions of the premium plugin (deprecated on July, 2014). * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ class SucuriScanInterface { /** * Initialization code for the plugin. * * @return void */ public static function initialize() { SucuriScanEvent::installScheduledTask(); if (SucuriScan::supportReverseProxy() || SucuriScan::isBehindFirewall()) { $_SERVER['SUCURIREAL_REMOTE_ADDR'] = $_SERVER['REMOTE_ADDR']; $_SERVER['REMOTE_ADDR'] = SucuriScan::getRemoteAddr(); } } /** * Define which javascript and css files will be loaded in the header of the * plugin pages, only when the administrator panel is accessed. * * @return void */ public static function enqueueScripts() { wp_register_style( 'sucuriscan', SUCURISCAN_URL . '/inc/css/styles.css', array(/* empty */), SucuriScan::fileVersion('inc/css/styles.css') ); wp_enqueue_style('sucuriscan'); wp_register_script( 'sucuriscan', SUCURISCAN_URL . '/inc/js/scripts.js', array(/* empty */), SucuriScan::fileVersion('inc/js/scripts.js') ); wp_enqueue_script('sucuriscan'); if (SucuriScanRequest::get('page', 'sucuriscan_firewall') !== false) { wp_register_style( 'sucuriscan2', SUCURISCAN_URL . '/inc/css/flags.min.css', array(/* empty */), SucuriScan::fileVersion('inc/css/flags.min.css') ); wp_enqueue_style('sucuriscan2'); } } /** * Remove the old Sucuri plugins. * * Considering that in the new version (after 1.6.0) all the functionality * of the others will be merged here, this will remove duplicated code, * duplicated bugs and/or duplicated maintenance reports allowing us to * focus in one unique project. * * @return void */ public static function handleOldPlugins() { // @codeCoverageIgnoreStart if (!class_exists('SucuriScanFileInfo')) { return; } // @codeCoverageIgnoreEnd $finfo = new SucuriScanFileInfo(); $finfo->ignore_files = false; $finfo->ignore_directories = false; $finfo->skip_directories = false; $finfo->run_recursively = true; $plugins = array( 'c3VjdXJpLXdwLXBsdWdpbi9zdWN1cmkucGhw', 'c3VjdXJpLWNsb3VkcHJveHktd2FmL2Nsb3VkcHJveHkucGhw', 'ZGVzc2t5LXNlY3VyaXR5L2Rlc3NreS1zZWN1cml0eS5waHA=', ); foreach ($plugins as $plugin) { $plugin = base64_decode($plugin); $plugin_directory = dirname(WP_PLUGIN_DIR . '/' . $plugin); if (file_exists($plugin_directory)) { if (is_plugin_active($plugin)) { // @codeCoverageIgnoreStart deactivate_plugins($plugin); // @codeCoverageIgnoreEnd } $finfo->removeDirectoryTree($plugin_directory); } } } /** * Create a folder in the WordPress upload directory where the plugin will * store all the temporal or dynamic information. * * @return void */ public static function createStorageFolder() { $directory = SucuriScan::dataStorePath(); if (!file_exists($directory)) { @mkdir($directory, 0755, true); } if (file_exists($directory)) { // Create last-logins datastore file. sucuriscan_lastlogins_datastore_exists(); // Create a htaccess file to deny access from all. if (!SucuriScanHardening::isHardened($directory)) { SucuriScanHardening::hardenDirectory($directory); } // Create an index.html to avoid directory listing. if (!file_exists($directory . '/index.html')) { @file_put_contents( $directory . '/index.html', '' ); } } } /** * Display alerts and execute pre-checks before every page. * * This method verifies if the visibility of the requested page is allowed * for the current user in session which usually needs to be granted admin * privileges to access the plugin's tools. It also checks if the required * SPL library is available and if the settings file is writable. * * @return void */ public static function startupChecks() { self::checkPageVisibility(); self::noticeAfterUpdate(); if (!SucuriScanFileInfo::isSplAvailable()) { /* display a warning when system dependencies are not met */ self::error(__('The plugin requires PHP 5 >= 5.3.0 - OR - PHP 7', 'sucuri-scanner')); } $filename = SucuriScanOption::optionsFilePath(); if (!is_writable($filename)) { self::error( sprintf( __('Storage is not writable: %s', 'sucuri-scanner'), $filename /* absolute path of the settings file */ ) ); } } /** * Do something if the plugin was updated. * * Check if an option exists with the version number of the plugin, if the * number is different than the number defined in the constant that comes * with this code then we can consider this as an update, in which case we * will execute certain actions and/or display some messages. * * @codeCoverageIgnore * * @return void */ public static function noticeAfterUpdate() { /* get version of the plugin that was previously installed */ $version = SucuriScanOption::getOption(':plugin_version'); /* use simple comparison to force type cast. */ if ($version == SUCURISCAN_VERSION) { return; } /* update the version number in the plugin settings. */ SucuriScanOption::updateOption(':plugin_version', SUCURISCAN_VERSION); /** * Invite website owner to subscribe to our security newsletter. * * For every fresh installation of the plugin we will send a one-time * email to the website owner with an invitation to subscribe to our * security related newsletter where they can learn about better security * practices and get alerts from public vulnerabilities disclosures. * * @date Featured added at - May 01, 2017 */ self::info(__('Do you want to get vulnerability disclosures? Subscribe to our newsletter here', 'sucuri-scanner')); } /** * Check whether a user has the permissions to see a page from the plugin. * * @codeCoverageIgnore * * @return void */ public static function checkPageVisibility() { if (!function_exists('current_user_can') || !current_user_can('manage_options')) { SucuriScan::throwException(__('Access denied; cannot manage options', 'sucuri-scanner')); wp_die(sprintf(__('Access denied by %s', 'sucuri-scanner'), SUCURISCAN_PLUGIN_NAME)); } } /** * Verify the nonce of the previous page after a form submission. If the * validation fails the execution of the script will be stopped and a dead page * will be printed to the client using the official WordPress method. * * @codeCoverageIgnore * * @return bool True if the nonce is valid, false otherwise. */ public static function checkNonce() { if (!empty($_POST)) { $nonce_name = 'sucuriscan_page_nonce'; $nonce_value = SucuriScanRequest::post($nonce_name, '_nonce'); if (!$nonce_value || !wp_verify_nonce($nonce_value, $nonce_name)) { SucuriScan::throwException(__('Nonce is invalid', 'sucuri-scanner')); self::error(__('WordPress CSRF verification failed. The submitted form is missing an important unique code that prevents the execution of automated malicious scanners. Go back and try again. If you did not submit a form, this error message could be an indication of an incompatibility between this plugin and another add-on; one of them is inserting data into the global POST variable when the HTTP request is coming via GET. Disable them one by one (while reloading this page) to find the culprit.', 'sucuri-scanner')); return false; } } return true; } /** * Prints a HTML alert in the WordPress admin interface. * * @codeCoverageIgnore * * @param string $type The type of alert, it can be either Updated or Error. * @param string $message The message that will be printed in the alert. * @return void */ private static function adminNotice($type = 'updated', $message = '') { $display_notice = true; /** * Do not render notice during user authentication. * * There are some special cases when the error or warning messages * should not be rendered to the end user because it may break the * default functionality of the request handler. For instance, rendering * an HTML alert like this when the user authentication process is * executed may cause a "headers already sent" error. */ if (!empty($_POST) && SucuriScanRequest::post('log') && SucuriScanRequest::post('pwd') && SucuriScanRequest::post('wp-submit') ) { $display_notice = false; } /* display the HTML notice to the current user */ if ($display_notice === true && !empty($message)) { $message = SUCURISCAN_ADMIN_NOTICE_PREFIX . "\x20" . $message; SucuriScan::throwException($message, $type); echo SucuriScanTemplate::getSection( 'notification-admin', array( 'AlertType' => $type, 'AlertUnique' => rand(100, 999), 'AlertMessage' => $message, ) ); } } /** * Prints a HTML alert of type ERROR in the WordPress admin interface. * * @param string $msg The message that will be printed in the alert. * @return void */ public static function error($msg = '') { self::adminNotice('error', $msg); return false; /* assume failure */ } /** * Prints a HTML alert of type INFO in the WordPress admin interface. * * @param string $msg The message that will be printed in the alert. * @return void */ public static function info($msg = '') { self::adminNotice('updated', $msg); return true; /* assume success */ } } src/lastlogins-failed.php000060400000034503147177152050011457 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Print a list with the failed logins occurred during the last hour. * * @return string A list with the failed logins occurred during the last hour. */ function sucuriscan_failed_logins_panel() { $template_variables = array( 'FailedLogins.List' => '', 'FailedLogins.Total' => '', 'FailedLogins.MaxFailedLogins' => 0, 'FailedLogins.NoItemsVisibility' => 'visible', 'FailedLogins.WarningVisibility' => 'visible', 'FailedLogins.PaginationLinks' => '', 'FailedLogins.PaginationVisibility' => 'hidden', ); // Define variables for the pagination. $page_number = SucuriScanTemplate::pageNumber(); $max_per_page = SUCURISCAN_MAX_PAGINATION_BUTTONS; $page_offset = ($page_number - 1) * $max_per_page; $page_limit = ($page_offset + $max_per_page); // Clear failed login logins when delete button is pressed. if (SucuriScanInterface::checkNonce() && SucuriScanRequest::post(':delete_failedlogins')) { SucuriScanEvent::clearLastLogs('sucuri-failedlogins.php'); } $max_failed_logins = SucuriScanOption::getOption(':maximum_failed_logins'); $notify_bruteforce_attack = SucuriScanOption::getOption(':notify_bruteforce_attack'); $failed_logins = sucuriscan_get_all_failed_logins($page_offset, $max_per_page); if ($failed_logins) { $counter = 0; for ($key = $page_offset; $key < $page_limit; $key++) { if (array_key_exists($key, $failed_logins['entries'])) { $login_data = $failed_logins['entries'][ $key ]; if (!is_array($login_data)) { continue; } $template_variables['FailedLogins.List'] .= SucuriScanTemplate::getSnippet( 'lastlogins-failedlogins', array( 'FailedLogins.Num' => $login_data['attempt_count'], 'FailedLogins.Username' => $login_data['user_login'], 'FailedLogins.RemoteAddr' => $login_data['remote_addr'], 'FailedLogins.UserAgent' => $login_data['user_agent'], 'FailedLogins.Datetime' => SucuriScan::datetime($login_data['attempt_time']), ) ); $counter++; } } if ($counter > 0) { $template_variables['FailedLogins.NoItemsVisibility'] = 'hidden'; } $template_variables['FailedLogins.PaginationLinks'] = SucuriScanTemplate::pagination( '%%SUCURI.URL.Lastlogins%%#failed', $failed_logins['count'], $max_per_page ); if ($failed_logins['count'] > $max_per_page) { $template_variables['FailedLogins.PaginationVisibility'] = 'visible'; } } $template_variables['FailedLogins.MaxFailedLogins'] = $max_failed_logins; if ($notify_bruteforce_attack == 'enabled') { $template_variables['FailedLogins.WarningVisibility'] = 'hidden'; } return SucuriScanTemplate::getSection('lastlogins-failedlogins', $template_variables); } /** * Find the full path of the file where the information of the failed logins * will be stored, it will be created automatically if does not exists (and if * the destination folder has permissions to write). This method can also be * used to reset the content of the datastore file. * * @see sucuriscan_reset_failed_logins() * * @param bool $get_old_logs Whether the old logs will be retrieved or not. * @param bool $reset Whether the file will be resetted or not. * @return string|false Absolute path to the file. */ function sucuriscan_failed_logins_datastore_path($get_old_logs = false, $reset = false) { $file_name = $get_old_logs ? 'sucuri-oldfailedlogins.php' : 'sucuri-failedlogins.php'; $datastore_path = SucuriScan::dataStorePath($file_name); $default_content = sucuriscan_failed_logins_default_content(); // Create the file if it does not exists. if (!file_exists($datastore_path) || $reset) { @file_put_contents($datastore_path, $default_content, LOCK_EX); } // Return the datastore path if the file exists (or was created). if (is_readable($datastore_path)) { return $datastore_path; } return false; } /** * Default content of the datastore file where the failed logins are being kept. * * @return string Default content of the file. */ function sucuriscan_failed_logins_default_content() { return "\n"; } /** * Returns failed logins data including old entries. * * @param int $offset Initial index to start the array. * @param int $limit Number of items in the returned array. * @return array|false Failed logins data. */ function sucuriscan_get_all_failed_logins($offset = 0, $limit = -1) { $all = array(); $new = sucuriscan_get_failed_logins(); $old = sucuriscan_get_failed_logins(true, $offset, $limit); if ($new && $old) { // Merge the new and old failed logins. $all = array(); $all['first_attempt'] = $old['first_attempt']; $all['last_attempt'] = $new['last_attempt']; $all['count'] = $new['count'] + $old['count']; $all['diff_time'] = abs($all['last_attempt'] - $all['first_attempt']); $all['entries'] = array_merge($new['entries'], $old['entries']); return $all; } elseif ($new && !$old) { return $new; } elseif (!$new && $old) { return $old; } return false; } /** * Read and parse the content of the datastore file where the failed logins are * being kept. This method will also calculate the difference in time between * the first and last login attempt registered in the file to later decide if * there is a brute-force attack in progress (and send an email notification * with the report) or reset the file after considering it a normal behavior of * the site. * * @param bool $get_old_logs Whether the old logs will be retrieved or not. * @param int $offset Array index from where to start collecting the data. * @param int $limit Number of items to insert into the returned array. * @return array|false Information and entries gathered from the failed logins datastore file. */ function sucuriscan_get_failed_logins($get_old_logs = false, $offset = 0, $limit = -1) { $datastore_path = sucuriscan_failed_logins_datastore_path($get_old_logs); if (!$datastore_path) { return false; } $lines = SucuriScanFileInfo::fileLines($datastore_path); if (!$lines) { return false; } $failed_logins = array( 'count' => 0, 'first_attempt' => 0, 'last_attempt' => 0, 'diff_time' => 0, 'entries' => array(), ); // Read and parse all the entries found in the datastore file. $initial = count($lines) - 1; $processed = 0; // Start from the newest entry in the file. for ($key = $initial; $key >= 0; $key--) { $line = trim($lines[ $key ]); // Skip lines that are clearly not JSON-encoded. if (substr($line, 0, 1) !== '{') { continue; } // Reduce the memory allocation by skipping unnecessary lines (LEFT). if ($limit > 0 && $failed_logins['count'] < $offset) { $failed_logins['entries'][] = $line; $failed_logins['count'] += 1; continue; } // Reduce the memory allocation by skipping unnecessary lines (RIGHT). if ($limit > 0 && $processed > $limit) { $failed_logins['entries'][] = $line; $failed_logins['count'] += 1; continue; } // Decode data only if necessary. $login_data = @json_decode($line, true); $processed++; /* count decoded data */ if (is_array($login_data)) { $login_data['attempt_count'] = ( $key + 1 ); if (!$login_data['user_agent']) { $login_data['user_agent'] = __('Unknown', 'sucuri-scanner'); } if (!isset($login_data['user_password'])) { $login_data['user_password'] = ''; } $failed_logins['entries'][] = $login_data; $failed_logins['count'] += 1; } } // Stop if the there is no data. if ($failed_logins['count'] <= 0) { return false; } // Calculate the different time between the first and last attempt. $idx = abs($failed_logins['count'] - 1); $last = $failed_logins['entries'][$idx]; $first = $failed_logins['entries'][0]; if (!is_array($last)) { /* In case the JSON is not decoded yet */ $last = @json_decode($last, true); } if (!is_array($first)) { /* In case the JSON is not decoded yet */ $first = @json_decode($first, true); } $failed_logins['last_attempt'] = $last['attempt_time']; $failed_logins['first_attempt'] = $first['attempt_time']; $failed_logins['diff_time'] = abs($last['attempt_time'] - $first['attempt_time']); return $failed_logins; } /** * Add a new entry in the datastore file where the failed logins are being kept, * this entry will contain the username, timestamp of the login attempt, remote * address of the computer sending the request, and the user-agent. * * @param string $user_login Information from the current failed login event. * @return bool True if the information was saved, false otherwise. */ function sucuriscan_log_failed_login($user_login = '') { $storage = sucuriscan_failed_logins_datastore_path(); if (!$storage) { return false; } $login_data = json_encode( array( 'user_login' => $user_login, 'attempt_time' => time(), 'remote_addr' => SucuriScan::getRemoteAddr(), 'user_agent' => SucuriScan::getUserAgent(), ) ); return (bool) @file_put_contents( $storage, $login_data . "\n", FILE_APPEND ); } /** * Read and parse all the entries in the datastore file where the failed logins * are being kept, this will loop through all these items and generate a table * in HTML code to send as a report via email according to the plugin settings * for the email alerts. * * @param array $failed_logins Information gathered from the failed logins. * @return bool Whether the report was sent via email or not. */ function sucuriscan_report_failed_logins($failed_logins = array()) { if (!$failed_logins || !isset($failed_logins['count']) || $failed_logins['count'] < 1 ) { return false; } $mail_content = ''; $prettify_mails = SucuriScanMail::prettifyMails(); if ($prettify_mails) { $table_html = ''; // Add the table headers. $table_html .= ''; $table_html .= ''; $table_html .= ''; $table_html .= ''; $table_html .= ''; $table_html .= ''; $table_html .= ''; $table_html .= ''; $table_html .= ''; $table_html .= ''; } foreach ($failed_logins['entries'] as $login_data) { $login_data['attempt_date'] = SucuriScan::datetime($login_data['attempt_time']); if ($prettify_mails) { $table_html .= ''; $table_html .= ''; $table_html .= ''; $table_html .= ''; $table_html .= ''; $table_html .= ''; $table_html .= ''; } else { $mail_content .= "\n"; $mail_content .= __('Username', 'sucuri-scanner') . ":\x20" . $login_data['user_login'] . "\n"; $mail_content .= __('Password', 'sucuri-scanner') . ":\x20" . $login_data['user_password'] . "\n"; $mail_content .= __('IP Address', 'sucuri-scanner') . ":\x20" . $login_data['remote_addr'] . "\n"; $mail_content .= __('Attempt Timestamp', 'sucuri-scanner') . ":\x20" . $login_data['attempt_time'] . "\n"; $mail_content .= __('Attempt Date/Time', 'sucuri-scanner') . ":\x20" . $login_data['attempt_date'] . "\n"; } } if ($prettify_mails) { $table_html .= ''; $table_html .= '
    ' . __('Username', 'sucuri-scanner') . '' . __('Password', 'sucuri-scanner') . '' . __('IP Address', 'sucuri-scanner') . '' . __('Attempt Timestamp', 'sucuri-scanner') . '' . __('Attempt Date/Time', 'sucuri-scanner') . '
    ' . esc_attr($login_data['user_login']) . '' . esc_attr($login_data['user_password']) . '' . esc_attr($login_data['remote_addr']) . '' . esc_attr($login_data['attempt_time']) . '' . esc_attr($login_data['attempt_date']) . '
    '; $mail_content = $table_html; } if (SucuriScanEvent::notifyEvent('bruteforce_attack', $mail_content)) { sucuriscan_reset_failed_logins(); return true; } return false; } /** * Remove all the entries in the datastore file where the failed logins are * being kept. The execution of this method will not delete the file (which is * likely the best move) but rather will clean its content and append the * default code defined by another method above. * * @return bool Whether the datastore file was resetted or not. */ function sucuriscan_reset_failed_logins() { $datastore_path = SucuriScan::dataStorePath('sucuri-failedlogins.php'); $datastore_backup_path = sucuriscan_failed_logins_datastore_path(true, false); $default_content = sucuriscan_failed_logins_default_content(); $current_content = @file_get_contents($datastore_path); $current_content = str_replace($default_content, '', $current_content); @file_put_contents( $datastore_backup_path, $current_content, FILE_APPEND ); return (bool) sucuriscan_failed_logins_datastore_path(false, true); } src/lastlogins-loggedin.php000060400000017462147177152050012030 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Print a list of all the registered users that are currently in session. * * @return string The HTML code displaying a list of all the users logged in at the moment. */ function sucuriscan_loggedin_users_panel() { // Get user logged in list. $params = array( 'LoggedInUsers.List' => '', 'LoggedInUsers.Total' => 0, ); $logged_in_users = sucuriscan_get_online_users(true); if (is_array($logged_in_users) && !empty($logged_in_users)) { $params['LoggedInUsers.Total'] = count($logged_in_users); foreach ((array) $logged_in_users as $logged_in_user) { $logged_in_user['last_activity_datetime'] = SucuriScan::datetime($logged_in_user['last_activity']); $logged_in_user['user_registered_datetime'] = SucuriScan::datetime(strtotime($logged_in_user['user_registered'])); $params['LoggedInUsers.List'] .= SucuriScanTemplate::getSnippet( 'lastlogins-loggedin', array( 'LoggedInUsers.Id' => $logged_in_user['user_id'], 'LoggedInUsers.UserURL' => SucuriScan::adminURL('user-edit.php?user_id=' . $logged_in_user['user_id']), 'LoggedInUsers.UserLogin' => $logged_in_user['user_login'], 'LoggedInUsers.UserEmail' => $logged_in_user['user_email'], 'LoggedInUsers.LastActivity' => $logged_in_user['last_activity_datetime'], 'LoggedInUsers.Registered' => $logged_in_user['user_registered_datetime'], 'LoggedInUsers.RemoteAddr' => $logged_in_user['remote_addr'], ) ); } } return SucuriScanTemplate::getSection('lastlogins-loggedin', $params); } /** * Get a list of all the registered users that are currently in session. * * @param bool $add_current_user Whether the current user should be added to the list or not. * @return array List of registered users currently in session. */ function sucuriscan_get_online_users($add_current_user = false) { $users = array(); if (SucuriScan::isMultiSite()) { $users = get_site_transient('sucuriscan_online_users'); } else { $users = get_transient('sucuriscan_online_users'); } // If not online users but current user is logged in, add it to the list. if (empty($users) && $add_current_user) { $current_user = wp_get_current_user(); if ($current_user->ID > 0) { sucuriscan_set_online_user($current_user->user_login, $current_user); return sucuriscan_get_online_users(); } } return $users; } /** * Update the list of the registered users currently in session. * * Useful when you are removing users and need the list of the remaining users. * * @param array $logged_in_users List of registered users currently in session. * @return bool Either TRUE or FALSE representing the success or fail of the operation. */ function sucuriscan_save_online_users($logged_in_users = array()) { $expiration = 30 * 60; if (SucuriScan::isMultiSite()) { return set_site_transient('sucuriscan_online_users', $logged_in_users, $expiration); } else { return set_transient('sucuriscan_online_users', $logged_in_users, $expiration); } } if (!function_exists('sucuriscan_unset_online_user_on_logout')) { /** * Remove a logged in user from the list. * * @return void */ function sucuriscan_unset_online_user_on_logout() { $remote_addr = SucuriScan::getRemoteAddr(); $current_user = wp_get_current_user(); $user_id = $current_user->ID; sucuriscan_unset_online_user($user_id, $remote_addr); } add_action('wp_logout', 'sucuriscan_unset_online_user_on_logout'); } /** * Remove a logged in user from the list of registered users in session using * the user identifier and the ip address of the last computer used to login. * * @param int $user_id User ID of the account that will be logged out. * @param string $remote_addr IP address of the computer where the user logged in. * @return bool True on success, false otherwise. */ function sucuriscan_unset_online_user($user_id = 0, $remote_addr = '') { $logged_in_users = sucuriscan_get_online_users(); // Remove the specified user identifier from the list. if (is_array($logged_in_users) && !empty($logged_in_users)) { foreach ($logged_in_users as $i => $user) { if ($user['user_id'] == $user_id && strcmp($user['remote_addr'], $remote_addr) == 0 ) { unset($logged_in_users[ $i ]); break; } } } return sucuriscan_save_online_users($logged_in_users); } if (!function_exists('sucuriscan_set_online_user')) { /** * Add an user account to the list of registered users in session. * * @param string $user_login The name of the user account that just logged in the site. * @param bool $user The WordPress object containing all the information associated to the user. * @return void */ function sucuriscan_set_online_user($user_login = '', $user = false) { if (!$user) { return; } /* get logged in user information */ $current_user = ($user instanceof WP_User) ? $user : wp_get_current_user(); $current_user_id = $current_user->ID; $remote_addr = SucuriScan::getRemoteAddr(); $current_time = current_time('timestamp'); $logged_in_users = sucuriscan_get_online_users(); /* build the dataset for the transient variable */ $current_user_info = array( 'user_id' => $current_user_id, 'user_login' => $current_user->user_login, 'user_email' => $current_user->user_email, 'user_registered' => $current_user->user_registered, 'last_activity' => $current_time, 'remote_addr' => $remote_addr, ); /* no previous data, no need to merge, override */ if (!is_array($logged_in_users) || empty($logged_in_users)) { $logged_in_users = array( $current_user_info ); sucuriscan_save_online_users($logged_in_users); return; } $item_index = 0; $do_nothing = false; $update_existing = false; /* update user metadata if the session already exists */ foreach ($logged_in_users as $i => $user) { if ($user['user_id'] == $current_user_id && strcmp($user['remote_addr'], $remote_addr) == 0 ) { if ($user['last_activity'] < ($current_time - (15 * 60))) { $update_existing = true; $item_index = $i; break; } else { $do_nothing = true; break; } } } if ($do_nothing) { return; } if ($update_existing) { $logged_in_users[ $item_index ] = $current_user_info; sucuriscan_save_online_users($logged_in_users); return; } $logged_in_users[] = $current_user_info; sucuriscan_save_online_users($logged_in_users); } add_action('wp_login', 'sucuriscan_set_online_user', 50, 2); } src/lastlogins.php000060400000040242147177152050010232 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Placeholder for the last logins interface. * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ class SucuriScanLastLogins extends SucuriScan { } /** * List all the user administrator accounts. * * @see https://codex.wordpress.org/Class_Reference/WP_User_Query * * @return void */ function sucuriscan_lastlogins_admins() { // Page pseudo-variables initialization. $params = array( 'AdminUsers.List' => '', ); $user_query = new WP_User_Query(array('role' => 'Administrator')); $admins = $user_query->get_results(); foreach ((array) $admins as $admin) { $last_logins = sucuriscan_get_logins(5, 0, $admin->ID); $user_snippet = array( 'AdminUsers.Username' => $admin->user_login, 'AdminUsers.Email' => $admin->user_email, 'AdminUsers.LastLogins' => '', 'AdminUsers.RegisteredAt' => 'unknown', 'AdminUsers.UserURL' => SucuriScan::adminURL('user-edit.php?user_id=' . $admin->ID), 'AdminUsers.NoLastLogins' => 'visible', 'AdminUsers.NoLastLoginsTable' => 'hidden', ); if ($last_logins && isset($last_logins['entries']) && !empty($last_logins['entries']) ) { $user_snippet['AdminUsers.NoLastLogins'] = 'hidden'; $user_snippet['AdminUsers.NoLastLoginsTable'] = 'visible'; $user_snippet['AdminUsers.RegisteredAt'] = 'unknown'; foreach ($last_logins['entries'] as $i => $lastlogin) { if ($i === 0) { $user_snippet['AdminUsers.RegisteredAt'] = SucuriScan::datetime( $lastlogin['user_registered_timestamp'] ); } $user_snippet['AdminUsers.LastLogins'] .= SucuriScanTemplate::getSnippet( 'lastlogins-admins-lastlogin', array( 'AdminUsers.RemoteAddr' => $lastlogin['user_remoteaddr'], 'AdminUsers.Datetime' => SucuriScan::datetime($lastlogin['user_lastlogin_timestamp']), ) ); } } $params['AdminUsers.List'] .= SucuriScanTemplate::getSnippet('lastlogins-admins', $user_snippet); } return SucuriScanTemplate::getSection('lastlogins-admins', $params); } /** * List the last-logins for all user accounts in the site. * * This page will contains information of all the logins of the registered users. * * @return string Last-logings for all user accounts. */ function sucuriscan_lastlogins_all() { $max_per_page = SUCURISCAN_LASTLOGINS_USERSLIMIT; $page_number = SucuriScanTemplate::pageNumber(); $offset = ($max_per_page * $page_number) - $max_per_page; $params = array( 'UserList' => '', 'UserList.Limit' => $max_per_page, 'UserList.Total' => 0, 'UserList.Pagination' => '', 'UserList.PaginationVisibility' => 'hidden', 'UserList.NoItemsVisibility' => 'visible', ); // Clear last login logins when delete button is pressed. if (SucuriScanInterface::checkNonce() && SucuriScanRequest::post(':delete_lastlogins')) { SucuriScanEvent::clearLastLogs('sucuri-lastlogins.php'); } if (!sucuriscan_lastlogins_datastore_is_writable()) { $fpath = SucuriScan::escape(sucuriscan_lastlogins_datastore_filepath()); SucuriScanInterface::error(sprintf(__('Last-logins data file is not writable: %s', 'sucuri-scanner'), $fpath)); } $last_logins = sucuriscan_get_logins($max_per_page, $offset); if (is_array($last_logins) && !empty($last_logins)) { $params['UserList.Total'] = $last_logins['total']; if ($last_logins['total'] > $max_per_page) { $params['UserList.PaginationVisibility'] = 'visible'; } if ($last_logins['total'] > 0) { $params['UserList.NoItemsVisibility'] = 'hidden'; } foreach ($last_logins['entries'] as $user) { $user_dataset = array( 'UserList.Number' => $user['line_num'], 'UserList.UserId' => $user['user_id'], 'UserList.Username' => 'unknown', 'UserList.Displayname' => '', 'UserList.Email' => '', 'UserList.Registered' => '', 'UserList.RemoteAddr' => $user['user_remoteaddr'], 'UserList.Hostname' => $user['user_hostname'], 'UserList.Datetime' => SucuriScan::datetime($user['user_lastlogin_timestamp']), 'UserList.TimeAgo' => SucuriScan::humanTime($user['user_lastlogin_timestamp']), 'UserList.UserURL' => SucuriScan::adminURL('user-edit.php?user_id=' . $user['user_id']), ); if ($user['user_exists']) { $user_dataset['UserList.Username'] = $user['user_login']; $user_dataset['UserList.Displayname'] = $user['display_name']; $user_dataset['UserList.Email'] = $user['user_email']; $user_dataset['UserList.Registered'] = $user['user_registered']; } $params['UserList'] .= SucuriScanTemplate::getSnippet('lastlogins-all', $user_dataset); } // Generate the pagination for the list. $params['UserList.Pagination'] = SucuriScanTemplate::pagination( '%%SUCURI.URL.Lastlogins%%', $last_logins['total'], $max_per_page ); } return SucuriScanTemplate::getSection('lastlogins-all', $params); } /** * Get the filepath where the information of the last logins of all users is stored. * * @return string Absolute filepath where the user's last login information is stored. */ function sucuriscan_lastlogins_datastore_filepath() { return SucuriScan::dataStorePath('sucuri-lastlogins.php'); } /** * Check whether the user's last login datastore file exists or not, if not then * we try to create the file and check again the success of the operation. * * @return string|bool Path to the storage file if exists, false otherwise. */ function sucuriscan_lastlogins_datastore_exists() { $fpath = sucuriscan_lastlogins_datastore_filepath(); if (!file_exists($fpath)) { @file_put_contents($fpath, "\n", LOCK_EX); } return file_exists($fpath) ? $fpath : false; } /** * Check whether the user's last login datastore file is writable or not, if not * we try to set the right permissions and check again the success of the operation. * * @return string|bool Path to the storage file if writable, false otherwise. */ function sucuriscan_lastlogins_datastore_is_writable() { $datastore_filepath = sucuriscan_lastlogins_datastore_exists(); if ($datastore_filepath) { if (!is_writable($datastore_filepath)) { @chmod($datastore_filepath, 0644); } if (is_writable($datastore_filepath)) { return $datastore_filepath; } } return false; } /** * Check whether the user's last login datastore file is readable or not, if not * we try to set the right permissions and check again the success of the operation. * * @return string|bool Path to the storage file if readable, false otherwise. */ function sucuriscan_lastlogins_datastore_is_readable() { $datastore_filepath = sucuriscan_lastlogins_datastore_exists(); if ($datastore_filepath && is_readable($datastore_filepath)) { return $datastore_filepath; } return false; } if (!function_exists('sucuriscan_set_lastlogin')) { /** * Add a new user session to the list of last user logins. * * @param string $user_login User account involved in the operation. * @return void */ function sucuriscan_set_lastlogin($user_login = '') { $filename = sucuriscan_lastlogins_datastore_is_writable(); if (!is_string($filename)) { return false; } $current_user = get_user_by('login', $user_login); $remote_addr = SucuriScan::getRemoteAddr(); $login_info = array( 'user_id' => $current_user->ID, 'user_login' => $current_user->user_login, 'user_remoteaddr' => $remote_addr, 'user_hostname' => @gethostbyaddr($remote_addr), 'user_lastlogin' => current_time('mysql') ); @file_put_contents( $filename, json_encode($login_info) . "\n", FILE_APPEND ); } add_action('wp_login', 'sucuriscan_set_lastlogin', 50); } /** * Retrieve the list of all the user logins from the datastore file. * * The results of this operation can be filtered by specific user identifiers, * or limiting the quantity of entries. * * @param int $limit How many entries will be returned from the operation. * @param int $offset Initial point where the logs will be start counting. * @param int $user_id Optional user identifier to filter the results. * @return array|bool All user logins, false on failure. */ function sucuriscan_get_logins($limit = 10, $offset = 0, $user_id = 0) { $limit = intval($limit); /* prevent arbitrary user input */ $datastore_filepath = sucuriscan_lastlogins_datastore_is_readable(); $last_logins = array( 'total' => 0, 'entries' => array(), ); if (!$datastore_filepath) { return SucuriScan::throwException(__('Invalid last-logins storage file', 'sucuri-scanner')); } $parsed_lines = 0; $data_lines = SucuriScanFileInfo::fileLines($datastore_filepath); if (!$data_lines) { return SucuriScan::throwException(__('No last-logins data is available', 'sucuri-scanner')); } /** * This count will not be 100% accurate considering that we are checking the * syntax of each line in the loop bellow, there may be some lines without the * right syntax which will differ from the total entries returned, but there's * not other EASY way to do this without affect the performance of the code. * * @var integer */ $total_lines = count($data_lines); $last_logins['total'] = $total_lines; // Get a list with the latest entries in the first positions. $reversed_lines = array_reverse($data_lines); /** * Only the user accounts with administrative privileges can see the logs of all * the users, for the rest of the accounts they will only see their own logins. * * @var object */ $user_ids = array(); $current_user = wp_get_current_user(); $is_admin_user = (bool) current_user_can('manage_options'); for ($i = $offset; $i < $total_lines; $i++) { $line = $reversed_lines[$i] ? trim($reversed_lines[$i]) : ''; // Check if the data is serialized (which we will consider as insecure). $last_login = @json_decode($line, true); if (!$last_login) { $last_logins['total'] -= 1; continue; } $last_login['user_lastlogin_timestamp'] = strtotime($last_login['user_lastlogin']); $last_login['user_registered_timestamp'] = 0; // Only administrators can see all login stats. if (!$is_admin_user && $current_user->user_login != $last_login['user_login']) { continue; } // Filter the user identifiers using the value passed tot his function. if ($user_id > 0 && $last_login['user_id'] != $user_id) { continue; } $last_login['user_exists'] = false; $user_ids[] = $last_login['user_id']; $last_login['line_num'] = $i + 1; $last_logins['entries'][] = $last_login; $parsed_lines += 1; if ($limit > 0 && $parsed_lines >= $limit) { break; } } /* no need for database query */ if (empty($user_ids)) { return $last_logins; } /* extra information for the unique user accounts */ $user_ids = array_unique($user_ids); $dbquery = new WP_User_Query(array('include' => $user_ids)); if ($dbquery) { $results = $dbquery->get_results(); foreach ($last_logins['entries'] as $key => $entry) { foreach ($results as $dbentry) { if ($entry['user_id'] === $dbentry->ID) { $last_logins['entries'][$key]['user_exists'] = true; $last_logins['entries'][$key]['user_nicename'] = $dbentry->user_nicename; $last_logins['entries'][$key]['user_email'] = $dbentry->user_email; $last_logins['entries'][$key]['user_url'] = $dbentry->user_url; $last_logins['entries'][$key]['user_status'] = $dbentry->user_status; $last_logins['entries'][$key]['display_name'] = $dbentry->display_name; $last_logins['entries'][$key]['user_registered'] = $dbentry->user_registered; $last_logins['entries'][$key]['user_registered_timestamp'] = strtotime($dbentry->user_registered); } } } } return $last_logins; } if (!function_exists('sucuriscan_login_redirect')) { /** * Hook for the wp-login action to redirect the user to a specific URL after * his successfully login to the administrator interface. * * @param string $redirect_to The redirect destination URL. * @param mixed $request The requested redirect destination URL passed as a parameter. * @param bool $user WP_User object if login was successful, WP_Error object otherwise. * @return string URL where the browser must be redirected to. */ function sucuriscan_login_redirect($redirect_to = '', $request = null, $user = false) { $login_url = !empty($redirect_to) ? $redirect_to : SucuriScan::adminURL(); if ($user instanceof WP_User && in_array('administrator', $user->roles) && SucuriScanOption::isEnabled(':lastlogin_redirection') ) { $login_url = add_query_arg('sucuriscan_lastlogin', 1, $login_url); } return $login_url; } if (SucuriScanOption::isEnabled(':lastlogin_redirection')) { add_filter('login_redirect', 'sucuriscan_login_redirect', 10, 3); } } if (!function_exists('sucuriscan_get_user_lastlogin')) { /** * Display the last user login at the top of the admin interface. * * @return void */ function sucuriscan_get_user_lastlogin() { if (current_user_can('manage_options') && SucuriScanRequest::get(':lastlogin', '1') ) { $current_user = wp_get_current_user(); $last_logins = sucuriscan_get_logins(2, 0, $current_user->ID); if ($last_logins && isset($last_logins['entries']) && isset($last_logins['entries'][1]) ) { $row = $last_logins['entries'][1]; $page_url = SucuriScanTemplate::getUrl('lastlogins'); $message = sprintf( __('Last login was at %s from %s (%s) view all logs', 'sucuri-scanner'), SucuriScan::datetime($row['user_lastlogin_timestamp']), SucuriScan::escape($row['user_remoteaddr']), SucuriScan::escape($row['user_hostname']), SucuriScan::escape($page_url) ); SucuriScanInterface::info($message); } } } add_action('network_admin_notices', 'sucuriscan_get_user_lastlogin'); add_action('admin_notices', 'sucuriscan_get_user_lastlogin'); } src/mail.lib.php000060400000023421147177152050007542 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Process and send emails. * * One of the core features of the plugin is the event alerts, a list of rules * will check if the site is being compromised, in which case a notification * will be sent to the site email address (an address that can be configured in * the settings page). * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ class SucuriScanMail extends SucuriScanOption { /** * Check whether the email alerts will be sent in HTML or Plain/Text. * * @return bool Whether the emails will be in HTML or Plain/Text. */ public static function prettifyMails() { return self::isEnabled(':prettify_mails'); } /** * Send a message to a specific email address. * * @param string $email The email address of the recipient that will receive the message. * @param string $subject The reason of the message that will be sent. * @param string $message Body of the message that will be sent. * @param array $data_set Optional parameter to add more information to the notification. * @return bool Whether the email contents were sent successfully. */ public static function sendMail($email = '', $subject = '', $message = '', $data_set = array()) { $headers = array(); $subject = ucwords(strtolower($subject)); $force = (bool) (isset($data_set['Force']) && $data_set['Force']); unset($data_set['Force']); /* remove to prevent inheritance */ /* check whether the email alerts will be sent in HTML or plain/text */ if (self::prettifyMails() || (isset($data_set['ForceHTML']) && $data_set['ForceHTML'])) { $headers = array('Content-Type: text/html'); $data_set['PrettifyType'] = 'pretty'; unset($data_set['ForceHTML']); } else { $headers = array('Content-Type: text/plain'); $message = strip_tags($message); } if (self::emailsPerHourReached() && !$force) { return self::throwException(__('Maximum number of emails per hour reached', 'sucuri-scanner')); } /* check if we need to load a template file to wrap the message */ if (!array_key_exists('UseRawHTML', $data_set) || !$data_set['UseRawHTML']) { $message = self::prettifyMail($subject, $message, $data_set); } $subject = self::getEmailSubject($subject); try { /** * WordPress uses a library named PHPMailer to send emails through the * provided method wp_mail, unfortunately the debug information is * completely removed and this makes it difficult to troubleshoots * issues reported by users when the SMTP server in their sites is * misconfigured. To reduce the number of tickets related with this * issue we will provide an option to allow the users to choose which * technique will be used to send the alerts. * * @see https://github.com/PHPMailer/PHPMailer * @see https://developer.wordpress.org/reference/functions/wp_mail/ */ if (SucuriScanOption::isEnabled(':use_wpmail')) { wp_mail($email, $subject, $message, $headers); } else { @mail($email, $subject, $message, implode("\r\n", $headers)); } $mails_sent = (int) self::getOption(':emails_sent'); self::updateOption(':emails_sent', $mails_sent + 1); self::updateOption(':last_email_at', time()); return true; /* assume mail delivery */ } catch ( Throwable $e ) { SucuriScanEvent::reportErrorEvent('An error occurred sending email - please check your server mail configuration.'); return false; } } /** * Generate a subject for the email alerts. * * @param string $event The reason of the message that will be sent. * @return string A text with the subject for the email alert. */ private static function getEmailSubject($event = '') { $subject = self::getOption(':email_subject'); $subject = strip_tags((string) $subject); $ip = self::getRemoteAddr(); $subject = str_replace(':event', $event, $subject); $subject = str_replace(':domain', self::getDomain(), $subject); $subject = str_replace(':remoteaddr', $ip, $subject); if (strpos($subject, ':hostname') !== false) { /* expensive operation; reverse user ip address if requested */ $subject = str_replace(':hostname', gethostbyaddr($ip), $subject); } /* include data from the user in session, if necessary */ if (strpos($subject, ':username') !== false || strpos($subject, ':email') !== false ) { $user = wp_get_current_user(); $username = 'unknown'; $eaddress = 'unknown'; if ($user instanceof WP_User && isset($user->user_login) && isset($user->user_email) ) { $username = $user->user_login; $eaddress = $user->user_email; } $subject = str_replace(':username', $user->user_login, $subject); $subject = str_replace(':email', $user->user_email, $subject); } return $subject; } /** * Generate a HTML version of the message that will be sent through an email. * * @param string $subject The reason of the message that will be sent. * @param string $message Body of the message that will be sent. * @param array $data_set Optional parameter to add more information to the notification. * @return string The message formatted in a HTML template. */ private static function prettifyMail($subject = '', $message = '', $data_set = array()) { $params = array(); $display_name = ''; $prettify_type = 'simple'; $user = wp_get_current_user(); $website = self::getDomain(); if (isset($data_set['PrettifyType'])) { $prettify_type = $data_set['PrettifyType']; } if ($user instanceof WP_User && isset($user->user_login) && !empty($user->user_login) ) { $display_name = sprintf( __('User: %s (%s)', 'sucuri-scanner'), $user->display_name, $user->user_login ); } // Format list of items when the event has multiple entries. if (strpos($message, 'multiple') !== false) { $message_parts = SucuriScanAPI::parseMultipleEntries($message); if (is_array($message_parts)) { $message = ( $prettify_type == 'pretty' ) ? $message_parts[0] . '
      ' : $message_parts[0]; unset($message_parts[0]); foreach ($message_parts as $msg_part) { if ($prettify_type == 'pretty') { $message .= sprintf("
    • %s
    • \n", $msg_part); } else { $message .= sprintf("\n- %s", $msg_part); } } $message .= ( $prettify_type == 'pretty' ) ? '
    ' : ''; } } $params['TemplateTitle'] = __('Sucuri Alert', 'sucuri-scanner'); $params['Subject'] = $subject; $params['Website'] = $website; $params['RemoteAddress'] = self::getRemoteAddr(); $params['ReverseAddress'] = gethostbyaddr($params['RemoteAddress']); $params['Message'] = $message; $params['User'] = $display_name; $params['Time'] = SucuriScan::datetime(); foreach ($data_set as $var_key => $var_value) { $params[ $var_key ] = $var_value; } /* SucuriScanTemplate::notification-pretty */ /* SucuriScanTemplate::notification-simple */ return SucuriScanTemplate::getSection('notification-' . $prettify_type, $params); } /** * Check whether the maximum quantity of emails per hour was reached. * * @return bool Whether the quota emails per hour was reached. */ private static function emailsPerHourReached() { $max_per_hour = self::getOption(':emails_per_hour'); if ($max_per_hour != 'unlimited') { // Check if we are still in that sixty minutes. $current_time = time(); $last_email_at = self::getOption(':last_email_at'); $diff_time = abs($current_time - $last_email_at); if ($diff_time <= 3600) { // Check if the quantity of emails sent is bigger than the configured. $emails_sent = (int) self::getOption(':emails_sent'); $max_per_hour = intval($max_per_hour); if ($emails_sent >= $max_per_hour) { return true; } } else { // Reset the counter of emails sent. self::updateOption(':emails_sent', 0); } } return false; } } src/option.lib.php000060400000074014147177152050010134 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Plugin options handler. * * Options are pieces of data that WordPress uses to store various preferences * and configuration settings. Listed below are the options, along with some of * the default values from the current WordPress install. By using the * appropriate function, options can be added, changed, removed, and retrieved, * from the wp_options table. * * The Options API is a simple and standardized way of storing data in the * database. The API makes it easy to create, access, update, and delete * options. All the data is stored in the wp_options table under a given custom * name. This page contains the technical documentation needed to use the * Options API. A list of default options can be found in the Option Reference. * * Note that the _site_ methods are essentially the same as their * counterparts. The only differences occur for WP Multisite, when the options * apply network-wide and the data is stored in the wp_sitemeta table under the * given custom name. * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner * @see https://codex.wordpress.org/Option_Reference * @see https://codex.wordpress.org/Options_API */ class SucuriScanOption extends SucuriScanRequest { /** * Default values for all the plugin's options. * * @return array Default values for all the plugin's options. */ private static function getDefaultOptionValues() { $defaults = array( 'sucuriscan_account' => '', 'sucuriscan_addr_header' => 'HTTP_X_SUCURI_CLIENTIP', 'sucuriscan_api_key' => false, 'sucuriscan_api_protocol' => 'https', 'sucuriscan_api_service' => 'disabled', 'sucuriscan_auto_clear_cache' => 'disabled', 'sucuriscan_checksum_api' => '', 'sucuriscan_cloudproxy_apikey' => '', 'sucuriscan_diff_utility' => 'disabled', 'sucuriscan_dns_lookups' => 'enabled', 'sucuriscan_email_subject' => '', 'sucuriscan_emails_per_hour' => 5, 'sucuriscan_emails_sent' => 0, 'sucuriscan_ignored_events' => '', 'sucuriscan_last_email_at' => time(), 'sucuriscan_lastlogin_redirection' => 'enabled', 'sucuriscan_maximum_failed_logins' => 30, 'sucuriscan_notify_available_updates' => 'disabled', 'sucuriscan_notify_bruteforce_attack' => 'disabled', 'sucuriscan_notify_failed_login' => 'disabled', 'sucuriscan_notify_plugin_activated' => 'enabled', 'sucuriscan_notify_plugin_change' => 'enabled', 'sucuriscan_notify_plugin_deactivated' => 'disabled', 'sucuriscan_notify_plugin_deleted' => 'disabled', 'sucuriscan_notify_plugin_installed' => 'disabled', 'sucuriscan_notify_plugin_updated' => 'disabled', 'sucuriscan_notify_post_publication' => 'enabled', 'sucuriscan_notify_scan_checksums' => 'disabled', 'sucuriscan_notify_settings_updated' => 'enabled', 'sucuriscan_notify_success_login' => 'disabled', 'sucuriscan_notify_theme_activated' => 'enabled', 'sucuriscan_notify_theme_deleted' => 'disabled', 'sucuriscan_notify_theme_editor' => 'enabled', 'sucuriscan_notify_theme_installed' => 'disabled', 'sucuriscan_notify_theme_updated' => 'disabled', 'sucuriscan_notify_to' => '', 'sucuriscan_notify_user_registration' => 'disabled', 'sucuriscan_notify_website_updated' => 'disabled', 'sucuriscan_notify_widget_added' => 'disabled', 'sucuriscan_notify_widget_deleted' => 'disabled', 'sucuriscan_plugin_version' => '0.0', 'sucuriscan_prettify_mails' => 'disabled', 'sucuriscan_revproxy' => 'disabled', 'sucuriscan_runtime' => 0, 'sucuriscan_selfhosting_fpath' => '', 'sucuriscan_selfhosting_monitor' => 'disabled', 'sucuriscan_site_version' => '0.0', 'sucuriscan_sitecheck_target' => '', 'sucuriscan_timezone' => 'UTC+00.00', 'sucuriscan_use_wpmail' => 'enabled', 'sucuriscan_headers_cache_control' => 'disabled', 'sucuriscan_headers_cache_control_options' => array( 'front_page' => array( 'id' => 'front_page', 'title' => __('Front Page', 'sucuri-scanner'), 'max_age' => 21600, 's_maxage' => 0, 'stale_if_error' => 0, 'stale_while_revalidate' => 0, 'pagination_factor' => 'unavailable', 'old_age_multiplier' => 'unavailable', ), 'posts' => array( 'id' => 'posts', 'title' => __('Posts', 'sucuri-scanner'), 'max_age' => 43200, 's_maxage' => 0, 'stale_if_error' => 0, 'stale_while_revalidate' => 0, 'pagination_factor' => 'unavailable', 'old_age_multiplier' => true, ), 'pages' => array( 'id' => 'pages', 'title' => __('Pages', 'sucuri-scanner'), 'max_age' => 86400, 's_maxage' => 0, 'stale_if_error' => 0, 'stale_while_revalidate' => 0, 'pagination_factor' => 'unavailable', 'old_age_multiplier' => 'unavailable', ), 'main_index' => array( 'id' => 'main_index', 'title' => __('Main Index', 'sucuri-scanner'), 'max_age' => 21600, 's_maxage' => 0, 'stale_if_error' => 0, 'stale_while_revalidate' => 0, 'pagination_factor' => 5, 'old_age_multiplier' => 'unavailable', ), 'categories' => array( 'id' => 'categories', 'title' => __('Categories', 'sucuri-scanner'), 'max_age' => 86400, 's_maxage' => 0, 'stale_if_error' => 0, 'stale_while_revalidate' => 0, 'pagination_factor' => 8, 'old_age_multiplier' => 'unavailable', ), 'tags' => array( 'id' => 'tags', 'title' => __('Tags', 'sucuri-scanner'), 'max_age' => 86400, 's_maxage' => 0, 'stale_if_error' => 0, 'stale_while_revalidate' => 0, 'pagination_factor' => 10, 'old_age_multiplier' => 'unavailable', ), 'authors' => array( 'id' => 'authors', 'title' => __('Authors', 'sucuri-scanner'), 'max_age' => 86400, 's_maxage' => 0, 'stale_if_error' => 0, 'stale_while_revalidate' => 0, 'pagination_factor' => 10, 'old_age_multiplier' => 'unavailable', ), 'archives' => array( 'id' => 'archives', 'title' => __('Archives', 'sucuri-scanner'), 'max_age' => 86400, 's_maxage' => 0, 'stale_if_error' => 0, 'stale_while_revalidate' => 0, 'pagination_factor' => 'unavailable', 'old_age_multiplier' => 'unavailable', ), 'feeds' => array( 'id' => 'feeds', 'title' => __('Feeds', 'sucuri-scanner'), 'max_age' => 21600, 's_maxage' => 0, 'stale_if_error' => 0, 'stale_while_revalidate' => 0, 'pagination_factor' => 'unavailable', 'old_age_multiplier' => 'unavailable', ), 'attachment_pages' => array( 'id' => 'attachment_pages', 'title' => __('Attachment Pages', 'sucuri-scanner'), 'max_age' => 86400, 's_maxage' => 0, 'stale_if_error' => 0, 'stale_while_revalidate' => 0, 'pagination_factor' => 'unavailable', 'old_age_multiplier' => 'unavailable', ), 'search_results' => array( 'id' => 'search_results', 'title' => __('Search Results', 'sucuri-scanner'), 'max_age' => 86400, 's_maxage' => 0, 'stale_if_error' => 0, 'stale_while_revalidate' => 0, 'pagination_factor' => 'unavailable', 'old_age_multiplier' => 'unavailable', ), '404_not_found' => array( 'id' => '404_not_found', 'title' => __('404 Not Found', 'sucuri-scanner'), 'max_age' => 86400, 's_maxage' => 0, 'stale_if_error' => 0, 'stale_while_revalidate' => 0, 'pagination_factor' => 'unavailable', 'old_age_multiplier' => 'unavailable', ), 'redirects' => array( 'id' => 'attachment', 'title' => __('Redirects', 'sucuri-scanner'), 'max_age' => 86400, 's_maxage' => 0, 'stale_if_error' => 0, 'stale_while_revalidate' => 0, 'pagination_factor' => 'unavailable', 'old_age_multiplier' => 'unavailable', ), 'woocommerce_products' => array( 'id' => 'woocommerce_products', 'title' => __('Woocommerce Products', 'sucuri-scanner'), 'max_age' => 86400, 's_maxage' => 0, 'stale_if_error' => 0, 'stale_while_revalidate' => 0, 'pagination_factor' => 'unavailable', 'old_age_multiplier' => 'unavailable', ), 'woocommerce_categories' => array( 'id' => 'woocommerce_categories', 'title' => __('Woocommerce Categories', 'sucuri-scanner'), 'max_age' => 86400, 's_maxage' => 0, 'stale_if_error' => 0, 'stale_while_revalidate' => 0, 'pagination_factor' => 'unavailable', 'old_age_multiplier' => 'unavailable', ), ) ); return (array)apply_filters('sucuriscan_option_defaults', $defaults); } /** * Name of all valid plugin's options. * * @return array Name of all valid plugin's options. */ public static function getDefaultOptionNames() { $options = self::getDefaultOptionValues(); $names = array_keys($options); return $names; } /** * Retrieve the default values for some specific options. * * @param string $option List of options, or single option name. * @return mixed The default values for the specified options. */ private static function getDefaultOptions($option = '') { $default = self::getDefaultOptionValues(); // Use framework built-in function. if (function_exists('get_option')) { $admin_email = get_option('admin_email'); $default['sucuriscan_account'] = $admin_email; $default['sucuriscan_notify_to'] = $admin_email; $default['sucuriscan_email_subject'] = sprintf(__('Sucuri Alert, %s, %s, %s', 'sucuri-scanner'), ':domain', ':event', ':remoteaddr'); } return @$default[$option]; } /** * Returns path of the options storage. * * Returns the absolute path of the file that will store the options * associated to the plugin. This must be a PHP file without public access, * for which reason it will contain a header with an exit point to prevent * malicious people to read the its content. The rest of the file will * content a JSON encoded array. * * @return string File path of the options storage. */ public static function optionsFilePath() { return self::dataStorePath('sucuri-settings.php'); } /** * Returns an array with all the plugin options. * * NOTE: There is a maximum number of lines for this file, one is for the * exit point and the other one is for a single line JSON encoded string. * We will discard any other content that exceeds this limit. * * @return array Array with all the plugin options. */ public static function getAllOptions() { $options = wp_cache_get('alloptions', SUCURISCAN); if ($options && is_array($options)) { return $options; } $options = array(); $fpath = self::optionsFilePath(); /* Use this over SucuriScanCache to prevent nested method calls */ $content = SucuriScanFileInfo::fileContent($fpath); if ($content !== false) { // Refer to self::optionsFilePath to know why the number two. $lines = explode("\n", $content, 2); if (count($lines) >= 2) { $jsonData = json_decode($lines[1], true); if (is_array($jsonData) && !empty($jsonData)) { $options = $jsonData; } } } wp_cache_set('alloptions', $options, SUCURISCAN); return $options; } /** * Write new options into the external options file. * * @param array $options Array with plugins options. * @return bool True if the new options were saved, false otherwise. */ public static function writeNewOptions($options = array()) { wp_cache_delete('alloptions', SUCURISCAN); $fpath = self::optionsFilePath(); $content = "\n"; $content .= @json_encode($options) . "\n"; return (bool)@file_put_contents($fpath, $content); } /** * Returns data from the settings file or the database. * * To facilitate the development, you can prefix the name of the key in the * request (when accessing it) with a single colon, this method will automa- * tically replace that character with the unique identifier of the plugin. * * NOTE: The SucuriScanCache library is a better interface to read the * content of a configuration file following the same standard in the other * files associated to the plugin. However, this library makes use of this * method to retrieve the directory where the files are stored, if we use * this library for this specific task we will end up provoking a maximum * nesting method call warning. * * @see https://developer.wordpress.org/reference/functions/get_option/ * * @param string $option Name of the option. * @return mixed Value associated to the option. */ public static function getOption($option = '') { $options = self::getAllOptions(); $option = self::varPrefix($option); if (array_key_exists($option, $options)) { return $options[$option]; } /** * Fallback to the default values. * * If the option is not set in the external options file then we must * search in the database for older data, this to provide backward * compatibility with older installations of the plugin. If the option * is found in the database we must insert it in the external file and * delete it from the database before the value is returned to the user. * * If the option is not in the external file nor in the database, and * the name starts with the same prefix used by the plugin then we must * return the default value defined by the author. * * Note that if the plain text file is not writable the method should * not delete the option from the database to keep backward compatibility * with previous installations of the plugin. */ if (function_exists('get_option')) { $value = get_option($option); if ($value !== false) { if (strpos($option, SUCURISCAN . '_') === 0) { $written = self::updateOption($option, $value); if ($written === true) { delete_option($option); } } return $value; } } /** * Cache default value to stop querying the database. * * The option was not found in the database either, we will return the * data from the array of default values hardcoded in the source code, * then will attempt to write the default value into the flat settings * file to stop querying the database in subsequent requests. */ if (strpos($option, SUCURISCAN . '_') === 0) { $value = self::getDefaultOptions($option); self::updateOption($option, $value); return $value; } return false; } /** * Update the value of an database' option. * * Use the method to update a named option/value pair to the options database * table. The option name value is escaped with a special database method before * the insert SQL statement but not the option value, this value should always * be properly sanitized. * * @see https://developer.wordpress.org/reference/functions/update_option/ * * @param string $option Name of the option. * @param mixed $value New value for the option. * @return bool True if option has been updated, false otherwise. */ public static function updateOption($option = '', $value = '') { if (strpos($option, ':') === 0 || strpos($option, SUCURISCAN) === 0) { $options = self::getAllOptions(); $option = self::varPrefix($option); $options[$option] = $value; return self::writeNewOptions($options); } return update_option($option, $value); } /** * Remove an option from the database. * * A safe way of removing a named option/value pair from the options database table. * * @see https://developer.wordpress.org/reference/functions/delete_option/ * * @param string $option Name of the option to be deleted. * @return bool True if option is successfully deleted, false otherwise. */ public static function deleteOption($option = '') { if (strpos($option, ':') === 0 || strpos($option, SUCURISCAN) === 0) { $options = self::getAllOptions(); $option = self::varPrefix($option); // Create/Modify option's value. if (array_key_exists($option, $options)) { unset($options[$option]); return self::writeNewOptions($options); } } return delete_option($option); } /** * Check whether a setting is enabled or not. * * @param string $option Name of the option to be deleted. * @return bool True if the option is enabled, false otherwise. */ public static function isEnabled($option = '') { return (bool)(self::getOption($option) === 'enabled'); } /** * Check whether a setting is disabled or not. * * @param string $option Name of the option to be deleted. * @return bool True if the option is disabled, false otherwise. */ public static function isDisabled($option = '') { return (bool)(self::getOption($option) === 'disabled'); } /** * Retrieve all the options stored by Wordpress in the database. The options * containing the word "transient" are excluded from the results, this method * compatible with multisite instances. * * @return array All the options stored by Wordpress in the database. */ private static function getSiteOptions() { $settings = array(); if (array_key_exists('wpdb', $GLOBALS)) { $results = $GLOBALS['wpdb']->get_results( 'SELECT * FROM ' . $GLOBALS['wpdb']->options . ' WHERE opti' . 'on_name NOT LIKE "%_transient_%" ORDER BY option_id ASC' ); foreach ($results as $row) { $settings[$row->option_name] = $row->option_value; } } $external = self::getAllOptions(); foreach ($external as $option => $value) { $settings[$option] = $value; } return $settings; } /** * Check what Wordpress options were changed comparing the values in the database * with the values sent through a simple request using a GET or POST method. * * @param array $request The content of the global variable GET or POST considering SERVER[REQUEST_METHOD]. * @return array A list of all the options that were changes through this request. */ public static function whatOptionsWereChanged($request = array()) { $options_changed = array( 'original' => array(), 'changed' => array() ); $site_options = self::getSiteOptions(); foreach ($request as $req_name => $req_value) { if (array_key_exists($req_name, $site_options) && $site_options[$req_name] != $req_value ) { $options_changed['original'][$req_name] = $site_options[$req_name]; $options_changed['changed'][$req_name] = $req_value; } } return $options_changed; } /** * Check the nonce comming from any of the settings pages. * * @return bool True if the nonce is valid, false otherwise. */ public static function checkOptionsNonce() { // Create the option_page value if permalink submission. if (!isset($_POST['option_page']) && isset($_POST['permalink_structure'])) { $_POST['option_page'] = 'permalink'; } /* check if the option_page has an allowed value */ $option_page = SucuriScanRequest::post('option_page'); if (!$option_page) { return false; } $action = ''; $nonce = '_wpnonce'; switch ($option_page) { case 'general': /* no_break */ case 'writing': /* no_break */ case 'reading': /* no_break */ case 'discussion': /* no_break */ case 'media': /* no_break */ case 'options': /* no_break */ $action = $option_page . '-options'; break; case 'permalink': $action = 'update-permalink'; break; } /* check the nonce validity */ return (bool)( !empty($action) && isset($_REQUEST[$nonce]) && wp_verify_nonce($_REQUEST[$nonce], $action) ); } /** * Returns a list of post-types. * * The list of post-types includes objects such as Post and Page but also * the transitions between each post type, for example, if there are posts * of type Draft and they change to Trash, this function will include a new * post type called "from_draft_to_trash" and so on. * * @return array List of post-types with transitions. */ public static function getPostTypes() { $postTypes = get_post_types(); $transitions = array( 'new', 'publish', 'pending', 'draft', 'auto-draft', 'future', 'private', 'inherit', 'trash', ); /* include post-type transitions */ foreach ($transitions as $from) { foreach ($transitions as $to) { if ($from === $to) { continue; } $event = sprintf('from_%s_to_%s', $from, $to); if (!array_key_exists($event, $postTypes)) { $postTypes[$event] = $event; } } } /* include custom non-registered post-types */ $ignoredEvents = SucuriScanOption::getIgnoredEvents(); foreach ($ignoredEvents as $event => $time) { if (!array_key_exists($event, $postTypes)) { $postTypes[$event] = $event; } } return $postTypes; } /** * Check whether an event is being ignored to send alerts or not. * * @param string $event Unique post-type name. * @return bool Whether an event is being ignored or not. */ public static function isIgnoredEvent($event = '') { $event = strtolower($event); $ignored = self::getIgnoredEvents(); return array_key_exists($event, $ignored); } /** * Get a list of the post types ignored to receive email alerts when the * "new site content" hook is triggered. * * @return array List of ignored posts-types to send alerts. */ public static function getIgnoredEvents() { $post_types = self::getOption(':ignored_events'); if (is_string($post_types)) { $post_types = @json_decode($post_types, true); } return (array)$post_types; } /** * Retrieve a list of basic security keys and check whether their values were * randomized correctly. * * @return array Array with three keys: good, missing, bad. */ public static function getSecurityKeys() { $response = array( 'good' => array(), 'missing' => array(), 'bad' => array(), ); $key_names = array( 'AUTH_KEY', 'AUTH_SALT', 'LOGGED_IN_KEY', 'LOGGED_IN_SALT', 'NONCE_KEY', 'NONCE_SALT', 'SECURE_AUTH_KEY', 'SECURE_AUTH_SALT', ); foreach ($key_names as $key_name) { if (defined($key_name)) { $key_value = constant($key_name); if (stripos($key_value, 'unique phrase') !== false) { $response['bad'][$key_name] = $key_value; } else { $response['good'][$key_name] = $key_value; } } else { $response['missing'][$key_name] = false; } } return $response; } /** * Change the reverse proxy setting. * * When enabled this option forces the plugin to override the value of the * global IP address variable from the HTTP header selected by the user from * the settings. Note that this may also be automatically enabled when the * firewall page is activated as it assumes that the proxy is creating a * custom HTTP header for the real IP. * * @param string $action Enable or disable the reverse proxy. * @param bool $silent Hide admin notices on success. * @return void */ public static function setRevProxy($action = 'disable', $silent = false) { if ($action !== 'enable' && $action !== 'disable') { return self::deleteOption(':revproxy'); } $action_d = $action . 'd'; $message = 'Reverse proxy support was ' . $action_d . ''; self::updateOption(':revproxy', $action_d); SucuriScanEvent::reportInfoEvent($message); SucuriScanEvent::notifyEvent('plugin_change', $message); if ($silent) { return true; } return SucuriScanInterface::info( sprintf( 'Reverse proxy support was set to %s', $action_d /* either enabled or disabled */ ) ); } /** * Change the HTTP header to retrieve the real IP address. * * @param string $header Valid HTTP header name. * @param bool $silent Hide admin notices on success. * @return void */ public static function setAddrHeader($header = 'REMOTE_ADDR', $silent = false) { $header = strtoupper($header); $allowed = SucuriScan::allowedHttpHeaders(true); if (!array_key_exists($header, $allowed)) { return SucuriScanInterface::error('HTTP header is not allowed'); } $message = sprintf('HTTP header was set to %s', $header); self::updateOption(':addr_header', $header); SucuriScanEvent::reportInfoEvent($message); SucuriScanEvent::notifyEvent('plugin_change', $message); if ($silent) { return true; } return SucuriScanInterface::info( sprintf( 'HTTP header was set to %s', $header /* one of the allowed HTTP headers */ ) ); } } src/pagehandler.php000060400000022002147177152050010317 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Renders the content of the plugin's dashboard page. * * @return void */ function sucuriscan_page() { $params = array(); SucuriScanInterface::startupChecks(); /* load data for the Integrity section */ $params['Integrity'] = SucuriScanIntegrity::pageIntegrity(); /* load data for the AuditLogs section */ $params['AuditLogs'] = SucuriScanAuditLogs::pageAuditLogs(); /* load data for the SiteCheck section */ $params['SiteCheck.Refresh'] = 'false'; $params['SiteCheck.iFramesTitle'] = __('iFrames', 'sucuri-scanner'); $params['SiteCheck.LinksTitle'] = __('Links', 'sucuri-scanner'); $params['SiteCheck.ScriptsTitle'] = __('Scripts', 'sucuri-scanner'); $params['SiteCheck.iFramesContent'] = __('Loading...', 'sucuri-scanner'); $params['SiteCheck.LinksContent'] = __('Loading...', 'sucuri-scanner'); $params['SiteCheck.ScriptsContent'] = __('Loading...', 'sucuri-scanner'); $params['SiteCheck.Malware'] = '
    '; $params['SiteCheck.Blocklist'] = '
    '; $params['SiteCheck.Recommendations'] = '
    '; /* load data for the WordPress best practices section */ $params['WordPress.Recommendations'] = SucuriWordPressRecommendations::pageWordPressRecommendations(); if (SucuriScanRequest::get(':sitecheck_refresh') !== false) { $params['SiteCheck.Refresh'] = 'true'; } echo SucuriScanTemplate::getTemplate('dashboard', $params); } /** * Renders the content of the plugin's firewall page. * * @return void */ function sucuriscan_firewall_page() { SucuriScanInterface::startupChecks(); $params = array( 'Firewall.Settings' => SucuriScanFirewall::settingsPage(), 'Firewall.AuditLogs' => SucuriScanFirewall::auditlogsPage(), 'Firewall.IPAccess' => SucuriScanFirewall::ipAccessPage(), 'Firewall.ClearCache' => SucuriScanFirewall::clearCachePage(), ); echo SucuriScanTemplate::getTemplate('firewall', $params); } /** * Renders the content of the plugin's last logins page. * * @return void */ function sucuriscan_lastlogins_page() { SucuriScanInterface::startupChecks(); // Reset the file with the last-logins logs. if (SucuriScanInterface::checkNonce() && SucuriScanRequest::post(':reset_lastlogins') !== false ) { $file_path = sucuriscan_lastlogins_datastore_filepath(); if (@unlink($file_path)) { sucuriscan_lastlogins_datastore_exists(); SucuriScanInterface::info(__('Last-Logins logs were successfully reset.', 'sucuri-scanner')); } else { SucuriScanInterface::error(__('Could not reset the last-logins data file.', 'sucuri-scanner')); } } // Page pseudo-variables initialization. $params = array( 'LastLogins.AllUsers' => sucuriscan_lastlogins_all(), 'LastLogins.Admins' => sucuriscan_lastlogins_admins(), 'LoggedInUsers' => sucuriscan_loggedin_users_panel(), 'FailedLogins' => sucuriscan_failed_logins_panel(), ); echo SucuriScanTemplate::getTemplate('lastlogins', $params); } /** * Renders the content of the plugin's settings page. * * @return void */ function sucuriscan_settings_page() { SucuriScanInterface::startupChecks(); $params = array(); $nonce = SucuriScanInterface::checkNonce(); // Keep the reset options panel and form submission processor before anything else. $params['Settings.General.ResetOptions'] = sucuriscan_settings_general_resetoptions($nonce); /* settings - general */ $params['Settings.General.DataStorage'] = sucuriscan_settings_general_datastorage($nonce); $params['Settings.General.SelfHosting'] = sucuriscan_settings_general_selfhosting($nonce); $params['Settings.General.ReverseProxy'] = sucuriscan_settings_general_reverseproxy($nonce); $params['Settings.General.ImportExport'] = sucuriscan_settings_general_importexport($nonce); $params['Settings.General.Timezone'] = sucuriscan_settings_general_timezone($nonce); $params['Settings.General.IPDiscoverer'] = sucuriscan_settings_general_ipdiscoverer($nonce); /* settings - scanner */ $params['Settings.Scanner.Cronjobs'] = SucuriScanSettingsScanner::cronjobs($nonce); $params['Settings.Scanner.IntegrityDiffUtility'] = SucuriScanSettingsIntegrity::diffUtility($nonce); $params['Settings.Scanner.IntegrityCache'] = SucuriScanSettingsIntegrity::cache($nonce); $params['Settings.Scanner.IgnoreFolders'] = SucuriScanSettingsScanner::ignoreFolders($nonce); /* settings - hardening */ $params['Settings.Hardening.Firewall'] = SucuriScanHardeningPage::firewall(); $params['Settings.Hardening.WPVersion'] = SucuriScanHardeningPage::wpversion(); $params['Settings.Hardening.RemoveGenerator'] = SucuriScanHardeningPage::wpgenerator(); $params['Settings.Hardening.NginxPHPFPM'] = SucuriScanHardeningPage::nginxphp(); $params['Settings.Hardening.WPUploads'] = SucuriScanHardeningPage::wpuploads(); $params['Settings.Hardening.WPContent'] = SucuriScanHardeningPage::wpcontent(); $params['Settings.Hardening.WPIncludes'] = SucuriScanHardeningPage::wpincludes(); $params['Settings.Hardening.Readme'] = SucuriScanHardeningPage::readme(); $params['Settings.Hardening.AdminUser'] = SucuriScanHardeningPage::adminuser(); $params['Settings.Hardening.FileEditor'] = SucuriScanHardeningPage::fileeditor(); $params['Settings.Hardening.SecKeyUpdater'] = SucuriScanHardeningPage::autoSecretKeyUpdater(); $params['Settings.Hardening.AllowlistPHPFiles'] = SucuriScanHardeningPage::AllowPHPFiles(); /* settings - posthack */ $params['Settings.Posthack.SecurityKeys'] = SucuriScanSettingsPosthack::securityKeys(); $params['Settings.Posthack.ResetPassword'] = SucuriScanSettingsPosthack::resetPassword(); $params['Settings.Posthack.ResetPlugins'] = SucuriScanSettingsPosthack::resetPlugins(); $params['Settings.Posthack.AvailableUpdates'] = SucuriScanSettingsPosthack::availableUpdates(); /* settings - alerts */ $params['Settings.Alerts.Recipients'] = sucuriscan_settings_alerts_recipients($nonce); $params['Settings.Alerts.Subject'] = sucuriscan_settings_alerts_subject($nonce); $params['Settings.Alerts.PerHour'] = sucuriscan_settings_alerts_perhour($nonce); $params['Settings.Alerts.BruteForce'] = sucuriscan_settings_alerts_bruteforce($nonce); $params['Settings.Alerts.Events'] = sucuriscan_settings_alerts_events($nonce); $params['Settings.Alerts.IgnorePosts'] = sucuriscan_settings_alerts_ignore_posts(); $params['Settings.Alerts.TrustedIPs'] = sucuriscan_settings_alerts_trustedips(); /* settings - cache options */ $params['Settings.Headers.Cache'] = sucuriscan_settings_cache_options($nonce); /* settings - api service */ $params['Settings.APIService.Status'] = sucuriscan_settings_apiservice_status($nonce); $params['Settings.APIService.Proxy'] = sucuriscan_settings_apiservice_proxy(); $params['Settings.SiteCheck.Target'] = SucuriScanSiteCheck::targetURLOption(); $params['Settings.APIService.Checksums'] = sucuriscan_settings_apiservice_checksums($nonce); /* settings - website info */ $params['Settings.Webinfo.Details'] = sucuriscan_settings_webinfo_details(); $params['Settings.Webinfo.HTAccess'] = sucuriscan_settings_webinfo_htaccess(); echo SucuriScanTemplate::getTemplate('settings', $params); } /** * Handles all the AJAX plugin's requests. * * @return void */ function sucuriscan_ajax() { SucuriScanInterface::checkPageVisibility(); if (SucuriScanInterface::checkNonce()) { SucuriScanAuditLogs::ajaxAuditLogs(); SucuriScanAuditLogs::ajaxAuditLogsSendLogs(); SucuriScanSiteCheck::ajaxMalwareScan(); SucuriScanIntegrity::ajaxIntegrity(); SucuriScanIntegrity::ajaxIntegrityDiffUtility(); SucuriScanFirewall::auditlogsAjax(); SucuriScanFirewall::ipAccessAjax(); SucuriScanFirewall::blocklistAjax(); SucuriScanFirewall::deblocklistAjax(); SucuriScanFirewall::getSettingsAjax(); SucuriScanFirewall::clearCacheAjax(); SucuriScanFirewall::clearAutoCacheAjax(); SucuriScanSettingsScanner::cronjobsAjax(); SucuriScanSettingsPosthack::availableUpdatesAjax(); SucuriScanSettingsPosthack::getPluginsAjax(); SucuriScanSettingsPosthack::resetPasswordAjax(); SucuriScanSettingsPosthack::resetPluginAjax(); } wp_send_json(array('ok' => false, 'error' => 'invalid ajax action'), 200); } src/request.lib.php000060400000010626147177152050010313 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * HTTP request handler. * * Function definitions to retrieve, validate, and clean the parameters during a * HTTP request, generally after a form submission or while loading a URL. Use * these methods at most instead of accessing an index in the global PHP * variables _POST, _GET, _REQUEST since they may come with insecure data. * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ class SucuriScanRequest extends SucuriScan { /** * Returns the value of the _GET, _POST or _REQUEST key. * * You can pass an additional parameter to execute a regular expression that * will return False if the value doesn't matches what the RegExp defined. * Very useful to filter user input besides form validations. * * @param array $list The array where the specified key will be searched. * @param string $key Name of the variable contained in _POST. * @param string $pattern Optional pattern to match allowed values. * @return array|string|bool Value from the global _GET or _POST variable. */ private static function request($list = array(), $key = '', $pattern = '') { $key = self::varPrefix((string) $key); if (!is_array($list) || !isset($list[$key])) { return false; } $key_value = $list[$key]; /* raw request parameter */ /* if the request data is an array, then only cast the value. */ if ($pattern === '_array' && is_array($key_value)) { return (array) $key_value; } /* match WordPress nonce */ if ($pattern === '_nonce') { $pattern = '[a-z0-9]{10}'; } /* match valid page identifier */ if ($pattern === '_page') { $pattern = '[a-z_]+'; } /* match every data format */ if ($pattern === '') { $pattern = '.*'; } /* check the format of the request data with a regex defined above. */ if (@preg_match('/^' . $pattern . '$/', $key_value)) { return self::escape($key_value); } return false; } /** * Returns the value stored in a specific index in the global _GET variable, * you can specify a pattern as the second argument to match allowed values. * * @param string $key Name of the variable contained in _GET. * @param string $pattern Optional pattern to match allowed values. * @return array|string Value from the global _GET variable. */ public static function get($key = '', $pattern = '') { return self::request($_GET, $key, $pattern); } /** * Returns the value stored in a specific index in the global _POST variable, * you can specify a pattern as the second argument to match allowed values. * * @param string $key Name of the variable contained in _POST. * @param string $pattern Optional pattern to match allowed values. * @return array|string Value from the global _POST variable. */ public static function post($key = '', $pattern = '') { return self::request($_POST, $key, $pattern); } /** * Returns the value stored in a specific index in the global _REQUEST variable, * you can specify a pattern as the second argument to match allowed values. * * @param string $key Name of the variable contained in _REQUEST. * @param string $pattern Optional pattern to match allowed values. * @return array|string Value from the global _REQUEST variable. */ public static function getOrPost($key = '', $pattern = '') { return self::request($_REQUEST, $key, $pattern); } } src/settings-alerts.php000060400000065675147177152050011224 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Returns the HTML to configure who receives the email alerts. * * By default the plugin sends the email notifications about the security events * to the first email address used during the installation of the website. This * is usually the email of the website owner. The plugin allows to add more * emails to the list so the alerts are sent to other people. * * @param bool $nonce True if the CSRF protection worked, false otherwise. * @return string HTML for the email alert recipients. */ function sucuriscan_settings_alerts_recipients($nonce) { $params = array(); $params['Alerts.Recipients'] = ''; $notify_to = SucuriScanOption::getOption(':notify_to'); $emails = array(); // If the recipient list is not empty, explode. if (is_string($notify_to)) { $emails = explode(',', $notify_to); } // Process form submission. if ($nonce) { // Add new email address to the alert recipient list. if (SucuriScanRequest::post(':save_recipient') !== false) { $new_email = SucuriScanRequest::post(':recipient'); if (SucuriScan::isValidEmail($new_email)) { $emails[] = $new_email; $message = sprintf(__('The email alerts will be sent to: %s', 'sucuri-scanner'), $new_email); SucuriScanOption::updateOption(':notify_to', implode(',', $emails)); SucuriScanEvent::reportInfoEvent(sprintf(__('The email alerts will be sent to: %s', 'sucuri-scanner'), $new_email)); SucuriScanEvent::notifyEvent('plugin_change', $message); SucuriScanInterface::info($message); } else { SucuriScanInterface::error(__('Email format not supported.', 'sucuri-scanner')); } } // Delete one or more recipients from the list. if (SucuriScanRequest::post(':delete_recipients') !== false) { $deleted_emails = array(); $recipients = SucuriScanRequest::post(':recipients', '_array'); foreach ($recipients as $address) { if (in_array($address, $emails)) { $deleted_emails[] = $address; $index = array_search($address, $emails); unset($emails[$index]); } } if (!empty($deleted_emails)) { $deleted_emails_str = implode(",\x20", $deleted_emails); $message = sprintf(__('These emails will stop receiving alerts: %s', 'sucuri-scanner'), $deleted_emails_str); SucuriScanOption::updateOption(':notify_to', implode(',', $emails)); SucuriScanEvent::reportInfoEvent(sprintf(__('These emails will stop receiving alerts: %s', 'sucuri-scanner'), $deleted_emails_str)); SucuriScanEvent::notifyEvent('plugin_change', $message); SucuriScanInterface::info($message); } } // Debug ability of the plugin to send email alerts correctly. if (SucuriScanRequest::post(':debug_email')) { $recipients = SucuriScanOption::getOption(':notify_to'); $mailSentSuccess = SucuriScanMail::sendMail( $recipients, __('Test Email Alert', 'sucuri-scanner'), sprintf(__('Test email alert sent at %s', 'sucuri-scanner'), SucuriScan::datetime()), array('Force' => true) ); if ($mailSentSuccess) { SucuriScanInterface::info(__('A test alert was sent to your email, check your inbox', 'sucuri-scanner')); }else { SucuriScanInterface::error(__('An error occurred sending email - please check your server mail configuration.', 'sucuri-scanner')); } } } foreach ($emails as $email) { if (!empty($email)) { $params['Alerts.Recipients'] .= SucuriScanTemplate::getSnippet( 'settings-alerts-recipients', array('Recipient.Email' => $email) ); } } return SucuriScanTemplate::getSection('settings-alerts-recipients', $params); } /** * Returns the HTML to configure the list of trusted IPs. * * The plugin will not report security events coming from these IP addresses. If * the users are all from the same network, like in an office, they can include * the IP of the entire LAN as a valid CIDR format. * * @return string HTML for the trusted IP addresses. */ function sucuriscan_settings_alerts_trustedips() { $params = array(); $params['TrustedIPs.List'] = ''; $params['TrustedIPs.NoItems.Visibility'] = 'visible'; $cache = new SucuriScanCache('trustip'); if (SucuriScanInterface::checkNonce()) { // Trust and IP address to ignore alerts for a subnet. $trust_ip = SucuriScanRequest::post(':trust_ip'); if ($trust_ip) { if (SucuriScan::isValidIP($trust_ip) || SucuriScan::isValidCIDR($trust_ip)) { $ip_info = SucuriScan::getIPInfo($trust_ip); $cache_key = md5($ip_info['remote_addr']); $ip_info['added_at'] = time(); if ($cache->exists($cache_key)) { SucuriScanInterface::error(__('The IP specified address was already added.', 'sucuri-scanner')); } elseif ($cache->add($cache_key, $ip_info)) { SucuriScanEvent::reportWarningEvent(sprintf(__('IP has been trusted: %s', 'sucuri-scanner'), $trust_ip)); SucuriScanInterface::info(sprintf(__('Events generated from this IP will be ignored: %s', 'sucuri-scanner'), $trust_ip)); } else { SucuriScanInterface::error(__('The IP address could not be added to the trusted list', 'sucuri-scanner')); } } } // Trust and IP address to ignore alerts for a subnet. $del_trust_ip = SucuriScanRequest::post(':del_trust_ip', '_array'); if ($del_trust_ip) { foreach ($del_trust_ip as $cache_key) { $cache->delete($cache_key); } SucuriScanInterface::info(__('The selected IP addresses were successfully deleted.', 'sucuri-scanner')); } } $trusted_ips = $cache->getAll(); if ($trusted_ips) { foreach ($trusted_ips as $cache_key => $ip_info) { if ($ip_info->cidr_range == 32) { $ip_info->cidr_format = __('n/a', 'sucuri-scanner'); } $params['TrustedIPs.List'] .= SucuriScanTemplate::getSnippet( 'settings-alerts-trustedips', array( 'TrustIP.CacheKey' => $cache_key, 'TrustIP.RemoteAddr' => SucuriScan::escape($ip_info->remote_addr), 'TrustIP.CIDRFormat' => SucuriScan::escape($ip_info->cidr_format), 'TrustIP.AddedAt' => SucuriScan::datetime($ip_info->added_at), ) ); } $params['TrustedIPs.NoItems.Visibility'] = 'hidden'; } return SucuriScanTemplate::getSection('settings-alerts-trustedips', $params); } /** * Returns the HTML to configure the subject for the email alerts. * * @param bool $nonce True if the CSRF protection worked, false otherwise. * @return string HTML for the email alert subject option. */ function sucuriscan_settings_alerts_subject($nonce) { $params = array( 'Alerts.Subject' => '', 'Alerts.CustomChecked' => '', 'Alerts.CustomValue' => '', ); $subjects = array( sprintf(__('Sucuri Alert, %s, %s', 'sucuri-scanner'), ':domain', ':event'), sprintf(__('Sucuri Alert, %s, %s, %s', 'sucuri-scanner'), ':domain', ':event', ':remoteaddr'), sprintf(__('Sucuri Alert, %s, %s, %s', 'sucuri-scanner'), ':domain', ':event', ':username'), sprintf(__('Sucuri Alert, %s, %s, %s', 'sucuri-scanner'), ':domain', ':event', ':email'), sprintf(__('Sucuri Alert, %s, %s', 'sucuri-scanner'), ':event', ':remoteaddr'), sprintf(__('Sucuri Alert, %s, %s', 'sucuri-scanner'), ':event', ':hostname'), sprintf(__('Sucuri Alert, %s', 'sucuri-scanner'), ':event'), ); // Process form submission to change the alert settings. if ($nonce) { $email_subject = SucuriScanRequest::post(':email_subject'); if ($email_subject) { $current_value = SucuriScanOption::getOption(':email_subject'); $new_subject = false; /** * Validate the format of the email subject format. * * If the user chooses the option to build the subject of the email alerts * manually we will need to validate the characters. Otherwise we will need to * check if the pseudo-tags selected by the user are allowed and supported. */ if ($email_subject === 'custom') { $format_pattern = '/^[0-9a-zA-Z:,\s]+$/'; $custom_subject = SucuriScanRequest::post(':custom_email_subject'); if ($custom_subject !== false && !empty($custom_subject) && @preg_match($format_pattern, $custom_subject) ) { $new_subject = trim($custom_subject); } else { SucuriScanInterface::error(__('Invalid characters in the email subject.', 'sucuri-scanner')); } } elseif (is_array($subjects) && in_array($email_subject, $subjects)) { $new_subject = trim($email_subject); } // Proceed with the operation saving the new subject. if ($new_subject !== false && $current_value !== $new_subject) { $message = sprintf(__('Email subject set to %s', 'sucuri-scanner'), $new_subject); SucuriScanOption::updateOption(':email_subject', $new_subject); SucuriScanEvent::reportInfoEvent($message); SucuriScanEvent::notifyEvent('plugin_change', $message); SucuriScanInterface::info(__('The email subject has been successfully updated', 'sucuri-scanner')); } } } // Build the HTML code for the interface. if (is_array($subjects)) { $email_subject = SucuriScanOption::getOption(':email_subject'); $is_official_subject = false; foreach ($subjects as $subject_format) { if ($email_subject === $subject_format) { $is_official_subject = true; $checked = 'checked="checked"'; } else { $checked = ''; } $params['Alerts.Subject'] .= SucuriScanTemplate::getSnippet( 'settings-alerts-subject', array( 'EmailSubject.Name' => $subject_format, 'EmailSubject.Value' => $subject_format, 'EmailSubject.Checked' => $checked, ) ); } if ($is_official_subject === false) { $params['Alerts.CustomChecked'] = 'checked="checked"'; $params['Alerts.CustomValue'] = $email_subject; } } return SucuriScanTemplate::getSection('settings-alerts-subject', $params); } /** * Returns the HTML to configure the maximum number of alerts per hour. * * @param bool $nonce True if the CSRF protection worked, false otherwise. * @return string HTML for the maximum number of alerts per hour. */ function sucuriscan_settings_alerts_perhour($nonce) { $params = array(); $params['Alerts.PerHour'] = ''; $emails_per_hour = array( '5' => __('Maximum 5 per hour', 'sucuri-scanner'), '10' => __('Maximum 10 per hour', 'sucuri-scanner'), '20' => __('Maximum 20 per hour', 'sucuri-scanner'), '40' => __('Maximum 40 per hour', 'sucuri-scanner'), '80' => __('Maximum 80 per hour', 'sucuri-scanner'), '160' => __('Maximum 160 per hour', 'sucuri-scanner'), 'unlimited' => __('Unlimited alerts per hour', 'sucuri-scanner'), ); if ($nonce) { // Update the value for the maximum emails per hour. $per_hour = SucuriScanRequest::post(':emails_per_hour'); if ($per_hour) { if (array_key_exists($per_hour, $emails_per_hour)) { $per_hour_label = strtolower($emails_per_hour[$per_hour]); $message = sprintf(__('Maximum alerts per hour set to %s', 'sucuri-scanner'), $per_hour_label); SucuriScanOption::updateOption(':emails_per_hour', $per_hour); SucuriScanEvent::reportInfoEvent($message); SucuriScanEvent::notifyEvent('plugin_change', $message); SucuriScanInterface::info(__('The maximum number of alerts per hour has been updated', 'sucuri-scanner')); } else { SucuriScanInterface::error(__('Error updating the maximum number of alerts per hour', 'sucuri-scanner')); } } } $per_hour = (int) SucuriScanOption::getOption(':emails_per_hour'); $per_hour_options = SucuriScanTemplate::selectOptions($emails_per_hour, $per_hour); $params['Alerts.PerHour'] = $per_hour_options; return SucuriScanTemplate::getSection('settings-alerts-perhour', $params); } /** * Returns the HTML to configure the trigger for the brute-force alerts. * * @param bool $nonce True if the CSRF protection worked, false otherwise. * @return string HTML for the trigger for the brute-force alerts. */ function sucuriscan_settings_alerts_bruteforce($nonce) { $params = array(); $params['Alerts.BruteForce'] = ''; $max_failed_logins = array( '30' => __('30 failed logins per hour', 'sucuri-scanner'), '60' => __('60 failed logins per hour', 'sucuri-scanner'), '120' => __('120 failed logins per hour', 'sucuri-scanner'), '240' => __('240 failed logins per hour', 'sucuri-scanner'), '480' => __('480 failed logins per hour', 'sucuri-scanner'), ); if ($nonce) { // Update the maximum failed logins per hour before consider it a brute-force attack. $maximum = SucuriScanRequest::post(':maximum_failed_logins'); if ($maximum) { if (array_key_exists($maximum, $max_failed_logins)) { $message = sprintf(__('Consider brute-force attack after %s failed logins per hour', 'sucuri-scanner'), $maximum); SucuriScanOption::updateOption(':maximum_failed_logins', $maximum); SucuriScanEvent::reportInfoEvent($message); SucuriScanEvent::notifyEvent('plugin_change', $message); SucuriScanInterface::info(sprintf(__('The plugin will assume that your website is under a brute-force attack after %s failed logins are detected during the same hour', 'sucuri-scanner'), $maximum)); } else { SucuriScanInterface::error(__('Invalid number of failed logins per hour', 'sucuri-scanner')); } } } $maximum = (int) SucuriScanOption::getOption(':maximum_failed_logins'); $maximum_options = SucuriScanTemplate::selectOptions($max_failed_logins, $maximum); $params['Alerts.BruteForce'] = $maximum_options; return SucuriScanTemplate::getSection('settings-alerts-bruteforce', $params); } /** * Returns the HTML to configure which alerts will be sent. * * @param bool $nonce True if the CSRF protection worked, false otherwise. * @return string HTML for the alerts that will be sent. */ function sucuriscan_settings_alerts_events($nonce) { $params = array(); $params['Alerts.Events'] = ''; $params['Alerts.NoAlertsVisibility'] = 'hidden'; $notify_options = array( 'sucuriscan_notify_plugin_change' => 'setting:' . __('Receive email alerts for changes in the settings of the plugin', 'sucuri-scanner'), 'sucuriscan_prettify_mails' => 'setting:' . __('Receive email alerts in HTML (there may be issues with some mail services)', 'sucuri-scanner'), 'sucuriscan_use_wpmail' => 'setting:' . __('Use WordPress functions to send mails (uncheck to use native PHP functions)', 'sucuri-scanner'), 'sucuriscan_lastlogin_redirection' => 'setting:' . __('Allow redirection after login to report the last-login information', 'sucuri-scanner'), 'sucuriscan_notify_scan_checksums' => 'setting:' . __('Receive email alerts for core integrity checks', 'sucuri-scanner'), 'sucuriscan_notify_available_updates' => 'setting:' . __('Receive email alerts for available updates', 'sucuri-scanner'), 'sucuriscan_notify_user_registration' => 'user:' . __('Receive email alerts for new user registration', 'sucuri-scanner'), 'sucuriscan_notify_success_login' => 'user:' . __('Receive email alerts for successful login attempts', 'sucuri-scanner'), 'sucuriscan_notify_failed_login' => 'user:' . __('Receive email alerts for failed login attempts (you may receive tons of emails)', 'sucuri-scanner'), 'sucuriscan_notify_bruteforce_attack' => 'user:' . __('Receive email alerts for password guessing attacks (summary of failed logins per hour)', 'sucuri-scanner'), 'sucuriscan_notify_post_publication' => 'setting:' . __('Receive email alerts for changes in the post status (configure from Ignore Posts Changes)', 'sucuri-scanner'), 'sucuriscan_notify_website_updated' => 'setting:' . __('Receive email alerts when the WordPress version is updated', 'sucuri-scanner'), 'sucuriscan_notify_settings_updated' => 'setting:' . __('Receive email alerts when your website settings are updated', 'sucuri-scanner'), 'sucuriscan_notify_theme_editor' => 'setting:' . __('Receive email alerts when a file is modified with theme/plugin editor', 'sucuri-scanner'), 'sucuriscan_notify_plugin_installed' => 'plugin:' . __('Receive email alerts when a plugin is installed', 'sucuri-scanner'), 'sucuriscan_notify_plugin_activated' => 'plugin:' . __('Receive email alerts when a plugin is activated', 'sucuri-scanner'), 'sucuriscan_notify_plugin_deactivated' => 'plugin:' . __('Receive email alerts when a plugin is deactivated', 'sucuri-scanner'), 'sucuriscan_notify_plugin_updated' => 'plugin:' . __('Receive email alerts when a plugin is updated', 'sucuri-scanner'), 'sucuriscan_notify_plugin_deleted' => 'plugin:' . __('Receive email alerts when a plugin is deleted', 'sucuri-scanner'), 'sucuriscan_notify_widget_added' => 'widget:' . __('Receive email alerts when a widget is added to a sidebar', 'sucuri-scanner'), 'sucuriscan_notify_widget_deleted' => 'widget:' . __('Receive email alerts when a widget is deleted from a sidebar', 'sucuri-scanner'), 'sucuriscan_notify_theme_installed' => 'theme:' . __('Receive email alerts when a theme is installed', 'sucuri-scanner'), 'sucuriscan_notify_theme_activated' => 'theme:' . __('Receive email alerts when a theme is activated', 'sucuri-scanner'), 'sucuriscan_notify_theme_updated' => 'theme:' . __('Receive email alerts when a theme is updated', 'sucuri-scanner'), 'sucuriscan_notify_theme_deleted' => 'theme:' . __('Receive email alerts when a theme is deleted', 'sucuri-scanner'), ); /** * Hide successful and failed logins option. * * Due to an incompatibility with the Postman-SMTP plugin we cannot sent * email alerts when a successful or failed user authentication happens, the * result is an infinite loop while our plugin tries to notify about changes * in the posts and the other plugin creates temporary post objects to track * the emails. * * @date 30 June, 2017 * @see https://wordpress.org/plugins/postman-smtp/ * @see https://wordpress.org/support/topic/unable-to-access-wordpress-dashboard-after-update-to-1-8-7/ */ if (is_plugin_active('postman-smtp/postman-smtp.php')) { $params['Alerts.NoAlertsVisibility'] = 'visible'; unset($notify_options['sucuriscan_notify_success_login']); unset($notify_options['sucuriscan_notify_failed_login']); } // Process form submission to change the alert settings. if ($nonce) { // Update the notification settings. if (SucuriScanRequest::post(':save_alert_events') !== false) { $ucounter = 0; foreach ($notify_options as $alert_type => $alert_label) { $option_value = SucuriScanRequest::post($alert_type, '(1|0)'); if ($option_value !== false) { $current_value = SucuriScanOption::getOption($alert_type); $option_value = ($option_value == 1) ? 'enabled' : 'disabled'; // Check that the option value was actually changed. if ($current_value !== $option_value) { $written = SucuriScanOption::updateOption($alert_type, $option_value); $ucounter += ($written === true) ? 1 : 0; } } } if ($ucounter > 0) { $message = sprintf(__('A total of %s alert events were changed', 'sucuri-scanner'), $ucounter ); SucuriScanEvent::reportInfoEvent($message); SucuriScanEvent::notifyEvent('plugin_change', $message); SucuriScanInterface::info(__('The alert settings have been updated', 'sucuri-scanner')); } } } /* build the HTML code for the checkbox input fields */ foreach ($notify_options as $alert_type => $alert_label) { $alert_value = SucuriScanOption::getOption($alert_type); $checked = ($alert_value == 'enabled') ? 'checked="checked"' : ''; $alert_icon = ''; /* identify the optional icon */ $offset = strpos($alert_label, ':'); $alert_group = substr($alert_label, 0, $offset); $alert_label = substr($alert_label, $offset + 1); switch ($alert_group) { case 'user': $alert_icon = 'dashicons-before dashicons-admin-users'; break; case 'plugin': $alert_icon = 'dashicons-before dashicons-admin-plugins'; break; case 'theme': $alert_icon = 'dashicons-before dashicons-admin-appearance'; break; case 'setting': $alert_icon = 'dashicons-before dashicons-admin-tools'; break; case 'widget': $alert_icon = 'dashicons-before dashicons-admin-post'; break; } $params['Alerts.Events'] .= SucuriScanTemplate::getSnippet( 'settings-alerts-events', array( 'Event.Name' => $alert_type, 'Event.Checked' => $checked, 'Event.Label' => $alert_label, 'Event.LabelIcon' => $alert_icon, ) ); } return SucuriScanTemplate::getSection('settings-alerts-events', $params); } /** * Returns the HTML to configure the post-types that will be ignored. * * @return string HTML for the ignored post-types. */ function sucuriscan_settings_alerts_ignore_posts() { $params = array(); $post_types = SucuriScanOption::getPostTypes(); $ignored_events = SucuriScanOption::getIgnoredEvents(); $params['PostTypes.List'] = ''; $params['PostTypes.ErrorVisibility'] = 'hidden'; if (SucuriScanInterface::checkNonce()) { // Ignore a new event for email alerts. $action = SucuriScanRequest::post(':ignorerule_action'); $ignore_rule = SucuriScanRequest::post(':ignorerule'); $selected = SucuriScanRequest::post(':posttypes', '_array'); if ($action === 'add') { if (!preg_match('/^[a-z0-9_\-]{1,20}+$/', $ignore_rule)) { SucuriScanInterface::error(__('Only lowercase letters, numbers, underscores and hyphens are allowed. Post Types cannot exceed 20 characters as well.', 'sucuri-scanner')); } elseif (array_key_exists($ignore_rule, $ignored_events)) { SucuriScanInterface::error(__('The post-type is already being ignored (duplicate).', 'sucuri-scanner')); } else { $ignored_events[$ignore_rule] = time(); SucuriScanInterface::info(__('Post-type has been successfully ignored.', 'sucuri-scanner')); SucuriScanOption::updateOption(':ignored_events', $ignored_events); SucuriScanEvent::reportWarningEvent(sprintf(__('Changes in %s post-type will be ignored', 'sucuri-scanner'), $ignore_rule)); } } if ($action === 'batch') { /* reset current data to start all over again */ $ignored_events = array(); $timestamp = time(); foreach ($post_types as $post_type) { if (is_array($selected) && !in_array($post_type, $selected)) { $ignored_events[$post_type] = $timestamp; } } SucuriScanInterface::info(__('List of monitored post-types has been updated.', 'sucuri-scanner')); SucuriScanOption::updateOption(':ignored_events', $ignored_events); SucuriScanEvent::reportWarningEvent(__('List of monitored post-types has been updated', 'sucuri-scanner')); } } /* notifications are post updates are disabled; print error */ if (SucuriScanOption::isDisabled(':notify_post_publication')) { $params['PostTypes.ErrorVisibility'] = 'visible'; $params['PostTypes.List'] = sprintf('%s', __('no data available', 'sucuri-scanner')); return SucuriScanTemplate::getSection('settings-alerts-ignore-posts', $params); } /* Check which post-types are being ignored */ foreach ($post_types as $post_type) { $was_ignored_at = '--'; $selected = 'checked="checked"'; $post_type_title = ucwords(str_replace('_', "\x20", $post_type)); if (array_key_exists($post_type, $ignored_events)) { $was_ignored_at = SucuriScan::datetime($ignored_events[$post_type]); $selected = ''; /* uncheck the HTML checkbox */ } $params['PostTypes.List'] .= SucuriScanTemplate::getSnippet( 'settings-alerts-ignore-posts', array( 'PostTypes.Selected' => $selected, 'PostTypes.UniqueID' => $post_type, 'PostTypes.Title' => $post_type_title, 'PostTypes.IgnoredAt' => $was_ignored_at, ) ); } return SucuriScanTemplate::getSection('settings-alerts-ignore-posts', $params); } src/settings-apiservice.php000060400000014613147177152050012046 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Returns the HTML to configure the API service status. * * @param bool $nonce True if the CSRF protection worked, false otherwise. * @return string HTML for the API service status option. */ function sucuriscan_settings_apiservice_status($nonce) { $api_url_is_set = SucuriScan::issetScanApiUrl(); $params = array(); if ($nonce) { // Enable or disable the API service communication. $api_service = SucuriScanRequest::post(':api_service', '(en|dis)able'); if ($api_service) { if (!$api_url_is_set) { SucuriScanInterface::error(__('The status of the API service could not be enabled because the required SUCURISCAN_API_URL configuration was not found.', 'sucuri-scanner')); } else { $action_d = $api_service . 'd'; $message = sprintf(__('API service communication was %s', 'sucuri-scanner'), $action_d); SucuriScanEvent::reportInfoEvent($message); SucuriScanEvent::notifyEvent('plugin_change', $message); SucuriScanOption::updateOption(':api_service', $action_d); SucuriScanInterface::info(__('The status of the API service has been changed', 'sucuri-scanner')); } } } $api_service_option = SucuriScanOption::getOption(':api_service'); if ($api_service_option === 'enabled') { $params['ApiStatus.StatusNum'] = '1'; $params['ApiStatus.Status'] = __('Enabled', 'sucuri-scanner'); $params['ApiStatus.SwitchText'] = __('Disable', 'sucuri-scanner'); $params['ApiStatus.SwitchValue'] = 'disable'; $params['ApiStatus.WarningVisibility'] = 'visible'; $params['ApiStatus.ErrorVisibility'] = 'hidden'; } if ($api_service_option === 'disabled' || !$api_url_is_set) { $params['ApiStatus.StatusNum'] = '2'; $params['ApiStatus.Status'] = __('Disabled', 'sucuri-scanner'); $params['ApiStatus.SwitchText'] = __('Enable', 'sucuri-scanner'); $params['ApiStatus.SwitchValue'] = 'enable'; $params['ApiStatus.WarningVisibility'] = 'hidden'; $params['ApiStatus.ErrorVisibility'] = 'visible'; } if ($api_service_option === 'disabled' && $api_url_is_set) { $params['ApiStatus.StatusNum'] = '0'; } $params['ApiStatus.ServiceURL'] = !$api_url_is_set ? __('Service API URL not set. To enable the API service, add your custom API service URL as the SUCURISCAN_API_URL constant value to the main configuration file (wp-config.php). If you do not have a custom API to store the audit logs, the plugin will still store these logs on your hosting environment.') : __('Service API URL: '). SUCURISCAN_API_URL; $api_key = SucuriScanAPI::getPluginKey(); $params['ApiStatus.ApiKey'] = $api_key ? $api_key : __('NONE', 'sucuri-scanner'); return SucuriScanTemplate::getSection('settings-apiservice-status', $params); } /** * Returns the HTML to configure the API service proxy. * * @return string HTML for the API service proxy option. */ function sucuriscan_settings_apiservice_proxy() { $params = array( 'APIProxy.Host' => 'no_proxy_host', 'APIProxy.Port' => 'no_proxy_port', 'APIProxy.Username' => 'no_proxy_username', 'APIProxy.Password' => 'no_proxy_password', 'APIProxy.PasswordType' => 'default', 'APIProxy.PasswordText' => 'empty', ); if (class_exists('WP_HTTP_Proxy')) { $wp_http_proxy = new WP_HTTP_Proxy(); if ($wp_http_proxy->is_enabled()) { $proxy_host = SucuriScan::escape($wp_http_proxy->host()); $proxy_port = SucuriScan::escape($wp_http_proxy->port()); $proxy_username = SucuriScan::escape($wp_http_proxy->username()); $proxy_password = SucuriScan::escape($wp_http_proxy->password()); $params['APIProxy.Host'] = $proxy_host; $params['APIProxy.Port'] = $proxy_port; $params['APIProxy.Username'] = $proxy_username; $params['APIProxy.Password'] = $proxy_password; $params['APIProxy.PasswordType'] = 'info'; $params['APIProxy.PasswordText'] = 'hidden'; } } return SucuriScanTemplate::getSection('settings-apiservice-proxy', $params); } /** * Returns the HTML to configure the URL for the checkums API. * * @param bool $nonce True if the CSRF protection worked, false otherwise. * @return string HTML for the URL for the checksums API service. */ function sucuriscan_settings_apiservice_checksums($nonce) { $params = array(); $url = SucuriScanRequest::post(':checksum_api'); if ($nonce && $url !== false) { /* https://github.com/WordPress/WordPress - OR - WordPress/WordPress */ $pattern = '/^(https:\/\/github\.com\/)?([0-9a-zA-Z_]+\/[0-9a-zA-Z_]+)/'; if (@preg_match($pattern, $url, $match)) { SucuriScanOption::updateOption(':checksum_api', $match[2]); $message = sprintf(__('Core integrity API changed: %s', 'sucuri-scanner'), SucuriScanAPI::checksumAPI()); SucuriScanEvent::reportInfoEvent($message); SucuriScanEvent::notifyEvent('plugin_change', $message); SucuriScanInterface::info(__('The URL to retrieve the WordPress checksums has been changed', 'sucuri-scanner')); } else { SucuriScanOption::deleteOption(':checksum_api'); $message = sprintf(__('Core integrity API changed: %s', 'sucuri-scanner'), SucuriScanAPI::checksumAPI()); SucuriScanEvent::reportInfoEvent($message); SucuriScanEvent::notifyEvent('plugin_change', $message); SucuriScanInterface::info(__('The URL to retrieve the WordPress checksums has been changed', 'sucuri-scanner')); } } $params['ChecksumsAPI'] = SucuriScanAPI::checksumAPI(); return SucuriScanTemplate::getSection('settings-apiservice-checksums', $params); } src/settings-general.php000060400000055225147177152050011335 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Renders a page with information about the reset options feature. * * @param bool $nonce True if the CSRF protection worked. * @return string Page with information about the reset options. */ function sucuriscan_settings_general_resetoptions($nonce) { // Reset all the plugin's options. if ($nonce && SucuriScanRequest::post(':reset_options') !== false) { $process = SucuriScanRequest::post(':process_form'); if (intval($process) === 1) { $message = __('Local security logs, hardening and settings were deleted', 'sucuri-scanner'); sucuriscanResetAndDeactivate(); /* simulate plugin deactivation */ SucuriScanEvent::reportCriticalEvent($message); SucuriScanEvent::notifyEvent('plugin_change', $message); SucuriScanInterface::info(__('Local security logs, hardening and settings were deleted', 'sucuri-scanner')); } else { SucuriScanInterface::error(__('You need to confirm that you understand the risk of this operation.', 'sucuri-scanner')); } } return SucuriScanTemplate::getSection('settings-general-resetoptions'); } /** * Renders a page with information about the data storage feature. * * @param bool $nonce True if the CSRF protection worked. * @return string Page with information about the data storage. */ function sucuriscan_settings_general_datastorage($nonce) { $params = array(); $files = array( '' => __('Directory used to store the plugin settings, cache and system logs', 'sucuri-scanner'), 'auditlogs' => sprintf(__('Cache to store the system logs obtained from the API service; expires after %s seconds.', 'sucuri-scanner'), SUCURISCAN_AUDITLOGS_LIFETIME), 'auditqueue' => __('Local queue to store the most recent logs before they are sent to the remote API service.', 'sucuri-scanner'), 'blockedusers' => __('Deprecated on 1.8.12; it was used to store a list of blocked user names.', 'sucuri-scanner'), /* TODO: deprecated on 1.8.12 */ 'failedlogins' => __('Stores the data for every failed login attempt. The data is moved to "oldfailedlogins" every hour during a brute force password attack.', 'sucuri-scanner'), 'hookdata' => __('Temporarily stores data to complement the logs during destructive operations like deleting a post, page, comment, etc.', 'sucuri-scanner'), 'ignorescanning' => __('Stores a list of files and folders chosen by the user to be ignored by the file system scanner.', 'sucuri-scanner'), 'integrity' => __('Stores a list of files marked as fixed by the user via the WordPress Integrity tool.', 'sucuri-scanner'), 'lastlogins' => __('Stores the data associated to every successful user login. The data never expires; manually delete if the file is too large.', 'sucuri-scanner'), 'oldfailedlogins' => __('Stores the data for every failed login attempt after the plugin sends a report about a brute force password attack via email.', 'sucuri-scanner'), 'plugindata' => sprintf(__('Cache to store the data associated to the installed plugins listed in the Post-Hack page. Expires after %s seconds.', 'sucuri-scanner'), SUCURISCAN_GET_PLUGINS_LIFETIME), 'settings' => __('Stores all the options used to configure the functionality and behavior of the plugin.', 'sucuri-scanner'), 'sitecheck' => sprintf(__('Cache to store the result of the malware scanner. Expires after %s seconds, reset at any time to force a re-scan.', 'sucuri-scanner'), SUCURISCAN_SITECHECK_LIFETIME), 'trustip' => __('Stores a list of IP addresses trusted by the plugin, events triggered by one of these IPs will not be reported to the remote monitoring API service.', 'sucuri-scanner'), ); $params['Storage.Files'] = ''; $params['Storage.Path'] = SucuriScan::dataStorePath(); if ($nonce) { $filenames = SucuriScanRequest::post(':filename', '_array'); if ($filenames) { $deleted = 0; foreach ($filenames as $filename) { $short = substr($filename, 7); /* drop directroy path */ $short = substr($short, 0, -4); /* drop file extension */ if (!$short || empty($short) || !array_key_exists($short, $files)) { continue; /* prevent path traversal */ } $filepath = SucuriScan::dataStorePath($filename); if (!file_exists($filepath) || is_dir($filepath)) { continue; /* there is nothing to reset */ } /* ignore write permissions */ if (@unlink($filepath)) { $deleted++; } } // Register on audit logs and return result. SucuriScanEvent::reportInfoEvent( sprintf( __('%s were deleted.', 'sucuri-scanner'), implode(', ', $filenames) ) ); SucuriScanInterface::info( sprintf( __('%d out of %d files have been deleted.', 'sucuri-scanner'), $deleted, count($filenames) ) ); } } foreach ($files as $name => $desc) { if ($name === '') { /* convert to folder */ $name = ''; } $fsize = 0; $fname = ($name ? sprintf('sucuri-%s.php', $name) : ''); $fpath = SucuriScan::dataStorePath($fname); $disabled = 'disabled="disabled"'; $iswritable = __('Not Writable', 'sucuri-scanner'); $exists = __('Does Not Exist', 'sucuri-scanner'); $labelExistence = 'danger'; $labelWritability = 'default'; if (file_exists($fpath)) { $fsize = @filesize($fpath); $exists = __('Exists', 'sucuri-scanner'); $labelExistence = 'success'; $labelWritability = 'danger'; if (is_writable($fpath)) { $disabled = ''; /* Allow file deletion */ $iswritable = __('Writable', 'sucuri-scanner'); $labelWritability = 'success'; } } $params['Storage.Filename'] = $fname; $params['Storage.Filepath'] = str_replace(ABSPATH, '', $fpath); $params['Storage.Filesize'] = SucuriScan::humanFileSize($fsize); $params['Storage.Exists'] = $exists; $params['Storage.IsWritable'] = $iswritable; $params['Storage.DisabledInput'] = $disabled; $params['Storage.Existence'] = $labelExistence; $params['Storage.Writability'] = $labelWritability; $params['Storage.Description'] = $desc; if (is_dir($fpath)) { $params['Storage.Filesize'] = ''; $params['Storage.DisabledInput'] = 'disabled="disabled"'; } $params['Storage.Files'] .= SucuriScanTemplate::getSnippet('settings-general-datastorage', $params); } return SucuriScanTemplate::getSection('settings-general-datastorage', $params); } /** * Returns the path to the local event monitoring file. * * The website owner can configure the plugin to send a copy of the security * events to a local file that can be integrated with other monitoring systems * like OSSEC, OpenVAS, NewRelic and similar. * * @return string|bool Path to the log file, false if disabled. */ function sucuriscan_selfhosting_fpath() { $monitor = SucuriScanOption::getOption(':selfhosting_monitor'); $monitor_fpath = SucuriScanOption::getOption(':selfhosting_fpath'); $folder = dirname($monitor_fpath); if ($monitor === 'enabled' && !empty($monitor_fpath) && is_writable($folder) ) { return $monitor_fpath; } return false; } /** * Renders a page with information about the self-hosting feature. * * @param bool $nonce True if the CSRF protection worked. * @return string Page with information about the self-hosting. */ function sucuriscan_settings_general_selfhosting($nonce) { $params = array(); $params['SelfHosting.DisabledVisibility'] = 'visible'; $params['SelfHosting.Status'] = __('Enabled', 'sucuri-scanner'); $params['SelfHosting.SwitchText'] = __('Disable', 'sucuri-scanner'); $params['SelfHosting.SwitchValue'] = 'disable'; $params['SelfHosting.FpathVisibility'] = 'hidden'; $params['SelfHosting.Fpath'] = ''; if ($nonce) { // Set a file path for the self-hosted event monitor. $monitor_fpath = SucuriScanRequest::post(':selfhosting_fpath'); if ($monitor_fpath !== false) { if (empty($monitor_fpath)) { $message = __('Log exporter was disabled', 'sucuri-scanner'); SucuriScanEvent::reportInfoEvent($message); SucuriScanOption::deleteOption(':selfhosting_fpath'); SucuriScanOption::updateOption(':selfhosting_monitor', 'disabled'); SucuriScanEvent::notifyEvent('plugin_change', $message); SucuriScanInterface::info(__('The log exporter feature has been disabled', 'sucuri-scanner')); } elseif (strpos($monitor_fpath, $_SERVER['DOCUMENT_ROOT']) !== false) { SucuriScanInterface::error(__('File should not be publicly accessible.', 'sucuri-scanner')); } elseif (file_exists($monitor_fpath)) { SucuriScanInterface::error(__('File already exists and will not be overwritten.', 'sucuri-scanner')); } elseif (!is_writable(dirname($monitor_fpath))) { SucuriScanInterface::error(__('File parent directory is not writable.', 'sucuri-scanner')); } else { @file_put_contents($monitor_fpath, '', LOCK_EX); $message = __('Log exporter file path was correctly set', 'sucuri-scanner'); SucuriScanEvent::reportInfoEvent($message); SucuriScanOption::updateOption(':selfhosting_monitor', 'enabled'); SucuriScanOption::updateOption(':selfhosting_fpath', $monitor_fpath); SucuriScanEvent::notifyEvent('plugin_change', $message); SucuriScanInterface::info(__('The log exporter feature has been enabled and the data file was successfully set.', 'sucuri-scanner')); } } } $monitor = SucuriScanOption::getOption(':selfhosting_monitor'); $monitor_fpath = SucuriScanOption::getOption(':selfhosting_fpath'); if ($monitor === 'disabled') { $params['SelfHosting.Status'] = __('Disabled', 'sucuri-scanner'); $params['SelfHosting.SwitchText'] = __('Enable', 'sucuri-scanner'); $params['SelfHosting.SwitchValue'] = 'enable'; } if ($monitor === 'enabled' && $monitor_fpath) { $params['SelfHosting.DisabledVisibility'] = 'hidden'; $params['SelfHosting.FpathVisibility'] = 'visible'; $params['SelfHosting.Fpath'] = SucuriScan::escape($monitor_fpath); } return SucuriScanTemplate::getSection('settings-general-selfhosting', $params); } /** * Renders a page with information about the reverse proxy feature. * * @param bool $nonce True if the CSRF protection worked. * @return string Page with information about the reverse proxy. */ function sucuriscan_settings_general_reverseproxy($nonce) { $params = array( 'ReverseProxyStatus' => __('Enabled', 'sucuri-scanner'), 'ReverseProxySwitchText' => __('Disable', 'sucuri-scanner'), 'ReverseProxySwitchValue' => 'disable', ); // Enable or disable the reverse proxy support. if ($nonce) { $revproxy = SucuriScanRequest::post(':revproxy', '(en|dis)able'); if ($revproxy) { if ($revproxy === 'enable') { SucuriScanOption::setRevProxy('enable'); SucuriScanOption::setAddrHeader('HTTP_X_SUCURI_CLIENTIP'); } else { SucuriScanOption::setRevProxy('disable'); SucuriScanOption::setAddrHeader('REMOTE_ADDR'); } } } if (SucuriScanOption::isDisabled(':revproxy')) { $params['ReverseProxyStatus'] = __('Disabled', 'sucuri-scanner'); $params['ReverseProxySwitchText'] = __('Enable', 'sucuri-scanner'); $params['ReverseProxySwitchValue'] = 'enable'; } return SucuriScanTemplate::getSection('settings-general-reverseproxy', $params); } /** * Renders a page with information about the IP discoverer feature. * * @param bool $nonce True if the CSRF protection worked. * @return string Page with information about the IP discoverer. */ function sucuriscan_settings_general_ipdiscoverer($nonce) { $params = array( 'TopLevelDomain' => __('unknown', 'sucuri-scanner'), 'WebsiteHostName' => __('unknown', 'sucuri-scanner'), 'WebsiteHostAddress' => __('unknown', 'sucuri-scanner'), 'IsUsingFirewall' => __('unknown', 'sucuri-scanner'), 'WebsiteURL' => __('unknown', 'sucuri-scanner'), 'RemoteAddress' => '127.0.0.1', 'RemoteAddressHeader' => __('INVALID', 'sucuri-scanner'), 'AddrHeaderOptions' => '', /* Switch form information. */ 'DnsLookupsStatus' => __('Enabled', 'sucuri-scanner'), 'DnsLookupsSwitchText' => __('Disable', 'sucuri-scanner'), 'DnsLookupsSwitchValue' => 'disable', ); // Get main HTTP header for IP retrieval. $allowed_headers = SucuriScan::allowedHttpHeaders(true); // Configure the DNS lookups option for reverse proxy detection. if ($nonce) { $dns_lookups = SucuriScanRequest::post(':dns_lookups', '(en|dis)able'); $addr_header = SucuriScanRequest::post(':addr_header'); if ($dns_lookups) { $action_d = $dns_lookups . 'd'; $message = sprintf(__('DNS lookups for reverse proxy detection %s', 'sucuri-scanner'), $action_d); SucuriScanOption::updateOption(':dns_lookups', $action_d); SucuriScanEvent::reportInfoEvent($message); SucuriScanEvent::notifyEvent('plugin_change', $message); SucuriScanInterface::info(__('The status of the DNS lookups for the reverse proxy detection has been changed', 'sucuri-scanner')); } if ($addr_header) { if ($addr_header === 'REMOTE_ADDR') { SucuriScanOption::setAddrHeader('REMOTE_ADDR'); SucuriScanOption::setRevProxy('disable'); } else { SucuriScanOption::setAddrHeader($addr_header); SucuriScanOption::setRevProxy('enable'); } } } if (SucuriScanOption::isDisabled(':dns_lookups')) { $params['DnsLookupsStatus'] = __('Disabled', 'sucuri-scanner'); $params['DnsLookupsSwitchText'] = __('Enable', 'sucuri-scanner'); $params['DnsLookupsSwitchValue'] = 'enable'; } $proxy_info = SucuriScan::isBehindFirewall(true); $base_domain = SucuriScan::getDomain(true); $params['TopLevelDomain'] = $proxy_info['http_host']; $params['WebsiteHostName'] = $proxy_info['host_name']; $params['WebsiteHostAddress'] = $proxy_info['host_addr']; $params['RemoteAddressHeader'] = SucuriScan::getRemoteAddrHeader(); $params['RemoteAddress'] = SucuriScan::getRemoteAddr(); $params['WebsiteURL'] = SucuriScan::getDomain(); $params['AddrHeaderOptions'] = SucuriScanTemplate::selectOptions( $allowed_headers, /* list is limited to a few options */ SucuriScanOption::getOption(':addr_header') ); $params['IsUsingFirewall'] = $proxy_info['status'] ? 'active' : 'not active'; if ($base_domain !== $proxy_info['http_host']) { $params['TopLevelDomain'] = sprintf('%s (%s)', $params['TopLevelDomain'], $base_domain); } return SucuriScanTemplate::getSection('settings-general-ipdiscoverer', $params); } /** * Renders a page with information about the import export feature. * * @param bool $nonce True if the CSRF protection worked. * @return string Page with information about the import export. */ function sucuriscan_settings_general_importexport($nonce) { $settings = array(); $params = array(); $allowed = array( ':addr_header', ':api_protocol', ':api_service', ':cloudproxy_apikey', ':diff_utility', ':dns_lookups', ':email_subject', ':emails_per_hour', ':ignored_events', ':lastlogin_redirection', ':maximum_failed_logins', ':notify_available_updates', ':notify_bruteforce_attack', ':notify_failed_login', ':notify_plugin_activated', ':notify_plugin_change', ':notify_plugin_deactivated', ':notify_plugin_deleted', ':notify_plugin_installed', ':notify_plugin_updated', ':notify_post_publication', ':notify_scan_checksums', ':notify_settings_updated', ':notify_success_login', ':notify_theme_activated', ':notify_theme_deleted', ':notify_theme_editor', ':notify_theme_installed', ':notify_theme_updated', ':notify_to', ':notify_user_registration', ':notify_website_updated', ':notify_widget_added', ':notify_widget_deleted', ':prettify_mails', ':revproxy', ':selfhosting_fpath', ':selfhosting_monitor', ':use_wpmail', ); if ($nonce && SucuriScanRequest::post(':import') !== false) { $process = SucuriScanRequest::post(':process_form'); if (intval($process) === 1) { $json = SucuriScanRequest::post(':settings'); $json = str_replace('\"', '"', $json); $data = @json_decode($json, true); if ($data) { $count = 0; $total = count($data); /* minimum length for option name */ $minLength = strlen(SUCURISCAN . '_'); foreach ($data as $option => $value) { if (strlen($option) <= $minLength) { continue; } $option_name = ':' . substr($option, $minLength); /* check if the option can be imported */ if (!in_array($option_name, $allowed)) { continue; } SucuriScanOption::updateOption($option_name, $value); $count++; } /* import trusted ip addresses */ if (array_key_exists('trusted_ips', $data) && is_array($data)) { $cache = new SucuriScanCache('trustip'); foreach ($data['trusted_ips'] as $trustedIP) { $trustedIP = str_replace('\/', '/', $trustedIP); $trustedIP = str_replace('/32', '', $trustedIP); if (SucuriScan::isValidIP($trustedIP) || SucuriScan::isValidCIDR($trustedIP)) { $ipInfo = SucuriScan::getIPInfo($trustedIP); $cacheKey = md5($ipInfo['remote_addr']); $ipInfo['added_at'] = time(); if (!$cache->exists($cacheKey)) { $cache->add($cacheKey, $ipInfo); } } } } SucuriScanInterface::info( sprintf( __('%d out of %d option have been successfully imported', 'sucuri-scanner'), $count, $total ) ); } else { SucuriScanInterface::error(__('Data is incorrectly encoded', 'sucuri-scanner')); } } else { SucuriScanInterface::error(__('You need to confirm that you understand the risk of this operation.', 'sucuri-scanner')); } } foreach ($allowed as $option) { $option_name = SucuriScan::varPrefix($option); $settings[$option_name] = SucuriScanOption::getOption($option); } /* include the trusted IP address list */ $settings['trusted_ips'] = array(); $cache = new SucuriScanCache('trustip'); $trusted = $cache->getAll(); foreach ($trusted as $trustedIP) { $settings['trusted_ips'][] = $trustedIP->cidr_format; } $params['Export'] = @json_encode($settings); return SucuriScanTemplate::getSection('settings-general-importexport', $params); } /** * Renders a page with the option to configure the timezone. * * @param bool $nonce True if the CSRF protection worked. * @return string Page to configure the timezone. */ function sucuriscan_settings_general_timezone($nonce) { $params = array(); $current = time(); $options = array(); $offsets = array( -12.0, -11.5, -11.0, -10.5, -10.0, -9.50, -9.00, -8.50, -8.00, -7.50, -7.00, -6.50, -6.00, -5.50, -5.00, -4.50, -4.00, -3.50, -3.00, -2.50, -2.00, -1.50, -1.00, -0.50, +0.00, +0.50, +1.00, +1.50, +2.00, +2.50, +3.00, +3.50, +4.00, +4.50, +5.00, +5.50, +5.75, +6.00, +6.50, +7.00, +7.50, +8.00, +8.50, +8.75, +9.00, +9.50, 10.00, 10.50, 11.00, 11.50, 12.00, 12.75, 13.00, 13.75, 14.00 ); foreach ($offsets as $hour) { $sign = ($hour < 0) ? '-' : '+'; $fill = (abs($hour) < 10) ? '0' : ''; $keyname = sprintf('UTC%s%s%.2f', $sign, $fill, abs($hour)); $label = date('d M, Y H:i:s', $current + ($hour * 3600)); $options[$keyname] = $keyname . ' (' . $label . ')'; } if ($nonce) { $pattern = 'UTC[\-\+][0-9]{2}\.[0-9]{2}'; $timezone = SucuriScanRequest::post(':timezone', $pattern); if ($timezone) { $message = sprintf(__('Timezone override will use %s', 'sucuri-scanner'), $timezone); SucuriScanOption::updateOption(':timezone', $timezone); SucuriScanEvent::reportInfoEvent($message); SucuriScanEvent::notifyEvent('plugin_change', $message); SucuriScanInterface::info(__('The timezone for the date and time in the audit logs has been changed', 'sucuri-scanner')); } } $val = SucuriScanOption::getOption(':timezone'); $params['Timezone.Dropdown'] = SucuriScanTemplate::selectOptions($options, $val); $params['Timezone.Example'] = SucuriScan::datetime(); return SucuriScanTemplate::getSection('settings-general-timezone', $params); } src/settings-hardening.php000060400000104653147177152050011657 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Renders the content of the plugin's hardening page. * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ class SucuriScanHardeningPage extends SucuriScan { /** * Generate the HTML code necessary to show a form with the options to harden * a specific part of the WordPress installation, if the Status variable is * set as a positive integer the button is shown as "unharden". * * @param array $args Array with template variables to replace. * @return string HTML code with the replaced template variables. */ private static function drawSection($args = array()) { $params = array(); $params['Hardening.Title'] = ''; $params['Hardening.Status'] = ''; $params['Hardening.FieldName'] = ''; $params['Hardening.FieldText'] = ''; $params['Hardening.FieldAttrs'] = ''; $params['Hardening.Description'] = ''; foreach ($args as $keyname => $value) { $params[$keyname] = $value; } if (!empty($params['Hardening.FieldName'])) { $params['Hardening.FieldName'] = sprintf( '%s_hardening_%s', SUCURISCAN, $params['Hardening.FieldName'] ); } return SucuriScanTemplate::getSnippet('settings-hardening-options', $params); } /** * Checks if the request has a valid nonce to prevent a CSRF. * * @param string $function Name of the action that was executed. * @return bool True if the request has a valid CSRF protection. */ private static function processRequest($function) { return (bool)(SucuriScanInterface::checkNonce() /* CSRF protection */ && SucuriScanRequest::post(':hardening_' . $function)); } /** * Checks if the Firewall service is enabled and configured. * * WAF is a protection layer for your web site, blocking all sort of attacks * (brute force attempts, DDoS, SQL injections, etc) and helping it remain * malware and blocklist free. This test checks if your site is using Sucuri * Firewall to protect your site. * * @return string HTML code with the replaced template variables. */ public static function firewall() { $params = array(); if (self::processRequest(__FUNCTION__)) { SucuriScanInterface::error( __( 'The firewall is a premium service that you need purchase at - Sucuri Firewall', 'sucuri-scanner' ) ); } $params['Hardening.FieldName'] = __FUNCTION__; $params['Hardening.Title'] = __('Enable Website Firewall Protection', 'sucuri-scanner'); $params['Hardening.Description'] = __( 'A WAF is a protection layer for your web site, blocking all sort of attacks (brute force attempts, DDoS, SQL injections, etc) and helping it remain malware and blocklist free. This test checks if your site is using Sucuri Firewall to protect your site.', 'sucuri-scanner' ); if (!SucuriScan::isBehindFirewall()) { $params['Hardening.Status'] = 0; $params['Hardening.FieldText'] = __('Apply Hardening', 'sucuri-scanner'); } else { $params['Hardening.Status'] = 1; $params['Hardening.FieldAttrs'] = 'disabled'; $params['Hardening.FieldText'] = __('Revert Hardening', 'sucuri-scanner'); } return self::drawSection($params); } /** * Checks if the WordPress version is the latest available. * * Why keep your site updated? WordPress is an open-source project which * means that with every update the details of the changes made to the * source code are made public, if there were security fixes then someone * with malicious intent can use this information to attack any site that * has not been upgraded. * * @return HTML with the information about this hardening option. */ public static function wpversion() { $params = array(); $updates = get_core_updates(); $site_version = SucuriScan::siteVersion(); $params['URL.Settings'] = admin_url('update-core.php'); $params['Hardening.Status'] = 0; $params['Hardening.FieldText'] = __('Check Updates Now', 'sucuri-scanner'); $params['Hardening.Title'] = __('Verify WordPress Version', 'sucuri-scanner'); $params['Hardening.Description'] = __( 'Why keep your site updated? WordPress is an open-source project which means that with every update the details of the changes made to the source code are made public, if there were security fixes then someone with malicious intent can use this information to attack any site that has not been upgraded.', 'sucuri-scanner' ); if (isset($updates[0]) && $updates[0] instanceof stdClass) { if ($updates[0]->response == 'latest' || $updates[0]->response == 'development') { $params['Hardening.FieldText'] = __('WordPress Update Available', 'sucuri-scanner'); $params['Hardening.FieldAttrs'] = 'disabled'; $params['Hardening.Status'] = 1; } } return self::drawSection($params); } /** * Notify the state of the hardening for the removal of the Generator tag in * HTML code printed by WordPress to show the current version number of the * installation. * * @return HTML with the information about this hardening option. */ public static function wpgenerator() { $params = array(); $params['Hardening.Title'] = __('Remove WordPress Version', 'sucuri-scanner'); $params['Hardening.Status'] = 1; $params['Hardening.FieldText'] = __('Revert Hardening', 'sucuri-scanner'); $params['Hardening.FieldAttrs'] = 'disabled'; $params['Hardening.Description'] = __( 'It checks if your WordPress version is being leaked to the public via a HTML meta-tag. Many web vulnerability scanners use this to determine which version of the code is running in your website. They use this to find disclosed vulnerabilities associated to this version number. A vulnerability scanner can still guess which version of WordPress is installed by comparing the checksum of some static files.', 'sucuri-scanner' ); return self::drawSection($params); } /** * Offers information to apply a hardening to an Nginx installation. * * @return HTML with the information about this hardening option. */ public static function nginxphp() { if (!SucuriScan::isNginxServer()) { return ''; /* empty page */ } $params = array(); if (self::processRequest(__FUNCTION__)) { SucuriScanInterface::error( __( 'Read the official WordPress guidelines to learn how to restrict access to PHP files in sensitive directories - Nginx Global Restrictions For WordPress', 'sucuri-scanner' ) ); } $params['Hardening.Title'] = __('Block of Certain PHP Files', 'sucuri-scanner'); $params['Hardening.Status'] = 2; $params['Hardening.FieldName'] = __FUNCTION__; $params['Hardening.FieldText'] = __('Check Hardening', 'sucuri-scanner'); $params['Hardening.Description'] = __( 'Block the execution of PHP files in sensitive directories. Be careful while applying this hardening option as there are many plugins and theme which rely on the ability to execute PHP files in the content directory to generate images or save temporary data. Use the "Add PHP Files to the Allowlist" tool to add exceptions to individual files.', 'sucuri-scanner' ); return self::drawSection($params); } /** * Check whether the WordPress upload folder is protected or not. * * A htaccess file is placed in the upload folder denying the access to any php * file that could be uploaded through a vulnerability in a Plugin, Theme or * WordPress itself. * * @return HTML with the information about this hardening option. */ public static function wpuploads() { if (SucuriScan::isNginxServer() || SucuriScan::isIISServer()) { return ''; /* empty page */ } $params = array(); $folder = WP_CONTENT_DIR . '/uploads'; if (self::processRequest(__FUNCTION__)) { $result = SucuriScanHardening::hardenDirectory($folder); if ($result === true) { SucuriScanEvent::reportNoticeEvent(__('Hardening applied to the uploads directory', 'sucuri-scanner')); SucuriScanInterface::info(__('Hardening applied to the uploads directory', 'sucuri-scanner')); } else { SucuriScanInterface::error(__('Error hardening directory, check the permissions.', 'sucuri-scanner')); } } if (self::processRequest(__FUNCTION__ . '_revert')) { $result = SucuriScanHardening::unhardenDirectory($folder); if ($result === true) { SucuriScanEvent::reportErrorEvent(__('Hardening reverted in the uploads directory', 'sucuri-scanner')); SucuriScanInterface::info(__('Hardening reverted in the uploads directory', 'sucuri-scanner')); } else { SucuriScanInterface::error(__('Access file is not writable, check the permissions.', 'sucuri-scanner')); } } $params['Hardening.Title'] = __('Block PHP Files in Uploads Directory', 'sucuri-scanner'); $params['Hardening.Description'] = __( 'Block the execution of PHP files in sensitive directories. Be careful while applying this hardening option as there are many plugins and theme which rely on the ability to execute PHP files in the content directory to generate images or save temporary data. Use the "Add PHP Files to the Allowlist" tool to add exceptions to individual files.', 'sucuri-scanner' ); if (SucuriScan::isBehindFirewall()) { $params['Hardening.Status'] = 1; $params['Hardening.FieldAttrs'] = 'disabled'; $params['Hardening.FieldText'] = __('Revert Hardening', 'sucuri-scanner'); } elseif (SucuriScanHardening::isHardened($folder)) { $params['Hardening.Status'] = 1; $params['Hardening.FieldName'] = __FUNCTION__ . '_revert'; $params['Hardening.FieldText'] = __('Revert Hardening', 'sucuri-scanner'); } else { $params['Hardening.Status'] = 0; $params['Hardening.FieldName'] = __FUNCTION__; $params['Hardening.FieldText'] = __('Apply Hardening', 'sucuri-scanner'); } return self::drawSection($params); } /** * Check whether the WordPress content folder is protected or not. * * A htaccess file is placed in the content folder denying the access to any php * file that could be uploaded through a vulnerability in a Plugin, Theme or * WordPress itself. * * @return HTML with the information about this hardening option. */ public static function wpcontent() { if (SucuriScan::isNginxServer() || SucuriScan::isIISServer()) { return ''; /* empty page */ } $params = array(); if (self::processRequest(__FUNCTION__)) { $result = SucuriScanHardening::hardenDirectory(WP_CONTENT_DIR); if ($result === true) { SucuriScanEvent::reportNoticeEvent(__('Hardening applied to the content directory', 'sucuri-scanner')); SucuriScanInterface::info(__('Hardening applied to the content directory', 'sucuri-scanner')); } else { SucuriScanInterface::error(__('Error hardening directory, check the permissions.', 'sucuri-scanner')); } } if (self::processRequest(__FUNCTION__ . '_revert')) { $result = SucuriScanHardening::unhardenDirectory(WP_CONTENT_DIR); if ($result === true) { SucuriScanEvent::reportErrorEvent(__('Hardening reverted in the content directory', 'sucuri-scanner')); SucuriScanInterface::info(__('Hardening reverted in the content directory', 'sucuri-scanner')); } else { SucuriScanInterface::error(__('Access file is not writable, check the permissions.', 'sucuri-scanner')); } } $params['Hardening.Title'] = __('Block PHP Files in WP-CONTENT Directory', 'sucuri-scanner'); $params['Hardening.Description'] = __( 'Block the execution of PHP files in sensitive directories. Be careful while applying this hardening option as there are many plugins and theme which rely on the ability to execute PHP files in the content directory to generate images or save temporary data. Use the "Add PHP Files to the Allowlist" tool to add exceptions to individual files.', 'sucuri-scanner' ); if (SucuriScan::isBehindFirewall()) { $params['Hardening.Status'] = 1; $params['Hardening.FieldAttrs'] = 'disabled'; $params['Hardening.FieldText'] = __('Revert Hardening', 'sucuri-scanner'); } elseif (SucuriScanHardening::isHardened(WP_CONTENT_DIR)) { $params['Hardening.Status'] = 1; $params['Hardening.FieldName'] = __FUNCTION__ . '_revert'; $params['Hardening.FieldText'] = __('Revert Hardening', 'sucuri-scanner'); } else { $params['Hardening.Status'] = 0; $params['Hardening.FieldName'] = __FUNCTION__; $params['Hardening.FieldText'] = __('Apply Hardening', 'sucuri-scanner'); } return self::drawSection($params); } /** * Check whether the WordPress includes folder is protected or not. * * A htaccess file is placed in the includes folder denying the access to any php * file that could be uploaded through a vulnerability in a Plugin, Theme or * WordPress itself, there are some exceptions for some specific files that must * be available publicly. * * @return HTML with the information about this hardening option. */ public static function wpincludes() { if (SucuriScan::isNginxServer() || SucuriScan::isIISServer()) { return ''; /* empty page */ } $params = array(); $folder = ABSPATH . '/wp-includes'; if (self::processRequest(__FUNCTION__)) { $result = SucuriScanHardening::hardenDirectory($folder); if ($result === true) { try { SucuriScanHardening::allow('wp-tinymce.php', 'wp-includes'); SucuriScanHardening::allow('ms-files.php', 'wp-includes'); SucuriScanEvent::reportNoticeEvent(__( 'Hardening applied to the library directory', 'sucuri-scanner' )); SucuriScanInterface::info(__('Hardening applied to the library directory', 'sucuri-scanner')); } catch (Exception $e) { SucuriScanInterface::error($e->getMessage()); } } else { SucuriScanInterface::error(__('Error hardening directory, check the permissions.', 'sucuri-scanner')); } } if (self::processRequest(__FUNCTION__ . '_revert')) { $result = SucuriScanHardening::unhardenDirectory($folder); if ($result === true) { SucuriScanHardening::removeFromAllowlist('wp-tinymce.php', 'wp-includes'); SucuriScanHardening::removeFromAllowlist('ms-files.php', 'wp-includes'); SucuriScanEvent::reportErrorEvent(__('Hardening reverted in the library directory', 'sucuri-scanner')); SucuriScanInterface::info(__('Hardening reverted in the library directory', 'sucuri-scanner')); } else { SucuriScanInterface::error(__('Access file is not writable, check the permissions.', 'sucuri-scanner')); } } $params['Hardening.Title'] = __('Block PHP Files in WP-INCLUDES Directory', 'sucuri-scanner'); $params['Hardening.Description'] = __( 'Block the execution of PHP files in sensitive directories. Be careful while applying this hardening option as there are many plugins and theme which rely on the ability to execute PHP files in the content directory to generate images or save temporary data. Use the "Add PHP Files to the Allowlist" tool to add exceptions to individual files.', 'sucuri-scanner' ); if (SucuriScan::isBehindFirewall()) { $params['Hardening.Status'] = 1; $params['Hardening.FieldAttrs'] = 'disabled'; $params['Hardening.FieldText'] = __('Revert Hardening', 'sucuri-scanner'); } elseif (SucuriScanHardening::isHardened($folder)) { $params['Hardening.Status'] = 1; $params['Hardening.FieldName'] = __FUNCTION__ . '_revert'; $params['Hardening.FieldText'] = __('Revert Hardening', 'sucuri-scanner'); } else { $params['Hardening.Status'] = 0; $params['Hardening.FieldName'] = __FUNCTION__; $params['Hardening.FieldText'] = __('Apply Hardening', 'sucuri-scanner'); } return self::drawSection($params); } /** * Check whether the "readme.html" file is still available in the root of the * site or not, which can lead to an attacker to know which version number of * Wordpress is being used and search for possible vulnerabilities. * * @return HTML with the information about this hardening option. */ public static function readme() { $params = array(); if (self::processRequest(__FUNCTION__)) { if (@unlink(ABSPATH . '/readme.html') === false) { SucuriScanInterface::error(sprintf( __('Cannot delete %s/readme.html', 'sucuri-scanner'), ABSPATH )); } else { SucuriScanEvent::reportNoticeEvent(__( 'Hardening applied to the readme.html file', 'sucuri-scanner' )); SucuriScanInterface::info(__( 'Hardening applied to the readme.html file', 'sucuri-scanner' )); } } $params['Hardening.Title'] = __('Avoid Information Leakage', 'sucuri-scanner'); $params['Hardening.Description'] = __( 'Checks if the WordPress README file still exists in the website. The information in this file can be used by malicious users to pin-point which disclosed vulnerabilities are associated to the website. Be aware that WordPress recreates this file automatically with every update.', 'sucuri-scanner' ); if (file_exists(ABSPATH . '/readme.html')) { $params['Hardening.Status'] = 0; $params['Hardening.FieldName'] = __FUNCTION__; $params['Hardening.FieldText'] = __('Apply Hardening', 'sucuri-scanner'); } else { $params['Hardening.Status'] = 1; $params['Hardening.FieldText'] = __('Revert Hardening', 'sucuri-scanner'); $params['Hardening.FieldAttrs'] = 'disabled'; } return self::drawSection($params); } /** * Check whether the main admin user still has the default name "admin" or * not, which can lead to an attacker to perform a brute force attack. * * @return HTML with the information about this hardening option. */ public static function adminuser() { $params = array(); $user_query = new WP_User_Query( array( 'search' => 'admin', 'fields' => array('ID', 'user_login'), 'search_columns' => array('user_login'), ) ); $results = $user_query->get_results(); $params['URL.Settings'] = admin_url('users.php?role=administrator'); $params['Hardening.Title'] = __('Verify Default Admin Account', 'sucuri-scanner'); $params['Hardening.Description'] = __( 'Check if the primary user account still uses the name "admin". This allows malicious users to easily identify which account has the highest privileges to target an attack.', 'sucuri-scanner' ); if (count($results) === 0) { $params['Hardening.Status'] = 1; $params['Hardening.FieldAttrs'] = 'disabled'; $params['Hardening.FieldText'] = __('Revert Hardening', 'sucuri-scanner'); } else { $params['Hardening.Status'] = 0; $params['Hardening.FieldName'] = __FUNCTION__; $params['Hardening.FieldText'] = __('Apply Hardening', 'sucuri-scanner'); } return self::drawSection($params); } /** * Enable or disable the user of the built-in Wordpress file editor. * * @return HTML with the information about this hardening option. */ public static function fileeditor() { $params = array(); $fileEditorWasDisabled = (bool)(defined('DISALLOW_FILE_EDIT') && DISALLOW_FILE_EDIT); if (self::processRequest(__FUNCTION__)) { $config = SucuriScan::getConfigPath(); if (!$config) { SucuriScanInterface::error(__('WordPress configuration file was not found.', 'sucuri-scanner')); } elseif (!is_writable($config)) { SucuriScanInterface::error(__('WordPress configuration file is not writable.', 'sucuri-scanner')); } else { $content = SucuriScanFileInfo::fileContent($config); $lines = explode("\n", $content); $newlines = array(); foreach ($lines as $line) { if (self::containsConstant($line, 'DISALLOW_FILE_EDIT')) { // Skip lines that define the `DISALLOW_FILE_EDIT` constant, // to make hardening possible when other plugins have already // defined the same constant with a falsy value. continue; } if (strpos($line, 'DB_COLLATE') === false) { $newlines[] = $line; continue; } $newlines[] = $line; /* add current line */ $newlines[] = ''; /* add line separator */ } $newlines[] = "define('DISALLOW_FILE_EDIT', true);"; $fileEditorWasDisabled = true; $content = implode("\n", $newlines); @file_put_contents($config, $content, LOCK_EX); SucuriScanEvent::reportNoticeEvent(__( 'Hardening applied to the plugin and theme editor', 'sucuri-scanner' )); SucuriScanInterface::info(__('Hardening applied to the plugin and theme editor', 'sucuri-scanner')); } } if (self::processRequest(__FUNCTION__ . '_revert')) { $config = SucuriScan::getConfigPath(); if (!$config) { SucuriScanInterface::error(__('WordPress configuration file was not found.', 'sucuri-scanner')); } elseif (!is_writable($config)) { SucuriScanInterface::error(__('WordPress configuration file is not writable.', 'sucuri-scanner')); } else { $content = SucuriScanFileInfo::fileContent($config); $lines = explode("\n", $content); $hardeningWasReverted = false; $newlines = array(); foreach ($lines as $line) { if (strpos($line, 'DISALLOW_FILE_EDIT') !== false) { $hardeningWasReverted = true; continue; /* remove the constant from the file */ } $newlines[] = $line; /* add current line */ } if (!$hardeningWasReverted) { SucuriScanInterface::error( __( 'File Editor was not disabled using this tool. You must scan your project for a constant defined as DISALLOW_FILE_EDIT, then either delete it or set its value to False. Any plugin/theme can disable the file editor, so it is impossible to determine the origin of the constant.', 'sucuri-scanner' ) ); } else { $fileEditorWasDisabled = false; $content = implode("\n", $newlines); @file_put_contents($config, $content, LOCK_EX); SucuriScanEvent::reportErrorEvent(__( 'Hardening reverted in the plugin and theme editor', 'sucuri-scanner' )); SucuriScanInterface::info(__( 'Hardening reverted in the plugin and theme editor', 'sucuri-scanner' )); } } } $params['Hardening.Title'] = __('Disable Plugin and Theme Editor', 'sucuri-scanner'); $params['Hardening.Description'] = __( 'Disables the theme and plugin editors to prevent unwanted modifications to the code. If you are having problems reverting this please open the wp-config.php file and delete the line with the constant DISALLOW_FILE_EDIT.', 'sucuri-scanner' ); if ($fileEditorWasDisabled) { $params['Hardening.Status'] = 1; $params['Hardening.FieldName'] = __FUNCTION__ . '_revert'; $params['Hardening.FieldText'] = __('Revert Hardening', 'sucuri-scanner'); } else { $params['Hardening.Status'] = 0; $params['Hardening.FieldName'] = __FUNCTION__; $params['Hardening.FieldText'] = __('Apply Hardening', 'sucuri-scanner'); } return self::drawSection($params); } /** * Checks if the Automatic Secret Keys Updater is enabled. * * Changing the Secret Keys will invalidate all existing cookies, forcing all * logged in users to login again. Doing this frequently will decrease the * chances of misuse of sessions left open on unprotected devices. * * @return string HTML code with the replaced template variables */ public static function autoSecretKeyUpdater() { $cronName = 'sucuriscan_autoseckeyupdater'; $cronFrequency = 'weekly'; // Activate auto secret key update. if (self::processRequest(__FUNCTION__)) { if (SucuriScanEvent::addScheduledTask($cronName, $cronFrequency)) { SucuriScanInterface::info(__( 'Automatic Secret Keys Updater enabled. The default frequency is "Weekly", but you can change the frequency on Settings -> Post-Hack -> Update Secret Keys section.', 'sucuri-scanner' )); SucuriScanEvent::reportNoticeEvent(__('Automatic Secret Keys Updater enabled.', 'sucuri-scanner')); } else { SucuriScanInterface::error(__('Something went wrong.', 'sucuri-scanner')); } } // Deactivate auto secret key update. if (self::processRequest(__FUNCTION__ . '_revert')) { if (SucuriScanEvent::deleteScheduledTask($cronName)) { SucuriScanInterface::info(__('Automatic Secret Keys Updater disabled.', 'sucuri-scanner')); SucuriScanEvent::reportNoticeEvent(__('Automatic Secret Keys Updater disabled.', 'sucuri-scanner')); } else { SucuriScanInterface::error(__('Something went wrong.', 'sucuri-scanner')); } } // Set status of auto secret key update. $params = array(); $params['Hardening.Title'] = __('Activate Automatic Secret Keys Updater', 'sucuri-scanner'); $params['Hardening.Description'] = __( 'Changing the Secret Keys will invalidate all existing cookies, forcing all logged in users to login again. Doing this frequently will decrease the chances of misuse of sessions left open on unprotected devices.', 'sucuri-scanner' ); $params['Hardening.Status'] = 0; $params['Hardening.FieldName'] = __FUNCTION__; $params['Hardening.FieldText'] = __('Apply Hardening', 'sucuri-scanner'); if (wp_next_scheduled($cronName)) { $params['Hardening.Status'] = 1; $params['Hardening.FieldName'] = __FUNCTION__ . '_revert'; $params['Hardening.FieldText'] = __('Revert Hardening', 'sucuri-scanner'); } return self::drawSection($params); } /** * Allow individual PHP files. * * Allows an admin to allow individual PHP files after the directory has * been hardened. Since the hardening rules denies access to all PHP files * contained in such directory, 3rd-party plugins and themes that makes use * of these direct requests will stop working. The admins will want to allow * direct access to certain PHP files. * * @return HTML with the information about this hardening option. */ public static function AllowPHPFiles() { $params = array( 'HardeningAllowlist.List' => '', 'HardeningAllowlist.AllowedFolders' => '', 'HardeningAllowlist.NoItemsVisibility' => 'visible', ); $upload_dir = wp_upload_dir(); $allowed_folders = array( rtrim(ABSPATH, '/') . '/' . WPINC, WP_CONTENT_DIR, $upload_dir['basedir'] ); if (SucuriScanInterface::checkNonce()) { // Add a new file to the hardening allowlist. $fwhite = SucuriScanRequest::post(':hardening_allowlist'); if ($fwhite) { $folder = SucuriScanRequest::post(':hardening_folder'); if (in_array($folder, $allowed_folders)) { try { SucuriScanHardening::allow($fwhite, $folder); SucuriScanInterface::info(__('The file has been allowed', 'sucuri-scanner')); } catch (Exception $e) { SucuriScanInterface::error($e->getMessage()); } } else { SucuriScanInterface::error(__('Specified folder is not hardened by this plugin', 'sucuri-scanner')); } } // Remove a file from the hardening allowlist. $rmfwhite = SucuriScanRequest::post(':hardening_rmfwhite', '_array'); $rmferror = false; if ($rmfwhite) { foreach ($rmfwhite as $fpath) { $is_legacy = strpos($fpath, '/.*/') !== false; $finfo = SucuriScanHardening::getFolderAndFilePath($fpath, $allowed_folders); // File is not in the $allowed_folders. if ($finfo === false) { $rmferror = true; continue; } SucuriScanHardening::removeFromAllowlist( $finfo['relative_path'], $finfo['base_directory'], $is_legacy ); } if ($rmferror) { SucuriScanInterface::error(__('Some files could not be removed', 'sucuri-scanner')); } else { SucuriScanInterface::info(__('Selected files have been removed', 'sucuri-scanner')); } } } // Read the access control file and retrieve the files in the allowlist. foreach ($allowed_folders as $folder) { $files = SucuriScanHardening::getAllowlist($folder); $params['HardeningAllowlist.AllowedFolders'] .= sprintf( '', SucuriScan::escape($folder), SucuriScan::escape($folder) ); if (is_array($files) && !empty($files)) { $params['HardeningAllowlist.NoItemsVisibility'] = 'hidden'; foreach ($files as $file) { $pattern = sprintf('%s/.*/%s', $folder, $file['file']); if (!$file['wildcard_pattern']) { $pattern = realpath($folder . '/' . $file['relative_path']); } if ($pattern === false) { $pattern = $folder . '/' . $file['relative_path']; } $html = SucuriScanTemplate::getSnippet( 'settings-hardening-allowlist-phpfiles', array( 'HardeningAllowlist.Regexp' => $pattern, 'HardeningAllowlist.Folder' => $folder, 'HardeningAllowlist.File' => $file['relative_path'], ) ); $params['HardeningAllowlist.List'] .= $html; } } } return SucuriScanTemplate::getSection('settings-hardening-allowlist-phpfiles', $params); } private static function containsConstant($line, $constant) { return strpos($line, "'" . $constant . "'") !== false || strpos($line, '"' . $constant . '"') !== false; } } src/settings-headers.php000060400000012613147177152050011325 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Returns the HTML to configure the header's cache options. * * WordPress by default does not come with cache control headers, * used by WAFs and CDNs and that are useful to both improve performance * and reduce bandwidth and other resources demand on the hosting server. * * @param bool $nonce True if the CSRF protection worked, false otherwise. * @return string HTML for the email alert recipients. */ function sucuriscan_settings_cache_options($nonce) { $isWooCommerceActive = in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins'))); $params = array( 'CacheOptions.Options' => '', 'CacheOptions.Modes' => '', ); $availableSettings = array( __('disabled', 'sucuri-scanner'), __('static', 'sucuri-scanner'), __('occasional', 'sucuri-scanner'), __('frequent', 'sucuri-scanner'), __('busy', 'sucuri-scanner'), __('custom', 'sucuri-scanner'), ); $headersCacheControlOptions = SucuriScanOption::getOption(':headers_cache_control_options'); foreach ($availableSettings as $mode) { $params['CacheOptions.Modes'] .= sprintf('', $mode, ucfirst($mode)); } if (SucuriScanInterface::checkNonce() && SucuriScanRequest::post(':update_cache_options')) { $headerCacheControlMode = sanitize_text_field(SucuriScanRequest::post(':cache_options_mode')); $newOptions = array(); foreach ($headersCacheControlOptions as $pageType => $options) { $newOptions[$pageType] = array(); foreach ($options as $optionName => $defaultValue) { $postKey = 'sucuriscan_' . $pageType . '_' . $optionName; $postValue = sanitize_text_field(SucuriScanRequest::post($postKey)); if (isset($_POST[$postKey])) { if ($postValue === 'unavailable' || $postValue === '') { $newOptions[$pageType][$optionName] = 'unavailable'; } else { $newOptions[$pageType][$optionName] = intval($postValue); } } else { $newOptions[$pageType][$optionName] = $defaultValue; } } } if (in_array($headerCacheControlMode, $availableSettings)) { SucuriScanOption::updateOption(':headers_cache_control', $headerCacheControlMode); SucuriScanOption::updateOption(':headers_cache_control_options', $newOptions); if ($headerCacheControlMode === 'disabled') { SucuriScanInterface::info(__('Cache-Control header was deactivated.', 'sucuri-scanner')); } else { SucuriScanInterface::info(__('Cache-Control header was activated.', 'sucuri-scanner')); } } else { SucuriScanInterface::error(__('Invalid cache control mode selected.', 'sucuri-scanner')); } } $latestHeadersCacheControlOptions = SucuriScanOption::getOption(':headers_cache_control_options'); foreach ($latestHeadersCacheControlOptions as $option) { if (!$isWooCommerceActive && in_array($option['id'], array('woocommerce_products', 'woocommerce_categories'))) { continue; } $params['CacheOptions.Options'] .= SucuriScanTemplate::getSnippet( 'settings-headers-cache-option', array( 'id' => $option['id'], 'name' => $option['title'], 'maxAge' => $option['max_age'], 'sMaxAge' => $option['s_maxage'], 'staleIfError' => $option['stale_if_error'], 'staleWhileRevalidate' => $option['stale_while_revalidate'], 'paginationFactor' => $option['pagination_factor'], 'paginationFactorVisibility' => $option['pagination_factor'] !== 'unavailable' ? 'visible' : 'hidden', 'oldAgeMultiplier' => $option['old_age_multiplier'], 'oldAgeMultiplierVisibility' => $option['old_age_multiplier'] !== 'unavailable' ? 'visible' : 'hidden', ) ); } $headersCacheControlMode = SucuriScanOption::getOption(':headers_cache_control'); $isCacheControlHeaderDisabled = $headersCacheControlMode === 'disabled'; $params['CacheOptions.NoItemsVisibility'] = 'hidden'; $params['CacheOptions.CacheControl'] = $isCacheControlHeaderDisabled ? 0 : 1; $params['CacheOptions.Status'] = $isCacheControlHeaderDisabled ? __('Disabled', 'sucuri-scanner') : __('Enabled', 'sucuri-scanner'); $params['CacheOptions.Modes'] = str_replace('option value="' . $headersCacheControlMode . '"', 'option value="' . $headersCacheControlMode . '" selected', $params['CacheOptions.Modes']); return SucuriScanTemplate::getSection('settings-headers-cache', $params); } src/settings-integrity.php000060400000012577147177152050011741 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Settings for the WordPress integrity scanner. * * Generates the HTML code to display a list of options in the settings page to * allow the website owner to configure the functionality of the WordPress core * integrity scanner and the optional Unix diff utility. This also includes some * options to configure the website installation language and the false positive * cache file. * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ class SucuriScanSettingsIntegrity extends SucuriScanSettings { /** * Configures the diffUtility for the integrity scanner. * * @param bool $nonce True if the CSRF protection worked, false otherwise. * @return string HTML code to render the configuration panel. */ public static function diffUtility($nonce) { $params = array(); $params['DiffUtility.StatusNum'] = 0; $params['DiffUtility.Status'] = 'Disabled'; $params['DiffUtility.SwitchText'] = 'Enable'; $params['DiffUtility.SwitchValue'] = 'enable'; if ($nonce) { // Enable or disable the Unix diff utility. $status = SucuriScanRequest::post(':diff_utility', '(en|dis)able'); if ($status) { if (!SucuriScanCommand::exists('diff')) { SucuriScanInterface::error(__('Your hosting provider has blocked the execution of external commands.', 'sucuri-scanner')); } else { $status = $status . 'd'; /* add past tense */ $message = sprintf(__('Integrity diff utility has been %s', 'sucuri-scanner'), $status); SucuriScanOption::updateOption(':diff_utility', $status); SucuriScanEvent::reportInfoEvent($message); SucuriScanEvent::notifyEvent('plugin_change', $message); SucuriScanInterface::info(__('The status of the integrity diff utility has been changed', 'sucuri-scanner')); } } } if (SucuriScanOption::isEnabled(':diff_utility')) { $params['DiffUtility.StatusNum'] = 1; $params['DiffUtility.Status'] = __('Enabled', 'sucuri-scanner'); $params['DiffUtility.SwitchText'] = __('Disable', 'sucuri-scanner'); $params['DiffUtility.SwitchValue'] = 'disable'; } return SucuriScanTemplate::getSection('settings-scanner-integrity-diff-utility', $params); } /** * Configures the cache for the integrity scanner. * * @param bool $nonce True if the CSRF protection worked, false otherwise. * @return string HTML code to render the configuration panel. */ public static function cache($nonce) { $params = array(); $cache = new SucuriScanCache('integrity'); $fpath = SucuriScan::dataStorePath('sucuri-integrity.php'); if ($nonce && SucuriScanRequest::post(':reset_integrity_cache')) { $deletedFiles = array(); $files = SucuriScanRequest::post(':corefile_path', '_array'); foreach ((array) $files as $path) { if ($cache->delete(md5($path))) { $deletedFiles[] = $path; } } if (!empty($deletedFiles)) { SucuriScanEvent::reportDebugEvent( sprintf(__('Core files that will not be ignored anymore: (multiple entries): %s', 'sucuri-scanner'), implode(',', $deletedFiles)) ); SucuriScanInterface::info(__('The selected files have been successfully processed.', 'sucuri-scanner')); } } $params['IgnoredFiles'] = ''; $params['CacheSize'] = SucuriScan::humanFileSize(@filesize($fpath)); $params['CacheLifeTime'] = SUCURISCAN_SITECHECK_LIFETIME; $params['NoFilesVisibility'] = 'visible'; $ignored_files = $cache->getAll(); if (is_array($ignored_files) && !empty($ignored_files)) { $params['NoFilesVisibility'] = 'hidden'; foreach ($ignored_files as $hash => $data) { $params['IgnoredFiles'] .= SucuriScanTemplate::getSnippet( 'settings-scanner-integrity-cache', array( 'UniqueId' => substr($hash, 0, 8), 'FilePath' => $data->file_path, 'StatusType' => $data->file_status, 'IgnoredAt' => SucuriScan::datetime($data->ignored_at), ) ); } } return SucuriScanTemplate::getSection('settings-scanner-integrity-cache', $params); } } src/settings.php000060400000001663147177152050007717 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Abstract class for the settings page. * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ class SucuriScanSettings extends SucuriScanOption { } src/settings-posthack.php000060400000053007147177152050011530 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Tools to execute after a hack attempt. * * The plugin allows to execute some tools that will clear up the site after a * suspicious activity. This includes the ability to reset the secret security * keys, the password for each user account, and the installed plugins. * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ class SucuriScanSettingsPosthack extends SucuriScanSettings { /** * Update the WordPress secret keys. * * @return string HTML code with the information of the process. */ public static function securityKeys() { $params = array(); $params['SecurityKeys.List'] = ''; $params['WPConfigUpdate.NewConfig'] = ''; $params['WPConfigUpdate.Visibility'] = 'hidden'; // Update all WordPress secret keys. if (SucuriScanInterface::checkNonce() && SucuriScanRequest::post(':update_wpconfig')) { if (SucuriScanRequest::post(':process_form') != 1) { SucuriScanInterface::error(__('You need to confirm that you understand the risk of this operation.', 'sucuri-scanner')); } else { $wpconfig_process = SucuriScanEvent::setNewConfigKeys(); if (!$wpconfig_process) { SucuriScanInterface::error(__('WordPress configuration file was not found or new keys could not be created.', 'sucuri-scanner')); } elseif ($wpconfig_process['updated']) { SucuriScanEvent::reportNoticeEvent(__('Generate new security keys (success)', 'sucuri-scanner')); SucuriScanInterface::info(__('Secret keys updated successfully (summary of the operation bellow).', 'sucuri-scanner')); $params['WPConfigUpdate.Visibility'] = 'visible'; $params['WPConfigUpdate.NewConfig'] .= sprintf("/* %s */\n", __('Old Security Keys', 'sucuri-scanner')); $params['WPConfigUpdate.NewConfig'] .= $wpconfig_process['old_keys_string']; $params['WPConfigUpdate.NewConfig'] .= "\n"; $params['WPConfigUpdate.NewConfig'] .= sprintf("/* %s */\n", __('New Security Keys', 'sucuri-scanner')); $params['WPConfigUpdate.NewConfig'] .= $wpconfig_process['new_keys_string']; } else { SucuriScanEvent::reportNoticeEvent(__('Generate new security keys (failure)', 'sucuri-scanner')); SucuriScanInterface::error(__('WordPress configuration file is not writable.', 'sucuri-scanner')); $params['WPConfigUpdate.Visibility'] = 'visible'; $params['WPConfigUpdate.NewConfig'] = $wpconfig_process['new_wpconfig']; } } } // Display the current status of the security keys. $current_keys = SucuriScanOption::getSecurityKeys(); foreach ($current_keys as $key_status => $key_list) { foreach ($key_list as $key_name => $key_value) { switch ($key_status) { case 'good': $key_status_text = 'good'; break; case 'bad': $key_status_text = 'not randomized'; break; case 'missing': $key_value = ''; $key_status_text = '(not set)'; break; } if (isset($key_status_text)) { $params['SecurityKeys.List'] .= SucuriScanTemplate::getSnippet( 'settings-posthack-security-keys', array( 'SecurityKey.KeyName' => $key_name, 'SecurityKey.KeyValue' => $key_value, 'SecurityKey.KeyStatusText' => $key_status_text, ) ); } } } // Automatic Secret Keys Updater $cronName = 'sucuriscan_autoseckeyupdater'; $params['SecurityKeys.AutoStatusNum'] = 0; $params['SecurityKeys.AutoStatus'] = "Disabled"; $params['SecurityKeys.Schedules'] = ''; $availableSchedules = array('disabled', 'daily', 'weekly', 'monthly', 'quarterly'); // Populate frequency selection box foreach ($availableSchedules as $freq) { $params['SecurityKeys.Schedules'] .= sprintf('', $freq, ucfirst($freq)); } // Set to enabled if cron is found if (wp_next_scheduled($cronName)) { $params['SecurityKeys.AutoStatusNum'] = 1; $params['SecurityKeys.AutoStatus'] = "Enabled"; } // Activate/Deactivate the Automatic Secret Keys Updater if (SucuriScanInterface::checkNonce() && SucuriScanRequest::post(':autoseckeyupdater')) { $cronFrequency = SucuriScanRequest::post(':autoseckeyupdater_frequency'); // Deny action if cron frequency is invalid if (empty($cronFrequency) || !in_array($cronFrequency, $availableSchedules)) { SucuriScanInterface::error(__('No frequency selected for the automatic secret key updater.', 'sucuri-scanner')); } elseif ($cronFrequency === "disabled") { // Disable Automatic Secret Keys Updater if (SucuriScanEvent::deleteScheduledTask($cronName)) { $params['SecurityKeys.Schedules'] = str_replace('option value="'.$cronFrequency.'"', 'option value="'.$cronFrequency.'" selected', $params['SecurityKeys.Schedules']); $params['SecurityKeys.AutoStatusNum'] = 0; $params['SecurityKeys.AutoStatus'] = "Disabled"; SucuriScanInterface::info(__('Automatic Secret Keys Updater disabled.', 'sucuri-scanner')); SucuriScanEvent::reportNoticeEvent(__('Automatic Secret Keys Updater disabled.', 'sucuri-scanner')); } else { SucuriScanInterface::error(__('Something went wrong.', 'sucuri-scanner')); } } else { // Enable Automatic Secret Keys Updater if (SucuriScanEvent::addScheduledTask($cronName, $cronFrequency)) { $params['SecurityKeys.Schedules'] = str_replace('option value="'.$cronFrequency.'"', 'option value="'.$cronFrequency.'" selected', $params['SecurityKeys.Schedules']); $params['SecurityKeys.AutoStatusNum'] = 1; $params['SecurityKeys.AutoStatus'] = "Enabled"; SucuriScanInterface::info(__('Automatic Secret Keys Updater enabled.', 'sucuri-scanner')); SucuriScanEvent::reportNoticeEvent(__('Automatic Secret Keys Updater enabled.', 'sucuri-scanner')); } else { SucuriScanInterface::error(__('Something went wrong.', 'sucuri-scanner')); } } } else { // Re-order selection box with the current cron frequency if (wp_next_scheduled($cronName)) { $activeSchedules = SucuriScanEvent::activeSchedules(); if ( isset($activeSchedules[$cronName]) && isset($activeSchedules[$cronName]['schedule'])) { $currentCronFrequency = $activeSchedules[$cronName]['schedule']; $params['SecurityKeys.Schedules'] = str_replace('option value="'.$currentCronFrequency.'"', 'option value="'.$currentCronFrequency.'" selected', $params['SecurityKeys.Schedules']); } } } return SucuriScanTemplate::getSection('settings-posthack-security-keys', $params); } /** * Display a list of users in a table that will be used to select the accounts * where a password reset action will be executed. * * @return string HTML code for a table where a list of user accounts will be shown. */ public static function resetPassword() { $params = array(); $session = wp_get_current_user(); $params['ResetPassword.UserList'] = ''; $params['ResetPassword.PaginationLinks'] = ''; $params['ResetPassword.PaginationVisibility'] = 'hidden'; // Fill the user list for ResetPassword action. $user_list = array(); $page_number = SucuriScanTemplate::pageNumber(); $max_per_page = SUCURISCAN_MAX_PAGINATION_BUTTONS; $dbquery = new WP_User_Query( array( 'number' => $max_per_page, 'offset' => ($page_number - 1) * $max_per_page, 'fields' => 'all_with_meta', 'orderby' => 'ID', ) ); // Retrieve the results and build the pagination links. if ($dbquery) { $total_items = $dbquery->get_total(); $user_list = $dbquery->get_results(); $params['ResetPassword.PaginationLinks'] = SucuriScanTemplate::pagination( '%%SUCURI.URL.Settings%%#posthack', $total_items, $max_per_page ); if ($total_items > $max_per_page) { $params['ResetPassword.PaginationVisibility'] = 'visible'; } } if ($user_list) { foreach ($user_list as $user) { $user->user_registered_timestamp = strtotime($user->user_registered); $user->user_registered_formatted = SucuriScan::datetime($user->user_registered_timestamp); $disabled = ($user->user_login == $session->user_login) ? 'disabled' : ''; $params['ResetPassword.UserList'] .= SucuriScanTemplate::getSnippet( 'settings-posthack-reset-password', array( 'ResetPassword.UserID' => $user->ID, 'ResetPassword.Username' => $user->user_login, 'ResetPassword.Email' => $user->user_email, 'ResetPassword.Registered' => $user->user_registered_formatted, 'ResetPassword.Roles' => @implode(', ', $user->roles), 'ResetPassword.Disabled' => $disabled, ) ); } } return SucuriScanTemplate::getSection('settings-posthack-reset-password', $params); } /** * Sets a new password for the specified user account. * * @return void */ public static function resetPasswordAjax() { if (SucuriScanRequest::post('form_action') !== 'reset_user_password') { return; } $response = 'Error'; $user_id = intval(SucuriScanRequest::post('user_id')); if (SucuriScanEvent::setNewPassword($user_id)) { $response = 'Done'; SucuriScanEvent::reportNoticeEvent(sprintf(__('Password changed for user #%d', 'sucuri-scanner'), $user_id)); } wp_send_json($response, 200); } /** * Reset all the FREE plugins, even if they are not activated. * * @return void */ public static function resetPlugins() { $params = array( 'ResetPlugin.PluginList' => '', 'ResetPlugin.CacheLifeTime' => 'unknown', ); if (defined('SUCURISCAN_GET_PLUGINS_LIFETIME')) { $params['ResetPlugin.CacheLifeTime'] = SUCURISCAN_GET_PLUGINS_LIFETIME; } return SucuriScanTemplate::getSection('settings-posthack-reset-plugins', $params); } /** * Find and list available updates for plugins and themes. * * @return void */ public static function availableUpdates() { $params = array(); return SucuriScanTemplate::getSection('settings-posthack-available-updates', $params); } /** * Process the Ajax request to retrieve the plugins metadata. * * @return void */ public static function getPluginsAjax() { if (SucuriScanRequest::post('form_action') !== 'get_plugins_data') { return; } $response = ''; $allPlugins = SucuriScanAPI::getPlugins(); foreach ($allPlugins as $plugin_path => $plugin_data) { $plugin_type_class = ($plugin_data['PluginType'] == 'free') ? 'primary' : 'warning'; $input_disabled = ($plugin_data['PluginType'] == 'free') ? '' : 'disabled="disabled"'; $plugin_status_class = $plugin_data['IsPluginActive'] ? 'success' : 'default'; $plugin_status = $plugin_data['IsPluginActive'] ? 'active' : 'not active'; $response .= SucuriScanTemplate::getSnippet( 'settings-posthack-reset-plugins', array( 'ResetPlugin.Disabled' => $input_disabled, 'ResetPlugin.Path' => $plugin_path, 'ResetPlugin.Unique' => crc32($plugin_path), 'ResetPlugin.Repository' => $plugin_data['Repository'], 'ResetPlugin.Plugin' => SucuriScan::excerpt($plugin_data['Name'], 60), 'ResetPlugin.Version' => $plugin_data['Version'], 'ResetPlugin.Type' => $plugin_data['PluginType'], 'ResetPlugin.TypeClass' => $plugin_type_class, 'ResetPlugin.Status' => $plugin_status, 'ResetPlugin.StatusClass' => $plugin_status_class, ) ); } wp_send_json($response, true); } /** * Process the Ajax request to reset one free plugin. * * @return void */ public static function resetPluginAjax() { if (SucuriScanRequest::post('form_action') !== 'reset_plugin') { return; } $response = ''; /* request response */ $plugin = SucuriScanRequest::post(':plugin_name'); $allPlugins = SucuriScanAPI::getPlugins(); /* Check if the plugin actually exists */ if (!array_key_exists($plugin, $allPlugins)) { $response = '' . __('not installed', 'sucuri-scanner') . ''; } elseif ($allPlugins[$plugin]['IsFreePlugin'] !== true) { // Ignore plugins not listed in the WordPress repository. // This usually applies to premium plugins. They cannot be downloaded from // a reliable source because we can't check the checksum of the files nor // we can verify if the installation of the new code will work or not. $response = '' . __('Plugin is Premium', 'sucuri-scanner') . ''; } elseif (!is_writable($allPlugins[$plugin]['InstallationPath'])) { $response = '' . __('Not Writable', 'sucuri-scanner') . ''; } elseif (!class_exists('SucuriScanPluginInstallerSkin')) { $response = '' . __('Missing Library', 'sucuri-scanner') . ''; } else { // Get data associated to the plugin. $data = $allPlugins[$plugin]; $info = SucuriScanAPI::getRemotePluginData($data['RepositoryName']); $hash = substr(md5(microtime(true)), 0, 8); $newpath = $data['InstallationPath'] . '_' . $hash; if (!$info) { $response = '' . __('Cannot Download', 'sucuri-scanner') . ''; } elseif (!rename($data['InstallationPath'], $newpath)) { $response = '' . __('Cannot Backup', 'sucuri-scanner') . ''; } else { ob_start(); $upgrader_skin = new SucuriScanPluginInstallerSkin(); $upgrader = new Plugin_Upgrader($upgrader_skin); $upgrader->install($info['download_link']); $output = ob_get_contents(); ob_end_clean(); if (!file_exists($data['InstallationPath'])) { /* Revert backup to its original location */ @rename($newpath, $data['InstallationPath']); $response = '' . __('Cannot Install', 'sucuri-scanner') . ''; } else { /* Destroy the backup of the plugin */ $fifo = new SucuriScanFileInfo(); $fifo->ignore_files = false; $fifo->ignore_directories = false; $fifo->skip_directories = false; $fifo->removeDirectoryTree($newpath); $installed = sprintf(__('Installed v%s', 'sucuri-scanner'), SucuriScan::escape($info['version'])); $response = '' . $installed . ''; } } } wp_send_json($response, 200); } /** * Retrieve the information for the available updates. * * @param bool $send_email Sends the available updates via email. * @return string|bool HTML code for a table with the updates information. */ public static function availableUpdatesContent($send_email = false) { if (!function_exists('wp_update_plugins') || !function_exists('get_plugin_updates') || !function_exists('wp_update_themes') || !function_exists('get_theme_updates') ) { return false; } $response = ''; $result = wp_update_plugins(); $updates = get_plugin_updates(); if (is_array($updates) && !empty($updates)) { foreach ($updates as $data) { $params = array( 'Update.IconType' => 'plugins', 'Update.Extension' => SucuriScan::excerpt($data->Name, 35), 'Update.Version' => $data->Version, 'Update.NewVersion' => 'unknown', 'Update.TestedWith' => 'unknown', 'Update.ArchiveUrl' => 'unknown', 'Update.MarketUrl' => 'unknown', ); if (property_exists($data->update, 'new_version')) { $params['Update.NewVersion'] = $data->update->new_version; } if (property_exists($data->update, 'tested')) { $params['Update.TestedWith'] = "WordPress\x20" . $data->update->tested; } if (property_exists($data->update, 'package')) { $params['Update.ArchiveUrl'] = $data->update->package; } if (property_exists($data->update, 'url')) { $params['Update.MarketUrl'] = $data->update->url; } $response .= SucuriScanTemplate::getSnippet('settings-posthack-available-updates', $params); } } // Check for available theme updates. $result = wp_update_themes(); $updates = get_theme_updates(); if (is_array($updates) && !empty($updates)) { foreach ($updates as $data) { $response .= SucuriScanTemplate::getSnippet( 'settings-posthack-available-updates', array( 'Update.IconType' => 'appearance', 'Update.Extension' => SucuriScan::excerpt($data->Name, 35), 'Update.Version' => $data->Version, 'Update.NewVersion' => $data->update['new_version'], 'Update.TestedWith' => __('Newest WordPress', 'sucuri-scanner'), 'Update.ArchiveUrl' => $data->update['package'], 'Update.MarketUrl' => $data->update['url'], ) ); } } if (!is_string($response) || empty($response)) { return false; } // Send an email notification with the affected files. if ($send_email === true) { $params = array('AvailableUpdates.Content' => $response); $content = SucuriScanTemplate::getSection('settings-posthack-available-updates-alert', $params); $sent = SucuriScanEvent::notifyEvent('available_updates', $content); return $sent; } return $response; } /** * Process the Ajax request to retrieve the available updates. * * @return void */ public static function availableUpdatesAjax() { if (SucuriScanRequest::post('form_action') !== 'get_available_updates') { return; } $response = SucuriScanSettingsPosthack::availableUpdatesContent(); if (!$response) { $response = '' . __('There are no updates available.', 'sucuri-scanner') . ''; } wp_send_json($response, 200); } } src/settings-scanner.php000060400000023307147177152050011345 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Returns the HTML to configure the scanner. * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ class SucuriScanSettingsScanner extends SucuriScanSettings { /** * Renders a page with information about the cronjobs feature. * * @param bool $nonce True if the CSRF protection worked. * @return string Page with information about the cronjobs. */ public static function cronjobs($nonce) { $params = array( 'Cronjob.Schedules' => '', ); if ($nonce) { // Modify the scheduled tasks (run now, remove, re-schedule). $allowed_actions = array_keys(SucuriScanEvent::availableSchedules()); $allowed_actions[] = 'runnow'; /* execute in the next 10 seconds */ $allowed_actions[] = 'remove'; /* can be reinstalled automatically */ $allowed_actions = sprintf('(%s)', implode('|', $allowed_actions)); $cronjob_action = SucuriScanRequest::post(':cronjob_action', $allowed_actions); if ($cronjob_action) { $cronjobs = SucuriScanRequest::post(':cronjobs', '_array'); if (!empty($cronjobs)) { $total_tasks = count($cronjobs); if ($cronjob_action == 'runnow') { /* Force execution of the selected scheduled tasks. */ SucuriScanInterface::info( sprintf( __('%d tasks has been scheduled to run in the next ten seconds.', 'sucuri-scanner'), $total_tasks /* some cronjobs will be ignored */ ) ); SucuriScanEvent::reportNoticeEvent( sprintf( __('Force execution of scheduled tasks: (multiple entries): %s', 'sucuri-scanner'), @implode(',', $cronjobs) ) ); foreach ($cronjobs as $task_name) { wp_schedule_single_event(time() + 10, $task_name); } } elseif ($cronjob_action == 'remove' || $cronjob_action == '_oneoff') { /* Force deletion of the selected scheduled tasks. */ SucuriScanInterface::info( sprintf( __('%d scheduled tasks have been removed.', 'sucuri-scanner'), $total_tasks /* some cronjobs will be ignored */ ) ); SucuriScanEvent::reportNoticeEvent( sprintf( __('Delete scheduled tasks: (multiple entries): %s', 'sucuri-scanner'), @implode(',', $cronjobs) ) ); foreach ($cronjobs as $task_name) { wp_clear_scheduled_hook($task_name); } } else { SucuriScanInterface::info( sprintf( __('%d tasks has been re-scheduled to run %s.', 'sucuri-scanner'), $total_tasks, /* some cronjobs will be ignored */ $cronjob_action /* frequency to run cronjob */ ) ); SucuriScanEvent::reportNoticeEvent( sprintf( __('Re-configure scheduled tasks %s: (multiple entries): %s', 'sucuri-scanner'), $cronjob_action, @implode(',', $cronjobs) ) ); foreach ($cronjobs as $task_name) { $next_due = wp_next_scheduled($task_name); wp_schedule_event($next_due, $cronjob_action, $task_name); } } } else { SucuriScanInterface::error(__('No scheduled tasks were selected from the list.', 'sucuri-scanner')); } } } $available = SucuriScanEvent::availableSchedules(); /* Hardcode the first one to allow the immediate execution of the cronjob(s) */ $params['Cronjob.Schedules'] .= ''; foreach ($available as $freq => $name) { $params['Cronjob.Schedules'] .= sprintf('', $freq, $name); } $hasSPL = SucuriScanFileInfo::isSplAvailable(); $params['NoSPL.Visibility'] = SucuriScanTemplate::visibility(!$hasSPL); return SucuriScanTemplate::getSection('settings-scanner-cronjobs', $params); } /** * Process the Ajax request to retrieve the list of cronjobs. * * @return void */ public static function cronjobsAjax() { if (SucuriScanRequest::post('form_action') !== 'get_cronjobs') { return; } $response = ''; $cronjobs = _get_cron_array(); foreach ($cronjobs as $timestamp => $cronhooks) { foreach ((array) $cronhooks as $hook => $events) { foreach ((array) $events as $key => $event) { if (empty($event['args'])) { $event['args'] = array('[]'); } $response .= SucuriScanTemplate::getSnippet( 'settings-scanner-cronjobs', array( 'Cronjob.Hook' => $hook, 'Cronjob.Schedule' => $event['schedule'], 'Cronjob.NextTime' => SucuriScan::datetime($timestamp), 'Cronjob.NextTimeHuman' => SucuriScan::humanTime($timestamp), 'Cronjob.Arguments' => json_encode($event['args']), ) ); } } } if (!$response) { $response = '' . __('no data available', 'sucuri-scanner') . ''; } wp_send_json($response, 200); } /** * Returns the HTML for the folder scanner skipper. * * If the website has too many files it would be wise to force the plugin to * ignore some directories that are not relevant for the scanner. This includes * directories with media files like images, audio, videos, etc and directories * used to store cache data. * * @param bool $nonce True if the CSRF protection worked, false otherwise. * @return string HTML for the folder scanner skipper. */ public static function ignoreFolders($nonce) { $params = array(); $params['IgnoreScan.List'] = ''; if ($nonce) { $ign_ress = SucuriScanRequest::post(':ignorefolder'); $ign_dirs = SucuriScanRequest::post(':unignorefolders', '_array'); if ($ign_ress !== false && SucuriScanFSScanner::ignoreDirectory($ign_ress)) { SucuriScanInterface::info(__('Selected files have been successfully processed.', 'sucuri-scanner')); SucuriScanEvent::reportWarningEvent(sprintf(__('This directory will not be scanned: %s', 'sucuri-scanner'), $ign_ress)); } if ($ign_dirs !== false && is_array($ign_dirs) && !empty($ign_dirs)) { foreach ($ign_dirs as $dir) { SucuriScanFSScanner::unignoreDirectory($dir); } SucuriScanInterface::info(__('Selected files have been successfully processed.', 'sucuri-scanner')); SucuriScanEvent::reportNoticeEvent( __('Directories will be scanned: (multiple entries): ', 'sucuri-scanner') . @implode(',', $ign_dirs) /* all directories */ ); } } $ignored_dirs = SucuriScanFSScanner::getIgnoredDirectories(); foreach ($ignored_dirs['directories'] as $index => $folder) { $ts = $ignored_dirs['ignored_at_list'][$index]; $params['IgnoreScan.List'] .= SucuriScanTemplate::getSnippet( 'settings-scanner-ignore-folders', array( 'IgnoreScan.Directory' => $folder, 'IgnoreScan.IgnoredAt' => SucuriScan::datetime($ts), ) ); } if (empty($ignored_dirs['directories'])) { $params['IgnoreScan.List'] .= '' . __('no data available', 'sucuri-scanner') . ''; } return SucuriScanTemplate::getSection('settings-scanner-ignore-folders', $params); } } src/settings-webinfo.php000060400000013057147177152050011346 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Gather information from the server, database engine, and PHP interpreter. * * @return string HTML for the system info page. */ function sucuriscan_settings_webinfo_details() { $params = array(); $info_vars = array( 'Plugin_version' => SUCURISCAN_VERSION, 'Last_filesystem_scan' => SucuriScanFSScanner::getFilesystemRuntime(true), 'Datetime_and_Timezone' => '', 'Operating_system' => sprintf('%s (%d Bit)', PHP_OS, PHP_INT_SIZE * 8), 'Server' => 'unknown', 'WordPress_debug' => __('not active', 'sucuri-scanner'), 'Memory_usage' => __('unknown', 'sucuri-scanner'), 'PHP_version' => PHP_VERSION, ); $params['ServerInfo.Variables'] = ''; $info_vars['Datetime_and_Timezone'] = sprintf( '%s (%s)', SucuriScan::datetime(), SucuriScanOption::getOption(':timezone') ); if (defined('WP_DEBUG') && WP_DEBUG) { $info_vars['WordPress_debug'] = __('active', 'sucuri-scanner'); } if (function_exists('memory_get_usage')) { $info_vars['Memory_usage'] = round(memory_get_usage() / 1024 / 1024, 2).' MB'; } if (isset($_SERVER['SERVER_SOFTWARE'])) { $info_vars['Server'] = $_SERVER['SERVER_SOFTWARE']; } /* PHP INI Settings */ $field_names = array( 'safe_mode', 'expose_php', 'allow_url_fopen', 'memory_limit', 'upload_max_filesize', 'post_max_size', 'max_execution_time', 'max_input_time', ); foreach ($field_names as $php_flag) { $php_flag_value = SucuriScan::iniGet($php_flag); $php_flag_name = 'PHP_' . $php_flag; $info_vars[$php_flag_name] = $php_flag_value ? $php_flag_value : 'N/A'; } /* PHP constants */ $constants = array( 'ABSPATH', // 'SUCURISCAN', // 'SUCURISCAN_INIT', 'SUCURISCAN_API_URL', 'SUCURI_DATA_STORAGE', // 'SUCURISCAN_ADMIN_INIT', 'SUCURISCAN_GET_PLUGINS_LIFETIME', 'SUCURISCAN_THROW_EXCEPTIONS', ); foreach ($constants as $name) { $info_vars[$name] = defined($name) ? constant($name) : '--'; } foreach ($info_vars as $var_name => $var_value) { $var_name = str_replace('_', "\x20", $var_name); $params['ServerInfo.Variables'] .= SucuriScanTemplate::getSnippet( 'settings-webinfo-details', array( 'ServerInfo.Title' => $var_name, 'ServerInfo.Value' => $var_value, ) ); } return SucuriScanTemplate::getSection('settings-webinfo-details', $params); } /** * Find the main htaccess file for the site and check whether the rules of the * main htaccess file of the site are the default rules generated by WordPress. * * @return string The HTML code displaying the information about the HTAccess rules. */ function sucuriscan_settings_webinfo_htaccess() { $htaccess = SucuriScan::getHtaccessPath(); $params = array( 'HTAccess.Content' => '', 'HTAccess.TextareaVisible' => 'hidden', 'HTAccess.StandardVisible' => 'hidden', 'HTAccess.NotFoundVisible' => 'hidden', 'HTAccess.NotApache' => 'hidden', 'HTAccess.FoundVisible' => 'hidden', 'HTAccess.Fpath' => 'unknown', ); // If it's not Apache, do not based the analysis on htaccess file. if (SucuriScan::isNginxServer() || SucuriScan::isIISServer()) { $params['HTAccess.NotApache'] = 'visible'; } elseif ($htaccess) { $rules = SucuriScanFileInfo::fileContent($htaccess); $params['HTAccess.TextareaVisible'] = 'visible'; $params['HTAccess.Content'] = $rules; $params['HTAccess.Fpath'] = $htaccess; $params['HTAccess.FoundVisible'] = 'visible'; if (sucuriscan_htaccess_is_standard($rules)) { $params['HTAccess.StandardVisible'] = 'visible'; } } else { $params['HTAccess.NotFoundVisible'] = 'visible'; } return SucuriScanTemplate::getSection('settings-webinfo-htaccess', $params); } /** * Check if the standard rules for a normal WordPress installation (not network * based) are inside the main htaccess file. This only applies to websites that * have permalinks enabled, or 3rd-party plugins that require custom rules * (generally based on mod_deflate) to compress and/or generate static files for * cache. * * @param string $rules Content of the main htaccess file. * @return bool True if the htaccess has the standard rules, false otherwise. */ function sucuriscan_htaccess_is_standard($rules = '') { if (!$rules) { $htaccess = SucuriScan::getHtaccessPath(); if ($htaccess) { $rules = SucuriScanFileInfo::fileContent($htaccess); } } if (class_exists('WP_Rewrite') && is_string($rules) && !empty($rules)) { $rewrite = new WP_Rewrite(); $standard = $rewrite->mod_rewrite_rules(); if (!empty($standard)) { return (bool) (strpos($rules, $standard) !== false); } } return false; } src/sitecheck.lib.php000060400000046326147177152050010573 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Controls the execution of the SiteCheck scanner. * * SiteCheck is a web application scanner that reads the source code of a * website to determine if it is serving malicious code, it scans the home page * and linked sub-pages, then compares the results with a list of signatures as * well as a list of blocklist services to see if other malware scanners have * flagged the website before. This operation may take a couple of seconds, * around twenty seconds in most cases; be sure to set enough timeout for the * operation to finish, otherwise the scanner will return innacurate * information. * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner * @see https://sitecheck.sucuri.net/ */ class SucuriScanSiteCheck extends SucuriScanAPI { /** * Returns the URL that will be scanned by SiteCheck. * * @return string URL to be scanned. */ private static function targetURL() { /* allow to set a custom URL for the scans */ $custom = SucuriScanOption::getOption(':sitecheck_target'); if ($custom) { return $custom; } return SucuriScan::getDomain(); } /** * Executes a malware scan against the specified website. * * @see https://sitecheck.sucuri.net/ * * @param bool $clear Request the results from a fresh scan or not. * @return array|bool JSON encoded website scan results. */ public static function runMalwareScan($clear = false) { $params = array(); $params['json'] = 1; $params['fromwp'] = 2; $params['scan'] = self::targetURL(); /* force clear scan */ if ($clear === true) { $params['clear'] = 1; } $args = array('assoc' => true, 'timeout' => 60); return self::apiCall('https://sitecheck.sucuri.net/', 'GET', $params, $args); } /** * Scans a website for malware using SiteCheck. * * This method will first check if the scan results have been cached by a * previous scan. The lifetime of the cache is defined in the global script * but usually it should not be higher than fifteen minutes. If the cache * exists it will be used to display the information in the dashboard. * * If the cache does not exists or has already expired, it will send a HTTP * request to the SiteCheck API service to execute a fresh scan, this takes * around twenty seconds, it will decode and process the response and render * the results in the dashboard. * * If the user sends a GET parameter named "s" with a valid domain name, it * will be used instead of the one of the current website. This is useful if * you want to test the functionality of the scanner in a different website * without access to its domain, which is basically the same thing that you * can do in the official SiteCheck website. This parameter also bypasses * the cache. * * @return array|bool SiteCheck scan results. */ public static function scanAndCollectData() { $cache = new SucuriScanCache('sitecheck'); if (SucuriScanRequest::post(':sitecheck_refresh') === 'true') { /* user requested to reset the sitecheck cache */ $cache->delete('scan_results'); } $results = $cache->get('scan_results', SUCURISCAN_SITECHECK_LIFETIME, 'array'); /* return cached malware scan results. */ if ($results && !empty($results)) { return $results; } /* delete expired cache */ $cache->delete('scan_results'); /* send HTTP request to SiteCheck's API service. */ $results = self::runMalwareScan(true); /* check for error in the request's response. */ if (is_string($results) || isset($results['SYSTEM']['ERROR'])) { if (isset($results['SYSTEM']['ERROR'])) { $results = implode("\x20", $results['SYSTEM']['ERROR']); } return SucuriScanInterface::error('SiteCheck error: ' . $results); } /* cache the results for some time. */ $cache->add('scan_results', $results); return $results; } /** * Returns the amount of time left before the SiteCheck cache expires. * * @return string Time left before the SiteCheck cache expires. */ private static function cacheLifetime() { $current = time(); $cache = new SucuriScanCache('sitecheck'); $timeDiff = $current - $cache->updatedAt(); $timeLeft = SUCURISCAN_SITECHECK_LIFETIME - $timeDiff; return self::humanTime($current + $timeLeft); } /** * Generates the HTML section for the SiteCheck details. * * @return string HTML code to render the details section. */ public static function details() { $params = array(); $data = self::scanAndCollectData(); $data['details'] = array(); $params['SiteCheck.Metadata'] = ''; $params['SiteCheck.Lifetime'] = self::cacheLifetime(); $data['details'][] = sprintf(__('PHP Version: %s', 'sucuri-scanner'), phpversion()); $data['details'][] = sprintf(__('Version: %s', 'sucuri-scanner'), SucuriScan::siteVersion()); if (isset($data['SCAN']['SITE'])) { $params['SiteCheck.Website'] = $data['SCAN']['SITE'][0]; } if (isset($data['SCAN']['IP'])) { $params['SiteCheck.ServerAddress'] = $data['SCAN']['IP'][0]; } if (isset($data['SCAN']['HOSTING'])) { $data['details'][] = sprintf(__('Hosting: %s', 'sucuri-scanner'), apply_filters( 'sucuriscan_sitecheck_details_hosting', $data['SCAN']['HOSTING'][0] )); } if (isset($data['SCAN']['CMS'])) { $data['details'][] = sprintf(__('CMS: %s', 'sucuri-scanner'), $data['SCAN']['CMS'][0]); } if (isset($data['SYSTEM']['NOTICE'])) { $data['details'] = array_merge( $data['details'], $data['SYSTEM']['NOTICE'] ); } if (isset($data['SYSTEM']['INFO'])) { $data['details'] = array_merge( $data['details'], $data['SYSTEM']['INFO'] ); } if (isset($data['WEBAPP']['VERSION'])) { $data['details'] = array_merge( $data['details'], $data['WEBAPP']['VERSION'] ); } if (isset($data['WEBAPP']['WARN'])) { $data['details'] = array_merge( $data['details'], $data['WEBAPP']['WARN'] ); } if (isset($data['OUTDATEDSCAN'])) { foreach ($data['OUTDATEDSCAN'] as $outdated) { if (isset($outdated[0]) && isset($outdated[2])) { $data['details'][] = $outdated[0] . ':' . $outdated[2]; } } } foreach ($data['details'] as $text) { $parts = explode(':', $text, 2); if (count($parts) === 2) { /* prefer local version number over SiteCheck's */ if (strpos($parts[0], 'WordPress version') !== false) { continue; } /* redundant; we already know the CMS is WordPress */ if (strpos($parts[0], 'CMS') !== false) { continue; } $params['SiteCheck.Metadata'] .= SucuriScanTemplate::getSnippet( 'sitecheck-details', array( 'SiteCheck.Title' => trim($parts[0]), 'SiteCheck.Value' => trim($parts[1]), ) ); } } return SucuriScanTemplate::getSection('sitecheck-details', $params); } /** * Generates the HTML section for the SiteCheck malware. * * @return string HTML code to render the malware section. */ public static function malware() { $params = array(); $data = self::scanAndCollectData(); $params['Malware.Content'] = ''; $params['Malware.Color'] = 'green'; $params['Malware.Title'] = __('Site is Clean', 'sucuri-scanner'); $params['Malware.CleanVisibility'] = 'visible'; $params['Malware.InfectedVisibility'] = 'hidden'; if (isset($data['MALWARE']['WARN']) && !empty($data['MALWARE']['WARN'])) { $params['Malware.Color'] = 'red'; $params['Malware.Title'] = __('Site is not Clean', 'sucuri-scanner'); $params['Malware.CleanVisibility'] = 'hidden'; $params['Malware.InfectedVisibility'] = 'visible'; foreach ($data['MALWARE']['WARN'] as $mal) { $info = self::malwareDetails($mal); if ($info) { $params['Malware.Content'] .= SucuriScanTemplate::getSnippet( 'sitecheck-malware', array( 'Malware.InfectedURL' => $info['infected_url'], 'Malware.MalwareType' => $info['malware_type'], 'Malware.MalwareDocs' => $info['malware_docs'], 'Malware.AlertMessage' => $info['alert_message'], 'Malware.MalwarePayload' => $info['malware_payload'], ) ); } } } return SucuriScanTemplate::getSection('sitecheck-malware', $params); } /** * Generates the HTML section for the SiteCheck blocklist. * * @return string HTML code to render the blocklist section. */ public static function blocklist() { $params = array(); $data = self::scanAndCollectData(); if (!isset($data['BLACKLIST']) || !is_array($data['BLACKLIST'])) { return ''; /* there is not enough information to render */ } $params['Blocklist.Title'] = __('Not blocklisted', 'sucuri-scanner'); $params['Blocklist.Color'] = 'green'; $params['Blocklist.Content'] = ''; foreach ($data['BLACKLIST'] as $type => $proof) { foreach ($proof as $info) { $url = $info[1]; $title = @preg_replace( '/Domain (clean|blacklisted) (on|by) (the )?/', '' /* remove unnecessary text from the output */, substr($info[0], 0, strrpos($info[0], ':')) ); $params['Blocklist.Content'] .= SucuriScanTemplate::getSnippet( 'sitecheck-blocklist', array( 'Blocklist.URL' => $url, 'Blocklist.Status' => $type, 'Blocklist.Service' => $title, ) ); } } if (isset($data['BLACKLIST']['WARN'])) { $params['Blocklist.Title'] = __('In the blocklist', 'sucuri-scanner'); $params['Blocklist.Color'] = 'red'; } return SucuriScanTemplate::getSection('sitecheck-blocklist', $params); } /** * Generates the HTML section for the SiteCheck recommendations. * * @return string HTML code to render the recommendations section. */ public static function recommendations() { $data = self::scanAndCollectData(); if (!isset($data['RECOMMENDATIONS'])) { return; } $params = array(); $params['Recommendations.Content'] = ''; $params['Recommendations.Color'] = 'blue'; foreach ($data['RECOMMENDATIONS'] as $recommendation) { if (count($recommendation) < 3) { continue; } $params['Recommendations.Content'] .= SucuriScanTemplate::getSnippet( 'sitecheck-recommendations', array( 'Recommendations.Title' => $recommendation[0], 'Recommendations.Value' => $recommendation[1], 'Recommendations.URL' => $recommendation[2], ) ); } return SucuriScanTemplate::getSection('sitecheck-recommendations', $params); } /** * Returns the title for the iFrames section. * * @return string Title for the iFrames section. */ public static function iFramesTitle() { $data = self::scanAndCollectData(); $niframes = isset($data['LINKS']['IFRAME']) && is_array($data['LINKS']['IFRAME']) ? count($data['LINKS']['IFRAME']) : 0; return sprintf(__('iFrames: %d', 'sucuri-scanner'), $niframes); } /** * Returns the title for the links section. * * @return string Title for the links section. */ public static function linksTitle() { $data = self::scanAndCollectData(); $nlinks = isset($data['LINKS']['URL']) && is_array($data['LINKS']['URL']) ? count($data['LINKS']['URL']) : 0; return sprintf(__('Links: %d', 'sucuri-scanner'), $nlinks); } /** * Returns the title for the scripts section. * * @return string Title for the scripts section. */ public static function scriptsTitle() { $data = self::scanAndCollectData(); $total = 0; /* all type of scripts */ if (isset($data['LINKS']['JSLOCAL'])) { $total += count($data['LINKS']['JSLOCAL']); } if (isset($data['LINKS']['JSEXTERNAL'])) { $total += count($data['LINKS']['JSEXTERNAL']); } return sprintf(__('Scripts: %d', 'sucuri-scanner'), $total); } /** * Returns the content for the iFrames section. * * @return string Content for the iFrames section. */ public static function iFramesContent() { $data = self::scanAndCollectData(); return isset($data['LINKS']['IFRAME']) ? $data['LINKS']['IFRAME'] : array(); } /** * Returns the content for the links section. * * @return string Content for the links section. */ public static function linksContent() { $data = self::scanAndCollectData(); return isset($data['LINKS']['URL']) ? $data['LINKS']['URL'] : array(); } /** * Returns the content for the scripts section. * * @return array Content for the scripts section. */ public static function scriptsContent() { $links = array(); $data = self::scanAndCollectData(); if (isset($data['LINKS']['JSLOCAL'])) { $links = array_merge($links, $data['LINKS']['JSLOCAL']); } if (isset($data['LINKS']['JSEXTERNAL'])) { $links = array_merge($links, $data['LINKS']['JSEXTERNAL']); } return $links; } /** * Extract detailed information from a SiteCheck malware payload. * * @param array $malware Array with two entries with basic malware information. * @return array Detailed information of the malware found by SiteCheck. */ public static function malwareDetails($malware = array()) { if (count($malware) < 2) { return array(/* empty details */); } $data = array( 'alert_message' => '', 'infected_url' => '', 'malware_type' => '', 'malware_docs' => '', 'malware_payload' => '', ); // Extract the information from the alert message. $alert_parts = explode(':', $malware[0], 2); if (isset($alert_parts[1])) { $data['alert_message'] = $alert_parts[0]; $data['infected_url'] = trim($alert_parts[1]); } // Extract the information from the malware message. $malware_parts = explode("\n", $malware[1], 2); if (isset($malware_parts[1])) { $pattern = ".\x20Details:\x20"; if (strpos($malware_parts[0], $pattern) !== false) { $offset = strpos($malware_parts[0], $pattern); $data['malware_type'] = substr($malware_parts[0], 0, $offset); $data['malware_docs'] = substr($malware_parts[0], $offset + 11); } $data['malware_payload'] = trim($malware_parts[1]); } return $data; } /** * Returns a JSON-encoded object with the malware scan results. * * @codeCoverageIgnore - Notice that there is a test case that covers this * code, but since the WP-Send-JSON method uses die() to stop any further * output it means that XDebug cannot cover the next line, leaving a report * with a missing line in the coverage. Since the test case takes care of * the functionality of this code we will assume that it is fully covered. * * @return void */ public static function ajaxMalwareScan() { if (SucuriScanRequest::post('form_action') !== 'malware_scan') { return; } ob_start(); $response = array(); $response['malware'] = SucuriScanSiteCheck::malware(); $response['blocklist'] = SucuriScanSiteCheck::blocklist(); $response['recommendations'] = SucuriScanSiteCheck::recommendations(); $response['iframes'] = array( 'title' => SucuriScanSiteCheck::iFramesTitle(), 'content' => SucuriScanSiteCheck::iFramesContent(), ); $response['links'] = array( 'title' => SucuriScanSiteCheck::linksTitle(), 'content' => SucuriScanSiteCheck::linksContent(), ); $response['scripts'] = array( 'title' => SucuriScanSiteCheck::scriptsTitle(), 'content' => SucuriScanSiteCheck::scriptsContent(), ); $errors = ob_get_clean(); /* capture possible errors */ if (!empty($errors)) { $response['malware'] = ''; $response['blocklist'] = ''; $response['recommendations'] = ''; } wp_send_json($response, 200); } /** * Returns the HTML to configure the API SiteCheck service. * * @return string HTML for the API SiteCheck service option. */ public static function targetURLOption() { $params = array(); if (SucuriScanInterface::checkNonce()) { $custom = SucuriScanRequest::post(':sitecheck_target'); if ($custom !== false) { SucuriScanOption::updateOption(':sitecheck_target', $custom); } } $params['SiteCheck.Target'] = self::targetURL(); return SucuriScanTemplate::getSection('sitecheck-target', $params); } } src/strings.php000060400000137635147177152050007561 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } // auditlogs.html.tpl __('Loading...', 'sucuri-scanner'); __('Total logs in the queue:', 'sucuri-scanner'); __('Maximum execution time:', 'sucuri-scanner'); __('Successfully sent to the API:', 'sucuri-scanner'); __('Total request timeouts (failures):', 'sucuri-scanner'); __('Total execution time:', 'sucuri-scanner'); __('Send Logs', 'sucuri-scanner'); // base.html.tpl __('Sucuri Security', 'sucuri-scanner'); __('WP Plugin', 'sucuri-scanner'); __('Review', 'sucuri-scanner'); __('Generate API Key', 'sucuri-scanner'); __('Dashboard', 'sucuri-scanner'); __('Firewall (WAF)', 'sucuri-scanner'); __('Settings', 'sucuri-scanner'); __('Copyright', 'sucuri-scanner'); __('Sucuri Inc. All Rights Reserved.', 'sucuri-scanner'); __('Help & More', 'sucuri-scanner'); // dashboard.html.tpl __('no data available', 'sucuri-scanner'); __('Audit Logs', 'sucuri-scanner'); // firewall-auditlogs.html.tpl __('Firewall Audit Logs', 'sucuri-scanner'); __('The firewall logs every request involved in an attack and separates them from the legitimate requests. You can analyze the data from the latest entries in the logs using this tool and take action either enabling the advanced features of the IDS (Intrusion Detection System) from the Firewall Dashboard and/or blocking IP addresses and URL paths directly from the Firewall Audit Trails page.', 'sucuri-scanner'); __('Non-blocked requests are hidden from the logs, this is intentional.', 'sucuri-scanner'); __('Loading...', 'sucuri-scanner'); __('Submit', 'sucuri-scanner'); // firewall-auditlogs.snippet.tpl __('Date/Time:', 'sucuri-scanner'); __('Signature:', 'sucuri-scanner'); __('Request:', 'sucuri-scanner'); __('U-Agent:', 'sucuri-scanner'); __('Target:', 'sucuri-scanner'); __('Referer:', 'sucuri-scanner'); // firewall-clearcache.html.tpl __('Loading...', 'sucuri-scanner'); __('Clear cache when a post or page is updated (Loading...)', 'sucuri-scanner'); __('Clear cache when a post or page is updated', 'sucuri-scanner'); __('Clear Cache', 'sucuri-scanner'); __('The firewall offers multiple options to configure the cache level applied to your website. You can either enable the full cache which is the recommended setting, or you can set the cache level to minimal which will keep the pages static for a couple of minutes, or force the usage of the website headers (only for advanced users), or in extreme cases where you do not need the cache you can simply disable it. Find more information about it in the Sucuri Knowledge Base website.', 'sucuri-scanner'); __('Note that the firewall has special caching rules for Images, CSS, PDF, TXT, JavaScript, media files and a few more extensions that are stored on our edge. The only way to flush the cache for these files is by clearing the firewall’s cache completely (for the whole website). Due to our caching of JavaScript and CSS files, often, as is best practice, the use of versioning during development will ensure updates going live as expected. This is done by adding a query string such as ?ver=1.2.3 and incrementing on each update.', 'sucuri-scanner'); __('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. — WikiPedia - Web Cache', 'sucuri-scanner'); // firewall-ipaccess.html.tpl __('Delete', 'sucuri-scanner'); __('Submit', 'sucuri-scanner'); __('Loading...', 'sucuri-scanner'); __('IP Address Access', 'sucuri-scanner'); __('This tool allows you to add one or more IP addresses to the blocklist and stop them from accessing your website.', 'sucuri-scanner'); __('To delete an IP from the blocklist you can use the form below or you can log into the Firewall dashboard.', 'sucuri-scanner'); __('Add IP to the Blocklist:', 'sucuri-scanner'); __('e.g. 192.168.1.54', 'sucuri-scanner'); __('IP Address', 'sucuri-scanner'); // firewall-settings.html.tpl __('Firewall Settings', 'sucuri-scanner'); __('A powerful Web Application Firewall and Intrusion Detection System for any WordPress user and many other platforms. This page will help you to configure and monitor your site through the Sucuri Firewall. Once enabled, our firewall will act as a shield, protecting your site from attacks and preventing malware infections and reinfections. It will block SQL injection attempts, brute force attacks, XSS, RFI, backdoors and many other threats against your site.', 'sucuri-scanner'); __('Add your Firewall API key in the form below to start communicating with the firewall API service.', 'sucuri-scanner'); __('Firewall API Key:', 'sucuri-scanner'); __('Delete', 'sucuri-scanner'); __('Save', 'sucuri-scanner'); __('Name', 'sucuri-scanner'); __('Value', 'sucuri-scanner'); __('[1] More information about the Sucuri Firewall, features and pricing.
    [2] Instructions and videos in the official Knowledge Base site.
    [3] Sign up for a new account and start protecting your site.', 'sucuri-scanner'); // firewall.html.tpl __('Settings', 'sucuri-scanner'); __('Audit Logs', 'sucuri-scanner'); __('IP Access', 'sucuri-scanner'); __('Clear Cache', 'sucuri-scanner'); // integrity-correct.html.tpl __('WordPress Integrity', 'sucuri-scanner'); __('We inspect your WordPress installation and look for modifications on the core files as provided by WordPress.org. Files located in the root directory, wp-admin and wp-includes will be compared against the files distributed with v%%SUCURI.WordPressVersion%%; all files with inconsistencies will be listed here. Any changes might indicate a hack.', 'sucuri-scanner'); __('All Core WordPress Files Are Correct', 'sucuri-scanner'); __('We have not identified additional files, deleted files, or relevant changes to the core files in your WordPress installation. If you are experiencing other malware issues, please use a Server Side Scanner.', 'sucuri-scanner'); __('Review False Positives', 'sucuri-scanner'); // integrity-diff-utility.html.tpl __('Loading...', 'sucuri-scanner'); __('Lines with a minus sign as the prefix (here in red) show the original code. Lines with a plus sign as the prefix (here in green) show the modified code. You can read more about the DIFF format from the WikiPedia article about the Unix Diff Utility.', 'sucuri-scanner'); // integrity-incorrect.html.tpl __('WordPress Integrity', 'sucuri-scanner'); __('We inspect your WordPress installation and look for modifications on the core files as provided by WordPress.org. Files located in the root directory, wp-admin and wp-includes will be compared against the files distributed with v%%SUCURI.WordPressVersion%%; all files with inconsistencies will be listed here. Any changes might indicate a hack.', 'sucuri-scanner'); __('Core WordPress Files Were Modified', 'sucuri-scanner'); __('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 Server Side Scanner.', 'sucuri-scanner'); __('Review False Positives', 'sucuri-scanner'); __('WordPress Integrity (%%SUCURI.Integrity.ListCount%%)', 'sucuri-scanner'); __('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 advised to restore the original content immediately.', 'sucuri-scanner'); __('Select All', 'sucuri-scanner'); __('File Size', 'sucuri-scanner'); __('Modified At', 'sucuri-scanner'); __('File Path', 'sucuri-scanner'); __('I understand that this operation cannot be reverted.', 'sucuri-scanner'); __('Action:', 'sucuri-scanner'); __('Mark as Fixed', 'sucuri-scanner'); __('Restore File', 'sucuri-scanner'); __('Delete File', 'sucuri-scanner'); __('Submit', 'sucuri-scanner'); __('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.', 'sucuri-scanner'); // integrity-notification.html.tpl __('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 Server Side Scanner.', 'sucuri-scanner'); __('WordPress Integrity (%%SUCURI.Integrity.ListCount%%)', 'sucuri-scanner'); __('Status', 'sucuri-scanner'); __('File Size', 'sucuri-scanner'); __('Modified At', 'sucuri-scanner'); __('File Path', 'sucuri-scanner'); __('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.', 'sucuri-scanner'); // integrity.html.tpl __('WordPress Integrity', 'sucuri-scanner'); __('We inspect your WordPress installation and look for modifications on the core files as provided by WordPress.org. Files located in the root directory, wp-admin and wp-includes will be compared against the files distributed with v%%SUCURI.WordPressVersion%%; all files with inconsistencies will be listed here. Any changes might indicate a hack.', 'sucuri-scanner'); __('Loading...', 'sucuri-scanner'); // lastlogins.html.tpl __('All Users', 'sucuri-scanner'); __('Admins', 'sucuri-scanner'); __('Logged-in Users', 'sucuri-scanner'); __('Failed Logins', 'sucuri-scanner'); // lastlogins-admins.html.tpl __('Successful Logins (admins)', 'sucuri-scanner'); __('Here you can see a list of all the successful logins of accounts with admin privileges.', 'sucuri-scanner'); __('Username', 'sucuri-scanner'); __('Registration', 'sucuri-scanner'); __('Newest To Oldest', 'sucuri-scanner'); // lastlogins-admins.snippet.tpl __('no data available', 'sucuri-scanner'); __('IP Address', 'sucuri-scanner'); __('Date/Time', 'sucuri-scanner'); __('Edit User Profile', 'sucuri-scanner'); // lastlogins-all.html.tpl __('Successful Logins (all)', 'sucuri-scanner'); __('Here you can see a list of all the successful user logins.', 'sucuri-scanner'); __('Username', 'sucuri-scanner'); __('IP Address', 'sucuri-scanner'); __('Hostname', 'sucuri-scanner'); __('Date/Time', 'sucuri-scanner'); __('no data available', 'sucuri-scanner'); __('Delete All Successful Logins', 'sucuri-scanner'); // lastlogins-all.snippet.tpl __('Edit', 'sucuri-scanner'); // lastlogins-failedlogins.html.tpl __('Failed logins', 'sucuri-scanner'); __('This information will be used to determine if your site is being victim of Password Guessing Brute Force Attacks. These logs will be accumulated and the plugin will send a report via email if there are more than %%SUCURI.FailedLogins.MaxFailedLogins%% failed login attempts during the same hour, you can change this number from here. NOTE: Some "Two-Factor Authentication" plugins do not follow the same rules that WordPress have to report failed login attempts, so you may not see all the attempts in this panel if you have one of these plugins installed.', 'sucuri-scanner'); __('Username', 'sucuri-scanner'); __('IP Address', 'sucuri-scanner'); __('Date/Time', 'sucuri-scanner'); __('Web Browser', 'sucuri-scanner'); __('no data available', 'sucuri-scanner'); __('Block', 'sucuri-scanner'); __('Delete All Failed Logins', 'sucuri-scanner'); // lastlogins-loggedin.html.tpl __('Logged-in Users}', 'sucuri-scanner'); __('Here you can see a list of the users that are currently logged-in.', 'sucuri-scanner'); __('ID', 'sucuri-scanner'); __('Username', 'sucuri-scanner'); __('Last Activity', 'sucuri-scanner'); __('Registered', 'sucuri-scanner'); __('IP Address', 'sucuri-scanner'); // lastlogins-loggedin.snippet.tpl __('Edit User Profile', 'sucuri-scanner'); __('Website:', 'sucuri-scanner'); __('IP Address:', 'sucuri-scanner'); __('Reverse IP:', 'sucuri-scanner'); __('Date/Time:', 'sucuri-scanner'); __('Message:', 'sucuri-scanner'); // register-site.html.tpl __('An API key is required to activate some additional tools available in this plugin. The keys are free and you can virtually generate an unlimited number of them as long as the domain name and email address are unique. The key is used to authenticate the HTTP requests sent by the plugin to an API service managed by Sucuri Inc.', 'sucuri-scanner'); __('If you experience issues generating the API key you can request one by sending the domain name and email address that you want to use to info@sucuri.net. Note that generating a key for a website that is not facing the Internet is not possible because the API service needs to validate that the domain name exists.', 'sucuri-scanner'); __('Website:', 'sucuri-scanner'); __('E-mail:', 'sucuri-scanner'); __('DNS Lookups', 'sucuri-scanner'); __('Check the box if your website is behind a known firewall service, this guarantees that the IP address of your visitors will be detected correctly for the security logs. You can change this later from the settings.', 'sucuri-scanner'); __('Enable DNS Lookups On Startup', 'sucuri-scanner'); __('I agree to the Terms of Service.', 'sucuri-scanner'); __('I have read and understand the Privacy Policy.', 'sucuri-scanner'); __('Submit', 'sucuri-scanner'); // settings-alerts-bruteforce.html.tpl __('Password Guessing Brute Force Attacks', 'sucuri-scanner'); __('Password guessing brute force attacks are very common against web sites and web servers. They are one of the most common vectors used to compromise web sites. The process is very simple and the attackers basically try multiple combinations of usernames and passwords until they find one that works. Once they get in, they can compromise the web site with malware, spam , phishing or anything else they want.', 'sucuri-scanner'); __('Consider Brute-Force Attack After:', 'sucuri-scanner'); __('Submit', 'sucuri-scanner'); // settings-alerts-events.html.tpl __('Security Alerts', 'sucuri-scanner'); __('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.', 'sucuri-scanner'); __('Select All', 'sucuri-scanner'); __('Event', 'sucuri-scanner'); __('Submit', 'sucuri-scanner'); // settings-alerts-ignore-posts.html.tpl __('Post-Type Alerts', 'sucuri-scanner'); __('It seems that you disabled the email alerts for new site content, this panel is intended to provide a way to ignore specific events in your site and with that the alerts reported to your email. Since you have deactivated the new site content alerts, this panel will be disabled too.', 'sucuri-scanner'); __('This is a list of registered Post Types. You will receive an email alert when a custom page or post associated to any of these types is created or updated. If you don’t want to receive one or more of these alerts, feel free to uncheck the boxes in the table below. If you are receiving alerts for post types that are not listed in this table, it may be because there is an add-on that that is generating a custom post-type on runtime, you will have to find out by yourself what is the unique ID of that post-type and type it in the form below. The plugin will do its best to ignore these alerts as long as the unique ID is valid.', 'sucuri-scanner'); __('Stop Alerts For This Post-Type:', 'sucuri-scanner'); __('e.g. unique_post_type_id', 'sucuri-scanner'); __('Submit', 'sucuri-scanner'); __('Show Post-Types Table', 'sucuri-scanner'); __('Hide Post-Types Table', 'sucuri-scanner'); __('Select All', 'sucuri-scanner'); __('Post Type', 'sucuri-scanner'); __('Post Type ID', 'sucuri-scanner'); __('Ignored At (optional)', 'sucuri-scanner'); // settings-alerts-perhour.html.tpl __('Alerts Per Hour', 'sucuri-scanner'); __('Configure the maximum number of email alerts per hour. If the number is exceeded and the plugin detects more events during the same hour, it will still log the events into the audit logs but will not send the email alerts. Be careful with this as you will miss important information.', 'sucuri-scanner'); __('Maximum Alerts Per Hour:', 'sucuri-scanner'); __('Submit', 'sucuri-scanner'); // settings-alerts-recipients.html.tpl __('Alerts Recipient', 'sucuri-scanner'); __('By default, the plugin will send the email alerts to the primary admin account, the same account created during the installation of WordPress in your web server. You can add more people to the list, they will receive a copy of the same security alerts.', 'sucuri-scanner'); __('E-mail:', 'sucuri-scanner'); __('e.g. user@example.com', 'sucuri-scanner'); __('Submit', 'sucuri-scanner'); __('Select All', 'sucuri-scanner'); __('E-mail', 'sucuri-scanner'); __('Delete', 'sucuri-scanner'); __('Test Alerts', 'sucuri-scanner'); // settings-alerts-subject.html.tpl __('Alert Subject', 'sucuri-scanner'); __('Format of the subject for the email alerts, by default the plugin will use the website name and the event identifier that is being reported, you can use this panel to include the IP address of the user that triggered the event and some additional data. You can create filters in your email client creating a custom email subject using the pseudo-tags shown below.', 'sucuri-scanner'); __('Custom Format', 'sucuri-scanner'); __('Submit', 'sucuri-scanner'); // settings-alerts-trustedips.html.tpl __('Trusted IP Addresses', 'sucuri-scanner'); __('If you are working in a LAN (Local Area Network) you may want to include the IP addresses of all the nodes in the subnet, this will force the plugin to stop sending email alerts about actions executed from trusted IP addresses. Use the CIDR (Classless Inter Domain Routing) format to specify ranges of IP addresses (only 8, 16, and 24).', 'sucuri-scanner'); __('IP Address:', 'sucuri-scanner'); __('e.g. 182.120.56.0/24', 'sucuri-scanner'); __('Submit', 'sucuri-scanner'); __('Select All', 'sucuri-scanner'); __('IP Address', 'sucuri-scanner'); __('CIDR Format', 'sucuri-scanner'); __('IP Added At', 'sucuri-scanner'); __('no data available', 'sucuri-scanner'); __('Delete', 'sucuri-scanner'); // settings-apirecovery.html.tpl __('If this operation was successful you will receive a message in the email used during the registration of the API key (usually the email of the main admin user). This message contains the key in plain text, copy and paste the key in the form field below. The plugin will verify the authenticity of the key sending an initial HTTP request to the API service, if this fails the key will be removed automatically and you will have to start the process all over again.', 'sucuri-scanner'); __('There are cases where this operation may fail, an example would be when the email address is not associated with the domain anymore, this happens when the base URL changes (from www to none or viceversa). If you are having issues recovering the key please send an email explaining the situation to info@sucuri.net', 'sucuri-scanner'); __('API Key:', 'sucuri-scanner'); __('Submit', 'sucuri-scanner'); // settings-apiregistered.html.tpl __('Congratulations! The rest of the features available in the plugin have been enabled. This product is designed to supplement existing security products. It’s not a silver bullet for your security needs, but it’ll give you greater security awareness and better posture, all with the intent of reducing risk.', 'sucuri-scanner'); __('Your website has been granted a new API key and it was associated to the email address that you chose during the registration process. You can use the same email to recover the key if you happen to lose it sometime. We encourage you to check the rest of the settings page and configure the plugin to your own needs.', 'sucuri-scanner'); __('Dashboard', 'sucuri-scanner'); __('Settings', 'sucuri-scanner'); // settings-apiservice-checksums.html.tpl __('WordPress Checksums API', 'sucuri-scanner'); __('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 development version of the code.', 'sucuri-scanner'); __('WordPress Checksums API', 'sucuri-scanner'); __('e.g. URL — or — user/repo', 'sucuri-scanner'); __('Submit', 'sucuri-scanner'); // settings-apiservice-proxy.html.tpl __('API Communication via Proxy', 'sucuri-scanner'); __('All the HTTP requests used to communicate with the API service are being sent using the WordPress built-in functions, so (almost) all its official features are inherited, this is useful if you need to pass these HTTP requests through a proxy. According to the official documentation you have to add some constants to the main configuration file: WP_PROXY_HOST, WP_PROXY_PORT, WP_PROXY_USERNAME, WP_PROXY_PASSWORD.', 'sucuri-scanner'); __('HTTP Proxy Hostname', 'sucuri-scanner'); __('HTTP Proxy Port num', 'sucuri-scanner'); __('HTTP Proxy Username', 'sucuri-scanner'); __('HTTP Proxy Password', 'sucuri-scanner'); // settings-apiservice-status.html.tpl __('API Service Communication', 'sucuri-scanner'); __('Once the API key is generate the plugin will communicate with a remote API service that will act as a safe data storage for the audit logs generated when the website triggers certain events that the plugin monitors. If the website is hacked the attacker will not have access to these logs and that way you can investigate what was modified (for malware infaction) and/or how the malicious person was able to gain access to the website.', 'sucuri-scanner'); __('Disabling the API service communication will stop the event monitoring, consider to enable the Log Exporter to keep the monitoring working while the HTTP requests are ignored, otherwise an attacker may execute an action that will not be registered in the security logs and you will not have a way to investigate the attack in the future.', 'sucuri-scanner'); __('Are you a developer? You may be interested in our API. Feel free to use the URL shown below to access the latest 50 entries in your security log, change the value for the parameter l=N if you need more. Be aware that the API doesn’t provides an offset parameter, so if you have the intention to query specific sections of the log you will need to wrap the HTTP request around your own cache mechanism. We DO NOT take feature requests for the API, this is a semi-private service tailored for the specific needs of the plugin and not intended to be used by 3rd-party apps, we may change the behavior of each API endpoint without previous notice, use it at your own risk.', 'sucuri-scanner'); // settings-general-datastorage.html.tpl __('Data Storage', 'sucuri-scanner'); __('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 (one level up the document root) please define a constant in the "wp-config.php" file named "SUCURI_DATA_STORAGE" with the absolute path to the new directory.', 'sucuri-scanner'); __('Select All', 'sucuri-scanner'); __('File Path', 'sucuri-scanner'); __('File Size', 'sucuri-scanner'); __('Status', 'sucuri-scanner'); __('Writable', 'sucuri-scanner'); __('Delete', 'sucuri-scanner'); // settings-general-importexport.html.tpl __('Import & Export Settings', 'sucuri-scanner'); __('Copy the JSON-encoded data from the box below, go to your other websites and click the "Import" button in the settings page. The plugin will start using the same settings from this website. Notice that some options are omitted as they contain values specific to this website. To import the settings from another website into this one, replace the JSON-encoded data in the box below with the JSON-encoded data exported from the other website, then click the button "Import". Notice that some options will not be imported to reduce the security risk of writing arbitrary data into the disk.', 'sucuri-scanner'); __('I understand that this operation cannot be reverted.', 'sucuri-scanner'); __('Submit', 'sucuri-scanner'); // settings-general-ipdiscoverer.html.tpl __('IP Address Discoverer', 'sucuri-scanner'); __('IP address discoverer will use DNS lookups to automatically detect if the website is behind the Sucuri Firewall, in which case it will modify the global server variable Remote-Addr to set the real IP of the website’s visitors. This check runs on every WordPress init action and that is why it may slow down your website as some hosting providers rely on slow DNS servers which makes the operation take more time than it should.', 'sucuri-scanner'); __('HTTP Header:', 'sucuri-scanner'); __('Proceed', 'sucuri-scanner'); __('Sucuri Firewall', 'sucuri-scanner'); __('Website:', 'sucuri-scanner'); __('Top Level Domain:', 'sucuri-scanner'); __('Hostname:', 'sucuri-scanner'); __('IP Address (Hostname):', 'sucuri-scanner'); __('IP Address (Username):', 'sucuri-scanner'); // settings-general-resetoptions.html.tpl __('Reset Security Logs, Hardening and Settings', 'sucuri-scanner'); __('This action will trigger the deactivation / uninstallation process of the plugin. All local security logs, hardening and settings will be deleted. Notice that the security logs stored in the API service will not be deleted, this is to prevent tampering from a malicious user. You can request a new API key if you want to start from scratch.', 'sucuri-scanner'); __('I understand that this operation cannot be reverted.', 'sucuri-scanner'); __('Submit', 'sucuri-scanner'); // settings-general-reverseproxy.html.tpl __('Reverse Proxy', 'sucuri-scanner'); __('The event monitor uses the API address of the origin of the request to track the actions. The plugin uses two methods to retrieve this: the main method uses the global server variable Remote-Addr available in most modern web servers, and an alternative method uses custom HTTP headers (which are unsafe by default). You should not worry about this option unless you know what a reverse proxy is. Services like the Sucuri Firewall — once active — force the network traffic to pass through them to filter any security threat that may affect the original server. A side effect of this is that the real IP address is no longer available in the global server variable Remote-Addr but in a custom HTTP header with a name provided by the service.', 'sucuri-scanner'); // settings-general-selfhosting.html.tpl __('Log Exporter', 'sucuri-scanner'); __('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 (we recommend OSSEC). That will give visibility from within WordPress to complement your log monitoring infrastructure. NOTE: 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.', 'sucuri-scanner'); __('File Path:', 'sucuri-scanner'); __('Submit', 'sucuri-scanner'); // settings-general-timezone.html.tpl __('Timezone Override', 'sucuri-scanner'); __('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.', 'sucuri-scanner'); __('Timezone:', 'sucuri-scanner'); __('Submit', 'sucuri-scanner'); // settings-hardening-allowlist-phpfiles.html.tpl __('Allow Blocked PHP Files', 'sucuri-scanner'); __('After you apply the hardening in either the includes, content, and/or uploads directories, the plugin will add a rule in the access control file to deny access to any PHP file located in these folders. This is a good precaution in case an attacker is able to upload a shell script. With a few exceptions the "index.php" file is the only one that should be publicly accessible, however many theme/plugin developers decide to use these folders to process some operations. In this case applying the hardening may break their functionality.', 'sucuri-scanner'); __('File Path:', 'sucuri-scanner'); __('Submit', 'sucuri-scanner'); __('Select All', 'sucuri-scanner'); __('File Path', 'sucuri-scanner'); __('Directory', 'sucuri-scanner'); __('Pattern', 'sucuri-scanner'); __('no data available', 'sucuri-scanner'); __('Delete', 'sucuri-scanner'); // settings-posthack-available-updates-alert.html.tpl __('WordPress has a big user base in the public Internet, which brings interest to attackers to find vulnerabilities in the code, 3rd-party extensions, and themes that other companies develop. You should keep every piece of code installed in your website updated to prevent attacks as soon as disclosed vulnerabilities are patched.', 'sucuri-scanner'); __('Name', 'sucuri-scanner'); __('Version', 'sucuri-scanner'); __('Update', 'sucuri-scanner'); __('Tested With', 'sucuri-scanner'); // settings-posthack-available-updates.html.tpl __('Available Plugin and Theme Updates', 'sucuri-scanner'); __('WordPress has a big user base in the public Internet, which brings interest to attackers to find vulnerabilities in the code, 3rd-party extensions, and themes that other companies develop. You should keep every piece of code installed in your website updated to prevent attacks as soon as disclosed vulnerabilities are patched.', 'sucuri-scanner'); __('Name', 'sucuri-scanner'); __('Version', 'sucuri-scanner'); __('Update', 'sucuri-scanner'); __('Tested With', 'sucuri-scanner'); __('Loading...', 'sucuri-scanner'); // settings-posthack-available-updates.snippet.tpl __('Download', 'sucuri-scanner'); // settings-posthack-reset-password-alert.html.tpl __('WordPress has invalidated the password for your account %%SUCURI.ResetPassword.UserName%% at %%SUCURI.ResetPassword.Website%%. The change has been requested by one of the admins in this website for security reasons. You can set a new password at — %%%SUCURI.ResetPassword.ResetURL%%% —.', 'sucuri-scanner'); // settings-posthack-reset-password.html.tpl __('Reset User Password', 'sucuri-scanner'); __('Loading...', 'sucuri-scanner'); __('Select users from the list in order to change their passwords, terminate their sessions and email them a password reset link. Please be aware that the plugin will change the passwords before sending the emails, meaning that if your web server is unable to send emails, your users will be locked out of the site.', 'sucuri-scanner'); __('Select All', 'sucuri-scanner'); __('Username', 'sucuri-scanner'); __('E-mail', 'sucuri-scanner'); __('Registered', 'sucuri-scanner'); __('Roles', 'sucuri-scanner'); __('Submit', 'sucuri-scanner'); // settings-posthack-reset-plugins.html.tpl __('Reset Installed Plugins', 'sucuri-scanner'); __('Loading...', 'sucuri-scanner'); __('In case you suspect having an infection in your site, or after you got rid of a malicious code, it’s recommended to reinstall all the plugins installed in your site, including the ones you are not using. Notice that premium plugins will not be automatically reinstalled to prevent backward compatibility issues and problems with licenses.', 'sucuri-scanner'); __('The information shown here is cached for %%SUCURI.ResetPlugin.CacheLifeTime%% seconds. This is necessary to reduce the quantity of HTTP requests sent to the WordPress servers and the bandwidth of your site. Currently there is no option to recreate this cache.', 'sucuri-scanner'); __('WARNING! This procedure can break your website. The reset will not affect the database nor the settings of each plugin, but depending on how they were written the reset action might break them. Be sure to create a backup of the plugins directory before the execution of this tool.', 'sucuri-scanner'); __('Select All', 'sucuri-scanner'); __('Name', 'sucuri-scanner'); __('Version', 'sucuri-scanner'); __('Type', 'sucuri-scanner'); __('Status', 'sucuri-scanner'); __('Submit', 'sucuri-scanner'); // settings-posthack-security-keys.html.tpl __('Update Secret Keys', 'sucuri-scanner'); __('The secret or security keys are a list of constants added to your site to ensure better encryption of information stored in the user’s cookies. A secret key makes your site harder to hack by adding random elements to the password. You do not have to remember the keys, just write a random, complicated, and long string in the wp-config.php file. You can change these keys at any point in time. Changing them will invalidate all existing cookies, forcing all logged in users to login again.', 'sucuri-scanner'); __('Your current session will expire once the form is submitted.', 'sucuri-scanner'); __('Status', 'sucuri-scanner'); __('Name', 'sucuri-scanner'); __('Value', 'sucuri-scanner'); __('I understand that this operation cannot be reverted.', 'sucuri-scanner'); __('Generate New Security Keys', 'sucuri-scanner'); __('Automatic Secret Keys Updater', 'sucuri-scanner'); __('Changing the Secret Keys frequently will decrease the chances of misuse of sessions left open on unprotected devices.', 'sucuri-scanner'); __('Frequency:', 'sucuri-scanner'); __('Submit', 'sucuri-scanner'); // settings-scanner-cronjobs.html.tpl __('Scheduled Tasks', 'sucuri-scanner'); __('The plugin scans your entire website looking for changes which are later reported via the API in the audit logs page. By default the scanner runs daily but you can change the frequency to meet your requirements. Notice that scanning your project files too frequently may affect the performance of your website. Be sure to have enough server resources before changing this option. The memory limit and maximum execution time are two of the PHP options that your server will set to stop your website from consuming too much resources.', 'sucuri-scanner'); __('The scanner uses the PHP SPL library and the Filesystem Iterator class to scan the directory tree where your website is located in the server. This library is only available on PHP 5 >= 5.3.0 — OR — PHP 7; if you have an older version of PHP the plugin will not work as expected. Please ask your hosting provider to advise you on this matter.', 'sucuri-scanner'); __('Scheduled tasks are rules registered in your database by a plugin, theme, or the base system itself; they are used to automatically execute actions defined in the code every certain amount of time. A good use of these rules is to generate backup files of your site, execute a security scanner, or remove unused elements like drafts. Note: Scheduled tasks can be re-installed by any plugin/theme automatically.', 'sucuri-scanner'); __('Select All', 'sucuri-scanner'); __('Name', 'sucuri-scanner'); __('Schedule', 'sucuri-scanner'); __('Next Due', 'sucuri-scanner'); __('Arguments', 'sucuri-scanner'); __('Loading...', 'sucuri-scanner'); __('Action:', 'sucuri-scanner'); __('Submit', 'sucuri-scanner'); // settings-scanner-ignore-folders.html.tpl __('Ignore Files And Folders During The Scans', 'sucuri-scanner'); __('Use this tool to select the files and/or folders that are too heavy for the scanner to process. These are usually folders with images, media files like videos and audios, backups and — in general — anything that is not code-related. Ignoring these files or folders will reduce the memory consumption of the PHP script.', 'sucuri-scanner'); __('Ignore a file or directory:', 'sucuri-scanner'); __('e.g. /private/directory/', 'sucuri-scanner'); __('Submit', 'sucuri-scanner'); __('Select All', 'sucuri-scanner'); __('File Path', 'sucuri-scanner'); __('Status', 'sucuri-scanner'); __('Unignore Selected Directories', 'sucuri-scanner'); // settings-scanner-integrity-cache.html.tpl __('WordPress Integrity (False Positives)', 'sucuri-scanner'); __('Since the scanner doesn’t read the files during the execution of the integrity check, it is possible to find false positives. Files listed here have been marked as false positives and will be ignored by the scanner in subsequent scans.', 'sucuri-scanner'); __('Select All', 'sucuri-scanner'); __('Reason', 'sucuri-scanner'); __('Ignored At', 'sucuri-scanner'); __('File Path', 'sucuri-scanner'); __('no data available', 'sucuri-scanner'); __('Stop Ignoring the Selected Files', 'sucuri-scanner'); // settings-scanner-integrity-diff-utility.html.tpl __('WordPress Integrity Diff Utility', 'sucuri-scanner'); __('If your server allows the execution of system commands, you can configure the plugin to use the Unix Diff Utility 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.', 'sucuri-scanner'); __('WordPress Integrity Diff Utility', 'sucuri-scanner'); // settings-webinfo-details.html.tpl __('Environment Variables', 'sucuri-scanner'); // settings-webinfo-htaccess.html.tpl __('Access File Integrity', 'sucuri-scanner'); __('The .htaccess file is a distributed configuration file, and is how the Apache web server handles configuration changes on a per-directory basis. WordPress uses this file to manipulate how Apache serves files from its root directory and subdirectories thereof; most notably, it modifies this file to be able to handle pretty permalinks.', 'sucuri-scanner'); __('Htaccess file found in', 'sucuri-scanner'); __('Your website has no .htaccess file or it was not found in the default location.', 'sucuri-scanner'); __('Your web server does not support .htaccess files.', 'sucuri-scanner'); __('The main .htaccess file in your site has the standard rules for a WordPress installation. You can customize it to improve the performance and change the behaviour of the redirections for pages and posts in your site. To get more information visit the official documentation at Codex WordPress - Creating and editing (.htaccess)', 'sucuri-scanner'); __('Codex WordPress HTAccess', 'sucuri-scanner'); // settings.html.tpl __('General Settings', 'sucuri-scanner'); __('Scanner', 'sucuri-scanner'); __('Hardening', 'sucuri-scanner'); __('Post-Hack', 'sucuri-scanner'); __('Alerts', 'sucuri-scanner'); __('API Service Communication', 'sucuri-scanner'); __('Website Info', 'sucuri-scanner'); __('Hardening Options', 'sucuri-scanner'); // sitecheck-details.html.tpl __('This information will be updated %%SUCURI.SiteCheck.Lifetime%%', 'sucuri-scanner'); __('Refresh Malware Scan', 'sucuri-scanner'); // sitecheck-malware.html.tpl __('Request Malware Cleanup', 'sucuri-scanner'); __('No malicious JavaScript', 'sucuri-scanner'); __('No malicious iFrames', 'sucuri-scanner'); __('No suspicious redirections', 'sucuri-scanner'); __('No blackhat SEO spam', 'sucuri-scanner'); __('No anomaly detection', 'sucuri-scanner'); __('This is a free website security scanner. Some types of malware and security issues cannot be detected by this scanner. If no issues are detected but you suspect a problem still exists, sign up for a complete and in depth website scan with malware cleanup.', 'sucuri-scanner'); __('The Sucuri Security Plugin's automated scanner has detected malware in your WordPress environment.', 'sucuri-scanner'); __('Log in to the Sucuri Platform dashboard for a complete scan of your website files and guaranteed malware removal. You can sign up here if you don't have an account yet.', 'sucuri-scanner'); // sitecheck-malware.snippet.tpl __('Hover to see the Payload', 'sucuri-scanner'); // sitecheck-recommendations.html.tpl __('Recommendations', 'sucuri-scanner'); // sitecheck-target.html.tpl __('Malware Scan Target', 'sucuri-scanner'); __('The remote malware scanner provided by the plugin is powered by Sucuri SiteCheck, 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.', 'sucuri-scanner'); __('Malware Scan Target', 'sucuri-scanner'); __('Malware Scan Target:', 'sucuri-scanner'); __('Submit', 'sucuri-scanner'); // wordpress-recommendations.html.tpl __('WordPress Security Recommendations', 'sucuri-scanner'); // settings-headers-cache.html.tpl __('The max-age setting tells your browser how long, in seconds, it can keep a copy of a web page before it needs to check for a new version. This is the basic setting needed to make caching work on most devices.', 'sucuri-scanner'); __('The s-maxage setting tells shared caches, like those used by multiple visitors or devices (such as CDNs or web accelerators), how long they can keep a copy of a web page. It allows you to control how often these shared caches update their content compared to private caches.', 'sucuri-scanner'); __('The stale-if-error setting allows a cached page to be served even after it has expired if the original web server returns an error. This helps keep your website available by showing an older version of the page instead of an error message. You need to set a private or shared cache duration to use this option, and it can be set for hours or days.', 'sucuri-scanner'); __('The stale-while-revalidate setting lets shared caches serve an old version of a web page while they update the cached copy in the background. This improves loading times because visitors don’t have to wait for the updated content. Like stale-if-error, it requires a private or shared cache duration, and can be used together with stale-if-error. This setting is useful for ensuring quick page loads while keeping content reasonably fresh.', 'sucuri-scanner'); __('When this option is set, older pages will be cached for longer than newer pages (determined by page number). The configured pagination factor is added to the main maxage and s-maxage options. This allows less popular archives to be served as stale for longer.', 'sucuri-scanner'); __('When this option is set, the max-age and s-maxage values will be multiplied by the number of years since the last edit or comment (the Last Modified time). This allows posts that were published a long time ago to be cached longer than newer posts.', 'sucuri-scanner'); __('Here you can see all the cache options available.', 'sucuri-scanner'); __('Option', 'sucuri-scanner'); __('No options available', 'sucuri-scanner'); __('Cache Control Header', 'sucuri-scanner'); __('Enabled', 'sucuri-scanner'); __('Disabled', 'sucuri-scanner'); __('Mode:', 'sucuri-scanner'); __('Update', 'sucuri-scanner'); __('Edit', 'sucuri-scanner'); __('Please enable site caching on your WAF to use these settings. If you are a Sucuri client and require assistance, please {{create a ticket}} and reach out to the firewall team for support.', 'sucuri-scanner'); // settings-headers-cache-option.snippet.tpl __('Edit', 'sucuri-scanner'); src/template.lib.php000060400000045255147177152050010444 0ustar00 * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Read, parse and handle everything related with the templates. * * A web template system uses a template processor to combine web templates to * form finished web pages, possibly using some data source to customize the * pages or present a large amount of content on similar-looking pages. It is a * web publishing tool present in content management systems, web application * frameworks, and HTML editors. * * Web templates can be used like the template of a form letter to either * generate a large number of "static" (unchanging) web pages in advance, or to * produce "dynamic" web pages on demand. * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ class SucuriScanTemplate extends SucuriScanRequest { /** * Replace all pseudo-variables from a string of characters. * * @see http://php.net/manual/en/function.gettype.php * * @param string $content The content of a template file which contains pseudo-variables. * @param array $params List of pseudo-variables that will be replaced in the template. * @return string The content of the template with the pseudo-variables replated. */ private static function replacePseudoVars($content = '', $params = array()) { $params = is_array($params) ? $params : array(); foreach ($params as $keyname => $kvalue) { $tplkey = 'SUCURI.' . $keyname; $with_escape = '%%' . $tplkey . '%%'; $wout_escape = '%%%' . $tplkey . '%%%'; if (is_bool($kvalue)) { $kvalue = ($kvalue === true) ? 'True' : 'False'; } elseif (!is_string($kvalue) && !is_numeric($kvalue)) { $kvalue = gettype($kvalue); } if (strpos($content, $wout_escape) !== false) { $content = str_replace($wout_escape, $kvalue, $content); continue; } if (strpos($content, $with_escape) !== false) { $kvalue = SucuriScan::escape($kvalue); $content = str_replace($with_escape, $kvalue, $content); continue; } } global $locale; preg_match_all('~{{(.+?)}}~', $content, $matches); if (!empty($matches[1])) { foreach ($matches[1] as $index => $string) { $search = $matches[0][$index]; $replace = ('en_US' !== $locale) ? translate($string, 'sucuri-scanner') : $string; $content = str_replace($search, $replace, $content); } } return $content; } /** * Gather and generate the information required globally by all the template files. * * @param string $target Scenario where the params are going to be replaced. * @param array $params Key-value array with variables shared with the template. * @return array Additional list of variables for the template files. */ private static function sharedParams($target = null, $params = array()) { $params = is_array($params) ? $params : array(); // Base parameters, required to render all the pages. $params = self::linksAndNavbar($params); // Global parameters, used through out all the pages. $params['GenerateAPIKey.Modal'] = ''; $params['GenerateAPIKey.Visibility'] = 'hidden'; $params['PageNonce'] = wp_create_nonce('sucuriscan_page_nonce'); $params['WordPressVersion'] = self::siteVersion(); $params['PluginVersion'] = SUCURISCAN_VERSION; $params['CleanDomain'] = self::getDomain(); $params['Year'] = date('Y'); if (!array_key_exists('PageStyleClass', $params)) { $params['PageStyleClass'] = 'base'; } if ($target === 'base' && current_user_can('manage_options') && !SucuriScanAPI::getPluginKey() ) { $params['GenerateAPIKey.Visibility'] = 'visible'; $params['GenerateAPIKey.Modal'] = /* register-site */ SucuriScanTemplate::getModal( 'register-site', array( 'Title' => __('Generate API Key', 'sucuri-scanner'), 'Identifier' => 'register-site', 'Visibility' => 'hidden', ) ); } // Get a list of admin users for the API key generation. if ($target === 'modal' && !SucuriScanAPI::getPluginKey()) { $admin_users = SucuriScan::getUsersForAPIKey(); $params['AdminEmails'] = self::selectOptions($admin_users); } return $params; } /** * Return a string indicating the visibility of a HTML component. * * @param bool $visible Whether the condition executed returned a positive value or not. * @return string A string indicating the visibility of a HTML component. */ public static function visibility($visible = false) { return ($visible === true ? 'visible' : 'hidden'); } /** * Generate an URL pointing to the page indicated in the method and that must * be loaded through the administrator panel. * * @param string $page Short name of the page that will be generated. * @param bool $ajax True if the URL should point to the Ajax handler. * @return string Full string containing the link of the page. */ public static function getUrl($page = '', $ajax = false) { $suffix = ($ajax === true) ? 'admin-ajax' : 'admin'; $url_path = SucuriScan::adminURL($suffix . '.php?page=sucuriscan'); if (!empty($page)) { $url_path .= '_' . strtolower($page); } /* convert URL to multisite format */ $networkURL = str_replace( 'wp-admin/network/admin-ajax.php', 'wp-admin/admin-ajax.php', $url_path ); return SucuriScan::isMultiSite() ? $networkURL : $url_path; } /** * Generate an URL pointing to the page indicated in the method and that must * be loaded through the Ajax handler of the administrator panel. * * @param string $page Short name of the page that will be generated. * @return string Full string containing the link of the page. */ public static function getAjaxUrl($page = '') { return self::getUrl($page, true); } /** * Complement the list of pseudo-variables that will be used in the base * template files, this will also generate the navigation bar and detect which * items in it are selected by the current page. * * @param array $params Key-value array with pseudo-variables shared with the template. * @return array A complementary list of pseudo-variables for the template files. */ private static function linksAndNavbar($params = array()) { $pages = sucuriscanMainPages(); $params = is_array($params) ? $params : array(); $sub_pages = is_array($pages) ? $pages : array(); foreach ($sub_pages as $sub_page_func => $sub_page_title) { $func_parts = explode('_', $sub_page_func, 2); if (isset($func_parts[1])) { $unique_name = $func_parts[1]; $pseudo_var = 'URL.' . ucwords($unique_name); } else { $unique_name = ''; $pseudo_var = 'URL.Dashboard'; } $params[$pseudo_var] = self::getUrl($unique_name); // Copy URL variable and create an Ajax handler. $pseudo_var_ajax = 'Ajax' . $pseudo_var; $params[$pseudo_var_ajax] = self::getAjaxUrl($unique_name); } return $params; } /** * Generate a HTML code using a template and replacing all the pseudo-variables * by the dynamic variables provided by the developer through one of the parameters * of the function. * * @param string $html The HTML content of a template file with its pseudo-variables parsed. * @param array $params Key-value array with pseudo-variables shared with the template. * @return string The formatted HTML content of the base template. */ public static function getBaseTemplate($html = '', $params = array()) { $params = is_array($params) ? $params : array(); $params = self::sharedParams('base', $params); $params['PageContent'] = $html; return self::getTemplate('base', $params); } /** * Generate a HTML code using a template and replacing all the pseudo-variables * by the dynamic variables provided by the developer through one of the parameters * of the function. * * @param string $template Filename of the template that will be used to generate the page. * @param array $params Key-value array with pseudo-variables shared with the template. * @param string $type Template type; either page, section or snippet. * @return string Formatted HTML code after pseudo-variables replacement. */ public static function getTemplate($template = '', $params = array(), $type = 'page') { $params = is_array($params) ? $params : array(); $filenames = array( 'page' => '%s/inc/tpl/%s.html.tpl', 'section' => '%s/inc/tpl/%s.html.tpl', 'snippet' => '%s/inc/tpl/%s.snippet.tpl', ); if (!array_key_exists($type, $filenames)) { return (string)SucuriScan::throwException(__('Invalid template type', 'sucuri-scanner')); } $output = ''; /* initialize response */ $_page = self::get('page', '_page'); $params['PluginURL'] = SUCURISCAN_URL; $trailing = $_page ? 'admin.php?page=' . $_page : ''; $params['CurrentURL'] = SucuriScan::adminURL($trailing); $params['DashboardButtonVisibility'] = $_page == 'sucuriscan' ? 'hidden' : 'visible'; $params['SettingsButtonVisibility'] = $_page == 'sucuriscan_settings' ? 'hidden' : 'visible'; $params['FirewallButtonVisibility'] = $_page == 'sucuriscan_firewall' ? 'hidden' : 'visible'; /* load raw content from the specified template file */ $fpath = sprintf($filenames[$type], SUCURISCAN_PLUGIN_PATH, $template); $output = SucuriScanFileInfo::fileContent($fpath); /* replace the global pseudo-variables in the section/snippets templates. */ if ($template == 'base' && array_key_exists('PageContent', $params) && strpos($params['PageContent'], '%%SUCURI.') !== false ) { $params['PageContent'] = self::replacePseudoVars($params['PageContent'], $params); } $output = self::replacePseudoVars($output, $params); if ($template == 'base' || $type != 'page') { return $output; } return self::getBaseTemplate($output, $params); } /** * Generate a HTML code using a template and replacing all the pseudo-variables * by the dynamic variables provided by the developer through one of the parameters * of the function. * * @param string $template Filename of the template that will be used to generate the page. * @param array $params Key-value array with pseudo-variables shared with the template. * @return string The formatted HTML page after replace all the pseudo-variables. */ public static function getSection($template = '', $params = array()) { $params = self::sharedParams('section', $params); return self::getTemplate($template, $params, 'section'); } /** * Generate a HTML code using a template and replacing all the pseudo-variables * by the dynamic variables provided by the developer through one of the parameters * of the function. * * @param string $template Filename of the template that will be used to generate the page. * @param array $params Key-value array with pseudo-variables shared with the template. * @return string The formatted HTML page after replace all the pseudo-variables. */ public static function getModal($template = '', $params = array()) { $required = array( 'Title' => 'Lorem ipsum dolor sit amet', 'Visibility' => 'visible', 'Identifier' => 'foobar', 'CssClass' => '', 'Content' => '

    Lorem ipsum dolor sit amet, consectetur adipisici' . 'ng elit, sed do eiusmod tempor incididunt ut labore et dolore m' . 'agna aliqua. Ut enim ad minim veniam, quis nostrud exercitation' . ' ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis ' . 'aute irure dolor in reprehenderit in voluptate velit esse cillu' . 'm dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupi' . 'datat non proident, sunt in culpa qui officia deserunt mollit a' . 'nim id est laborum.

    ', ); if (!empty($template) && $template !== 'none') { $params['Content'] = self::getSection($template); } foreach ($required as $param_name => $param_value) { if (!isset($params[$param_name])) { $params[$param_name] = $param_value; } } $params['Visibility'] = SUCURISCAN . '-' . $params['Visibility']; $params['Identifier'] = SUCURISCAN . '-' . $params['Identifier'] . '-modal'; $params = self::sharedParams('modal', $params); return self::getTemplate('modalwindow', $params, 'section'); } /** * Generate a HTML code using a template and replacing all the pseudo-variables * by the dynamic variables provided by the developer through one of the parameters * of the function. * * @param string $template Filename of the template that will be used to generate the page. * @param array $params Key-value array with pseudo-variables shared with the template. * @return string The formatted HTML page after replace all the pseudo-variables. */ public static function getSnippet($template = '', $params = array()) { $params = self::sharedParams('snippet', $params); return self::getTemplate($template, $params, 'snippet'); } /** * Generate the HTML code necessary to render a list of options in a form. * * @param array $allowed Key-value array with allowed options. * @param string|int $selected Optional selected value from the list. * @return string HTML code for the select box. */ public static function selectOptions($allowed = array(), $selected = '') { $options = ''; foreach ((array)$allowed as $option_name => $option_label) { $selectedAttr = ''; if ($option_name === $selected) { $selectedAttr = "\x20selected=\"selected\""; } $options .= sprintf( "\n", SucuriScan::escape($option_name), $selectedAttr, /* do not escape HTML */ SucuriScan::escape($option_label) ); } return $options; } /** * Detect which number in a pagination was clicked. * * @return int Page number of the link clicked in a pagination. */ public static function pageNumber() { $paged = self::get('paged', '[0-9]{1,5}'); return ($paged ? intval($paged) : 1); } /** * Generate the HTML code to display a pagination. * * @param string $base_url Base URL for the links before the page number. * @param int $total_items Total quantity of items retrieved from a query. * @param int $max_per_page Maximum number of items that will be shown per page. * @return string HTML code for a pagination generated using the provided data. */ public static function pagination($base_url = '', $total_items = 0, $max_per_page = 1, $query_params = array()) { /* calculate the number of links for the pagination */ $html_links = ''; $page_number = self::pageNumber(); $max_pages = ceil($total_items / $max_per_page); $final_page = $max_pages; $start_page = 1; $extra_url = ''; /* fix for inline anchor URLs */ $offset = strpos($base_url, '#'); if ($offset !== false) { $clean_url = substr($base_url, 0, $offset); $extra_url = substr($base_url, $offset); $base_url = $clean_url; } /* keep the number of pagination buttons at limit */ if ($max_pages > SUCURISCAN_MAX_PAGINATION_BUTTONS) { $middle = floor(SUCURISCAN_MAX_PAGINATION_BUTTONS / 2); if ($page_number > $middle) { $start_page = max(1, $page_number - $middle); $final_page = min($max_pages, $page_number + $middle); if ($final_page - $start_page + 1 < SUCURISCAN_MAX_PAGINATION_BUTTONS) { $start_page = max(1, $final_page - SUCURISCAN_MAX_PAGINATION_BUTTONS + 1); } } else { $final_page = SUCURISCAN_MAX_PAGINATION_BUTTONS; } } else { $final_page = $max_pages; } $query_params_str = http_build_query($query_params); if (!empty($query_params) && !empty($query_params_str)) { $extra_url .= '&' . $query_params_str; } /* generate the HTML links for the pagination */ for ($j = $start_page; $j <= $final_page; $j++) { $link_class = 'sucuriscan-pagination-link'; if ($page_number == $j) { $link_class .= "\x20sucuriscan-pagination-active"; } $html_links .= sprintf( '
  • %s
  • ', $base_url, $j, $extra_url, $link_class, $j, $j ); } return $html_links; } } src/wordpress-recommendations.lib.php000060400000025632147177152050014043 0ustar00 * @copyright 2010-2019 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * * @see https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Make sure the WordPress install follows security best practices. * * @category Library * * @author Northon Torga * @copyright 2010-2019 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * * @see https://wordpress.org/plugins/sucuri-scanner * @see https://sucuri.net/guides/wordpress-security/ */ class SucuriWordPressRecommendations { /** * Generates the HTML section for the WordPress recommendations section. * * @return string HTML code to render the recommendations section */ public static function pageWordPressRecommendations() { $params = array(); $params['WordPress.Recommendations.Content'] = ''; /* * Register all possible recommendations. */ // phpcs:disable Generic.Files.LineLength $recommendations = array( 'noSSL' => array( __('Implement an SSL Certificate', 'sucuri-scanner') => __('SSL certificates help protect the integrity of the data in transit between the host (web server or firewall) and the client (web browser).', 'sucuri-scanner'), ), 'PHPVersionCheck' => array( __('Upgrade PHP to a supported version', 'sucuri-scanner') => __('The PHP version you are using no longer receives security support and could be exposed to unpatched security vulnerabilities.', 'sucuri-scanner'), ), 'wpSaltExistenceChecker' => array( __('Missing WordPress Salt & Security Keys', 'sucuri-scanner') => __('Consider using WordPress Salt & Security Keys to add an extra layer of protection to the session cookies and credentials.', 'sucuri-scanner'), ), 'wpSaltAgeDiscriminator' => array( __('WordPress Salt & Security Keys should be updated', 'sucuri-scanner') => __('Updating WordPress Salt & Security Keys after a compromise and on a regular basis, at least once a year, reduces the risks of session hijacking.', 'sucuri-scanner'), ), 'adminBadUsername' => array( __('Admin/Administrator username still exists', 'sucuri-scanner') => __('Using a unique username and removing the default admin/administrator account make it more difficult for attackers to brute force your WordPress.', 'sucuri-scanner'), ), 'lonelySuperAdmin' => array( __('Use super admin account only when needed', 'sucuri-scanner') => __('Create an Editor account instead of always using the super-admin to reduce the damage in case of session hijacking.', 'sucuri-scanner'), ), 'forgottenExtension' => array( __('Remove unwanted/unused extensions', 'sucuri-scanner') => __('Keeping unwanted themes and plugins increases the chance of a compromise, even if they are disabled.', 'sucuri-scanner'), ), 'tooMuchPlugins' => array( __('Decrease the number of plugins', 'sucuri-scanner') => __('The greater the number of plugins installed, the greater the risk of infection and performance issues.', 'sucuri-scanner'), ), 'fileEditStillEnabled' => array( __('Disable file editing', 'sucuri-scanner') => __('Using "DISALLOW_FILE_EDIT" helps prevent an attacker from changing your files through WordPress backend.', 'sucuri-scanner'), ), 'wpDebugOnline' => array( __('Disable WordPress debug mode', 'sucuri-scanner') => __('When "WP_DEBUG" is set to true, it will cause all PHP errors, notices and warnings to be displayed which can expose sensitive information.', 'sucuri-scanner'), ), 'notHardened' => array( __('Prevent PHP direct execution on sensitive directories', 'sucuri-scanner') => __('Directories such as "wp-content" and "wp-includes" are generally not intended to be accessed by any user, consider hardening them via Sucuri Security -> Settings -> Hardening.', 'sucuri-scanner'), ), ); // phpcs:enable /* * Remove recommendations accordingly. */ /* * Check if a SSL cert is being used. * @see https://blog.sucuri.net/2019/03/how-to-add-ssl-move-wordpress-from-http-to-https.html */ if (is_ssl()) { unset($recommendations['noSSL']); } /* * Check PHP version. * @see https://www.php.net/supported-versions.php */ if (version_compare(phpversion(), '7.2', '>')) { unset($recommendations['PHPVersionCheck']); } /* * Check if WordPress Salt & Security Keys are set and were updated on the last 12 months. * @see https://wordpress.org/support/article/editing-wp-config-php/#security-keys * @see https://sucuri.net/guides/wordpress-security/#harrec */ if (defined('AUTH_KEY') && defined('AUTH_SALT')) { unset($recommendations['wpSaltExistenceChecker']); } if (file_exists(ABSPATH.'/wp-config.php') && (filemtime(ABSPATH.'/wp-config.php') > strtotime('-12 months'))) { unset($recommendations['wpSaltAgeDiscriminator']); } /* * Check for standard administrator/admin account. * @see https://sucuri.net/guides/wordpress-security/#uac */ $usersWithAdminLogin = array(); $adminUsernames = array('admin', 'administrator'); if (version_compare(SucuriScan::siteVersion(), '4.7', '>=')) { $usersWithAdminLogin = get_users(array( 'role' => 'administrator', 'login__in' => $adminUsernames, )); } else { $allUsers = get_users(array( 'role' => 'administrator', 'fields' => array('user_login'), )); foreach($allUsers as $user) { if (in_array($user->user_login, $adminUsernames)) { $usersWithAdminLogin[] = $user->user_login; } } } if (empty($usersWithAdminLogin)) { unset($recommendations['adminBadUsername']); } /* * Check if super-admin isn't being used for day-to-day operations. * @see https://sucuri.net/guides/wordpress-security/#uac */ $wpUsersCount = count_users(); if ($wpUsersCount['total_users'] !== 1) { unset($recommendations['lonelySuperAdmin']); } /* * Check for unwanted extensions. * @see https://sucuri.net/guides/wordpress-security/#apt * * NOTE: $wpPluginsInstalledName, $wpPluginsActivatedName, $wpPluginsDeactivatedName * are created by this feature. */ $wpPluginsInstalled = get_plugins(); $wpPluginsActivatedName = array(); $wpPluginsDeactivatedName = array(); foreach ($wpPluginsInstalled as $pluginPath => $pluginDetails) { $wpPluginsInstalledName[] = $pluginDetails['Name']; if (is_plugin_active($pluginPath)) { $wpPluginsActivatedName[] = $pluginDetails['Name']; } else { $wpPluginsDeactivatedName[] = $pluginDetails['Name']; } } // phpcs:disable Generic.Files.LineLength if ((count(wp_get_themes()) < 2 || count($wpPluginsDeactivatedName) < 1) || is_multisite()) { unset($recommendations['forgottenExtension']); } // phpcs:enable /* * Check for too much plugins. * @see https://sucuri.net/guides/wordpress-security/#apt */ if (count($wpPluginsInstalled) < 50 || is_multisite()) { unset($recommendations['tooMuchPlugins']); } /* * Check if File Editing was disabled. * @see https://sucuri.net/guides/wordpress-security/#appconf */ if (defined('DISALLOW_FILE_EDIT') && true === DISALLOW_FILE_EDIT) { unset($recommendations['fileEditStillEnabled']); } /* * Check if WordPress Debug Mode isn't set. * @see https://wordpress.org/support/article/debugging-in-wordpress/ */ if (!defined('WP_DEBUG') || defined('WP_DEBUG') && false === WP_DEBUG) { unset($recommendations['wpDebugOnline']); } /* * Check if Hardening was applied if possible. * @see https://sucuri.net/guides/wordpress-security/#harrec */ // phpcs:disable Generic.Files.LineLength if (SucuriScan::isNginxServer() || SucuriScan::isIISServer() || SucuriScan::isBehindFirewall() || (SucuriScanHardening::isHardened(WP_CONTENT_DIR) && SucuriScanHardening::isHardened(ABSPATH.'/wp-includes'))) { unset($recommendations['notHardened']); } // phpcs:enable /* * DELIVERY RESULTS * * Delivery an "all is good" message, unless recommendations array has values, * in which case the plugin must display the items that need fixing. */ $params['WordPress.Recommendations.Color'] = 'green'; // phpcs:disable Generic.Files.LineLength $params['WordPress.Recommendations.Content'] = __('Your WordPress install is following the security best practices.', 'sucuri-scanner'); // phpcs:enable if (count($recommendations) !== 0) { /* Set title to blue as not there is still recommendations to be followed. */ $params['WordPress.Recommendations.Color'] = 'blue'; $params['WordPress.Recommendations.Content'] = null; /* Delivery the recommendations using the getSnippet function. */ $recommendation = array_keys($recommendations); foreach ($recommendation as $checkid) { foreach ($recommendations[$checkid] as $title => $description) { $params['WordPress.Recommendations.Content'] .= SucuriScanTemplate::getSnippet( 'wordpress-recommendations', array( 'WordPress.Recommendations.Title' => $title, 'WordPress.Recommendations.Value' => $description, ) ); } } } return SucuriScanTemplate::getSection('wordpress-recommendations', $params); } } index.html000060400000000046147177152050006546 0ustar00 LICENSE000060400000043254147177152050005566 0ustar00 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. readme.txt000060400000104161147177152050006552 0ustar00=== Sucuri Security - Auditing, Malware Scanner and Security Hardening === Contributors: wordpress@sucuri.net Donate Link: https://sucuri.net/ Tags: malware, security, firewall, scan, spam, virus, sucuri, protection, blocklist, detection, hardening, file integrity Requires at least: 3.6 Tested up to: 6.6 Stable tag: 1.9.6 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html The Sucuri WordPress Security plugin is a security toolset for security integrity monitoring, malware detection and security hardening. == Description == Sucuri Inc. is a globally recognized authority in all matters related to website security, with specialization in WordPress Security. The Sucuri Security WordPress plugin is free to all WordPress users. It is a security suite meant to complement your existing security posture. Currently the ownership of this plugin was transferred to GoDaddy. It offers its users a set of security features for their website, each designed to have a positive effect on their security posture: * Security Activity Auditing * File Integrity Monitoring * Remote Malware Scanning * Blocklist Monitoring * Effective Security Hardening * Post-Hack Security Actions * Security Notifications * Website Firewall (premium) * Cache-Control header administration == Installation == The installation of the Sucuri 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. To install Sucuri Security and complement your Security posture: 1. Log into your WordPress administration panel, 2. In the sidebar, choose "Plugins" and then "Add New", 3. Type "sucuri" or "sucuri-scanner" in the search box, 4. Install the option with the "By Sucuri Inc." at the foot, 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 a unique key to authenticate your website against the remote Sucuri WordPress API service, 6. Feel free to visit the plugin' settings page to configure other options including the security alerts, hardening options, file system scanner paths and API service communication. 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 them. == Frequently Asked Questions == More information on the Sucuri Security WordPress plugin can be found in our [Knowledge Base](https://kb.sucuri.net/plugins/WordPress+Plugin). = What is the security activity auditing? = 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, and as such we try to record it. 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? Since version 1.9.6, we have added support for filters in the audit logs, allowing you to filter by various event types and dates. = What is the file integrity monitoring = 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. 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. = What is the remote malware scanning? = 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. = What is the blocklist monitoring? = Another very interesting feature of the Security Malware Scanner is that it checks various blocklist engines, including the following: * Sucuri Labs * Google Safe Browsing * Norton * AVG * Phish Tank * ESET * McAfee Site Advisor * Yandex * SpamHaus * Bitdefender These are some of the largest blocklisting entities, each having the ability to directly impact your brand's online reputation. By synchronizing 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 of the security blocklist. = What is effective security hardening = 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. = What are the post-hack security actions = 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. = What are the security notifications = 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. = What is the website firewall (premium) = 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, including: * Denial of Service (DOS / DDOS) Attacks * Exploitation of Software Vulnerabilities * Zero Day Disclosure Patches * Brute Force Attacks against your Access Control Mechanisms This is coupled with a number of features like: * Performance Optimization * Advanced Access Control Features * Failover and Redundancy This is **not included as a free** option of 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. The Sucuri 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. = What does this plugin do that other security plugins don't do? = 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 its safe keeping. This security plugin also takes a different approach to security plugins, stripping it of what we categorize as unnecessary features for a basic website end-user. We've narrowed the key features we felt were most pertinent to any website owner and integrated them into this plugin. = If I install the Sucuri Security plugin do I get a Sucuri account? = No, this is a free plugin that we offer at no charge. It does not mean you get a free account. = If I have the premium plugin, do I need the free plugin? = The premium plugin was deprecated back in 2014. All the major features were merged into the free plugin. If you are still using the (old) premium plugin please consider deleting it and installing the (new) free plugin from the WordPress plugin market. Notice that you will need to generate a new API key as the new API service does not supports the old one. = Do I still need Sucuri’s products if I have this plugin? = Yes. This plugin compliments your existing security toolsets. It is not designed to replace the Sucuri Website Security or Firewall products. = Where do I get support for this plugin? = 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). = Does your plugin conflict with WordFence? = The plugin does not, but there might be issues with our scanners. If you get an “Unable to Properly Scan Your Site” error, 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. = What are the Remote Malware Scanner limitations? = 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. = Your plugin didn’t detect this malware? = 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). 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). The plugin is not performing application level malware / security scanning so this is not uncommon. = Is it free to enable the Website Firewall option? = No, it is not. To enable you must subscribe to the [Website Firewall](https://sucuri.net/website-firewall-signup) service. = Will this plugin impact the performance of my website? = We improve the performance of the code with every release. However, due to differences between hosting providers there are cases where the plugin may affect the responsiveness of the website upon installation. Things like HTTP requests, SSL certificate verifications and DNS lookups are among the few things that, depending on how your web server is configured, will slow down your website. = Do the logs get stored to my database? = No, they do not. = Are there any issues installing your plugin with any hosts? = Not that we are aware of. = Do I need this plugin to use the Website Firewall service? = 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. = What information does Sucuri collect? = We take your privacy seriously. For free plugin users without an API key, no information is collected by Sucuri. After activating an API key, Sucuri will store some information, such as logs. Please see our [Terms of Service](https://sucuri.net/terms) and [Privacy Policy](https://sucuri.net/privacy). Please email gdpr@sucuri.net if you have other questions about your privacy. # How do I configure the Cache-Control header? Go to Settings > Headers and enable the Cache-Control header selecting a mode according to your website's need and click on submit. You can also activate the Cache-Control header by updating the cache header fields in one of the page types by using the "Edit" button in the table rows. Please enable site caching on your WAF to use these settings. If you are a Sucuri client and require assistance, please [create a ticket](https://sucuri.net/privacy) and reach out to the firewall team for support. == Screenshots == 1. WordPress Integrity Tool - Detects added, modified, and removed files. 2. Integrity Diff Utility - Shows differences in the core WordPress files. 3. Audit Logs and Malware Scanner - Reports suspicious events and malicious code. 4. Sucuri Firewall - Settings visibility, audit logs, IP blocklisting, and cache. 5. Website Hardening - Offers multiple options to increase the security of the website. 6. Failed Logins - Shows failed login attempts, successful logins and online users. 7. Post Hack Tools - Offers multiple tools to react after the suspiciousness of a hack. 8. Settings - Offers multiple settings to configure the functionality of the plugin. 9. Cache control headers - Offers multiple options to configure the cache control header. == Upgrade Notice == = 1.8.37 = This version removes the API communication service dependency on https://wordpress.sucuri.net/api/, because this service has been discontinued until further notice. Users who have their custom APIs to use in place of https://wordpress.sucuri.net/api/ can still use the API communication service by adding the API endpoint as SUCURISCAN_API_URL on the wp-config.php file. = 1.8.19 = This version adds an option to refresh the malware scan results on demand, as well as several small bug fixes and improvements. == Contributors & Maintenance Notice == = 1.8.30 = Daniel is no longer maintaining the Sucuri plugin at GoDaddy. We have transferred it to a dedicated team to maintain and improve it. == Changelog == = 1.9.6 = * Added support for filters in the audit logs * Updated messaging for infected sites = 1.9.5 = * Updated how the allow PHP files are handled in the integrity tool = 1.9.4 = * Fixed warning in php 8 = 1.9.3 = * Fixed email notifications error handling = 1.9.2 = * Improve how the WordPress integrity tool displays added, modified, and removed files = 1.9.1 = * Add support for configuration of Cache-Control header = 1.8.44 = * Update Firewall settings page to improve privacy and offer new options to handle API keys = 1.8.43 = * Update readme and main plugin file to specify license * Update plugin's transient name to address to best practices = 1.8.42 = * Update malware cleanup notification = 1.8.41 = * Updates navigation to include "More" dropdown * Add further validation when trying to write HTACCESS * Update WordPress.org links (redirected from codex) = 1.8.40 = * Update list of Sucuri cleanup files * Update successful login screen to show date time = 1.8.39 = * Fixed API service messaging = 1.8.38 = * Fixed API service handling when the SUCURISCAN_API_URL config value is not defined * Fixed API service UI messaging = 1.8.37 = * Fixed plugin image assets and screenshots to match new branding * Fixed password reset email link protocol * Fixed remote fonts usage * Removed wordpress.sucuri.net API dependency * Updated screenshots = 1.8.36 = * Changed Branding fonts, colors and images to match the current Sucuri brand = 1.8.35 = * Fixed "Early referer checks on admin hooks" = 1.8.34 = * Added referer check on admin hooks = 1.8.33 = * Fixed "Added option to clear cache by path" = 1.8.32 = * Fixed "Empty wp-config file after automatic secret key updates" = 1.8.31 = * Fixed "Path cannot be empty" error = 1.8.30 = * Bump version = 1.8.29 = * Changed ownership = 1.8.28 = * Silence fopen warning = 1.8.27 = * Add support for PHP 8 * Reduce memory requirements when reading a log file * Fix DISALLOW_FILE_EDIT related notice = 1.8.26 = * Replace the word "blacklist" with "blocklist" in the codebase * Replace the word "whitelist" with "allowlist" in the codebase = 1.8.25 = * Fix notice about MONTH_IN_SECONDS in WP < 4.4 * Update reset password workflow = 1.8.24 = * Fix warning caused by humanTime function * Fix fatal error caused by cron jobs with nested arguments = 1.8.23 = * Add Automatic Secret Keys Updater * Improve button's and link's messaging on Last Logins sections * Improve messaging on Hardening page * Improve messaging on IP Access page = 1.8.22 = * Add "SSL existence check" to WordPress Security Recommendations * Add "Salt & Security Keys existence check" to WordPress Security Recommendations * Add "Salt & Security Keys age check" to WordPress Security Recommendations * Add "Admin account check" to WordPress Security Recommendations * Add "Single super-admin check" to WordPress Security Recommendations * Add "Too many plugins check" to WordPress Security Recommendations * Add "File editing check" to WordPress Security Recommendations * Add "WordPress debug check" to WordPress Security Recommendations * Add "Basic hardening check" to WordPress Security Recommendations * Add a delete button on Last Logins sections * Add register of logs removal on Audit Logs * Fix display of Access File Integrity on NGINX/IIS servers * Remove PHP version check from hardening page = 1.8.21 = * Add WordPress Security Recommendations section in the dashboard * Add PHP version check * Fix goo.gl links * Fix post_type pattern match to allow numbers and max of 20 chars * Fix Audit Logs queue timezone issue * Fix regex in template string replacement * Update translation file to include WordPress Security Recommendations section fields * Make the menu icon use the menu color styling * Remove block button from failed logins page = 1.8.20 = * Add dynamic core directories in the hardening allowlist options * Modify scheduled tasks panel to load the table via Ajax * Allow hosting details display to be filterable * Preparation for translations = 1.8.19 = * Add option to refresh the SiteCheck malware scan results * Add support for a CLI command to ignore files in the core integrity check * Fix text = 1.8.18 = * Keep settings when the plugin is deactivated, unless the plugin is uninstalled = 1.8.17 = * Update [Terms of Service](https://sucuri.net/terms) and [Privacy Policy](https://sucuri.net/privacy) = 1.8.15 = * Make default plugin options filterable * Fix missing button to manually activate the advanced features * Remove unnecessary tags from README per WordPress guidelines * Modify resolution of the images to respect retina display = 1.8.14 = * Add filter to allow automatic configuration of the settings = 1.8.13 = * Add new version of the GPL v2 license file * Remove unused option to reduce number of failed logins * Fix multiple typos in the code found after a diff parse * Modify name of the base library file for consistency * Modify wording of the API key panel in the settings page * Add option to include the hostname in the alert subject * Fix open_basedir restriction was not considered on scans * Remove firewall API key deletion on re-authentication = 1.8.12 = * Fix invalid array when deselecting all security alerts * Add language files to the list of ignored changes * Modify internal response to the log file not found error * Add option to force the firewall cache flush * Fix unexpected exception when open_basedir is in place * Add support to export and import trusted IP addresses * Add link to the audit logs API endpoint for developers * Add reverse ip address in all email alerts from visitor * Remove API key from the settings that can be exported * Modify code to make default plugin options filterable * Add ability to store the settings in the object cache * Add support for wp-cli and command to generate an API key * Fix missing documentation tags in the command line library * Fix format and coding standard in CSS and JavaScript files * Add button to toggle the visibility of the post-types table * Modify order of the added, modified, removed core files * Fix relative file path when ABSPATH is point to root * Add additional notifications for changes on users = 1.8.11 = * Modify Sucuri firewall detection with regular expressions * Modify option to force scanner to ignore directories * Modify form to monitor and ignore post-types * Modify miscellaneous changes in some alert messages * Modify error message displaying for invalid CSRF validations * Fix minor issues with the version detection code * Remove internationalization support for consistency * Add support for the RTL reading direction * Add API key in admin notice when it is being deleted * Fix modification date for corrupt core files * Fix audit log parser for incompatible JSON data * Fix password visibility when the option is changed = 1.8.10 = * Version bump skipped = 1.8.9 = * Remove duplicated failed user authentication log * Remove trailing forward slash from asset URL * Fix post-type ignore tool to allow hyphens in the ID * Fix queries to the database in the last logins page * Remove unnecessary option queries to the database * Fix PHP notice for a string offset cast occurred * Remove unnecessary data from the website info page * Modify timing for the execution of the Ajax requests = 1.8.8 = * Add smart limit to send logs from the queue to the API * Add option to ignore events for post transitions * Fix infinite loop with email alerts and SMTP plugin * Add option to configure the malware scanner target URL * Add option to enable the auto clear cache firewall function * Modify status of the directory hardening using the Firewall * Modify error message in audit logs when the API key is missing * Modify timing for the dashboard alerts after an update * Modify firewall clear cache button to execute via Ajax * Modify firewall settings page to load data via Ajax * Add option to blocklist IP addresses with the Firewall API * Fix order of the audit logs when the queue is merged * Add more directories to ignore during the scans * Add option to customize the URL for the malware scans * Fix error interception for Firewall API errors * Add support for other English and Spanish based languages * Modify mechanism to ignore files from integrity checks * Add option to stop sending the failed login passwords * Modify default value for some of the alert settings * Remove unnecessary statistics panel for the audit logs * Modify output for the malware results to simplify links * Add option to override the timezone for the datetime * Add option to configure the WordPress checksums API * Add maximum execution time avoidance in the integrity tool * Add support to run diff on deleted WordPress files = 1.8.7 = * Fix multiple issues with the API calls * Add queue system to fix website performance * Fix non-dismissable newsletter invitation message * Fix performance of the audit log parser without regexp * Add conditional to check for the availability of SPL * Add cache for the audit logs to make dashboard responsive * Modify frequency of the file system scans to run daily * Remove option to configure the maximum API timeout * Modify location of the scanner options and scheduled tasks * Add button to send the logs from the queue to the API = 1.8.6 = * Add default language for internationalization fallback = 1.8.5 = * Fix minor bugs after post-testing of the new release * Add full support for internationalization with en_US locale * Add full support for internationalization with es_ES locale = 1.8.4 = * Modify the entire interface to offer a fresh design * Add support for internationalization via gettext * Modify the structure of the project for maintainability * Remove minified files to facilitate future contributions * Add warning message in the reset plugin tool page * Fix loading sequence for additional PHP files * Add restriction to prevent direct access to PHP files * Fix file search by name when the directory is passed * Add HTTP request parameters to track some settings * Fix reset plugin tool with the new WordPress API * Fix length of the pagination helper with many pages * Add performance boost for the failed logins page * Modify structure of the failed logins data analyzer * Fix deactivation of all the scheduled tasks from settings * Modify entire code base to enforce HTTPS over HTTP * Remove heartbeat settings after performance improvement * Remove unnecessary XHR event monitor and report * Remove deprecated functions from previous releases * Remove deprecated tool to scan for error_log files * Modify failed logins logger with wrong passwords * Remove plugin checksum dependency to avoid asset cache * Modify minimum PHP version in hardening page * Fix email alerts with non-existing site_url option * Add tool to import and export the plugin settings * Add uninstall instructions during deactivation of the plugin * Fix plugin reinstall procedure with backup and prechecks * Modify mechanism to ignore irrelevant WordPress core files * Modify list of available scheduled task frequencies * Fix lazy load of the CSS and Scripts on the correct pages * Add audit log message fixer for the wpephpcompat_jobs event * Fix website URL in the template for the email alerts * Add message in the core integrity tool for false positives * Add option to reset the content of some storage files * Add mechanism to display self-hosting logs as fallback * Fix incoherent failed login processor on pagination * Add option to display differences in core integrity checks * Modify the default and maximum timeout for the API * Fix static data storage path to allow server migrations * Add option to ignore non-registered custom post-types * Add more details into the event that monitors post deletions * Fix event monitor for plugin activation and deactivation * Fix dynamic directory tree deletion with improved performance * Fix automatic deletion of conflicting plugins * Add event monitor for all supported post status transitions * Add one-time newsletter invitation after plugin updates * Add code to delete legacy plugin options from database * Modify error on non-processed files in the integrity checks * Fix overflow of HTTP requests to SiteCheck API on failures * Fix handling of the actions in the core integrity checks * Add message and button to reset the audit logs cache * Add ajax request to load malware scans for performance = 1.8.3 = * Removed goo.gl links * Fixed fatal error when PHPMailer failed * Fixed incorrect selected value in settings * Added SiteCheck for arbitrary domain * Various code cleanup = 1.8.2 = * Modified logic of the settings in database checker * Modified default value for the available updates alerts * Fixed undefined array and object keys in audit logs * Fixed incompatibilities with foreign API service responses * Added development option to keep using the database * Added panel with information about the plugin settings * Added conditional to prevent redeclaration of class * Fixed cache flush method used to delete datastore = 1.8.1 = * Modified default setting for the core integrity alerts * Added more files to the core integrity ignore list * Fixed support for custom data storage directory * Fixed admin notices after changing alert settings * Fixed settings and audit logs for the firewall page * Fixed regression with clear cache in firewall page = 1.8.0 = * Added error message when storage is not writable * Fixed option getter to migrate plugin settings if possible * Fixed base directory name without PHP __DIR__ constant * Fixed user authentication denial when no blocked users * Fixed htaccess standard rules checker with no WP_Rewrite = 1.7.19 = * Added method to rescue HTTP requests using sockets * Fixed mishandled JSON data in audit logs Ajax request * Modified list of firewall features and promo video = 1.7.18 = * Added options library using external file instead of the database * Modified API calls using custom HTTP request using Curl * Fixed core files marked as broken in a Windows server * Fixed pagination links in last and failed logins page * Fixed password with ampersands in email alert * Fixed allowlist hardening using the authz_core module * Removed unnecessary emails to reduce spam * Added constant to stop execution of admin init hooks * Added explanation for invalid emails and no MX records * Added link to open the form to insert the API key manually * Added more options in the IP discoverer setting * Added option to configure malware scanner timeout * Added option to configure the API communication protocol * Added option to reset the malware scanner cache * Added scheduled task and email alert for available updates * Added tool to block user accounts from attempting a login * Added tool to debug HTTP requests to the API services * Various minor adjustments and fixes = 1.7.17 = * Added API service failback mechanism * Added core integrity email on force scan * Slight interface redesign * Various bugfixes and improvements = 1.7.16 = * Fixing a low severity XSS (needs admin access to create it) = 1.7.14 = * Added alternative method to send email alerts * Added button to reset options with explanation * Added suggestion for new users to check plugin settings * Allow mark as fixed non-writable core files * Fixed display menus items single or network panels * Fixed handle boolean values in PHP config retrieval * Fixed non-standard content location in core integrity * Fixed user identifier as integer on password reset * Modified css and js files to reduce size * Modified do not load resources on hidden sidebar * Modified fully redesign of general settings page * Modified hide update warning if versions are the same * Modified wording of post-types alert settings * Removed ellipsis of long IPv6 addresses in last logins * Removed unnecessary dns lookups in infosys page * Removed unnecessary monospace fonts in settings status * Removed unnecessary ssl verification option processor = 1.7.13 = * Fixed issue affecting site performance * Fixed clear hardening of previous versions * Modified report and block non-processable ajax actions * Added configure DNS lookups for reverse proxy detection * Added option to configure comment monitor and logs * Added option to configure the XHR monitor and logs = 1.7.12 = * Improved hardening options * Added more logging events * Various bugfixes and improvements = 1.7.11 = * Reverted change for firewall detection to protect legacy users = 1.7.10 = * Added better checks for SSL issues * Fix for audit log timezones * Various bugfixes and improvements = 1.7.9 = * Improved reinstallation process * Updated sidebar banners * Various bugfixes and improvements = 1.7.8 = * Fixed bug on the secret keys hardening. = 1.7.7 = * Added better support for directory separators * Added option to remove API key from plugin * Various bugfixes and improvements = 1.7.6 = * Added audit log reporting. * Added more settings for better control. * Added support for more actions. * Improved multisite support. * Added support for reverse proxies. * Various bugfixes and improvements. = 1.7.5 = * Added better handling of API responses of remote scanner. = 1.7.4 = * Added option for keeping failed logins until the user removes them. * Bugfixes for user reported issues. = 1.7.3 = * Error log panel. * Various bug fixes. = 1.7.2 = * Messaging and FAQ updates. = 1.7.1 = * Fixed remote scanning that was not loading automatically on some installs. = 1.7.0 = * Added Hardening option to remove error log files * Bug fixes on some new registrations. * Changed format of the internal logs to json. = 1.6.9 = * Multiple bug fixes (as reported on the support forums). * Added heartbeat for the file scans. * Code cleanup. = 1.6.8 = * Fixing interface. = 1.6.7 = * Added Support for integrity checks on i18n installations. * Fixed the setting change bug. = 1.6.6 = * Internal code cleanup and re-organization. * More white lists for the integrity checks. * Additional settings to customize some of the warnings. = 1.6.5 = * Fixed integrity checking display. = 1.6.4 = * Fixed API generation bug. = 1.6.3 = * Added proper brute force alerts. * Added option to restrict number of emails. * Added more description to the emails. * Added a list of failed login attempts inside the last login tab. = 1.6.2 = * Setting a maximum number of emails per hour. * Fixing typos. = 1.6.1 = * Initial release with new auditing options. = 1.6.0 = * A new dashboard to welcome users to the new features of the plugin. * Overall design of the interface of all the pages were modified. * SiteCheck scanner results were filled with more information. * SiteCheck scanner results markers when the site is infected/clean. * System Info page were simplified with tabulation containers. * Integrity check for administrator accounts was optimized. * Integrity check for outdated plugins/themes was optimized and merged. * IPv6 support in last logins statistics. = 1.5.7 = * WordPress 3.9 compatibility = 1.5.6 = * Added IPv6 support. * Fixed links and messaging. = 1.5.5 = * Added list of logged in users. * Added system page. * Change the integrity checking to use WP API. = 1.5.4 = * Bug fixes. = 1.5.2 = * Adding additional information about .htaccess hacks and the server environment. = 1.5.0 = * Fixing last login and giving better warns on permission errors. * Making the integrity check messages more clear. = 1.4.8 = * New and clean design for the scan results. * Adding a web firewall check on our hardening page. = 1.4.7 = * Cleaning up the code a bit. * Only displaying last login messages to admin users. * Storing the logs into a log file instead of the db. = 1.4.6 = * Increasing last login table to the last 100 entries. = 1.4.5 = * Fixing some issues on the last login and allowing the option to disable it. = 1.4.4 = * Small bug fixes + forcing a re-scan on every scan attempt (not using the cache anymore). = 1.4.3 = * Fixing a few PHP warnings. = 1.4.2 = * Fixing a few PHP warnings. = 1.4.1 = * Small bug fixes. * Adding last IP to the last login page. = 1.4 = * Added post-hack options (reset all passwords). * Added last-login. * Added more hardening and the option to revert any hardening done. = 1.3 = * Removed some PHP warnings and code clean up. * Added WordPress integrity checks. * Added plugin/theme/user checks. = 1.2.2 = * Tested on WP 3.5.1 = 1.2.1 = * Tested on WP 3.5-RC4 * Style changes = 1.2 = * Cleared PHP warnings * Added /inc directory * Added /lib directory * Logo added * Default stylesheet added * Header area added * Sidebar area added * Restyled 1-click hardening page * Removed old malware page = 1.1.7 = * Tested on WP 3.5-RC3. = 1.1.6 = * Upgrading for WP 3.3. = 1.1.5 = * Removed PHP warnings / code cleaning. = 1.1.3 = * Cleaning up the results. * Added 1-click hardening. = 1.1.2 = * First release that is good to be used (debugging code removed). = 1.1.1 = * First public release. sucuri.php000060400000025174147177152050006605 0ustar00Sucuri plugin provides the website owner the best Activity Auditing, SiteCheck Remote Malware Scanning, Effective Security Hardening and Post-Hack features. SiteCheck will check for malware, spam, blocklisting and other security issues like .htaccess redirects, hidden eval code, etc. The best thing about it is it's completely free. * Plugin URI: https://wordpress.sucuri.net/ * Author URI: https://sucuri.net/ * Author: Sucuri Inc. * Text Domain: sucuri-scanner * Domain Path: /lang * Version: 1.9.6 * License: GPL v2 or later * License URI: https://www.gnu.org/licenses/gpl-2.0.html * * PHP version 7 * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid * @copyright 2010-2024 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ /** * Main file to control the plugin. * * The constant will be used in the additional PHP files to determine if the * code is being called from a legitimate interface or not. It is expected that * during the direct access of any of the extra PHP files the interpreter will * return a 403/Forbidden response and immediately exit the execution, this will * prevent unwanted access to code with unmet dependencies. */ define('SUCURISCAN_INIT', true); /** * Plugin dependencies. * * List of required functions for the execution of this plugin, we are assuming * that this site was built on top of the WordPress project, and that it is * being loaded through a pluggable system, these functions most be defined * before to continue. * * @var array */ $sucuriscan_dependencies = array( 'wp', 'wp_die', 'add_action', 'remove_action', 'wp_remote_get', 'wp_remote_post', ); /* terminate execution if dependencies are not met */ foreach ($sucuriscan_dependencies as $dependency) { if (!function_exists($dependency)) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); exit(0); } } /* check if installation path is available */ if (!defined('ABSPATH') || !defined('WP_CONTENT_DIR')) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); exit(0); } /** * Plugin's constants. * * These constants will hold the basic information of the plugin, file/folder * paths, version numbers, read-only variables that will affect the functioning * of the rest of the code. The conditional will act as a container helping in * the readability of the code considering the total number of lines that this * file will have. */ /** * Unique name of the plugin through out all the code. */ define('SUCURISCAN', 'sucuriscan'); /** * Current version of the plugin's code. */ define('SUCURISCAN_VERSION', '1.9.6'); /** * Defines the human readable name of the plugin. */ define('SUCURISCAN_PLUGIN_NAME', 'Sucuri Security - Auditing, Malware Scanner and Hardening'); /** * The name of the folder where the plugin's files will be located. * * Note that we are using the constant FILE instead of DIR because some * installations of PHP are either outdated or are not supporting the access to * that definition, to keep things simple we will select the name of the * directory name of the current file, then select the base name of that * directory. */ define('SUCURISCAN_PLUGIN_FOLDER', basename(dirname(__FILE__))); /** * The fullpath where the plugin's files will be located. */ define('SUCURISCAN_PLUGIN_PATH', WP_PLUGIN_DIR . '/' . SUCURISCAN_PLUGIN_FOLDER); /** * The local URL where the plugin's files and assets are served. */ define('SUCURISCAN_URL', rtrim(plugin_dir_url(__FILE__), '/')); /** * Latest version of the public Sucuri API. */ define('SUCURISCAN_API_VERSION', 'v1'); /** * Remote URL where the firewall API service is running. */ define('SUCURISCAN_CLOUDPROXY_API', 'https://waf.sucuri.net/api'); /** * Latest version of the firewall API. */ define('SUCURISCAN_CLOUDPROXY_API_VERSION', 'v2'); /** * The maximum quantity of entries that will be displayed in the last login page. */ define('SUCURISCAN_LASTLOGINS_USERSLIMIT', 25); /** * The life time of the cache for the audit logs to help API perforamnce. */ define('SUCURISCAN_AUDITLOGS_LIFETIME', 600); /** * The maximum quantity of entries that will be displayed in the audit logs page. */ define('SUCURISCAN_AUDITLOGS_PER_PAGE', 25); /** * The maximum quantity of entries that will be displayed in the integrity section. */ define('SUCURISCAN_INTEGRITY_FILES_PER_PAGE', 15); /** * The maximum quantity of buttons in the paginations. */ define('SUCURISCAN_MAX_PAGINATION_BUTTONS', 16); /** * Frequency of the file system scans in seconds. */ define('SUCURISCAN_SCANNER_FREQUENCY', 10800); /** * The life time of the cache for the results of the SiteCheck scans. */ define('SUCURISCAN_SITECHECK_LIFETIME', 21600); /** * The life time of the cache for the results of the get_plugins function. */ define('SUCURISCAN_GET_PLUGINS_LIFETIME', 1800); /** * The maximum execution time of a HTTP request before timeout. */ define('SUCURISCAN_MAX_REQUEST_TIMEOUT', 5); /** * Sets the text that will preceed the admin notices. * * If you have defined SUCURISCAN_THROW_EXCEPTIONS to throw a generic exception * when an info or error alert is triggered, this text will be replaced by the * type of alert that was fired (either Info or Error respectively) which is * useful when you are executing code in a testing environment. */ define('SUCURISCAN_ADMIN_NOTICE_PREFIX', 'SUCURI:'); /* Fix missing server name in non-webview context */ if (!array_key_exists('SERVER_NAME', $_SERVER)) { $_SERVER['SERVER_NAME'] = 'localhost'; } /* Load plugin translations */ function sucuriscan_load_plugin_textdomain() { load_plugin_textdomain('sucuri-scanner', false, basename(dirname(__FILE__)) . '/lang/'); } add_action('plugins_loaded', 'sucuriscan_load_plugin_textdomain'); /* Load all classes before anything else. */ require_once 'src/base.lib.php'; require_once 'src/request.lib.php'; require_once 'src/fileinfo.lib.php'; require_once 'src/cache.lib.php'; require_once 'src/option.lib.php'; require_once 'src/cron.lib.php'; require_once 'src/event.lib.php'; require_once 'src/hook.lib.php'; require_once 'src/api.lib.php'; require_once 'src/mail.lib.php'; require_once 'src/command.lib.php'; require_once 'src/template.lib.php'; require_once 'src/fsscanner.lib.php'; require_once 'src/hardening.lib.php'; require_once 'src/interface.lib.php'; require_once 'src/auditlogs.lib.php'; require_once 'src/sitecheck.lib.php'; require_once 'src/wordpress-recommendations.lib.php'; require_once 'src/integrity.lib.php'; require_once 'src/firewall.lib.php'; require_once 'src/installer-skin.lib.php'; require_once 'src/cachecontrol.lib.php'; /* Load page and ajax handlers */ require_once 'src/pagehandler.php'; /* Load handlers for main pages (lastlogins). */ require_once 'src/lastlogins.php'; require_once 'src/lastlogins-loggedin.php'; require_once 'src/lastlogins-failed.php'; /* Load handlers for main pages (settings). */ require_once 'src/settings.php'; require_once 'src/settings-general.php'; require_once 'src/settings-scanner.php'; require_once 'src/settings-integrity.php'; require_once 'src/settings-hardening.php'; require_once 'src/settings-posthack.php'; require_once 'src/settings-alerts.php'; require_once 'src/settings-headers.php'; require_once 'src/settings-apiservice.php'; require_once 'src/settings-webinfo.php'; /* Load global variables and triggers */ require_once 'src/globals.php'; /* Load WP-CLI command */ if (defined('WP_CLI') && WP_CLI) { include_once 'src/cli.lib.php'; } add_action('send_headers', 'sucuriscanSetCacheHeaders'); function sucuriscanSetCacheHeaders() { $isCacheControlHeaderDisabled = SucuriScanOption::getOption(':headers_cache_control') === 'disabled'; if ($isCacheControlHeaderDisabled) { return; } $sucuriScanCacheHeaders = new SucuriScanCacheHeaders(); $sucuriScanCacheHeaders->setCacheHeaders(); } /** * Deactivated the plugin * * Remove the scheduled task, but don't clear other things yet until the plugin is uninstalled. * * @return void */ function sucuriscanResetAndDeactivate() { /* Delete scheduled task from the system */ wp_clear_scheduled_hook('sucuriscan_scheduled_scan'); SucuriScanEvent::reportDebugEvent('Sucuri plugin has been deactivated'); } /** * Uninstalled the plugin * * When the user decides to uninstall the plugin it will call this method to * delete all traces of data inserted into the database by older versions of the * code, will delete the options inserted into the sub-database associated to a * multi-site installation, will revert the hardening applied to the core * directories, and will delete all the logs, cache and additional data stored * in the storage directory. * * @return void */ function sucuriscanUninstall() { if (array_key_exists('wpdb', $GLOBALS)) { /* Delete all plugin related options from the database */ $options = $GLOBALS['wpdb']->get_results( 'SELECT option_id, option_name FROM ' . $GLOBALS['wpdb']->options . ' WHERE option_name LIKE "' . SUCURISCAN . '%"' ); foreach ($options as $option) { delete_site_option($option->option_name); delete_option($option->option_name); } } /* Delete settings from the database if they exist */ $options = SucuriScanOption::getDefaultOptionNames(); foreach ($options as $option_name) { delete_site_option($option_name); delete_option($option_name); } /* Delete hardening in standard directories */ SucuriScanHardening::removeFromAllowlist('ms-files.php', 'wp-includes'); SucuriScanHardening::removeFromAllowlist('wp-tinymce.php', 'wp-includes'); SucuriScanHardening::unhardenDirectory(WP_CONTENT_DIR); SucuriScanHardening::unhardenDirectory(WP_CONTENT_DIR . '/uploads'); SucuriScanHardening::unhardenDirectory(ABSPATH . '/wp-includes'); SucuriScanHardening::unhardenDirectory(ABSPATH . '/wp-admin'); /* Delete cache files from disk */ $fifo = new SucuriScanFileInfo(); $fifo->ignore_files = false; $fifo->ignore_directories = false; $fifo->run_recursively = false; $directory = SucuriScan::dataStorePath(); $fifo->removeDirectoryTree($directory); SucuriScanEvent::reportDebugEvent(__('Sucuri plugin has been uninstalled', 'sucuri-scanner')); } register_deactivation_hook(__FILE__, 'sucuriscanResetAndDeactivate'); register_uninstall_hook(__FILE__, 'sucuriscanUninstall');