source: ogServer-Git/src/rest.c @ 261d490

Last change on this file since 261d490 was 261d490, checked in by OpenGnSys Support Team <soporte-og@…>, 4 years ago

#1052 Populate session column when adding actions

If the scope of a command, procedure or task is related to a group of
computers then actions associated with that schedule can share the same
session value.

og_dbi_add_action was not initializing session value, as it is only used
for visualization purposes in the legacy web interface.

This patch enables og_dbi_add_action to populate session column by
assigning it the id value of the first action related to the scope.

Example: Power off command for a room scope of 4 clients will result in
4 actions, a power off for each client. The first action id will determine
the session value for the rest.

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