source: admin/WebConsole/rest/server.php

lgromero-new-oglive
Last change on this file was c434493, checked in by Natalia Serrano <natalia.serrano@…>, 16 months ago

refs #235 Add several improvements

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