source: ogServer-Git/src/rest.c @ 1fdb7e6

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

#915 Add commands and procedures to procedure creation

Adds the possibility to create a procedure with commands and other
procedures integrated as steps.

Note: "steps" parameter is optional and "steps" array object order
defines execution order.

Request:
POST /procedure/add
{

"center": "1",
"name": "procedure",
"description": "My procedure",
"steps": [

{

"command": "wol",
"params": { "type": "broadcast" }

},
{

"procedure": 22

},
{

"command": "poweroff",
"params": {}

}

]

}

Response:
200 OK

This commit also updates unit tests for /procedure/add POST method to
include steps.

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