From ab9557c681c329cc741e36bf7dc3a0f594583d36 Mon Sep 17 00:00:00 2001 From: "alejandro.campos@artica.es" <alejandro.campos@artica.es> Date: Thu, 21 Apr 2022 18:09:26 +0200 Subject: [PATCH 01/38] prevent registration dialog from showing up in update manager of metaconsole nodes --- pandora_console/godmode/update_manager/update_manager.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pandora_console/godmode/update_manager/update_manager.php b/pandora_console/godmode/update_manager/update_manager.php index da9eb8543d..991491843a 100644 --- a/pandora_console/godmode/update_manager/update_manager.php +++ b/pandora_console/godmode/update_manager/update_manager.php @@ -107,7 +107,11 @@ switch ($tab) { case 'online': default: - $mode = \UpdateManager\UI\Manager::MODE_ONLINE; - include $config['homedir'].'/godmode/um_client/index.php'; + if ($config['node_metaconsole'] === 0) { + $mode = \UpdateManager\UI\Manager::MODE_ONLINE; + include $config['homedir'].'/godmode/um_client/index.php'; + } else { + ui_print_warning_message(__('Please register on metaconsole.')); + } break; } From 5c029effdb47dadd83015540979c6fe7f74f29e1 Mon Sep 17 00:00:00 2001 From: "alejandro.campos@artica.es" <alejandro.campos@artica.es> Date: Thu, 28 Apr 2022 11:51:48 +0200 Subject: [PATCH 02/38] minor fix --- pandora_server/lib/PandoraFMS/DataServer.pm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pandora_server/lib/PandoraFMS/DataServer.pm b/pandora_server/lib/PandoraFMS/DataServer.pm index 232361a50f..083fb77f8e 100644 --- a/pandora_server/lib/PandoraFMS/DataServer.pm +++ b/pandora_server/lib/PandoraFMS/DataServer.pm @@ -583,6 +583,11 @@ sub process_xml_data ($$$$$) { $module_data->{'data'} = $data->{'value'}; my $data_timestamp = get_tag_value ($data, 'timestamp', $timestamp); + + if ($pa_config->{'use_xml_timestamp'} eq '0' && defined($timestamp)) { + $data_timestamp = $timestamp; + } + process_module_data ($pa_config, $module_data, $server_id, $agent, $module_name, $module_type, $interval, $data_timestamp, $dbh, $new_agent); } From 9fd4e415c0f1911d579bb5e0d8d2057d843b4f60 Mon Sep 17 00:00:00 2001 From: Daniel Maya <daniel.maya@artica.es> Date: Tue, 3 May 2022 10:02:39 +0200 Subject: [PATCH 03/38] #8899 Fixed pass with entities --- pandora_console/include/functions_config.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandora_console/include/functions_config.php b/pandora_console/include/functions_config.php index 07537de173..c934a7aea7 100644 --- a/pandora_console/include/functions_config.php +++ b/pandora_console/include/functions_config.php @@ -1607,7 +1607,7 @@ function config_update_config() 'port' => $config['history_db_port'], 'name' => $config['history_db_name'], 'user' => $config['history_db_user'], - 'pass' => $config['history_db_pass'], + 'pass' => io_output_password($config['history_db_pass']), ] ); From 5c789125f2b561017a7fab325da91764eb8cf462 Mon Sep 17 00:00:00 2001 From: "alejandro.campos@artica.es" <alejandro.campos@artica.es> Date: Mon, 9 May 2022 12:40:36 +0200 Subject: [PATCH 04/38] changed id_user field length from tusuario --- pandora_console/extras/mr/55.sql | 15 +++++++++++++++ .../extras/pandoradb_migrate_6.0_to_759.mysql.sql | 15 +++++++++++++++ pandora_console/pandoradb.sql | 12 ++++++------ 3 files changed, 36 insertions(+), 6 deletions(-) create mode 100644 pandora_console/extras/mr/55.sql diff --git a/pandora_console/extras/mr/55.sql b/pandora_console/extras/mr/55.sql new file mode 100644 index 0000000000..b00619d357 --- /dev/null +++ b/pandora_console/extras/mr/55.sql @@ -0,0 +1,15 @@ +START TRANSACTION; + +ALTER TABLE `tuser_double_auth` DROP FOREIGN KEY `tuser_double_auth_ibfk_1`, MODIFY `id_user` VARCHAR(255) NOT NULL; +ALTER TABLE `tnotification_user` DROP FOREIGN KEY `tnotification_user_ibfk_2`, MODIFY `id_user` VARCHAR(255) NOT NULL; +ALTER TABLE `tnotification_source_user` DROP FOREIGN KEY `tnotification_source_user_ibfk_2`, MODIFY `id_user` VARCHAR(255) NOT NULL; +ALTER TABLE `tnotification_source_group_user` DROP FOREIGN KEY `tnotification_source_group_user_ibfk_2`, MODIFY `id_user` VARCHAR(255) NOT NULL; +ALTER TABLE `tvisual_console_elements_cache` DROP FOREIGN KEY `tvisual_console_elements_cache_ibfk_3`, MODIFY `user_id` VARCHAR(255) DEFAULT NULL; +ALTER TABLE `tusuario` MODIFY `id_user` VARCHAR(255) NOT NULL DEFAULT '0'; +ALTER TABLE `tuser_double_auth` ADD CONSTRAINT `tuser_double_auth_ibfk_1` FOREIGN KEY (`id_user`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE; +ALTER TABLE `tnotification_user` ADD CONSTRAINT `tnotification_user_ibfk_2` FOREIGN KEY (`id_user`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE ON UPDATE CASCADE; +ALTER TABLE `tnotification_source_user` ADD CONSTRAINT `tnotification_source_user_ibfk_2` FOREIGN KEY (`id_user`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE ON UPDATE CASCADE; +ALTER TABLE `tnotification_source_group_user` ADD CONSTRAINT `tnotification_source_group_user_ibfk_2` FOREIGN KEY (`id_user`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE ON UPDATE CASCADE; +ALTER TABLE `tvisual_console_elements_cache` ADD CONSTRAINT `tvisual_console_elements_cache_ibfk_3` FOREIGN KEY (`user_id`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE ON UPDATE CASCADE; + +COMMIT; diff --git a/pandora_console/extras/pandoradb_migrate_6.0_to_759.mysql.sql b/pandora_console/extras/pandoradb_migrate_6.0_to_759.mysql.sql index ca68a5472a..242e7d42c6 100644 --- a/pandora_console/extras/pandoradb_migrate_6.0_to_759.mysql.sql +++ b/pandora_console/extras/pandoradb_migrate_6.0_to_759.mysql.sql @@ -4338,3 +4338,18 @@ ALTER TABLE `talert_special_days` DROP COLUMN `same_day`; ALTER TABLE `talert_special_days` ADD FOREIGN KEY (`id_calendar`) REFERENCES `talert_calendar`(`id`) ON DELETE CASCADE ON UPDATE CASCADE; UPDATE `tconfig` c1 JOIN (select count(*) as n FROM `tconfig` c2 WHERE (c2.`token` = "node_metaconsole" AND c2.`value` = 1) OR (c2.`token` = "centralized_management" AND c2.`value` = 1) ) v SET c1. `value` = 0 WHERE c1.token = "autocreate_remote_users" AND v.n = 2; + +-- ---------------------------------------------------------------------- +-- Table `tusuario` +-- ---------------------------------------------------------------------- +ALTER TABLE `tuser_double_auth` DROP FOREIGN KEY `tuser_double_auth_ibfk_1`, MODIFY `id_user` VARCHAR(255) NOT NULL; +ALTER TABLE `tnotification_user` DROP FOREIGN KEY `tnotification_user_ibfk_2`, MODIFY `id_user` VARCHAR(255) NOT NULL; +ALTER TABLE `tnotification_source_user` DROP FOREIGN KEY `tnotification_source_user_ibfk_2`, MODIFY `id_user` VARCHAR(255) NOT NULL; +ALTER TABLE `tnotification_source_group_user` DROP FOREIGN KEY `tnotification_source_group_user_ibfk_2`, MODIFY `id_user` VARCHAR(255) NOT NULL; +ALTER TABLE `tvisual_console_elements_cache` DROP FOREIGN KEY `tvisual_console_elements_cache_ibfk_3`, MODIFY `user_id` VARCHAR(255) DEFAULT NULL; +ALTER TABLE `tusuario` MODIFY `id_user` VARCHAR(255) NOT NULL DEFAULT '0'; +ALTER TABLE `tuser_double_auth` ADD CONSTRAINT `tuser_double_auth_ibfk_1` FOREIGN KEY (`id_user`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE; +ALTER TABLE `tnotification_user` ADD CONSTRAINT `tnotification_user_ibfk_2` FOREIGN KEY (`id_user`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE ON UPDATE CASCADE; +ALTER TABLE `tnotification_source_user` ADD CONSTRAINT `tnotification_source_user_ibfk_2` FOREIGN KEY (`id_user`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE ON UPDATE CASCADE; +ALTER TABLE `tnotification_source_group_user` ADD CONSTRAINT `tnotification_source_group_user_ibfk_2` FOREIGN KEY (`id_user`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE ON UPDATE CASCADE; +ALTER TABLE `tvisual_console_elements_cache` ADD CONSTRAINT `tvisual_console_elements_cache_ibfk_3` FOREIGN KEY (`user_id`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index 29ec6e572b..bb98a706e3 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -1260,7 +1260,7 @@ CREATE TABLE IF NOT EXISTS `tevent_filter` ( -- Table `tusuario` -- ---------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `tusuario` ( - `id_user` VARCHAR(60) NOT NULL DEFAULT '0', + `id_user` VARCHAR(255) NOT NULL DEFAULT '0', `fullname` VARCHAR(255) NOT NULL, `firstname` VARCHAR(255) NOT NULL, `lastname` VARCHAR(255) NOT NULL, @@ -1328,7 +1328,7 @@ CREATE TABLE IF NOT EXISTS `tusuario_perfil` ( -- ---------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `tuser_double_auth` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, - `id_user` VARCHAR(60) NOT NULL, + `id_user` VARCHAR(255) NOT NULL, `secret` VARCHAR(20) NOT NULL, PRIMARY KEY (`id`), UNIQUE (`id_user`), @@ -1388,7 +1388,7 @@ CREATE TABLE IF NOT EXISTS `tmensajes` ( -- ---------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `tnotification_user` ( `id_mensaje` INT UNSIGNED NOT NULL, - `id_user` VARCHAR(60) NOT NULL, + `id_user` VARCHAR(255) NOT NULL, `utimestamp_read` BIGINT, `utimestamp_erased` BIGINT, `postpone` INT, @@ -1415,7 +1415,7 @@ CREATE TABLE IF NOT EXISTS `tnotification_group` ( -- ---------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `tnotification_source_user` ( `id_source` BIGINT UNSIGNED NOT NULL, - `id_user` VARCHAR(60), + `id_user` VARCHAR(255), `enabled` INT DEFAULT NULL, `also_mail` INT DEFAULT NULL, PRIMARY KEY (`id_source`,`id_user`), @@ -1443,7 +1443,7 @@ CREATE TABLE IF NOT EXISTS `tnotification_source_group` ( CREATE TABLE IF NOT EXISTS `tnotification_source_group_user` ( `id_source` BIGINT UNSIGNED NOT NULL, `id_group` MEDIUMINT UNSIGNED NOT NULL, - `id_user` VARCHAR(60), + `id_user` VARCHAR(255), `enabled` INT DEFAULT NULL, `also_mail` INT DEFAULT NULL, PRIMARY KEY (`id_source`,`id_user`), @@ -3836,7 +3836,7 @@ CREATE TABLE IF NOT EXISTS `tvisual_console_elements_cache` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `vc_id` INT UNSIGNED NOT NULL, `vc_item_id` INT UNSIGNED NOT NULL, - `user_id` VARCHAR(60) DEFAULT NULL, + `user_id` VARCHAR(255) DEFAULT NULL, `data` TEXT, `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, `expiration` INT UNSIGNED NOT NULL COMMENT 'Seconds to expire', From 672d48b49dbe46ab649144fb52308487b34a69f6 Mon Sep 17 00:00:00 2001 From: Daniel Maya <daniel.maya@pandorafms.com> Date: Thu, 26 May 2022 11:14:21 +0200 Subject: [PATCH 05/38] #9022 Fixed version --- .../update_manager_client/lib/UpdateManager/Client.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandora_console/update_manager_client/lib/UpdateManager/Client.php b/pandora_console/update_manager_client/lib/UpdateManager/Client.php index 4e38b20a75..c9785280d9 100644 --- a/pandora_console/update_manager_client/lib/UpdateManager/Client.php +++ b/pandora_console/update_manager_client/lib/UpdateManager/Client.php @@ -2228,7 +2228,7 @@ class Client if (is_callable($this->postUpdateFN) === true) { call_user_func( $this->postUpdateFN, - $this->currentPackage, + (string) $version, 'server' ); } From 0c9fdf8a18ea8cc14bb49d58bbacb89f89a1a317 Mon Sep 17 00:00:00 2001 From: "alejandro.campos@artica.es" <alejandro.campos@artica.es> Date: Fri, 3 Jun 2022 12:25:24 +0200 Subject: [PATCH 06/38] changed field max length --- pandora_console/godmode/users/configure_user.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandora_console/godmode/users/configure_user.php b/pandora_console/godmode/users/configure_user.php index 669bdf4fdf..67a269bc66 100644 --- a/pandora_console/godmode/users/configure_user.php +++ b/pandora_console/godmode/users/configure_user.php @@ -860,7 +860,7 @@ if (!$new_user) { '', '', 20, - 100, + 255, !$new_user || $view_mode, '', [ From ad00594b1de4187a7eaa71fedfd3ab0cd3d44890 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Gonz=C3=A1lez?= <jose.gonzalez@pandorafms.com> Date: Tue, 7 Jun 2022 17:21:13 +0200 Subject: [PATCH 07/38] Set new brand and color for header --- .../custom_logo/logo-pandorafms-1-collapsed.png | Bin 0 -> 36861 bytes .../images/custom_logo/logo-pandorafms-1.png | Bin 0 -> 16310 bytes pandora_console/include/functions_config.php | 8 ++++---- pandora_console/include/styles/menu.css | 3 ++- 4 files changed, 6 insertions(+), 5 deletions(-) create mode 100644 pandora_console/images/custom_logo/logo-pandorafms-1-collapsed.png create mode 100644 pandora_console/images/custom_logo/logo-pandorafms-1.png diff --git a/pandora_console/images/custom_logo/logo-pandorafms-1-collapsed.png b/pandora_console/images/custom_logo/logo-pandorafms-1-collapsed.png new file mode 100644 index 0000000000000000000000000000000000000000..494003c145e1d04acf03ad1b8d4428cb0240933b GIT binary patch literal 36861 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 Y)bMM)we>|Ne;t?UZA+s%1DBZp0r7R*2mk;8 literal 0 HcmV?d00001 diff --git a/pandora_console/images/custom_logo/logo-pandorafms-1.png b/pandora_console/images/custom_logo/logo-pandorafms-1.png new file mode 100644 index 0000000000000000000000000000000000000000..172802af8b55f163314a6975531ebb60857052d5 GIT binary patch literal 16310 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	DT`!82T^}h}X@uOXHx`fcuU>hBU zP~@dxt9w@&XX>Zn)S7<rxa|!Gw!V%J5>T-oD3W02Vl!z=eXhHujzF0_Bp6v3d%pXt zeFXs#c!;#5@aAf6RoF`J#0>vDGA>DRi{$|13rd4VN^*?0=JxgJE>2AANp+AW-B_tb zxW*qnp5qqobvlrIlc;2TlN|y*^6NyGJ3ZSre^!aXrm3D)Sj1A;%rR|`m|hRw5J8W~ zVc!wbj(q{=*c97NIBj;Dw&$`ccbLBa_;s+~?8TRuQEe^z#~X|v7o^scrAWsJ_P*G} zNF{>38CLfm3$@d6_v+ZbdUIUURT|rvoky()F9<B=_Piue(`}!)CDM4GbssZIj=oEU zH)W_s+?PjqZ^qjn<(sKvKv$IjCb!-f&at8vM^Du(f1s%XWtdRr_aI@*k3Y8E)~F@P znkH4WCruu5V7!x{dJrQneXsF8<&3stpLH|+;m}YZS7eI~ro`z^s#W~ty3oet8A<Yb z-!~>yTcYgveeo^7{z&X=WU^$s-gaYUoFjM=WCscjaKq26ks*t3cPx<=@M$|LV^P}@ z&$KG<i_%ZavE+wet*`D90%w^7V5~r}55v5!Hd&)h&BQs&)Ok<f!!p5DL;(F1PApxQ z;@|*UgXHe&A~PsvPDoqaH|BGKxYw-l%E}zsiM(e_9)K)AJW_2tE^N$Tp6iBjs;l=& zWr5FZG7F*QR_#+_F5T1gLH#f$1#bF2BM02^k%HPZCW|y4fcm@an&eLR;m>^ner#~! z07Z1!zKq7!sT?!m^6kr|k)6eH;Nl7l5GHKJ-ojxdnJ$c~2%6wxibV*am!?FAIvXXI zKcPN5(C7yL&{^ouf=Yhe+OX`iT4B#A2PK2c#uGYj|2y~9vyW()!H~_N$Jtd8K2a6A z3K@lsIsPZG_9AG*YlO5z(nl5W5Aky0SZ>c*KRD7H%e^5pCq?R8)D(@oF}gAL{97V- z_)d7-2l1Rcl(vd1iF-j1CDj*u|FoUMA=90(_IuI!E>C_@eDleZrLA8&z&hO%+cd*! zvs$ajY^Cm5kYZTmvG#muLmVMZUV2eJZk>KGfpYE$5@NxpRYKv<;4@`w-PW3&g8RH< zU-dFVg~3b4*fa#%(20;1r2W2b?JcUM<r>}WpQc1tdZ$;`*048{qAosY+m)>9z1Hg$ zk^S3$Q5!N}4!1%+uaTsWEpUP=jzMq)#}(0IgJDKrf0k4uuE+WOrCtoic_Bn^q^|p2 z;dP44#Qoe^zkW+>!SL-6`M6pHxH+O;(aqP^tVQCwsbF$`!jd#a($4EN1v%%^JtTMl z!8H)v_*&t|g&Yc~lDda{J2KFQ=FQw8O?dpRa}K_4&OGAp@<CM&4&p|~w8k~*zPBd1 zpsq1yp<08Adqc+A6~B`*q^^G<c6~$bY~?GhcQFQw)(hzeplOgF36!=fP46?m9^<4? zSndM4V{q7slcapr7g}HI97`JaoQ%`(Y9(%U<T9Muf#p-qR9t$!cS(?i%J-b3zm@n{ z{2;Ztz(ueZoa?8t+{axGE!UiMk>ViD1#Im-J+k%n{am%hX4w0B?OjjE^gH-2wBeqp zwD~))oStXZfrl;e+gvMVW0q56jK^I{&Jw10z0PCQ_-0Zw`1Y}TM>J)r>n^8JlEZ~l z8eNb)B+1I}%hz%vhh9mOg2O8pJKLofTBI5ur&pIHok+}h>Z-n=^@(;b#b!u4E7yUr zAv3~a7meY5dr$r&$JItR!@}d*QHZS`yQLO`yA+vo-r(-cQfQLQ6o!}+pdJ{!zc}>e zjE#%^hy$EBOc6DBb6h(Nv9e?rrmALu<(8WBo5;;#l*iN%5LIPKmG91S_SqW_#`7R^ zmA`-7+P#7r+k{Mq!9DA>fbfIRpM5xr&bi`JN&MsK?K4O8AymmNP%NHY8O40H<8u%% zsUR1B)r-F#fO%FsiNL+u1n(xn`_b>0oiDji_7V?%Z@+}Q5?j?<?r&TmhyU*2KGWaV zrf+=tY@<=<mehA<|B9gNa}GS`bGKB+FfYp_&$dK2sa@M!Dd%SaE;!bMFSnTsTq!5c z$(I`7%P+Oxj-RsJmMcB8K9O5^C*^Qwh^bt&ujqy#c%D$sl|dVbk9X0JzLb@)j31V3 zCrT_;-GiJF!wwiZ>~{+Xit4Q{UOj3r3aRJ3CthB5`|kIqR(sszwRQ>iq&t^&@_9do zv*XTR&Js3yKeOAdYjd@_y0kGn+y1Nr_)dVyhyE=<V_|##M6P&`f@9vw>FDrRzNB(q z-zbsVtR`WvogHTKt#RA^-{47+yQ6wPN|9*eqn}37hn{NB^$ijSa_1jRgfn=jK(`nY zn$N6CjLqFanxz&rgv4a8wzGOV52wDIJWxe!gu})$&06FKOf#5!X?iuq&o#5G7NWkC z%WqB<`6EIj>nLzo;>wHA`CPr(hz*_id3}SK(7}Zryv5Ao7ySmSq9yPKd`jgz5+?Ch ziqz6(3T=z|UAD*w-!JY0UMc25je9j$h=+gXAiKX*Bg@DxPIzV*C>$}C0=2$cT@x3F zzF-<TwqknJ6kyh9%*M!fgbOY{vIg3`bom;P?lucGZm9F?rTaq2`3WLTg<TdV;qTf& z-8yACW>~h5j&_ij)Gj|O*1W^@S}W})`tsIqBD`z1!N`7Dsj`3;Qw#$P+*LPP_U6<D zN#9m43oj}G(7_0*{+pUyL+Z&luafULfR~U$RMw>$*0^u-wr<%9cjzQ6)K%dxJYyIu zq2c~&%_HE=rBq@?YRKgu<a_Z2d;9k(k(UuL#rUkv1KncHO_LWQ57yd7YFH|Lehf=^ zt<E0tv;XU^oukzG^BI87`XqLXc4$n~E9Yzu?S9lsv=yBPhYZQKL;F&Ejh^K7$at}; zo`Zl(ImgUC8qZkg8;&?JT!iImhYb!GdM`Tu*P*c}v+>|q<~>Vs8qPhk&jCQX2vuot zf$x3o%?hpZaB`2{5FEUS9lhAB6<BF&(>JyLav-tp<#)Vk9i(;;j8pn^3b|HWdR&it z4e_K-#XX2q@;8A|OcK*ROqh6Q^E4@x42=EI5To_^ah_9#!-|olrXh{No%V`^#BzQH zm?|sks-Gb&0hFnr>2~<Dp%{QStsLgS*1sD#CveRXS@2r*i0tnkFhCvz8VP!n2Z5LS z|5!|i`RC%_F#kIOfccH^ck_Qo_*;-8vQf;ilYhwYKOx)(3cUK47XOmLg#ji&mtols z-RKKD=Jpl|JLU?4JRyLi-GK|h0nFceb(y=ZgYQ@p3&=3oRVmO!OUsTNhDnssH7)y! zfE`mvoN!`-9ZUzFI+$J$KAn*&iwy%TfAa+mEc;+O8GQMIUgY?r$-DDv5kcqg%m5P_ zKsWCCgMWhCp7uTlz&Z?kyyNG-E&zjFFDQk<%=~4M`(S*I;~cQOt~cey46s{LV7M(s zmM9E{`@!(5j&e~3*agpYdsZ0VlV>ELM{kWM9{k_?EpeJ9$tU%)sW12@31(_+X;f-} Hz3{&PyZF!y literal 0 HcmV?d00001 diff --git a/pandora_console/include/functions_config.php b/pandora_console/include/functions_config.php index 855bc67a7d..52d72063aa 100644 --- a/pandora_console/include/functions_config.php +++ b/pandora_console/include/functions_config.php @@ -2357,12 +2357,12 @@ function config_process_config() config_update_value('custom_favicon', ''); } - if (!isset($config['custom_logo'])) { - config_update_value('custom_logo', 'pandora_logo_head_4.png'); + if (isset($config['custom_logo']) === false) { + config_update_value('custom_logo', 'logo-pandorafms-1.png'); } - if (!isset($config['custom_logo_collapsed'])) { - config_update_value('custom_logo_collapsed', 'pandora_logo_green_collapsed.png'); + if (isset($config['custom_logo_collapsed']) === false) { + config_update_value('custom_logo_collapsed', 'logo-pandorafms-1-collapsed.png'); } if (is_metaconsole()) { diff --git a/pandora_console/include/styles/menu.css b/pandora_console/include/styles/menu.css index ebf201c761..7348875a45 100644 --- a/pandora_console/include/styles/menu.css +++ b/pandora_console/include/styles/menu.css @@ -399,7 +399,8 @@ ul li { } .logo_green { - height: 60px; + background-color: #fff; + min-height: 60px; display: flex; justify-content: center; align-items: center; From 12b0f5cda10b34ba065dbbf0941768e6a005691e Mon Sep 17 00:00:00 2001 From: "alejandro.campos@artica.es" <alejandro.campos@artica.es> Date: Wed, 8 Jun 2022 11:49:48 +0200 Subject: [PATCH 08/38] database changes --- pandora_console/extras/mr/55.sql | 35 +++++++-- .../pandoradb_migrate_6.0_to_759.mysql.sql | 73 +++++++++++++++++++ pandora_console/pandoradb.sql | 46 ++++++------ 3 files changed, 125 insertions(+), 29 deletions(-) diff --git a/pandora_console/extras/mr/55.sql b/pandora_console/extras/mr/55.sql index f833cb0517..ea2d76070e 100644 --- a/pandora_console/extras/mr/55.sql +++ b/pandora_console/extras/mr/55.sql @@ -1,16 +1,39 @@ START TRANSACTION; -ALTER TABLE `tuser_double_auth` DROP FOREIGN KEY `tuser_double_auth_ibfk_1`, MODIFY `id_user` VARCHAR(255) NOT NULL; -ALTER TABLE `tnotification_user` DROP FOREIGN KEY `tnotification_user_ibfk_2`, MODIFY `id_user` VARCHAR(255) NOT NULL; -ALTER TABLE `tnotification_source_user` DROP FOREIGN KEY `tnotification_source_user_ibfk_2`, MODIFY `id_user` VARCHAR(255) NOT NULL; -ALTER TABLE `tnotification_source_group_user` DROP FOREIGN KEY `tnotification_source_group_user_ibfk_2`, MODIFY `id_user` VARCHAR(255) NOT NULL; -ALTER TABLE `tvisual_console_elements_cache` DROP FOREIGN KEY `tvisual_console_elements_cache_ibfk_3`, MODIFY `user_id` VARCHAR(255) DEFAULT NULL; -ALTER TABLE `tusuario` MODIFY `id_user` VARCHAR(255) NOT NULL DEFAULT '0'; +ALTER TABLE `tuser_double_auth` DROP FOREIGN KEY `tuser_double_auth_ibfk_1`, MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL; +ALTER TABLE `tnotification_user` DROP FOREIGN KEY `tnotification_user_ibfk_2`, MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL; +ALTER TABLE `tnotification_source_user` DROP FOREIGN KEY `tnotification_source_user_ibfk_2`, MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL; +ALTER TABLE `tnotification_source_group_user` DROP FOREIGN KEY `tnotification_source_group_user_ibfk_2`, MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL; +ALTER TABLE `tvisual_console_elements_cache` DROP FOREIGN KEY `tvisual_console_elements_cache_ibfk_3`, MODIFY COLUMN `user_id` VARCHAR(255) DEFAULT NULL; +ALTER TABLE `tusuario` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT '0'; ALTER TABLE `tuser_double_auth` ADD CONSTRAINT `tuser_double_auth_ibfk_1` FOREIGN KEY (`id_user`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE; ALTER TABLE `tnotification_user` ADD CONSTRAINT `tnotification_user_ibfk_2` FOREIGN KEY (`id_user`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE `tnotification_source_user` ADD CONSTRAINT `tnotification_source_user_ibfk_2` FOREIGN KEY (`id_user`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE `tnotification_source_group_user` ADD CONSTRAINT `tnotification_source_group_user_ibfk_2` FOREIGN KEY (`id_user`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE `tvisual_console_elements_cache` ADD CONSTRAINT `tvisual_console_elements_cache_ibfk_3` FOREIGN KEY (`user_id`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE `tservice` ADD COLUMN `enable_sunburst` tinyint(1) NOT NULL default 0; +ALTER TABLE `tattachment` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT ''; +ALTER TABLE `tevento` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0'; +ALTER TABLE `tincidencia` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT ''; +ALTER TABLE `tnota` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0'; +ALTER TABLE `tsesion` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0'; +ALTER TABLE `ttrap` MODIFY COLUMN `id_usuario` VARCHAR(255) DEFAULT ''; +ALTER TABLE `tusuario_perfil` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT ''; +ALTER TABLE `treset_pass_history` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL; +ALTER TABLE `tmensajes` MODIFY COLUMN `id_usuario_origen` VARCHAR(255) NOT NULL DEFAULT ''; +ALTER TABLE `tgraph` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; +ALTER TABLE `treport` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; +ALTER TABLE `tplanned_downtime` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT '0'; +ALTER TABLE `tnetwork_map` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL; +ALTER TABLE `tpassword_history` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL; +ALTER TABLE `tupdate_journal` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; +ALTER TABLE `tmap` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; +ALTER TABLE `tdashboard` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; +ALTER TABLE `treport_template` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; +ALTER TABLE `tmetaconsole_event` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0'; +ALTER TABLE `tmetaconsole_event_history` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0'; +ALTER TABLE `treset_pass` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; +ALTER TABLE `tuser_task_scheduled` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0'; +ALTER TABLE `tbackup` MODIFY COLUMN `id_user` VARCHAR(255) DEFAULT ''; COMMIT; diff --git a/pandora_console/extras/pandoradb_migrate_6.0_to_759.mysql.sql b/pandora_console/extras/pandoradb_migrate_6.0_to_759.mysql.sql index 242e7d42c6..df09c2b8e4 100644 --- a/pandora_console/extras/pandoradb_migrate_6.0_to_759.mysql.sql +++ b/pandora_console/extras/pandoradb_migrate_6.0_to_759.mysql.sql @@ -838,6 +838,8 @@ CREATE TABLE IF NOT EXISTS `treport_template` ( PRIMARY KEY(`id_report`) ) ENGINE = InnoDB DEFAULT CHARSET=utf8; +ALTER TABLE `treport_template` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; + -- ----------------------------------------------------- -- Table `treport_content_template` -- ----------------------------------------------------- @@ -1054,6 +1056,7 @@ ALTER TABLE `tmetaconsole_event` ADD INDEX `tme_module_status_idx` (`module_stat ALTER TABLE `tmetaconsole_event` ADD INDEX `tme_criticity_idx` (`criticity`); ALTER TABLE `tmetaconsole_event` ADD INDEX `tme_agent_name_idx` (`agent_name`); ALTER TABLE `tmetaconsole_event` MODIFY `data` TINYTEXT default NULL; +ALTER TABLE `tmetaconsole_event` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0'; -- --------------------------------------------------------------------- -- Table `tmetaconsole_event_history` @@ -1104,6 +1107,8 @@ ALTER TABLE `tmetaconsole_event_history` ADD COLUMN `data` double(50,5) default ALTER TABLE `tmetaconsole_event_history` ADD COLUMN `module_status` int(4) NOT NULL default '0'; ALTER TABLE `tmetaconsole_event_history` ADD INDEX `tmeh_estado_idx` (`estado`); ALTER TABLE `tmetaconsole_event_history` ADD INDEX `tmeh_timestamp_idx` (`timestamp`); +ALTER TABLE `tmetaconsole_event_history` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0'; + -- --------------------------------------------------------------------- -- Table `textension_translate_string` -- --------------------------------------------------------------------- @@ -1454,6 +1459,7 @@ ALTER TABLE `talert_commands` MODIFY COLUMN `id_group` mediumint(8) unsigned NUL -- Table `tmap` -- --------------------------------------------------------------------- ALTER TABLE `tmap` MODIFY COLUMN `id_user` varchar(250) NOT NULL DEFAULT ''; +ALTER TABLE `tmap` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; -- --------------------------------------------------------------------- -- Table `ttag` @@ -1749,6 +1755,7 @@ ALTER TABLE tgraph ADD COLUMN `average_series` tinyint(1) UNSIGNED NOT NULL def ALTER TABLE tgraph ADD COLUMN `modules_series` tinyint(1) UNSIGNED NOT NULL default '0'; ALTER TABLE tgraph ADD COLUMN `fullscale` tinyint(1) UNSIGNED NOT NULL default '0'; ALTER TABLE `tgraph` MODIFY COLUMN `percentil` tinyint(1) unsigned NOT NULL DEFAULT '0'; +ALTER TABLE `tgraph` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; -- --------------------------------------------------------------------- -- Table `tnetflow_filter` @@ -1952,6 +1959,8 @@ CREATE TABLE IF NOT EXISTS `treset_pass_history` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +ALTER TABLE `treset_pass_history` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL; + -- --------------------------------------------------------------------- -- Table `tcontainer_item` -- --------------------------------------------------------------------- @@ -1978,6 +1987,9 @@ CREATE TABLE IF NOT EXISTS `tcontainer_item` ( ALTER TABLE tusuario add default_event_filter int(10) unsigned NOT NULL DEFAULT 0; +-- --------------------------------------------------------------------- +-- Table `treset_pass` +-- --------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `treset_pass` ( `id` bigint(10) unsigned NOT NULL auto_increment, `id_user` varchar(100) NOT NULL default '', @@ -1986,6 +1998,8 @@ CREATE TABLE IF NOT EXISTS `treset_pass` ( PRIMARY KEY (`id`) )ENGINE=InnoDB DEFAULT CHARSET=utf8; +ALTER TABLE `treset_pass` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; + UPDATE tgis_map_connection SET conection_data = '{"type":"OSM","url":"http://tile.openstreetmap.org/${z}/${x}/${y}.png"}' where id_tmap_connection = 1; ALTER TABLE tpolicy_modules MODIFY post_process double(24,15) default 0; @@ -2047,6 +2061,7 @@ INSERT INTO `ttipo_modulo` VALUES -- Table `tdashboard` -- --------------------------------------------------------------------- ALTER TABLE `tdashboard` ADD COLUMN `cells_slideshow` TINYINT(1) NOT NULL default 0; +ALTER TABLE `tdashboard` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; -- --------------------------------------------------------------------- -- Table `tsnmp_filter` @@ -2356,6 +2371,7 @@ ALTER TABLE `treport` ADD COLUMN `orientation` varchar(25) NOT NULL default 'ver ALTER TABLE `treport` MODIFY COLUMN `hidden` tinyint(1) NULL DEFAULT '0' AFTER `non_interactive`; ALTER TABLE `treport` ADD COLUMN `cover_page_render` tinyint(1) NOT NULL DEFAULT 1; ALTER TABLE `treport` ADD COLUMN `index_render` tinyint(1) NOT NULL DEFAULT 1; +ALTER TABLE `treport` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; ALTER TABLE `trecon_task` ADD COLUMN `snmp_version` varchar(5) NOT NULL default '1'; ALTER TABLE `trecon_task` ADD COLUMN `snmp_auth_user` varchar(255) NOT NULL default ''; @@ -2393,6 +2409,8 @@ ALTER TABLE `tevento` ADD COLUMN `module_status` int(4) NOT NULL default '0'; ALTER TABLE `tevento` MODIFY `data` TINYTEXT default NULL; +ALTER TABLE `tevento` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0'; + -- --------------------------------------------------------------------- -- Table `tevent_extended` -- --------------------------------------------------------------------- @@ -2462,6 +2480,8 @@ CREATE TABLE IF NOT EXISTS `tuser_task_scheduled` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +ALTER TABLE `tuser_task_scheduled` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0'; + -- ----------------------------------------------------- -- Table `tnotification_source` -- ----------------------------------------------------- @@ -2501,6 +2521,8 @@ ALTER TABLE `tmensajes` ADD CONSTRAINT `tsource_fk` FOREIGN KEY (`id_source`) RE ALTER TABLE `tmensajes` DROP COLUMN `id_usuario_destino`, ADD UNIQUE INDEX `id_mensaje` (`id_mensaje`); +ALTER TABLE `tmensajes` MODIFY COLUMN `id_usuario_origen` VARCHAR(255) NOT NULL DEFAULT ''; + -- ---------------------------------------------------------------------- -- Table `tnotification_user` -- ---------------------------------------------------------------------- @@ -2796,6 +2818,7 @@ UPDATE `trecon_script` SET `description`='Specific Pandora FMS In -- Table `tusuario_perfil` -- --------------------------------------------------------------------- ALTER TABLE `tusuario_perfil` MODIFY COLUMN `no_hierarchy` tinyint(1) NOT NULL DEFAULT '0'; +ALTER TABLE `tusuario_perfil` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT ''; -- Extra tnetwork_component @@ -4353,3 +4376,53 @@ ALTER TABLE `tnotification_user` ADD CONSTRAINT `tnotification_user_ibfk_2` FORE ALTER TABLE `tnotification_source_user` ADD CONSTRAINT `tnotification_source_user_ibfk_2` FOREIGN KEY (`id_user`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE `tnotification_source_group_user` ADD CONSTRAINT `tnotification_source_group_user_ibfk_2` FOREIGN KEY (`id_user`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE `tvisual_console_elements_cache` ADD CONSTRAINT `tvisual_console_elements_cache_ibfk_3` FOREIGN KEY (`user_id`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE ON UPDATE CASCADE; + +-- ---------------------------------------------------------------------- +-- Table `tattachment` +-- ---------------------------------------------------------------------- +ALTER TABLE `tattachment` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT ''; + +-- ---------------------------------------------------------------------- +-- Table `tincidencia` +-- ---------------------------------------------------------------------- +ALTER TABLE `tincidencia` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT ''; + +-- ---------------------------------------------------------------------- +-- Table `tnota` +-- ---------------------------------------------------------------------- +ALTER TABLE `tnota` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0'; + +-- ---------------------------------------------------------------------- +-- Table `tsesion` +-- ---------------------------------------------------------------------- +ALTER TABLE `tsesion` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0'; + +-- ---------------------------------------------------------------------- +-- Table `ttrap` +-- ---------------------------------------------------------------------- +ALTER TABLE `ttrap` MODIFY COLUMN `id_usuario` VARCHAR(255) DEFAULT ''; + +-- ---------------------------------------------------------------------- +-- Table `tplanned_downtime` +-- ---------------------------------------------------------------------- +ALTER TABLE `tplanned_downtime` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT '0'; + +-- ---------------------------------------------------------------------- +-- Table `tnetwork_map` +-- ---------------------------------------------------------------------- +ALTER TABLE `tnetwork_map` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL; + +-- ---------------------------------------------------------------------- +-- Table `tpassword_history` +-- ---------------------------------------------------------------------- +ALTER TABLE `tpassword_history` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL; + +-- ---------------------------------------------------------------------- +-- Table `tupdate_journal` +-- ---------------------------------------------------------------------- +ALTER TABLE `tupdate_journal` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; + +-- ---------------------------------------------------------------------- +-- Table `tbackup` +-- ---------------------------------------------------------------------- +ALTER TABLE `tbackup` MODIFY COLUMN `id_user` VARCHAR(255) DEFAULT ''; diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index 9bdad4af90..08a43d2979 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -616,7 +616,7 @@ CREATE TABLE IF NOT EXISTS `talert_execution_queue` ( CREATE TABLE IF NOT EXISTS `tattachment` ( `id_attachment` INT UNSIGNED NOT NULL AUTO_INCREMENT, `id_incidencia` INT UNSIGNED NOT NULL DEFAULT 0, - `id_usuario` VARCHAR(60) NOT NULL DEFAULT '', + `id_usuario` VARCHAR(255) NOT NULL DEFAULT '', `filename` VARCHAR(255) NOT NULL DEFAULT '', `description` VARCHAR(150) DEFAULT '', `size` BIGINT UNSIGNED NOT NULL DEFAULT 0, @@ -689,7 +689,7 @@ CREATE TABLE IF NOT EXISTS `tcontainer_item` ( CREATE TABLE IF NOT EXISTS `tevento` ( `id_evento` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `id_agente` INT NOT NULL DEFAULT 0, - `id_usuario` VARCHAR(100) NOT NULL DEFAULT '0', + `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0', `id_grupo` MEDIUMINT NOT NULL DEFAULT 0, `estado` TINYINT UNSIGNED NOT NULL DEFAULT 0, `timestamp` DATETIME NOT NULL DEFAULT '1970-01-01 00:00:00', @@ -779,7 +779,7 @@ CREATE TABLE IF NOT EXISTS `tincidencia` ( `cierre` DATETIME NOT NULL DEFAULT '1970-01-01 00:00:00', `titulo` TEXT, `descripcion` TEXT, - `id_usuario` VARCHAR(60) NOT NULL DEFAULT '', + `id_usuario` VARCHAR(255) NOT NULL DEFAULT '', `origen` VARCHAR(100) NOT NULL DEFAULT '', `estado` INT NOT NULL DEFAULT 0, `prioridad` INT NOT NULL DEFAULT 0, @@ -1059,7 +1059,7 @@ CREATE TABLE IF NOT EXISTS `tnetwork_profile_pen` ( CREATE TABLE IF NOT EXISTS `tnota` ( `id_nota` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `id_incident` BIGINT UNSIGNED NOT NULL, - `id_usuario` VARCHAR(100) NOT NULL DEFAULT '0', + `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0', `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `nota` MEDIUMTEXT, PRIMARY KEY (`id_nota`), @@ -1172,7 +1172,7 @@ CREATE TABLE IF NOT EXISTS `tserver` ( -- ---------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `tsesion` ( `id_sesion` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, - `id_usuario` VARCHAR(60) NOT NULL DEFAULT '0', + `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0', `ip_origen` VARCHAR(100) NOT NULL DEFAULT '', `accion` VARCHAR(100) NOT NULL DEFAULT '', `descripcion` TEXT, @@ -1208,7 +1208,7 @@ CREATE TABLE IF NOT EXISTS `ttrap` ( `value_custom` TEXT, `alerted` SMALLINT NOT NULL DEFAULT 0, `status` SMALLINT NOT NULL DEFAULT 0, - `id_usuario` VARCHAR(150) DEFAULT '', + `id_usuario` VARCHAR(255) DEFAULT '', `timestamp` DATETIME NOT NULL DEFAULT '1970-01-01 00:00:00', `priority` TINYINT UNSIGNED NOT NULL DEFAULT 2, `text` VARCHAR(255) DEFAULT '', @@ -1313,7 +1313,7 @@ CREATE TABLE IF NOT EXISTS `tusuario` ( -- ---------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `tusuario_perfil` ( `id_up` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, - `id_usuario` VARCHAR(100) NOT NULL DEFAULT '', + `id_usuario` VARCHAR(255) NOT NULL DEFAULT '', `id_perfil` INT UNSIGNED NOT NULL DEFAULT 0, `id_grupo` INT NOT NULL DEFAULT 0, `no_hierarchy` TINYINT NOT NULL DEFAULT 0, @@ -1340,7 +1340,7 @@ CREATE TABLE IF NOT EXISTS `tuser_double_auth` ( -- ---------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `treset_pass_history` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, - `id_user` VARCHAR(60) NOT NULL, + `id_user` VARCHAR(255) NOT NULL, `reset_moment` DATETIME NOT NULL, `success` TINYINT NOT NULL, PRIMARY KEY (`id`) @@ -1366,7 +1366,7 @@ CREATE TABLE IF NOT EXISTS `tnotification_source` ( -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS `tmensajes` ( `id_mensaje` INT UNSIGNED NOT NULL AUTO_INCREMENT, - `id_usuario_origen` VARCHAR(60) NOT NULL DEFAULT '', + `id_usuario_origen` VARCHAR(255) NOT NULL DEFAULT '', `mensaje` TEXT, `timestamp` BIGINT UNSIGNED NOT NULL DEFAULT 0, `subject` VARCHAR(255) NOT NULL DEFAULT '', @@ -1476,7 +1476,7 @@ CREATE TABLE IF NOT EXISTS `tnews` ( -- ---------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `tgraph` ( `id_graph` INT UNSIGNED NOT NULL AUTO_INCREMENT, - `id_user` VARCHAR(100) NOT NULL DEFAULT '', + `id_user` VARCHAR(255) NOT NULL DEFAULT '', `name` VARCHAR(150) NOT NULL DEFAULT '', `description` TEXT, `period` INT NOT NULL DEFAULT 0, @@ -1514,7 +1514,7 @@ CREATE TABLE IF NOT EXISTS `tgraph_source` ( -- ---------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `treport` ( `id_report` INT UNSIGNED NOT NULL AUTO_INCREMENT, - `id_user` VARCHAR(100) NOT NULL DEFAULT '', + `id_user` VARCHAR(255) NOT NULL DEFAULT '', `name` VARCHAR(150) NOT NULL DEFAULT '', `description` TEXT, `private` TINYINT UNSIGNED NOT NULL DEFAULT 0, @@ -1813,7 +1813,7 @@ CREATE TABLE IF NOT EXISTS `tplanned_downtime` ( `type_downtime` VARCHAR(100) NOT NULL DEFAULT 'disabled_agents_alerts', `type_execution` VARCHAR(100) NOT NULL DEFAULT 'once', `type_periodicity` VARCHAR(100) NOT NULL DEFAULT 'weekly', - `id_user` VARCHAR(100) NOT NULL DEFAULT '0', + `id_user` VARCHAR(255) NOT NULL DEFAULT '0', PRIMARY KEY ( `id` ) ) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4; @@ -2036,7 +2036,7 @@ CREATE TABLE IF NOT EXISTS `tgroup_stat` ( -- ---------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `tnetwork_map` ( `id_networkmap` INT UNSIGNED NOT NULL AUTO_INCREMENT, - `id_user` VARCHAR(60) NOT NULL, + `id_user` VARCHAR(255) NOT NULL, `name` VARCHAR(100) NOT NULL, `type` VARCHAR(20) NOT NULL, `layout` VARCHAR(20) NOT NULL, @@ -2196,7 +2196,7 @@ CREATE TABLE IF NOT EXISTS `tnetflow_report_content` ( -- --------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `tpassword_history` ( `id_pass` INT UNSIGNED NOT NULL AUTO_INCREMENT, - `id_user` VARCHAR(60) NOT NULL, + `id_user` VARCHAR(255) NOT NULL, `password` VARCHAR(45) DEFAULT NULL, `date_begin` DATETIME, `date_end` DATETIME, @@ -2249,7 +2249,7 @@ CREATE TABLE `tupdate_journal` ( `version` VARCHAR(25) DEFAULT '', `type` VARCHAR(25) DEFAULT '', `origin` VARCHAR(25) DEFAULT '', - `id_user` VARCHAR(250) NOT NULL DEFAULT '' + `id_user` VARCHAR(255) NOT NULL DEFAULT '' ) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4; -- --------------------------------------------------------------------- @@ -2298,7 +2298,7 @@ CREATE TABLE IF NOT EXISTS `tsessions_php` ( CREATE TABLE IF NOT EXISTS `tmap` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `id_group` INT UNSIGNED NOT NULL DEFAULT 0, - `id_user` VARCHAR(250) NOT NULL DEFAULT '', + `id_user` VARCHAR(255) NOT NULL DEFAULT '', `type` INT UNSIGNED NOT NULL DEFAULT 0, `subtype` INT UNSIGNED NOT NULL DEFAULT 0, `name` VARCHAR(250) DEFAULT '', @@ -2579,7 +2579,7 @@ CREATE TABLE IF NOT EXISTS `tpolicy_group_agents` ( CREATE TABLE IF NOT EXISTS `tdashboard` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `name` VARCHAR(60) NOT NULL DEFAULT '', - `id_user` VARCHAR(60) NOT NULL DEFAULT '', + `id_user` VARCHAR(255) NOT NULL DEFAULT '', `id_group` INT NOT NULL DEFAULT 0, `active` TINYINT NOT NULL DEFAULT 0, `cells` INT UNSIGNED DEFAULT 0, @@ -3128,7 +3128,7 @@ CREATE TABLE IF NOT EXISTS `tnetworkmap_ent_rel_nodes` ( -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS `treport_template` ( `id_report` INT UNSIGNED NOT NULL AUTO_INCREMENT, - `id_user` VARCHAR(100) NOT NULL DEFAULT '', + `id_user` VARCHAR(255) NOT NULL DEFAULT '', `name` VARCHAR(150) NOT NULL DEFAULT '', `description` TEXT, `private` TINYINT UNSIGNED NOT NULL DEFAULT 0, @@ -3297,7 +3297,7 @@ CREATE TABLE IF NOT EXISTS `tmetaconsole_event` ( `id_source_event` BIGINT UNSIGNED NOT NULL, `id_agente` INT NOT NULL DEFAULT 0, `agent_name` VARCHAR(600) NOT NULL DEFAULT '', - `id_usuario` VARCHAR(100) NOT NULL DEFAULT '0', + `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0', `id_grupo` MEDIUMINT NOT NULL DEFAULT 0, `group_name` VARCHAR(100) NOT NULL DEFAULT '', `estado` TINYINT UNSIGNED NOT NULL DEFAULT 0, @@ -3349,7 +3349,7 @@ CREATE TABLE IF NOT EXISTS `tmetaconsole_event_history` ( `id_source_event` BIGINT UNSIGNED NOT NULL, `id_agente` INT NOT NULL DEFAULT 0, `agent_name` VARCHAR(600) NOT NULL DEFAULT '', - `id_usuario` VARCHAR(100) NOT NULL DEFAULT '0', + `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0', `id_grupo` MEDIUMINT NOT NULL DEFAULT 0, `group_name` VARCHAR(100) NOT NULL DEFAULT '', `estado` TINYINT UNSIGNED NOT NULL DEFAULT 0, @@ -3513,7 +3513,7 @@ CREATE TABLE IF NOT EXISTS `tphase`( CREATE TABLE IF NOT EXISTS `treset_pass` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, - `id_user` VARCHAR(100) NOT NULL DEFAULT '', + `id_user` VARCHAR(255) NOT NULL DEFAULT '', `cod_hash` VARCHAR(100) NOT NULL DEFAULT '', `reset_time` INT UNSIGNED NOT NULL DEFAULT 0, PRIMARY KEY (`id`) @@ -3818,7 +3818,7 @@ CREATE TABLE IF NOT EXISTS `tuser_task` ( -- --------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `tuser_task_scheduled` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, - `id_usuario` VARCHAR(60) NOT NULL DEFAULT '0', + `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0', `id_user_task` INT UNSIGNED NOT NULL DEFAULT 0, `args` TEXT, `scheduled` ENUM('no','hourly','daily','weekly','monthly','yearly','custom') DEFAULT 'no', @@ -4217,7 +4217,7 @@ CREATE TABLE IF NOT EXISTS `tbackup` ( `id` SERIAL, `utimestamp` BIGINT DEFAULT 0, `filename` VARCHAR(512) DEFAULT '', - `id_user` VARCHAR(60) DEFAULT '', + `id_user` VARCHAR(255) DEFAULT '', `description` MEDIUMTEXT, `pid` INT UNSIGNED DEFAULT 0, `filepath` VARCHAR(512) DEFAULT '', From bce182f2b2183e2701ee814f69789751df81c61d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Gonz=C3=A1lez?= <jose.gonzalez@pandorafms.com> Date: Thu, 9 Jun 2022 11:02:11 +0200 Subject: [PATCH 09/38] Improve event names --- pandora_console/include/styles/events.css | 1 + pandora_console/operation/events/events.php | 9 +++------ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/pandora_console/include/styles/events.css b/pandora_console/include/styles/events.css index 4b8177b2af..2b12f58e98 100644 --- a/pandora_console/include/styles/events.css +++ b/pandora_console/include/styles/events.css @@ -116,6 +116,7 @@ table.dataTable tbody td { padding-top: 7px; padding-bottom: 7px; border-bottom: 2px solid #dedede; + word-break: break-all; } .filter_input { diff --git a/pandora_console/operation/events/events.php b/pandora_console/operation/events/events.php index b72217fa2c..c1a88ee723 100644 --- a/pandora_console/operation/events/events.php +++ b/pandora_console/operation/events/events.php @@ -375,20 +375,17 @@ if (is_ajax() === true) { } $tmp->evento = str_replace('"', '', io_safe_output($tmp->evento)); - if (strlen($tmp->evento) >= 255) { - $tmp->evento = ui_print_truncate_text($tmp->evento, 255, $tmp->evento, true, false); - } - if ($tmp->module_name) { + if (empty($tmp->module_name) === false) { $tmp->module_name = io_safe_output($tmp->module_name); } - if ($tmp->comments) { + if (empty($tmp->comments) === false) { $tmp->comments = ui_print_comments($tmp->comments); } // Show last event. - if (isset($tmp->max_id_evento) && $tmp->max_id_evento !== $tmp->id_evento) { + if (isset($tmp->max_id_evento) === true && $tmp->max_id_evento !== $tmp->id_evento) { $max_event = db_get_row_sql( sprintf( 'SELECT criticity, timestamp FROM %s From a5517a9c0243cafe8a3ff9aaae7a71f94b866d02 Mon Sep 17 00:00:00 2001 From: Daniel Maya <daniel.maya@pandorafms.com> Date: Thu, 9 Jun 2022 15:12:05 +0200 Subject: [PATCH 10/38] #9134 Added disabled --- pandora_console/pandoradb.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index ebd940c749..6da9fd470b 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -3664,7 +3664,7 @@ CREATE TABLE IF NOT EXISTS `tautoconfig` ( `name` VARCHAR(100) NOT NULL, `order` INT NOT NULL DEFAULT 0, `description` TEXT, - + `disabled` TINYINT DEFAULT 0, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4; From 519fd13299b4a2ba96d09ce6d5c08b7fce681b97 Mon Sep 17 00:00:00 2001 From: Daniel Maya <daniel.maya@pandorafms.com> Date: Thu, 9 Jun 2022 15:22:14 +0200 Subject: [PATCH 11/38] #9134 Added dsiabled in mr --- pandora_console/extras/mr/55.sql | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pandora_console/extras/mr/55.sql b/pandora_console/extras/mr/55.sql index f53133c456..b802aa2dd8 100644 --- a/pandora_console/extras/mr/55.sql +++ b/pandora_console/extras/mr/55.sql @@ -4,4 +4,14 @@ ALTER TABLE `tservice` ADD COLUMN `enable_sunburst` tinyint(1) NOT NULL default ALTER TABLE `tdashboard` MODIFY `name` TEXT NOT NULL DEFAULT ''; +SET @st_oum763 = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = 'tautoconfig' AND table_schema = DATABASE() AND column_name = 'disabled') > 0, + "SELECT 1", + "ALTER TABLE `tautoconfig` ADD COLUMN `disabled` TINYINT DEFAULT 0" +)); + +PREPARE pr_oum763 FROM @st_oum763; +EXECUTE pr_oum763; +DEALLOCATE PREPARE pr_oum763; + COMMIT; From ae657ee018106361af096002dc6fe85474011d0b Mon Sep 17 00:00:00 2001 From: "edu.corral" <eduardo.corral@artica.es> Date: Thu, 9 Jun 2022 17:22:00 +0200 Subject: [PATCH 12/38] 8856 meta api functions --- pandora_console/include/functions_api.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pandora_console/include/functions_api.php b/pandora_console/include/functions_api.php index a265c10c84..d2c4f11823 100644 --- a/pandora_console/include/functions_api.php +++ b/pandora_console/include/functions_api.php @@ -5116,7 +5116,7 @@ function api_set_update_snmp_module($id_module, $thrash1, $other, $thrash3) function api_set_new_network_component($id, $thrash1, $other, $thrash2) { global $config; - if (is_metaconsole() === true) { + if (defined('METACONSOLE')) { return; } @@ -5218,7 +5218,7 @@ function api_set_new_plugin_component($id, $thrash1, $other, $thrash2) { global $config; - if (is_metaconsole() === true) { + if (defined('METACONSOLE')) { return; } @@ -5498,7 +5498,7 @@ function api_set_new_local_component($id, $thrash1, $other, $thrash2) { global $config; - if (is_metaconsole() === true) { + if (defined('METACONSOLE')) { return; } From 815a737a6937dbe1a60a5f54b73895d20fb40a4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Gonz=C3=A1lez?= <jose.gonzalez@pandorafms.com> Date: Fri, 10 Jun 2022 10:17:23 +0200 Subject: [PATCH 13/38] Change strings for Update Manager references to WARP update --- pandora_console/godmode/menu.php | 10 ++++---- pandora_console/godmode/um_client/index.php | 2 +- .../godmode/update_manager/update_manager.php | 24 +++++++++++------- .../update_manager/update_manager.setup.php | 25 ++++++++++--------- .../include/class/OrderInterpreter.class.php | 6 ++--- .../update_manager_client/views/register.php | 10 ++++---- 6 files changed, 42 insertions(+), 35 deletions(-) diff --git a/pandora_console/godmode/menu.php b/pandora_console/godmode/menu.php index aeecc25273..9d7719dd89 100644 --- a/pandora_console/godmode/menu.php +++ b/pandora_console/godmode/menu.php @@ -525,21 +525,21 @@ $menu_godmode['links']['sub'] = $sub; // Update Manager if (check_acl($config['id_user'], 0, 'PM') && $config['enable_update_manager']) { - $menu_godmode['messages']['text'] = __('Update manager'); + $menu_godmode['messages']['text'] = __('WARP Update'); $menu_godmode['messages']['id'] = 'god-um_messages'; $menu_godmode['messages']['sec2'] = ''; $sub = []; - $sub['godmode/update_manager/update_manager&tab=offline']['text'] = __('Update Manager offline'); + $sub['godmode/update_manager/update_manager&tab=offline']['text'] = __('Update offline'); $sub['godmode/update_manager/update_manager&tab=offline']['id'] = 'Offline'; - $sub['godmode/update_manager/update_manager&tab=online']['text'] = __('Update Manager online'); + $sub['godmode/update_manager/update_manager&tab=online']['text'] = __('Update online'); $sub['godmode/update_manager/update_manager&tab=online']['id'] = 'Online'; - $sub['godmode/update_manager/update_manager&tab=setup']['text'] = __('Update Manager options'); + $sub['godmode/update_manager/update_manager&tab=setup']['text'] = __('Options'); $sub['godmode/update_manager/update_manager&tab=setup']['id'] = 'Options'; - $sub['godmode/update_manager/update_manager&tab=history']['text'] = __('Update Manager journal'); + $sub['godmode/update_manager/update_manager&tab=history']['text'] = __('WARP journal'); $sub['godmode/update_manager/update_manager&tab=history']['id'] = 'Journal'; $menu_godmode['messages']['sub'] = $sub; diff --git a/pandora_console/godmode/um_client/index.php b/pandora_console/godmode/um_client/index.php index ebd13796c6..e74045b570 100644 --- a/pandora_console/godmode/um_client/index.php +++ b/pandora_console/godmode/um_client/index.php @@ -313,7 +313,7 @@ if (is_array($config) === true) { if ($mode === Manager::MODE_ONLINE && ($puid === null || $puid === 'OFFLINE') ) { - ui_print_error_message(__('Update manager online requires registration.')); + ui_print_error_message(__('Update online requires registration.')); } if ($mode === Manager::MODE_OFFLINE) { diff --git a/pandora_console/godmode/update_manager/update_manager.php b/pandora_console/godmode/update_manager/update_manager.php index da9eb8543d..e880e82a43 100644 --- a/pandora_console/godmode/update_manager/update_manager.php +++ b/pandora_console/godmode/update_manager/update_manager.php @@ -39,7 +39,7 @@ $buttons['setup'] = [ 'active' => ($tab == 'setup') ? true : false, 'text' => '<a href="'.ui_get_full_url( 'index.php?sec=gsetup&sec2=godmode/update_manager/update_manager&tab=setup' - ).'">'.html_print_image('images/gm_setup.png', true, ['title' => __('Options'), 'class' => 'invert_filter']).'</a>', + ).'">'.html_print_image('images/gm_setup.png', true, ['title' => __('Setup'), 'class' => 'invert_filter']).'</a>', ]; $buttons['history'] = [ @@ -53,42 +53,48 @@ $buttons['offline'] = [ 'active' => ($tab == 'offline') ? true : false, 'text' => '<a href="'.ui_get_full_url( 'index.php?sec=gsetup&sec2=godmode/update_manager/update_manager&tab=offli' - ).'ne">'.html_print_image('images/box.png', true, ['title' => __('Offline update manager'), 'class' => 'invert_filter']).'</a>', + ).'ne">'.html_print_image('images/box.png', true, ['title' => __('Offline update'), 'class' => 'invert_filter']).'</a>', ]; $buttons['online'] = [ 'active' => ($tab == 'online') ? true : false, 'text' => '<a href="'.ui_get_full_url( 'index.php?sec=gsetup&sec2=godmode/update_manager/update_manager&tab=onlin' - ).'e">'.html_print_image('images/op_gis.png', true, ['title' => __('Online update manager'), 'class' => 'invert_filter']).'</a>', + ).'e">'.html_print_image('images/op_gis.png', true, ['title' => __('Online update'), 'class' => 'invert_filter']).'</a>', ]; switch ($tab) { case 'history': - $title = __('Update manager » Journal'); + $title = __('Journal'); break; case 'setup': - $title = __('Update manager » Setup'); + $title = __('Setup'); break; case 'offline': - $title = __('Update manager » Offline'); + $title = __('Offline'); break; case 'online': default: - $title = __('Update manager » Online'); + $title = __('Online'); break; } -ui_print_page_header( +ui_print_standard_header( $title, 'images/gm_setup.png', false, '', true, - $buttons + $buttons, + [ + [ + 'link' => '', + 'label' => 'Warp Update', + ], + ] ); switch ($tab) { diff --git a/pandora_console/godmode/update_manager/update_manager.setup.php b/pandora_console/godmode/update_manager/update_manager.setup.php index e22c31031d..a671424bdc 100644 --- a/pandora_console/godmode/update_manager/update_manager.setup.php +++ b/pandora_console/godmode/update_manager/update_manager.setup.php @@ -268,17 +268,18 @@ $table->style[$i] = 'font-weight: bolder;width:250px'; $url_update_manager = update_manager_get_url(); -$table->data[$i][0] = __('URL update manager:'); +$table->data[$i][0] = __('WARP Update URL'); $table->data[$i++][1] = html_print_input_text( 'url_update_manager', $url_update_manager, __('URL update manager'), 80, 255, + true, true ); -$table->data[$i][0] = __('Use secured update manager:'); +$table->data[$i][0] = __('Use secured WARP Update'); $table->data[$i++][1] = html_print_input( [ 'type' => 'switch', @@ -287,7 +288,7 @@ $table->data[$i++][1] = html_print_input( ] ); -$table->data[$i][0] = __('Proxy server:'); +$table->data[$i][0] = __('Proxy server'); $table->data[$i++][1] = html_print_input_text( 'update_manager_proxy_server', $update_manager_proxy_server, @@ -297,7 +298,7 @@ $table->data[$i++][1] = html_print_input_text( true ); -$table->data[$i][0] = __('Proxy port:'); +$table->data[$i][0] = __('Proxy port'); $table->data[$i++][1] = html_print_input_text( 'update_manager_proxy_port', $update_manager_proxy_port, @@ -307,7 +308,7 @@ $table->data[$i++][1] = html_print_input_text( true ); -$table->data[$i][0] = __('Proxy user:'); +$table->data[$i][0] = __('Proxy user'); $table->data[$i++][1] = html_print_input_text( 'update_manager_proxy_user', $update_manager_proxy_user, @@ -317,7 +318,7 @@ $table->data[$i++][1] = html_print_input_text( true ); -$table->data[$i][0] = __('Proxy password:'); +$table->data[$i][0] = __('Proxy password'); $table->data[$i++][1] = html_print_input_password( 'update_manager_proxy_password', $update_manager_proxy_password, @@ -327,7 +328,7 @@ $table->data[$i++][1] = html_print_input_password( true ); -$table->data[$i][0] = __('Allow no-consecutive patches:'); +$table->data[$i][0] = __('Allow no-consecutive patches'); $table->data[$i++][1] = html_print_switch( [ 'name' => 'allow_offline_patches', @@ -336,7 +337,7 @@ $table->data[$i++][1] = html_print_switch( ] ); -$table->data[$i][0] = __('Limit to LTS updates:'); +$table->data[$i][0] = __('Limit to LTS updates'); $table->data[$i++][1] = html_print_switch( [ 'name' => 'lts_updates', @@ -346,11 +347,11 @@ $table->data[$i++][1] = html_print_switch( ); -$table->data[$i][0] = __('Registration ID:'); -$table->data[$i++][1] = '<i>'.$config['pandora_uid'].'</i>'; +$table->data[$i][0] = __('Registration ID'); +$table->data[$i++][1] = '<i>'.($config['pandora_uid'] ?? __('Not registred yet')).'</i>'; if (update_manager_verify_registration() === true && users_is_admin()) { - $table->data[$i][0] = __('Cancel registration:'); + $table->data[$i][0] = __('Cancel registration'); $table->data[$i][1] = '<a href="'; if ((bool) is_metaconsole() === true) { $table->data[$i][1] .= ui_get_full_url( @@ -367,7 +368,7 @@ if (update_manager_verify_registration() === true && users_is_admin()) { if (license_free()) { $config['identification_reminder'] = isset($config['identification_reminder']) ? $config['identification_reminder'] : 1; - $table->data[$i][0] = __('Pandora FMS community reminder').ui_print_help_tip(__('Every 8 days, a message is displayed to admin users to remember to register this Pandora instance'), true); + $table->data[$i][0] = __('%s community reminder', get_product_name()).ui_print_help_tip(__('Every 8 days, a message is displayed to admin users to remember to register this %s instance', get_product_name()), true); $table->data[$i][1] = __('Yes').' '.html_print_radio_button('identification_reminder', 1, '', $config['identification_reminder'], true).' '; $table->data[$i++][1] .= __('No').' '.html_print_radio_button('identification_reminder', 0, '', $config['identification_reminder'], true); } diff --git a/pandora_console/include/class/OrderInterpreter.class.php b/pandora_console/include/class/OrderInterpreter.class.php index 25ecfdae64..5762a678a7 100644 --- a/pandora_console/include/class/OrderInterpreter.class.php +++ b/pandora_console/include/class/OrderInterpreter.class.php @@ -336,7 +336,7 @@ class OrderInterpreter extends Wizard ), ], [ - 'name' => __('Update Manager'), + 'name' => __('WARP Update'), 'icon' => ui_get_full_url( 'images/menu/um_messages.menu_gray.png' ), @@ -404,10 +404,10 @@ class OrderInterpreter extends Wizard '.$value['name'].'</a><br>'; } - $iterator ++; + $iterator++; if ($iterator > 10) { - $more_results ++; + $more_results++; } } } diff --git a/pandora_console/update_manager_client/views/register.php b/pandora_console/update_manager_client/views/register.php index 45767ea1cc..7f126c79b6 100644 --- a/pandora_console/update_manager_client/views/register.php +++ b/pandora_console/update_manager_client/views/register.php @@ -45,7 +45,7 @@ $product_name = get_product_name(); ?> </head> <div id="registration_wizard" title=" - <?php echo __('Register to Update Manager'); ?> + <?php echo __('Register to WARP Update'); ?> " class="invisible"> <div class="register_update_manager"> <?php echo html_print_image('images/pandora_circle_big.png', true); ?> @@ -59,10 +59,10 @@ $product_name = get_product_name(); ?> <p> <?php echo __( - 'When you subscribe to the %s Update Manager service, you accept that we + 'When you subscribe to the WARP update service for %s, you accept that we register your %s instance as an identifier on a database owned by %s. This data will solely be used to provide you with information about %s and will not be conceded to third parties. You can unregister from - said database at any time from the Update Manager options.', + said database at any time from the WARP update options.', $product_name, $product_name, $product_name, @@ -72,7 +72,7 @@ $product_name = get_product_name(); ?> </p> <p> - <?php echo __('Visit our privacy policy for more information'); ?>: + <?php echo __('Visit our privacy policy for more information'); ?>: <a href="https://pandorafms.com/privacy-policy/" target="_blank">https://pandorafms.com/privacy-policy/</a> </p> @@ -109,7 +109,7 @@ $product_name = get_product_name(); ?> <!-- Verification modal.. --> <div id="reg_ensure_cancel" title="Confirmation Required" class="invisible"> <div class="font_12_20"> - <?php echo __('Are you sure you don\'t want to use update manager?'); ?> + <?php echo __('Are you sure you don\'t want to use WARP update?'); ?> <p> <?php echo __( From eed2030bba9d303d3d0ac5edaeb1b368470012a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Gonz=C3=A1lez?= <jose.gonzalez@pandorafms.com> Date: Fri, 10 Jun 2022 10:17:53 +0200 Subject: [PATCH 14/38] WIP: Backup upload --- .../update_manager_client/resources/styles/pandora.css | 6 +++--- pandora_console/update_manager_client/views/online.php | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pandora_console/update_manager_client/resources/styles/pandora.css b/pandora_console/update_manager_client/resources/styles/pandora.css index 6003234002..3781aa6fb2 100644 --- a/pandora_console/update_manager_client/resources/styles/pandora.css +++ b/pandora_console/update_manager_client/resources/styles/pandora.css @@ -168,7 +168,7 @@ div#box_online * { font-size: 16pt; - margin-bottom: 50px; + /*margin-bottom: 50px;*/ } #box_online .content { @@ -224,9 +224,9 @@ a.update_manager_button:after { #box_online #pkg_version { color: #82b92e; - font-size: 75pt; + font-size: 6em; font-weight: bold; - margin-bottom: 50px; + margin: 35px 0 !important; } /* METACONSOLE */ diff --git a/pandora_console/update_manager_client/views/online.php b/pandora_console/update_manager_client/views/online.php index a72372f0f7..5fa953d74b 100644 --- a/pandora_console/update_manager_client/views/online.php +++ b/pandora_console/update_manager_client/views/online.php @@ -40,10 +40,10 @@ <span class="loading" style="font-size: 18pt; display: none;"> <img src="images/wait.gif"> </span> - - <p style="font-weight: 600;">The latest version of package installed is:</p> + + <p style="font-weight: 600;margin-top: 3em;"><?php echo __('The latest version of package installed is').':'; ?></p> <div id="pkg_version"><?php echo $version; ?></div> - + <div class="content"> <?php if (empty($error) !== true) { From 0784b25ea06ee9f149b42599bf9a42f6206a3cb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Gonz=C3=A1lez?= <jose.gonzalez@pandorafms.com> Date: Fri, 10 Jun 2022 12:56:45 +0200 Subject: [PATCH 15/38] Update Warp strings --- pandora_console/godmode/menu.php | 4 ++-- .../godmode/update_manager/update_manager.setup.php | 4 ++-- pandora_console/include/constants.php | 2 +- pandora_console/update_manager_client/views/register.php | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pandora_console/godmode/menu.php b/pandora_console/godmode/menu.php index 9d7719dd89..bb43ad0df5 100644 --- a/pandora_console/godmode/menu.php +++ b/pandora_console/godmode/menu.php @@ -525,7 +525,7 @@ $menu_godmode['links']['sub'] = $sub; // Update Manager if (check_acl($config['id_user'], 0, 'PM') && $config['enable_update_manager']) { - $menu_godmode['messages']['text'] = __('WARP Update'); + $menu_godmode['messages']['text'] = __('Warp Update'); $menu_godmode['messages']['id'] = 'god-um_messages'; $menu_godmode['messages']['sec2'] = ''; @@ -539,7 +539,7 @@ if (check_acl($config['id_user'], 0, 'PM') && $config['enable_update_manager']) $sub['godmode/update_manager/update_manager&tab=setup']['text'] = __('Options'); $sub['godmode/update_manager/update_manager&tab=setup']['id'] = 'Options'; - $sub['godmode/update_manager/update_manager&tab=history']['text'] = __('WARP journal'); + $sub['godmode/update_manager/update_manager&tab=history']['text'] = __('Warp journal'); $sub['godmode/update_manager/update_manager&tab=history']['id'] = 'Journal'; $menu_godmode['messages']['sub'] = $sub; diff --git a/pandora_console/godmode/update_manager/update_manager.setup.php b/pandora_console/godmode/update_manager/update_manager.setup.php index a671424bdc..e3ca9f4958 100644 --- a/pandora_console/godmode/update_manager/update_manager.setup.php +++ b/pandora_console/godmode/update_manager/update_manager.setup.php @@ -268,7 +268,7 @@ $table->style[$i] = 'font-weight: bolder;width:250px'; $url_update_manager = update_manager_get_url(); -$table->data[$i][0] = __('WARP Update URL'); +$table->data[$i][0] = __('Warp Update URL'); $table->data[$i++][1] = html_print_input_text( 'url_update_manager', $url_update_manager, @@ -279,7 +279,7 @@ $table->data[$i++][1] = html_print_input_text( true ); -$table->data[$i][0] = __('Use secured WARP Update'); +$table->data[$i][0] = __('Use secured Warp Update'); $table->data[$i++][1] = html_print_input( [ 'type' => 'switch', diff --git a/pandora_console/include/constants.php b/pandora_console/include/constants.php index e1d24ede9c..9e4f13dedc 100644 --- a/pandora_console/include/constants.php +++ b/pandora_console/include/constants.php @@ -802,7 +802,7 @@ define('AUDIT_LOG_SNMP_MANAGEMENT', 'SNMP management'); define('AUDIT_LOG_DASHBOARD_MANAGEMENT', 'Dashboard management'); define('AUDIT_LOG_SERVICE_MANAGEMENT', 'Service management'); define('AUDIT_LOG_INCIDENT_MANAGEMENT', 'Incident management'); -define('AUDIT_LOG_UMC', 'Update Manager'); +define('AUDIT_LOG_UMC', 'Warp Manager'); // MIMEs. define( diff --git a/pandora_console/update_manager_client/views/register.php b/pandora_console/update_manager_client/views/register.php index 7f126c79b6..89225432ad 100644 --- a/pandora_console/update_manager_client/views/register.php +++ b/pandora_console/update_manager_client/views/register.php @@ -45,7 +45,7 @@ $product_name = get_product_name(); ?> </head> <div id="registration_wizard" title=" - <?php echo __('Register to WARP Update'); ?> + <?php echo __('Register to Warp Update'); ?> " class="invisible"> <div class="register_update_manager"> <?php echo html_print_image('images/pandora_circle_big.png', true); ?> @@ -59,10 +59,10 @@ $product_name = get_product_name(); ?> <p> <?php echo __( - 'When you subscribe to the WARP update service for %s, you accept that we + 'When you subscribe to the Warp update service for %s, you accept that we register your %s instance as an identifier on a database owned by %s. This data will solely be used to provide you with information about %s and will not be conceded to third parties. You can unregister from - said database at any time from the WARP update options.', + said database at any time from the Warp update options.', $product_name, $product_name, $product_name, @@ -109,7 +109,7 @@ $product_name = get_product_name(); ?> <!-- Verification modal.. --> <div id="reg_ensure_cancel" title="Confirmation Required" class="invisible"> <div class="font_12_20"> - <?php echo __('Are you sure you don\'t want to use WARP update?'); ?> + <?php echo __('Are you sure you don\'t want to use Warp update?'); ?> <p> <?php echo __( From 022d28981dacb8e0f17502e265857f15509a0e89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Gonz=C3=A1lez?= <jose.gonzalez@pandorafms.com> Date: Fri, 10 Jun 2022 12:57:04 +0200 Subject: [PATCH 16/38] Update styles --- pandora_console/include/styles/pandora_black.css | 4 ---- .../update_manager_client/resources/styles/pandora.css | 9 ++++----- .../update_manager_client/resources/styles/um.css | 8 ++++---- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/pandora_console/include/styles/pandora_black.css b/pandora_console/include/styles/pandora_black.css index 3db3587bef..e3df14e51e 100644 --- a/pandora_console/include/styles/pandora_black.css +++ b/pandora_console/include/styles/pandora_black.css @@ -1186,13 +1186,9 @@ a.pandora_pagination, } #box_online { background-image: url("../../images/update_pandora_black.jpg") !important; - background-position: left, left !important; - background-repeat: no-repeat; background-color: #000 !important; padding: 40px 50px; border: 1px solid #111 !important; - border-radius: 5px; - min-height: 600px; background-size: contain; box-shadow: 1px 1px 4px rgba(160, 160, 160, 0.514); } diff --git a/pandora_console/update_manager_client/resources/styles/pandora.css b/pandora_console/update_manager_client/resources/styles/pandora.css index 3781aa6fb2..537f28c823 100644 --- a/pandora_console/update_manager_client/resources/styles/pandora.css +++ b/pandora_console/update_manager_client/resources/styles/pandora.css @@ -156,19 +156,18 @@ #box_online { background-image: url("../images/update_manager_background.jpg"); - background-position: center center; + background-position: top right; background-repeat: no-repeat; background-color: #fff; padding: 40px 50px; border: 1px solid #f3f3f3; border-radius: 5px; - min-height: 600px; + min-height: 400px; background-size: contain; } div#box_online * { - font-size: 16pt; - /*margin-bottom: 50px;*/ + font-size: 14pt; } #box_online .content { @@ -226,7 +225,7 @@ a.update_manager_button:after { color: #82b92e; font-size: 6em; font-weight: bold; - margin: 35px 0 !important; + margin: 30px 0 !important; } /* METACONSOLE */ diff --git a/pandora_console/update_manager_client/resources/styles/um.css b/pandora_console/update_manager_client/resources/styles/um.css index a876a69219..1f469512ef 100644 --- a/pandora_console/update_manager_client/resources/styles/um.css +++ b/pandora_console/update_manager_client/resources/styles/um.css @@ -26,10 +26,10 @@ #um-loading { background-image: url(../images/spinner.gif); - height: 1.3em; + height: 1em; background-repeat: no-repeat; background-size: contain; - text-indent: 6em; + text-indent: 4.5em; } #um-buttons { @@ -72,10 +72,10 @@ background-color: #343434; background-repeat: no-repeat; background-position: 50% 20%; - height: 3em; + height: 1.8em; text-align: center; display: block; - padding-top: 5.7em; + padding-top: 5.3em; width: 100%; } #um-update-details-content { From 05bcbfaf7942a21d49b440bb02f49b616faf297f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Gonz=C3=A1lez?= <jose.gonzalez@pandorafms.com> Date: Fri, 10 Jun 2022 12:57:25 +0200 Subject: [PATCH 17/38] Minor fixes --- .../godmode/update_manager/update_manager.php | 49 ++++++++++++------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/pandora_console/godmode/update_manager/update_manager.php b/pandora_console/godmode/update_manager/update_manager.php index e880e82a43..755680d6d1 100644 --- a/pandora_console/godmode/update_manager/update_manager.php +++ b/pandora_console/godmode/update_manager/update_manager.php @@ -1,21 +1,36 @@ <?php +/** + * Update manager. + * + * @category Update Manager + * @package Pandora FMS + * @subpackage Community + * @version 1.0.0 + * @license See below + * + * ______ ___ _______ _______ ________ + * | __ \.-----.--.--.--| |.-----.----.-----. | ___| | | __| + * | __/| _ | | _ || _ | _| _ | | ___| |__ | + * |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______| + * + * ============================================================================ + * Copyright (c) 2005-2022 Artica Soluciones Tecnologicas + * Please see http://pandorafms.org for full contribution list + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation for version 2. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * ============================================================================ + */ -// Pandora FMS - http://pandorafms.com -// ================================================== -// Copyright (c) 2005-2021 Artica Soluciones Tecnologicas -// Please see http://pandorafms.org for full contribution list -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; version 2 -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// Begin. global $config; check_login(); -// The ajax is in -// include/ajax/update_manager.php +// The ajax is in include/ajax/update_manager.php. if (! check_acl($config['id_user'], 0, 'PM') && ! is_user_admin($config['id_user'])) { db_pandora_audit( AUDIT_LOG_ACL_VIOLATION, @@ -36,28 +51,28 @@ if ($php_version_array[0] < 7) { $tab = get_parameter('tab', 'online'); $buttons['setup'] = [ - 'active' => ($tab == 'setup') ? true : false, + 'active' => ($tab === 'setup') ? true : false, 'text' => '<a href="'.ui_get_full_url( 'index.php?sec=gsetup&sec2=godmode/update_manager/update_manager&tab=setup' ).'">'.html_print_image('images/gm_setup.png', true, ['title' => __('Setup'), 'class' => 'invert_filter']).'</a>', ]; $buttons['history'] = [ - 'active' => ($tab == 'history') ? true : false, + 'active' => ($tab === 'history') ? true : false, 'text' => '<a href="'.ui_get_full_url( 'index.php?sec=gsetup&sec2=godmode/update_manager/update_manager&tab=histo' ).'ry">'.html_print_image('images/gm_db.png', true, ['title' => __('Journal'), 'class' => 'invert_filter']).'</a>', ]; $buttons['offline'] = [ - 'active' => ($tab == 'offline') ? true : false, + 'active' => ($tab === 'offline') ? true : false, 'text' => '<a href="'.ui_get_full_url( 'index.php?sec=gsetup&sec2=godmode/update_manager/update_manager&tab=offli' ).'ne">'.html_print_image('images/box.png', true, ['title' => __('Offline update'), 'class' => 'invert_filter']).'</a>', ]; $buttons['online'] = [ - 'active' => ($tab == 'online') ? true : false, + 'active' => ($tab === 'online') ? true : false, 'text' => '<a href="'.ui_get_full_url( 'index.php?sec=gsetup&sec2=godmode/update_manager/update_manager&tab=onlin' ).'e">'.html_print_image('images/op_gis.png', true, ['title' => __('Online update'), 'class' => 'invert_filter']).'</a>', From 3ec50f10b4b0dc56e2d5bce29b0a353abc21bda7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Gonz=C3=A1lez?= <jose.gonzalez@pandorafms.com> Date: Fri, 10 Jun 2022 12:57:45 +0200 Subject: [PATCH 18/38] Update warp strings --- pandora_console/include/class/OrderInterpreter.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandora_console/include/class/OrderInterpreter.class.php b/pandora_console/include/class/OrderInterpreter.class.php index 5762a678a7..f32c48b1d0 100644 --- a/pandora_console/include/class/OrderInterpreter.class.php +++ b/pandora_console/include/class/OrderInterpreter.class.php @@ -336,7 +336,7 @@ class OrderInterpreter extends Wizard ), ], [ - 'name' => __('WARP Update'), + 'name' => __('Warp Update'), 'icon' => ui_get_full_url( 'images/menu/um_messages.menu_gray.png' ), From b068b35d78082a1f9fa246f47e3ab46958ccdac6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Gonz=C3=A1lez?= <jose.gonzalez@pandorafms.com> Date: Fri, 10 Jun 2022 12:58:13 +0200 Subject: [PATCH 19/38] Visual improvements --- .../update_manager_client/resources/javascript/umc.js | 2 +- pandora_console/update_manager_client/views/online.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pandora_console/update_manager_client/resources/javascript/umc.js b/pandora_console/update_manager_client/resources/javascript/umc.js index e5b3ba1a5c..659a240c61 100644 --- a/pandora_console/update_manager_client/resources/javascript/umc.js +++ b/pandora_console/update_manager_client/resources/javascript/umc.js @@ -469,7 +469,7 @@ function umShowUpdateDetails(update) { if (typeof $ == "function") { $("#um-update-details").dialog({ title: update, - width: 650, + width: 800, height: 600 }); } diff --git a/pandora_console/update_manager_client/views/online.php b/pandora_console/update_manager_client/views/online.php index 5fa953d74b..d58ad825aa 100644 --- a/pandora_console/update_manager_client/views/online.php +++ b/pandora_console/update_manager_client/views/online.php @@ -41,7 +41,7 @@ <img src="images/wait.gif"> </span> - <p style="font-weight: 600;margin-top: 3em;"><?php echo __('The latest version of package installed is').':'; ?></p> + <p style="font-weight: 600;"><?php echo __('The latest version of package installed is').':'; ?></p> <div id="pkg_version"><?php echo $version; ?></div> <div class="content"> From 2568c877a2cfb48ecaff59ae9333d2e3b55f95d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Gonz=C3=A1lez?= <jose.gonzalez@pandorafms.com> Date: Mon, 13 Jun 2022 12:31:33 +0200 Subject: [PATCH 20/38] Clear unnecessary CSS file --- .../resources/styles/pandora.css | 317 ------------------ .../update_manager_client/views/offline.php | 1 - .../update_manager_client/views/online.php | 1 - 3 files changed, 319 deletions(-) delete mode 100644 pandora_console/update_manager_client/resources/styles/pandora.css diff --git a/pandora_console/update_manager_client/resources/styles/pandora.css b/pandora_console/update_manager_client/resources/styles/pandora.css deleted file mode 100644 index 537f28c823..0000000000 --- a/pandora_console/update_manager_client/resources/styles/pandora.css +++ /dev/null @@ -1,317 +0,0 @@ -.update_text p { - font-size: 11pt; -} - -.update_text a { - font-size: 11pt; - color: #82b92e; -} - -.update_manager_warning p { - font-size: 10pt; -} - -.ui-widget-content, -.ui-widget-content p { - font-size: 12pt; -} -.fileupload_form { - background-color: #373a3d; - background-image: -moz-linear-gradient(center, #373a3d, #313437); - border-radius: 3px; - margin: 0px; - padding: 30px; -} -#drop_file { - background-color: #e6e6e6; - border: 20px solid rgba(0, 0, 0, 0); - border-radius: 3px; - color: #707070; - font-size: 16px; - font-weight: bold; - margin-bottom: 30px; - padding: 40px 50px; - text-align: center; - text-transform: uppercase; -} -#drop_file table { - vertical-align: middle; -} -#drop_file table td, -#drop_file table label { - color: #707070; - font-size: 16px; - font-weight: bold; - margin-top: 0; - vertical-align: middle; -} -#drop_file table select { - float: none; -} -#drop_file a { - background-color: #82b92e; - border-radius: 2px; - color: #ffffff; - cursor: pointer; - display: inline-block; - font-size: 14px; - line-height: 1; - padding: 12px 26px; -} -#drop_file a:hover { - background-color: #a6ce67; - text-decoration: none; -} -#drop_file input { - display: none; -} - -.fileupload_form ul { - border-bottom: 1px solid #3d4043; - border-top: 1px solid #2b2e31; - list-style: none outside none; - margin: 0 -30px; - padding: 0; -} -.fileupload_form ul li { - background-color: #333639; - background-image: -moz-linear-gradient(center, #333639, #303335); - border-bottom: 1px solid #2b2e31; - border-top: 1px solid #3d4043; - padding: 15px; - position: relative; -} -.fileupload_form ul li #input-progress { - left: 68px; - position: absolute; -} -.fileupload_form ul li p { - color: #eeeeee; - font-size: 12px; - font-weight: bold; - left: 95px; - overflow: hidden; - position: absolute; - top: 12px; - white-space: nowrap; -} -.fileupload_form ul li i { - color: #7f7f7f; - display: block; - font-style: normal; - font-weight: normal; -} -.fileupload_form ul li canvas { - left: 13px; - position: absolute; - top: 15px; -} -.fileupload_form ul li span { - background: url("../images/check-cross.png") no-repeat scroll 0 0 - rgba(0, 0, 0, 0); - cursor: pointer; - height: 12px; - position: absolute; - right: 13px; - top: 34px; - width: 15px; -} -.fileupload_form ul li div { - display: block !important; -} -.fileupload_form ul li.working span { - background-position: 0 -12px; - height: 16px; -} -.fileupload_form ul li.loading span { - background: url("../images/spinner.gif") no-repeat scroll 0 0 rgba(0, 0, 0, 0); - height: 16px; -} -.fileupload_form ul li.suc span { - background: url("../images/check-cross.png") no-repeat scroll 0 0 - rgba(0, 0, 0, 0); - height: 12px; -} -.fileupload_form ul li.suc p { - color: #5a8629; -} -.fileupload_form ul li.error span { - background: url("../images/check-cross.png") no-repeat scroll 0 -12px rgba(0, 0, 0, 0); - height: 16px; -} -.fileupload_form ul li.error p { - color: #ff3333; -} - -#log_zone { - background-color: #e6e6e6; - border: 20px solid rgba(0, 0, 0, 0); - border-radius: 3px; - color: #707070; - font-size: 12px; - margin-bottom: 30px; - padding: 10px; - text-align: left; -} - -#box_online { - background-image: url("../images/update_manager_background.jpg"); - background-position: top right; - background-repeat: no-repeat; - background-color: #fff; - padding: 40px 50px; - border: 1px solid #f3f3f3; - border-radius: 5px; - min-height: 400px; - background-size: contain; -} - -div#box_online * { - font-size: 14pt; -} - -#box_online .content { - max-width: 50%; -} - -.update_popup { - display: flex; - justify-content: space-between; - align-items: center; - padding-left: 10px; - padding-right: 10px; -} - -.update_icon { - padding-left: 20px; -} - -.update_text h3 { - font-weight: bold; - font-size: 12pt; -} - -.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { - float: left; - padding-left: 19px; - padding-bottom: 5px; -} - -a.update_manager_button { - padding: 10px 12px; - margin-top: 10px; - display: inline-flex; - align-items: center; - font-size: 16px; - border-radius: 4px; - text-decoration: none; -} - -a.update_manager_button:after { - content: url(../images/update_manager_button.png); - padding-left: 10px; -} - -.progressbar { - margin-top: 15px; -} - -.ui-draggable, -.ui-draggable .ui-dialog-titlebar { - cursor: default; -} - -#box_online #pkg_version { - color: #82b92e; - font-size: 6em; - font-weight: bold; - margin: 30px 0 !important; -} - -/* METACONSOLE */ -.box_online_meta { - background: none; - min-height: 400px; - text-align: center; - border: none; -} - -div#box_online.box_online_meta * { - font-size: 14pt; -} - -#box_online.box_online_meta .content { - max-width: 100%; -} - -#box_online.box_online_meta #pkg_version { - font-size: 60pt; -} - -/* COMMUNITY */ -.update_manager_open { - max-width: 50%; - font-size: 10pt; - margin-top: 40px; - padding: 20px; - border: 1px solid #eaeaea; - border-radius: 5px; -} - -.update_manager_warning { - display: flex; - align-items: center; - margin-bottom: 10px; -} - -.update_manager_warning img { - padding-right: 20px; - width: 90px; -} - -a.update_manager_button_open { - padding: 5px 10px; - font-size: 16px; - text-decoration: none; - border: 1px solid #82b92e; - color: #82b92e; - border-radius: 2px; -} - -a.update_manager_button_open:hover { - color: #fff; - background-color: #82b92e; -} - -#um-update-details-header { - background-image: url(../images/pandora_logo.png); -} - -.um-progress-bar { - background-color: #8bb92e !important; -} - -.um-error { - color: #e63c52; -} - -.um-success { - color: #8bb92e; -} - -.dz-success-mark svg { - background: #8bb92e; - border-radius: 50%; -} - -.newsletter_div { - font-size: 12pt; - margin: 5px 20px; - float: left; - padding-top: 23px; -} -.register_update_manager { - margin: 5px 0 10px; - float: left; - padding-left: 15px; -} diff --git a/pandora_console/update_manager_client/views/offline.php b/pandora_console/update_manager_client/views/offline.php index 0278491228..ae64d92fde 100644 --- a/pandora_console/update_manager_client/views/offline.php +++ b/pandora_console/update_manager_client/views/offline.php @@ -45,7 +45,6 @@ <script src="<?php $asset('resources/javascript/jquery.iframe-transport.js'); ?>" type="text/javascript"></script> <script src="<?php $asset('resources/javascript/jquery.knob.js'); ?>" type="text/javascript"></script> <link rel="stylesheet" href="<?php $asset('resources/styles/um.css'); ?>"> - <link rel="stylesheet" href="<?php $asset('resources/styles/pandora.css'); ?>"> </head> <div id="box_offline"> diff --git a/pandora_console/update_manager_client/views/online.php b/pandora_console/update_manager_client/views/online.php index d58ad825aa..2ba4787dd4 100644 --- a/pandora_console/update_manager_client/views/online.php +++ b/pandora_console/update_manager_client/views/online.php @@ -31,7 +31,6 @@ ?> <head> <link rel="stylesheet" href="<?php $asset('resources/styles/um.css'); ?>"> - <link rel="stylesheet" href="<?php $asset('resources/styles/pandora.css'); ?>"> <script src="<?php $asset('resources/javascript/umc.js'); ?>" type="text/javascript"></script> </head> From 5539ca51c52f0c49a3b71b2f823cf910b5af1d8e Mon Sep 17 00:00:00 2001 From: "alejandro.campos@artica.es" <alejandro.campos@artica.es> Date: Mon, 13 Jun 2022 12:32:04 +0200 Subject: [PATCH 21/38] minor change --- .../godmode/update_manager/update_manager.php | 39 ++++++++++++++++--- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/pandora_console/godmode/update_manager/update_manager.php b/pandora_console/godmode/update_manager/update_manager.php index 991491843a..80a81f8ecb 100644 --- a/pandora_console/godmode/update_manager/update_manager.php +++ b/pandora_console/godmode/update_manager/update_manager.php @@ -107,11 +107,40 @@ switch ($tab) { case 'online': default: - if ($config['node_metaconsole'] === 0) { - $mode = \UpdateManager\UI\Manager::MODE_ONLINE; - include $config['homedir'].'/godmode/um_client/index.php'; - } else { - ui_print_warning_message(__('Please register on metaconsole.')); + if (is_metaconsole() === false && has_metaconsole() === true) { + $meta_puid = null; + + $server_id = $config['metaconsole_node_id']; + $dbh = (object) $config['dbconnection']; + + // Connect to metaconsole. + $result_code = metaconsole_load_external_db( + [ + 'dbhost' => $config['replication_dbhost'], + 'dbuser' => $config['replication_dbuser'], + 'dbpass' => io_output_password($config['replication_dbpass']), + 'dbname' => $config['replication_dbname'], + ] + ); + + if ($result_code < 0) { + break; + } + + $value = db_get_value('value', 'tconfig', 'token', 'pandora_uid'); + + $meta_puid = $value; + + // Return connection to node. + metaconsole_restore_db(); + + if ($meta_puid === false || $meta_puid === null) { + ui_print_warning_message(__('Please register on metaconsole first.')); + break; + } } + + $mode = \UpdateManager\UI\Manager::MODE_ONLINE; + include $config['homedir'].'/godmode/um_client/index.php'; break; } From b5de60fb691c5dbce8e868674f5d6abcc831e165 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Gonz=C3=A1lez?= <jose.gonzalez@pandorafms.com> Date: Mon, 13 Jun 2022 12:33:03 +0200 Subject: [PATCH 22/38] Update manager to Warp manager --- pandora_console/extras/delete_files/delete_files.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/pandora_console/extras/delete_files/delete_files.txt b/pandora_console/extras/delete_files/delete_files.txt index fe13fd3149..73284cb169 100644 --- a/pandora_console/extras/delete_files/delete_files.txt +++ b/pandora_console/extras/delete_files/delete_files.txt @@ -1665,3 +1665,4 @@ godmode/um_client/vendor/sebastian/object-enumerator/tests godmode/um_client/vendor/sebastian/object-enumerator godmode/um_client/vendor/sebastian godmode/um_client/vendor +/update_manager_client/resources/styles/pandora.css \ No newline at end of file From 8e4cffbc0a426e9d6ee901c77bf0a080abe20bfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Gonz=C3=A1lez?= <jose.gonzalez@pandorafms.com> Date: Mon, 13 Jun 2022 12:34:16 +0200 Subject: [PATCH 23/38] Several style refactory --- pandora_console/include/styles/register.css | 4 +- .../resources/javascript/umc.js | 6 +- .../resources/styles/um.css | 325 +++++++++++++++++- .../update_manager_client/views/register.php | 20 +- 4 files changed, 339 insertions(+), 16 deletions(-) diff --git a/pandora_console/include/styles/register.css b/pandora_console/include/styles/register.css index b1d8068ef3..77d56dbc85 100644 --- a/pandora_console/include/styles/register.css +++ b/pandora_console/include/styles/register.css @@ -29,7 +29,7 @@ input[type="button"].submit-next { background: #fff; padding: 5px; font-size: 1.3em; - margin: 0.5em 1em 0.5em 0; + margin: 0.5em 0em; cursor: pointer; text-align: center; height: 30px; @@ -71,7 +71,7 @@ div.submit_buttons_container { position: relative; margin: 10px auto 0px; bottom: 0px; - width: 90%; + width: 95%; clear: both; height: 4em; } diff --git a/pandora_console/update_manager_client/resources/javascript/umc.js b/pandora_console/update_manager_client/resources/javascript/umc.js index 659a240c61..af5832daba 100644 --- a/pandora_console/update_manager_client/resources/javascript/umc.js +++ b/pandora_console/update_manager_client/resources/javascript/umc.js @@ -460,7 +460,9 @@ function umShowUpdateDetails(update) { var um_update_details = document.getElementById("um-update-details"); var header = document.getElementById("um-update-details-header"); var content = document.getElementById("um-update-details-content"); - + var detailTitle = document + .getElementsByClassName("um-package-details") + .item(0).innerText; header.innerText = texts.updateText + " " + updates[update].version; content.innerText = updates[update].description; @@ -468,7 +470,7 @@ function umShowUpdateDetails(update) { um_update_details.style.display = "block"; if (typeof $ == "function") { $("#um-update-details").dialog({ - title: update, + title: detailTitle, width: 800, height: 600 }); diff --git a/pandora_console/update_manager_client/resources/styles/um.css b/pandora_console/update_manager_client/resources/styles/um.css index 1f469512ef..d0208bd468 100644 --- a/pandora_console/update_manager_client/resources/styles/um.css +++ b/pandora_console/update_manager_client/resources/styles/um.css @@ -9,6 +9,58 @@ margin: 5% auto; padding: 2em; } +a.update_manager_button { + padding: 10px 12px; + margin-top: 10px; + display: inline-flex; + align-items: center; + font-size: 16px; + border-radius: 4px; + text-decoration: none; +} + +a.update_manager_button:after { + content: url(../images/update_manager_button.png); + padding-left: 10px; +} + +.progressbar { + margin-top: 15px; +} + +#log_zone { + background-color: #e6e6e6; + border: 20px solid rgba(0, 0, 0, 0); + border-radius: 3px; + color: #707070; + font-size: 12px; + margin-bottom: 30px; + padding: 10px; + text-align: left; +} + +#box_online { + background-image: url("../images/update_manager_background.jpg"); + background-position: top right; + background-repeat: no-repeat; + background-color: #fff; + padding: 40px 50px; + border: 1px solid #f3f3f3; + border-radius: 5px; + min-height: 400px; + background-size: contain; +} + +#box_online #pkg_version { + color: #82b92e; + font-size: 6em; + font-weight: bold; + margin: 30px 0 !important; +} + +.update_manager_warning p { + font-size: 10pt; +} #update-list { max-height: 0; overflow: hidden; @@ -16,6 +68,31 @@ flex-direction: column; transition: max-height 0.15s ease-in-out; } +.update_popup { + display: flex; + justify-content: space-between; + align-items: center; + padding-left: 10px; + padding-right: 10px; +} + +.update_icon { + padding-left: 20px; +} + +.update_text h3 { + font-weight: bold; + font-size: 12pt; +} + +.update_text p { + font-size: 11pt; +} + +.update_text a { + font-size: 11pt; + color: #82b92e; +} .update { display: flex; @@ -23,7 +100,155 @@ justify-content: space-around; align-items: center; } +#drop_file { + background-color: #e6e6e6; + border: 20px solid rgba(0, 0, 0, 0); + border-radius: 3px; + color: #707070; + font-size: 16px; + font-weight: bold; + margin-bottom: 30px; + padding: 40px 50px; + text-align: center; + text-transform: uppercase; +} +#drop_file table { + vertical-align: middle; +} + +#drop_file table td, +#drop_file table label { + color: #707070; + font-size: 16px; + font-weight: bold; + margin-top: 0; + vertical-align: middle; +} + +#drop_file table select { + float: none; +} + +#drop_file a { + background-color: #82b92e; + border-radius: 2px; + color: #ffffff; + cursor: pointer; + display: inline-block; + font-size: 14px; + line-height: 1; + padding: 12px 26px; +} + +#drop_file a:hover { + background-color: #a6ce67; + text-decoration: none; +} + +#drop_file input { + display: none; +} + +/* Offline form */ +.fileupload_form { + background-color: #373a3d; + background-image: -moz-linear-gradient(center, #373a3d, #313437); + border-radius: 3px; + margin: 0px; + padding: 30px; +} + +.fileupload_form ul { + border-bottom: 1px solid #3d4043; + border-top: 1px solid #2b2e31; + list-style: none outside none; + margin: 0 -30px; + padding: 0; +} + +.fileupload_form ul li { + background-color: #333639; + background-image: -moz-linear-gradient(center, #333639, #303335); + border-bottom: 1px solid #2b2e31; + border-top: 1px solid #3d4043; + padding: 15px; + position: relative; +} + +.fileupload_form ul li #input-progress { + left: 68px; + position: absolute; +} + +.fileupload_form ul li p { + color: #eeeeee; + font-size: 12px; + font-weight: bold; + left: 95px; + overflow: hidden; + position: absolute; + top: 12px; + white-space: nowrap; +} + +.fileupload_form ul li i { + color: #7f7f7f; + display: block; + font-style: normal; + font-weight: normal; +} + +.fileupload_form ul li canvas { + left: 13px; + position: absolute; + top: 15px; +} + +.fileupload_form ul li span { + background: url("../images/check-cross.png") no-repeat scroll 0 0 + rgba(0, 0, 0, 0); + cursor: pointer; + height: 12px; + position: absolute; + right: 13px; + top: 34px; + width: 15px; +} + +.fileupload_form ul li div { + display: block !important; +} + +.fileupload_form ul li.working span { + background-position: 0 -12px; + height: 16px; +} + +.fileupload_form ul li.loading span { + background: url("../images/spinner.gif") no-repeat scroll 0 0 rgba(0, 0, 0, 0); + height: 16px; +} + +.fileupload_form ul li.suc span { + background: url("../images/check-cross.png") no-repeat scroll 0 0 + rgba(0, 0, 0, 0); + height: 12px; +} + +.fileupload_form ul li.suc p { + color: #5a8629; +} + +.fileupload_form ul li.error span { + background: url("../images/check-cross.png") no-repeat scroll 0 -12px rgba(0, 0, 0, 0); + height: 16px; +} + +.fileupload_form ul li.error p { + top: 18px; + color: #ff3333; +} #um-loading { background-image: url(../images/spinner.gif); height: 1em; @@ -64,7 +289,7 @@ } #um-update-details * { - font-size: 16pt; + font-size: 10pt; } #um-update-details-header { @@ -115,11 +340,17 @@ background-color: #1f282b; } +div#box_online * { + font-size: 14pt; +} + +#box_online .content { + max-width: 50%; +} #box_offline form { background-color: #373a3d; background-image: -moz-linear-gradient(top, #373a3d, #313437); border-radius: 3px; - font-family: "PT Sans Narrow", sans-serif; margin: 0px; padding: 30px; } @@ -180,7 +411,9 @@ span.warning { justify-content: space-between; } .ui-dialog-content.ui-widget-content p { + font-size: 10pt; word-break: keep-all; + text-align: justify; } .license_text { @@ -204,3 +437,91 @@ input.error { textarea#signature { margin-top: 1em; } +a.update_manager_button_open:hover { + color: #fff; + background-color: #82b92e; +} + +#um-update-details-header { + background-image: url(../images/pandora_logo.png); + font-size: 16pt; +} + +.um-progress-bar { + background-color: #8bb92e !important; +} + +.um-error { + color: #e63c52; +} + +.um-success { + color: #8bb92e; +} + +.dz-success-mark svg { + background: #8bb92e; + border-radius: 50%; +} + +.newsletter_div { + margin: 5px 20px; + float: left; + padding-top: 23px; +} + +.register_update_manager { + margin: 5px 0 10px; + float: left; + padding-left: 15px; +} + +/* METACONSOLE */ +.box_online_meta { + background: none; + min-height: 400px; + text-align: center; + border: none; +} + +div#box_online.box_online_meta * { + font-size: 14pt; +} + +#box_online.box_online_meta .content { + max-width: 100%; +} + +#box_online.box_online_meta #pkg_version { + font-size: 60pt; +} + +/* COMMUNITY */ +.update_manager_open { + max-width: 50%; + font-size: 10pt; + margin-top: 40px; + padding: 20px; + border: 1px solid #eaeaea; + border-radius: 5px; +} + +.update_manager_warning { + display: flex; + align-items: center; + margin-bottom: 10px; +} + +.update_manager_warning img { + padding-right: 20px; + width: 90px; +} + +a.update_manager_button_open { + padding: 5px 10px; + font-size: 16px; + text-decoration: none; + border: 1px solid #82b92e; + color: #82b92e; + border-radius: 2px; +} diff --git a/pandora_console/update_manager_client/views/register.php b/pandora_console/update_manager_client/views/register.php index 89225432ad..b893479c23 100644 --- a/pandora_console/update_manager_client/views/register.php +++ b/pandora_console/update_manager_client/views/register.php @@ -41,7 +41,6 @@ $product_name = get_product_name(); ?> <script src="<?php $asset('resources/javascript/umc.js'); ?>" type="text/javascript"></script> <link rel="stylesheet" href="<?php $asset('resources/styles/jquery-ui.min.css'); ?>"> <link rel="stylesheet" href="<?php $asset('resources/styles/um.css'); ?>"> - <link rel="stylesheet" href="<?php $asset('resources/styles/pandora.css'); ?>"> </head> <div id="registration_wizard" title=" @@ -51,12 +50,12 @@ $product_name = get_product_name(); ?> <?php echo html_print_image('images/pandora_circle_big.png', true); ?> </div> - <div class="newsletter_div"> - <?php echo __('Keep this %s console up to date with latest updates.', $product_name); ?> + <div class="newsletter_div lato font_10pt"> + <?php echo __('Keep this %s console up to date with latest updates.', $product_name); ?> </div> <div class="license_text both"> - <p> + <p class="lato font_10pt"> <?php echo __( 'When you subscribe to the Warp update service for %s, you accept that we @@ -71,12 +70,12 @@ $product_name = get_product_name(); ?> ?> </p> - <p> + <p class="lato font_10pt"> <?php echo __('Visit our privacy policy for more information'); ?>: <a href="https://pandorafms.com/privacy-policy/" target="_blank">https://pandorafms.com/privacy-policy/</a> </p> - <input id="registration-email" type="email" placeholder="<?php echo __('Your email'); ?>" /> + <input id="registration-email" class="lato" type="email" placeholder="<?php echo __('Your email'); ?>" /> </div> <div class="submit_buttons_container"> @@ -86,7 +85,8 @@ $product_name = get_product_name(); ?> __('Cancel'), 'cancel_registration', false, - 'class="ui-widget ui-state-default ui-corner-all ui-button-text-only sub upd submit-cancel"', + 'class="lato ui-widget + ui-state-default ui-corner-all ui-button-text-only sub upd submit-cancel"', true ); ?> @@ -97,7 +97,7 @@ $product_name = get_product_name(); ?> __('OK!'), 'register', false, - 'class="ui-widget + 'class="lato ui-widget ui-state-default ui-corner-all ui-button-text-only sub ok submit-next w100px"', true ); @@ -108,7 +108,7 @@ $product_name = get_product_name(); ?> <!-- Verification modal.. --> <div id="reg_ensure_cancel" title="Confirmation Required" class="invisible"> - <div class="font_12_20"> + <div class="lato font_10pt"> <?php echo __('Are you sure you don\'t want to use Warp update?'); ?> <p> <?php @@ -124,7 +124,7 @@ $product_name = get_product_name(); ?> <!-- Results modal. --> <div id="reg_result" title="Registration process result" class="invisible"> - <div id="reg_result_content" class="font_12_20"> + <div id="reg_result_content" class="lato font_10pt"> </div> </div> From dc599d2fe6e302c0f38a188edc3de394c9866d21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Gonz=C3=A1lez?= <jose.gonzalez@pandorafms.com> Date: Mon, 13 Jun 2022 16:23:37 +0200 Subject: [PATCH 24/38] Handle header image with community and with black theme --- pandora_console/general/main_menu.php | 64 +++++---------- .../custom_logo/logo-black-pandorafms.png | Bin 0 -> 14859 bytes .../custom_logo/logo-default-pandorafms.png | Bin 0 -> 19534 bytes .../images/custom_logo/logo-pandorafms-1.png | Bin 16310 -> 0 bytes pandora_console/include/constants.php | 6 +- pandora_console/include/functions_config.php | 4 +- pandora_console/include/functions_html.php | 76 ++++++++++++++++++ .../include/styles/pandora_black.css | 3 + 8 files changed, 104 insertions(+), 49 deletions(-) create mode 100644 pandora_console/images/custom_logo/logo-black-pandorafms.png create mode 100644 pandora_console/images/custom_logo/logo-default-pandorafms.png delete mode 100644 pandora_console/images/custom_logo/logo-pandorafms-1.png diff --git a/pandora_console/general/main_menu.php b/pandora_console/general/main_menu.php index f0b75c51a5..590dbe328a 100644 --- a/pandora_console/general/main_menu.php +++ b/pandora_console/general/main_menu.php @@ -26,6 +26,8 @@ * ============================================================================ */ +use function PHPSTORM_META\map; + // Begin. if (isset($config['id_user']) === false) { include 'general/login_page.php'; @@ -57,52 +59,22 @@ if (isset($config['autohidden_menu']) === true && (bool) $config['autohidden_men // Start of full lateral menu. echo sprintf('<div id="menu_full" class="menu_full_%s">', $menuTypeClass); -$custom_logo = 'images/custom_logo/'.$config['custom_logo']; -$custom_logo_collapsed = 'images/custom_logo/'.$config['custom_logo_collapsed']; - -if (defined('PANDORA_ENTERPRISE') === false) { - $logo_title = get_product_name().' Opensource'; - $custom_logo = 'images/custom_logo/pandora_logo_head_3.png'; - $custom_logo_collapsed = 'images/custom_logo/pandora_logo_green_collapsed.png'; -} else { - if (file_exists(ENTERPRISE_DIR.'/'.$custom_logo) === true) { - $custom_logo = ENTERPRISE_DIR.'/'.$custom_logo; - } - - $logo_title = get_product_name().' Enterprise'; -} - -echo '<div class="logo_green"><a href="index.php?sec=main">'; - -if (isset($config['custom_logo']) === true) { - echo html_print_image( - $custom_logo, - true, - [ - 'border' => '0', - 'width' => '215', - 'alt' => $logo_title, - 'class' => 'logo_full', - 'style' => ($menuCollapsed === true) ? 'display:none' : 'display:block', - ] - ); -} - -if (isset($config['custom_logo_collapsed']) === true) { - echo html_print_image( - $custom_logo_collapsed, - true, - [ - 'border' => '0', - 'width' => '60', - 'alt' => $logo_title, - 'class' => 'logo_icon', - 'style' => ($menuCollapsed === true) ? 'display:block' : 'display:none', - ] - ); -} - -echo '</a></div>'; +// Header logo. +html_print_div( + [ + 'class' => 'logo_green', + 'content' => html_print_anchor( + [ + 'href' => ui_get_full_url('index.php'), + 'content' => html_print_header_logo_image( + $menuCollapsed, + true + ), + ], + true + ), + ] +); require 'operation/menu.php'; require 'godmode/menu.php'; diff --git a/pandora_console/images/custom_logo/logo-black-pandorafms.png b/pandora_console/images/custom_logo/logo-black-pandorafms.png new file mode 100644 index 0000000000000000000000000000000000000000..b1b909089ecbbca54039bd31df0e04e2b2d43460 GIT binary patch literal 14859 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 Q!T^AdhQYN`HT1pz19kXDKL7v# literal 0 HcmV?d00001 diff --git a/pandora_console/images/custom_logo/logo-default-pandorafms.png b/pandora_console/images/custom_logo/logo-default-pandorafms.png new file mode 100644 index 0000000000000000000000000000000000000000..6a32836fd38565fba9f8694bd08ac28f7114044b GIT binary patch literal 19534 zcmeIacQl-D6F0s@uOUj5s3FSgUDOC7qK4hoEmm7CdM61Y1kqL^5j}#%5+%A=B1)pK zPNMe~CHi~I_xrT-d;fXP`Mv)=&f%JwYvwc8%sp3IH_!ETH7UuM$v_|wrPjT>h9D5B zH3)<kNpc1FDYr}V76c-H6KDkUHiY|eczC+oJGme@yaPNC90-3Wdl1NfJpYwN(xfa^ z#EegjB0ecCK>+I$WtyO;iszyFX^nGi&HmK_bw&^^Iubix+R*P|=OLM4J4uOy4~GL; zN_Z@NhB%W&6hj&pPhLL^QJ!IBjPD(@`mSuDY!zwy6V?>Eys`Ew?Cr(m_S~ymGkay^ zCB4+=Yt*@+H}b>GmVaf@(vVsmIArgbeE2#-ee|*AZDz>}x3H-vnPqcJ=Vg-Hhix6B zTlvb2N9SA4cJ6|`{9Fa|Nx#7h*HoS>2XxJA&q**onf<t{7#iFg#>L6m+&$RKxDw_T zVHy_HFJgRjv|(0d7woy$XlksKmg27Erkv2Mcwu)IVmv)`vCvs{5z#5KG<bGrBDo2n ze7-q#))ZvV_)*$$O6kpUdHW&Dh+IOn=HatGQ}Oc@p7jvw>5L_CQT5>c??DTRk)BiL zzrIV%1W(U(#a=CbtNB8NOS>zmf-#x1ICwb0ugM0HVj*8;?mmW0%q*WjEaxs+3Nc;k zyzNzJ$I$&aRyjmDED+nM8u^wxEk!A87<w~F=ej}d?|E^7q^(<p$GpEgPEG_@O+RF5 zpq_F)Z95*JEj<dmuRnc<QP?Qn%Db~#nfxUeTM0ojIenIMt)rXV>*$3CT(=3+BZTu~ z9zI43yy3`44Sdi^^OvlFg^JMA>ngw1?D-JUDw`{v`yj@+_z8RQ4GJA0Q{$>ar;+TB zsgO6-ICLbRt{{Z{A<`b_I=Y@eQrhUV)|jC5?8OtuRY$A_yKPUW#4SO+&3ERa1+k1} zr3o@JTS~#gKR&Jw45Lb#zNDM^jxBe%P592(_9j#7%kM8cb?7S3^^gy_1-LZ^PE<{7 zefs4vtb{n5IH4{=DH|u(7(U8ALo+*k3k4^t=}J0le4a0S9b=XPQqdj)@0%CjUC6O_ zB0=kO-iu4$V5QG}vTxV_CTwUku`EVo;k>L)5fWDT=5(-2(V$KlJvp;>P+zpsSHBNg zkBv+mGO}iGW}ivTPl#UAbzo<))pAW)V=~-guyQvF^t&O!MW+{XJIBTe<r(wqY}2l$ zXKc!+#P+B%YBEEPWcShGSj3`Ljff%@*}CvOq8sl0lIwgf=J}biv&OE)KJ$;pODzt@ zW5LymY$>mGEbq*?z7s1`>z^%N|3Y;PFB$bo{{Dqp-Rk5)(kHID^bwrN#=RiviRN_< zeFxJL|64>;3*MPE%#Sjs>5Qk$Tr!)!E*WKGB;r=CaVmfO&F!=E)Gx3$C1|s4^6r4f zxV-LN)86VT-)zo}NIu~-50=ShXu7Y-vr2`h1;?`7Pn#)z2*|m233(?*JjTx(3ZtrV zefRy7t6TT)m}xEAXA1FaJ=9fryCqk$gM#+8RnlhKHk&NHox88?RTc*5j~EpGTrWs| zZGLM)>5lx#oCfEE$6tTMS6|iGdg=iEq5S#g!r-Hz=KbG0T5XD3RmU1$f(zTPsV4n{ zd%hX!FghZcxYj4SvYJ=37RKJ^-bhk7BnmI~(3*jeeZs$^?raLZC2M0ge#?$VRurmD z71>+JfKSCOe@7*b<*qw1M~R(nKd%;-XGoT8TUN1B#u;zcO71nNJ6u<WIQ?tjmBtW# zyrg7?2VHDb-|<_uxtFl;ES&&*{VDF;sfhz=NcG%RyM=n*^veFX8s*}qL&D}O+!I;7 zgM*xJpLZA@V~Q!lE8cyM3KCws`URFp68TUM%J8C#q|?U7BRj<U0+wejx@1``QLgZ2 z)zu&$%p<*(@qI{MRf?G<Dp#iMGkLJ5et0%$WX#zT!>_j&593_Q^~1G@)UrQbr(7?Y z3W)aGFc2~EqaEDcfB1Ac^U1IJyNP|A9+k^TgdM)>!w;;Vv`kNE?#2(v30Dns=lNSh zh_q+ltbGgXq$+-Va_~UY$n^V(EMc4*h1!%j8MDt7{aVc04TI(#Lr>g}^)4ZN2{cl2 zj<L1T)GD#f{a|>HwR`<xDiK%S?XN25ernbX_pj)k2x@<ae)4;{c6v9`E-B%uWC6m! zyVnEWx9>bb@4TJ3j*flnmllj9^|*SC@A@)j>qdg7E0)UC;<|6N))fuRv0RycslKDN zSB_b3-&ALo*3`T&SL9>op^-xgpKF0?zoc{utIUI6uUMwoYAlC$NDtLJ-q20knbnwg zdFAsp_H*5QYBVoi_M#8Rh3tSfwFZjJ<Zwmiu(}W2P@qR4NL?#ApCkWhR1j9#P`N_w z+&&jf>Af0JRJcg#@WZ3th311wL++iBt6AhnE~xijeLhZo)@cyfD~{*J2R!ScjI-pO zJJ+T}65c<NVY{C;B{Jpv*{#w?fJeLbt&?QkgUF8j!$JSVhjaw-rGy9lb;(qSsfYa3 zjmz{|<GB$p*<E?#HQc3d)b?v%(Ucn^QmeFBj?3bDQ~k81Rcnun_|aJBW6s1<Ek(*n z{d*4xwI@*?H)5W-ka&4#E|;Z_+nZQa@tP}C3Sh1rjV8A2(qFr4FL9DY984GUNMt?8 zS0jg3SV3(Nqtf35Z$YeOeJHQt5AudAr6q&n2c!h<sxr{26YhWgaV<J`*FUck*~7+@ zyXW07;TjoOB#gzwqxgWf{h{{5jq?iT8If0gvPg*CM_b2yl?={;0X4?Hx&`0-AA+() z*9m$a-zQsLTuyeQ+Z^cdVlwMCT~3_Tpn7SvnM_J}X7^x1WlR4i^(rSvM(veb{xgXy z;uIu}xl%8G6)}aBJa}G4RfDmmd174#t6!(N(L}QRgY!43_rsH_N8$Iv%)EVdt7G2e zm1$A3(_vYER5~@5iYk`GN)GiHH05LX8C41i)2uq+pN+dH;+~JuT}wP3^B(LB6@R5h z_(}nqFNRl5vu>ODB0{I3+SvM<XO;H5PfiV;TI)=LxAgY323q=T@os$}W#4|4A?+jZ zikXJ`rP{l^oM-Uo$j(oA&6WOp%;E{B>yhMHCmcL-FNQqp2(RY}#OV@r)$kA*UysPd zZdr4U(Z@$@AUT54KVykm8dNmw<EfxGAbvP`H46A4p~&xSnz;7wAl^?h^4A!ynB9H) z;m!9&@4gNWpLi<MS6H067+ViAq?+Mk@U!=bjY`v#xiVtgxT&Cx5jzU$^bN)OA8c$J zOwXK{FT4gmcf9YDq%nH?lYJxcjpmOND)F8xqM>&g^t(Rv+rOx_E?Y|$rSsqqm$6y{ z1(%DH&Zq`)(px*I7<kj%3hK;wj8{h$)tGC@lg@Xx;<U{C_Strya&~8S0^uzrWfT{y zYfFCT@9<fxPd2|5IEvcB2#m3wdvC^{9*AwPJJL`H+?>$57FufUwDkQeaYnQ0Rgo@O z8ejEm=a+HYkzbi@67PHzyZr-Vz?3(o*Lw28Bkp@6mOQ2-D~=O>l~y$BFemebgcO(7 zChFh)wC7nqLW4#+R(Ss$qVAY78SXgEKy)DPU7||se7&Lm)dS43M-fErtk)|$Fh4we ziKz24&AK@W-a(K9{PcMBL{8H!3$<qe7As245WSQ7%=#9easw1Ct?dfuQZ;YMD;JH% z+Uc+vaWo9RGPwCxh^Ga|OpPBd70@Am{4@hD%?dv&Xc_>`3=_Xw&-q-*L7v?D1?{FG z9l`vS+nLlOSD5i(e_jT$?(uUbmp1l8=HqyFgfoe#I31s?fq71c(O{u_vsehe9TE3? zZ2o8u)rnxktL->aPj&3QS;^M*oq4(`2_gjqbJ48I489{$%3<Zcg@?Ut>xqjkM5#Zw zkAL#?In#4h!ovqI*vhjW@yT*@KmF3Jpn`rr#t6fhYf3H$exgYhyUj)<+L!;@iqVTU z1HU^$`40NJWnvIvp?-}@)(eyDbP6BJW`S11n=IVoIas{tnjQ*T3hih%FADt?@=VA{ zi@HHJe|YqlrrA-4Q|RW>?_lK}>V&02go&yU1Lyjy-(NdT&JUBL`7~J0WL*-R6wb}| zn{OZOfV<d}f`QX|gp-<@zLuKWKaT0Z;rwk#qT)TQ3TwNSawV4#)dt7x%WQd*tMreC z1n9Ewe4sb=5v|=LPnW#OFC6~_`T27~d(qR_kEK+lPdI+#%`VU9Epzdli||)Q@BH}0 zzO|{iIgNL2pIT_|!KyFS{WUM?j&QR;gk^s$NozD0pV-69YweN>9V3dt!HwG6;4QDP z_-I2>CScWac<lyjV`&?FgZdtjDf^`>=}xe&f_)$1bM{){`qMA9^O#JBFE3o|-^pr# zQ|e%wHV|o}S^n8iInF6ty|rkM=~*;n4IQF)-s+)hX0j;%4W5UI=83+_ksD7|gn5}| z%-w!B>L8izoU=nDNt+i+_=1)EgKFgb@6Q)M{A%nUdA911-Fp0vapL?s-ko}tV)(>N zNA;9E9)532DsE>ay`|^YN?bgHGCooD<Jh%$-YvYe+butmg_)AL2_27P)qkA5XyT{7 z>;Cv$s;1^ZNtZnw?33DrM@99xpB7OT)KFhmUlZ0_d2)hxpzrBpB4_RkT&Gx_fNK*> z=YhPfyQ?tV&fNwf?C<IUT(m$S1!aE^xGfUl&0&LZaB@@R+Ny8n;&8H4<bq1+i0XK# zAsn6V1$rVL2I?Bw1|n_c?6{Pb$Q1nL0RUHoH=M)Y)y2(A-d~aH53W2wUy4PzIR2=3 zBNe$|I{F-H?w$w^NnuH0Q6Y7ICtq<cB{B{LPdj^g!@C-PLjas2m!r40hrEc0pP!$w zpM<cxr-O)?oSdA9sJMu@xDcQr<Q3rN4fhvv^WwgQ_zUAM!pqjv$-~>p-HqcC6K><~ z<E_ZW1@v?LV|=b2Iy(P^ck}u?3qU?Z{NWxVV#1;#uC5~gZsFyv?hAnYJ)r-qg_jX< z`xG%mc)9y{+9K3_5pLex{|;ei`%ilhA5WJ*;n>-VAY2fxfT|bZRqQ`pYHI1||I^|! z1rAQG9)GNWWdDbzx0C(9lJy^ByX^TB&c6=?F#jj+e`x<B_CLyimX416U3Xib%i(F= zRph$#FK_2=>trYYhm@2MwY8HGl@yY*m5~yXv=fsMf=kOu2qDD8?Ia{5Y^BBFa{mUU z<>uuLce6!YLIL2yP5_RSs07?jT1r+(Oin^tNKzJVBP45Y4;Qkru@{w+h0EAWNZ9`y zgr27pP?d0(e;?H)l-(tin5`_rR?Jq&27!<flC-yj3(49_+6YO>+1p4<+DV9tN{j!2 zva^-faQAeD1CP_m74Co#@o;na({Y(_c~yNaMJ{n+(SJ$wUEtpKfPo^H4&0VQ@8Q3C zjGSB%553`+=@gTek`faamlc(hk^~x=e<?u_o?bvHUV@5=3QPP2eED4DfoOot!Y>OI z0Qh481S7BJiGX{%dm6dByC`y9j)~*a@=twpDE#$Q?m2k@8UdFj|98<pL_GS7`)dxk zIQ{A3;P_Lw@^IU~oOr=~5q5tZ0d{|N**e1A91y?+|GT38A$R(}JS{lFUd&!nPE1Hn zS`<jJgp9ZlTt>o9NWw<iR#rkzQd~w#>OaxF-0i*n;GPIo2Ov@)8lZyyM8m=NS1$Sg zQ{B%IahWJlV0Md23yDb>iAl<fi^_}235tr#i;8lI{2j5#<-Gn!$O<C=pQI@KQTVro z0I>T@1}reZdL{DD1?%smUFPxs;n&{}<Nu)t0Q!GU{;T}{FJ1pj*MF6P|4R9P)%Cx0 z{Z|?Iuay5+UH`wOi|k)l9)ufk4DtgmG!eLWPQYbITK|EOI?z6FdUSa=`ft8=D10pe zeLQbN-G?BR#ZllFQXo7VZOyx&Xu=!!0EX1#o{1L-#7J}bjn~EdOBoOndu!>a6E6}` zQqYl##IB5hKpY^gyQ)V1;~N?MsP&>!JEr4{gw4?9+sB*6PTUbUZz?Pe$^{vZ!w7zY z)_cU>f4xA27wKNGuV$Cf?VEz>7fc1{hfRxswg_ko>4(#YRx`tL@9R|^@AnR^IFzuR zKe>NaGCVh<U(`uJoD9XSUYv!+?AOCCP7jsCR7*l}v&t6<HfKV(kJ&7&8#7_Qw=z$A zF9N*o1~|8^jlFZ*x(MwVI8)ZUxc)#ri2dv&^MY+_3vZgROnE}PJXFJV!yMteIdWZD z=PZn6&lG)Fr|?B}42%l2msu+qaaN?)mX6&&`E>m8TkQVvh`1om#YK^E?OFTjuUg`% z3$O5JoF{tap>L1RFwMq01+bz$#ggGN<XOo4#rcjuA4<V;Sef>Ckd&Hn|0c|=eEPuo zt^qipAxMEvTRMh^x@Pv!Ca&G4)2n<@27B1ftX=-4%;u~%eTFz%5O?t|<+Rw&fB{)e zvJ63&TYv+)-J35A&CpJtLvK|z+H~f@W{uF<VALr;E{rAHQdpl<8w!3c_(R!sS_s!| zGZ~A2!T%bKF8vU(Z;1|ITh#{-vo7<HvBXHdZx5`cS=oyEczW!zZR^Wu#JJ|_pqcu^ zK~?89@sc05bIdYE>im3o>!V5RK40I`BQZ9L^L$vv)%y!e8GfU&JjGo}HHzg+Hs4&g zGi4=Tw>1X+G<#seheO`%pQL72;!ieyW<|{E-p<_Ho}RE}#ZYO4F1X0H$_+40IFW-s z7sQ=_s0C5yuPYCGby2D8=M(-SxU1^^=O;5^Oy#Ev6G0C%Q{^*%DU{SViChg0pgGUy zT4y<bm#~IwEkqFs<clyw4nSkYSBljW_l9%s9y=Rwgw%eBuQN^2un_Lb5oYA+XLw=C z*R4(u>EPUlN%$94(B1gZW5|~;D>!&#^`m&=`#a>ZR7ToT-?B{yP0xP&t>(R<HY_Qy zQM@3{4=khSEi370HXAlt+o(c^T|BW-99|vC)GzMn$UQ&rZw>rDu@<GwUKix}de!Au zT5A-x{`K6M(@U)?2Fvd$RcR7Zy}C;0J7uH4z12S|WioW1doF$?F=|h$xm|g#(^q4| zKP@9UvbyhsO-++PtS$6>vx&>M(V6)+)b#dfZZPbkx9pjHX6*h5@50ixnO}Yq&yIbt z%I(Ji>U!<zMTlD1oL~8TAxy6ft!rs<w9mVI(zx7vG1&B`FmPr&fc3jo_Q_Pk&ggfm zk>g|Q-7*=~f-)Aj#<ztqG(QBrbVwQ3K9Hhq0iHXFx=2~tuVT_Ex11(rR&G*Q8d;0l z-Ku|$6mignJ}_=iZ<gLYS?E!|Q6PlVXIPv0b-|B=J*OHRM(C9DZm~GW=0kAWLuSIb zKE>1$Vbr;{==6-?@oiRY?7qZU<FtfS`*?8Vrj&xf*0{ja%mrvWi}$YgwH`s-C_nDb z_gx{>@l?;n<YEV;JoHOl&BzC7+EZ<dXN&owOdp{P4g*QUulA>lI*QYEyY0?}x7MJ! z*JG+g<xZ`-Lj<dKMQ}spVf09UMx<lR{$%KgjbhVVxy3b;X7jKTnC*ev`^AL^VhwMd zf)e+$9~P`}HpicyxRh-K23UB@ul$_qS%_TdEN-MjR`6kYiz`eOd@9X^$nwh=5I|{h z0j2dEC@qy$XM-CdwR~}PrbFr$BKLF9j8)bj?$o^0i{r2}!1qyo@!=|CTOpaN>MQh1 z27*p9C)Jk#0Yl{f23JMUn+UN!4t$~uEhf&+5j|~6qa4I9DP0%VwCEqMkhW~DxPtgx zTsnPj?nCDsTgs3|pF*5dN22Wx`RKl6ek@NacC;{&DcDrMew6k=N(Xvc^~rK#Hn8uc zaB)U`&5rtuls-b$4<eg#I58$ud3O5AV0>IT;ge(u=I(`1QM!l)##uXvZb2?2k_Y7$ zBG=|=B_u7oH{cS*Q)HD)?N8$bh4h9v9P555Kj1wdJXsv%zJ6?#pM9tuWPS%{o?e~6 zSh9Ea!xyp9z1q04)*5(Rpq1w6)-mpGc|F;zeXo~W_?sHc>kUgXZ1qF&aEX%|3GQ^F zXGStoD#gp~&KBeoFZ!ndI=fcAcVUhL4acPl&wV06Iz~#ppM^Pw2ioT{;D+c<Blefx zyt8`x`oa_&g`Pi)%{`2)I>=B8YhuPkW2QA{w;6E1Ln01Yo+LEAU3X@4@RLAk!9Jej zgupJONS@Sj#woTd6IjMf{$C?eUrxRE4=j#~ml&$xaj)@CPtP0YS`G7U=W-_W;Ah<8 z*rI2-m=_5*-Ak+|P+QZR;G9~iFH>YoiguQnhTrr<XBdQnKoErM+I<E}<fqkDxr(n| z>AgL$*a^Pk)^urv7L1DAWO1W(<Mz)ko2__ER8HCAzESU^cg4<AXJaH=dVVjTS(;U{ zC1c)tBN$Qp@8yi@CQUgk5`VhvX;)x)liifziX$!3w<I^{$G1k*c+lls;8dh8#HF(S zhhUmLJq|{LGZRyYsH%8#5IFIO1_h2Qh!pCn%78v(lFoUPhLM~g>8@XtM!fbNhWexm zpvP{&Px=|YEzWf3={#~`YfV3_oijvz$<#UNU88?>`g4>92fK!I7L}ZAKx_<1KY7}Z zt6}_UwWe69C+zP|rV_@s9-zwcPX3v8YSn7g_j6J|fo^2_T^-<;1p;5m2J+RVI8{uI zXz}yZ=`V?^0I}a<Wi~`P*{<H$Vqrc++Ayr{1Iqg3XFw9&z+%WiLcR@D@%u<RQX2@% zONP5&|DF>6oEvvn$PlV8O7$5cF1u0yqHXza$tCgF0=ku%n_}IUI*X;dhV#xpQ&@-~ zgs)Jm$f=eT=iBP*_pLbZ^QF*z880*D1bfh;Rz&IOqaNBhe8byo6`xV&7pxmk9R7vJ z2W}NV-|jf!<OA244yGO)Qt}J6j;9Q7<?5Sy=c6KLJBsuf8c4L6N-e4HKI$Ld#fqJ@ zRtOs}hrRgaBT&zVUm1xJp=dg5+<>~>D!9jpTGaDPMVJx|Uf_NYP%pU&&y-lCgK=v7 zV1xanpE6T7A`uP40c2}uBQCCU`<Y=R%ONNE-*}g1xxr_>!Y5}QTNR~{bl0o6ad&Yf zI<&kjst`|bv%<r!7;|?_ZF+)lVy@H8q<c8c4nDT!fr!ipzj<0w9b(#psygi{QiWCU zfXk^O!nGyHwIy43!w#Lzpj(tPbhy?t^+9~3mC!}iCuiT1wPLbvj>oC5=gO2r<i^&U z*{`8?o12V0>w<TNM&sCwKRj|W;ekNQbgUS05BG1u?Mq6_LZqa!S2B@{?8oHsj5wR1 z!3ZASZo_ZqywDF?+1;(_Z>_|x_OvqNwI<zwQ{IAaIB-(K<FKvFWt?_B#I2^9-!|1W z;FLOh+O#NR=<8PI;?^V|IHfDeYoV1gQe+#+nx3m=H3#b5ZGG}?bg=`16K&bLJFYl6 zc2|oY<<{v{F^i-@Ic|~!!TnKt=+?kVFZQx-%JbH7QFI5(kt$rrRg=LqYwC_9iFRuw z&jp!(b^L-LTFAnf4##&3?HB9Ehy#$%;PNsSE7EHRkx~y@lODF3c2V7jJEeWNC`oT1 z?LH~E5`qtDz_i^&KTpynLn1OpKjEEkalTv232^BEqaR~vBc(heq!=O)VR?QgFwgt2 z<8L)%JzE<W8P{;L-%$w|I{~oXhyXvhd$HbGD?19~!eSrPnp6NC8P3?`19#G*ej2>| z(kiZ$YTx4mWKEdJja-|I1nEM)=89UbQK|b0GignthYKCd--?uqCqpV-9MGVY(uI^L zY>iRQPs6levwYz0U-a(X8=8k?QxR1dmE*nBt|z8$bT|(hoakO^1erEiRRRJ#);5En zl1mxfdZO}ywI-?z)6;9qU%fsTxvzAUD}rY%s%o3ptQs@j5gVX*7>&^of}hDGj@nl1 zz)(zIOt%V&Q@PrkC`EqdQfec)1L3X;%8NYUG$F@sGkMDd)$5T`8STyEg%DVUf<5ry z1zTy`C)93pYEL(r4QWB2x2EgXVV}J7q29~F+>!A?ednu7I|g!kJrZHg*1rz9L4&f9 z;xU57nxbd~z;e9k_SY3~7D+W2RvpHo_x<!FQ<|u#NbKN#2|3bbBMIDVTh*ymMAChs ztvdZ)pqO0O5C*e#NV}U4?*10^b3h>?KmDD2=l#R&!SsvFtGL;ivZK!G_KXFsWayV3 zjatdpfzXG;@f8fH=w}wt?o`9`T>Av)wK48*naGaT)_kE}pD$|F{R~dpMuW9W;DQHf zH9zYcG!uqxvjp`?kvp0}Gz<^y1>P5Y?xR-#PY5lUEY%X2JDVUM@*K(uOs<+JZQ<z~ z!mi?u=cvLf`sj_I3=0t?2!jVIus#iw6k4tnbxzJZCMh%kL32r5E|NzacTDK00m%x7 zifIZZK=cCy9R<);eo2s>R;fP+7E(H5U?DXC{m3<m!^cxO;^)B;f`m%QCh)`UA(5_l zDz`tjR)VrpP2i@WzAm(=5NLS;;?Dr`_7qeg2g%pczas=?Op^8DheLcL5qK)x^{o}4 ztV9dA38?RDDFzIZb%I7+>*oZ$w1=MD%6|yr7%yej)9nDMq*xr)gg4=ZgPLQU38$`r zN`2|aX#+_>4W|OxLf*8X^%G+Va+w!2`m4AH*Jl8F=>}0aq5^duBr5)DD+m4PvCUr8 z=!1iP8|Rr7D!s79Qwg_vov<}TCr=4L`UrO5`jDXOs2b=irAS-6@C2)k8>8h~h1uc- zi{-cY#V@AiwpS<-3;Zz~Ppo`<d%cPybKf2*MdRx|`rYZen>d*`@45Vdn&d+Fe!&$t z%V<r?)nnr#B_uN{=*A+kjI{0U^UCrqzxB$=3O|=acZcyh@I!<9$}9mMuh_iMWLDXA z?yxoNL<vEn57oL<r=xc@eB<@$&lSzdQA*FJ67i`!8CGr`Qqo-hut<hlpR#-wls_}% z2&(_qY&I}4pHk5IxWe~?Z4|viNHTY$^t?FMR9N$VRNP^)HMhsR#|})W`8@ItQX`1@ z^Fp^|OE34lvm{h;qU0KtG@5_~!}bde*J|5od~o|VF}h|HUOij)hW&c<la3E*@OI5n zf@b;pUknd3_OAp`z--l6EwHBe1+OPo`)h(+WhK=P3mho5g9oAqF|tTlfy{KwbzE2O zyP&6S#R&?ONS@M9r8is;$486OnkJ}NP_Lfl9apeEGqe^WL)$>bz*V#|4h@zvFbC`a z?^Q1uLMGgHb2ptR+TaT&G<fx`6+(oRiB)hA6D0+I;fNhj(!E9_KE+FlCxH^en#wOa zVa1j8s@!3@FW`uYR41AG$M84;Y!U^wB0o!!lZOc<DS@uF<$s|2@kZ_V7q6g*xd^M0 z+Yl+N>FtU+x6mkfq_a|4XFXo=6S&R|?VpdjELsho+3a*Bxhgxs(y38m;F{1KvdD?h z;m?@1UJO|+M74Q0Xy_ywzOfZ=vR_1F6-*k#gzEMplcGeT_n*4eg&uGU*3Yn377s`7 z8)GYA9U)N*mE|ADmuaJ<Ak5_-9gMzy5;#tsS!*VyKw2HyjI0fOdIWy#EslQFhH0qj zbeQmB_zar}o5Xy9Hwz$P=Xl6&3~%Na%#f>zo0qkOABFZbZ-iif@5fI+qkP6o?KT8O zb}70m2}HRl*Qzc=!9Ln`%(%XDzivm76_W$6t`Q1tp92?c;F<~!Q(3Zo70ZM*lur(+ zg#H5mB3&?x%2x;&j~JD-`i+JoqHCk!o%c7%()Elb!CF%2ln&;cIH@iS>&X0;4s6Fp z)(%$G!T7dDM9&np<6_u>`J#&Ll3N|R!bU}F0~;8`JZY*Daaydatl6#bTiy~nV(Rvk zrlCLvNJ#Wy*dkup!?52l!RZaai3m%^ns@v@(qH>5+PJIiI}>DF;h}_X*qK%Y{CPWO zcZSE@AZF4HhNS#e`^`uk%#VQ0y@c}!zaVVn*g%!oW~P+Ky&x>9ltKR-6@B<7K@+VJ z>hlF-BWSyp13Z0^`J)HI)wcrW8d0vW)!WCO3c{~2km3`C3E5fbN>u8Pc@5PF7Tomx zcjema+}wU_VFhq4Rcyrv4oOGEZ{xdhu9|xi=;1O$Ur*Z;HRKw*$-0y+8-<Bc%#EC` z&F8T22Q$3p&hugCQrOZbp$md7nE3{H+y?7QQ8`Ozua;f)R#)B`%z702wxE^gteK|O zt%%2KCR(AXHZblfj7Bw_P%oh-=$nr*x&j_&7$v1qXWMuVA7wuMx?5~UiOjbtucJt8 z98^;EE*lm@FE|dgmQl=f`Mda`(QuQ5C07{tH_Vev)}7U=5!-I5D1-&(SD2aYP3zj` zb}M^3r%fqzq7AISH{SnXynDwsa3dNx3t_viYQ)<T2L3w0_f*9)7f@)QXyfzeP=tBf z=}oEDyylLQdT@uf!|dC=HraZgPevd6G@Y=!5A1c#zOg+Fka;AhBOw!HHd*(L$Iacc z#%W;I>m$?H=tAS860>~ICYu@BakGjY8R3u7FvU&w$zy|W0w`Ox$?lql+i!SI9<D#& z2+n<ApiLYu9iO_${=^Ee<-Kjb|Gl655+H93T1rssk>DvA$dXmi|5oAd0YAw54FfK) z@}(O-sQxL~<Uy?F1>TQt6#ZeSB<Kh1H$BMOWRxBh+)}>G2wJu=@g@UFmV@O9K<O}s z3_OqyI5r*>&WlpN1yZ5z&N&D5wSDAM1nq5uW2i1WpIlKP@68zi^<gXd#6XqXU}tiW zka=tpz6$wZP70{6rJ9c&G;}CLMg(dviJb+hTp7vX0`<As--`rgJ%#=RHn^V44bBk( zdBp(Q`?n3QWSy)VKU~S}a)Y~7-}(`hmHe*_&e0AE1NOsRK~{3m_$WP!5ES=ET{jfi zc2rpY?1#x#KVhK0jxrB0$kFy+>c_w7;|W2o>tr4H;ToZTw$J9)a!^*nztorKpt8VV zb}rHXQZG2|^5hC60C}D{FGcK;g6xil&rMe7LHD)=GbILvKv!L1p-b<rKpX>Q!FqbV zz(#BJ*G7A_nat@*;}y_(DE$yw9Wm%Fr6A_U9yQ4S*w{sTnG@vkt9bi;pC;&sEsWGP zI|0;!E%Rhn6TwrFYn~k=0!53X8*qJkAj|@^uq3+xlr>}~8{AI;intDWa}B>`<V-;E zI}qi|<r}BGguqiNUQ+u316_55O*oWSKR(BADKl(7_b;a3yAFz?Ux60&+5o*jpezpC zj-(+(;c&vE;nrJXz=2@}ip<28gIb0$v+MV#m;)(6Sh5$;rf=CJpzUIe|H3reF(8Ub zrz#Dm!{Ud#G*^V3PP$jIohc2ECXdEm#T6}ElDiyF$Q3mT28}5y50+JGl5FBCtn%iZ z+&=cw9r>7V&4<jgs0W{|y2sX(uGcx;e=y?CmX`-VYS?HD3`T16vTHT&*R#q?RJyQE zU(^iN2=`c`a;P5_oTQ4e<xyq6)U<bfRwI4W5vGp1T`_U9WMq<3u)>j;q52wS_fD23 zH)NdlX~*Z1jaR`r?`<`G-`w;u<HuGE=k28pWiWr>{}_FJLHkF*<Rb1dcC}9+z_4b6 zO@0j1Hie0Cp`SlW?ZwjuKXK16agzd*mi+qZmYl!>$)5VwM@V!bXOF-pHT-mTRbR)* zmlviDxDI^BRNq<Y+@Bi#9Aw>}Qvug{vMb1fieNZ0uj%Zd6m$)!DYTNCVWXwgu9%H< z*r#QTz^8iG=lTRr?}z@y0w!kFp3N7Li{e?L5De2S^C-I^h0ZW;mME_O8AXpI)S=YQ zNwt~;4%&P3Z6O+>=-U*6<D_phxjMzcq>!eI<S-NRJ7UBaFX3?#QK=Q5CT7ak={qp- z%&2+YTJl3vN8h;hXL>A<7UM5Qnon*B`n<wPfHyi=86t!lgIh2;#D&Rl9`uI&bw~_l zo(B4?og-JDE^MXxWf~k-VTF;!8iuj-RPrDxYr8SH37>IHl8rWSTxl|McMZNFi7r=8 z8Mz4jxkY)l#UV9i^-c=Bqs6@@r00hg4@JDSv}3{zOa-p(PS$<(nVqG1U7g^za$%A0 zbg^fMC1bjuU3Jf#p@LPm7xTrk_4?x|o}H+wm&y+mjfXIM#AikDICE^#JhZxKi3v9< zhVGxnRBG6*7w}=3br%HOV2d5NX=O1tDfHKk$bl%HHx|p4uQTB=+YStxR^AzQ1uI^) znFZ%j=GC9Tq_9tzHx?pc@*?7ghH_ZuG$vfM7~0?~Mxz2w8pT5;)0G@m)vq;}5V${n z(6iV8r+j*qG78~|_Cjv1gd(D0Hz<&8EGWC{xZf%8xWy<Qrzoj`Q)jwgf@*DDlHgRj z1siOI&O}?W8COBX6a^BzW)Gu4h8Q@e$bb{AJ67Fb+*k|&_P83Z^#V?RveN1q8VMic zCFt6y<BqD56Msm7tQlElLisa6c)E+EIfr^(mE11(XG)6V7<imImf06uWNSirCctAu z$c&qPe1lS36dVM#vW8W-!_;ETAho1$!?so6-1ZW#1;>)@6jMd<e2+55Rtg-`M<JxZ zg-)=b8y_8Dp5^d39;{*4^xmWa9+vq!Dh(cY9a|xEFSr}y%W#9486|riGT+O{C<;!b z>u|P%CE3H~qTz%$hFxGvv3Z9~C<11j>WIJ!^g3z`2&rqk*atiAg;#>li-%mNt{yBk z_P7HZ!{nvFO`5JSVVP4Ykvp+BEtOnlz$2M=N)a$Ft@z;%3@ap(QG+<jCj<UG0p1x8 zr>v>tWx_c%w*q@S&vlflkPapC10~Ynp!C|f2QW^^_zRC-3{ez)rG{i6Fi0kdNp}$w zCWaYRDGL6KLFEtNFj3NhEOu4{70$=TR@fvvY+&P6if$$8dS(>*=+$WG^Mkjx7S=GQ z5g}eIb9t1MDEL`o1YC~lS56d9(lU&Y0@<9sNL3?j1c!A=`)f=0W4seYev3>&Jkj`} z#@{gt%*?hhku+Kxp@Dvkc$;|}rfmj;5+TLj7eoK>)nLN4U_{X#Skrn;AP@osfu*JB zhS$xsVkE7Cq#7u+g97#$%0<!pQ$2jxz;&!7mU)3vd$wJ_9dmOMlS706iuHs(s;W-L zqziMWxkbb-VLJ;RCmpr#o6jx-=68n4X-YAnUZ^SGNpywb&L(rB5PaR4Vf`0{&uY9c zlTi6R$>y>EjDN?>OJ&@Pf)kcXid2Hz%sg*&dx{s@0dpd7Rh>e6n2chrN8W#0nlq|O zn(4U=dM2F|SOAE&ypu*^&XbJlSa74xqq!-YVrauqpYNCf$nLX!_a@}!oMJ{5ersne z7X|N}jDJ+Yl3j<`NTM@33SGHvk;J91;grf)&-z|EabP$$`R;>QV6wSVXg4{+ux_v? z@Y<7M8f;g{r|wg;wN32(5lb(bTH$3|7!fv!D5@&3S`Z&cf+_wm60&+7<#HW$^i%00 zq^jgo3q~Uan5T&Am?{dvCUG2F3>$>y+tg@KHB!o_AP)_9b#oq?;9*4>ygu3p0Z!47 zgca}lZF99>%?~NrI}Ae{FNkJSsFZABhTqG;QS|ARU-+^2!<6!p;U(VT*<~ru{A53L zyS`6{$H@Y7!6n|VBb^X^uLCIV+my(=OsEOpmEE1QG!Z3xnC%RvZQJyr5SGm18}s3H z+*fIIITEJ(aUR2x)B(mJ8h_hHEj0Ki$=*8cRepCUNU?^2^K2=9TE8|4B%uSNLELP5 z?$iEN2&=x5ARom;Pl3G20@;pV2~DKr_MWtZ&1nGZ>(dT7T+y}|IyXwHiv`lBp%mpa zP_~yV<2{btE*_7Pq5>RCg1gnO26gz!fNR?^XtSK-jW6<{Rc<iV_$u(pW4LPy7?Q?W zC$l$xk|>6bk3#sT$UDpmUWZs<D^mOqf1@me6swI1_bHISuj7_~K(QWSw<YoTkTAn` zj7AcC%()@Jp8~1JLv^xCf7)dO+x+r&70Lv-X2RVQ1AC=ru&0f#BPq1S-6S1Y1;y{D z55>bX#L*ezTdXs#w;<9P`B`vE5p2xyQO97^!gby_n+^=hm8-O#Rj9kZOE5}GSR7ox z9y^g5AoYFa&abl~U=b(?DyZ-!Hd+br?<gz`e96M>>8RPUU;c8y7cs3AUH^R<KT_M7 zRT8{Vj4(OWZ=S1P8qKowV*kc~9iOWFum+L8?P(q?4lZQ~AX5!d3DQP~<?{cS{?=}0 zMfI_MYLjYJ>Tt)Uw!8joQ<gD5Ww#>7M$>Z?7v3D6jA_pAH(!0mVaD>T6Jypn%(E6v z3yH}*C%_)zEy$)ZF_v+M0`yy$CFsZZ;)y44ycS4XmlySC49Hr<1~K;R2NZ;1Dz9KA zXvPoUh)%WTiex_lg)7CU!nuKic{nyt^s|<;GL#$?!Ug%1MiNR0(xnj`)w|zpPYP;e zEgofj2^{XW75FJmn3Gm#>aKv!xFBDljj0z9HIU;9Y{LKDV<r4>SVzo`5(rpkz@V1$ zZ9&lQm$v=4L4EDz%PfEt1nOul13pWNS8oQXFm~iXL0Pf3{kQ(~(*Q?$m^TT?`w<ub zuamtz(p#{`mV&~C<JC0*_3j+TKkCGP)bT*ev#=rdOT}U0OO*}0tmg;=ze};v4N$r) z0}miZsW;*QE~eAZfcNNWcrV`tFmMGq+L#zIU)~ywi7qYU{#aUFiia33#Xf|W*9e_I zVm;9EPZJ|rP#}y!ogkd|o%$IlE7Hk8=8u>HB>#!Q2S1#sTHO_R{Q$K2E}i!5k}#K` zcOnN`4tZ!|CD4Xjw~PF~?5K=|%!4mGOldw|^705lLk6IIS#r<hlDDX!=f5;0fkymM zGxvF_3;e+@sFj}cFR|UFIJ`Gs@XjBz(yuUpSE=K&#RJ-4NsGkt%YJY5FZe(^K+kk( z_2bP-%nL$*XcOf6cdLeDVQ(cs{PJ&<1}>XRl%1I9OJ$Y+WdFAPNAKV4)v_WUwm+a( z%UZ>$XfEAFLpeL6{y?yQhb{;+Uyev+#^3m0oQ47*_hO+7<l&A0m1WT6Y)D{t8K2^; zaq)eQ8vw=ku8f)C$__xOO!*I2bCHk$q`+eFw7TjYfYJwBTIe$x5dfsm?yyv<>gCHI z`kYo%#>{z_!h*TskakrafbtNvnlfc2xC~_uxe_yfiNm;9JRw4B07Ut+OjwtFJru}N z%l^^oft`9QK!&qC?6A?kcbU>YX)EJT?|Q_ugaKyP_|U&9z?b$id3#+@;<7nADgEmJ zb5w+=^HdZey$oBP0DX;7zkoLy2r@i)n9m|IBQfIAd*m-;-wAC9QT89VtG8lbBqst> z0hDFgwEDKRVeRQCz<h=JaI3G9YF+x)=d-?nd^F6=DFZOO#-Al0EuL;%!|f}(glvi@ zX@3lQr+4}x;E2h3E2qHn30+G)*Rzu+qk|V;%<^l8$$Weo<UL*&lyTGwym6?Nw_|kj z{zlN}i_xMy?e?rz6X1IsJnXw8kR?Tcb{;X!KH>=}iJ(YdtzU!13Lh1|*JkR9e0xPA z=47PFjN(m<kkCW))_ieacS--=`jhpHxz@<kz;D7$X~z3WP1iB=b~P!3KpGx32#DIs z^5u1PuceB7n7nc|sNj=}Nxma?p`zcnddz1x)hJp{6U8cQao`p>S2Er6OXtY4B`IBm zm6Z&(TM|Aj2iNZX%zH>tJ#hu~cI|bMC$F_sJhY>LQj_i`<Ll58UPh_mC*qEROQ@$h z$Mna!c-jKQXtPDzn)zalu^$gfwM)g$oGFFt&WsF+LaI)`eTL+GCO~7R3(<D?5M5&d zUoO10(Z~^`n<r1*40@dG^=FM1`Fi8DFvdC?>|9Rpuoy#1hJraWCVuNXiWIin89t1@ z&=G33L8mggu#><H#jP#Me?Bs3ab_VSQ?~NAZE@cBgg6#AF=39I-a-!xt-~@42O;>l z*Tlwdu&0fDR#ou?hqus%c-qJ2cRW4<dU@qfl*Qlh4-FmXEA(ss9RFlZd5{x6taNq0 zX1g1&xVL_*f8*G`W%by`GUjFzi#-zh>xa$2<M827(u4QGKI*KWZo}!xVXkhNpF$^& zElFQ?eVko!vYWOH7Bxjw*KK|q`&d0`<hP!pB}$q&S_x0}eLAIJU;8#hyT!D2+q34S z7hd<ko<bQ3lgs`V_9$x9#$a=eG}hn8m)W5F<F)#Y-=B-uiHFHyT3C*Q-`SeVtQg$5 z1^nhUj2i_^PU^(FrOq{f0T;p3{y^D{5PSH6KgN{}^F*eMmI#+9l&eq%7L6i>y<@x@ zTBBX~dxNyty2-hQL#t(+@9WRnz>IMEpCy`ZXB{{tR^~1L^va)M-sQ4LObCzljo&K^ zB@&W#f<DIWuH8_kH_$X<G|4liT6#k_&QIPgo^kxBE4<@+k>OJDoq~@rG?@ED=$?TP z32O`HGFnDt83k;UH^kfO!{oWjPWVD&M~cF`bcGgLzoI8kHze@12i#MZuHg8ltB8#s zxi*lc?}ps6J`$FTlxi?)@$?&cS`*q)tjn$wpodAJfYB3A2;m{~m~GO+rJVgX%I|vl zG$j4ndRapSD<u^~PqpKt>{6t)2rZ!@HsF0S*mrF1taUxFHDxAp`<`bcKJL_RzW8J} zb^f$M5O3}6LK-<NNq_u_nd@ix(%n{P7R-IBYHC6-qZ+Fmo}la3{T^tl=i{OIA|CWS z(E<@Vx8}WF=ROHcssBSA=M)1bZ{E88mUSFmb0-<BiKiKCX&ggnNRN*@8YGmivu^QJ zm~xui`?P3_b^O)#yhPWp;`FnxL5t@-n3CN0Th@fl%hIN54FWGQBrq#dm>c~HEk*&A z86TJ9PK5rdaSd}fBf<BV@oe8(=2PKbs38kJ?&l!=esFBPeCm8tIFIq&HQz<gwFm;V zG#>I0`fB$I1827wU9jVk05?2D(K?{*`J<L!I-9Exlcn*B7m_)Y3UrZvZ-UiZjx&ii zEux_@Z!(Marq;*9_sjixe$G5-C4*@9*3=fq@{zy@z*|lfc!CDt?7|M@e5%QlBcqn% z@!izp98#EAL9FYez!pz_?ac71tzWk~^v}Y5teMX5$u%=ze5E%PQWG)zYAweHyQv2i zqyUtN-@a+x#e)`kIqUC);IITvYaSs#qIlw&<&47@lz3~o-O!(;vEe>Fy9os7Gm9Je zI3c{^0X3>r;t5wgWJG6I$eOH0<P0Tj<{Oj%jE~B#kAKl;z-=vcT>UiY3TkejO<>6f z4@p4Zikxg0cpct;VEv9tgc9b|3wm1@x!D%}Vo0@x%UX!OVB5ObvMyQ<hr>s0byG{- z5B6(0-rhCdHe9W_0x|2IiNzzODTKBN^pCP!L2WIB3R(wT+&vgzMG9I4gi!}oDFj)x z90xXWSx<cm_Yt;s9ex(B-Xi~z$gAk>zTkDyj`2~B7r(RLB;_>nScfQD(qKHdiVum= z8Jir|G?>XXE+C>?S5Pis>-N(mYvT=HYFMUK(*PZ?j)+*@poATq|Iv#z48%-b$Dq<M zZ|B~WYm=JP*2`LTLJ80>h0i@(#QjL{fMm@#X|;G(ftHke>uZzCSBbzYWO#x>YjWA; z4p&e<1hha^O)q><9NnaVeMcIO$@p<WK8N#!kk(aro@I<;6)R~OF)u<qZCjWL(8)Eq zv%)9C;fRY_bmas!O>vu=+}SUByzb_p+d)kaDKM4U1})=4;&_4`S|qSr_^72rVOC2; zP8(wqSjMH^*)B0&_mJS_!*Rzes$Va`>)tAGzprp{Z3Gzh+Am`x)(<s2lMPwl@KK-1 zfSN#SGXeu_R-SE^MtPnb`L`yeTWYr)-)(Uo9Q_eqr9^dEHzVRH>@FijU{_DFdu~Uc z7raOX_s8p&inCNiffsy;@Ve76#{}pN=1kVR{A)=(Tnu=~`kckwLZxe0C*v0xXi+Em ziDe`(^0cYK5-Kt45*`9{ih+^ciqN#~Ds}bhj=-M!>`SZRLK-tSJy-w~r({KgF^pTY z#Y4LCRg=P~czCVjwyolLtTz~U9b1?!uHZaQ3|A9~(dS1o;l?86lXMu!7ho+~Fqrki zI&SrR{}%6^LiDucT*yE7F{czV#q=JGv61lfXYlZH?Cs|37=|yvPUnRuC=RE=P>J|4 zP{Vczd96b({fa}UZ~HXPOc_nR<HhUFZ|xu&SbTnF7UJs_8*VIZO&I?sPv9EnD^wNw zyFA<{aY=JhhkOcMq+tHY`R2wu>8yU$>N_p+H!xpnW5&L)krof60{?1*@4a@z>VBj} zso!8MJ_`D{_eK83$EZrVR+uS8b@vtAwqL=Ic3XVNYr%R>U<|th!v(-v?Dg^f(0KW? z1g@tK9>iX8R&5cuiaB-XJdy7N?*nT!y%p{0PVn%LiDT#cyb{*6mS?r$3ntU2JM)je zd>{%M$?34>wpK5BK4xb0A&}j&mCFiPjP^$!R4DIJ!!(Q5q;rCG8FA)IrdKh}cM06x z@5_S7VM}EjVeH|-J}}XR<l#FKNS(LA<O8>@2|wKQ(htZGEG;k1cN8Dpq=sR~>>g6} zAy_uXBlfpCI-!*K5OURNR*VMPliT>J1i`?U)VYBBMq^9*gj^(eg3jver&Bqr8{$D0 zSWYXS7qG{Nt=+y)PZo-c@Vb$&=BJOZJX7h9TX_f+?7JZZCWOOUj$G80)TMYme=BVP z_zO{GZD6_sbwLYxo?(+26Tx;q*>$ku6!xC|DyE_7Wu9qE(b?C|D$=#1-1%beCr+Gp zE3-$R{RXKC(DQ+Lc_ZlXg=EY)MYSGK&n4Sy_>h@k`n>5wz3HoE8WQbSG0cSEnR^D0 zmh;ncvt-&57B>*_v@{Xn^i`}lL`&Rvf?nA-U{zr&H<@<tmlc&er@!l0hJgw)G;$1S zg-y7*W_~`13zuS5_cv*A&M4!0=LHSH_%t}D0fqk!9~a&4Vb#2DcgSSxTGLqTrqZ%I zb&a&SAh~RHIxysx!C|`~J|r^OSkXG}YMf7Xw~||?1g<)L((!WZKMLu5-2sn=BDNai zWP*4WpaJe<q`cPc(>fv)Fs)+gXKykkalWP*E<^<2-tg3qg6d60wOXSAQsUf}S_``8 zx=qekG5Af6CG}<pj-lf)iJFE%>yrm9p7qxp*q`~QzQQnz+~YM-09G^l%v)V?AMHNM zkDWF=fth7)5E7t!o*kY_>eLna9#*kusl(ig-`qAY+NzXL)Z2@@MQG8yY5v(CP;0^y z^lOjsH(ouc4~k}aSHj27iVx`xmkRdrjfLXeLY<AlPy@+pVM^9<547($ZiL91*B;zk z#CPb|6m)i8B1;okiTN4nGd!klX;O1kn<{30|690EXvhBPyy&9>gCfdmZEUJT>#m?p z<EBe#Ci#P+4}wv^`%m_1-_&BIn@??A%05HRzr6iqp3;zqa$=jaH;>WZetxTL)1{1a zWz*1y+alQF2Eum^Txq$MtUb?$iJ`3C^>gSwKy0k0z8-#|_i}TJ*z1>=`tat@E?NbH zq|>?Ij@zS^`3bS@HHx){-Hf9y7%Awx!E!gxliu>JyOa!x--&$h5&^fc)-L~0Y5twJ zudXGR0rwGW8F)tbjYsgPlFN7UWnW`9yV(@FhynW9H5>vj!cQN#=5Q!NBM6d^gY-wh z|DOtvsCsu@_&!(gGiE?*=pHPsjixF0@-EeN6Wm0V9(;L8Qqtm9c(d0FX%hq(7zHao zp89=rflG6c_%&2spNMJVrS}$;(m>Mv`NO6^W66TF$!na&s%ii|eM0c5WDwvxJc4lk z5`@Es=F%cOLcQtoF3iPn^*`C2OYCUaABP}XhCi<UX8$(*M=uBbFQjPohJQ!;n-ypH z4<xStU^#3PO940kMEZ*j|J(HM-tZUdb(g^63@evo`f-gZR`)U|fAe2qd6)5oQ%8X1 zuL8tZSj3<B>}dW#mr|ST(E;L@6(mrg0onag?tXar0SX9|2d<z88kNRZ>cf}Gd8=M| w>FNVRCEuS<5;TW$q5vLL|2UTGvOntL%48f^cd>}X^ir&)u6wuij`frO17L;ctN;K2 literal 0 HcmV?d00001 diff --git a/pandora_console/images/custom_logo/logo-pandorafms-1.png b/pandora_console/images/custom_logo/logo-pandorafms-1.png deleted file mode 100644 index 172802af8b55f163314a6975531ebb60857052d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16310 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	DT`!82T^}h}X@uOXHx`fcuU>hBU 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 Hz3{&PyZF!y diff --git a/pandora_console/include/constants.php b/pandora_console/include/constants.php index e1d24ede9c..966fd3c201 100644 --- a/pandora_console/include/constants.php +++ b/pandora_console/include/constants.php @@ -294,7 +294,11 @@ define('SERVICE_ELEMENT_DYNAMIC', 'dynamic'); define('SERVICE_MODE_MANUAL', 0); define('SERVICE_MODE_SMART', 1); - +// New installation Product Logo. +define('HEADER_LOGO_DEFAULT_CLASSIC', 'logo-default-pandorafms.png'); +define('HEADER_LOGO_DEFAULT_COLLAPSED', 'logo-default-pandorafms-collapsed.png'); +define('HEADER_LOGO_BLACK_CLASSIC', 'logo-black-pandorafms.png'); +define('HEADER_LOGO_BLACK_COLLAPSED', 'logo-default-pandorafms-collapsed.png'); // Status images. // For modules. diff --git a/pandora_console/include/functions_config.php b/pandora_console/include/functions_config.php index 52d72063aa..caa86cc716 100644 --- a/pandora_console/include/functions_config.php +++ b/pandora_console/include/functions_config.php @@ -2358,11 +2358,11 @@ function config_process_config() } if (isset($config['custom_logo']) === false) { - config_update_value('custom_logo', 'logo-pandorafms-1.png'); + config_update_value('custom_logo', HEADER_LOGO_DEFAULT_CLASSIC); } if (isset($config['custom_logo_collapsed']) === false) { - config_update_value('custom_logo_collapsed', 'logo-pandorafms-1-collapsed.png'); + config_update_value('custom_logo_collapsed', HEADER_LOGO_DEFAULT_COLLAPSED); } if (is_metaconsole()) { diff --git a/pandora_console/include/functions_html.php b/pandora_console/include/functions_html.php index 10539fae91..a02d140290 100644 --- a/pandora_console/include/functions_html.php +++ b/pandora_console/include/functions_html.php @@ -4237,6 +4237,82 @@ function html_print_image( } +/** + * Function for print the logo in menu header. + * + * @param boolean $menuCollapsed If true, the menu is collapsed. + * @param boolean $return If true, the formed element is returned. + * + * @return mixed. + */ +function html_print_header_logo_image(bool $menuCollapsed, bool $return=false) +{ + global $config; + + if (defined('PANDORA_ENTERPRISE') === false) { + if ($config['style'] === 'pandora_black') { + $custom_logo = 'images/custom_logo/'.HEADER_LOGO_BLACK_CLASSIC; + $custom_logo_collapsed = 'images/custom_logo/'.HEADER_LOGO_DEFAULT_COLLAPSED; + } else if ($config['style'] === 'pandora') { + $custom_logo = 'images/custom_logo/'.HEADER_LOGO_DEFAULT_CLASSIC; + $custom_logo_collapsed = 'images/custom_logo/'.HEADER_LOGO_DEFAULT_COLLAPSED; + } + + $logo_title = get_product_name().' Opensource'; + } else { + // Handle default logos when change theme. + if ($config['style'] === 'pandora_black' && $config['custom_logo'] === HEADER_LOGO_DEFAULT_CLASSIC) { + $config['custom_logo'] = HEADER_LOGO_BLACK_CLASSIC; + } else if ($config['style'] === 'pandora' && $config['custom_logo'] === HEADER_LOGO_BLACK_CLASSIC) { + $config['custom_logo'] = HEADER_LOGO_DEFAULT_CLASSIC; + } + + $logo_title = get_product_name().' Enterprise'; + $custom_logo = 'images/custom_logo/'.$config['custom_logo']; + + $custom_logo_collapsed = 'images/custom_logo/'.$config['custom_logo_collapsed']; + + if (file_exists(ENTERPRISE_DIR.'/'.$custom_logo) === true) { + $custom_logo = ENTERPRISE_DIR.'/'.$custom_logo; + } + } + + if (isset($config['custom_logo']) === true) { + $output = html_print_image( + $custom_logo, + true, + [ + 'border' => '0', + 'width' => '215', + 'alt' => $logo_title, + 'class' => 'logo_full', + 'style' => ($menuCollapsed === true) ? 'display:none' : 'display:block', + ] + ); + } + + if (isset($config['custom_logo_collapsed']) === true) { + $output .= html_print_image( + $custom_logo_collapsed, + true, + [ + 'border' => '0', + 'width' => '60', + 'alt' => $logo_title, + 'class' => 'logo_icon', + 'style' => ($menuCollapsed === true) ? 'display:block' : 'display:none', + ] + ); + } + + if ($return === false) { + echo $output; + } else { + return $output; + } +} + + /** * Render an input text element. Extended version, use html_print_input_text() to simplify. * diff --git a/pandora_console/include/styles/pandora_black.css b/pandora_console/include/styles/pandora_black.css index 3db3587bef..ac500a35a9 100644 --- a/pandora_console/include/styles/pandora_black.css +++ b/pandora_console/include/styles/pandora_black.css @@ -65,6 +65,9 @@ table.agent_info_table tr { color: #fff !important; } +.logo_green { + background-color: #000; +} #um-next:hover, #um-last:hover { border: 1px solid #888 !important; From 38c207227cb855f0d88038dc087cb6a6993cacd1 Mon Sep 17 00:00:00 2001 From: Rafael Ameijeiras <rafael.ameijeiras@artica.es> Date: Mon, 13 Jun 2022 17:41:49 +0200 Subject: [PATCH 25/38] ent-8673-13219-r-works-instalador-de-tentacle_server --- tentacle/.gitignore | 4 + tentacle/Makefile.PL | 22 + tentacle/NetBSD/tentacle_server | 1869 ++++++++++++++++++++++++ tentacle/build_tentacle_server.sh | 26 + tentacle/conf/tentacle_server.conf.new | 75 + tentacle/man/man1/tentacle_server.1.gz | Bin 0 -> 1309 bytes tentacle/tentacle_server_installer | 438 ++++++ tentacle/util/tentacle_serverd | 185 +++ tentacle/util/tentacle_serverd.service | 14 + 9 files changed, 2633 insertions(+) create mode 100644 tentacle/.gitignore create mode 100644 tentacle/Makefile.PL create mode 100755 tentacle/NetBSD/tentacle_server create mode 100755 tentacle/build_tentacle_server.sh create mode 100644 tentacle/conf/tentacle_server.conf.new create mode 100644 tentacle/man/man1/tentacle_server.1.gz create mode 100755 tentacle/tentacle_server_installer create mode 100755 tentacle/util/tentacle_serverd create mode 100644 tentacle/util/tentacle_serverd.service diff --git a/tentacle/.gitignore b/tentacle/.gitignore new file mode 100644 index 0000000000..c39a713dcc --- /dev/null +++ b/tentacle/.gitignore @@ -0,0 +1,4 @@ +dist/ +blib/ +Makefile +pm_to_blib \ No newline at end of file diff --git a/tentacle/Makefile.PL b/tentacle/Makefile.PL new file mode 100644 index 0000000000..cc444b8524 --- /dev/null +++ b/tentacle/Makefile.PL @@ -0,0 +1,22 @@ +use 5.000; +use ExtUtils::MakeMaker; + +my %ARGV = map { my @r = split /=/,$_; defined $r[1] or $r[1]=1; @r } @ARGV; +my @exe_files = qw(tentacle_server); + +WriteMakefile( + INSTALLSITELIB => '/usr/lib/perl5', + (($^O eq 'freebsd') + ? (INSTALLSITELIB => '') : () + ), + ($^O eq 'netbsd') ? ( + INSTALLSITELIB => '', + INSTALLSITESCRIPT => '/usr/local/bin', + ) :(), + + NAME => 'PandoraFMS', + AUTHOR => 'Artica ST <info@artica.es>', + EXE_FILES => [ @exe_files ], + PMLIBDIRS => [ 'lib' ], + 'dist' => { 'TAR' => 'tar', 'TARFLAGS' => 'cvfz', 'SUFFIX' => '.gz', 'COMPRESS' => 'gzip'} +); diff --git a/tentacle/NetBSD/tentacle_server b/tentacle/NetBSD/tentacle_server new file mode 100755 index 0000000000..d945a134e8 --- /dev/null +++ b/tentacle/NetBSD/tentacle_server @@ -0,0 +1,1869 @@ +#!/usr/bin/perl +########################################################################## +# Tentacle Server +# See https://pandorafms.com/docs/ for protocol description. +# Tentacle have IANA assigned port tpc/41121 as official port. +########################################################################## +# Copyright (c) 2007-2008 Ramon Novoa <rnovoa@artica.es> +# Copyright (c) 2005-2010 Artica Soluciones Tecnologicas S.L +# +# tentacle_server.pl Tentacle Server. See https://pandorafms.com/docs/ for +# protocol description. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +########################################################################## + +package tentacle::server; +=head1 NAME + +tentacle_server - Tentacle Server + +=head1 VERSION + +Version 0.6.1 + +=head1 USAGE + +tentacle_server B<< -s F<storage_directory> >> [I<options>] + +=head1 DESCRIPTION + +B<tentacle_server(1)> is a server for B<tentacle>, a B<client/server> file transfer protocol that aims to be: + +=over + +=item * Secure by design. + +=item * Easy to use. + +=item * Versatile and cross-platform. + +=back + +Tentacle was created to replace more complex tools like SCP and FTP for simple file transfer/retrieval, and switch from authentication mechanisms like .netrc, interactive logins and SSH keys to X.509 certificates. Simple password authentication over a SSL secured connection is supported too. + +The client and server (B<TCP port 41121>) are designed to be run from the command line or called from a shell script, and B<no configuration files are needed>. + +=cut + +use strict; +use warnings; +use Getopt::Std; +use IO::Select; +use IO::Compress::Zip qw(zip $ZipError); +use IO::Uncompress::Unzip qw(unzip $UnzipError); +use threads; +use Thread::Semaphore; +use POSIX ":sys_wait_h"; +use Time::HiRes qw(usleep); +use Scalar::Util qw(refaddr); +use POSIX qw(strftime); + +# Constants for Win32 services. +use constant WIN32_SERVICE_STOPPED => 0x01; +use constant WIN32_SERVICE_RUNNING => 0x04; + +my $t_libwrap_installed = eval { require Authen::Libwrap } ? 1 : 0; + +if ($t_libwrap_installed) { + Authen::Libwrap->import( qw( hosts_ctl STRING_UNKNOWN ) ); +} + +# Log errors, 1 enabled, 0 disabled +my $t_log = 0; + +# Log information, 1 enabled, 0 enabled +my $t_log_hard = 0; + +my $SOCKET_MODULE; +if ($^O eq 'MSWin32') { + # Only support INET on windows + require IO::Socket::INET; + $SOCKET_MODULE = 'IO::Socket::INET'; +} else { + $SOCKET_MODULE = + eval { require IO::Socket::INET6 } ? 'IO::Socket::INET6' + : eval { require IO::Socket::INET } ? 'IO::Socket::INET' + : die $@; +} + +# Service name for Win32. +my $SERVICE_NAME="Tentacle Server"; + +# Service parameters. +my $SERVICE_PARAMS=join(' ', @ARGV); + +# Program version +our $VERSION = '0.6.2'; + +# IPv4 address to listen on +my @t_addresses = ('0', '0.0.0.0'); + +# Block size for socket read/write operations in bytes +my $t_block_size = 1024; + +# Client socket +my $t_client_socket; + +# Run as daemon, 1 true, 0 false +my $t_daemon = 0; + +# Storage directory +my $t_directory = ''; + +# Filters +my @t_filters; + +# Enable (1) or disable (0) insecure mode +my $t_insecure = 0; + +# String containing quoted invalid file name characters +my $t_invalid_chars = '\?\[\]\/\\\=\+\<\>\:\;\'\,\*\~'; + +# Maximum number of simultaneous connections +my $t_max_conn = 10; + +# Maximum file size allowed by the server in bytes +my $t_max_size = 2000000; + +# File overwrite, 1 enabled, 0 disabled +my $t_overwrite = 0; + +# Port to listen on +my $t_port = 41121; + +# Server password +my $t_pwd = ''; + +# Do not output error messages, 1 enabled, 0 disabled +my $t_quiet = 0; + +# Number of retries for socket read/write operations +my $t_retries = 3; + +# Select handler +my $t_select; + +# Semaphore +my $t_sem :shared; + +# Server socket +my @t_server_sockets; + +# Server select handler +my $t_server_select; + +# Use SSL, 1 true, 0 false +my $t_ssl = 0; + +# SSL ca certificate file +my $t_ssl_ca = ''; + +# SSL certificate file +my $t_ssl_cert = ''; + +# SSL private key file +my $t_ssl_key = ''; + +# SSL private key password +my $t_ssl_pwd = ''; + +# Timeout for socket read/write operations in seconds +my $t_timeout = 1; + +# Address to proxy client requests to +my $t_proxy_ip = undef; + +# Port to proxy client requests to +my $t_proxy_port = 41121; + +# Proxy socket +my $t_proxy_socket; + +# Proxy selected handler +my $t_proxy_select; + +# Use libwrap, 1 true, 0 false +my $t_use_libwrap = 0; + +# Program name for libwrap +my $t_program_name = $0; +$t_program_name =~ s/.*\///g; + +# Log file +my $log_file = undef; + +################################################################################ +## SUB print_help +## Print help screen. +################################################################################ +sub print_help { + $" = ','; + + print ("Usage: $0 -s <storage directory> [options]\n\n"); + print ("Tentacle server v$VERSION. See https://pandorafms.com/docs/ for protocol description.\n\n"); + print ("Options:\n"); + print ("\t-a ip_addresses\tIP addresses to listen on (default @t_addresses).\n"); + print ("\t \t(Multiple addresses separated by comma can be defined.)\n"); + print ("\t-c number\tMaximum number of simultaneous connections (default $t_max_conn).\n"); + print ("\t-d\t\tRun as daemon.\n"); + print ("\t-e cert\t\tOpenSSL certificate file. Enables SSL.\n"); + print ("\t-f ca_cert\tVerify that the peer certificate is signed by a ca.\n"); + print ("\t-F config_file\tConfiguration file full path.\n"); + print ("\t-h\t\tShow help.\n"); + print ("\t-I\t\tEnable insecure operations (file listing and moving).\n"); + print ("\t-i\t\tFilters.\n"); + print ("\t-k key\t\tOpenSSL private key file.\n"); + print ("\t-l log_file\t\tFile to write logs.\n"); + print ("\t-m size\t\tMaximum file size in bytes (default ${t_max_size}b).\n"); + print ("\t-o\t\tEnable file overwrite.\n"); + print ("\t-p port\t\tPort to listen on (default $t_port).\n"); + print ("\t-q\t\tQuiet. Do now print error messages.\n"); + print ("\t-r number\tNumber of retries for network opertions (default $t_retries).\n"); + print ("\t-S (install|uninstall|run) Manage the win32 service.\n"); + print ("\t-t time\t\tTime-out for network operations in seconds (default ${t_timeout}s).\n"); + print ("\t-v\t\tBe verbose (display errors).\n"); + print ("\t-V\t\tBe verbose on hard way (display errors and other info).\n"); + print ("\t-w\t\tPrompt for OpenSSL private key password.\n"); + print ("\t-x pwd\t\tServer password.\n"); + print ("\t-b ip_address\tProxy requests to the given address.\n"); + print ("\t-g port\t\tProxy requests to the given port.\n"); + print ("\t-T\t\tEnable tcpwrappers support.\n"); + print ("\t \t\t(To use this option, 'Authen::Libwrap' should be installed.)\n\n"); +} + +################################################################################ +## SUB daemonize +## Turn the current process into a daemon. +################################################################################ +sub daemonize { + my $pid; + + require POSIX; + + chdir ('/') || error ("Cannot chdir to /: $!."); + umask 0; + + open (STDIN, '/dev/null') || error ("Cannot read /dev/null: $!."); + + # Do not be verbose when running as a daemon + open (STDOUT, '>/dev/null') || error ("Cannot write to /dev/null: $!."); + open (STDERR, '>/dev/null') || error ("Cannot write to /dev/null: $!."); + + # Fork + $pid = fork (); + if (! defined ($pid)) { + error ("Cannot fork: $!."); + } + + # Parent + if ($pid != 0) { + exit; + } + + # Child + POSIX::setsid () || error ("Cannot start a new session: $!."); +} + +################################################################################ +## SUB parse_options +## Parse command line options and initialize global variables. +################################################################################ +sub parse_options { + my %opts; + my $CONF = {}; + my $token_value; + my $tmp; + my @t_addresses_tmp; + + # Get options + if (getopts ('a:b:c:de:f:F:g:hIi:k:l:m:op:qr:s:S:t:TvVwx:', \%opts) == 0 || defined ($opts{'h'})) { + print_help (); + exit 1; + } + + # The Win32 service must be installed/uninstalled without checking other parameters. + if (defined ($opts{'S'})) { + my $service_action = $opts{'S'}; + if ($^O ne 'MSWin32') { + error ("Windows services are only available on Win32."); + } else { + eval "use Win32::Daemon"; + die($@) if ($@); + + if ($service_action eq 'install') { + install_service(); + } elsif ($service_action eq 'uninstall') { + uninstall_service(); + } + } + } + + # Configuration file + if (defined($opts{'F'})) { + parse_config_file($opts{'F'}, $CONF); + } + + # Address + $token_value = get_config_value($opts{'a'}, $CONF->{'addresses'}); + if (defined ($token_value)) { + @t_addresses = (); + @t_addresses_tmp = split(/,/, $token_value); + + foreach my $t_address (@t_addresses_tmp) { + $t_address =~ s/^ *(.*?) *$/$1/; + if (($t_address ne '0') && + ($t_address !~ /^[a-zA-Z\.]+$/ && ($t_address !~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ + || $1 < 0 || $1 > 255 || $2 < 0 || $2 > 255 + || $3 < 0 || $3 > 255 || $4 < 0 || $4 > 255)) && + ($t_address !~ /^[0-9a-f:]+$/o)) { + error ("Address $t_address is not valid."); + } + push @t_addresses, $t_address; + } + } + + # Maximum simultaneous connections + $token_value = get_config_value($opts{'c'}, $CONF->{'max_connections'}); + if (defined ($token_value)) { + $t_max_conn = $token_value; + if ($t_max_conn !~ /^\d+$/ || $t_max_conn < 1) { + error ("Invalid number of maximum simultaneous connections."); + } + } + + # Run as daemon + $token_value = get_config_value($opts{'d'}, $CONF->{'daemon'}, 1); + if (defined ($token_value)) { + if ($^ eq 'MSWin32') { + error ("-d flag not available for this OS."); + } + + $t_daemon = 1; + } + + # Enable SSL + $token_value = get_config_value($opts{'e'}, $CONF->{'ssl_cert'}); + if (defined ($token_value)) { + + require IO::Socket::SSL; + + $t_ssl_cert = $token_value; + if (! -f $t_ssl_cert) { + error ("File $t_ssl_cert does not exist."); + } + + $t_ssl = 1; + } + + # Verify peer certificate + $token_value = get_config_value($opts{'f'}, $CONF->{'ssl_ca'}); + if (defined ($token_value)) { + $t_ssl_ca = $token_value; + if (! -f $t_ssl_ca) { + error ("File $t_ssl_ca does not exist."); + } + } + + # Insecure mode + $token_value = get_config_value($opts{'I'}, $CONF->{'insecure'}, 1); + if (defined ($token_value)) { + $t_insecure = 1; + } + + # Filters (regexp:dir;regexp:dir...) + $token_value = get_config_value($opts{'i'}, $CONF->{'filters'}); + if (defined ($token_value)) { + my @filters = split (';', $token_value); + foreach my $filter (@filters) { + my ($regexp, $dir) = split (':', $filter); + next unless defined ($regexp) && defined ($dir); + + # Remove any trailing / + my $char = chop ($dir); + $dir .= $char if ($char) ne '/'; + + push(@t_filters, [$regexp, $dir]); + } + } + + # SSL private key file + $token_value = get_config_value($opts{'k'}, $CONF->{'ssl_key'}); + if (defined ($token_value)) { + $t_ssl_key = $token_value; + if (! -f $t_ssl_key) { + error ("File $t_ssl_key does not exist."); + } + } + + # Maximum file size + $token_value = get_config_value($opts{'m'}, $CONF->{'max_size'}); + if (defined ($token_value)) { + $t_max_size = $token_value; + if ($t_max_size !~ /^\d+$/ || $t_max_size < 1) { + error ("Invalid maximum file size."); + } + } + + # File overwrite + $token_value = get_config_value($opts{'o'}, $CONF->{'overwrite'}, 1); + if (defined ($token_value)) { + $t_overwrite = 1; + } + + # Port + $token_value = get_config_value($opts{'p'}, $CONF->{'port'}); + if (defined ($token_value)) { + $t_port = $token_value; + if ($t_port !~ /^\d+$/ || $t_port < 1 || $t_port > 65535) { + error ("Port $t_port is not valid."); + } + } + + # Quiet mode + $token_value = get_config_value($opts{'q'}, $CONF->{'quiet'}, 1); + if (defined ($token_value)) { + $t_quiet = 1; + } + + # Retries + $token_value = get_config_value($opts{'r'}, $CONF->{'retries'}); + if (defined ($token_value)) { + $t_retries = $token_value; + if ($t_retries !~ /^\d+$/ || $t_retries < 1) { + error ("Invalid number of retries for network operations."); + } + } + + # Storage directory + $token_value = get_config_value($opts{'s'}, $CONF->{'directory'}); + if (defined ($token_value)) { + + $t_directory = $token_value; + + # Check that directory exists + if (! -d $t_directory) { + error ("Directory $t_directory does not exist."); + } + + # Check directory permissions + if (! -w $t_directory) { + error ("Cannot write to directory $t_directory."); + } + + # Remove the trailing / if present + $tmp = chop ($t_directory); + if ($tmp ne '/') { + $t_directory .= $tmp; + } + } + else { + $token_value = get_config_value($opts{'b'}, $CONF->{'proxy_ip'}); + if (! defined($token_value)) { + print_help (); + exit 1; + } + } + + # Timeout + $token_value = get_config_value($opts{'t'}, $CONF->{'timeout'}); + if (defined ($token_value)) { + $t_timeout = $token_value; + if ($t_timeout !~ /^\d+$/ || $t_timeout < 1) { + error ("Invalid timeout for network operations."); + } + } + + # Read verbose from config file + if (defined($CONF->{'verbose'})) { + if ($CONF->{'verbose'} eq "1") { + $t_log = 1; + } elsif ($CONF->{'verbose'} eq "2") { + $t_log = 1; + $t_log_hard = 1; + } + } + # Be verbose + if (defined ($opts{'v'})) { + $t_log = 1; + $t_log_hard = 0; + } + # Be verbose hard + if (defined ($opts{'V'})) { + $t_log = 1; + $t_log_hard = 1; + } + + # SSL private key password + $token_value = get_config_value($opts{'w'}, $CONF->{'ssl_password'}, 1); + if (defined ($token_value)) { + $t_ssl_pwd = ask_passwd ("Enter private key file password: ", "Enter private key file password again for confirmation: "); + } + + # Server password + $token_value = get_config_value($opts{'x'}, $CONF->{'password'}); + if (defined ($token_value)) { + $t_pwd = $token_value; + } + + #Proxy IP address + $token_value = get_config_value($opts{'b'}, $CONF->{'proxy_ip'}); + if (defined ($token_value)) { + $t_proxy_ip = $token_value; + if ($t_proxy_ip !~ /^[a-zA-Z\.]+$/ && ($t_proxy_ip !~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ + || $1 < 0 || $1 > 255 || $2 < 0 || $2 > 255 + || $3 < 0 || $3 > 255 || $4 < 0 || $4 > 255) && + $t_proxy_ip !~ /^[0-9a-f:]+$/o) { + error ("Proxy address $t_proxy_ip is not valid."); + } + } + + # Proxy Port + $token_value = get_config_value($opts{'g'}, $CONF->{'proxy_port'}); + if (defined ($token_value)) { + $t_proxy_port = $token_value; + if ($t_proxy_port !~ /^\d+$/ || $t_proxy_port < 1 || $t_proxy_port > 65535) { + error ("Proxy port $t_port is not valid."); + } + } + + # TCP wrappers support + $token_value = get_config_value($opts{'T'}, $CONF->{'use_libwrap'}, 1); + if (defined ($token_value)) { + if ($t_libwrap_installed) { + $t_use_libwrap = 1; + } else { + error ("Authen::Libwrap is not installed."); + } + } + + # Win32 service management + if (defined ($opts{'S'})) { + my $service_action = $opts{'S'}; + if ($^O ne 'MSWin32') { + error ("Windows services are only available on Win32."); + } else { + eval "use Win32::Daemon"; + die($@) if ($@); + + if ($service_action eq 'run') { + Win32::Daemon::RegisterCallbacks({ + start => \&callback_start, + running => \&callback_running, + stop => \&callback_stop, + }); + Win32::Daemon::StartService(); + exit 0; + } else { + error("Unknown action: $service_action"); + } + } + } + + # Get the config file + $token_value = get_config_value($opts{'l'}, $CONF->{'log_file'}); + if (defined ($token_value)) { + $log_file = $token_value; + } + + # No command lines config values + + # Get the block size + if (defined ($CONF->{'block_size'})) { + if ($t_port !~ /^\d+$/ || $t_port < 1) { + error ("Invalid block size: " . $CONF->{'block_size'} . "."); + } + $t_block_size = $CONF->{'block_size'}; + } + + # Configuration file invalid chars + if (defined ($CONF->{'invalid_chars'})) { + $t_invalid_chars = $CONF->{'invalid_chars'}; + } +} + +################################################################################ +## SUB parse_config_file +## Get all options from a config file. +################################################################################ +sub parse_config_file { + my ($config_file, $CONF) = @_; + + # File should be writable + if (! -r $config_file) { + print "Configuration file $config_file is not readable.\n"; + return; + } + + # Open the file + my $FH; + if (! open ($FH, "< $config_file")) { + print "Cannot open configuration file $config_file.\n"; + return; + } + + # Read the file and only get the well formed lines + while (<$FH>) { + my $buffer_line = $_; + if ($buffer_line =~ /^[a-zA-Z]/){ # begins with letters + if ($buffer_line =~ m/([\w\-\_\.]+)\s+(.*)/){ + $CONF->{$1} = $2 unless $2 eq ""; + } + } + } + + close ($FH); + return; +} + +################################################################################ +## SUB parse_config_file +## Search in command line options and config hash from configuration file +## to get a value (command line is a priority) +################################################################################ +sub get_config_value { + my ($cmd_value, $conf_value, $bool) = @_; + $bool = 0 unless defined($bool); + + return $cmd_value if defined($cmd_value); + # The boolean type value is 1 or undef (0 should be translated like undefP) + if ($bool && defined($conf_value)) { + return undef if ($conf_value ne "1"); + } + return $conf_value; +} + +################################################################################ +## SUB start_proxy +## Open the proxy server socket. +################################################################################ +sub start_proxy { + + # Connect to server + $t_proxy_socket = $SOCKET_MODULE->new ( + PeerAddr => $t_proxy_ip, + PeerPort => $t_proxy_port, + ); + + if (! defined ($t_proxy_socket)) { + error ("Cannot connect to $t_proxy_ip on port $t_proxy_port: $!."); + } + + # Create proxy selector + $t_proxy_select = IO::Select->new (); + $t_proxy_select->add ($t_proxy_socket); + +} + +################################################################################ +## SUB start_server +## Open the server socket. +################################################################################ +sub start_server { + + my $t_server_socket; + + foreach my $t_address (@t_addresses) { + + $t_server_socket = $SOCKET_MODULE->new ( + Listen => $t_max_conn, + LocalAddr => $t_address, + LocalPort => $t_port, + Proto => 'tcp', + ReuseAddr => 1, + ); + + if (! defined ($t_server_socket)) { + print_log ("Cannot open socket for address $t_address on port $t_port: $!."); + next; + } + + print_log ("Server listening on $t_address port $t_port (press <ctr-c> to stop)"); + + # Say message if tentacle proxy is enable + if (defined ($t_proxy_ip)) { + print_log ("Proxy Mode enable, data will be sent to $t_proxy_ip port $t_proxy_port"); + } + + push @t_server_sockets, $t_server_socket; + } + + if (!@t_server_sockets) { + error ("Cannot open socket for all addresses on port $t_port: $!."); + } + + $t_server_select = IO::Select->new(); + foreach my $t_server_socket (@t_server_sockets){ + $t_server_select->add($t_server_socket); + } +} + +################################################################################ +## SUB send_data_proxy +## Send data to proxy socket. +################################################################################ +sub send_data_proxy { + my $data = $_[0]; + my $block_size; + my $retries = 0; + my $size; + my $total = 0; + my $written; + + $size = length ($data); + + while (1) { + + # Try to write data to the socket + if ($t_proxy_select->can_write ($t_timeout)) { + + $block_size = ($size - $total) > $t_block_size ? $t_block_size : ($size - $total); + $written = syswrite ($t_proxy_socket, $data, $size - $total, $total); + + # Write error + if (! defined ($written)) { + error ("Connection error from " . $t_proxy_socket->sockhost () . ": $!."); + } + + # EOF + if ($written == 0) { + error ("Connection from " . $t_proxy_socket->sockhost () . " unexpectedly closed."); + } + + $total += $written; + + # Check if all data was written + if ($total == $size) { + return; + } + } + # Retry + else { + $retries++; + if ($retries > $t_retries) { + error ("Connection from " . $t_proxy_socket->sockhost () . " timed out."); + } + } + } +} + +################################################################################ +## SUB close_proxy +## Close the proxy socket. +################################################################################ +sub close_proxy { + $t_proxy_socket->shutdown (2); + $t_proxy_socket->close (); +} + +################################################################################ +## SUB stop_server +## Close the server socket. +################################################################################ +sub stop_server { + + foreach my $t_server_socket (@t_server_sockets) { + $t_server_socket->shutdown (2); + $t_server_socket->close (); + } + print_log ("Server going down"); + + exit 0; +} + +################################################################################ +## SUB start_ssl +## Convert the client socket to an IO::Socket::SSL socket. +################################################################################ +sub start_ssl { + my $err; + + if ($t_ssl_ca eq '') { + IO::Socket::SSL->start_SSL ( + $t_client_socket, + SSL_cert_file => $t_ssl_cert, + SSL_key_file => $t_ssl_key, + SSL_passwd_cb => sub {return $t_ssl_pwd}, + SSL_server => 1, + # Verify peer + SSL_verify_mode => 0x01, + ); + } + else { + IO::Socket::SSL->start_SSL ( + $t_client_socket, + SSL_ca_file => $t_ssl_ca, + SSL_cert_file => $t_ssl_cert, + SSL_key_file => $t_ssl_key, + SSL_passwd_cb => sub {return $t_ssl_pwd}, + SSL_server => 1, + # Fail verification if no peer certificate exists + SSL_verify_mode => 0x03, + ); + } + + $err = IO::Socket::SSL::errstr (); + if ($err ne '') { + error ($err); + } + + print_log ("SSL started for " . $t_client_socket->sockhost ()); +} + +################################################################################ +## SUB accept_connections +## Manage incoming connections. +################################################################################ +sub accept_connections { + my $pid; + my $t_server_socket; + + # Ignore SIGPIPE + $SIG{PIPE} = 'IGNORE'; + + # Start server + start_server (); + + # Initialize semaphore + $t_sem = Thread::Semaphore->new ($t_max_conn); + + while (1) { + my @ready = $t_server_select->can_read; + foreach $t_server_socket (@ready) { + + # Accept connection + $t_client_socket = $t_server_socket->accept (); + + if (! defined ($t_client_socket)) { + next if ($! ne ''); # EINTR + error ("accept: $!."); + } + + print_info ("Client connected from " . $t_client_socket->peerhost ()); + + if ($t_use_libwrap && (! hosts_ctl($t_program_name, $t_client_socket))) { + print_log ("Connection from " . $t_client_socket->peerhost() . " is closed by tcpwrappers."); + $t_client_socket->shutdown (2); + $t_client_socket->close(); + } + else { + + # Create a new thread and serve the client + $t_sem->down(); + my $thr = threads->create(\&serve_client); + if (! defined ($thr)) { + error ("Error creating thread: $!."); + } + $thr->detach(); + $t_client_socket->close (); + } + } + + usleep (1000); + } +} + +################################################################################ +## SUB serve_client +## Serve a connected client. +################################################################################ +sub serve_client() { + + eval { + # Add client socket to select queue + $t_select = IO::Select->new (); + $t_select->add ($t_client_socket); + + # Start SSL + if ($t_ssl == 1) { + start_ssl (); + } + + # Authenticate client + if ($t_pwd ne '') { + auth_pwd (); + } + + # Check if proxy mode is enable + if (defined ($t_proxy_ip)) { + serve_proxy_connection (); + } else { + serve_connection (); + } + }; + + $t_client_socket->shutdown (2); + $t_client_socket->close (); + $t_sem->up(); +} + +################################################################################ +## SUB serve_proxy_connection +## Actuate as a proxy between its client and other tentacle server. +################################################################################ +sub serve_proxy_connection { + + # We are a proxy! Start a connection to the Tentacle Server. + start_proxy(); + + # Forward data between the client and the server. + eval { + my $select = IO::Select->new (); + $select->add($t_proxy_socket); + $select->add($t_client_socket); + while (my @ready = $select->can_read()) { + foreach my $socket (@ready) { + if (refaddr($socket) == refaddr($t_client_socket)) { + my ($read, $data) = recv_data($t_block_size); + return unless defined($data); + send_data_proxy($data); + } + else { + my ($read, $data) = recv_data_proxy($t_block_size); + return unless defined($data); + send_data($data); + } + } + } + }; + + # Close the connection to the Tentacle Server. + close_proxy(); +} + +################################################################################ +## SUB serve_connection +## Read and process commands from the client. +################################################################################ +sub serve_connection { + my $command; + + # Read commands + while ($command = recv_command ($t_block_size)) { + + # Client wants to send a file + if ($command =~ /^SEND <(.*)> SIZE (\d+)$/) { + print_info ("Request to send file '$1' size ${2}b from " . $t_client_socket->sockhost ()); + recv_file ($1, $2); + } + # Client wants to receive a file + elsif ($command =~ /^RECV <(.*)>$/) { + print_info ("Request to receive file '$1' from " . $t_client_socket->sockhost ()); + send_file ($1); + } + elsif ($command =~ /^ZSEND <(.*)> SIZE (\d+)$/) { + print_info ("Request to send compressed file '$1' size ${2}b from " . $t_client_socket->sockhost ()); + zrecv_file ($1, $2); + } + # Client wants to receive a file + elsif ($command =~ /^ZRECV <(.*)>$/) { + print_info ("Request to receive compressed file '$1' from " . $t_client_socket->sockhost ()); + zsend_file ($1); + } + # Quit + elsif ($command =~ /^QUIT$/) { + print_info ("Connection closed from " . $t_client_socket->sockhost ()); + last; + } + # File listing. + elsif ($command =~ /^LS <(.*)>$/) { + if ($t_insecure == 0) { + print_info ("Insecure mode disabled. Rejected request to list files matched by filter $1 from " . $t_client_socket->sockhost ()); + last; + } + + print_info ("Request to list files matched by filter $1 from " . $t_client_socket->sockhost ()); + send_file_list ($1); + } + # Client wants to move a file + elsif ($command =~ /^MV <(.*)>$/) { + if ($t_insecure == 0) { + print_info ("Insecure mode disabled. Rejected request to move file $1 from " . $t_client_socket->sockhost ()); + last; + } + + print_info ("Request to move file '$1' from " . $t_client_socket->sockhost ()); + move_file ($1); + } + # Unknown command + else { + print_log ("Unknown command '$command' from " . $t_client_socket->sockhost ()); + last; + } + } +} + +################################################################################ +## SUB auth_pwd +## Authenticate client with server password. +################################################################################ +sub auth_pwd { + my $client_digest; + my $command; + my $pwd_digest; + + require Digest::MD5; + + # Wait for password + $command = recv_command ($t_block_size); + if ($command !~ /^PASS (.*)$/) { + error ("Client " . $t_client_socket->sockhost () . " did not authenticate."); + } + + $client_digest = $1; + $pwd_digest = Digest::MD5::md5 ($t_pwd); + $pwd_digest = Digest::MD5::md5_hex ($pwd_digest); + + if ($client_digest ne $pwd_digest) { + error ("Invalid password from " . $t_client_socket->sockhost () . "."); + } + + print_log ("Client " . $t_client_socket->sockhost () . " authenticated"); + send_data ("PASS OK\n"); +} + +################################################################################ +## SUB recv_file +## Receive a file of size $_[1] and save it in $t_directory as $_[0]. +################################################################################ +sub recv_file { + my $base_name = $_[0]; + my $data = ''; + my $file; + my $size = $_[1]; + + # Check file name + if ($base_name =~ /[$t_invalid_chars]/) { + print_log ("File '$base_name' size ${size}b from " . $t_client_socket->sockhost () . " has an invalid file name"); + send_data ("SEND ERR (invalid file name)\n"); + return; + } + + # Check file size, empty files are not allowed + if ($size < 1 || $size > $t_max_size) { + print_log ("File '$base_name' size ${size}b from " . $t_client_socket->sockhost () . " is too big"); + send_data ("SEND ERR (file is too big)\n"); + return; + } + + # Apply filters + $file = "$t_directory/" . apply_filters ($base_name) . $base_name; + + # Check if file exists + if (-f $file && $t_overwrite == 0) { + print_log ("File '$base_name' size ${size}b from " . $t_client_socket->sockhost () . " already exists"); + send_data ("SEND ERR (file already exists)\n"); + return; + } + + send_data ("SEND OK\n"); + + # Receive file + $data = recv_data_block ($size); + + # Write it to disk + open (FILE, "> $file") || error ("Cannot open file '$file' for writing."); + binmode (FILE); + print (FILE $data); + close (FILE); + + send_data ("SEND OK\n"); + print_info ("Received file '$base_name' size ${size}b from " . $t_client_socket->sockhost ()); +} + +################################################################################ +## SUB zrecv_file +## Receive a compressed file of size $_[1] and save it in $t_directory as $_[0]. +################################################################################ +sub zrecv_file { + my $base_name = $_[0]; + my $data = ''; + my $file; + my $size = $_[1]; + my $zdata = ''; + + # Check file name + if ($base_name =~ /[$t_invalid_chars]/) { + print_log ("File '$base_name' size ${size}b from " . $t_client_socket->sockhost () . " has an invalid file name"); + send_data ("ZSEND ERR (invalid file name)\n"); + return; + } + + # Check file size, empty files are not allowed + if ($size < 1 || $size > $t_max_size) { + print_log ("File '$base_name' size ${size}b from " . $t_client_socket->sockhost () . " is too big"); + send_data ("ZSEND ERR (file is too big)\n"); + return; + } + + # Apply filters + $file = "$t_directory/" . apply_filters ($base_name) . $base_name; + + # Check if file exists + if (-f $file && $t_overwrite == 0) { + print_log ("File '$base_name' size ${size}b from " . $t_client_socket->sockhost () . " already exists"); + send_data ("ZSEND ERR (file already exists)\n"); + return; + } + + send_data ("ZSEND OK\n"); + + # Receive file + $zdata = recv_data_block ($size); + if (!unzip(\$zdata => \$data)) { + print_log ("Uncompress error: $UnzipError"); + send_data ("ZSEND ERR\n"); + return; + } + + # Write it to disk + open (FILE, "> $file") || error ("Cannot open file '$file' for writing."); + binmode (FILE); + print (FILE $data); + close (FILE); + + send_data ("ZSEND OK\n"); + print_info ("Received compressed file '$base_name' size ${size}b from " . $t_client_socket->sockhost ()); +} + +################################################################################ +## SUB send_file +## Send a file to the client +################################################################################ +sub send_file { + my $base_name = $_[0]; + my $data = ''; + my $file; + my $response; + my $size; + + # Check file name + if ($base_name =~ /[$t_invalid_chars]/) { + print_log ("Requested file '$base_name' from " . $t_client_socket->sockhost () . " has an invalid file name"); + send_data ("RECV ERR (file has an invalid file name)\n"); + return; + } + + # Apply filters + $file = "$t_directory/" . apply_filters ($base_name) . $base_name; + + # Check if file exists + if (! -f $file) { + print_log ("Requested file '$file' from " . $t_client_socket->sockhost () . " does not exist"); + send_data ("RECV ERR (file does not exist)\n"); + return; + } + + $size = -s $file; + send_data ("RECV SIZE $size\n"); + + # Wait for client response + $response = recv_command ($t_block_size); + if ($response ne "RECV OK") { + print_log ("Requested file '$file' from " . $t_client_socket->sockhost () . " not sent"); + return; + } + + # Send the file + open (FILE, $file) || error ("Cannot open file '$file' for reading."); + binmode (FILE); + { + local $/ = undef; + $data = <FILE>; + } + + send_data ($data); + close (FILE); + + print_log ("Requested file '$file' from " . $t_client_socket->sockhost () . " sent"); +} + +################################################################################ +## SUB zsend_file +## Send a file to the client +################################################################################ +sub zsend_file { + my $base_name = $_[0]; + my $data = ''; + my $file; + my $response; + my $size; + + # Check file name + if ($base_name =~ /[$t_invalid_chars]/) { + print_log ("Requested compressed file '$base_name' from " . $t_client_socket->sockhost () . " has an invalid file name"); + send_data ("ZRECV ERR (file has an invalid file name)\n"); + return; + } + + # Apply filters + $file = "$t_directory/" . apply_filters ($base_name) . $base_name; + + # Check if file exists + if (! -f $file) { + print_log ("Requested compressed '$file' from " . $t_client_socket->sockhost () . " does not exist"); + send_data ("ZRECV ERR (file does not exist)\n"); + return; + } + + # Read the file and compress its contents + if (! zip($file => \$data)) { + send_data ("QUIT\n"); + error ("Compression error: $ZipError"); + return; + } + + $size = length($data); + send_data ("ZRECV SIZE $size\n"); + + # Wait for client response + $response = recv_command ($t_block_size); + if ($response ne "ZRECV OK") { + print_log ("Requested compressed '$file' from " . $t_client_socket->sockhost () . " not sent"); + return; + } + + # Send the file + send_data ($data); + + print_log ("Requested compressed '$file' from " . $t_client_socket->sockhost () . " sent"); +} + +################################################################################ +# Common functions +################################################################################ + +################################################################################ +## SUB print_log +## Print log messages. +################################################################################ +sub print_log($) { + + my ($msg) = @_; + + return unless ($t_log == 1); + + my $fh = *STDOUT; + if (defined($log_file)) { + open($fh, ">>", $log_file) || die("Starting log failed: $!.\n"); + } + + print ($fh strftime ("%Y-%m-%d %H:%M:%S", localtime()) . "[log]$msg.\n"); + + close ($fh) if (defined($log_file)); + +} + +################################################################################ +## SUB print_log +## Print log messages. +################################################################################ +sub print_info($) { + + my ($msg) = @_; + + return unless ($t_log_hard == 1); + + my $fh = *STDOUT; + if (defined($log_file)) { + open($fh, ">>", $log_file) || die("Starting log failed: $!.\n"); + } + + print ($fh strftime ("%Y-%m-%d %H:%M:%S", localtime()) . "[info]$msg.\n"); + + close ($fh) if (defined($log_file)); + +} + +################################################################################ +## SUB error +## Print an error and exit the program. +################################################################################ +sub error { + + my ($msg) = @_; + + return unless ($t_quiet == 0); + + my $fh = *STDERR; + if (defined($log_file)) { + open($fh, ">>", $log_file) || die("$!\n"); + } + + print ($fh strftime ("%Y-%m-%d %H:%M:%S", localtime()) . "[err]$msg\n"); + + close ($fh) if (defined($log_file)); + + die("\n"); +} + +################################################################################ +## SUB move_file +## Send a file to the client and delete it +################################################################################ +sub move_file { + my $base_name = $_[0]; + my $data = ''; + my $file; + my $response; + my $size; + + # Check file name + if ($base_name =~ /[$t_invalid_chars]/) { + print_log ("Requested file '$base_name' from " . $t_client_socket->sockhost () . " has an invalid file name"); + send_data ("MV ERR\n"); + return; + } + + # Apply filters + $file = "$t_directory/" . apply_filters ($base_name) . $base_name; + + # Check if file exists + if (! -f $file) { + print_log ("Requested file '$file' from " . $t_client_socket->sockhost () . " does not exist"); + send_data ("MV ERR\n"); + return; + } + + $size = -s $file; + send_data ("MV SIZE $size\n"); + + # Wait for client response + $response = recv_command ($t_block_size); + if ($response ne "MV OK") { + print_log ("Requested file '$file' from " . $t_client_socket->sockhost () . " not sent"); + return; + } + + # Send the file + open (FILE, $file) || error ("Cannot open file '$file' for reading."); + binmode (FILE); + + while ($data = <FILE>) { + send_data ($data); + } + + close (FILE); + unlink($file); + + print_log ("Requested file '$file' from " . $t_client_socket->sockhost () . " sent and deleted"); +} + +################################################################################ +## SUB send_file_list +## Send a list of files to the client after applying the given filter. +################################################################################ +sub send_file_list { + my $filter = $_[0]; + my $data = ''; + my $dir; + my $dh; + my $response; + my $size; + + # Check file name + if ($filter =~ /[$t_invalid_chars]/) { + print_log ("Invalid file listing filter '$filter' from " . $t_client_socket->sockhost ()); + send_data ("LS ERR\n"); + return; + } + + # Apply filters + $dir = "$t_directory/" . apply_filters ($filter); + + # Open the directory. + if (! opendir ($dh, $dir)) { + print_log ("Error opening directory $dir as requested from " . $t_client_socket->sockhost () . ": $!"); + send_data ("LS ERR\n"); + return; + } + + # List files. + while (my $file = readdir ($dh)) { + next if ($file =~ /[$t_invalid_chars]/); # Only list files valid for Tentacle. + $data .= "$file\n"; + } + closedir $dh; + + $size = length ($data); + send_data ("LS SIZE $size\n"); + + # Wait for client response + $response = recv_command ($t_block_size); + if ($response ne "LS OK") { + print_log ("Requested directory listing from " . $t_client_socket->sockhost () . " not sent"); + return; + } + + send_data ($data); + + print_log ("Requested directory listing from " . $t_client_socket->sockhost () . " sent"); +} + +################################################################################ +## SUB recv_data_proxy +## Recv data from proxy socket. +################################################################################ +sub recv_data_proxy { + my $data; + my $read; + my $retries = 0; + my $size = $_[0]; + + while (1) { + + # Try to read data from the socket + if ($t_proxy_select->can_read ($t_timeout)) { + + # Read at most $size bytes + $read = sysread ($t_proxy_socket, $data, $size); + + # Read error + if (! defined ($read)) { + error ("Read error from " . $t_proxy_socket->sockhost () . ": $!."); + } + + # EOF + if ($read == 0) { + error ("Connection from " . $t_proxy_socket->sockhost () . " unexpectedly closed."); + } + + return ($read, $data); + } + + # Retry + $retries++; + + # But check for error conditions first + if ($retries > $t_retries) { + error ("Connection from " . $t_proxy_socket->sockhost () . " timed out."); + } + } +} +################################################################################ +## SUB recv_data +## Read data from the client socket. Returns the number of bytes read and the +## string of bytes as a two element array. +################################################################################ +sub recv_data { + my $data; + my $read; + my $retries = 0; + my $size = $_[0]; + + while (1) { + + # Try to read data from the socket + if ($t_select->can_read ($t_timeout)) { + + # Read at most $size bytes + $read = sysread ($t_client_socket, $data, $size); + + # Read error + if (! defined ($read)) { + error ("Read error from " . $t_client_socket->sockhost () . ": $!."); + } + + # EOF + if ($read == 0) { + error ("Connection from " . $t_client_socket->sockhost () . " unexpectedly closed."); + } + + return ($read, $data); + } + + # Retry + $retries++; + + # But check for error conditions first + if ($retries > $t_retries) { + error ("Connection from " . $t_client_socket->sockhost () . " timed out."); + } + } +} + +################################################################################ +## SUB send_data +## Write data to the client socket. +################################################################################ +sub send_data { + my $data = $_[0]; + my $block_size; + my $retries = 0; + my $size; + my $total = 0; + my $written; + + $size = length ($data); + + while (1) { + + # Try to write data to the socket + if ($t_select->can_write ($t_timeout)) { + + $block_size = ($size - $total) > $t_block_size ? $t_block_size : ($size - $total); + $written = syswrite ($t_client_socket, $data, $block_size, $total); + + # Write error + if (! defined ($written)) { + error ("Connection error from " . $t_client_socket->sockhost () . ": $!."); + } + + # EOF + if ($written == 0) { + error ("Connection from " . $t_client_socket->sockhost () . " unexpectedly closed."); + } + + $total += $written; + + # Check if all data was written + if ($total == $size) { + return; + } + } + # Retry + else { + $retries++; + if ($retries > $t_retries) { + error ("Connection from " . $t_client_socket->sockhost () . " timed out."); + } + } + } +} + +################################################################################ +## SUB recv_command +## Read a command from the client, ended by a new line character. +################################################################################ +sub recv_command { + my $buffer; + my $char; + my $command = ''; + my $read; + my $total = 0; + + while (1) { + + ($read, $buffer) = recv_data ($t_block_size); + $command .= $buffer; + $total += $read; + + # Check if the command is complete + $char = chop ($command); + if ($char eq "\n") { + return $command; + } + + $command .= $char; + + # Avoid overflow + if ($total > $t_block_size) { + error ("Received too much data from " . $t_client_socket->sockhost () . "."); + } + } +} + +################################################################################ +## SUB recv_data_block +## Read $_[0] bytes of data from the client. +################################################################################ +sub recv_data_block { + my $buffer = ''; + my $data = ''; + my $read; + my $size = $_[0]; + my $total = 0; + + while (1) { + + ($read, $buffer) = recv_data ($size - $total); + $data .= $buffer; + $total += $read; + + # Check if all data has been read + if ($total == $size) { + return $data; + } + } +} + +################################################################################ +## SUB ask_passwd +## Asks the user for a password. +################################################################################ +sub ask_passwd { + my $msg1 = $_[0]; + my $msg2 = $_[1]; + my $pwd1; + my $pwd2; + + require Term::ReadKey; + + # Disable keyboard echo + Term::ReadKey::ReadMode('noecho'); + + # Promt for password + print ($msg1); + $pwd1 = Term::ReadKey::ReadLine(0); + print ("\n$msg2"); + $pwd2 = Term::ReadKey::ReadLine(0); + print ("\n"); + + # Restore original settings + Term::ReadKey::ReadMode('restore'); + + if ($pwd1 ne $pwd2) { + print ("Error: passwords do not match.\n"); + exit 1; + } + + # Remove the trailing new line character + chop $pwd1; + + return $pwd1; +} + +################################################################################ +## SUB apply_filters +## Applies filters to the given file. +################################################################################ +sub apply_filters ($) { + my ($file_name) = @_; + + foreach my $filter (@t_filters) { + my ($regexp, $dir) = @{$filter}; + if ($file_name =~ /$regexp/) { + print_log ("File '$file_name' matches filter '$regexp' (changing to directory '$dir')"); + return $dir . '/'; + } + } + + return ''; +} + +################################################################################ +## SUB install_service +## Install the Windows service. +################################################################################ +sub install_service() { + + my $service_path = $0; + my $service_params = $SERVICE_PARAMS; + + # Change the service parameter from 'install' to 'run'. + $service_params =~ s/\-S\s+\S+/\-S run/; + + my %service_hash = ( + machine => '', + name => 'TENTACLESRV', + display => $SERVICE_NAME, + path => $service_path, + user => '', + pwd => '', + description => 'Tentacle Server http://sourceforge.net/projects/tentacled/', + parameters => $service_params + ); + + if (Win32::Daemon::CreateService(\%service_hash)) { + print "Successfully added.\n"; + exit 0; + } else { + print "Failed to add service: " . Win32::FormatMessage(Win32::Daemon::GetLastError()) . "\n"; + exit 1; + } +} + +################################################################################ +## SUB uninstall_service +## Install the Windows service. +################################################################################ +sub uninstall_service() { + if (Win32::Daemon::DeleteService('', 'TENTACLESRV')) { + print "Successfully deleted.\n"; + exit 0; + } else { + print "Failed to delete service: " . Win32::FormatMessage(Win32::Daemon::GetLastError()) . "\n"; + exit 1; + } +} + +################################################################################ +## SUB callback_running +## Windows service callback function for the running event. +################################################################################ +sub callback_running { + + if (Win32::Daemon::State() == WIN32_SERVICE_RUNNING) { + } +} + +################################################################################ +## SUB callback_start +## Windows service callback function for the start event. +################################################################################ +sub callback_start { + + # Accept_connections (); + my $thr = threads->create(\&accept_connections); + if (!defined($thr)) { + Win32::Daemon::State(WIN32_SERVICE_STOPPED); + Win32::Daemon::StopService(); + return; + } + $thr->detach(); + + Win32::Daemon::State(WIN32_SERVICE_RUNNING); +} + +################################################################################ +## SUB callback_stop +## Windows service callback function for the stop event. +################################################################################ +sub callback_stop { + + foreach my $t_server_socket (@t_server_sockets) { + $t_server_socket->shutdown (2); + $t_server_socket->close (); + } + + Win32::Daemon::State(WIN32_SERVICE_STOPPED); + Win32::Daemon::StopService(); +} + +################################################################################ +# Main +################################################################################ + +# Never run as root +if ($> == 0 && $^O ne 'MSWin32') { + print ("Error: for safety reasons $0 cannot be run with root privileges.\n"); + exit 1; +} + +# Parse command line options +parse_options (); + +# Check command line arguments +if ($#ARGV != -1) { + print_help (); + exit 1; +} + +# Show IPv6 status +if ($SOCKET_MODULE eq 'IO::Socket::INET') { + print_log ("IO::Socket::INET6 is not found. IPv6 is disabled."); +} + +# Run as daemon? +if ($t_daemon == 1 && $^O ne 'MSWin32') { + daemonize (); +} + +# Handle ctr-c +if ($^O eq 'MSWin32') { + no warnings; + $SIG{INT2} = \&stop_server; + use warnings; +} +else { + $SIG{INT} = \&stop_server; +} + +# Accept connections +accept_connections(); + +__END__ + +=head1 REQUIRED ARGUMENTES + +=over + +=item B<< -s F<storage_directory> >> Root directory to store the files received by the server + +=back + +=head1 OPTIONS + +=over + +=item I<-a ip_address> Address to B<listen> on (default I<0.0.0.0>). + +=item I<-c number> B<Maximum> number of simultaneous B<connections> (default I<10>). + +=item I<-d> Run as B<daemon>. + +=item I<-e cert> B<OpenSSL certificate> file. Enables SSL. + +=item I<-f ca_cert> Verify that the peer certificate is signed by a B<CA>. + +=item I<-h> Show B<help>. + +=item I<-i> B<Filters>. + +=item I<-k key> B<OpenSSL private key> file. + +=item I<-m size> B<Maximum file size> in bytes (default I<2000000b>). + +=item I<-o> Enable file B<overwrite>. + +=item I<-p port> B<Port to listen> on (default I<41121>). + +=item I<-q> B<Quiet>. Do now print error messages. + +=item I<-r number> B<Number of retries> for network opertions (default I<3>). + +=item I<-t time> B<Time-out> for network operations in B<seconds> (default I<1s>). + +=item I<-v> Be B<verbose>. + +=item I<-w> Prompt for B<OpenSSL private key password>. + +=item I<-x> pwd B<Server password>. + +=back + +=head1 EXIT STATUS + +=over + +=item 0 on Success + +=item 1 on Error + +=back + +=head1 CONFIGURATION + +Tentacle doesn't use any configurationf files, all the configuration is done by the options passed when it's started. + +=head1 DEPENDENCIES + +L<Getopt::Std>, L<IO::Select>, L<IO::Socket::INET>, L<Thread::Semaphore>, L<POSIX> + + +=head1 LICENSE + +This is released under the GNU Lesser General Public License. + +=head1 SEE ALSO + +L<Getopt::Std>, L<IO::Select>, L<IO::Socket::INET>, L<Thread::Semaphore>, L<POSIX> + +Protocol description and more info at: L<< https://pandorafms.com/docs/index.php?title=Pandora:Documentation_en:Tentacle >> + +=head1 COPYRIGHT + +Copyright (c) 2005-2010 Artica Soluciones Tecnologicas S.L + +=cut + diff --git a/tentacle/build_tentacle_server.sh b/tentacle/build_tentacle_server.sh new file mode 100755 index 0000000000..9f833edc99 --- /dev/null +++ b/tentacle/build_tentacle_server.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +CODEHOME=$HOME/code/pandorafms + +# Add build string for nightly builds +if [ "$1" == "nightly" ]; then + LOCAL_VERSION="$VERSION-$BUILD" +else + LOCAL_VERSION=$1 +fi + +if [ ! -d $CODEHOME/tentacle/dist ]; then + mkdir -p $CODEHOME/tentacle/dist || exit 1 +fi + +echo "Creating source tarballs in $(pwd)/dist" + +# Server +cd $CODEHOME && tar zcvf $CODEHOME/tentacle/dist/tentacle_server-$LOCAL_VERSION.tar.gz \ +--exclude \.svn \ +--exclude \.exe \ +--exclude dist \ +--exclude build_tentacle_server.sh \ +tentacle || exit 1 + +exit 0 \ No newline at end of file diff --git a/tentacle/conf/tentacle_server.conf.new b/tentacle/conf/tentacle_server.conf.new new file mode 100644 index 0000000000..1acf082ca2 --- /dev/null +++ b/tentacle/conf/tentacle_server.conf.new @@ -0,0 +1,75 @@ +########################################################################## +# Tentacle Server Parameters +# See https://pandorafms.com/manual/en/documentation/08_technical_reference/09_tentacle +# for protocol description. +# Tentacle have IANA assigned port tpc/41121 as official port. +########################################################################## + +# [-a] IPv4 address to listen on. Several IPs cam be selected separating if by comma. +addresses 0.0.0.0 + +# [-p] Port to listen on +port 41121 + +# [-c] Maximum number of simultaneous connections +# max_connections 10 + +# [-d] Run as daemon. 1 true, 0 false +daemon 1 + +# [-i] Enable insecure mode +# insecure 0 + +# Filters (regexp:dir;regexp:dir...) +filters .*\.conf:conf;.*\.md5:md5;.*\.zip:collections;.*\.lock:trans;.*\.rcmd:commands + +# [-m] Maximum file size allowed by the server in bytes +#max_size 2000000 + +# [-o] Accept files with a repeated name +# overwrite 0 + +# [-q] Do not output error messages. +# quiet 0 + +# [-r] Number of retries for socket read/write operations +# retries 3 + +# [-s] Storage directory +directory /var/spool/pandora/data_in + +# [-b] Address to proxy client requests to +# proxy_ip 127.0.0.1 + +# [-g] Port to proxy client requests to +# proxy_port 41121 + +# [-t] Timeout for socket read/write operations in seconds +# timeout 1 + +# [-v and -V] Verbose level +# 0: Do not display any informative messages +# 1: Display only important messages [-v] +# 2: Display all messages [-V] +# verbose 0 + +# [-l] Log file +log_file /dev/null + +# [-x] Server password +# password PASSWORD + +# [-e] SSL certificate file full path +# ssl_cert /path/to/ssl/cert + +# [-f] SSL CA file full path +# ssl_ca /path/to/ssl/ca + +# [-k] SSL private key file +# ssl_key /path/to/private/key/file + +# [-w] SSL password. Set to 1 to ask for password by command line +# ssl_password 0 + +# [-T] Use libwrap library (Authen::Libwrap perl module) +# use_libwrap 0 \ No newline at end of file diff --git a/tentacle/man/man1/tentacle_server.1.gz b/tentacle/man/man1/tentacle_server.1.gz new file mode 100644 index 0000000000000000000000000000000000000000..eea67284be92f11ac83639c5c5fb9648e2629014 GIT binary patch literal 1309 zcmV+&1>*W2iwFqFhU!ZK19W9>bYWv`WnXh;a&~2ME-?U=R&7rkM-cvgzhcCf+EF-c z8rn3issM2mBwk$3N)rhQt<Ph;;%@h{yJtgxeV^I2IrEZ80m*QCGtbOC^USP&x!R$S z<@kK{iY5ytHML8oN*gA>ux&M?xpgH|m{t@lO<_Te<Hp&Ny|)g2(fv#rYSayjIR!RB zl@-gIEN{vzpM0Xp=zMZ`d^)-=Mwg#Qmo%iE{lRdsJ2==K4tHp0kniUM{4Llm+0k5A zi0YK_b37qlu%)d4SA3%L!?RJg33Ba|!__WQ^FMNqzQxz`i*a#M#H^*_1y>D~wyu?# z#lo}vh@OCFf7vEzYy964<HM*pzC0OEPA<+fv7W50DbpTFl$FN8-Vbx3uuy@Nu6?5Q z9f71G3u;Qe_x(S!imE)@eLuS6vc(}F;CbT|>_M<c($ywu54+;t2d=49RpqHSZ%rA~ z6{n@1@r<VTh{$xy&T!R-$Elt=<?f%mtaMmtvk3=A#7?vCBf(LYJ=D5Vo=V3m039Vj z6P1EcYU@}sYbw6OxdnKoZ<&hYF$u#TC*!CQuf^msJ9~};LM>JGI@)^VQZ8ujY)z^~ z{wC;BNt#r1xll&?dJUf&xR$R;o4`(?6j8Cg(I`le3Uuw3?<3h?@`J%2RI&?tE^zE~ zDpEF$@_uFA>}fPBjZ{E6g~H0#q2$sU!;vyV(|y}C)+H)zPM`^7Cmp0pk`{Usupox? zW;om*_DO-P8GC(W5{sBG*P2wZ^lMv}(s=0>EE6MZ8TiuaCM3p;mBi-yrgbTE;n&A7 zh8aT0w>pTtja|h!GoGuq3QxpZb6D880cZ?#>lA%FD`KD{HRXy%!gk}d=O?(4&Kd_u z7GfH+tD@WCd2vF=)caQhZUuc-DgYi`)TXRjB-jViSKFdeLohLwRe(q=-f&3z(ng$8 zg%~5Lz|PT3ttu*Pi-m>vSVk+JdL1z1AvEvy_BK;J%YA1g%Gr~a$z)%|p)T<7Y1|dG zUP<d6Kr*XSCxgGM@b3xf=332W4hvBZ-(`pCK^j_V3?>9*sJG#GkjGyXx<M%;ifQX9 zyM%D2?sVPO>oXK5^8#mO*tUL4e7?gSZbQxhatS42NN0*`Yr0n)qlx}gtc!+?D0^!n zq7HJjS2m9q-FNQu<gTtegwO2s{64KT=|#iHc^gh9BxxLb2n$kma0~bs3&>FRaCfY6 z{83ksm+ua5V`$9r<HRArr9{Dtl=y=~E%sjj$B$W!Dwku?=JXyLpkr}=5PzmyTw1s$ zDw3ycgO!7>I+G@5CX<~ajb+APZhxBm&h;D2|7kUcoIcn%kf;Z1gPpT7g5Kj=-6Fv~ z6U+I7NYeiFabh8Btg>6ERvPh0DZg%o4-qctdd<-U|Lxi~Ji|~41dL$?T3kC@%JW-* zOMo0PfupJQTNJH?7VNDiLBG_z&HC+}?h>!7SxRm_h@D-U+R>N8v+?N&clu-u!;`1i z_Z7Yz)O3XjdGq$*_uojKJwEqB-Nc7wR=jW>#jB9&XQJ^OdpkTk`cc3;AV1tEKNazN zw@}a6u)cr#KNXqrDdU(oT*rf3e1h<Y=eZcDM<%P6QjW1-N_l<NZO^<c?C(^Pl9w-X z7ZY^tVb41L)@p3dbYC3gZ{^Bc=$i$?fN+tbPaQ8tBRV`SF1l}lDTCgy{~A%_UA1Q9 T(Gf-|8fE_jMPl+Q`3e94Q~-)> literal 0 HcmV?d00001 diff --git a/tentacle/tentacle_server_installer b/tentacle/tentacle_server_installer new file mode 100755 index 0000000000..469ac326c3 --- /dev/null +++ b/tentacle/tentacle_server_installer @@ -0,0 +1,438 @@ +#!/bin/sh + +# Tentacle Server Installer +# Linux/FreeBSD Version (generic), for SuSe, Debian/Ubuntu and FreeBSD only +# other Linux distros could not work properly without modifications +# Please see http://www.pandorafms.org +# v1.0 Build 13062022 +# This code is licensed under GPL 2.0 license. +# ********************************************************************** + +PI_VERSION="7.0NG.762" +PI_BUILD="220613" + +MODE=$1 +if [ $# -gt 1 ]; then + shift +fi + +# Defaults +PREFIX=/usr +PANDORA_SPOOL=/var/spool/pandora +TENTACLE_SERVER=/etc/init.d/tentacle_serverd +TENTACLE_CFG_DIR=/etc/tentacle +TENTACLE_CFG_FILE=$TENTACLE_CFG_DIR/tentacle_server.conf +TENTACLE_CFG_FILE_DIST=conf/tentacle_server.conf.new +TENTACLE_INIT_SCRIPT=util/tentacle_serverd +PERL=perl +MANDIR=$PREFIX/share/man/man1 +INITDIR=/etc/init.d +WITHOUT_TENTACLE=0 + +# +# set_global_vars +# Check platform and set DISTRO, OS_VERSION and LINUX. +# Also, define some platform sepcific variables (e.g. PANDORA_RC_VAR for (Free|Net)BSD) +# and override some of defaults defined above if needed. +# +set_global_vars () { + # Default + LINUX=NO + OS_VERSION=`uname -r` + DISTRO=`uname -s` + + # set correct value for LINUX_DISTRO + case $DISTRO in + Linux) + # Default for Linux + LINUX=YES + DISTRO="GENERIC" + # Get Linux Distro type and version + # We assume we are on Linux unless told otherwise + if [ -f "/etc/SuSE-release" ] + then + OS_VERSION=`cat /etc/SuSE-release | grep VERSION | cut -f 3 -d " "` + DISTRO=SUSE + elif [ -f "/etc/lsb-release" ] && [ ! -f "/etc/redhat-release" ] + then + OS_VERSION=`cat /etc/lsb-release | grep DISTRIB_RELEASE | cut -f 2 -d "="` + DISTRO=UBUNTU + OS_VERSION="UBUNTU $OS_VERSION" + elif [ -f "/etc/debian_version" ] + then + OS_VERSION=`cat /etc/debian_version` + OS_VERSION="DEBIAN $OS_VERSION" + DISTRO=DEBIAN + elif [ -f "/etc/fedora-release" ] + then + OS_VERSION=`cat /etc/fedora-release | cut -f 4 -d " "` + OS_VERSION="FEDORA $OS_VERSION" + DISTRO=FEDORA + fi + ;; + Darwin|AIX) + # For future reference, Darwin doesn't have /etc/init.d but uses LaunchDaemons. + # AIX doesn't have /etc/init.d + ;; + SunOS) + # Some Solaris and other Unices don't have /etc/init.d, some have /usr/spool instead of /var/spool + DISTRO="Solaris" + ;; + FreeBSD) + PREFIX=/usr/local + TENTACLE_SERVER=$PREFIX/etc/rc.d/tentacle_server + TENTACLE_CFG_DIR=$PREFIX/etc/tentacle + TENTACLE_CFG_FILE=$TENTACLE_CFG_DIR/tentacle_server.conf + TENTACLE_INIT_SCRIPT=$DISTRO/tentacle_server + MANDIR=$PREFIX/man/man1 + INITDIR=$PREFIX/etc/rc.d + PERL=/usr/local/bin/perl + TENTACLE_RC_VAR="tentacle_server_enable" + ;; + NetBSD) + PREFIX=/usr/local + TENTACLE_CFG_DIR=$PREFIX/etc/tentacle + TENTACLE_CFG_FILE=$TENTACLE_CFG_DIR/tentacle_server.conf + TENTACLE_SERVER=/etc/rc.d/tentacle_server + TENTACLE_INIT_SCRIPT=$DISTRO/tentacle_server + PERL=/usr/pkg/bin/perl + INITDIR=/etc/rc.d + PANDORA_RC_VAR="pandora_server" + TENTACLE_RC_VAR="tentacle_server" + ;; + esac +} + +# +# install_startup_script [options...] SRC +# copy SRC into the $INITDIR and do additional required operation according to $DISTRO +# if $INITDIR is not set or empty, do nothing. +# If $DESTDIR is set, skip enabling service +# OPTIONS: +# -s SPRIO specify startup priority for service +# +install_startup_script () { + [ "$INITDIR" ] || return 1 + if [ "$1" = "-s" ] + then + SPRIO=$2 + shift;shift + fi + SRC=$1 + SCRIPT_NAME=`basename $SRC` + + echo "Copying the daemon script into $INITDIR" + [ -d $DESTDIR$INITDIR ] || mkdir -p $DESTDIR$INITDIR + cp $SRC $DESTDIR$INITDIR + + [ "$DESTDIR" ] && return + + case $DISTRO in + UBUNTU|DEBIAN) + echo "Linking startup script to /etc/rc2.d" + update-rc.d $SCRIPT_NAME defaults + ;; + SUSE) + echo "Creating startup daemons" + insserv $SCRIPT_NAME + ;; + FeeBSD|NetBSD) + chmod 555 $DESTDIR$INITDIR/$SCRIPT_NAME + ;; + *) + if [ "$LINUX" = YES ] + then + # Pandora FMS Server install (Other Distros) + INITLV=`grep '[0-9]:initdefault' /etc/inittab | cut -f 2 -d ':'` + : ${INITLV:=2} + echo "Linking startup script to /etc/rc.d/rc$INITLV.d/S$SPRIO$SCRIPT_NAME" + ln -s $INITDIR/$SCRIPT_NAME /etc/rc.d/rc$INITLV.d/S$SPRIO$SCRIPT_NAME + fi + ;; + esac +} + +install () { + set_global_vars + + FORCE=0 + + # parse options + while : + do + case $1 in + --force) FORCE=1;; + --destdir) DESTDIR=$2;shift;; + *) break;; + esac + shift + done + + if [ "$LINUX" = YES ] + then + echo "$DISTRO distribution detected" + else + echo "$DISTRO detected" + fi + + $PERL -v &> /dev/null + if [ $? != 0 ]; then + echo ' ' + echo 'Error, no PERL Interpeter found, please install perl on your system' + exit 1 + fi + + #Check dependenciaes. + if [ $FORCE -eq 0 ]; then + # Execute tools check + execute_cmd "ps --version" 'Checking dependencies: ps' "Error ps not found, please install procps" + execute_cmd "sudo --version" 'Checking dependencies: sudo' "Error sudo not found, please install sudo" + fi + + # install tentacle + $PERL Makefile.PL INSTALLMAN1DIR=none > output 2>&1 + #&& sleep 2 && cat output | grep "found" | wc -l + DEPENDENCIAS=`cat output | grep "found" | wc -l` + + if [ $DEPENDENCIAS -gt 0 ] && [ $FORCE -eq 0 ] + then + echo "You are missing the following dependencies" + echo " " + cat output | awk -F ": prerequisite" '{print $2}' | awk -F " " '{print $1}' + echo "The complete installation guide is at: https://pandorafms.com/docs/" + echo " " + rm output + exit 1 + fi + + echo "Installing binaries and libraries" + make + make DESTDIR=$DESTDIR install + + echo "Checking binaries at /usr/local/bin -> /usr/bin" + if [ ! -f "$DESTDIR/usr/bin/tentacle_server" ] + then + if [ ! -f "$DESTDIR/usr/local/bin/tentacle_server" ] + then + echo "ERROR compiling Tentacle Server from sources. Aborting" + exit 1 + fi + if [ "$DISTRO" != "FreeBSD" ] && [ "$DISTRO" != "NetBSD" ] + then + [ -d $DESTDIR$PREFIX/bin ] || mkdir -p $DESTDIR$PREFIX/bin + ln -s /usr/local/bin/tentacle_server $DESTDIR$PREFIX/bin + + fi + fi + + + echo "Creating common Pandora FMS directories" + id pandora 2> /dev/null + if [ $? -eq 0 ]; then + echo " " + echo "User pandora does exist, make sure the SSH directories are correct" + elif [ "$DESTDIR" ] + then + # chown can fail with fakeroot installation + echo "User 'pandora' does not exist. All chown operations may fail." + echo "You should manualy set proper ownership to $DESTDIR$PANDORA_SPOOL if needed." + echo + else + echo "Are you sure we can create a standard 'pandora' user locally? [y/N]" + read AREYOUSURE + if [ "$AREYOUSURE" = "y" ]; then + if [ "$DISTRO" = "FreeBSD" ] + then + echo "pandora:41121:::::Pandora FMS:/home/pandora:/usr/sbin/nologin:" | adduser -f - -w no 2> /dev/null + else + useradd pandora + mkdir /home/pandora 2> /dev/null + mkdir /home/pandora/.ssh 2> /dev/null + chown -R pandora /home/pandora + fi + else + echo "Please create the 'pandora' user manually according to your authentication scheme, then start again the installation" + echo "Aborting..." + exit 1 + fi + fi + + mkdir -p $DESTDIR$PANDORA_SPOOL/data_in 2> /dev/null + chmod 2770 $DESTDIR$PANDORA_SPOOL/data_in + mkdir $DESTDIR$PANDORA_SPOOL/data_in/conf 2> /dev/null + chmod 2770 $DESTDIR$PANDORA_SPOOL/data_in/conf + mkdir $DESTDIR$PANDORA_SPOOL/data_in/md5 2> /dev/null + chmod 2770 $DESTDIR$PANDORA_SPOOL/data_in/md5 + mkdir $DESTDIR$PANDORA_SPOOL/data_in/collections 2> /dev/null + chmod 2770 $DESTDIR$PANDORA_SPOOL/data_in/collections + mkdir $DESTDIR$PANDORA_SPOOL/data_in/netflow 2> /dev/null + chmod 2770 $DESTDIR$PANDORA_SPOOL/data_in/netflow + mkdir $DESTDIR$PANDORA_SPOOL/data_in/trans 2> /dev/null + chmod 2770 $DESTDIR$PANDORA_SPOOL/data_in/trans + mkdir $DESTDIR$PANDORA_SPOOL/data_in/commands 2> /dev/null + chmod 2770 $DESTDIR$PANDORA_SPOOL/data_in/commands + + + echo "Giving proper permission to /var/spool/pandora" + for group in "www-data" wwwrun www apache + do + IDGROUP=`id -g "$group" 2> /dev/null` + if [ $? -eq 0 ] + then + GROUPNAME=`grep ":$IDGROUP:" /etc/group | awk -F":" '{print $1}'` + break + fi + done + if [ -z "$GROUPNAME" ] + then + echo "No web server user found, some functionality might not perform correctly" + GROUPNAME=0 + fi + # when fakeroot installation, this can fail + chown -R pandora:$GROUPNAME $DESTDIR$PANDORA_SPOOL 2>/dev/null + + chown apache:$GROUPNAME $DESTDIR$PANDORA_SPOOL/data_in/customer_key 2>/dev/null + + # install tentacle_server + install_startup_script -s 80 $TENTACLE_INIT_SCRIPT + + # Create the directory to locate the Tentacle configuration file + echo "Creating setup Tentacle directory in $TENTACLE_CFG_DIR" + mkdir -p $DESTDIR$TENTACLE_CFG_DIR 2> /dev/null + if [ -f "$DESTDIR$TENTACLE_CFG_FILE" ] + then + echo cp $TENTACLE_CFG_FILE_DIST $DESTDIR$TENTACLE_CFG_DIR + cp $TENTACLE_CFG_FILE_DIST $DESTDIR$TENTACLE_CFG_DIR + else + echo cp $TENTACLE_CFG_FILE_DIST $DESTDIR$TENTACLE_CFG_FILE + cp $TENTACLE_CFG_FILE_DIST $DESTDIR$TENTACLE_CFG_FILE + chmod 774 $DESTDIR$TENTACLE_CFG_FILE + fi + + echo "Installing Tentacle Server manual" + [ -d $DESTDIR$MANDIR ] || mkdir -p $DESTDIR$MANDIR + cp man/man1/tentacle_server.1.gz $DESTDIR$MANDIR + + # Fix util paths + sed -i -e "s|directory.*|directory $DESTDIR$PANDORA_SPOOL/data_in|g" $DESTDIR$TENTACLE_CFG_FILE + sed -i -e "s|TENTACLE_PATH=\"/usr/bin\"|TENTACLE_PATH=$DESTDIR$PREFIX/bin|g" $DESTDIR$TENTACLE_SERVER + sed -i -e "s|^TENTACLE_CONFIG_FILE=.*|TENTACLE_CONFIG_FILE=$DESTDIR$TENTACLE_CFG_FILE|g" $DESTDIR$TENTACLE_SERVER + + echo "Tentacle Server installed" + + +} + +uninstall () { + set_global_vars + + # parse options + while : + do + case $1 in + --destdir) DESTDIR=$2;shift;; + *) break;; + esac + shift + done + + if [ "$LINUX" != "YES" ] && [ "$DISTRO" != "FreeBSD" ] && [ "$DISTRO" != "NetBSD" ] + then + echo "This is not a Linux-based distro. Uninstaller is currently not working for your OS" + exit 1 + fi + + + echo "Removing Tentacle Server" + if [ -d $DESTDIR$PANDORA_SPOOL/data_out ]; then + rm -Rf $DESTDIR$PANDORA_SPOOL/data_in + else + rm -Rf $DESTDIR$PANDORA_SPOOL + fi + + echo "If the user Pandora is not being used for any other operations, please delete using the following commands:" + if [ "$DISTRO" != "FreeBSD" ] || [ "$DISTRO" != "NetBSD" ] + then + echo " rmuser pandora" + else + echo " userdel pandora" + echo " rm -Rf /home/pandora/" + fi + + ## Just to clarify here. Some people (like me) are using the pandora user + ## for other purposes and/or using an LDAP-based user management + ## I would hate to have a script clear out this users' information without any notification + + + rm -f $DESTDIR$TENTACLE_CFG_FILE 2> /dev/null + rm -f "$DESTDIR$TENTACLE_CFG_FILE.new" 2> /dev/null + # Do not remove tentacle files if agent is still installed... + [ -e $DESTDIR$PREFIX/bin/pandora_agent ] || rm -f $DESTDIR$PREFIX/bin/tentacle_server 2> /dev/null + [ -e $DESTDIR$PREFIX/bin/pandora_agent ] || rm -f $DESTDIR$PREFIX/bin/tentacle_client 2> /dev/null + if [ "$DESTDIR" ] + then + rm -f $DESTDIR$TENTACLE_SERVER + elif [ "$DISTRO" = "UBUNTU" ] || [ "$DISTRO" = "DEBIAN" ] + then + update-rc.d -f tentacle_serverd remove + fi + + rm -f $DESTDIR/etc/rc2.d/S80tentacle_serverd 2> /dev/null + rm -f $DESTDIR/etc/rc.d/rc3.d/S80tentacle_serverd 2> /dev/null + + echo "Done" + echo $DESTDIR$TENTACLE_SERVER +} + +help () { + echo " --install To install Pandora FMS Servers on this system (You have to be root)" + echo " --uninstall To uninstall and remove Pandora FMS Servers on this System" + echo " " + echo " Additional second parameter (after --install) " + echo " " + echo " --force Ignore dependency problems and do the install" + echo " --destdir DIR Specify root directory for \"fakeroot\" installation" + echo " " +} + +execute_cmd () { + cmd="$1" + msg="$2" + + echo "$msg" + $cmd &>> /dev/null + if [ $? -ne 0 ]; then + echo "Fail" + [ "$3" ] && echo "$3" + echo "Error installing Tentacle server" + exit 1 + else + echo "Ok" + return 0 + fi +} + +##Main + +# Script banner at start +echo " " +echo "Tentacle Server Installer $PI_VERSION $PI_BUILD (c) 2008-2022 Artica ST" +echo "This program is licensed under GPL2 Terms. http://pandorafms.com" +echo " " + +case "$MODE" in + +'--install') + install "$@" + exit 0 + ;; + +'--uninstall') + uninstall "$@" + exit 0 + ;; + +*) + help +esac + diff --git a/tentacle/util/tentacle_serverd b/tentacle/util/tentacle_serverd new file mode 100755 index 0000000000..0c0f35ff97 --- /dev/null +++ b/tentacle/util/tentacle_serverd @@ -0,0 +1,185 @@ +#!/bin/bash +# Copyright (c) 2005-2010 Artica ST +# +# Author: Sancho Lerena <slerena@artica.es> 2006-2010 +# +# /etc/init.d/tentacle_server +# +# System startup script for Tentacle Server +# +# Comments to support chkconfig on RedHat Linux +# chkconfig: 2345 90 90 +# description: Tentacle Server startup script +# +# Comments to support LSB init script conventions +### BEGIN INIT INFO +# Provides: tentacle_server +# Required-Start: $network +# Should-Start: $syslog +# Required-Stop: $network +# Should-Stop: $network +# Default-Start: 2 3 5 +# Default-Stop: 0 1 6 +# Short-Description: Tentacle Server startup script +# Description: Tentacle Server startup script +### END INIT INFO + +if [ -x /lib/lsb/init-functions ]; then +. /lib/lsb/init-functions +fi + +# Uses a wait limit before sending a KILL signal, before trying to stop +# Pandora FMS server nicely. Some big systems need some time before close +# all pending tasks / threads. + +export MAXWAIT=60 + +# Check for SUSE status scripts +if [ -f /etc/rc.status ] +then + . /etc/rc.status + rc_reset +else + # Define part of rc functions for non-suse systems + function rc_status () { + RETVAL=$? + case $1 in + -v) RETVAL=0;; + esac + } + function rc_exit () { exit $RETVAL; } + function rc_failed () { RETVAL=${1:-1}; } + RETVAL=0 +fi + +function get_pid { + # This sets COLUMNS to XXX chars, because if command is run + # in a "strech" term, ps aux don't report more than COLUMNS + # characters and this will not work. + COLUMNS=300 + TENTACLE_PID=`ps -Af | grep "$TENTACLE_PATH$TENTACLE_DAEMON" | grep "$TENTACLE_CONFIG_FILE" | grep -v grep | tail -1 | awk '{ print $2 }'` + echo $TENTACLE_PID +} + +function get_all_pid { + # This sets COLUMNS to XXX chars, because if command is run + # in a "strech" term, ps aux don't report more than COLUMNS + # characters and this will not work. + COLUMNS=300 + TENTACLE_PIDS=`ps aux | grep "$TENTACLE_PATH$TENTACLE_DAEMON" | grep -v grep | awk '{ print $2 }'` + TENTACLE_PID="${TENTACLE_PIDS//\\n/' '}" + echo $TENTACLE_PID +} + +# Tentacle server settings +TENTACLE_DAEMON="tentacle_server" +TENTACLE_PATH="/usr/bin" +TENTACLE_USER="pandora" +TENTACLE_CONFIG_FILE="/etc/tentacle/tentacle_server.conf" +TENTACLE_EXT_OPTS="" + +# Set umask to 0002, because group MUST have access to write files to +# use remote file management on Pandora FMS Enterprise. + +umask 0007 + +# Main script +TENTACLE_OPTS="-F $TENTACLE_CONFIG_FILE $TENTACLE_EXT_OPTS" + +# Fix TENTACLE_PATH +case "$TENTACLE_PATH" in + *\/) + ;; + *) + TENTACLE_PATH="${TENTACLE_PATH}/" + ;; +esac + +if [ ! -f "${TENTACLE_PATH}$TENTACLE_DAEMON" ]; then + echo "Tentacle Server not found in ${TENTACLE_PATH}$TENTACLE_DAEMON" + rc_failed 5 # program is not installed + rc_exit +fi + +case "$1" in + start) + TENTACLE_PID=`get_pid` + if [ ! -z "$TENTACLE_PID" ]; then + echo "Tentacle Server is already running with PID $TENTACLE_PID" + rc_exit # running start on a service already running + fi + + # Init the tentacle process + sudo -u $TENTACLE_USER ${TENTACLE_PATH}$TENTACLE_DAEMON $TENTACLE_OPTS + sleep 1 + + TENTACLE_PID=`get_pid` + if [ ! -z "$TENTACLE_PID" ]; then + echo "Tentacle Server is now running with PID $TENTACLE_PID" + rc_status -v + else + echo "Tentacle Server could not be started." + echo "Verify that Tentacle port is not used." + rc_failed 7 # program not running + fi + + ;; + + stop) + TENTACLE_PID=`get_all_pid` + if [ -z "$TENTACLE_PID" ]; then + echo "Tentacle Server does not seem to be running" + rc_exit # running stop on a service already stopped or not running + else + kill $TENTACLE_PID + + COUNTER=0 + while [ $COUNTER -lt $MAXWAIT ] + do + _PID=`get_all_pid` + if [ "$_PID" != "$TENTACLE_PID" ] + # tentacle already stopped + then + COUNTER=$MAXWAIT + fi + COUNTER=`expr $COUNTER + 1` + sleep 1 + done + + if [ "$_PID" = "$TENTACLE_PID" ] + then + kill -9 $TENTACLE_PID > /dev/null 2>&1 + fi + + echo "Stopping Tentacle Server" + rc_status -v + fi + + ;; + + force-reload|restart) + $0 stop + sleep 1 + $0 start + rc_status + ;; + + status) + TENTACLE_PID=`get_pid` + if [ -z "$TENTACLE_PID" ]; then + echo "Tentacle Server is not running." + rc_failed 7 # program is not running + else + echo "Tentacle Server is running with PID $TENTACLE_PID." + rc_status + fi + + ;; + + *) + echo "Usage: $0 {start | stop | restart | status}" + exit 1 + ;; +esac + +rc_exit diff --git a/tentacle/util/tentacle_serverd.service b/tentacle/util/tentacle_serverd.service new file mode 100644 index 0000000000..fb6d2af2e3 --- /dev/null +++ b/tentacle/util/tentacle_serverd.service @@ -0,0 +1,14 @@ +[Unit] +Description=Tentacle server daemon +After=network-online.target +Requires=network.target + +[Service] +Type=forking +ExecStart=/usr/bin/tentacle_server -F /etc/tentacle/tentacle_server.conf +User=pandora +Restart=on-failure +RestartPreventExitStatus=1 + +[Install] +WantedBy=multi-user.target From c7b8c55284496a4b06aed7706811f557b8b74ea4 Mon Sep 17 00:00:00 2001 From: artica <artica.devel@gmail.com> Date: Tue, 14 Jun 2022 01:00:42 +0200 Subject: [PATCH 26/38] Auto-updated build strings. --- pandora_agents/unix/DEBIAN/control | 2 +- pandora_agents/unix/DEBIAN/make_deb_package.sh | 2 +- pandora_agents/unix/pandora_agent | 2 +- pandora_agents/unix/pandora_agent.redhat.spec | 2 +- pandora_agents/unix/pandora_agent.spec | 2 +- pandora_agents/unix/pandora_agent_installer | 2 +- pandora_agents/win32/installer/pandora.mpi | 2 +- pandora_agents/win32/pandora.cc | 2 +- pandora_agents/win32/versioninfo.rc | 2 +- pandora_console/DEBIAN/control | 2 +- pandora_console/DEBIAN/make_deb_package.sh | 2 +- pandora_console/include/config_process.php | 2 +- pandora_console/install.php | 2 +- pandora_console/pandora_console.redhat.spec | 2 +- pandora_console/pandora_console.rhel7.spec | 2 +- pandora_console/pandora_console.spec | 2 +- pandora_server/DEBIAN/control | 2 +- pandora_server/DEBIAN/make_deb_package.sh | 2 +- pandora_server/lib/PandoraFMS/Config.pm | 2 +- pandora_server/lib/PandoraFMS/PluginTools.pm | 2 +- pandora_server/pandora_server.redhat.spec | 2 +- pandora_server/pandora_server.spec | 2 +- pandora_server/pandora_server_installer | 2 +- pandora_server/util/pandora_db.pl | 2 +- pandora_server/util/pandora_manage.pl | 2 +- 25 files changed, 25 insertions(+), 25 deletions(-) diff --git a/pandora_agents/unix/DEBIAN/control b/pandora_agents/unix/DEBIAN/control index 77758e69fe..ad4eead89a 100644 --- a/pandora_agents/unix/DEBIAN/control +++ b/pandora_agents/unix/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-agent-unix -Version: 7.0NG.762-220613 +Version: 7.0NG.762-220614 Architecture: all Priority: optional Section: admin diff --git a/pandora_agents/unix/DEBIAN/make_deb_package.sh b/pandora_agents/unix/DEBIAN/make_deb_package.sh index f0a5d37893..25a646be50 100644 --- a/pandora_agents/unix/DEBIAN/make_deb_package.sh +++ b/pandora_agents/unix/DEBIAN/make_deb_package.sh @@ -14,7 +14,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -pandora_version="7.0NG.762-220613" +pandora_version="7.0NG.762-220614" echo "Test if you has the tools for to make the packages." whereis dpkg-deb | cut -d":" -f2 | grep dpkg-deb > /dev/null diff --git a/pandora_agents/unix/pandora_agent b/pandora_agents/unix/pandora_agent index 67a52c8cbe..8763ad999e 100755 --- a/pandora_agents/unix/pandora_agent +++ b/pandora_agents/unix/pandora_agent @@ -1015,7 +1015,7 @@ my $Sem = undef; my $ThreadSem = undef; use constant AGENT_VERSION => '7.0NG.762'; -use constant AGENT_BUILD => '220613'; +use constant AGENT_BUILD => '220614'; # Agent log default file size maximum and instances use constant DEFAULT_MAX_LOG_SIZE => 600000; diff --git a/pandora_agents/unix/pandora_agent.redhat.spec b/pandora_agents/unix/pandora_agent.redhat.spec index 6e19bc9abc..3dec167453 100644 --- a/pandora_agents/unix/pandora_agent.redhat.spec +++ b/pandora_agents/unix/pandora_agent.redhat.spec @@ -3,7 +3,7 @@ # %define name pandorafms_agent_unix %define version 7.0NG.762 -%define release 220613 +%define release 220614 Summary: Pandora FMS Linux agent, PERL version Name: %{name} diff --git a/pandora_agents/unix/pandora_agent.spec b/pandora_agents/unix/pandora_agent.spec index f6c87cb14c..1249b8e6e7 100644 --- a/pandora_agents/unix/pandora_agent.spec +++ b/pandora_agents/unix/pandora_agent.spec @@ -3,7 +3,7 @@ # %define name pandorafms_agent_unix %define version 7.0NG.762 -%define release 220613 +%define release 220614 Summary: Pandora FMS Linux agent, PERL version Name: %{name} diff --git a/pandora_agents/unix/pandora_agent_installer b/pandora_agents/unix/pandora_agent_installer index e1f22051f6..07f0a9babf 100755 --- a/pandora_agents/unix/pandora_agent_installer +++ b/pandora_agents/unix/pandora_agent_installer @@ -10,7 +10,7 @@ # ********************************************************************** PI_VERSION="7.0NG.762" -PI_BUILD="220613" +PI_BUILD="220614" OS_NAME=`uname -s` FORCE=0 diff --git a/pandora_agents/win32/installer/pandora.mpi b/pandora_agents/win32/installer/pandora.mpi index 567e8751c9..4d65f05a32 100644 --- a/pandora_agents/win32/installer/pandora.mpi +++ b/pandora_agents/win32/installer/pandora.mpi @@ -186,7 +186,7 @@ UpgradeApplicationID {} Version -{220613} +{220614} ViewReadme {Yes} diff --git a/pandora_agents/win32/pandora.cc b/pandora_agents/win32/pandora.cc index 28d4f93091..6a4d7782f9 100644 --- a/pandora_agents/win32/pandora.cc +++ b/pandora_agents/win32/pandora.cc @@ -30,7 +30,7 @@ using namespace Pandora; using namespace Pandora_Strutils; #define PATH_SIZE _MAX_PATH+1 -#define PANDORA_VERSION ("7.0NG.762 Build 220613") +#define PANDORA_VERSION ("7.0NG.762 Build 220614") string pandora_path; string pandora_dir; diff --git a/pandora_agents/win32/versioninfo.rc b/pandora_agents/win32/versioninfo.rc index c7990e794e..ca70a5662b 100644 --- a/pandora_agents/win32/versioninfo.rc +++ b/pandora_agents/win32/versioninfo.rc @@ -11,7 +11,7 @@ BEGIN VALUE "LegalCopyright", "Artica ST" VALUE "OriginalFilename", "PandoraAgent.exe" VALUE "ProductName", "Pandora FMS Windows Agent" - VALUE "ProductVersion", "(7.0NG.762(Build 220613))" + VALUE "ProductVersion", "(7.0NG.762(Build 220614))" VALUE "FileVersion", "1.0.0.0" END END diff --git a/pandora_console/DEBIAN/control b/pandora_console/DEBIAN/control index df0a3dc5c1..28ad21f54e 100644 --- a/pandora_console/DEBIAN/control +++ b/pandora_console/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-console -Version: 7.0NG.762-220613 +Version: 7.0NG.762-220614 Architecture: all Priority: optional Section: admin diff --git a/pandora_console/DEBIAN/make_deb_package.sh b/pandora_console/DEBIAN/make_deb_package.sh index 9f71fde1d6..af4c21ef4e 100644 --- a/pandora_console/DEBIAN/make_deb_package.sh +++ b/pandora_console/DEBIAN/make_deb_package.sh @@ -14,7 +14,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -pandora_version="7.0NG.762-220613" +pandora_version="7.0NG.762-220614" package_pear=0 package_pandora=1 diff --git a/pandora_console/include/config_process.php b/pandora_console/include/config_process.php index 21197bb7aa..b7d03fe4f4 100644 --- a/pandora_console/include/config_process.php +++ b/pandora_console/include/config_process.php @@ -20,7 +20,7 @@ /** * Pandora build version and version */ -$build_version = 'PC220613'; +$build_version = 'PC220614'; $pandora_version = 'v7.0NG.762'; // Do not overwrite default timezone set if defined. diff --git a/pandora_console/install.php b/pandora_console/install.php index 47a6e72997..6b3aeef58f 100644 --- a/pandora_console/install.php +++ b/pandora_console/install.php @@ -129,7 +129,7 @@ <div style='height: 10px'> <?php $version = '7.0NG.762'; - $build = '220613'; + $build = '220614'; $banner = "v$version Build $build"; error_reporting(0); diff --git a/pandora_console/pandora_console.redhat.spec b/pandora_console/pandora_console.redhat.spec index 5d3d25f936..ccc9b3922e 100644 --- a/pandora_console/pandora_console.redhat.spec +++ b/pandora_console/pandora_console.redhat.spec @@ -3,7 +3,7 @@ # %define name pandorafms_console %define version 7.0NG.762 -%define release 220613 +%define release 220614 # User and Group under which Apache is running %define httpd_name httpd diff --git a/pandora_console/pandora_console.rhel7.spec b/pandora_console/pandora_console.rhel7.spec index de2d2be11e..cc364d3d5d 100644 --- a/pandora_console/pandora_console.rhel7.spec +++ b/pandora_console/pandora_console.rhel7.spec @@ -3,7 +3,7 @@ # %define name pandorafms_console %define version 7.0NG.762 -%define release 220613 +%define release 220614 # User and Group under which Apache is running %define httpd_name httpd diff --git a/pandora_console/pandora_console.spec b/pandora_console/pandora_console.spec index a864c32583..d9f4fcdb85 100644 --- a/pandora_console/pandora_console.spec +++ b/pandora_console/pandora_console.spec @@ -3,7 +3,7 @@ # %define name pandorafms_console %define version 7.0NG.762 -%define release 220613 +%define release 220614 %define httpd_name httpd # User and Group under which Apache is running %define httpd_name apache2 diff --git a/pandora_server/DEBIAN/control b/pandora_server/DEBIAN/control index aa9e8a47ec..487239a2d6 100644 --- a/pandora_server/DEBIAN/control +++ b/pandora_server/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-server -Version: 7.0NG.762-220613 +Version: 7.0NG.762-220614 Architecture: all Priority: optional Section: admin diff --git a/pandora_server/DEBIAN/make_deb_package.sh b/pandora_server/DEBIAN/make_deb_package.sh index 27de524149..8102a1c5d8 100644 --- a/pandora_server/DEBIAN/make_deb_package.sh +++ b/pandora_server/DEBIAN/make_deb_package.sh @@ -14,7 +14,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -pandora_version="7.0NG.762-220613" +pandora_version="7.0NG.762-220614" package_cpan=0 package_pandora=1 diff --git a/pandora_server/lib/PandoraFMS/Config.pm b/pandora_server/lib/PandoraFMS/Config.pm index 57ea747870..8fec3e4bf4 100644 --- a/pandora_server/lib/PandoraFMS/Config.pm +++ b/pandora_server/lib/PandoraFMS/Config.pm @@ -46,7 +46,7 @@ our @EXPORT = qw( # version: Defines actual version of Pandora Server for this module only my $pandora_version = "7.0NG.762"; -my $pandora_build = "220613"; +my $pandora_build = "220614"; our $VERSION = $pandora_version." ".$pandora_build; # Setup hash diff --git a/pandora_server/lib/PandoraFMS/PluginTools.pm b/pandora_server/lib/PandoraFMS/PluginTools.pm index 0d6be46a1d..4a1afb0c36 100644 --- a/pandora_server/lib/PandoraFMS/PluginTools.pm +++ b/pandora_server/lib/PandoraFMS/PluginTools.pm @@ -34,7 +34,7 @@ our @ISA = qw(Exporter); # version: Defines actual version of Pandora Server for this module only my $pandora_version = "7.0NG.762"; -my $pandora_build = "220613"; +my $pandora_build = "220614"; our $VERSION = $pandora_version." ".$pandora_build; our %EXPORT_TAGS = ( 'all' => [ qw() ] ); diff --git a/pandora_server/pandora_server.redhat.spec b/pandora_server/pandora_server.redhat.spec index 820393a670..1b5ebbdc00 100644 --- a/pandora_server/pandora_server.redhat.spec +++ b/pandora_server/pandora_server.redhat.spec @@ -3,7 +3,7 @@ # %define name pandorafms_server %define version 7.0NG.762 -%define release 220613 +%define release 220614 Summary: Pandora FMS Server Name: %{name} diff --git a/pandora_server/pandora_server.spec b/pandora_server/pandora_server.spec index c929b470fa..785b404cb2 100644 --- a/pandora_server/pandora_server.spec +++ b/pandora_server/pandora_server.spec @@ -3,7 +3,7 @@ # %define name pandorafms_server %define version 7.0NG.762 -%define release 220613 +%define release 220614 Summary: Pandora FMS Server Name: %{name} diff --git a/pandora_server/pandora_server_installer b/pandora_server/pandora_server_installer index d9d76e8c91..5642aa9ec6 100755 --- a/pandora_server/pandora_server_installer +++ b/pandora_server/pandora_server_installer @@ -9,7 +9,7 @@ # ********************************************************************** PI_VERSION="7.0NG.762" -PI_BUILD="220613" +PI_BUILD="220614" MODE=$1 if [ $# -gt 1 ]; then diff --git a/pandora_server/util/pandora_db.pl b/pandora_server/util/pandora_db.pl index 185ecd2b86..c2cd3f5a11 100755 --- a/pandora_server/util/pandora_db.pl +++ b/pandora_server/util/pandora_db.pl @@ -35,7 +35,7 @@ use PandoraFMS::Config; use PandoraFMS::DB; # version: define current version -my $version = "7.0NG.762 Build 220613"; +my $version = "7.0NG.762 Build 220614"; # Pandora server configuration my %conf; diff --git a/pandora_server/util/pandora_manage.pl b/pandora_server/util/pandora_manage.pl index 59a75bb3a8..cffa3811ef 100755 --- a/pandora_server/util/pandora_manage.pl +++ b/pandora_server/util/pandora_manage.pl @@ -36,7 +36,7 @@ use Encode::Locale; Encode::Locale::decode_argv; # version: define current version -my $version = "7.0NG.762 Build 220613"; +my $version = "7.0NG.762 Build 220614"; # save program name for logging my $progname = basename($0); From c09d1334d6297408fd6ccd5327d712af86cf3baa Mon Sep 17 00:00:00 2001 From: "alejandro.campos@artica.es" <alejandro.campos@artica.es> Date: Tue, 14 Jun 2022 10:05:05 +0200 Subject: [PATCH 27/38] revert migrate file --- .../pandoradb_migrate_6.0_to_759.mysql.sql | 73 ------------------- 1 file changed, 73 deletions(-) diff --git a/pandora_console/extras/pandoradb_migrate_6.0_to_759.mysql.sql b/pandora_console/extras/pandoradb_migrate_6.0_to_759.mysql.sql index df09c2b8e4..242e7d42c6 100644 --- a/pandora_console/extras/pandoradb_migrate_6.0_to_759.mysql.sql +++ b/pandora_console/extras/pandoradb_migrate_6.0_to_759.mysql.sql @@ -838,8 +838,6 @@ CREATE TABLE IF NOT EXISTS `treport_template` ( PRIMARY KEY(`id_report`) ) ENGINE = InnoDB DEFAULT CHARSET=utf8; -ALTER TABLE `treport_template` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; - -- ----------------------------------------------------- -- Table `treport_content_template` -- ----------------------------------------------------- @@ -1056,7 +1054,6 @@ ALTER TABLE `tmetaconsole_event` ADD INDEX `tme_module_status_idx` (`module_stat ALTER TABLE `tmetaconsole_event` ADD INDEX `tme_criticity_idx` (`criticity`); ALTER TABLE `tmetaconsole_event` ADD INDEX `tme_agent_name_idx` (`agent_name`); ALTER TABLE `tmetaconsole_event` MODIFY `data` TINYTEXT default NULL; -ALTER TABLE `tmetaconsole_event` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0'; -- --------------------------------------------------------------------- -- Table `tmetaconsole_event_history` @@ -1107,8 +1104,6 @@ ALTER TABLE `tmetaconsole_event_history` ADD COLUMN `data` double(50,5) default ALTER TABLE `tmetaconsole_event_history` ADD COLUMN `module_status` int(4) NOT NULL default '0'; ALTER TABLE `tmetaconsole_event_history` ADD INDEX `tmeh_estado_idx` (`estado`); ALTER TABLE `tmetaconsole_event_history` ADD INDEX `tmeh_timestamp_idx` (`timestamp`); -ALTER TABLE `tmetaconsole_event_history` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0'; - -- --------------------------------------------------------------------- -- Table `textension_translate_string` -- --------------------------------------------------------------------- @@ -1459,7 +1454,6 @@ ALTER TABLE `talert_commands` MODIFY COLUMN `id_group` mediumint(8) unsigned NUL -- Table `tmap` -- --------------------------------------------------------------------- ALTER TABLE `tmap` MODIFY COLUMN `id_user` varchar(250) NOT NULL DEFAULT ''; -ALTER TABLE `tmap` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; -- --------------------------------------------------------------------- -- Table `ttag` @@ -1755,7 +1749,6 @@ ALTER TABLE tgraph ADD COLUMN `average_series` tinyint(1) UNSIGNED NOT NULL def ALTER TABLE tgraph ADD COLUMN `modules_series` tinyint(1) UNSIGNED NOT NULL default '0'; ALTER TABLE tgraph ADD COLUMN `fullscale` tinyint(1) UNSIGNED NOT NULL default '0'; ALTER TABLE `tgraph` MODIFY COLUMN `percentil` tinyint(1) unsigned NOT NULL DEFAULT '0'; -ALTER TABLE `tgraph` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; -- --------------------------------------------------------------------- -- Table `tnetflow_filter` @@ -1959,8 +1952,6 @@ CREATE TABLE IF NOT EXISTS `treset_pass_history` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -ALTER TABLE `treset_pass_history` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL; - -- --------------------------------------------------------------------- -- Table `tcontainer_item` -- --------------------------------------------------------------------- @@ -1987,9 +1978,6 @@ CREATE TABLE IF NOT EXISTS `tcontainer_item` ( ALTER TABLE tusuario add default_event_filter int(10) unsigned NOT NULL DEFAULT 0; --- --------------------------------------------------------------------- --- Table `treset_pass` --- --------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `treset_pass` ( `id` bigint(10) unsigned NOT NULL auto_increment, `id_user` varchar(100) NOT NULL default '', @@ -1998,8 +1986,6 @@ CREATE TABLE IF NOT EXISTS `treset_pass` ( PRIMARY KEY (`id`) )ENGINE=InnoDB DEFAULT CHARSET=utf8; -ALTER TABLE `treset_pass` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; - UPDATE tgis_map_connection SET conection_data = '{"type":"OSM","url":"http://tile.openstreetmap.org/${z}/${x}/${y}.png"}' where id_tmap_connection = 1; ALTER TABLE tpolicy_modules MODIFY post_process double(24,15) default 0; @@ -2061,7 +2047,6 @@ INSERT INTO `ttipo_modulo` VALUES -- Table `tdashboard` -- --------------------------------------------------------------------- ALTER TABLE `tdashboard` ADD COLUMN `cells_slideshow` TINYINT(1) NOT NULL default 0; -ALTER TABLE `tdashboard` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; -- --------------------------------------------------------------------- -- Table `tsnmp_filter` @@ -2371,7 +2356,6 @@ ALTER TABLE `treport` ADD COLUMN `orientation` varchar(25) NOT NULL default 'ver ALTER TABLE `treport` MODIFY COLUMN `hidden` tinyint(1) NULL DEFAULT '0' AFTER `non_interactive`; ALTER TABLE `treport` ADD COLUMN `cover_page_render` tinyint(1) NOT NULL DEFAULT 1; ALTER TABLE `treport` ADD COLUMN `index_render` tinyint(1) NOT NULL DEFAULT 1; -ALTER TABLE `treport` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; ALTER TABLE `trecon_task` ADD COLUMN `snmp_version` varchar(5) NOT NULL default '1'; ALTER TABLE `trecon_task` ADD COLUMN `snmp_auth_user` varchar(255) NOT NULL default ''; @@ -2409,8 +2393,6 @@ ALTER TABLE `tevento` ADD COLUMN `module_status` int(4) NOT NULL default '0'; ALTER TABLE `tevento` MODIFY `data` TINYTEXT default NULL; -ALTER TABLE `tevento` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0'; - -- --------------------------------------------------------------------- -- Table `tevent_extended` -- --------------------------------------------------------------------- @@ -2480,8 +2462,6 @@ CREATE TABLE IF NOT EXISTS `tuser_task_scheduled` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -ALTER TABLE `tuser_task_scheduled` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0'; - -- ----------------------------------------------------- -- Table `tnotification_source` -- ----------------------------------------------------- @@ -2521,8 +2501,6 @@ ALTER TABLE `tmensajes` ADD CONSTRAINT `tsource_fk` FOREIGN KEY (`id_source`) RE ALTER TABLE `tmensajes` DROP COLUMN `id_usuario_destino`, ADD UNIQUE INDEX `id_mensaje` (`id_mensaje`); -ALTER TABLE `tmensajes` MODIFY COLUMN `id_usuario_origen` VARCHAR(255) NOT NULL DEFAULT ''; - -- ---------------------------------------------------------------------- -- Table `tnotification_user` -- ---------------------------------------------------------------------- @@ -2818,7 +2796,6 @@ UPDATE `trecon_script` SET `description`='Specific Pandora FMS In -- Table `tusuario_perfil` -- --------------------------------------------------------------------- ALTER TABLE `tusuario_perfil` MODIFY COLUMN `no_hierarchy` tinyint(1) NOT NULL DEFAULT '0'; -ALTER TABLE `tusuario_perfil` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT ''; -- Extra tnetwork_component @@ -4376,53 +4353,3 @@ ALTER TABLE `tnotification_user` ADD CONSTRAINT `tnotification_user_ibfk_2` FORE ALTER TABLE `tnotification_source_user` ADD CONSTRAINT `tnotification_source_user_ibfk_2` FOREIGN KEY (`id_user`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE `tnotification_source_group_user` ADD CONSTRAINT `tnotification_source_group_user_ibfk_2` FOREIGN KEY (`id_user`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE `tvisual_console_elements_cache` ADD CONSTRAINT `tvisual_console_elements_cache_ibfk_3` FOREIGN KEY (`user_id`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE ON UPDATE CASCADE; - --- ---------------------------------------------------------------------- --- Table `tattachment` --- ---------------------------------------------------------------------- -ALTER TABLE `tattachment` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT ''; - --- ---------------------------------------------------------------------- --- Table `tincidencia` --- ---------------------------------------------------------------------- -ALTER TABLE `tincidencia` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT ''; - --- ---------------------------------------------------------------------- --- Table `tnota` --- ---------------------------------------------------------------------- -ALTER TABLE `tnota` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0'; - --- ---------------------------------------------------------------------- --- Table `tsesion` --- ---------------------------------------------------------------------- -ALTER TABLE `tsesion` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0'; - --- ---------------------------------------------------------------------- --- Table `ttrap` --- ---------------------------------------------------------------------- -ALTER TABLE `ttrap` MODIFY COLUMN `id_usuario` VARCHAR(255) DEFAULT ''; - --- ---------------------------------------------------------------------- --- Table `tplanned_downtime` --- ---------------------------------------------------------------------- -ALTER TABLE `tplanned_downtime` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT '0'; - --- ---------------------------------------------------------------------- --- Table `tnetwork_map` --- ---------------------------------------------------------------------- -ALTER TABLE `tnetwork_map` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL; - --- ---------------------------------------------------------------------- --- Table `tpassword_history` --- ---------------------------------------------------------------------- -ALTER TABLE `tpassword_history` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL; - --- ---------------------------------------------------------------------- --- Table `tupdate_journal` --- ---------------------------------------------------------------------- -ALTER TABLE `tupdate_journal` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; - --- ---------------------------------------------------------------------- --- Table `tbackup` --- ---------------------------------------------------------------------- -ALTER TABLE `tbackup` MODIFY COLUMN `id_user` VARCHAR(255) DEFAULT ''; From ac246aefb12573ec3af4d60820bd9b706d02d4ef Mon Sep 17 00:00:00 2001 From: "alejandro.campos@artica.es" <alejandro.campos@artica.es> Date: Tue, 14 Jun 2022 10:06:28 +0200 Subject: [PATCH 28/38] revert migrate file --- .../pandoradb_migrate_6.0_to_759.mysql.sql | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/pandora_console/extras/pandoradb_migrate_6.0_to_759.mysql.sql b/pandora_console/extras/pandoradb_migrate_6.0_to_759.mysql.sql index 242e7d42c6..df09c2b8e4 100644 --- a/pandora_console/extras/pandoradb_migrate_6.0_to_759.mysql.sql +++ b/pandora_console/extras/pandoradb_migrate_6.0_to_759.mysql.sql @@ -838,6 +838,8 @@ CREATE TABLE IF NOT EXISTS `treport_template` ( PRIMARY KEY(`id_report`) ) ENGINE = InnoDB DEFAULT CHARSET=utf8; +ALTER TABLE `treport_template` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; + -- ----------------------------------------------------- -- Table `treport_content_template` -- ----------------------------------------------------- @@ -1054,6 +1056,7 @@ ALTER TABLE `tmetaconsole_event` ADD INDEX `tme_module_status_idx` (`module_stat ALTER TABLE `tmetaconsole_event` ADD INDEX `tme_criticity_idx` (`criticity`); ALTER TABLE `tmetaconsole_event` ADD INDEX `tme_agent_name_idx` (`agent_name`); ALTER TABLE `tmetaconsole_event` MODIFY `data` TINYTEXT default NULL; +ALTER TABLE `tmetaconsole_event` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0'; -- --------------------------------------------------------------------- -- Table `tmetaconsole_event_history` @@ -1104,6 +1107,8 @@ ALTER TABLE `tmetaconsole_event_history` ADD COLUMN `data` double(50,5) default ALTER TABLE `tmetaconsole_event_history` ADD COLUMN `module_status` int(4) NOT NULL default '0'; ALTER TABLE `tmetaconsole_event_history` ADD INDEX `tmeh_estado_idx` (`estado`); ALTER TABLE `tmetaconsole_event_history` ADD INDEX `tmeh_timestamp_idx` (`timestamp`); +ALTER TABLE `tmetaconsole_event_history` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0'; + -- --------------------------------------------------------------------- -- Table `textension_translate_string` -- --------------------------------------------------------------------- @@ -1454,6 +1459,7 @@ ALTER TABLE `talert_commands` MODIFY COLUMN `id_group` mediumint(8) unsigned NUL -- Table `tmap` -- --------------------------------------------------------------------- ALTER TABLE `tmap` MODIFY COLUMN `id_user` varchar(250) NOT NULL DEFAULT ''; +ALTER TABLE `tmap` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; -- --------------------------------------------------------------------- -- Table `ttag` @@ -1749,6 +1755,7 @@ ALTER TABLE tgraph ADD COLUMN `average_series` tinyint(1) UNSIGNED NOT NULL def ALTER TABLE tgraph ADD COLUMN `modules_series` tinyint(1) UNSIGNED NOT NULL default '0'; ALTER TABLE tgraph ADD COLUMN `fullscale` tinyint(1) UNSIGNED NOT NULL default '0'; ALTER TABLE `tgraph` MODIFY COLUMN `percentil` tinyint(1) unsigned NOT NULL DEFAULT '0'; +ALTER TABLE `tgraph` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; -- --------------------------------------------------------------------- -- Table `tnetflow_filter` @@ -1952,6 +1959,8 @@ CREATE TABLE IF NOT EXISTS `treset_pass_history` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +ALTER TABLE `treset_pass_history` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL; + -- --------------------------------------------------------------------- -- Table `tcontainer_item` -- --------------------------------------------------------------------- @@ -1978,6 +1987,9 @@ CREATE TABLE IF NOT EXISTS `tcontainer_item` ( ALTER TABLE tusuario add default_event_filter int(10) unsigned NOT NULL DEFAULT 0; +-- --------------------------------------------------------------------- +-- Table `treset_pass` +-- --------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `treset_pass` ( `id` bigint(10) unsigned NOT NULL auto_increment, `id_user` varchar(100) NOT NULL default '', @@ -1986,6 +1998,8 @@ CREATE TABLE IF NOT EXISTS `treset_pass` ( PRIMARY KEY (`id`) )ENGINE=InnoDB DEFAULT CHARSET=utf8; +ALTER TABLE `treset_pass` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; + UPDATE tgis_map_connection SET conection_data = '{"type":"OSM","url":"http://tile.openstreetmap.org/${z}/${x}/${y}.png"}' where id_tmap_connection = 1; ALTER TABLE tpolicy_modules MODIFY post_process double(24,15) default 0; @@ -2047,6 +2061,7 @@ INSERT INTO `ttipo_modulo` VALUES -- Table `tdashboard` -- --------------------------------------------------------------------- ALTER TABLE `tdashboard` ADD COLUMN `cells_slideshow` TINYINT(1) NOT NULL default 0; +ALTER TABLE `tdashboard` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; -- --------------------------------------------------------------------- -- Table `tsnmp_filter` @@ -2356,6 +2371,7 @@ ALTER TABLE `treport` ADD COLUMN `orientation` varchar(25) NOT NULL default 'ver ALTER TABLE `treport` MODIFY COLUMN `hidden` tinyint(1) NULL DEFAULT '0' AFTER `non_interactive`; ALTER TABLE `treport` ADD COLUMN `cover_page_render` tinyint(1) NOT NULL DEFAULT 1; ALTER TABLE `treport` ADD COLUMN `index_render` tinyint(1) NOT NULL DEFAULT 1; +ALTER TABLE `treport` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; ALTER TABLE `trecon_task` ADD COLUMN `snmp_version` varchar(5) NOT NULL default '1'; ALTER TABLE `trecon_task` ADD COLUMN `snmp_auth_user` varchar(255) NOT NULL default ''; @@ -2393,6 +2409,8 @@ ALTER TABLE `tevento` ADD COLUMN `module_status` int(4) NOT NULL default '0'; ALTER TABLE `tevento` MODIFY `data` TINYTEXT default NULL; +ALTER TABLE `tevento` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0'; + -- --------------------------------------------------------------------- -- Table `tevent_extended` -- --------------------------------------------------------------------- @@ -2462,6 +2480,8 @@ CREATE TABLE IF NOT EXISTS `tuser_task_scheduled` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +ALTER TABLE `tuser_task_scheduled` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0'; + -- ----------------------------------------------------- -- Table `tnotification_source` -- ----------------------------------------------------- @@ -2501,6 +2521,8 @@ ALTER TABLE `tmensajes` ADD CONSTRAINT `tsource_fk` FOREIGN KEY (`id_source`) RE ALTER TABLE `tmensajes` DROP COLUMN `id_usuario_destino`, ADD UNIQUE INDEX `id_mensaje` (`id_mensaje`); +ALTER TABLE `tmensajes` MODIFY COLUMN `id_usuario_origen` VARCHAR(255) NOT NULL DEFAULT ''; + -- ---------------------------------------------------------------------- -- Table `tnotification_user` -- ---------------------------------------------------------------------- @@ -2796,6 +2818,7 @@ UPDATE `trecon_script` SET `description`='Specific Pandora FMS In -- Table `tusuario_perfil` -- --------------------------------------------------------------------- ALTER TABLE `tusuario_perfil` MODIFY COLUMN `no_hierarchy` tinyint(1) NOT NULL DEFAULT '0'; +ALTER TABLE `tusuario_perfil` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT ''; -- Extra tnetwork_component @@ -4353,3 +4376,53 @@ ALTER TABLE `tnotification_user` ADD CONSTRAINT `tnotification_user_ibfk_2` FORE ALTER TABLE `tnotification_source_user` ADD CONSTRAINT `tnotification_source_user_ibfk_2` FOREIGN KEY (`id_user`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE `tnotification_source_group_user` ADD CONSTRAINT `tnotification_source_group_user_ibfk_2` FOREIGN KEY (`id_user`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE `tvisual_console_elements_cache` ADD CONSTRAINT `tvisual_console_elements_cache_ibfk_3` FOREIGN KEY (`user_id`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE ON UPDATE CASCADE; + +-- ---------------------------------------------------------------------- +-- Table `tattachment` +-- ---------------------------------------------------------------------- +ALTER TABLE `tattachment` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT ''; + +-- ---------------------------------------------------------------------- +-- Table `tincidencia` +-- ---------------------------------------------------------------------- +ALTER TABLE `tincidencia` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT ''; + +-- ---------------------------------------------------------------------- +-- Table `tnota` +-- ---------------------------------------------------------------------- +ALTER TABLE `tnota` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0'; + +-- ---------------------------------------------------------------------- +-- Table `tsesion` +-- ---------------------------------------------------------------------- +ALTER TABLE `tsesion` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0'; + +-- ---------------------------------------------------------------------- +-- Table `ttrap` +-- ---------------------------------------------------------------------- +ALTER TABLE `ttrap` MODIFY COLUMN `id_usuario` VARCHAR(255) DEFAULT ''; + +-- ---------------------------------------------------------------------- +-- Table `tplanned_downtime` +-- ---------------------------------------------------------------------- +ALTER TABLE `tplanned_downtime` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT '0'; + +-- ---------------------------------------------------------------------- +-- Table `tnetwork_map` +-- ---------------------------------------------------------------------- +ALTER TABLE `tnetwork_map` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL; + +-- ---------------------------------------------------------------------- +-- Table `tpassword_history` +-- ---------------------------------------------------------------------- +ALTER TABLE `tpassword_history` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL; + +-- ---------------------------------------------------------------------- +-- Table `tupdate_journal` +-- ---------------------------------------------------------------------- +ALTER TABLE `tupdate_journal` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; + +-- ---------------------------------------------------------------------- +-- Table `tbackup` +-- ---------------------------------------------------------------------- +ALTER TABLE `tbackup` MODIFY COLUMN `id_user` VARCHAR(255) DEFAULT ''; From 4d3d684eebf1ce170e7c0346f07d5bfb78ef136d Mon Sep 17 00:00:00 2001 From: "alejandro.campos@artica.es" <alejandro.campos@artica.es> Date: Tue, 14 Jun 2022 10:15:15 +0200 Subject: [PATCH 29/38] revert migrate file --- .../pandoradb_migrate_6.0_to_759.mysql.sql | 73 ------------------- 1 file changed, 73 deletions(-) diff --git a/pandora_console/extras/pandoradb_migrate_6.0_to_759.mysql.sql b/pandora_console/extras/pandoradb_migrate_6.0_to_759.mysql.sql index df09c2b8e4..242e7d42c6 100644 --- a/pandora_console/extras/pandoradb_migrate_6.0_to_759.mysql.sql +++ b/pandora_console/extras/pandoradb_migrate_6.0_to_759.mysql.sql @@ -838,8 +838,6 @@ CREATE TABLE IF NOT EXISTS `treport_template` ( PRIMARY KEY(`id_report`) ) ENGINE = InnoDB DEFAULT CHARSET=utf8; -ALTER TABLE `treport_template` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; - -- ----------------------------------------------------- -- Table `treport_content_template` -- ----------------------------------------------------- @@ -1056,7 +1054,6 @@ ALTER TABLE `tmetaconsole_event` ADD INDEX `tme_module_status_idx` (`module_stat ALTER TABLE `tmetaconsole_event` ADD INDEX `tme_criticity_idx` (`criticity`); ALTER TABLE `tmetaconsole_event` ADD INDEX `tme_agent_name_idx` (`agent_name`); ALTER TABLE `tmetaconsole_event` MODIFY `data` TINYTEXT default NULL; -ALTER TABLE `tmetaconsole_event` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0'; -- --------------------------------------------------------------------- -- Table `tmetaconsole_event_history` @@ -1107,8 +1104,6 @@ ALTER TABLE `tmetaconsole_event_history` ADD COLUMN `data` double(50,5) default ALTER TABLE `tmetaconsole_event_history` ADD COLUMN `module_status` int(4) NOT NULL default '0'; ALTER TABLE `tmetaconsole_event_history` ADD INDEX `tmeh_estado_idx` (`estado`); ALTER TABLE `tmetaconsole_event_history` ADD INDEX `tmeh_timestamp_idx` (`timestamp`); -ALTER TABLE `tmetaconsole_event_history` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0'; - -- --------------------------------------------------------------------- -- Table `textension_translate_string` -- --------------------------------------------------------------------- @@ -1459,7 +1454,6 @@ ALTER TABLE `talert_commands` MODIFY COLUMN `id_group` mediumint(8) unsigned NUL -- Table `tmap` -- --------------------------------------------------------------------- ALTER TABLE `tmap` MODIFY COLUMN `id_user` varchar(250) NOT NULL DEFAULT ''; -ALTER TABLE `tmap` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; -- --------------------------------------------------------------------- -- Table `ttag` @@ -1755,7 +1749,6 @@ ALTER TABLE tgraph ADD COLUMN `average_series` tinyint(1) UNSIGNED NOT NULL def ALTER TABLE tgraph ADD COLUMN `modules_series` tinyint(1) UNSIGNED NOT NULL default '0'; ALTER TABLE tgraph ADD COLUMN `fullscale` tinyint(1) UNSIGNED NOT NULL default '0'; ALTER TABLE `tgraph` MODIFY COLUMN `percentil` tinyint(1) unsigned NOT NULL DEFAULT '0'; -ALTER TABLE `tgraph` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; -- --------------------------------------------------------------------- -- Table `tnetflow_filter` @@ -1959,8 +1952,6 @@ CREATE TABLE IF NOT EXISTS `treset_pass_history` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -ALTER TABLE `treset_pass_history` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL; - -- --------------------------------------------------------------------- -- Table `tcontainer_item` -- --------------------------------------------------------------------- @@ -1987,9 +1978,6 @@ CREATE TABLE IF NOT EXISTS `tcontainer_item` ( ALTER TABLE tusuario add default_event_filter int(10) unsigned NOT NULL DEFAULT 0; --- --------------------------------------------------------------------- --- Table `treset_pass` --- --------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `treset_pass` ( `id` bigint(10) unsigned NOT NULL auto_increment, `id_user` varchar(100) NOT NULL default '', @@ -1998,8 +1986,6 @@ CREATE TABLE IF NOT EXISTS `treset_pass` ( PRIMARY KEY (`id`) )ENGINE=InnoDB DEFAULT CHARSET=utf8; -ALTER TABLE `treset_pass` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; - UPDATE tgis_map_connection SET conection_data = '{"type":"OSM","url":"http://tile.openstreetmap.org/${z}/${x}/${y}.png"}' where id_tmap_connection = 1; ALTER TABLE tpolicy_modules MODIFY post_process double(24,15) default 0; @@ -2061,7 +2047,6 @@ INSERT INTO `ttipo_modulo` VALUES -- Table `tdashboard` -- --------------------------------------------------------------------- ALTER TABLE `tdashboard` ADD COLUMN `cells_slideshow` TINYINT(1) NOT NULL default 0; -ALTER TABLE `tdashboard` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; -- --------------------------------------------------------------------- -- Table `tsnmp_filter` @@ -2371,7 +2356,6 @@ ALTER TABLE `treport` ADD COLUMN `orientation` varchar(25) NOT NULL default 'ver ALTER TABLE `treport` MODIFY COLUMN `hidden` tinyint(1) NULL DEFAULT '0' AFTER `non_interactive`; ALTER TABLE `treport` ADD COLUMN `cover_page_render` tinyint(1) NOT NULL DEFAULT 1; ALTER TABLE `treport` ADD COLUMN `index_render` tinyint(1) NOT NULL DEFAULT 1; -ALTER TABLE `treport` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; ALTER TABLE `trecon_task` ADD COLUMN `snmp_version` varchar(5) NOT NULL default '1'; ALTER TABLE `trecon_task` ADD COLUMN `snmp_auth_user` varchar(255) NOT NULL default ''; @@ -2409,8 +2393,6 @@ ALTER TABLE `tevento` ADD COLUMN `module_status` int(4) NOT NULL default '0'; ALTER TABLE `tevento` MODIFY `data` TINYTEXT default NULL; -ALTER TABLE `tevento` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0'; - -- --------------------------------------------------------------------- -- Table `tevent_extended` -- --------------------------------------------------------------------- @@ -2480,8 +2462,6 @@ CREATE TABLE IF NOT EXISTS `tuser_task_scheduled` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -ALTER TABLE `tuser_task_scheduled` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0'; - -- ----------------------------------------------------- -- Table `tnotification_source` -- ----------------------------------------------------- @@ -2521,8 +2501,6 @@ ALTER TABLE `tmensajes` ADD CONSTRAINT `tsource_fk` FOREIGN KEY (`id_source`) RE ALTER TABLE `tmensajes` DROP COLUMN `id_usuario_destino`, ADD UNIQUE INDEX `id_mensaje` (`id_mensaje`); -ALTER TABLE `tmensajes` MODIFY COLUMN `id_usuario_origen` VARCHAR(255) NOT NULL DEFAULT ''; - -- ---------------------------------------------------------------------- -- Table `tnotification_user` -- ---------------------------------------------------------------------- @@ -2818,7 +2796,6 @@ UPDATE `trecon_script` SET `description`='Specific Pandora FMS In -- Table `tusuario_perfil` -- --------------------------------------------------------------------- ALTER TABLE `tusuario_perfil` MODIFY COLUMN `no_hierarchy` tinyint(1) NOT NULL DEFAULT '0'; -ALTER TABLE `tusuario_perfil` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT ''; -- Extra tnetwork_component @@ -4376,53 +4353,3 @@ ALTER TABLE `tnotification_user` ADD CONSTRAINT `tnotification_user_ibfk_2` FORE ALTER TABLE `tnotification_source_user` ADD CONSTRAINT `tnotification_source_user_ibfk_2` FOREIGN KEY (`id_user`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE `tnotification_source_group_user` ADD CONSTRAINT `tnotification_source_group_user_ibfk_2` FOREIGN KEY (`id_user`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE `tvisual_console_elements_cache` ADD CONSTRAINT `tvisual_console_elements_cache_ibfk_3` FOREIGN KEY (`user_id`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE ON UPDATE CASCADE; - --- ---------------------------------------------------------------------- --- Table `tattachment` --- ---------------------------------------------------------------------- -ALTER TABLE `tattachment` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT ''; - --- ---------------------------------------------------------------------- --- Table `tincidencia` --- ---------------------------------------------------------------------- -ALTER TABLE `tincidencia` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT ''; - --- ---------------------------------------------------------------------- --- Table `tnota` --- ---------------------------------------------------------------------- -ALTER TABLE `tnota` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0'; - --- ---------------------------------------------------------------------- --- Table `tsesion` --- ---------------------------------------------------------------------- -ALTER TABLE `tsesion` MODIFY COLUMN `id_usuario` VARCHAR(255) NOT NULL DEFAULT '0'; - --- ---------------------------------------------------------------------- --- Table `ttrap` --- ---------------------------------------------------------------------- -ALTER TABLE `ttrap` MODIFY COLUMN `id_usuario` VARCHAR(255) DEFAULT ''; - --- ---------------------------------------------------------------------- --- Table `tplanned_downtime` --- ---------------------------------------------------------------------- -ALTER TABLE `tplanned_downtime` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT '0'; - --- ---------------------------------------------------------------------- --- Table `tnetwork_map` --- ---------------------------------------------------------------------- -ALTER TABLE `tnetwork_map` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL; - --- ---------------------------------------------------------------------- --- Table `tpassword_history` --- ---------------------------------------------------------------------- -ALTER TABLE `tpassword_history` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL; - --- ---------------------------------------------------------------------- --- Table `tupdate_journal` --- ---------------------------------------------------------------------- -ALTER TABLE `tupdate_journal` MODIFY COLUMN `id_user` VARCHAR(255) NOT NULL DEFAULT ''; - --- ---------------------------------------------------------------------- --- Table `tbackup` --- ---------------------------------------------------------------------- -ALTER TABLE `tbackup` MODIFY COLUMN `id_user` VARCHAR(255) DEFAULT ''; From ec7a2f89bd5fc9f72d65b69cdd0e88d54ddaba32 Mon Sep 17 00:00:00 2001 From: "alejandro.campos@artica.es" <alejandro.campos@artica.es> Date: Tue, 14 Jun 2022 10:17:43 +0200 Subject: [PATCH 30/38] revert migrate file --- .../extras/pandoradb_migrate_6.0_to_759.mysql.sql | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/pandora_console/extras/pandoradb_migrate_6.0_to_759.mysql.sql b/pandora_console/extras/pandoradb_migrate_6.0_to_759.mysql.sql index 242e7d42c6..ca68a5472a 100644 --- a/pandora_console/extras/pandoradb_migrate_6.0_to_759.mysql.sql +++ b/pandora_console/extras/pandoradb_migrate_6.0_to_759.mysql.sql @@ -4338,18 +4338,3 @@ ALTER TABLE `talert_special_days` DROP COLUMN `same_day`; ALTER TABLE `talert_special_days` ADD FOREIGN KEY (`id_calendar`) REFERENCES `talert_calendar`(`id`) ON DELETE CASCADE ON UPDATE CASCADE; UPDATE `tconfig` c1 JOIN (select count(*) as n FROM `tconfig` c2 WHERE (c2.`token` = "node_metaconsole" AND c2.`value` = 1) OR (c2.`token` = "centralized_management" AND c2.`value` = 1) ) v SET c1. `value` = 0 WHERE c1.token = "autocreate_remote_users" AND v.n = 2; - --- ---------------------------------------------------------------------- --- Table `tusuario` --- ---------------------------------------------------------------------- -ALTER TABLE `tuser_double_auth` DROP FOREIGN KEY `tuser_double_auth_ibfk_1`, MODIFY `id_user` VARCHAR(255) NOT NULL; -ALTER TABLE `tnotification_user` DROP FOREIGN KEY `tnotification_user_ibfk_2`, MODIFY `id_user` VARCHAR(255) NOT NULL; -ALTER TABLE `tnotification_source_user` DROP FOREIGN KEY `tnotification_source_user_ibfk_2`, MODIFY `id_user` VARCHAR(255) NOT NULL; -ALTER TABLE `tnotification_source_group_user` DROP FOREIGN KEY `tnotification_source_group_user_ibfk_2`, MODIFY `id_user` VARCHAR(255) NOT NULL; -ALTER TABLE `tvisual_console_elements_cache` DROP FOREIGN KEY `tvisual_console_elements_cache_ibfk_3`, MODIFY `user_id` VARCHAR(255) DEFAULT NULL; -ALTER TABLE `tusuario` MODIFY `id_user` VARCHAR(255) NOT NULL DEFAULT '0'; -ALTER TABLE `tuser_double_auth` ADD CONSTRAINT `tuser_double_auth_ibfk_1` FOREIGN KEY (`id_user`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE; -ALTER TABLE `tnotification_user` ADD CONSTRAINT `tnotification_user_ibfk_2` FOREIGN KEY (`id_user`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE ON UPDATE CASCADE; -ALTER TABLE `tnotification_source_user` ADD CONSTRAINT `tnotification_source_user_ibfk_2` FOREIGN KEY (`id_user`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE ON UPDATE CASCADE; -ALTER TABLE `tnotification_source_group_user` ADD CONSTRAINT `tnotification_source_group_user_ibfk_2` FOREIGN KEY (`id_user`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE ON UPDATE CASCADE; -ALTER TABLE `tvisual_console_elements_cache` ADD CONSTRAINT `tvisual_console_elements_cache_ibfk_3` FOREIGN KEY (`user_id`) REFERENCES `tusuario` (`id_user`) ON DELETE CASCADE ON UPDATE CASCADE; From 838cde88650a7aca5a8467039a06eba329ad6e7d Mon Sep 17 00:00:00 2001 From: Rafael Ameijeiras <rafael.ameijeiras@artica.es> Date: Tue, 14 Jun 2022 12:43:43 +0200 Subject: [PATCH 31/38] Adding dependencies check for centos7/el8 --- tentacle/tentacle_server_installer | 52 ++++++------------------------ 1 file changed, 9 insertions(+), 43 deletions(-) diff --git a/tentacle/tentacle_server_installer b/tentacle/tentacle_server_installer index 469ac326c3..176a4743e5 100755 --- a/tentacle/tentacle_server_installer +++ b/tentacle/tentacle_server_installer @@ -121,7 +121,7 @@ install_startup_script () { SRC=$1 SCRIPT_NAME=`basename $SRC` - echo "Copying the daemon script into $INITDIR" + echo "Copying the daemon script into $DESTDIR$INITDIR" [ -d $DESTDIR$INITDIR ] || mkdir -p $DESTDIR$INITDIR cp $SRC $DESTDIR$INITDIR @@ -187,56 +187,22 @@ install () { # Execute tools check execute_cmd "ps --version" 'Checking dependencies: ps' "Error ps not found, please install procps" execute_cmd "sudo --version" 'Checking dependencies: sudo' "Error sudo not found, please install sudo" + execute_cmd "perl -MIO::Compress::Zip -le 'pass'" 'Checking dependencies: perl IO::Compress' "Error perl IO::Compress not found, please install perl IO::Compress" fi # install tentacle - $PERL Makefile.PL INSTALLMAN1DIR=none > output 2>&1 - #&& sleep 2 && cat output | grep "found" | wc -l - DEPENDENCIAS=`cat output | grep "found" | wc -l` + [ -d $DESTDIR$PREFIX/bin/ ] || mkdir -p $DESTDIR$PREFIX/bin/ + echo ">Installing the tentacle_server binary to $DESTDIR$PREFIX/bin/..." + cp -f tentacle_server "$DESTDIR$PREFIX/bin/" - if [ $DEPENDENCIAS -gt 0 ] && [ $FORCE -eq 0 ] - then - echo "You are missing the following dependencies" - echo " " - cat output | awk -F ": prerequisite" '{print $2}' | awk -F " " '{print $1}' - echo "The complete installation guide is at: https://pandorafms.com/docs/" - echo " " - rm output - exit 1 - fi - - echo "Installing binaries and libraries" - make - make DESTDIR=$DESTDIR install - - echo "Checking binaries at /usr/local/bin -> /usr/bin" - if [ ! -f "$DESTDIR/usr/bin/tentacle_server" ] - then - if [ ! -f "$DESTDIR/usr/local/bin/tentacle_server" ] - then - echo "ERROR compiling Tentacle Server from sources. Aborting" - exit 1 - fi - if [ "$DISTRO" != "FreeBSD" ] && [ "$DISTRO" != "NetBSD" ] - then - [ -d $DESTDIR$PREFIX/bin ] || mkdir -p $DESTDIR$PREFIX/bin - ln -s /usr/local/bin/tentacle_server $DESTDIR$PREFIX/bin - - fi - fi - + echo ">Installing the tentacle_client binary to $DESTDIR$PREFIX/bin/..." + cp -f tentacle_client "$DESTDIR$PREFIX/bin/" echo "Creating common Pandora FMS directories" id pandora 2> /dev/null if [ $? -eq 0 ]; then echo " " echo "User pandora does exist, make sure the SSH directories are correct" - elif [ "$DESTDIR" ] - then - # chown can fail with fakeroot installation - echo "User 'pandora' does not exist. All chown operations may fail." - echo "You should manualy set proper ownership to $DESTDIR$PANDORA_SPOOL if needed." - echo else echo "Are you sure we can create a standard 'pandora' user locally? [y/N]" read AREYOUSURE @@ -273,7 +239,7 @@ install () { chmod 2770 $DESTDIR$PANDORA_SPOOL/data_in/commands - echo "Giving proper permission to /var/spool/pandora" + echo "Giving proper permission to $DESTDIR$PANDORA_SPOOL/" for group in "www-data" wwwrun www apache do IDGROUP=`id -g "$group" 2> /dev/null` @@ -297,7 +263,7 @@ install () { install_startup_script -s 80 $TENTACLE_INIT_SCRIPT # Create the directory to locate the Tentacle configuration file - echo "Creating setup Tentacle directory in $TENTACLE_CFG_DIR" + echo "Creating setup Tentacle directory in $DESTDIR$TENTACLE_CFG_DIR" mkdir -p $DESTDIR$TENTACLE_CFG_DIR 2> /dev/null if [ -f "$DESTDIR$TENTACLE_CFG_FILE" ] then From 30fd072cb96f2482b8d512d217f8bce36d695dea Mon Sep 17 00:00:00 2001 From: Rafael Ameijeiras <rafael.ameijeiras@artica.es> Date: Tue, 14 Jun 2022 16:51:03 +0200 Subject: [PATCH 32/38] Adding dependencies to pandorafms rpm packages --- pandora_console/pandora_console.redhat.spec | 1 + 1 file changed, 1 insertion(+) diff --git a/pandora_console/pandora_console.redhat.spec b/pandora_console/pandora_console.redhat.spec index ccc9b3922e..73f7cfca74 100644 --- a/pandora_console/pandora_console.redhat.spec +++ b/pandora_console/pandora_console.redhat.spec @@ -31,6 +31,7 @@ Requires: php-gd, php-ldap, php-snmp, php-session, php-gettext Requires: php-mysqlnd, php-mbstring, php-zip, php-zlib, php-curl Requires: xorg-x11-fonts-75dpi, xorg-x11-fonts-misc, php-pecl-zip Requires: graphviz +Requires: openldap-clients libzstd expect Provides: %{name}-%{version} From 26038b6aaa2893b622e3b1044e90db27896ee4c0 Mon Sep 17 00:00:00 2001 From: Rafael Ameijeiras <rafael.ameijeiras@artica.es> Date: Tue, 14 Jun 2022 16:55:25 +0200 Subject: [PATCH 33/38] Adding dependencies to pandorafms rpm packages --- pandora_console/pandora_console.redhat.spec | 2 +- pandora_server/pandora_server.redhat.spec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pandora_console/pandora_console.redhat.spec b/pandora_console/pandora_console.redhat.spec index 73f7cfca74..0d00df75ab 100644 --- a/pandora_console/pandora_console.redhat.spec +++ b/pandora_console/pandora_console.redhat.spec @@ -31,7 +31,7 @@ Requires: php-gd, php-ldap, php-snmp, php-session, php-gettext Requires: php-mysqlnd, php-mbstring, php-zip, php-zlib, php-curl Requires: xorg-x11-fonts-75dpi, xorg-x11-fonts-misc, php-pecl-zip Requires: graphviz -Requires: openldap-clients libzstd expect +Requires: openldap-clients libzstd Provides: %{name}-%{version} diff --git a/pandora_server/pandora_server.redhat.spec b/pandora_server/pandora_server.redhat.spec index 1b5ebbdc00..41cce7f5f1 100644 --- a/pandora_server/pandora_server.redhat.spec +++ b/pandora_server/pandora_server.redhat.spec @@ -30,7 +30,7 @@ Requires: perl(NetAddr::IP) net-snmp net-tools Requires: perl(IO::Socket::INET6) perl(IO::Socket::SSL) perl(Net::Telnet) Requires: fping nmap sudo perl(JSON) Requires: perl(Time::HiRes) perl(Encode::Locale) -Requires: perl perl(Sys::Syslog) perl(HTML::Entities) perl(Geo::IP) +Requires: perl perl(Sys::Syslog) perl(HTML::Entities) perl(Geo::IP) expect %description Pandora FMS is a monitoring system for big IT environments. It uses remote tests, or local agents to grab information. Pandora supports all standard OS (Linux, AIX, HP-UX, Solaris and Windows XP,2000/2003), and support multiple setups in HA enviroments. From 20e1cdd9a77a903014e651f187c5653dcdcb0f1d Mon Sep 17 00:00:00 2001 From: Rafael Ameijeiras <rafael.ameijeiras@artica.es> Date: Tue, 14 Jun 2022 17:23:51 +0200 Subject: [PATCH 34/38] Adding dependencies to online installation tools --- extras/deploy-scripts/pandora_deploy_community.sh | 2 ++ extras/deploy-scripts/pandora_deploy_community_el8.sh | 2 ++ 2 files changed, 4 insertions(+) diff --git a/extras/deploy-scripts/pandora_deploy_community.sh b/extras/deploy-scripts/pandora_deploy_community.sh index 87e4bb4b35..a0f08822e1 100644 --- a/extras/deploy-scripts/pandora_deploy_community.sh +++ b/extras/deploy-scripts/pandora_deploy_community.sh @@ -256,6 +256,8 @@ console_dependencies=" \ poppler-data \ php-yaml \ mod_ssl \ + libzstd \ + openldap-clients \ http://firefly.artica.es/centos8/phantomjs-2.1.1-1.el7.x86_64.rpm" execute_cmd "yum install -y $console_dependencies" "Installing Pandora FMS Console dependencies" diff --git a/extras/deploy-scripts/pandora_deploy_community_el8.sh b/extras/deploy-scripts/pandora_deploy_community_el8.sh index c8c7561ffc..5b549a2933 100644 --- a/extras/deploy-scripts/pandora_deploy_community_el8.sh +++ b/extras/deploy-scripts/pandora_deploy_community_el8.sh @@ -307,6 +307,8 @@ console_dependencies=" \ poppler-data \ php-yaml \ mod_ssl \ + libzstd \ + openldap-clients \ http://firefly.artica.es/centos8/perl-Net-Telnet-3.04-1.el8.noarch.rpm \ http://firefly.artica.es/centos7/wmic-1.4-1.el7.x86_64.rpm \ http://firefly.artica.es/centos8/phantomjs-2.1.1-1.el7.x86_64.rpm" From 3ee1ba0bbcf07e7bc08ad06dce2538e71eb360ab Mon Sep 17 00:00:00 2001 From: artica <artica.devel@gmail.com> Date: Wed, 15 Jun 2022 01:00:16 +0200 Subject: [PATCH 35/38] Auto-updated build strings. --- pandora_agents/unix/DEBIAN/control | 2 +- pandora_agents/unix/DEBIAN/make_deb_package.sh | 2 +- pandora_agents/unix/pandora_agent | 2 +- pandora_agents/unix/pandora_agent.redhat.spec | 2 +- pandora_agents/unix/pandora_agent.spec | 2 +- pandora_agents/unix/pandora_agent_installer | 2 +- pandora_agents/win32/installer/pandora.mpi | 2 +- pandora_agents/win32/pandora.cc | 2 +- pandora_agents/win32/versioninfo.rc | 2 +- pandora_console/DEBIAN/control | 2 +- pandora_console/DEBIAN/make_deb_package.sh | 2 +- pandora_console/include/config_process.php | 2 +- pandora_console/install.php | 2 +- pandora_console/pandora_console.redhat.spec | 2 +- pandora_console/pandora_console.rhel7.spec | 2 +- pandora_console/pandora_console.spec | 2 +- pandora_server/DEBIAN/control | 2 +- pandora_server/DEBIAN/make_deb_package.sh | 2 +- pandora_server/lib/PandoraFMS/Config.pm | 2 +- pandora_server/lib/PandoraFMS/PluginTools.pm | 2 +- pandora_server/pandora_server.redhat.spec | 2 +- pandora_server/pandora_server.spec | 2 +- pandora_server/pandora_server_installer | 2 +- pandora_server/util/pandora_db.pl | 2 +- pandora_server/util/pandora_manage.pl | 2 +- 25 files changed, 25 insertions(+), 25 deletions(-) diff --git a/pandora_agents/unix/DEBIAN/control b/pandora_agents/unix/DEBIAN/control index ad4eead89a..119f59a1e4 100644 --- a/pandora_agents/unix/DEBIAN/control +++ b/pandora_agents/unix/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-agent-unix -Version: 7.0NG.762-220614 +Version: 7.0NG.762-220615 Architecture: all Priority: optional Section: admin diff --git a/pandora_agents/unix/DEBIAN/make_deb_package.sh b/pandora_agents/unix/DEBIAN/make_deb_package.sh index 25a646be50..8c9841cbb7 100644 --- a/pandora_agents/unix/DEBIAN/make_deb_package.sh +++ b/pandora_agents/unix/DEBIAN/make_deb_package.sh @@ -14,7 +14,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -pandora_version="7.0NG.762-220614" +pandora_version="7.0NG.762-220615" echo "Test if you has the tools for to make the packages." whereis dpkg-deb | cut -d":" -f2 | grep dpkg-deb > /dev/null diff --git a/pandora_agents/unix/pandora_agent b/pandora_agents/unix/pandora_agent index 8763ad999e..e3a83cec84 100755 --- a/pandora_agents/unix/pandora_agent +++ b/pandora_agents/unix/pandora_agent @@ -1015,7 +1015,7 @@ my $Sem = undef; my $ThreadSem = undef; use constant AGENT_VERSION => '7.0NG.762'; -use constant AGENT_BUILD => '220614'; +use constant AGENT_BUILD => '220615'; # Agent log default file size maximum and instances use constant DEFAULT_MAX_LOG_SIZE => 600000; diff --git a/pandora_agents/unix/pandora_agent.redhat.spec b/pandora_agents/unix/pandora_agent.redhat.spec index 3dec167453..03414f5138 100644 --- a/pandora_agents/unix/pandora_agent.redhat.spec +++ b/pandora_agents/unix/pandora_agent.redhat.spec @@ -3,7 +3,7 @@ # %define name pandorafms_agent_unix %define version 7.0NG.762 -%define release 220614 +%define release 220615 Summary: Pandora FMS Linux agent, PERL version Name: %{name} diff --git a/pandora_agents/unix/pandora_agent.spec b/pandora_agents/unix/pandora_agent.spec index 1249b8e6e7..ce161155b3 100644 --- a/pandora_agents/unix/pandora_agent.spec +++ b/pandora_agents/unix/pandora_agent.spec @@ -3,7 +3,7 @@ # %define name pandorafms_agent_unix %define version 7.0NG.762 -%define release 220614 +%define release 220615 Summary: Pandora FMS Linux agent, PERL version Name: %{name} diff --git a/pandora_agents/unix/pandora_agent_installer b/pandora_agents/unix/pandora_agent_installer index 07f0a9babf..88b55738c5 100755 --- a/pandora_agents/unix/pandora_agent_installer +++ b/pandora_agents/unix/pandora_agent_installer @@ -10,7 +10,7 @@ # ********************************************************************** PI_VERSION="7.0NG.762" -PI_BUILD="220614" +PI_BUILD="220615" OS_NAME=`uname -s` FORCE=0 diff --git a/pandora_agents/win32/installer/pandora.mpi b/pandora_agents/win32/installer/pandora.mpi index 4d65f05a32..4a81e3c2a7 100644 --- a/pandora_agents/win32/installer/pandora.mpi +++ b/pandora_agents/win32/installer/pandora.mpi @@ -186,7 +186,7 @@ UpgradeApplicationID {} Version -{220614} +{220615} ViewReadme {Yes} diff --git a/pandora_agents/win32/pandora.cc b/pandora_agents/win32/pandora.cc index 6a4d7782f9..490ac8919b 100644 --- a/pandora_agents/win32/pandora.cc +++ b/pandora_agents/win32/pandora.cc @@ -30,7 +30,7 @@ using namespace Pandora; using namespace Pandora_Strutils; #define PATH_SIZE _MAX_PATH+1 -#define PANDORA_VERSION ("7.0NG.762 Build 220614") +#define PANDORA_VERSION ("7.0NG.762 Build 220615") string pandora_path; string pandora_dir; diff --git a/pandora_agents/win32/versioninfo.rc b/pandora_agents/win32/versioninfo.rc index ca70a5662b..695cb556d0 100644 --- a/pandora_agents/win32/versioninfo.rc +++ b/pandora_agents/win32/versioninfo.rc @@ -11,7 +11,7 @@ BEGIN VALUE "LegalCopyright", "Artica ST" VALUE "OriginalFilename", "PandoraAgent.exe" VALUE "ProductName", "Pandora FMS Windows Agent" - VALUE "ProductVersion", "(7.0NG.762(Build 220614))" + VALUE "ProductVersion", "(7.0NG.762(Build 220615))" VALUE "FileVersion", "1.0.0.0" END END diff --git a/pandora_console/DEBIAN/control b/pandora_console/DEBIAN/control index 28ad21f54e..51e17e0701 100644 --- a/pandora_console/DEBIAN/control +++ b/pandora_console/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-console -Version: 7.0NG.762-220614 +Version: 7.0NG.762-220615 Architecture: all Priority: optional Section: admin diff --git a/pandora_console/DEBIAN/make_deb_package.sh b/pandora_console/DEBIAN/make_deb_package.sh index af4c21ef4e..558ea0017b 100644 --- a/pandora_console/DEBIAN/make_deb_package.sh +++ b/pandora_console/DEBIAN/make_deb_package.sh @@ -14,7 +14,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -pandora_version="7.0NG.762-220614" +pandora_version="7.0NG.762-220615" package_pear=0 package_pandora=1 diff --git a/pandora_console/include/config_process.php b/pandora_console/include/config_process.php index b7d03fe4f4..9823d14fe5 100644 --- a/pandora_console/include/config_process.php +++ b/pandora_console/include/config_process.php @@ -20,7 +20,7 @@ /** * Pandora build version and version */ -$build_version = 'PC220614'; +$build_version = 'PC220615'; $pandora_version = 'v7.0NG.762'; // Do not overwrite default timezone set if defined. diff --git a/pandora_console/install.php b/pandora_console/install.php index 6b3aeef58f..07c51d5494 100644 --- a/pandora_console/install.php +++ b/pandora_console/install.php @@ -129,7 +129,7 @@ <div style='height: 10px'> <?php $version = '7.0NG.762'; - $build = '220614'; + $build = '220615'; $banner = "v$version Build $build"; error_reporting(0); diff --git a/pandora_console/pandora_console.redhat.spec b/pandora_console/pandora_console.redhat.spec index ccc9b3922e..d4ca79d56d 100644 --- a/pandora_console/pandora_console.redhat.spec +++ b/pandora_console/pandora_console.redhat.spec @@ -3,7 +3,7 @@ # %define name pandorafms_console %define version 7.0NG.762 -%define release 220614 +%define release 220615 # User and Group under which Apache is running %define httpd_name httpd diff --git a/pandora_console/pandora_console.rhel7.spec b/pandora_console/pandora_console.rhel7.spec index cc364d3d5d..2e3929ae46 100644 --- a/pandora_console/pandora_console.rhel7.spec +++ b/pandora_console/pandora_console.rhel7.spec @@ -3,7 +3,7 @@ # %define name pandorafms_console %define version 7.0NG.762 -%define release 220614 +%define release 220615 # User and Group under which Apache is running %define httpd_name httpd diff --git a/pandora_console/pandora_console.spec b/pandora_console/pandora_console.spec index d9f4fcdb85..88670756ac 100644 --- a/pandora_console/pandora_console.spec +++ b/pandora_console/pandora_console.spec @@ -3,7 +3,7 @@ # %define name pandorafms_console %define version 7.0NG.762 -%define release 220614 +%define release 220615 %define httpd_name httpd # User and Group under which Apache is running %define httpd_name apache2 diff --git a/pandora_server/DEBIAN/control b/pandora_server/DEBIAN/control index 487239a2d6..5fba1e1706 100644 --- a/pandora_server/DEBIAN/control +++ b/pandora_server/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-server -Version: 7.0NG.762-220614 +Version: 7.0NG.762-220615 Architecture: all Priority: optional Section: admin diff --git a/pandora_server/DEBIAN/make_deb_package.sh b/pandora_server/DEBIAN/make_deb_package.sh index 8102a1c5d8..4334b47273 100644 --- a/pandora_server/DEBIAN/make_deb_package.sh +++ b/pandora_server/DEBIAN/make_deb_package.sh @@ -14,7 +14,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -pandora_version="7.0NG.762-220614" +pandora_version="7.0NG.762-220615" package_cpan=0 package_pandora=1 diff --git a/pandora_server/lib/PandoraFMS/Config.pm b/pandora_server/lib/PandoraFMS/Config.pm index 8fec3e4bf4..5352c013c0 100644 --- a/pandora_server/lib/PandoraFMS/Config.pm +++ b/pandora_server/lib/PandoraFMS/Config.pm @@ -46,7 +46,7 @@ our @EXPORT = qw( # version: Defines actual version of Pandora Server for this module only my $pandora_version = "7.0NG.762"; -my $pandora_build = "220614"; +my $pandora_build = "220615"; our $VERSION = $pandora_version." ".$pandora_build; # Setup hash diff --git a/pandora_server/lib/PandoraFMS/PluginTools.pm b/pandora_server/lib/PandoraFMS/PluginTools.pm index 4a1afb0c36..ff33fdf1ce 100644 --- a/pandora_server/lib/PandoraFMS/PluginTools.pm +++ b/pandora_server/lib/PandoraFMS/PluginTools.pm @@ -34,7 +34,7 @@ our @ISA = qw(Exporter); # version: Defines actual version of Pandora Server for this module only my $pandora_version = "7.0NG.762"; -my $pandora_build = "220614"; +my $pandora_build = "220615"; our $VERSION = $pandora_version." ".$pandora_build; our %EXPORT_TAGS = ( 'all' => [ qw() ] ); diff --git a/pandora_server/pandora_server.redhat.spec b/pandora_server/pandora_server.redhat.spec index 1b5ebbdc00..5c4d09f07f 100644 --- a/pandora_server/pandora_server.redhat.spec +++ b/pandora_server/pandora_server.redhat.spec @@ -3,7 +3,7 @@ # %define name pandorafms_server %define version 7.0NG.762 -%define release 220614 +%define release 220615 Summary: Pandora FMS Server Name: %{name} diff --git a/pandora_server/pandora_server.spec b/pandora_server/pandora_server.spec index 785b404cb2..9dead83f81 100644 --- a/pandora_server/pandora_server.spec +++ b/pandora_server/pandora_server.spec @@ -3,7 +3,7 @@ # %define name pandorafms_server %define version 7.0NG.762 -%define release 220614 +%define release 220615 Summary: Pandora FMS Server Name: %{name} diff --git a/pandora_server/pandora_server_installer b/pandora_server/pandora_server_installer index 5642aa9ec6..f7453e724d 100755 --- a/pandora_server/pandora_server_installer +++ b/pandora_server/pandora_server_installer @@ -9,7 +9,7 @@ # ********************************************************************** PI_VERSION="7.0NG.762" -PI_BUILD="220614" +PI_BUILD="220615" MODE=$1 if [ $# -gt 1 ]; then diff --git a/pandora_server/util/pandora_db.pl b/pandora_server/util/pandora_db.pl index c2cd3f5a11..d5ca16614c 100755 --- a/pandora_server/util/pandora_db.pl +++ b/pandora_server/util/pandora_db.pl @@ -35,7 +35,7 @@ use PandoraFMS::Config; use PandoraFMS::DB; # version: define current version -my $version = "7.0NG.762 Build 220614"; +my $version = "7.0NG.762 Build 220615"; # Pandora server configuration my %conf; diff --git a/pandora_server/util/pandora_manage.pl b/pandora_server/util/pandora_manage.pl index cffa3811ef..96ae2ece1a 100755 --- a/pandora_server/util/pandora_manage.pl +++ b/pandora_server/util/pandora_manage.pl @@ -36,7 +36,7 @@ use Encode::Locale; Encode::Locale::decode_argv; # version: define current version -my $version = "7.0NG.762 Build 220614"; +my $version = "7.0NG.762 Build 220615"; # save program name for logging my $progname = basename($0); From 9a7e0e32289361fffda4e5025878a609e865a649 Mon Sep 17 00:00:00 2001 From: Daniel Maya <daniel.maya@pandorafms.com> Date: Wed, 15 Jun 2022 09:37:29 +0200 Subject: [PATCH 36/38] #8899 Fixed history_db_enabled --- pandora_console/include/functions_config.php | 83 ++++++++++---------- 1 file changed, 43 insertions(+), 40 deletions(-) diff --git a/pandora_console/include/functions_config.php b/pandora_console/include/functions_config.php index c934a7aea7..635ca25767 100644 --- a/pandora_console/include/functions_config.php +++ b/pandora_console/include/functions_config.php @@ -1619,48 +1619,51 @@ function config_update_config() $dbm->process(); } else if ($dbm->check() !== true) { $errors[] = $dbm->getLastError(); + config_update_value('history_db_enabled', false); + } + + if ($dbm->check() === true) { + // Historical configuration tokens (stored in historical db). + if (Config::set( + 'days_purge', + get_parameter('history_dbh_purge'), + true + ) !== true + ) { + $error_update[] = __('Historical database purge'); + } + + if (Config::set( + 'history_partitions_auto', + get_parameter_switch('history_partitions_auto', 0), + true + ) !== true + ) { + $error_update[] = __('Historical database partitions'); + } + + if (Config::set( + 'event_purge', + get_parameter('history_dbh_events_purge'), + true + ) !== true + ) { + $error_update[] = __('Historical database events purge'); + } + + if (Config::set( + 'string_purge', + get_parameter('history_dbh_string_purge'), + true + ) !== true + ) { + $error_update[] = __('Historical database string purge'); + } + + // Disable history db in history db. + Config::set('history_db_enabled', 0, true); } } - - // Historical configuration tokens (stored in historical db). - if (Config::set( - 'days_purge', - get_parameter('history_dbh_purge'), - true - ) !== true - ) { - $error_update[] = __('Historical database purge'); - } - - if (Config::set( - 'history_partitions_auto', - get_parameter_switch('history_partitions_auto', 0), - true - ) !== true - ) { - $error_update[] = __('Historical database partitions'); - } - - if (Config::set( - 'event_purge', - get_parameter('history_dbh_events_purge'), - true - ) !== true - ) { - $error_update[] = __('Historical database events purge'); - } - - if (Config::set( - 'string_purge', - get_parameter('history_dbh_string_purge'), - true - ) !== true - ) { - $error_update[] = __('Historical database string purge'); - } - - // Disable history db in history db. - Config::set('history_db_enabled', 0, true); break; case 'ehorus': From 592d09d34a99f3c019afe84cdd7ed31187a443ce Mon Sep 17 00:00:00 2001 From: artica <artica.devel@gmail.com> Date: Thu, 16 Jun 2022 01:00:17 +0200 Subject: [PATCH 37/38] Auto-updated build strings. --- pandora_agents/unix/DEBIAN/control | 2 +- pandora_agents/unix/DEBIAN/make_deb_package.sh | 2 +- pandora_agents/unix/pandora_agent | 2 +- pandora_agents/unix/pandora_agent.redhat.spec | 2 +- pandora_agents/unix/pandora_agent.spec | 2 +- pandora_agents/unix/pandora_agent_installer | 2 +- pandora_agents/win32/installer/pandora.mpi | 2 +- pandora_agents/win32/pandora.cc | 2 +- pandora_agents/win32/versioninfo.rc | 2 +- pandora_console/DEBIAN/control | 2 +- pandora_console/DEBIAN/make_deb_package.sh | 2 +- pandora_console/include/config_process.php | 2 +- pandora_console/install.php | 2 +- pandora_console/pandora_console.redhat.spec | 2 +- pandora_console/pandora_console.rhel7.spec | 2 +- pandora_console/pandora_console.spec | 2 +- pandora_server/DEBIAN/control | 2 +- pandora_server/DEBIAN/make_deb_package.sh | 2 +- pandora_server/lib/PandoraFMS/Config.pm | 2 +- pandora_server/lib/PandoraFMS/PluginTools.pm | 2 +- pandora_server/pandora_server.redhat.spec | 2 +- pandora_server/pandora_server.spec | 2 +- pandora_server/pandora_server_installer | 2 +- pandora_server/util/pandora_db.pl | 2 +- pandora_server/util/pandora_manage.pl | 2 +- 25 files changed, 25 insertions(+), 25 deletions(-) diff --git a/pandora_agents/unix/DEBIAN/control b/pandora_agents/unix/DEBIAN/control index 119f59a1e4..7aa0b1dc23 100644 --- a/pandora_agents/unix/DEBIAN/control +++ b/pandora_agents/unix/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-agent-unix -Version: 7.0NG.762-220615 +Version: 7.0NG.762-220616 Architecture: all Priority: optional Section: admin diff --git a/pandora_agents/unix/DEBIAN/make_deb_package.sh b/pandora_agents/unix/DEBIAN/make_deb_package.sh index 8c9841cbb7..da2264d92c 100644 --- a/pandora_agents/unix/DEBIAN/make_deb_package.sh +++ b/pandora_agents/unix/DEBIAN/make_deb_package.sh @@ -14,7 +14,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -pandora_version="7.0NG.762-220615" +pandora_version="7.0NG.762-220616" echo "Test if you has the tools for to make the packages." whereis dpkg-deb | cut -d":" -f2 | grep dpkg-deb > /dev/null diff --git a/pandora_agents/unix/pandora_agent b/pandora_agents/unix/pandora_agent index e3a83cec84..746683baf2 100755 --- a/pandora_agents/unix/pandora_agent +++ b/pandora_agents/unix/pandora_agent @@ -1015,7 +1015,7 @@ my $Sem = undef; my $ThreadSem = undef; use constant AGENT_VERSION => '7.0NG.762'; -use constant AGENT_BUILD => '220615'; +use constant AGENT_BUILD => '220616'; # Agent log default file size maximum and instances use constant DEFAULT_MAX_LOG_SIZE => 600000; diff --git a/pandora_agents/unix/pandora_agent.redhat.spec b/pandora_agents/unix/pandora_agent.redhat.spec index 03414f5138..d64f371dcd 100644 --- a/pandora_agents/unix/pandora_agent.redhat.spec +++ b/pandora_agents/unix/pandora_agent.redhat.spec @@ -3,7 +3,7 @@ # %define name pandorafms_agent_unix %define version 7.0NG.762 -%define release 220615 +%define release 220616 Summary: Pandora FMS Linux agent, PERL version Name: %{name} diff --git a/pandora_agents/unix/pandora_agent.spec b/pandora_agents/unix/pandora_agent.spec index ce161155b3..9bfcd6774f 100644 --- a/pandora_agents/unix/pandora_agent.spec +++ b/pandora_agents/unix/pandora_agent.spec @@ -3,7 +3,7 @@ # %define name pandorafms_agent_unix %define version 7.0NG.762 -%define release 220615 +%define release 220616 Summary: Pandora FMS Linux agent, PERL version Name: %{name} diff --git a/pandora_agents/unix/pandora_agent_installer b/pandora_agents/unix/pandora_agent_installer index 88b55738c5..e32d36a978 100755 --- a/pandora_agents/unix/pandora_agent_installer +++ b/pandora_agents/unix/pandora_agent_installer @@ -10,7 +10,7 @@ # ********************************************************************** PI_VERSION="7.0NG.762" -PI_BUILD="220615" +PI_BUILD="220616" OS_NAME=`uname -s` FORCE=0 diff --git a/pandora_agents/win32/installer/pandora.mpi b/pandora_agents/win32/installer/pandora.mpi index 4a81e3c2a7..b50d0d622d 100644 --- a/pandora_agents/win32/installer/pandora.mpi +++ b/pandora_agents/win32/installer/pandora.mpi @@ -186,7 +186,7 @@ UpgradeApplicationID {} Version -{220615} +{220616} ViewReadme {Yes} diff --git a/pandora_agents/win32/pandora.cc b/pandora_agents/win32/pandora.cc index 490ac8919b..06b91d8b58 100644 --- a/pandora_agents/win32/pandora.cc +++ b/pandora_agents/win32/pandora.cc @@ -30,7 +30,7 @@ using namespace Pandora; using namespace Pandora_Strutils; #define PATH_SIZE _MAX_PATH+1 -#define PANDORA_VERSION ("7.0NG.762 Build 220615") +#define PANDORA_VERSION ("7.0NG.762 Build 220616") string pandora_path; string pandora_dir; diff --git a/pandora_agents/win32/versioninfo.rc b/pandora_agents/win32/versioninfo.rc index 695cb556d0..0610000718 100644 --- a/pandora_agents/win32/versioninfo.rc +++ b/pandora_agents/win32/versioninfo.rc @@ -11,7 +11,7 @@ BEGIN VALUE "LegalCopyright", "Artica ST" VALUE "OriginalFilename", "PandoraAgent.exe" VALUE "ProductName", "Pandora FMS Windows Agent" - VALUE "ProductVersion", "(7.0NG.762(Build 220615))" + VALUE "ProductVersion", "(7.0NG.762(Build 220616))" VALUE "FileVersion", "1.0.0.0" END END diff --git a/pandora_console/DEBIAN/control b/pandora_console/DEBIAN/control index 51e17e0701..9bc4338c1f 100644 --- a/pandora_console/DEBIAN/control +++ b/pandora_console/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-console -Version: 7.0NG.762-220615 +Version: 7.0NG.762-220616 Architecture: all Priority: optional Section: admin diff --git a/pandora_console/DEBIAN/make_deb_package.sh b/pandora_console/DEBIAN/make_deb_package.sh index 558ea0017b..57af185b00 100644 --- a/pandora_console/DEBIAN/make_deb_package.sh +++ b/pandora_console/DEBIAN/make_deb_package.sh @@ -14,7 +14,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -pandora_version="7.0NG.762-220615" +pandora_version="7.0NG.762-220616" package_pear=0 package_pandora=1 diff --git a/pandora_console/include/config_process.php b/pandora_console/include/config_process.php index 9823d14fe5..9db7f38355 100644 --- a/pandora_console/include/config_process.php +++ b/pandora_console/include/config_process.php @@ -20,7 +20,7 @@ /** * Pandora build version and version */ -$build_version = 'PC220615'; +$build_version = 'PC220616'; $pandora_version = 'v7.0NG.762'; // Do not overwrite default timezone set if defined. diff --git a/pandora_console/install.php b/pandora_console/install.php index 07c51d5494..727e4c4d98 100644 --- a/pandora_console/install.php +++ b/pandora_console/install.php @@ -129,7 +129,7 @@ <div style='height: 10px'> <?php $version = '7.0NG.762'; - $build = '220615'; + $build = '220616'; $banner = "v$version Build $build"; error_reporting(0); diff --git a/pandora_console/pandora_console.redhat.spec b/pandora_console/pandora_console.redhat.spec index d4ca79d56d..59781de1a2 100644 --- a/pandora_console/pandora_console.redhat.spec +++ b/pandora_console/pandora_console.redhat.spec @@ -3,7 +3,7 @@ # %define name pandorafms_console %define version 7.0NG.762 -%define release 220615 +%define release 220616 # User and Group under which Apache is running %define httpd_name httpd diff --git a/pandora_console/pandora_console.rhel7.spec b/pandora_console/pandora_console.rhel7.spec index 2e3929ae46..d67df879aa 100644 --- a/pandora_console/pandora_console.rhel7.spec +++ b/pandora_console/pandora_console.rhel7.spec @@ -3,7 +3,7 @@ # %define name pandorafms_console %define version 7.0NG.762 -%define release 220615 +%define release 220616 # User and Group under which Apache is running %define httpd_name httpd diff --git a/pandora_console/pandora_console.spec b/pandora_console/pandora_console.spec index 88670756ac..b17922032b 100644 --- a/pandora_console/pandora_console.spec +++ b/pandora_console/pandora_console.spec @@ -3,7 +3,7 @@ # %define name pandorafms_console %define version 7.0NG.762 -%define release 220615 +%define release 220616 %define httpd_name httpd # User and Group under which Apache is running %define httpd_name apache2 diff --git a/pandora_server/DEBIAN/control b/pandora_server/DEBIAN/control index 5fba1e1706..88e8056af5 100644 --- a/pandora_server/DEBIAN/control +++ b/pandora_server/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-server -Version: 7.0NG.762-220615 +Version: 7.0NG.762-220616 Architecture: all Priority: optional Section: admin diff --git a/pandora_server/DEBIAN/make_deb_package.sh b/pandora_server/DEBIAN/make_deb_package.sh index 4334b47273..c7a1a53370 100644 --- a/pandora_server/DEBIAN/make_deb_package.sh +++ b/pandora_server/DEBIAN/make_deb_package.sh @@ -14,7 +14,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -pandora_version="7.0NG.762-220615" +pandora_version="7.0NG.762-220616" package_cpan=0 package_pandora=1 diff --git a/pandora_server/lib/PandoraFMS/Config.pm b/pandora_server/lib/PandoraFMS/Config.pm index 5352c013c0..6a2dffb4bc 100644 --- a/pandora_server/lib/PandoraFMS/Config.pm +++ b/pandora_server/lib/PandoraFMS/Config.pm @@ -46,7 +46,7 @@ our @EXPORT = qw( # version: Defines actual version of Pandora Server for this module only my $pandora_version = "7.0NG.762"; -my $pandora_build = "220615"; +my $pandora_build = "220616"; our $VERSION = $pandora_version." ".$pandora_build; # Setup hash diff --git a/pandora_server/lib/PandoraFMS/PluginTools.pm b/pandora_server/lib/PandoraFMS/PluginTools.pm index ff33fdf1ce..74c972bf88 100644 --- a/pandora_server/lib/PandoraFMS/PluginTools.pm +++ b/pandora_server/lib/PandoraFMS/PluginTools.pm @@ -34,7 +34,7 @@ our @ISA = qw(Exporter); # version: Defines actual version of Pandora Server for this module only my $pandora_version = "7.0NG.762"; -my $pandora_build = "220615"; +my $pandora_build = "220616"; our $VERSION = $pandora_version." ".$pandora_build; our %EXPORT_TAGS = ( 'all' => [ qw() ] ); diff --git a/pandora_server/pandora_server.redhat.spec b/pandora_server/pandora_server.redhat.spec index 5c4d09f07f..6fb8f0728d 100644 --- a/pandora_server/pandora_server.redhat.spec +++ b/pandora_server/pandora_server.redhat.spec @@ -3,7 +3,7 @@ # %define name pandorafms_server %define version 7.0NG.762 -%define release 220615 +%define release 220616 Summary: Pandora FMS Server Name: %{name} diff --git a/pandora_server/pandora_server.spec b/pandora_server/pandora_server.spec index 9dead83f81..7f8879a00c 100644 --- a/pandora_server/pandora_server.spec +++ b/pandora_server/pandora_server.spec @@ -3,7 +3,7 @@ # %define name pandorafms_server %define version 7.0NG.762 -%define release 220615 +%define release 220616 Summary: Pandora FMS Server Name: %{name} diff --git a/pandora_server/pandora_server_installer b/pandora_server/pandora_server_installer index f7453e724d..2cfa52c101 100755 --- a/pandora_server/pandora_server_installer +++ b/pandora_server/pandora_server_installer @@ -9,7 +9,7 @@ # ********************************************************************** PI_VERSION="7.0NG.762" -PI_BUILD="220615" +PI_BUILD="220616" MODE=$1 if [ $# -gt 1 ]; then diff --git a/pandora_server/util/pandora_db.pl b/pandora_server/util/pandora_db.pl index d5ca16614c..d9eb2ebdae 100755 --- a/pandora_server/util/pandora_db.pl +++ b/pandora_server/util/pandora_db.pl @@ -35,7 +35,7 @@ use PandoraFMS::Config; use PandoraFMS::DB; # version: define current version -my $version = "7.0NG.762 Build 220615"; +my $version = "7.0NG.762 Build 220616"; # Pandora server configuration my %conf; diff --git a/pandora_server/util/pandora_manage.pl b/pandora_server/util/pandora_manage.pl index 96ae2ece1a..5c6f848398 100755 --- a/pandora_server/util/pandora_manage.pl +++ b/pandora_server/util/pandora_manage.pl @@ -36,7 +36,7 @@ use Encode::Locale; Encode::Locale::decode_argv; # version: define current version -my $version = "7.0NG.762 Build 220615"; +my $version = "7.0NG.762 Build 220616"; # save program name for logging my $progname = basename($0); From bb01bfe2d0d6dbc4531a1653a41386f83e306f76 Mon Sep 17 00:00:00 2001 From: Daniel Maya <daniel.maya@pandorafms.com> Date: Thu, 16 Jun 2022 08:44:09 +0200 Subject: [PATCH 38/38] #8899 Fixed history_db_enabled 2 --- pandora_console/include/functions_config.php | 22 ++++++++----------- .../include/lib/Core/DBMaintainer.php | 2 +- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/pandora_console/include/functions_config.php b/pandora_console/include/functions_config.php index 635ca25767..25a5093a69 100644 --- a/pandora_console/include/functions_config.php +++ b/pandora_console/include/functions_config.php @@ -1624,44 +1624,40 @@ function config_update_config() if ($dbm->check() === true) { // Historical configuration tokens (stored in historical db). - if (Config::set( + if ($dbm->setConfigToken( 'days_purge', - get_parameter('history_dbh_purge'), - true + get_parameter('history_dbh_purge') ) !== true ) { $error_update[] = __('Historical database purge'); } - if (Config::set( + if ($dbm->setConfigToken( 'history_partitions_auto', - get_parameter_switch('history_partitions_auto', 0), - true + get_parameter_switch('history_partitions_auto', 0) ) !== true ) { $error_update[] = __('Historical database partitions'); } - if (Config::set( + if ($dbm->setConfigToken( 'event_purge', - get_parameter('history_dbh_events_purge'), - true + get_parameter('history_dbh_events_purge') ) !== true ) { $error_update[] = __('Historical database events purge'); } - if (Config::set( + if ($dbm->setConfigToken( 'string_purge', - get_parameter('history_dbh_string_purge'), - true + get_parameter('history_dbh_string_purge') ) !== true ) { $error_update[] = __('Historical database string purge'); } // Disable history db in history db. - Config::set('history_db_enabled', 0, true); + $dbm->setConfigToken('history_db_enabled', 0); } } break; diff --git a/pandora_console/include/lib/Core/DBMaintainer.php b/pandora_console/include/lib/Core/DBMaintainer.php index 5bd0ba6695..aa09c385f8 100644 --- a/pandora_console/include/lib/Core/DBMaintainer.php +++ b/pandora_console/include/lib/Core/DBMaintainer.php @@ -384,7 +384,7 @@ final class DBMaintainer * * @return boolean Success or not. */ - private function setConfigToken(string $token, $value) + public function setConfigToken(string $token, $value) { $prev = $this->getValue('tconfig', 'value', ['token' => $token]); // If failed or not found, then insert.