<?php

/**
 * @file    index.php
 * @brief   OpenGnsys REST API: common functions and routes
 * @warning All input and output messages are formatted in JSON.
 * @note    Some ideas are based on article "How to create REST API for Android app using PHP, Slim and MySQL" by Ravi Tamada, thanx.
 * @license GNU GPLv3+
 * @author  Ramón M. Gómez, ETSII Univ. Sevilla
 * @version 1.1.0 - First version
 * @date    2016-11-17
 */


// Common constants.
define('REST_LOGFILE', '/opt/opengnsys/log/rest.log');
define('VERSION_FILE', '/opt/opengnsys/doc/VERSION.json');

// Set time zone.
if (function_exists("date_default_timezone_set")) {
    if (exec("timedatectl status | awk '/Time zone/ {print $3}'", $out, $err)) {
        date_default_timezone_set($out[0]);
    }
}

// Common functions.

/**
 * @brief   Function to write a line into log file.
 * @param   string message  Message to log.
 * warning  Line format: "Date: ClientIP: UserId: Status: Method Route: Message"
 */
function writeRestLog($message = "")
{
    global $userid;
    if (is_writable(REST_LOGFILE)) {
        $app = \Slim\Slim::getInstance();
        file_put_contents(
            REST_LOGFILE,
            date(DATE_ISO8601) . ": " .
                $_SERVER['REMOTE_ADDR'] . ": " .
                (isset($userid) ? $userid : "-") . ": " .
                $app->response->getStatus() . ": " .
                $app->request->getMethod() . " " .
                $app->request->getPathInfo() . ": $message\n",
            FILE_APPEND
        );
    }
}

/**
 * @brief   Compose JSON response.
 * @param   int status      Status code for HTTP response.
 * @param   array response  Response data.
 * @param   int opts        Options to encode JSON data.
 * @return  string          JSON response.
 */
function jsonResponse($status, $response, $opts = 0)
{
    $app = \Slim\Slim::getInstance();
    // HTTP status code.
    $app->status($status);
    // Content-type HTTP header.
    $app->contentType('application/json; charset=utf-8');
    // JSON response.
    echo json_encode($response, $opts);
}

/**
 * @brief   Print immediately JSON response to continue processing.
 * @param   int status      Status code for HTTP response.
 * @param   array response  Response data.
 * @param   int opts        Options to encode JSON data.
 * @return  string          JSON response.
 */
function jsonResponseNow($status, $response, $opts = 0)
{
    // Compose headers and content.
    ignore_user_abort();
    http_response_code((int)$status);
    header('Content-type: application/json; charset=utf-8');
    ob_start();
    echo json_encode($response, $opts);
    $size = ob_get_length();
    header("Content-Length: $size");
    // Print content.
    ob_end_flush();
    flush();
    session_write_close();
}

/**
 * @brief    Validate API key included in "Authorization" HTTP header.
 * @return   string  JSON response on error.
 */
function validateApiKey()
{
    global $cmd;
    global $userid;
    $response = [];
    $app = \Slim\Slim::getInstance();
    // Read Authorization HTTP header.
    if (!empty($_SERVER['HTTP_AUTHORIZATION'])) {
        // Assign user id. that match this key to global variable.
        $apikey = htmlspecialchars($_SERVER['HTTP_AUTHORIZATION']);
        $cmd->texto = "SELECT idusuario
				 FROM usuarios
				WHERE apikey='$apikey' LIMIT 1";
        $rs = new Recordset;
        $rs->Comando = &$cmd;
        if ($rs->Abrir()) {
            $rs->Primero();
            if (!$rs->EOF) {
                // Fetch user id.
                $userid = $rs->campos["idusuario"];
            } else {
                // Credentials error.
                $response['message'] = 'Login failed, incorrect credentials';
                jsonResponse(401, $response);
                $app->stop();
            }
            $rs->Cerrar();
        } else {
            // Database error.
            $response['message'] = "An error occurred, please try again";
            jsonResponse(500, $response);
        }
    } else {
        // Error: missing API key.
        $response['message'] = 'Missing API key';
        jsonResponse(400, $response);
        $app->stop();
    }
}

/**
 * @brief    Check if parameter is set and print error messages if empty.
 * @param    string param    Parameter to check.
 * @return   boolean         "false" if parameter is null, otherwise "true".
 */
function checkParameter($param)
{
    $response = [];
    if (isset($param)) {
        return true;
    } else {
        // Print error message.
        $response['message'] = 'Parameter not found';
        jsonResponse(400, $response);
        return false;
    }
}

/**
 * @brief    Check if all parameters are positive integer numbers.
 * @param    int id ...      Identificators to check (variable number of parameters).
 * @return   boolean         "true" if all ids are int>0, otherwise "false".
 */
function checkIds()
{
    $opts = ['options' => ['min_range' => 1]];    // Check for int>0
    foreach (func_get_args() as $id) {
        if (filter_var($id, FILTER_VALIDATE_INT, $opts) === false) {
            return false;
        }
    }
    return true;
}

/**
 * @brief   Show custom message for "not found" error (404).
 */
$app->notFound(
    function () {
        $response['message'] = 'REST route not found';
        jsonResponse(404, $response);
    }
);

/**
 * @brief   Hook to write an error log message and a REST exit log message if debug is enabled.
 * @warning Error message will be written in web server's error file.
 * @warning REST message will be written in REST log file.
 */
$app->hook(
    'slim.after',
    function () use ($app) {
        $max_body_len_to_log = 150;
        if ($app->response->getStatus() != 200) {
            // Compose error message (truncating long lines). 
            $app->log->error(date(DATE_ISO8601) . ': ' .
                $app->getName() . ': ' .
                $_SERVER['REMOTE_ADDR'] . ": " .
                (isset($userid) ? $userid : "-") . ": " .
                $app->response->getStatus() . ': ' .
                $app->request->getMethod() . ' ' .
                $app->request->getPathInfo() . ': ' .
                substr($app->response->getBody(), 0, 100));
        }
        if ($app->settings['debug']) {
            $body = $app->response->getBody();
            if (strlen($body) > $max_body_len_to_log) {
                $body = substr($body, 0, $max_body_len_to_log) . '... (output has been truncated)';
            }
            writeRestLog($body);
        }
    }
);


// Common routes.

/**
 * @brief    Get general server information 
 * @note     Route: /info, Method: GET
 * @return   string  JSON object with basic server information (version, services, etc.)
 */
$app->get(
    '/info',
    function () {
        $hasOglive = false;
        $response = new \stdClass;
        // Reading version file.
        $data = json_decode(@file_get_contents(VERSION_FILE));
        if (isset($data->project)) {
            $response = $data;
        } else {
            $response->project = 'OpenGnsys';
        }
        // Getting actived services.
        @$services = parse_ini_file('/etc/default/opengnsys');
        $response->services = [];
        if (@$services["RUN_OGADMSERVER"] === "yes") {
            array_push($response->services, "server");
            $hasOglive = true;
        }
        if (@$services["RUN_OGADMREPO"] === "yes")  array_push($response->services, "repository");
        if (@$services["RUN_BTTRACKER"] === "yes")  array_push($response->services, "tracker");
        // Reading installed ogLive information file.
        if ($hasOglive === true) {
            $data = json_decode(@file_get_contents('/opt/opengnsys/etc/ogliveinfo.json'));
            if (isset($data->oglive)) {
                $response->oglive = $data->oglive;
            }
        }
        jsonResponse(200, $response);
    }
);


function backupConfig()
{
    $get_command = 'config-get';
    $get_output = executeCurlCommand($get_command);
    if ($get_output == false || $get_output[0]["result"] != 0) {
        throw new Exception('Error al obtener la configuración actual de Kea DHCP');
    }
    $config_text = json_encode($get_output[0]['arguments']);
    $configurationParsed = str_replace('\\', '', $config_text);

    $backup_dir = '/opt/opengnsys/etc/kea/backup';
    if (!is_dir($backup_dir)) {
        throw new Exception('El directorio de backup no existe');
    }
    if (!is_writable($backup_dir)) {
        throw new Exception('El directorio de backup no tiene permisos de escritura');
    }
    $backup_files = glob($backup_dir . '/*.conf');
    if (count($backup_files) >= 10) {
        usort($backup_files, function ($a, $b) {
            return filemtime($a) - filemtime($b);
        });
        unlink($backup_files[0]);
    }
    $backup_file = $backup_dir . '/' . date('Y-m-d_H-i-s') . '.conf';
    if (!file_put_contents($backup_file, $configurationParsed)) {
        throw new Exception('Error al guardar la configuración de backup');
    }
}

function executeCurlCommand($command, $arguments = null, $create_backup = true)
{
    $apiUrl = getenv('DHCP_IP');
    if (!$apiUrl) {
        $apiUrl = 'http://localhost:8000/';
    }

    if ($command == 'config-get' || $command == 'config-write') {
        $requestData = array(
            'command' => $command,
            'service' => array('dhcp4'),
        );
    } elseif ($command == 'config-set' || $command == 'config-test') {
        $requestData = array(
            'command' => $command,
            'service' => array('dhcp4'),
            'arguments' => $arguments,
        );
    } else {
        return "Error: Comando no válido";
    }
    if (($command == 'config-set' || $command == 'config-write') && $create_backup) {
        backupConfig();
    }
    $jsonData = json_encode($requestData);
    try {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $apiUrl);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Expect:'));
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);
        curl_setopt($ch, CURLOPT_POST, true);
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $output = json_decode($response, true);

        if ($httpCode >= 200 && $httpCode < 300) {

            return $output;
        } else {
            $error = curl_error($ch);
            throw new Exception($error);
            //return false;
        }
    } catch (Exception $e) {
        throw new Exception($e->getMessage());
    }
}


/**
 * @brief    Get configuration of kea dhcp server 
 * @note     Route: /dhcp, Method: GET
 * @return   string  JSON object with all kea configuration
 */
$app->get('/dhcp', function () {
    try {
        $response = executeCurlCommand('config-get');

        if (!$response) {
            $responseError = 'Error: No se pudo acceder al archivo dhcpd.conf';
            jsonResponse(400, $responseError);
        } else {
            $result_code = $response[0]["result"];
            if ($result_code == 0) {
                $arrayDhcp4 = $response[0]['arguments'];
                jsonResponse(200, $arrayDhcp4, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
            } else {
                $responseError =  "Error kea configuration invalid: " . $response[0]["text"];
                jsonResponse(400, $responseError);
            }
        }
    } catch (Exception $e) {
        $responseError =  "Error al obtener la configuración de Kea DHCP: " . $e->getMessage();
        jsonResponse(400, $responseError);
    }
});

/**
 * @brief    Get hosts from kea configuration
 * @note     Route: /dhcp/hosts, Method: GET
 * @return   string  JSON object with all hosts in kea configuration
 */

$app->get('/dhcp/hosts', function () {
    try {
        $response = executeCurlCommand('config-get');

        if (!$response) {
            $responseError = 'Error: No se pudo acceder al archivo dhcpd.conf';
            jsonResponse(400, $response);
        } else {
            $result_code = $response[0]["result"];
            if ($result_code == 0) {
                if (!isset($response[0]['arguments']['Dhcp4']['reservations'])) {
                    $responseError = 'El campo \'reservations\' no está inicializado';
                    jsonResponse(400, $responseError);
                } else {
                    $arrayReservations = $response[0]['arguments']['Dhcp4']['reservations'];
                    jsonResponse(200, $arrayReservations, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
                }
            } else {
                $responseError =  "Error kea configuration invalid: " . $response[0]["text"];
                jsonResponse(400, $responseError);
            }
        }
    } catch (Exception $e) {
        $responseError =  "Error al obtener la configuración de Kea DHCP: " . $e->getMessage();
        jsonResponse(400, $responseError);
    }
});

/**
 * @brief    Update kea configuration
 * @note     Route: /dhcp/save, Method: POST
 * @param    string configurationText 
 * @return   string  JSON object with all hosts in kea configuration
 */

$app->post('/dhcp/save', function () use ($app) {
    try {
        $input = json_decode($app->request()->getBody());
        $configurationText = htmlspecialchars($input->configurationText);
    } catch (Exception $e) {
        $response["message"] = $e->getMessage();
        jsonResponse(400, $response);
        $app->stop();
    }

    $configurationParsed = str_replace(' ', '', $configurationText);
    $configurationParsed = str_replace("\n", '', $configurationParsed);
    $configurationParsed = str_replace('&quot;', '"', $configurationParsed);
    $configuration = json_decode($configurationParsed);

    if ($configuration === null || json_last_error() !== JSON_ERROR_NONE) {
        $responseError = "Error: El texto proporcionado no es un JSON válido.";
        jsonResponse(400, $responseError);
    } else {
        try {
            $responseTest = executeCurlCommand('config-test', $configuration);
            if ($responseTest[0]["result"] == 0) {
                $responseSet = executeCurlCommand('config-set', $configuration);
                if ($responseSet == false || $responseSet[0]["result"] != 0) {
                    $responseError =  "Error al guardar la configuración en Kea DHCP: " . $responseSet[0]["text"];
                    jsonResponse(400, $responseError);
                } else {
                    $responseSuccess =  "Configuración cargada correctamente";
                    jsonResponse(200, $responseSuccess);
                }
            } else {
                $responseError =  "Error al guardar la configuración en Kea DHCP: " . $responseTest[0]["text"];
                jsonResponse(400, $responseError);
            }
        } catch (Exception $e) {
            $responseError =  "Error al obtener la configuración de Kea DHCP: " . $e->getMessage();
            jsonResponse(400, $responseError);
        }
    }
});


$app->post(
    '/dhcp/add',
    function () use ($app) {
        try {
            $input = json_decode($app->request()->getBody());
            $host = htmlspecialchars($input->host);
            $macAddress = htmlspecialchars($input->macAddress);
            $address = htmlspecialchars($input->address);
            $nextServer = htmlspecialchars($input->nextServer);
        } catch (Exception $e) {
            $response["message"] = $e->getMessage();
            jsonResponse(400, $response);
            $app->stop();
        }
        try {
            $response = executeCurlCommand('config-get');
            $nuevoHost = [
                "hostname" => $host,
                "hw-address" => $macAddress,
                "ip-address" => $address,
                "next-server" => $nextServer
            ];
            //En caso de que no esté declarado el array de reservations, lo inicializamos
            if (!isset($response[0]['arguments']['Dhcp4']['reservations'])) {
                $response[0]['arguments']['Dhcp4']['reservations'] = [];
            }
            $existe = False;
            $existe = array_reduce($response[0]['arguments']['Dhcp4']['reservations'], function ($existe, $reserva) use ($host) {
                return $existe || ($reserva['hostname'] === $host);
            });

            if ($existe) {
                $response =  "Error: El host con el hostname '$host' ya existe en las reservaciones.";
                jsonResponse(400, $response);
            } else {
                $response[0]['arguments']['Dhcp4']['reservations'][] = $nuevoHost;
                $array_encoded = json_encode($response[0]['arguments']);
                $configurationParsed = str_replace('\\', '', $array_encoded);
                $configuration = json_decode($configurationParsed);
                $responseTest = executeCurlCommand('config-test', $configuration);

                if ($responseTest[0]["result"] == 0) {
                    $responseSet = executeCurlCommand('config-set', $configuration);
                    if ($responseSet == false || $responseSet[0]["result"] != 0) {
                        $responseError =  "Error al guardar la configuración en Kea DHCP: " . $responseSet[0]["text"];
                        jsonResponse(400, $responseError);
                    } else {
                        $responseSuccess =  "Configuración cargada correctamente";
                        jsonResponse(200, $responseSuccess);
                    }
                } else {
                    $responseError =  "Error kea configuration invalid: " . $responseTest[0]["text"];
                    jsonResponse(400, $responseError);
                }
            }
        } catch (Exception $e) {
            $responseError =  "Error al obtener la configuración de Kea DHCP: " . $e->getMessage();
            jsonResponse(400, $responseError);
        }
    }
);


$app->post(
    '/dhcp/delete',
    function () use ($app) {
        try {
            $input = json_decode($app->request()->getBody());
            $host = htmlspecialchars($input->host);
        } catch (Exception $e) {
            $response["message"] = $e->getMessage();
            jsonResponse(400, $response);
            $app->stop();
        }
        try {
            $response = executeCurlCommand('config-get');
            $existe = False;

            if (isset($response[0]['arguments']['Dhcp4']['reservations'])) {
                foreach ($response[0]['arguments']['Dhcp4']['reservations'] as $key => $reservation) {
                    if (isset($reservation['hostname']) && $reservation['hostname'] === $host) {
                        unset($response[0]['arguments']['Dhcp4']['reservations'][$key]);
                        $existe = True;
                        $response[0]['arguments']['Dhcp4']['reservations'] = array_values($response[0]['arguments']['Dhcp4']['reservations']);
                        break;
                    }
                }
                if ($existe) {
                    $array_encoded = json_encode($response[0]['arguments']);
                    $configurationParsed = str_replace('\\', '', $array_encoded);
                    $configuration = json_decode($configurationParsed);

                    $responseTest = executeCurlCommand('config-test', $configuration);
                    if ($response[0]["result"] == 0) {
                        $responseSet = executeCurlCommand('config-set', $configuration);
                        if ($responseSet == false || $responseSet[0]["result"] != 0) {
                            $responseError =  "Error al guardar la configuración en Kea DHCP: " . $responseSet[0]["text"];
                            jsonResponse(400, $responseError);
                        } else {
                            $responseSuccess =  "Configuración cargada correctamente";
                            jsonResponse(200, $responseSuccess);
                        }
                    } else {
                        $responseError =  "Error al guardar la configuración en Kea DHCP: " . $responseTest[0]["text"];
                        jsonResponse(400, $responseError);
                    }
                } else {
                    $responseError =  "Error: El host con el hostname '$host' no existe en las reservaciones.";
                    jsonResponse(400, $responseError);
                }
            } else {
                $responseError =  'El campo \'reservations\' no está inicializado';
                jsonResponse(400, $responseError);
            }
        } catch (Exception $e) {
            $responseError =  "Error al obtener la configuración de Kea DHCP: " . $e->getMessage();
            jsonResponse(400, $responseError);
        }
    }
);

$app->post(
    '/dhcp/update',
    function () use ($app) {
        try {
            $input = json_decode($app->request()->getBody());
            $host = htmlspecialchars($input->host);
            $oldMacAddress = htmlspecialchars($input->oldMacAddress);
            $oldAddress = htmlspecialchars($input->oldAddress);
            $macAddress = htmlspecialchars($input->macAddress);
            $address = htmlspecialchars($input->address);
            $nextServer = htmlspecialchars($input->nextServer);
        } catch (Exception $e) {
            $response["message"] = $e->getMessage();
            jsonResponse(400, $response);
            $app->stop();
        }
        try {
            $response = executeCurlCommand('config-get');
            $existe = False;
            if (isset($response[0]['arguments']['Dhcp4']['reservations'])) {
                foreach ($response[0]['arguments']['Dhcp4']['reservations'] as &$reservation) {
                    if ($reservation['hw-address'] == $oldMacAddress && $reservation['ip-address'] == $oldAddress) {
                        $existe = True;
                        $reservation['hw-address'] = $macAddress;
                        $reservation['ip-address'] = $address;
                        $reservation['hostname'] = $host;
                        $reservation['next-server'] = $nextServer;

                        $array_encoded = json_encode($response[0]['arguments']);
                        $configurationParsed = str_replace('\\', '', $array_encoded);
                        $configuration = json_decode($configurationParsed);
                        $responseTest = executeCurlCommand('config-test', $configuration);

                        if ($responseTest[0]["result"] == 0) {
                            $responseSet = executeCurlCommand('config-set', $configuration);
                            if ($responseSet == false && $responseSet[0]["result"] != 0) {
                                $responseError =  "Error al guardar la configuración en Kea DHCP: " . $responseSet[0]["text"];
                                jsonResponse(400, $responseError);
                            } else {
                                $responseSuccess =  "Configuración cargada correctamente";
                                jsonResponse(200, $responseSuccess);
                            }
                        } else {
                            $responseError =  "Error al guardar la configuración en Kea DHCP: " . $responseTest[0]["text"];
                            jsonResponse(400, $responseError);
                        }
                    }
                }
                if (!$existe) {
                    $responseError =  "Error: La IP " . $oldAddress . " y la MAC " . $oldMacAddress . " no existe en las reservaciones.";

                    jsonResponse(400, $responseError);
                }
            } else {
                $responseError =  'El campo \'reservations\' no está inicializado';
                jsonResponse(400, $responseError);
            }
        } catch (Exception $e) {
            $responseError =  "Error al obtener la configuración de Kea DHCP: " . $e->getMessage();
            jsonResponse(400, $responseError);
        }
    }
);

$app->post(
    '/dhcp/apply',
    function () use ($app) {
        try {
            $response = executeCurlCommand('config-write');
            if ($response[0]["result"] == 0) {
                jsonResponse(200, $response);
            } else {
                $responseError =  "Error al escribir la configuración en Kea DHCP: " . $response[0]["text"];
                jsonResponse(400, $responseError);
            }
        } catch (Exception $e) {
            $responseError =  "Error al escribir la configuración en Kea DHCP: " . $e->getMessage();
            jsonResponse(400, $responseError);
        }
    }
);



/**
 * @brief    Restore kea configuration.
 * @note     Route: /dhcp/backup, Method: POST
 * @return   string            Result of operation.
 * @note     All modifications in kea configuration is stored"/opt/opengnsys/etc/kea/backup" directory.
 */

$app->post('/dhcp/backup', function () use ($app) {
    $backup_dir = '/opt/opengnsys/etc/kea/backup';
    try {
        $backup_files = glob($backup_dir . '/*.conf');
        if (empty($backup_files)) {
            $response =  "No se encontraron archivos de backup";
            jsonResponse(400, $response);
        } else {
            usort($backup_files, function ($a, $b) {
                return filemtime($b) - filemtime($a);
            });
            $backup_file = reset($backup_files);
            $config = file_get_contents($backup_file);
            $configuration = json_decode($config);

            $test_command = 'config-test';
            $test_output = executeCurlCommand($test_command, $configuration);
            if ($test_output == false || $test_output[0]["result"] != 0) {
                $responseError =  "Error al comprobar la configuración de Kea: " . $test_output[0]["text"];
                jsonResponse(400, $responseError);
            } else {
                $set_command = 'config-set';
                $set_output = executeCurlCommand($set_command, $configuration, false);
                if ($set_output == false || $set_output[0]["result"] != 0) {
                    $responseError =  "Error al guardar la última configuración de Kea: " . $set_output[0]["text"];
                    jsonResponse(400, $responseError);
                } else {
                    unlink($backup_file);
                    $responseSuccess =  "última configuración cargada correctamente";
                    jsonResponse(200, $responseSuccess);
                }
            }
        }
    } catch (Exception $e) {
        $responseError =  "Error al restaurar la configuración: " . $e->getMessage();
        jsonResponse(400, $responseError);
    }
});



/**
 * @brief    Upload kea configuration file.
 * @note     Route: /dhcp/upload, Method: POST
 * @param    File file.
 * @return   string            Route of stored file.
 */

$app->post('/dhcp/upload', function () use ($app) {
    if (!isset($_FILES['file_input_name'])) {
        $responseError =  "No se ha subido ningún archivo";
        jsonResponse(400, $responseError);
        return;
    }

    $file_path = $_FILES['file_input_name']['tmp_name'];
    $json_data = file_get_contents($file_path);
    $config_data = json_decode($json_data, true);
    if (json_last_error() !== JSON_ERROR_NONE) {
        $responseError =  "El archivo JSON subido no está correctamente escrito";
        jsonResponse(400, $responseError);
    }
    try {
        $test_command = 'config-test';
        $test_output = executeCurlCommand($test_command, $config_data);
        if ($test_output == false || $test_output[0]["result"] != 0) {
            $responseError =  "La configuración no es válida";
            jsonResponse(400, $responseError);
        } else {
            $set_command = 'config-set';
            $set_output = executeCurlCommand($set_command, $config_data);
            if ($test_output == false || $test_output[0]["result"] != 0) {
                $responseError =  "Error al guardar la configuración en Kea DHCP";
                jsonResponse(400, $responseError);
                http_response_code(400);
            } else {
                $responseSuccess =  "Configuración cargada correctamente en el fichero: " . $file_path;;
                jsonResponse(200, $responseSuccess);
                http_response_code(200);
            }
        }
    } catch (Exception $e) {
        $responseError =  "Error al obtener la configuración de Kea DHCP: " . $e->getMessage();
        jsonResponse(400, $responseError);
    }
});




/**
 * @brief    Get the server status
 * @note     Route: /status, Method: GET
 * @return   string  JSON object with all data collected from server status (RAM, %CPU, etc.).
 */
$app->get(
    '/status',
    function () {
        $response = [];
        // Getting memory and CPU information.
        exec("awk '$1~/Mem/ {print $2}' /proc/meminfo", $memInfo);
        $memInfo = array("total" => $memInfo[0], "used" => $memInfo[1]);
        $cpuInfo = exec("awk '$1==\"cpu\" {printf \"%.2f\",($2+$4)*100/($2+$4+$5)}' /proc/stat");
        $cpuModel = exec("awk -F: '$1~/model name/ {print $2}' /proc/cpuinfo");
        $response["memInfo"] = $memInfo;
        $response["cpu"] = array("model" => trim($cpuModel), "usage" => $cpuInfo);
        jsonResponse(200, $response);
    }
);
