<?php
// st-check.php — STANDALONE "is my server ready for Soft-Transport?" checker (David 2026-06-13).
// The self-host web-installer flow: a Standard customer downloads THIS one small file, uploads it to
// their own hosting (their web root), opens it in the browser, and instantly sees whether their server
// can run Soft-Transport — BEFORE they upload the 114 MB app. No IT knowledge: it's a green/red checklist
// with plain-language "ask your host to enable X" hints. No .exe, no code-signing cert (it's just a PHP
// page). Self-contained: zero dependencies, safe to run on any PHP host. READ-ONLY: it inspects the PHP
// environment + tries to write one temp file in its own dir; it changes nothing else.

// [cc 2026-09-07] instalare.php rescrie linia de mai jos la descărcare când linkul poartă un token; ?token= din URL are prioritate.
$ST_TOKEN = ''; /*ST_TOKEN*/

/* ST-CHECKS-BEGIN */
// [cc 2026-09-07] Shared requirements block, byte-identical copy in st-install.php. Shape: [ label, ok, detail, hint, blocker ]; blockers stop install, rest are amber.
function st_bytes( $v ) { $v = trim( (string) $v ); if ( $v === '' ) { return 0; } if ( $v === '-1' ) { return PHP_INT_MAX; } $n = (float) $v; $u = strtoupper( substr( $v, -1 ) ); return (int) ( $n * ( $u === 'G' ? 1073741824 : ( $u === 'M' ? 1048576 : ( $u === 'K' ? 1024 : 1 ) ) ) ); }
function st_https_ok( $url ) { if ( ! function_exists( 'curl_init' ) ) { return [ false, 'curl lipsă' ]; } $ch = curl_init( $url ); curl_setopt_array( $ch, [ CURLOPT_NOBODY => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 8, CURLOPT_CONNECTTIMEOUT => 5, CURLOPT_SSL_VERIFYPEER => true, CURLOPT_SSL_VERIFYHOST => 2 ] ); curl_exec( $ch ); $code = (int) curl_getinfo( $ch, CURLINFO_HTTP_CODE ); $err = curl_error( $ch ); curl_close( $ch ); return [ $code >= 200 && $code < 500, $err !== '' ? $err : ( 'HTTP ' . $code ) ]; }
function st_self_get( $url ) {
	// [cc] fetch our own URL; if the server cannot reach its own name, pin the host to 127.0.0.1 then to SERVER_ADDR
	if ( ! function_exists( 'curl_init' ) ) { return [ 0, '' ]; }
	$host = (string) parse_url( $url, PHP_URL_HOST ); $port = (int) ( parse_url( $url, PHP_URL_PORT ) ?: ( parse_url( $url, PHP_URL_SCHEME ) === 'https' ? 443 : 80 ) );
	foreach ( [ null, '127.0.0.1', (string) ( $_SERVER['SERVER_ADDR'] ?? '' ) ] as $pin ) {
		if ( $pin === '' ) { continue; }
		$ch = curl_init( $url ); curl_setopt_array( $ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 8, CURLOPT_CONNECTTIMEOUT => 4, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_SSL_VERIFYHOST => 0 ] );
		if ( $pin !== null ) { curl_setopt( $ch, CURLOPT_RESOLVE, [ $host . ':' . $port . ':' . $pin ] ); }
		$b = curl_exec( $ch ); $code = (int) curl_getinfo( $ch, CURLINFO_HTTP_CODE ); curl_close( $ch );
		if ( $code > 0 ) { return [ $code, (string) $b ]; }
	}
	return [ 0, '' ];
}
function st_requirements( array $opt = [] ): array {
	$c = [];
	// [cc 2026-09-07] 7.2 e pragul REAL (kitul e criptat pentru ținta 7.2 și o parte din flotă rulează 7.2.34); 7.4+ rămâne recomandarea, ca rând galben separat
	$c[] = [ 'PHP ' . PHP_VERSION, version_compare( PHP_VERSION, '7.2.0', '>=' ), 'Necesar: PHP 7.2 sau mai nou — pe serverul tău rulează PHP ' . PHP_VERSION, 'Cere furnizorului de hosting PHP 7.2+ (ideal 8.1).', true ];
	$c[] = [ 'PHP recomandat 7.4+', version_compare( PHP_VERSION, '7.4.0', '>=' ), 'Pe serverul tău rulează PHP ' . PHP_VERSION . ' — merge, dar 7.4 sau 8.1 e recomandat', 'Cere trecerea la PHP 7.4 sau 8.1 când poți — e mai rapid și mai sigur.', false ];
	$icOk = extension_loaded( 'ionCube Loader' ); $icVer = ( $icOk && function_exists( 'ioncube_loader_version' ) ) ? (float) ioncube_loader_version() : 0;
	$c[] = [ 'ionCube Loader' . ( $icOk ? ' v' . ( $icVer ?: '?' ) : '' ), $icOk && ( $icVer >= 10 || $icVer === 0.0 ), 'OBLIGATORIU — codul Soft-Transport este criptat ionCube', 'Cere furnizorului să activeze extensia „ionCube Loader" (v10+) pentru PHP. Pe Plesk/cPanel e o bifă.', true ];
	$c[] = [ 'MySQL (mysqli)', extension_loaded( 'mysqli' ), 'Necesar pentru baza de date', 'Cere activarea extensiei „mysqli".', true ];
	$c[] = [ 'Arhivare ZIP', class_exists( 'ZipArchive' ) || extension_loaded( 'zip' ), 'Necesar pentru despachetarea aplicației', 'Cere activarea extensiei PHP „zip".', true ];
	$c[] = [ 'cURL', extension_loaded( 'curl' ), 'Hărți HERE, Google Drive, actualizări', 'Cere activarea extensiei „curl".', true ];
	$c[] = [ 'openssl', extension_loaded( 'openssl' ), 'Conexiuni securizate', 'Cere activarea extensiei „openssl".', true ];
	$c[] = [ 'json', extension_loaded( 'json' ), 'Date interne', 'Cere activarea extensiei „json".', true ];
	$c[] = [ 'mbstring', extension_loaded( 'mbstring' ), 'Text cu diacritice', 'Cere activarea extensiei „mbstring".', false ];
	$c[] = [ 'gd', extension_loaded( 'gd' ), 'Imagini și PDF', 'Cere activarea extensiei „gd".', false ];
	$probe = __DIR__ . '/.st_write_probe_' . substr( md5( (string) getmypid() ), 0, 8 ); $wr = @file_put_contents( $probe, 'ok' ) !== false; if ( $wr ) { @unlink( $probe ); }
	$c[] = [ 'Scriere în folder', $wr, 'Necesar pentru instalare și configurare', 'Folderul în care ai pus acest fișier trebuie să fie scriibil (permisiuni 755/775).', true ];
	$ht = __DIR__ . '/.htaccess'; $htOk = ! file_exists( $ht ) || is_writable( $ht );
	$c[] = [ '.htaccess din rădăcină', $htOk, $htOk ? ( file_exists( $ht ) ? 'există și se poate rescrie' : 'nu există încă (se creează la instalare)' ) : 'există dar NU se poate rescrie', 'Un singur fișier neinscriptibil oprește toată despachetarea. Cere drept de scriere pe .htaccess.', true ];
	$free = @disk_free_space( __DIR__ ); $freeMb = $free !== false ? (int) ( $free / 1048576 ) : -1;
	$c[] = [ 'Spațiu liber: ' . ( $freeMb < 0 ? '?' : $freeMb . ' MB' ), $freeMb < 0 || $freeMb >= 600, 'Necesar: 600 MB (arhivă + copie de siguranță + despachetare)', 'Eliberează spațiu sau cere mai mult de la hosting.', true ];
	// [cc 2026-09-07] instalatorul ridică singur limita la 512M; dacă ini_set e permis, un 128M pornit nu mai e blocant — doar galben
	$mem = (string) ini_get( 'memory_limit' ); $memOk = st_bytes( $mem ) >= 256 * 1048576 || @ini_set( 'memory_limit', '256M' ) !== false;
	$c[] = [ 'Memorie PHP: ' . $mem, $memOk, $memOk ? 'Recomandat: 256M+ (limita se poate ridica din instalator)' : 'Recomandat: 256M+, iar limita NU se poate ridica din PHP', 'Cere ridicarea „memory_limit" la 256M.', false ];
	$met = (int) ini_get( 'max_execution_time' ); $canSet = function_exists( 'set_time_limit' ) && ! in_array( 'set_time_limit', array_map( 'trim', explode( ',', (string) ini_get( 'disable_functions' ) ) ), true );
	$c[] = [ 'Timp de execuție: ' . ( $met === 0 ? 'nelimitat' : $met . 's' ), $met === 0 || $met >= 300 || $canSet, 'Necesar: 300s sau set_time_limit permis', 'Cere „max_execution_time = 300".', true ];
	$up = st_bytes( ini_get( 'upload_max_filesize' ) ); $post = st_bytes( ini_get( 'post_max_size' ) );
	$c[] = [ 'Upload: ' . ini_get( 'upload_max_filesize' ) . ' / ' . ini_get( 'post_max_size' ), $up >= 32 * 1048576 && $post >= 32 * 1048576, 'Recomandat: 32M pentru documente scanate', 'Cere „upload_max_filesize = 32M" și „post_max_size = 32M".', false ];
	$miv = (int) ini_get( 'max_input_vars' ); $c[] = [ 'max_input_vars: ' . $miv, $miv >= 3000, 'Recomandat: 3000 (formulare mari)', 'Cere „max_input_vars = 3000".', false ];
	// [cc 2026-09-07] spec §3.3: open_basedir restrânge căile, iar /tmp e folosit la dezarhivare și la copiile de siguranță
	$obd = trim( (string) ini_get( 'open_basedir' ) );
	$c[] = [ 'open_basedir: ' . ( $obd !== '' ? $obd : 'nesetat' ), $obd === '', $obd === '' ? 'fără restricții de cale' : 'căi restricționate — /tmp și copiile de siguranță pot eșua', 'Cere adăugarea folderului temporar (/tmp) în „open_basedir", sau dezactivarea lui.', false ];
	[ $h1, $h1w ] = st_https_ok( 'https://www.soft-transport.com/update.manifest.php' );
	$c[] = [ 'HTTPS spre soft-transport.com', $h1, $h1 ? 'merge, cu verificarea certificatului' : $h1w, 'Serverul trebuie să iasă pe internet prin HTTPS cu certificate valide (curl.cainfo / ca-certificates).', true ];
	[ $h2, $h2w ] = st_https_ok( 'https://www.googleapis.com/discovery/v1/apis' ); [ $h3, $h3w ] = st_https_ok( 'https://router.hereapi.com/' );
	$c[] = [ 'HTTPS spre Google și HERE', $h2 && $h3, ( $h2 ? 'Google ok' : 'Google: ' . $h2w ) . ' · ' . ( $h3 ? 'HERE ok' : 'HERE: ' . $h3w ), 'Firewall-ul trebuie să permită ieșirea spre googleapis.com și hereapi.com.', false ];
	$rwOk = false; $rwDetail = 'neverificat (nu pot apela propriul server)';
	$rwDir = __DIR__ . '/.st_rw_probe'; if ( ! is_dir( $rwDir ) ) { @mkdir( $rwDir, 0755 ); }
	if ( is_dir( $rwDir ) ) {
		$w1 = @file_put_contents( $rwDir . '/.htaccess', "RewriteEngine On\nRewriteRule ^x$ ok.txt [L]\n" ); $w2 = @file_put_contents( $rwDir . '/ok.txt', 'ok' ); // [cc 2026-09-07] cleanup below now runs even if a write fails partway — no leaked .st_rw_probe/
		if ( $w1 !== false && $w2 !== false ) {
			$self = isset( $opt['self_url'] ) ? (string) $opt['self_url'] : ( ( ( ! empty( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] !== 'off' ) ? 'https' : 'http' ) . '://' . ( $_SERVER['HTTP_HOST'] ?? 'localhost' ) . rtrim( str_replace( '\\', '/', dirname( (string) ( $_SERVER['SCRIPT_NAME'] ?? '/' ) ) ), '/' ) );
			[ $code, $body ] = st_self_get( $self . '/.st_rw_probe/x' );
			if ( $code === 200 && trim( $body ) === 'ok' ) { $rwOk = true; $rwDetail = 'mod_rewrite și .htaccess funcționează'; } elseif ( $code > 0 ) { $rwDetail = 'regulile .htaccess NU se aplică (HTTP ' . $code . ')'; }
		}
		@unlink( $rwDir . '/.htaccess' ); @unlink( $rwDir . '/ok.txt' ); @rmdir( $rwDir );
	}
	$c[] = [ 'Rescriere URL (mod_rewrite)', $rwOk, $rwDetail, 'Aplicația șoferilor folosește /api/ prin .htaccess. Cere „AllowOverride All" și mod_rewrite.', false ];
	$sub = rtrim( str_replace( '\\', '/', dirname( (string) ( $_SERVER['SCRIPT_NAME'] ?? '/' ) ) ), '/' );
	$c[] = [ 'Locație: ' . ( $sub === '' ? 'rădăcina domeniului' : 'subfolder ' . $sub ), true, 'Aplicația va fi la ' . ( $sub === '' ? '/' : $sub . '/' ), '', false ];
	$mailOk = function_exists( 'mail' ) && trim( (string) ini_get( 'sendmail_path' ) ) !== '';
	$c[] = [ 'Email din PHP', $mailOk, $mailOk ? 'sendmail configurat' : 'sendmail_path lipsă', 'Notificările pleacă prin mail(). Cere configurarea sendmail/postfix.', false ];
	$tz = (string) ini_get( 'date.timezone' ); $c[] = [ 'Fus orar: ' . ( $tz !== '' ? $tz : 'nesetat' ), $tz !== '', 'Orele din comenzi depind de el', 'Cere „date.timezone = Europe/Bucharest".', false ];
	if ( ! empty( $opt['db_name'] ) && extension_loaded( 'mysqli' ) ) {
		if ( function_exists( 'mysqli_report' ) ) { mysqli_report( MYSQLI_REPORT_OFF ); } // [cc 2026-09-07] PHP 8.1+ defaults to MYSQLI_REPORT_STRICT (throws on connect failure) — keep the connect_errno branch working
		$mysqli = @new mysqli( 'localhost', (string) $opt['db_user'], (string) $opt['db_pass'], (string) $opt['db_name'] );
		if ( $mysqli->connect_errno ) { $c[] = [ 'Baza de date', false, $mysqli->connect_error, 'Verifică numele bazei, utilizatorul și parola în panoul hostingului.', true ]; }
		else { $ver = $mysqli->server_info; $q = $mysqli->query( 'SELECT @@sql_mode' ); $row = $q ? $q->fetch_row() : null; $mode = (string) ( $row[0] ?? '' ); $mysqli->close(); // [cc 2026-09-07] query() returns false on failure — guard before fetch_row() to avoid a fatal
			// [cc 2026-09-07] spec §3.3: prag real de versiune (MySQL 5.7 / MariaDB 10.2) — era hardcodat true; MariaDB raportează „5.5.5-10.x-MariaDB", deci tăiem prefixul înainte de comparație
			$vraw = preg_replace( '/^5\.5\.5-/', '', (string) $ver ); $isMaria = stripos( $vraw, 'mariadb' ) !== false;
			$vnum = preg_match( '/^(\d+\.\d+(?:\.\d+)?)/', $vraw, $vm ) ? $vm[1] : '0';
			$verOk = $isMaria ? version_compare( $vnum, '10.2', '>=' ) : version_compare( $vnum, '5.7', '>=' );
			$c[] = [ 'Baza de date: MySQL ' . $ver, $verOk, $verOk ? 'conectare reușită' : 'versiune prea veche — necesar MySQL 5.7+ sau MariaDB 10.2+', 'Cere furnizorului MySQL 5.7 sau mai nou (MariaDB 10.2+).', true ];
			$c[] = [ 'sql_mode', stripos( $mode, 'ONLY_FULL_GROUP_BY' ) === false, $mode === '' ? 'implicit' : $mode, 'Cere scoaterea ONLY_FULL_GROUP_BY din sql_mode (SET GLOBAL sql_mode = \'\').', false ]; }
	}
	$blockers = [];
	foreach ( $c as $x ) { if ( ! $x[1] && $x[4] ) { $blockers[] = $x[0]; } }
	return [ $c, count( $blockers ) === 0, $blockers ];
}
/* ST-CHECKS-END */
if ( defined( 'ST_CHECK_LIB' ) ) { return; }

// [cc 2026-09-07] adresa centrală; st-install.local.php e o punte doar de dezvoltare (gitignorată, nu pleacă niciodată la client)
function st_check_central(): string {
	$loc = __DIR__ . '/st-install.local.php';
	if ( is_file( $loc ) ) { $u = @include $loc; if ( is_string( $u ) && preg_match( '#^https?://#', $u ) ) { return rtrim( $u, '/' ); } }
	return 'https://www.soft-transport.com';
}

// [cc 2026-09-07] geamănul lui st_report() din st-install.php — verificatorul singur bifează pasul „check" în fișa clientului; eșecul e mut, nu blochează nimic
function st_check_report( string $token, bool $ok, array $details ): void {
	if ( $token === '' || ! function_exists( 'curl_init' ) ) { return; }
	$ch = curl_init( st_check_central() . '/install.report.php' );
	curl_setopt_array( $ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 12, CURLOPT_CONNECTTIMEOUT => 6, CURLOPT_SSL_VERIFYPEER => true, CURLOPT_SSL_VERIFYHOST => 2, CURLOPT_USERAGENT => 'Soft-Transport server check', CURLOPT_POSTFIELDS => http_build_query( [ 't' => $token, 'stage' => 'check', 'ok' => $ok ? '1' : '0', 'details' => json_encode( $details ) ] ) ] );
	@curl_exec( $ch ); curl_close( $ch );
}

$token = (string) ( $_GET['token'] ?? '' );
if ( $token === '' ) { $token = (string) $ST_TOKEN; }
if ( ! preg_match( '/^[a-f0-9]{64}$/', $token ) ) { $token = ''; }

$dbOpt = [];
if ( ( $_SERVER['REQUEST_METHOD'] ?? '' ) === 'POST' && ! empty( $_POST['db_name'] ) ) { $dbOpt = [ 'db_name' => (string) $_POST['db_name'], 'db_user' => (string) ( $_POST['db_user'] ?? $_POST['db_name'] ), 'db_pass' => (string) ( $_POST['db_pass'] ?? '' ) ]; }
[ $checks, $allOk, $blockers ] = st_requirements( $dbOpt );

// [cc 2026-09-07] raportăm chiar și (mai ales) când serverul e roșu — altfel pasul „check" nu apărea niciodată în soft admin
st_check_report( $token, $allOk, [ 'php' => PHP_VERSION, 'loader' => function_exists( 'ioncube_loader_version' ) ? (string) ioncube_loader_version() : '', 'host' => (string) ( $_SERVER['HTTP_HOST'] ?? '' ), 'dir' => rtrim( str_replace( '\\', '/', dirname( (string) ( $_SERVER['SCRIPT_NAME'] ?? '/' ) ) ), '/' ), 'blockers' => $blockers, 'reason' => $allOk ? '' : implode( ', ', $blockers ) ] );

header( 'Content-Type: text/html; charset=utf-8' );
echo '<!doctype html><html lang="ro"><head><meta charset="utf-8"><title>Verificare server — Soft-Transport</title>';
echo '<meta name="viewport" content="width=device-width,initial-scale=1">';
echo '<style>body{font:16px/1.6 system-ui,-apple-system,Segoe UI,sans-serif;background:#14110E;color:#F1ECDF;margin:0;padding:24px;box-sizing:border-box}';
echo '.box{max-width:680px;margin:0 auto}h1{font-size:22px;color:#46B5E0;margin:0 0 4px}.sub{color:#C9C2B2;margin:0 0 22px}';
echo '.verdict{padding:16px 20px;border-radius:10px;font-size:18px;font-weight:700;margin-bottom:22px}';
echo '.verdict.ok{background:#1f3a1a;border:1px solid #3c763d;color:#bfe9a0}.verdict.no{background:#3a1c1c;border:1px solid #a94442;color:#f0b9b9}';
echo 'ul{list-style:none;padding:0;margin:0}li{display:flex;gap:12px;padding:12px 14px;border-bottom:1px solid #2a2620;align-items:flex-start}';
echo '.ic{font-size:20px;line-height:1.2;flex:0 0 24px}.ic.y{color:#7ed957}.ic.n{color:#ff6b6b}.ic.w{color:#e8b96b}.lbl{font-weight:600}.det{color:#9a9384;font-size:13px}';
echo '.fix{color:#e8b96b;font-size:13px;margin-top:3px}.foot{margin-top:24px;color:#8a8474;font-size:13px}';
echo '.cta{display:block;text-align:center;margin-top:22px;padding:16px 22px;border-radius:10px;font-size:18px;font-weight:800;text-decoration:none}';
echo '.cta.go{background:#46B5E0;color:#06303d}.cta.ghost{background:transparent;border:2px solid #46B5E0;color:#46B5E0}.cta.warn{background:transparent;border:1px solid #6b6459;color:#C9C2B2;font-size:15px;font-weight:600}</style></head><body><div class="box">';
echo '<h1>Soft-Transport — verificare server</h1><p class="sub">Rulează pe serverul tău (acolo unde vrei să instalezi). Verifică dacă găzduirea ta poate rula aplicația.</p>';

if ( $allOk ) {
	echo '<div class="verdict ok">✓ Serverul tău este PREGĂTIT. Poți instala Soft-Transport.</div>';
} else {
	echo '<div class="verdict no">✗ Mai lipsesc câteva lucruri: ' . htmlspecialchars( implode( ', ', $blockers ), ENT_QUOTES, 'UTF-8' ) . '. Vezi mai jos ce să ceri furnizorului tău de hosting.</div>';
}

echo '<ul>';
foreach ( $checks as $c ) {
	$cls = $c[1] ? 'y' : ( $c[4] ? 'n' : 'w' );
	echo '<li><div class="ic ' . $cls . '">' . ( $c[1] ? '✓' : ( $c[4] ? '✗' : '!' ) ) . '</div><div><div class="lbl">' . htmlspecialchars( $c[0], ENT_QUOTES, 'UTF-8' ) . '</div><div class="det">' . htmlspecialchars( $c[2], ENT_QUOTES, 'UTF-8' ) . '</div>' . ( ( ! $c[1] && $c[3] !== '' ) ? '<div class="fix">' . htmlspecialchars( $c[3], ENT_QUOTES, 'UTF-8' ) . '</div>' : '' ) . '</div></li>';
}
echo '</ul><form method="post" style="margin-top:18px"><div class="det">Opțional: verifică și baza de date (numele = utilizatorul, așa cum le-ai creat în panoul hostingului).</div>';
echo '<input type="text" name="db_name" placeholder="numele bazei / utilizator" style="width:100%;margin:6px 0;padding:10px"><input type="password" name="db_pass" placeholder="parola bazei" autocomplete="off" style="width:100%;margin:6px 0;padding:10px">';   // [cc 2026-09-07] parola bazei nu se mai afișează în clar pe ecran
echo '<button class="cta ghost" type="submit" style="width:100%">Verifică baza de date</button></form>';

// [cc] David 2026-06-13: the page MUST give a button / next action, not be a dead-end checklist.
$guide = 'https://www.soft-transport.com/instalare.php' . ( $token !== '' ? '?token=' . rawurlencode( $token ) : '' );   // [cc 2026-09-07] o singură gazdă (www) peste tot + tokenul merge mai departe
$guideEsc = htmlspecialchars( $guide, ENT_QUOTES, 'UTF-8' );
if ( $allOk ) {
	echo '<a class="cta go" href="' . $guideEsc . '">Serverul e pregătit — continuă instalarea →</a>';
} else {
	echo '<a class="cta warn" href="javascript:location.reload()">Am cerut hostingului să activeze ce lipsește — verifică din nou</a>';
	echo '<a class="cta ghost" href="' . $guideEsc . '">Vezi ghidul de instalare pas cu pas →</a>';
}

// [cc 2026-09-07] numele fișierului iese din textul linkului și intră în nota alăturată
echo '<p class="foot">Acest fișier nu modifică nimic pe server — îl poți șterge după verificare. Ghid complet: <a style="color:#46B5E0" href="' . $guideEsc . '">pagina de instalare Soft-Transport</a> (<code>soft-transport.com/instalare.php</code>)</p>';
echo '</div></body></html>';
