source: ogServer-Git/src/rest.c @ 6fc89cd

Last change on this file since 6fc89cd was e16f36c, checked in by Jose M. Guisado <jguisado@…>, 3 years ago

#915 Fix create image payload parsing

Commit 141b0797e17f616d6 introduced command scheduling rest api to
ogserver. Part of this changeset included
og_json_parse_create_image as a utility funtion to parse the json
payload of a "create image" command.

og_json_parse_create_image did not include the parsing of optional
parameters "description", "center_id" and "group_id". New components
like ogCP or ogCLI use these parameters.

Fix this by adding a struct og_image member to the struct og_msg_params
and assigning it when processing a "create image" command.

This could be extended to further payload parsing for image related
commands in the future.

  • Property mode set to 100644
File size: 143.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        const char *key;
2048        json_t *value;
2049        int err = 0;
2050
2051        if (json_typeof(element) != JSON_OBJECT)
2052                return -1;
2053
2054        json_object_foreach(element, key, value) {
2055                if (!strcmp(key, "disk")) {
2056                        err = og_json_parse_string(value, &params->disk);
2057                        params->flags |= OG_REST_PARAM_DISK;
2058                } else if (!strcmp(key, "partition")) {
2059                        err = og_json_parse_string(value, &params->partition);
2060                        params->flags |= OG_REST_PARAM_PARTITION;
2061                } else if (!strcmp(key, "name")) {
2062                        err = og_json_parse_string_copy(value,
2063                                                        (char *)&params->image.name,
2064                                                        sizeof(params->image.name));
2065                        params->flags |= OG_REST_PARAM_NAME;
2066                } else if (!strcmp(key, "repository")) {
2067                        err = og_json_parse_string(value, &params->repository);
2068                        params->flags |= OG_REST_PARAM_REPO;
2069                } else if (!strcmp(key, "clients")) {
2070                        err = og_json_parse_clients(value, params);
2071                } else if (!strcmp(key, "id")) {
2072                        err = og_json_parse_string(value, &params->id);
2073                        params->flags |= OG_REST_PARAM_ID;
2074                } else if (!strcmp(key, "code")) {
2075                        err = og_json_parse_string(value, &params->code);
2076                        params->flags |= OG_REST_PARAM_CODE;
2077                } else if (!strcmp(key, "description")) {
2078                        err = og_json_parse_string_copy(value,
2079                                                        (char *)&params->image.description,
2080                                                        sizeof(params->image.description));
2081                } else if (!strcmp(key, "group_id")) {
2082                        err = og_json_parse_uint64(value, &params->image.group_id);
2083                } else if (!strcmp(key, "center_id")) {
2084                        err = og_json_parse_uint64(value, &params->image.center_id);
2085                }
2086
2087                if (err < 0)
2088                        return err;
2089        }
2090
2091        return 0;
2092}
2093
2094static int og_cmd_create_image(json_t *element, struct og_msg_params *params)
2095{
2096        char new_image_id[OG_DB_INT_MAXLEN + 1];
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 (params->image.description[0]) {
2116                dbi = og_dbi_open(&ogconfig.db);
2117                if (!dbi) {
2118                        syslog(LOG_ERR,
2119                               "cannot open connection database (%s:%d)\n",
2120                               __func__, __LINE__);
2121                        return -1;
2122                }
2123
2124                err = og_dbi_add_image(dbi, &params->image);
2125
2126                og_dbi_close(dbi);
2127                if (err < 0)
2128                        return err;
2129
2130                snprintf(new_image_id, sizeof(new_image_id), "%u", err);
2131                params->id = new_image_id;
2132        }
2133
2134        clients = json_copy(element);
2135        json_object_del(clients, "clients");
2136
2137        return og_send_request(OG_METHOD_POST, OG_CMD_IMAGE_CREATE, params,
2138                               clients);
2139}
2140
2141int og_json_parse_restore_image(json_t *element, struct og_msg_params *params)
2142{
2143        const char *key;
2144        json_t *value;
2145        int err = 0;
2146
2147        if (json_typeof(element) != JSON_OBJECT)
2148                return -1;
2149
2150        json_object_foreach(element, key, value) {
2151                if (!strcmp(key, "disk")) {
2152                        err = og_json_parse_string(value, &params->disk);
2153                        params->flags |= OG_REST_PARAM_DISK;
2154                } else if (!strcmp(key, "partition")) {
2155                        err = og_json_parse_string(value, &params->partition);
2156                        params->flags |= OG_REST_PARAM_PARTITION;
2157                } else if (!strcmp(key, "name")) {
2158                        err = og_json_parse_string(value, &params->name);
2159                        params->flags |= OG_REST_PARAM_NAME;
2160                } else if (!strcmp(key, "repository")) {
2161                        err = og_json_parse_string(value, &params->repository);
2162                        params->flags |= OG_REST_PARAM_REPO;
2163                } else if (!strcmp(key, "clients")) {
2164                        err = og_json_parse_clients(value, params);
2165                } else if (!strcmp(key, "type")) {
2166                        err = og_json_parse_string(value, &params->type);
2167                        params->flags |= OG_REST_PARAM_TYPE;
2168                } else if (!strcmp(key, "profile")) {
2169                        err = og_json_parse_string(value, &params->profile);
2170                        params->flags |= OG_REST_PARAM_PROFILE;
2171                } else if (!strcmp(key, "id")) {
2172                        err = og_json_parse_string(value, &params->id);
2173                        params->flags |= OG_REST_PARAM_ID;
2174                }
2175
2176                if (err < 0)
2177                        return err;
2178        }
2179
2180        return 0;
2181}
2182
2183static int og_cmd_restore_image(json_t *element, struct og_msg_params *params)
2184{
2185        json_t *clients;
2186        int err = 0;
2187
2188        err = og_json_parse_restore_image(element, params);
2189        if (err < 0)
2190                return err;
2191
2192        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
2193                                            OG_REST_PARAM_DISK |
2194                                            OG_REST_PARAM_PARTITION |
2195                                            OG_REST_PARAM_NAME |
2196                                            OG_REST_PARAM_REPO |
2197                                            OG_REST_PARAM_TYPE |
2198                                            OG_REST_PARAM_PROFILE |
2199                                            OG_REST_PARAM_ID))
2200                return -1;
2201
2202        clients = json_copy(element);
2203        json_object_del(clients, "clients");
2204
2205        return og_send_request(OG_METHOD_POST, OG_CMD_IMAGE_RESTORE, params,
2206                               clients);
2207}
2208
2209static int og_cmd_delete_image(json_t *element, struct og_msg_params *params)
2210{
2211        char filename[PATH_MAX + 1];
2212        const char *key, *image;
2213        struct og_dbi *dbi;
2214        dbi_result result;
2215        int rval, err = 0;
2216        json_t *value;
2217
2218
2219        if (json_typeof(element) != JSON_OBJECT)
2220                return -1;
2221
2222        json_object_foreach(element, key, value) {
2223                if (!strcmp(key, "image")) {
2224                        err = og_json_parse_string(value, &params->id);
2225                        params->flags |= OG_REST_PARAM_ID;
2226                }
2227
2228                if (err < 0)
2229                        return err;
2230        }
2231
2232        if (!og_msg_params_validate(params, OG_REST_PARAM_ID))
2233                return -1;
2234
2235        dbi = og_dbi_open(&ogconfig.db);
2236        if (!dbi) {
2237                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
2238                       __func__, __LINE__);
2239                return -1;
2240        }
2241
2242        result = dbi_conn_queryf(dbi->conn,
2243                                 "SELECT nombreca FROM imagenes "
2244                                 "WHERE idimagen='%s'",
2245                                 params->id);
2246        if (!result) {
2247                og_dbi_close(dbi);
2248                syslog(LOG_ERR, "failed to query database\n");
2249                return -1;
2250        }
2251        if (!dbi_result_next_row(result)) {
2252                dbi_result_free(result);
2253                og_dbi_close(dbi);
2254                syslog(LOG_ERR, "image does not exist in database\n");
2255                return -1;
2256        }
2257
2258        image = dbi_result_get_string(result, "nombreca");
2259        snprintf(filename, sizeof(filename), "%s/%s.img", ogconfig.repo.dir,
2260                 image);
2261        dbi_result_free(result);
2262
2263        result = dbi_conn_queryf(dbi->conn,
2264                                 "DELETE FROM imagenes "
2265                                 "WHERE idimagen='%s'",
2266                                 params->id);
2267        if (!result) {
2268                og_dbi_close(dbi);
2269                syslog(LOG_ERR, "failed to query database\n");
2270                return -1;
2271        }
2272        dbi_result_free(result);
2273
2274        rval = unlink(filename);
2275        if (rval) {
2276                og_dbi_close(dbi);
2277                syslog(LOG_ERR, "cannot delete image %s: %s\n",
2278                       image, strerror(errno));
2279                return -1;
2280        }
2281        og_dbi_close(dbi);
2282
2283        return 0;
2284}
2285
2286static int og_cmd_setup(json_t *element, struct og_msg_params *params)
2287{
2288        json_t *value, *clients;
2289        const char *key;
2290        int err = 0;
2291
2292        if (json_typeof(element) != JSON_OBJECT)
2293                return -1;
2294
2295        json_object_foreach(element, key, value) {
2296                if (!strcmp(key, "clients")) {
2297                        err = og_json_parse_clients(value, params);
2298                } else if (!strcmp(key, "type")) {
2299                        err = og_json_parse_string(value, &params->type);
2300                        params->flags |= OG_REST_PARAM_TYPE;
2301                } else if (!strcmp(key, "disk")) {
2302                        err = og_json_parse_string(value, &params->disk);
2303                        params->flags |= OG_REST_PARAM_DISK;
2304                } else if (!strcmp(key, "cache")) {
2305                        err = og_json_parse_string(value, &params->cache);
2306                        params->flags |= OG_REST_PARAM_CACHE;
2307                } else if (!strcmp(key, "cache_size")) {
2308                        err = og_json_parse_string(value, &params->cache_size);
2309                        params->flags |= OG_REST_PARAM_CACHE_SIZE;
2310                } else if (!strcmp(key, "partition_setup")) {
2311                        err = og_json_parse_partition_setup(value, params);
2312                }
2313
2314                if (err < 0)
2315                        return err;
2316        }
2317
2318        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
2319                                            OG_REST_PARAM_TYPE |
2320                                            OG_REST_PARAM_DISK |
2321                                            OG_REST_PARAM_CACHE |
2322                                            OG_REST_PARAM_CACHE_SIZE |
2323                                            OG_REST_PARAM_PART_0 |
2324                                            OG_REST_PARAM_PART_1 |
2325                                            OG_REST_PARAM_PART_2 |
2326                                            OG_REST_PARAM_PART_3))
2327                return -1;
2328
2329        clients = json_copy(element);
2330        json_object_del(clients, "clients");
2331
2332        return og_send_request(OG_METHOD_POST, OG_CMD_SETUP, params, clients);
2333}
2334
2335static int og_cmd_run_schedule(json_t *element, struct og_msg_params *params)
2336{
2337        const char *key;
2338        json_t *value;
2339        int err = 0;
2340
2341        json_object_foreach(element, key, value) {
2342                if (!strcmp(key, "clients"))
2343                        err = og_json_parse_clients(value, params);
2344
2345                if (err < 0)
2346                        return err;
2347        }
2348
2349        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
2350                return -1;
2351
2352        return og_send_request(OG_METHOD_GET, OG_CMD_RUN_SCHEDULE, params,
2353                               NULL);
2354}
2355
2356static LIST_HEAD(cmd_list);
2357
2358const struct og_cmd *og_cmd_find(const char *client_ip)
2359{
2360        struct og_cmd *cmd, *next;
2361
2362        list_for_each_entry_safe(cmd, next, &cmd_list, list) {
2363                if (strcmp(cmd->ip, client_ip))
2364                        continue;
2365
2366                list_del(&cmd->list);
2367                return cmd;
2368        }
2369
2370        return NULL;
2371}
2372
2373void og_cmd_free(const struct og_cmd *cmd)
2374{
2375        struct og_msg_params *params = (struct og_msg_params *)&cmd->params;
2376        int i;
2377
2378        for (i = 0; i < params->ips_array_len; i++) {
2379                free((void *)params->netmask_array[i]);
2380                free((void *)params->ips_array[i]);
2381                free((void *)params->mac_array[i]);
2382        }
2383        free((void *)params->wol_type);
2384
2385        if (cmd->json)
2386                json_decref(cmd->json);
2387
2388        free((void *)cmd->ip);
2389        free((void *)cmd->mac);
2390        free((void *)cmd);
2391}
2392
2393static void og_cmd_init(struct og_cmd *cmd, enum og_rest_method method,
2394                        enum og_cmd_type type, json_t *root)
2395{
2396        cmd->type = type;
2397        cmd->method = method;
2398        cmd->params.ips_array[0] = strdup(cmd->ip);
2399        cmd->params.ips_array_len = 1;
2400        cmd->json = root;
2401        gettimeofday(&cmd->tv, NULL);
2402}
2403
2404static int og_cmd_legacy_wol(const char *input, struct og_cmd *cmd)
2405{
2406        char wol_type[2] = {};
2407        const char *msglog;
2408        struct og_dbi *dbi;
2409        dbi_result result;
2410
2411        if (sscanf(input, "mar=%s", wol_type) != 1) {
2412                syslog(LOG_ERR, "malformed database legacy input\n");
2413                return -1;
2414        }
2415
2416        dbi = og_dbi_open(&ogconfig.db);
2417        if (!dbi) {
2418                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
2419                       __func__, __LINE__);
2420                return -1;
2421        }
2422
2423        result = dbi_conn_queryf(dbi->conn,
2424                                 "SELECT aulas.netmask "
2425                                 "FROM   ordenadores "
2426                                 "INNER JOIN aulas "
2427                                         "ON ordenadores.idaula = aulas.idaula "
2428                                 "WHERE  ordenadores.ip = '%s'",
2429                                 cmd->ip);
2430        if (!result) {
2431                dbi_conn_error(dbi->conn, &msglog);
2432                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2433                       __func__, __LINE__, msglog);
2434                og_dbi_close(dbi);
2435                return -1;
2436        }
2437        dbi_result_next_row(result);
2438
2439        og_cmd_init(cmd, OG_METHOD_NO_HTTP, OG_CMD_WOL, NULL);
2440        cmd->params.netmask_array[0] = dbi_result_get_string_copy(result,
2441                                                                  "netmask");
2442        cmd->params.mac_array[0] = strdup(cmd->mac);
2443        cmd->params.wol_type = strdup(wol_type);
2444
2445        dbi_result_free(result);
2446        og_dbi_close(dbi);
2447
2448        return 0;
2449}
2450
2451static int og_cmd_legacy_shell_run(const char *input, struct og_cmd *cmd)
2452{
2453        json_t *root, *script, *echo;
2454
2455        script = json_string(input + 4);
2456        echo = json_boolean(false);
2457
2458        root = json_object();
2459        if (!root)
2460                return -1;
2461        json_object_set_new(root, "run", script);
2462        json_object_set_new(root, "echo", echo);
2463
2464        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_SHELL_RUN, root);
2465
2466        return 0;
2467}
2468
2469static int og_cmd_legacy_session(const char *input, struct og_cmd *cmd)
2470{
2471        char part_str[OG_DB_SMALLINT_MAXLEN + 1];
2472        char disk_str[OG_DB_SMALLINT_MAXLEN + 1];
2473        json_t *root, *disk, *partition;
2474
2475        if (sscanf(input, "dsk=%s\rpar=%s\r", disk_str, part_str) != 2)
2476                return -1;
2477        partition = json_string(part_str);
2478        disk = json_string(disk_str);
2479
2480        root = json_object();
2481        if (!root)
2482                return -1;
2483        json_object_set_new(root, "partition", partition);
2484        json_object_set_new(root, "disk", disk);
2485
2486        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_SESSION, root);
2487
2488        return 0;
2489}
2490
2491static int og_cmd_legacy_poweroff(const char *input, struct og_cmd *cmd)
2492{
2493        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_POWEROFF, NULL);
2494
2495        return 0;
2496}
2497
2498static int og_cmd_legacy_refresh(const char *input, struct og_cmd *cmd)
2499{
2500        og_cmd_init(cmd, OG_METHOD_GET, OG_CMD_REFRESH, NULL);
2501
2502        return 0;
2503}
2504
2505static int og_cmd_legacy_reboot(const char *input, struct og_cmd *cmd)
2506{
2507        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_REBOOT, NULL);
2508
2509        return 0;
2510}
2511
2512static int og_cmd_legacy_stop(const char *input, struct og_cmd *cmd)
2513{
2514        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_STOP, NULL);
2515
2516        return 0;
2517}
2518
2519static int og_cmd_legacy_hardware(const char *input, struct og_cmd *cmd)
2520{
2521        og_cmd_init(cmd, OG_METHOD_GET, OG_CMD_HARDWARE, NULL);
2522
2523        return 0;
2524}
2525
2526static int og_cmd_legacy_software(const char *input, struct og_cmd *cmd)
2527{
2528        char part_str[OG_DB_SMALLINT_MAXLEN + 1];
2529        char disk_str[OG_DB_SMALLINT_MAXLEN + 1];
2530        json_t *root, *disk, *partition;
2531
2532        if (sscanf(input, "dsk=%s\rpar=%s\r", disk_str, part_str) != 2)
2533                return -1;
2534        partition = json_string(part_str);
2535        disk = json_string(disk_str);
2536
2537        root = json_object();
2538        if (!root)
2539                return -1;
2540        json_object_set_new(root, "partition", partition);
2541        json_object_set_new(root, "disk", disk);
2542
2543        og_cmd_init(cmd, OG_METHOD_GET, OG_CMD_SOFTWARE, root);
2544
2545        return 0;
2546}
2547
2548static int og_cmd_legacy_image_create(const char *input, struct og_cmd *cmd)
2549{
2550        json_t *root, *disk, *partition, *code, *image_id, *name, *repo;
2551        struct og_image_legacy img = {};
2552
2553        if (sscanf(input, "dsk=%s\rpar=%s\rcpt=%s\ridi=%s\rnci=%s\ripr=%s\r",
2554                   img.disk, img.part, img.code, img.image_id, img.name,
2555                   img.repo) != 6)
2556                return -1;
2557        image_id = json_string(img.image_id);
2558        partition = json_string(img.part);
2559        code = json_string(img.code);
2560        name = json_string(img.name);
2561        repo = json_string(img.repo);
2562        disk = json_string(img.disk);
2563
2564        root = json_object();
2565        if (!root)
2566                return -1;
2567        json_object_set_new(root, "partition", partition);
2568        json_object_set_new(root, "repository", repo);
2569        json_object_set_new(root, "id", image_id);
2570        json_object_set_new(root, "code", code);
2571        json_object_set_new(root, "name", name);
2572        json_object_set_new(root, "disk", disk);
2573
2574        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_IMAGE_CREATE, root);
2575
2576        return 0;
2577}
2578
2579#define OG_DB_RESTORE_TYPE_MAXLEN       64
2580
2581static int og_cmd_legacy_image_restore(const char *input, struct og_cmd *cmd)
2582{
2583        json_t *root, *disk, *partition, *image_id, *name, *repo;
2584        char restore_type_str[OG_DB_RESTORE_TYPE_MAXLEN + 1] = {};
2585        char software_id_str[OG_DB_INT_MAXLEN + 1] = {};
2586        json_t *software_id, *restore_type;
2587        struct og_image_legacy img = {};
2588
2589        if (sscanf(input,
2590                   "dsk=%s\rpar=%s\ridi=%s\rnci=%s\r"
2591                   "ipr=%s\rifs=%s\rptc=%[^\r]\r",
2592                   img.disk, img.part, img.image_id, img.name, img.repo,
2593                   software_id_str, restore_type_str) != 7)
2594                return -1;
2595
2596        restore_type = json_string(restore_type_str);
2597        software_id = json_string(software_id_str);
2598        image_id = json_string(img.image_id);
2599        partition = json_string(img.part);
2600        name = json_string(img.name);
2601        repo = json_string(img.repo);
2602        disk = json_string(img.disk);
2603
2604        root = json_object();
2605        if (!root)
2606                return -1;
2607        json_object_set_new(root, "profile", software_id);
2608        json_object_set_new(root, "partition", partition);
2609        json_object_set_new(root, "type", restore_type);
2610        json_object_set_new(root, "repository", repo);
2611        json_object_set_new(root, "id", image_id);
2612        json_object_set_new(root, "name", name);
2613        json_object_set_new(root, "disk", disk);
2614
2615        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_IMAGE_RESTORE, root);
2616
2617        return 0;
2618}
2619
2620#define OG_PARTITION_TABLE_TYPE_MAXLEN 5
2621
2622static int og_cmd_legacy_setup(const char *input, struct og_cmd *cmd)
2623{
2624        json_t *root, *disk, *cache, *cache_size, *partition_setup, *object;
2625        char part_table_type_str[OG_PARTITION_TABLE_TYPE_MAXLEN + 1];
2626        struct og_legacy_partition part_cfg[OG_PARTITION_MAX] = {};
2627        json_t *part_table_type, *part, *code, *fs, *size, *format;
2628        char cache_size_str [OG_DB_INT_MAXLEN + 1];
2629        char disk_str [OG_DB_SMALLINT_MAXLEN + 1];
2630        unsigned int partition_len = 0;
2631        const char *in_ptr;
2632        char cache_str[2];
2633
2634        if (sscanf(input, "ttp=%s\rdsk=%s\rcfg=dis=%*[^*]*che=%[^*]*tch=%[^!]!",
2635                   part_table_type_str, disk_str, cache_str, cache_size_str) != 4)
2636                return -1;
2637
2638        in_ptr = strstr(input, "!") + 1;
2639        while (strlen(in_ptr) > 0) {
2640                if(sscanf(in_ptr,
2641                          "par=%[^*]*cpt=%[^*]*sfi=%[^*]*tam=%[^*]*ope=%[^%%]%%",
2642                          part_cfg[partition_len].partition,
2643                          part_cfg[partition_len].code,
2644                          part_cfg[partition_len].filesystem,
2645                          part_cfg[partition_len].size,
2646                          part_cfg[partition_len].format) != 5)
2647                        return -1;
2648                in_ptr = strstr(in_ptr, "%") + 1;
2649                partition_len++;
2650        }
2651
2652        root = json_object();
2653        if (!root)
2654                return -1;
2655
2656        part_table_type = json_string(part_table_type_str);
2657        cache_size = json_string(cache_size_str);
2658        cache = json_string(cache_str);
2659        partition_setup = json_array();
2660        disk = json_string(disk_str);
2661
2662        for (unsigned int i = 0; i < partition_len; ++i) {
2663                object = json_object();
2664                if (!object) {
2665                        json_decref(root);
2666                        return -1;
2667                }
2668
2669                part = json_string(part_cfg[i].partition);
2670                fs = json_string(part_cfg[i].filesystem);
2671                format = json_string(part_cfg[i].format);
2672                code = json_string(part_cfg[i].code);
2673                size = json_string(part_cfg[i].size);
2674
2675                json_object_set_new(object, "partition", part);
2676                json_object_set_new(object, "filesystem", fs);
2677                json_object_set_new(object, "format", format);
2678                json_object_set_new(object, "code", code);
2679                json_object_set_new(object, "size", size);
2680
2681                json_array_append_new(partition_setup, object);
2682        }
2683
2684        json_object_set_new(root, "partition_setup", partition_setup);
2685        json_object_set_new(root, "cache_size", cache_size);
2686        json_object_set_new(root, "type", part_table_type);
2687        json_object_set_new(root, "cache", cache);
2688        json_object_set_new(root, "disk", disk);
2689
2690        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_SETUP, root);
2691
2692        return 0;
2693}
2694
2695static int og_cmd_legacy_run_schedule(const char *input, struct og_cmd *cmd)
2696{
2697        og_cmd_init(cmd, OG_METHOD_GET, OG_CMD_RUN_SCHEDULE, NULL);
2698
2699        return 0;
2700}
2701
2702static int og_cmd_legacy(const char *input, struct og_cmd *cmd)
2703{
2704        char legacy_cmd[32] = {};
2705        int err = -1;
2706
2707        if (sscanf(input, "nfn=%31s\r", legacy_cmd) != 1) {
2708                syslog(LOG_ERR, "malformed database legacy input\n");
2709                return -1;
2710        }
2711        input = strchr(input, '\r') + 1;
2712
2713        if (!strcmp(legacy_cmd, "Arrancar")) {
2714                err = og_cmd_legacy_wol(input, cmd);
2715        } else if (!strcmp(legacy_cmd, "EjecutarScript")) {
2716                err = og_cmd_legacy_shell_run(input, cmd);
2717        } else if (!strcmp(legacy_cmd, "IniciarSesion")) {
2718                err = og_cmd_legacy_session(input, cmd);
2719        } else if (!strcmp(legacy_cmd, "Apagar")) {
2720                err = og_cmd_legacy_poweroff(input, cmd);
2721        } else if (!strcmp(legacy_cmd, "Actualizar")) {
2722                err = og_cmd_legacy_refresh(input, cmd);
2723        } else if (!strcmp(legacy_cmd, "Reiniciar")) {
2724                err = og_cmd_legacy_reboot(input, cmd);
2725        } else if (!strcmp(legacy_cmd, "Purgar")) {
2726                err = og_cmd_legacy_stop(input, cmd);
2727        } else if (!strcmp(legacy_cmd, "InventarioHardware")) {
2728                err = og_cmd_legacy_hardware(input, cmd);
2729        } else if (!strcmp(legacy_cmd, "InventarioSoftware")) {
2730                err = og_cmd_legacy_software(input, cmd);
2731        } else if (!strcmp(legacy_cmd, "CrearImagen")) {
2732                err = og_cmd_legacy_image_create(input, cmd);
2733        } else if (!strcmp(legacy_cmd, "RestaurarImagen")) {
2734                err = og_cmd_legacy_image_restore(input, cmd);
2735        } else if (!strcmp(legacy_cmd, "Configurar")) {
2736                err = og_cmd_legacy_setup(input, cmd);
2737        } else if (!strcmp(legacy_cmd, "EjecutaComandosPendientes") ||
2738                   !strcmp(legacy_cmd, "Actualizar")) {
2739                err = og_cmd_legacy_run_schedule(input, cmd);
2740        }
2741
2742        return err;
2743}
2744
2745static int og_dbi_add_action(const struct og_dbi *dbi, struct og_task *task,
2746                             struct og_cmd *cmd)
2747{
2748        char start_date_string[24];
2749        struct tm *start_date;
2750        const char *msglog;
2751        dbi_result result;
2752        time_t now;
2753
2754        time(&now);
2755        start_date = localtime(&now);
2756
2757        sprintf(start_date_string, "%hu/%hhu/%hhu %hhu:%hhu:%hhu",
2758                start_date->tm_year + 1900, start_date->tm_mon + 1,
2759                start_date->tm_mday, start_date->tm_hour, start_date->tm_min,
2760                start_date->tm_sec);
2761        result = dbi_conn_queryf(dbi->conn,
2762                                "INSERT INTO acciones (idordenador, "
2763                                "tipoaccion, idtipoaccion, descriaccion, ip, "
2764                                "sesion, idcomando, parametros, fechahorareg, "
2765                                "estado, resultado, ambito, idambito, "
2766                                "restrambito, idprocedimiento, idcentro, "
2767                                "idprogramacion) "
2768                                "VALUES (%d, %d, %d, '%s', '%s', %d, %d, '%s', "
2769                                "'%s', %d, %d, %d, %d, '%s', %d, %d, %d)",
2770                                cmd->client_id, EJECUCION_TAREA, task->task_id,
2771                                "", cmd->ip, task->session, task->command_id,
2772                                task->params, start_date_string,
2773                                ACCION_INICIADA, ACCION_SINRESULTADO,
2774                                task->type_scope, task->scope, "",
2775                                task->procedure_id, task->center_id,
2776                                task->schedule_id);
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        cmd->id = dbi_conn_sequence_last(dbi->conn, NULL);
2785        if (!task->session) {
2786                task->session = cmd->id;
2787                dbi_result_free(result);
2788                result = dbi_conn_queryf(dbi->conn,
2789                                         "UPDATE acciones SET sesion=%d "
2790                                         "WHERE idaccion=%d",
2791                                         task->session, cmd->id);
2792        }
2793
2794        dbi_result_free(result);
2795
2796        return 0;
2797}
2798
2799static int og_queue_task_command(struct og_dbi *dbi, struct og_task *task,
2800                                 char *query)
2801{
2802        struct og_cmd *cmd;
2803        const char *msglog;
2804        dbi_result result;
2805
2806        result = dbi_conn_queryf(dbi->conn, query);
2807        if (!result) {
2808                dbi_conn_error(dbi->conn, &msglog);
2809                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2810                       __func__, __LINE__, msglog);
2811                return -1;
2812        }
2813
2814        while (dbi_result_next_row(result)) {
2815                cmd = (struct og_cmd *)calloc(1, sizeof(struct og_cmd));
2816                if (!cmd) {
2817                        dbi_result_free(result);
2818                        return -1;
2819                }
2820
2821                cmd->client_id  = dbi_result_get_uint(result, "idordenador");
2822                cmd->ip         = strdup(dbi_result_get_string(result, "ip"));
2823                cmd->mac        = strdup(dbi_result_get_string(result, "mac"));
2824
2825                og_cmd_legacy(task->params, cmd);
2826
2827                if (task->procedure_id) {
2828                        if (og_dbi_add_action(dbi, task, cmd)) {
2829                                dbi_result_free(result);
2830                                return -1;
2831                        }
2832                } else {
2833                        cmd->id = task->task_id;
2834                }
2835
2836                list_add_tail(&cmd->list, &cmd_list);
2837        }
2838
2839        dbi_result_free(result);
2840
2841        return 0;
2842}
2843
2844static int og_queue_task_group_clients(struct og_dbi *dbi, struct og_task *task,
2845                                       char *query)
2846{
2847
2848        const char *msglog;
2849        dbi_result result;
2850
2851        result = dbi_conn_queryf(dbi->conn, query);
2852        if (!result) {
2853                dbi_conn_error(dbi->conn, &msglog);
2854                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2855                       __func__, __LINE__, msglog);
2856                return -1;
2857        }
2858
2859        while (dbi_result_next_row(result)) {
2860                uint32_t group_id = dbi_result_get_uint(result, "idgrupo");
2861
2862                sprintf(query, "SELECT idgrupo FROM gruposordenadores "
2863                                "WHERE grupoid=%d", group_id);
2864                if (og_queue_task_group_clients(dbi, task, query)) {
2865                        dbi_result_free(result);
2866                        return -1;
2867                }
2868
2869                sprintf(query,"SELECT ip, mac, idordenador FROM ordenadores "
2870                              "WHERE grupoid=%d", group_id);
2871                if (og_queue_task_command(dbi, task, query)) {
2872                        dbi_result_free(result);
2873                        return -1;
2874                }
2875
2876        }
2877
2878        dbi_result_free(result);
2879
2880        return 0;
2881}
2882
2883static int og_queue_task_group_classrooms(struct og_dbi *dbi,
2884                                          struct og_task *task, char *query)
2885{
2886
2887        const char *msglog;
2888        dbi_result result;
2889
2890        result = dbi_conn_queryf(dbi->conn, query);
2891        if (!result) {
2892                dbi_conn_error(dbi->conn, &msglog);
2893                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2894                       __func__, __LINE__, msglog);
2895                return -1;
2896        }
2897
2898        while (dbi_result_next_row(result)) {
2899                uint32_t group_id = dbi_result_get_uint(result, "idgrupo");
2900
2901                sprintf(query, "SELECT idgrupo FROM grupos "
2902                                "WHERE grupoid=%d AND tipo=%d", group_id, AMBITO_GRUPOSAULAS);
2903                if (og_queue_task_group_classrooms(dbi, task, query)) {
2904                        dbi_result_free(result);
2905                        return -1;
2906                }
2907
2908                sprintf(query,
2909                        "SELECT ip,mac,idordenador "
2910                        "FROM ordenadores INNER JOIN aulas "
2911                        "WHERE ordenadores.idaula=aulas.idaula "
2912                        "AND aulas.grupoid=%d",
2913                        group_id);
2914                if (og_queue_task_command(dbi, task, query)) {
2915                        dbi_result_free(result);
2916                        return -1;
2917                }
2918
2919        }
2920
2921        dbi_result_free(result);
2922
2923        return 0;
2924}
2925
2926static int og_queue_task_clients(struct og_dbi *dbi, struct og_task *task)
2927{
2928        char query[4096];
2929
2930        switch (task->type_scope) {
2931                case AMBITO_CENTROS:
2932                        sprintf(query,
2933                                "SELECT ip,mac,idordenador "
2934                                "FROM ordenadores INNER JOIN aulas "
2935                                "WHERE ordenadores.idaula=aulas.idaula "
2936                                "AND idcentro=%d",
2937                                task->scope);
2938                        return og_queue_task_command(dbi, task, query);
2939                case AMBITO_GRUPOSAULAS:
2940                        sprintf(query,
2941                                "SELECT idgrupo FROM grupos "
2942                                "WHERE idgrupo=%i AND tipo=%d",
2943                                task->scope, AMBITO_GRUPOSAULAS);
2944                        return og_queue_task_group_classrooms(dbi, task, query);
2945                case AMBITO_AULAS:
2946                        sprintf(query,
2947                                "SELECT ip,mac,idordenador FROM ordenadores "
2948                                "WHERE idaula=%d",
2949                                task->scope);
2950                        return og_queue_task_command(dbi, task, query);
2951                case AMBITO_GRUPOSORDENADORES:
2952                        sprintf(query,
2953                                "SELECT idgrupo FROM gruposordenadores "
2954                                "WHERE idgrupo = %d",
2955                                task->scope);
2956                        return og_queue_task_group_clients(dbi, task, query);
2957                case AMBITO_ORDENADORES:
2958                        sprintf(query,
2959                                "SELECT ip, mac, idordenador FROM ordenadores "
2960                                "WHERE idordenador = %d",
2961                                task->scope);
2962                        return og_queue_task_command(dbi, task, query);
2963        }
2964        return 0;
2965}
2966
2967int og_dbi_queue_procedure(struct og_dbi *dbi, struct og_task *task)
2968{
2969        uint32_t procedure_id;
2970        const char *msglog;
2971        dbi_result result;
2972
2973        result = dbi_conn_queryf(dbi->conn,
2974                        "SELECT parametros, procedimientoid, idcomando "
2975                        "FROM procedimientos_acciones "
2976                        "WHERE idprocedimiento=%d ORDER BY orden", task->procedure_id);
2977        if (!result) {
2978                dbi_conn_error(dbi->conn, &msglog);
2979                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2980                       __func__, __LINE__, msglog);
2981                return -1;
2982        }
2983
2984        while (dbi_result_next_row(result)) {
2985                procedure_id = dbi_result_get_uint(result, "procedimientoid");
2986                if (procedure_id > 0) {
2987                        task->procedure_id = procedure_id;
2988                        if (og_dbi_queue_procedure(dbi, task))
2989                                return -1;
2990                        continue;
2991                }
2992
2993                task->params = dbi_result_get_string(result, "parametros");
2994                task->command_id = dbi_result_get_uint(result, "idcomando");
2995                if (og_queue_task_clients(dbi, task))
2996                        return -1;
2997        }
2998
2999        dbi_result_free(result);
3000
3001        return 0;
3002}
3003
3004static int og_dbi_queue_task(struct og_dbi *dbi, uint32_t task_id,
3005                             uint32_t schedule_id)
3006{
3007        struct og_task task = {};
3008        uint32_t task_id_next;
3009        const char *msglog;
3010        dbi_result result;
3011
3012        task.schedule_id = schedule_id;
3013
3014        result = dbi_conn_queryf(dbi->conn,
3015                        "SELECT tareas_acciones.orden, "
3016                                "tareas_acciones.idprocedimiento, "
3017                                "tareas_acciones.tareaid, "
3018                                "tareas.idtarea, "
3019                                "tareas.idcentro, "
3020                                "tareas.ambito, "
3021                                "tareas.idambito, "
3022                                "tareas.restrambito "
3023                        " FROM tareas"
3024                                " INNER JOIN tareas_acciones ON tareas_acciones.idtarea=tareas.idtarea"
3025                        " WHERE tareas_acciones.idtarea=%u ORDER BY tareas_acciones.orden ASC", task_id);
3026        if (!result) {
3027                dbi_conn_error(dbi->conn, &msglog);
3028                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3029                       __func__, __LINE__, msglog);
3030                return -1;
3031        }
3032
3033        while (dbi_result_next_row(result)) {
3034                task_id_next = dbi_result_get_uint(result, "tareaid");
3035
3036                if (task_id_next > 0) {
3037                        if (og_dbi_queue_task(dbi, task_id_next, schedule_id))
3038                                return -1;
3039
3040                        continue;
3041                }
3042                task.task_id = dbi_result_get_uint(result, "idtarea");
3043                task.center_id = dbi_result_get_uint(result, "idcentro");
3044                task.procedure_id = dbi_result_get_uint(result, "idprocedimiento");
3045                task.type_scope = dbi_result_get_uint(result, "ambito");
3046                task.scope = dbi_result_get_uint(result, "idambito");
3047                task.filtered_scope = dbi_result_get_string(result, "restrambito");
3048
3049                og_dbi_queue_procedure(dbi, &task);
3050        }
3051
3052        dbi_result_free(result);
3053
3054        return 0;
3055}
3056
3057static int og_dbi_queue_command(struct og_dbi *dbi, uint32_t task_id,
3058                                uint32_t schedule_id)
3059{
3060        struct og_task task = {};
3061        const char *msglog;
3062        dbi_result result;
3063        char query[4096];
3064
3065        result = dbi_conn_queryf(dbi->conn,
3066                        "SELECT idaccion, idcentro, idordenador, parametros "
3067                        "FROM acciones "
3068                        "WHERE sesion = %u", task_id);
3069        if (!result) {
3070                dbi_conn_error(dbi->conn, &msglog);
3071                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3072                       __func__, __LINE__, msglog);
3073                return -1;
3074        }
3075
3076        while (dbi_result_next_row(result)) {
3077                task.task_id = dbi_result_get_uint(result, "idaccion");
3078                task.center_id = dbi_result_get_uint(result, "idcentro");
3079                task.scope = dbi_result_get_uint(result, "idordenador");
3080                task.params = dbi_result_get_string(result, "parametros");
3081
3082                sprintf(query,
3083                        "SELECT ip, mac, idordenador FROM ordenadores "
3084                        "WHERE idordenador = %d",
3085                        task.scope);
3086                if (og_queue_task_command(dbi, &task, query)) {
3087                        dbi_result_free(result);
3088                        return -1;
3089                }
3090        }
3091
3092        dbi_result_free(result);
3093
3094        return 0;
3095}
3096
3097int og_dbi_update_action(uint32_t id, bool success)
3098{
3099        char end_date_string[24];
3100        struct tm *end_date;
3101        const char *msglog;
3102        struct og_dbi *dbi;
3103        uint8_t status = 2;
3104        dbi_result result;
3105        time_t now;
3106
3107        if (!id)
3108                return 0;
3109
3110        dbi = og_dbi_open(&ogconfig.db);
3111        if (!dbi) {
3112                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3113                       __func__, __LINE__);
3114                return -1;
3115        }
3116
3117        time(&now);
3118        end_date = localtime(&now);
3119
3120        sprintf(end_date_string, "%hu/%hhu/%hhu %hhu:%hhu:%hhu",
3121                end_date->tm_year + 1900, end_date->tm_mon + 1,
3122                end_date->tm_mday, end_date->tm_hour, end_date->tm_min,
3123                end_date->tm_sec);
3124        result = dbi_conn_queryf(dbi->conn,
3125                                 "UPDATE acciones SET fechahorafin='%s', "
3126                                 "estado=%d, resultado=%d WHERE idaccion=%d",
3127                                 end_date_string, ACCION_FINALIZADA,
3128                                 status - success, id);
3129
3130        if (!result) {
3131                dbi_conn_error(dbi->conn, &msglog);
3132                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3133                       __func__, __LINE__, msglog);
3134                og_dbi_close(dbi);
3135                return -1;
3136        }
3137        dbi_result_free(result);
3138        og_dbi_close(dbi);
3139
3140        return 0;
3141}
3142
3143void og_schedule_run(unsigned int task_id, unsigned int schedule_id,
3144                     enum og_schedule_type type)
3145{
3146        struct og_msg_params params = {};
3147        bool duplicated = false;
3148        struct og_cmd *cmd, *next;
3149        struct og_dbi *dbi;
3150        unsigned int i;
3151
3152        dbi = og_dbi_open(&ogconfig.db);
3153        if (!dbi) {
3154                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3155                       __func__, __LINE__);
3156                return;
3157        }
3158
3159        switch (type) {
3160        case OG_SCHEDULE_TASK:
3161                og_dbi_queue_task(dbi, task_id, schedule_id);
3162                break;
3163        case OG_SCHEDULE_PROCEDURE:
3164        case OG_SCHEDULE_COMMAND:
3165                og_dbi_queue_command(dbi, task_id, schedule_id);
3166                break;
3167        }
3168        og_dbi_close(dbi);
3169
3170        list_for_each_entry(cmd, &cmd_list, list) {
3171                for (i = 0; i < params.ips_array_len; i++) {
3172                        if (!strncmp(cmd->ip, params.ips_array[i],
3173                                     OG_DB_IP_MAXLEN)) {
3174                                duplicated = true;
3175                                break;
3176                        }
3177                }
3178
3179                if (!duplicated)
3180                        params.ips_array[params.ips_array_len++] = strdup(cmd->ip);
3181                else
3182                        duplicated = false;
3183        }
3184
3185        list_for_each_entry_safe(cmd, next, &cmd_list, list) {
3186                if (cmd->type != OG_CMD_WOL)
3187                        continue;
3188
3189                if (Levanta((char **)cmd->params.ips_array,
3190                            (char **)cmd->params.mac_array,
3191                            (char **)cmd->params.netmask_array,
3192                            cmd->params.ips_array_len,
3193                            (char *)cmd->params.wol_type))
3194                        og_dbi_update_action(cmd->id, true);
3195
3196                list_del(&cmd->list);
3197                og_cmd_free(cmd);
3198        }
3199
3200        og_send_request(OG_METHOD_GET, OG_CMD_RUN_SCHEDULE, &params, NULL);
3201
3202        for (i = 0; i < params.ips_array_len; i++)
3203                free((void *)params.ips_array[i]);
3204}
3205
3206static int og_cmd_task_post(json_t *element, struct og_msg_params *params)
3207{
3208        struct og_cmd *cmd;
3209        struct og_dbi *dbi;
3210        const char *key;
3211        json_t *value;
3212        int err = 0;
3213
3214        if (json_typeof(element) != JSON_OBJECT)
3215                return -1;
3216
3217        json_object_foreach(element, key, value) {
3218                if (!strcmp(key, "task")) {
3219                        err = og_json_parse_string(value, &params->task_id);
3220                        params->flags |= OG_REST_PARAM_TASK;
3221                }
3222
3223                if (err < 0)
3224                        return err;
3225        }
3226
3227        if (!og_msg_params_validate(params, OG_REST_PARAM_TASK))
3228                return -1;
3229
3230        dbi = og_dbi_open(&ogconfig.db);
3231        if (!dbi) {
3232                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3233                           __func__, __LINE__);
3234                return -1;
3235        }
3236
3237        og_schedule_run(atoi(params->task_id), 0, OG_SCHEDULE_TASK);
3238        og_dbi_close(dbi);
3239
3240        list_for_each_entry(cmd, &cmd_list, list)
3241                params->ips_array[params->ips_array_len++] = cmd->ip;
3242
3243        return og_send_request(OG_METHOD_GET, OG_CMD_RUN_SCHEDULE, params,
3244                               NULL);
3245}
3246
3247static int og_dbi_scope_get_computer(struct og_dbi *dbi, json_t *array,
3248                                     uint32_t room_id)
3249{
3250        const char *computer_name, *computer_ip;
3251        uint32_t computer_id;
3252        const char *msglog;
3253        dbi_result result;
3254        json_t *computer;
3255
3256        result = dbi_conn_queryf(dbi->conn,
3257                                 "SELECT idordenador, nombreordenador, ip "
3258                                 "FROM ordenadores WHERE idaula=%d",
3259                                 room_id);
3260        if (!result) {
3261                dbi_conn_error(dbi->conn, &msglog);
3262                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3263                       __func__, __LINE__, msglog);
3264                return -1;
3265        }
3266
3267        while (dbi_result_next_row(result)) {
3268                computer_id = dbi_result_get_uint(result, "idordenador");
3269                computer_name = dbi_result_get_string(result, "nombreordenador");
3270                computer_ip = dbi_result_get_string(result, "ip");
3271
3272                computer = json_object();
3273                if (!computer) {
3274                        dbi_result_free(result);
3275                        return -1;
3276                }
3277
3278                json_object_set_new(computer, "name", json_string(computer_name));
3279                json_object_set_new(computer, "type", json_string("computer"));
3280                json_object_set_new(computer, "id", json_integer(computer_id));
3281                json_object_set_new(computer, "scope", json_array());
3282                json_object_set_new(computer, "ip", json_string(computer_ip));
3283                json_array_append(array, computer);
3284                json_decref(computer);
3285        }
3286        dbi_result_free(result);
3287
3288        return 0;
3289}
3290
3291static int og_dbi_scope_get_room(struct og_dbi *dbi, json_t *array,
3292                                 uint32_t center_id)
3293{
3294        char room_name[OG_DB_ROOM_NAME_MAXLEN + 1] = {};
3295        json_t *room, *room_array;
3296        const char *msglog;
3297        dbi_result result;
3298        uint32_t room_id;
3299
3300        result = dbi_conn_queryf(dbi->conn,
3301                                 "SELECT idaula, nombreaula FROM aulas WHERE "
3302                                 "idcentro=%d",
3303                                 center_id);
3304        if (!result) {
3305                dbi_conn_error(dbi->conn, &msglog);
3306                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3307                       __func__, __LINE__, msglog);
3308                return -1;
3309        }
3310
3311        while (dbi_result_next_row(result)) {
3312                room_id = dbi_result_get_uint(result, "idaula");
3313                strncpy(room_name,
3314                        dbi_result_get_string(result, "nombreaula"),
3315                        OG_DB_CENTER_NAME_MAXLEN);
3316
3317                room = json_object();
3318                if (!room) {
3319                        dbi_result_free(result);
3320                        return -1;
3321                }
3322
3323                json_object_set_new(room, "name", json_string(room_name));
3324                json_object_set_new(room, "type", json_string("room"));
3325                json_object_set_new(room, "id", json_integer(room_id));
3326                json_object_set_new(room, "scope", json_array());
3327                json_array_append(array, room);
3328                json_decref(room);
3329
3330                room_array = json_object_get(room, "scope");
3331                if (!room_array) {
3332                        dbi_result_free(result);
3333                        return -1;
3334                }
3335
3336                if (og_dbi_scope_get_computer(dbi, room_array, room_id)) {
3337                        dbi_result_free(result);
3338                        return -1;
3339                }
3340        }
3341        dbi_result_free(result);
3342
3343        return 0;
3344}
3345
3346static int og_dbi_scope_get(struct og_dbi *dbi, json_t *array)
3347{
3348        char center_name[OG_DB_CENTER_NAME_MAXLEN + 1] = {};
3349        json_t *center, *array_room;
3350        const char *msglog;
3351        uint32_t center_id;
3352        dbi_result result;
3353
3354        result = dbi_conn_queryf(dbi->conn,
3355                                 "SELECT nombrecentro, idcentro FROM centros");
3356        if (!result) {
3357                dbi_conn_error(dbi->conn, &msglog);
3358                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3359                       __func__, __LINE__, msglog);
3360                return -1;
3361        }
3362
3363        while (dbi_result_next_row(result)) {
3364                center_id = dbi_result_get_uint(result, "idcentro");
3365                strncpy(center_name,
3366                        dbi_result_get_string(result, "nombrecentro"),
3367                        OG_DB_CENTER_NAME_MAXLEN);
3368
3369                center = json_object();
3370                if (!center) {
3371                        dbi_result_free(result);
3372                        return -1;
3373                }
3374
3375                array_room = json_array();
3376                if (!array_room) {
3377                        dbi_result_free(result);
3378                        json_decref(center);
3379                        return -1;
3380                }
3381
3382                json_object_set_new(center, "name", json_string(center_name));
3383                json_object_set_new(center, "type", json_string("center"));
3384                json_object_set_new(center, "id", json_integer(center_id));
3385                json_object_set_new(center, "scope", array_room);
3386                json_array_append(array, center);
3387                json_decref(center);
3388
3389                if (og_dbi_scope_get_room(dbi, array_room, center_id)) {
3390                        dbi_result_free(result);
3391                        return -1;
3392                }
3393        }
3394
3395        dbi_result_free(result);
3396
3397        return 0;
3398}
3399
3400static int og_cmd_scope_get(json_t *element, struct og_msg_params *params,
3401                            char *buffer_reply)
3402{
3403        struct og_buffer og_buffer = {
3404                .data = buffer_reply
3405        };
3406        json_t *root, *array;
3407        struct og_dbi *dbi;
3408
3409        root = json_object();
3410        if (!root)
3411                return -1;
3412
3413        array = json_array();
3414        if (!array) {
3415                json_decref(root);
3416                return -1;
3417        }
3418        json_object_set_new(root, "scope", array);
3419
3420        dbi = og_dbi_open(&ogconfig.db);
3421        if (!dbi) {
3422                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3423                       __func__, __LINE__);
3424                json_decref(root);
3425                return -1;
3426        }
3427
3428        if (og_dbi_scope_get(dbi, array)) {
3429                og_dbi_close(dbi);
3430                json_decref(root);
3431                return -1;
3432        }
3433
3434        og_dbi_close(dbi);
3435
3436        if (json_dump_callback(root, og_json_dump_clients, &og_buffer, 0)) {
3437                json_decref(root);
3438                return -1;
3439        }
3440
3441        json_decref(root);
3442
3443        return 0;
3444}
3445
3446int og_dbi_schedule_get(void)
3447{
3448        uint32_t schedule_id, task_id;
3449        struct og_schedule_time time;
3450        struct og_dbi *dbi;
3451        const char *msglog;
3452        dbi_result result;
3453
3454        dbi = og_dbi_open(&ogconfig.db);
3455        if (!dbi) {
3456                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3457                       __func__, __LINE__);
3458                return -1;
3459        }
3460
3461        result = dbi_conn_queryf(dbi->conn,
3462                                 "SELECT idprogramacion, tipoaccion, identificador, "
3463                                 "sesion, annos, meses, diario, dias, semanas, horas, "
3464                                 "ampm, minutos FROM programaciones "
3465                                 "WHERE suspendida = 0");
3466        if (!result) {
3467                dbi_conn_error(dbi->conn, &msglog);
3468                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3469                       __func__, __LINE__, msglog);
3470                og_dbi_close(dbi);
3471                return -1;
3472        }
3473
3474        while (dbi_result_next_row(result)) {
3475                memset(&time, 0, sizeof(time));
3476                schedule_id = dbi_result_get_uint(result, "idprogramacion");
3477                task_id = dbi_result_get_uint(result, "identificador");
3478                time.years = dbi_result_get_uint(result, "annos");
3479                time.months = dbi_result_get_uint(result, "meses");
3480                time.weeks = dbi_result_get_uint(result, "semanas");
3481                time.week_days = dbi_result_get_uint(result, "dias");
3482                time.days = dbi_result_get_uint(result, "diario");
3483                time.hours = dbi_result_get_uint(result, "horas");
3484                time.am_pm = dbi_result_get_uint(result, "ampm");
3485                time.minutes = dbi_result_get_uint(result, "minutos");
3486                time.check_stale = true;
3487
3488                og_schedule_create(schedule_id, task_id, OG_SCHEDULE_TASK,
3489                                   &time);
3490        }
3491
3492        dbi_result_free(result);
3493        og_dbi_close(dbi);
3494
3495        return 0;
3496}
3497
3498static int og_dbi_schedule_create(struct og_dbi *dbi,
3499                                  struct og_msg_params *params,
3500                                  uint32_t *schedule_id,
3501                                  enum og_schedule_type schedule_type)
3502{
3503        uint8_t suspended = 0;
3504        uint32_t session = 0;
3505        const char *msglog;
3506        dbi_result result;
3507        uint8_t type;
3508
3509        switch (schedule_type) {
3510        case OG_SCHEDULE_TASK:
3511                type = 3;
3512                break;
3513        case OG_SCHEDULE_PROCEDURE:
3514                type = 2;
3515                break;
3516        case OG_SCHEDULE_COMMAND:
3517                session = atoi(params->task_id);
3518                type = 1;
3519                break;
3520        }
3521
3522        result = dbi_conn_queryf(dbi->conn,
3523                                 "INSERT INTO programaciones (tipoaccion,"
3524                                 " identificador, nombrebloque, annos, meses,"
3525                                 " semanas, dias, diario, horas, ampm, minutos,"
3526                                 " suspendida, sesion) VALUES (%d, %s, '%s',"
3527                                 " %d, %d, %d, %d, %d, %d, %d, %d, %d, %d)",
3528                                 type, params->task_id, params->name,
3529                                 params->time.years, params->time.months,
3530                                 params->time.weeks, params->time.week_days,
3531                                 params->time.days, params->time.hours,
3532                                 params->time.am_pm, params->time.minutes,
3533                                 suspended, session);
3534        if (!result) {
3535                dbi_conn_error(dbi->conn, &msglog);
3536                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3537                       __func__, __LINE__, msglog);
3538                return -1;
3539        }
3540        dbi_result_free(result);
3541
3542        *schedule_id = dbi_conn_sequence_last(dbi->conn, NULL);
3543
3544        return 0;
3545}
3546
3547static int og_dbi_schedule_update(struct og_dbi *dbi,
3548                                  struct og_msg_params *params)
3549{
3550        const char *msglog;
3551        dbi_result result;
3552        uint8_t type = 3;
3553
3554        result = dbi_conn_queryf(dbi->conn,
3555                                 "UPDATE programaciones SET tipoaccion=%d, "
3556                                 "identificador='%s', nombrebloque='%s', "
3557                                 "annos=%d, meses=%d, "
3558                                 "diario=%d, horas=%d, ampm=%d, minutos=%d "
3559                                 "WHERE idprogramacion='%s'",
3560                                 type, params->task_id, params->name,
3561                                 params->time.years, params->time.months,
3562                                 params->time.days, params->time.hours,
3563                                 params->time.am_pm, params->time.minutes,
3564                                 params->id);
3565
3566        if (!result) {
3567                dbi_conn_error(dbi->conn, &msglog);
3568                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3569                       __func__, __LINE__, msglog);
3570                return -1;
3571        }
3572        dbi_result_free(result);
3573
3574        return 0;
3575}
3576
3577static int og_dbi_schedule_delete(struct og_dbi *dbi, uint32_t id)
3578{
3579        const char *msglog;
3580        dbi_result result;
3581
3582        result = dbi_conn_queryf(dbi->conn,
3583                                 "DELETE FROM programaciones WHERE idprogramacion=%d",
3584                                 id);
3585        if (!result) {
3586                dbi_conn_error(dbi->conn, &msglog);
3587                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3588                       __func__, __LINE__, msglog);
3589                return -1;
3590        }
3591        dbi_result_free(result);
3592
3593        return 0;
3594}
3595
3596struct og_db_schedule {
3597        uint32_t                id;
3598        uint32_t                task_id;
3599        const char              *name;
3600        struct og_schedule_time time;
3601        uint32_t                week_days;
3602        uint32_t                weeks;
3603        uint32_t                suspended;
3604        uint32_t                session;
3605};
3606
3607static int og_dbi_schedule_get_json(struct og_dbi *dbi, json_t *root,
3608                                    const char *task_id, const char *schedule_id)
3609{
3610        struct og_db_schedule schedule;
3611        json_t *obj, *array;
3612        const char *msglog;
3613        dbi_result result;
3614        int err = 0;
3615
3616        if (task_id) {
3617                result = dbi_conn_queryf(dbi->conn,
3618                                         "SELECT idprogramacion,"
3619                                         "       identificador, nombrebloque,"
3620                                         "       annos, meses, diario, dias,"
3621                                         "       semanas, horas, ampm,"
3622                                         "       minutos,suspendida, sesion "
3623                                         "FROM programaciones "
3624                                         "WHERE identificador=%d",
3625                                         atoi(task_id));
3626        } else if (schedule_id) {
3627                result = dbi_conn_queryf(dbi->conn,
3628                                         "SELECT idprogramacion,"
3629                                         "       identificador, nombrebloque,"
3630                                         "       annos, meses, diario, dias,"
3631                                         "       semanas, horas, ampm,"
3632                                         "       minutos,suspendida, sesion "
3633                                         "FROM programaciones "
3634                                         "WHERE idprogramacion=%d",
3635                                         atoi(schedule_id));
3636        } else {
3637                result = dbi_conn_queryf(dbi->conn,
3638                                         "SELECT idprogramacion,"
3639                                         "       identificador, nombrebloque,"
3640                                         "       annos, meses, diario, dias,"
3641                                         "       semanas, horas, ampm,"
3642                                         "       minutos,suspendida, sesion "
3643                                         "FROM programaciones");
3644        }
3645
3646        if (!result) {
3647                dbi_conn_error(dbi->conn, &msglog);
3648                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3649                       __func__, __LINE__, msglog);
3650                return -1;
3651        }
3652
3653        array = json_array();
3654        if (!array)
3655                return -1;
3656
3657        while (dbi_result_next_row(result)) {
3658                schedule.id = dbi_result_get_uint(result, "idprogramacion");
3659                schedule.task_id = dbi_result_get_uint(result, "identificador");
3660                schedule.name = dbi_result_get_string(result, "nombrebloque");
3661                schedule.time.years = dbi_result_get_uint(result, "annos");
3662                schedule.time.months = dbi_result_get_uint(result, "meses");
3663                schedule.time.days = dbi_result_get_uint(result, "diario");
3664                schedule.time.hours = dbi_result_get_uint(result, "horas");
3665                schedule.time.am_pm = dbi_result_get_uint(result, "ampm");
3666                schedule.time.minutes = dbi_result_get_uint(result, "minutos");
3667                schedule.week_days = dbi_result_get_uint(result, "dias");
3668                schedule.weeks = dbi_result_get_uint(result, "semanas");
3669                schedule.suspended = dbi_result_get_uint(result, "suspendida");
3670                schedule.session = dbi_result_get_uint(result, "sesion");
3671
3672                obj = json_object();
3673                if (!obj) {
3674                        err = -1;
3675                        break;
3676                }
3677                json_object_set_new(obj, "id", json_integer(schedule.id));
3678                json_object_set_new(obj, "task", json_integer(schedule.task_id));
3679                json_object_set_new(obj, "name", json_string(schedule.name));
3680                json_object_set_new(obj, "years", json_integer(schedule.time.years));
3681                json_object_set_new(obj, "months", json_integer(schedule.time.months));
3682                json_object_set_new(obj, "days", json_integer(schedule.time.days));
3683                json_object_set_new(obj, "hours", json_integer(schedule.time.hours));
3684                json_object_set_new(obj, "am_pm", json_integer(schedule.time.am_pm));
3685                json_object_set_new(obj, "minutes", json_integer(schedule.time.minutes));
3686                json_object_set_new(obj, "week_days", json_integer(schedule.week_days));
3687                json_object_set_new(obj, "weeks", json_integer(schedule.weeks));
3688                json_object_set_new(obj, "suspended", json_integer(schedule.suspended));
3689                json_object_set_new(obj, "session", json_integer(schedule.session));
3690
3691                json_array_append_new(array, obj);
3692        }
3693
3694        json_object_set_new(root, "schedule", array);
3695
3696        dbi_result_free(result);
3697
3698        return err;
3699}
3700
3701static int og_task_schedule_create(struct og_msg_params *params)
3702{
3703        enum og_schedule_type type;
3704        uint32_t schedule_id;
3705        struct og_dbi *dbi;
3706        int err;
3707
3708        if (!strcmp(params->type, "task"))
3709                type = OG_SCHEDULE_TASK;
3710        else if (!strcmp(params->type, "procedure"))
3711                type = OG_SCHEDULE_PROCEDURE;
3712        else if (!strcmp(params->type, "command"))
3713                type = OG_SCHEDULE_COMMAND;
3714        else
3715                return -1;
3716
3717        dbi = og_dbi_open(&ogconfig.db);
3718        if (!dbi) {
3719                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3720                       __func__, __LINE__);
3721                return -1;
3722        }
3723
3724        err = og_dbi_schedule_create(dbi, params, &schedule_id, type);
3725        if (err < 0) {
3726                og_dbi_close(dbi);
3727                return -1;
3728        }
3729        og_schedule_create(schedule_id, atoi(params->task_id), type,
3730                           &params->time);
3731        og_schedule_refresh(og_loop);
3732        og_dbi_close(dbi);
3733
3734        return 0;
3735}
3736
3737static uint32_t og_tm_years_mask(struct tm *tm)
3738{
3739        int i, j = 0;
3740
3741        for (i = 2010; i < 2026; i++, j++) {
3742                if (tm->tm_year + 1900 == i)
3743                        break;
3744        }
3745
3746        return (1 << j);
3747}
3748
3749static uint32_t og_tm_months_mask(struct tm *tm)
3750{
3751        return 1 << tm->tm_mon;
3752}
3753
3754static uint16_t og_tm_hours_mask(struct tm *tm)
3755{
3756        return tm->tm_hour >= 12 ? 1 << (tm->tm_hour - 12) : 1 << tm->tm_hour;
3757}
3758
3759static uint32_t og_tm_ampm(struct tm *tm)
3760{
3761        return tm->tm_hour < 12 ? 0 : 1;
3762}
3763
3764static uint32_t og_tm_days_mask(struct tm *tm)
3765{
3766        return 1 << (tm->tm_mday - 1);
3767}
3768
3769static void og_schedule_time_now(struct og_schedule_time *ogtime)
3770{
3771        struct tm *tm;
3772        time_t now;
3773
3774        now = time(NULL);
3775        tm = localtime(&now);
3776
3777        ogtime->years = og_tm_years_mask(tm);
3778        ogtime->months = og_tm_months_mask(tm);
3779        ogtime->weeks = 0;
3780        ogtime->week_days = 0;
3781        ogtime->days =  og_tm_days_mask(tm);
3782        ogtime->hours = og_tm_hours_mask(tm);
3783        ogtime->am_pm = og_tm_ampm(tm);
3784        ogtime->minutes = tm->tm_min;
3785}
3786
3787static int og_cmd_schedule_create(json_t *element, struct og_msg_params *params)
3788{
3789        bool when = false;
3790        const char *key;
3791        json_t *value;
3792        int err = 0;
3793
3794        if (json_typeof(element) != JSON_OBJECT)
3795                return -1;
3796
3797        json_object_foreach(element, key, value) {
3798                if (!strcmp(key, "task")) {
3799                        err = og_json_parse_string(value, &params->task_id);
3800                        params->flags |= OG_REST_PARAM_TASK;
3801                } else if (!strcmp(key, "name")) {
3802                        err = og_json_parse_string(value, &params->name);
3803                        params->flags |= OG_REST_PARAM_NAME;
3804                } else if (!strcmp(key, "when")) {
3805                        err = og_json_parse_time_params(value, params);
3806                        when = true;
3807                } else if (!strcmp(key, "type")) {
3808                        err = og_json_parse_string(value, &params->type);
3809                        params->flags |= OG_REST_PARAM_TYPE;
3810                }
3811
3812                if (err < 0)
3813                        return err;
3814        }
3815
3816        if (!when) {
3817                params->time.check_stale = false;
3818                og_schedule_time_now(&params->time);
3819                params->flags |= OG_REST_PARAM_TIME_YEARS |
3820                                 OG_REST_PARAM_TIME_MONTHS |
3821                                 OG_REST_PARAM_TIME_WEEKS |
3822                                 OG_REST_PARAM_TIME_WEEK_DAYS |
3823                                 OG_REST_PARAM_TIME_DAYS |
3824                                 OG_REST_PARAM_TIME_HOURS |
3825                                 OG_REST_PARAM_TIME_AM_PM |
3826                                 OG_REST_PARAM_TIME_MINUTES;
3827        } else {
3828                params->time.check_stale = true;
3829        }
3830
3831        if (!og_msg_params_validate(params, OG_REST_PARAM_TASK |
3832                                            OG_REST_PARAM_NAME |
3833                                            OG_REST_PARAM_TIME_YEARS |
3834                                            OG_REST_PARAM_TIME_MONTHS |
3835                                            OG_REST_PARAM_TIME_WEEKS |
3836                                            OG_REST_PARAM_TIME_WEEK_DAYS |
3837                                            OG_REST_PARAM_TIME_DAYS |
3838                                            OG_REST_PARAM_TIME_HOURS |
3839                                            OG_REST_PARAM_TIME_MINUTES |
3840                                            OG_REST_PARAM_TIME_AM_PM |
3841                                            OG_REST_PARAM_TYPE))
3842                return -1;
3843
3844        return og_task_schedule_create(params);
3845}
3846
3847static int og_cmd_schedule_update(json_t *element, struct og_msg_params *params)
3848{
3849        struct og_dbi *dbi;
3850        bool when = false;
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                } else if (!strcmp(key, "task")) {
3863                        err = og_json_parse_string(value, &params->task_id);
3864                        params->flags |= OG_REST_PARAM_TASK;
3865                } else if (!strcmp(key, "name")) {
3866                        err = og_json_parse_string(value, &params->name);
3867                        params->flags |= OG_REST_PARAM_NAME;
3868                } else if (!strcmp(key, "when")) {
3869                        err = og_json_parse_time_params(value, params);
3870                        when = true;
3871                }
3872
3873                if (err < 0)
3874                        return err;
3875        }
3876
3877        if (!when) {
3878                params->time.check_stale = false;
3879                og_schedule_time_now(&params->time);
3880                params->flags |= OG_REST_PARAM_TIME_YEARS |
3881                                 OG_REST_PARAM_TIME_MONTHS |
3882                                 OG_REST_PARAM_TIME_WEEKS |
3883                                 OG_REST_PARAM_TIME_WEEK_DAYS |
3884                                 OG_REST_PARAM_TIME_DAYS |
3885                                 OG_REST_PARAM_TIME_HOURS |
3886                                 OG_REST_PARAM_TIME_AM_PM |
3887                                 OG_REST_PARAM_TIME_MINUTES;
3888        } else {
3889                params->time.check_stale = true;
3890        }
3891
3892        if (!og_msg_params_validate(params, OG_REST_PARAM_ID |
3893                                            OG_REST_PARAM_TASK |
3894                                            OG_REST_PARAM_NAME |
3895                                            OG_REST_PARAM_TIME_YEARS |
3896                                            OG_REST_PARAM_TIME_MONTHS |
3897                                            OG_REST_PARAM_TIME_DAYS |
3898                                            OG_REST_PARAM_TIME_HOURS |
3899                                            OG_REST_PARAM_TIME_MINUTES |
3900                                            OG_REST_PARAM_TIME_AM_PM))
3901                return -1;
3902
3903        dbi = og_dbi_open(&ogconfig.db);
3904        if (!dbi) {
3905                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3906                           __func__, __LINE__);
3907                return -1;
3908        }
3909
3910        err = og_dbi_schedule_update(dbi, params);
3911        og_dbi_close(dbi);
3912
3913        if (err < 0)
3914                return err;
3915
3916        og_schedule_update(og_loop, atoi(params->id), atoi(params->task_id),
3917                           &params->time);
3918        og_schedule_refresh(og_loop);
3919
3920        return err;
3921}
3922
3923static int og_cmd_schedule_delete(json_t *element, struct og_msg_params *params)
3924{
3925        struct og_dbi *dbi;
3926        const char *key;
3927        json_t *value;
3928        int err = 0;
3929
3930        if (json_typeof(element) != JSON_OBJECT)
3931                return -1;
3932
3933        json_object_foreach(element, key, value) {
3934                if (!strcmp(key, "id")) {
3935                        err = og_json_parse_string(value, &params->id);
3936                        params->flags |= OG_REST_PARAM_ID;
3937                }
3938
3939                if (err < 0)
3940                        return err;
3941        }
3942
3943        if (!og_msg_params_validate(params, OG_REST_PARAM_ID))
3944                return -1;
3945
3946        dbi = og_dbi_open(&ogconfig.db);
3947        if (!dbi) {
3948                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3949                           __func__, __LINE__);
3950                return -1;
3951        }
3952
3953        err = og_dbi_schedule_delete(dbi, atoi(params->id));
3954        og_dbi_close(dbi);
3955
3956        og_schedule_delete(og_loop, atoi(params->id));
3957
3958        return err;
3959}
3960
3961static int og_cmd_schedule_get(json_t *element, struct og_msg_params *params,
3962                               char *buffer_reply)
3963{
3964        struct og_buffer og_buffer = {
3965                .data   = buffer_reply,
3966        };
3967        json_t *schedule_root;
3968        struct og_dbi *dbi;
3969        const char *key;
3970        json_t *value;
3971        int err = 0;
3972
3973        if (element) {
3974                if (json_typeof(element) != JSON_OBJECT)
3975                        return -1;
3976
3977                json_object_foreach(element, key, value) {
3978                        if (!strcmp(key, "task")) {
3979                                err = og_json_parse_string(value,
3980                                                           &params->task_id);
3981                        } else if (!strcmp(key, "id")) {
3982                                err = og_json_parse_string(value, &params->id);
3983                        }
3984
3985                        if (err < 0)
3986                                return err;
3987                }
3988        }
3989
3990        dbi = og_dbi_open(&ogconfig.db);
3991        if (!dbi) {
3992                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3993                           __func__, __LINE__);
3994                return -1;
3995        }
3996
3997        schedule_root = json_object();
3998        if (!schedule_root) {
3999                og_dbi_close(dbi);
4000                return -1;
4001        }
4002
4003        err = og_dbi_schedule_get_json(dbi, schedule_root,
4004                                       params->task_id, params->id);
4005        og_dbi_close(dbi);
4006
4007        if (err >= 0)
4008                err = json_dump_callback(schedule_root, og_json_dump_clients,
4009                                         &og_buffer, 0);
4010
4011        json_decref(schedule_root);
4012
4013        return err;
4014}
4015
4016#define OG_LIVE_JSON_FILE_PATH "/opt/opengnsys/etc/ogliveinfo.json"
4017
4018static int og_cmd_oglive_list(char *buffer_reply)
4019{
4020        struct og_buffer og_buffer = {
4021                .data = buffer_reply
4022        };
4023        json_error_t json_err;
4024        json_t *root;
4025
4026        root = json_load_file(OG_LIVE_JSON_FILE_PATH, 0, &json_err);
4027        if (!root) {
4028                syslog(LOG_ERR, "malformed json line %d: %s\n",
4029                       json_err.line, json_err.text);
4030                return -1;
4031        }
4032
4033        if (json_dump_callback(root, og_json_dump_clients, &og_buffer, 0)) {
4034                json_decref(root);
4035                return -1;
4036        }
4037
4038        json_decref(root);
4039
4040        return 0;
4041}
4042
4043static int og_cmd_post_center_add(json_t *element,
4044                                  struct og_msg_params *params,
4045                                  char *buffer_reply)
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, "name")) {
4055                        err = og_json_parse_string(value, &params->name);
4056                        params->flags |= OG_REST_PARAM_NAME;
4057                } else if (!strcmp(key, "comment")) {
4058                        err = og_json_parse_string(value, &params->comment);
4059                }
4060
4061                if (err < 0)
4062                        return err;
4063        }
4064
4065        if (!og_msg_params_validate(params, OG_REST_PARAM_NAME))
4066                return -1;
4067        if (!params->comment)
4068                params->comment = "";
4069
4070        dbi = og_dbi_open(&ogconfig.db);
4071        if (!dbi) {
4072                syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
4073                       __func__, __LINE__);
4074                return -1;
4075        }
4076
4077        result = dbi_conn_queryf(dbi->conn,
4078                                 "SELECT nombrecentro FROM centros WHERE nombrecentro='%s'",
4079                                 params->name);
4080
4081        if (!result) {
4082                dbi_conn_error(dbi->conn, &msglog);
4083                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
4084                       __func__, __LINE__, msglog);
4085                og_dbi_close(dbi);
4086                return -1;
4087        }
4088
4089        if (dbi_result_get_numrows(result) > 0) {
4090                syslog(LOG_ERR, "Center with name %s already exists\n",
4091                       params->name);
4092                dbi_result_free(result);
4093                og_dbi_close(dbi);
4094                return -1;
4095        }
4096        dbi_result_free(result);
4097
4098        result = dbi_conn_queryf(dbi->conn,
4099                                 "INSERT INTO centros("
4100                                 "  nombrecentro,"
4101                                 "  comentarios,"
4102                                 "  identidad) VALUES ("
4103                                 "'%s', '%s', 1)",
4104                                 params->name, params->comment);
4105
4106        if (!result) {
4107                dbi_conn_error(dbi->conn, &msglog);
4108                syslog(LOG_ERR, "failed to add center to database (%s:%d) %s\n",
4109                       __func__, __LINE__, msglog);
4110                og_dbi_close(dbi);
4111                return -1;
4112        }
4113
4114        dbi_result_free(result);
4115        og_dbi_close(dbi);
4116        return 0;
4117}
4118
4119static int og_cmd_post_center_delete(json_t *element,
4120                                     struct og_msg_params *params)
4121{
4122        const char *key, *msglog;
4123        struct og_dbi *dbi;
4124        dbi_result result;
4125        json_t *value;
4126        int err = 0;
4127
4128        json_object_foreach(element, key, value) {
4129                if (!strcmp(key, "id")) {
4130                        err = og_json_parse_string(value, &params->id);
4131                        params->flags |= OG_REST_PARAM_ID;
4132                }
4133                if (err < 0)
4134                        return err;
4135        }
4136
4137        if (!og_msg_params_validate(params, OG_REST_PARAM_ID))
4138                return -1;
4139
4140        dbi = og_dbi_open(&ogconfig.db);
4141        if (!dbi) {
4142                syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
4143                       __func__, __LINE__);
4144                return -1;
4145        }
4146
4147        result = dbi_conn_queryf(dbi->conn,
4148                                 "DELETE FROM centros WHERE idcentro=%s",
4149                                 params->id);
4150
4151        if (!result) {
4152                dbi_conn_error(dbi->conn, &msglog);
4153                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
4154                       __func__, __LINE__, msglog);
4155                og_dbi_close(dbi);
4156                return -1;
4157        }
4158
4159        dbi_result_free(result);
4160
4161        og_dbi_close(dbi);
4162        return 0;
4163}
4164
4165int og_procedure_add_steps(struct og_dbi *dbi, struct og_procedure *proc)
4166{
4167        struct og_procedure_step *step;
4168        const char *legacy_params;
4169        const char *msglog;
4170        dbi_result result;
4171        int i;
4172
4173        for (i = 0; i < proc->num_steps; i++) {
4174                step = &proc->steps[i];
4175                switch (step->type) {
4176                case OG_STEP_COMMAND:
4177                        legacy_params = og_msg_params_to_legacy(&step->cmd);
4178                        if (!legacy_params) {
4179                                og_dbi_close(dbi);
4180                                return -1;
4181                        }
4182                        result = dbi_conn_queryf(dbi->conn,
4183                                                 "INSERT INTO procedimientos_acciones "
4184                                                 "(idprocedimiento, orden, parametros) "
4185                                                 "VALUES (%d, %d, '%s')",
4186                                                 proc->id,
4187                                                 step->position,
4188                                                 legacy_params);
4189                        if (!result) {
4190                                dbi_conn_error(dbi->conn, &msglog);
4191                                syslog(LOG_ERR,
4192                                       "failed to add procedure command to database (%s:%d) %s\n",
4193                                       __func__, __LINE__, msglog);
4194                                og_dbi_close(dbi);
4195                                free((char *)legacy_params);
4196                                return -1;
4197                        }
4198
4199                        dbi_result_free(result);
4200                        free((char *)legacy_params);
4201                        break;
4202                case OG_STEP_PROCEDURE:
4203                        result = dbi_conn_queryf(dbi->conn,
4204                                                 "INSERT INTO procedimientos_acciones "
4205                                                 "(idprocedimiento, orden, procedimientoid) "
4206                                                 "VALUES (%d, %d, %d)",
4207                                                 proc->id,
4208                                                 step->position,
4209                                                 step->procedure.id);
4210                        if (!result) {
4211                                dbi_conn_error(dbi->conn, &msglog);
4212                                syslog(LOG_ERR,
4213                                       "failed to add procedure child to database (%s:%d) %s\n",
4214                                       __func__, __LINE__, msglog);
4215                                og_dbi_close(dbi);
4216                                return -1;
4217                        }
4218                        dbi_result_free(result);
4219                        break;
4220                case OG_STEP_TASK:
4221                        syslog(LOG_ERR, "Procedures can not include tasks. "
4222                                        "Invalid step: %d\n",
4223                               step->position);
4224                        return -1;
4225                        break;
4226                }
4227        }
4228
4229        return 0;
4230}
4231
4232static int og_cmd_post_procedure_add(json_t *element,
4233                                     struct og_msg_params *params)
4234{
4235        struct og_procedure proc = {};
4236        const char *key, *msglog;
4237        struct og_dbi *dbi;
4238        dbi_result result;
4239        json_t *value;
4240        int err = 0;
4241
4242        json_object_foreach(element, key, value) {
4243                if (!strcmp(key, "center")) {
4244                        err = og_json_parse_string(value, &params->id);
4245                        params->flags |= OG_REST_PARAM_ID;
4246                } else if (!strcmp(key, "name")) {
4247                        err = og_json_parse_string(value, &params->name);
4248                        params->flags |= OG_REST_PARAM_NAME;
4249                } else if (!strcmp(key, "description")) {
4250                        err = og_json_parse_string(value, &params->comment);
4251                } else if (!strcmp(key, "steps")) {
4252                        err = og_json_parse_procedure(value, &proc);
4253                }
4254
4255                if (err < 0)
4256                        return err;
4257        }
4258
4259        if (!og_msg_params_validate(params, OG_REST_PARAM_ID |
4260                                            OG_REST_PARAM_NAME))
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                                 "SELECT descripcion FROM procedimientos "
4272                                 "WHERE descripcion='%s' AND idcentro=%s",
4273                                 params->name, params->id);
4274
4275        if (!result) {
4276                dbi_conn_error(dbi->conn, &msglog);
4277                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
4278                       __func__, __LINE__, msglog);
4279                og_dbi_close(dbi);
4280                return -1;
4281        }
4282
4283        if (dbi_result_get_numrows(result) > 0) {
4284                syslog(LOG_ERR, "Procedure with name %s already exists in the "
4285                                "center with id %s\n",
4286                       params->name, params->id);
4287                dbi_result_free(result);
4288                og_dbi_close(dbi);
4289                return -1;
4290        }
4291        dbi_result_free(result);
4292
4293        result = dbi_conn_queryf(dbi->conn,
4294                                 "INSERT INTO procedimientos("
4295                                 "idcentro, descripcion, comentarios) "
4296                                 "VALUES (%s, '%s', '%s')",
4297                                 params->id, params->name, params->comment);
4298
4299        if (!result) {
4300                dbi_conn_error(dbi->conn, &msglog);
4301                syslog(LOG_ERR,
4302                       "failed to add procedure to database (%s:%d) %s\n",
4303                       __func__, __LINE__, msglog);
4304                og_dbi_close(dbi);
4305                return -1;
4306        }
4307        dbi_result_free(result);
4308
4309        proc.id = dbi_conn_sequence_last(dbi->conn, NULL);
4310        err = og_procedure_add_steps(dbi, &proc);
4311
4312        og_dbi_close(dbi);
4313
4314        return err;
4315}
4316
4317static int og_cmd_post_procedure_delete(json_t *element,
4318                                        struct og_msg_params *params)
4319{
4320        const char *key, *msglog;
4321        struct og_dbi *dbi;
4322        dbi_result result;
4323        json_t *value;
4324        int err = 0;
4325
4326        json_object_foreach(element, key, value) {
4327                if (!strcmp(key, "id")) {
4328                        err = og_json_parse_string(value, &params->id);
4329                        params->flags |= OG_REST_PARAM_ID;
4330                }
4331                if (err < 0)
4332                        return err;
4333        }
4334
4335        if (!og_msg_params_validate(params, OG_REST_PARAM_ID))
4336                return -1;
4337
4338        dbi = og_dbi_open(&ogconfig.db);
4339        if (!dbi) {
4340                syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
4341                       __func__, __LINE__);
4342                return -1;
4343        }
4344
4345        result = dbi_conn_queryf(dbi->conn,
4346                                 "DELETE FROM procedimientos WHERE idprocedimiento=%s",
4347                                 params->id);
4348
4349        if (!result) {
4350                dbi_conn_error(dbi->conn, &msglog);
4351                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
4352                       __func__, __LINE__, msglog);
4353                og_dbi_close(dbi);
4354                return -1;
4355        } else if (dbi_result_get_numrows_affected(result) < 1) {
4356                syslog(LOG_ERR, "delete did not modify any row (%s:%d)\n",
4357                       __func__, __LINE__);
4358        }
4359
4360        dbi_result_free(result);
4361
4362        og_dbi_close(dbi);
4363        return 0;
4364}
4365
4366static int og_cmd_post_procedure_update(json_t *element,
4367                                        struct og_msg_params *params)
4368{
4369        struct og_procedure proc = {};
4370        const char *key, *msglog;
4371        struct og_dbi *dbi;
4372        dbi_result result;
4373        json_t *value;
4374        int err = 0;
4375
4376        json_object_foreach(element, key, value) {
4377                if (!strcmp(key, "procedure")) {
4378                        err = og_json_parse_string(value, &params->task_id);
4379                        params->flags |= OG_REST_PARAM_TASK;
4380                } else if (!strcmp(key, "center")) {
4381                        err = og_json_parse_string(value, &params->id);
4382                        params->flags |= OG_REST_PARAM_ID;
4383                } else if (!strcmp(key, "name")) {
4384                        err = og_json_parse_string(value, &params->name);
4385                        params->flags |= OG_REST_PARAM_NAME;
4386                } else if (!strcmp(key, "description")) {
4387                        err = og_json_parse_string(value, &params->comment);
4388                } else if (!strcmp(key, "steps")) {
4389                        err = og_json_parse_procedure(value, &proc);
4390                }
4391
4392                if (err < 0)
4393                        return err;
4394        }
4395
4396        if (!og_msg_params_validate(params, OG_REST_PARAM_TASK |
4397                                            OG_REST_PARAM_ID |
4398                                            OG_REST_PARAM_NAME))
4399                return -1;
4400
4401        dbi = og_dbi_open(&ogconfig.db);
4402        if (!dbi) {
4403                syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
4404                       __func__, __LINE__);
4405                return -1;
4406        }
4407
4408        result = dbi_conn_queryf(dbi->conn,
4409                                 "SELECT descripcion FROM procedimientos "
4410                                 "WHERE descripcion = '%s' AND idcentro = %s "
4411                                 "AND idprocedimiento <> %s",
4412                                 params->name, params->id, params->task_id);
4413
4414        if (!result) {
4415                dbi_conn_error(dbi->conn, &msglog);
4416                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
4417                       __func__, __LINE__, msglog);
4418                og_dbi_close(dbi);
4419                return -1;
4420        }
4421
4422        if (dbi_result_get_numrows(result) > 0) {
4423                syslog(LOG_ERR, "Procedure with name %s already exists in the "
4424                                "center with id %s\n",
4425                       params->name, params->id);
4426                dbi_result_free(result);
4427                og_dbi_close(dbi);
4428                return -1;
4429        }
4430        dbi_result_free(result);
4431
4432        result = dbi_conn_queryf(dbi->conn,
4433                                 "UPDATE procedimientos SET idcentro = %s, "
4434                                 "descripcion = '%s', comentarios = '%s' "
4435                                 "WHERE idprocedimiento = %s",
4436                                 params->id, params->name, params->comment,
4437                                 params->task_id);
4438
4439        if (!result) {
4440                dbi_conn_error(dbi->conn, &msglog);
4441                syslog(LOG_ERR,
4442                       "failed to update procedure %s (%s:%d) %s\n",
4443                       params->task_id, __func__, __LINE__, msglog);
4444                og_dbi_close(dbi);
4445                return -1;
4446        }
4447        dbi_result_free(result);
4448
4449        result = dbi_conn_queryf(dbi->conn,
4450                                 "DELETE FROM procedimientos_acciones "
4451                                 "WHERE idprocedimiento = %s",
4452                                 params->task_id);
4453
4454        if (!result) {
4455                dbi_conn_error(dbi->conn, &msglog);
4456                syslog(LOG_ERR,
4457                       "failed to delete old procedure %s steps (%s:%d) %s\n",
4458                       params->task_id, __func__, __LINE__, msglog);
4459                og_dbi_close(dbi);
4460                return -1;
4461        }
4462        dbi_result_free(result);
4463
4464        proc.id = atoll(params->task_id);
4465        err = og_procedure_add_steps(dbi, &proc);
4466
4467        og_dbi_close(dbi);
4468
4469        return err;
4470}
4471
4472static int og_task_add_steps(struct og_dbi *dbi, struct og_procedure *task)
4473{
4474        struct og_procedure_step *step;
4475        const char *msglog;
4476        dbi_result result;
4477        int i;
4478
4479        for (i = 0; i < task->num_steps; i++) {
4480                step = &task->steps[i];
4481                switch (step->type) {
4482                case OG_STEP_COMMAND:
4483                        syslog(LOG_ERR, "Tasks can not include commands. "
4484                                        "Invalid step: %d\n",
4485                               step->position);
4486                        return -1;
4487                        break;
4488                case OG_STEP_PROCEDURE:
4489                        result = dbi_conn_queryf(dbi->conn,
4490                                                 "INSERT INTO tareas_acciones "
4491                                                 "(idtarea, orden, idprocedimiento) "
4492                                                 "VALUES (%d, %d, %d)",
4493                                                 task->id,
4494                                                 step->position,
4495                                                 step->procedure.id);
4496                        if (!result) {
4497                                dbi_conn_error(dbi->conn, &msglog);
4498                                syslog(LOG_ERR,
4499                                       "failed to add procedure child to database (%s:%d) %s\n",
4500                                       __func__, __LINE__, msglog);
4501                                og_dbi_close(dbi);
4502                                return -1;
4503                        }
4504                        dbi_result_free(result);
4505                        break;
4506                case OG_STEP_TASK:
4507                        result = dbi_conn_queryf(dbi->conn,
4508                                                 "INSERT INTO tareas_acciones "
4509                                                 "(idtarea, orden, tareaid) "
4510                                                 "VALUES (%d, %d, %d)",
4511                                                 task->id,
4512                                                 step->position,
4513                                                 step->procedure.id);
4514                        if (!result) {
4515                                dbi_conn_error(dbi->conn, &msglog);
4516                                syslog(LOG_ERR,
4517                                       "failed to add task child to database (%s:%d) %s\n",
4518                                       __func__, __LINE__, msglog);
4519                                og_dbi_close(dbi);
4520                                return -1;
4521                        }
4522                        dbi_result_free(result);
4523                        break;
4524                }
4525        }
4526
4527        return 0;
4528}
4529
4530static int og_cmd_post_task_add(json_t *element,
4531                                     struct og_msg_params *params)
4532{
4533        struct og_procedure task = {};
4534        const char *key, *msglog;
4535        struct og_dbi *dbi;
4536        dbi_result result;
4537        json_t *value;
4538        int err = 0;
4539
4540        json_object_foreach(element, key, value) {
4541                if (!strcmp(key, "center")) {
4542                        err = og_json_parse_string(value, &params->id);
4543                        params->flags |= OG_REST_PARAM_ID;
4544                } else if (!strcmp(key, "name")) {
4545                        err = og_json_parse_string(value, &params->name);
4546                        params->flags |= OG_REST_PARAM_NAME;
4547                } else if (!strcmp(key, "description")) {
4548                        err = og_json_parse_string(value, &params->comment);
4549                } else if (!strcmp(key, "steps")) {
4550                        err = og_json_parse_procedure(value, &task);
4551                }
4552
4553                if (err < 0)
4554                        return err;
4555        }
4556
4557        if (!og_msg_params_validate(params, OG_REST_PARAM_ID |
4558                                            OG_REST_PARAM_NAME))
4559                return -1;
4560
4561        dbi = og_dbi_open(&ogconfig.db);
4562        if (!dbi) {
4563                syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
4564                       __func__, __LINE__);
4565                return -1;
4566        }
4567
4568        result = dbi_conn_queryf(dbi->conn,
4569                                 "SELECT descripcion FROM tareas "
4570                                 "WHERE descripcion='%s' AND idcentro=%s",
4571                                 params->name, params->id);
4572
4573        if (!result) {
4574                dbi_conn_error(dbi->conn, &msglog);
4575                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
4576                       __func__, __LINE__, msglog);
4577                og_dbi_close(dbi);
4578                return -1;
4579        }
4580
4581        if (dbi_result_get_numrows(result) > 0) {
4582                syslog(LOG_ERR, "Task with name %s already exists in the "
4583                                "center with id %s\n",
4584                       params->name, params->id);
4585                dbi_result_free(result);
4586                og_dbi_close(dbi);
4587                return -1;
4588        }
4589        dbi_result_free(result);
4590
4591        result = dbi_conn_queryf(dbi->conn,
4592                                 "INSERT INTO tareas("
4593                                 "idcentro, descripcion, comentarios) "
4594                                 "VALUES (%s, '%s', '%s')",
4595                                 params->id, params->name, params->comment);
4596
4597        if (!result) {
4598                dbi_conn_error(dbi->conn, &msglog);
4599                syslog(LOG_ERR,
4600                       "failed to add task to database (%s:%d) %s\n",
4601                       __func__, __LINE__, msglog);
4602                og_dbi_close(dbi);
4603                return -1;
4604        }
4605        dbi_result_free(result);
4606
4607        task.id = dbi_conn_sequence_last(dbi->conn, NULL);
4608        err = og_task_add_steps(dbi, &task);
4609
4610        og_dbi_close(dbi);
4611
4612        return err;
4613}
4614
4615static int og_cmd_post_room_add(json_t *element,
4616                                struct og_msg_params *params)
4617{
4618        struct og_room room = {};
4619        const char *key, *msglog;
4620        struct og_dbi *dbi;
4621        dbi_result result;
4622        json_t *value;
4623        int err = 0;
4624
4625        json_object_foreach(element, key, value) {
4626                if (!strcmp(key, "name")) {
4627                        err = og_json_parse_string_copy(value, room.name,
4628                                                        sizeof(room.name));
4629                        params->flags |= OG_REST_PARAM_NAME;
4630                } else if (!strcmp(key, "location")) {
4631                        err = og_json_parse_string_copy(value, room.location,
4632                                                        sizeof(room.location));
4633                } else if (!strcmp(key, "gateway")) {
4634                        err = og_json_parse_string_copy(value, room.gateway,
4635                                                        sizeof(room.gateway));
4636                } else if (!strcmp(key, "netmask")) {
4637                        err = og_json_parse_string_copy(value, room.netmask,
4638                                                        sizeof(room.netmask));
4639                        params->flags |= OG_REST_PARAM_NETMASK;
4640                } else if (!strcmp(key, "ntp")) {
4641                        err = og_json_parse_string_copy(value, room.ntp,
4642                                                        sizeof(room.ntp));
4643                } else if (!strcmp(key, "dns")) {
4644                        err = og_json_parse_string_copy(value, room.dns,
4645                                                        sizeof(room.dns));
4646                } else if (!strcmp(key, "center")) {
4647                        err = og_json_parse_uint(value, &room.center);
4648                        params->flags |= OG_REST_PARAM_CENTER;
4649                } else if (!strcmp(key, "group")) {
4650                        err = og_json_parse_uint(value, &room.group);
4651                } else if (!strcmp(key, "remote")) {
4652                        err = og_json_parse_bool(value, &room.remote);
4653                }
4654
4655                if (err < 0)
4656                        return err;
4657        }
4658
4659        if (!og_msg_params_validate(params, OG_REST_PARAM_NAME |
4660                                            OG_REST_PARAM_NETMASK |
4661                                            OG_REST_PARAM_CENTER))
4662                return -1;
4663
4664        dbi = og_dbi_open(&ogconfig.db);
4665        if (!dbi) {
4666                syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
4667                       __func__, __LINE__);
4668                return -1;
4669        }
4670
4671        result = dbi_conn_queryf(dbi->conn,
4672                                 "SELECT nombreaula FROM aulas "
4673                                 "WHERE nombreaula='%s' AND idcentro=%d",
4674                                 room.name, room.center);
4675
4676        if (!result) {
4677                dbi_conn_error(dbi->conn, &msglog);
4678                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
4679                       __func__, __LINE__, msglog);
4680                og_dbi_close(dbi);
4681                return -1;
4682        }
4683
4684        if (dbi_result_get_numrows(result) > 0) {
4685                syslog(LOG_ERR, "Room with name %s already exists in the "
4686                                "center with id %d\n",
4687                       room.name, room.center);
4688                dbi_result_free(result);
4689                og_dbi_close(dbi);
4690                return -1;
4691        }
4692        dbi_result_free(result);
4693
4694        result = dbi_conn_queryf(dbi->conn,
4695                                 "INSERT INTO aulas("
4696                                 "  idcentro,"
4697                                 "  nombreaula,"
4698                                 "  netmask,"
4699                                 "  grupoid,"
4700                                 "  ubicacion,"
4701                                 "  router,"
4702                                 "  dns,"
4703                                 "  ntp,"
4704                                 "  inremotepc) VALUES ("
4705                                 "%d, '%s', '%s', %d, '%s', "
4706                                 "'%s', '%s', '%s', %d)",
4707                                 room.center, room.name, room.netmask,
4708                                 room.group, room.location, room.gateway,
4709                                 room.dns, room.ntp, room.remote);
4710
4711        if (!result) {
4712                dbi_conn_error(dbi->conn, &msglog);
4713                syslog(LOG_ERR, "failed to add room to database (%s:%d) %s\n",
4714                       __func__, __LINE__, msglog);
4715                og_dbi_close(dbi);
4716                return -1;
4717        }
4718
4719        dbi_result_free(result);
4720        og_dbi_close(dbi);
4721        return 0;
4722}
4723
4724static int og_cmd_post_room_delete(json_t *element,
4725                                   struct og_msg_params *params)
4726{
4727        const char *key, *msglog;
4728        struct og_dbi *dbi;
4729        dbi_result result;
4730        json_t *value;
4731        int err = 0;
4732
4733        json_object_foreach(element, key, value) {
4734                if (!strcmp(key, "id")) {
4735                        err = og_json_parse_string(value, &params->id);
4736                        params->flags |= OG_REST_PARAM_ID;
4737                }
4738                if (err < 0)
4739                        return err;
4740        }
4741
4742        if (!og_msg_params_validate(params, OG_REST_PARAM_ID))
4743                return -1;
4744
4745        dbi = og_dbi_open(&ogconfig.db);
4746        if (!dbi) {
4747                syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
4748                       __func__, __LINE__);
4749                return -1;
4750        }
4751
4752        result = dbi_conn_queryf(dbi->conn,
4753                                 "DELETE FROM aulas WHERE idaula=%s",
4754                                 params->id);
4755
4756        if (!result) {
4757                dbi_conn_error(dbi->conn, &msglog);
4758                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
4759                       __func__, __LINE__, msglog);
4760                og_dbi_close(dbi);
4761                return -1;
4762        }
4763
4764        dbi_result_free(result);
4765
4766        og_dbi_close(dbi);
4767        return 0;
4768}
4769
4770enum {
4771        OG_SCHEDULE_CMD_TYPE    = 0,
4772        OG_SCHEDULE_CMD_PARAMS,
4773};
4774
4775static bool og_cmd_validate(const struct og_cmd_json *cmd,
4776                            const uint64_t flags)
4777{
4778        return (cmd->flags & flags) == flags;
4779}
4780
4781
4782static int og_cmd_post_schedule_command(json_t *element,
4783                                        struct og_msg_params *params)
4784{
4785        char *centerid_query  = "SELECT o.idordenador, c.idcentro "
4786                                "FROM `ordenadores` AS o "
4787                                "INNER JOIN aulas AS a ON o.idaula = a.idaula "
4788                                "INNER JOIN centros AS c ON a.idcentro = c.idcentro "
4789                                "WHERE o.ip = '%s';";
4790        uint32_t sequence, session = 0;
4791        int center_id, client_id, len;
4792        struct og_cmd_json cmd = {};
4793        const char *legacy_params;
4794        const char *key, *msglog;
4795        struct og_dbi *dbi;
4796        char task_id[128];
4797        bool when = false;
4798        dbi_result result;
4799        json_t *value;
4800        int err = 0, i;
4801
4802        json_object_foreach(element, key, value) {
4803                if (!strcmp(key, "clients")) {
4804                        err = og_json_parse_clients(value, params);
4805                } else if (!strcmp(key, "command")) {
4806                        err = og_json_parse_string(value, &cmd.type);
4807                        cmd.flags |= OG_SCHEDULE_CMD_TYPE;
4808                } else if (!strcmp(key, "params")) {
4809                        cmd.json = value;
4810                        cmd.flags |= OG_SCHEDULE_CMD_PARAMS;
4811                } else if (!strcmp(key, "when")) {
4812                        err = og_json_parse_time_params(value, params);
4813                        when = true;
4814                }
4815
4816                if (err < 0)
4817                        return err;
4818        }
4819
4820        if (!og_cmd_validate(&cmd, OG_SCHEDULE_CMD_TYPE |
4821                                   OG_SCHEDULE_CMD_PARAMS))
4822                return -1;
4823
4824        if (!when) {
4825                params->time.check_stale = false;
4826                og_schedule_time_now(&params->time);
4827                params->flags |= OG_REST_PARAM_TIME_YEARS |
4828                                 OG_REST_PARAM_TIME_MONTHS |
4829                                 OG_REST_PARAM_TIME_WEEKS |
4830                                 OG_REST_PARAM_TIME_WEEK_DAYS |
4831                                 OG_REST_PARAM_TIME_DAYS |
4832                                 OG_REST_PARAM_TIME_HOURS |
4833                                 OG_REST_PARAM_TIME_AM_PM |
4834                                 OG_REST_PARAM_TIME_MINUTES;
4835        } else {
4836                params->time.check_stale = true;
4837        }
4838
4839        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
4840                                            OG_REST_PARAM_TIME_YEARS |
4841                                            OG_REST_PARAM_TIME_MONTHS |
4842                                            OG_REST_PARAM_TIME_WEEKS |
4843                                            OG_REST_PARAM_TIME_WEEK_DAYS |
4844                                            OG_REST_PARAM_TIME_DAYS |
4845                                            OG_REST_PARAM_TIME_HOURS |
4846                                            OG_REST_PARAM_TIME_MINUTES |
4847                                            OG_REST_PARAM_TIME_AM_PM))
4848                return -1;
4849
4850        params->type = "command";
4851        dbi = og_dbi_open(&ogconfig.db);
4852        if (!dbi) {
4853                syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
4854                       __func__, __LINE__);
4855                goto err_dbi_open;
4856        }
4857
4858        legacy_params = og_msg_params_to_legacy(&cmd);
4859        if (!legacy_params)
4860                goto err_legacy_params;
4861
4862        /* ips_array -> ids */
4863        for (i = 0; i < params->ips_array_len; i++) {
4864
4865                result = dbi_conn_queryf(dbi->conn, centerid_query, params->ips_array[i]);
4866                if (!result) {
4867                        dbi_conn_error(dbi->conn, &msglog);
4868                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
4869                               __func__, __LINE__, msglog);
4870                        goto err_dbi_result;
4871                }
4872                if (dbi_result_get_numrows(result) != 1) {
4873                        dbi_conn_error(dbi->conn, &msglog);
4874                        syslog(LOG_ERR, "client not found (%s:%d) %s\n",
4875                               __func__, __LINE__, msglog);
4876                        goto err_dbi;
4877                }
4878
4879                if (!dbi_result_next_row(result)) {
4880                        dbi_conn_error(dbi->conn, &msglog);
4881                        syslog(LOG_ERR, "failed to get idcentro (%s:%d) %s\n",
4882                               __func__, __LINE__, msglog);
4883                        goto err_dbi;
4884                }
4885                center_id = dbi_result_get_uint(result, "idcentro");
4886                if (!center_id) {
4887                        dbi_conn_error(dbi->conn, &msglog);
4888                        syslog(LOG_ERR, "failed to get idcentro (%s:%d) %s\n",
4889                               __func__, __LINE__, msglog);
4890                        goto err_dbi;
4891                }
4892                client_id = dbi_result_get_uint(result, "idordenador");
4893                dbi_result_free(result);
4894
4895                result = dbi_conn_queryf(dbi->conn, "INSERT INTO acciones (idordenador, "
4896                                                    "idcentro, parametros)"
4897                                                    "VALUES (%d, %d, '%s')",
4898                                         client_id, center_id, legacy_params);
4899                if (!result) {
4900                        dbi_conn_error(dbi->conn, &msglog);
4901                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
4902                               __func__, __LINE__, msglog);
4903                        goto err_dbi_result;
4904                }
4905                dbi_result_free(result);
4906
4907                sequence = dbi_conn_sequence_last(dbi->conn, NULL);
4908
4909                /* This 'session' ID allows us to correlate the schedule with
4910                 * the commands after expansion.
4911                 */
4912                if (!session)
4913                        session = dbi_conn_sequence_last(dbi->conn, NULL);
4914
4915                result = dbi_conn_queryf(dbi->conn, "UPDATE acciones SET idordenador=%d, "
4916                                                    "idcentro=%d, parametros='%s', sesion=%d"
4917                                                    "WHERE idaccion=%d",
4918                                         client_id, center_id, legacy_params,
4919                                         session, sequence);
4920                if (!result) {
4921                        dbi_conn_error(dbi->conn, &msglog);
4922                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
4923                               __func__, __LINE__, msglog);
4924                        goto err_dbi_result;
4925                }
4926                dbi_result_free(result);
4927        }
4928
4929        len = snprintf(task_id, sizeof(session), "%d", session);
4930        if (len >= (int)sizeof(task_id)) {
4931                syslog(LOG_ERR, "truncated snprintf (%s:%d)\n",
4932                       __func__, __LINE__);
4933                goto err_dbi_result;
4934        }
4935        params->task_id = task_id;
4936
4937        og_task_schedule_create(params);
4938
4939        free((char *)legacy_params);
4940        og_dbi_close(dbi);
4941        return 0;
4942
4943err_dbi:
4944        dbi_result_free(result);
4945err_dbi_result:
4946        free((char *)legacy_params);
4947err_legacy_params:
4948        og_dbi_close(dbi);
4949err_dbi_open:
4950        return -1;
4951}
4952
4953static int og_cmd_post_procedure_run(json_t *element,
4954                                     struct og_msg_params *params)
4955{
4956        const char *centerid_query  = "SELECT o.idordenador, c.idcentro "
4957                                      "FROM `ordenadores` AS o "
4958                                      "INNER JOIN aulas AS a "
4959                                      "ON o.idaula = a.idaula "
4960                                      "INNER JOIN centros AS c "
4961                                      "ON a.idcentro = c.idcentro "
4962                                      "WHERE o.ip = '%s';";
4963        struct og_task task = {};
4964        const char *key, *msglog;
4965        struct og_dbi *dbi;
4966        dbi_result result;
4967        int i, err = 0;
4968        json_t *value;
4969
4970        json_object_foreach(element, key, value) {
4971                if (!strcmp(key, "clients")) {
4972                        err = og_json_parse_clients(value, params);
4973                } else if (!strcmp(key, "procedure")) {
4974                        err = og_json_parse_string(value, &params->id);
4975                        params->flags |= OG_REST_PARAM_ID;
4976                }
4977
4978                if (err < 0)
4979                        goto err_return;
4980        }
4981
4982        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
4983                                            OG_REST_PARAM_ID ))
4984                goto err_return;
4985
4986        task.type_scope = AMBITO_ORDENADORES;
4987        task.procedure_id = atoi(params->id);
4988
4989        dbi = og_dbi_open(&ogconfig.db);
4990        if (!dbi) {
4991                syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
4992                       __func__, __LINE__);
4993                goto err_return;
4994        }
4995
4996        for (i = 0; i < params->ips_array_len; i++) {
4997
4998                result = dbi_conn_queryf(dbi->conn, centerid_query, params->ips_array[i]);
4999                if (!result) {
5000                        dbi_conn_error(dbi->conn, &msglog);
5001                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
5002                               __func__, __LINE__, msglog);
5003                        goto err_close_dbi;
5004                }
5005
5006                if (dbi_result_get_numrows(result) != 1 ||
5007                    !dbi_result_next_row(result) ||
5008                    !dbi_result_get_uint(result, "idcentro") ||
5009                    !dbi_result_get_uint(result, "idordenador")) {
5010                        dbi_conn_error(dbi->conn, &msglog);
5011                        syslog(LOG_ERR, "failed to get query data (%s:%d) %s\n",
5012                               __func__, __LINE__, msglog);
5013                        goto err_free_result;
5014                }
5015
5016                task.center_id = dbi_result_get_uint(result, "idcentro");
5017                task.scope = dbi_result_get_uint(result, "idordenador");
5018                dbi_result_free(result);
5019
5020                if (og_dbi_queue_procedure(dbi, &task))
5021                        goto err_close_dbi;
5022        }
5023
5024        og_dbi_close(dbi);
5025
5026        return og_send_request(OG_METHOD_GET, OG_CMD_RUN_SCHEDULE, params,
5027                               NULL);
5028
5029err_free_result:
5030        dbi_result_free(result);
5031err_close_dbi:
5032        og_dbi_close(dbi);
5033err_return:
5034        return -1;
5035}
5036
5037static int og_client_method_not_found(struct og_client *cli)
5038{
5039        /* To meet RFC 7231, this function MUST generate an Allow header field
5040         * containing the correct methods. For example: "Allow: POST\r\n"
5041         */
5042        char buf[] = "HTTP/1.1 405 Method Not Allowed\r\n"
5043                     "Content-Length: 0\r\n\r\n";
5044
5045        send(og_client_socket(cli), buf, strlen(buf), 0);
5046
5047        return -1;
5048}
5049
5050static int og_client_bad_request(struct og_client *cli)
5051{
5052        char buf[] = "HTTP/1.1 400 Bad Request\r\nContent-Length: 0\r\n\r\n";
5053
5054        send(og_client_socket(cli), buf, strlen(buf), 0);
5055
5056        return -1;
5057}
5058
5059static int og_client_not_found(struct og_client *cli)
5060{
5061        char buf[] = "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n";
5062
5063        send(og_client_socket(cli), buf, strlen(buf), 0);
5064
5065        return -1;
5066}
5067
5068static int og_client_not_authorized(struct og_client *cli)
5069{
5070        char buf[] = "HTTP/1.1 401 Unauthorized\r\n"
5071                     "WWW-Authenticate: Basic\r\n"
5072                     "Content-Length: 0\r\n\r\n";
5073
5074        send(og_client_socket(cli), buf, strlen(buf), 0);
5075
5076        return -1;
5077}
5078
5079static int og_server_internal_error(struct og_client *cli)
5080{
5081        char buf[] = "HTTP/1.1 500 Internal Server Error\r\n"
5082                     "Content-Length: 0\r\n\r\n";
5083
5084        send(og_client_socket(cli), buf, strlen(buf), 0);
5085
5086        return -1;
5087}
5088
5089static int og_client_ok(struct og_client *cli, char *buf_reply)
5090{
5091        char buf[OG_MSG_RESPONSE_MAXLEN] = {};
5092        int len;
5093
5094        len = snprintf(buf, sizeof(buf),
5095                       "HTTP/1.1 200 OK\r\nContent-Length: %ld\r\n\r\n%s",
5096                       strlen(buf_reply), buf_reply);
5097        if (len >= (int)sizeof(buf)) {
5098                syslog(LOG_ERR, "HTTP response to %s:%hu is too large\n",
5099                       inet_ntoa(cli->addr.sin_addr),
5100                       ntohs(cli->addr.sin_port));
5101                return og_server_internal_error(cli);
5102        }
5103
5104        send(og_client_socket(cli), buf, strlen(buf), 0);
5105
5106        return 0;
5107}
5108
5109int og_client_state_process_payload_rest(struct og_client *cli)
5110{
5111        char buf_reply[OG_MSG_RESPONSE_MAXLEN] = {};
5112        struct og_msg_params params = {};
5113        enum og_rest_method method;
5114        const char *cmd, *body;
5115        json_error_t json_err;
5116        json_t *root = NULL;
5117        int err = 0;
5118
5119        syslog(LOG_DEBUG, "%s:%hu %.32s ...\n",
5120               inet_ntoa(cli->addr.sin_addr),
5121               ntohs(cli->addr.sin_port), cli->buf);
5122
5123        if (!strncmp(cli->buf, "GET", strlen("GET"))) {
5124                method = OG_METHOD_GET;
5125                cmd = cli->buf + strlen("GET") + 2;
5126        } else if (!strncmp(cli->buf, "POST", strlen("POST"))) {
5127                method = OG_METHOD_POST;
5128                cmd = cli->buf + strlen("POST") + 2;
5129        } else
5130                return og_client_method_not_found(cli);
5131
5132        body = strstr(cli->buf, "\r\n\r\n") + 4;
5133
5134        if (strcmp(cli->auth_token, ogconfig.rest.api_token)) {
5135                syslog(LOG_ERR, "wrong Authentication key\n");
5136                return og_client_not_authorized(cli);
5137        }
5138
5139        if (cli->content_length) {
5140                root = json_loads(body, 0, &json_err);
5141                if (!root) {
5142                        syslog(LOG_ERR, "malformed json line %d: %s\n",
5143                               json_err.line, json_err.text);
5144                        return og_client_not_found(cli);
5145                }
5146        }
5147
5148        if (!strncmp(cmd, "clients", strlen("clients"))) {
5149                if (method != OG_METHOD_POST &&
5150                    method != OG_METHOD_GET) {
5151                        err = og_client_method_not_found(cli);
5152                        goto err_process_rest_payload;
5153                }
5154
5155                if (method == OG_METHOD_POST && !root) {
5156                        syslog(LOG_ERR, "command clients with no payload\n");
5157                        err = og_client_bad_request(cli);
5158                        goto err_process_rest_payload;
5159                }
5160                switch (method) {
5161                case OG_METHOD_POST:
5162                        err = og_cmd_post_clients(root, &params);
5163                        break;
5164                case OG_METHOD_GET:
5165                        err = og_cmd_get_clients(root, &params, buf_reply);
5166                        break;
5167                default:
5168                        err = og_client_bad_request(cli);
5169                        goto err_process_rest_payload;
5170                }
5171        } else if (!strncmp(cmd, "client/setup",
5172                            strlen("client/setup"))) {
5173                if (method != OG_METHOD_GET) {
5174                        err = og_client_method_not_found(cli);
5175                        goto err_process_rest_payload;
5176                }
5177
5178                if (!root) {
5179                        syslog(LOG_ERR,
5180                               "command client partitions with no payload\n");
5181                        err = og_client_bad_request(cli);
5182                        goto err_process_rest_payload;
5183                }
5184
5185                err = og_cmd_get_client_setup(root, &params, buf_reply);
5186        } else if (!strncmp(cmd, "client/info",
5187                            strlen("client/info"))) {
5188                if (method != OG_METHOD_GET) {
5189                        err = og_client_method_not_found(cli);
5190                        goto err_process_rest_payload;
5191                }
5192                if (!root) {
5193                        syslog(LOG_ERR,
5194                               "command client info with no payload\n");
5195                        err = og_client_bad_request(cli);
5196                        goto err_process_rest_payload;
5197                }
5198
5199                err = og_cmd_get_client_info(root, &params, buf_reply);
5200        } else if (!strncmp(cmd, "client/add", strlen("client/add"))) {
5201                if (method != OG_METHOD_POST) {
5202                        err = og_client_method_not_found(cli);
5203                        goto err_process_rest_payload;
5204                }
5205
5206                if (!root) {
5207                        syslog(LOG_ERR,
5208                               "command client info with no payload\n");
5209                        err = og_client_bad_request(cli);
5210                        goto err_process_rest_payload;
5211                }
5212
5213                err = og_cmd_post_client_add(root, &params, buf_reply);
5214        } else if (!strncmp(cmd, "client/delete", strlen("client/delete"))) {
5215                if (method != OG_METHOD_POST) {
5216                        err = og_client_method_not_found(cli);
5217                        goto err_process_rest_payload;
5218                }
5219
5220                if (!root) {
5221                        syslog(LOG_ERR,
5222                               "command client delete with no payload\n");
5223                        err = og_client_bad_request(cli);
5224                        goto err_process_rest_payload;
5225                }
5226
5227                err = og_cmd_post_client_delete(root, &params);
5228        } else if (!strncmp(cmd, "wol", strlen("wol"))) {
5229                if (method != OG_METHOD_POST) {
5230                        err = og_client_method_not_found(cli);
5231                        goto err_process_rest_payload;
5232                }
5233
5234                if (!root) {
5235                        syslog(LOG_ERR, "command wol with no payload\n");
5236                        err = og_client_bad_request(cli);
5237                        goto err_process_rest_payload;
5238                }
5239                err = og_cmd_wol(root, &params);
5240        } else if (!strncmp(cmd, "shell/run", strlen("shell/run"))) {
5241                if (method != OG_METHOD_POST) {
5242                        err = og_client_method_not_found(cli);
5243                        goto err_process_rest_payload;
5244                }
5245
5246                if (!root) {
5247                        syslog(LOG_ERR, "command run with no payload\n");
5248                        err = og_client_bad_request(cli);
5249                        goto err_process_rest_payload;
5250                }
5251                err = og_cmd_run_post(root, &params);
5252        } else if (!strncmp(cmd, "shell/output", strlen("shell/output"))) {
5253                if (method != OG_METHOD_POST) {
5254                        err = og_client_method_not_found(cli);
5255                        goto err_process_rest_payload;
5256                }
5257
5258                if (!root) {
5259                        syslog(LOG_ERR, "command output with no payload\n");
5260                        err = og_client_bad_request(cli);
5261                        goto err_process_rest_payload;
5262                }
5263
5264                err = og_cmd_run_get(root, &params, buf_reply);
5265        } else if (!strncmp(cmd, "session", strlen("session"))) {
5266                if (method != OG_METHOD_POST && method != OG_METHOD_GET) {
5267                        err = og_client_method_not_found(cli);
5268                        goto err_process_rest_payload;
5269                }
5270
5271                if (!root) {
5272                        syslog(LOG_ERR, "command session with no payload\n");
5273                        err = og_client_bad_request(cli);
5274                        goto err_process_rest_payload;
5275                }
5276
5277                if (method == OG_METHOD_POST)
5278                        err = og_cmd_session(root, &params);
5279                else
5280                        err = og_cmd_get_session(root, &params, buf_reply);
5281        } else if (!strncmp(cmd, "scopes", strlen("scopes"))) {
5282                if (method != OG_METHOD_GET) {
5283                        err = og_client_method_not_found(cli);
5284                        goto err_process_rest_payload;
5285                }
5286
5287                if (root) {
5288                        syslog(LOG_ERR, "command scopes with payload\n");
5289                        err = og_client_bad_request(cli);
5290                        goto err_process_rest_payload;
5291                }
5292
5293                err = og_cmd_scope_get(root, &params, buf_reply);
5294        } else if (!strncmp(cmd, "poweroff", strlen("poweroff"))) {
5295                if (method != OG_METHOD_POST) {
5296                        err = og_client_method_not_found(cli);
5297                        goto err_process_rest_payload;
5298                }
5299
5300                if (!root) {
5301                        syslog(LOG_ERR, "command poweroff with no payload\n");
5302                        err = og_client_bad_request(cli);
5303                        goto err_process_rest_payload;
5304                }
5305                err = og_cmd_poweroff(root, &params);
5306        } else if (!strncmp(cmd, "reboot", strlen("reboot"))) {
5307                if (method != OG_METHOD_POST) {
5308                        err = og_client_method_not_found(cli);
5309                        goto err_process_rest_payload;
5310                }
5311
5312                if (!root) {
5313                        syslog(LOG_ERR, "command reboot with no payload\n");
5314                        err = og_client_bad_request(cli);
5315                        goto err_process_rest_payload;
5316                }
5317                err = og_cmd_reboot(root, &params);
5318        } else if (!strncmp(cmd, "mode", strlen("mode"))) {
5319                if (method != OG_METHOD_GET && method != OG_METHOD_POST) {
5320                        err = og_client_method_not_found(cli);
5321                        goto err_process_rest_payload;
5322                }
5323
5324                if (method == OG_METHOD_POST && !root) {
5325                        syslog(LOG_ERR, "command mode with no payload\n");
5326                        err = og_client_bad_request(cli);
5327                        goto err_process_rest_payload;
5328                }
5329
5330                if (method == OG_METHOD_GET)
5331                        err = og_cmd_get_modes(root, &params, buf_reply);
5332                else if (method == OG_METHOD_POST)
5333                        err = og_cmd_post_modes(root, &params);
5334        } else if (!strncmp(cmd, "stop", strlen("stop"))) {
5335                if (method != OG_METHOD_POST) {
5336                        err = og_client_method_not_found(cli);
5337                        goto err_process_rest_payload;
5338                }
5339
5340                if (!root) {
5341                        syslog(LOG_ERR, "command stop with no payload\n");
5342                        err = og_client_bad_request(cli);
5343                        goto err_process_rest_payload;
5344                }
5345                err = og_cmd_stop(root, &params);
5346        } else if (!strncmp(cmd, "refresh", strlen("refresh"))) {
5347                if (method != OG_METHOD_POST) {
5348                        err = og_client_method_not_found(cli);
5349                        goto err_process_rest_payload;
5350                }
5351
5352                if (!root) {
5353                        syslog(LOG_ERR, "command refresh with no payload\n");
5354                        err = og_client_bad_request(cli);
5355                        goto err_process_rest_payload;
5356                }
5357                err = og_cmd_refresh(root, &params);
5358        } else if (!strncmp(cmd, "hardware", strlen("hardware"))) {
5359                if (method != OG_METHOD_GET && method != OG_METHOD_POST) {
5360                        err = og_client_method_not_found(cli);
5361                        goto err_process_rest_payload;
5362                }
5363
5364                if (!root) {
5365                        syslog(LOG_ERR, "command hardware with no payload\n");
5366                        err = og_client_bad_request(cli);
5367                        goto err_process_rest_payload;
5368                }
5369
5370                if (method == OG_METHOD_GET)
5371                        err = og_cmd_get_hardware(root, &params, buf_reply);
5372                else if (method == OG_METHOD_POST)
5373                        err = og_cmd_hardware(root, &params);
5374        } else if (!strncmp(cmd, "software", strlen("software"))) {
5375                if (method != OG_METHOD_POST && method != OG_METHOD_GET) {
5376                        err = og_client_method_not_found(cli);
5377                        goto err_process_rest_payload;
5378                }
5379
5380                if (!root) {
5381                        syslog(LOG_ERR, "command software with no payload\n");
5382                        err = og_client_bad_request(cli);
5383                        goto err_process_rest_payload;
5384                }
5385
5386                if (method == OG_METHOD_POST)
5387                        err = og_cmd_software(root, &params);
5388                else
5389                        err = og_cmd_get_software(root, &params, buf_reply);
5390        } else if (!strncmp(cmd, "images", strlen("images"))) {
5391                if (method != OG_METHOD_GET) {
5392                        err = og_client_method_not_found(cli);
5393                        goto err_process_rest_payload;
5394                }
5395
5396                if (root) {
5397                        err = og_client_bad_request(cli);
5398                        goto err_process_rest_payload;
5399                }
5400
5401                err = og_cmd_images(buf_reply);
5402        } else if (!strncmp(cmd, "image/create", strlen("image/create"))) {
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 create with no payload\n");
5410                        err = og_client_bad_request(cli);
5411                        goto err_process_rest_payload;
5412                }
5413                err = og_cmd_create_image(root, &params);
5414        } else if (!strncmp(cmd, "image/restore", strlen("image/restore"))) {
5415                if (method != OG_METHOD_POST) {
5416                        err = og_client_method_not_found(cli);
5417                        goto err_process_rest_payload;
5418                }
5419
5420                if (!root) {
5421                        syslog(LOG_ERR, "command create with no payload\n");
5422                        err = og_client_bad_request(cli);
5423                        goto err_process_rest_payload;
5424                }
5425                err = og_cmd_restore_image(root, &params);
5426        } else if (!strncmp(cmd, "image/delete", strlen("image/delete"))) {
5427                if (method != OG_METHOD_POST) {
5428                        err = og_client_method_not_found(cli);
5429                        goto err_process_rest_payload;
5430                }
5431
5432                if (!root) {
5433                        syslog(LOG_ERR,
5434                               "command image delete with no payload\n");
5435                        err = og_client_bad_request(cli);
5436                        goto err_process_rest_payload;
5437                }
5438                err = og_cmd_delete_image(root, &params);
5439        } else if (!strncmp(cmd, "setup", strlen("setup"))) {
5440                if (method != OG_METHOD_POST) {
5441                        err = og_client_method_not_found(cli);
5442                        goto err_process_rest_payload;
5443                }
5444
5445                if (!root) {
5446                        syslog(LOG_ERR, "command create with no payload\n");
5447                        err = og_client_bad_request(cli);
5448                        goto err_process_rest_payload;
5449                }
5450                err = og_cmd_setup(root, &params);
5451        } else if (!strncmp(cmd, "run/schedule", strlen("run/schedule"))) {
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, "command create with no payload\n");
5459                        err = og_client_bad_request(cli);
5460                        goto err_process_rest_payload;
5461                }
5462
5463                err = og_cmd_run_schedule(root, &params);
5464        } else if (!strncmp(cmd, "task/run", strlen("task/run"))) {
5465                if (method != OG_METHOD_POST) {
5466                        err = og_client_method_not_found(cli);
5467                        goto err_process_rest_payload;
5468                }
5469
5470                if (!root) {
5471                        syslog(LOG_ERR, "command task with no payload\n");
5472                        err = og_client_bad_request(cli);
5473                        goto err_process_rest_payload;
5474                }
5475                err = og_cmd_task_post(root, &params);
5476        } else if (!strncmp(cmd, "schedule/create",
5477                            strlen("schedule/create"))) {
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, "command task with no payload\n");
5485                        err = og_client_bad_request(cli);
5486                        goto err_process_rest_payload;
5487                }
5488                err = og_cmd_schedule_create(root, &params);
5489        } else if (!strncmp(cmd, "schedule/delete",
5490                            strlen("schedule/delete"))) {
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, "command task with no payload\n");
5498                        err = og_client_bad_request(cli);
5499                        goto err_process_rest_payload;
5500                }
5501                err = og_cmd_schedule_delete(root, &params);
5502        } else if (!strncmp(cmd, "schedule/update",
5503                            strlen("schedule/update"))) {
5504                if (method != OG_METHOD_POST) {
5505                        err = og_client_method_not_found(cli);
5506                        goto err_process_rest_payload;
5507                }
5508
5509                if (!root) {
5510                        syslog(LOG_ERR, "command task with no payload\n");
5511                        err = og_client_bad_request(cli);
5512                        goto err_process_rest_payload;
5513                }
5514                err = og_cmd_schedule_update(root, &params);
5515        } else if (!strncmp(cmd, "schedule/get",
5516                            strlen("schedule/get"))) {
5517                if (method != OG_METHOD_POST) {
5518                        err = og_client_method_not_found(cli);
5519                        goto err_process_rest_payload;
5520                }
5521
5522                err = og_cmd_schedule_get(root, &params, buf_reply);
5523        } else if (!strncmp(cmd, "oglive/list",
5524                            strlen("oglive/list"))) {
5525                if (method != OG_METHOD_GET) {
5526                        err = og_client_method_not_found(cli);
5527                        goto err_process_rest_payload;
5528                }
5529
5530                err = og_cmd_oglive_list(buf_reply);
5531        } else if (!strncmp(cmd, "center/add",
5532                            strlen("center/add"))) {
5533                if (method != OG_METHOD_POST) {
5534                        err = og_client_method_not_found(cli);
5535                        goto err_process_rest_payload;
5536                }
5537
5538                err = og_cmd_post_center_add(root, &params, buf_reply);
5539        } else if (!strncmp(cmd, "center/delete", strlen("center/delete"))) {
5540                if (method != OG_METHOD_POST) {
5541                        err = og_client_method_not_found(cli);
5542                        goto err_process_rest_payload;
5543                }
5544
5545                if (!root) {
5546                        syslog(LOG_ERR,
5547                               "command center delete with no payload\n");
5548                        err = og_client_bad_request(cli);
5549                        goto err_process_rest_payload;
5550                }
5551                err = og_cmd_post_center_delete(root, &params);
5552        } else if (!strncmp(cmd, "room/add",
5553                            strlen("room/add"))) {
5554                if (method != OG_METHOD_POST) {
5555                        err = og_client_method_not_found(cli);
5556                        goto err_process_rest_payload;
5557                }
5558
5559                if (!root) {
5560                        syslog(LOG_ERR, "command task with no payload\n");
5561                        err = og_client_bad_request(cli);
5562                        goto err_process_rest_payload;
5563                }
5564                err = og_cmd_post_room_add(root, &params);
5565        } else if (!strncmp(cmd, "room/delete", strlen("room/delete"))) {
5566                if (method != OG_METHOD_POST) {
5567                        err = og_client_method_not_found(cli);
5568                        goto err_process_rest_payload;
5569                }
5570
5571                if (!root) {
5572                        syslog(LOG_ERR,
5573                               "command room delete with no payload\n");
5574                        err = og_client_bad_request(cli);
5575                        goto err_process_rest_payload;
5576                }
5577                err = og_cmd_post_room_delete(root, &params);
5578        } else if (!strncmp(cmd, "procedure/add", strlen("procedure/add"))) {
5579                if (method != OG_METHOD_POST) {
5580                        err = og_client_method_not_found(cli);
5581                        goto err_process_rest_payload;
5582                }
5583
5584                if (!root) {
5585                        syslog(LOG_ERR,
5586                               "command procedure add with no payload\n");
5587                        err = og_client_bad_request(cli);
5588                        goto err_process_rest_payload;
5589                }
5590                err = og_cmd_post_procedure_add(root, &params);
5591        } else if (!strncmp(cmd, "procedure/update",
5592                            strlen("procedure/update"))) {
5593                if (method != OG_METHOD_POST) {
5594                        err = og_client_method_not_found(cli);
5595                        goto err_process_rest_payload;
5596                }
5597
5598                if (!root) {
5599                        syslog(LOG_ERR,
5600                               "command procedure update with no payload\n");
5601                        err = og_client_bad_request(cli);
5602                        goto err_process_rest_payload;
5603                }
5604                err = og_cmd_post_procedure_update(root, &params);
5605        } else if (!strncmp(cmd, "procedure/run", strlen("procedure/run"))) {
5606                if (method != OG_METHOD_POST) {
5607                        err = og_client_method_not_found(cli);
5608                        goto err_process_rest_payload;
5609                }
5610
5611                if (!root) {
5612                        syslog(LOG_ERR,
5613                               "command procedure run with no payload\n");
5614                        err = og_client_bad_request(cli);
5615                        goto err_process_rest_payload;
5616                }
5617                err = og_cmd_post_procedure_run(root, &params);
5618        } else if (!strncmp(cmd, "schedule/command", strlen("schedule/command"))) {
5619                if (method != OG_METHOD_POST) {
5620                        err = og_client_method_not_found(cli);
5621                        goto err_process_rest_payload;
5622                }
5623
5624                if (!root) {
5625                        syslog(LOG_ERR,
5626                               "command schedule action with no payload\n");
5627                        err = og_client_bad_request(cli);
5628                        goto err_process_rest_payload;
5629                }
5630                err = og_cmd_post_schedule_command(root, &params);
5631        } else if (!strncmp(cmd, "procedure/delete", strlen("schedule/command"))) {
5632                if (method != OG_METHOD_POST) {
5633                        err = og_client_method_not_found(cli);
5634                        goto err_process_rest_payload;
5635                }
5636
5637                if (!root) {
5638                        syslog(LOG_ERR,
5639                               "command procedure delete with no payload\n");
5640                        err = og_client_bad_request(cli);
5641                        goto err_process_rest_payload;
5642                }
5643                err = og_cmd_post_procedure_delete(root, &params);
5644        } else if (!strncmp(cmd, "task/add", strlen("task/add"))) {
5645                if (method != OG_METHOD_POST) {
5646                        err = og_client_method_not_found(cli);
5647                        goto err_process_rest_payload;
5648                }
5649
5650                if (!root) {
5651                        syslog(LOG_ERR,
5652                               "command task add with no payload\n");
5653                        err = og_client_bad_request(cli);
5654                        goto err_process_rest_payload;
5655                }
5656                err = og_cmd_post_task_add(root, &params);
5657        } else {
5658                syslog(LOG_ERR, "unknown command: %.32s ...\n", cmd);
5659                err = og_client_not_found(cli);
5660        }
5661
5662        json_decref(root);
5663
5664        if (err < 0)
5665                return og_client_bad_request(cli);
5666
5667        return og_client_ok(cli, buf_reply);
5668
5669err_process_rest_payload:
5670        json_decref(root);
5671
5672        return err;
5673}
Note: See TracBrowser for help on using the repository browser.