0, 'path' => '/', 'domain' => '', 'secure' => isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on', 'httponly' => true, 'samesite' => 'Lax']); session_start(); // Include configuration and database connection require_once __DIR__ . '/config.php'; require_once __DIR__ . '/app/db.php'; // Initializes $pdo // --- Helper Function for GeoIP Lookup --- function get_visitor_country_code($ip_address) { $api_url = "http://ip-api.com/json/" . urlencode($ip_address) . "?fields=status,countryCode"; $response_json = @file_get_contents($api_url, false, stream_context_create(['http' => ['timeout' => 2]])); if ($response_json === false) { error_log("GeoIP API call failed for IP: " . $ip_address); return null; } $response_data = json_decode($response_json, true); if (isset($response_data['status']) && $response_data['status'] === 'success' && isset($response_data['countryCode'])) { return strtoupper($response_data['countryCode']); } else { error_log("GeoIP API returned non-success for IP: " . $ip_address . " Response: " . $response_json); return null; } } // --- URL Parsing --- $request_uri = $_SERVER['REQUEST_URI'] ?? '/'; $request_parts = explode('?', $request_uri, 2); $request_uri_path = $request_parts[0]; $original_query_string = $_SERVER['QUERY_STRING'] ?? (isset($request_parts[1]) ? $request_parts[1] : ''); $path = trim(filter_var($request_uri_path, FILTER_SANITIZE_URL), '/'); $segments = $path ? explode('/', $path) : []; // --- Routing --- // 1. Check for Admin Routes if (isset($segments[0]) && $segments[0] === 'admin') { // --- Handle Logout Action --- if (isset($_GET['action']) && $_GET['action'] === 'logout') { $_SESSION = array(); if (ini_get("session.use_cookies")) { $params = session_get_cookie_params(); setcookie(session_name(), '', time() - 42000, $params["path"], $params["domain"], $params["secure"], $params["httponly"]); } session_destroy(); $login_url = defined('BASE_URL') ? BASE_URL . '/admin' : '/admin'; if (ob_get_level()) ob_end_clean(); header('Location: ' . $login_url); exit; } // --- Check if logged in --- if (!isset($_SESSION['user_id'])) { if (file_exists(__DIR__ . '/views/login.php')) { require __DIR__ . '/views/login.php'; } else { http_response_code(500); echo "Error: Login view file not found."; } exit; } // --- User IS Logged In --- $admin_action = $segments[1] ?? 'dashboard'; $item_id = $segments[2] ?? null; switch ($admin_action) { case 'link-builder': if (file_exists(__DIR__ . '/views/link_builder.php')) { require __DIR__ . '/views/link_builder.php'; } else { http_response_code(500); echo "Error: Link builder view file not found."; } break; case 'settings': if (file_exists(__DIR__ . '/views/settings.php')) { require __DIR__ . '/views/settings.php'; } else { http_response_code(500); echo "Error: Settings view file not found."; } break; case 'edit-link': if (isset($item_id) && is_numeric($item_id)) { if (file_exists(__DIR__ . '/views/edit_link.php')) { require __DIR__ . '/views/edit_link.php'; } else { http_response_code(500); echo "Error: Edit link view file not found."; } } else { $_SESSION['flash_message'] = "Error: Invalid or missing ID for editing link."; $dashboard_url = defined('BASE_URL') ? BASE_URL . '/admin/dashboard' : '/admin/dashboard'; if (ob_get_level()) ob_end_clean(); header('Location: ' . $dashboard_url); exit; } break; case 'delete-link': if (isset($item_id) && is_numeric($item_id)) { try { $sql_delete = "DELETE FROM links WHERE id = :id"; $stmt_delete = $pdo->prepare($sql_delete); $stmt_delete->execute(['id' => $item_id]); $_SESSION['flash_message'] = ($stmt_delete->rowCount() > 0) ? "Link (ID: " . htmlspecialchars($item_id) . ") deleted successfully." : "Error: Link (ID: " . htmlspecialchars($item_id) . ") not found or already deleted."; } catch (PDOException $e) { error_log("Delete Link Error: " . $e->getMessage()); $_SESSION['flash_message'] = "Error deleting link. Database error."; } } else { $_SESSION['flash_message'] = "Error: Invalid link ID for deletion."; } $dashboard_url = defined('BASE_URL') ? BASE_URL . '/admin/dashboard' : '/admin/dashboard'; if (ob_get_level()) ob_end_clean(); header('Location: ' . $dashboard_url); exit; break; case 'dashboard': default: if (file_exists(__DIR__ . '/views/dashboard.php')) { require __DIR__ . '/views/dashboard.php'; } else { http_response_code(500); echo "Error: Dashboard view file not found."; } break; } exit; // Exit after handling admin action } // --- End of Admin Route Check --- // 2. Check for Tracking Link Route (e.g., /campaign_id/ad_id) if (count($segments) === 2) { $campaign_id = preg_replace('/[^a-zA-Z0-9_-]/', '', $segments[0]); $ad_id = preg_replace('/[^a-zA-Z0-9_-]/', '', $segments[1]); if (empty($campaign_id) || empty($ad_id)) { goto handle_not_found; } try { $sql_find = "SELECT id, target_url FROM links WHERE campaign_id = :campaign_id AND ad_id = :ad_id LIMIT 1"; $stmt_find = $pdo->prepare($sql_find); $stmt_find->execute(['campaign_id' => $campaign_id, 'ad_id' => $ad_id]); $link = $stmt_find->fetch(); if ($link) { $link_id = $link['id']; $target_url = $link['target_url']; // --- Increment click count --- $sql_update = "UPDATE links SET click_count = click_count + 1 WHERE id = :id"; $stmt_update = $pdo->prepare($sql_update); $stmt_update->execute(['id' => $link_id]); // --- Country Blocking Logic (Read from DB) --- <<<--- UPDATED BLOCK $redirect_url = $target_url; // Default to original target $blocked_countries_from_db = []; try { $stmt_fetch_block = $pdo->query("SELECT country_code FROM blocked_countries"); $blocked_countries_from_db = $stmt_fetch_block->fetchAll(PDO::FETCH_COLUMN, 0); } catch (PDOException $e) { error_log("Error fetching blocked countries: " . $e->getMessage()); // Fail-safe: If DB error, proceed without blocking } if (!empty($blocked_countries_from_db)) { $visitor_ip = $_SERVER['REMOTE_ADDR'] ?? null; if ($visitor_ip) { $country_code = get_visitor_country_code($visitor_ip); if ($country_code !== null && in_array($country_code, $blocked_countries_from_db)) { error_log("Blocked access from country: " . $country_code . " (IP: " . $visitor_ip . ") for link ID: " . $link_id); $redirect_url = BASE_URL . '/'; // Redirect to homepage $original_query_string = ''; // Clear query string for blocked redirect } elseif ($country_code === null) { error_log("GeoIP lookup failed for IP: " . $visitor_ip . ". Allowing redirect for link ID: " . $link_id); } // Else: Country not blocked or code found, keep original redirect_url } else { error_log("Could not determine visitor IP. Allowing redirect for link ID: " . $link_id); } } // --- End Country Blocking Logic --- // --- Append Original Query String --- $final_redirect_url = $redirect_url; if (!empty($original_query_string)) { if (strpos($redirect_url, '?') === false) { $final_redirect_url .= '?' . $original_query_string; } else { $final_redirect_url .= '&' . $original_query_string; } } // --- End Append Logic --- // --- Perform Redirect --- if (!empty($final_redirect_url) && filter_var($final_redirect_url, FILTER_VALIDATE_URL)) { if (ob_get_level()) ob_end_clean(); $redirect_code = ($redirect_url === $target_url) ? 301 : 302; header("Location: " . $final_redirect_url, true, $redirect_code); exit; } else { error_log("Invalid final redirect URL for link ID: " . $link_id . " (URL: " . $final_redirect_url . ")"); goto handle_not_found; } } else { goto handle_not_found; } // Link not found } catch (PDOException $e) { error_log("Database Error: " . $e->getMessage()); http_response_code(500); echo "Database error occurred."; exit; } } // 3. Handle Root Path (/) or other unmatched paths handle_not_found: if (empty($path)) { $homepage_file = __DIR__ . '/index.html'; if (file_exists($homepage_file)) { header('Content-Type: text/html; charset=utf-8'); if (ob_get_level()) ob_end_clean(); readfile($homepage_file); exit; } else { http_response_code(404); echo "Homepage file not found."; exit; } } else { http_response_code(404); echo "404 - Page Not Found"; exit; } ?>