source: ogServer-Git/src/rest.c @ 141b079

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

#915 Add schedule/command

Enables ogserver to schedule commands (also referred as actions in
legacy web console jargon).

This feature enables ogserver to write in the "acciones" table in order
to have full capabilities for command scheduling purposes, thus not
depending in the legacy web console to insert into "acciones" table.

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