source: ogServer-Git/src/rest.c @ 90eab86

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

#915 fix "response too large" error path

Otherwise, ogServer sends "200 OK" after a "500 Internal Server Error
error" response.

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