WisPanel 1.0 Official Release
After months of intensive development and community feedback, we're thrilled to announce the official release of WisPanel 1.0!
<?php
require_once '../database/connection.php';
require_once '../helpers/LicenseHelpers.php';
// ============================================
// CONSTANTS
// ============================================
const PRIVATE_KEY = '-----BEGIN PRIVATE KEY-----
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
2u2XDXcn+4MZJRoSsUaVPZYG4mTY
-----END PRIVATE KEY-----';
const MASTER_KEY = 'WHMCSNULLED_MASTER001';
const LAGOM_PRODUCT_IDS = ['6', '18', '19'];
const ALL_EXTENSIONS = 'Client Notifications,Promotion Manager,Website Builder,Email Template,Custom Code,Support Hours,Sensitive Data';
const VALID_API_KEYS = [
'whmcsnulled' => 'prx8fxkifpbPOoVKDiprOI21Bz',
'whmcspremium' => 'haJG9VhPVECT2jarHFWQgTzr0u',
'client3' => 'POoG9VVKDiarHFWQgTzr0u',
];
const EXTENSION_PRODUCT_MAP = [
115 => 'Client Notifications',
129 => 'Sensitive Data',
67 => 'Promotion Manager',
6 => 'Promotion Manager,Email Template',
19 => 'Promotion Manager',
122 => 'Website Builder',
97 => 'Email Template',
123 => 'Custom Code',
124 => 'Support Hours',
];
// ============================================
// HELPER FUNCTIONS
// ============================================
function getPrivateKey()
{
$key = openssl_pkey_get_private(PRIVATE_KEY);
if (!$key) {
throw new Exception('Private key loading failed.');
}
return $key;
}
function encode($data)
{
$key = getPrivateKey();
$dataString = json_encode($data);
$chunks = str_split($dataString, 117);
$encryptedData = '';
foreach ($chunks as $chunk) {
openssl_private_encrypt($chunk, $encryptedChunk, $key);
$encryptedData .= $encryptedChunk;
}
return base64_encode($encryptedData);
}
function encodeString($string)
{
try {
$key = getPrivateKey();
openssl_private_encrypt($string, $encrypted, $key);
return base64_encode($encrypted);
} catch (Exception $e) {
return '';
}
}
function sendResponse($data, $httpCode = 200)
{
http_response_code($httpCode);
echo encode($data);
exit;
}
function sendError($message, $status = 'Invalid', $httpCode = 200, $extra = [])
{
$response = array_merge(['status' => $status, 'message' => $message], $extra);
sendResponse($response, $httpCode);
}
function isMasterKey($licenseKey)
{
return $licenseKey === MASTER_KEY;
}
function isLagomProduct($productId)
{
return in_array($productId, LAGOM_PRODUCT_IDS);
}
// ============================================
// DOMAIN FUNCTIONS
// ============================================
function getMainDomain($domain)
{
$domain = strtolower($domain);
if (filter_var($domain, FILTER_VALIDATE_IP)) {
return $domain;
}
$arr = array_values(array_filter(explode('.', $domain, 4), fn($v) => $v !== 'www'));
if (count($arr) <= 2) {
if (count($arr) === 2) {
$first = array_shift($arr);
if (strpos(join('.', $arr), '.') === false && !in_array($arr[0], ['localhost', 'test', 'invalid'])) {
array_unshift($arr, $first);
}
}
return join('.', $arr);
}
$count = count($arr);
$lastPart = explode('.', $count === 4 ? $arr[3] : $arr[2]);
$tlds = ['aero', 'arpa', 'asia', 'biz', 'cat', 'com', 'coop', 'edu', 'gov', 'info', 'jobs', 'mil', 'mobi', 'museum', 'name', 'net', 'org', 'post', 'pro', 'tel', 'travel', 'xxx'];
if (count($lastPart) === 2) {
array_shift($arr);
if ($count === 4) array_shift($arr);
} elseif (count($lastPart) === 1) {
$removed = array_shift($arr);
if (strlen($lastPart[0]) === 2 && $count === 3) {
array_unshift($arr, $removed);
} elseif (count($arr) > 2 && in_array($lastPart[0], $tlds)) {
array_shift($arr);
}
} else {
for ($i = count($lastPart); $i > 1; $i--) {
array_shift($arr);
}
}
return join('.', $arr);
}
function buildDomainList($domain, $ip)
{
$clean = str_replace('www.', '', $domain);
return implode(',', [$clean, 'www.' . $clean, getMainDomain($domain), $ip]);
}
function cleanDomain($domain)
{
return str_replace('www.', '', $domain);
}
// ============================================
// DATABASE FUNCTIONS
// ============================================
function logAction($license, $domain, $path, $ip, $message, $licenseCode = null)
{
$db = getDatabaseConnection();
$finalLicenseCode = $license['license_key'] ?? $licenseCode;
$check = $db->prepare("
SELECT id FROM license_logs
WHERE license_code = :license_code AND domain = :domain AND path = :path AND ip = :ip AND DATE(created_at) = CURDATE()
LIMIT 1
");
$check->execute([
'license_code' => $finalLicenseCode,
'domain' => $domain,
'path' => $path,
'ip' => $ip
]);
$existing = $check->fetch(PDO::FETCH_ASSOC);
if ($existing) {
$db->prepare("UPDATE license_logs SET updated_at = NOW(), message = :message WHERE id = :id")
->execute(['message' => $message, 'id' => $existing['id']]);
} else {
$db->prepare("
INSERT INTO license_logs (license_id, license_code, user_id, product_id, domain, ip, path, message, created_at, updated_at)
VALUES (:license_id, :license_code, :user_id, :product_id, :domain, :ip, :path, :message, NOW(), NOW())
")->execute([
'license_id' => $license['id'] ?? null,
'license_code' => $finalLicenseCode,
'user_id' => $license['user_id'] ?? null,
'product_id' => $license['product_id'] ?? null,
'domain' => $domain ?? '',
'ip' => $ip ?? '',
'path' => $path ?? '',
'message' => $message ?? ''
]);
}
}
function isBlocked($domain, $ip)
{
$db = getDatabaseConnection();
$mainDomain = getMainDomain($domain);
$query = $db->prepare("SELECT 1 FROM blocked_domains_ips WHERE domain = :domain OR ip = :ip LIMIT 1");
$query->execute(['domain' => $mainDomain, 'ip' => $ip]);
return (bool)$query->fetch();
}
function findLicense($licenseKey, $productId)
{
$db = getDatabaseConnection();
if (isMasterKey($licenseKey)) {
$query = $db->prepare("SELECT * FROM licenses WHERE license_key = :license_key");
$query->execute(['license_key' => $licenseKey]);
} elseif (isLagomProduct($productId)) {
$query = $db->prepare("SELECT * FROM licenses WHERE license_key = :license_key AND product_id IN (6, 18, 19)");
$query->execute(['license_key' => $licenseKey]);
} else {
$query = $db->prepare("SELECT * FROM licenses WHERE license_key = :license_key AND product_id = :product_id");
$query->execute(['license_key' => $licenseKey, 'product_id' => $productId]);
}
return $query->fetch(PDO::FETCH_ASSOC);
}
function updateLastAccess($licenseId)
{
$db = getDatabaseConnection();
$db->prepare("UPDATE licenses SET last_access = NOW() WHERE id = :id")->execute(['id' => $licenseId]);
}
function reissueLicense($license, $domain, $ip, $directory)
{
$db = getDatabaseConnection();
$cleanDomain = cleanDomain($domain);
$validDomain = $cleanDomain . ',www.' . $cleanDomain;
$db->prepare("
UPDATE licenses SET validdomain = :validdomain, validip = :validip, validdirectory = :validdirectory, status = 'Active' WHERE id = :id
")->execute([
'validdomain' => $validDomain,
'validip' => $ip,
'validdirectory' => $directory,
'id' => $license['id']
]);
return ['validdomain' => $validDomain, 'validip' => $ip, 'validdirectory' => $directory];
}
// ============================================
// VALIDATION FUNCTIONS
// ============================================
function validateInput($data)
{
$errors = [];
if (empty($data['licensekey'])) {
$errors[] = "License key is required.";
}
if (empty($data['domain'])) {
$errors[] = "Invalid domain format.";
} else {
$domain = $data['domain'];
if (strpos($domain, '${') !== false || strpos($domain, '$') !== false || preg_match('/[<>"\'\{\}]/', $domain)) {
$errors[] = "Invalid domain format - special characters not allowed.";
}
if (!preg_match('/^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$/', $domain)) {
$errors[] = "Invalid domain format.";
}
}
if (empty($data['ip']) || !filter_var($data['ip'], FILTER_VALIDATE_IP)) {
$errors[] = "Invalid IP address.";
}
if (empty($data['dir'])) {
$errors[] = "Directory is required.";
}
if (empty($data['product_id'])) {
$errors[] = "Product ID is required.";
}
return $errors;
}
function checkLicenseValidity($license, $isReseller = false)
{
// Check expiration
if (!empty($license['expires_at']) && strtotime($license['expires_at']) < time()) {
return ['valid' => false, 'status' => 'Expired', 'message' => 'License Expired. Please contact support.'];
}
// For reseller: accept Active and Reissued
if ($isReseller) {
if (in_array($license['status'], ['Expired', 'Inactive', 'Suspended'])) {
return ['valid' => false, 'status' => $license['status'], 'message' => "License {$license['status']}. Please contact support."];
}
} else {
// For non-reseller: only accept Active
if ($license['status'] !== 'Active') {
return ['valid' => false, 'status' => $license['status'], 'message' => "License {$license['status']}. Please contact support."];
}
}
return ['valid' => true];
}
function validateResellerAccess($license, $domain, $ip, $directory)
{
$validDomains = array_map('trim', explode(',', $license['validdomain']));
$validIps = array_map('trim', explode(',', $license['validip']));
$validDirs = array_map('trim', explode(',', $license['validdirectory']));
if (!in_array($domain, $validDomains)) {
return ['valid' => false, 'field' => 'Domain'];
}
if (!in_array($ip, $validIps)) {
return ['valid' => false, 'field' => 'IP'];
}
if (!in_array($directory, $validDirs)) {
return ['valid' => false, 'field' => 'Directory'];
}
return ['valid' => true];
}
// ============================================
// EXTENSION FUNCTIONS
// ============================================
function getExtensions($userId)
{
$db = getDatabaseConnection();
$extensions = [];
$query = $db->prepare("SELECT product_id FROM licenses WHERE user_id = :user_id AND status = 'Active'");
$query->execute(['user_id' => $userId]);
$activeProducts = $query->fetchAll(PDO::FETCH_COLUMN);
$addedExtensions = [];
foreach ($activeProducts as $productId) {
if (isset(EXTENSION_PRODUCT_MAP[$productId])) {
foreach (explode(',', EXTENSION_PRODUCT_MAP[$productId]) as $ext) {
$ext = trim($ext);
if (!in_array($ext, $addedExtensions)) {
$extensions[] = $ext;
$addedExtensions[] = $ext;
}
}
}
}
return implode(',', $extensions);
}
// ============================================
// RESPONSE BUILDERS
// ============================================
function buildBaseResponse($license, $validDomain, $validIp, $validDirectory, $productId)
{
$durationText = LicenseHelpers::getDurationDescription($license['duration_months'] ?? 0);
$response = [
'license_key' => $license['license_key'],
'status' => 'Active',
'validdomain' => $validDomain,
'validip' => $validIp,
'validdirectory' => $validDirectory,
'checkdate' => time(),
'last_access' => $license['last_access'],
'expires_at' => $license['expires_at'],
'regdate' => $license['created_at'] ?? date('Y-m-d H:i:s'),
'registeredname' => $license['owner'] ?? 'WHMCSNULLED.COM',
'email' => $license['email_support'] ?? '[email protected]',
'valid_until_hard' => strtotime('+1 days'),
'valid_until_soft' => strtotime('+3 days'),
'duration' => $license['duration_months'] ?? 0,
'duration_text' => $durationText,
'billingcycle' => $durationText,
'nextduedate' => $license['expires_at'] ?? date('Y-m-d', strtotime('+1 year')),
];
// Add extensions for Lagom products
if (isLagomProduct($productId)) {
$response['extensions'] = isMasterKey($license['license_key'])
? ALL_EXTENSIONS
: getExtensions($license['user_id']);
}
return $response;
}
function buildLagomResponse($license, $validDomain, $validIp, $validDirectory, $version, $productId)
{
$currentDate = date('Y-m-d');
$durationText = LicenseHelpers::getDurationDescription($license['duration_months'] ?? 0);
$nextDueDate = $license['expires_at'] ?? date('Y-m-d', strtotime('+1 year'));
$response = [
// Required fields for validateDetails
'status' => 'Active',
'service_status' => 'Active',
'license_status' => 'Active',
'nextduedate' => $nextDueDate,
'version' => $version,
'regdate' => $license['created_at'] ?? $currentDate,
'first_payment_amount' => '$149.00',
'recuring_amount' => '$149.00',
'payment_method' => 'PayPal',
// Domain/IP validation fields
'validdomain' => $validDomain,
'validip' => $validIp,
'validdirectory' => $validDirectory,
// Additional fields
'license_key' => $license['license_key'],
'checkdate' => time(),
'last_access' => $license['last_access'] ?? $currentDate,
'expires_at' => $license['expires_at'],
'registeredname' => $license['owner'] ?? 'WHMCSNULLED.COM',
'email' => $license['email_support'] ?? '[email protected]',
'fullversion' => 'Lagom ' . $version,
'billingcycle' => $durationText,
'duration' => $license['duration_months'] ?? 0,
'duration_text' => $durationText,
// Encrypted date for integrity check
'encryptedCurrentClientDate' => encodeString($currentDate),
// Extensions
'extensions' => isMasterKey($license['license_key'])
? ALL_EXTENSIONS
: getExtensions($license['user_id'])
];
return $response;
}
function buildResellerResponse($license, $productId)
{
$response = buildBaseResponse(
$license,
$license['validdomain'],
$license['validip'],
$license['validdirectory'],
$productId
);
return $response;
}
function buildStandardResponse($license, $domain, $ip, $directory, $productId)
{
$cleanDomain = cleanDomain($domain);
$validDomain = $cleanDomain . ',www.' . $cleanDomain . ',' . getMainDomain($domain) . ',' . $ip;
return buildBaseResponse($license, $validDomain, $ip, $directory, $productId);
}
// ============================================
// MAIN HANDLER
// ============================================
function handleRequest()
{
// Check method
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(404);
echo json_encode(['error' => 'Page not found.']);
exit;
}
// Parse input
$request = json_decode(file_get_contents('php://input'), true);
if (!$request) {
http_response_code(400);
echo json_encode(['status' => 'Invalid', 'message' => 'Invalid JSON input.']);
exit;
}
// Validate API key
if (!isset($request['api_key']) || !in_array($request['api_key'], VALID_API_KEYS)) {
http_response_code(401);
echo json_encode(['status' => 'Unauthorized', 'message' => 'Invalid API Key.']);
exit;
}
// Validate input
$errors = validateInput($request);
if (!empty($errors)) {
sendError(implode(', ', $errors));
}
// Extract params
$licenseKey = $request['licensekey'];
$domain = $request['domain'];
$ip = $request['ip'];
$directory = $request['dir'];
$productId = $request['product_id'];
$version = $request['version'] ?? '1.0.0';
$domainList = buildDomainList($domain, $ip);
// Check blocked
if (isBlocked($domain, $ip)) {
logAction(null, $domain, $directory, $ip, 'Access denied - Domain/IP is blocked', $licenseKey);
http_response_code(403);
sendError('Domain or IP is blocked due to policy violation.', 'Blocked', 403);
}
// Find license
$license = findLicense($licenseKey, $productId);
if (!$license) {
logAction(null, $domainList, $directory, $ip, 'License key is incorrect', $licenseKey);
sendError('License key is incorrect. Please contact support.');
}
// Master key - always valid
if (isMasterKey($licenseKey)) {
$response = isLagomProduct($productId)
? buildLagomResponse($license, $domain . ',www.' . $domain, $ip, $directory, $version, $productId)
: buildStandardResponse($license, $domain, $ip, $directory, $productId);
logAction($license, $domain, $directory, $ip, 'Admin License Active', $licenseKey);
sendResponse($response);
}
// ============================================
// XỬ LÝ LAGOM THEME (Product ID 18, 6, 19)
// ============================================
if (isLagomProduct($productId)) {
// Lagom + Reseller
if ($license['is_reseller'] == 1) {
// Check validity - Reseller accept Active và Reissued
$validity = checkLicenseValidity($license, true);
if (!$validity['valid']) {
logAction($license, $domainList, $directory, $ip, "License {$validity['status']}", $licenseKey);
sendError($validity['message'], 'Invalid', 200, [
'service_status' => $validity['status'],
'license_status' => $validity['status']
]);
}
// Handle Reissued status
if ($license['status'] === 'Reissued') {
$reissued = reissueLicense($license, $domain, $ip, $directory);
$license['validdomain'] = $reissued['validdomain'];
$license['validip'] = $reissued['validip'];
$license['validdirectory'] = $reissued['validdirectory'];
$license['status'] = 'Active';
if ($license['reissues'] > 0) {
logAction($license, $domain, $directory, $ip, 'License Reissued', $licenseKey);
}
$response = buildLagomResponse($license, $reissued['validdomain'], $reissued['validip'], $reissued['validdirectory'], $version, $productId);
logAction($license, $domain, $directory, $ip, 'License Active', $licenseKey);
sendResponse($response);
}
// Active status - validate access
$accessCheck = validateResellerAccess($license, $domain, $ip, $directory);
if (!$accessCheck['valid']) {
logAction(null, $domain, $directory, $ip, "{$accessCheck['field']} Invalid", $licenseKey);
sendError("{$accessCheck['field']} Invalid. Please contact support.", 'Invalid', 200, [
'service_status' => 'Invalid',
'license_status' => 'Invalid'
]);
}
$response = buildLagomResponse($license, $license['validdomain'], $license['validip'], $license['validdirectory'], $version, $productId);
logAction($license, $domain, $directory, $ip, 'License Active', $licenseKey);
sendResponse($response);
}
// Lagom + Non-reseller
$validity = checkLicenseValidity($license, false);
if (!$validity['valid']) {
logAction($license, $domainList, $directory, $ip, "License {$validity['status']}", $licenseKey);
sendError($validity['message'], 'Invalid', 200, [
'service_status' => $validity['status'],
'license_status' => $validity['status']
]);
}
updateLastAccess($license['id']);
$cleanDomain = cleanDomain($domain);
$validDomain = $cleanDomain . ',www.' . $cleanDomain;
$response = buildLagomResponse($license, $validDomain, $ip, $directory, $version, $productId);
logAction($license, $domain, $directory, $ip, 'License Active', $licenseKey);
sendResponse($response);
}
// ============================================
// XỬ LÝ RESELLER
// ============================================
if ($license['is_reseller'] == 1) {
// Check validity - Reseller accept Active và Reissued
$validity = checkLicenseValidity($license, true);
if (!$validity['valid']) {
logAction($license, $domainList, $directory, $ip, "License {$validity['status']}", $licenseKey);
sendError($validity['message']);
}
// Handle Reissued status
if ($license['status'] === 'Reissued') {
$reissued = reissueLicense($license, $domain, $ip, $directory);
$license['validdomain'] = $reissued['validdomain'];
$license['validip'] = $reissued['validip'];
$license['validdirectory'] = $reissued['validdirectory'];
$license['status'] = 'Active';
if ($license['reissues'] > 0) {
logAction($license, $domain, $directory, $ip, 'License Reissued', $licenseKey);
}
$response = buildResellerResponse($license, $productId);
logAction($license, $domain, $directory, $ip, 'License Active', $licenseKey);
sendResponse($response);
}
// Active status - validate access
$accessCheck = validateResellerAccess($license, $domain, $ip, $directory);
if (!$accessCheck['valid']) {
logAction(null, $domain, $directory, $ip, "{$accessCheck['field']} Invalid", $licenseKey);
sendError("{$accessCheck['field']} Invalid. Please contact support.");
}
$response = buildResellerResponse($license, $productId);
logAction($license, $domain, $directory, $ip, 'License Active', $licenseKey);
sendResponse($response);
}
// ============================================
// XỬ LÝ STANDARD PRODUCTS
// ============================================
// Check validity - Standard chỉ accept Active
$validity = checkLicenseValidity($license, false);
if (!$validity['valid']) {
logAction($license, $domain, $directory, $ip, 'License Suspended', $licenseKey);
sendError('License Suspended. Please contact support.');
}
updateLastAccess($license['id']);
$response = buildStandardResponse($license, $domain, $ip, $directory, $productId);
logAction($license, $domain, $directory, $ip, 'License Active', $licenseKey);
sendResponse($response);
}
// Run
handleRequest();
What's New {#whats-new}
- Complete Server Management: Full control over your VPS and dedicated servers
- Domain Management: Create and manage unlimited domains with automatic Nginx configuration
- SSL Certificates: One-click Let's Encrypt SSL with automatic renewal
- Database Management: MySQL/MariaDB with phpMyAdmin integration
- Automated Backups: Schedule backups to local or S3-compatible storage
Getting Started {#getting-started}
Install WisPanel with a single command:
curl -sSL https://wispanel.com/install.sh | bash
Supported Systems {#supported-systems}
- Ubuntu 20.04/22.04/24.04 LTS
- Debian 11/12
- AlmaLinux 8/9
Thank you to everyone who participated in our beta testing program!