source: ogServer-Git/src/rest.c @ 3b4aa72

Last change on this file since 3b4aa72 was 3b4aa72, checked in by Javier Sánchez Parra <jsanchez@…>, 3 years ago

#915 Add GET /stats REST request

This request returns certain statistics on memory and swap usage, as
well as the uptime.

The below structure gives the sizes of the memory and swap fields in
bytes.

Request: GET /stats
NO BODY

Response: 200 OK
{

"time": {

"now": 1647262765, /* Seconds since 1970 */
"boot": 2151909 /* Seconds since boot */

},
"memory": {

"size": 4104679424, /* Total usable main memory size */
"free": 322174976 /* Available memory size */

},
"swap": {

"size": 2147479552, /* Total swap space size */
"free": 2122563584 /* Swap space still available */

}

}

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