date('Y-m-d H:i:s'), 'ip' => $_SERVER['REMOTE_ADDR'] ?? 'unknown', 'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'unknown', 'endpoint' => $endpoint, 'params' => $params, 'response' => $response ]; $logFile = '/web/admin/logs/indexer/api/requests.log'; $logDir = dirname($logFile); if (!is_dir($logDir)) { mkdir($logDir, 0755, true); } file_put_contents($logFile, json_encode($logData) . "\n", FILE_APPEND | LOCK_EX); } function jsonResponse($data, $status = 200) { http_response_code($status); echo json_encode($data, JSON_PRETTY_PRINT); exit(); } function errorResponse($message, $status = 400) { logRequest($_GET['action'] ?? 'unknown', $_GET, 'error: ' . $message); jsonResponse(['error' => $message, 'status' => $status], $status); } function loadExtensionMappings() { global $extensionMapFile; if (!file_exists($extensionMapFile)) { return null; } $mappingData = file_get_contents($extensionMapFile); $mappings = json_decode($mappingData, true); return $mappings ?: null; } function loadIconMappings() { global $iconsMappingFile; if (!file_exists($iconsMappingFile)) { return []; } $mappingData = file_get_contents($iconsMappingFile); $mappings = json_decode($mappingData, true); return $mappings ?: []; } function findIconForType($type, $extension = '') { global $iconsDir; $iconMappings = loadIconMappings(); if ($type === 'folder') { $iconFile = isset($iconMappings['folder']) ? $iconMappings['folder'] : 'folder.png'; } else { $extension = strtolower($extension); $iconFile = isset($iconMappings[$extension]) ? $iconMappings[$extension] : 'text.png'; } $iconPath = $iconsDir . '/' . $iconFile; if (!file_exists($iconPath)) { $iconFile = 'text.png'; $iconPath = $iconsDir . '/' . $iconFile; if (!file_exists($iconPath)) { return null; } } return [ 'filename' => $iconFile, 'url' => 'https://api.indexer.ccls.icu/icons/' . $iconFile, 'path' => $iconPath, 'size' => filesize($iconPath), 'last_modified' => filemtime($iconPath) ]; } $action = $_GET['action'] ?? ''; switch ($action) { case 'versionCheck': handleVersionCheckRequest(); break; case 'config': handleConfigRequest(); break; case 'icons': handleIconsRequest(); break; case 'icon': handleSingleIconRequest(); break; case 'findIcon': handleFindIconRequest(); break; case 'iconMappings': handleIconMappingsRequest(); break; case 'extensionMappings': handleExtensionMappingsRequest(); break; case 'getExtensionSetting': handleGetExtensionSettingRequest(); break; case 'configReference': handleConfigReferenceRequest(); break; case 'status': handleStatusRequest(); break; default: handleDefaultRequest(); break; } function handleVersionCheckRequest() { global $configFile; $currentVersion = $_GET['current_version'] ?? ''; if (empty($currentVersion)) { errorResponse('Current version parameter is required'); } if (!file_exists($configFile)) { errorResponse('Configuration file not found', 404); } $configData = file_get_contents($configFile); $config = json_decode($configData, true); if ($config === null) { errorResponse('Invalid configuration file', 500); } $latestVersion = isset($config['version']) ? $config['version'] : '1.1.10'; $updateNeeded = version_compare($currentVersion, $latestVersion, '<'); $response = [ 'success' => true, 'current_version' => $currentVersion, 'latest_version' => $latestVersion, 'update_needed' => $updateNeeded, 'timestamp' => date('Y-m-d H:i:s') ]; if ($updateNeeded) { $response['message'] = "Update available: {$currentVersion} -> {$latestVersion}"; $response['config_url'] = 'https://api.indexer.ccls.icu/api.php?action=config'; } else { $response['message'] = "You have the latest version: {$currentVersion}"; } logRequest('versionCheck', ['current_version' => $currentVersion, 'latest_version' => $latestVersion, 'update_needed' => $updateNeeded]); header('Cache-Control: public, max-age=900'); jsonResponse($response); } function handleExtensionMappingsRequest() { $type = $_GET['type'] ?? 'all'; $extensionMappings = loadExtensionMappings(); if ($extensionMappings === null) { errorResponse('Extension mappings not found or invalid', 404); } $response = [ 'success' => true ]; switch ($type) { case 'indexing': $response['mappings'] = $extensionMappings['indexing']; $response['count'] = count($extensionMappings['indexing']); break; case 'viewing': $response['mappings'] = $extensionMappings['viewing']; $response['count'] = count($extensionMappings['viewing']); break; case 'all': default: $response['mappings'] = $extensionMappings; $response['indexing_count'] = count($extensionMappings['indexing']); $response['viewing_count'] = count($extensionMappings['viewing']); break; } logRequest('extensionMappings', ['type' => $type]); header('Cache-Control: public, max-age=86400'); jsonResponse($response); } function handleGetExtensionSettingRequest() { $extension = $_GET['extension'] ?? ''; $type = $_GET['type'] ?? 'indexing'; if (empty($extension)) { errorResponse('Extension parameter is required'); } $extensionMappings = loadExtensionMappings(); if ($extensionMappings === null) { errorResponse('Extension mappings not found or invalid', 404); } $extension = strtolower($extension); $setting = null; if ($type === 'indexing' && isset($extensionMappings['indexing'][$extension])) { $setting = $extensionMappings['indexing'][$extension]; } elseif ($type === 'viewing' && isset($extensionMappings['viewing'][$extension])) { $setting = $extensionMappings['viewing'][$extension]; } logRequest('getExtensionSetting', ['extension' => $extension, 'type' => $type]); header('Cache-Control: public, max-age=86400'); jsonResponse([ 'success' => true, 'extension' => $extension, 'type' => $type, 'setting' => $setting, 'found' => $setting !== null ]); } function handleFindIconRequest() { $type = $_GET['type'] ?? 'file'; $extension = $_GET['extension'] ?? ''; if (empty($extension) && $type !== 'folder') { errorResponse('Extension parameter is required for file types'); } $iconInfo = findIconForType($type, $extension); if ($iconInfo === null) { errorResponse('Icon not found', 404); } logRequest('findIcon', ['type' => $type, 'extension' => $extension]); header('Cache-Control: public, max-age=86400'); jsonResponse([ 'success' => true, 'type' => $type, 'extension' => $extension, 'icon' => $iconInfo ]); } function handleIconMappingsRequest() { $iconMappings = loadIconMappings(); if (empty($iconMappings)) { errorResponse('Icon mappings not found or invalid', 404); } logRequest('iconMappings'); header('Cache-Control: public, max-age=86400'); jsonResponse([ 'success' => true, 'mappings' => $iconMappings, 'count' => count($iconMappings) ]); } function handleConfigRequest() { global $configFile; if (!file_exists($configFile)) { errorResponse('Configuration file not found', 404); } $configData = file_get_contents($configFile); $config = json_decode($configData, true); if ($config === null) { errorResponse('Invalid configuration file', 500); } logRequest('config'); header('Cache-Control: public, max-age=3600'); jsonResponse([ 'success' => true, 'config' => $config, 'version' => '1.1.10', 'last_modified' => filemtime($configFile) ]); } function handleIconsRequest() { global $iconsDir; if (!is_dir($iconsDir)) { errorResponse('Icons directory not found', 404); } $icons = []; $files = scandir($iconsDir); foreach ($files as $file) { if ($file === '.' || $file === '..') continue; $filePath = $iconsDir . '/' . $file; if (is_file($filePath) && preg_match('/\.(png|jpg|jpeg|gif|svg|webp)$/i', $file)) { $icons[] = [ 'filename' => $file, 'url' => 'https://api.indexer.ccls.icu/icons/' . $file, 'size' => filesize($filePath), 'last_modified' => filemtime($filePath) ]; } } logRequest('icons'); header('Cache-Control: public, max-age=86400'); jsonResponse([ 'success' => true, 'icons' => $icons, 'count' => count($icons) ]); } function handleSingleIconRequest() { global $iconsDir; $iconName = $_GET['name'] ?? ''; if (empty($iconName)) { errorResponse('Icon name not specified'); } $iconName = basename($iconName); if (!preg_match('/\.(png|jpg|jpeg|gif|svg|webp)$/i', $iconName)) { errorResponse('Invalid icon file type'); } $iconPath = $iconsDir . '/' . $iconName; if (!file_exists($iconPath)) { errorResponse('Icon not found', 404); } logRequest('icon', ['name' => $iconName]); jsonResponse([ 'success' => true, 'icon' => [ 'filename' => $iconName, 'url' => 'https://api.indexer.ccls.icu/icons/' . $iconName, 'size' => filesize($iconPath), 'last_modified' => filemtime($iconPath) ] ]); } function handleStatusRequest() { global $configFile, $iconsDir, $iconsMappingFile, $extensionMapFile; $status = [ 'success' => true, 'service' => 'Indexer API', 'version' => '1.1.10', 'timestamp' => date('Y-m-d H:i:s'), 'config_exists' => file_exists($configFile), 'icons_dir_exists' => is_dir($iconsDir), 'icon_mappings_exists' => file_exists($iconsMappingFile), 'extension_mappings_exists' => file_exists($extensionMapFile), 'icon_count' => 0, 'mapping_count' => 0, 'extension_mapping_count' => 0 ]; if (is_dir($iconsDir)) { $files = glob($iconsDir . '/*.{png,jpg,jpeg,gif,svg,webp}', GLOB_BRACE); $status['icon_count'] = count($files); } if (file_exists($configFile)) { $status['config_last_modified'] = filemtime($configFile); } if (file_exists($iconsMappingFile)) { $status['mappings_last_modified'] = filemtime($iconsMappingFile); $mappings = loadIconMappings(); $status['mapping_count'] = count($mappings); } if (file_exists($extensionMapFile)) { $status['extension_mappings_last_modified'] = filemtime($extensionMapFile); $extensionMappings = loadExtensionMappings(); if ($extensionMappings !== null) { $status['extension_mapping_count'] = count($extensionMappings['indexing']) + count($extensionMappings['viewing']); } } logRequest('status'); jsonResponse($status); } function handleConfigReferenceRequest() { $referenceFile = __DIR__ . '/config-reference.txt'; if (!file_exists($referenceFile)) { errorResponse('Configuration reference not found', 404); } $content = file_get_contents($referenceFile); $lastModified = filemtime($referenceFile); logRequest('configReference'); header('Cache-Control: public, max-age=86400'); jsonResponse([ 'success' => true, 'content' => $content, 'last_modified' => $lastModified, 'version' => '1.2', 'format' => 'text' ]); } function handleDefaultRequest() { $info = [ 'success' => true, 'service' => 'Indexer API', 'version' => '1.1.10', 'description' => 'API for the custom indexer project', 'endpoints' => [ 'versionCheck' => [ 'url' => '?action=versionCheck¤t_version={version}', 'description' => 'Check if a config update is available', 'method' => 'GET' ], 'config' => [ 'url' => '?action=config', 'description' => 'Get configuration file', 'method' => 'GET' ], 'icons' => [ 'url' => '?action=icons', 'description' => 'List all available icons', 'method' => 'GET' ], 'icon' => [ 'url' => '?action=icon&name={filename}', 'description' => 'Get information about a specific icon', 'method' => 'GET' ], 'findIcon' => [ 'url' => '?action=findIcon&type={file|folder}&extension={ext}', 'description' => 'Find the appropriate icon for a file type or folder', 'method' => 'GET' ], 'iconMappings' => [ 'url' => '?action=iconMappings', 'description' => 'Get all icon mappings from icons.json', 'method' => 'GET' ], 'extensionMappings' => [ 'url' => '?action=extensionMappings&type={all|indexing|viewing}', 'description' => 'Get extension mappings for indexing or viewing', 'method' => 'GET' ], 'getExtensionSetting' => [ 'url' => '?action=getExtensionSetting&extension={ext}&type={indexing|viewing}', 'description' => 'Get the configuration setting for a specific file extension', 'method' => 'GET' ], 'configReference' => [ 'url' => '?action=configReference', 'description' => 'Get configuration reference documentation', 'method' => 'GET' ], 'status' => [ 'url' => '?action=status', 'description' => 'Get API status and health information', 'method' => 'GET' ] ], 'icon_base_url' => 'https://api.indexer.ccls.icu/icons/', 'timestamp' => date('Y-m-d H:i:s') ]; logRequest('info'); jsonResponse($info); } ?>