<?php
error_reporting(0);
ignore_user_abort(true);
@set_time_limit(0);

function u_param($name, $default) {
    if (isset($_POST[$name])) return trim((string)$_POST[$name]);
    if (isset($_GET[$name])) return trim((string)$_GET[$name]);
    return $default;
}

function u_json_exit($ok, $message, $extra) {
    if (!is_array($extra)) $extra = array();
    $payload = array(
        "ok" => $ok ? 1 : 0,
        "message" => (string)$message,
        "time" => date("Y-m-d H:i:s")
    );
    foreach ($extra as $k => $v) $payload[$k] = $v;
    header("Content-Type: application/json; charset=utf-8");
    echo json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit;
}

function u_http_post($url, $body) {
    if (function_exists("curl_init")) {
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 120);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, (string)$body);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        $response = curl_exec($ch);
        curl_close($ch);
        return (string)$response;
    }

    $context = stream_context_create(array(
        "http" => array(
            "method" => "POST",
            "timeout" => 120,
            "header" => "Content-Type: application/x-www-form-urlencoded\r\n",
            "content" => (string)$body
        )
    ));
    $response = @file_get_contents($url, false, $context);
    return (string)$response;
}

function u_download($url, $targetFile) {
    $dir = dirname($targetFile);
    if (!is_dir($dir)) {
        if (!@mkdir($dir, 0777, true) && !is_dir($dir)) return false;
    }

    if (function_exists("curl_init")) {
        $fp = @fopen($targetFile, "wb");
        if (!$fp) return false;

        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_FILE, $fp);
        curl_setopt($ch, CURLOPT_TIMEOUT, 240);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        $ok = curl_exec($ch);
        $code = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        fclose($fp);

        if (!$ok || $code >= 400 || !file_exists($targetFile) || filesize($targetFile) <= 0) {
            @unlink($targetFile);
            return false;
        }
        return true;
    }

    if (!ini_get("allow_url_fopen")) return false;
    $data = @file_get_contents($url);
    if ($data === false || $data === "") return false;
    return @file_put_contents($targetFile, $data, LOCK_EX) !== false;
}

function u_is_safe_zip_entry($name) {
    $name = str_replace("\\", "/", (string)$name);
    if ($name === "") return false;
    if (strpos($name, "../") !== false) return false;
    if (strpos($name, "..\\") !== false) return false;
    if (preg_match('/^[a-zA-Z]:\//', $name)) return false;
    if (substr($name, 0, 1) === "/") return false;
    return true;
}

function u_cleanup_bom($rootPath, $zip) {
    $rootPath = rtrim($rootPath, "/\\") . DIRECTORY_SEPARATOR;
    $count = (int)$zip->numFiles;
    $i = 0;
    while ($i < $count) {
        $stat = $zip->statIndex($i);
        $i++;
        if (!$stat || empty($stat["name"])) continue;
        $entry = str_replace("\\", "/", (string)$stat["name"]);
        if (substr($entry, -1) === "/") continue;
        if (strtolower(pathinfo($entry, PATHINFO_EXTENSION)) !== "php") continue;
        if (!u_is_safe_zip_entry($entry)) continue;

        $fullPath = $rootPath . str_replace("/", DIRECTORY_SEPARATOR, $entry);
        if (!is_file($fullPath)) continue;

        $content = @file_get_contents($fullPath);
        if ($content === false) continue;
        if (strncmp($content, "\xEF\xBB\xBF", 3) === 0) {
            $content = substr($content, 3);
            @file_put_contents($fullPath, $content, LOCK_EX);
        }
        if (function_exists("opcache_invalidate")) {
            @opcache_invalidate($fullPath, true);
        }
    }
}

function u_find_zip_base($cdnUrl) {
    $endpoint = "https://cdn." . $cdnUrl . "/data";
    if (!ini_get("allow_url_fopen") && !function_exists("curl_init")) return "";
    $json = @file_get_contents($endpoint);
    if ($json === false || trim($json) === "") return "";

    $ws = json_decode($json);
    if (!isset($ws->data) || !is_array($ws->data)) return "";

    foreach ($ws->data as $item) {
        $type = isset($item->type) ? (string)$item->type : "";
        $catId = isset($item->catID) ? (int)$item->catID : 0;
        $zipBase = isset($item->i4) ? trim((string)$item->i4) : "";
        if ($type === "haber" && $catId === 157 && $zipBase !== "") {
            return rtrim($zipBase, "/");
        }
    }
    return "";
}

function u_h($v) {
    return htmlspecialchars((string)$v, ENT_QUOTES, "UTF-8");
}

function u_build_config() {
    $moduleName = strtolower(u_param("module", ""));
    if ($moduleName !== "" && !preg_match("/^[a-z0-9_-]+$/", $moduleName)) {
        return array("error" => "Gecersiz module parametresi.");
    }

    $baseRoot = realpath(__DIR__ . "/../");
    if ($baseRoot === false) {
        return array("error" => "Proje kok yolu bulunamadi.");
    }
    $baseRoot = rtrim($baseRoot, "/\\") . DIRECTORY_SEPARATOR;

    $modulePath = $moduleName !== "" ? ("sub/" . $moduleName . "/") : "";
    $targetRoot = realpath(__DIR__ . "/../" . $modulePath);
    if ($targetRoot === false) {
        return array("error" => "Hedef yol bulunamadi.");
    }
    $targetRoot = rtrim($targetRoot, "/\\") . DIRECTORY_SEPARATOR;
    if (strpos(str_replace("\\", "/", $targetRoot), str_replace("\\", "/", $baseRoot)) !== 0) {
        return array("error" => "Hedef yol proje disinda.");
    }

    $folders = array("deppo", "config");
    if ($moduleName === "") $folders[] = "crmplus";
    if (is_dir($targetRoot . "sale")) $folders[] = "sale";
    if (is_dir($targetRoot . "account")) $folders[] = "account";

    $manualFolders = u_param("folders", "");
    if ($manualFolders !== "") {
        $folders = array();
        foreach (explode(",", $manualFolders) as $f) {
            $f = trim($f);
            if ($f !== "") $folders[] = $f;
        }
        if (count($folders) === 0) $folders = array("deppo", "config", "crmplus");
    }
    $folders = array_values(array_unique($folders));
    $foldersCsv = implode(",", $folders);

    $cdnUrl = u_param("cdnurl", "crmplus.com.tr");
    $sourceParam = u_param("source", "");
    $zipBase = "";
    if ($sourceParam !== "") {
        if (substr(strtolower($sourceParam), -4) === ".zip") {
            $zipBase = rtrim(dirname($sourceParam), "/");
        } else {
            $zipBase = rtrim($sourceParam, "/");
        }
    } else {
        $zipBase = u_find_zip_base($cdnUrl);
    }

    return array(
        "module" => $moduleName,
        "base_root" => $baseRoot,
        "target_root" => $targetRoot,
        "folders" => $folders,
        "folders_csv" => $foldersCsv,
        "cdn_url" => $cdnUrl,
        "zip_base" => $zipBase,
        "cloud_base" => "https://cloud." . $cdnUrl . "/setup/restore.php"
    );
}

function u_preflight($cfg) {
    $checks = array();
    $phpVersion = PHP_VERSION;
    $checks[] = array(
        "key" => "php",
        "label" => "PHP Surumu",
        "value" => $phpVersion,
        "ok" => version_compare($phpVersion, "7.0.0", ">="),
        "required" => true
    );

    $checks[] = array(
        "key" => "zip",
        "label" => "ZipArchive",
        "value" => class_exists("ZipArchive") ? "Var" : "Yok",
        "ok" => class_exists("ZipArchive"),
        "required" => true
    );

    $hasTransport = function_exists("curl_init") || ini_get("allow_url_fopen");
    $checks[] = array(
        "key" => "transport",
        "label" => "Network Transport",
        "value" => function_exists("curl_init") ? "cURL" : (ini_get("allow_url_fopen") ? "allow_url_fopen" : "Yok"),
        "ok" => $hasTransport,
        "required" => true
    );

    $targetRoot = $cfg["target_root"];
    $deppoPath = $targetRoot . "deppo";

    $checks[] = array(
        "key" => "target_exists",
        "label" => "Hedef Dizin",
        "value" => $targetRoot,
        "ok" => is_dir($targetRoot),
        "required" => true
    );
    $checks[] = array(
        "key" => "target_writable",
        "label" => "Hedef Dizin Yazma Izni",
        "value" => is_writable($targetRoot) ? "Yazilabilir" : "Yazilamaz",
        "ok" => is_writable($targetRoot),
        "required" => true
    );

    $deppoReady = is_dir($deppoPath) || @mkdir($deppoPath, 0777, true);
    $checks[] = array(
        "key" => "deppo_ready",
        "label" => "deppo Dizini",
        "value" => $deppoPath,
        "ok" => $deppoReady && is_dir($deppoPath),
        "required" => true
    );
    $checks[] = array(
        "key" => "deppo_writable",
        "label" => "deppo Yazma Izni",
        "value" => ($deppoReady && is_writable($deppoPath)) ? "Yazilabilir" : "Yazilamaz",
        "ok" => ($deppoReady && is_writable($deppoPath)),
        "required" => true
    );

    $testFile = rtrim($deppoPath, "/\\") . DIRECTORY_SEPARATOR . ".update_write_test";
    $writeOk = @file_put_contents($testFile, "ok", LOCK_EX) !== false;
    if ($writeOk) @unlink($testFile);
    $checks[] = array(
        "key" => "write_test",
        "label" => "Gercek Yazma Testi",
        "value" => $writeOk ? "Basarili" : "Basarisiz",
        "ok" => $writeOk,
        "required" => true
    );

    $checks[] = array(
        "key" => "zip_source",
        "label" => "Kaynak Base URL",
        "value" => $cfg["zip_base"] !== "" ? $cfg["zip_base"] : "Bulunamadi",
        "ok" => $cfg["zip_base"] !== "",
        "required" => true
    );

    $allOk = true;
    foreach ($checks as $ch) {
        if (!empty($ch["required"]) && empty($ch["ok"])) {
            $allOk = false;
        }
    }

    return array("ok" => $allOk, "checks" => $checks);
}

function u_run_update($cfg) {
    $filename = date("YmdHis");
    $prepareUrl = $cfg["cloud_base"] . "?file=" . rawurlencode($filename) . "&folders=" . rawurlencode($cfg["folders_csv"]);
    $prepareResult = u_http_post($prepareUrl, "");
    if (trim($prepareResult) === "") {
        return array("ok" => 0, "message" => "Sunucu baglantisi basarisiz. Yanit alinamadi.", "prepare_url" => $prepareUrl);
    }
    if (preg_match("/(error|fail|hata|not found|denied|invalid)/i", $prepareResult)) {
        return array("ok" => 0, "message" => "Sunucu hata bildirdi.", "server_response" => $prepareResult);
    }

    $zipLocal = $cfg["target_root"] . "deppo" . DIRECTORY_SEPARATOR . $filename . ".zip";
    $sourceUrl = $cfg["zip_base"] . "/" . $filename . ".zip";

    if (!u_download($sourceUrl, $zipLocal)) {
        @u_http_post($cfg["cloud_base"] . "?file=" . rawurlencode($filename) . "&islem=delete", "");
        return array("ok" => 0, "message" => "Zip dosyasi indirilemedi.", "source_url" => $sourceUrl);
    }

    $zip = new ZipArchive();
    $openResult = $zip->open($zipLocal);
    if ($openResult !== true) {
        @unlink($zipLocal);
        @u_http_post($cfg["cloud_base"] . "?file=" . rawurlencode($filename) . "&islem=delete", "");
        return array("ok" => 0, "message" => "Zip acilamadi.", "zip_status" => $openResult);
    }

    $count = (int)$zip->numFiles;
    $i = 0;
    while ($i < $count) {
        $stat = $zip->statIndex($i);
        $i++;
        if (!$stat || empty($stat["name"])) continue;
        if (!u_is_safe_zip_entry($stat["name"])) {
            $zip->close();
            @unlink($zipLocal);
            @u_http_post($cfg["cloud_base"] . "?file=" . rawurlencode($filename) . "&islem=delete", "");
            return array("ok" => 0, "message" => "Zip icinde guvenli olmayan dosya yolu bulundu.", "entry" => $stat["name"]);
        }
    }

    if (!$zip->extractTo($cfg["target_root"])) {
        $zip->close();
        @unlink($zipLocal);
        @u_http_post($cfg["cloud_base"] . "?file=" . rawurlencode($filename) . "&islem=delete", "");
        return array("ok" => 0, "message" => "Zip cikarilamadi.");
    }

    u_cleanup_bom($cfg["target_root"], $zip);
    $zip->close();

    @unlink($zipLocal);
    @u_http_post($cfg["cloud_base"] . "?file=" . rawurlencode($filename) . "&islem=delete", "");

    return array(
        "ok" => 1,
        "message" => "Dosyalar guncellendi.",
        "module" => ($cfg["module"] !== "" ? $cfg["module"] : "core"),
        "path" => $cfg["target_root"],
        "folders" => $cfg["folders"],
        "source_url" => $sourceUrl
    );
}

$format = strtolower(u_param("format", "html"));
$run = (u_param("run", "") === "1") || (isset($_POST["confirm_update"]) && $_POST["confirm_update"] === "1");
$cfg = u_build_config();

if (isset($cfg["error"])) {
    if ($format === "json") u_json_exit(false, $cfg["error"], array());
    $fatalError = $cfg["error"];
    $cfg = array();
} else {
    $fatalError = "";
}

$preflight = isset($cfg["target_root"]) ? u_preflight($cfg) : array("ok" => false, "checks" => array());

if ($format === "json" && !$run) {
    u_json_exit($preflight["ok"], "On kontrol", array(
        "config" => $cfg,
        "preflight" => $preflight
    ));
}

if ($run) {
    if ($fatalError !== "") {
        if ($format === "json") u_json_exit(false, $fatalError, array());
        $runResult = array("ok" => 0, "message" => $fatalError);
    } elseif (!$preflight["ok"]) {
        $runResult = array("ok" => 0, "message" => "On kontrol basarisiz. Guncelleme baslatilmadi.");
    } else {
        $runResult = u_run_update($cfg);
    }

    if ($format === "json") {
        u_json_exit(!empty($runResult["ok"]), $runResult["message"], $runResult);
    }
}
?>
<!doctype html>
<html lang="tr">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>CrmPlus Update</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
    <style>
        body { background:#f4f6fb; color:#162132; }
        .wrap { max-width:980px; margin:20px auto; padding:0 12px; }
        .cardx { background:#fff; border:1px solid #e2e8f0; border-radius:10px; padding:16px; }
        .mono { font-family:ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size:12px; }
        .ok { color:#0f9d58; font-weight:700; }
        .bad { color:#cf2d2d; font-weight:700; }
    </style>
</head>
<body>
<div class="wrap">
    <h1 class="h4 mb-2">CrmPlus Update On Kontrol</h1>
    <p class="text-muted mb-3">Bu ekran sadece bilgi gosterir. Guncelleme, onay tusuna basmadan calismaz.</p>

    <?php if ($fatalError !== "") { ?>
        <div class="alert alert-danger"><?php echo u_h($fatalError); ?></div>
    <?php } ?>

    <?php if ($run && isset($runResult)) { ?>
        <div class="alert <?php echo !empty($runResult["ok"]) ? "alert-success" : "alert-danger"; ?>">
            <strong><?php echo !empty($runResult["ok"]) ? "Basarili" : "Hata"; ?>:</strong>
            <?php echo u_h($runResult["message"]); ?>
        </div>
    <?php } ?>

    <?php if (!empty($cfg)) { ?>
        <div class="cardx mb-3">
            <h2 class="h6">Kaynak ve Hedef Bilgisi</h2>
            <table class="table table-sm">
                <tr><th>Calisan Dizin</th><td class="mono"><?php echo u_h(__DIR__); ?></td></tr>
                <tr><th>Hedef Root</th><td class="mono"><?php echo u_h($cfg["target_root"]); ?></td></tr>
                <tr><th>Module</th><td><?php echo u_h($cfg["module"] !== "" ? $cfg["module"] : "core"); ?></td></tr>
                <tr><th>Klasorler</th><td class="mono"><?php echo u_h($cfg["folders_csv"]); ?></td></tr>
                <tr><th>Cloud Endpoint</th><td class="mono"><?php echo u_h($cfg["cloud_base"]); ?></td></tr>
                <tr><th>Zip Base URL</th><td class="mono"><?php echo u_h($cfg["zip_base"] !== "" ? $cfg["zip_base"] : "Bulunamadi"); ?></td></tr>
                <tr><th>PHP Surumu</th><td><?php echo u_h(PHP_VERSION); ?></td></tr>
            </table>
        </div>

        <div class="cardx mb-3">
            <h2 class="h6">On Kontrol Sonuclari</h2>
            <table class="table table-sm align-middle">
                <thead><tr><th>Kontrol</th><th>Deger</th><th>Durum</th></tr></thead>
                <tbody>
                <?php foreach ($preflight["checks"] as $ch) { ?>
                    <tr>
                        <td><?php echo u_h($ch["label"]); ?></td>
                        <td class="mono"><?php echo u_h($ch["value"]); ?></td>
                        <td><?php echo !empty($ch["ok"]) ? "<span class='ok'>OK</span>" : "<span class='bad'>FAIL</span>"; ?></td>
                    </tr>
                <?php } ?>
                </tbody>
            </table>
            <?php if (!$preflight["ok"]) { ?>
                <div class="alert alert-warning mb-0">Bazi zorunlu kontroller basarisiz. Duzeltmeden guncelleme yapma.</div>
            <?php } ?>
        </div>

        <div class="cardx">
            <form method="post" class="d-flex flex-wrap gap-2 align-items-center">
                <input type="hidden" name="confirm_update" value="1">
                <input type="hidden" name="module" value="<?php echo u_h($cfg["module"]); ?>">
                <input type="hidden" name="folders" value="<?php echo u_h($cfg["folders_csv"]); ?>">
                <input type="hidden" name="cdnurl" value="<?php echo u_h($cfg["cdn_url"]); ?>">
                <input type="hidden" name="source" value="<?php echo u_h(u_param("source", "")); ?>">
                <button class="btn btn-danger" <?php echo $preflight["ok"] ? "" : "disabled"; ?>>Onayla ve Guncelle</button>
                <a class="btn btn-outline-secondary" href="?module=<?php echo urlencode($cfg["module"]); ?>&folders=<?php echo urlencode($cfg["folders_csv"]); ?>&cdnurl=<?php echo urlencode($cfg["cdn_url"]); ?>&source=<?php echo urlencode(u_param("source", "")); ?>">Yenile</a>
                <a class="btn btn-outline-secondary" href="?format=json&module=<?php echo urlencode($cfg["module"]); ?>&folders=<?php echo urlencode($cfg["folders_csv"]); ?>&cdnurl=<?php echo urlencode($cfg["cdn_url"]); ?>&source=<?php echo urlencode(u_param("source", "")); ?>">JSON Gorunum</a>
            </form>
        </div>
    <?php } ?>
</div>
</body>
</html>

