source: ogServer-Git/src/rest.c @ 64bbc0c

Last change on this file since 64bbc0c was b6b1040, checked in by Jose M. Guisado <jguisado@…>, 3 years ago

#1065 client: add support for ogclient win state

ogClient can be run in windows mode, enabling connection with ogServer
when running on a Windows machine.

Don't expect the same payload in windows mode as a in live or virtual.
Client in windows mode does not send partition setup information, only
the status/state. (same case for linux mode)

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