source: ogServer-Git/src/rest.c @ 5a3fd51

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

#1065 client: add support for ogclient linux state

ogClient can be run in linux mode, intended for exposing some
ogServer commands when running in a linux distribution.

When connecting with a client in linux mode, do not expect a full
partition setup response. Just expect a 'status', and then accept
the connection without updating any partition information in
the database.

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