source: ogServer-Git/src/rest.c @ dd578a9

Last change on this file since dd578a9 was dd578a9, checked in by Javier Sánchez Parra <jsanchez@…>, 3 years ago

#915 Add POST /oglive/set REST request

This patch allows you to update clients' database entry and PXE boot
file with the specified ogLive.

If you specify either an incorrect or unexisting ogLive, then, clients
use the default ogLive image. You can query ogLives installed on the
server with ogServer's GET /oglive/list API.

If you set the oglive field to "default", then the default ogLive is
used.

Request: POST /oglive/set
{

"clients": ["192.168.56.11", "192.168.56.12"],
"name": "ogLive-5.4.0-r20200629"

}
Response: 200 OK

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