source: admin/WebConsole/rest/server.php @ f838845

918-git-images-111dconfigure-oglivegit-imageslgromero-new-oglivemainmaint-cronmount-efivarfsmultivmmultivm-ogboot-installerogClonningEngineogboot-installer-jenkinsoglive-ipv6test-python-scriptsticket-301ticket-50ticket-50-oldticket-577ticket-585ticket-611ticket-612ticket-693ticket-700ubu24tplunification2use-local-agent-oglivevarios-instalacion
Last change on this file since f838845 was 16491c9, checked in by Ramón M. Gómez <ramongomez@…>, 5 years ago

#839 #915: Fix bug in route GET /ous/:ouid/labs/:labid/clients/:clntid/status when a client has never connected to the server.

  • Property mode set to 100644
File size: 31.4 KB
RevLine 
[fb2ee20]1<?php
2/**
3 * @file    index.php
[3551804]4 * @brief   OpenGnsys Server REST API manager.
[fb2ee20]5 * @warning All input and output messages are formatted in JSON.
6 * @note    Some ideas are based on article "How to create REST API for Android app using PHP, Slim and MySQL" by Ravi Tamada, thanx.
7 * @license GNU GPLv3+
8 * @author  Ramón M. Gómez, ETSII Univ. Sevilla
[3551804]9 * @version 1.1.0 - First version
[ac8b234e]10 * @date    2016-09-19
[fb2ee20]11 */
12
13
14// Auxiliar functions.
15
16/**
17 * @brief    Check if user is administrator and print error messages if not.
[43f3bde]18 * @param    int adminid  Administrator id.
19 * @return   boolean      "true" if admin id. is equals to global user id., otherwise "false".
[fb2ee20]20 */
21function checkAdmin($adminid) {
22        global $userid;
23
24        if ($adminid == $userid) {
25                return true;
26        } else {
27                // Print error message.
28                $response['message'] = 'Cannot access this resource';
29                jsonResponse(401, $response);
30                return false;
31        }
32}
33
[606a0c7]34/**
35 * @fn    addClassroomGroup(&$classroomGroups, $rs)
36 * @brief Funcion privada usada para añadir grupos de aulas recursivamente
37 * @param classroomGroups Grupos de aulas que pueden contener más grupos
38 * @param rs resultset de la consulta a la base de datos.
39 */
40function addClassroomGroup(&$classroomGroups, $rs){
41
42        array_walk($classroomGroups, function(&$group,$key){
43                global $rs;
44                if (isset($group['id']) && $group['id'] === $rs->campos["group_group_id"]) {
45                        array_push($group["classroomGroups"],array("id" => $rs->campos["group_id"],
46                                "name" => $rs->campos["nombregrupoordenador"],
47                                "comments" => $rs->campos["comentarios"],
48                                "classroomGroups" => array()));
49                }
50                else if(count($group["classroomGroups"]) > 0){
51                        addClassroomGroup($group["classroomGroups"], $rs);
52                }
53                /**/
54        });
55}
[fb2ee20]56
[2a337db]57/**
58 * @fn    getStatus(ouid, labid, [clntid])
59 * @brief    Returns client execution status or status of all lab's clients.
[43f3bde]60 * @param    int ouid    OU id.
61 * @param    int labid   Lab. id.
62 * @param    int clntid  Client id. (optional)
63 * @return   string      JSON object or array of objects including status data.
[2a337db]64 */
65function getStatus($ouid, $labid, $clntid=0) {
66        global $userid;
67        global $cmd;
68        global $LONCABECERA;
69        global $LONHEXPRM;
[16491c9]70        $app = \Slim\Slim::getInstance();
[43f3bde]71        $response = [];
72        $id = [];
73        $stat = [];
74        $ip = "";
[16491c9]75        $urls = [];
[2a337db]76        // Status mapping.
[16491c9]77        $status = ['OFF'=>"off",
78                   'INI'=>"initializing",
79                   'OPG'=>"oglive",
80                   'BSY'=>"busy",
81                   'LNX'=>"linux",
82                   'OSX'=>"macos",
83                   'WIN'=>"windows",
84                   'UNK'=>"unknown"];
[2a337db]85        // Parameters.
86        $ouid = htmlspecialchars($ouid);
87        $labid = htmlspecialchars($labid);
88        $single = is_numeric(explode("/", $app->request->getResourceUri())[6]);
89
90        // Database query.
91        $cmd->texto = <<<EOD
[dbb1b6c]92SELECT adm.idusuario, aulas.idaula, ordenadores.idordenador, ordenadores.ip
93  FROM ordenadores
[2a337db]94  JOIN aulas USING(idaula)
95 RIGHT JOIN administradores_centros AS adm USING(idcentro)
[9199fc7]96 WHERE adm.idusuario = '$userid'
[2a337db]97   AND adm.idcentro='$ouid'
98   AND aulas.idaula='$labid'
99EOD;
100        // Request for a single client.
101        if ($single) {
102                $clntid = htmlspecialchars($clntid);
103                $cmd->texto .= <<<EOD
104   AND ordenadores.idordenador='$clntid';
105EOD;
106        }
107        $rs=new Recordset;
108        $rs->Comando=&$cmd;
109        if (!$rs->Abrir()) return(false);       // Error oppening recordset.
110        $rs->Primero();
111        // Check if user is an UO admin and asset exists.
[9199fc7]112        if (checkAdmin($rs->campos["idusuario"]) and (($single and checkParameter($rs->campos["idordenador"])) or (! $single and checkParameter($rs->campos["idaula"])))) {
[2a337db]113                while (!$rs->EOF) {
114                        $id[$rs->campos["ip"]] = $rs->campos["idordenador"];
115                        $stat[$rs->campos["ip"]] = $status['OFF'];
116                        $rs->Siguiente();
117                }
[dbb1b6c]118                // Get client status.
[2a337db]119                $clientid = implode(",", $id);
120                $clientip = implode(";", array_keys($id));
[dbb1b6c]121                $result = clients(2, $clientip);
[16491c9]122                // Check status type.
123                if (checkParameter($result)) {
124                        foreach (explode(";", $result) as $data) {
125                                if (!empty($data)) {
126                                        list($clip, $clst) = explode("/", $data);
127                                        if ($clst != "OFF") {
128                                                // Update current status.
129                                                $stat[$clip] = $status[$clst];
[2a337db]130                                        }
131                                }
132                        }
[16491c9]133                }
134                // Prepare request to new OGAgent for OSes.
135                foreach ($stat as $ip => $st) {
136                        if ($st == "off") {
137                                $urls[$ip] = "https://$ip:8000/opengnsys/status";
[2a337db]138                        }
[16491c9]139                }
140                // Send request to OGAgents.
141                if (isset($urls)) {
142                        $result = multiRequest($urls);
143                }
144                // Parse responses.
145                reset($urls);
146                foreach ($result as $res) {
147                        if (!empty($res['data'])) {
148                                // Get status and session data.
149                                $ip = key($urls);
150                                $data = json_decode($res['data']);
151                                if (@isset($status[$data->status])) {
152                                        $stat[$ip] = $status[$data->status];
153                                        $logged[$ip] = $data->loggedin;
154                                } else {
155                                        $stat[$ip] = $status['UNK'];
[2a337db]156                                }
157                        }
[16491c9]158                        unset($urls[$ip]);
159                }
160                // Compose JSON response.
161                if ($single) {
162                        // Single response.
163                        $response['id'] = (int)reset($id);
164                        $response['ip'] = key($id);
165                        $response['status'] = $stat[key($id)];
166                        empty($logged[$ip]) || $response['loggedin'] = $logged[$ip];
[2a337db]167                } else {
[16491c9]168                        // Multiple responses.
169                        foreach ($stat as $ip => $st) {
170                                $tmp = Array();
171                                $tmp['id'] = (int)$id[$ip];
172                                $tmp['ip'] = $ip;
173                                $tmp['status'] = $stat[$ip];
174                                empty($logged[$ip]) || $tmp['loggedin'] = $logged[$ip];
175                                array_push($response, $tmp);
176                        }
[2a337db]177                }
[16491c9]178                jsonResponse(200, $response);
[2a337db]179        }
180        $rs->Cerrar();
181}
182
[fb2ee20]183
[3551804]184// REST routes.
[fb2ee20]185
186/**
187 * @brief    user login.
188 * @note     Route: /login, Method: POST
189 * @param    string username   User name.
190 * @param    string password   User password.
191 * @return   string            JSON response with user id. and API key.
192 * @note     User's API key is stored in a new field of "usuarios" table.
193 */
194$app->post('/login',
195    function() use ($app) {
196        global $cmd;
197        global $userid;
198
[5ff84a5]199        $response = Array();
[fb2ee20]200        // Reading JSON parameters.
201        try {
202                $input = json_decode($app->request()->getBody());
203                $user = htmlspecialchars($input->username);
204                $pass = htmlspecialchars($input->password);
205        } catch (Exception $e) {
[29bc749]206                // Error message.
[fb2ee20]207                $response["message"] = $e->getMessage();
208                jsonResponse(400, $response);
209                $app->stop();
210        }
211
[3551804]212        // Checking parameters.
[fb2ee20]213        if (! empty($user) and ! empty($pass)) {
214                // Database query.
215                $cmd->texto = "SELECT idusuario, apikey
216                                 FROM usuarios
[7441e57]217                                WHERE usuario='$user' AND pasguor=SHA2('$pass',224)";
[fb2ee20]218                $rs=new Recordset;
219                $rs->Comando=&$cmd;
220                if ($rs->Abrir()) {
221                        $rs->Primero();
222                        if (!$rs->EOF){
223                                // JSON response.
224                                $userid=$rs->campos["idusuario"];
225                                $apikey=$rs->campos["apikey"];
226                                $response['userid'] = $userid;
227                                $response['apikey'] = $apikey;
228                                jsonResponse(200, $response);
229                        } else {
230                                // Credentials error.
231                                $response['message'] = 'Login failed. Incorrect credentials';
232                                jsonResponse(401, $response);
233                                $app->stop();
234                        }
235                        $rs->Cerrar();
236                } else {
237                        // Access error.
238                        $response['message'] = "An error occurred. Please try again";
239                        jsonResponse(500, $response);
240                        $app->stop();
241                }
242        } else {
243                # Error: missing some input parameter.
244                $response['message'] = 'Missing username or password';
245                jsonResponse(400, $response);
246                $app->stop();
247        }
248    }
249);
250
251/**
252 * @brief    List all defined Organizational Units
253 * @note     Route: /ous, Method: GET
[43f3bde]254 * @return   string  JSON array with id. and name for every defined OU
[fb2ee20]255 */
[18391d1]256$app->get('/ous(/)', function() {
[fb2ee20]257        global $cmd;
258
259        $cmd->texto = "SELECT * FROM centros";
260        $rs=new Recordset;
261        $rs->Comando=&$cmd;
[2aa8687]262        if (!$rs->Abrir()) return(false);       // Error oppening recordset.
[5ff84a5]263        $response = Array();
[fb2ee20]264        $rs->Primero();
265        while (!$rs->EOF) {
[5ff84a5]266                $tmp = Array();
[ffaf580]267                $tmp['id'] = (int)$rs->campos["idcentro"];
[1485b99]268                $tmp['name'] = $rs->campos["nombrecentro"];
[4a511f81]269                array_push($response, $tmp);
[fb2ee20]270                $rs->Siguiente();
271        }
272        $rs->Cerrar();
273        jsonResponse(200, $response);
[3551804]274   }
[fb2ee20]275);
276
277/**
278 * @brief    Get Organizational Unit data
[43f3bde]279 * @note     Route: /ous/:ouid, Method: GET
280 * @param    int ouid  OU id.
281 * @return   string    JSON string with OU's parameters
[fb2ee20]282 */
[18391d1]283$app->get('/ous/:ouid(/)', 'validateApiKey',
[fb2ee20]284    function($ouid) {
285        global $cmd;
[18391d1]286        global $userid;
[fb2ee20]287
288        $ouid = htmlspecialchars($ouid);
[18391d1]289        // Show OU information if user is OU's admin.
290        $cmd->texto = <<<EOD
291SELECT *
292  FROM centros
293 RIGHT JOIN administradores_centros USING(idcentro)
[9199fc7]294 WHERE administradores_centros.idusuario = '$userid'
[18391d1]295   AND centros.idcentro = '$ouid'
296 LIMIT 1;
297EOD;
[fb2ee20]298        $rs=new Recordset;
299        $rs->Comando=&$cmd;
[2aa8687]300        if (!$rs->Abrir()) return(false);       // Error oppening recordset.
[fb2ee20]301        $rs->Primero();
[9199fc7]302        if (checkAdmin($rs->campos["idusuario"]) and
[18391d1]303            checkParameter($rs->campos["idcentro"])) {
[ffaf580]304                $response['id'] = (int)$ouid;
[bbc672f]305                $response['name'] = $rs->campos["nombrecentro"];
[fb2ee20]306                $response['description'] = $rs->campos["comentarios"];
307                jsonResponse(200, $response);
308        }
309        $rs->Cerrar();
310    }
311);
312
[18391d1]313/**
314 * @brief    List group of labs in an Organizational Unit
[43f3bde]315 * @note     Route: /ous/:ouid/groups, Method: GET
316 * @param    int ouid   OU id.
317 * @return   string      JSON array of OU groups
[18391d1]318 */
319$app->get('/ous/:ouid/groups(/)', 'validateApiKey', function($ouid) {
[23a72c0]320        global $cmd;
321        global $userid;
322
323        $ouid = htmlspecialchars($ouid);
[18391d1]324        // List group of labs if user is OU's admin.
325        $cmd->texto = <<<EOD
[9199fc7]326SELECT adm.idusuario, grupos.*
[18391d1]327  FROM grupos
328 RIGHT JOIN administradores_centros AS adm USING(idcentro)
[9199fc7]329 WHERE adm.idusuario = '$userid'
[18391d1]330   AND idcentro='$ouid';
331EOD;
332        $rs=new Recordset;
333        $rs->Comando=&$cmd;
[2aa8687]334        if (!$rs->Abrir()) return(false);       // Error oppening recordset.
[18391d1]335        $rs->Primero();
336        // Check if user is an UO admin.
[9199fc7]337        if (checkAdmin($rs->campos["idusuario"])) {
[5ff84a5]338                $response = Array();
[18391d1]339                // Read data.
340                if (! is_null($rs->campos["idcentro"])) {
341                        while (!$rs->EOF) {
[5ff84a5]342                                $tmp = Array();
[ffaf580]343                                $tmp['id'] = (int)$rs->campos["idgrupo"];
[18391d1]344                                $tmp['name'] = $rs->campos["nombregrupo"];
345                                $tmp['type'] = $rs->campos["tipo"];
346                                $tmp['comments'] = $rs->campos["comentarios"];
[23a72c0]347                                if($rs->campos["grupoid"] != 0){
[ffaf580]348                                        $tmp['parent']['id'] = (int)$rs->campos["grupoid"];
[23a72c0]349                                }
350                                array_push($response, $tmp);
351                                $rs->Siguiente();
352                        }
353                }
[18391d1]354                jsonResponse(200, $response);
[23a72c0]355        }
[18391d1]356        $rs->Cerrar();
[23a72c0]357    }
358);
359
[ac8b234e]360/**
361 * @brief    List all labs defined in an OU
[43f3bde]362 * @note     Route: /ous/:ouid/labs, Method: GET
363 * @param    int ouid  OU id.
364 * @return   string    JSON array of all UO's labs data
[ac8b234e]365 */
[18391d1]366$app->get('/ous/:ouid/labs(/)', 'validateApiKey',
[fb2ee20]367    function($ouid) {
[606a0c7]368        global $userid;
[fb2ee20]369        global $cmd;
370
371        $ouid = htmlspecialchars($ouid);
[2aa8687]372        // Database query.
[fb2ee20]373        $cmd->texto = <<<EOD
[9199fc7]374SELECT adm.idusuario, aulas.*, grp.idgrupo AS group_id,
[606a0c7]375       grp.nombregrupoordenador, grp.grupoid AS group_group_id, grp.comentarios
[fb2ee20]376  FROM aulas
377 RIGHT JOIN administradores_centros AS adm USING(idcentro)
[606a0c7]378  LEFT JOIN gruposordenadores AS grp USING(idaula)
[9199fc7]379 WHERE adm.idusuario = '$userid'
[5ff84a5]380   AND adm.idcentro='$ouid'
[606a0c7]381 ORDER BY aulas.idaula, grp.idgrupo
[fb2ee20]382EOD;
383        $rs=new Recordset;
384        $rs->Comando=&$cmd;
[606a0c7]385        if (!$rs->Abrir()) return(false);       // Error opening recordset.
[18391d1]386        // Check if user is an UO admin.
[fb2ee20]387        $rs->Primero();
[9199fc7]388        if (checkAdmin($rs->campos["idusuario"])) {
[5ff84a5]389                $response = Array();
[18391d1]390                if (! is_null($rs->campos["idcentro"])) {
391                        while (!$rs->EOF) {
392                                // En los resultados las aulas vienen repetidas tantas veces como grupos tengan, solo dejamos uno
393                                $classroomIndex = -1;
394                                $found=false;
395                                $index = 0;
396                                while(!$found && $index < count($response)){
397                                        if(isset($response[$index]["id"]) && $response[$index]["id"] == $rs->campos["idaula"]){
398                                                $classroomIndex = $index;
399                                                $found = true;
400                                        }
401                                        $index++;
[606a0c7]402                                }
[18391d1]403                                if(!$found){
[5ff84a5]404                                        $tmp = Array();
[ffaf580]405                                        $tmp['id'] = (int)$rs->campos["idaula"];
[18391d1]406                                        $tmp['name'] = $rs->campos["nombreaula"];
[43f3bde]407                                        $tmp['inremotepc'] = ($rs->campos["inremotepc"] == 1);
[ffaf580]408                                        $tmp['group']['id'] = (int)$rs->campos["grupoid"];
409                                        $tmp['ou']['id'] = (int)$ouid;
[18391d1]410                                        array_push($response, $tmp);
[606a0c7]411                                }
[18391d1]412                                else{
413                                        // Le añadimos el grupo en cuestion siempre que no sea un subgrupo
414                                        if($rs->campos["group_group_id"] == 0){
415                                                array_push($response[$classroomIndex]['classroomGroups'],
[ffaf580]416                                                        array("id" => (int)$rs->campos["group_id"],
[18391d1]417                                                        "name" => $rs->campos["nombregrupoordenador"],
418                                                        "comments" => $rs->campos["comentarios"],
419                                                        "classroomGroups" => array()));
420                                        }
421                                        else {
422                                                // Buscamos el grupo donde añadir el grupo
423                                                addClassroomGroup($response[$classroomIndex]['classroomGroups'], $rs);
424                                        }
[606a0c7]425                                }
[18391d1]426                                $rs->Siguiente();
[606a0c7]427                        }
[fb2ee20]428                }
429                jsonResponse(200, $response);
430        }
431        $rs->Cerrar();
432    }
433);
434
[ac8b234e]435/**
436 * @brief    Get lab data
[43f3bde]437 * @note     Route: /ous/:ouid/labs/:labid, Method: GET
438 * @param    int ouid   OU id.
439 * @param    int labid  lab id.
440 * @return   string     JSON string with lab parameters
[ac8b234e]441 */
[4139899]442$app->get('/ous/:ouid/labs/:labid(/)', 'validateApiKey',
[fb2ee20]443    function($ouid, $labid) {
[4139899]444        global $userid;
[fb2ee20]445        global $cmd;
446
447        $ouid = htmlspecialchars($ouid);
448        $labid = htmlspecialchars($labid);
[2aa8687]449        // Database query.
[fb2ee20]450        $cmd->texto = <<<EOD
[9199fc7]451SELECT adm.idusuario, COUNT(idordenador) AS defclients, aulas.*
[fb2ee20]452  FROM aulas
453 RIGHT JOIN administradores_centros AS adm USING(idcentro)
454  LEFT JOIN ordenadores USING(idaula)
[9199fc7]455 WHERE adm.idusuario = '$userid'
[4139899]456   AND idcentro='$ouid'
[fb2ee20]457   AND idaula='$labid';
458EOD;
459        $rs=new Recordset;
460        $rs->Comando=&$cmd;
[2aa8687]461        if (!$rs->Abrir()) return(false);       // Error oppening recordset.
[fb2ee20]462        $rs->Primero();
[4139899]463        // Check if user is an UO admin and lab exists.
[9199fc7]464        if (checkAdmin($rs->campos["idusuario"]) and checkParameter($rs->campos["idaula"])) {
[ffaf580]465                $response['id'] = (int)$rs->campos["idaula"];
[bbc672f]466                $response['name'] = $rs->campos["nombreaula"];
467                $response['location'] = $rs->campos["ubicacion"];
[fb2ee20]468                $response['description'] = $rs->campos["comentarios"];
[43f3bde]469                $response['inremotepc'] = ($rs->campos["inremotepc"] == 1);
[ffaf580]470                $response['capacity'] = (int)$rs->campos["puestos"];
[43f3bde]471                if ($rs->campos["idordprofesor"]) {
472                        $response['profclient']['id'] = (int)$rs->campos["idordprofesor"];
473                }
[ffaf580]474                $response['defclients'] = (int)$rs->campos["defclients"];
[43f3bde]475                $response['projector'] = ($rs->campos["cagnon"] == 1);
476                $response['board'] = ($rs->campos["pizarra"] == 1);
[fb2ee20]477                $response['routerip'] = $rs->campos["router"];
478                $response['netmask'] = $rs->campos["netmask"];
479                $response['ntp'] = $rs->campos["ntp"];
480                $response['dns'] = $rs->campos["dns"];
481                $response['proxyurl'] = $rs->campos["proxy"];
482                switch ($rs->campos["modomul"]) {
483                        case 1:  $response['mcastmode'] = "half-duplex"; break;
484                        case 2:  $response['mcastmode'] = "full-duplex"; break;
485                        default: $response['mcastmode'] = $rs->campos["modomul"];
486                }
487                $response['mcastip'] = $rs->campos["ipmul"];
488                $response['mcastport'] = $rs->campos["pormul"];
489                $response['mcastspeed'] = $rs->campos["velmul"];
490                $response['p2pmode'] = $rs->campos["modp2p"];
491                $response['p2ptime'] = $rs->campos["timep2p"];
[0126b05]492                $response['picture'] = $rs->campos["urlfoto"];
[fb2ee20]493                jsonResponse(200, $response);
494        }
495        $rs->Cerrar();
496    }
497);
498
[213a832]499
[4139899]500/**
501 * @brief    List all clients defined in a lab
[43f3bde]502 * @note     Route: /ous/:ouid/labs/:labid/clients, Method: GET
503 * @param    int ouid   OU id.
504 * @param    int labid  lab id.
505 * @return   string     JSON data with lab id. and array of lab parameters
[4139899]506 */
507$app->get('/ous/:ouid/labs/:labid/clients(/)', 'validateApiKey',
[fb2ee20]508    function($ouid, $labid) {
[4139899]509        global $userid;
[fb2ee20]510        global $cmd;
511
512        $ouid = htmlspecialchars($ouid);
513        $labid = htmlspecialchars($labid);
[2aa8687]514        // Database query.
[fb5338c]515        $cmd->texto = <<<EOD
[9199fc7]516SELECT adm.idusuario, ordenadores.*, aulas.idaula AS labid
[fb5338c]517  FROM ordenadores
[4139899]518 RIGHT JOIN aulas USING(idaula)
[fb5338c]519 RIGHT JOIN administradores_centros AS adm USING(idcentro)
[9199fc7]520 WHERE adm.idusuario = '$userid'
[2aa8687]521   AND adm.idcentro='$ouid'
522   AND aulas.idaula='$labid';
[fb5338c]523EOD;
[fb2ee20]524        $rs=new Recordset;
525        $rs->Comando=&$cmd;
[2aa8687]526        if (!$rs->Abrir()) return(false);       // Error oppening recordset.
[fb2ee20]527        $rs->Primero();
[4139899]528        // Check if user is an UO admin and lab exists.
[9199fc7]529        if (checkAdmin($rs->campos["idusuario"]) and checkParameter($rs->campos["labid"])) {
[5ff84a5]530                $response = Array();
[fb2ee20]531                while (!$rs->EOF) {
[4139899]532                        if (!is_null($rs->campos["idordenador"])) {
[5ff84a5]533                                $tmp = Array();
[ffaf580]534                                $tmp['id'] = (int)$rs->campos["idordenador"];
[4139899]535                                $tmp['name'] = $rs->campos["nombreordenador"];
536                                $tmp['ip'] = $rs->campos["ip"];
537                                $tmp['mac'] = $rs->campos["mac"];
[ffaf580]538                                $tmp['ou']['id'] = (int)$ouid;
539                                $tmp['lab']['id'] = (int)$labid;
[4139899]540                                array_push($response, $tmp);
541                        }
[fb2ee20]542                        $rs->Siguiente();
543                }
544                jsonResponse(200, $response);
545        }
546        $rs->Cerrar();
547    }
548);
549
[4139899]550/**
[2a337db]551 * @brief    Get execution status of all clients defined in a lab
[43f3bde]552 * @note     Route: /ous/:ouid/labs/:labid/clients/:clntid/status, Method: GET
553 * @param    int ouid   OU id.
554 * @param    int labid  lab id.
555 * @return   string     JSON string with array of all client status defined in a lab
[2a337db]556 */
557$app->get('/ous/:ouid/labs/:labid/clients/status(/)', 'validateApiKey', 'getStatus');
558
559/**
[4139899]560 * @brief    Get client data
561 * @note     Route: /ous/id1/labs/id2clients/id3, Method: GET
[43f3bde]562 * @param    int ouid    OU id.
563 * @param    int labid   lab id.
564 * @param    int clntid  client id.
565 * @return   string      JSON string with hardware parameters
[4139899]566 */
567$app->get('/ous/:ouid/labs/:labid/clients/:clntid(/)', 'validateApiKey',
[fb2ee20]568    function($ouid, $labid, $clntid) {
[4139899]569        global $userid;
[fb2ee20]570        global $cmd;
571
572        $ouid = htmlspecialchars($ouid);
573        $labid = htmlspecialchars($labid);
574        $clntid = htmlspecialchars($clntid);
[2aa8687]575        // Database query.
[fb5338c]576        $cmd->texto = <<<EOD
[9199fc7]577SELECT adm.idusuario, ordenadores.*,
[43f3bde]578       IF(ordenadores.idordenador=aulas.idordprofesor, 1, 0) AS profclient
[fb5338c]579  FROM ordenadores
580  JOIN aulas USING(idaula)
581 RIGHT JOIN administradores_centros AS adm USING(idcentro)
[9199fc7]582 WHERE adm.idusuario = '$userid'
[4139899]583   AND idcentro='$ouid'
[fb5338c]584   AND idaula='$labid'
585   AND idordenador='$clntid';
586EOD;
[fb2ee20]587        $rs=new Recordset;
588        $rs->Comando=&$cmd;
[2aa8687]589        if (!$rs->Abrir()) return(false);       // Error oppening recordset.
[fb2ee20]590        $rs->Primero();
[4139899]591        // Check if user is an UO admin, lab exists and client exists.
[9199fc7]592        if (checkAdmin($rs->campos["idusuario"]) and checkParameter($rs->campos["idaula"]) and checkParameter($rs->campos["idordenador"])) {
[2aa8687]593                // Read data.
[ffaf580]594                $response['id'] = (int)$rs->campos["idordenador"];
[bbc672f]595                $response['name'] = $rs->campos["nombreordenador"];
596                $response['serialno'] = $rs->campos["numserie"];
[fb2ee20]597                $response['netiface'] = $rs->campos["netiface"];
598                $response['netdriver'] = $rs->campos["netdriver"];
599                $response['mac'] = $rs->campos["mac"];
600                $response['ip'] = $rs->campos["ip"];
601                $response['netmask'] = $rs->campos["mascara"];
602                $response['routerip'] = $rs->campos["router"];
[ffaf580]603                $response['repo']['id'] = (int)$rs->campos["idrepositorio"];
[43f3bde]604                $response['profclient'] = ($rs->campos["profclient"] == 1);
[4a511f81]605                //$response['hardprofile']['id'] = $rs->campos["idperfilhard"];
606                //$response['menu']['id'] = $rs->campos["idmenu"];
[43f3bde]607                $response['validation'] = ($rs->campos["validacion"] == 1);
[fb5338c]608                $response['boottype'] = $rs->campos["arranque"];
[0126b05]609                $response['picture'] = $rs->campos["fotoord"];
[fb2ee20]610                jsonResponse(200, $response);
611        }
612        $rs->Cerrar();
613    }
614);
615
[2aa8687]616/**
617 * @brief    Get client's harware configuration data
[43f3bde]618 * @note     Route: /ous/:ouid/labs/:labid/clients/:clntid/hardware, Method: GET
619 * @param    int ouid    OU id.
620 * @param    int labid   lab id.
621 * @param    int clntid  client id.
622 * @return   string      JSON string with cleint parameters
[2aa8687]623 */
624$app->get('/ous/:ouid/labs/:labid/clients/:clntid/hardware(/)', 'validateApiKey',
[fb2ee20]625    function($ouid, $labid, $clntid) {
[4139899]626        global $userid;
[fb2ee20]627        global $cmd;
628
629        $ouid = htmlspecialchars($ouid);
630        $labid = htmlspecialchars($labid);
631        $clntid = htmlspecialchars($clntid);
[2aa8687]632        // Database query.
[fb2ee20]633        $cmd->texto = <<<EOD
[9199fc7]634SELECT adm.idusuario, ordenadores.idordenador, ordenadores.nombreordenador,
[fb2ee20]635       tipohardwares.nemonico, hardwares.descripcion
[2aa8687]636  FROM ordenadores
637  JOIN aulas USING(idaula)
638 RIGHT JOIN administradores_centros AS adm USING(idcentro)
639  LEFT JOIN perfileshard_hardwares USING(idperfilhard)
640  LEFT JOIN hardwares ON perfileshard_hardwares.idhardware=hardwares.idhardware
641  LEFT JOIN tipohardwares ON tipohardwares.idtipohardware=hardwares.idtipohardware
[9199fc7]642 WHERE adm.idusuario = '$userid'
[2aa8687]643   AND adm.idcentro='$ouid'
644   AND aulas.idaula='$labid'
645   AND ordenadores.idordenador='$clntid';
[fb2ee20]646EOD;
647        $rs=new Recordset;
648        $rs->Comando=&$cmd;
[2aa8687]649        if (!$rs->Abrir()) return(false);       // Error oppening recordset.
[fb2ee20]650        $rs->Primero();
[2aa8687]651        // Check if user is an UO admin and client exists.
[9199fc7]652        if (checkAdmin($rs->campos["idusuario"]) and checkParameter($rs->campos["idordenador"])) {
[2aa8687]653                // Read data.
[ffaf580]654                $response['id'] = (int)$rs->campos["idordenador"];
[bbc672f]655                $response['name'] = $rs->campos["nombreordenador"];
[5ff84a5]656                $response['hardware'] = Array();
[fb2ee20]657                while (!$rs->EOF) {
[2aa8687]658                        if (!is_null($rs->campos["nemonico"])) {
[5ff84a5]659                                $tmp = Array();
[2aa8687]660                                $tmp['type'] = $rs->campos["nemonico"];
661                                $tmp['description'] = $rs->campos["descripcion"];
662                                array_push($response['hardware'], $tmp);
663                        }
[fb2ee20]664                        $rs->Siguiente();
665                }
666                jsonResponse(200, $response);
667        }
668        $rs->Cerrar();
669    }
670);
671
[2aa8687]672/**
673 * @brief    Get client's disk configuration data
[43f3bde]674 * @note     Route: /ous/:ouid1/labs/:labid/clients/:clntid/diskcfg, Method: GET
675 * @param    int ouid    OU id.
676 * @param    int labid   lab id.
677 * @param    int clntid  client id.
678 * @return   string      JSON string with disk parameters
[2aa8687]679 */
680$app->get('/ous/:ouid/labs/:labid/clients/:clntid/diskcfg(/)', 'validateApiKey',
[fb2ee20]681    function($ouid, $labid, $clntid) {
[2aa8687]682        global $userid;
[fb2ee20]683        global $cmd;
684
685        $ouid = htmlspecialchars($ouid);
686        $labid = htmlspecialchars($labid);
687        $clntid = htmlspecialchars($clntid);
[2aa8687]688        // Database query.
[fb2ee20]689        $cmd->texto = <<<EOD
[9199fc7]690SELECT adm.idusuario, ordenadores.idordenador AS clientid,
[2aa8687]691       ordenadores.nombreordenador, ordenadores_particiones.*, tipospar.tipopar,
[208ee50]692       sistemasficheros.nemonico, nombresos.nombreso, imagenes.nombreca,
693       (imagenes.revision - ordenadores_particiones.revision) AS difimagen
[fb2ee20]694  FROM ordenadores_particiones
695 RIGHT JOIN ordenadores USING(idordenador)
[2aa8687]696  JOIN aulas USING(idaula)
697 RIGHT JOIN administradores_centros AS adm USING(idcentro)
[fb2ee20]698  LEFT JOIN tipospar USING(codpar)
699  LEFT JOIN sistemasficheros USING(idsistemafichero)
700  LEFT JOIN nombresos USING(idnombreso)
701  LEFT JOIN imagenes USING(idimagen)
[9199fc7]702 WHERE adm.idusuario = '$userid'
[2aa8687]703   AND adm.idcentro='$ouid'
704   AND aulas.idaula='$labid'
705   AND ordenadores.idordenador='$clntid'
[fb2ee20]706 ORDER BY numdisk ASC, numpar ASC;
707EOD;
708        $rs=new Recordset;
709        $rs->Comando=&$cmd;
[2aa8687]710        if (!$rs->Abrir()) return(false);       // Error oppening recordset.
[fb2ee20]711        $rs->Primero();
[2aa8687]712        // Check if user is an UO admin and client exists.
[9199fc7]713        if (checkAdmin($rs->campos["idusuario"]) and checkParameter($rs->campos["clientid"])) {
[2aa8687]714                // Read data.
[ffaf580]715                $response['id'] = (int)$rs->campos["clientid"];
[bbc672f]716                $response['name'] = $rs->campos["nombreordenador"];
[5ff84a5]717                $response['diskcfg'] = Array();
[fb2ee20]718                while (!$rs->EOF) {
[d57fcbc]719                        // Skip header.
[fb2ee20]720                        if ($rs->campos["numdisk"] == 0) {
721                                $rs->Siguiente();
722                                continue;
723                        }
[5ff84a5]724                        $tmp = Array();
[2fd9054]725                        // Common data.
[ffaf580]726                        $tmp['disk'] = (int)$rs->campos["numdisk"];
727                        $tmp['size'] = (int)$rs->campos["tamano"];
[fb2ee20]728                        if ($rs->campos["numpar"] == 0) {
[2aa8687]729                                // Disk data.
[fb2ee20]730                                switch ($rs->campos["codpar"]) {
731                                        case 1:  $tmp['parttable'] = "MSDOS"; break;
732                                        case 2:  $tmp['parttable'] = "GPT"; break;
733                                        case 3:  $tmp['parttable'] = "LVM"; break;
734                                        case 4:  $tmp['parttable'] = "ZPOOL"; break;
735                                        default: $tmp['parttable'] = $rs->campos["codpar"];
736                                }
737                        } else {
[2aa8687]738                                // Partition data.
[ffaf580]739                                $tmp['partition'] = (int)$rs->campos["numpar"];
[fb2ee20]740                                $tmp['parttype'] = $rs->campos["tipopar"];
741                                $tmp['filesystem'] = $rs->campos["nemonico"];
[ffaf580]742                                $tmp['usage'] = (int)$rs->campos["uso"];
[fb2ee20]743                                if ($rs->campos["nombreso"] != null) {
744                                        $tmp['os'] = $rs->campos["nombreso"];
[df81ab78]745                                        if ($rs->campos["idimagen"] > 0) {
[2aa8687]746                                                // Restored image data.
[ffaf580]747                                                $tmp['image']['id'] = (int)$rs->campos["idimagen"];
[df81ab78]748                                                $tmp['image']['deploydate'] = $rs->campos["fechadespliegue"];
[2aa8687]749                                                // Check if image is updated.
[43f3bde]750                                                $tmp['image']['updated'] = ($rs->campos["difimagen"] == 0);
[df81ab78]751                                        }
[fb2ee20]752                                }
753                                //$tmp['cachedata'] = $rs->campos["cache"];
754                        }
755                        array_push($response['diskcfg'], $tmp);
756                        $rs->Siguiente();
757                }
758                jsonResponse(200, $response);
759        }
760        $rs->Cerrar();
761    }
762);
763
[2aa8687]764/**
765 * @brief    Get client's execution status
[43f3bde]766 * @note     Route: /ous/:ouid/labs/:labid/clients/:clntid/status, Method: GET
767 * @param    int ouid    OU id.
768 * @param    int labid   lab id.
769 * @param    int clntid  client id.
770 * @return   string      JSON string with client status
[2aa8687]771 */
[213a832]772$app->get('/ous/:ouid/labs/:labid/clients/:clntid/status(/)', 'validateApiKey', 'getStatus');
[fb2ee20]773
[2aa8687]774/**
775 * @brief    List all image repositories defined in an OU
776 * @note     Route: /ous/id/repos, Method: GET
[43f3bde]777 * @param    int ouid  OU id.
778 * @return   string    JSON array of all UO's repo data
[2aa8687]779 */
780$app->get('/ous/:ouid/repos(/)', 'validateApiKey',
[fb2ee20]781    function($ouid) {
[2aa8687]782        global $userid;
[fb2ee20]783        global $cmd;
784
785        $ouid = htmlspecialchars($ouid);
[2aa8687]786        // Database query.
787        $cmd->texto = <<<EOD
[9199fc7]788SELECT adm.idusuario, adm.idcentro AS ouid, repositorios.*
[2aa8687]789  FROM repositorios
790 RIGHT JOIN administradores_centros AS adm USING(idcentro)
[9199fc7]791 WHERE adm.idusuario = '$userid'
[2aa8687]792   AND adm.idcentro='$ouid';
793EOD;
[fb2ee20]794        $rs=new Recordset;
795        $rs->Comando=&$cmd;
[2aa8687]796        if (!$rs->Abrir()) return(false);       // Error oppening recordset.
[fb2ee20]797        $rs->Primero();
[2aa8687]798        // Check if user is an UO admin.
[9199fc7]799        if (checkAdmin($rs->campos["idusuario"]) and checkParameter($rs->campos["ouid"])) {
[5ff84a5]800                $response = Array();
[fb2ee20]801                while (!$rs->EOF) {
[2aa8687]802                        if (! is_null($rs->campos["idcentro"])) {
[5ff84a5]803                                $tmp = Array();
[ffaf580]804                                $tmp['id'] = (int)$rs->campos["idrepositorio"];
[2aa8687]805                                $tmp['name'] = $rs->campos["nombrerepositorio"];
[ffaf580]806                                $tmp['ou']['id'] = (int)$ouid;
[2aa8687]807                                array_push($response, $tmp);
808                        }
[fb2ee20]809                        $rs->Siguiente();
810                }
811                jsonResponse(200, $response);
812        }
813        $rs->Cerrar();
814    }
815);
816
[2aa8687]817/**
818 * @brief    Get image repository data
[43f3bde]819 * @note     Route: /ous/:ouid/repos/:repoid, Method: GET
820 * @param    int ouid    OU id.
821 * @param    int repoid  repository id.
822 * @return   string      JSON string with repo parameters
[2aa8687]823 */
824$app->get('/ous/:ouid/repos/:repoid(/)', 'validateApiKey',
[fb2ee20]825    function($ouid, $repoid) {
[2aa8687]826        global $userid;
[fb2ee20]827        global $cmd;
828
829        $ouid = htmlspecialchars($ouid);
830        $repoid = htmlspecialchars($repoid);
[2aa8687]831        // Database query.
832        $cmd->texto = <<<EOD
[9199fc7]833SELECT adm.idusuario, repositorios.*
[2aa8687]834  FROM repositorios
835 RIGHT JOIN administradores_centros AS adm USING(idcentro)
[9199fc7]836 WHERE adm.idusuario = '$userid'
[2aa8687]837   AND adm.idcentro='$ouid'
838   AND idrepositorio='$repoid';
839EOD;
[fb2ee20]840        $rs=new Recordset;
841        $rs->Comando=&$cmd;
[2aa8687]842        if (!$rs->Abrir()) return(false);       // Error oppening recordset.
[fb2ee20]843        $rs->Primero();
[2aa8687]844        // Check if user is an UO admin and repo exists.
[9199fc7]845        if (checkAdmin($rs->campos["idusuario"]) and checkParameter($rs->campos["idrepositorio"])) {
[2aa8687]846                // Read data.
[ffaf580]847                $response['id'] = (int)$rs->campos["idrepositorio"];
[bbc672f]848                $response['name'] = $rs->campos["nombrerepositorio"];
[fb2ee20]849                $response['description'] = $rs->campos["comentarios"];
[4a511f81]850                $response['ip'] = $rs->campos["ip"];
[fb2ee20]851                jsonResponse(200, $response);
852        }
853        $rs->Cerrar();
854    }
855);
856
[5ff84a5]857/**
858 * @brief    List all images defined in an OU
[43f3bde]859 * @note     Route: /ous/:ouid/images, Method: GET
860 * @param    int ouid  OU id.
861 * @return   string    JSON array of all UO's image data
[5ff84a5]862 */
863$app->get('/ous/:ouid/images(/)', 'validateApiKey',
[fb2ee20]864    function($ouid) {
[5ff84a5]865        global $userid;
[fb2ee20]866        global $cmd;
867
868        $ouid = htmlspecialchars($ouid);
[5ff84a5]869        // Database query.
870        $cmd->texto = <<<EOD
[9199fc7]871SELECT adm.idusuario, adm.idcentro AS ouid, imagenes.*
[5ff84a5]872  FROM imagenes
873 RIGHT JOIN administradores_centros AS adm USING(idcentro)
[9199fc7]874 WHERE adm.idusuario = '$userid'
[5ff84a5]875   AND adm.idcentro='$ouid';
876EOD;
[fb2ee20]877        $rs=new Recordset;
878        $rs->Comando=&$cmd;
[5ff84a5]879        if (!$rs->Abrir()) return(false);       // Error oppening recordset.
[fb2ee20]880        $rs->Primero();
[5ff84a5]881        // Check if user is an UO admin.
[9199fc7]882        if (checkAdmin($rs->campos["idusuario"]) and checkParameter($rs->campos["ouid"])) {
[5ff84a5]883                $response = Array();
[fb2ee20]884                while (!$rs->EOF) {
[5ff84a5]885                        if (! is_null($rs->campos["idcentro"])) {
886                                $tmp = Array();
[ffaf580]887                                $tmp['id'] = (int)$rs->campos["idimagen"];
[5ff84a5]888                                $tmp['name'] = $rs->campos["nombreca"];
[43f3bde]889                                $tmp['inremotepc'] = ($rs->campos["inremotepc"] == 1);
[ffaf580]890                                $tmp['ou']['id'] = (int)$ouid;
[5ff84a5]891                                array_push($response, $tmp);
892                        }
[fb2ee20]893                        $rs->Siguiente();
894                }
895                jsonResponse(200, $response);
896        }
897    }
898);
899
[5ff84a5]900/**
901 * @brief    Get image data
[43f3bde]902 * @note     Route: /ous/:ouid/images/:imgid, Method: GET
903 * @param    int ouid   OU id.
904 * @param    int imgid  image id.
905 * @return   string     JSON string with image parameters
[5ff84a5]906 */
907$app->get('/ous/:ouid/images/:imgid(/)', 'validateApiKey',
[fb2ee20]908    function($ouid, $imgid) {
[5ff84a5]909        global $userid;
[fb2ee20]910        global $cmd;
911
912        $ouid = htmlspecialchars($ouid);
913        $imgid = htmlspecialchars($imgid);
[5ff84a5]914        // Database query.
915        $cmd->texto = <<<EOD
[9199fc7]916SELECT adm.idusuario, imagenes.*, nombreso AS os
[5ff84a5]917  FROM imagenes
918 RIGHT JOIN administradores_centros AS adm USING(idcentro)
[2154cbb]919  LEFT JOIN perfilessoft USING(idperfilsoft)
920  LEFT JOIN nombresos USING(idnombreso)
[9199fc7]921 WHERE adm.idusuario = '$userid'
[5ff84a5]922   AND adm.idcentro='$ouid'
923   AND idimagen='$imgid';
924EOD;
[fb2ee20]925        $rs=new Recordset;
926        $rs->Comando=&$cmd;
[5ff84a5]927        if (!$rs->Abrir()) return(false);       // Error oppening recordset.
[fb2ee20]928        $rs->Primero();
[5ff84a5]929        // Check if user is an UO admin and repo exists.
[9199fc7]930        if (checkAdmin($rs->campos["idusuario"]) and checkParameter($rs->campos["idimagen"])) {
[5ff84a5]931                // Read data.
[ffaf580]932                $response['id'] = (int)$rs->campos["idimagen"];
[bbc672f]933                $response['name'] = $rs->campos["nombreca"];
[fb2ee20]934                $response['description'] = $rs->campos["descripcion"];
935                $response['comments'] = $rs->campos["comentarios"];
[43f3bde]936                $response['inremotepc'] = ($rs->campos["inremotepc"] == 1);
[ffaf580]937                $response['repo']['id'] = (int)$rs->campos["idrepositorio"];
[fb2ee20]938                switch ($rs->campos["tipo"]) {
[5ff84a5]939                        // Image type.
[fb2ee20]940                        case 1:  $response['type'] = "monolithic"; break;
941                        case 2:  $response['type'] = "base"; break;
942                        case 3:  $response['type'] = "incremental";
943                                 $response['baseimg'] = $rs->campos["imagenid"];
944                                 $response['path'] = $rs->campos["ruta"];
945                                 break;
946                        default: $response['type'] = $rs->campos["tipo"];
947                }
948                if ($rs->campos["idordenador"] != 0) {
[5ff84a5]949                        // Source client data.
[ffaf580]950                        $response['client']['id'] = (int)$rs->campos["idordenador"];
951                        $response['client']['disk'] = (int)$rs->campos["numdisk"];
952                        $response['client']['partition'] = (int)$rs->campos["numpar"];
[fb2ee20]953                        $response['creationdate'] = $rs->campos["fechacreacion"];
[ffaf580]954                        $response['release'] = (int)$rs->campos["revision"];
[2154cbb]955                        $response['os'] = $rs->campos["os"];
[fb2ee20]956                }
957                jsonResponse(200, $response);
958        }
959        $rs->Cerrar();
960    }
961);
962
963// Lista de softeare instalado en una imagen.
[43f3bde]964/**
965 * @brief    List software installed in an image
966 * @note     Route: /ous/:ouid/images/:imgid/software, Method: GET
967 * @param    int ouid   OU id.
968 * @param    int imgid  image id.
969 * @return   string     JSON array with installed software
970 */$app->get('/ous/:ouid/images/:imgid/software(/)', 'validateApiKey',
[fb2ee20]971    function($ouid, $imgid) {
[5ff84a5]972        global $userid;
[fb2ee20]973        global $cmd;
974
975        $ouid = htmlspecialchars($ouid);
976        $imgid = htmlspecialchars($imgid);
[5ff84a5]977        // Database query.
[fb2ee20]978        $cmd->texto = <<<EOD
[9199fc7]979SELECT adm.idusuario, imagenes.idimagen, imagenes.nombreca,
[5ff84a5]980       nombresos.nombreso, softwares.descripcion
981  FROM imagenes
982 RIGHT JOIN administradores_centros AS adm USING(idcentro)
983  LEFT JOIN perfilessoft USING(idperfilsoft)
[bbc672f]984  LEFT JOIN nombresos USING(idnombreso)
[fb2ee20]985  LEFT JOIN perfilessoft_softwares USING(idperfilsoft)
986  LEFT JOIN softwares USING(idsoftware)
[9199fc7]987 WHERE adm.idusuario = '$userid'
[43f3bde]988   AND adm.idcentro='$ouid'
[5ff84a5]989   AND imagenes.idimagen='$imgid'
[fb2ee20]990 ORDER BY softwares.descripcion ASC;
991EOD;
992        $rs=new Recordset;
993        $rs->Comando=&$cmd;
[5ff84a5]994        if (!$rs->Abrir()) return(false);       // Error oppening recordset.
[fb2ee20]995        $rs->Primero();
[5ff84a5]996        // Check if user is an UO admin and repo exists.
[9199fc7]997        if (checkAdmin($rs->campos["idusuario"]) and checkParameter($rs->campos["idimagen"])) {
[ffaf580]998                $response['id'] = (int)$rs->campos["idimagen"];
[bbc672f]999                $response['name'] = $rs->campos["nombreca"];
[5ff84a5]1000                if (is_null($rs->campos["nombreso"])) {
1001                        // Null object.
1002                        $response['software'] = Array();
1003                        jsonResponse(200, $response, JSON_FORCE_OBJECT);
1004                } else {
1005                        // Read data.
1006                        $response['software']['os'] = $rs->campos["nombreso"];
1007                        //$response['software']['type'] = ...;  // OS type
1008                        $response['software']['applications'] = Array();
1009                        while (!$rs->EOF) {
1010                                // Ignoring empty fields.
1011                                if (!is_null($rs->campos["descripcion"])) {
[57200ac]1012                                        array_push($response['software']['applications'], $rs->campos["descripcion"]);
[5ff84a5]1013                                }
[fb2ee20]1014                                $rs->Siguiente();
1015                        }
[5ff84a5]1016                        jsonResponse(200, $response);
[fb2ee20]1017                }
1018        }
1019        $rs->Cerrar();
1020    }
1021);
1022
Note: See TracBrowser for help on using the repository browser.