source: ogServer-Git/src/rest.c @ 5cf2de7

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

#915 Add POST /repository/delete

This method deletes a repository from the database.

Request:
POST /repository/delete
{

"id": "10"

}

Response:
200 OK

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