source: ogServer-Git/src/rest.c

Last change on this file was 2213d00, checked in by Javier Sánchez Parra <jsanchez@…>, 22 months ago

#915 List all database images.

ogServer "GET /images" list images that exist simultaneously in database
and in disk (/opt/opengnsys/images).

With this patch, ogServer list all images in database, exist or not in
disk. If an image exists in disk, it retrieves more information about
them.

This change is useful for environments where images are in different
machines/repositories.

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