source: ogServer-Git/src/rest.c @ 772811e

Last change on this file since 772811e was 772811e, checked in by Jose M. Guisado <jguisado@…>, 3 years ago

#1065 Add support for client events

ogServer supports events from clients in an agent mode
(linux/windows).

Client sends event information (eg. user login/logout)
via a 103 Early Hints http response message.

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