From b44389a0a2744602d91ceddf23bfd6ac69c75eed Mon Sep 17 00:00:00 2001 From: mstfyldz Date: Sun, 22 Feb 2026 17:08:48 +0300 Subject: [PATCH] Initial commit with security patches --- .dockerignore | 7 + .gitignore | 20 +++ .htaccess | 67 +++++++ DEPLOYMENT.md | 205 ++++++++++++++++++++++ Dockerfile | 14 ++ README.md | 17 ++ api_secured.php | 329 ++++++++++++++++++++++++++++++++++ composer.json | 13 ++ config.php | 166 ++++++++++++++++++ index.php | 5 + login.html | 304 ++++++++++++++++++++++++++++++++ panel.php | 455 ++++++++++++++++++++++++++++++++++++++++++++++++ vercel.json | 17 ++ 13 files changed, 1619 insertions(+) create mode 100644 .dockerignore create mode 100644 .gitignore create mode 100644 .htaccess create mode 100644 DEPLOYMENT.md create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 api_secured.php create mode 100644 composer.json create mode 100644 config.php create mode 100644 index.php create mode 100644 login.html create mode 100644 panel.php create mode 100644 vercel.json diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..53cdf3a --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +.git +.gitignore +.DS_Store +README.md +DEPLOYMENT.md +dockerfile +.dockerignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..62a027e --- /dev/null +++ b/.gitignore @@ -0,0 +1,20 @@ +# Logs +*.log +rate_limit.json +api_access.log + +# Tokens +tokens/ + +# IDE +.vscode/ +.idea/ +*.swp +*.swo + +# OS +.DS_Store +Thumbs.db + +# Vercel +.vercel diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..af97c07 --- /dev/null +++ b/.htaccess @@ -0,0 +1,67 @@ +# XC IPTV API - Apache Configuration + +# CORS (Cross-Origin Resource Sharing) + + Header set Access-Control-Allow-Origin "*" + Header set Access-Control-Allow-Methods "GET, POST, OPTIONS" + Header set Access-Control-Allow-Headers "Content-Type, Authorization" + + +# GZIP Compression + + AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/json + + +# Cache Control + + ExpiresActive On + ExpiresByType application/json "access plus 5 minutes" + + +# Security Headers + + Header set X-Content-Type-Options "nosniff" + Header set X-Frame-Options "DENY" + Header set X-XSS-Protection "1; mode=block" + + +# Disable Directory Listing +Options -Indexes + +# Protect Config and Sensitive Files + + Order Allow,Deny + Deny from all + + +# Protect Tokens Directory + + RewriteRule ^tokens/ - [F,L] + + +# Error Pages +ErrorDocument 404 /404.html +ErrorDocument 500 /500.html + +# Rewrite Rules (opsiyonel - SEF URLs için) + + RewriteEngine On + RewriteBase / + + # API endpoint'i temizle + # /api/v1 yerine /api + RewriteRule ^api/?$ api_secured.php [L] + + # Maintenance check + RewriteCond %{REQUEST_URI} !maintenance.html + RewriteCond %{DOCUMENT_ROOT}/maintenance.flag -f + RewriteRule .* /maintenance.html [R=503,L] + + +# PHP Settings (eğer izin veriliyorsa) + + php_value upload_max_filesize 10M + php_value post_max_size 10M + php_value memory_limit 128M + php_value max_execution_time 30 + diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md new file mode 100644 index 0000000..18dab6b --- /dev/null +++ b/DEPLOYMENT.md @@ -0,0 +1,205 @@ +# 🚀 DEPLOYMENT GUIDE - Adım Adım + +## 📦 DOSYALARI GITHUB'A YÜKLE + +### 1️⃣ GitHub'da Yeni Repo Oluştur + +1. https://github.com/new adresine git +2. Repository name: **xciptv-api** (ya da istediğin isim) +3. ✅ **Public** seç (ücretsiz için) +4. ❌ README ekleme (bizde zaten var) +5. **Create repository** tıkla + +### 2️⃣ Dosyaları Yükle + +İki yöntem var: + +#### Yöntem A: GitHub Web'den (KOLAY ✅) + +1. Yeni oluşturduğun repo sayfasında: +2. **"uploading an existing file"** linkine tıkla +3. Tüm dosyaları sürükle-bırak: + - api_secured.php + - login.html + - panel.html + - config.php + - index.php + - vercel.json + - composer.json + - .gitignore + - README.md + +4. Commit message: "Initial commit" +5. **Commit changes** tıkla + +#### Yöntem B: Git ile (Terminal) + +```bash +# Dosyaların olduğu klasöre git +cd /path/to/xciptv-deploy + +# Git başlat +git init + +# Dosyaları ekle +git add . + +# Commit +git commit -m "Initial commit" + +# GitHub'a bağla (değiştir: USERNAME ve REPO_NAME) +git remote add origin https://github.com/USERNAME/REPO_NAME.git + +# Push et +git branch -M main +git push -u origin main +``` + +--- + +## 🚀 VERCEL'E DEPLOY ET + +### 1️⃣ Vercel'e Git + +1. https://vercel.com/new adresine git +2. **"Import Git Repository"** tıkla + +### 2️⃣ GitHub Repo'nu Seç + +1. GitHub hesabını bağla (ilk seferse) +2. Listeden **xciptv-api** repo'sunu seç +3. **Import** tıkla + +### 3️⃣ Deploy Ayarları + +``` +Framework Preset: Other +Root Directory: ./ +Build Command: (boş bırak) +Output Directory: (boş bırak) +Install Command: (boş bırak) +``` + +### 4️⃣ Deploy! + +**Deploy** butonuna tıkla ve bekle (30-60 saniye). + +### 5️⃣ URL'ini Al + +Deploy bitince sana URL verecek: + +``` +https://xciptv-api-xxxxx.vercel.app +``` + +Bu URL'i kopyala! ✅ + +--- + +## 🧪 TEST ET + +### 1️⃣ Admin Panel + +Tarayıcıda aç: +``` +https://xciptv-api-xxxxx.vercel.app/login.html +``` + +Giriş yap: +- Username: **admin** +- Password: **admin123** + +### 2️⃣ API Test + +Terminal'de test et: + +```bash +# Token al +curl "https://xciptv-api-xxxxx.vercel.app/api_secured.php?action=get_token&api_key=myapp_v1_secret_key_2024" +``` + +Response gelirse **BAŞARILI!** 🎉 + +--- + +## ⚙️ ŞİFRE DEĞİŞTİR (ÖNEMLİ!) + +### 1️⃣ Yeni Şifre Oluştur + +Bu PHP kodunu çalıştır: + +```php + +``` + +Çıktı: +``` +$2y$10$abcdefghijklmnopqrstuvwxyz... +``` + +### 2️⃣ api_secured.php'yi Düzenle + +GitHub'daki `api_secured.php` dosyasını aç → Edit: + +```php +$SECURITY_CONFIG = [ + 'admin_username' => 'admin', // 👈 İstersen değiştir + 'admin_password' => '$2y$10$abc...', // 👈 Yeni hash'i yapıştır +]; +``` + +**Commit changes** → Vercel otomatik yeniden deploy eder (1 dk) + +--- + +## 🎯 APK'YA BAĞLA + +APK'da kullanacağın URL: + +``` +https://xciptv-api-xxxxx.vercel.app/api_secured.php +``` + +### Token Al: +``` +?action=get_token&api_key=myapp_v1_secret_key_2024 +``` + +### Config Çek: +``` +?action=get_config&token=ALDGIN_TOKEN +``` + +--- + +## 🆘 SORUN ÇÖZME + +### "500 Internal Server Error" + +Vercel'de PHP çalışmıyorsa: + +1. `vercel.json` dosyası var mı kontrol et +2. Repo'nun root'unda olmalı + +### "404 Not Found" + +URL'i doğru yazdığından emin ol: +``` +✅ https://xxx.vercel.app/login.html +❌ https://xxx.vercel.app/login +``` + +### Şifre Çalışmıyor + +Yeni hash oluştur ve güncelle: +```bash +php -r "echo password_hash('admin123', PASSWORD_BCRYPT);" +``` + +--- + +## 📞 Takıldın mı? + +Geri gel, birlikte hallederiz! 💪 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..e8d5a70 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,14 @@ +FROM php:7.4-apache + +# Tüm dosyaları sunucuya kopyala +COPY . /var/www/html/ + +# Klasör izinlerini ayarla +RUN chown -R www-data:www-data /var/www/html \ + && chmod -R 755 /var/www/html + +# Apache'nin PHP'yi işlemesini sağla ve AllowOverride ayarını aktifleştir +RUN a2enmod rewrite \ + && sed -i 's/AllowOverride None/AllowOverride All/g' /etc/apache2/apache2.conf + +EXPOSE 80 \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e3f9fae --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +# XC IPTV API - Secured Panel + +## 🚀 Quick Start + +1. Admin Panel: `login.html` +2. Default Login: admin / admin123 +3. API Endpoint: `api_secured.php` + +## 🔐 Security + +- Change password in `api_secured.php` +- Update API keys +- Configure in `config.php` + +## 📖 Documentation + +See full docs in repository. diff --git a/api_secured.php b/api_secured.php new file mode 100644 index 0000000..1fd0f44 --- /dev/null +++ b/api_secured.php @@ -0,0 +1,329 @@ + 'admin', + 'admin_password' => password_hash('admin123', PASSWORD_BCRYPT), // Değiştir! + + // API Keys (Her APK için farklı key) + 'api_keys' => [ + 'myapp_v1_secret_key_2024', // APK 1 + 'myapp_v2_secret_key_2024', // APK 2 + 'myapp_v3_secret_key_2024', // APK 3 + ], + + // IP Whitelist (Boş = tüm IP'ler) + 'allowed_ips' => [], + + // Rate Limiting + 'rate_limit' => [ + 'enabled' => true, + 'max_requests' => 60, // dakika başına + 'block_duration' => 3600, // 1 saat ban + ], + + // Token Expiry (saat cinsinden) + 'token_expiry' => 24, +]; + +// ========================================== +// SESSION BAŞLAT +// ========================================== + +session_start(); + +// ========================================== +// RATE LIMIT KONTROLÜ +// ========================================== + +function checkRateLimit($ip) { + global $SECURITY_CONFIG; + + if (!$SECURITY_CONFIG['rate_limit']['enabled']) { + return true; + } + + $log_file = 'rate_limit.json'; + $max_requests = $SECURITY_CONFIG['rate_limit']['max_requests']; + $block_duration = $SECURITY_CONFIG['rate_limit']['block_duration']; + + // Load log + $data = file_exists($log_file) ? json_decode(file_get_contents($log_file), true) : []; + + // Check if IP is blocked + if (isset($data[$ip]['blocked_until']) && time() < $data[$ip]['blocked_until']) { + return false; + } + + // Initialize or reset counter + if (!isset($data[$ip]) || time() - $data[$ip]['last_reset'] > 60) { + $data[$ip] = [ + 'count' => 1, + 'last_reset' => time(), + 'blocked_until' => null + ]; + } else { + $data[$ip]['count']++; + + // Block if exceeded + if ($data[$ip]['count'] > $max_requests) { + $data[$ip]['blocked_until'] = time() + $block_duration; + file_put_contents($log_file, json_encode($data)); + return false; + } + } + + file_put_contents($log_file, json_encode($data)); + return true; +} + +// ========================================== +// API KEY KONTROLÜ +// ========================================== + +function validateApiKey($key) { + global $SECURITY_CONFIG; + return in_array($key, $SECURITY_CONFIG['api_keys']); +} + +// ========================================== +// TOKEN OLUŞTUR +// ========================================== + +function generateToken($api_key) { + global $SECURITY_CONFIG; + + $token_data = [ + 'api_key' => $api_key, + 'issued_at' => time(), + 'expires_at' => time() + ($SECURITY_CONFIG['token_expiry'] * 3600), + 'random' => bin2hex(random_bytes(16)) + ]; + + // Token'ı encode et + $token = base64_encode(json_encode($token_data)); + + // Token'ı kaydet (opsiyonel) + $token_file = 'tokens/' . md5($token) . '.json'; + @mkdir('tokens', 0755, true); + @file_put_contents($token_file, json_encode($token_data)); + + return $token; +} + +// ========================================== +// TOKEN DOĞRULA +// ========================================== + +function validateToken($token) { + if (empty($token)) return false; + + try { + $token_data = json_decode(base64_decode($token), true); + + if (!$token_data || !isset($token_data['expires_at'])) { + return false; + } + + // Expire check + if (time() > $token_data['expires_at']) { + return false; + } + + // API key check + if (!validateApiKey($token_data['api_key'])) { + return false; + } + + return true; + } catch (Exception $e) { + return false; + } +} + +// ========================================== +// IP KONTROL +// ========================================== + +$client_ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown'; + +if (!empty($SECURITY_CONFIG['allowed_ips']) && !in_array($client_ip, $SECURITY_CONFIG['allowed_ips'])) { + http_response_code(403); + die(json_encode([ + 'status' => 'error', + 'error_code' => 'IP_BLOCKED', + 'message' => 'Your IP is not whitelisted' + ])); +} + +// Rate limit check +if (!checkRateLimit($client_ip)) { + http_response_code(429); + die(json_encode([ + 'status' => 'error', + 'error_code' => 'RATE_LIMIT_EXCEEDED', + 'message' => 'Too many requests. Try again later.', + 'retry_after' => $SECURITY_CONFIG['rate_limit']['block_duration'] + ])); +} + +// ========================================== +// ENDPOINT: LOGIN (Admin Panel) +// ========================================== + +if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'login') { + header('Content-Type: application/json'); + + $username = $_POST['username'] ?? ''; + $password = $_POST['password'] ?? ''; + + if ($username === $SECURITY_CONFIG['admin_username'] && + password_verify($password, $SECURITY_CONFIG['admin_password'])) { + + $_SESSION['admin_logged_in'] = true; + $_SESSION['login_time'] = time(); + + echo json_encode([ + 'status' => 'success', + 'message' => 'Login successful', + 'redirect' => 'panel.php' + ]); + } else { + sleep(2); // Brute force protection + echo json_encode([ + 'status' => 'error', + 'message' => 'Invalid credentials' + ]); + } + exit; +} + +// ========================================== +// ENDPOINT: GET TOKEN (APK için) +// ========================================== + +if (isset($_GET['action']) && $_GET['action'] === 'get_token') { + header('Content-Type: application/json'); + + $api_key = $_GET['api_key'] ?? $_POST['api_key'] ?? ''; + + if (!validateApiKey($api_key)) { + http_response_code(401); + echo json_encode([ + 'status' => 'error', + 'error_code' => 'INVALID_API_KEY', + 'message' => 'Invalid API key' + ]); + exit; + } + + $token = generateToken($api_key); + + echo json_encode([ + 'status' => 'success', + 'token' => $token, + 'expires_in' => $SECURITY_CONFIG['token_expiry'] * 3600, + 'issued_at' => time() + ]); + exit; +} + +// ========================================== +// ENDPOINT: GET CONFIG (Ana API) +// ========================================== + +if (isset($_GET['action']) && $_GET['action'] === 'get_config') { + header('Content-Type: application/json'); + + // Token kontrolü + $token = $_GET['token'] ?? $_SERVER['HTTP_AUTHORIZATION'] ?? ''; + $token = str_replace('Bearer ', '', $token); + + if (!validateToken($token)) { + http_response_code(401); + echo json_encode([ + 'status' => 'error', + 'error_code' => 'INVALID_TOKEN', + 'message' => 'Invalid or expired token' + ]); + exit; + } + + // ========================================== + // CONFIG (Token geçerli ise döndür) + // ========================================== + + require_once 'config.php'; + + $config = [ + 'app' => [ + 'name' => 'MAGTV Android Player', + 'customer_id' => 'v2000', + 'expiry' => 'LIFETIME', + 'version' => '7.0', + ], + 'portals' => [ + [ + 'id' => 1, + 'name' => 'GİRİŞ 1', + 'url' => 'http://hdd.inoon.uk', + 'port' => '8080', + ], + [ + 'id' => 2, + 'name' => 'GİRİŞ 2', + 'url' => 'http://hdd.inoon.uk', + 'port' => '8080', + ], + [ + 'id' => 3, + 'name' => 'GİRİŞ 3', + 'url' => 'http://imagson.site', + 'port' => '8080', + ], + ], + ]; + + echo json_encode([ + 'status' => 'success', + 'data' => $config, + 'timestamp' => time() + ], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); + + exit; +} + +// ========================================== +// ADMIN PANEL ACCESS CHECK +// ========================================== + +// Güvenli oturum kontrolü artık panel.php'nin en üstünde yapılmaktadır. + +// ========================================== +// DEFAULT: API Dökümantasyonu +// ========================================== + +if (!isset($_GET['action'])) { + header('Content-Type: application/json'); + echo json_encode([ + 'name' => 'XC IPTV Secured API', + 'version' => '2.0', + 'status' => 'online', + 'security' => 'enabled', + 'endpoints' => [ + 'POST /api.php?action=login' => 'Admin login', + 'GET /api.php?action=get_token&api_key=YOUR_KEY' => 'Get access token', + 'GET /api.php?action=get_config&token=YOUR_TOKEN' => 'Get portal config', + ], + 'documentation' => 'https://docs.yourdomain.com' + ], JSON_PRETTY_PRINT); +} +?> diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..2d59588 --- /dev/null +++ b/composer.json @@ -0,0 +1,13 @@ +{ + "name": "xciptv/api", + "description": "XC IPTV Secured API Panel", + "type": "project", + "require": { + "php": ">=7.4" + }, + "config": { + "platform": { + "php": "8.2" + } + } +} diff --git a/config.php b/config.php new file mode 100644 index 0000000..9b1b048 --- /dev/null +++ b/config.php @@ -0,0 +1,166 @@ + [ + 'url' => 'http://panel.example.com', // Panel URL + 'port' => '8080', // Panel Port + 'api_path' => '/player_api.php', // API endpoint + 'timeout' => 30, // Connection timeout (saniye) + ], + + // ========================================== + // UYGULAMA AYARLARI + // ========================================== + 'app' => [ + 'name' => 'My IPTV', + 'package' => 'com.myiptv.app', + 'version' => '7.0', + 'version_code' => 70, + + // Güncelleme + 'force_update' => false, + 'latest_version' => '7.0', + 'update_url' => 'https://yourdomain.com/downloads/myiptv.apk', + 'update_message' => 'Yeni versiyon mevcut! Lütfen güncelleyin.', + + // Splash Screen + 'splash_duration' => 3, // saniye + 'splash_logo' => 'https://yourdomain.com/assets/logo.png', + ], + + // ========================================== + // ÖZELLİKLER + // ========================================== + 'features' => [ + 'live_tv' => true, + 'vod' => true, + 'series' => true, + 'catchup' => true, + 'epg' => true, + 'recording' => false, + 'parental_control' => true, + 'multi_profile' => false, + 'chromecast' => true, + 'download' => false, + ], + + // ========================================== + // PLAYER AYARLARI + // ========================================== + 'player' => [ + 'default_quality' => 'auto', + 'buffer_size' => 'medium', // small, medium, large + 'hardware_acceleration' => true, + 'subtitle_enabled' => true, + 'audio_passthrough' => false, + ], + + // ========================================== + // REKLAM AYARLARI (AdMob) + // ========================================== + 'ads' => [ + 'enabled' => false, + 'provider' => 'admob', // admob, facebook, unity + + // AdMob IDs + 'banner_id' => 'ca-app-pub-xxxxx', + 'interstitial_id' => 'ca-app-pub-xxxxx', + 'rewarded_id' => 'ca-app-pub-xxxxx', + 'native_id' => 'ca-app-pub-xxxxx', + + // Görüntüleme Sıklığı + 'show_on_startup' => false, + 'show_between_videos' => true, + 'videos_between_ads' => 3, // Her 3 videoda bir + ], + + // ========================================== + // BAKIM MODU + // ========================================== + 'maintenance' => [ + 'enabled' => false, + 'title' => 'Bakımda', + 'message' => 'Sistem şu an bakımda. Lütfen daha sonra tekrar deneyin.', + 'estimated_time' => '2 saat', + 'support_url' => 'https://yourdomain.com/support', + ], + + // ========================================== + // DUYURULAR + // ========================================== + 'announcement' => [ + 'enabled' => false, + 'type' => 'info', // info, warning, error, success + 'title' => 'Önemli Duyuru', + 'message' => 'Sistemde güncellemeler yapılmaktadır.', + 'show_once' => true, // Kullanıcıya bir kere göster + 'button_text' => 'Anladım', + 'link' => '', // Opsiyonel: Daha fazla bilgi linki + ], + + // ========================================== + // GÜVENLİK + // ========================================== + 'security' => [ + 'require_ssl' => false, // HTTPS zorunlu + 'api_key_required' => false, + 'api_key' => 'your-secret-api-key-here', + 'rate_limit' => 100, // İstek limiti (dakika başına) + 'allowed_ips' => [], // Boşsa tüm IP'ler izinli + 'blocked_ips' => [], + ], + + // ========================================== + // SOSYAL MEDYA & DESTEK + // ========================================== + 'social' => [ + 'facebook' => '', + 'twitter' => '', + 'instagram' => '', + 'telegram' => '', + 'website' => 'https://yourdomain.com', + 'support_email' => 'support@yourdomain.com', + 'support_phone' => '+90 XXX XXX XX XX', + ], + + // ========================================== + // GELİŞMİŞ AYARLAR + // ========================================== + 'advanced' => [ + 'cache_enabled' => true, + 'cache_duration' => 3600, // 1 saat + 'debug_mode' => false, + 'log_enabled' => true, + 'log_file' => 'api.log', + 'compression' => true, // GZIP sıkıştırma + ], + + // ========================================== + // VERSİYON GEÇMİŞİ + // ========================================== + 'changelog' => [ + '7.0' => [ + 'date' => '2024-02-21', + 'changes' => [ + 'Yeni arayüz tasarımı', + 'Performans iyileştirmeleri', + 'Bug düzeltmeleri' + ] + ], + '6.5' => [ + 'date' => '2024-01-15', + 'changes' => [ + 'EPG desteği eklendi', + 'Chromecast entegrasyonu' + ] + ] + ] +]; diff --git a/index.php b/index.php new file mode 100644 index 0000000..9fa5bc4 --- /dev/null +++ b/index.php @@ -0,0 +1,5 @@ + diff --git a/login.html b/login.html new file mode 100644 index 0000000..8da26f2 --- /dev/null +++ b/login.html @@ -0,0 +1,304 @@ + + + + + + + Admin Login - XC IPTV Panel + + + + +
+ + +
+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+ + +
+ + +
+ + + + + \ No newline at end of file diff --git a/panel.php b/panel.php new file mode 100644 index 0000000..cce8686 --- /dev/null +++ b/panel.php @@ -0,0 +1,455 @@ + + + + + + + XC IPTV Panel - Portal Yönetimi + + + +
+
+

📺 XC IPTV Panel Yönetimi

+

appsnscripts Style - Multi Portal Manager

+
+ +
+ +
+

📱 App Settings

+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ + +
+ + +
+

🌐 Portal Settings

+ +
+ +
+ ACTIVE +

Portal 1

+
+ + +
+
+ + +
+
+ + +
+ ACTIVE +

Portal 2

+
+ + +
+
+ + +
+
+ + +
+ ACTIVE +

Portal 3

+
+ + +
+
+ + +
+
+ + +
+ INACTIVE +

Portal 4

+
+ + +
+
+ + +
+
+ + +
+ INACTIVE +

Portal 5

+
+ + +
+
+ + +
+
+
+ + +
+ + +
+

🎨 UI Control

+ +
+ +
+
Portal 1
+
Portal 2
+
Portal 3
+
Portal 4
+
Portal 5
+
+
+ +
+ +
+
Portal 1
+
Portal 2
+
Portal 3
+
Portal 4
+
Portal 5
+
+
+ +
+ +
+
Portal 1
+
Portal 2
+
Portal 3
+
Portal 4
+
Portal 5
+
+
+
+ + +
+

🔗 API Information

+ +
+
+
3
+
Active Portals
+
+
+
+
License Status
+
+
+ +
+ https://yourdomain.com/api/app.php +
+ + + +
+
+
+ + + + diff --git a/vercel.json b/vercel.json new file mode 100644 index 0000000..acae190 --- /dev/null +++ b/vercel.json @@ -0,0 +1,17 @@ +{ + "version": 2, + "functions": { + "api/**/*.php": { + "runtime": "vercel-php@0.6.0" + } + }, + "routes": [ + { + "src": "/(.*)", + "dest": "/$1" + } + ], + "env": { + "PHP_VERSION": "8.2" + } +}