mirror of
https://dev.iopsys.eu/bbf/icwmp.git
synced 2025-12-10 07:44:41 +01:00
Static code fixes
This commit is contained in:
parent
9bd32215e6
commit
14bfffafc3
20 changed files with 69 additions and 65 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -35,3 +35,5 @@ missing
|
|||
/ltmain.sh
|
||||
*.gcno
|
||||
*.gcda
|
||||
/icwmpd
|
||||
/Makefile
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ include:
|
|||
variables:
|
||||
DEBUG: 'TRUE'
|
||||
COMMON_IMAGE: "iopsys/code-analysis:0.25"
|
||||
RUN_CPPCHECK: "cppcheck --enable=all --inline-suppr --include=/usr/include/uci.h --suppress=unusedFunction -i ./test/"
|
||||
SOURCE_FOLDER: "."
|
||||
|
||||
stages:
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ int get_bkp_attribute_index_type(char *name)
|
|||
void load_specific_backup_attributes(mxml_node_t *tree, struct backup_attributes *bkp_attrs)
|
||||
{
|
||||
mxml_node_t *b = tree, *c;
|
||||
int idx = -1;
|
||||
int idx;
|
||||
void **ptr;
|
||||
|
||||
b = mxmlWalkNext(b, tree, MXML_DESCEND);
|
||||
|
|
@ -213,7 +213,7 @@ mxml_node_t *bkp_session_node_found(mxml_node_t *tree, char *name, struct search
|
|||
if (c->type == MXML_ELEMENT && strcmp(keys[i].name, c->value.element.name) == 0) {
|
||||
d = c;
|
||||
d = mxmlWalkNext(d, c, MXML_DESCEND);
|
||||
if ((keys[i].value == NULL) || (d && d->type == MXML_OPAQUE && keys[i].value != NULL && strcmp(keys[i].value, d->value.opaque) == 0))
|
||||
if ((keys[i].value == NULL) || (d && d->type == MXML_OPAQUE && STRCMP(keys[i].value, d->value.opaque) == 0))
|
||||
i++;
|
||||
}
|
||||
c = mxmlWalkNext(c, b, MXML_NO_DESCEND);
|
||||
|
|
@ -521,7 +521,7 @@ void bkp_session_delete_apply_schedule_download(struct apply_schedule_download *
|
|||
|
||||
void bkp_session_insert_change_du_state(struct change_du_state *pchange_du_state)
|
||||
{
|
||||
struct operations *p;
|
||||
struct operations *p = NULL;
|
||||
char schedule_time[128];
|
||||
mxml_node_t *b, *n;
|
||||
|
||||
|
|
@ -663,7 +663,7 @@ void bkp_session_delete_upload(struct upload *pupload)
|
|||
void bkp_session_insert_du_state_change_complete(struct du_state_change_complete *pdu_state_change_complete)
|
||||
{
|
||||
char schedule_time[128], resolved[8], fault_code[8];
|
||||
struct opresult *p;
|
||||
struct opresult *p = NULL;
|
||||
mxml_node_t *b;
|
||||
|
||||
pthread_mutex_lock(&mutex_backup_session);
|
||||
|
|
@ -800,6 +800,7 @@ void load_queue_event(mxml_node_t *tree, struct cwmp *cwmp)
|
|||
while (b) {
|
||||
if (b->type == MXML_ELEMENT) {
|
||||
if (strcmp(b->value.element.name, "command_key") == 0) {
|
||||
// cppcheck-suppress knownConditionTrueFalse
|
||||
if (idx != -1) {
|
||||
if (EVENT_CONST[idx].RETRY & EVENT_RETRY_AFTER_REBOOT) {
|
||||
event_container_save = cwmp_add_event_container(cwmp, idx, ((command_key != NULL) ? command_key : ""));
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
AC_INIT([icwmp], [0.1], [mohamed.kallel@pivasoftware.com])
|
||||
AC_INIT([icwmp], [1.0], [dev@iopsys.eu])
|
||||
AM_INIT_AUTOMAKE
|
||||
AC_CONFIG_SRCDIR([cwmp.c])
|
||||
|
||||
|
|
|
|||
10
cwmp.c
10
cwmp.c
|
|
@ -325,7 +325,7 @@ int run_session_end_func(void)
|
|||
|
||||
static void cwmp_schedule_session(struct cwmp *cwmp)
|
||||
{
|
||||
int t, error = CWMP_OK;
|
||||
int t;
|
||||
struct timespec time_to_wait = { 0, 0 };
|
||||
bool retry = false;
|
||||
char *exec_download = NULL;
|
||||
|
|
@ -335,6 +335,7 @@ static void cwmp_schedule_session(struct cwmp *cwmp)
|
|||
while (1) {
|
||||
struct list_head *ilist;
|
||||
struct session *session;
|
||||
int error;
|
||||
|
||||
pthread_mutex_lock(&(cwmp->mutex_session_send));
|
||||
ilist = (&(cwmp->head_session_queue))->next;
|
||||
|
|
@ -460,15 +461,14 @@ void load_forced_inform_json_file(struct cwmp *cwmp)
|
|||
const struct blobmsg_policy p[1] = { { "forced_inform", BLOBMSG_TYPE_ARRAY } };
|
||||
struct blob_attr *tb[1] = { NULL };
|
||||
blobmsg_parse(p, 1, tb, blobmsg_data(bbuf.head), blobmsg_len(bbuf.head));
|
||||
if (!tb[0])
|
||||
return;
|
||||
custom_forced_inform_list = tb[0];
|
||||
if (custom_forced_inform_list == NULL) {
|
||||
if (tb[0] == NULL) {
|
||||
CWMP_LOG(WARNING, "The JSON file %s doesn't contain a forced inform parameters list", cwmp->conf.custom_notify_json);
|
||||
blob_buf_free(&bbuf);
|
||||
return;
|
||||
}
|
||||
|
||||
custom_forced_inform_list = tb[0];
|
||||
|
||||
blobmsg_for_each_attr(cur, custom_forced_inform_list, rem)
|
||||
{
|
||||
char parameter_path[128];
|
||||
|
|
|
|||
13
cwmp_uci.c
13
cwmp_uci.c
|
|
@ -323,7 +323,7 @@ int uci_set_value_by_path(char *path, char *value, uci_config_paths uci_type)
|
|||
CWMP_LOG(ERROR, "UCI delete not succeed %s", path);
|
||||
return UCI_ERR_NOTFOUND;
|
||||
}
|
||||
return UCI_OK;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cwmp_uci_set_value_by_path(char *path, char *value)
|
||||
|
|
@ -499,7 +499,7 @@ int uci_add_list_value(char *cmd, uci_config_paths uci_type)
|
|||
CWMP_LOG(ERROR, "UCI delete not succeed %s", cmd);
|
||||
return UCI_ERR_NOTFOUND;
|
||||
}
|
||||
return UCI_OK;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -587,7 +587,7 @@ int uci_delete_value(char *path, int uci_type)
|
|||
CWMP_LOG(ERROR, "UCI delete not succeed %s", path);
|
||||
return CWMP_GEN_ERR;
|
||||
}
|
||||
return CWMP_OK;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cwmp_uci_get_section_type(char *package, char *section, uci_config_paths uci_type, char **value)
|
||||
|
|
@ -742,12 +742,15 @@ int cwmp_uci_export(const char *output_path, uci_config_paths uci_type)
|
|||
char **configs = NULL;
|
||||
char **p;
|
||||
|
||||
if ((uci_list_configs(uci_save_conf_paths[uci_type].uci_ctx, &configs) != UCI_OK) || !configs)
|
||||
if (uci_list_configs(uci_save_conf_paths[uci_type].uci_ctx, &configs) != UCI_OK)
|
||||
return -1;
|
||||
|
||||
if (configs == NULL)
|
||||
return -1;
|
||||
|
||||
for (p = configs; *p; p++)
|
||||
cwmp_uci_export_package(*p, output_path, uci_type);
|
||||
|
||||
free(configs);
|
||||
FREE(configs);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -362,7 +362,7 @@ void *thread_cwmp_rpc_cpe_download(void *v)
|
|||
struct download *pdownload;
|
||||
struct timespec download_timeout = { 0, 0 };
|
||||
time_t current_time, stime;
|
||||
int error = FAULT_CPE_NO_FAULT;
|
||||
int error;
|
||||
struct transfer_complete *ptransfer_complete;
|
||||
long int time_of_grace = 3600, timeout;
|
||||
|
||||
|
|
|
|||
4
event.c
4
event.c
|
|
@ -386,7 +386,7 @@ void *thread_event_periodic(void *v)
|
|||
|
||||
bool event_exist_in_list(struct cwmp *cwmp, int event)
|
||||
{
|
||||
struct event_container *event_container;
|
||||
struct event_container *event_container = NULL;
|
||||
list_for_each_entry (event_container, cwmp->head_event_container, list) {
|
||||
if (event_container->code == event)
|
||||
return true;
|
||||
|
|
@ -507,7 +507,7 @@ int cwmp_root_cause_events(struct cwmp *cwmp)
|
|||
return CWMP_OK;
|
||||
}
|
||||
|
||||
int cwmp_get_int_event_code(char *code)
|
||||
int cwmp_get_int_event_code(const char *code)
|
||||
{
|
||||
if (code && code[0] == '1')
|
||||
return EVENT_IDX_1BOOT;
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@
|
|||
#define FIREWALL_CWMP "/etc/firewall.cwmp"
|
||||
#define CWMP_VARSTATE_UCI_PACKAGE "/var/state/cwmp"
|
||||
|
||||
#define STRCMP(S1, S2) ((S1 != NULL && S2 != NULL) ? strcmp(S1, S2) : -1)
|
||||
extern char *commandKey;
|
||||
extern bool thread_end;
|
||||
extern bool signal_exit;
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ void cwmp_save_event_container(struct event_container *event_container);
|
|||
void *thread_event_periodic(void *v);
|
||||
void connection_request_ip_value_change(struct cwmp *cwmp, int version);
|
||||
void connection_request_port_value_change(struct cwmp *cwmp, int port);
|
||||
int cwmp_get_int_event_code(char *code);
|
||||
int cwmp_get_int_event_code(const char *code);
|
||||
bool event_exist_in_list(struct cwmp *cwmp, int event);
|
||||
int cwmp_root_cause_events(struct cwmp *cwmp);
|
||||
int cwmp_root_cause_transfer_complete(struct cwmp *cwmp, struct transfer_complete *p);
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@
|
|||
#include "common.h"
|
||||
#define ARRAY_MAX 8
|
||||
|
||||
extern struct ubus_context *ubus_ctx;
|
||||
int cwmp_ubus_init(struct cwmp *cwmp);
|
||||
void cwmp_ubus_exit(void);
|
||||
|
||||
|
|
|
|||
2
log.c
2
log.c
|
|
@ -129,7 +129,7 @@ void puts_log(int severity, const char *fmt, ...)
|
|||
}
|
||||
}
|
||||
va_start(args, fmt);
|
||||
i += vsprintf(buf + i, (const char *)fmt, args);
|
||||
vsprintf(buf + i, (const char *)fmt, args);
|
||||
if (enable_log_file) {
|
||||
CWMP_STRNCPY(buf_file, buf, sizeof(buf_file));
|
||||
buf_file[strlen(buf)] = '\n';
|
||||
|
|
|
|||
2
md5.c
2
md5.c
|
|
@ -54,7 +54,7 @@ static void byteReverse(unsigned char *buf, unsigned longs)
|
|||
* reflect the addition of 16 longwords of new data. MD5Update blocks
|
||||
* the data and converts bytes into longwords for this routine.
|
||||
*/
|
||||
static void md5_transform(uint32_t buf[4], uint32_t in[16])
|
||||
static void md5_transform(uint32_t buf[4], const uint32_t in[16])
|
||||
{
|
||||
uint32_t a, b, c, d;
|
||||
|
||||
|
|
|
|||
|
|
@ -263,6 +263,7 @@ char *cwmp_get_parameter_attributes(char *parameter_name, struct list_head *para
|
|||
bool parameter_is_other_notif_object_child(char *parent, char *parameter)
|
||||
{
|
||||
struct list_head list_iter, *list_ptr;
|
||||
// cppcheck-suppress unreadVariable
|
||||
list_iter.next = list_param_obj_notify.next;
|
||||
list_iter.prev = list_param_obj_notify.prev;
|
||||
struct cwmp_dm_parameter *dm_parameter = NULL;
|
||||
|
|
@ -318,7 +319,7 @@ char* updated_list_param_leaf_notify_with_sub_parameter_list(struct list_head *l
|
|||
|
||||
void create_list_param_leaf_notify(struct list_head *list_param_leaf_notify, void (*update_notify_file_line_arg)(FILE *notify_file, char *param_name, char *param_type, char *param_value, int notification), FILE* notify_file_arg)
|
||||
{
|
||||
struct cwmp_dm_parameter *param_iter;
|
||||
struct cwmp_dm_parameter *param_iter = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < (int)ARRAY_SIZE(forced_notifications_parameters); i++)
|
||||
|
|
@ -411,18 +412,14 @@ void load_custom_notify_json(struct cwmp *cwmp)
|
|||
const struct blobmsg_policy p_notif[1] = { { "custom_notification", BLOBMSG_TYPE_ARRAY } };
|
||||
struct blob_attr *tb_notif[1] = { NULL};
|
||||
blobmsg_parse(p_notif, 1, tb_notif, blobmsg_data(bbuf.head), blobmsg_len(bbuf.head));
|
||||
if (!tb_notif[0]) {
|
||||
creat(NOTIFY_FILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
return;
|
||||
}
|
||||
custom_notify_list = tb_notif[0];
|
||||
|
||||
if (custom_notify_list == NULL) {
|
||||
if (tb_notif[0] == NULL) {
|
||||
CWMP_LOG(WARNING, "The JSON file %s doesn't contain a notify parameters list", cwmp->conf.custom_notify_json);
|
||||
blob_buf_free(&bbuf);
|
||||
creat(NOTIFY_FILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
return;
|
||||
}
|
||||
custom_notify_list = tb_notif[0];
|
||||
|
||||
const struct blobmsg_policy p[2] = { { "parameter", BLOBMSG_TYPE_STRING }, { "notify_type", BLOBMSG_TYPE_STRING } };
|
||||
blobmsg_for_each_attr(cur, custom_notify_list, rem)
|
||||
{
|
||||
|
|
@ -561,7 +558,7 @@ void *thread_periodic_check_notify(void *v)
|
|||
bool periodic_enable;
|
||||
struct timespec periodic_timeout = { 0, 0 };
|
||||
time_t current_time;
|
||||
int is_notify = 0;
|
||||
int is_notify;
|
||||
|
||||
periodic_interval = cwmp->conf.periodic_notify_interval;
|
||||
periodic_enable = cwmp->conf.periodic_notify_enable;
|
||||
|
|
|
|||
16
reboot.c
16
reboot.c
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
static pthread_t delay_reboot_thread;
|
||||
static pthread_t delay_schedule_thread;
|
||||
static int g_curr_delay_reboot = -1;
|
||||
static time_t g_curr_schedule_redoot = 0;
|
||||
|
||||
static void *thread_delay_reboot(void *arg)
|
||||
{
|
||||
|
|
@ -104,18 +106,16 @@ static void create_schedule_reboot_thread(struct cwmp *cwmp, bool thread_exist)
|
|||
|
||||
void launch_reboot_methods(struct cwmp *cwmp)
|
||||
{
|
||||
int curr_delay_reboot = -1;
|
||||
time_t curr_schedule_redoot = 0;
|
||||
|
||||
if (cwmp->conf.delay_reboot != curr_delay_reboot && cwmp->conf.delay_reboot > 0) {
|
||||
if (cwmp->conf.delay_reboot != g_curr_delay_reboot && cwmp->conf.delay_reboot > 0) {
|
||||
|
||||
create_delay_reboot_thread(cwmp, (curr_delay_reboot != -1));
|
||||
curr_delay_reboot = cwmp->conf.delay_reboot;
|
||||
create_delay_reboot_thread(cwmp, (g_curr_delay_reboot != -1));
|
||||
g_curr_delay_reboot = cwmp->conf.delay_reboot;
|
||||
}
|
||||
|
||||
if (cwmp->conf.schedule_reboot != curr_schedule_redoot && (cwmp->conf.schedule_reboot - time(NULL)) > 0) {
|
||||
if (cwmp->conf.schedule_reboot != g_curr_schedule_redoot && (cwmp->conf.schedule_reboot - time(NULL)) > 0) {
|
||||
|
||||
create_schedule_reboot_thread(cwmp, (curr_schedule_redoot != 0));
|
||||
curr_schedule_redoot = cwmp->conf.schedule_reboot;
|
||||
create_schedule_reboot_thread(cwmp, (g_curr_schedule_redoot != 0));
|
||||
g_curr_schedule_redoot = cwmp->conf.schedule_reboot;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
38
rpc_soap.c
38
rpc_soap.c
|
|
@ -2253,27 +2253,25 @@ int cwmp_handle_rpc_cpe_schedule_download(struct session *session, struct rpc *r
|
|||
if (!t)
|
||||
goto fault;
|
||||
|
||||
if (error == FAULT_CPE_NO_FAULT) {
|
||||
pthread_mutex_lock(&mutex_schedule_download);
|
||||
list_add_tail(&(schedule_download->list), &(list_schedule_download));
|
||||
if (schedule_download_delay[0] != 0) {
|
||||
count_download_queue++;
|
||||
}
|
||||
while (i > 0) {
|
||||
i--;
|
||||
schedule_download->timewindowstruct[i].windowstart = time(NULL) + schedule_download_delay[i * 2];
|
||||
schedule_download->timewindowstruct[i].windowend = time(NULL) + schedule_download_delay[i * 2 + 1];
|
||||
}
|
||||
bkp_session_insert_schedule_download(schedule_download);
|
||||
bkp_session_save();
|
||||
if (schedule_download_delay[0] != 0) {
|
||||
CWMP_LOG(INFO, "Schedule download will start in %us", schedule_download_delay[0]);
|
||||
} else {
|
||||
CWMP_LOG(INFO, "Schedule Download will start at the end of session");
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_schedule_download);
|
||||
pthread_cond_signal(&threshold_schedule_download);
|
||||
pthread_mutex_lock(&mutex_schedule_download);
|
||||
list_add_tail(&(schedule_download->list), &(list_schedule_download));
|
||||
if (schedule_download_delay[0] != 0) {
|
||||
count_download_queue++;
|
||||
}
|
||||
while (i > 0) {
|
||||
i--;
|
||||
schedule_download->timewindowstruct[i].windowstart = time(NULL) + schedule_download_delay[i * 2];
|
||||
schedule_download->timewindowstruct[i].windowend = time(NULL) + schedule_download_delay[i * 2 + 1];
|
||||
}
|
||||
bkp_session_insert_schedule_download(schedule_download);
|
||||
bkp_session_save();
|
||||
if (schedule_download_delay[0] != 0) {
|
||||
CWMP_LOG(INFO, "Schedule download will start in %us", schedule_download_delay[0]);
|
||||
} else {
|
||||
CWMP_LOG(INFO, "Schedule Download will start at the end of session");
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_schedule_download);
|
||||
pthread_cond_signal(&threshold_schedule_download);
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -103,7 +103,8 @@ struct session *cwmp_add_queue_session(struct cwmp *cwmp)
|
|||
INIT_LIST_HEAD(&(session->head_event_container));
|
||||
INIT_LIST_HEAD(&(session->head_rpc_acs));
|
||||
INIT_LIST_HEAD(&(session->head_rpc_cpe));
|
||||
if ((rpc_acs = cwmp_add_session_rpc_acs_head(session, RPC_ACS_INFORM)) == NULL) {
|
||||
rpc_acs = cwmp_add_session_rpc_acs_head(session, RPC_ACS_INFORM);
|
||||
if (rpc_acs == NULL) {
|
||||
FREE(session);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
6
ubus.c
6
ubus.c
|
|
@ -354,7 +354,7 @@ int cwmp_ubus_call(const char *obj, const char *method, const struct cwmp_ubus_a
|
|||
}
|
||||
blobmsg_close_array(&b, a);
|
||||
} else if (u_args[i].type == UBUS_List_Param_Set) {
|
||||
struct cwmp_dm_parameter *param_value;
|
||||
struct cwmp_dm_parameter *param_value = NULL;
|
||||
void *a;
|
||||
a = blobmsg_open_array(&b, u_args[i].key);
|
||||
list_for_each_entry (param_value, u_args[i].val.param_value_list, list) {
|
||||
|
|
@ -368,7 +368,7 @@ int cwmp_ubus_call(const char *obj, const char *method, const struct cwmp_ubus_a
|
|||
}
|
||||
blobmsg_close_array(&b, a);
|
||||
} else if (u_args[i].type == UBUS_List_Param_Get) {
|
||||
struct cwmp_dm_parameter *param_value;
|
||||
struct cwmp_dm_parameter *param_value = NULL;
|
||||
void *a;
|
||||
a = blobmsg_open_array(&b, u_args[i].key);
|
||||
list_for_each_entry (param_value, u_args[i].val.param_value_list, list) {
|
||||
|
|
@ -378,7 +378,7 @@ int cwmp_ubus_call(const char *obj, const char *method, const struct cwmp_ubus_a
|
|||
}
|
||||
blobmsg_close_array(&b, a);
|
||||
} else if (u_args[i].type == UBUS_Obj_Obj) {
|
||||
struct cwmp_dm_parameter *param_value;
|
||||
struct cwmp_dm_parameter *param_value = NULL;
|
||||
json_object *input_json_obj = json_object_new_object();
|
||||
list_for_each_entry (param_value, u_args[i].val.param_value_list, list) {
|
||||
if (!param_value->name)
|
||||
|
|
|
|||
3
upload.c
3
upload.c
|
|
@ -97,7 +97,7 @@ int cwmp_launch_upload(struct upload *pupload, struct transfer_complete **ptrans
|
|||
int error = FAULT_CPE_NO_FAULT;
|
||||
char *upload_startTime;
|
||||
struct transfer_complete *p;
|
||||
char *name = "";
|
||||
char *name = NULL;
|
||||
upload_startTime = mix_get_time();
|
||||
char file_path[128] = {'\0'};
|
||||
bkp_session_delete_upload(pupload);
|
||||
|
|
@ -105,6 +105,7 @@ int cwmp_launch_upload(struct upload *pupload, struct transfer_complete **ptrans
|
|||
|
||||
if (pupload->file_type[0] == '1' || pupload->file_type[0] == '3') {
|
||||
if (pupload->f_instance && isdigit(pupload->f_instance[0])) {
|
||||
name = NULL;
|
||||
lookup_vcf_name(pupload->f_instance, &name);
|
||||
if (name && strlen(name) > 0) {
|
||||
snprintf(file_path, sizeof(file_path), "/tmp/%s", name);
|
||||
|
|
|
|||
2
xml.c
2
xml.c
|
|
@ -35,7 +35,7 @@ mxmlFindElementOpaque(mxml_node_t *node, /* I - Current node */
|
|||
node = mxmlWalkNext(node, top, descend);
|
||||
|
||||
while (node != NULL) {
|
||||
if (node->type == MXML_OPAQUE && node->value.opaque && (!text || !strcmp(node->value.opaque, text))) {
|
||||
if (node->type == MXML_OPAQUE && node->value.opaque && (!strcmp(node->value.opaque, text))) {
|
||||
return (node);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue