source: ogServer-Git/src/rest.c @ 2d68f8a

Last change on this file since 2d68f8a was 2d68f8a, checked in by OpenGnSys Support Team <soporte-og@…>, 3 years ago

#1061 add timeout to pending scheduled commands

Pending schedule commands can deny ogLive boot of clients due
to filling of pending cmd queue with commands such as "Iniciar Sesión".

For example: Using RemotePC to serve clients that do not boot into
ogLive will fill up the pending command queue with "Iniciar Sesión".

Introduce a safety timeout for pending (scheduled) commands to
avoid this situation.

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