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

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

Add REST POST /room/delete method

This method deletes a room (lab) from the DB and deletes on cascade
computers and computers partitions.

Note: if the room id do not exists in the database, ogserver still
tries to delete it and replies with 200 OK.

Request:
POST /room/delete
{

"id": "1"

}

Response:
200 OK

  • Property mode set to 100644
File size: 119.7 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 <ev.h>
19#include <syslog.h>
20#include <sys/ioctl.h>
21#include <ifaddrs.h>
22#include <sys/types.h>
23#include <sys/stat.h>
24#include <fcntl.h>
25#include <jansson.h>
26#include <dirent.h>
27#include <time.h>
28#include <stdlib.h>
29#include <unistd.h>
30#include <sys/wait.h>
31#include <sys/statvfs.h>
32
33struct ev_loop *og_loop;
34
35#define OG_REST_PARAM_ADDR                      (1UL << 0)
36#define OG_REST_PARAM_MAC                       (1UL << 1)
37#define OG_REST_PARAM_WOL_TYPE                  (1UL << 2)
38#define OG_REST_PARAM_RUN_CMD                   (1UL << 3)
39#define OG_REST_PARAM_DISK                      (1UL << 4)
40#define OG_REST_PARAM_PARTITION                 (1UL << 5)
41#define OG_REST_PARAM_REPO                      (1UL << 6)
42#define OG_REST_PARAM_NAME                      (1UL << 7)
43#define OG_REST_PARAM_ID                        (1UL << 8)
44#define OG_REST_PARAM_CODE                      (1UL << 9)
45#define OG_REST_PARAM_TYPE                      (1UL << 10)
46#define OG_REST_PARAM_PROFILE                   (1UL << 11)
47#define OG_REST_PARAM_CACHE                     (1UL << 12)
48#define OG_REST_PARAM_CACHE_SIZE                (1UL << 13)
49#define OG_REST_PARAM_PART_0                    (1UL << 14)
50#define OG_REST_PARAM_PART_1                    (1UL << 15)
51#define OG_REST_PARAM_PART_2                    (1UL << 16)
52#define OG_REST_PARAM_PART_3                    (1UL << 17)
53#define OG_REST_PARAM_SYNC_SYNC                 (1UL << 18)
54#define OG_REST_PARAM_SYNC_DIFF                 (1UL << 19)
55#define OG_REST_PARAM_SYNC_REMOVE               (1UL << 20)
56#define OG_REST_PARAM_SYNC_COMPRESS             (1UL << 21)
57#define OG_REST_PARAM_SYNC_CLEANUP              (1UL << 22)
58#define OG_REST_PARAM_SYNC_CACHE                (1UL << 23)
59#define OG_REST_PARAM_SYNC_CLEANUP_CACHE        (1UL << 24)
60#define OG_REST_PARAM_SYNC_REMOVE_DST           (1UL << 25)
61#define OG_REST_PARAM_SYNC_DIFF_ID              (1UL << 26)
62#define OG_REST_PARAM_SYNC_DIFF_NAME            (1UL << 27)
63#define OG_REST_PARAM_SYNC_PATH                 (1UL << 28)
64#define OG_REST_PARAM_SYNC_METHOD               (1UL << 29)
65#define OG_REST_PARAM_ECHO                      (1UL << 30)
66#define OG_REST_PARAM_TASK                      (1UL << 31)
67#define OG_REST_PARAM_TIME_YEARS                (1UL << 32)
68#define OG_REST_PARAM_TIME_MONTHS               (1UL << 33)
69#define OG_REST_PARAM_TIME_WEEKS                (1UL << 34)
70#define OG_REST_PARAM_TIME_WEEK_DAYS            (1UL << 35)
71#define OG_REST_PARAM_TIME_DAYS                 (1UL << 36)
72#define OG_REST_PARAM_TIME_HOURS                (1UL << 37)
73#define OG_REST_PARAM_TIME_AM_PM                (1UL << 38)
74#define OG_REST_PARAM_TIME_MINUTES              (1UL << 39)
75#define OG_REST_PARAM_NETMASK                   (1UL << 40)
76#define OG_REST_PARAM_SCOPE                     (1UL << 41)
77#define OG_REST_PARAM_MODE                      (1UL << 42)
78#define OG_REST_PARAM_CENTER                    (1UL << 43)
79
80static LIST_HEAD(client_list);
81static LIST_HEAD(client_wol_list);
82
83void og_client_add(struct og_client *cli)
84{
85        list_add(&cli->list, &client_list);
86}
87
88static struct og_client *og_client_find(const char *ip)
89{
90        struct og_client *client;
91        struct in_addr addr;
92        int res;
93
94        res = inet_aton(ip, &addr);
95        if (!res) {
96                syslog(LOG_ERR, "Invalid IP string: %s\n", ip);
97                return NULL;
98        }
99
100        list_for_each_entry(client, &client_list, list) {
101                if (client->addr.sin_addr.s_addr == addr.s_addr && client->agent) {
102                        return client;
103                }
104        }
105
106        return NULL;
107}
108
109static const char *og_client_status(const struct og_client *cli)
110{
111        switch (cli->last_cmd) {
112        case OG_CMD_UNSPEC:
113        case OG_CMD_PROBE:
114                break;
115        default:
116                return "BSY";
117        }
118
119        switch (cli->status) {
120        case OG_CLIENT_STATUS_BUSY:
121                return "BSY";
122        case OG_CLIENT_STATUS_OGLIVE:
123                return "OPG";
124        case OG_CLIENT_STATUS_VIRTUAL:
125                return "VDI";
126        default:
127                return "OFF";
128        }
129}
130
131static bool og_msg_params_validate(const struct og_msg_params *params,
132                                   const uint64_t flags)
133{
134        return (params->flags & flags) == flags;
135}
136
137static bool og_flags_validate(const uint64_t flags,
138                              const uint64_t required_flags)
139{
140        return (flags & required_flags) == required_flags;
141}
142
143static int og_json_parse_clients(json_t *element, struct og_msg_params *params)
144{
145        unsigned int i;
146        json_t *k;
147
148        if (json_typeof(element) != JSON_ARRAY)
149                return -1;
150
151        for (i = 0; i < json_array_size(element); i++) {
152                k = json_array_get(element, i);
153                if (json_typeof(k) != JSON_STRING)
154                        return -1;
155
156                params->ips_array[params->ips_array_len++] =
157                        json_string_value(k);
158
159                params->flags |= OG_REST_PARAM_ADDR;
160        }
161
162        return 0;
163}
164
165static int og_json_parse_partition_setup(json_t *element,
166                                         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
2044static int og_cmd_create_image(json_t *element, struct og_msg_params *params)
2045{
2046        char new_image_id[OG_DB_INT_MAXLEN + 1];
2047        struct og_image image = {};
2048        json_t *value, *clients;
2049        struct og_dbi *dbi;
2050        const char *key;
2051        int err = 0;
2052
2053        if (json_typeof(element) != JSON_OBJECT)
2054                return -1;
2055
2056        json_object_foreach(element, key, value) {
2057                if (!strcmp(key, "disk")) {
2058                        err = og_json_parse_string(value, &params->disk);
2059                        params->flags |= OG_REST_PARAM_DISK;
2060                } else if (!strcmp(key, "partition")) {
2061                        err = og_json_parse_string(value, &params->partition);
2062                        params->flags |= OG_REST_PARAM_PARTITION;
2063                } else if (!strcmp(key, "name")) {
2064                        err = og_json_parse_string(value, &params->name);
2065                        params->flags |= OG_REST_PARAM_NAME;
2066                } else if (!strcmp(key, "repository")) {
2067                        err = og_json_parse_string(value, &params->repository);
2068                        params->flags |= OG_REST_PARAM_REPO;
2069                } else if (!strcmp(key, "clients")) {
2070                        err = og_json_parse_clients(value, params);
2071                } else if (!strcmp(key, "id")) {
2072                        err = og_json_parse_string(value, &params->id);
2073                        params->flags |= OG_REST_PARAM_ID;
2074                } else if (!strcmp(key, "code")) {
2075                        err = og_json_parse_string(value, &params->code);
2076                        params->flags |= OG_REST_PARAM_CODE;
2077                } else if (!strcmp(key, "description")) {
2078                        err = og_json_parse_string_copy(value,
2079                                                        image.description,
2080                                                        sizeof(image.description));
2081                } else if (!strcmp(key, "group_id")) {
2082                        err = og_json_parse_uint64(value, &image.group_id);
2083                } else if (!strcmp(key, "center_id")) {
2084                        err = og_json_parse_uint64(value, &image.center_id);
2085                }
2086
2087                if (err < 0)
2088                        return err;
2089        }
2090
2091        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
2092                                            OG_REST_PARAM_DISK |
2093                                            OG_REST_PARAM_PARTITION |
2094                                            OG_REST_PARAM_CODE |
2095                                            OG_REST_PARAM_ID |
2096                                            OG_REST_PARAM_NAME |
2097                                            OG_REST_PARAM_REPO))
2098                return -1;
2099
2100        /* If there is a description, this means the image is not in the DB. */
2101        if (image.description[0]) {
2102                snprintf(image.name, sizeof(image.name), "%s", params->name);
2103
2104                dbi = og_dbi_open(&ogconfig.db);
2105                if (!dbi) {
2106                        syslog(LOG_ERR,
2107                               "cannot open connection database (%s:%d)\n",
2108                               __func__, __LINE__);
2109                        return -1;
2110                }
2111
2112                err = og_dbi_add_image(dbi, &image);
2113
2114                og_dbi_close(dbi);
2115                if (err < 0)
2116                        return err;
2117
2118                snprintf(new_image_id, sizeof(new_image_id), "%u", err);
2119                params->id = new_image_id;
2120        }
2121
2122        clients = json_copy(element);
2123        json_object_del(clients, "clients");
2124
2125        return og_send_request(OG_METHOD_POST, OG_CMD_IMAGE_CREATE, params,
2126                               clients);
2127}
2128
2129static int og_cmd_restore_image(json_t *element, struct og_msg_params *params)
2130{
2131        json_t *clients, *value;
2132        const char *key;
2133        int err = 0;
2134
2135        if (json_typeof(element) != JSON_OBJECT)
2136                return -1;
2137
2138        json_object_foreach(element, key, value) {
2139                if (!strcmp(key, "disk")) {
2140                        err = og_json_parse_string(value, &params->disk);
2141                        params->flags |= OG_REST_PARAM_DISK;
2142                } else if (!strcmp(key, "partition")) {
2143                        err = og_json_parse_string(value, &params->partition);
2144                        params->flags |= OG_REST_PARAM_PARTITION;
2145                } else if (!strcmp(key, "name")) {
2146                        err = og_json_parse_string(value, &params->name);
2147                        params->flags |= OG_REST_PARAM_NAME;
2148                } else if (!strcmp(key, "repository")) {
2149                        err = og_json_parse_string(value, &params->repository);
2150                        params->flags |= OG_REST_PARAM_REPO;
2151                } else if (!strcmp(key, "clients")) {
2152                        err = og_json_parse_clients(value, params);
2153                } else if (!strcmp(key, "type")) {
2154                        err = og_json_parse_string(value, &params->type);
2155                        params->flags |= OG_REST_PARAM_TYPE;
2156                } else if (!strcmp(key, "profile")) {
2157                        err = og_json_parse_string(value, &params->profile);
2158                        params->flags |= OG_REST_PARAM_PROFILE;
2159                } else if (!strcmp(key, "id")) {
2160                        err = og_json_parse_string(value, &params->id);
2161                        params->flags |= OG_REST_PARAM_ID;
2162                }
2163
2164                if (err < 0)
2165                        return err;
2166        }
2167
2168        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
2169                                            OG_REST_PARAM_DISK |
2170                                            OG_REST_PARAM_PARTITION |
2171                                            OG_REST_PARAM_NAME |
2172                                            OG_REST_PARAM_REPO |
2173                                            OG_REST_PARAM_TYPE |
2174                                            OG_REST_PARAM_PROFILE |
2175                                            OG_REST_PARAM_ID))
2176                return -1;
2177
2178        clients = json_copy(element);
2179        json_object_del(clients, "clients");
2180
2181        return og_send_request(OG_METHOD_POST, OG_CMD_IMAGE_RESTORE, params,
2182                               clients);
2183}
2184
2185static int og_cmd_setup(json_t *element, struct og_msg_params *params)
2186{
2187        json_t *value, *clients;
2188        const char *key;
2189        int err = 0;
2190
2191        if (json_typeof(element) != JSON_OBJECT)
2192                return -1;
2193
2194        json_object_foreach(element, key, value) {
2195                if (!strcmp(key, "clients")) {
2196                        err = og_json_parse_clients(value, params);
2197                } else if (!strcmp(key, "type")) {
2198                        err = og_json_parse_string(value, &params->type);
2199                        params->flags |= OG_REST_PARAM_TYPE;
2200                } else if (!strcmp(key, "disk")) {
2201                        err = og_json_parse_string(value, &params->disk);
2202                        params->flags |= OG_REST_PARAM_DISK;
2203                } else if (!strcmp(key, "cache")) {
2204                        err = og_json_parse_string(value, &params->cache);
2205                        params->flags |= OG_REST_PARAM_CACHE;
2206                } else if (!strcmp(key, "cache_size")) {
2207                        err = og_json_parse_string(value, &params->cache_size);
2208                        params->flags |= OG_REST_PARAM_CACHE_SIZE;
2209                } else if (!strcmp(key, "partition_setup")) {
2210                        err = og_json_parse_partition_setup(value, params);
2211                }
2212
2213                if (err < 0)
2214                        return err;
2215        }
2216
2217        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
2218                                            OG_REST_PARAM_TYPE |
2219                                            OG_REST_PARAM_DISK |
2220                                            OG_REST_PARAM_CACHE |
2221                                            OG_REST_PARAM_CACHE_SIZE |
2222                                            OG_REST_PARAM_PART_0 |
2223                                            OG_REST_PARAM_PART_1 |
2224                                            OG_REST_PARAM_PART_2 |
2225                                            OG_REST_PARAM_PART_3))
2226                return -1;
2227
2228        clients = json_copy(element);
2229        json_object_del(clients, "clients");
2230
2231        return og_send_request(OG_METHOD_POST, OG_CMD_SETUP, params, clients);
2232}
2233
2234static int og_cmd_run_schedule(json_t *element, struct og_msg_params *params)
2235{
2236        const char *key;
2237        json_t *value;
2238        int err = 0;
2239
2240        json_object_foreach(element, key, value) {
2241                if (!strcmp(key, "clients"))
2242                        err = og_json_parse_clients(value, params);
2243
2244                if (err < 0)
2245                        return err;
2246        }
2247
2248        if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
2249                return -1;
2250
2251        return og_send_request(OG_METHOD_GET, OG_CMD_RUN_SCHEDULE, params,
2252                               NULL);
2253}
2254
2255static LIST_HEAD(cmd_list);
2256
2257const struct og_cmd *og_cmd_find(const char *client_ip)
2258{
2259        struct og_cmd *cmd, *next;
2260
2261        list_for_each_entry_safe(cmd, next, &cmd_list, list) {
2262                if (strcmp(cmd->ip, client_ip))
2263                        continue;
2264
2265                list_del(&cmd->list);
2266                return cmd;
2267        }
2268
2269        return NULL;
2270}
2271
2272void og_cmd_free(const struct og_cmd *cmd)
2273{
2274        struct og_msg_params *params = (struct og_msg_params *)&cmd->params;
2275        int i;
2276
2277        for (i = 0; i < params->ips_array_len; i++) {
2278                free((void *)params->netmask_array[i]);
2279                free((void *)params->ips_array[i]);
2280                free((void *)params->mac_array[i]);
2281        }
2282        free((void *)params->wol_type);
2283
2284        if (cmd->json)
2285                json_decref(cmd->json);
2286
2287        free((void *)cmd->ip);
2288        free((void *)cmd->mac);
2289        free((void *)cmd);
2290}
2291
2292static void og_cmd_init(struct og_cmd *cmd, enum og_rest_method method,
2293                        enum og_cmd_type type, json_t *root)
2294{
2295        cmd->type = type;
2296        cmd->method = method;
2297        cmd->params.ips_array[0] = strdup(cmd->ip);
2298        cmd->params.ips_array_len = 1;
2299        cmd->json = root;
2300}
2301
2302static int og_cmd_legacy_wol(const char *input, struct og_cmd *cmd)
2303{
2304        char wol_type[2] = {};
2305        const char *msglog;
2306        struct og_dbi *dbi;
2307        dbi_result result;
2308
2309        if (sscanf(input, "mar=%s", wol_type) != 1) {
2310                syslog(LOG_ERR, "malformed database legacy input\n");
2311                return -1;
2312        }
2313
2314        dbi = og_dbi_open(&ogconfig.db);
2315        if (!dbi) {
2316                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
2317                       __func__, __LINE__);
2318                return -1;
2319        }
2320
2321        result = dbi_conn_queryf(dbi->conn,
2322                                 "SELECT aulas.netmask "
2323                                 "FROM   ordenadores "
2324                                 "INNER JOIN aulas "
2325                                         "ON ordenadores.idaula = aulas.idaula "
2326                                 "WHERE  ordenadores.ip = '%s'",
2327                                 cmd->ip);
2328        if (!result) {
2329                dbi_conn_error(dbi->conn, &msglog);
2330                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2331                       __func__, __LINE__, msglog);
2332                og_dbi_close(dbi);
2333                return -1;
2334        }
2335        dbi_result_next_row(result);
2336
2337        og_cmd_init(cmd, OG_METHOD_NO_HTTP, OG_CMD_WOL, NULL);
2338        cmd->params.netmask_array[0] = dbi_result_get_string_copy(result,
2339                                                                  "netmask");
2340        cmd->params.mac_array[0] = strdup(cmd->mac);
2341        cmd->params.wol_type = strdup(wol_type);
2342
2343        dbi_result_free(result);
2344        og_dbi_close(dbi);
2345
2346        return 0;
2347}
2348
2349static int og_cmd_legacy_shell_run(const char *input, struct og_cmd *cmd)
2350{
2351        json_t *root, *script, *echo;
2352
2353        script = json_string(input + 4);
2354        echo = json_boolean(false);
2355
2356        root = json_object();
2357        if (!root)
2358                return -1;
2359        json_object_set_new(root, "run", script);
2360        json_object_set_new(root, "echo", echo);
2361
2362        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_SHELL_RUN, root);
2363
2364        return 0;
2365}
2366
2367static int og_cmd_legacy_session(const char *input, struct og_cmd *cmd)
2368{
2369        char part_str[OG_DB_SMALLINT_MAXLEN + 1];
2370        char disk_str[OG_DB_SMALLINT_MAXLEN + 1];
2371        json_t *root, *disk, *partition;
2372
2373        if (sscanf(input, "dsk=%s\rpar=%s\r", disk_str, part_str) != 2)
2374                return -1;
2375        partition = json_string(part_str);
2376        disk = json_string(disk_str);
2377
2378        root = json_object();
2379        if (!root)
2380                return -1;
2381        json_object_set_new(root, "partition", partition);
2382        json_object_set_new(root, "disk", disk);
2383
2384        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_SESSION, root);
2385
2386        return 0;
2387}
2388
2389static int og_cmd_legacy_poweroff(const char *input, struct og_cmd *cmd)
2390{
2391        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_POWEROFF, NULL);
2392
2393        return 0;
2394}
2395
2396static int og_cmd_legacy_refresh(const char *input, struct og_cmd *cmd)
2397{
2398        og_cmd_init(cmd, OG_METHOD_GET, OG_CMD_REFRESH, NULL);
2399
2400        return 0;
2401}
2402
2403static int og_cmd_legacy_reboot(const char *input, struct og_cmd *cmd)
2404{
2405        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_REBOOT, NULL);
2406
2407        return 0;
2408}
2409
2410static int og_cmd_legacy_stop(const char *input, struct og_cmd *cmd)
2411{
2412        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_STOP, NULL);
2413
2414        return 0;
2415}
2416
2417static int og_cmd_legacy_hardware(const char *input, struct og_cmd *cmd)
2418{
2419        og_cmd_init(cmd, OG_METHOD_GET, OG_CMD_HARDWARE, NULL);
2420
2421        return 0;
2422}
2423
2424static int og_cmd_legacy_software(const char *input, struct og_cmd *cmd)
2425{
2426        char part_str[OG_DB_SMALLINT_MAXLEN + 1];
2427        char disk_str[OG_DB_SMALLINT_MAXLEN + 1];
2428        json_t *root, *disk, *partition;
2429
2430        if (sscanf(input, "dsk=%s\rpar=%s\r", disk_str, part_str) != 2)
2431                return -1;
2432        partition = json_string(part_str);
2433        disk = json_string(disk_str);
2434
2435        root = json_object();
2436        if (!root)
2437                return -1;
2438        json_object_set_new(root, "partition", partition);
2439        json_object_set_new(root, "disk", disk);
2440
2441        og_cmd_init(cmd, OG_METHOD_GET, OG_CMD_SOFTWARE, root);
2442
2443        return 0;
2444}
2445
2446static int og_cmd_legacy_image_create(const char *input, struct og_cmd *cmd)
2447{
2448        json_t *root, *disk, *partition, *code, *image_id, *name, *repo;
2449        struct og_image_legacy img = {};
2450
2451        if (sscanf(input, "dsk=%s\rpar=%s\rcpt=%s\ridi=%s\rnci=%s\ripr=%s\r",
2452                   img.disk, img.part, img.code, img.image_id, img.name,
2453                   img.repo) != 6)
2454                return -1;
2455        image_id = json_string(img.image_id);
2456        partition = json_string(img.part);
2457        code = json_string(img.code);
2458        name = json_string(img.name);
2459        repo = json_string(img.repo);
2460        disk = json_string(img.disk);
2461
2462        root = json_object();
2463        if (!root)
2464                return -1;
2465        json_object_set_new(root, "partition", partition);
2466        json_object_set_new(root, "repository", repo);
2467        json_object_set_new(root, "id", image_id);
2468        json_object_set_new(root, "code", code);
2469        json_object_set_new(root, "name", name);
2470        json_object_set_new(root, "disk", disk);
2471
2472        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_IMAGE_CREATE, root);
2473
2474        return 0;
2475}
2476
2477#define OG_DB_RESTORE_TYPE_MAXLEN       64
2478
2479static int og_cmd_legacy_image_restore(const char *input, struct og_cmd *cmd)
2480{
2481        json_t *root, *disk, *partition, *image_id, *name, *repo;
2482        char restore_type_str[OG_DB_RESTORE_TYPE_MAXLEN + 1] = {};
2483        char software_id_str[OG_DB_INT_MAXLEN + 1] = {};
2484        json_t *software_id, *restore_type;
2485        struct og_image_legacy img = {};
2486
2487        if (sscanf(input,
2488                   "dsk=%s\rpar=%s\ridi=%s\rnci=%s\r"
2489                   "ipr=%s\rifs=%s\rptc=%[^\r]\r",
2490                   img.disk, img.part, img.image_id, img.name, img.repo,
2491                   software_id_str, restore_type_str) != 7)
2492                return -1;
2493
2494        restore_type = json_string(restore_type_str);
2495        software_id = json_string(software_id_str);
2496        image_id = json_string(img.image_id);
2497        partition = json_string(img.part);
2498        name = json_string(img.name);
2499        repo = json_string(img.repo);
2500        disk = json_string(img.disk);
2501
2502        root = json_object();
2503        if (!root)
2504                return -1;
2505        json_object_set_new(root, "profile", software_id);
2506        json_object_set_new(root, "partition", partition);
2507        json_object_set_new(root, "type", restore_type);
2508        json_object_set_new(root, "repository", repo);
2509        json_object_set_new(root, "id", image_id);
2510        json_object_set_new(root, "name", name);
2511        json_object_set_new(root, "disk", disk);
2512
2513        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_IMAGE_RESTORE, root);
2514
2515        return 0;
2516}
2517
2518#define OG_PARTITION_TABLE_TYPE_MAXLEN 5
2519
2520static int og_cmd_legacy_setup(const char *input, struct og_cmd *cmd)
2521{
2522        json_t *root, *disk, *cache, *cache_size, *partition_setup, *object;
2523        char part_table_type_str[OG_PARTITION_TABLE_TYPE_MAXLEN + 1];
2524        struct og_legacy_partition part_cfg[OG_PARTITION_MAX] = {};
2525        json_t *part_table_type, *part, *code, *fs, *size, *format;
2526        char cache_size_str [OG_DB_INT_MAXLEN + 1];
2527        char disk_str [OG_DB_SMALLINT_MAXLEN + 1];
2528        unsigned int partition_len = 0;
2529        const char *in_ptr;
2530        char cache_str[2];
2531
2532        if (sscanf(input, "ttp=%s\rdsk=%s\rcfg=dis=%*[^*]*che=%[^*]*tch=%[^!]!",
2533                   part_table_type_str, disk_str, cache_str, cache_size_str) != 4)
2534                return -1;
2535
2536        in_ptr = strstr(input, "!") + 1;
2537        while (strlen(in_ptr) > 0) {
2538                if(sscanf(in_ptr,
2539                          "par=%[^*]*cpt=%[^*]*sfi=%[^*]*tam=%[^*]*ope=%[^%%]%%",
2540                          part_cfg[partition_len].partition,
2541                          part_cfg[partition_len].code,
2542                          part_cfg[partition_len].filesystem,
2543                          part_cfg[partition_len].size,
2544                          part_cfg[partition_len].format) != 5)
2545                        return -1;
2546                in_ptr = strstr(in_ptr, "%") + 1;
2547                partition_len++;
2548        }
2549
2550        root = json_object();
2551        if (!root)
2552                return -1;
2553
2554        part_table_type = json_string(part_table_type_str);
2555        cache_size = json_string(cache_size_str);
2556        cache = json_string(cache_str);
2557        partition_setup = json_array();
2558        disk = json_string(disk_str);
2559
2560        for (unsigned int i = 0; i < partition_len; ++i) {
2561                object = json_object();
2562                if (!object) {
2563                        json_decref(root);
2564                        return -1;
2565                }
2566
2567                part = json_string(part_cfg[i].partition);
2568                fs = json_string(part_cfg[i].filesystem);
2569                format = json_string(part_cfg[i].format);
2570                code = json_string(part_cfg[i].code);
2571                size = json_string(part_cfg[i].size);
2572
2573                json_object_set_new(object, "partition", part);
2574                json_object_set_new(object, "filesystem", fs);
2575                json_object_set_new(object, "format", format);
2576                json_object_set_new(object, "code", code);
2577                json_object_set_new(object, "size", size);
2578
2579                json_array_append_new(partition_setup, object);
2580        }
2581
2582        json_object_set_new(root, "partition_setup", partition_setup);
2583        json_object_set_new(root, "cache_size", cache_size);
2584        json_object_set_new(root, "type", part_table_type);
2585        json_object_set_new(root, "cache", cache);
2586        json_object_set_new(root, "disk", disk);
2587
2588        og_cmd_init(cmd, OG_METHOD_POST, OG_CMD_SETUP, root);
2589
2590        return 0;
2591}
2592
2593static int og_cmd_legacy_run_schedule(const char *input, struct og_cmd *cmd)
2594{
2595        og_cmd_init(cmd, OG_METHOD_GET, OG_CMD_RUN_SCHEDULE, NULL);
2596
2597        return 0;
2598}
2599
2600static int og_cmd_legacy(const char *input, struct og_cmd *cmd)
2601{
2602        char legacy_cmd[32] = {};
2603        int err = -1;
2604
2605        if (sscanf(input, "nfn=%31s\r", legacy_cmd) != 1) {
2606                syslog(LOG_ERR, "malformed database legacy input\n");
2607                return -1;
2608        }
2609        input = strchr(input, '\r') + 1;
2610
2611        if (!strcmp(legacy_cmd, "Arrancar")) {
2612                err = og_cmd_legacy_wol(input, cmd);
2613        } else if (!strcmp(legacy_cmd, "EjecutarScript")) {
2614                err = og_cmd_legacy_shell_run(input, cmd);
2615        } else if (!strcmp(legacy_cmd, "IniciarSesion")) {
2616                err = og_cmd_legacy_session(input, cmd);
2617        } else if (!strcmp(legacy_cmd, "Apagar")) {
2618                err = og_cmd_legacy_poweroff(input, cmd);
2619        } else if (!strcmp(legacy_cmd, "Actualizar")) {
2620                err = og_cmd_legacy_refresh(input, cmd);
2621        } else if (!strcmp(legacy_cmd, "Reiniciar")) {
2622                err = og_cmd_legacy_reboot(input, cmd);
2623        } else if (!strcmp(legacy_cmd, "Purgar")) {
2624                err = og_cmd_legacy_stop(input, cmd);
2625        } else if (!strcmp(legacy_cmd, "InventarioHardware")) {
2626                err = og_cmd_legacy_hardware(input, cmd);
2627        } else if (!strcmp(legacy_cmd, "InventarioSoftware")) {
2628                err = og_cmd_legacy_software(input, cmd);
2629        } else if (!strcmp(legacy_cmd, "CrearImagen")) {
2630                err = og_cmd_legacy_image_create(input, cmd);
2631        } else if (!strcmp(legacy_cmd, "RestaurarImagen")) {
2632                err = og_cmd_legacy_image_restore(input, cmd);
2633        } else if (!strcmp(legacy_cmd, "Configurar")) {
2634                err = og_cmd_legacy_setup(input, cmd);
2635        } else if (!strcmp(legacy_cmd, "EjecutaComandosPendientes") ||
2636                   !strcmp(legacy_cmd, "Actualizar")) {
2637                err = og_cmd_legacy_run_schedule(input, cmd);
2638        }
2639
2640        return err;
2641}
2642
2643static int og_dbi_add_action(const struct og_dbi *dbi, const struct og_task *task,
2644                             struct og_cmd *cmd)
2645{
2646        char start_date_string[24];
2647        struct tm *start_date;
2648        const char *msglog;
2649        dbi_result result;
2650        time_t now;
2651
2652        time(&now);
2653        start_date = localtime(&now);
2654
2655        sprintf(start_date_string, "%hu/%hhu/%hhu %hhu:%hhu:%hhu",
2656                start_date->tm_year + 1900, start_date->tm_mon + 1,
2657                start_date->tm_mday, start_date->tm_hour, start_date->tm_min,
2658                start_date->tm_sec);
2659        result = dbi_conn_queryf(dbi->conn,
2660                                "INSERT INTO acciones (idordenador, "
2661                                "tipoaccion, idtipoaccion, descriaccion, ip, "
2662                                "sesion, idcomando, parametros, fechahorareg, "
2663                                "estado, resultado, ambito, idambito, "
2664                                "restrambito, idprocedimiento, idcentro, "
2665                                "idprogramacion) "
2666                                "VALUES (%d, %d, %d, '%s', '%s', %d, %d, '%s', "
2667                                "'%s', %d, %d, %d, %d, '%s', %d, %d, %d)",
2668                                cmd->client_id, EJECUCION_TAREA, task->task_id,
2669                                "", cmd->ip, 0, task->command_id,
2670                                task->params, start_date_string,
2671                                ACCION_INICIADA, ACCION_SINRESULTADO,
2672                                task->type_scope, task->scope, "",
2673                                task->procedure_id, task->center_id,
2674                                task->schedule_id);
2675        if (!result) {
2676                dbi_conn_error(dbi->conn, &msglog);
2677                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2678                       __func__, __LINE__, msglog);
2679                return -1;
2680        }
2681        cmd->id = dbi_conn_sequence_last(dbi->conn, NULL);
2682        dbi_result_free(result);
2683
2684        return 0;
2685}
2686
2687static int og_queue_task_command(struct og_dbi *dbi, const struct og_task *task,
2688                                 char *query)
2689{
2690        struct og_cmd *cmd;
2691        const char *msglog;
2692        dbi_result result;
2693
2694        result = dbi_conn_queryf(dbi->conn, query);
2695        if (!result) {
2696                dbi_conn_error(dbi->conn, &msglog);
2697                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2698                       __func__, __LINE__, msglog);
2699                return -1;
2700        }
2701
2702        while (dbi_result_next_row(result)) {
2703                cmd = (struct og_cmd *)calloc(1, sizeof(struct og_cmd));
2704                if (!cmd) {
2705                        dbi_result_free(result);
2706                        return -1;
2707                }
2708
2709                cmd->client_id  = dbi_result_get_uint(result, "idordenador");
2710                cmd->ip         = strdup(dbi_result_get_string(result, "ip"));
2711                cmd->mac        = strdup(dbi_result_get_string(result, "mac"));
2712
2713                og_cmd_legacy(task->params, cmd);
2714
2715                if (task->procedure_id) {
2716                        if (og_dbi_add_action(dbi, task, cmd)) {
2717                                dbi_result_free(result);
2718                                return -1;
2719                        }
2720                } else {
2721                        cmd->id = task->task_id;
2722                }
2723
2724                list_add_tail(&cmd->list, &cmd_list);
2725        }
2726
2727        dbi_result_free(result);
2728
2729        return 0;
2730}
2731
2732static int og_queue_task_group_clients(struct og_dbi *dbi, struct og_task *task,
2733                                       char *query)
2734{
2735
2736        const char *msglog;
2737        dbi_result result;
2738
2739        result = dbi_conn_queryf(dbi->conn, query);
2740        if (!result) {
2741                dbi_conn_error(dbi->conn, &msglog);
2742                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2743                       __func__, __LINE__, msglog);
2744                return -1;
2745        }
2746
2747        while (dbi_result_next_row(result)) {
2748                uint32_t group_id = dbi_result_get_uint(result, "idgrupo");
2749
2750                sprintf(query, "SELECT idgrupo FROM gruposordenadores "
2751                                "WHERE grupoid=%d", group_id);
2752                if (og_queue_task_group_clients(dbi, task, query)) {
2753                        dbi_result_free(result);
2754                        return -1;
2755                }
2756
2757                sprintf(query,"SELECT ip, mac, idordenador FROM ordenadores "
2758                              "WHERE grupoid=%d", group_id);
2759                if (og_queue_task_command(dbi, task, query)) {
2760                        dbi_result_free(result);
2761                        return -1;
2762                }
2763
2764        }
2765
2766        dbi_result_free(result);
2767
2768        return 0;
2769}
2770
2771static int og_queue_task_group_classrooms(struct og_dbi *dbi,
2772                                          struct og_task *task, char *query)
2773{
2774
2775        const char *msglog;
2776        dbi_result result;
2777
2778        result = dbi_conn_queryf(dbi->conn, query);
2779        if (!result) {
2780                dbi_conn_error(dbi->conn, &msglog);
2781                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2782                       __func__, __LINE__, msglog);
2783                return -1;
2784        }
2785
2786        while (dbi_result_next_row(result)) {
2787                uint32_t group_id = dbi_result_get_uint(result, "idgrupo");
2788
2789                sprintf(query, "SELECT idgrupo FROM grupos "
2790                                "WHERE grupoid=%d AND tipo=%d", group_id, AMBITO_GRUPOSAULAS);
2791                if (og_queue_task_group_classrooms(dbi, task, query)) {
2792                        dbi_result_free(result);
2793                        return -1;
2794                }
2795
2796                sprintf(query,
2797                        "SELECT ip,mac,idordenador "
2798                        "FROM ordenadores INNER JOIN aulas "
2799                        "WHERE ordenadores.idaula=aulas.idaula "
2800                        "AND aulas.grupoid=%d",
2801                        group_id);
2802                if (og_queue_task_command(dbi, task, query)) {
2803                        dbi_result_free(result);
2804                        return -1;
2805                }
2806
2807        }
2808
2809        dbi_result_free(result);
2810
2811        return 0;
2812}
2813
2814static int og_queue_task_clients(struct og_dbi *dbi, struct og_task *task)
2815{
2816        char query[4096];
2817
2818        switch (task->type_scope) {
2819                case AMBITO_CENTROS:
2820                        sprintf(query,
2821                                "SELECT ip,mac,idordenador "
2822                                "FROM ordenadores INNER JOIN aulas "
2823                                "WHERE ordenadores.idaula=aulas.idaula "
2824                                "AND idcentro=%d",
2825                                task->scope);
2826                        return og_queue_task_command(dbi, task, query);
2827                case AMBITO_GRUPOSAULAS:
2828                        sprintf(query,
2829                                "SELECT idgrupo FROM grupos "
2830                                "WHERE idgrupo=%i AND tipo=%d",
2831                                task->scope, AMBITO_GRUPOSAULAS);
2832                        return og_queue_task_group_classrooms(dbi, task, query);
2833                case AMBITO_AULAS:
2834                        sprintf(query,
2835                                "SELECT ip,mac,idordenador FROM ordenadores "
2836                                "WHERE idaula=%d",
2837                                task->scope);
2838                        return og_queue_task_command(dbi, task, query);
2839                case AMBITO_GRUPOSORDENADORES:
2840                        sprintf(query,
2841                                "SELECT idgrupo FROM gruposordenadores "
2842                                "WHERE idgrupo = %d",
2843                                task->scope);
2844                        return og_queue_task_group_clients(dbi, task, query);
2845                case AMBITO_ORDENADORES:
2846                        sprintf(query,
2847                                "SELECT ip, mac, idordenador FROM ordenadores "
2848                                "WHERE idordenador = %d",
2849                                task->scope);
2850                        return og_queue_task_command(dbi, task, query);
2851        }
2852        return 0;
2853}
2854
2855int og_dbi_queue_procedure(struct og_dbi *dbi, struct og_task *task)
2856{
2857        uint32_t procedure_id;
2858        const char *msglog;
2859        dbi_result result;
2860
2861        result = dbi_conn_queryf(dbi->conn,
2862                        "SELECT parametros, procedimientoid, idcomando "
2863                        "FROM procedimientos_acciones "
2864                        "WHERE idprocedimiento=%d ORDER BY orden", task->procedure_id);
2865        if (!result) {
2866                dbi_conn_error(dbi->conn, &msglog);
2867                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2868                       __func__, __LINE__, msglog);
2869                return -1;
2870        }
2871
2872        while (dbi_result_next_row(result)) {
2873                procedure_id = dbi_result_get_uint(result, "procedimientoid");
2874                if (procedure_id > 0) {
2875                        task->procedure_id = procedure_id;
2876                        if (og_dbi_queue_procedure(dbi, task))
2877                                return -1;
2878                        continue;
2879                }
2880
2881                task->params = dbi_result_get_string(result, "parametros");
2882                task->command_id = dbi_result_get_uint(result, "idcomando");
2883                if (og_queue_task_clients(dbi, task))
2884                        return -1;
2885        }
2886
2887        dbi_result_free(result);
2888
2889        return 0;
2890}
2891
2892static int og_dbi_queue_task(struct og_dbi *dbi, uint32_t task_id,
2893                             uint32_t schedule_id)
2894{
2895        struct og_task task = {};
2896        uint32_t task_id_next;
2897        const char *msglog;
2898        dbi_result result;
2899
2900        task.schedule_id = schedule_id;
2901
2902        result = dbi_conn_queryf(dbi->conn,
2903                        "SELECT tareas_acciones.orden, "
2904                                "tareas_acciones.idprocedimiento, "
2905                                "tareas_acciones.tareaid, "
2906                                "tareas.idtarea, "
2907                                "tareas.idcentro, "
2908                                "tareas.ambito, "
2909                                "tareas.idambito, "
2910                                "tareas.restrambito "
2911                        " FROM tareas"
2912                                " INNER JOIN tareas_acciones ON tareas_acciones.idtarea=tareas.idtarea"
2913                        " WHERE tareas_acciones.idtarea=%u ORDER BY tareas_acciones.orden ASC", task_id);
2914        if (!result) {
2915                dbi_conn_error(dbi->conn, &msglog);
2916                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2917                       __func__, __LINE__, msglog);
2918                return -1;
2919        }
2920
2921        while (dbi_result_next_row(result)) {
2922                task_id_next = dbi_result_get_uint(result, "tareaid");
2923
2924                if (task_id_next > 0) {
2925                        if (og_dbi_queue_task(dbi, task_id_next, schedule_id))
2926                                return -1;
2927
2928                        continue;
2929                }
2930                task.task_id = dbi_result_get_uint(result, "idtarea");
2931                task.center_id = dbi_result_get_uint(result, "idcentro");
2932                task.procedure_id = dbi_result_get_uint(result, "idprocedimiento");
2933                task.type_scope = dbi_result_get_uint(result, "ambito");
2934                task.scope = dbi_result_get_uint(result, "idambito");
2935                task.filtered_scope = dbi_result_get_string(result, "restrambito");
2936
2937                og_dbi_queue_procedure(dbi, &task);
2938        }
2939
2940        dbi_result_free(result);
2941
2942        return 0;
2943}
2944
2945static int og_dbi_queue_command(struct og_dbi *dbi, uint32_t task_id,
2946                                uint32_t schedule_id)
2947{
2948        struct og_task task = {};
2949        const char *msglog;
2950        dbi_result result;
2951        char query[4096];
2952
2953        result = dbi_conn_queryf(dbi->conn,
2954                        "SELECT idaccion, idcentro, idordenador, parametros "
2955                        "FROM acciones "
2956                        "WHERE sesion = %u", task_id);
2957        if (!result) {
2958                dbi_conn_error(dbi->conn, &msglog);
2959                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
2960                       __func__, __LINE__, msglog);
2961                return -1;
2962        }
2963
2964        while (dbi_result_next_row(result)) {
2965                task.task_id = dbi_result_get_uint(result, "idaccion");
2966                task.center_id = dbi_result_get_uint(result, "idcentro");
2967                task.scope = dbi_result_get_uint(result, "idordenador");
2968                task.params = dbi_result_get_string(result, "parametros");
2969
2970                sprintf(query,
2971                        "SELECT ip, mac, idordenador FROM ordenadores "
2972                        "WHERE idordenador = %d",
2973                        task.scope);
2974                if (og_queue_task_command(dbi, &task, query)) {
2975                        dbi_result_free(result);
2976                        return -1;
2977                }
2978        }
2979
2980        dbi_result_free(result);
2981
2982        return 0;
2983}
2984
2985int og_dbi_update_action(uint32_t id, bool success)
2986{
2987        char end_date_string[24];
2988        struct tm *end_date;
2989        const char *msglog;
2990        struct og_dbi *dbi;
2991        uint8_t status = 2;
2992        dbi_result result;
2993        time_t now;
2994
2995        if (!id)
2996                return 0;
2997
2998        dbi = og_dbi_open(&ogconfig.db);
2999        if (!dbi) {
3000                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3001                       __func__, __LINE__);
3002                return -1;
3003        }
3004
3005        time(&now);
3006        end_date = localtime(&now);
3007
3008        sprintf(end_date_string, "%hu/%hhu/%hhu %hhu:%hhu:%hhu",
3009                end_date->tm_year + 1900, end_date->tm_mon + 1,
3010                end_date->tm_mday, end_date->tm_hour, end_date->tm_min,
3011                end_date->tm_sec);
3012        result = dbi_conn_queryf(dbi->conn,
3013                                 "UPDATE acciones SET fechahorafin='%s', "
3014                                 "estado=%d, resultado=%d WHERE idaccion=%d",
3015                                 end_date_string, ACCION_FINALIZADA,
3016                                 status - success, id);
3017
3018        if (!result) {
3019                dbi_conn_error(dbi->conn, &msglog);
3020                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3021                       __func__, __LINE__, msglog);
3022                og_dbi_close(dbi);
3023                return -1;
3024        }
3025        dbi_result_free(result);
3026        og_dbi_close(dbi);
3027
3028        return 0;
3029}
3030
3031void og_schedule_run(unsigned int task_id, unsigned int schedule_id,
3032                     enum og_schedule_type type)
3033{
3034        struct og_msg_params params = {};
3035        bool duplicated = false;
3036        struct og_cmd *cmd, *next;
3037        struct og_dbi *dbi;
3038        unsigned int i;
3039
3040        dbi = og_dbi_open(&ogconfig.db);
3041        if (!dbi) {
3042                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3043                       __func__, __LINE__);
3044                return;
3045        }
3046
3047        switch (type) {
3048        case OG_SCHEDULE_TASK:
3049                og_dbi_queue_task(dbi, task_id, schedule_id);
3050                break;
3051        case OG_SCHEDULE_PROCEDURE:
3052        case OG_SCHEDULE_COMMAND:
3053                og_dbi_queue_command(dbi, task_id, schedule_id);
3054                break;
3055        }
3056        og_dbi_close(dbi);
3057
3058        list_for_each_entry(cmd, &cmd_list, list) {
3059                for (i = 0; i < params.ips_array_len; i++) {
3060                        if (!strncmp(cmd->ip, params.ips_array[i],
3061                                     OG_DB_IP_MAXLEN)) {
3062                                duplicated = true;
3063                                break;
3064                        }
3065                }
3066
3067                if (!duplicated)
3068                        params.ips_array[params.ips_array_len++] = strdup(cmd->ip);
3069                else
3070                        duplicated = false;
3071        }
3072
3073        list_for_each_entry_safe(cmd, next, &cmd_list, list) {
3074                if (cmd->type != OG_CMD_WOL)
3075                        continue;
3076
3077                if (Levanta((char **)cmd->params.ips_array,
3078                            (char **)cmd->params.mac_array,
3079                            (char **)cmd->params.netmask_array,
3080                            cmd->params.ips_array_len,
3081                            (char *)cmd->params.wol_type))
3082                        og_dbi_update_action(cmd->id, true);
3083
3084                list_del(&cmd->list);
3085                og_cmd_free(cmd);
3086        }
3087
3088        og_send_request(OG_METHOD_GET, OG_CMD_RUN_SCHEDULE, &params, NULL);
3089
3090        for (i = 0; i < params.ips_array_len; i++)
3091                free((void *)params.ips_array[i]);
3092}
3093
3094static int og_cmd_task_post(json_t *element, struct og_msg_params *params)
3095{
3096        struct og_cmd *cmd;
3097        struct og_dbi *dbi;
3098        const char *key;
3099        json_t *value;
3100        int err = 0;
3101
3102        if (json_typeof(element) != JSON_OBJECT)
3103                return -1;
3104
3105        json_object_foreach(element, key, value) {
3106                if (!strcmp(key, "task")) {
3107                        err = og_json_parse_string(value, &params->task_id);
3108                        params->flags |= OG_REST_PARAM_TASK;
3109                }
3110
3111                if (err < 0)
3112                        return err;
3113        }
3114
3115        if (!og_msg_params_validate(params, OG_REST_PARAM_TASK))
3116                return -1;
3117
3118        dbi = og_dbi_open(&ogconfig.db);
3119        if (!dbi) {
3120                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3121                           __func__, __LINE__);
3122                return -1;
3123        }
3124
3125        og_schedule_run(atoi(params->task_id), 0, OG_SCHEDULE_TASK);
3126        og_dbi_close(dbi);
3127
3128        list_for_each_entry(cmd, &cmd_list, list)
3129                params->ips_array[params->ips_array_len++] = cmd->ip;
3130
3131        return og_send_request(OG_METHOD_GET, OG_CMD_RUN_SCHEDULE, params,
3132                               NULL);
3133}
3134
3135static int og_dbi_scope_get_computer(struct og_dbi *dbi, json_t *array,
3136                                     uint32_t room_id)
3137{
3138        const char *computer_name, *computer_ip;
3139        uint32_t computer_id;
3140        const char *msglog;
3141        dbi_result result;
3142        json_t *computer;
3143
3144        result = dbi_conn_queryf(dbi->conn,
3145                                 "SELECT idordenador, nombreordenador, ip "
3146                                 "FROM ordenadores WHERE idaula=%d",
3147                                 room_id);
3148        if (!result) {
3149                dbi_conn_error(dbi->conn, &msglog);
3150                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3151                       __func__, __LINE__, msglog);
3152                return -1;
3153        }
3154
3155        while (dbi_result_next_row(result)) {
3156                computer_id = dbi_result_get_uint(result, "idordenador");
3157                computer_name = dbi_result_get_string(result, "nombreordenador");
3158                computer_ip = dbi_result_get_string(result, "ip");
3159
3160                computer = json_object();
3161                if (!computer) {
3162                        dbi_result_free(result);
3163                        return -1;
3164                }
3165
3166                json_object_set_new(computer, "name", json_string(computer_name));
3167                json_object_set_new(computer, "type", json_string("computer"));
3168                json_object_set_new(computer, "id", json_integer(computer_id));
3169                json_object_set_new(computer, "scope", json_array());
3170                json_object_set_new(computer, "ip", json_string(computer_ip));
3171                json_array_append(array, computer);
3172                json_decref(computer);
3173        }
3174        dbi_result_free(result);
3175
3176        return 0;
3177}
3178
3179static int og_dbi_scope_get_room(struct og_dbi *dbi, json_t *array,
3180                                 uint32_t center_id)
3181{
3182        char room_name[OG_DB_ROOM_NAME_MAXLEN + 1] = {};
3183        json_t *room, *room_array;
3184        const char *msglog;
3185        dbi_result result;
3186        uint32_t room_id;
3187
3188        result = dbi_conn_queryf(dbi->conn,
3189                                 "SELECT idaula, nombreaula FROM aulas WHERE "
3190                                 "idcentro=%d",
3191                                 center_id);
3192        if (!result) {
3193                dbi_conn_error(dbi->conn, &msglog);
3194                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3195                       __func__, __LINE__, msglog);
3196                return -1;
3197        }
3198
3199        while (dbi_result_next_row(result)) {
3200                room_id = dbi_result_get_uint(result, "idaula");
3201                strncpy(room_name,
3202                        dbi_result_get_string(result, "nombreaula"),
3203                        OG_DB_CENTER_NAME_MAXLEN);
3204
3205                room = json_object();
3206                if (!room) {
3207                        dbi_result_free(result);
3208                        return -1;
3209                }
3210
3211                json_object_set_new(room, "name", json_string(room_name));
3212                json_object_set_new(room, "type", json_string("room"));
3213                json_object_set_new(room, "id", json_integer(room_id));
3214                json_object_set_new(room, "scope", json_array());
3215                json_array_append(array, room);
3216                json_decref(room);
3217
3218                room_array = json_object_get(room, "scope");
3219                if (!room_array) {
3220                        dbi_result_free(result);
3221                        return -1;
3222                }
3223
3224                if (og_dbi_scope_get_computer(dbi, room_array, room_id)) {
3225                        dbi_result_free(result);
3226                        return -1;
3227                }
3228        }
3229        dbi_result_free(result);
3230
3231        return 0;
3232}
3233
3234static int og_dbi_scope_get(struct og_dbi *dbi, json_t *array)
3235{
3236        char center_name[OG_DB_CENTER_NAME_MAXLEN + 1] = {};
3237        json_t *center, *array_room;
3238        const char *msglog;
3239        uint32_t center_id;
3240        dbi_result result;
3241
3242        result = dbi_conn_queryf(dbi->conn,
3243                                 "SELECT nombrecentro, idcentro FROM centros");
3244        if (!result) {
3245                dbi_conn_error(dbi->conn, &msglog);
3246                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3247                       __func__, __LINE__, msglog);
3248                return -1;
3249        }
3250
3251        while (dbi_result_next_row(result)) {
3252                center_id = dbi_result_get_uint(result, "idcentro");
3253                strncpy(center_name,
3254                        dbi_result_get_string(result, "nombrecentro"),
3255                        OG_DB_CENTER_NAME_MAXLEN);
3256
3257                center = json_object();
3258                if (!center) {
3259                        dbi_result_free(result);
3260                        return -1;
3261                }
3262
3263                array_room = json_array();
3264                if (!array_room) {
3265                        dbi_result_free(result);
3266                        json_decref(center);
3267                        return -1;
3268                }
3269
3270                json_object_set_new(center, "name", json_string(center_name));
3271                json_object_set_new(center, "type", json_string("center"));
3272                json_object_set_new(center, "id", json_integer(center_id));
3273                json_object_set_new(center, "scope", array_room);
3274                json_array_append(array, center);
3275                json_decref(center);
3276
3277                if (og_dbi_scope_get_room(dbi, array_room, center_id)) {
3278                        dbi_result_free(result);
3279                        return -1;
3280                }
3281        }
3282
3283        dbi_result_free(result);
3284
3285        return 0;
3286}
3287
3288static int og_cmd_scope_get(json_t *element, struct og_msg_params *params,
3289                            char *buffer_reply)
3290{
3291        struct og_buffer og_buffer = {
3292                .data = buffer_reply
3293        };
3294        json_t *root, *array;
3295        struct og_dbi *dbi;
3296
3297        root = json_object();
3298        if (!root)
3299                return -1;
3300
3301        array = json_array();
3302        if (!array) {
3303                json_decref(root);
3304                return -1;
3305        }
3306        json_object_set_new(root, "scope", array);
3307
3308        dbi = og_dbi_open(&ogconfig.db);
3309        if (!dbi) {
3310                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3311                       __func__, __LINE__);
3312                json_decref(root);
3313                return -1;
3314        }
3315
3316        if (og_dbi_scope_get(dbi, array)) {
3317                og_dbi_close(dbi);
3318                json_decref(root);
3319                return -1;
3320        }
3321
3322        og_dbi_close(dbi);
3323
3324        if (json_dump_callback(root, og_json_dump_clients, &og_buffer, 0)) {
3325                json_decref(root);
3326                return -1;
3327        }
3328
3329        json_decref(root);
3330
3331        return 0;
3332}
3333
3334int og_dbi_schedule_get(void)
3335{
3336        uint32_t schedule_id, task_id;
3337        struct og_schedule_time time;
3338        struct og_dbi *dbi;
3339        const char *msglog;
3340        dbi_result result;
3341
3342        dbi = og_dbi_open(&ogconfig.db);
3343        if (!dbi) {
3344                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3345                       __func__, __LINE__);
3346                return -1;
3347        }
3348
3349        result = dbi_conn_queryf(dbi->conn,
3350                                 "SELECT idprogramacion, tipoaccion, identificador, "
3351                                 "sesion, annos, meses, diario, dias, semanas, horas, "
3352                                 "ampm, minutos FROM programaciones "
3353                                 "WHERE suspendida = 0");
3354        if (!result) {
3355                dbi_conn_error(dbi->conn, &msglog);
3356                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3357                       __func__, __LINE__, msglog);
3358                og_dbi_close(dbi);
3359                return -1;
3360        }
3361
3362        while (dbi_result_next_row(result)) {
3363                memset(&time, 0, sizeof(time));
3364                schedule_id = dbi_result_get_uint(result, "idprogramacion");
3365                task_id = dbi_result_get_uint(result, "identificador");
3366                time.years = dbi_result_get_uint(result, "annos");
3367                time.months = dbi_result_get_uint(result, "meses");
3368                time.weeks = dbi_result_get_uint(result, "semanas");
3369                time.week_days = dbi_result_get_uint(result, "dias");
3370                time.days = dbi_result_get_uint(result, "diario");
3371                time.hours = dbi_result_get_uint(result, "horas");
3372                time.am_pm = dbi_result_get_uint(result, "ampm");
3373                time.minutes = dbi_result_get_uint(result, "minutos");
3374                time.check_stale = true;
3375
3376                og_schedule_create(schedule_id, task_id, OG_SCHEDULE_TASK,
3377                                   &time);
3378        }
3379
3380        dbi_result_free(result);
3381        og_dbi_close(dbi);
3382
3383        return 0;
3384}
3385
3386static int og_dbi_schedule_create(struct og_dbi *dbi,
3387                                  struct og_msg_params *params,
3388                                  uint32_t *schedule_id,
3389                                  enum og_schedule_type schedule_type)
3390{
3391        uint8_t suspended = 0;
3392        uint32_t session = 0;
3393        const char *msglog;
3394        dbi_result result;
3395        uint8_t type;
3396
3397        switch (schedule_type) {
3398        case OG_SCHEDULE_TASK:
3399                type = 3;
3400                break;
3401        case OG_SCHEDULE_PROCEDURE:
3402                type = 2;
3403                break;
3404        case OG_SCHEDULE_COMMAND:
3405                session = atoi(params->task_id);
3406                type = 1;
3407                break;
3408        }
3409
3410        result = dbi_conn_queryf(dbi->conn,
3411                                 "INSERT INTO programaciones (tipoaccion,"
3412                                 " identificador, nombrebloque, annos, meses,"
3413                                 " semanas, dias, diario, horas, ampm, minutos,"
3414                                 " suspendida, sesion) VALUES (%d, %s, '%s',"
3415                                 " %d, %d, %d, %d, %d, %d, %d, %d, %d, %d)",
3416                                 type, params->task_id, params->name,
3417                                 params->time.years, params->time.months,
3418                                 params->time.weeks, params->time.week_days,
3419                                 params->time.days, params->time.hours,
3420                                 params->time.am_pm, params->time.minutes,
3421                                 suspended, session);
3422        if (!result) {
3423                dbi_conn_error(dbi->conn, &msglog);
3424                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3425                       __func__, __LINE__, msglog);
3426                return -1;
3427        }
3428        dbi_result_free(result);
3429
3430        *schedule_id = dbi_conn_sequence_last(dbi->conn, NULL);
3431
3432        return 0;
3433}
3434
3435static int og_dbi_schedule_update(struct og_dbi *dbi,
3436                                  struct og_msg_params *params)
3437{
3438        const char *msglog;
3439        dbi_result result;
3440        uint8_t type = 3;
3441
3442        result = dbi_conn_queryf(dbi->conn,
3443                                 "UPDATE programaciones SET tipoaccion=%d, "
3444                                 "identificador='%s', nombrebloque='%s', "
3445                                 "annos=%d, meses=%d, "
3446                                 "diario=%d, horas=%d, ampm=%d, minutos=%d "
3447                                 "WHERE idprogramacion='%s'",
3448                                 type, params->task_id, params->name,
3449                                 params->time.years, params->time.months,
3450                                 params->time.days, params->time.hours,
3451                                 params->time.am_pm, params->time.minutes,
3452                                 params->id);
3453
3454        if (!result) {
3455                dbi_conn_error(dbi->conn, &msglog);
3456                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3457                       __func__, __LINE__, msglog);
3458                return -1;
3459        }
3460        dbi_result_free(result);
3461
3462        return 0;
3463}
3464
3465static int og_dbi_schedule_delete(struct og_dbi *dbi, uint32_t id)
3466{
3467        const char *msglog;
3468        dbi_result result;
3469
3470        result = dbi_conn_queryf(dbi->conn,
3471                                 "DELETE FROM programaciones WHERE idprogramacion=%d",
3472                                 id);
3473        if (!result) {
3474                dbi_conn_error(dbi->conn, &msglog);
3475                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3476                       __func__, __LINE__, msglog);
3477                return -1;
3478        }
3479        dbi_result_free(result);
3480
3481        return 0;
3482}
3483
3484struct og_db_schedule {
3485        uint32_t                id;
3486        uint32_t                task_id;
3487        const char              *name;
3488        struct og_schedule_time time;
3489        uint32_t                week_days;
3490        uint32_t                weeks;
3491        uint32_t                suspended;
3492        uint32_t                session;
3493};
3494
3495static int og_dbi_schedule_get_json(struct og_dbi *dbi, json_t *root,
3496                                    const char *task_id, const char *schedule_id)
3497{
3498        struct og_db_schedule schedule;
3499        json_t *obj, *array;
3500        const char *msglog;
3501        dbi_result result;
3502        int err = 0;
3503
3504        if (task_id) {
3505                result = dbi_conn_queryf(dbi->conn,
3506                                         "SELECT idprogramacion,"
3507                                         "       identificador, nombrebloque,"
3508                                         "       annos, meses, diario, dias,"
3509                                         "       semanas, horas, ampm,"
3510                                         "       minutos,suspendida, sesion "
3511                                         "FROM programaciones "
3512                                         "WHERE identificador=%d",
3513                                         atoi(task_id));
3514        } else if (schedule_id) {
3515                result = dbi_conn_queryf(dbi->conn,
3516                                         "SELECT idprogramacion,"
3517                                         "       identificador, nombrebloque,"
3518                                         "       annos, meses, diario, dias,"
3519                                         "       semanas, horas, ampm,"
3520                                         "       minutos,suspendida, sesion "
3521                                         "FROM programaciones "
3522                                         "WHERE idprogramacion=%d",
3523                                         atoi(schedule_id));
3524        } else {
3525                result = dbi_conn_queryf(dbi->conn,
3526                                         "SELECT idprogramacion,"
3527                                         "       identificador, nombrebloque,"
3528                                         "       annos, meses, diario, dias,"
3529                                         "       semanas, horas, ampm,"
3530                                         "       minutos,suspendida, sesion "
3531                                         "FROM programaciones");
3532        }
3533
3534        if (!result) {
3535                dbi_conn_error(dbi->conn, &msglog);
3536                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3537                       __func__, __LINE__, msglog);
3538                return -1;
3539        }
3540
3541        array = json_array();
3542        if (!array)
3543                return -1;
3544
3545        while (dbi_result_next_row(result)) {
3546                schedule.id = dbi_result_get_uint(result, "idprogramacion");
3547                schedule.task_id = dbi_result_get_uint(result, "identificador");
3548                schedule.name = dbi_result_get_string(result, "nombrebloque");
3549                schedule.time.years = dbi_result_get_uint(result, "annos");
3550                schedule.time.months = dbi_result_get_uint(result, "meses");
3551                schedule.time.days = dbi_result_get_uint(result, "diario");
3552                schedule.time.hours = dbi_result_get_uint(result, "horas");
3553                schedule.time.am_pm = dbi_result_get_uint(result, "ampm");
3554                schedule.time.minutes = dbi_result_get_uint(result, "minutos");
3555                schedule.week_days = dbi_result_get_uint(result, "dias");
3556                schedule.weeks = dbi_result_get_uint(result, "semanas");
3557                schedule.suspended = dbi_result_get_uint(result, "suspendida");
3558                schedule.session = dbi_result_get_uint(result, "sesion");
3559
3560                obj = json_object();
3561                if (!obj) {
3562                        err = -1;
3563                        break;
3564                }
3565                json_object_set_new(obj, "id", json_integer(schedule.id));
3566                json_object_set_new(obj, "task", json_integer(schedule.task_id));
3567                json_object_set_new(obj, "name", json_string(schedule.name));
3568                json_object_set_new(obj, "years", json_integer(schedule.time.years));
3569                json_object_set_new(obj, "months", json_integer(schedule.time.months));
3570                json_object_set_new(obj, "days", json_integer(schedule.time.days));
3571                json_object_set_new(obj, "hours", json_integer(schedule.time.hours));
3572                json_object_set_new(obj, "am_pm", json_integer(schedule.time.am_pm));
3573                json_object_set_new(obj, "minutes", json_integer(schedule.time.minutes));
3574                json_object_set_new(obj, "week_days", json_integer(schedule.week_days));
3575                json_object_set_new(obj, "weeks", json_integer(schedule.weeks));
3576                json_object_set_new(obj, "suspended", json_integer(schedule.suspended));
3577                json_object_set_new(obj, "session", json_integer(schedule.session));
3578
3579                json_array_append_new(array, obj);
3580        }
3581
3582        json_object_set_new(root, "schedule", array);
3583
3584        dbi_result_free(result);
3585
3586        return err;
3587}
3588
3589static int og_task_schedule_create(struct og_msg_params *params)
3590{
3591        enum og_schedule_type type;
3592        uint32_t schedule_id;
3593        struct og_dbi *dbi;
3594        int err;
3595
3596        if (!strcmp(params->type, "task"))
3597                type = OG_SCHEDULE_TASK;
3598        else if (!strcmp(params->type, "procedure"))
3599                type = OG_SCHEDULE_PROCEDURE;
3600        else if (!strcmp(params->type, "command"))
3601                type = OG_SCHEDULE_COMMAND;
3602        else
3603                return -1;
3604
3605        dbi = og_dbi_open(&ogconfig.db);
3606        if (!dbi) {
3607                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3608                       __func__, __LINE__);
3609                return -1;
3610        }
3611
3612        err = og_dbi_schedule_create(dbi, params, &schedule_id, type);
3613        if (err < 0) {
3614                og_dbi_close(dbi);
3615                return -1;
3616        }
3617        og_schedule_create(schedule_id, atoi(params->task_id), type,
3618                           &params->time);
3619        og_schedule_refresh(og_loop);
3620        og_dbi_close(dbi);
3621
3622        return 0;
3623}
3624
3625static uint32_t og_tm_years_mask(struct tm *tm)
3626{
3627        int i, j = 0;
3628
3629        for (i = 2010; i < 2026; i++, j++) {
3630                if (tm->tm_year + 1900 == i)
3631                        break;
3632        }
3633
3634        return (1 << j);
3635}
3636
3637static uint32_t og_tm_months_mask(struct tm *tm)
3638{
3639        return 1 << tm->tm_mon;
3640}
3641
3642static uint16_t og_tm_hours_mask(struct tm *tm)
3643{
3644        return tm->tm_hour >= 12 ? 1 << (tm->tm_hour - 12) : 1 << tm->tm_hour;
3645}
3646
3647static uint32_t og_tm_ampm(struct tm *tm)
3648{
3649        return tm->tm_hour < 12 ? 0 : 1;
3650}
3651
3652static uint32_t og_tm_days_mask(struct tm *tm)
3653{
3654        return 1 << (tm->tm_mday - 1);
3655}
3656
3657static void og_schedule_time_now(struct og_schedule_time *ogtime)
3658{
3659        struct tm *tm;
3660        time_t now;
3661
3662        now = time(NULL);
3663        tm = localtime(&now);
3664
3665        ogtime->years = og_tm_years_mask(tm);
3666        ogtime->months = og_tm_months_mask(tm);
3667        ogtime->weeks = 0;
3668        ogtime->week_days = 0;
3669        ogtime->days =  og_tm_days_mask(tm);
3670        ogtime->hours = og_tm_hours_mask(tm);
3671        ogtime->am_pm = og_tm_ampm(tm);
3672        ogtime->minutes = tm->tm_min;
3673}
3674
3675static int og_cmd_schedule_create(json_t *element, struct og_msg_params *params)
3676{
3677        bool when = false;
3678        const char *key;
3679        json_t *value;
3680        int err = 0;
3681
3682        if (json_typeof(element) != JSON_OBJECT)
3683                return -1;
3684
3685        json_object_foreach(element, key, value) {
3686                if (!strcmp(key, "task")) {
3687                        err = og_json_parse_string(value, &params->task_id);
3688                        params->flags |= OG_REST_PARAM_TASK;
3689                } else if (!strcmp(key, "name")) {
3690                        err = og_json_parse_string(value, &params->name);
3691                        params->flags |= OG_REST_PARAM_NAME;
3692                } else if (!strcmp(key, "when")) {
3693                        err = og_json_parse_time_params(value, params);
3694                        when = true;
3695                } else if (!strcmp(key, "type")) {
3696                        err = og_json_parse_string(value, &params->type);
3697                        params->flags |= OG_REST_PARAM_TYPE;
3698                }
3699
3700                if (err < 0)
3701                        return err;
3702        }
3703
3704        if (!when) {
3705                params->time.check_stale = false;
3706                og_schedule_time_now(&params->time);
3707                params->flags |= OG_REST_PARAM_TIME_YEARS |
3708                                 OG_REST_PARAM_TIME_MONTHS |
3709                                 OG_REST_PARAM_TIME_WEEKS |
3710                                 OG_REST_PARAM_TIME_WEEK_DAYS |
3711                                 OG_REST_PARAM_TIME_DAYS |
3712                                 OG_REST_PARAM_TIME_HOURS |
3713                                 OG_REST_PARAM_TIME_AM_PM |
3714                                 OG_REST_PARAM_TIME_MINUTES;
3715        } else {
3716                params->time.check_stale = true;
3717        }
3718
3719        if (!og_msg_params_validate(params, OG_REST_PARAM_TASK |
3720                                            OG_REST_PARAM_NAME |
3721                                            OG_REST_PARAM_TIME_YEARS |
3722                                            OG_REST_PARAM_TIME_MONTHS |
3723                                            OG_REST_PARAM_TIME_WEEKS |
3724                                            OG_REST_PARAM_TIME_WEEK_DAYS |
3725                                            OG_REST_PARAM_TIME_DAYS |
3726                                            OG_REST_PARAM_TIME_HOURS |
3727                                            OG_REST_PARAM_TIME_MINUTES |
3728                                            OG_REST_PARAM_TIME_AM_PM |
3729                                            OG_REST_PARAM_TYPE))
3730                return -1;
3731
3732        return og_task_schedule_create(params);
3733}
3734
3735static int og_cmd_schedule_update(json_t *element, struct og_msg_params *params)
3736{
3737        struct og_dbi *dbi;
3738        bool when = false;
3739        const char *key;
3740        json_t *value;
3741        int err = 0;
3742
3743        if (json_typeof(element) != JSON_OBJECT)
3744                return -1;
3745
3746        json_object_foreach(element, key, value) {
3747                if (!strcmp(key, "id")) {
3748                        err = og_json_parse_string(value, &params->id);
3749                        params->flags |= OG_REST_PARAM_ID;
3750                } else if (!strcmp(key, "task")) {
3751                        err = og_json_parse_string(value, &params->task_id);
3752                        params->flags |= OG_REST_PARAM_TASK;
3753                } else if (!strcmp(key, "name")) {
3754                        err = og_json_parse_string(value, &params->name);
3755                        params->flags |= OG_REST_PARAM_NAME;
3756                } else if (!strcmp(key, "when")) {
3757                        err = og_json_parse_time_params(value, params);
3758                        when = true;
3759                }
3760
3761                if (err < 0)
3762                        return err;
3763        }
3764
3765        if (!when) {
3766                params->time.check_stale = false;
3767                og_schedule_time_now(&params->time);
3768                params->flags |= OG_REST_PARAM_TIME_YEARS |
3769                                 OG_REST_PARAM_TIME_MONTHS |
3770                                 OG_REST_PARAM_TIME_WEEKS |
3771                                 OG_REST_PARAM_TIME_WEEK_DAYS |
3772                                 OG_REST_PARAM_TIME_DAYS |
3773                                 OG_REST_PARAM_TIME_HOURS |
3774                                 OG_REST_PARAM_TIME_AM_PM |
3775                                 OG_REST_PARAM_TIME_MINUTES;
3776        } else {
3777                params->time.check_stale = true;
3778        }
3779
3780        if (!og_msg_params_validate(params, OG_REST_PARAM_ID |
3781                                            OG_REST_PARAM_TASK |
3782                                            OG_REST_PARAM_NAME |
3783                                            OG_REST_PARAM_TIME_YEARS |
3784                                            OG_REST_PARAM_TIME_MONTHS |
3785                                            OG_REST_PARAM_TIME_DAYS |
3786                                            OG_REST_PARAM_TIME_HOURS |
3787                                            OG_REST_PARAM_TIME_MINUTES |
3788                                            OG_REST_PARAM_TIME_AM_PM))
3789                return -1;
3790
3791        dbi = og_dbi_open(&ogconfig.db);
3792        if (!dbi) {
3793                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3794                           __func__, __LINE__);
3795                return -1;
3796        }
3797
3798        err = og_dbi_schedule_update(dbi, params);
3799        og_dbi_close(dbi);
3800
3801        if (err < 0)
3802                return err;
3803
3804        og_schedule_update(og_loop, atoi(params->id), atoi(params->task_id),
3805                           &params->time);
3806        og_schedule_refresh(og_loop);
3807
3808        return err;
3809}
3810
3811static int og_cmd_schedule_delete(json_t *element, struct og_msg_params *params)
3812{
3813        struct og_dbi *dbi;
3814        const char *key;
3815        json_t *value;
3816        int err = 0;
3817
3818        if (json_typeof(element) != JSON_OBJECT)
3819                return -1;
3820
3821        json_object_foreach(element, key, value) {
3822                if (!strcmp(key, "id")) {
3823                        err = og_json_parse_string(value, &params->id);
3824                        params->flags |= OG_REST_PARAM_ID;
3825                }
3826
3827                if (err < 0)
3828                        return err;
3829        }
3830
3831        if (!og_msg_params_validate(params, OG_REST_PARAM_ID))
3832                return -1;
3833
3834        dbi = og_dbi_open(&ogconfig.db);
3835        if (!dbi) {
3836                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3837                           __func__, __LINE__);
3838                return -1;
3839        }
3840
3841        err = og_dbi_schedule_delete(dbi, atoi(params->id));
3842        og_dbi_close(dbi);
3843
3844        og_schedule_delete(og_loop, atoi(params->id));
3845
3846        return err;
3847}
3848
3849static int og_cmd_schedule_get(json_t *element, struct og_msg_params *params,
3850                               char *buffer_reply)
3851{
3852        struct og_buffer og_buffer = {
3853                .data   = buffer_reply,
3854        };
3855        json_t *schedule_root;
3856        struct og_dbi *dbi;
3857        const char *key;
3858        json_t *value;
3859        int err = 0;
3860
3861        if (element) {
3862                if (json_typeof(element) != JSON_OBJECT)
3863                        return -1;
3864
3865                json_object_foreach(element, key, value) {
3866                        if (!strcmp(key, "task")) {
3867                                err = og_json_parse_string(value,
3868                                                           &params->task_id);
3869                        } else if (!strcmp(key, "id")) {
3870                                err = og_json_parse_string(value, &params->id);
3871                        }
3872
3873                        if (err < 0)
3874                                return err;
3875                }
3876        }
3877
3878        dbi = og_dbi_open(&ogconfig.db);
3879        if (!dbi) {
3880                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
3881                           __func__, __LINE__);
3882                return -1;
3883        }
3884
3885        schedule_root = json_object();
3886        if (!schedule_root) {
3887                og_dbi_close(dbi);
3888                return -1;
3889        }
3890
3891        err = og_dbi_schedule_get_json(dbi, schedule_root,
3892                                       params->task_id, params->id);
3893        og_dbi_close(dbi);
3894
3895        if (err >= 0)
3896                err = json_dump_callback(schedule_root, og_json_dump_clients,
3897                                         &og_buffer, 0);
3898
3899        json_decref(schedule_root);
3900
3901        return err;
3902}
3903
3904#define OG_LIVE_JSON_FILE_PATH "/opt/opengnsys/etc/ogliveinfo.json"
3905
3906static int og_cmd_oglive_list(char *buffer_reply)
3907{
3908        struct og_buffer og_buffer = {
3909                .data = buffer_reply
3910        };
3911        json_error_t json_err;
3912        json_t *root;
3913
3914        root = json_load_file(OG_LIVE_JSON_FILE_PATH, 0, &json_err);
3915        if (!root) {
3916                syslog(LOG_ERR, "malformed json line %d: %s\n",
3917                       json_err.line, json_err.text);
3918                return -1;
3919        }
3920
3921        if (json_dump_callback(root, og_json_dump_clients, &og_buffer, 0)) {
3922                json_decref(root);
3923                return -1;
3924        }
3925
3926        json_decref(root);
3927
3928        return 0;
3929}
3930
3931static int og_cmd_post_center_add(json_t *element,
3932                                  struct og_msg_params *params,
3933                                  char *buffer_reply)
3934{
3935        const char *key, *msglog;
3936        struct og_dbi *dbi;
3937        dbi_result result;
3938        json_t *value;
3939        int err = 0;
3940
3941        json_object_foreach(element, key, value) {
3942                if (!strcmp(key, "name")) {
3943                        err = og_json_parse_string(value, &params->name);
3944                        params->flags |= OG_REST_PARAM_NAME;
3945                } else if (!strcmp(key, "comment")) {
3946                        err = og_json_parse_string(value, &params->comment);
3947                }
3948
3949                if (err < 0)
3950                        return err;
3951        }
3952
3953        if (!og_msg_params_validate(params, OG_REST_PARAM_NAME))
3954                return -1;
3955        if (!params->comment)
3956                params->comment = "";
3957
3958        dbi = og_dbi_open(&ogconfig.db);
3959        if (!dbi) {
3960                syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
3961                       __func__, __LINE__);
3962                return -1;
3963        }
3964
3965        result = dbi_conn_queryf(dbi->conn,
3966                                 "SELECT nombrecentro FROM centros WHERE nombrecentro='%s'",
3967                                 params->name);
3968
3969        if (!result) {
3970                dbi_conn_error(dbi->conn, &msglog);
3971                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
3972                       __func__, __LINE__, msglog);
3973                og_dbi_close(dbi);
3974                return -1;
3975        }
3976
3977        if (dbi_result_get_numrows(result) > 0) {
3978                syslog(LOG_ERR, "Center with name %s already exists\n",
3979                       params->name);
3980                dbi_result_free(result);
3981                og_dbi_close(dbi);
3982                return -1;
3983        }
3984        dbi_result_free(result);
3985
3986        result = dbi_conn_queryf(dbi->conn,
3987                                 "INSERT INTO centros("
3988                                 "  nombrecentro,"
3989                                 "  comentarios,"
3990                                 "  identidad) VALUES ("
3991                                 "'%s', '%s', 1)",
3992                                 params->name, params->comment);
3993
3994        if (!result) {
3995                dbi_conn_error(dbi->conn, &msglog);
3996                syslog(LOG_ERR, "failed to add center to database (%s:%d) %s\n",
3997                       __func__, __LINE__, msglog);
3998                og_dbi_close(dbi);
3999                return -1;
4000        }
4001
4002        dbi_result_free(result);
4003        og_dbi_close(dbi);
4004        return 0;
4005}
4006
4007static int og_cmd_post_center_delete(json_t *element,
4008                                     struct og_msg_params *params)
4009{
4010        const char *key, *msglog;
4011        struct og_dbi *dbi;
4012        dbi_result result;
4013        json_t *value;
4014        int err = 0;
4015
4016        json_object_foreach(element, key, value) {
4017                if (!strcmp(key, "id")) {
4018                        err = og_json_parse_string(value, &params->id);
4019                        params->flags |= OG_REST_PARAM_ID;
4020                }
4021                if (err < 0)
4022                        return err;
4023        }
4024
4025        if (!og_msg_params_validate(params, OG_REST_PARAM_ID))
4026                return -1;
4027
4028        dbi = og_dbi_open(&ogconfig.db);
4029        if (!dbi) {
4030                syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
4031                       __func__, __LINE__);
4032                return -1;
4033        }
4034
4035        result = dbi_conn_queryf(dbi->conn,
4036                                 "DELETE FROM centros WHERE idcentro=%s",
4037                                 params->id);
4038
4039        if (!result) {
4040                dbi_conn_error(dbi->conn, &msglog);
4041                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
4042                       __func__, __LINE__, msglog);
4043                og_dbi_close(dbi);
4044                return -1;
4045        }
4046
4047        dbi_result_free(result);
4048
4049        og_dbi_close(dbi);
4050        return 0;
4051}
4052
4053static int og_cmd_post_room_add(json_t *element,
4054                                struct og_msg_params *params)
4055{
4056        struct og_room room = {};
4057        const char *key, *msglog;
4058        struct og_dbi *dbi;
4059        dbi_result result;
4060        json_t *value;
4061        int err = 0;
4062
4063        json_object_foreach(element, key, value) {
4064                if (!strcmp(key, "name")) {
4065                        err = og_json_parse_string_copy(value, room.name,
4066                                                        sizeof(room.name));
4067                        params->flags |= OG_REST_PARAM_NAME;
4068                } else if (!strcmp(key, "location")) {
4069                        err = og_json_parse_string_copy(value, room.location,
4070                                                        sizeof(room.location));
4071                } else if (!strcmp(key, "gateway")) {
4072                        err = og_json_parse_string_copy(value, room.gateway,
4073                                                        sizeof(room.gateway));
4074                } else if (!strcmp(key, "netmask")) {
4075                        err = og_json_parse_string_copy(value, room.netmask,
4076                                                        sizeof(room.netmask));
4077                        params->flags |= OG_REST_PARAM_NETMASK;
4078                } else if (!strcmp(key, "ntp")) {
4079                        err = og_json_parse_string_copy(value, room.ntp,
4080                                                        sizeof(room.ntp));
4081                } else if (!strcmp(key, "dns")) {
4082                        err = og_json_parse_string_copy(value, room.dns,
4083                                                        sizeof(room.dns));
4084                } else if (!strcmp(key, "center")) {
4085                        err = og_json_parse_uint(value, &room.center);
4086                        params->flags |= OG_REST_PARAM_CENTER;
4087                } else if (!strcmp(key, "group")) {
4088                        err = og_json_parse_uint(value, &room.group);
4089                } else if (!strcmp(key, "remote")) {
4090                        err = og_json_parse_bool(value, &room.remote);
4091                }
4092
4093                if (err < 0)
4094                        return err;
4095        }
4096
4097        if (!og_msg_params_validate(params, OG_REST_PARAM_NAME |
4098                                            OG_REST_PARAM_NETMASK |
4099                                            OG_REST_PARAM_CENTER))
4100                return -1;
4101
4102        dbi = og_dbi_open(&ogconfig.db);
4103        if (!dbi) {
4104                syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
4105                       __func__, __LINE__);
4106                return -1;
4107        }
4108
4109        result = dbi_conn_queryf(dbi->conn,
4110                                 "SELECT nombreaula FROM aulas "
4111                                 "WHERE nombreaula='%s' AND idcentro=%d",
4112                                 room.name, room.center);
4113
4114        if (!result) {
4115                dbi_conn_error(dbi->conn, &msglog);
4116                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
4117                       __func__, __LINE__, msglog);
4118                og_dbi_close(dbi);
4119                return -1;
4120        }
4121
4122        if (dbi_result_get_numrows(result) > 0) {
4123                syslog(LOG_ERR, "Room with name %s already exists in the "
4124                                "center with id %d\n",
4125                       room.name, room.center);
4126                dbi_result_free(result);
4127                og_dbi_close(dbi);
4128                return -1;
4129        }
4130        dbi_result_free(result);
4131
4132        result = dbi_conn_queryf(dbi->conn,
4133                                 "INSERT INTO aulas("
4134                                 "  idcentro,"
4135                                 "  nombreaula,"
4136                                 "  netmask,"
4137                                 "  grupoid,"
4138                                 "  ubicacion,"
4139                                 "  router,"
4140                                 "  dns,"
4141                                 "  ntp,"
4142                                 "  inremotepc) VALUES ("
4143                                 "%d, '%s', '%s', %d, '%s', "
4144                                 "'%s', '%s', '%s', %d)",
4145                                 room.center, room.name, room.netmask,
4146                                 room.group, room.location, room.gateway,
4147                                 room.dns, room.ntp, room.remote);
4148
4149        if (!result) {
4150                dbi_conn_error(dbi->conn, &msglog);
4151                syslog(LOG_ERR, "failed to add room to database (%s:%d) %s\n",
4152                       __func__, __LINE__, msglog);
4153                og_dbi_close(dbi);
4154                return -1;
4155        }
4156
4157        dbi_result_free(result);
4158        og_dbi_close(dbi);
4159        return 0;
4160}
4161
4162static int og_cmd_post_room_delete(json_t *element,
4163                                   struct og_msg_params *params)
4164{
4165        const char *key, *msglog;
4166        struct og_dbi *dbi;
4167        dbi_result result;
4168        json_t *value;
4169        int err = 0;
4170
4171        json_object_foreach(element, key, value) {
4172                if (!strcmp(key, "id")) {
4173                        err = og_json_parse_string(value, &params->id);
4174                        params->flags |= OG_REST_PARAM_ID;
4175                }
4176                if (err < 0)
4177                        return err;
4178        }
4179
4180        if (!og_msg_params_validate(params, OG_REST_PARAM_ID))
4181                return -1;
4182
4183        dbi = og_dbi_open(&ogconfig.db);
4184        if (!dbi) {
4185                syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
4186                       __func__, __LINE__);
4187                return -1;
4188        }
4189
4190        result = dbi_conn_queryf(dbi->conn,
4191                                 "DELETE FROM aulas WHERE idaula=%s",
4192                                 params->id);
4193
4194        if (!result) {
4195                dbi_conn_error(dbi->conn, &msglog);
4196                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
4197                       __func__, __LINE__, msglog);
4198                og_dbi_close(dbi);
4199                return -1;
4200        }
4201
4202        dbi_result_free(result);
4203
4204        og_dbi_close(dbi);
4205        return 0;
4206}
4207
4208static int og_client_method_not_found(struct og_client *cli)
4209{
4210        /* To meet RFC 7231, this function MUST generate an Allow header field
4211         * containing the correct methods. For example: "Allow: POST\r\n"
4212         */
4213        char buf[] = "HTTP/1.1 405 Method Not Allowed\r\n"
4214                     "Content-Length: 0\r\n\r\n";
4215
4216        send(og_client_socket(cli), buf, strlen(buf), 0);
4217
4218        return -1;
4219}
4220
4221static int og_client_bad_request(struct og_client *cli)
4222{
4223        char buf[] = "HTTP/1.1 400 Bad Request\r\nContent-Length: 0\r\n\r\n";
4224
4225        send(og_client_socket(cli), buf, strlen(buf), 0);
4226
4227        return -1;
4228}
4229
4230static int og_client_not_found(struct og_client *cli)
4231{
4232        char buf[] = "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n";
4233
4234        send(og_client_socket(cli), buf, strlen(buf), 0);
4235
4236        return -1;
4237}
4238
4239static int og_client_not_authorized(struct og_client *cli)
4240{
4241        char buf[] = "HTTP/1.1 401 Unauthorized\r\n"
4242                     "WWW-Authenticate: Basic\r\n"
4243                     "Content-Length: 0\r\n\r\n";
4244
4245        send(og_client_socket(cli), buf, strlen(buf), 0);
4246
4247        return -1;
4248}
4249
4250static int og_server_internal_error(struct og_client *cli)
4251{
4252        char buf[] = "HTTP/1.1 500 Internal Server Error\r\n"
4253                     "Content-Length: 0\r\n\r\n";
4254
4255        send(og_client_socket(cli), buf, strlen(buf), 0);
4256
4257        return -1;
4258}
4259
4260static int og_client_ok(struct og_client *cli, char *buf_reply)
4261{
4262        char buf[OG_MSG_RESPONSE_MAXLEN] = {};
4263        int len;
4264
4265        len = snprintf(buf, sizeof(buf),
4266                       "HTTP/1.1 200 OK\r\nContent-Length: %ld\r\n\r\n%s",
4267                       strlen(buf_reply), buf_reply);
4268        if (len >= (int)sizeof(buf)) {
4269                syslog(LOG_ERR, "HTTP response to %s:%hu is too large\n",
4270                       inet_ntoa(cli->addr.sin_addr),
4271                       ntohs(cli->addr.sin_port));
4272                return og_server_internal_error(cli);
4273        }
4274
4275        send(og_client_socket(cli), buf, strlen(buf), 0);
4276
4277        return 0;
4278}
4279
4280int og_client_state_process_payload_rest(struct og_client *cli)
4281{
4282        char buf_reply[OG_MSG_RESPONSE_MAXLEN] = {};
4283        struct og_msg_params params = {};
4284        enum og_rest_method method;
4285        const char *cmd, *body;
4286        json_error_t json_err;
4287        json_t *root = NULL;
4288        int err = 0;
4289
4290        syslog(LOG_DEBUG, "%s:%hu %.32s ...\n",
4291               inet_ntoa(cli->addr.sin_addr),
4292               ntohs(cli->addr.sin_port), cli->buf);
4293
4294        if (!strncmp(cli->buf, "GET", strlen("GET"))) {
4295                method = OG_METHOD_GET;
4296                cmd = cli->buf + strlen("GET") + 2;
4297        } else if (!strncmp(cli->buf, "POST", strlen("POST"))) {
4298                method = OG_METHOD_POST;
4299                cmd = cli->buf + strlen("POST") + 2;
4300        } else
4301                return og_client_method_not_found(cli);
4302
4303        body = strstr(cli->buf, "\r\n\r\n") + 4;
4304
4305        if (strcmp(cli->auth_token, ogconfig.rest.api_token)) {
4306                syslog(LOG_ERR, "wrong Authentication key\n");
4307                return og_client_not_authorized(cli);
4308        }
4309
4310        if (cli->content_length) {
4311                root = json_loads(body, 0, &json_err);
4312                if (!root) {
4313                        syslog(LOG_ERR, "malformed json line %d: %s\n",
4314                               json_err.line, json_err.text);
4315                        return og_client_not_found(cli);
4316                }
4317        }
4318
4319        if (!strncmp(cmd, "clients", strlen("clients"))) {
4320                if (method != OG_METHOD_POST &&
4321                    method != OG_METHOD_GET) {
4322                        err = og_client_method_not_found(cli);
4323                        goto err_process_rest_payload;
4324                }
4325
4326                if (method == OG_METHOD_POST && !root) {
4327                        syslog(LOG_ERR, "command clients with no payload\n");
4328                        err = og_client_bad_request(cli);
4329                        goto err_process_rest_payload;
4330                }
4331                switch (method) {
4332                case OG_METHOD_POST:
4333                        err = og_cmd_post_clients(root, &params);
4334                        break;
4335                case OG_METHOD_GET:
4336                        err = og_cmd_get_clients(root, &params, buf_reply);
4337                        break;
4338                default:
4339                        err = og_client_bad_request(cli);
4340                        goto err_process_rest_payload;
4341                }
4342        } else if (!strncmp(cmd, "client/setup",
4343                            strlen("client/setup"))) {
4344                if (method != OG_METHOD_GET) {
4345                        err = og_client_method_not_found(cli);
4346                        goto err_process_rest_payload;
4347                }
4348
4349                if (!root) {
4350                        syslog(LOG_ERR,
4351                               "command client partitions with no payload\n");
4352                        err = og_client_bad_request(cli);
4353                        goto err_process_rest_payload;
4354                }
4355
4356                err = og_cmd_get_client_setup(root, &params, buf_reply);
4357        } else if (!strncmp(cmd, "client/info",
4358                            strlen("client/info"))) {
4359                if (method != OG_METHOD_GET) {
4360                        err = og_client_method_not_found(cli);
4361                        goto err_process_rest_payload;
4362                }
4363                if (!root) {
4364                        syslog(LOG_ERR,
4365                               "command client info with no payload\n");
4366                        err = og_client_bad_request(cli);
4367                        goto err_process_rest_payload;
4368                }
4369
4370                err = og_cmd_get_client_info(root, &params, buf_reply);
4371        } else if (!strncmp(cmd, "client/add", strlen("client/add"))) {
4372                if (method != OG_METHOD_POST) {
4373                        err = og_client_method_not_found(cli);
4374                        goto err_process_rest_payload;
4375                }
4376
4377                if (!root) {
4378                        syslog(LOG_ERR,
4379                               "command client info with no payload\n");
4380                        err = og_client_bad_request(cli);
4381                        goto err_process_rest_payload;
4382                }
4383
4384                err = og_cmd_post_client_add(root, &params, buf_reply);
4385        } else if (!strncmp(cmd, "client/delete", strlen("client/delete"))) {
4386                if (method != OG_METHOD_POST) {
4387                        err = og_client_method_not_found(cli);
4388                        goto err_process_rest_payload;
4389                }
4390
4391                if (!root) {
4392                        syslog(LOG_ERR,
4393                               "command client delete with no payload\n");
4394                        err = og_client_bad_request(cli);
4395                        goto err_process_rest_payload;
4396                }
4397
4398                err = og_cmd_post_client_delete(root, &params);
4399        } else if (!strncmp(cmd, "wol", strlen("wol"))) {
4400                if (method != OG_METHOD_POST) {
4401                        err = og_client_method_not_found(cli);
4402                        goto err_process_rest_payload;
4403                }
4404
4405                if (!root) {
4406                        syslog(LOG_ERR, "command wol with no payload\n");
4407                        err = og_client_bad_request(cli);
4408                        goto err_process_rest_payload;
4409                }
4410                err = og_cmd_wol(root, &params);
4411        } else if (!strncmp(cmd, "shell/run", strlen("shell/run"))) {
4412                if (method != OG_METHOD_POST) {
4413                        err = og_client_method_not_found(cli);
4414                        goto err_process_rest_payload;
4415                }
4416
4417                if (!root) {
4418                        syslog(LOG_ERR, "command run with no payload\n");
4419                        err = og_client_bad_request(cli);
4420                        goto err_process_rest_payload;
4421                }
4422                err = og_cmd_run_post(root, &params);
4423        } else if (!strncmp(cmd, "shell/output", strlen("shell/output"))) {
4424                if (method != OG_METHOD_POST) {
4425                        err = og_client_method_not_found(cli);
4426                        goto err_process_rest_payload;
4427                }
4428
4429                if (!root) {
4430                        syslog(LOG_ERR, "command output with no payload\n");
4431                        err = og_client_bad_request(cli);
4432                        goto err_process_rest_payload;
4433                }
4434
4435                err = og_cmd_run_get(root, &params, buf_reply);
4436        } else if (!strncmp(cmd, "session", strlen("session"))) {
4437                if (method != OG_METHOD_POST && method != OG_METHOD_GET) {
4438                        err = og_client_method_not_found(cli);
4439                        goto err_process_rest_payload;
4440                }
4441
4442                if (!root) {
4443                        syslog(LOG_ERR, "command session with no payload\n");
4444                        err = og_client_bad_request(cli);
4445                        goto err_process_rest_payload;
4446                }
4447
4448                if (method == OG_METHOD_POST)
4449                        err = og_cmd_session(root, &params);
4450                else
4451                        err = og_cmd_get_session(root, &params, buf_reply);
4452        } else if (!strncmp(cmd, "scopes", strlen("scopes"))) {
4453                if (method != OG_METHOD_GET) {
4454                        err = og_client_method_not_found(cli);
4455                        goto err_process_rest_payload;
4456                }
4457
4458                if (root) {
4459                        syslog(LOG_ERR, "command scopes with payload\n");
4460                        err = og_client_bad_request(cli);
4461                        goto err_process_rest_payload;
4462                }
4463
4464                err = og_cmd_scope_get(root, &params, buf_reply);
4465        } else if (!strncmp(cmd, "poweroff", strlen("poweroff"))) {
4466                if (method != OG_METHOD_POST) {
4467                        err = og_client_method_not_found(cli);
4468                        goto err_process_rest_payload;
4469                }
4470
4471                if (!root) {
4472                        syslog(LOG_ERR, "command poweroff with no payload\n");
4473                        err = og_client_bad_request(cli);
4474                        goto err_process_rest_payload;
4475                }
4476                err = og_cmd_poweroff(root, &params);
4477        } else if (!strncmp(cmd, "reboot", strlen("reboot"))) {
4478                if (method != OG_METHOD_POST) {
4479                        err = og_client_method_not_found(cli);
4480                        goto err_process_rest_payload;
4481                }
4482
4483                if (!root) {
4484                        syslog(LOG_ERR, "command reboot with no payload\n");
4485                        err = og_client_bad_request(cli);
4486                        goto err_process_rest_payload;
4487                }
4488                err = og_cmd_reboot(root, &params);
4489        } else if (!strncmp(cmd, "mode", strlen("mode"))) {
4490                if (method != OG_METHOD_GET && method != OG_METHOD_POST) {
4491                        err = og_client_method_not_found(cli);
4492                        goto err_process_rest_payload;
4493                }
4494
4495                if (method == OG_METHOD_POST && !root) {
4496                        syslog(LOG_ERR, "command mode with no payload\n");
4497                        err = og_client_bad_request(cli);
4498                        goto err_process_rest_payload;
4499                }
4500
4501                if (method == OG_METHOD_GET)
4502                        err = og_cmd_get_modes(root, &params, buf_reply);
4503                else if (method == OG_METHOD_POST)
4504                        err = og_cmd_post_modes(root, &params);
4505        } else if (!strncmp(cmd, "stop", strlen("stop"))) {
4506                if (method != OG_METHOD_POST) {
4507                        err = og_client_method_not_found(cli);
4508                        goto err_process_rest_payload;
4509                }
4510
4511                if (!root) {
4512                        syslog(LOG_ERR, "command stop with no payload\n");
4513                        err = og_client_bad_request(cli);
4514                        goto err_process_rest_payload;
4515                }
4516                err = og_cmd_stop(root, &params);
4517        } else if (!strncmp(cmd, "refresh", strlen("refresh"))) {
4518                if (method != OG_METHOD_POST) {
4519                        err = og_client_method_not_found(cli);
4520                        goto err_process_rest_payload;
4521                }
4522
4523                if (!root) {
4524                        syslog(LOG_ERR, "command refresh with no payload\n");
4525                        err = og_client_bad_request(cli);
4526                        goto err_process_rest_payload;
4527                }
4528                err = og_cmd_refresh(root, &params);
4529        } else if (!strncmp(cmd, "hardware", strlen("hardware"))) {
4530                if (method != OG_METHOD_GET && method != OG_METHOD_POST) {
4531                        err = og_client_method_not_found(cli);
4532                        goto err_process_rest_payload;
4533                }
4534
4535                if (!root) {
4536                        syslog(LOG_ERR, "command hardware with no payload\n");
4537                        err = og_client_bad_request(cli);
4538                        goto err_process_rest_payload;
4539                }
4540
4541                if (method == OG_METHOD_GET)
4542                        err = og_cmd_get_hardware(root, &params, buf_reply);
4543                else if (method == OG_METHOD_POST)
4544                        err = og_cmd_hardware(root, &params);
4545        } else if (!strncmp(cmd, "software", strlen("software"))) {
4546                if (method != OG_METHOD_POST && method != OG_METHOD_GET) {
4547                        err = og_client_method_not_found(cli);
4548                        goto err_process_rest_payload;
4549                }
4550
4551                if (!root) {
4552                        syslog(LOG_ERR, "command software with no payload\n");
4553                        err = og_client_bad_request(cli);
4554                        goto err_process_rest_payload;
4555                }
4556
4557                if (method == OG_METHOD_POST)
4558                        err = og_cmd_software(root, &params);
4559                else
4560                        err = og_cmd_get_software(root, &params, buf_reply);
4561        } else if (!strncmp(cmd, "images", strlen("images"))) {
4562                if (method != OG_METHOD_GET) {
4563                        err = og_client_method_not_found(cli);
4564                        goto err_process_rest_payload;
4565                }
4566
4567                if (root) {
4568                        err = og_client_bad_request(cli);
4569                        goto err_process_rest_payload;
4570                }
4571
4572                err = og_cmd_images(buf_reply);
4573        } else if (!strncmp(cmd, "image/create", strlen("image/create"))) {
4574                if (method != OG_METHOD_POST) {
4575                        err = og_client_method_not_found(cli);
4576                        goto err_process_rest_payload;
4577                }
4578
4579                if (!root) {
4580                        syslog(LOG_ERR, "command create with no payload\n");
4581                        err = og_client_bad_request(cli);
4582                        goto err_process_rest_payload;
4583                }
4584                err = og_cmd_create_image(root, &params);
4585        } else if (!strncmp(cmd, "image/restore", strlen("image/restore"))) {
4586                if (method != OG_METHOD_POST) {
4587                        err = og_client_method_not_found(cli);
4588                        goto err_process_rest_payload;
4589                }
4590
4591                if (!root) {
4592                        syslog(LOG_ERR, "command create with no payload\n");
4593                        err = og_client_bad_request(cli);
4594                        goto err_process_rest_payload;
4595                }
4596                err = og_cmd_restore_image(root, &params);
4597        } else if (!strncmp(cmd, "setup", strlen("setup"))) {
4598                if (method != OG_METHOD_POST) {
4599                        err = og_client_method_not_found(cli);
4600                        goto err_process_rest_payload;
4601                }
4602
4603                if (!root) {
4604                        syslog(LOG_ERR, "command create with no payload\n");
4605                        err = og_client_bad_request(cli);
4606                        goto err_process_rest_payload;
4607                }
4608                err = og_cmd_setup(root, &params);
4609        } else if (!strncmp(cmd, "run/schedule", strlen("run/schedule"))) {
4610                if (method != OG_METHOD_POST) {
4611                        err = og_client_method_not_found(cli);
4612                        goto err_process_rest_payload;
4613                }
4614
4615                if (!root) {
4616                        syslog(LOG_ERR, "command create with no payload\n");
4617                        err = og_client_bad_request(cli);
4618                        goto err_process_rest_payload;
4619                }
4620
4621                err = og_cmd_run_schedule(root, &params);
4622        } else if (!strncmp(cmd, "task/run", strlen("task/run"))) {
4623                if (method != OG_METHOD_POST) {
4624                        err = og_client_method_not_found(cli);
4625                        goto err_process_rest_payload;
4626                }
4627
4628                if (!root) {
4629                        syslog(LOG_ERR, "command task with no payload\n");
4630                        err = og_client_bad_request(cli);
4631                        goto err_process_rest_payload;
4632                }
4633                err = og_cmd_task_post(root, &params);
4634        } else if (!strncmp(cmd, "schedule/create",
4635                            strlen("schedule/create"))) {
4636                if (method != OG_METHOD_POST) {
4637                        err = og_client_method_not_found(cli);
4638                        goto err_process_rest_payload;
4639                }
4640
4641                if (!root) {
4642                        syslog(LOG_ERR, "command task with no payload\n");
4643                        err = og_client_bad_request(cli);
4644                        goto err_process_rest_payload;
4645                }
4646                err = og_cmd_schedule_create(root, &params);
4647        } else if (!strncmp(cmd, "schedule/delete",
4648                            strlen("schedule/delete"))) {
4649                if (method != OG_METHOD_POST) {
4650                        err = og_client_method_not_found(cli);
4651                        goto err_process_rest_payload;
4652                }
4653
4654                if (!root) {
4655                        syslog(LOG_ERR, "command task with no payload\n");
4656                        err = og_client_bad_request(cli);
4657                        goto err_process_rest_payload;
4658                }
4659                err = og_cmd_schedule_delete(root, &params);
4660        } else if (!strncmp(cmd, "schedule/update",
4661                            strlen("schedule/update"))) {
4662                if (method != OG_METHOD_POST) {
4663                        err = og_client_method_not_found(cli);
4664                        goto err_process_rest_payload;
4665                }
4666
4667                if (!root) {
4668                        syslog(LOG_ERR, "command task with no payload\n");
4669                        err = og_client_bad_request(cli);
4670                        goto err_process_rest_payload;
4671                }
4672                err = og_cmd_schedule_update(root, &params);
4673        } else if (!strncmp(cmd, "schedule/get",
4674                            strlen("schedule/get"))) {
4675                if (method != OG_METHOD_POST) {
4676                        err = og_client_method_not_found(cli);
4677                        goto err_process_rest_payload;
4678                }
4679
4680                err = og_cmd_schedule_get(root, &params, buf_reply);
4681        } else if (!strncmp(cmd, "oglive/list",
4682                            strlen("oglive/list"))) {
4683                if (method != OG_METHOD_GET) {
4684                        err = og_client_method_not_found(cli);
4685                        goto err_process_rest_payload;
4686                }
4687
4688                err = og_cmd_oglive_list(buf_reply);
4689        } else if (!strncmp(cmd, "center/add",
4690                            strlen("center/add"))) {
4691                if (method != OG_METHOD_POST) {
4692                        err = og_client_method_not_found(cli);
4693                        goto err_process_rest_payload;
4694                }
4695
4696                err = og_cmd_post_center_add(root, &params, buf_reply);
4697        } else if (!strncmp(cmd, "center/delete", strlen("center/delete"))) {
4698                if (method != OG_METHOD_POST) {
4699                        err = og_client_method_not_found(cli);
4700                        goto err_process_rest_payload;
4701                }
4702
4703                if (!root) {
4704                        syslog(LOG_ERR,
4705                               "command center delete with no payload\n");
4706                        err = og_client_bad_request(cli);
4707                        goto err_process_rest_payload;
4708                }
4709                err = og_cmd_post_center_delete(root, &params);
4710        } else if (!strncmp(cmd, "room/add",
4711                            strlen("room/add"))) {
4712                if (method != OG_METHOD_POST) {
4713                        err = og_client_method_not_found(cli);
4714                        goto err_process_rest_payload;
4715                }
4716
4717                if (!root) {
4718                        syslog(LOG_ERR, "command task with no payload\n");
4719                        err = og_client_bad_request(cli);
4720                        goto err_process_rest_payload;
4721                }
4722                err = og_cmd_post_room_add(root, &params);
4723        } else if (!strncmp(cmd, "room/delete", strlen("room/delete"))) {
4724                if (method != OG_METHOD_POST) {
4725                        err = og_client_method_not_found(cli);
4726                        goto err_process_rest_payload;
4727                }
4728
4729                if (!root) {
4730                        syslog(LOG_ERR,
4731                               "command room delete with no payload\n");
4732                        err = og_client_bad_request(cli);
4733                        goto err_process_rest_payload;
4734                }
4735                err = og_cmd_post_room_delete(root, &params);
4736        } else {
4737                syslog(LOG_ERR, "unknown command: %.32s ...\n", cmd);
4738                err = og_client_not_found(cli);
4739        }
4740
4741        json_decref(root);
4742
4743        if (err < 0)
4744                return og_client_bad_request(cli);
4745
4746        return og_client_ok(cli, buf_reply);
4747
4748err_process_rest_payload:
4749        json_decref(root);
4750
4751        return err;
4752}
Note: See TracBrowser for help on using the repository browser.