source: ogServer-Git/src/rest.c @ 6e70916

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

#915 Remove useless WoL shim code

Levanta() is not required, iterate over the array of IP address and make
direct calls to WakeUp?().

This is also implicitly fixing up a memleak in og_cmd_wol().

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