source: ogServer-Git/src/rest.c @ f3422f6

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

#915 add seconds since ogserver has been launched

Extend GET /stats to show the number of seconds since the ogserver started.

{

"time": {

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

},
[...]

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