source: admin/WebConsole/rest/server.php @ 940b1c7f

918-git-images-111dconfigfileconfigure-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 940b1c7f was dbb1b6c, checked in by Ramón M. Gómez <ramongomez@…>, 6 years ago

#915: REST function to get client status uses new ogAdmServer REST API.

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