source: ogServer-Git/src/rest.c @ a801e78

Last change on this file since a801e78 was a801e78, checked in by Javier Sánchez Parra <jsanchez@…>, 3 years ago

#915 Add folders to scope

The database represents rooms groups and computers groups scope sets
with "grupos" (groups) and "gruposordenadores" (computers groups) tables
respectively. With this commit, ogServer abstracts both sets and offers
them though the API as the set "folder".

"grupos" table do not only group rooms, it can group other
elements of the database. You can see which kind of elements groups
looking at the column "tipo".

This commit often refers "rooms group" as group and "computers
group" as computers.

Request:
GET /scopes
NO BODY

Response
200 OK
{

"scope": [

{

"name": "center1",
"type": "center",
"id": 1,
"scope": [

{

"name": "folder1",
"type": "folder",
"id": 1,
"scope": [

{

"name": "folder2",
"type": "folder",
"id": 2,
"scope": []

},
{

"name": "room1",
"type": "room",
"id": 2,
"scope": [

{

"name": "folder3",
"type": "folder",
"id": 3,
"scope": [

{

"name": "folder4",
"type": "folder",
"id": 4,
"scope": []

},
{

"name": "computer1",
"type": "computer",
"id": 8,
"scope": [],
"ip": "192.168.56.12"

}

]

},
{

"name": "computer2",
"type": "computer",
"id": 7,
"scope": [],
"ip": "172.18.0.71"

}

]

}

]

},
{

"name": "room2",
"type": "room",
"id": 1,
"scope": []

}

]

}

]

}

  • Property mode set to 100644
File size: 149.7 KB
RevLine 
[04ca20e]1/*
[a7cce8d]2 * Copyright (C) 2020-2021 Soleta Networks <info@soleta.eu>
[04ca20e]3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Affero General Public License as published by the
[a7cce8d]6 * Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
[04ca20e]8 */
9
10#include "ogAdmServer.h"
11#include "dbi.h"
12#include "utils.h"
13#include "list.h"
14#include "rest.h"
[1f13855]15#include "wol.h"
[866b6c5]16#include "cfg.h"
[04ca20e]17#include "schedule.h"
[141b079]18#include "legacy.h"
[04ca20e]19#include <ev.h>
20#include <syslog.h>
21#include <sys/ioctl.h>
22#include <ifaddrs.h>
23#include <sys/types.h>
24#include <sys/stat.h>
25#include <fcntl.h>
26#include <jansson.h>
[608709f]27#include <dirent.h>
[04ca20e]28#include <time.h>
[532b081]29#include <stdlib.h>
[139633a]30#include <unistd.h>
31#include <sys/wait.h>
[403e7c3]32#include <sys/statvfs.h>
[04ca20e]33
[48de515]34struct ev_loop *og_loop;
35
[04ca20e]36#define OG_REST_PARAM_ADDR                      (1UL << 0)
37#define OG_REST_PARAM_MAC                       (1UL << 1)
38#define OG_REST_PARAM_WOL_TYPE                  (1UL << 2)
39#define OG_REST_PARAM_RUN_CMD                   (1UL << 3)
40#define OG_REST_PARAM_DISK                      (1UL << 4)
41#define OG_REST_PARAM_PARTITION                 (1UL << 5)
42#define OG_REST_PARAM_REPO                      (1UL << 6)
43#define OG_REST_PARAM_NAME                      (1UL << 7)
44#define OG_REST_PARAM_ID                        (1UL << 8)
45#define OG_REST_PARAM_CODE                      (1UL << 9)
46#define OG_REST_PARAM_TYPE                      (1UL << 10)
47#define OG_REST_PARAM_PROFILE                   (1UL << 11)
48#define OG_REST_PARAM_CACHE                     (1UL << 12)
49#define OG_REST_PARAM_CACHE_SIZE                (1UL << 13)
50#define OG_REST_PARAM_PART_0                    (1UL << 14)
51#define OG_REST_PARAM_PART_1                    (1UL << 15)
52#define OG_REST_PARAM_PART_2                    (1UL << 16)
53#define OG_REST_PARAM_PART_3                    (1UL << 17)
54#define OG_REST_PARAM_SYNC_SYNC                 (1UL << 18)
55#define OG_REST_PARAM_SYNC_DIFF                 (1UL << 19)
56#define OG_REST_PARAM_SYNC_REMOVE               (1UL << 20)
57#define OG_REST_PARAM_SYNC_COMPRESS             (1UL << 21)
58#define OG_REST_PARAM_SYNC_CLEANUP              (1UL << 22)
59#define OG_REST_PARAM_SYNC_CACHE                (1UL << 23)
60#define OG_REST_PARAM_SYNC_CLEANUP_CACHE        (1UL << 24)
61#define OG_REST_PARAM_SYNC_REMOVE_DST           (1UL << 25)
62#define OG_REST_PARAM_SYNC_DIFF_ID              (1UL << 26)
63#define OG_REST_PARAM_SYNC_DIFF_NAME            (1UL << 27)
64#define OG_REST_PARAM_SYNC_PATH                 (1UL << 28)
65#define OG_REST_PARAM_SYNC_METHOD               (1UL << 29)
66#define OG_REST_PARAM_ECHO                      (1UL << 30)
67#define OG_REST_PARAM_TASK                      (1UL << 31)
68#define OG_REST_PARAM_TIME_YEARS                (1UL << 32)
69#define OG_REST_PARAM_TIME_MONTHS               (1UL << 33)
70#define OG_REST_PARAM_TIME_WEEKS                (1UL << 34)
71#define OG_REST_PARAM_TIME_WEEK_DAYS            (1UL << 35)
72#define OG_REST_PARAM_TIME_DAYS                 (1UL << 36)
73#define OG_REST_PARAM_TIME_HOURS                (1UL << 37)
74#define OG_REST_PARAM_TIME_AM_PM                (1UL << 38)
75#define OG_REST_PARAM_TIME_MINUTES              (1UL << 39)
[06af0c2]76#define OG_REST_PARAM_NETMASK                   (1UL << 40)
[33b0c6f]77#define OG_REST_PARAM_SCOPE                     (1UL << 41)
78#define OG_REST_PARAM_MODE                      (1UL << 42)
[29e7641]79#define OG_REST_PARAM_CENTER                    (1UL << 43)
[04ca20e]80
81static LIST_HEAD(client_list);
[1f13855]82static LIST_HEAD(client_wol_list);
[04ca20e]83
84void og_client_add(struct og_client *cli)
85{
86        list_add(&cli->list, &client_list);
87}
88
89static struct og_client *og_client_find(const char *ip)
90{
91        struct og_client *client;
92        struct in_addr addr;
93        int res;
94
95        res = inet_aton(ip, &addr);
96        if (!res) {
97                syslog(LOG_ERR, "Invalid IP string: %s\n", ip);
98                return NULL;
99        }
100
101        list_for_each_entry(client, &client_list, list) {
102                if (client->addr.sin_addr.s_addr == addr.s_addr && client->agent) {
103                        return client;
104                }
105        }
106
107        return NULL;
108}
109
110static const char *og_client_status(const struct og_client *cli)
111{
[a1aaad4]112        switch (cli->last_cmd) {
113        case OG_CMD_UNSPEC:
114        case OG_CMD_PROBE:
115                break;
116        default:
[04ca20e]117                return "BSY";
[a1aaad4]118        }
[04ca20e]119
120        switch (cli->status) {
121        case OG_CLIENT_STATUS_BUSY:
122                return "BSY";
123        case OG_CLIENT_STATUS_OGLIVE:
124                return "OPG";
[c0f5d2c]125        case OG_CLIENT_STATUS_VIRTUAL:
126                return "VDI";
[5a3fd51]127        case OG_CLIENT_STATUS_LINUX:
128                return "LINUX";
[b6b1040]129        case OG_CLIENT_STATUS_WIN:
130                return "WIN";
[04ca20e]131        default:
132                return "OFF";
133        }
134}
135
136static bool og_msg_params_validate(const struct og_msg_params *params,
137                                   const uint64_t flags)
138{
139        return (params->flags & flags) == flags;
140}
141
[33b0c6f]142static bool og_flags_validate(const uint64_t flags,
143                              const uint64_t required_flags)
144{
145        return (flags & required_flags) == required_flags;
146}
147
[04ca20e]148static int og_json_parse_clients(json_t *element, struct og_msg_params *params)
149{
150        unsigned int i;
151        json_t *k;
152
153        if (json_typeof(element) != JSON_ARRAY)
154                return -1;
155
156        for (i = 0; i < json_array_size(element); i++) {
157                k = json_array_get(element, i);
158                if (json_typeof(k) != JSON_STRING)
159                        return -1;
160
161                params->ips_array[params->ips_array_len++] =
162                        json_string_value(k);
163
164                params->flags |= OG_REST_PARAM_ADDR;
165        }
166
167        return 0;
168}
169
[141b079]170int og_json_parse_partition_setup(json_t *element, struct og_msg_params *params)
[04ca20e]171{
172        unsigned int i;
173        json_t *k;
174
175        if (json_typeof(element) != JSON_ARRAY)
176                return -1;
177
178        for (i = 0; i < json_array_size(element) && i < OG_PARTITION_MAX; ++i) {
179                k = json_array_get(element, i);
180
181                if (json_typeof(k) != JSON_OBJECT)
182                        return -1;
183
184                if (og_json_parse_partition(k, &params->partition_setup[i],
185                                            OG_PARAM_PART_NUMBER |
186                                            OG_PARAM_PART_CODE |
187                                            OG_PARAM_PART_FILESYSTEM |
188                                            OG_PARAM_PART_SIZE |
189                                            OG_PARAM_PART_FORMAT) < 0)
190                        return -1;
191
192                params->flags |= (OG_REST_PARAM_PART_0 << i);
193        }
194        return 0;
195}
196
197static int og_json_parse_time_params(json_t *element,
198                                     struct og_msg_params *params)
199{
200        const char *key;
201        json_t *value;
202        int err = 0;
203
204        json_object_foreach(element, key, value) {
205                if (!strcmp(key, "years")) {
206                        err = og_json_parse_uint(value, &params->time.years);
207                        params->flags |= OG_REST_PARAM_TIME_YEARS;
208                } else if (!strcmp(key, "months")) {
209                        err = og_json_parse_uint(value, &params->time.months);
210                        params->flags |= OG_REST_PARAM_TIME_MONTHS;
211                } else if (!strcmp(key, "weeks")) {
212                        err = og_json_parse_uint(value, &params->time.weeks);
213                        params->flags |= OG_REST_PARAM_TIME_WEEKS;
214                } else if (!strcmp(key, "week_days")) {
215                        err = og_json_parse_uint(value, &params->time.week_days);
216                        params->flags |= OG_REST_PARAM_TIME_WEEK_DAYS;
217                } else if (!strcmp(key, "days")) {
218                        err = og_json_parse_uint(value, &params->time.days);
219                        params->flags |= OG_REST_PARAM_TIME_DAYS;
220                } else if (!strcmp(key, "hours")) {
221                        err = og_json_parse_uint(value, &params->time.hours);
222                        params->flags |= OG_REST_PARAM_TIME_HOURS;
223                } else if (!strcmp(key, "am_pm")) {
224                        err = og_json_parse_uint(value, &params->time.am_pm);
225                        params->flags |= OG_REST_PARAM_TIME_AM_PM;
226                } else if (!strcmp(key, "minutes")) {
227                        err = og_json_parse_uint(value, &params->time.minutes);
228                        params->flags |= OG_REST_PARAM_TIME_MINUTES;
229                }
230                if (err != 0)
231                        return err;
232        }
233
234        return err;
235}
236
237static const char *og_cmd_to_uri[OG_CMD_MAX] = {
238        [OG_CMD_WOL]            = "wol",
239        [OG_CMD_PROBE]          = "probe",
240        [OG_CMD_SHELL_RUN]      = "shell/run",
241        [OG_CMD_SESSION]        = "session",
242        [OG_CMD_POWEROFF]       = "poweroff",
243        [OG_CMD_REFRESH]        = "refresh",
244        [OG_CMD_REBOOT]         = "reboot",
245        [OG_CMD_STOP]           = "stop",
246        [OG_CMD_HARDWARE]       = "hardware",
247        [OG_CMD_SOFTWARE]       = "software",
248        [OG_CMD_IMAGE_CREATE]   = "image/create",
249        [OG_CMD_IMAGE_RESTORE]  = "image/restore",
250        [OG_CMD_SETUP]          = "setup",
251        [OG_CMD_RUN_SCHEDULE]   = "run/schedule",
[403e7c3]252        [OG_CMD_IMAGES]         = "images",
[04ca20e]253};
254
255static bool og_client_is_busy(const struct og_client *cli,
256                              enum og_cmd_type type)
257{
258        switch (type) {
259        case OG_CMD_REBOOT:
260        case OG_CMD_POWEROFF:
261        case OG_CMD_STOP:
262                break;
263        default:
264                if (cli->last_cmd != OG_CMD_UNSPEC)
265                        return true;
266                break;
267        }
268
269        return false;
270}
271
272int og_send_request(enum og_rest_method method, enum og_cmd_type type,
273                    const struct og_msg_params *params,
274                    const json_t *data)
275{
276        const char *content_type = "Content-Type: application/json";
277        char content [OG_MSG_REQUEST_MAXLEN - 700] = {};
278        char buf[OG_MSG_REQUEST_MAXLEN] = {};
279        unsigned int content_length;
280        char method_str[5] = {};
281        struct og_client *cli;
282        const char *uri;
283        unsigned int i;
284        int client_sd;
285
286        if (method == OG_METHOD_GET)
287                snprintf(method_str, 5, "GET");
288        else if (method == OG_METHOD_POST)
289                snprintf(method_str, 5, "POST");
290        else
291                return -1;
292
293        if (!data)
294                content_length = 0;
295        else
296                content_length = json_dumpb(data, content,
297                                            OG_MSG_REQUEST_MAXLEN - 700,
298                                            JSON_COMPACT);
299
300        uri = og_cmd_to_uri[type];
301        snprintf(buf, OG_MSG_REQUEST_MAXLEN,
302                 "%s /%s HTTP/1.1\r\nContent-Length: %d\r\n%s\r\n\r\n%s",
303                 method_str, uri, content_length, content_type, content);
304
305        for (i = 0; i < params->ips_array_len; i++) {
306                cli = og_client_find(params->ips_array[i]);
307                if (!cli)
308                        continue;
309
310                if (og_client_is_busy(cli, type))
311                        continue;
312
313                client_sd = cli->io.fd;
314                if (client_sd < 0) {
315                        syslog(LOG_INFO, "Client %s not conected\n",
316                               params->ips_array[i]);
317                        continue;
318                }
319
320                if (send(client_sd, buf, strlen(buf), 0) < 0)
321                        continue;
322
323                cli->last_cmd = type;
324        }
325
[1c52b78]326        json_decref((json_t *)data);
327
[04ca20e]328        return 0;
329}
330
331static int og_cmd_post_clients(json_t *element, struct og_msg_params *params)
332{
333        const char *key;
334        json_t *value;
335        int err = 0;
336
337        if (json_typeof(element) != JSON_OBJECT)
338                return -1;
339
340        json_object_foreach(element, key, value) {
341                if (!strcmp(key, "clients"))
342                        err = og_json_parse_clients(value, params);
343
344                if (err < 0)
[e7e80cd]345                        return err;
[04ca20e]346        }
347
348        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
349                return -1;
350
351        return og_send_request(OG_METHOD_POST, OG_CMD_PROBE, params, NULL);
352}
353
354struct og_buffer {
355        char    *data;
356        int     len;
357};
358
[49fc6c5]359#define OG_MSG_RESPONSE_MAXLEN  262144
[2c6cef7]360
[04ca20e]361static int og_json_dump_clients(const char *buffer, size_t size, void *data)
362{
363        struct og_buffer *og_buffer = (struct og_buffer *)data;
364
[2c6cef7]365        if (size >= OG_MSG_RESPONSE_MAXLEN - og_buffer->len) {
366                syslog(LOG_ERR, "Response JSON body is too large\n");
367                return -1;
368        }
369
[04ca20e]370        memcpy(og_buffer->data + og_buffer->len, buffer, size);
371        og_buffer->len += size;
372
373        return 0;
374}
375
[c05f134]376static int og_json_client_append(json_t *array, struct og_client *client)
377{
378        json_t *addr, *state, *object;
379
380        object = json_object();
381        if (!object)
382                return -1;
383
384        addr = json_string(inet_ntoa(client->addr.sin_addr));
385        if (!addr) {
386                json_decref(object);
387                return -1;
388        }
389        json_object_set_new(object, "addr", addr);
390        state = json_string(og_client_status(client));
391        if (!state) {
392                json_decref(object);
393                return -1;
394        }
395        json_object_set_new(object, "state", state);
[40d4279]396        json_object_set_new(object, "speed", json_integer(client->speed));
[c05f134]397        json_array_append_new(array, object);
398
399        return 0;
400}
401
[1f13855]402static int og_json_client_wol_append(json_t *array,
403                                     struct og_client_wol *cli_wol)
404{
405        json_t *addr, *state, *object;
406
407        object = json_object();
408        if (!object)
409                return -1;
410
411        addr = json_string(inet_ntoa(cli_wol->addr));
412        if (!addr) {
413                json_decref(object);
414                return -1;
415        }
416        json_object_set_new(object, "addr", addr);
417        state = json_string(og_client_wol_status(cli_wol));
418        if (!state) {
419                json_decref(object);
420                return -1;
421        }
422        json_object_set_new(object, "state", state);
423        json_array_append_new(array, object);
424
425        return 0;
426}
427
[04ca20e]428static int og_cmd_get_clients(json_t *element, struct og_msg_params *params,
429                              char *buffer_reply)
430{
431        struct og_buffer og_buffer = {
432                .data   = buffer_reply,
433        };
[1f13855]434        struct og_client_wol *cli_wol;
435        struct og_client *client;
[c05f134]436        json_t *array, *root;
[04ca20e]437
438        array = json_array();
439        if (!array)
440                return -1;
441
[1f13855]442        list_for_each_entry(cli_wol, &client_wol_list, list) {
443                if (og_json_client_wol_append(array, cli_wol) < 0) {
444                        json_decref(array);
445                        return -1;
446                }
447        }
448
[04ca20e]449        list_for_each_entry(client, &client_list, list) {
450                if (!client->agent)
451                        continue;
452
[c05f134]453                if (og_json_client_append(array, client) < 0) {
[04ca20e]454                        json_decref(array);
455                        return -1;
456                }
457        }
[c05f134]458
[04ca20e]459        root = json_pack("{s:o}", "clients", array);
460        if (!root) {
461                json_decref(array);
462                return -1;
463        }
464
[2c6cef7]465        if (json_dump_callback(root, og_json_dump_clients, &og_buffer, 0)) {
466                json_decref(root);
467                return -1;
468        }
469
[04ca20e]470        json_decref(root);
471
472        return 0;
473}
474
475static int og_json_parse_type(json_t *element, struct og_msg_params *params)
476{
477        const char *type;
478
479        if (json_typeof(element) != JSON_STRING)
480                return -1;
481
482        params->wol_type = json_string_value(element);
483
484        type = json_string_value(element);
485        if (!strcmp(type, "unicast"))
486                params->wol_type = "2";
487        else if (!strcmp(type, "broadcast"))
488                params->wol_type = "1";
489
490        params->flags |= OG_REST_PARAM_WOL_TYPE;
491
492        return 0;
493}
494
[1f13855]495struct og_client_wol *og_client_wol_find(const struct in_addr *addr)
496{
497        struct og_client_wol *cli_wol;
498
499        list_for_each_entry(cli_wol, &client_wol_list, list) {
500                if (cli_wol->addr.s_addr == addr->s_addr)
501                        return cli_wol;
502        }
503
504        return NULL;
505}
506
[04ca20e]507static int og_cmd_wol(json_t *element, struct og_msg_params *params)
508{
[e4cb91b]509        char ips_str[(OG_DB_IP_MAXLEN + 1) * OG_CLIENTS_MAX + 1] = {};
[1f13855]510        struct og_client_wol *cli_wol;
[e4cb91b]511        int ips_str_len = 0;
[1f13855]512        struct in_addr addr;
[e4cb91b]513        const char *msglog;
514        struct og_dbi *dbi;
515        int err = 0, i = 0;
516        dbi_result result;
[04ca20e]517        const char *key;
518        json_t *value;
519
520        if (json_typeof(element) != JSON_OBJECT)
521                return -1;
522
523        json_object_foreach(element, key, value) {
524                if (!strcmp(key, "clients")) {
[e4cb91b]525                        err = og_json_parse_clients(value, params);
[04ca20e]526                } else if (!strcmp(key, "type")) {
527                        err = og_json_parse_type(value, params);
528                }
529
530                if (err < 0)
[e7e80cd]531                        return err;
[04ca20e]532        }
533        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
534                                            OG_REST_PARAM_WOL_TYPE))
535                return -1;
536
[e4cb91b]537        for (i = 0; i < params->ips_array_len; ++i) {
538                ips_str_len += snprintf(ips_str + ips_str_len,
539                                        sizeof(ips_str) - ips_str_len,
540                                        "'%s',", params->ips_array[i]);
541        }
542        ips_str[ips_str_len - 1] = '\0';
543
544        dbi = og_dbi_open(&ogconfig.db);
545        if (!dbi) {
546                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
547                       __func__, __LINE__);
548                return -1;
549        }
550
551        result = dbi_conn_queryf(dbi->conn,
[e6c2c26]552                                 "SELECT ordenadores.ip, ordenadores.mac, "
553                                        "aulas.netmask "
554                                 "FROM   ordenadores "
555                                 "INNER JOIN aulas "
556                                         "ON ordenadores.idaula = aulas.idaula "
557                                 "WHERE  ordenadores.ip IN (%s)",
558                                 ips_str);
[e4cb91b]559        if (!result) {
560                dbi_conn_error(dbi->conn, &msglog);
561                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
562                       __func__, __LINE__, msglog);
563                og_dbi_close(dbi);
564                return -1;
565        }
566
567        for (i = 0; dbi_result_next_row(result); i++) {
568                params->ips_array[i] = dbi_result_get_string_copy(result, "ip");
569                params->mac_array[i] = dbi_result_get_string_copy(result, "mac");
[e6c2c26]570                params->netmask_array[i] = dbi_result_get_string_copy(result, "netmask");
[e4cb91b]571        }
572
573        dbi_result_free(result);
574        og_dbi_close(dbi);
575
[a71cba4]576        if (i == 0)
577                return 0;
578
[1f13855]579        for (i = 0; i < params->ips_array_len; i++) {
[927d42b]580                if (og_client_find(params->ips_array[i]))
581                        continue;
582
[1f13855]583                if (inet_aton(params->ips_array[i], &addr) < 0)
584                        return -1;
585
586                cli_wol = og_client_wol_find(&addr);
587                if (cli_wol) {
588                        og_client_wol_refresh(cli_wol);
589                        continue;
590                }
591
592                cli_wol = og_client_wol_create(&addr);
593                if (!cli_wol)
594                        return -1;
595
596                list_add_tail(&cli_wol->list, &client_wol_list);
597        }
598
[04ca20e]599        if (!Levanta((char **)params->ips_array, (char **)params->mac_array,
[a71cba4]600                     (char **)params->netmask_array, i,
[06af0c2]601                     (char *)params->wol_type))
[04ca20e]602                return -1;
603
[a46b69b]604        for (i = 0; i < params->ips_array_len; ++i) {
605                free((void *)params->ips_array[i]);
606                free((void *)params->mac_array[i]);
607                free((void *)params->netmask_array[i]);
608        }
609
[04ca20e]610        return 0;
611}
612
613static int og_json_parse_run(json_t *element, struct og_msg_params *params)
614{
615        if (json_typeof(element) != JSON_STRING)
616                return -1;
617
618        snprintf(params->run_cmd, sizeof(params->run_cmd), "%s",
619                 json_string_value(element));
620
621        params->flags |= OG_REST_PARAM_RUN_CMD;
622
623        return 0;
624}
625
626static int og_cmd_run_post(json_t *element, struct og_msg_params *params)
627{
628        json_t *value, *clients;
629        const char *key;
630        unsigned int i;
631        int err = 0;
632
633        if (json_typeof(element) != JSON_OBJECT)
634                return -1;
635
636        json_object_foreach(element, key, value) {
637                if (!strcmp(key, "clients"))
638                        err = og_json_parse_clients(value, params);
639                else if (!strcmp(key, "run"))
640                        err = og_json_parse_run(value, params);
641                else if (!strcmp(key, "echo")) {
642                        err = og_json_parse_bool(value, &params->echo);
643                        params->flags |= OG_REST_PARAM_ECHO;
644                }
645
646                if (err < 0)
[e7e80cd]647                        return err;
[04ca20e]648        }
649
650        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
651                                            OG_REST_PARAM_RUN_CMD |
652                                            OG_REST_PARAM_ECHO))
653                return -1;
654
655        clients = json_copy(element);
656        json_object_del(clients, "clients");
657
658        err = og_send_request(OG_METHOD_POST, OG_CMD_SHELL_RUN, params, clients);
659        if (err < 0)
660                return err;
661
662        for (i = 0; i < params->ips_array_len; i++) {
663                char filename[4096];
664                FILE *f;
665
666                sprintf(filename, "/tmp/_Seconsola_%s", params->ips_array[i]);
667                f = fopen(filename, "wt");
668                fclose(f);
669        }
670
671        return 0;
672}
673
674static int og_cmd_run_get(json_t *element, struct og_msg_params *params,
675                          char *buffer_reply)
676{
677        struct og_buffer og_buffer = {
678                .data   = buffer_reply,
679        };
680        json_t *root, *value, *array;
681        const char *key;
682        unsigned int i;
683        int err = 0;
684
685        if (json_typeof(element) != JSON_OBJECT)
686                return -1;
687
688        json_object_foreach(element, key, value) {
689                if (!strcmp(key, "clients"))
690                        err = og_json_parse_clients(value, params);
691
692                if (err < 0)
693                        return err;
694        }
695
696        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
697                return -1;
698
699        array = json_array();
700        if (!array)
701                return -1;
702
703        for (i = 0; i < params->ips_array_len; i++) {
704                json_t *object, *output, *addr;
705                char data[4096] = {};
706                char filename[4096];
707                int fd, numbytes;
708
709                sprintf(filename, "/tmp/_Seconsola_%s", params->ips_array[i]);
710
711                fd = open(filename, O_RDONLY);
712                if (!fd)
713                        return -1;
714
715                numbytes = read(fd, data, sizeof(data));
716                if (numbytes < 0) {
717                        close(fd);
718                        return -1;
719                }
720                data[sizeof(data) - 1] = '\0';
721                close(fd);
722
723                object = json_object();
724                if (!object) {
725                        json_decref(array);
726                        return -1;
727                }
728                addr = json_string(params->ips_array[i]);
729                if (!addr) {
730                        json_decref(object);
731                        json_decref(array);
732                        return -1;
733                }
734                json_object_set_new(object, "addr", addr);
735
736                output = json_string(data);
737                if (!output) {
738                        json_decref(object);
739                        json_decref(array);
740                        return -1;
741                }
742                json_object_set_new(object, "output", output);
743
744                json_array_append_new(array, object);
745        }
746
747        root = json_pack("{s:o}", "clients", array);
748        if (!root)
749                return -1;
750
[2c6cef7]751        if (json_dump_callback(root, og_json_dump_clients, &og_buffer, 0)) {
752                json_decref(root);
753                return -1;
754        }
755
[04ca20e]756        json_decref(root);
757
758        return 0;
759}
760
761static int og_cmd_session(json_t *element, struct og_msg_params *params)
762{
763        json_t *clients, *value;
764        const char *key;
765        int err = 0;
766
767        if (json_typeof(element) != JSON_OBJECT)
768                return -1;
769
770        json_object_foreach(element, key, value) {
771                if (!strcmp(key, "clients")) {
772                        err = og_json_parse_clients(value, params);
773                } else if (!strcmp(key, "disk")) {
774                        err = og_json_parse_string(value, &params->disk);
775                        params->flags |= OG_REST_PARAM_DISK;
776                } else if (!strcmp(key, "partition")) {
777                        err = og_json_parse_string(value, &params->partition);
778                        params->flags |= OG_REST_PARAM_PARTITION;
779                }
780
781                if (err < 0)
782                        return err;
783        }
784
785        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
786                                            OG_REST_PARAM_DISK |
787                                            OG_REST_PARAM_PARTITION))
788                return -1;
789
790        clients = json_copy(element);
791        json_object_del(clients, "clients");
792
793        return og_send_request(OG_METHOD_POST, OG_CMD_SESSION, params, clients);
794}
795
[7f5ab4a]796static int og_cmd_get_session(json_t *element, struct og_msg_params *params,
797                              char *buffer_reply)
798{
799        json_t *value, *root, *array, *item;
800        const char *key, *msglog, *os_name;
801        unsigned int disk, partition;
802        struct og_dbi *dbi;
803        dbi_result result;
804        int err = 0;
805
806        struct og_buffer og_buffer = {
807                .data = buffer_reply
808        };
809
810        json_object_foreach(element, key, value) {
811                if (!strcmp(key, "client"))
812                        err = og_json_parse_clients(value, params);
813                else
814                        err = -1;
815
816                if (err < 0)
817                        return err;
818        }
819
820        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
821                return -1;
822
823        dbi = og_dbi_open(&ogconfig.db);
824        if (!dbi) {
825                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
826                       __func__, __LINE__);
827                return -1;
828        }
829
830        result = dbi_conn_queryf(dbi->conn,
831                                 "SELECT op.numdisk, op.numpar, nom.nombreso "
832                                 "FROM ordenadores o "
833                                 "INNER JOIN ordenadores_particiones op "
834                                 "    ON o.idordenador = op.idordenador "
835                                 "INNER JOIN nombresos nom "
836                                 "    ON op.idnombreso = nom.idnombreso "
837                                 "WHERE o.ip = '%s'",
838                                 params->ips_array[0]);
839        if (!result) {
840                dbi_conn_error(dbi->conn, &msglog);
841                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
842                       __func__, __LINE__, msglog);
843                og_dbi_close(dbi);
844                return -1;
845        }
846
847        array = json_array();
848        if (!array) {
849                dbi_result_free(result);
850                og_dbi_close(dbi);
851                return -1;
852        }
853
854        while (dbi_result_next_row(result)) {
855                item = json_object();
856                if (!item) {
857                        dbi_result_free(result);
858                        og_dbi_close(dbi);
859                        json_decref(array);
860                        return -1;
861                }
862
863                disk = dbi_result_get_uint(result, "numdisk");
864                partition = dbi_result_get_uint(result, "numpar");
865                os_name = dbi_result_get_string(result, "nombreso");
866
867                json_object_set_new(item, "disk", json_integer(disk));
868                json_object_set_new(item, "partition", json_integer(partition));
869                json_object_set_new(item, "name", json_string(os_name));
870                json_array_append_new(array, item);
871        }
872
873        dbi_result_free(result);
874        og_dbi_close(dbi);
875
876        root = json_object();
877        if (!root){
878                json_decref(array);
879                return -1;
880        }
881
882        json_object_set_new(root, "sessions", array);
883
[2c6cef7]884        if (json_dump_callback(root, og_json_dump_clients, &og_buffer, 0)) {
885                json_decref(root);
886                return -1;
887        }
888
[7f5ab4a]889        json_decref(root);
890        return 0;
891}
892
[04ca20e]893static int og_cmd_poweroff(json_t *element, struct og_msg_params *params)
894{
895        const char *key;
896        json_t *value;
897        int err = 0;
898
899        if (json_typeof(element) != JSON_OBJECT)
900                return -1;
901
902        json_object_foreach(element, key, value) {
903                if (!strcmp(key, "clients"))
904                        err = og_json_parse_clients(value, params);
905
906                if (err < 0)
[e7e80cd]907                        return err;
[04ca20e]908        }
909
910        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
911                return -1;
912
913        return og_send_request(OG_METHOD_POST, OG_CMD_POWEROFF, params, NULL);
914}
915
916static int og_cmd_refresh(json_t *element, struct og_msg_params *params)
917{
918        const char *key;
919        json_t *value;
920        int err = 0;
921
922        if (json_typeof(element) != JSON_OBJECT)
923                return -1;
924
925        json_object_foreach(element, key, value) {
926                if (!strcmp(key, "clients"))
927                        err = og_json_parse_clients(value, params);
928
929                if (err < 0)
[e7e80cd]930                        return err;
[04ca20e]931        }
932
933        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
934                return -1;
935
936        return og_send_request(OG_METHOD_GET, OG_CMD_REFRESH, params, NULL);
937}
938
939static int og_cmd_reboot(json_t *element, struct og_msg_params *params)
940{
941        const char *key;
942        json_t *value;
943        int err = 0;
944
945        if (json_typeof(element) != JSON_OBJECT)
946                return -1;
947
948        json_object_foreach(element, key, value) {
949                if (!strcmp(key, "clients"))
950                        err = og_json_parse_clients(value, params);
951
952                if (err < 0)
[e7e80cd]953                        return err;
[04ca20e]954        }
955
956        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
957                return -1;
958
959        return og_send_request(OG_METHOD_POST, OG_CMD_REBOOT, params, NULL);
960}
961
[85d0928]962#define OG_TFTP_TMPL_PATH_UEFI "/opt/opengnsys/tftpboot/grub/templates"
[608709f]963#define OG_TFTP_TMPL_PATH "/opt/opengnsys/tftpboot/menu.lst/templates"
964
965static int og_cmd_get_modes(json_t *element, struct og_msg_params *params,
966                            char *buffer_reply)
967{
968        struct og_buffer og_buffer = {
969                .data = buffer_reply
970        };
971        json_t *root, *modes;
972        struct dirent *dent;
973        DIR *d = NULL;
974
975        root = json_object();
976        if (!root)
977                return -1;
978
979        modes = json_array();
980        if (!modes) {
981                json_decref(root);
982                return -1;
983        }
984
985        d = opendir(OG_TFTP_TMPL_PATH);
986        if (!d) {
987                json_decref(modes);
988                json_decref(root);
989                syslog(LOG_ERR, "Cannot open directory %s\n",
990                       OG_TFTP_TMPL_PATH);
991                return -1;
992        }
993
994        dent = readdir(d);
995        while (dent) {
996                if (dent->d_type != DT_REG) {
997                        dent = readdir(d);
998                        continue;
999                }
1000                json_array_append_new(modes, json_string(dent->d_name));
1001                dent = readdir(d);
1002        }
1003        json_object_set_new(root, "modes", modes);
[2c6cef7]1004
1005        if (json_dump_callback(root, og_json_dump_clients, &og_buffer, 0)) {
1006                json_decref(root);
1007                return -1;
1008        }
1009
[608709f]1010        json_decref(root);
[e54c5ca]1011        closedir(d);
[608709f]1012
1013        return 0;
1014}
1015
[532b081]1016static int og_change_db_mode(struct og_dbi *dbi, const char *mac,
1017                             const char * mode)
1018{
1019        const char *msglog;
1020        dbi_result result;
1021
1022        result = dbi_conn_queryf(dbi->conn,
1023                                 "UPDATE ordenadores SET arranque='%s' "
1024                                 "WHERE mac='%s'",
1025                                 mode, mac);
1026
1027        if (!result) {
1028                dbi_conn_error(dbi->conn, &msglog);
1029                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1030                       __func__, __LINE__, msglog);
1031                return -1;
1032        }
1033
1034        dbi_result_free(result);
1035        return 0;
1036}
1037
1038static int og_set_client_mode(struct og_dbi *dbi, const char *mac,
[4ae9903]1039                              const char *mode, const char *template_name)
[532b081]1040{
1041        char filename[PATH_MAX + 1] = "/tmp/mode_params_XXXXXX";
[1855b68]1042        char cmd_params[16384] = {};
1043        char params[4096] = "\0";
[532b081]1044        const char *msglog;
1045        dbi_result result;
1046        unsigned int i;
1047        int numbytes;
[139633a]1048        int status;
[532b081]1049        int fd;
1050
1051        result = dbi_conn_queryf(dbi->conn,
1052                "SELECT ' LANG=%s', ' ip=', CONCAT_WS(':', ordenadores.ip, (SELECT (@serverip:=ipserveradm) FROM entornos LIMIT 1), aulas.router, aulas.netmask, ordenadores.nombreordenador, ordenadores.netiface, 'none'), ' group=', REPLACE(TRIM(aulas.nombreaula), ' ', '_'), ' ogrepo=', (@repoip:=IFNULL(repositorios.ip, '')), ' oglive=', @serverip, ' oglog=', @serverip, ' ogshare=', @serverip, ' oglivedir=', ordenadores.oglivedir, ' ogprof=', IF(ordenadores.idordenador=aulas.idordprofesor, 'true', 'false'), IF(perfileshard.descripcion<>'', CONCAT(' hardprofile=', REPLACE(TRIM(perfileshard.descripcion), ' ', '_')), ''), IF(aulas.ntp<>'', CONCAT(' ogntp=', aulas.ntp), ''), IF(aulas.dns<>'', CONCAT(' ogdns=', aulas.dns), ''), IF(aulas.proxy<>'', CONCAT(' ogproxy=', aulas.proxy), ''), IF(entidades.ogunit=1 AND NOT centros.directorio='', CONCAT(' ogunit=', centros.directorio), ''), CASE WHEN menus.resolucion IS NULL THEN '' WHEN menus.resolucion <= '999' THEN CONCAT(' vga=', menus.resolucion) WHEN menus.resolucion LIKE '%:%' THEN CONCAT(' video=', menus.resolucion) ELSE menus.resolucion END FROM ordenadores JOIN aulas USING(idaula) JOIN centros USING(idcentro) JOIN entidades USING(identidad) LEFT JOIN repositorios USING(idrepositorio) LEFT JOIN perfileshard USING(idperfilhard) LEFT JOIN menus USING(idmenu) WHERE ordenadores.mac='%s'", getenv("LANG"), mac);
1053
1054        if (dbi_result_get_numrows(result) != 1) {
1055                dbi_conn_error(dbi->conn, &msglog);
1056                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1057                       __FILE__, __LINE__, msglog);
1058                dbi_result_free(result);
1059                return -1;
1060        }
1061        dbi_result_next_row(result);
1062
1063        for (i = 1; i <= dbi_result_get_numfields(result); ++i)
1064                strcat(params, dbi_result_get_string_idx(result, i));
1065
1066        dbi_result_free(result);
1067
1068        snprintf(cmd_params, sizeof(cmd_params),
1069                 "MODE_FILE='%s'\nMAC='%s'\nDATA='%s'\n"
1070                 "MODE='PERM'\nTEMPLATE_NAME='%s'",
1071                 mode, mac, params, template_name);
1072
1073        fd = mkstemp(filename);
1074        if (fd < 0) {
1075                syslog(LOG_ERR, "cannot generate temp file (%s:%d)\n",
1076                       __func__, __LINE__);
1077                return -1;
1078        }
1079
1080        numbytes = write(fd, cmd_params, strlen(cmd_params) + 1);
1081        close(fd);
1082
1083        if (numbytes < 0) {
1084                syslog(LOG_ERR, "cannot write file\n");
1085                unlink(filename);
1086                return -1;
1087        }
1088
[139633a]1089        if (fork() == 0) {
1090                execlp("/bin/bash", "/bin/bash",
1091                       "/opt/opengnsys/bin/setclientmode", filename, NULL);
[5286c93]1092                syslog(LOG_ERR, "failed script execution (%s:%d)\n",
1093                       __func__, __LINE__);
1094                exit(EXIT_FAILURE);
[139633a]1095        } else {
1096                wait(&status);
1097        }
[532b081]1098        unlink(filename);
[139633a]1099
1100        if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
[532b081]1101                syslog(LOG_ERR, "failed script execution (%s:%d)\n",
1102                       __func__, __LINE__);
1103                return -1;
1104        }
1105
1106        if (og_change_db_mode(dbi, mac, mode) < 0) {
1107                syslog(LOG_ERR, "failed to change db mode (%s:%d)\n",
1108                       __func__, __LINE__);
1109                return -1;
1110        }
1111
1112        return 0;
1113}
1114
[33b0c6f]1115static int og_cmd_post_modes(json_t *element, struct og_msg_params *params)
1116{
[4ae9903]1117        char ips_str[(OG_DB_IP_MAXLEN + 1) * OG_CLIENTS_MAX + 1] = {};
[85d0928]1118        char template_file_uefi[PATH_MAX + 1] = {};
[532b081]1119        char template_file[PATH_MAX + 1] = {};
1120        char template_name[PATH_MAX + 1] = {};
1121        char first_line[PATH_MAX + 1] = {};
[4ae9903]1122        const char *mode_str, *mac;
1123        int ips_str_len = 0;
[33b0c6f]1124        struct og_dbi *dbi;
1125        uint64_t flags = 0;
1126        dbi_result result;
1127        const char *key;
1128        json_t *value;
1129        int err = 0;
[532b081]1130        FILE *f;
[4ae9903]1131        int i;
[33b0c6f]1132
1133        json_object_foreach(element, key, value) {
[4ae9903]1134                if (!strcmp(key, "clients")) {
1135                        err = og_json_parse_clients(value, params);
[33b0c6f]1136                } else if (!strcmp(key, "mode")) {
1137                        err = og_json_parse_string(value, &mode_str);
1138                        flags |= OG_REST_PARAM_MODE;
1139                } else {
1140                        err = -1;
1141                }
1142
1143                if (err < 0)
[e7e80cd]1144                        return err;
[33b0c6f]1145        }
1146
[4ae9903]1147        if (!og_flags_validate(flags, OG_REST_PARAM_MODE) ||
1148            !og_msg_params_validate(params, OG_REST_PARAM_ADDR))
[33b0c6f]1149                return -1;
1150
[532b081]1151        snprintf(template_file, sizeof(template_file), "%s/%s",
1152                 OG_TFTP_TMPL_PATH, mode_str);
1153        f = fopen(template_file, "r");
1154        if (!f) {
[85d0928]1155                syslog(LOG_WARNING, "cannot open file %s (%s:%d). Trying UEFI template instead.\n",
1156                       template_file, __func__, __LINE__);
1157
1158                snprintf(template_file_uefi, sizeof(template_file_uefi), "%s/%s",
1159                         OG_TFTP_TMPL_PATH_UEFI, mode_str);
1160                f = fopen(template_file_uefi, "r");
1161                if (!f) {
1162                        syslog(LOG_ERR, "cannot open file %s (%s:%d). No template found.\n",
1163                               template_file_uefi, __func__, __LINE__);
1164                        return -1;
1165                }
[33b0c6f]1166        }
1167
[532b081]1168        if (!fgets(first_line, sizeof(first_line), f)) {
1169                fclose(f);
1170                syslog(LOG_ERR, "cannot read file (%s:%d)\n",
[33b0c6f]1171                       __func__, __LINE__);
1172                return -1;
1173        }
1174
[532b081]1175        fclose(f);
1176
1177        if (sscanf(first_line, "##NO-TOCAR-ESTA-LINEA %s", template_name) != 1) {
1178                syslog(LOG_ERR, "malformed template: %s", first_line);
1179                return -1;
1180        }
1181
[4ae9903]1182        for (i = 0; i < params->ips_array_len; ++i) {
1183                ips_str_len += snprintf(ips_str + ips_str_len,
1184                                        sizeof(ips_str) - ips_str_len,
1185                                        "'%s',", params->ips_array[i]);
1186        }
1187        ips_str[ips_str_len - 1] = '\0';
1188
[fe1ce97]1189        dbi = og_dbi_open(&ogconfig.db);
[532b081]1190        if (!dbi) {
1191                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
1192                       __func__, __LINE__);
[33b0c6f]1193                return -1;
1194        }
1195
[532b081]1196        result = dbi_conn_queryf(dbi->conn,
1197                                 "SELECT mac FROM ordenadores "
[4ae9903]1198                                 "WHERE ip IN (%s)", ips_str);
[532b081]1199
1200        while (dbi_result_next_row(result)) {
1201                mac = dbi_result_get_string(result, "mac");
[4ae9903]1202                err = og_set_client_mode(dbi, mac, mode_str, template_name);
[532b081]1203                if (err != 0) {
1204                        dbi_result_free(result);
1205                        og_dbi_close(dbi);
1206                        return -1;
1207                }
1208        }
1209
[33b0c6f]1210        dbi_result_free(result);
1211        og_dbi_close(dbi);
1212
1213        return 0;
1214}
1215
[b59ff7c]1216static int og_cmd_get_client_setup(json_t *element,
1217                                   struct og_msg_params *params,
1218                                   char *buffer_reply)
1219{
1220        json_t *value, *root, *partitions_array, *partition_json;
1221        const char *key, *msglog;
1222        unsigned int len_part;
1223        struct og_dbi *dbi;
1224        dbi_result result;
1225        int err = 0;
1226
1227        struct og_buffer og_buffer = {
1228                .data = buffer_reply
1229        };
1230
1231        struct {
1232                int disk;
1233                int number;
1234                int code;
[4d2e1dd]1235                uint64_t size;
[b59ff7c]1236                int filesystem;
1237                int format;
1238                int os;
1239                int used_size;
1240                int image;
1241                int software;
1242        } partition;
1243
1244        json_object_foreach(element, key, value) {
1245                if (!strcmp(key, "client")) {
1246                        err = og_json_parse_clients(value, params);
1247                }
1248
1249                if (err < 0)
[e7e80cd]1250                        return err;
[b59ff7c]1251        }
1252
1253        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
1254                return -1;
1255
1256        if (params->ips_array_len != 1)
1257                return -1;
1258
1259        root = json_object();
1260        if (!root)
1261                return -1;
1262
1263        partitions_array = json_array();
1264        if (!partitions_array) {
1265                json_decref(root);
1266                return -1;
1267        }
1268        json_object_set_new(root, "partitions", partitions_array);
1269
[fe1ce97]1270        dbi = og_dbi_open(&ogconfig.db);
[b59ff7c]1271        if (!dbi) {
1272                json_decref(root);
1273                syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
1274                       __func__, __LINE__);
1275                return -1;
1276        }
1277
1278        result = dbi_conn_queryf(dbi->conn,
1279                                 "SELECT numdisk, numpar, codpar, tamano, "
1280                                 "       uso, idsistemafichero, idnombreso, "
1281                                 "       idimagen, idperfilsoft "
1282                                 "FROM ordenadores_particiones "
1283                                 "INNER JOIN ordenadores "
1284                                 "ON ordenadores.idordenador = ordenadores_particiones.idordenador "
1285                                 "WHERE ordenadores.ip='%s'",
1286                                 params->ips_array[0]);
1287        if (!result) {
1288                json_decref(root);
1289                dbi_conn_error(dbi->conn, &msglog);
1290                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1291                       __func__, __LINE__, msglog);
1292                og_dbi_close(dbi);
1293                return -1;
1294        }
1295
1296        len_part = 0;
[ff71a2a]1297        /* partition 0 represents the full disk, hence OG_PARTITION_MAX + 1. */
1298        while (dbi_result_next_row(result) && len_part < OG_PARTITION_MAX + 1) {
[b59ff7c]1299                partition.disk = dbi_result_get_int(result, "numdisk");
1300                partition.number = dbi_result_get_int(result, "numpar");
1301                partition.code = dbi_result_get_int(result, "codpar");
[4d2e1dd]1302                partition.size = dbi_result_get_longlong(result, "tamano");
[b59ff7c]1303                partition.used_size = dbi_result_get_int(result, "uso");
1304                partition.filesystem = dbi_result_get_int(result, "idsistemafichero");
1305                partition.os = dbi_result_get_int(result, "idnombreso");
1306                partition.image = dbi_result_get_int(result, "idimagen");
1307                partition.software = dbi_result_get_int(result, "idperfilsoft");
1308
1309                partition_json = json_object();
1310                if (!partition_json) {
1311                        json_decref(root);
1312                        dbi_result_free(result);
1313                        og_dbi_close(dbi);
1314                        return -1;
1315                }
1316
1317                json_object_set_new(partition_json, "disk",
1318                                    json_integer(partition.disk));
1319                json_object_set_new(partition_json, "partition",
1320                                    json_integer(partition.number));
1321                json_object_set_new(partition_json, "code",
1322                                    json_integer(partition.code));
1323                json_object_set_new(partition_json, "size",
1324                                    json_integer(partition.size));
1325                json_object_set_new(partition_json, "used_size",
1326                                    json_integer(partition.used_size));
1327                json_object_set_new(partition_json, "filesystem",
1328                                    json_integer(partition.filesystem));
1329                json_object_set_new(partition_json, "os",
1330                                    json_integer(partition.os));
1331                json_object_set_new(partition_json, "image",
1332                                    json_integer(partition.image));
1333                json_object_set_new(partition_json, "software",
1334                                    json_integer(partition.software));
1335                json_array_append_new(partitions_array, partition_json);
1336
1337                ++len_part;
1338        }
1339
1340        dbi_result_free(result);
1341        og_dbi_close(dbi);
1342
[2c6cef7]1343        if (json_dump_callback(root, og_json_dump_clients, &og_buffer, 0)) {
1344                json_decref(root);
1345                return -1;
1346        }
1347
[b59ff7c]1348        json_decref(root);
1349        return 0;
1350}
1351
[af47a08]1352static int og_cmd_get_client_info(json_t *element,
1353                                  struct og_msg_params *params,
1354                                  char *buffer_reply)
1355{
1356        struct og_computer computer = {};
1357        json_t *value, *root;
1358        struct in_addr addr;
1359        struct og_dbi *dbi;
1360        const char *key;
1361        int err = 0;
1362
1363        struct og_buffer og_buffer = {
1364                .data = buffer_reply
1365        };
1366
1367        json_object_foreach(element, key, value) {
1368                if (!strcmp(key, "client")) {
1369                        err = og_json_parse_clients(value, params);
1370                }
1371
1372                if (err < 0)
[e7e80cd]1373                        return err;
[af47a08]1374        }
1375
1376        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
1377                return -1;
1378
1379        if (params->ips_array_len != 1)
1380                return -1;
1381
1382        if (inet_aton(params->ips_array[0], &addr) == 0)
1383                return -1;
1384
[fe1ce97]1385        dbi = og_dbi_open(&ogconfig.db);
[af47a08]1386        if (!dbi) {
1387                syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
1388                       __func__, __LINE__);
1389                return -1;
1390        }
1391
1392        if (og_dbi_get_computer_info(dbi, &computer, addr)) {
1393                og_dbi_close(dbi);
1394                return -1;
1395        }
1396
1397        og_dbi_close(dbi);
1398
1399        root = json_object();
1400        if (!root)
1401                return -1;
1402
1403        json_object_set_new(root, "serial_number",
1404                            json_string(computer.serial_number));
1405        json_object_set_new(root, "hardware_id",
1406                            json_integer(computer.hardware_id));
1407        json_object_set_new(root, "netdriver", json_string(computer.netdriver));
1408        json_object_set_new(root, "maintenance", json_boolean(computer.name));
1409        json_object_set_new(root, "netiface", json_string(computer.netiface));
1410        json_object_set_new(root, "repo_id", json_integer(computer.repo_id));
1411        json_object_set_new(root, "livedir", json_string(computer.livedir));
1412        json_object_set_new(root, "netmask", json_string(computer.netmask));
1413        json_object_set_new(root, "center", json_integer(computer.center));
1414        json_object_set_new(root, "remote", json_boolean(computer.remote));
1415        json_object_set_new(root, "room", json_integer(computer.room));
1416        json_object_set_new(root, "name", json_string(computer.name));
1417        json_object_set_new(root, "boot", json_string(computer.boot));
1418        json_object_set_new(root, "mac", json_string(computer.mac));
1419        json_object_set_new(root, "id", json_integer(computer.id));
1420        json_object_set_new(root, "ip", json_string(computer.ip));
1421
[2c6cef7]1422        if (json_dump_callback(root, og_json_dump_clients, &og_buffer, 0)) {
1423                json_decref(root);
1424                return -1;
1425        }
1426
[af47a08]1427        json_decref(root);
1428        return 0;
1429}
1430
[65a14e5]1431static int og_cmd_post_client_add(json_t *element,
1432                                  struct og_msg_params *params,
1433                                  char *buffer_reply)
1434{
1435        struct og_computer computer = {};
[f537daf]1436        const char *key, *msglog;
[65a14e5]1437        struct og_dbi *dbi;
1438        dbi_result result;
1439        json_t *value;
1440        int err = 0;
1441
1442        json_object_foreach(element, key, value) {
1443                if (!strcmp(key, "serial_number")) {
[f537daf]1444                        err = og_json_parse_string_copy(value,
1445                                                        computer.serial_number,
1446                                                        sizeof(computer.serial_number));
[65a14e5]1447                } else if (!strcmp(key, "hardware_id")) {
1448                        err = og_json_parse_uint(value, &computer.hardware_id);
1449                } else if (!strcmp(key, "netdriver")) {
[f537daf]1450                        err = og_json_parse_string_copy(value,
1451                                                        computer.netdriver,
1452                                                        sizeof(computer.netdriver));
[65a14e5]1453                } else if (!strcmp(key, "maintenance")) {
1454                        err = og_json_parse_bool(value, &computer.maintenance);
1455                } else if (!strcmp(key, "netiface")) {
[f537daf]1456                        err = og_json_parse_string_copy(value,
1457                                                        computer.netiface,
1458                                                        sizeof(computer.netiface));
[65a14e5]1459                } else if (!strcmp(key, "repo_id")) {
1460                        err = og_json_parse_uint(value, &computer.repo_id);
1461                } else if (!strcmp(key, "livedir")) {
[f537daf]1462                        err = og_json_parse_string_copy(value,
1463                                                        computer.livedir,
1464                                                        sizeof(computer.livedir));
[65a14e5]1465                } else if (!strcmp(key, "netmask")) {
[f537daf]1466                        err = og_json_parse_string_copy(value,
1467                                                        computer.netmask,
1468                                                        sizeof(computer.netmask));
[65a14e5]1469                } else if (!strcmp(key, "remote")) {
1470                        err = og_json_parse_bool(value, &computer.remote);
1471                } else if (!strcmp(key, "room")) {
1472                        err = og_json_parse_uint(value, &computer.room);
1473                } else if (!strcmp(key, "name")) {
[f537daf]1474                        err = og_json_parse_string_copy(value,
1475                                                        computer.name,
1476                                                        sizeof(computer.name));
[65a14e5]1477                } else if (!strcmp(key, "boot")) {
[f537daf]1478                        err = og_json_parse_string_copy(value,
1479                                                        computer.boot,
1480                                                        sizeof(computer.boot));
[65a14e5]1481                } else if (!strcmp(key, "mac")) {
[f537daf]1482                        err = og_json_parse_string_copy(value,
1483                                                        computer.mac,
1484                                                        sizeof(computer.mac));
[65a14e5]1485                } else if (!strcmp(key, "ip")) {
[f537daf]1486                        err = og_json_parse_string_copy(value,
1487                                                        computer.ip,
1488                                                        sizeof(computer.ip));
[65a14e5]1489                }
1490
1491                if (err < 0)
[e7e80cd]1492                        return err;
[65a14e5]1493        }
1494
[fe1ce97]1495        dbi = og_dbi_open(&ogconfig.db);
[65a14e5]1496        if (!dbi) {
1497                syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
1498                       __func__, __LINE__);
1499                return -1;
1500        }
1501
1502        result = dbi_conn_queryf(dbi->conn,
1503                                 "SELECT ip FROM ordenadores WHERE ip='%s'",
1504                                 computer.ip);
1505
1506        if (!result) {
1507                dbi_conn_error(dbi->conn, &msglog);
1508                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1509                       __func__, __LINE__, msglog);
1510                og_dbi_close(dbi);
1511                return -1;
1512        }
1513
1514        if (dbi_result_get_numrows(result) > 0) {
1515                syslog(LOG_ERR, "client with the same IP already exists: %s\n",
1516                       computer.ip);
1517                dbi_result_free(result);
1518                og_dbi_close(dbi);
1519                return -1;
1520        }
1521        dbi_result_free(result);
1522
1523        result = dbi_conn_queryf(dbi->conn,
1524                                 "INSERT INTO ordenadores("
1525                                 "  nombreordenador,"
1526                                 "  numserie,"
1527                                 "  ip,"
1528                                 "  mac,"
1529                                 "  idaula,"
1530                                 "  idperfilhard,"
1531                                 "  idrepositorio,"
1532                                 "  mascara,"
1533                                 "  arranque,"
1534                                 "  netiface,"
1535                                 "  netdriver,"
1536                                 "  oglivedir,"
1537                                 "  inremotepc,"
1538                                 "  maintenance"
1539                                 ") VALUES ('%s', '%s', '%s', '%s', %u, %u,"
1540                                 "           %u, '%s', '%s', '%s', '%s',"
1541                                 "          '%s', %u, %u)",
1542                                 computer.name, computer.serial_number,
1543                                 computer.ip, computer.mac, computer.room,
1544                                 computer.hardware_id, computer.repo_id,
1545                                 computer.netmask, computer.boot,
1546                                 computer.netiface, computer.netdriver,
1547                                 computer.livedir, computer.remote,
1548                                 computer.maintenance);
1549
1550        if (!result) {
1551                dbi_conn_error(dbi->conn, &msglog);
1552                syslog(LOG_ERR, "failed to add client to database (%s:%d) %s\n",
1553                       __func__, __LINE__, msglog);
1554                og_dbi_close(dbi);
1555                return -1;
1556        }
1557
1558        dbi_result_free(result);
1559        og_dbi_close(dbi);
1560        return 0;
1561}
1562
[24c8b94]1563static int og_cmd_post_client_delete(json_t *element,
1564                                     struct og_msg_params *params)
1565{
1566        const char *key, *msglog;
1567        struct og_dbi *dbi;
1568        dbi_result result;
1569        unsigned int i;
1570        json_t *value;
1571        int err = 0;
1572
1573        json_object_foreach(element, key, value) {
1574                if (!strcmp(key, "clients"))
1575                        err = og_json_parse_clients(value, params);
1576
1577                if (err < 0)
[e7e80cd]1578                        return err;
[24c8b94]1579        }
1580
1581        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
1582                return -1;
1583
1584        dbi = og_dbi_open(&ogconfig.db);
1585        if (!dbi) {
1586                syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
1587                       __func__, __LINE__);
1588                return -1;
1589        }
1590
1591        for (i = 0; i < params->ips_array_len; i++) {
1592                result = dbi_conn_queryf(dbi->conn,
1593                                         "DELETE FROM ordenadores WHERE ip='%s'",
1594                                         params->ips_array[i]);
1595
1596                if (!result) {
1597                        dbi_conn_error(dbi->conn, &msglog);
1598                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1599                               __func__, __LINE__, msglog);
1600                        og_dbi_close(dbi);
1601                        return -1;
1602                }
1603
1604                dbi_result_free(result);
1605        }
1606
1607        og_dbi_close(dbi);
1608        return 0;
1609}
1610
[04ca20e]1611static int og_cmd_stop(json_t *element, struct og_msg_params *params)
1612{
1613        const char *key;
1614        json_t *value;
1615        int err = 0;
1616
1617        if (json_typeof(element) != JSON_OBJECT)
1618                return -1;
1619
1620        json_object_foreach(element, key, value) {
1621                if (!strcmp(key, "clients"))
1622                        err = og_json_parse_clients(value, params);
1623
1624                if (err < 0)
[e7e80cd]1625                        return err;
[04ca20e]1626        }
1627
1628        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
1629                return -1;
1630
1631        return og_send_request(OG_METHOD_POST, OG_CMD_STOP, params, NULL);
1632}
1633
1634static int og_cmd_hardware(json_t *element, struct og_msg_params *params)
1635{
1636        const char *key;
1637        json_t *value;
1638        int err = 0;
1639
1640        if (json_typeof(element) != JSON_OBJECT)
1641                return -1;
1642
1643        json_object_foreach(element, key, value) {
1644                if (!strcmp(key, "clients"))
1645                        err = og_json_parse_clients(value, params);
1646
1647                if (err < 0)
[e7e80cd]1648                        return err;
[04ca20e]1649        }
1650
1651        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
1652                return -1;
1653
1654        return og_send_request(OG_METHOD_GET, OG_CMD_HARDWARE, params, NULL);
1655}
1656
[a8eccba]1657static int og_cmd_get_hardware(json_t *element, struct og_msg_params *params,
1658                               char *buffer_reply)
1659{
1660        const char *key, *msglog, *hw_item, *hw_type;
1661        json_t *value, *root, *array, *item;
1662        struct og_dbi *dbi;
1663        dbi_result result;
1664        int err = 0;
1665
1666        struct og_buffer og_buffer = {
1667                .data = buffer_reply
1668        };
1669
1670        json_object_foreach(element, key, value) {
[2958d23]1671                if (!strcmp(key, "client"))
1672                        err = og_json_parse_clients(value, params);
[a8eccba]1673
1674                if (err < 0)
1675                        return err;
1676        }
1677
[2958d23]1678        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
[a8eccba]1679                return -1;
1680
[fe1ce97]1681        dbi = og_dbi_open(&ogconfig.db);
[a8eccba]1682        if (!dbi) {
1683                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
1684                       __func__, __LINE__);
1685                return -1;
1686        }
1687
1688        result = dbi_conn_queryf(dbi->conn,
1689                                 "SELECT hardwares.descripcion AS item, "
1690                                 "       tipohardwares.descripcion AS type "
1691                                 "FROM hardwares "
1692                                 "INNER JOIN perfileshard_hardwares "
1693                                 "    ON hardwares.idhardware = perfileshard_hardwares.idhardware "
1694                                 "INNER JOIN ordenadores "
1695                                 "    ON perfileshard_hardwares.idperfilhard = ordenadores.idperfilhard "
1696                                 "INNER JOIN tipohardwares "
1697                                 "    ON hardwares.idtipohardware = tipohardwares.idtipohardware "
[2958d23]1698                                 "WHERE ordenadores.ip = '%s'",
1699                                 params->ips_array[0]);
[a8eccba]1700        if (!result) {
1701                dbi_conn_error(dbi->conn, &msglog);
1702                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1703                       __func__, __LINE__, msglog);
1704                og_dbi_close(dbi);
1705                return -1;
1706        }
1707
1708        array = json_array();
1709        if (!array) {
1710                dbi_result_free(result);
1711                og_dbi_close(dbi);
1712                return -1;
1713        }
1714
1715        while (dbi_result_next_row(result)) {
1716                item = json_object();
1717                if (!item) {
1718                        dbi_result_free(result);
1719                        og_dbi_close(dbi);
1720                        json_decref(array);
1721                        return -1;
1722                }
1723
1724                hw_item = dbi_result_get_string(result, "item");
1725                hw_type = dbi_result_get_string(result, "type");
1726
1727                json_object_set_new(item, "type", json_string(hw_type));
1728                json_object_set_new(item, "description", json_string(hw_item));
1729                json_array_append_new(array, item);
1730        }
1731
1732        dbi_result_free(result);
1733        og_dbi_close(dbi);
1734
1735        root = json_object();
1736        if (!root){
1737                json_decref(array);
1738                return -1;
1739        }
1740
1741        json_object_set_new(root, "hardware", array);
1742
[2c6cef7]1743        if (json_dump_callback(root, og_json_dump_clients, &og_buffer, 0)) {
1744                json_decref(root);
1745                return -1;
1746        }
1747
[a8eccba]1748        json_decref(root);
1749        return 0;
1750}
1751
[04ca20e]1752static int og_cmd_software(json_t *element, struct og_msg_params *params)
1753{
1754        json_t *clients, *value;
1755        const char *key;
1756        int err = 0;
1757
1758        if (json_typeof(element) != JSON_OBJECT)
1759                return -1;
1760
1761        json_object_foreach(element, key, value) {
1762                if (!strcmp(key, "clients"))
1763                        err = og_json_parse_clients(value, params);
1764                else if (!strcmp(key, "disk")) {
1765                        err = og_json_parse_string(value, &params->disk);
1766                        params->flags |= OG_REST_PARAM_DISK;
1767                }
1768                else if (!strcmp(key, "partition")) {
1769                        err = og_json_parse_string(value, &params->partition);
1770                        params->flags |= OG_REST_PARAM_PARTITION;
1771                }
1772
1773                if (err < 0)
[e7e80cd]1774                        return err;
[04ca20e]1775        }
1776
1777        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
1778                                            OG_REST_PARAM_DISK |
1779                                            OG_REST_PARAM_PARTITION))
1780                return -1;
1781
1782        clients = json_copy(element);
1783        json_object_del(clients, "clients");
1784
[8d91456]1785        return og_send_request(OG_METHOD_GET, OG_CMD_SOFTWARE, params, clients);
[04ca20e]1786}
1787
[25c1c16]1788static int og_cmd_get_software(json_t *element, struct og_msg_params *params,
1789                               char *buffer_reply)
1790{
1791        json_t *value, *software, *root;
1792        const char *key, *msglog, *name;
1793        uint64_t disk, partition;
1794        uint64_t flags = 0;
1795        struct og_dbi *dbi;
1796        dbi_result result;
1797        int err = 0;
1798
1799        struct og_buffer og_buffer = {
1800                .data = buffer_reply
1801        };
1802
1803        if (json_typeof(element) != JSON_OBJECT)
1804                return -1;
1805
1806        json_object_foreach(element, key, value) {
1807                if (!strcmp(key, "client")) {
1808                        err = og_json_parse_clients(value, params);
1809                } else if (!strcmp(key, "disk")) {
1810                        err = og_json_parse_uint64(value, &disk);
1811                        flags |= OG_REST_PARAM_DISK;
1812                } else if (!strcmp(key, "partition")) {
1813                        err = og_json_parse_uint64(value, &partition);
1814                        flags |= OG_REST_PARAM_PARTITION;
1815                }
1816
1817                if (err < 0)
[e7e80cd]1818                        return err;
[25c1c16]1819        }
1820
1821        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR) ||
1822            !og_flags_validate(flags, OG_REST_PARAM_DISK |
1823                                      OG_REST_PARAM_PARTITION))
1824                return -1;
1825
1826        dbi = og_dbi_open(&ogconfig.db);
1827        if (!dbi) {
1828                syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
1829                       __func__, __LINE__);
1830                return -1;
1831        }
1832
1833        result = dbi_conn_queryf(dbi->conn,
1834                                 "SELECT s.descripcion "
1835                                 "FROM softwares s "
1836                                 "INNER JOIN perfilessoft_softwares pss "
1837                                 "ON s.idsoftware = pss.idsoftware "
1838                                 "INNER JOIN ordenadores_particiones op "
1839                                 "ON pss.idperfilsoft = op.idperfilsoft "
1840                                 "INNER JOIN ordenadores o "
1841                                 "ON o.idordenador = op.idordenador "
1842                                 "WHERE o.ip='%s' AND "
1843                                 "      op.numdisk=%lu AND "
1844                                 "      op.numpar=%lu",
1845                                 params->ips_array[0], disk, partition);
1846        if (!result) {
1847                dbi_conn_error(dbi->conn, &msglog);
1848                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1849                       __func__, __LINE__, msglog);
1850                return -1;
1851        }
1852        software = json_array();
1853        if (!software) {
1854                dbi_result_free(result);
1855                og_dbi_close(dbi);
1856                return -1;
1857        }
1858
1859        while (dbi_result_next_row(result)) {
1860                name = dbi_result_get_string(result, "descripcion");
1861                json_array_append_new(software, json_string(name));
1862        }
1863
1864        dbi_result_free(result);
1865        og_dbi_close(dbi);
1866
1867        root = json_object();
1868        if (!root) {
1869                json_decref(software);
1870                return -1;
1871        }
1872        json_object_set_new(root, "software", software);
1873
[2c6cef7]1874        if (json_dump_callback(root, og_json_dump_clients, &og_buffer, 0)) {
1875                json_decref(root);
1876                return -1;
1877        }
1878
[25c1c16]1879        json_decref(root);
1880        return 0;
1881}
1882
[403e7c3]1883#define OG_IMAGE_TYPE_MAXLEN    4
1884
1885static int og_get_image_stats(const char *name,
1886                              struct stat *image_stats)
1887{
[3cea4bb]1888        const char *dir = ogconfig.repo.dir;
[403e7c3]1889        char filename[PATH_MAX + 1];
1890
[d8b78bb]1891        snprintf(filename, sizeof(filename), "%s/%s.img", dir, name);
[403e7c3]1892        if (stat(filename, image_stats) < 0) {
1893                syslog(LOG_ERR, "%s image does not exists", name);
1894                return -1;
1895        }
1896        return 0;
1897}
1898
1899static json_t *og_json_disk_alloc()
1900{
[3cea4bb]1901        const char *dir = ogconfig.repo.dir;
[403e7c3]1902        struct statvfs buffer;
1903        json_t *disk_json;
1904        int ret;
1905
1906        ret = statvfs(dir, &buffer);
1907        if (ret)
1908                return NULL;
1909
1910        disk_json = json_object();
1911        if (!disk_json)
1912                return NULL;
1913
1914        json_object_set_new(disk_json, "total",
1915                            json_integer(buffer.f_blocks * buffer.f_frsize));
1916        json_object_set_new(disk_json, "free",
1917                            json_integer(buffer.f_bfree * buffer.f_frsize));
1918
1919        return disk_json;
1920}
1921
1922#define OG_PERMS_IRWX (S_IRWXU | S_IRWXG | S_IRWXO)
1923#define OG_PERMS_MAXLEN 4
1924
1925static json_t *og_json_image_alloc(struct og_image *image)
1926{
1927        char perms_string[OG_PERMS_MAXLEN];
1928        json_t *image_json;
1929        char *modified;
1930        uint16_t perms;
1931
1932        image_json = json_object();
1933        if (!image_json)
1934                return NULL;
1935
1936        perms = image->image_stats.st_mode & OG_PERMS_IRWX;
1937        snprintf(perms_string, sizeof(perms_string), "%o", perms);
1938
1939        modified = ctime(&image->image_stats.st_mtime);
1940        modified[strlen(modified) - 1] = '\0';
1941
[d8b78bb]1942        json_object_set_new(image_json, "name",
1943                            json_string(image->name));
[403e7c3]1944        json_object_set_new(image_json, "datasize",
1945                            json_integer(image->datasize));
1946        json_object_set_new(image_json, "size",
1947                            json_integer(image->image_stats.st_size));
1948        json_object_set_new(image_json, "modified",
1949                            json_string(modified));
1950        json_object_set_new(image_json, "permissions",
1951                            json_string(perms_string));
[d8b78bb]1952        json_object_set_new(image_json, "software_id",
1953                            json_integer(image->software_id));
1954        json_object_set_new(image_json, "type",
1955                            json_integer(image->type));
1956        json_object_set_new(image_json, "id",
1957                            json_integer(image->id));
[403e7c3]1958
1959        return image_json;
1960}
1961
1962static int og_cmd_images(char *buffer_reply)
1963{
1964        json_t *root, *images, *image_json, *disk_json;
1965        struct og_buffer og_buffer = {
1966                .data = buffer_reply
1967        };
1968        struct og_image image;
1969        struct og_dbi *dbi;
1970        dbi_result result;
1971
1972        root = json_object();
1973        if (!root)
1974                return -1;
1975
1976        images = json_array();
1977        if (!images) {
1978                json_decref(root);
1979                return -1;
1980        }
1981
1982        json_object_set_new(root, "images", images);
1983
[fe1ce97]1984        dbi = og_dbi_open(&ogconfig.db);
[403e7c3]1985        if (!dbi) {
1986                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
1987                       __func__, __LINE__);
1988                json_decref(root);
1989                return -1;
1990        }
1991
1992        result = dbi_conn_queryf(dbi->conn,
1993                                 "SELECT i.nombreca, o.nombreordenador, "
1994                                 "       i.clonator, i.compressor, "
[d8b78bb]1995                                 "       i.filesystem, i.datasize, "
1996                                 "       i.idperfilsoft, i.tipo, "
1997                                 "       i.idimagen "
[403e7c3]1998                                 "FROM imagenes i "
1999                                 "LEFT JOIN ordenadores o "
2000                                 "ON i.idordenador = o.idordenador");
2001
2002        while (dbi_result_next_row(result)) {
2003                image = (struct og_image){0};
2004                image.datasize = dbi_result_get_ulonglong(result, "datasize");
[d8b78bb]2005                image.software_id = dbi_result_get_ulonglong(result, "idperfilsoft");
2006                image.type = dbi_result_get_ulonglong(result, "tipo");
2007                image.id = dbi_result_get_ulonglong(result, "idimagen");
2008                snprintf(image.name, sizeof(image.name), "%s",
2009                         dbi_result_get_string(result, "nombreca"));
[403e7c3]2010
[d8b78bb]2011                if (og_get_image_stats(image.name, &image.image_stats)) {
[403e7c3]2012                        continue;
2013                }
2014
2015                image_json = og_json_image_alloc(&image);
2016                if (!image_json) {
2017                        dbi_result_free(result);
2018                        og_dbi_close(dbi);
2019                        json_decref(root);
2020                        return -1;
2021                }
2022
[76e6375]2023                json_array_append_new(images, image_json);
[403e7c3]2024        }
2025
2026        dbi_result_free(result);
2027        og_dbi_close(dbi);
2028
2029        disk_json = og_json_disk_alloc();
2030        if (!disk_json) {
2031                syslog(LOG_ERR, "cannot allocate disk json");
2032                json_decref(root);
2033                return -1;
2034        }
2035
2036        json_object_set_new(root, "disk", disk_json);
2037
[2c6cef7]2038        if (json_dump_callback(root, og_json_dump_clients, &og_buffer, 0)) {
2039                json_decref(root);
2040                return -1;
2041        }
2042
[403e7c3]2043        json_decref(root);
2044
2045        return 0;
2046}
2047
[141b079]2048int og_json_parse_create_image(json_t *element,
2049                               struct og_msg_params *params)
[04ca20e]2050{
2051        const char *key;
[e16f36c]2052        json_t *value;
[04ca20e]2053        int err = 0;
2054
2055        if (json_typeof(element) != JSON_OBJECT)
2056                return -1;
2057
2058        json_object_foreach(element, key, value) {
2059                if (!strcmp(key, "disk")) {
2060                        err = og_json_parse_string(value, &params->disk);
2061                        params->flags |= OG_REST_PARAM_DISK;
2062                } else if (!strcmp(key, "partition")) {
2063                        err = og_json_parse_string(value, &params->partition);
2064                        params->flags |= OG_REST_PARAM_PARTITION;
2065                } else if (!strcmp(key, "name")) {
[e16f36c]2066                        err = og_json_parse_string_copy(value,
2067                                                        (char *)&params->image.name,
2068                                                        sizeof(params->image.name));
[04ca20e]2069                        params->flags |= OG_REST_PARAM_NAME;
2070                } else if (!strcmp(key, "repository")) {
2071                        err = og_json_parse_string(value, &params->repository);
2072                        params->flags |= OG_REST_PARAM_REPO;
2073                } else if (!strcmp(key, "clients")) {
2074                        err = og_json_parse_clients(value, params);
2075                } else if (!strcmp(key, "id")) {
2076                        err = og_json_parse_string(value, &params->id);
2077                        params->flags |= OG_REST_PARAM_ID;
2078                } else if (!strcmp(key, "code")) {
2079                        err = og_json_parse_string(value, &params->code);
2080                        params->flags |= OG_REST_PARAM_CODE;
[d2f20d0]2081                } else if (!strcmp(key, "description")) {
2082                        err = og_json_parse_string_copy(value,
[e16f36c]2083                                                        (char *)&params->image.description,
2084                                                        sizeof(params->image.description));
[d2f20d0]2085                } else if (!strcmp(key, "group_id")) {
[e16f36c]2086                        err = og_json_parse_uint64(value, &params->image.group_id);
[d2f20d0]2087                } else if (!strcmp(key, "center_id")) {
[e16f36c]2088                        err = og_json_parse_uint64(value, &params->image.center_id);
[04ca20e]2089                }
2090
2091                if (err < 0)
[e7e80cd]2092                        return err;
[04ca20e]2093        }
2094
[141b079]2095        return 0;
2096}
2097
2098static int og_cmd_create_image(json_t *element, struct og_msg_params *params)
2099{
2100        char new_image_id[OG_DB_INT_MAXLEN + 1];
2101        struct og_dbi *dbi;
2102        json_t *clients;
2103        int err = 0;
2104
2105        err = og_json_parse_create_image(element, params);
2106        if (err < 0)
2107                return err;
2108
[04ca20e]2109        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
2110                                            OG_REST_PARAM_DISK |
2111                                            OG_REST_PARAM_PARTITION |
2112                                            OG_REST_PARAM_CODE |
2113                                            OG_REST_PARAM_ID |
2114                                            OG_REST_PARAM_NAME |
2115                                            OG_REST_PARAM_REPO))
2116                return -1;
2117
[d2f20d0]2118        /* If there is a description, this means the image is not in the DB. */
[e16f36c]2119        if (params->image.description[0]) {
[d2f20d0]2120                dbi = og_dbi_open(&ogconfig.db);
2121                if (!dbi) {
2122                        syslog(LOG_ERR,
2123                               "cannot open connection database (%s:%d)\n",
2124                               __func__, __LINE__);
2125                        return -1;
2126                }
2127
[e16f36c]2128                err = og_dbi_add_image(dbi, &params->image);
[d2f20d0]2129
2130                og_dbi_close(dbi);
2131                if (err < 0)
2132                        return err;
2133
2134                snprintf(new_image_id, sizeof(new_image_id), "%u", err);
2135                params->id = new_image_id;
2136        }
2137
[04ca20e]2138        clients = json_copy(element);
2139        json_object_del(clients, "clients");
2140
2141        return og_send_request(OG_METHOD_POST, OG_CMD_IMAGE_CREATE, params,
2142                               clients);
2143}
2144
[141b079]2145int og_json_parse_restore_image(json_t *element, struct og_msg_params *params)
[04ca20e]2146{
2147        const char *key;
[141b079]2148        json_t *value;
[04ca20e]2149        int err = 0;
2150
2151        if (json_typeof(element) != JSON_OBJECT)
2152                return -1;
2153
2154        json_object_foreach(element, key, value) {
2155                if (!strcmp(key, "disk")) {
2156                        err = og_json_parse_string(value, &params->disk);
2157                        params->flags |= OG_REST_PARAM_DISK;
2158                } else if (!strcmp(key, "partition")) {
2159                        err = og_json_parse_string(value, &params->partition);
2160                        params->flags |= OG_REST_PARAM_PARTITION;
2161                } else if (!strcmp(key, "name")) {
2162                        err = og_json_parse_string(value, &params->name);
2163                        params->flags |= OG_REST_PARAM_NAME;
2164                } else if (!strcmp(key, "repository")) {
2165                        err = og_json_parse_string(value, &params->repository);
2166                        params->flags |= OG_REST_PARAM_REPO;
2167                } else if (!strcmp(key, "clients")) {
2168                        err = og_json_parse_clients(value, params);
2169                } else if (!strcmp(key, "type")) {
2170                        err = og_json_parse_string(value, &params->type);
2171                        params->flags |= OG_REST_PARAM_TYPE;
2172                } else if (!strcmp(key, "profile")) {
2173                        err = og_json_parse_string(value, &params->profile);
2174                        params->flags |= OG_REST_PARAM_PROFILE;
2175                } else if (!strcmp(key, "id")) {
2176                        err = og_json_parse_string(value, &params->id);
2177                        params->flags |= OG_REST_PARAM_ID;
2178                }
2179
2180                if (err < 0)
[e7e80cd]2181                        return err;
[04ca20e]2182        }
2183
[141b079]2184        return 0;
2185}
2186
2187static int og_cmd_restore_image(json_t *element, struct og_msg_params *params)
2188{
2189        json_t *clients;
2190        int err = 0;
2191
2192        err = og_json_parse_restore_image(element, params);
2193        if (err < 0)
2194                return err;
2195
[04ca20e]2196        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
2197                                            OG_REST_PARAM_DISK |
2198                                            OG_REST_PARAM_PARTITION |
2199                                            OG_REST_PARAM_NAME |
2200                                            OG_REST_PARAM_REPO |
2201                                            OG_REST_PARAM_TYPE |
2202                                            OG_REST_PARAM_PROFILE |
2203                                            OG_REST_PARAM_ID))
2204                return -1;
2205
2206        clients = json_copy(element);
2207        json_object_del(clients, "clients");
2208
2209        return og_send_request(OG_METHOD_POST, OG_CMD_IMAGE_RESTORE, params,
2210                               clients);
2211}
2212
[36f0232]2213static int og_cmd_delete_image(json_t *element, struct og_msg_params *params)
2214{
2215        char filename[PATH_MAX + 1];
2216        const char *key, *image;
2217        struct og_dbi *dbi;
2218        dbi_result result;
2219        int rval, err = 0;
2220        json_t *value;
2221
2222
2223        if (json_typeof(element) != JSON_OBJECT)
2224                return -1;
2225
2226        json_object_foreach(element, key, value) {
2227                if (!strcmp(key, "image")) {
2228                        err = og_json_parse_string(value, &params->id);
2229                        params->flags |= OG_REST_PARAM_ID;
2230                }
2231
2232                if (err < 0)
2233                        return err;
2234        }
2235
2236        if (!og_msg_params_validate(params, OG_REST_PARAM_ID))
2237                return -1;
2238
2239        dbi = og_dbi_open(&ogconfig.db);
2240        if (!dbi) {
2241                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
2242                       __func__, __LINE__);
2243                return -1;
2244        }
2245
2246        result = dbi_conn_queryf(dbi->conn,
2247                                 "SELECT nombreca FROM imagenes "
2248                                 "WHERE idimagen='%s'",
2249                                 params->id);
2250        if (!result) {
2251                og_dbi_close(dbi);
2252                syslog(LOG_ERR, "failed to query database\n");
2253                return -1;
2254        }
2255        if (!dbi_result_next_row(result)) {
2256                dbi_result_free(result);
2257                og_dbi_close(dbi);
2258                syslog(LOG_ERR, "image does not exist in database\n");
2259                return -1;
2260        }
2261
2262        image = dbi_result_get_string(result, "nombreca");
2263        snprintf(filename, sizeof(filename), "%s/%s.img", ogconfig.repo.dir,
2264                 image);
2265        dbi_result_free(result);
2266
2267        result = dbi_conn_queryf(dbi->conn,
2268                                 "DELETE FROM imagenes "
2269                                 "WHERE idimagen='%s'",
2270                                 params->id);
2271        if (!result) {
2272                og_dbi_close(dbi);
2273                syslog(LOG_ERR, "failed to query database\n");
2274                return -1;
2275        }
2276        dbi_result_free(result);
2277
2278        rval = unlink(filename);
2279        if (rval) {
2280                og_dbi_close(dbi);
2281                syslog(LOG_ERR, "cannot delete image %s: %s\n",
2282                       image, strerror(errno));
2283                return -1;
2284        }
2285        og_dbi_close(dbi);
2286
2287        return 0;
2288}
2289
[04ca20e]2290static int og_cmd_setup(json_t *element, struct og_msg_params *params)
2291{
2292        json_t *value, *clients;
2293        const char *key;
2294        int err = 0;
2295
2296        if (json_typeof(element) != JSON_OBJECT)
2297                return -1;
2298
2299        json_object_foreach(element, key, value) {
2300                if (!strcmp(key, "clients")) {
2301                        err = og_json_parse_clients(value, params);
[0dd3edd]2302                } else if (!strcmp(key, "type")) {
2303                        err = og_json_parse_string(value, &params->type);
2304                        params->flags |= OG_REST_PARAM_TYPE;
[04ca20e]2305                } else if (!strcmp(key, "disk")) {
2306                        err = og_json_parse_string(value, &params->disk);
2307                        params->flags |= OG_REST_PARAM_DISK;
2308                } else if (!strcmp(key, "cache")) {
2309                        err = og_json_parse_string(value, &params->cache);
2310                        params->flags |= OG_REST_PARAM_CACHE;
2311                } else if (!strcmp(key, "cache_size")) {
2312                        err = og_json_parse_string(value, &params->cache_size);
2313                        params->flags |= OG_REST_PARAM_CACHE_SIZE;
2314                } else if (!strcmp(key, "partition_setup")) {
2315                        err = og_json_parse_partition_setup(value, params);
2316                }
2317
2318                if (err < 0)
[e7e80cd]2319                        return err;
[04ca20e]2320        }
2321
2322        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
[0dd3edd]2323                                            OG_REST_PARAM_TYPE |
[04ca20e]2324                                            OG_REST_PARAM_DISK |
2325                                            OG_REST_PARAM_CACHE |
2326                                            OG_REST_PARAM_CACHE_SIZE |
2327                                            OG_REST_PARAM_PART_0 |
2328                                            OG_REST_PARAM_PART_1 |
2329                                            OG_REST_PARAM_PART_2 |
2330                                            OG_REST_PARAM_PART_3))
2331                return -1;
2332
2333        clients = json_copy(element);
2334        json_object_del(clients, "clients");
2335
2336        return og_send_request(OG_METHOD_POST, OG_CMD_SETUP, params, clients);
2337}
2338
2339static int og_cmd_run_schedule(json_t *element, struct og_msg_params *params)
2340{
2341        const char *key;
2342        json_t *value;
2343        int err = 0;
2344
2345        json_object_foreach(element, key, value) {
2346                if (!strcmp(key, "clients"))
2347                        err = og_json_parse_clients(value, params);
2348
2349                if (err < 0)
[e7e80cd]2350                        return err;
[04ca20e]2351        }
2352
2353        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
2354                return -1;
2355
2356        return og_send_request(OG_METHOD_GET, OG_CMD_RUN_SCHEDULE, params,
2357                               NULL);
2358}
2359
2360static LIST_HEAD(cmd_list);
2361
2362const struct og_cmd *og_cmd_find(const char *client_ip)
2363{
2364        struct og_cmd *cmd, *next;
2365
2366        list_for_each_entry_safe(cmd, next, &cmd_list, list) {
2367                if (strcmp(cmd->ip, client_ip))
2368                        continue;
2369
2370                list_del(&cmd->list);
2371                return cmd;
2372        }
2373
2374        return NULL;
2375}
2376
2377void og_cmd_free(const struct og_cmd *cmd)
2378{
2379        struct og_msg_params *params = (struct og_msg_params *)&cmd->params;
2380        int i;
2381
2382        for (i = 0; i < params->ips_array_len; i++) {
[ed0d86b]2383                free((void *)params->netmask_array[i]);
[04ca20e]2384                free((void *)params->ips_array[i]);
2385                free((void *)params->mac_array[i]);
2386        }
2387        free((void *)params->wol_type);
2388
2389        if (cmd->json)
2390                json_decref(cmd->json);
2391
2392        free((void *)cmd->ip);
2393        free((void *)cmd->mac);
2394        free((void *)cmd);
2395}
2396
2397static void og_cmd_init(struct og_cmd *cmd, enum og_rest_method method,
2398                        enum og_cmd_type type, json_t *root)
2399{
2400        cmd->type = type;
2401        cmd->method = method;
2402        cmd->params.ips_array[0] = strdup(cmd->ip);
2403        cmd->params.ips_array_len = 1;
2404        cmd->json = root;
[2d68f8a]2405        gettimeofday(&cmd->tv, NULL);
[04ca20e]2406}
2407
2408static int og_cmd_legacy_wol(const char *input, struct og_cmd *cmd)
2409{
2410        char wol_type[2] = {};
[ed0d86b]2411        const char *msglog;
2412        struct og_dbi *dbi;
2413        dbi_result result;
[04ca20e]2414
2415        if (sscanf(input, "mar=%s", wol_type) != 1) {
2416                syslog(LOG_ERR, "malformed database legacy input\n");
2417                return -1;
2418        }
2419
[ed0d86b]2420        dbi = og_dbi_open(&ogconfig.db);
2421        if (!dbi) {
2422                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
2423                       __func__, __LINE__);
2424                return -1;
2425        }
2426
2427        result = dbi_conn_queryf(dbi->conn,
[e6c2c26]2428                                 "SELECT aulas.netmask "
2429                                 "FROM   ordenadores "
2430                                 "INNER JOIN aulas "
2431                                         "ON ordenadores.idaula = aulas.idaula "
2432                                 "WHERE  ordenadores.ip = '%s'",
2433                                 cmd->ip);
[ed0d86b]2434        if (!result) {
2435                dbi_conn_error(dbi->conn, &msglog);
2436                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2437                       __func__, __LINE__, msglog);
2438                og_dbi_close(dbi);
2439                return -1;
2440        }
2441        dbi_result_next_row(result);
2442
[04ca20e]2443        og_cmd_init(cmd, OG_METHOD_NO_HTTP, OG_CMD_WOL, NULL);
[ed0d86b]2444        cmd->params.netmask_array[0] = dbi_result_get_string_copy(result,
[e6c2c26]2445                                                                  "netmask");
[04ca20e]2446        cmd->params.mac_array[0] = strdup(cmd->mac);
2447        cmd->params.wol_type = strdup(wol_type);
2448
[ed0d86b]2449        dbi_result_free(result);
2450        og_dbi_close(dbi);
2451
[04ca20e]2452        return 0;
2453}
2454
2455static int og_cmd_legacy_shell_run(const char *input, struct og_cmd *cmd)
2456{
2457        json_t *root, *script, *echo;
2458
2459        script = json_string(input + 4);
2460        echo = json_boolean(false);
2461
2462        root = json_object();
2463        if (!root)
2464                return -1;
2465        json_object_set_new(root, "run", script);
2466        json_object_set_new(root, "echo", echo);
2467
2468        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_SHELL_RUN, root);
2469
2470        return 0;
2471}
2472
2473static int og_cmd_legacy_session(const char *input, struct og_cmd *cmd)
2474{
2475        char part_str[OG_DB_SMALLINT_MAXLEN + 1];
2476        char disk_str[OG_DB_SMALLINT_MAXLEN + 1];
2477        json_t *root, *disk, *partition;
2478
2479        if (sscanf(input, "dsk=%s\rpar=%s\r", disk_str, part_str) != 2)
2480                return -1;
2481        partition = json_string(part_str);
2482        disk = json_string(disk_str);
2483
2484        root = json_object();
2485        if (!root)
2486                return -1;
2487        json_object_set_new(root, "partition", partition);
2488        json_object_set_new(root, "disk", disk);
2489
2490        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_SESSION, root);
2491
2492        return 0;
2493}
2494
2495static int og_cmd_legacy_poweroff(const char *input, struct og_cmd *cmd)
2496{
2497        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_POWEROFF, NULL);
2498
2499        return 0;
2500}
2501
2502static int og_cmd_legacy_refresh(const char *input, struct og_cmd *cmd)
2503{
2504        og_cmd_init(cmd, OG_METHOD_GET, OG_CMD_REFRESH, NULL);
2505
2506        return 0;
2507}
2508
2509static int og_cmd_legacy_reboot(const char *input, struct og_cmd *cmd)
2510{
2511        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_REBOOT, NULL);
2512
2513        return 0;
2514}
2515
2516static int og_cmd_legacy_stop(const char *input, struct og_cmd *cmd)
2517{
2518        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_STOP, NULL);
2519
2520        return 0;
2521}
2522
2523static int og_cmd_legacy_hardware(const char *input, struct og_cmd *cmd)
2524{
2525        og_cmd_init(cmd, OG_METHOD_GET, OG_CMD_HARDWARE, NULL);
2526
2527        return 0;
2528}
2529
2530static int og_cmd_legacy_software(const char *input, struct og_cmd *cmd)
2531{
[6d628dc]2532        char part_str[OG_DB_SMALLINT_MAXLEN + 1];
2533        char disk_str[OG_DB_SMALLINT_MAXLEN + 1];
2534        json_t *root, *disk, *partition;
2535
2536        if (sscanf(input, "dsk=%s\rpar=%s\r", disk_str, part_str) != 2)
2537                return -1;
2538        partition = json_string(part_str);
2539        disk = json_string(disk_str);
2540
2541        root = json_object();
2542        if (!root)
2543                return -1;
2544        json_object_set_new(root, "partition", partition);
2545        json_object_set_new(root, "disk", disk);
2546
2547        og_cmd_init(cmd, OG_METHOD_GET, OG_CMD_SOFTWARE, root);
[04ca20e]2548
2549        return 0;
2550}
2551
2552static int og_cmd_legacy_image_create(const char *input, struct og_cmd *cmd)
2553{
2554        json_t *root, *disk, *partition, *code, *image_id, *name, *repo;
2555        struct og_image_legacy img = {};
2556
2557        if (sscanf(input, "dsk=%s\rpar=%s\rcpt=%s\ridi=%s\rnci=%s\ripr=%s\r",
2558                   img.disk, img.part, img.code, img.image_id, img.name,
2559                   img.repo) != 6)
2560                return -1;
2561        image_id = json_string(img.image_id);
2562        partition = json_string(img.part);
2563        code = json_string(img.code);
2564        name = json_string(img.name);
2565        repo = json_string(img.repo);
2566        disk = json_string(img.disk);
2567
2568        root = json_object();
2569        if (!root)
2570                return -1;
2571        json_object_set_new(root, "partition", partition);
2572        json_object_set_new(root, "repository", repo);
2573        json_object_set_new(root, "id", image_id);
2574        json_object_set_new(root, "code", code);
2575        json_object_set_new(root, "name", name);
2576        json_object_set_new(root, "disk", disk);
2577
2578        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_IMAGE_CREATE, root);
2579
2580        return 0;
2581}
2582
2583#define OG_DB_RESTORE_TYPE_MAXLEN       64
2584
2585static int og_cmd_legacy_image_restore(const char *input, struct og_cmd *cmd)
2586{
2587        json_t *root, *disk, *partition, *image_id, *name, *repo;
2588        char restore_type_str[OG_DB_RESTORE_TYPE_MAXLEN + 1] = {};
2589        char software_id_str[OG_DB_INT_MAXLEN + 1] = {};
2590        json_t *software_id, *restore_type;
2591        struct og_image_legacy img = {};
2592
2593        if (sscanf(input,
[0e4857a]2594                   "dsk=%s\rpar=%s\ridi=%s\rnci=%s\r"
2595                   "ipr=%s\rifs=%s\rptc=%[^\r]\r",
[04ca20e]2596                   img.disk, img.part, img.image_id, img.name, img.repo,
2597                   software_id_str, restore_type_str) != 7)
2598                return -1;
2599
2600        restore_type = json_string(restore_type_str);
2601        software_id = json_string(software_id_str);
2602        image_id = json_string(img.image_id);
2603        partition = json_string(img.part);
2604        name = json_string(img.name);
2605        repo = json_string(img.repo);
2606        disk = json_string(img.disk);
2607
2608        root = json_object();
2609        if (!root)
2610                return -1;
2611        json_object_set_new(root, "profile", software_id);
2612        json_object_set_new(root, "partition", partition);
2613        json_object_set_new(root, "type", restore_type);
2614        json_object_set_new(root, "repository", repo);
2615        json_object_set_new(root, "id", image_id);
2616        json_object_set_new(root, "name", name);
2617        json_object_set_new(root, "disk", disk);
2618
2619        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_IMAGE_RESTORE, root);
2620
2621        return 0;
2622}
2623
[6a7a846]2624#define OG_PARTITION_TABLE_TYPE_MAXLEN 5
2625
[04ca20e]2626static int og_cmd_legacy_setup(const char *input, struct og_cmd *cmd)
2627{
2628        json_t *root, *disk, *cache, *cache_size, *partition_setup, *object;
[6a7a846]2629        char part_table_type_str[OG_PARTITION_TABLE_TYPE_MAXLEN + 1];
[04ca20e]2630        struct og_legacy_partition part_cfg[OG_PARTITION_MAX] = {};
[6a7a846]2631        json_t *part_table_type, *part, *code, *fs, *size, *format;
[04ca20e]2632        char cache_size_str [OG_DB_INT_MAXLEN + 1];
2633        char disk_str [OG_DB_SMALLINT_MAXLEN + 1];
2634        unsigned int partition_len = 0;
2635        const char *in_ptr;
2636        char cache_str[2];
2637
[6a7a846]2638        if (sscanf(input, "ttp=%s\rdsk=%s\rcfg=dis=%*[^*]*che=%[^*]*tch=%[^!]!",
2639                   part_table_type_str, disk_str, cache_str, cache_size_str) != 4)
[04ca20e]2640                return -1;
2641
2642        in_ptr = strstr(input, "!") + 1;
2643        while (strlen(in_ptr) > 0) {
2644                if(sscanf(in_ptr,
2645                          "par=%[^*]*cpt=%[^*]*sfi=%[^*]*tam=%[^*]*ope=%[^%%]%%",
2646                          part_cfg[partition_len].partition,
2647                          part_cfg[partition_len].code,
2648                          part_cfg[partition_len].filesystem,
2649                          part_cfg[partition_len].size,
2650                          part_cfg[partition_len].format) != 5)
2651                        return -1;
2652                in_ptr = strstr(in_ptr, "%") + 1;
2653                partition_len++;
2654        }
2655
2656        root = json_object();
2657        if (!root)
2658                return -1;
2659
[6a7a846]2660        part_table_type = json_string(part_table_type_str);
[04ca20e]2661        cache_size = json_string(cache_size_str);
2662        cache = json_string(cache_str);
2663        partition_setup = json_array();
2664        disk = json_string(disk_str);
2665
2666        for (unsigned int i = 0; i < partition_len; ++i) {
2667                object = json_object();
2668                if (!object) {
2669                        json_decref(root);
2670                        return -1;
2671                }
2672
2673                part = json_string(part_cfg[i].partition);
2674                fs = json_string(part_cfg[i].filesystem);
2675                format = json_string(part_cfg[i].format);
2676                code = json_string(part_cfg[i].code);
2677                size = json_string(part_cfg[i].size);
2678
2679                json_object_set_new(object, "partition", part);
2680                json_object_set_new(object, "filesystem", fs);
2681                json_object_set_new(object, "format", format);
2682                json_object_set_new(object, "code", code);
2683                json_object_set_new(object, "size", size);
2684
2685                json_array_append_new(partition_setup, object);
2686        }
2687
2688        json_object_set_new(root, "partition_setup", partition_setup);
2689        json_object_set_new(root, "cache_size", cache_size);
[6a7a846]2690        json_object_set_new(root, "type", part_table_type);
[04ca20e]2691        json_object_set_new(root, "cache", cache);
2692        json_object_set_new(root, "disk", disk);
2693
2694        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_SETUP, root);
2695
2696        return 0;
2697}
2698
2699static int og_cmd_legacy_run_schedule(const char *input, struct og_cmd *cmd)
2700{
2701        og_cmd_init(cmd, OG_METHOD_GET, OG_CMD_RUN_SCHEDULE, NULL);
2702
2703        return 0;
2704}
2705
2706static int og_cmd_legacy(const char *input, struct og_cmd *cmd)
2707{
2708        char legacy_cmd[32] = {};
2709        int err = -1;
2710
2711        if (sscanf(input, "nfn=%31s\r", legacy_cmd) != 1) {
2712                syslog(LOG_ERR, "malformed database legacy input\n");
2713                return -1;
2714        }
2715        input = strchr(input, '\r') + 1;
2716
2717        if (!strcmp(legacy_cmd, "Arrancar")) {
2718                err = og_cmd_legacy_wol(input, cmd);
2719        } else if (!strcmp(legacy_cmd, "EjecutarScript")) {
2720                err = og_cmd_legacy_shell_run(input, cmd);
2721        } else if (!strcmp(legacy_cmd, "IniciarSesion")) {
2722                err = og_cmd_legacy_session(input, cmd);
2723        } else if (!strcmp(legacy_cmd, "Apagar")) {
2724                err = og_cmd_legacy_poweroff(input, cmd);
2725        } else if (!strcmp(legacy_cmd, "Actualizar")) {
2726                err = og_cmd_legacy_refresh(input, cmd);
2727        } else if (!strcmp(legacy_cmd, "Reiniciar")) {
2728                err = og_cmd_legacy_reboot(input, cmd);
2729        } else if (!strcmp(legacy_cmd, "Purgar")) {
2730                err = og_cmd_legacy_stop(input, cmd);
2731        } else if (!strcmp(legacy_cmd, "InventarioHardware")) {
2732                err = og_cmd_legacy_hardware(input, cmd);
2733        } else if (!strcmp(legacy_cmd, "InventarioSoftware")) {
2734                err = og_cmd_legacy_software(input, cmd);
2735        } else if (!strcmp(legacy_cmd, "CrearImagen")) {
2736                err = og_cmd_legacy_image_create(input, cmd);
2737        } else if (!strcmp(legacy_cmd, "RestaurarImagen")) {
2738                err = og_cmd_legacy_image_restore(input, cmd);
2739        } else if (!strcmp(legacy_cmd, "Configurar")) {
2740                err = og_cmd_legacy_setup(input, cmd);
2741        } else if (!strcmp(legacy_cmd, "EjecutaComandosPendientes") ||
2742                   !strcmp(legacy_cmd, "Actualizar")) {
2743                err = og_cmd_legacy_run_schedule(input, cmd);
2744        }
2745
2746        return err;
2747}
2748
[261d490]2749static int og_dbi_add_action(const struct og_dbi *dbi, struct og_task *task,
[04ca20e]2750                             struct og_cmd *cmd)
2751{
2752        char start_date_string[24];
2753        struct tm *start_date;
2754        const char *msglog;
2755        dbi_result result;
2756        time_t now;
2757
2758        time(&now);
2759        start_date = localtime(&now);
2760
2761        sprintf(start_date_string, "%hu/%hhu/%hhu %hhu:%hhu:%hhu",
2762                start_date->tm_year + 1900, start_date->tm_mon + 1,
2763                start_date->tm_mday, start_date->tm_hour, start_date->tm_min,
2764                start_date->tm_sec);
2765        result = dbi_conn_queryf(dbi->conn,
2766                                "INSERT INTO acciones (idordenador, "
2767                                "tipoaccion, idtipoaccion, descriaccion, ip, "
2768                                "sesion, idcomando, parametros, fechahorareg, "
2769                                "estado, resultado, ambito, idambito, "
2770                                "restrambito, idprocedimiento, idcentro, "
2771                                "idprogramacion) "
2772                                "VALUES (%d, %d, %d, '%s', '%s', %d, %d, '%s', "
2773                                "'%s', %d, %d, %d, %d, '%s', %d, %d, %d)",
2774                                cmd->client_id, EJECUCION_TAREA, task->task_id,
[261d490]2775                                "", cmd->ip, task->session, task->command_id,
[04ca20e]2776                                task->params, start_date_string,
2777                                ACCION_INICIADA, ACCION_SINRESULTADO,
2778                                task->type_scope, task->scope, "",
2779                                task->procedure_id, task->center_id,
2780                                task->schedule_id);
2781        if (!result) {
2782                dbi_conn_error(dbi->conn, &msglog);
2783                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2784                       __func__, __LINE__, msglog);
2785                return -1;
2786        }
[261d490]2787
[04ca20e]2788        cmd->id = dbi_conn_sequence_last(dbi->conn, NULL);
[261d490]2789        if (!task->session) {
2790                task->session = cmd->id;
2791                dbi_result_free(result);
2792                result = dbi_conn_queryf(dbi->conn,
2793                                         "UPDATE acciones SET sesion=%d "
2794                                         "WHERE idaccion=%d",
2795                                         task->session, cmd->id);
2796        }
2797
[04ca20e]2798        dbi_result_free(result);
2799
2800        return 0;
2801}
2802
[261d490]2803static int og_queue_task_command(struct og_dbi *dbi, struct og_task *task,
[04ca20e]2804                                 char *query)
2805{
2806        struct og_cmd *cmd;
2807        const char *msglog;
2808        dbi_result result;
2809
2810        result = dbi_conn_queryf(dbi->conn, query);
2811        if (!result) {
2812                dbi_conn_error(dbi->conn, &msglog);
2813                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2814                       __func__, __LINE__, msglog);
2815                return -1;
2816        }
2817
2818        while (dbi_result_next_row(result)) {
2819                cmd = (struct og_cmd *)calloc(1, sizeof(struct og_cmd));
2820                if (!cmd) {
2821                        dbi_result_free(result);
2822                        return -1;
2823                }
2824
2825                cmd->client_id  = dbi_result_get_uint(result, "idordenador");
2826                cmd->ip         = strdup(dbi_result_get_string(result, "ip"));
2827                cmd->mac        = strdup(dbi_result_get_string(result, "mac"));
2828
2829                og_cmd_legacy(task->params, cmd);
2830
2831                if (task->procedure_id) {
2832                        if (og_dbi_add_action(dbi, task, cmd)) {
2833                                dbi_result_free(result);
2834                                return -1;
2835                        }
2836                } else {
2837                        cmd->id = task->task_id;
2838                }
2839
2840                list_add_tail(&cmd->list, &cmd_list);
2841        }
2842
2843        dbi_result_free(result);
2844
2845        return 0;
2846}
2847
2848static int og_queue_task_group_clients(struct og_dbi *dbi, struct og_task *task,
2849                                       char *query)
2850{
2851
2852        const char *msglog;
2853        dbi_result result;
2854
2855        result = dbi_conn_queryf(dbi->conn, query);
2856        if (!result) {
2857                dbi_conn_error(dbi->conn, &msglog);
2858                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2859                       __func__, __LINE__, msglog);
2860                return -1;
2861        }
2862
2863        while (dbi_result_next_row(result)) {
2864                uint32_t group_id = dbi_result_get_uint(result, "idgrupo");
2865
2866                sprintf(query, "SELECT idgrupo FROM gruposordenadores "
2867                                "WHERE grupoid=%d", group_id);
2868                if (og_queue_task_group_clients(dbi, task, query)) {
2869                        dbi_result_free(result);
2870                        return -1;
2871                }
2872
2873                sprintf(query,"SELECT ip, mac, idordenador FROM ordenadores "
2874                              "WHERE grupoid=%d", group_id);
2875                if (og_queue_task_command(dbi, task, query)) {
2876                        dbi_result_free(result);
2877                        return -1;
2878                }
2879
2880        }
2881
2882        dbi_result_free(result);
2883
2884        return 0;
2885}
2886
2887static int og_queue_task_group_classrooms(struct og_dbi *dbi,
2888                                          struct og_task *task, char *query)
2889{
2890
2891        const char *msglog;
2892        dbi_result result;
2893
2894        result = dbi_conn_queryf(dbi->conn, query);
2895        if (!result) {
2896                dbi_conn_error(dbi->conn, &msglog);
2897                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2898                       __func__, __LINE__, msglog);
2899                return -1;
2900        }
2901
2902        while (dbi_result_next_row(result)) {
2903                uint32_t group_id = dbi_result_get_uint(result, "idgrupo");
2904
2905                sprintf(query, "SELECT idgrupo FROM grupos "
2906                                "WHERE grupoid=%d AND tipo=%d", group_id, AMBITO_GRUPOSAULAS);
2907                if (og_queue_task_group_classrooms(dbi, task, query)) {
2908                        dbi_result_free(result);
2909                        return -1;
2910                }
2911
2912                sprintf(query,
2913                        "SELECT ip,mac,idordenador "
2914                        "FROM ordenadores INNER JOIN aulas "
2915                        "WHERE ordenadores.idaula=aulas.idaula "
2916                        "AND aulas.grupoid=%d",
2917                        group_id);
2918                if (og_queue_task_command(dbi, task, query)) {
2919                        dbi_result_free(result);
2920                        return -1;
2921                }
2922
2923        }
2924
2925        dbi_result_free(result);
2926
2927        return 0;
2928}
2929
2930static int og_queue_task_clients(struct og_dbi *dbi, struct og_task *task)
2931{
2932        char query[4096];
2933
2934        switch (task->type_scope) {
2935                case AMBITO_CENTROS:
2936                        sprintf(query,
2937                                "SELECT ip,mac,idordenador "
2938                                "FROM ordenadores INNER JOIN aulas "
2939                                "WHERE ordenadores.idaula=aulas.idaula "
2940                                "AND idcentro=%d",
2941                                task->scope);
2942                        return og_queue_task_command(dbi, task, query);
2943                case AMBITO_GRUPOSAULAS:
2944                        sprintf(query,
2945                                "SELECT idgrupo FROM grupos "
2946                                "WHERE idgrupo=%i AND tipo=%d",
2947                                task->scope, AMBITO_GRUPOSAULAS);
2948                        return og_queue_task_group_classrooms(dbi, task, query);
2949                case AMBITO_AULAS:
2950                        sprintf(query,
2951                                "SELECT ip,mac,idordenador FROM ordenadores "
2952                                "WHERE idaula=%d",
2953                                task->scope);
2954                        return og_queue_task_command(dbi, task, query);
2955                case AMBITO_GRUPOSORDENADORES:
2956                        sprintf(query,
2957                                "SELECT idgrupo FROM gruposordenadores "
2958                                "WHERE idgrupo = %d",
2959                                task->scope);
2960                        return og_queue_task_group_clients(dbi, task, query);
2961                case AMBITO_ORDENADORES:
2962                        sprintf(query,
2963                                "SELECT ip, mac, idordenador FROM ordenadores "
2964                                "WHERE idordenador = %d",
2965                                task->scope);
2966                        return og_queue_task_command(dbi, task, query);
2967        }
2968        return 0;
2969}
2970
2971int og_dbi_queue_procedure(struct og_dbi *dbi, struct og_task *task)
2972{
2973        uint32_t procedure_id;
2974        const char *msglog;
2975        dbi_result result;
2976
2977        result = dbi_conn_queryf(dbi->conn,
2978                        "SELECT parametros, procedimientoid, idcomando "
2979                        "FROM procedimientos_acciones "
2980                        "WHERE idprocedimiento=%d ORDER BY orden", task->procedure_id);
2981        if (!result) {
2982                dbi_conn_error(dbi->conn, &msglog);
2983                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2984                       __func__, __LINE__, msglog);
2985                return -1;
2986        }
2987
2988        while (dbi_result_next_row(result)) {
2989                procedure_id = dbi_result_get_uint(result, "procedimientoid");
2990                if (procedure_id > 0) {
2991                        task->procedure_id = procedure_id;
2992                        if (og_dbi_queue_procedure(dbi, task))
2993                                return -1;
2994                        continue;
2995                }
2996
[829f8d8]2997                task->params = dbi_result_get_string(result, "parametros");
[04ca20e]2998                task->command_id = dbi_result_get_uint(result, "idcomando");
2999                if (og_queue_task_clients(dbi, task))
3000                        return -1;
3001        }
3002
3003        dbi_result_free(result);
3004
3005        return 0;
3006}
3007
3008static int og_dbi_queue_task(struct og_dbi *dbi, uint32_t task_id,
3009                             uint32_t schedule_id)
3010{
3011        struct og_task task = {};
3012        uint32_t task_id_next;
3013        const char *msglog;
3014        dbi_result result;
3015
3016        task.schedule_id = schedule_id;
3017
3018        result = dbi_conn_queryf(dbi->conn,
3019                        "SELECT tareas_acciones.orden, "
3020                                "tareas_acciones.idprocedimiento, "
3021                                "tareas_acciones.tareaid, "
3022                                "tareas.idtarea, "
3023                                "tareas.idcentro, "
3024                                "tareas.ambito, "
3025                                "tareas.idambito, "
3026                                "tareas.restrambito "
3027                        " FROM tareas"
3028                                " INNER JOIN tareas_acciones ON tareas_acciones.idtarea=tareas.idtarea"
3029                        " WHERE tareas_acciones.idtarea=%u ORDER BY tareas_acciones.orden ASC", task_id);
3030        if (!result) {
3031                dbi_conn_error(dbi->conn, &msglog);
3032                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3033                       __func__, __LINE__, msglog);
3034                return -1;
3035        }
3036
3037        while (dbi_result_next_row(result)) {
3038                task_id_next = dbi_result_get_uint(result, "tareaid");
3039
3040                if (task_id_next > 0) {
3041                        if (og_dbi_queue_task(dbi, task_id_next, schedule_id))
3042                                return -1;
3043
3044                        continue;
3045                }
3046                task.task_id = dbi_result_get_uint(result, "idtarea");
3047                task.center_id = dbi_result_get_uint(result, "idcentro");
3048                task.procedure_id = dbi_result_get_uint(result, "idprocedimiento");
3049                task.type_scope = dbi_result_get_uint(result, "ambito");
3050                task.scope = dbi_result_get_uint(result, "idambito");
3051                task.filtered_scope = dbi_result_get_string(result, "restrambito");
3052
3053                og_dbi_queue_procedure(dbi, &task);
3054        }
3055
3056        dbi_result_free(result);
3057
3058        return 0;
3059}
3060
3061static int og_dbi_queue_command(struct og_dbi *dbi, uint32_t task_id,
3062                                uint32_t schedule_id)
3063{
3064        struct og_task task = {};
3065        const char *msglog;
3066        dbi_result result;
3067        char query[4096];
3068
3069        result = dbi_conn_queryf(dbi->conn,
3070                        "SELECT idaccion, idcentro, idordenador, parametros "
3071                        "FROM acciones "
[33d8cec]3072                        "WHERE sesion = %u", task_id);
[04ca20e]3073        if (!result) {
3074                dbi_conn_error(dbi->conn, &msglog);
3075                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3076                       __func__, __LINE__, msglog);
3077                return -1;
3078        }
3079
3080        while (dbi_result_next_row(result)) {
3081                task.task_id = dbi_result_get_uint(result, "idaccion");
3082                task.center_id = dbi_result_get_uint(result, "idcentro");
3083                task.scope = dbi_result_get_uint(result, "idordenador");
[829f8d8]3084                task.params = dbi_result_get_string(result, "parametros");
[04ca20e]3085
3086                sprintf(query,
3087                        "SELECT ip, mac, idordenador FROM ordenadores "
3088                        "WHERE idordenador = %d",
3089                        task.scope);
3090                if (og_queue_task_command(dbi, &task, query)) {
3091                        dbi_result_free(result);
3092                        return -1;
3093                }
3094        }
3095
3096        dbi_result_free(result);
3097
3098        return 0;
3099}
3100
3101int og_dbi_update_action(uint32_t id, bool success)
3102{
3103        char end_date_string[24];
3104        struct tm *end_date;
3105        const char *msglog;
3106        struct og_dbi *dbi;
3107        uint8_t status = 2;
3108        dbi_result result;
3109        time_t now;
3110
3111        if (!id)
3112                return 0;
3113
[fe1ce97]3114        dbi = og_dbi_open(&ogconfig.db);
[04ca20e]3115        if (!dbi) {
3116                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3117                       __func__, __LINE__);
3118                return -1;
3119        }
3120
3121        time(&now);
3122        end_date = localtime(&now);
3123
3124        sprintf(end_date_string, "%hu/%hhu/%hhu %hhu:%hhu:%hhu",
3125                end_date->tm_year + 1900, end_date->tm_mon + 1,
3126                end_date->tm_mday, end_date->tm_hour, end_date->tm_min,
3127                end_date->tm_sec);
3128        result = dbi_conn_queryf(dbi->conn,
3129                                 "UPDATE acciones SET fechahorafin='%s', "
3130                                 "estado=%d, resultado=%d WHERE idaccion=%d",
3131                                 end_date_string, ACCION_FINALIZADA,
3132                                 status - success, id);
3133
3134        if (!result) {
3135                dbi_conn_error(dbi->conn, &msglog);
3136                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3137                       __func__, __LINE__, msglog);
3138                og_dbi_close(dbi);
3139                return -1;
3140        }
3141        dbi_result_free(result);
3142        og_dbi_close(dbi);
3143
3144        return 0;
3145}
3146
3147void og_schedule_run(unsigned int task_id, unsigned int schedule_id,
3148                     enum og_schedule_type type)
3149{
3150        struct og_msg_params params = {};
3151        bool duplicated = false;
3152        struct og_cmd *cmd, *next;
3153        struct og_dbi *dbi;
3154        unsigned int i;
3155
[fe1ce97]3156        dbi = og_dbi_open(&ogconfig.db);
[04ca20e]3157        if (!dbi) {
3158                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3159                       __func__, __LINE__);
3160                return;
3161        }
3162
3163        switch (type) {
3164        case OG_SCHEDULE_TASK:
3165                og_dbi_queue_task(dbi, task_id, schedule_id);
3166                break;
3167        case OG_SCHEDULE_PROCEDURE:
3168        case OG_SCHEDULE_COMMAND:
3169                og_dbi_queue_command(dbi, task_id, schedule_id);
3170                break;
3171        }
3172        og_dbi_close(dbi);
3173
3174        list_for_each_entry(cmd, &cmd_list, list) {
3175                for (i = 0; i < params.ips_array_len; i++) {
3176                        if (!strncmp(cmd->ip, params.ips_array[i],
3177                                     OG_DB_IP_MAXLEN)) {
3178                                duplicated = true;
3179                                break;
3180                        }
3181                }
3182
3183                if (!duplicated)
[3b3405b]3184                        params.ips_array[params.ips_array_len++] = strdup(cmd->ip);
[04ca20e]3185                else
3186                        duplicated = false;
3187        }
3188
3189        list_for_each_entry_safe(cmd, next, &cmd_list, list) {
3190                if (cmd->type != OG_CMD_WOL)
3191                        continue;
3192
3193                if (Levanta((char **)cmd->params.ips_array,
3194                            (char **)cmd->params.mac_array,
[06af0c2]3195                            (char **)cmd->params.netmask_array,
[04ca20e]3196                            cmd->params.ips_array_len,
3197                            (char *)cmd->params.wol_type))
3198                        og_dbi_update_action(cmd->id, true);
3199
3200                list_del(&cmd->list);
3201                og_cmd_free(cmd);
3202        }
3203
3204        og_send_request(OG_METHOD_GET, OG_CMD_RUN_SCHEDULE, &params, NULL);
[3b3405b]3205
3206        for (i = 0; i < params.ips_array_len; i++)
3207                free((void *)params.ips_array[i]);
[04ca20e]3208}
3209
3210static int og_cmd_task_post(json_t *element, struct og_msg_params *params)
3211{
3212        struct og_cmd *cmd;
3213        struct og_dbi *dbi;
3214        const char *key;
3215        json_t *value;
[e7e80cd]3216        int err = 0;
[04ca20e]3217
3218        if (json_typeof(element) != JSON_OBJECT)
3219                return -1;
3220
3221        json_object_foreach(element, key, value) {
3222                if (!strcmp(key, "task")) {
3223                        err = og_json_parse_string(value, &params->task_id);
3224                        params->flags |= OG_REST_PARAM_TASK;
3225                }
3226
3227                if (err < 0)
[e7e80cd]3228                        return err;
[04ca20e]3229        }
3230
3231        if (!og_msg_params_validate(params, OG_REST_PARAM_TASK))
3232                return -1;
3233
[fe1ce97]3234        dbi = og_dbi_open(&ogconfig.db);
[04ca20e]3235        if (!dbi) {
3236                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3237                           __func__, __LINE__);
3238                return -1;
3239        }
3240
3241        og_schedule_run(atoi(params->task_id), 0, OG_SCHEDULE_TASK);
3242        og_dbi_close(dbi);
3243
3244        list_for_each_entry(cmd, &cmd_list, list)
3245                params->ips_array[params->ips_array_len++] = cmd->ip;
3246
3247        return og_send_request(OG_METHOD_GET, OG_CMD_RUN_SCHEDULE, params,
3248                               NULL);
3249}
3250
[a801e78]3251#define OG_QUERY_MAXLEN 4096
3252
3253static int og_dbi_scope_get_computer(const struct og_dbi *dbi, json_t *array,
3254                                     const char* query)
[c46fa3c]3255{
[91c3a28]3256        const char *computer_name, *computer_ip;
[f520a57]3257        uint32_t computer_id;
[3d253e6]3258        const char *msglog;
3259        dbi_result result;
[f520a57]3260        json_t *computer;
[3d253e6]3261
[a801e78]3262        result = dbi_conn_queryf(dbi->conn, query);
[3d253e6]3263        if (!result) {
3264                dbi_conn_error(dbi->conn, &msglog);
3265                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3266                       __func__, __LINE__, msglog);
3267                return -1;
3268        }
3269
3270        while (dbi_result_next_row(result)) {
[f520a57]3271                computer_id = dbi_result_get_uint(result, "idordenador");
[91c3a28]3272                computer_name = dbi_result_get_string(result, "nombreordenador");
3273                computer_ip = dbi_result_get_string(result, "ip");
[3d253e6]3274
[f520a57]3275                computer = json_object();
3276                if (!computer) {
[3d253e6]3277                        dbi_result_free(result);
3278                        return -1;
3279                }
3280
[f520a57]3281                json_object_set_new(computer, "name", json_string(computer_name));
3282                json_object_set_new(computer, "type", json_string("computer"));
3283                json_object_set_new(computer, "id", json_integer(computer_id));
3284                json_object_set_new(computer, "scope", json_array());
[91c3a28]3285                json_object_set_new(computer, "ip", json_string(computer_ip));
[f520a57]3286                json_array_append(array, computer);
3287                json_decref(computer);
[3d253e6]3288        }
3289        dbi_result_free(result);
3290
3291        return 0;
3292}
3293
[a801e78]3294static int og_dbi_scope_get_computer_from_room(const struct og_dbi *dbi,
3295                                               json_t *array, char *query,
3296                                               const uint32_t room_id)
[c46fa3c]3297{
[a801e78]3298        int ret = snprintf(query, OG_QUERY_MAXLEN,
3299                           "SELECT idordenador, nombreordenador, ip "
3300                           "FROM ordenadores WHERE idaula=%d and grupoid=0",
3301                           room_id);
3302        if (ret <= 0 || ret >= OG_QUERY_MAXLEN)
3303                return -1;
3304
3305        return og_dbi_scope_get_computer(dbi, array, query);
3306}
3307
3308static int og_dbi_scope_get_computer_from_computers(const struct og_dbi *dbi,
3309                                                    json_t *array,
3310                                                    char *query,
3311                                                    const uint32_t computers_id)
3312{
3313        int ret = snprintf(query, OG_QUERY_MAXLEN,
3314                           "SELECT idordenador, nombreordenador, ip "
3315                           "FROM ordenadores WHERE grupoid=%d",
3316                           computers_id);
3317        if (ret <= 0 || ret >= OG_QUERY_MAXLEN)
3318                return -1;
3319
3320        return og_dbi_scope_get_computer(dbi, array, query);
3321}
3322
3323static int og_dbi_scope_get_computers_from_computers(const struct og_dbi *dbi,
3324                                                     json_t *array,
3325                                                     char *query,
3326                                                     const uint32_t group_id);
3327
3328static int og_dbi_scope_get_computers(const struct og_dbi *dbi, json_t *array,
3329                                     char *query)
3330{
3331        const char *msglog, *computers_name;
3332        json_t *computers, *scope_array;
3333        uint32_t computers_id;
3334        dbi_result result;
3335
3336        result = dbi_conn_queryf(dbi->conn, query);
3337        if (!result) {
3338                dbi_conn_error(dbi->conn, &msglog);
3339                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3340                       __func__, __LINE__, msglog);
3341                return -1;
3342        }
3343
3344        while (dbi_result_next_row(result)) {
3345                computers_id = dbi_result_get_uint(result, "idgrupo");
3346                computers_name = dbi_result_get_string(result,
3347                                                      "nombregrupoordenador");
3348
3349                computers = json_object();
3350                if (!computers) {
3351                        dbi_result_free(result);
3352                        return -1;
3353                }
3354
3355                json_object_set_new(computers, "name",
3356                                    json_string(computers_name));
3357                json_object_set_new(computers, "type", json_string("folder"));
3358                json_object_set_new(computers, "id",
3359                                    json_integer(computers_id));
3360                json_object_set_new(computers, "scope", json_array());
3361                json_array_append(array, computers);
3362                json_decref(computers);
3363
3364                scope_array = json_object_get(computers, "scope");
3365                if (!scope_array) {
3366                        dbi_result_free(result);
3367                        return -1;
3368                }
3369
3370                if (og_dbi_scope_get_computers_from_computers(dbi,
3371                                                              scope_array,
3372                                                              query,
3373                                                              computers_id)) {
3374                        dbi_result_free(result);
3375                        return -1;
3376                }
3377
3378                if (og_dbi_scope_get_computer_from_computers(dbi,
3379                                                             scope_array,
3380                                                             query,
3381                                                             computers_id)) {
3382                        dbi_result_free(result);
3383                        return -1;
3384                }
3385        }
3386        dbi_result_free(result);
3387
3388        return 0;
3389}
3390
3391static int og_dbi_scope_get_computers_from_room(const struct og_dbi *dbi,
3392                                                json_t *array, char *query,
3393                                                const uint32_t room_id)
3394{
3395        int ret = snprintf(query, OG_QUERY_MAXLEN,
3396                           "SELECT idgrupo, nombregrupoordenador "
3397                           "FROM gruposordenadores "
3398                           "WHERE idaula=%d AND grupoid=0",
3399                           room_id);
3400        if (ret <= 0 || ret >= OG_QUERY_MAXLEN)
3401                return -1;
3402
3403        return og_dbi_scope_get_computers(dbi, array, query);
3404}
3405
3406static int og_dbi_scope_get_computers_from_computers(const struct og_dbi *dbi,
3407                                                     json_t *array,
3408                                                     char *query,
3409                                                     const uint32_t group_id)
3410{
3411        int ret = snprintf(query, OG_QUERY_MAXLEN,
3412                           "SELECT idgrupo, nombregrupoordenador "
3413                           "FROM gruposordenadores WHERE grupoid=%d",
3414                           group_id);
3415        if (ret <= 0 || ret >= OG_QUERY_MAXLEN)
3416                return -1;
3417
3418        return og_dbi_scope_get_computers(dbi, array, query);
3419}
3420
3421static int og_dbi_scope_get_room(const struct og_dbi *dbi, json_t *array,
3422                                 char *query)
3423{
3424        const char *msglog, *room_name;
3425        json_t *room, *scope_array;
[3d253e6]3426        dbi_result result;
3427        uint32_t room_id;
3428
[a801e78]3429        result = dbi_conn_queryf(dbi->conn, query);
[3d253e6]3430        if (!result) {
3431                dbi_conn_error(dbi->conn, &msglog);
3432                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3433                       __func__, __LINE__, msglog);
3434                return -1;
3435        }
3436
3437        while (dbi_result_next_row(result)) {
3438                room_id = dbi_result_get_uint(result, "idaula");
[a801e78]3439                room_name = dbi_result_get_string(result, "nombreaula");
[3d253e6]3440
3441                room = json_object();
3442                if (!room) {
3443                        dbi_result_free(result);
3444                        return -1;
3445                }
3446
3447                json_object_set_new(room, "name", json_string(room_name));
3448                json_object_set_new(room, "type", json_string("room"));
3449                json_object_set_new(room, "id", json_integer(room_id));
3450                json_object_set_new(room, "scope", json_array());
3451                json_array_append(array, room);
3452                json_decref(room);
[f520a57]3453
[a801e78]3454                scope_array = json_object_get(room, "scope");
3455                if (!scope_array) {
[f520a57]3456                        dbi_result_free(result);
3457                        return -1;
3458                }
3459
[a801e78]3460                if (og_dbi_scope_get_computers_from_room(dbi, scope_array,
3461                                                         query, room_id)) {
3462                        dbi_result_free(result);
3463                        return -1;
3464                }
3465
3466                if (og_dbi_scope_get_computer_from_room(dbi, scope_array,
3467                                                        query, room_id)) {
[f520a57]3468                        dbi_result_free(result);
3469                        return -1;
3470                }
[3d253e6]3471        }
3472        dbi_result_free(result);
3473
3474        return 0;
3475}
3476
[a801e78]3477static int og_dbi_scope_get_room_from_group(const struct og_dbi *dbi,
3478                                            json_t *array,
3479                                            char *query,
3480                                            const uint32_t group_id)
3481{
3482        int ret = snprintf(query, OG_QUERY_MAXLEN,
3483                           "SELECT idaula, nombreaula "
3484                           "FROM aulas WHERE grupoid=%d", group_id);
3485        if (ret <= 0 || ret >= OG_QUERY_MAXLEN)
3486                return -1;
3487
3488        return og_dbi_scope_get_room(dbi, array, query);
3489}
3490
3491static int og_dbi_scope_get_room_from_center(const struct og_dbi *dbi,
3492                                             json_t *array,
3493                                             char *query,
3494                                             const uint32_t center_id)
3495{
3496        int ret = snprintf(query, OG_QUERY_MAXLEN,
3497                           "SELECT idaula, nombreaula "
3498                           "FROM aulas WHERE idcentro=%d AND grupoid=0",
3499                           center_id);
3500        if (ret <= 0 || ret >= OG_QUERY_MAXLEN)
3501                return -1;
3502
3503        return og_dbi_scope_get_room(dbi, array, query);
3504}
3505
3506static int og_dbi_scope_get_group_from_group(const struct og_dbi *dbi,
3507                                             json_t *array,
3508                                             char *query,
3509                                             const uint32_t group_id);
3510
3511static int og_dbi_scope_get_group(const struct og_dbi *dbi,
3512                                  json_t *array,
3513                                  char *query)
3514{
3515        const char *msglog, *group_name;
3516        json_t *group, *scope_array;
3517        dbi_result result;
3518        uint32_t group_id;
3519
3520        result = dbi_conn_queryf(dbi->conn, query);
3521        if (!result) {
3522                dbi_conn_error(dbi->conn, &msglog);
3523                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3524                       __func__, __LINE__, msglog);
3525                return -1;
3526        }
3527
3528        while (dbi_result_next_row(result)) {
3529                group_id = dbi_result_get_uint(result, "idgrupo");
3530                group_name = dbi_result_get_string(result, "nombregrupo");
3531
3532                group = json_object();
3533                if (!group) {
3534                        dbi_result_free(result);
3535                        return -1;
3536                }
3537
3538                json_object_set_new(group, "name", json_string(group_name));
3539                json_object_set_new(group, "type", json_string("folder"));
3540                json_object_set_new(group, "id", json_integer(group_id));
3541                json_object_set_new(group, "scope", json_array());
3542                json_array_append(array, group);
3543                json_decref(group);
3544
3545                scope_array = json_object_get(group, "scope");
3546                if (!scope_array) {
3547                        dbi_result_free(result);
3548                        return -1;
3549                }
3550
3551                if (og_dbi_scope_get_group_from_group(dbi, scope_array, query,
3552                                                      group_id)) {
3553                        dbi_result_free(result);
3554                        return -1;
3555                }
3556
3557                if (og_dbi_scope_get_room_from_group(dbi, scope_array, query,
3558                                                     group_id)) {
3559                        dbi_result_free(result);
3560                        return -1;
3561                }
3562        }
3563        dbi_result_free(result);
3564
3565        return 0;
3566}
3567
3568static int og_dbi_scope_get_group_from_group(const struct og_dbi *dbi,
3569                                              json_t *array,
3570                                              char *query,
3571                                              const uint32_t group_id)
3572{
3573        int ret = snprintf(query, OG_QUERY_MAXLEN,
3574                           "SELECT idgrupo, nombregrupo "
3575                           "FROM grupos WHERE grupoid=%d", group_id);
3576        if (ret <= 0 || ret >= OG_QUERY_MAXLEN)
3577                return -1;
3578
3579        return og_dbi_scope_get_group(dbi, array, query);
3580}
3581
3582static int og_dbi_scope_get_group_from_center(const struct og_dbi *dbi,
3583                                              json_t *array,
3584                                              char *query,
3585                                              const uint32_t center_id)
3586{
3587        int group_type_room = 2;
3588        int ret = snprintf(query, OG_QUERY_MAXLEN,
3589                           "SELECT idgrupo, nombregrupo "
3590                           "FROM grupos "
3591                           "WHERE idcentro=%d AND grupoid=0 AND tipo=%d",
3592                           center_id, group_type_room);
3593        if (ret <= 0 || ret >= OG_QUERY_MAXLEN)
3594                return -1;
3595
3596        return og_dbi_scope_get_group(dbi, array, query);
3597}
3598
[f520a57]3599static int og_dbi_scope_get(struct og_dbi *dbi, json_t *array)
[c46fa3c]3600{
[a801e78]3601        const char *msglog, *center_name;
3602        json_t *center, *scope_array;
3603        char query[OG_QUERY_MAXLEN];
[f520a57]3604        uint32_t center_id;
[3d253e6]3605        dbi_result result;
3606
3607        result = dbi_conn_queryf(dbi->conn,
[f520a57]3608                                 "SELECT nombrecentro, idcentro FROM centros");
[3d253e6]3609        if (!result) {
3610                dbi_conn_error(dbi->conn, &msglog);
3611                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3612                       __func__, __LINE__, msglog);
3613                return -1;
3614        }
3615
3616        while (dbi_result_next_row(result)) {
[f520a57]3617                center_id = dbi_result_get_uint(result, "idcentro");
[a801e78]3618                center_name = dbi_result_get_string(result, "nombrecentro");
[3d253e6]3619
[f520a57]3620                center = json_object();
3621                if (!center) {
[3d253e6]3622                        dbi_result_free(result);
3623                        return -1;
3624                }
3625
[a801e78]3626                scope_array = json_array();
3627                if (!scope_array) {
[f520a57]3628                        dbi_result_free(result);
3629                        json_decref(center);
3630                        return -1;
3631                }
3632
3633                json_object_set_new(center, "name", json_string(center_name));
3634                json_object_set_new(center, "type", json_string("center"));
3635                json_object_set_new(center, "id", json_integer(center_id));
[a801e78]3636                json_object_set_new(center, "scope", scope_array);
[f520a57]3637                json_array_append(array, center);
3638                json_decref(center);
3639
[a801e78]3640                if (og_dbi_scope_get_group_from_center(dbi, scope_array, query,
3641                                                       center_id)) {
3642                        dbi_result_free(result);
3643                        return -1;
3644                }
3645
3646                if (og_dbi_scope_get_room_from_center(dbi, scope_array, query,
3647                                                      center_id)) {
[f520a57]3648                        dbi_result_free(result);
3649                        return -1;
3650                }
[3d253e6]3651        }
[f520a57]3652
[3d253e6]3653        dbi_result_free(result);
3654
3655        return 0;
3656}
3657
3658static int og_cmd_scope_get(json_t *element, struct og_msg_params *params,
3659                            char *buffer_reply)
3660{
3661        struct og_buffer og_buffer = {
3662                .data = buffer_reply
3663        };
[f520a57]3664        json_t *root, *array;
3665        struct og_dbi *dbi;
[3d253e6]3666
3667        root = json_object();
[76c0a05]3668        if (!root)
3669                return -1;
3670
[f520a57]3671        array = json_array();
3672        if (!array) {
[76c0a05]3673                json_decref(root);
[3d253e6]3674                return -1;
[76c0a05]3675        }
[f520a57]3676        json_object_set_new(root, "scope", array);
[3d253e6]3677
[fe1ce97]3678        dbi = og_dbi_open(&ogconfig.db);
[3d253e6]3679        if (!dbi) {
3680                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3681                       __func__, __LINE__);
[f520a57]3682                json_decref(root);
[3d253e6]3683                return -1;
3684        }
3685
[f520a57]3686        if (og_dbi_scope_get(dbi, array)) {
[3d253e6]3687                og_dbi_close(dbi);
[f520a57]3688                json_decref(root);
[3d253e6]3689                return -1;
3690        }
3691
3692        og_dbi_close(dbi);
3693
[2c6cef7]3694        if (json_dump_callback(root, og_json_dump_clients, &og_buffer, 0)) {
3695                json_decref(root);
3696                return -1;
3697        }
3698
[3d253e6]3699        json_decref(root);
3700
3701        return 0;
3702}
3703
[04ca20e]3704int og_dbi_schedule_get(void)
3705{
3706        uint32_t schedule_id, task_id;
3707        struct og_schedule_time time;
3708        struct og_dbi *dbi;
3709        const char *msglog;
3710        dbi_result result;
3711
[fe1ce97]3712        dbi = og_dbi_open(&ogconfig.db);
[04ca20e]3713        if (!dbi) {
3714                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3715                       __func__, __LINE__);
3716                return -1;
3717        }
3718
3719        result = dbi_conn_queryf(dbi->conn,
3720                                 "SELECT idprogramacion, tipoaccion, identificador, "
3721                                 "sesion, annos, meses, diario, dias, semanas, horas, "
3722                                 "ampm, minutos FROM programaciones "
3723                                 "WHERE suspendida = 0");
3724        if (!result) {
3725                dbi_conn_error(dbi->conn, &msglog);
3726                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3727                       __func__, __LINE__, msglog);
3728                og_dbi_close(dbi);
3729                return -1;
3730        }
3731
3732        while (dbi_result_next_row(result)) {
3733                memset(&time, 0, sizeof(time));
3734                schedule_id = dbi_result_get_uint(result, "idprogramacion");
3735                task_id = dbi_result_get_uint(result, "identificador");
3736                time.years = dbi_result_get_uint(result, "annos");
3737                time.months = dbi_result_get_uint(result, "meses");
3738                time.weeks = dbi_result_get_uint(result, "semanas");
3739                time.week_days = dbi_result_get_uint(result, "dias");
3740                time.days = dbi_result_get_uint(result, "diario");
3741                time.hours = dbi_result_get_uint(result, "horas");
3742                time.am_pm = dbi_result_get_uint(result, "ampm");
3743                time.minutes = dbi_result_get_uint(result, "minutos");
[e68fefe]3744                time.check_stale = true;
[04ca20e]3745
3746                og_schedule_create(schedule_id, task_id, OG_SCHEDULE_TASK,
3747                                   &time);
3748        }
3749
3750        dbi_result_free(result);
3751        og_dbi_close(dbi);
3752
3753        return 0;
3754}
3755
3756static int og_dbi_schedule_create(struct og_dbi *dbi,
3757                                  struct og_msg_params *params,
3758                                  uint32_t *schedule_id,
3759                                  enum og_schedule_type schedule_type)
3760{
3761        uint8_t suspended = 0;
3762        uint32_t session = 0;
3763        const char *msglog;
3764        dbi_result result;
3765        uint8_t type;
3766
3767        switch (schedule_type) {
3768        case OG_SCHEDULE_TASK:
3769                type = 3;
3770                break;
3771        case OG_SCHEDULE_PROCEDURE:
3772                type = 2;
3773                break;
3774        case OG_SCHEDULE_COMMAND:
3775                session = atoi(params->task_id);
3776                type = 1;
3777                break;
3778        }
3779
3780        result = dbi_conn_queryf(dbi->conn,
3781                                 "INSERT INTO programaciones (tipoaccion,"
3782                                 " identificador, nombrebloque, annos, meses,"
3783                                 " semanas, dias, diario, horas, ampm, minutos,"
3784                                 " suspendida, sesion) VALUES (%d, %s, '%s',"
3785                                 " %d, %d, %d, %d, %d, %d, %d, %d, %d, %d)",
3786                                 type, params->task_id, params->name,
3787                                 params->time.years, params->time.months,
3788                                 params->time.weeks, params->time.week_days,
3789                                 params->time.days, params->time.hours,
3790                                 params->time.am_pm, params->time.minutes,
3791                                 suspended, session);
3792        if (!result) {
3793                dbi_conn_error(dbi->conn, &msglog);
3794                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3795                       __func__, __LINE__, msglog);
3796                return -1;
3797        }
3798        dbi_result_free(result);
3799
3800        *schedule_id = dbi_conn_sequence_last(dbi->conn, NULL);
3801
3802        return 0;
3803}
3804
3805static int og_dbi_schedule_update(struct og_dbi *dbi,
3806                                  struct og_msg_params *params)
3807{
3808        const char *msglog;
3809        dbi_result result;
3810        uint8_t type = 3;
3811
3812        result = dbi_conn_queryf(dbi->conn,
3813                                 "UPDATE programaciones SET tipoaccion=%d, "
3814                                 "identificador='%s', nombrebloque='%s', "
3815                                 "annos=%d, meses=%d, "
3816                                 "diario=%d, horas=%d, ampm=%d, minutos=%d "
3817                                 "WHERE idprogramacion='%s'",
3818                                 type, params->task_id, params->name,
3819                                 params->time.years, params->time.months,
3820                                 params->time.days, params->time.hours,
3821                                 params->time.am_pm, params->time.minutes,
3822                                 params->id);
3823
3824        if (!result) {
3825                dbi_conn_error(dbi->conn, &msglog);
3826                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3827                       __func__, __LINE__, msglog);
3828                return -1;
3829        }
3830        dbi_result_free(result);
3831
3832        return 0;
3833}
3834
3835static int og_dbi_schedule_delete(struct og_dbi *dbi, uint32_t id)
3836{
3837        const char *msglog;
3838        dbi_result result;
3839
3840        result = dbi_conn_queryf(dbi->conn,
3841                                 "DELETE FROM programaciones WHERE idprogramacion=%d",
3842                                 id);
3843        if (!result) {
3844                dbi_conn_error(dbi->conn, &msglog);
3845                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3846                       __func__, __LINE__, msglog);
3847                return -1;
3848        }
3849        dbi_result_free(result);
3850
3851        return 0;
3852}
3853
3854struct og_db_schedule {
3855        uint32_t                id;
3856        uint32_t                task_id;
3857        const char              *name;
3858        struct og_schedule_time time;
3859        uint32_t                week_days;
3860        uint32_t                weeks;
3861        uint32_t                suspended;
3862        uint32_t                session;
3863};
3864
3865static int og_dbi_schedule_get_json(struct og_dbi *dbi, json_t *root,
3866                                    const char *task_id, const char *schedule_id)
3867{
3868        struct og_db_schedule schedule;
3869        json_t *obj, *array;
3870        const char *msglog;
3871        dbi_result result;
3872        int err = 0;
3873
3874        if (task_id) {
3875                result = dbi_conn_queryf(dbi->conn,
3876                                         "SELECT idprogramacion,"
3877                                         "       identificador, nombrebloque,"
3878                                         "       annos, meses, diario, dias,"
3879                                         "       semanas, horas, ampm,"
3880                                         "       minutos,suspendida, sesion "
3881                                         "FROM programaciones "
3882                                         "WHERE identificador=%d",
3883                                         atoi(task_id));
3884        } else if (schedule_id) {
3885                result = dbi_conn_queryf(dbi->conn,
3886                                         "SELECT idprogramacion,"
3887                                         "       identificador, nombrebloque,"
3888                                         "       annos, meses, diario, dias,"
3889                                         "       semanas, horas, ampm,"
3890                                         "       minutos,suspendida, sesion "
3891                                         "FROM programaciones "
3892                                         "WHERE idprogramacion=%d",
3893                                         atoi(schedule_id));
3894        } else {
3895                result = dbi_conn_queryf(dbi->conn,
3896                                         "SELECT idprogramacion,"
3897                                         "       identificador, nombrebloque,"
3898                                         "       annos, meses, diario, dias,"
3899                                         "       semanas, horas, ampm,"
3900                                         "       minutos,suspendida, sesion "
3901                                         "FROM programaciones");
3902        }
3903
3904        if (!result) {
3905                dbi_conn_error(dbi->conn, &msglog);
3906                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3907                       __func__, __LINE__, msglog);
3908                return -1;
3909        }
3910
3911        array = json_array();
3912        if (!array)
3913                return -1;
3914
3915        while (dbi_result_next_row(result)) {
3916                schedule.id = dbi_result_get_uint(result, "idprogramacion");
3917                schedule.task_id = dbi_result_get_uint(result, "identificador");
3918                schedule.name = dbi_result_get_string(result, "nombrebloque");
3919                schedule.time.years = dbi_result_get_uint(result, "annos");
3920                schedule.time.months = dbi_result_get_uint(result, "meses");
3921                schedule.time.days = dbi_result_get_uint(result, "diario");
3922                schedule.time.hours = dbi_result_get_uint(result, "horas");
3923                schedule.time.am_pm = dbi_result_get_uint(result, "ampm");
3924                schedule.time.minutes = dbi_result_get_uint(result, "minutos");
3925                schedule.week_days = dbi_result_get_uint(result, "dias");
3926                schedule.weeks = dbi_result_get_uint(result, "semanas");
3927                schedule.suspended = dbi_result_get_uint(result, "suspendida");
3928                schedule.session = dbi_result_get_uint(result, "sesion");
3929
3930                obj = json_object();
3931                if (!obj) {
3932                        err = -1;
3933                        break;
3934                }
3935                json_object_set_new(obj, "id", json_integer(schedule.id));
3936                json_object_set_new(obj, "task", json_integer(schedule.task_id));
3937                json_object_set_new(obj, "name", json_string(schedule.name));
3938                json_object_set_new(obj, "years", json_integer(schedule.time.years));
3939                json_object_set_new(obj, "months", json_integer(schedule.time.months));
3940                json_object_set_new(obj, "days", json_integer(schedule.time.days));
3941                json_object_set_new(obj, "hours", json_integer(schedule.time.hours));
3942                json_object_set_new(obj, "am_pm", json_integer(schedule.time.am_pm));
3943                json_object_set_new(obj, "minutes", json_integer(schedule.time.minutes));
3944                json_object_set_new(obj, "week_days", json_integer(schedule.week_days));
3945                json_object_set_new(obj, "weeks", json_integer(schedule.weeks));
3946                json_object_set_new(obj, "suspended", json_integer(schedule.suspended));
3947                json_object_set_new(obj, "session", json_integer(schedule.session));
3948
3949                json_array_append_new(array, obj);
3950        }
3951
3952        json_object_set_new(root, "schedule", array);
3953
3954        dbi_result_free(result);
3955
3956        return err;
3957}
3958
3959static int og_task_schedule_create(struct og_msg_params *params)
3960{
3961        enum og_schedule_type type;
3962        uint32_t schedule_id;
3963        struct og_dbi *dbi;
3964        int err;
3965
3966        if (!strcmp(params->type, "task"))
3967                type = OG_SCHEDULE_TASK;
3968        else if (!strcmp(params->type, "procedure"))
3969                type = OG_SCHEDULE_PROCEDURE;
3970        else if (!strcmp(params->type, "command"))
3971                type = OG_SCHEDULE_COMMAND;
3972        else
3973                return -1;
3974
[fe1ce97]3975        dbi = og_dbi_open(&ogconfig.db);
[04ca20e]3976        if (!dbi) {
3977                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3978                       __func__, __LINE__);
3979                return -1;
3980        }
3981
3982        err = og_dbi_schedule_create(dbi, params, &schedule_id, type);
3983        if (err < 0) {
3984                og_dbi_close(dbi);
3985                return -1;
3986        }
3987        og_schedule_create(schedule_id, atoi(params->task_id), type,
3988                           &params->time);
3989        og_schedule_refresh(og_loop);
3990        og_dbi_close(dbi);
3991
3992        return 0;
3993}
3994
[e68fefe]3995static uint32_t og_tm_years_mask(struct tm *tm)
3996{
3997        int i, j = 0;
3998
3999        for (i = 2010; i < 2026; i++, j++) {
4000                if (tm->tm_year + 1900 == i)
4001                        break;
4002        }
4003
4004        return (1 << j);
4005}
4006
4007static uint32_t og_tm_months_mask(struct tm *tm)
4008{
4009        return 1 << tm->tm_mon;
4010}
4011
[41bc66d]4012static uint16_t og_tm_hours_mask(struct tm *tm)
[e68fefe]4013{
[41bc66d]4014        return tm->tm_hour >= 12 ? 1 << (tm->tm_hour - 12) : 1 << tm->tm_hour;
[e68fefe]4015}
4016
4017static uint32_t og_tm_ampm(struct tm *tm)
4018{
4019        return tm->tm_hour < 12 ? 0 : 1;
4020}
4021
4022static uint32_t og_tm_days_mask(struct tm *tm)
4023{
4024        return 1 << (tm->tm_mday - 1);
4025}
4026
4027static void og_schedule_time_now(struct og_schedule_time *ogtime)
4028{
4029        struct tm *tm;
4030        time_t now;
4031
4032        now = time(NULL);
4033        tm = localtime(&now);
4034
4035        ogtime->years = og_tm_years_mask(tm);
4036        ogtime->months = og_tm_months_mask(tm);
4037        ogtime->weeks = 0;
4038        ogtime->week_days = 0;
4039        ogtime->days =  og_tm_days_mask(tm);
4040        ogtime->hours = og_tm_hours_mask(tm);
4041        ogtime->am_pm = og_tm_ampm(tm);
4042        ogtime->minutes = tm->tm_min;
4043}
4044
[04ca20e]4045static int og_cmd_schedule_create(json_t *element, struct og_msg_params *params)
4046{
[e68fefe]4047        bool when = false;
[04ca20e]4048        const char *key;
4049        json_t *value;
[e7e80cd]4050        int err = 0;
[04ca20e]4051
4052        if (json_typeof(element) != JSON_OBJECT)
4053                return -1;
4054
4055        json_object_foreach(element, key, value) {
4056                if (!strcmp(key, "task")) {
4057                        err = og_json_parse_string(value, &params->task_id);
4058                        params->flags |= OG_REST_PARAM_TASK;
4059                } else if (!strcmp(key, "name")) {
4060                        err = og_json_parse_string(value, &params->name);
4061                        params->flags |= OG_REST_PARAM_NAME;
4062                } else if (!strcmp(key, "when")) {
4063                        err = og_json_parse_time_params(value, params);
[e68fefe]4064                        when = true;
[04ca20e]4065                } else if (!strcmp(key, "type")) {
4066                        err = og_json_parse_string(value, &params->type);
4067                        params->flags |= OG_REST_PARAM_TYPE;
4068                }
4069
4070                if (err < 0)
[e7e80cd]4071                        return err;
[04ca20e]4072        }
4073
[e68fefe]4074        if (!when) {
4075                params->time.check_stale = false;
4076                og_schedule_time_now(&params->time);
4077                params->flags |= OG_REST_PARAM_TIME_YEARS |
4078                                 OG_REST_PARAM_TIME_MONTHS |
4079                                 OG_REST_PARAM_TIME_WEEKS |
4080                                 OG_REST_PARAM_TIME_WEEK_DAYS |
4081                                 OG_REST_PARAM_TIME_DAYS |
4082                                 OG_REST_PARAM_TIME_HOURS |
4083                                 OG_REST_PARAM_TIME_AM_PM |
4084                                 OG_REST_PARAM_TIME_MINUTES;
4085        } else {
4086                params->time.check_stale = true;
4087        }
4088
[04ca20e]4089        if (!og_msg_params_validate(params, OG_REST_PARAM_TASK |
4090                                            OG_REST_PARAM_NAME |
4091                                            OG_REST_PARAM_TIME_YEARS |
4092                                            OG_REST_PARAM_TIME_MONTHS |
4093                                            OG_REST_PARAM_TIME_WEEKS |
4094                                            OG_REST_PARAM_TIME_WEEK_DAYS |
4095                                            OG_REST_PARAM_TIME_DAYS |
4096                                            OG_REST_PARAM_TIME_HOURS |
4097                                            OG_REST_PARAM_TIME_MINUTES |
4098                                            OG_REST_PARAM_TIME_AM_PM |
4099                                            OG_REST_PARAM_TYPE))
4100                return -1;
4101
4102        return og_task_schedule_create(params);
4103}
4104
4105static int og_cmd_schedule_update(json_t *element, struct og_msg_params *params)
4106{
4107        struct og_dbi *dbi;
[8b7b5f3]4108        bool when = false;
[04ca20e]4109        const char *key;
4110        json_t *value;
[e7e80cd]4111        int err = 0;
[04ca20e]4112
4113        if (json_typeof(element) != JSON_OBJECT)
4114                return -1;
4115
4116        json_object_foreach(element, key, value) {
4117                if (!strcmp(key, "id")) {
4118                        err = og_json_parse_string(value, &params->id);
4119                        params->flags |= OG_REST_PARAM_ID;
4120                } else if (!strcmp(key, "task")) {
4121                        err = og_json_parse_string(value, &params->task_id);
4122                        params->flags |= OG_REST_PARAM_TASK;
4123                } else if (!strcmp(key, "name")) {
4124                        err = og_json_parse_string(value, &params->name);
4125                        params->flags |= OG_REST_PARAM_NAME;
[8b7b5f3]4126                } else if (!strcmp(key, "when")) {
[04ca20e]4127                        err = og_json_parse_time_params(value, params);
[8b7b5f3]4128                        when = true;
4129                }
[04ca20e]4130
4131                if (err < 0)
[e7e80cd]4132                        return err;
[04ca20e]4133        }
4134
[8b7b5f3]4135        if (!when) {
4136                params->time.check_stale = false;
4137                og_schedule_time_now(&params->time);
4138                params->flags |= OG_REST_PARAM_TIME_YEARS |
4139                                 OG_REST_PARAM_TIME_MONTHS |
4140                                 OG_REST_PARAM_TIME_WEEKS |
4141                                 OG_REST_PARAM_TIME_WEEK_DAYS |
4142                                 OG_REST_PARAM_TIME_DAYS |
4143                                 OG_REST_PARAM_TIME_HOURS |
4144                                 OG_REST_PARAM_TIME_AM_PM |
4145                                 OG_REST_PARAM_TIME_MINUTES;
4146        } else {
4147                params->time.check_stale = true;
4148        }
4149
[04ca20e]4150        if (!og_msg_params_validate(params, OG_REST_PARAM_ID |
4151                                            OG_REST_PARAM_TASK |
4152                                            OG_REST_PARAM_NAME |
4153                                            OG_REST_PARAM_TIME_YEARS |
4154                                            OG_REST_PARAM_TIME_MONTHS |
4155                                            OG_REST_PARAM_TIME_DAYS |
4156                                            OG_REST_PARAM_TIME_HOURS |
4157                                            OG_REST_PARAM_TIME_MINUTES |
4158                                            OG_REST_PARAM_TIME_AM_PM))
4159                return -1;
4160
[fe1ce97]4161        dbi = og_dbi_open(&ogconfig.db);
[04ca20e]4162        if (!dbi) {
4163                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
4164                           __func__, __LINE__);
4165                return -1;
4166        }
4167
4168        err = og_dbi_schedule_update(dbi, params);
4169        og_dbi_close(dbi);
4170
4171        if (err < 0)
4172                return err;
4173
4174        og_schedule_update(og_loop, atoi(params->id), atoi(params->task_id),
4175                           &params->time);
4176        og_schedule_refresh(og_loop);
4177
4178        return err;
4179}
4180
4181static int og_cmd_schedule_delete(json_t *element, struct og_msg_params *params)
4182{
4183        struct og_dbi *dbi;
4184        const char *key;
4185        json_t *value;
[e7e80cd]4186        int err = 0;
[04ca20e]4187
4188        if (json_typeof(element) != JSON_OBJECT)
4189                return -1;
4190
4191        json_object_foreach(element, key, value) {
4192                if (!strcmp(key, "id")) {
4193                        err = og_json_parse_string(value, &params->id);
4194                        params->flags |= OG_REST_PARAM_ID;
4195                }
4196
4197                if (err < 0)
[e7e80cd]4198                        return err;
[04ca20e]4199        }
4200
4201        if (!og_msg_params_validate(params, OG_REST_PARAM_ID))
4202                return -1;
4203
[fe1ce97]4204        dbi = og_dbi_open(&ogconfig.db);
[04ca20e]4205        if (!dbi) {
4206                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
4207                           __func__, __LINE__);
4208                return -1;
4209        }
4210
4211        err = og_dbi_schedule_delete(dbi, atoi(params->id));
4212        og_dbi_close(dbi);
4213
4214        og_schedule_delete(og_loop, atoi(params->id));
4215
4216        return err;
4217}
4218
4219static int og_cmd_schedule_get(json_t *element, struct og_msg_params *params,
4220                               char *buffer_reply)
4221{
4222        struct og_buffer og_buffer = {
4223                .data   = buffer_reply,
4224        };
4225        json_t *schedule_root;
4226        struct og_dbi *dbi;
4227        const char *key;
4228        json_t *value;
[e7e80cd]4229        int err = 0;
[04ca20e]4230
4231        if (element) {
4232                if (json_typeof(element) != JSON_OBJECT)
4233                        return -1;
4234
4235                json_object_foreach(element, key, value) {
4236                        if (!strcmp(key, "task")) {
4237                                err = og_json_parse_string(value,
4238                                                           &params->task_id);
4239                        } else if (!strcmp(key, "id")) {
4240                                err = og_json_parse_string(value, &params->id);
4241                        }
4242
4243                        if (err < 0)
[e7e80cd]4244                                return err;
[04ca20e]4245                }
4246        }
4247
[fe1ce97]4248        dbi = og_dbi_open(&ogconfig.db);
[04ca20e]4249        if (!dbi) {
4250                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
4251                           __func__, __LINE__);
4252                return -1;
4253        }
4254
4255        schedule_root = json_object();
4256        if (!schedule_root) {
4257                og_dbi_close(dbi);
4258                return -1;
4259        }
4260
4261        err = og_dbi_schedule_get_json(dbi, schedule_root,
4262                                       params->task_id, params->id);
4263        og_dbi_close(dbi);
4264
4265        if (err >= 0)
[2c6cef7]4266                err = json_dump_callback(schedule_root, og_json_dump_clients,
4267                                         &og_buffer, 0);
[04ca20e]4268
4269        json_decref(schedule_root);
4270
4271        return err;
4272}
4273
[8015f85]4274#define OG_LIVE_JSON_FILE_PATH "/opt/opengnsys/etc/ogliveinfo.json"
4275
4276static int og_cmd_oglive_list(char *buffer_reply)
4277{
4278        struct og_buffer og_buffer = {
4279                .data = buffer_reply
4280        };
4281        json_error_t json_err;
4282        json_t *root;
4283
4284        root = json_load_file(OG_LIVE_JSON_FILE_PATH, 0, &json_err);
4285        if (!root) {
4286                syslog(LOG_ERR, "malformed json line %d: %s\n",
4287                       json_err.line, json_err.text);
4288                return -1;
4289        }
4290
[2c6cef7]4291        if (json_dump_callback(root, og_json_dump_clients, &og_buffer, 0)) {
4292                json_decref(root);
4293                return -1;
4294        }
4295
[8015f85]4296        json_decref(root);
4297
4298        return 0;
4299}
4300
[0212091]4301static int og_cmd_post_center_add(json_t *element,
4302                                  struct og_msg_params *params,
4303                                  char *buffer_reply)
4304{
4305        const char *key, *msglog;
4306        struct og_dbi *dbi;
4307        dbi_result result;
4308        json_t *value;
4309        int err = 0;
4310
4311        json_object_foreach(element, key, value) {
4312                if (!strcmp(key, "name")) {
4313                        err = og_json_parse_string(value, &params->name);
4314                        params->flags |= OG_REST_PARAM_NAME;
4315                } else if (!strcmp(key, "comment")) {
4316                        err = og_json_parse_string(value, &params->comment);
4317                }
4318
4319                if (err < 0)
4320                        return err;
4321        }
4322
4323        if (!og_msg_params_validate(params, OG_REST_PARAM_NAME))
4324                return -1;
4325        if (!params->comment)
4326                params->comment = "";
4327
4328        dbi = og_dbi_open(&ogconfig.db);
4329        if (!dbi) {
4330                syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
4331                       __func__, __LINE__);
4332                return -1;
4333        }
4334
4335        result = dbi_conn_queryf(dbi->conn,
4336                                 "SELECT nombrecentro FROM centros WHERE nombrecentro='%s'",
4337                                 params->name);
4338
4339        if (!result) {
4340                dbi_conn_error(dbi->conn, &msglog);
4341                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
4342                       __func__, __LINE__, msglog);
4343                og_dbi_close(dbi);
4344                return -1;
4345        }
4346
4347        if (dbi_result_get_numrows(result) > 0) {
4348                syslog(LOG_ERR, "Center with name %s already exists\n",
4349                       params->name);
4350                dbi_result_free(result);
4351                og_dbi_close(dbi);
4352                return -1;
4353        }
4354        dbi_result_free(result);
4355
4356        result = dbi_conn_queryf(dbi->conn,
4357                                 "INSERT INTO centros("
4358                                 "  nombrecentro,"
4359                                 "  comentarios,"
4360                                 "  identidad) VALUES ("
4361                                 "'%s', '%s', 1)",
4362                                 params->name, params->comment);
4363
4364        if (!result) {
4365                dbi_conn_error(dbi->conn, &msglog);
4366                syslog(LOG_ERR, "failed to add center to database (%s:%d) %s\n",
4367                       __func__, __LINE__, msglog);
4368                og_dbi_close(dbi);
4369                return -1;
4370        }
4371
4372        dbi_result_free(result);
4373        og_dbi_close(dbi);
4374        return 0;
4375}
4376
[b487073]4377static int og_cmd_post_center_delete(json_t *element,
4378                                     struct og_msg_params *params)
4379{
4380        const char *key, *msglog;
4381        struct og_dbi *dbi;
4382        dbi_result result;
4383        json_t *value;
4384        int err = 0;
4385
4386        json_object_foreach(element, key, value) {
4387                if (!strcmp(key, "id")) {
4388                        err = og_json_parse_string(value, &params->id);
4389                        params->flags |= OG_REST_PARAM_ID;
4390                }
4391                if (err < 0)
4392                        return err;
4393        }
4394
4395        if (!og_msg_params_validate(params, OG_REST_PARAM_ID))
4396                return -1;
4397
4398        dbi = og_dbi_open(&ogconfig.db);
4399        if (!dbi) {
4400                syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
4401                       __func__, __LINE__);
4402                return -1;
4403        }
4404
4405        result = dbi_conn_queryf(dbi->conn,
4406                                 "DELETE FROM centros WHERE idcentro=%s",
4407                                 params->id);
4408
4409        if (!result) {
4410                dbi_conn_error(dbi->conn, &msglog);
4411                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
4412                       __func__, __LINE__, msglog);
4413                og_dbi_close(dbi);
4414                return -1;
4415        }
4416
4417        dbi_result_free(result);
4418
4419        og_dbi_close(dbi);
4420        return 0;
4421}
4422
[1fdb7e6]4423int og_procedure_add_steps(struct og_dbi *dbi, struct og_procedure *proc)
4424{
4425        struct og_procedure_step *step;
4426        const char *legacy_params;
4427        const char *msglog;
4428        dbi_result result;
4429        int i;
4430
4431        for (i = 0; i < proc->num_steps; i++) {
4432                step = &proc->steps[i];
4433                switch (step->type) {
4434                case OG_STEP_COMMAND:
4435                        legacy_params = og_msg_params_to_legacy(&step->cmd);
4436                        if (!legacy_params) {
4437                                og_dbi_close(dbi);
4438                                return -1;
4439                        }
4440                        result = dbi_conn_queryf(dbi->conn,
4441                                                 "INSERT INTO procedimientos_acciones "
4442                                                 "(idprocedimiento, orden, parametros) "
4443                                                 "VALUES (%d, %d, '%s')",
[cf7d074]4444                                                 proc->id,
[1fdb7e6]4445                                                 step->position,
4446                                                 legacy_params);
4447                        if (!result) {
4448                                dbi_conn_error(dbi->conn, &msglog);
4449                                syslog(LOG_ERR,
4450                                       "failed to add procedure command to database (%s:%d) %s\n",
4451                                       __func__, __LINE__, msglog);
4452                                og_dbi_close(dbi);
4453                                free((char *)legacy_params);
4454                                return -1;
4455                        }
4456
4457                        dbi_result_free(result);
4458                        free((char *)legacy_params);
4459                        break;
4460                case OG_STEP_PROCEDURE:
4461                        result = dbi_conn_queryf(dbi->conn,
4462                                                 "INSERT INTO procedimientos_acciones "
4463                                                 "(idprocedimiento, orden, procedimientoid) "
4464                                                 "VALUES (%d, %d, %d)",
[cf7d074]4465                                                 proc->id,
[1fdb7e6]4466                                                 step->position,
4467                                                 step->procedure.id);
4468                        if (!result) {
4469                                dbi_conn_error(dbi->conn, &msglog);
4470                                syslog(LOG_ERR,
4471                                       "failed to add procedure child to database (%s:%d) %s\n",
4472                                       __func__, __LINE__, msglog);
4473                                og_dbi_close(dbi);
4474                                return -1;
4475                        }
4476                        dbi_result_free(result);
4477                        break;
[7325a86]4478                case OG_STEP_TASK:
4479                        syslog(LOG_ERR, "Procedures can not include tasks. "
4480                                        "Invalid step: %d\n",
4481                               step->position);
4482                        return -1;
4483                        break;
[1fdb7e6]4484                }
4485        }
4486
4487        return 0;
4488}
4489
[41fad11]4490static int og_cmd_post_procedure_add(json_t *element,
4491                                     struct og_msg_params *params)
4492{
[1fdb7e6]4493        struct og_procedure proc = {};
[41fad11]4494        const char *key, *msglog;
4495        struct og_dbi *dbi;
4496        dbi_result result;
4497        json_t *value;
4498        int err = 0;
4499
4500        json_object_foreach(element, key, value) {
4501                if (!strcmp(key, "center")) {
4502                        err = og_json_parse_string(value, &params->id);
4503                        params->flags |= OG_REST_PARAM_ID;
4504                } else if (!strcmp(key, "name")) {
4505                        err = og_json_parse_string(value, &params->name);
4506                        params->flags |= OG_REST_PARAM_NAME;
[1fdb7e6]4507                } else if (!strcmp(key, "description")) {
[41fad11]4508                        err = og_json_parse_string(value, &params->comment);
[1fdb7e6]4509                } else if (!strcmp(key, "steps")) {
4510                        err = og_json_parse_procedure(value, &proc);
4511                }
[41fad11]4512
4513                if (err < 0)
4514                        return err;
4515        }
4516
4517        if (!og_msg_params_validate(params, OG_REST_PARAM_ID |
4518                                            OG_REST_PARAM_NAME))
4519                return -1;
4520
4521        dbi = og_dbi_open(&ogconfig.db);
4522        if (!dbi) {
4523                syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
4524                       __func__, __LINE__);
4525                return -1;
4526        }
4527
4528        result = dbi_conn_queryf(dbi->conn,
4529                                 "SELECT descripcion FROM procedimientos "
4530                                 "WHERE descripcion='%s' AND idcentro=%s",
4531                                 params->name, params->id);
4532
4533        if (!result) {
4534                dbi_conn_error(dbi->conn, &msglog);
4535                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
4536                       __func__, __LINE__, msglog);
4537                og_dbi_close(dbi);
4538                return -1;
4539        }
4540
4541        if (dbi_result_get_numrows(result) > 0) {
4542                syslog(LOG_ERR, "Procedure with name %s already exists in the "
4543                                "center with id %s\n",
4544                       params->name, params->id);
4545                dbi_result_free(result);
4546                og_dbi_close(dbi);
4547                return -1;
4548        }
4549        dbi_result_free(result);
4550
4551        result = dbi_conn_queryf(dbi->conn,
4552                                 "INSERT INTO procedimientos("
4553                                 "idcentro, descripcion, comentarios) "
4554                                 "VALUES (%s, '%s', '%s')",
4555                                 params->id, params->name, params->comment);
4556
4557        if (!result) {
4558                dbi_conn_error(dbi->conn, &msglog);
4559                syslog(LOG_ERR,
4560                       "failed to add procedure to database (%s:%d) %s\n",
4561                       __func__, __LINE__, msglog);
4562                og_dbi_close(dbi);
4563                return -1;
4564        }
4565        dbi_result_free(result);
[1fdb7e6]4566
4567        proc.id = dbi_conn_sequence_last(dbi->conn, NULL);
4568        err = og_procedure_add_steps(dbi, &proc);
4569
[41fad11]4570        og_dbi_close(dbi);
[1fdb7e6]4571
4572        return err;
[41fad11]4573}
4574
[830c321]4575static int og_cmd_post_procedure_delete(json_t *element,
4576                                        struct og_msg_params *params)
4577{
4578        const char *key, *msglog;
4579        struct og_dbi *dbi;
4580        dbi_result result;
4581        json_t *value;
4582        int err = 0;
4583
4584        json_object_foreach(element, key, value) {
4585                if (!strcmp(key, "id")) {
4586                        err = og_json_parse_string(value, &params->id);
4587                        params->flags |= OG_REST_PARAM_ID;
4588                }
4589                if (err < 0)
4590                        return err;
4591        }
4592
4593        if (!og_msg_params_validate(params, OG_REST_PARAM_ID))
4594                return -1;
4595
4596        dbi = og_dbi_open(&ogconfig.db);
4597        if (!dbi) {
4598                syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
4599                       __func__, __LINE__);
4600                return -1;
4601        }
4602
4603        result = dbi_conn_queryf(dbi->conn,
4604                                 "DELETE FROM procedimientos WHERE idprocedimiento=%s",
4605                                 params->id);
4606
4607        if (!result) {
4608                dbi_conn_error(dbi->conn, &msglog);
4609                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
4610                       __func__, __LINE__, msglog);
4611                og_dbi_close(dbi);
4612                return -1;
4613        } else if (dbi_result_get_numrows_affected(result) < 1) {
4614                syslog(LOG_ERR, "delete did not modify any row (%s:%d)\n",
4615                       __func__, __LINE__);
4616        }
4617
4618        dbi_result_free(result);
4619
4620        og_dbi_close(dbi);
4621        return 0;
4622}
4623
[a496da1]4624static int og_cmd_post_procedure_update(json_t *element,
4625                                        struct og_msg_params *params)
4626{
4627        struct og_procedure proc = {};
4628        const char *key, *msglog;
4629        struct og_dbi *dbi;
4630        dbi_result result;
4631        json_t *value;
4632        int err = 0;
4633
4634        json_object_foreach(element, key, value) {
4635                if (!strcmp(key, "procedure")) {
4636                        err = og_json_parse_string(value, &params->task_id);
4637                        params->flags |= OG_REST_PARAM_TASK;
4638                } else if (!strcmp(key, "center")) {
4639                        err = og_json_parse_string(value, &params->id);
4640                        params->flags |= OG_REST_PARAM_ID;
4641                } else if (!strcmp(key, "name")) {
4642                        err = og_json_parse_string(value, &params->name);
4643                        params->flags |= OG_REST_PARAM_NAME;
4644                } else if (!strcmp(key, "description")) {
4645                        err = og_json_parse_string(value, &params->comment);
4646                } else if (!strcmp(key, "steps")) {
4647                        err = og_json_parse_procedure(value, &proc);
4648                }
4649
4650                if (err < 0)
4651                        return err;
4652        }
4653
4654        if (!og_msg_params_validate(params, OG_REST_PARAM_TASK |
4655                                            OG_REST_PARAM_ID |
4656                                            OG_REST_PARAM_NAME))
4657                return -1;
4658
4659        dbi = og_dbi_open(&ogconfig.db);
4660        if (!dbi) {
4661                syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
4662                       __func__, __LINE__);
4663                return -1;
4664        }
4665
4666        result = dbi_conn_queryf(dbi->conn,
4667                                 "SELECT descripcion FROM procedimientos "
4668                                 "WHERE descripcion = '%s' AND idcentro = %s "
4669                                 "AND idprocedimiento <> %s",
4670                                 params->name, params->id, params->task_id);
4671
4672        if (!result) {
4673                dbi_conn_error(dbi->conn, &msglog);
4674                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
4675                       __func__, __LINE__, msglog);
4676                og_dbi_close(dbi);
4677                return -1;
4678        }
4679
4680        if (dbi_result_get_numrows(result) > 0) {
4681                syslog(LOG_ERR, "Procedure with name %s already exists in the "
4682                                "center with id %s\n",
4683                       params->name, params->id);
4684                dbi_result_free(result);
4685                og_dbi_close(dbi);
4686                return -1;
4687        }
4688        dbi_result_free(result);
4689
4690        result = dbi_conn_queryf(dbi->conn,
4691                                 "UPDATE procedimientos SET idcentro = %s, "
4692                                 "descripcion = '%s', comentarios = '%s' "
4693                                 "WHERE idprocedimiento = %s",
4694                                 params->id, params->name, params->comment,
4695                                 params->task_id);
4696
4697        if (!result) {
4698                dbi_conn_error(dbi->conn, &msglog);
4699                syslog(LOG_ERR,
4700                       "failed to update procedure %s (%s:%d) %s\n",
4701                       params->task_id, __func__, __LINE__, msglog);
4702                og_dbi_close(dbi);
4703                return -1;
4704        }
4705        dbi_result_free(result);
4706
4707        result = dbi_conn_queryf(dbi->conn,
4708                                 "DELETE FROM procedimientos_acciones "
4709                                 "WHERE idprocedimiento = %s",
4710                                 params->task_id);
4711
4712        if (!result) {
4713                dbi_conn_error(dbi->conn, &msglog);
4714                syslog(LOG_ERR,
4715                       "failed to delete old procedure %s steps (%s:%d) %s\n",
4716                       params->task_id, __func__, __LINE__, msglog);
4717                og_dbi_close(dbi);
4718                return -1;
4719        }
4720        dbi_result_free(result);
4721
4722        proc.id = atoll(params->task_id);
4723        err = og_procedure_add_steps(dbi, &proc);
4724
4725        og_dbi_close(dbi);
4726
4727        return err;
4728}
4729
[7325a86]4730static int og_task_add_steps(struct og_dbi *dbi, struct og_procedure *task)
4731{
4732        struct og_procedure_step *step;
4733        const char *msglog;
4734        dbi_result result;
4735        int i;
4736
4737        for (i = 0; i < task->num_steps; i++) {
4738                step = &task->steps[i];
4739                switch (step->type) {
4740                case OG_STEP_COMMAND:
4741                        syslog(LOG_ERR, "Tasks can not include commands. "
4742                                        "Invalid step: %d\n",
4743                               step->position);
4744                        return -1;
4745                        break;
4746                case OG_STEP_PROCEDURE:
4747                        result = dbi_conn_queryf(dbi->conn,
4748                                                 "INSERT INTO tareas_acciones "
4749                                                 "(idtarea, orden, idprocedimiento) "
4750                                                 "VALUES (%d, %d, %d)",
4751                                                 task->id,
4752                                                 step->position,
4753                                                 step->procedure.id);
4754                        if (!result) {
4755                                dbi_conn_error(dbi->conn, &msglog);
4756                                syslog(LOG_ERR,
4757                                       "failed to add procedure child to database (%s:%d) %s\n",
4758                                       __func__, __LINE__, msglog);
4759                                og_dbi_close(dbi);
4760                                return -1;
4761                        }
4762                        dbi_result_free(result);
4763                        break;
4764                case OG_STEP_TASK:
4765                        result = dbi_conn_queryf(dbi->conn,
4766                                                 "INSERT INTO tareas_acciones "
4767                                                 "(idtarea, orden, tareaid) "
4768                                                 "VALUES (%d, %d, %d)",
4769                                                 task->id,
4770                                                 step->position,
4771                                                 step->procedure.id);
4772                        if (!result) {
4773                                dbi_conn_error(dbi->conn, &msglog);
4774                                syslog(LOG_ERR,
4775                                       "failed to add task child to database (%s:%d) %s\n",
4776                                       __func__, __LINE__, msglog);
4777                                og_dbi_close(dbi);
4778                                return -1;
4779                        }
4780                        dbi_result_free(result);
4781                        break;
4782                }
4783        }
4784
4785        return 0;
4786}
4787
4788static int og_cmd_post_task_add(json_t *element,
4789                                     struct og_msg_params *params)
4790{
4791        struct og_procedure task = {};
4792        const char *key, *msglog;
4793        struct og_dbi *dbi;
4794        dbi_result result;
4795        json_t *value;
4796        int err = 0;
4797
4798        json_object_foreach(element, key, value) {
4799                if (!strcmp(key, "center")) {
4800                        err = og_json_parse_string(value, &params->id);
4801                        params->flags |= OG_REST_PARAM_ID;
4802                } else if (!strcmp(key, "name")) {
4803                        err = og_json_parse_string(value, &params->name);
4804                        params->flags |= OG_REST_PARAM_NAME;
4805                } else if (!strcmp(key, "description")) {
4806                        err = og_json_parse_string(value, &params->comment);
4807                } else if (!strcmp(key, "steps")) {
4808                        err = og_json_parse_procedure(value, &task);
4809                }
4810
4811                if (err < 0)
4812                        return err;
4813        }
4814
4815        if (!og_msg_params_validate(params, OG_REST_PARAM_ID |
4816                                            OG_REST_PARAM_NAME))
4817                return -1;
4818
4819        dbi = og_dbi_open(&ogconfig.db);
4820        if (!dbi) {
4821                syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
4822                       __func__, __LINE__);
4823                return -1;
4824        }
4825
4826        result = dbi_conn_queryf(dbi->conn,
4827                                 "SELECT descripcion FROM tareas "
4828                                 "WHERE descripcion='%s' AND idcentro=%s",
4829                                 params->name, params->id);
4830
4831        if (!result) {
4832                dbi_conn_error(dbi->conn, &msglog);
4833                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
4834                       __func__, __LINE__, msglog);
4835                og_dbi_close(dbi);
4836                return -1;
4837        }
4838
4839        if (dbi_result_get_numrows(result) > 0) {
4840                syslog(LOG_ERR, "Task with name %s already exists in the "
4841                                "center with id %s\n",
4842                       params->name, params->id);
4843                dbi_result_free(result);
4844                og_dbi_close(dbi);
4845                return -1;
4846        }
4847        dbi_result_free(result);
4848
4849        result = dbi_conn_queryf(dbi->conn,
4850                                 "INSERT INTO tareas("
4851                                 "idcentro, descripcion, comentarios) "
4852                                 "VALUES (%s, '%s', '%s')",
4853                                 params->id, params->name, params->comment);
4854
4855        if (!result) {
4856                dbi_conn_error(dbi->conn, &msglog);
4857                syslog(LOG_ERR,
4858                       "failed to add task to database (%s:%d) %s\n",
4859                       __func__, __LINE__, msglog);
4860                og_dbi_close(dbi);
4861                return -1;
4862        }
4863        dbi_result_free(result);
4864
4865        task.id = dbi_conn_sequence_last(dbi->conn, NULL);
4866        err = og_task_add_steps(dbi, &task);
4867
4868        og_dbi_close(dbi);
4869
4870        return err;
4871}
4872
[29e7641]4873static int og_cmd_post_room_add(json_t *element,
4874                                struct og_msg_params *params)
4875{
4876        struct og_room room = {};
4877        const char *key, *msglog;
4878        struct og_dbi *dbi;
4879        dbi_result result;
4880        json_t *value;
4881        int err = 0;
4882
4883        json_object_foreach(element, key, value) {
4884                if (!strcmp(key, "name")) {
4885                        err = og_json_parse_string_copy(value, room.name,
4886                                                        sizeof(room.name));
4887                        params->flags |= OG_REST_PARAM_NAME;
4888                } else if (!strcmp(key, "location")) {
4889                        err = og_json_parse_string_copy(value, room.location,
4890                                                        sizeof(room.location));
4891                } else if (!strcmp(key, "gateway")) {
4892                        err = og_json_parse_string_copy(value, room.gateway,
4893                                                        sizeof(room.gateway));
4894                } else if (!strcmp(key, "netmask")) {
4895                        err = og_json_parse_string_copy(value, room.netmask,
4896                                                        sizeof(room.netmask));
4897                        params->flags |= OG_REST_PARAM_NETMASK;
4898                } else if (!strcmp(key, "ntp")) {
4899                        err = og_json_parse_string_copy(value, room.ntp,
4900                                                        sizeof(room.ntp));
4901                } else if (!strcmp(key, "dns")) {
4902                        err = og_json_parse_string_copy(value, room.dns,
4903                                                        sizeof(room.dns));
4904                } else if (!strcmp(key, "center")) {
4905                        err = og_json_parse_uint(value, &room.center);
4906                        params->flags |= OG_REST_PARAM_CENTER;
4907                } else if (!strcmp(key, "group")) {
4908                        err = og_json_parse_uint(value, &room.group);
4909                } else if (!strcmp(key, "remote")) {
4910                        err = og_json_parse_bool(value, &room.remote);
4911                }
4912
4913                if (err < 0)
4914                        return err;
4915        }
4916
4917        if (!og_msg_params_validate(params, OG_REST_PARAM_NAME |
4918                                            OG_REST_PARAM_NETMASK |
4919                                            OG_REST_PARAM_CENTER))
4920                return -1;
4921
4922        dbi = og_dbi_open(&ogconfig.db);
4923        if (!dbi) {
4924                syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
4925                       __func__, __LINE__);
4926                return -1;
4927        }
4928
4929        result = dbi_conn_queryf(dbi->conn,
4930                                 "SELECT nombreaula FROM aulas "
4931                                 "WHERE nombreaula='%s' AND idcentro=%d",
4932                                 room.name, room.center);
4933
4934        if (!result) {
4935                dbi_conn_error(dbi->conn, &msglog);
4936                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
4937                       __func__, __LINE__, msglog);
4938                og_dbi_close(dbi);
4939                return -1;
4940        }
4941
4942        if (dbi_result_get_numrows(result) > 0) {
4943                syslog(LOG_ERR, "Room with name %s already exists in the "
4944                                "center with id %d\n",
4945                       room.name, room.center);
4946                dbi_result_free(result);
4947                og_dbi_close(dbi);
4948                return -1;
4949        }
4950        dbi_result_free(result);
4951
4952        result = dbi_conn_queryf(dbi->conn,
4953                                 "INSERT INTO aulas("
4954                                 "  idcentro,"
4955                                 "  nombreaula,"
4956                                 "  netmask,"
4957                                 "  grupoid,"
4958                                 "  ubicacion,"
4959                                 "  router,"
4960                                 "  dns,"
4961                                 "  ntp,"
4962                                 "  inremotepc) VALUES ("
4963                                 "%d, '%s', '%s', %d, '%s', "
4964                                 "'%s', '%s', '%s', %d)",
4965                                 room.center, room.name, room.netmask,
4966                                 room.group, room.location, room.gateway,
4967                                 room.dns, room.ntp, room.remote);
4968
4969        if (!result) {
4970                dbi_conn_error(dbi->conn, &msglog);
4971                syslog(LOG_ERR, "failed to add room to database (%s:%d) %s\n",
4972                       __func__, __LINE__, msglog);
4973                og_dbi_close(dbi);
4974                return -1;
4975        }
4976
4977        dbi_result_free(result);
4978        og_dbi_close(dbi);
4979        return 0;
4980}
4981
[bc94247]4982static int og_cmd_post_room_delete(json_t *element,
4983                                   struct og_msg_params *params)
4984{
4985        const char *key, *msglog;
4986        struct og_dbi *dbi;
4987        dbi_result result;
4988        json_t *value;
4989        int err = 0;
4990
4991        json_object_foreach(element, key, value) {
4992                if (!strcmp(key, "id")) {
4993                        err = og_json_parse_string(value, &params->id);
4994                        params->flags |= OG_REST_PARAM_ID;
4995                }
4996                if (err < 0)
4997                        return err;
4998        }
4999
5000        if (!og_msg_params_validate(params, OG_REST_PARAM_ID))
5001                return -1;
5002
5003        dbi = og_dbi_open(&ogconfig.db);
5004        if (!dbi) {
5005                syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
5006                       __func__, __LINE__);
5007                return -1;
5008        }
5009
5010        result = dbi_conn_queryf(dbi->conn,
5011                                 "DELETE FROM aulas WHERE idaula=%s",
5012                                 params->id);
5013
5014        if (!result) {
5015                dbi_conn_error(dbi->conn, &msglog);
5016                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
5017                       __func__, __LINE__, msglog);
5018                og_dbi_close(dbi);
5019                return -1;
5020        }
5021
5022        dbi_result_free(result);
5023
5024        og_dbi_close(dbi);
5025        return 0;
5026}
5027
[141b079]5028enum {
5029        OG_SCHEDULE_CMD_TYPE    = 0,
5030        OG_SCHEDULE_CMD_PARAMS,
5031};
5032
5033static bool og_cmd_validate(const struct og_cmd_json *cmd,
5034                            const uint64_t flags)
5035{
5036        return (cmd->flags & flags) == flags;
5037}
5038
5039
5040static int og_cmd_post_schedule_command(json_t *element,
5041                                        struct og_msg_params *params)
5042{
5043        char *centerid_query  = "SELECT o.idordenador, c.idcentro "
5044                                "FROM `ordenadores` AS o "
5045                                "INNER JOIN aulas AS a ON o.idaula = a.idaula "
5046                                "INNER JOIN centros AS c ON a.idcentro = c.idcentro "
5047                                "WHERE o.ip = '%s';";
[33d8cec]5048        uint32_t sequence, session = 0;
[141b079]5049        int center_id, client_id, len;
5050        struct og_cmd_json cmd = {};
5051        const char *legacy_params;
5052        const char *key, *msglog;
5053        struct og_dbi *dbi;
5054        char task_id[128];
5055        bool when = false;
5056        dbi_result result;
5057        json_t *value;
5058        int err = 0, i;
5059
5060        json_object_foreach(element, key, value) {
5061                if (!strcmp(key, "clients")) {
5062                        err = og_json_parse_clients(value, params);
5063                } else if (!strcmp(key, "command")) {
5064                        err = og_json_parse_string(value, &cmd.type);
5065                        cmd.flags |= OG_SCHEDULE_CMD_TYPE;
5066                } else if (!strcmp(key, "params")) {
5067                        cmd.json = value;
5068                        cmd.flags |= OG_SCHEDULE_CMD_PARAMS;
5069                } else if (!strcmp(key, "when")) {
5070                        err = og_json_parse_time_params(value, params);
5071                        when = true;
5072                }
5073
5074                if (err < 0)
5075                        return err;
5076        }
5077
5078        if (!og_cmd_validate(&cmd, OG_SCHEDULE_CMD_TYPE |
5079                                   OG_SCHEDULE_CMD_PARAMS))
5080                return -1;
5081
5082        if (!when) {
5083                params->time.check_stale = false;
5084                og_schedule_time_now(&params->time);
5085                params->flags |= OG_REST_PARAM_TIME_YEARS |
5086                                 OG_REST_PARAM_TIME_MONTHS |
5087                                 OG_REST_PARAM_TIME_WEEKS |
5088                                 OG_REST_PARAM_TIME_WEEK_DAYS |
5089                                 OG_REST_PARAM_TIME_DAYS |
5090                                 OG_REST_PARAM_TIME_HOURS |
5091                                 OG_REST_PARAM_TIME_AM_PM |
5092                                 OG_REST_PARAM_TIME_MINUTES;
5093        } else {
5094                params->time.check_stale = true;
5095        }
5096
5097        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
5098                                            OG_REST_PARAM_TIME_YEARS |
5099                                            OG_REST_PARAM_TIME_MONTHS |
5100                                            OG_REST_PARAM_TIME_WEEKS |
5101                                            OG_REST_PARAM_TIME_WEEK_DAYS |
5102                                            OG_REST_PARAM_TIME_DAYS |
5103                                            OG_REST_PARAM_TIME_HOURS |
5104                                            OG_REST_PARAM_TIME_MINUTES |
5105                                            OG_REST_PARAM_TIME_AM_PM))
5106                return -1;
5107
5108        params->type = "command";
5109        dbi = og_dbi_open(&ogconfig.db);
5110        if (!dbi) {
5111                syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
5112                       __func__, __LINE__);
5113                goto err_dbi_open;
5114        }
5115
5116        legacy_params = og_msg_params_to_legacy(&cmd);
5117        if (!legacy_params)
5118                goto err_legacy_params;
5119
5120        /* ips_array -> ids */
5121        for (i = 0; i < params->ips_array_len; i++) {
5122
5123                result = dbi_conn_queryf(dbi->conn, centerid_query, params->ips_array[i]);
5124                if (!result) {
5125                        dbi_conn_error(dbi->conn, &msglog);
5126                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
5127                               __func__, __LINE__, msglog);
5128                        goto err_dbi_result;
5129                }
5130                if (dbi_result_get_numrows(result) != 1) {
5131                        dbi_conn_error(dbi->conn, &msglog);
5132                        syslog(LOG_ERR, "client not found (%s:%d) %s\n",
5133                               __func__, __LINE__, msglog);
5134                        goto err_dbi;
5135                }
5136
5137                if (!dbi_result_next_row(result)) {
5138                        dbi_conn_error(dbi->conn, &msglog);
5139                        syslog(LOG_ERR, "failed to get idcentro (%s:%d) %s\n",
5140                               __func__, __LINE__, msglog);
5141                        goto err_dbi;
5142                }
5143                center_id = dbi_result_get_uint(result, "idcentro");
5144                if (!center_id) {
5145                        dbi_conn_error(dbi->conn, &msglog);
5146                        syslog(LOG_ERR, "failed to get idcentro (%s:%d) %s\n",
5147                               __func__, __LINE__, msglog);
5148                        goto err_dbi;
5149                }
5150                client_id = dbi_result_get_uint(result, "idordenador");
5151                dbi_result_free(result);
5152
5153                result = dbi_conn_queryf(dbi->conn, "INSERT INTO acciones (idordenador, "
5154                                                    "idcentro, parametros)"
5155                                                    "VALUES (%d, %d, '%s')",
5156                                         client_id, center_id, legacy_params);
5157                if (!result) {
5158                        dbi_conn_error(dbi->conn, &msglog);
5159                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
5160                               __func__, __LINE__, msglog);
5161                        goto err_dbi_result;
5162                }
5163                dbi_result_free(result);
5164
5165                sequence = dbi_conn_sequence_last(dbi->conn, NULL);
[33d8cec]5166
5167                /* This 'session' ID allows us to correlate the schedule with
5168                 * the commands after expansion.
5169                 */
5170                if (!session)
5171                        session = dbi_conn_sequence_last(dbi->conn, NULL);
5172
5173                result = dbi_conn_queryf(dbi->conn, "UPDATE acciones SET idordenador=%d, "
5174                                                    "idcentro=%d, parametros='%s', sesion=%d"
5175                                                    "WHERE idaccion=%d",
5176                                         client_id, center_id, legacy_params,
5177                                         session, sequence);
5178                if (!result) {
5179                        dbi_conn_error(dbi->conn, &msglog);
5180                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
5181                               __func__, __LINE__, msglog);
5182                        goto err_dbi_result;
5183                }
5184                dbi_result_free(result);
[8190c6f]5185        }
[33d8cec]5186
[8190c6f]5187        len = snprintf(task_id, sizeof(session), "%d", session);
5188        if (len >= (int)sizeof(task_id)) {
5189                syslog(LOG_ERR, "truncated snprintf (%s:%d)\n",
5190                       __func__, __LINE__);
5191                goto err_dbi_result;
[141b079]5192        }
[8190c6f]5193        params->task_id = task_id;
[141b079]5194
[33d8cec]5195        og_task_schedule_create(params);
5196
[141b079]5197        free((char *)legacy_params);
5198        og_dbi_close(dbi);
5199        return 0;
5200
5201err_dbi:
5202        dbi_result_free(result);
5203err_dbi_result:
5204        free((char *)legacy_params);
5205err_legacy_params:
5206        og_dbi_close(dbi);
5207err_dbi_open:
5208        return -1;
5209}
5210
[c03b87d]5211static int og_cmd_post_procedure_run(json_t *element,
5212                                     struct og_msg_params *params)
5213{
5214        const char *centerid_query  = "SELECT o.idordenador, c.idcentro "
5215                                      "FROM `ordenadores` AS o "
5216                                      "INNER JOIN aulas AS a "
5217                                      "ON o.idaula = a.idaula "
5218                                      "INNER JOIN centros AS c "
5219                                      "ON a.idcentro = c.idcentro "
5220                                      "WHERE o.ip = '%s';";
5221        struct og_task task = {};
5222        const char *key, *msglog;
5223        struct og_dbi *dbi;
5224        dbi_result result;
5225        int i, err = 0;
5226        json_t *value;
5227
5228        json_object_foreach(element, key, value) {
5229                if (!strcmp(key, "clients")) {
5230                        err = og_json_parse_clients(value, params);
5231                } else if (!strcmp(key, "procedure")) {
5232                        err = og_json_parse_string(value, &params->id);
5233                        params->flags |= OG_REST_PARAM_ID;
5234                }
5235
5236                if (err < 0)
5237                        goto err_return;
5238        }
5239
5240        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
5241                                            OG_REST_PARAM_ID ))
5242                goto err_return;
5243
5244        task.type_scope = AMBITO_ORDENADORES;
5245        task.procedure_id = atoi(params->id);
5246
5247        dbi = og_dbi_open(&ogconfig.db);
5248        if (!dbi) {
5249                syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
5250                       __func__, __LINE__);
5251                goto err_return;
5252        }
5253
5254        for (i = 0; i < params->ips_array_len; i++) {
5255
5256                result = dbi_conn_queryf(dbi->conn, centerid_query, params->ips_array[i]);
5257                if (!result) {
5258                        dbi_conn_error(dbi->conn, &msglog);
5259                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
5260                               __func__, __LINE__, msglog);
5261                        goto err_close_dbi;
5262                }
5263
5264                if (dbi_result_get_numrows(result) != 1 ||
5265                    !dbi_result_next_row(result) ||
5266                    !dbi_result_get_uint(result, "idcentro") ||
5267                    !dbi_result_get_uint(result, "idordenador")) {
5268                        dbi_conn_error(dbi->conn, &msglog);
5269                        syslog(LOG_ERR, "failed to get query data (%s:%d) %s\n",
5270                               __func__, __LINE__, msglog);
5271                        goto err_free_result;
5272                }
5273
5274                task.center_id = dbi_result_get_uint(result, "idcentro");
5275                task.scope = dbi_result_get_uint(result, "idordenador");
5276                dbi_result_free(result);
5277
5278                if (og_dbi_queue_procedure(dbi, &task))
5279                        goto err_close_dbi;
5280        }
5281
5282        og_dbi_close(dbi);
5283
5284        return og_send_request(OG_METHOD_GET, OG_CMD_RUN_SCHEDULE, params,
5285                               NULL);
5286
5287err_free_result:
5288        dbi_result_free(result);
5289err_close_dbi:
5290        og_dbi_close(dbi);
5291err_return:
5292        return -1;
5293}
5294
[04ca20e]5295static int og_client_method_not_found(struct og_client *cli)
5296{
5297        /* To meet RFC 7231, this function MUST generate an Allow header field
5298         * containing the correct methods. For example: "Allow: POST\r\n"
5299         */
5300        char buf[] = "HTTP/1.1 405 Method Not Allowed\r\n"
5301                     "Content-Length: 0\r\n\r\n";
5302
5303        send(og_client_socket(cli), buf, strlen(buf), 0);
5304
5305        return -1;
5306}
5307
5308static int og_client_bad_request(struct og_client *cli)
5309{
5310        char buf[] = "HTTP/1.1 400 Bad Request\r\nContent-Length: 0\r\n\r\n";
5311
5312        send(og_client_socket(cli), buf, strlen(buf), 0);
5313
5314        return -1;
5315}
5316
5317static int og_client_not_found(struct og_client *cli)
5318{
5319        char buf[] = "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n";
5320
5321        send(og_client_socket(cli), buf, strlen(buf), 0);
5322
5323        return -1;
5324}
5325
5326static int og_client_not_authorized(struct og_client *cli)
5327{
5328        char buf[] = "HTTP/1.1 401 Unauthorized\r\n"
5329                     "WWW-Authenticate: Basic\r\n"
5330                     "Content-Length: 0\r\n\r\n";
5331
5332        send(og_client_socket(cli), buf, strlen(buf), 0);
5333
5334        return -1;
5335}
5336
5337static int og_server_internal_error(struct og_client *cli)
5338{
5339        char buf[] = "HTTP/1.1 500 Internal Server Error\r\n"
5340                     "Content-Length: 0\r\n\r\n";
5341
5342        send(og_client_socket(cli), buf, strlen(buf), 0);
5343
5344        return -1;
5345}
5346
5347static int og_client_ok(struct og_client *cli, char *buf_reply)
5348{
5349        char buf[OG_MSG_RESPONSE_MAXLEN] = {};
[90eab86]5350        int len;
[04ca20e]5351
5352        len = snprintf(buf, sizeof(buf),
5353                       "HTTP/1.1 200 OK\r\nContent-Length: %ld\r\n\r\n%s",
5354                       strlen(buf_reply), buf_reply);
[90eab86]5355        if (len >= (int)sizeof(buf)) {
5356                syslog(LOG_ERR, "HTTP response to %s:%hu is too large\n",
5357                       inet_ntoa(cli->addr.sin_addr),
5358                       ntohs(cli->addr.sin_port));
5359                return og_server_internal_error(cli);
5360        }
[04ca20e]5361
5362        send(og_client_socket(cli), buf, strlen(buf), 0);
5363
[90eab86]5364        return 0;
[04ca20e]5365}
5366
5367int og_client_state_process_payload_rest(struct og_client *cli)
5368{
5369        char buf_reply[OG_MSG_RESPONSE_MAXLEN] = {};
5370        struct og_msg_params params = {};
5371        enum og_rest_method method;
5372        const char *cmd, *body;
5373        json_error_t json_err;
5374        json_t *root = NULL;
5375        int err = 0;
5376
5377        syslog(LOG_DEBUG, "%s:%hu %.32s ...\n",
5378               inet_ntoa(cli->addr.sin_addr),
5379               ntohs(cli->addr.sin_port), cli->buf);
5380
5381        if (!strncmp(cli->buf, "GET", strlen("GET"))) {
5382                method = OG_METHOD_GET;
5383                cmd = cli->buf + strlen("GET") + 2;
5384        } else if (!strncmp(cli->buf, "POST", strlen("POST"))) {
5385                method = OG_METHOD_POST;
5386                cmd = cli->buf + strlen("POST") + 2;
5387        } else
5388                return og_client_method_not_found(cli);
5389
5390        body = strstr(cli->buf, "\r\n\r\n") + 4;
5391
[fe1ce97]5392        if (strcmp(cli->auth_token, ogconfig.rest.api_token)) {
[04ca20e]5393                syslog(LOG_ERR, "wrong Authentication key\n");
5394                return og_client_not_authorized(cli);
5395        }
5396
5397        if (cli->content_length) {
5398                root = json_loads(body, 0, &json_err);
5399                if (!root) {
5400                        syslog(LOG_ERR, "malformed json line %d: %s\n",
5401                               json_err.line, json_err.text);
5402                        return og_client_not_found(cli);
5403                }
5404        }
5405
5406        if (!strncmp(cmd, "clients", strlen("clients"))) {
5407                if (method != OG_METHOD_POST &&
[9b708e0]5408                    method != OG_METHOD_GET) {
5409                        err = og_client_method_not_found(cli);
5410                        goto err_process_rest_payload;
5411                }
[04ca20e]5412
5413                if (method == OG_METHOD_POST && !root) {
5414                        syslog(LOG_ERR, "command clients with no payload\n");
[9b708e0]5415                        err = og_client_bad_request(cli);
5416                        goto err_process_rest_payload;
[04ca20e]5417                }
5418                switch (method) {
5419                case OG_METHOD_POST:
5420                        err = og_cmd_post_clients(root, &params);
5421                        break;
5422                case OG_METHOD_GET:
5423                        err = og_cmd_get_clients(root, &params, buf_reply);
5424                        break;
5425                default:
[9b708e0]5426                        err = og_client_bad_request(cli);
5427                        goto err_process_rest_payload;
[04ca20e]5428                }
[b59ff7c]5429        } else if (!strncmp(cmd, "client/setup",
5430                            strlen("client/setup"))) {
[9b708e0]5431                if (method != OG_METHOD_GET) {
5432                        err = og_client_method_not_found(cli);
5433                        goto err_process_rest_payload;
5434                }
[b59ff7c]5435
5436                if (!root) {
5437                        syslog(LOG_ERR,
5438                               "command client partitions with no payload\n");
[9b708e0]5439                        err = og_client_bad_request(cli);
5440                        goto err_process_rest_payload;
[b59ff7c]5441                }
5442
5443                err = og_cmd_get_client_setup(root, &params, buf_reply);
[af47a08]5444        } else if (!strncmp(cmd, "client/info",
5445                            strlen("client/info"))) {
[9b708e0]5446                if (method != OG_METHOD_GET) {
5447                        err = og_client_method_not_found(cli);
5448                        goto err_process_rest_payload;
5449                }
[af47a08]5450                if (!root) {
5451                        syslog(LOG_ERR,
5452                               "command client info with no payload\n");
[9b708e0]5453                        err = og_client_bad_request(cli);
5454                        goto err_process_rest_payload;
[af47a08]5455                }
5456
5457                err = og_cmd_get_client_info(root, &params, buf_reply);
[65a14e5]5458        } else if (!strncmp(cmd, "client/add", strlen("client/add"))) {
[9b708e0]5459                if (method != OG_METHOD_POST) {
5460                        err = og_client_method_not_found(cli);
5461                        goto err_process_rest_payload;
5462                }
[65a14e5]5463
5464                if (!root) {
5465                        syslog(LOG_ERR,
5466                               "command client info with no payload\n");
[9b708e0]5467                        err = og_client_bad_request(cli);
5468                        goto err_process_rest_payload;
[65a14e5]5469                }
5470
5471                err = og_cmd_post_client_add(root, &params, buf_reply);
[24c8b94]5472        } else if (!strncmp(cmd, "client/delete", strlen("client/delete"))) {
[9b708e0]5473                if (method != OG_METHOD_POST) {
5474                        err = og_client_method_not_found(cli);
5475                        goto err_process_rest_payload;
5476                }
[24c8b94]5477
5478                if (!root) {
5479                        syslog(LOG_ERR,
5480                               "command client delete with no payload\n");
[9b708e0]5481                        err = og_client_bad_request(cli);
5482                        goto err_process_rest_payload;
[24c8b94]5483                }
5484
5485                err = og_cmd_post_client_delete(root, &params);
[04ca20e]5486        } else if (!strncmp(cmd, "wol", strlen("wol"))) {
[9b708e0]5487                if (method != OG_METHOD_POST) {
5488                        err = og_client_method_not_found(cli);
5489                        goto err_process_rest_payload;
5490                }
[04ca20e]5491
5492                if (!root) {
5493                        syslog(LOG_ERR, "command wol with no payload\n");
[9b708e0]5494                        err = og_client_bad_request(cli);
5495                        goto err_process_rest_payload;
[04ca20e]5496                }
5497                err = og_cmd_wol(root, &params);
5498        } else if (!strncmp(cmd, "shell/run", strlen("shell/run"))) {
[9b708e0]5499                if (method != OG_METHOD_POST) {
5500                        err = og_client_method_not_found(cli);
5501                        goto err_process_rest_payload;
5502                }
[04ca20e]5503
5504                if (!root) {
5505                        syslog(LOG_ERR, "command run with no payload\n");
[9b708e0]5506                        err = og_client_bad_request(cli);
5507                        goto err_process_rest_payload;
[04ca20e]5508                }
5509                err = og_cmd_run_post(root, &params);
5510        } else if (!strncmp(cmd, "shell/output", strlen("shell/output"))) {
[9b708e0]5511                if (method != OG_METHOD_POST) {
5512                        err = og_client_method_not_found(cli);
5513                        goto err_process_rest_payload;
5514                }
[04ca20e]5515
5516                if (!root) {
5517                        syslog(LOG_ERR, "command output with no payload\n");
[9b708e0]5518                        err = og_client_bad_request(cli);
5519                        goto err_process_rest_payload;
[04ca20e]5520                }
5521
5522                err = og_cmd_run_get(root, &params, buf_reply);
5523        } else if (!strncmp(cmd, "session", strlen("session"))) {
[9b708e0]5524                if (method != OG_METHOD_POST && method != OG_METHOD_GET) {
5525                        err = og_client_method_not_found(cli);
5526                        goto err_process_rest_payload;
5527                }
[04ca20e]5528
5529                if (!root) {
5530                        syslog(LOG_ERR, "command session with no payload\n");
[9b708e0]5531                        err = og_client_bad_request(cli);
5532                        goto err_process_rest_payload;
[04ca20e]5533                }
[7f5ab4a]5534
5535                if (method == OG_METHOD_POST)
5536                        err = og_cmd_session(root, &params);
5537                else
5538                        err = og_cmd_get_session(root, &params, buf_reply);
[3d253e6]5539        } else if (!strncmp(cmd, "scopes", strlen("scopes"))) {
[9b708e0]5540                if (method != OG_METHOD_GET) {
5541                        err = og_client_method_not_found(cli);
5542                        goto err_process_rest_payload;
5543                }
[3d253e6]5544
[aeb53bd]5545                if (root) {
5546                        syslog(LOG_ERR, "command scopes with payload\n");
[9b708e0]5547                        err = og_client_bad_request(cli);
5548                        goto err_process_rest_payload;
[aeb53bd]5549                }
5550
[3d253e6]5551                err = og_cmd_scope_get(root, &params, buf_reply);
[04ca20e]5552        } else if (!strncmp(cmd, "poweroff", strlen("poweroff"))) {
[9b708e0]5553                if (method != OG_METHOD_POST) {
5554                        err = og_client_method_not_found(cli);
5555                        goto err_process_rest_payload;
5556                }
[04ca20e]5557
5558                if (!root) {
5559                        syslog(LOG_ERR, "command poweroff with no payload\n");
[9b708e0]5560                        err = og_client_bad_request(cli);
5561                        goto err_process_rest_payload;
[04ca20e]5562                }
5563                err = og_cmd_poweroff(root, &params);
5564        } else if (!strncmp(cmd, "reboot", strlen("reboot"))) {
[9b708e0]5565                if (method != OG_METHOD_POST) {
5566                        err = og_client_method_not_found(cli);
5567                        goto err_process_rest_payload;
5568                }
[04ca20e]5569
5570                if (!root) {
5571                        syslog(LOG_ERR, "command reboot with no payload\n");
[9b708e0]5572                        err = og_client_bad_request(cli);
5573                        goto err_process_rest_payload;
[04ca20e]5574                }
5575                err = og_cmd_reboot(root, &params);
[b8a509b]5576        } else if (!strncmp(cmd, "mode", strlen("mode"))) {
[9b708e0]5577                if (method != OG_METHOD_GET && method != OG_METHOD_POST) {
5578                        err = og_client_method_not_found(cli);
5579                        goto err_process_rest_payload;
5580                }
[608709f]5581
[33b0c6f]5582                if (method == OG_METHOD_POST && !root) {
[b8a509b]5583                        syslog(LOG_ERR, "command mode with no payload\n");
[9b708e0]5584                        err = og_client_bad_request(cli);
5585                        goto err_process_rest_payload;
[33b0c6f]5586                }
5587
5588                if (method == OG_METHOD_GET)
5589                        err = og_cmd_get_modes(root, &params, buf_reply);
5590                else if (method == OG_METHOD_POST)
5591                        err = og_cmd_post_modes(root, &params);
[04ca20e]5592        } else if (!strncmp(cmd, "stop", strlen("stop"))) {
[9b708e0]5593                if (method != OG_METHOD_POST) {
5594                        err = og_client_method_not_found(cli);
5595                        goto err_process_rest_payload;
5596                }
[04ca20e]5597
5598                if (!root) {
5599                        syslog(LOG_ERR, "command stop with no payload\n");
[9b708e0]5600                        err = og_client_bad_request(cli);
5601                        goto err_process_rest_payload;
[04ca20e]5602                }
5603                err = og_cmd_stop(root, &params);
5604        } else if (!strncmp(cmd, "refresh", strlen("refresh"))) {
[9b708e0]5605                if (method != OG_METHOD_POST) {
5606                        err = og_client_method_not_found(cli);
5607                        goto err_process_rest_payload;
5608                }
[04ca20e]5609
5610                if (!root) {
5611                        syslog(LOG_ERR, "command refresh with no payload\n");
[9b708e0]5612                        err = og_client_bad_request(cli);
5613                        goto err_process_rest_payload;
[04ca20e]5614                }
5615                err = og_cmd_refresh(root, &params);
5616        } else if (!strncmp(cmd, "hardware", strlen("hardware"))) {
[9b708e0]5617                if (method != OG_METHOD_GET && method != OG_METHOD_POST) {
5618                        err = og_client_method_not_found(cli);
5619                        goto err_process_rest_payload;
5620                }
[04ca20e]5621
5622                if (!root) {
5623                        syslog(LOG_ERR, "command hardware with no payload\n");
[9b708e0]5624                        err = og_client_bad_request(cli);
5625                        goto err_process_rest_payload;
[04ca20e]5626                }
[a8eccba]5627
5628                if (method == OG_METHOD_GET)
5629                        err = og_cmd_get_hardware(root, &params, buf_reply);
5630                else if (method == OG_METHOD_POST)
5631                        err = og_cmd_hardware(root, &params);
[04ca20e]5632        } else if (!strncmp(cmd, "software", strlen("software"))) {
[9b708e0]5633                if (method != OG_METHOD_POST && method != OG_METHOD_GET) {
5634                        err = og_client_method_not_found(cli);
5635                        goto err_process_rest_payload;
5636                }
[04ca20e]5637
5638                if (!root) {
5639                        syslog(LOG_ERR, "command software with no payload\n");
[9b708e0]5640                        err = og_client_bad_request(cli);
5641                        goto err_process_rest_payload;
[04ca20e]5642                }
[25c1c16]5643
5644                if (method == OG_METHOD_POST)
5645                        err = og_cmd_software(root, &params);
5646                else
5647                        err = og_cmd_get_software(root, &params, buf_reply);
[403e7c3]5648        } else if (!strncmp(cmd, "images", strlen("images"))) {
[9b708e0]5649                if (method != OG_METHOD_GET) {
5650                        err = og_client_method_not_found(cli);
5651                        goto err_process_rest_payload;
5652                }
[403e7c3]5653
[9b708e0]5654                if (root) {
[d9e1521]5655                        err = og_client_bad_request(cli);
[9b708e0]5656                        goto err_process_rest_payload;
5657                }
5658
5659                err = og_cmd_images(buf_reply);
[04ca20e]5660        } else if (!strncmp(cmd, "image/create", strlen("image/create"))) {
[9b708e0]5661                if (method != OG_METHOD_POST) {
5662                        err = og_client_method_not_found(cli);
5663                        goto err_process_rest_payload;
5664                }
[04ca20e]5665
5666                if (!root) {
5667                        syslog(LOG_ERR, "command create with no payload\n");
[9b708e0]5668                        err = og_client_bad_request(cli);
5669                        goto err_process_rest_payload;
[04ca20e]5670                }
5671                err = og_cmd_create_image(root, &params);
5672        } else if (!strncmp(cmd, "image/restore", strlen("image/restore"))) {
[9b708e0]5673                if (method != OG_METHOD_POST) {
5674                        err = og_client_method_not_found(cli);
5675                        goto err_process_rest_payload;
5676                }
[04ca20e]5677
5678                if (!root) {
5679                        syslog(LOG_ERR, "command create with no payload\n");
[9b708e0]5680                        err = og_client_bad_request(cli);
5681                        goto err_process_rest_payload;
[04ca20e]5682                }
5683                err = og_cmd_restore_image(root, &params);
[36f0232]5684        } else if (!strncmp(cmd, "image/delete", strlen("image/delete"))) {
5685                if (method != OG_METHOD_POST) {
5686                        err = og_client_method_not_found(cli);
5687                        goto err_process_rest_payload;
5688                }
5689
5690                if (!root) {
5691                        syslog(LOG_ERR,
5692                               "command image delete with no payload\n");
5693                        err = og_client_bad_request(cli);
5694                        goto err_process_rest_payload;
5695                }
5696                err = og_cmd_delete_image(root, &params);
[04ca20e]5697        } else if (!strncmp(cmd, "setup", strlen("setup"))) {
[9b708e0]5698                if (method != OG_METHOD_POST) {
5699                        err = og_client_method_not_found(cli);
5700                        goto err_process_rest_payload;
5701                }
[04ca20e]5702
5703                if (!root) {
5704                        syslog(LOG_ERR, "command create with no payload\n");
[9b708e0]5705                        err = og_client_bad_request(cli);
5706                        goto err_process_rest_payload;
[04ca20e]5707                }
5708                err = og_cmd_setup(root, &params);
5709        } else if (!strncmp(cmd, "run/schedule", strlen("run/schedule"))) {
[9b708e0]5710                if (method != OG_METHOD_POST) {
5711                        err = og_client_method_not_found(cli);
5712                        goto err_process_rest_payload;
5713                }
[04ca20e]5714
5715                if (!root) {
5716                        syslog(LOG_ERR, "command create with no payload\n");
[9b708e0]5717                        err = og_client_bad_request(cli);
5718                        goto err_process_rest_payload;
[04ca20e]5719                }
5720
5721                err = og_cmd_run_schedule(root, &params);
5722        } else if (!strncmp(cmd, "task/run", strlen("task/run"))) {
[9b708e0]5723                if (method != OG_METHOD_POST) {
5724                        err = og_client_method_not_found(cli);
5725                        goto err_process_rest_payload;
5726                }
[04ca20e]5727
5728                if (!root) {
5729                        syslog(LOG_ERR, "command task with no payload\n");
[9b708e0]5730                        err = og_client_bad_request(cli);
5731                        goto err_process_rest_payload;
[04ca20e]5732                }
5733                err = og_cmd_task_post(root, &params);
5734        } else if (!strncmp(cmd, "schedule/create",
5735                            strlen("schedule/create"))) {
[9b708e0]5736                if (method != OG_METHOD_POST) {
5737                        err = og_client_method_not_found(cli);
5738                        goto err_process_rest_payload;
5739                }
[04ca20e]5740
5741                if (!root) {
5742                        syslog(LOG_ERR, "command task with no payload\n");
[9b708e0]5743                        err = og_client_bad_request(cli);
5744                        goto err_process_rest_payload;
[04ca20e]5745                }
5746                err = og_cmd_schedule_create(root, &params);
5747        } else if (!strncmp(cmd, "schedule/delete",
5748                            strlen("schedule/delete"))) {
[9b708e0]5749                if (method != OG_METHOD_POST) {
5750                        err = og_client_method_not_found(cli);
5751                        goto err_process_rest_payload;
5752                }
[04ca20e]5753
5754                if (!root) {
5755                        syslog(LOG_ERR, "command task with no payload\n");
[9b708e0]5756                        err = og_client_bad_request(cli);
5757                        goto err_process_rest_payload;
[04ca20e]5758                }
5759                err = og_cmd_schedule_delete(root, &params);
5760        } else if (!strncmp(cmd, "schedule/update",
5761                            strlen("schedule/update"))) {
[9b708e0]5762                if (method != OG_METHOD_POST) {
5763                        err = og_client_method_not_found(cli);
5764                        goto err_process_rest_payload;
5765                }
[04ca20e]5766
5767                if (!root) {
5768                        syslog(LOG_ERR, "command task with no payload\n");
[9b708e0]5769                        err = og_client_bad_request(cli);
5770                        goto err_process_rest_payload;
[04ca20e]5771                }
5772                err = og_cmd_schedule_update(root, &params);
5773        } else if (!strncmp(cmd, "schedule/get",
5774                            strlen("schedule/get"))) {
[9b708e0]5775                if (method != OG_METHOD_POST) {
5776                        err = og_client_method_not_found(cli);
5777                        goto err_process_rest_payload;
5778                }
[04ca20e]5779
5780                err = og_cmd_schedule_get(root, &params, buf_reply);
[8015f85]5781        } else if (!strncmp(cmd, "oglive/list",
5782                            strlen("oglive/list"))) {
5783                if (method != OG_METHOD_GET) {
5784                        err = og_client_method_not_found(cli);
5785                        goto err_process_rest_payload;
5786                }
5787
5788                err = og_cmd_oglive_list(buf_reply);
[0212091]5789        } else if (!strncmp(cmd, "center/add",
5790                            strlen("center/add"))) {
5791                if (method != OG_METHOD_POST) {
5792                        err = og_client_method_not_found(cli);
5793                        goto err_process_rest_payload;
5794                }
5795
5796                err = og_cmd_post_center_add(root, &params, buf_reply);
[b487073]5797        } else if (!strncmp(cmd, "center/delete", strlen("center/delete"))) {
5798                if (method != OG_METHOD_POST) {
5799                        err = og_client_method_not_found(cli);
5800                        goto err_process_rest_payload;
5801                }
5802
5803                if (!root) {
5804                        syslog(LOG_ERR,
5805                               "command center delete with no payload\n");
5806                        err = og_client_bad_request(cli);
5807                        goto err_process_rest_payload;
5808                }
5809                err = og_cmd_post_center_delete(root, &params);
[29e7641]5810        } else if (!strncmp(cmd, "room/add",
5811                            strlen("room/add"))) {
5812                if (method != OG_METHOD_POST) {
5813                        err = og_client_method_not_found(cli);
5814                        goto err_process_rest_payload;
5815                }
5816
5817                if (!root) {
5818                        syslog(LOG_ERR, "command task with no payload\n");
5819                        err = og_client_bad_request(cli);
5820                        goto err_process_rest_payload;
5821                }
5822                err = og_cmd_post_room_add(root, &params);
[bc94247]5823        } else if (!strncmp(cmd, "room/delete", strlen("room/delete"))) {
5824                if (method != OG_METHOD_POST) {
5825                        err = og_client_method_not_found(cli);
5826                        goto err_process_rest_payload;
5827                }
5828
5829                if (!root) {
5830                        syslog(LOG_ERR,
5831                               "command room delete with no payload\n");
5832                        err = og_client_bad_request(cli);
5833                        goto err_process_rest_payload;
5834                }
5835                err = og_cmd_post_room_delete(root, &params);
[41fad11]5836        } else if (!strncmp(cmd, "procedure/add", strlen("procedure/add"))) {
5837                if (method != OG_METHOD_POST) {
5838                        err = og_client_method_not_found(cli);
5839                        goto err_process_rest_payload;
5840                }
5841
5842                if (!root) {
5843                        syslog(LOG_ERR,
5844                               "command procedure add with no payload\n");
5845                        err = og_client_bad_request(cli);
5846                        goto err_process_rest_payload;
5847                }
5848                err = og_cmd_post_procedure_add(root, &params);
[a496da1]5849        } else if (!strncmp(cmd, "procedure/update",
5850                            strlen("procedure/update"))) {
5851                if (method != OG_METHOD_POST) {
5852                        err = og_client_method_not_found(cli);
5853                        goto err_process_rest_payload;
5854                }
5855
5856                if (!root) {
5857                        syslog(LOG_ERR,
5858                               "command procedure update with no payload\n");
5859                        err = og_client_bad_request(cli);
5860                        goto err_process_rest_payload;
5861                }
5862                err = og_cmd_post_procedure_update(root, &params);
[c03b87d]5863        } else if (!strncmp(cmd, "procedure/run", strlen("procedure/run"))) {
5864                if (method != OG_METHOD_POST) {
5865                        err = og_client_method_not_found(cli);
5866                        goto err_process_rest_payload;
5867                }
5868
5869                if (!root) {
5870                        syslog(LOG_ERR,
5871                               "command procedure run with no payload\n");
5872                        err = og_client_bad_request(cli);
5873                        goto err_process_rest_payload;
5874                }
5875                err = og_cmd_post_procedure_run(root, &params);
[141b079]5876        } else if (!strncmp(cmd, "schedule/command", strlen("schedule/command"))) {
5877                if (method != OG_METHOD_POST) {
5878                        err = og_client_method_not_found(cli);
5879                        goto err_process_rest_payload;
5880                }
5881
5882                if (!root) {
5883                        syslog(LOG_ERR,
5884                               "command schedule action with no payload\n");
5885                        err = og_client_bad_request(cli);
5886                        goto err_process_rest_payload;
5887                }
5888                err = og_cmd_post_schedule_command(root, &params);
[830c321]5889        } else if (!strncmp(cmd, "procedure/delete", strlen("schedule/command"))) {
5890                if (method != OG_METHOD_POST) {
5891                        err = og_client_method_not_found(cli);
5892                        goto err_process_rest_payload;
5893                }
5894
5895                if (!root) {
5896                        syslog(LOG_ERR,
5897                               "command procedure delete with no payload\n");
5898                        err = og_client_bad_request(cli);
5899                        goto err_process_rest_payload;
5900                }
5901                err = og_cmd_post_procedure_delete(root, &params);
[7325a86]5902        } else if (!strncmp(cmd, "task/add", strlen("task/add"))) {
5903                if (method != OG_METHOD_POST) {
5904                        err = og_client_method_not_found(cli);
5905                        goto err_process_rest_payload;
5906                }
5907
5908                if (!root) {
5909                        syslog(LOG_ERR,
5910                               "command task add with no payload\n");
5911                        err = og_client_bad_request(cli);
5912                        goto err_process_rest_payload;
5913                }
5914                err = og_cmd_post_task_add(root, &params);
[04ca20e]5915        } else {
5916                syslog(LOG_ERR, "unknown command: %.32s ...\n", cmd);
5917                err = og_client_not_found(cli);
5918        }
5919
[9b708e0]5920        json_decref(root);
[04ca20e]5921
5922        if (err < 0)
5923                return og_client_bad_request(cli);
5924
[90eab86]5925        return og_client_ok(cli, buf_reply);
[9b708e0]5926
5927err_process_rest_payload:
5928        json_decref(root);
5929
5930        return err;
[04ca20e]5931}
Note: See TracBrowser for help on using the repository browser.