Файловый менеджер - Редактировать - /home/gqdcvggs/go.imators.com/Can.zip
Назад
PK �0�[ V� cli.phpnu �[��� <?php require_once 'core/parser.php'; require_once 'core/router.php'; require_once 'core/response.php'; if ($argc < 2) { echo "Usage: php cli.php \"your query\"\n"; exit(1); } $query = $argv[1]; try { $parser = new CanParser(); $router = new CanRouter(); $response = new CanResponse(); $parsed = $parser->parse($query); $result = $router->execute($parsed); echo $response->format($result, 'cli'); } catch (Exception $e) { echo "Error: " . $e->getMessage() . "\n"; exit(1); } ?>PK �0�[�G/ / core/response.phpnu �[��� <?php class CanResponse { public function format($result, $format = 'api') { switch ($format) { case 'cli': return $this->formatCli($result); case 'api': return $this->formatApi($result); default: return $this->formatApi($result); } } private function formatCli($result) { $output = "Status: " . $result['status'] . "\n"; $output .= "Message: " . $result['message'] . "\n"; $output .= "Execution time: " . $result['execution_time'] . "\n"; $output .= "Data: "; if (is_array($result['data']) || is_object($result['data'])) { $output .= json_encode($result['data'], JSON_PRETTY_PRINT); } else { $output .= $result['data']; } $output .= "\n"; return $output; } private function formatApi($result) { return json_encode($result, JSON_UNESCAPED_UNICODE); } public function error($message, $format = 'api') { $error_result = [ 'status' => 'error', 'message' => $message, 'data' => null, 'execution_time' => '0ms' ]; return $this->format($error_result, $format); } } ?>PK �0�[���{ core/router.phpnu �[��� <?php class CanRouter { private $connectors_path = __DIR__ . '/../connectors/'; public function execute($parsed) { $start_time = microtime(true); $connector_file = $this->connectors_path . $parsed['connector']; if (!file_exists($connector_file)) { throw new Exception("Connector file not found: " . $parsed['connector']); } require_once $connector_file; $connector_class = $this->getConnectorClass($parsed['connector']); if (!class_exists($connector_class)) { throw new Exception("Connector class not found: " . $connector_class); } $connector = new $connector_class(); if (!method_exists($connector, $parsed['action'])) { throw new Exception("Action '{$parsed['action']}' not supported by connector"); } $result = $connector->{$parsed['action']}($parsed['params'], $parsed['resource']); $execution_time = round((microtime(true) - $start_time) * 1000, 2); return [ 'status' => 'success', 'data' => $result, 'message' => 'Query executed successfully', 'execution_time' => $execution_time . 'ms', 'parsed_query' => $parsed ]; } private function getConnectorClass($connector_file) { $base_name = pathinfo($connector_file, PATHINFO_FILENAME); return ucfirst($base_name) . 'Connector'; } } ?>PK �0�[L��/ / core/parser.phpnu �[��� <?php class CanParser { public function parse($query) { $query = trim($query); if (!$this->isValidQuery($query)) { throw new Exception("Invalid query format"); } $action = $this->extractAction($query); $params = $this->extractParams($query); $resource = $this->extractResource($query); $connector = $this->extractConnector($query); return [ 'action' => $action, 'params' => $params, 'resource' => $resource, 'connector' => $connector, 'original_query' => $query ]; } private function isValidQuery($query) { return preg_match("/\b(?:in|from)\s+['\"].*?['\"]\s*,\s*conn\s+to\s+['\"].*?['\"]/i", $query); } private function extractAction($query) { $actions = ['add', 'insert', 'get', 'select', 'update', 'modify', 'delete', 'remove', 'search', 'find', 'count', 'calculate', 'send']; foreach ($actions as $action) { if (preg_match("/^{$action}\b/i", $query)) { return strtolower($action); } } throw new Exception("No valid action found in query"); } private function extractParams($query) { $pattern = "/^(\w+)\s+(.*?)\s+(?:in|from)\s+['\"].*?['\"]/i"; if (preg_match($pattern, $query, $matches)) { return trim($matches[2]); } return ''; } private function extractResource($query) { $pattern = "/(?:in|from)\s+['\"]([^'\"]+)['\"]/i"; if (preg_match($pattern, $query, $matches)) { return $matches[1]; } throw new Exception("No resource specified"); } private function extractConnector($query) { $pattern = "/conn\s+to\s+['\"]([^'\"]+)['\"]/i"; if (preg_match($pattern, $query, $matches)) { return $matches[1]; } throw new Exception("No connector specified"); } } ?>PK �0�[���I I api.phpnu �[��� <?php header('Content-Type: application/json'); header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: GET, POST'); header('Access-Control-Allow-Headers: Content-Type'); require_once 'core/parser.php'; require_once 'core/router.php'; require_once 'core/response.php'; $query = ''; if ($_SERVER['REQUEST_METHOD'] === 'POST') { $input = json_decode(file_get_contents('php://input'), true); $query = $input['query'] ?? ''; } elseif ($_SERVER['REQUEST_METHOD'] === 'GET') { $query = $_GET['query'] ?? ''; } if (empty($query)) { echo json_encode([ 'status' => 'error', 'message' => 'No query provided', 'data' => null ]); exit; } try { $parser = new CanParser(); $router = new CanRouter(); $response = new CanResponse(); $parsed = $parser->parse($query); $result = $router->execute($parsed); echo $response->format($result, 'api'); } catch (Exception $e) { echo json_encode([ 'status' => 'error', 'message' => $e->getMessage(), 'data' => null ]); } ?>PK �0�[��E connectors/file.phpnu �[��� <?php class FileConnector { private $base_path; public function __construct() { $this->base_path = __DIR__ . '/files/'; if (!is_dir($this->base_path)) { mkdir($this->base_path, 0755, true); } } private function getFilePath($resource) { $file_path = $this->base_path . $resource; if (!file_exists($file_path)) { throw new Exception("File not found: " . $resource); } return $file_path; } public function get($params, $resource) { $file_path = $this->getFilePath($resource); $extension = pathinfo($file_path, PATHINFO_EXTENSION); switch (strtolower($extension)) { case 'json': return $this->getFromJson($params, $file_path); case 'csv': return $this->getFromCsv($params, $file_path); case 'txt': return $this->getFromText($params, $file_path); default: return file_get_contents($file_path); } } public function add($params, $resource) { $file_path = $this->base_path . $resource; $extension = pathinfo($file_path, PATHINFO_EXTENSION); switch (strtolower($extension)) { case 'csv': return $this->addToCsv($params, $file_path); case 'txt': return $this->addToText($params, $file_path); default: return file_put_contents($file_path, $params, FILE_APPEND); } } public function update($params, $resource) { $file_path = $this->getFilePath($resource); $extension = pathinfo($file_path, PATHINFO_EXTENSION); switch (strtolower($extension)) { case 'json': return $this->updateJson($params, $file_path); default: throw new Exception("Update not supported for this file type"); } } public function search($params, $resource) { $file_path = $this->getFilePath($resource); $content = file_get_contents($file_path); if (preg_match("/text\s+['\"]([^'\"]+)['\"]/i", $params, $matches)) { $search_term = $matches[1]; $lines = explode("\n", $content); $results = []; foreach ($lines as $line_num => $line) { if (stripos($line, $search_term) !== false) { $results[] = [ 'line' => $line_num + 1, 'content' => trim($line) ]; } } return $results; } throw new Exception("Invalid search syntax"); } private function getFromJson($params, $file_path) { $data = json_decode(file_get_contents($file_path), true); if (preg_match("/value\s+from\s+key\s+['\"]([^'\"]+)['\"]/i", $params, $matches)) { $key = $matches[1]; return isset($data[$key]) ? $data[$key] : null; } return $data; } private function getFromCsv($params, $file_path) { $data = []; $handle = fopen($file_path, 'r'); if ($handle !== false) { $headers = fgetcsv($handle); if ($headers) { while (($row = fgetcsv($handle)) !== false) { if (count($row) === count($headers)) { $data[] = array_combine($headers, $row); } } } fclose($handle); } return $data; } private function getFromText($params, $file_path) { return file_get_contents($file_path); } private function addToCsv($params, $file_path) { if (preg_match("/line\s+['\"]([^'\"]+)['\"]/i", $params, $matches)) { $line = $matches[1]; $data = str_getcsv($line); $handle = fopen($file_path, 'a'); if ($handle !== false) { fputcsv($handle, $data); fclose($handle); return true; } } return false; } private function addToText($params, $file_path) { if (preg_match("/line\s+['\"]([^'\"]+)['\"]/i", $params, $matches)) { $line = $matches[1]; return file_put_contents($file_path, $line . "\n", FILE_APPEND); } return false; } private function updateJson($params, $file_path) { $data = json_decode(file_get_contents($file_path), true); if (preg_match("/key\s+['\"]([^'\"]+)['\"]\s+with\s+['\"]([^'\"]+)['\"]/i", $params, $matches)) { $key = $matches[1]; $value = $matches[2]; $data[$key] = $value; return file_put_contents($file_path, json_encode($data, JSON_PRETTY_PRINT)); } return false; } } ?>PK �0�[���3z z connectors/mysql.phpnu �[��� <?php class MysqlConnector { private $connections = []; private function getConnection($resource) { if (!isset($this->connections[$resource])) { $config = $this->getConfig($resource); try { $this->connections[$resource] = new PDO( "mysql:host={$config['host']};dbname={$config['database']};charset=utf8", $config['username'], $config['password'], [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION] ); } catch (PDOException $e) { throw new Exception("Database connection failed: " . $e->getMessage()); } } return $this->connections[$resource]; } private function getConfig($resource) { $config_file = __DIR__ . '/config/' . $resource . '.json'; if (!file_exists($config_file)) { throw new Exception("Database config not found for: " . $resource); } return json_decode(file_get_contents($config_file), true); } public function add($params, $resource) { return $this->insert($params, $resource); } public function insert($params, $resource) { $pdo = $this->getConnection($resource); if (preg_match("/(.+?)\s+value\s+to\s+colonne\s+['\"]([^'\"]+)['\"]/i", $params, $matches)) { $value = trim($matches[1]); $column = $matches[2]; $table = $this->extractTable($params); $sql = "INSERT INTO {$table} ({$column}) VALUES (?)"; $stmt = $pdo->prepare($sql); $stmt->execute([$value]); return $pdo->lastInsertId(); } throw new Exception("Invalid insert syntax"); } public function get($params, $resource) { return $this->select($params, $resource); } public function select($params, $resource) { $pdo = $this->getConnection($resource); if (preg_match("/all\s+(\w+)(?:\s+where\s+(.+))?/i", $params, $matches)) { $table = $matches[1]; $where = isset($matches[2]) ? $matches[2] : ''; $sql = "SELECT * FROM {$table}"; if ($where) { $sql .= " WHERE " . $this->sanitizeWhere($where); } $stmt = $pdo->prepare($sql); $stmt->execute(); return $stmt->fetchAll(PDO::FETCH_ASSOC); } throw new Exception("Invalid select syntax"); } public function update($params, $resource) { $pdo = $this->getConnection($resource); if (preg_match("/(\w+)=(\d+)\s+set\s+(.+)/i", $params, $matches)) { $id_field = $matches[1]; $id_value = $matches[2]; $set_clause = $matches[3]; $table = $this->extractTable($params); $sql = "UPDATE {$table} SET {$set_clause} WHERE {$id_field} = ?"; $stmt = $pdo->prepare($sql); $stmt->execute([$id_value]); return $stmt->rowCount(); } throw new Exception("Invalid update syntax"); } public function delete($params, $resource) { $pdo = $this->getConnection($resource); if (preg_match("/record\s+where\s+(.+)/i", $params, $matches)) { $where = $matches[1]; $table = $this->extractTable($params); $sql = "DELETE FROM {$table} WHERE " . $this->sanitizeWhere($where); $stmt = $pdo->prepare($sql); $stmt->execute(); return $stmt->rowCount(); } throw new Exception("Invalid delete syntax"); } public function count($params, $resource) { $pdo = $this->getConnection($resource); if (preg_match("/rows(?:\s+where\s+(.+))?/i", $params, $matches)) { $where = isset($matches[1]) ? $matches[1] : ''; $table = $this->extractTable($params); $sql = "SELECT COUNT(*) as count FROM {$table}"; if ($where) { $sql .= " WHERE " . $this->sanitizeWhere($where); } $stmt = $pdo->prepare($sql); $stmt->execute(); return $stmt->fetch(PDO::FETCH_ASSOC)['count']; } throw new Exception("Invalid count syntax"); } private function extractTable($params) { if (preg_match("/(?:from|into|table)\s+['\"]?(\w+)['\"]?/i", $params, $matches)) { return $matches[1]; } throw new Exception("No table specified"); } private function sanitizeWhere($where) { return preg_replace("/['\"]([^'\"]+)['\"]/", "'$1'", $where); } } ?>PK �0�[��� � connectors/api.phpnu �[��� <?php class ApiConnector { private function getConfig($resource) { $config_file = __DIR__ . '/config/' . $resource . '.json'; if (!file_exists($config_file)) { throw new Exception("API config not found for: " . $resource); } return json_decode(file_get_contents($config_file), true); } private function makeRequest($method, $url, $data = null, $headers = []) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 30); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); switch (strtoupper($method)) { case 'POST': curl_setopt($ch, CURLOPT_POST, true); if ($data) { curl_setopt($ch, CURLOPT_POSTFIELDS, $data); } break; case 'PUT': curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT'); if ($data) { curl_setopt($ch, CURLOPT_POSTFIELDS, $data); } break; case 'DELETE': curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE'); break; } $response = curl_exec($ch); $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); if (curl_error($ch)) { throw new Exception("cURL Error: " . curl_error($ch)); } curl_close($ch); if ($http_code >= 400) { throw new Exception("HTTP Error: " . $http_code); } return json_decode($response, true) ?: $response; } public function get($params, $resource) { $config = $this->getConfig($resource); if (preg_match("/(\w+)\s+where\s+(.+)/i", $params, $matches)) { $endpoint = $matches[1]; $query_params = $this->parseQueryParams($matches[2]); $url = $config['base_url'] . '/' . $endpoint; if (!empty($query_params)) { $url .= '?' . http_build_query($query_params); } $headers = $this->buildHeaders($config); return $this->makeRequest('GET', $url, null, $headers); } throw new Exception("Invalid get syntax for API"); } public function send($params, $resource) { $config = $this->getConfig($resource); if (preg_match("/data\s+['\"]({.*?})['\"]\s+to\s+endpoint\s+['\"]([^'\"]+)['\"]/i", $params, $matches)) { $data = $matches[1]; $endpoint = $matches[2]; $url = $config['base_url'] . '/' . $endpoint; $headers = $this->buildHeaders($config); $headers[] = 'Content-Type: application/json'; return $this->makeRequest('POST', $url, $data, $headers); } throw new Exception("Invalid send syntax for API"); } public function search($params, $resource) { $config = $this->getConfig($resource); if (preg_match("/(\w+)\s+['\"]([^'\"]+)['\"]/i", $params, $matches)) { $search_type = $matches[1]; $search_term = $matches[2]; $endpoint = $config['search_endpoint'] ?? 'search'; $url = $config['base_url'] . '/' . $endpoint; $query_params = [ $search_type => $search_term ]; $url .= '?' . http_build_query($query_params); $headers = $this->buildHeaders($config); return $this->makeRequest('GET', $url, null, $headers); } throw new Exception("Invalid search syntax for API"); } public function update($params, $resource) { $config = $this->getConfig($resource); if (preg_match("/(\w+)\s+id=(\d+)\s+with\s+['\"]({.*?})['\"]/i", $params, $matches)) { $endpoint = $matches[1]; $id = $matches[2]; $data = $matches[3]; $url = $config['base_url'] . '/' . $endpoint . '/' . $id; $headers = $this->buildHeaders($config); $headers[] = 'Content-Type: application/json'; return $this->makeRequest('PUT', $url, $data, $headers); } throw new Exception("Invalid update syntax for API"); } public function delete($params, $resource) { $config = $this->getConfig($resource); if (preg_match("/(\w+)\s+id=(\d+)/i", $params, $matches)) { $endpoint = $matches[1]; $id = $matches[2]; $url = $config['base_url'] . '/' . $endpoint . '/' . $id; $headers = $this->buildHeaders($config); return $this->makeRequest('DELETE', $url, null, $headers); } throw new Exception("Invalid delete syntax for API"); } private function parseQueryParams($query_string) { $params = []; if (preg_match_all("/(\w+)=['\"]?([^'\"&]+)['\"]?/", $query_string, $matches, PREG_SET_ORDER)) { foreach ($matches as $match) { $params[$match[1]] = $match[2]; } } return $params; } private function buildHeaders($config) { $headers = []; if (isset($config['auth_type'])) { switch ($config['auth_type']) { case 'bearer': $headers[] = 'Authorization: Bearer ' . $config['token']; break; case 'api_key': $headers[] = $config['api_key_header'] . ': ' . $config['api_key']; break; case 'basic': $auth = base64_encode($config['username'] . ':' . $config['password']); $headers[] = 'Authorization: Basic ' . $auth; break; } } if (isset($config['custom_headers'])) { $headers = array_merge($headers, $config['custom_headers']); } return $headers; } } ?>PK �0�[�N� connectors/files/cart.csvnu �[��� product_id,quantity,pricePK �0�[��T� � README.mdnu �[��� # Can - Algorithme de traitement de requêtes universelles Can est un système intelligent qui permet d'exécuter des requêtes sur différentes sources de données (bases de données, fichiers, APIs) via une syntaxe unifiée. ## Installation ```bash git clone https://github.com/votre-repo/can.git cd can ``` ## Structure ``` can/ ├── cli.php # Interface console ├── api.php # Endpoint API REST ├── core/ │ ├── parser.php # Analyseur de requêtes │ ├── router.php # Routeur vers connectors │ └── response.php # Gestionnaire de réponses └── connectors/ ├── mysql.php # Connector bases de données ├── file.php # Connector fichiers ├── api.php # Connector APIs externes └── config/ # Configurations des ressources ``` ## Syntaxe des requêtes ``` [action] [paramètres] in '[ressource]', conn to '[connector]' ``` ### Actions supportées - `add/insert` - Ajouter des données - `get/select` - Récupérer des données - `update/modify` - Modifier des données - `delete/remove` - Supprimer des données - `search/find` - Chercher dans les données - `count` - Compter des éléments - `send` - Envoyer vers APIs ## Configuration ### Base de données (MySQL) Créer `connectors/config/database_users.json` : ```json { "host": "localhost", "database": "myapp", "username": "user", "password": "pass" } ``` ### API externe Créer `connectors/config/inventory_api.json` : ```json { "base_url": "https://api.inventory.com/v1", "auth_type": "bearer", "token": "your_token_here", "search_endpoint": "search" } ``` ### Fichiers Placer les fichiers dans `connectors/files/` ## Utilisation ### Console ```bash php cli.php "get all users where status='active' in 'database_users', conn to 'mysql.php'" php cli.php "add line 'john,doe,30' to 'users.csv', conn to 'file.php'" php cli.php "search user 'john@doe.com' in 'crm_api', conn to 'api.php'" ``` ### API REST #### JavaScript ```javascript fetch('http://localhost/can/api', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ query: "get all users where status='active' in 'database_users', conn to 'mysql.php'" }) }) .then(response => response.json()) .then(data => console.log(data)); ``` #### PHP ```php $query = "add 1.92 value to colonne 'price' in 'products_db', conn to 'mysql.php'"; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'http://localhost/can/api'); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['query' => $query])); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); $data = json_decode($response, true); ``` #### Go ```go package main import ( "bytes" "encoding/json" "net/http" "io/ioutil" ) func callCan(query string) { payload, _ := json.Marshal(map[string]string{"query": query}) resp, _ := http.Post("http://localhost/can/api", "application/json", bytes.NewBuffer(payload)) defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) var result map[string]interface{} json.Unmarshal(body, &result) } ``` ## Intégration dans un service ### Service PHP existant ```php class MonService { private $can_url = 'http://localhost/can/api'; public function getUsersActive() { return $this->callCan("get all users where status='active' in 'database_users', conn to 'mysql.php'"); } public function updateUserEmail($userId, $email) { return $this->callCan("update user_id={$userId} set email='{$email}' in 'database_users', conn to 'mysql.php'"); } public function getAnalyticsData() { return $this->callCan("get value from key 'total_sales' in 'analytics.json', conn to 'file.php'"); } private function callCan($query) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $this->can_url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['query' => $query])); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); return json_decode($response, true); } } ``` ### Service JavaScript/Node.js ```javascript class CanService { constructor() { this.canUrl = 'http://localhost/can/api'; } async getUsersActive() { return await this.callCan("get all users where status='active' in 'database_users', conn to 'mysql.php'"); } async searchProduct(sku) { return await this.callCan(`search product where sku='${sku}' in 'inventory_api', conn to 'api.php'`); } async callCan(query) { const response = await fetch(this.canUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ query }) }); return await response.json(); } } ``` ## Exemples de requêtes ### Base de données ``` "add 1.92 value to colonne 'price' in 'products_db', conn to 'mysql.php'" "get all users where status='active' in 'users_db', conn to 'mysql.php'" "update user_id=123 set email='new@email.com' in 'users_db', conn to 'mysql.php'" "delete record where id=456 in 'logs_db', conn to 'mysql.php'" "count rows where date>'2024-01-01' in 'analytics_db', conn to 'mysql.php'" ``` ### Fichiers ``` "get value from key 'total_sales' in 'report.json', conn to 'file.php'" "add line 'new,data,row' to 'export.csv', conn to 'file.php'" "search text 'error' in 'logs.txt', conn to 'file.php'" "update key 'status' with 'completed' in 'config.json', conn to 'file.php'" ``` ### APIs externes ``` "get product_info where sku='ABC123' in 'inventory_api', conn to 'api.php'" "send data '{\"name\":\"John\"}' to endpoint 'users' in 'crm_api', conn to 'api.php'" "search user 'john@doe.com' in 'crm_api', conn to 'api.php'" "update users id=123 with '{\"status\":\"active\"}' in 'api_service', conn to 'api.php'" ``` ## Format de réponse ```json { "status": "success", "data": "résultat ou données", "message": "Query executed successfully", "execution_time": "15.2ms", "parsed_query": { "action": "get", "params": "all users where status='active'", "resource": "database_users", "connector": "mysql.php" } } ``` ## Création d'un nouveau connector Pour ajouter un nouveau type de source, créer `connectors/nouveau.php` : ```php <?php class NouveauConnector { public function get($params, $resource) { // Logique pour récupérer des données } public function add($params, $resource) { // Logique pour ajouter des données } // Autres méthodes... } ``` Puis utiliser : `conn to 'nouveau.php'` ## Sécurité - Valider toutes les entrées utilisateur - Configurer les accès aux bases de données avec des utilisateurs limités - Utiliser HTTPS pour les APIs - Implémenter une authentification pour l'API Can en productionPK �0�[ V� cli.phpnu �[��� PK �0�[�G/ / P core/response.phpnu �[��� PK �0�[���{ � core/router.phpnu �[��� PK �0�[L��/ / core/parser.phpnu �[��� PK �0�[���I I w api.phpnu �[��� PK �0�[��E � connectors/file.phpnu �[��� PK �0�[���3z z S/ connectors/mysql.phpnu �[��� PK �0�[��� � C connectors/api.phpnu �[��� PK �0�[�N� \ connectors/files/cart.csvnu �[��� PK �0�[��T� � t\ README.mdnu �[��� PK ny
| ver. 1.6 |
Github
|
.
| PHP 8.1.33 | Генерация страницы: 0 |
proxy
|
phpinfo
|
Настройка