'; } // --------------------------------------------------------------------------- // CONTENT ROUTER // --------------------------------------------------------------------------- function cry01_content() { if (function_exists('head_add_css')) { head_add_css('/addon/cry01/view/css/cry01.css'); } if (function_exists('head_add_js')) { head_add_js('/addon/cry01/view/js/cry01.js'); } $association_slug = argv(1) ?? ''; $sub_route = strtolower(argv(2) ?? ''); if (!$association_slug) { return cry01_render_index(); } $raw = @file_get_contents('addon/vs01/config.json'); if ($raw === false) return cry01_render_error('Configuration unavailable. Contact the operator.'); $cfg = json_decode($raw, true); if (!isset($cfg['associations'][$association_slug])) { return cry01_render_not_found(); } $access = cry01_access_state($association_slug); switch ($sub_route) { case 'signal': if ($_SERVER['REQUEST_METHOD'] === 'POST') { if ($access === 'public') return cry01_access_wall($association_slug); if (!cry01_verify_csrf()) { return cry01_render_error('Invalid form token. Please reload and try again.'); } return cry01_handle_signal_post($association_slug, $access); } if ($access === 'public') return cry01_access_wall($association_slug); return cry01_render_signal_form($association_slug, $access); case 'g1': if ($access !== 'operator') return cry01_access_wall($association_slug); return cry01_render_g1_candidates($association_slug); case 'manage': if ($access !== 'operator') return cry01_access_wall($association_slug); if ($_SERVER['REQUEST_METHOD'] === 'POST') { return cry01_handle_manage_post($association_slug); } return cry01_render_manage($association_slug); default: return cry01_render_landing($association_slug, $access); } } // --------------------------------------------------------------------------- // RENDER — INDEX // --------------------------------------------------------------------------- function cry01_render_index() { // Lists all registered associations with links to their value layer pages. $raw = @file_get_contents('addon/vs01/config.json'); $cfg = $raw ? json_decode($raw, true) : []; $list = $cfg['associations'] ?? []; if (empty($list)) { return '

No associations registered.

'; } $out = '
'; $out .= '

Value Layer

'; $out .= '
'; return $out; } // --------------------------------------------------------------------------- // RENDER — NOT FOUND / ERROR // --------------------------------------------------------------------------- function cry01_render_not_found() { return '
Association not found.
'; } function cry01_render_error($message) { // Shows a plain-language error message. Never shows a blank page or stack trace. return '
' . cry01_h($message) . '
'; } // --------------------------------------------------------------------------- // CSRF // --------------------------------------------------------------------------- function cry01_csrf_token() { // Generates and stores a CSRF token for the current session. if (empty($_SESSION['cry01_csrf'])) { $_SESSION['cry01_csrf'] = bin2hex(random_bytes(16)); } return ''; } function cry01_verify_csrf() { // Returns true if the CSRF token in POST matches the session token. return isset($_POST['cry01_csrf'], $_SESSION['cry01_csrf']) && hash_equals($_SESSION['cry01_csrf'], $_POST['cry01_csrf']); }