source: ogServer-Git/src/rest.c @ 5558fbc

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

#1051 Initialize task_id once in og_cmd_post_schedule_command

Fixes task_id re-initialization in commit 33d8cecfe.

Task id is to be initialized with the "session" value and can be done
out of the for loop it was before. Avoiding unnecesary snprintf's with
the same value.

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