From c0a4ba5cb400664208c46e9f78dc1eaa81330baf Mon Sep 17 00:00:00 2001 From: Calvo Date: Tue, 13 Jul 2021 11:12:06 +0200 Subject: [PATCH 01/92] Fix search component group passing invalid get params --- pandora_console/godmode/modules/manage_network_components.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pandora_console/godmode/modules/manage_network_components.php b/pandora_console/godmode/modules/manage_network_components.php index 1828e577a1..8b84eb2f22 100644 --- a/pandora_console/godmode/modules/manage_network_components.php +++ b/pandora_console/godmode/modules/manage_network_components.php @@ -560,7 +560,7 @@ if ($multiple_delete) { $id = 0; } -if ($id || $new_component +if ((bool) $id !== false || $new_component || $create_network_from_module || $create_network_from_snmp_browser ) { @@ -577,6 +577,7 @@ $url = ui_get_url_refresh( 'offset' => false, 'search_string' => $search_string, 'search_id_group' => $search_id_group, + 'id' => $id, ], true, false From 77552805a403f34d2d84901a50f1b6054e12aecd Mon Sep 17 00:00:00 2001 From: Calvo Date: Fri, 16 Jul 2021 13:55:31 +0200 Subject: [PATCH 02/92] Fix list agent with secondaty grouos on selec --- .../godmode/agentes/configurar_agente.php | 13 ++++++++++++- pandora_console/include/functions_agents.php | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/pandora_console/godmode/agentes/configurar_agente.php b/pandora_console/godmode/agentes/configurar_agente.php index abdb5a8dca..ee58019a5a 100644 --- a/pandora_console/godmode/agentes/configurar_agente.php +++ b/pandora_console/godmode/agentes/configurar_agente.php @@ -976,6 +976,8 @@ if ($update_agent) { $cps = get_parameter_switch('cps', -1); $old_values = db_get_row('tagente', 'id_agente', $id_agente); $fields = db_get_all_fields_in_table('tagent_custom_fields'); + $secondary_groups = (string) get_parameter('secondary_hidden', ''); + if ($fields === false) { $fields = []; @@ -1205,7 +1207,16 @@ if ($update_agent) { "Quiet":"'.(int) $quiet.'", "Cps":"'.(int) $cps.'"}'; - enterprise_hook('update_agent', [$id_agente]); + // Create the secondary groups. + enterprise_hook( + 'agents_update_secondary_groups', + [ + $id_agente, + explode(',', $secondary_groups), + [], + ] + ); + ui_print_success_message(__('Successfully updated')); db_pandora_audit( 'Agent management', diff --git a/pandora_console/include/functions_agents.php b/pandora_console/include/functions_agents.php index 8f9791332f..e0e6b560e7 100644 --- a/pandora_console/include/functions_agents.php +++ b/pandora_console/include/functions_agents.php @@ -1283,7 +1283,7 @@ function agents_get_group_agents( if (!$add_alert_bulk_op) { // Add the rest of the filter from the search array. foreach ($search as $key => $value) { - $filter[] = $value; + $filter[$key] = $value; } } } else if ($filter !== true) { From a8c0ba8e78c8a03f0d80c753dee0c38b08c01be3 Mon Sep 17 00:00:00 2001 From: Calvo Date: Mon, 19 Jul 2021 13:20:00 +0200 Subject: [PATCH 03/92] Include modules not init in total monitors count on tactical view --- pandora_console/general/logon_ok.php | 2 ++ pandora_console/include/functions_reporting.php | 10 +++++----- pandora_console/include/functions_tactical.php | 2 +- .../include/lib/Dashboard/Widgets/tactical.php | 1 + pandora_console/mobile/operation/tactical.php | 1 + pandora_console/operation/agentes/tactical.php | 1 + 6 files changed, 11 insertions(+), 6 deletions(-) diff --git a/pandora_console/general/logon_ok.php b/pandora_console/general/logon_ok.php index 2dbc1ff50c..4d18e0e79d 100644 --- a/pandora_console/general/logon_ok.php +++ b/pandora_console/general/logon_ok.php @@ -64,6 +64,8 @@ $data['monitor_critical'] = (int) $all_data['_monitors_critical_']; $data['monitor_not_normal'] = (int) $all_data['_monitor_not_normal_']; $data['monitor_alerts'] = (int) $all_data['_monitors_alerts_']; $data['monitor_alerts_fired'] = (int) $all_data['_monitors_alerts_fired_']; +$data['monitor_total'] = (int) $all_data['_monitor_total_']; + $data['total_agents'] = (int) $all_data['_total_agents_']; diff --git a/pandora_console/include/functions_reporting.php b/pandora_console/include/functions_reporting.php index cd68a65bcf..3c4b2dfcd4 100755 --- a/pandora_console/include/functions_reporting.php +++ b/pandora_console/include/functions_reporting.php @@ -10675,11 +10675,11 @@ function reporting_get_stats_agents_monitors($data) if ($mobile) { $urls = []; $urls['total_agents'] = 'index.php?page=agents'; - $urls['monitor_checks'] = 'index.php?page=modules'; + $urls['monitor_total'] = 'index.php?page=modules'; } else { $urls = []; $urls['total_agents'] = $config['homeurl'].'index.php?sec=estado&sec2=operation/agentes/estado_agente&refr=60'; - $urls['monitor_checks'] = $config['homeurl'].'index.php?sec=view&sec2=operation/agentes/status_monitor&refr=60&status=-1'; + $urls['monitor_total'] = $config['homeurl'].'index.php?sec=view&sec2=operation/agentes/status_monitor&refr=60&status=-1'; } // Agents and modules table @@ -10701,8 +10701,8 @@ function reporting_get_stats_agents_monitors($data) } $tdata[3] = html_print_image('images/module.png', true, ['title' => __('Monitor checks'), 'class' => 'invert_filter'], false, false, false, true); - $tdata[4] = $data['monitor_checks'] <= 0 ? '-' : $data['monitor_checks']; - $tdata[4] = ''.$tdata[4].''; + $tdata[4] = $data['monitor_total'] <= 0 ? '-' : $data['monitor_total']; + $tdata[4] = ''.$tdata[4].''; /* Hello there! :) @@ -10710,7 +10710,7 @@ function reporting_get_stats_agents_monitors($data) You can of course remove the warnings, that's why we include the source and do not use any kind of trick. And that's why we added here this comment, to let you know this does not reflect any change in our opensource mentality of does the last 14 years. */ if ($data['total_agents']) { - if (($data['monitor_checks'] / $data['total_agents'] > 100) && !enterprise_installed()) { + if (($data['monitor_total'] / $data['total_agents'] > 100) && !enterprise_installed()) { $tdata[5] = "
"; } } diff --git a/pandora_console/include/functions_tactical.php b/pandora_console/include/functions_tactical.php index 269df899d4..d425ff42b8 100644 --- a/pandora_console/include/functions_tactical.php +++ b/pandora_console/include/functions_tactical.php @@ -415,7 +415,7 @@ function tactical_get_data($id_user=false, $user_strict=false, $acltags, $return $total_agentes = agents_get_agents(false, ['count(DISTINCT id_agente) as total_agents'], 'AR', false, false, 1); $list['_total_agents_'] = $total_agentes[0]['total_agents']; - + $list['_monitor_total_'] = ($list['_monitors_not_init_'] + $list['_monitors_unknown_'] + $list['_monitors_warning_'] + $list['_monitors_critical_'] + $list['_monitors_ok_']); $list['_monitor_checks_'] = ($list['_monitors_unknown_'] + $list['_monitors_warning_'] + $list['_monitors_critical_'] + $list['_monitors_ok_']); // Calculate not_normal monitors diff --git a/pandora_console/include/lib/Dashboard/Widgets/tactical.php b/pandora_console/include/lib/Dashboard/Widgets/tactical.php index 06f14cf557..74d72d0c5c 100755 --- a/pandora_console/include/lib/Dashboard/Widgets/tactical.php +++ b/pandora_console/include/lib/Dashboard/Widgets/tactical.php @@ -339,6 +339,7 @@ class TacticalWidget extends Widget $data['monitor_not_normal'] = (int) $all_data['_monitor_not_normal_']; $data['monitor_alerts'] = (int) $all_data['_monitors_alerts_']; $data['monitor_alerts_fired'] = (int) $all_data['_monitors_alerts_fired_']; + $data['monitor_total'] = (int) $all_data['_monitor_total_']; $data['total_agents'] = (int) $all_data['_total_agents_']; diff --git a/pandora_console/mobile/operation/tactical.php b/pandora_console/mobile/operation/tactical.php index eed45507ed..e88287da6c 100755 --- a/pandora_console/mobile/operation/tactical.php +++ b/pandora_console/mobile/operation/tactical.php @@ -120,6 +120,7 @@ class Tactical $data['monitor_not_normal'] = (int) $all_data['_monitor_not_normal_']; $data['monitor_alerts'] = (int) $all_data['_monitors_alerts_']; $data['monitor_alerts_fired'] = (int) $all_data['_monitors_alerts_fired_']; + $data['monitor_total'] = (int) $all_data['_monitor_total_']; $data['total_agents'] = (int) $all_data['_total_agents_']; diff --git a/pandora_console/operation/agentes/tactical.php b/pandora_console/operation/agentes/tactical.php index d82a749a85..b4430ef128 100755 --- a/pandora_console/operation/agentes/tactical.php +++ b/pandora_console/operation/agentes/tactical.php @@ -98,6 +98,7 @@ $data['monitor_critical'] = (int) $all_data['_monitors_critical_']; $data['monitor_not_normal'] = (int) $all_data['_monitor_not_normal_']; $data['monitor_alerts'] = (int) $all_data['_monitors_alerts_']; $data['monitor_alerts_fired'] = (int) $all_data['_monitors_alerts_fired_']; +$data['monitor_total'] = (int) $all_data['_monitor_total_']; $data['total_agents'] = (int) $all_data['_total_agents_']; From 51ca2de1e544999e07eaa03ceda5544c0e27aab7 Mon Sep 17 00:00:00 2001 From: Calvo Date: Thu, 22 Jul 2021 11:34:07 +0200 Subject: [PATCH 04/92] Get command field if it is not defined in alert or action --- pandora_server/lib/PandoraFMS/Core.pm | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/pandora_server/lib/PandoraFMS/Core.pm b/pandora_server/lib/PandoraFMS/Core.pm index d4483046fa..61084010a3 100644 --- a/pandora_server/lib/PandoraFMS/Core.pm +++ b/pandora_server/lib/PandoraFMS/Core.pm @@ -1051,6 +1051,15 @@ sub pandora_execute_action ($$$$$$$$$;$) { my ($field1, $field2, $field3, $field4, $field5, $field6, $field7, $field8, $field9, $field10); my ($field11, $field12, $field13, $field14, $field15, $field16, $field17, $field18, $field19, $field20); + # Check for empty alert fields and assign command field. + my $index = 1; + my @command_fields = split(/,|\[|\]/, $action->{'fields_values'}); + foreach my $field (@command_fields) { + unless (defined($action->{'field'.$index}) && $action->{'field'.$index} ne "") { + $action->{'field'.$index} = defined($field) ? $field : "" ; + } + } + if (!defined($alert->{'snmp_alert'})) { # Regular alerts $field1 = defined($action->{'field1'}) && $action->{'field1'} ne "" ? $action->{'field1'} : $alert->{'field1'}; @@ -1097,6 +1106,8 @@ sub pandora_execute_action ($$$$$$$$$;$) { $field20 = defined($alert->{'field20'}) && $alert->{'field20'} ne "" ? $alert->{'field20'} : $action->{'field20'}; } + print Dumper($field1); + # Recovery fields, thanks to Kato Atsushi if ($alert_mode == RECOVERED_ALERT) { # Field 1 is a special case where [RECOVER] prefix is not added even when it is defined @@ -4145,9 +4156,9 @@ sub pandora_evaluate_snmp_alerts ($$$$$$$$$) { # Execute alert my $action = get_db_single_row ($dbh, 'SELECT * - FROM talert_actions, talert_commands - WHERE talert_actions.id_alert_command = talert_commands.id - AND talert_actions.id = ?', $alert->{'id_alert'}); + FROM talert_actions taa JOIN talert_commands tac + ON taa.id_alert_command = tac.id + WHERE tac.id = ?', $alert->{'id_alert'}); my $trap_rcv_full = $trap_oid . " " . $trap_value. " ". $trap_type. " " . $trap_custom_oid; From 72d57bc06704dd3540e75989a17723e1cdce5f84 Mon Sep 17 00:00:00 2001 From: Calvo Date: Thu, 22 Jul 2021 11:39:00 +0200 Subject: [PATCH 05/92] Get command field if it is not defined in alert or action --- pandora_server/lib/PandoraFMS/Core.pm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pandora_server/lib/PandoraFMS/Core.pm b/pandora_server/lib/PandoraFMS/Core.pm index 61084010a3..8a18caced9 100644 --- a/pandora_server/lib/PandoraFMS/Core.pm +++ b/pandora_server/lib/PandoraFMS/Core.pm @@ -1106,8 +1106,7 @@ sub pandora_execute_action ($$$$$$$$$;$) { $field20 = defined($alert->{'field20'}) && $alert->{'field20'} ne "" ? $alert->{'field20'} : $action->{'field20'}; } - print Dumper($field1); - + # Recovery fields, thanks to Kato Atsushi if ($alert_mode == RECOVERED_ALERT) { # Field 1 is a special case where [RECOVER] prefix is not added even when it is defined From ce765a5dbdd0b7e74ab3db245050d45867c99327 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Gonz=C3=A1lez?= Date: Thu, 29 Jul 2021 10:36:16 +0200 Subject: [PATCH 06/92] Fix module library --- pandora_console/include/styles/module_library.css | 4 ++-- pandora_console/include/styles/pandora.css | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pandora_console/include/styles/module_library.css b/pandora_console/include/styles/module_library.css index 2dac88304e..31dc57d9e3 100644 --- a/pandora_console/include/styles/module_library.css +++ b/pandora_console/include/styles/module_library.css @@ -110,7 +110,7 @@ /* --- Sidebar --- */ .sidebar_library { - min-width: 360px; + width: 240px; margin-left: 50px; border-left: 1px solid #d0d0d0; padding: 0px 0px 0px 30px; @@ -151,7 +151,7 @@ #category_result, #search_result { display: grid; - grid-template-columns: repeat(3, minmax(300px, 1fr)); + grid-template-columns: repeat(3, minmax(175px, 1fr)); grid-gap: 20px; } diff --git a/pandora_console/include/styles/pandora.css b/pandora_console/include/styles/pandora.css index 1e059ee78b..342dfc34fa 100644 --- a/pandora_console/include/styles/pandora.css +++ b/pandora_console/include/styles/pandora.css @@ -2990,7 +2990,7 @@ input.search_input { background-color: #f2f6f7; padding: 0px; margin: 0; - width: 300px; + width: 150px; height: 30px; margin-left: 2px; padding-left: 15px; From 9b736d0c48c3fd4cf759c2fd640f2d8fae61ada4 Mon Sep 17 00:00:00 2001 From: Calvo Date: Fri, 30 Jul 2021 13:49:22 +0200 Subject: [PATCH 07/92] Deleted and reubicated acl options --- .../extensions/users_connected.php | 2 +- pandora_console/godmode/menu.php | 7 +-- pandora_console/include/ajax/menu.ajax.php | 2 + pandora_console/include/functions_menu.php | 61 ++++++++++++++++--- pandora_console/operation/menu.php | 2 +- 5 files changed, 58 insertions(+), 16 deletions(-) diff --git a/pandora_console/extensions/users_connected.php b/pandora_console/extensions/users_connected.php index 884285dd28..2848d4be9b 100644 --- a/pandora_console/extensions/users_connected.php +++ b/pandora_console/extensions/users_connected.php @@ -159,7 +159,7 @@ function users_extension_main_god($god=true) } -extensions_add_operation_menu_option(__('Users connected'), 'workspace', 'users/icon.png', 'v1r1', '', 'UM'); +extensions_add_operation_menu_option(__('Users connected'), 'workspace', 'users/icon.png', 'v1r1', null, 'UM'); extensions_add_godmode_function('users_extension_main_god'); extensions_add_main_function('users_extension_main'); diff --git a/pandora_console/godmode/menu.php b/pandora_console/godmode/menu.php index f8996328b3..67428da474 100644 --- a/pandora_console/godmode/menu.php +++ b/pandora_console/godmode/menu.php @@ -458,9 +458,9 @@ if (is_array($config['extensions'])) { $menu_godmode[$extmenu['fatherId']]['sub'][$extmenu['sec2']]['refr'] = 0; $menu_godmode[$extmenu['fatherId']]['sub'][$extmenu['sec2']]['icon'] = $extmenu['icon']; if ($extmenu['name'] == 'Cron jobs') { - $menu_godmode[$extmenu['fatherId']]['sub'][$extmenu['sec2']]['sec'] = 'extensions'; + $menu_godmode[$extmenu['fatherId']]['sub'][$extmenu['sec2']]['sec'] = $extmenu['fatherId']; } else { - $menu_godmode[$extmenu['fatherId']]['sub'][$extmenu['sec2']]['sec'] = 'gextensions'; + $menu_godmode[$extmenu['fatherId']]['sub'][$extmenu['sec2']]['sec'] = $extmenu['fatherId']; } $menu_godmode[$extmenu['fatherId']]['sub'][$extmenu['sec2']]['extension'] = true; @@ -521,8 +521,8 @@ $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']['sec2'] = ''; $menu_godmode['messages']['id'] = 'god-um_messages'; + $menu_godmode['messages']['sec2'] = 'godmode/update_manager/update_manager'; $sub = []; if ($config['enterprise_installed']) { @@ -541,7 +541,6 @@ if (check_acl($config['id_user'], 0, 'PM') && $config['enable_update_manager']) // Module library. if (check_acl($config['id_user'], 0, 'AR')) { $menu_godmode['gmodule_library']['text'] = __('Module library'); - $menu_godmode['gmodule_library']['sec2'] = 'godmode/module_library/module_library_view'; $menu_godmode['gmodule_library']['id'] = 'god-module_library'; $sub = []; diff --git a/pandora_console/include/ajax/menu.ajax.php b/pandora_console/include/ajax/menu.ajax.php index 7b13f626f9..2ef22cd405 100644 --- a/pandora_console/include/ajax/menu.ajax.php +++ b/pandora_console/include/ajax/menu.ajax.php @@ -41,6 +41,8 @@ if ($get_sec_pages) { $pages = menu_get_sec_pages($sec, $menu_hash); } + $pages = menu_pepare_acl_select_data($pages, $sec); + echo json_encode($pages); return; } diff --git a/pandora_console/include/functions_menu.php b/pandora_console/include/functions_menu.php index 442a18f61f..432e350625 100644 --- a/pandora_console/include/functions_menu.php +++ b/pandora_console/include/functions_menu.php @@ -492,24 +492,16 @@ function menu_add_extras(&$menu) $menu_extra['gusuarios']['sub']['godmode/users/configure_user']['text'] = __('Configure user'); $menu_extra['gusuarios']['sub']['godmode/users/configure_profile']['text'] = __('Configure profile'); - $menu_extra['gservers']['sub']['godmode/servers/manage_recontask_form']['text'] = __('Manage recontask'); - $menu_extra['gmodules']['sub']['godmode/modules/manage_network_templates_form']['text'] = __('Module templates management'); $menu_extra['gmodules']['sub']['enterprise/godmode/modules/manage_inventory_modules_form']['text'] = __('Inventory modules management'); - $menu_extra['gmodules']['sub']['godmode/tag/edit_tag']['text'] = __('Tags management'); $menu_extra['gagente']['sub']['godmode/agentes/configurar_agente']['text'] = __('Agents management'); - $menu_extra['estado']['sub']['operation/agentes/ver_agente']['text'] = __('View agent'); - $menu_extra['galertas']['sub']['godmode/alerts/configure_alert_template']['text'] = __('Configure alert template'); - $menu_extra['network']['sub']['operation/agentes/networkmap']['text'] = __('Manage network map'); $menu_extra['network']['sub']['operation/visual_console/render_view']['text'] = __('View visual console'); $menu_extra['network']['sub']['godmode/reporting/visual_console_builder']['text'] = __('Builder visual console'); - $menu_extra['eventos']['sub']['godmode/events/events']['text'] = __('Administration events'); - $menu_extra['reporting']['sub']['operation/reporting/reporting_viewer']['text'] = __('View reporting'); $menu_extra['reporting']['sub']['operation/reporting/graph_viewer']['text'] = __('Graph viewer'); @@ -525,7 +517,6 @@ function menu_add_extras(&$menu) $menu_extra['godgismaps']['sub']['godmode/gis_maps/configure_gis_map']['text'] = __('Manage GIS Maps'); } - $menu_extra['workspace']['sub']['operation/incidents/incident_statistics']['text'] = __('Incidents statistics'); $menu_extra['workspace']['sub']['operation/messages/message_edit']['text'] = __('Manage messages'); $menu_extra['gagente']['sub']['godmode/groups/configure_group']['text'] = __('Manage groups'); @@ -534,7 +525,6 @@ function menu_add_extras(&$menu) $menu_extra['galertas']['sub']['godmode/alerts/configure_alert_action']['text'] = __('Manage alert actions'); $menu_extra['galertas']['sub']['godmode/alerts/configure_alert_command']['text'] = __('Manage commands'); - $menu_extra['galertas']['sub']['enterprise/godmode/alerts/alert_correlation']['text'] = __('Manage event alerts'); $menu_extra['gservers']['sub']['enterprise/godmode/servers/manage_export_form']['text'] = __('Manage export targets'); @@ -597,6 +587,10 @@ function menu_get_sec($with_categories=false) } } + if ($k === 'discovery') { + $in_godmode = true; + } + if ($in_godmode) { $category = __('Administration'); } else { @@ -673,6 +667,9 @@ function menu_get_sec_pages($sec, $menu_hash=false) // If this value has various parameters, we only get the first. $k = explode('&', $k); $k = $k[0]; + if (is_array($v['text']) === true) { + $v['text'] = $v['text'][0]; + } $sec2_array[$k] = $v['text']; } @@ -754,3 +751,47 @@ function menu_sec3_in_sec2($sec, $sec2, $sec3) return false; } + + +/** + * Prepare menu data for enterprise acl conf. + * + * @param array $pages + * @param string $sec + * @return string $pages + */ +function menu_pepare_acl_select_data($pages, $sec) +{ + $exclude_pages = [ + 'estado' => 'operation/agentes/tactical', + 'network' => 'operation/agentes/networkmap_list', + 'extensions' => [ + 'operation/extensions', + 'enterprise/extensions/vmware', + 'extensions/users_connected', + ], + 'gmodules' => 'godmode/modules/manage_network_templates', + 'geventos' => 'godmode/events/events&section=filter', + 'gsetup' => 'godmode/setup/setup§ion=general', + 'messages' => [ + 'godmode/update_manager/update_manager&tab=online', + 'godmode/update_manager/update_manager&tab=offline', + 'godmode/update_manager/update_manager&tab=setup', + ], + + ]; + + foreach ($exclude_pages as $exclude_sec => $sec2) { + if ($sec === $exclude_sec) { + if (is_array($sec2) === true) { + foreach ($sec2 as $value) { + unset($pages[$value]); + } + } + + unset($pages[$sec2]); + } + } + + return $pages; +} diff --git a/pandora_console/operation/menu.php b/pandora_console/operation/menu.php index 1d8178f1af..08cc0b0b57 100644 --- a/pandora_console/operation/menu.php +++ b/pandora_console/operation/menu.php @@ -545,7 +545,7 @@ if (is_array($config['extensions'])) { if (array_key_exists('fatherId', $extension_menu)) { // Check that extension father ID exists previously on the menu. if ((strlen($extension_menu['fatherId']) > 0)) { - if (array_key_exists('subfatherId', $extension_menu)) { + if (array_key_exists('subfatherId', $extension_menu) && empty($extension_menu['subfatherId']) === false) { if ((strlen($extension_menu['subfatherId']) > 0)) { $menu_operation[$extension_menu['fatherId']]['sub'][$extension_menu['subfatherId']]['sub2'][$extension_menu['sec2']]['text'] = __($extension_menu['name']); $menu_operation[$extension_menu['fatherId']]['sub'][$extension_menu['subfatherId']]['sub2'][$extension_menu['sec2']]['id'] = $extension_menu['name']; From 9d04933ca2b53bb0f657de0f66785f8d386d5300 Mon Sep 17 00:00:00 2001 From: Calvo Date: Fri, 6 Aug 2021 10:29:38 +0200 Subject: [PATCH 08/92] Added missing sec related to GET params to ACL enterprise --- pandora_console/godmode/menu.php | 60 +++++++++++----------- pandora_console/include/ajax/menu.ajax.php | 2 + pandora_console/include/functions_menu.php | 44 +++++++++++----- 3 files changed, 63 insertions(+), 43 deletions(-) diff --git a/pandora_console/godmode/menu.php b/pandora_console/godmode/menu.php index f8996328b3..a96d7c8238 100644 --- a/pandora_console/godmode/menu.php +++ b/pandora_console/godmode/menu.php @@ -250,20 +250,20 @@ if (check_acl($config['id_user'], 0, 'LW') $sub = []; if (check_acl($config['id_user'], 0, 'EW') || check_acl($config['id_user'], 0, 'EM')) { // Custom event fields - $sub['godmode/events/events&section=filter']['text'] = __('Event filters'); - $sub['godmode/events/events&section=filter']['id'] = 'Event filters'; + $sub['godmode/events/events§ion=filter']['text'] = __('Event filters'); + $sub['godmode/events/events§ion=filter']['id'] = 'Event filters'; } if (check_acl($config['id_user'], 0, 'PM')) { - $sub['godmode/events/events&section=fields']['text'] = __('Custom events'); - $sub['godmode/events/events&section=fields']['id'] = 'Custom events'; - $sub['godmode/events/events&section=responses']['text'] = __('Event responses'); - $sub['godmode/events/events&section=responses']['id'] = 'Event responses'; + $sub['godmode/events/events§ion=fields']['text'] = __('Custom events'); + $sub['godmode/events/events§ion=fields']['id'] = 'Custom events'; + $sub['godmode/events/events§ion=responses']['text'] = __('Event responses'); + $sub['godmode/events/events§ion=responses']['id'] = 'Event responses'; } if (!empty($sub)) { $menu_godmode['geventos']['text'] = __('Events'); - $menu_godmode['geventos']['sec2'] = 'godmode/events/events&section=filter'; + $menu_godmode['geventos']['sec2'] = 'godmode/events/events§ion=filter'; $menu_godmode['geventos']['id'] = 'god-events'; $menu_godmode['geventos']['sub'] = $sub; } @@ -303,7 +303,7 @@ if (check_acl($config['id_user'], 0, 'AW') || check_acl($config['id_user'], 0, ' if (check_acl($config['id_user'], 0, 'PM')) { // Setup $menu_godmode['gsetup']['text'] = __('Setup'); - $menu_godmode['gsetup']['sec2'] = 'godmode/setup/setup§ion=general'; + $menu_godmode['gsetup']['sec2'] = 'general'; $menu_godmode['gsetup']['id'] = 'god-setup'; $sub = []; @@ -315,50 +315,50 @@ if (check_acl($config['id_user'], 0, 'PM')) { $sub['general']['subtype'] = 'nolink'; $sub2 = []; - $sub2['godmode/setup/setup&section=general']['text'] = __('General Setup'); - $sub2['godmode/setup/setup&section=general']['id'] = 'General Setup'; - $sub2['godmode/setup/setup&section=general']['refr'] = 0; + $sub2['godmode/setup/setup§ion=general']['text'] = __('General Setup'); + $sub2['godmode/setup/setup§ion=general']['id'] = 'General Setup'; + $sub2['godmode/setup/setup§ion=general']['refr'] = 0; enterprise_hook('password_submenu'); enterprise_hook('enterprise_submenu'); enterprise_hook('historydb_submenu'); enterprise_hook('log_collector_submenu'); - $sub2['godmode/setup/setup&section=auth']['text'] = __('Authentication'); - $sub2['godmode/setup/setup&section=auth']['refr'] = 0; + $sub2['godmode/setup/setup§ion=auth']['text'] = __('Authentication'); + $sub2['godmode/setup/setup§ion=auth']['refr'] = 0; - $sub2['godmode/setup/setup&section=perf']['text'] = __('Performance'); - $sub2['godmode/setup/setup&section=perf']['refr'] = 0; + $sub2['godmode/setup/setup§ion=perf']['text'] = __('Performance'); + $sub2['godmode/setup/setup§ion=perf']['refr'] = 0; - $sub2['godmode/setup/setup&section=vis']['text'] = __('Visual styles'); - $sub2['godmode/setup/setup&section=vis']['refr'] = 0; + $sub2['godmode/setup/setup§ion=vis']['text'] = __('Visual styles'); + $sub2['godmode/setup/setup§ion=vis']['refr'] = 0; if (check_acl($config['id_user'], 0, 'AW')) { if ($config['activate_netflow']) { - $sub2['godmode/setup/setup&section=net']['text'] = __('Netflow'); - $sub2['godmode/setup/setup&section=net']['refr'] = 0; + $sub2['godmode/setup/setup§ion=net']['text'] = __('Netflow'); + $sub2['godmode/setup/setup§ion=net']['refr'] = 0; } } - $sub2['godmode/setup/setup&section=ehorus']['text'] = __('eHorus'); - $sub2['godmode/setup/setup&section=ehorus']['refr'] = 0; + $sub2['godmode/setup/setup§ion=ehorus']['text'] = __('eHorus'); + $sub2['godmode/setup/setup§ion=ehorus']['refr'] = 0; - $sub2['godmode/setup/setup&section=integria']['text'] = __('Integria IMS'); - $sub2['godmode/setup/setup&section=integria']['refr'] = 0; + $sub2['godmode/setup/setup§ion=integria']['text'] = __('Integria IMS'); + $sub2['godmode/setup/setup§ion=integria']['refr'] = 0; enterprise_hook('module_library_submenu'); - $sub2['godmode/setup/setup&section=notifications']['text'] = __('Notifications'); - $sub2['godmode/setup/setup&section=notifications']['refr'] = 0; + $sub2['godmode/setup/setup§ion=notifications']['text'] = __('Notifications'); + $sub2['godmode/setup/setup§ion=notifications']['refr'] = 0; - $sub2['godmode/setup/setup&section=websocket_engine']['text'] = __('Websocket Engine'); - $sub2['godmode/setup/setup&section=websocket_engine']['refr'] = 0; + $sub2['godmode/setup/setup§ion=websocket_engine']['text'] = __('Websocket Engine'); + $sub2['godmode/setup/setup§ion=websocket_engine']['refr'] = 0; - $sub2['godmode/setup/setup&section=external_tools']['text'] = __('External Tools'); - $sub2['godmode/setup/setup&section=external_tools']['refr'] = 0; + $sub2['godmode/setup/setup§ion=external_tools']['text'] = __('External Tools'); + $sub2['godmode/setup/setup§ion=external_tools']['refr'] = 0; if ($config['activate_gis']) { - $sub2['godmode/setup/setup&section=gis']['text'] = __('Map conections GIS'); + $sub2['godmode/setup/setup§ion=gis']['text'] = __('Map conections GIS'); } $sub['general']['sub2'] = $sub2; diff --git a/pandora_console/include/ajax/menu.ajax.php b/pandora_console/include/ajax/menu.ajax.php index 7b13f626f9..2ef22cd405 100644 --- a/pandora_console/include/ajax/menu.ajax.php +++ b/pandora_console/include/ajax/menu.ajax.php @@ -41,6 +41,8 @@ if ($get_sec_pages) { $pages = menu_get_sec_pages($sec, $menu_hash); } + $pages = menu_pepare_acl_select_data($pages, $sec); + echo json_encode($pages); return; } diff --git a/pandora_console/include/functions_menu.php b/pandora_console/include/functions_menu.php index 442a18f61f..7a748c08c1 100644 --- a/pandora_console/include/functions_menu.php +++ b/pandora_console/include/functions_menu.php @@ -667,13 +667,11 @@ function menu_get_sec_pages($sec, $menu_hash=false) foreach ($menu[$sec]['sub'] as $k => $v) { // Avoid special cases of standalone windows. if (preg_match('/^javascript:/', $k) || preg_match('/\.php/', $k)) { - continue; + if ($sec !== 'links') { + continue; + } } - // If this value has various parameters, we only get the first. - $k = explode('&', $k); - $k = $k[0]; - $sec2_array[$k] = $v['text']; } } @@ -704,6 +702,7 @@ function menu_get_sec2_pages($sec, $sec2, $menu_hash=false) } $sec3_array = []; + $sec2 = io_safe_output($sec2); if (isset($menu[$sec]['sub']) && isset($menu[$sec]['sub'][$sec2]['sub2'])) { // Get the sec2 of the subsections. @@ -728,10 +727,6 @@ function menu_sec2_in_sec($sec, $sec2) { $sec2_array = menu_get_sec_pages($sec); - // If this value has various parameters, we only get the first. - $sec2 = explode('&', $sec2); - $sec2 = $sec2[0]; - if ($sec2_array != null && in_array($sec2, array_keys($sec2_array))) { return true; } @@ -744,13 +739,36 @@ function menu_sec3_in_sec2($sec, $sec2, $sec3) { $sec3_array = menu_get_sec2_pages($sec, $sec2, $menu_hash = false); - // If this value has various parameters, we only get the first. - $sec3 = explode('&', $sec3); - $sec3 = $sec3[0]; - if ($sec3_array != null && in_array($sec3, array_keys($sec3_array))) { return true; } return false; } + + +/** + * Prepare menu data for enterprise acl conf. + * + * @param array $pages + * @param string $sec + * @return string $pages + */ +function menu_pepare_acl_select_data($pages, $sec) +{ + $exclude_pages = ['discovery' => 'godmode/servers/discovery']; + + foreach ($exclude_pages as $exclude_sec => $sec2) { + if ($sec === $exclude_sec) { + if (is_array($sec2) === true) { + foreach ($sec2 as $value) { + unset($pages[$value]); + } + } + + unset($pages[$sec2]); + } + } + + return $pages; +} From fcbd69c6039bcc0ba81e5b7caa61a76848ea4383 Mon Sep 17 00:00:00 2001 From: Calvo Date: Thu, 12 Aug 2021 14:16:25 +0200 Subject: [PATCH 09/92] Deleted js traces --- pandora_console/include/javascript/pandora_alerts.js | 1 - pandora_console/operation/agentes/estado_agente.php | 1 - 2 files changed, 2 deletions(-) diff --git a/pandora_console/include/javascript/pandora_alerts.js b/pandora_console/include/javascript/pandora_alerts.js index f6e8f3857d..7ecded70c8 100644 --- a/pandora_console/include/javascript/pandora_alerts.js +++ b/pandora_console/include/javascript/pandora_alerts.js @@ -12,7 +12,6 @@ function parse_alert_command(command, classs) { // Only render values different from '' var field = "_field" + nfield + "_"; var regex = new RegExp(field, "gi"); - console.log($(this).val()); if ($(this).val() == "") { if ( classs == "fields_recovery" && diff --git a/pandora_console/operation/agentes/estado_agente.php b/pandora_console/operation/agentes/estado_agente.php index 377cff3d4d..1127cd59b5 100644 --- a/pandora_console/operation/agentes/estado_agente.php +++ b/pandora_console/operation/agentes/estado_agente.php @@ -982,7 +982,6 @@ if (!empty($table->data)) { \ No newline at end of file + From 7daf138ef5872e662d56628ab844522d304b79a2 Mon Sep 17 00:00:00 2001 From: Calvo Date: Mon, 18 Oct 2021 15:47:22 +0200 Subject: [PATCH 25/92] Fix recursion and filter on modules massive operations --- pandora_console/include/javascript/pandora.js | 3 ++- pandora_console/operation/agentes/ver_agente.php | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pandora_console/include/javascript/pandora.js b/pandora_console/include/javascript/pandora.js index 0e545e9f4e..5b96a8fcd6 100644 --- a/pandora_console/include/javascript/pandora.js +++ b/pandora_console/include/javascript/pandora.js @@ -134,7 +134,8 @@ function agent_changed_by_multiple_agents(event, id_agent, selected) { $("input.module_types_excluded").each(function(index, el) { var module_type = parseInt($(el).val()); - if (module_type !== NaN) module_types_excluded.push(module_type); + if (isNaN(module_type) == false) + module_types_excluded.push(module_type); }); } catch (error) {} } diff --git a/pandora_console/operation/agentes/ver_agente.php b/pandora_console/operation/agentes/ver_agente.php index 1f47f75d17..2293a6044a 100644 --- a/pandora_console/operation/agentes/ver_agente.php +++ b/pandora_console/operation/agentes/ver_agente.php @@ -91,7 +91,7 @@ if (is_ajax()) { if ($get_agents_group_json) { $id_group = (int) get_parameter('id_group'); - $recursion = (get_parameter_switch('recursion', 'false') === 'true'); + $recursion = filter_var(get_parameter_switch('recursion', 'false'), FILTER_VALIDATE_BOOLEAN); $id_os = get_parameter('id_os', ''); $agent_name = get_parameter('name', ''); @@ -801,7 +801,7 @@ if (is_ajax()) { } } else { $sql = sprintf( - 'SELECT DISTINCT t1.nombre, t1.id_agente_modulo FROM tagente_modulo t1 + 'SELECT t1.nombre, t1.id_agente_modulo FROM tagente_modulo t1 INNER JOIN tagente_estado t2 ON t1.id_agente_modulo = t2.id_agente_modulo %s WHERE %s AND t1.delete_pending = 0 AND t1.id_agente IN ('.implode(',', $idAgents).') From c8a11543e8a5c837fbe554a48d9c1b4be452bf45 Mon Sep 17 00:00:00 2001 From: Daniel Maya Date: Mon, 18 Oct 2021 16:36:10 +0200 Subject: [PATCH 26/92] #8111 Fixed X-Frame-Options --- pandora_console/.htaccess | 3 +++ pandora_console/index.php | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pandora_console/.htaccess b/pandora_console/.htaccess index ca572f7df1..0d2cae3781 100644 --- a/pandora_console/.htaccess +++ b/pandora_console/.htaccess @@ -1,6 +1,9 @@ # pandora disable listing Options -Indexes +# Avoid clickjacking +Header always append X-Frame-Options SAMEORIGIN + Order Allow,Deny Deny from All diff --git a/pandora_console/index.php b/pandora_console/index.php index 548991159e..d6d3be20e0 100755 --- a/pandora_console/index.php +++ b/pandora_console/index.php @@ -220,8 +220,6 @@ echo ''."\n"; // This starts the page head. In the callback function, // $page['head'] array content will be processed into the head. ob_start('ui_process_page_head'); -// Avoid clickjacking. -header('X-Frame-Options: SAMEORIGIN'); // Enterprise main. enterprise_include_once('index.php'); From dc3e6905024822f7700f3c7e0ebabbf190d7593a Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Mon, 18 Oct 2021 17:24:41 +0200 Subject: [PATCH 27/92] Fixed issue with OK label --- pandora_console/include/class/AgentsAlerts.class.php | 1 + 1 file changed, 1 insertion(+) diff --git a/pandora_console/include/class/AgentsAlerts.class.php b/pandora_console/include/class/AgentsAlerts.class.php index 5e0861ed6c..bb5c11b8d9 100644 --- a/pandora_console/include/class/AgentsAlerts.class.php +++ b/pandora_console/include/class/AgentsAlerts.class.php @@ -831,6 +831,7 @@ class AgentsAlerts extends HTML 'arguments' => [ 'type' => 'button', 'return' => true, + 'label' => '', 'name' => 'pure', 'attributes' => 'class="full_screen_button '.$screenSwitchClass.'" title="'.$screenSwitchTitle.'"', ], From 05e352e9cf513e65fc96a59c34292bb8d7290359 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Tue, 19 Oct 2021 11:11:58 +0200 Subject: [PATCH 28/92] Fixed issue with class --- pandora_console/include/styles/pandora_black.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pandora_console/include/styles/pandora_black.css b/pandora_console/include/styles/pandora_black.css index f8848da4c4..42af9e36c6 100644 --- a/pandora_console/include/styles/pandora_black.css +++ b/pandora_console/include/styles/pandora_black.css @@ -58,7 +58,8 @@ input.sub, button.sub, .bg_general, .show_result_interpreter, -div#rules::after table.agent_info_table thead > tr:first-child th, +div#rules::after, +table.agent_info_table thead > tr:first-child th, table.agent_info_table tr { background-color: #222 !important; color: #fff !important; From 0b033dae7412768c907e24de817a9577e838a367 Mon Sep 17 00:00:00 2001 From: "alejandro.campos@artica.es" Date: Tue, 19 Oct 2021 15:32:22 +0200 Subject: [PATCH 29/92] add capability to upload files in ticket creation and update on Integria integration system --- .../include/functions_integriaims.php | 46 +++++++++++++++++ .../configure_integriaims_incident.php | 26 +++++++++- .../dashboard_detail_integriaims_incident.php | 49 +++---------------- 3 files changed, 76 insertions(+), 45 deletions(-) diff --git a/pandora_console/include/functions_integriaims.php b/pandora_console/include/functions_integriaims.php index f9e387c6de..af8d8c08df 100644 --- a/pandora_console/include/functions_integriaims.php +++ b/pandora_console/include/functions_integriaims.php @@ -454,3 +454,49 @@ function get_tickets_integriaims($tickets_filters) return $array_get_incidents; } + + +function integriaims_upload_file($filename, $incident_id, $file_description) +{ + hd('aqui0', true); + hd($_FILES, true); + if ($_FILES[$filename]['name'] != '') { + $filename = io_safe_input($_FILES[$filename]['name']); + $filesize = io_safe_input($_FILES[$filename]['size']); + + $extension = pathinfo($filename, PATHINFO_EXTENSION); + $invalid_extensions = '/^(bat|exe|cmd|sh|php|php1|php2|php3|php4|php5|pl|cgi|386|dll|com|torrent|js|app|jar|iso| + pif|vb|vbscript|wsf|asp|cer|csr|jsp|drv|sys|ade|adp|bas|chm|cpl|crt|csh|fxp|hlp|hta|inf|ins|isp|jse|htaccess| + htpasswd|ksh|lnk|mdb|mde|mdt|mdw|msc|msi|msp|mst|ops|pcd|prg|reg|scr|sct|shb|shs|url|vbe|vbs|wsc|wsf|wsh)$/i'; + hd('aqui1', true); + if (!preg_match($invalid_extensions, $extension)) { + hd('aqui2', true); + // The following is if you have clamavlib installed. + // (php5-clamavlib) and enabled in php.ini + // http://www.howtoforge.com/scan_viruses_with_php_clamavlib + if (extension_loaded('clamav')) { + cl_setlimits(5, 1000, 200, 0, 10485760); + $malware = cl_scanfile($_FILES['file']['tmp_name']); + if ($malware) { + $error = 'Malware detected: '.$malware.'
ClamAV version: '.clam_get_version(); + die($error); + } + } + + $filecontent = base64_encode(file_get_contents($_FILES[$filename]['tmp_name'])); + hd($filecontent, true); + $result_api_call = integria_api_call(null, null, null, null, 'attach_file', [$incident_id, $filename, $filesize, $file_description, $filecontent], false, '', '|;|'); + + // API method returns '0' string if success. + $file_added = ($result_api_call === '0') ? true : false; + + ui_print_result_message( + $file_added, + __('File successfully added'), + __('File could not be added') + ); + } else { + ui_print_error_message(__('File has an invalid extension')); + } + } +} diff --git a/pandora_console/operation/incidents/configure_integriaims_incident.php b/pandora_console/operation/incidents/configure_integriaims_incident.php index 5ac33db935..01c9ea5737 100644 --- a/pandora_console/operation/incidents/configure_integriaims_incident.php +++ b/pandora_console/operation/incidents/configure_integriaims_incident.php @@ -90,6 +90,7 @@ $incident_creator = get_parameter('creator'); $incident_status = (int) get_parameter('status'); $incident_title = events_get_field_value_by_event_id($event_id, get_parameter('incident_title')); $incident_content = events_get_field_value_by_event_id($event_id, get_parameter('incident_content')); +$file_description = get_parameter('file_description'); // Separator conversions. $incident_title = str_replace(',', ':::', $incident_title); @@ -100,7 +101,11 @@ if ($create_incident === true) { // Call Integria IMS API method to create an incident. $result_api_call = integria_api_call(null, null, null, null, 'create_incident', [$incident_title, $incident_group_id, $incident_criticity_id, $incident_content, '', $incident_type, '', $incident_owner, '0', $incident_status], false, '', ','); - // Necessary to explicitly set true if not false because function returns api call result in case of success instead of true value. + if ($userfile !== '' && $result_api_call !== false) { + integriaims_upload_file('userfile', $result_api_call, $file_description); + } + + // Necessary to explicitly set true if not false because function returns result of api call in case of success instead of true value. $incident_created_ok = ($result_api_call != false) ? true : false; ui_print_result_message( @@ -112,6 +117,10 @@ if ($create_incident === true) { // Call Integria IMS API method to update an incident. $result_api_call = integria_api_call(null, null, null, null, 'update_incident', [$incident_id_edit, $incident_title, $incident_content, '', $incident_group_id, $incident_criticity_id, 0, $incident_status, $incident_owner, 0, $incident_type], false, '', ','); + if ($userfile !== '') { + integriaims_upload_file('userfile', $incident_id_edit, $file_description); + } + // Necessary to explicitly set true if not false because function returns api call result in case of success instead of true value. $incident_updated_ok = ($result_api_call != false) ? true : false; @@ -153,6 +162,7 @@ $table->style[1] = 'width: 33%; padding-right: 50px; padding-left: 50px;'; $table->style[2] = 'width: 33%; padding-right: 100px; padding-left: 50px;'; $table->colspan[0][0] = 2; $table->colspan[3][0] = 3; +$table->colspan[5][0] = 3; $help_macros = isset($_GET['from_event']) ? ui_print_help_icon('response_macros', true) : ''; @@ -303,8 +313,20 @@ $table->data[3][0] .= '
'.html_print_textarea( true ).'
'; +$table->data[4][0] = '

'.__('File name').':

'; +$table->data[4][0] .= html_print_input_file('userfile', true); +$table->data[5][0] = '

'.__('Description').':

'; +$table->data[5][0] .= html_print_textarea( + 'file_description', + 3, + 20, + '', + '', + true +); + // Print forms and stuff. -echo '
'; +echo ''; html_print_table($table); if (!$update) { diff --git a/pandora_console/operation/incidents/dashboard_detail_integriaims_incident.php b/pandora_console/operation/incidents/dashboard_detail_integriaims_incident.php index 9229ffdd90..7839ad1f07 100644 --- a/pandora_console/operation/incidents/dashboard_detail_integriaims_incident.php +++ b/pandora_console/operation/incidents/dashboard_detail_integriaims_incident.php @@ -90,7 +90,7 @@ $resolution_text = integriaims_get_details('resolution', $resolution); $type_text = integriaims_get_details('type', $type); // Incident file management. -$upload_file = get_parameter('upload_file'); +$upload_file = (bool) get_parameter('upload_file'); $delete_file_id = get_parameter('delete_file'); $download_file_id = get_parameter('download_file'); $download_file_name = get_parameter('download_file_name'); @@ -121,47 +121,10 @@ $table_files->head[5] = __('Delete'); $table_files->data = []; -// Upload file. -if ($upload_file && ($_FILES['userfile']['name'] != '')) { - $filedescription = get_parameter('file_description', __('No description available')); +$filedescription = get_parameter('file_description', __('No description available')); - $filename = io_safe_input($_FILES['userfile']['name']); - $filesize = io_safe_input($_FILES['userfile']['size']); - - $extension = pathinfo($filename, PATHINFO_EXTENSION); - $invalid_extensions = '/^(bat|exe|cmd|sh|php|php1|php2|php3|php4|php5|pl|cgi|386|dll|com|torrent|js|app|jar|iso| - pif|vb|vbscript|wsf|asp|cer|csr|jsp|drv|sys|ade|adp|bas|chm|cpl|crt|csh|fxp|hlp|hta|inf|ins|isp|jse|htaccess| - htpasswd|ksh|lnk|mdb|mde|mdt|mdw|msc|msi|msp|mst|ops|pcd|prg|reg|scr|sct|shb|shs|url|vbe|vbs|wsc|wsf|wsh)$/i'; - - if (!preg_match($invalid_extensions, $extension)) { - // The following is if you have clamavlib installed. - // (php5-clamavlib) and enabled in php.ini - // http://www.howtoforge.com/scan_viruses_with_php_clamavlib - if (extension_loaded('clamav')) { - cl_setlimits(5, 1000, 200, 0, 10485760); - $malware = cl_scanfile($_FILES['file']['tmp_name']); - if ($malware) { - $error = 'Malware detected: '.$malware.'
ClamAV version: '.clam_get_version(); - die($error); - // On malware, we die because it's not good to handle it - } - } - - $filecontent = base64_encode(file_get_contents($_FILES['userfile']['tmp_name'])); - - $result_api_call = integria_api_call(null, null, null, null, 'attach_file', [$incident_id, $filename, $filesize, $filedescription, $filecontent], false, '', '|;|'); - - // API method returns '0' string if success. - $file_added = ($result_api_call === '0') ? true : false; - - ui_print_result_message( - $file_added, - __('File successfully added'), - __('File could not be added') - ); - } else { - ui_print_error_message(__('File has an invalid extension')); - } +if ($upload_file === true) { + integriaims_upload_file('userfile', $incident_id, $filedescription); } // Delete file. @@ -252,11 +215,11 @@ $table_files_section->data[1][0] .= html_print_textarea( true ); -$table_files_section->data[2][0] .= '
'.html_print_submit_button(__('Upload'), 'accion', false, 'class="sub wand"', true).'
'; +$table_files_section->data[2][0] .= '
'.html_print_submit_button(__('Upload2'), 'accion', false, 'class="sub wand"', true).'
'; $upload_file_form = '
'; -$upload_file_form .= ''.'

'.__('Add attachment').'

'.html_print_table($table_files_section, true).html_print_input_hidden('upload_file', 1, true); +$upload_file_form .= ''.'

'.__('Add attachment1').'

'.html_print_table($table_files_section, true).html_print_input_hidden('upload_file', true, true); $upload_file_form .= '

'.__('Attached files').'

'.html_print_table($table_files, true).'
'; From 79316680219bf12fff3cee8a39fbeec1fc09dea8 Mon Sep 17 00:00:00 2001 From: "alejandro.campos@artica.es" Date: Tue, 19 Oct 2021 15:34:17 +0200 Subject: [PATCH 30/92] add capability to upload files in ticket creation and update on Integria integration system --- pandora_console/include/functions_integriaims.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/pandora_console/include/functions_integriaims.php b/pandora_console/include/functions_integriaims.php index af8d8c08df..af04f5064d 100644 --- a/pandora_console/include/functions_integriaims.php +++ b/pandora_console/include/functions_integriaims.php @@ -458,8 +458,6 @@ function get_tickets_integriaims($tickets_filters) function integriaims_upload_file($filename, $incident_id, $file_description) { - hd('aqui0', true); - hd($_FILES, true); if ($_FILES[$filename]['name'] != '') { $filename = io_safe_input($_FILES[$filename]['name']); $filesize = io_safe_input($_FILES[$filename]['size']); @@ -468,9 +466,8 @@ function integriaims_upload_file($filename, $incident_id, $file_description) $invalid_extensions = '/^(bat|exe|cmd|sh|php|php1|php2|php3|php4|php5|pl|cgi|386|dll|com|torrent|js|app|jar|iso| pif|vb|vbscript|wsf|asp|cer|csr|jsp|drv|sys|ade|adp|bas|chm|cpl|crt|csh|fxp|hlp|hta|inf|ins|isp|jse|htaccess| htpasswd|ksh|lnk|mdb|mde|mdt|mdw|msc|msi|msp|mst|ops|pcd|prg|reg|scr|sct|shb|shs|url|vbe|vbs|wsc|wsf|wsh)$/i'; - hd('aqui1', true); + if (!preg_match($invalid_extensions, $extension)) { - hd('aqui2', true); // The following is if you have clamavlib installed. // (php5-clamavlib) and enabled in php.ini // http://www.howtoforge.com/scan_viruses_with_php_clamavlib @@ -484,7 +481,7 @@ function integriaims_upload_file($filename, $incident_id, $file_description) } $filecontent = base64_encode(file_get_contents($_FILES[$filename]['tmp_name'])); - hd($filecontent, true); + $result_api_call = integria_api_call(null, null, null, null, 'attach_file', [$incident_id, $filename, $filesize, $file_description, $filecontent], false, '', '|;|'); // API method returns '0' string if success. From 9699b368ef13a135762ce38de18ade2ba6b9c3b3 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Tue, 19 Oct 2021 16:56:54 +0200 Subject: [PATCH 31/92] Fixed visual issues and handle browser zoom --- pandora_console/include/styles/pandora.css | 5 ++--- pandora_console/operation/menu.php | 9 ++++++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/pandora_console/include/styles/pandora.css b/pandora_console/include/styles/pandora.css index e07cae0d09..45d80286e3 100644 --- a/pandora_console/include/styles/pandora.css +++ b/pandora_console/include/styles/pandora.css @@ -6150,9 +6150,8 @@ div.graph div.legend table { .sound_events { background-color: #494949; - max-width: 550px; - max-height: 400px; - margin-top: 40px; + margin: 40px 2em 0; + min-height: auto; } .w16px { diff --git a/pandora_console/operation/menu.php b/pandora_console/operation/menu.php index 1d8178f1af..d467001178 100644 --- a/pandora_console/operation/menu.php +++ b/pandora_console/operation/menu.php @@ -427,11 +427,18 @@ if (check_acl($config['id_user'], 0, 'ER') From b61e7c6c5804ee83b798165c4b57859899bdae52 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Tue, 19 Oct 2021 17:04:39 +0200 Subject: [PATCH 32/92] Fixed visual with browsers with more zoom --- pandora_console/operation/menu.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandora_console/operation/menu.php b/pandora_console/operation/menu.php index d467001178..880c9240c6 100644 --- a/pandora_console/operation/menu.php +++ b/pandora_console/operation/menu.php @@ -433,7 +433,7 @@ if (check_acl($config['id_user'], 0, 'ER') var defaultHeight = 450; // If the scale is 1, no zoom has been applied. var windowWidth = windowScale <= 1 ? defaultWidth : windowScale*defaultWidth; - var windowHeight = windowScale <= 1 ? defaultHeight : windowScale*defaultHeight; + var windowHeight = windowScale <= 1 ? defaultHeight : windowScale*defaultHeight + (defaultHeight*0.1); window.open( url, From 070c920e0ed964c90c58e8b7a7993fb4288d2976 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Wed, 20 Oct 2021 13:01:13 +0200 Subject: [PATCH 33/92] Fixed tip position and code style --- .../operation/agentes/status_monitor.php | 51 ++++++++++--------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/pandora_console/operation/agentes/status_monitor.php b/pandora_console/operation/agentes/status_monitor.php index 25d0ba31cb..aba4c170c5 100644 --- a/pandora_console/operation/agentes/status_monitor.php +++ b/pandora_console/operation/agentes/status_monitor.php @@ -769,39 +769,42 @@ if ($not_condition !== '') { $check_not_condition = true; } -$table->data[4][0] .= __('Not condition'); - $table->data[4][1] .= '
'; - $table->data[4][1] .= html_print_input( +$table->data[4][0] .= __('Not condition').' '.ui_print_help_tip(__('If you check this option, those elements that do NOT meet any of the requirements will be shown'), true); + $table->data[4][1] = html_print_div( [ - 'type' => 'switch', - 'name' => 'not_condition', - 'return' => false, - 'checked' => $check_not_condition, - 'value' => 'NOT', - 'id' => 'not_condition_switch', - 'onclick' => 'changeNotConditionStatus(this)', - ] + 'class' => 'w120px mrgn_5px mrgn_lft_0px mrgn_right_0px', + 'content' => html_print_input( + [ + 'type' => 'switch', + 'name' => 'not_condition', + 'return' => false, + 'checked' => $check_not_condition, + 'value' => 'NOT', + 'id' => 'not_condition_switch', + 'onclick' => 'changeNotConditionStatus(this)', + ] + ), + ], + true ); - $table->data[4][1] .= ui_print_help_tip(__('If you check this option, those elements that do NOT meet any of the requirements will be shown'), true); - $table->data[4][1] .= '
'; $table_custom_fields = new stdClass(); $table_custom_fields->class = 'filters'; $table_custom_fields->width = '100%'; + $table_custom_fields->style = []; + $table_custom_fields->style[0] = 'font-weight: bold;'; - if (is_metaconsole()) { + // Style is different in metaconsole. + if (is_metaconsole() === false) { + $table_custom_fields->style[0] = 'font-weight: bold; width: 150px;'; + } + + if (is_metaconsole() === true) { $table_custom_fields->styleTable = 'margin-left:0px; margin-top:15px;'; $table_custom_fields->cellpadding = '0'; $table_custom_fields->cellspacing = '0'; } - $table_custom_fields->style = []; - if (!is_metaconsole()) { - $table_custom_fields->style[0] = 'font-weight: bold; width: 150px;'; - } else { - $table_custom_fields->style[0] = 'font-weight: bold;'; - } - $table_custom_fields->colspan = []; $table_custom_fields->data = []; @@ -815,9 +818,9 @@ $table->data[4][0] .= __('Not condition'); $row[0] = $custom_field['name']; $custom_field_value = ''; - if (!empty($ag_custom_fields)) { + if (empty($ag_custom_fields) === false) { $custom_field_value = $ag_custom_fields[$custom_field['id_field']]; - if (empty($custom_field_value)) { + if (empty($custom_field_value) === true) { $custom_field_value = ''; } } @@ -830,7 +833,7 @@ $table->data[4][0] .= __('Not condition'); $filters = '
'; - if (is_metaconsole()) { + if (is_metaconsole() === true) { $table->colspan[5][0] = 7; $table->cellstyle[5][0] = 'padding: 10px;'; $table->data[5][0] = ui_toggle( From 30d1e3ec237205328c8fa25dc3e15f56e43a6f18 Mon Sep 17 00:00:00 2001 From: Daniel Maya Date: Wed, 20 Oct 2021 13:09:47 +0200 Subject: [PATCH 34/92] #7916 Fixed group name --- pandora_console/include/functions_reporting.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandora_console/include/functions_reporting.php b/pandora_console/include/functions_reporting.php index 5b24d9e166..fd96a29d53 100755 --- a/pandora_console/include/functions_reporting.php +++ b/pandora_console/include/functions_reporting.php @@ -13669,7 +13669,7 @@ function reporting_label_macro($item, $label) if (preg_match('/_agentgroup_/', $label)) { $label = str_replace( '_agentgroup_', - $item['agent_group'], + groups_get_name($item['agent_group']), $label ); } From 3e1dcbb5545bdcc5476f8b4001e131b41d87c70f Mon Sep 17 00:00:00 2001 From: "alejandro.campos@artica.es" Date: Wed, 20 Oct 2021 13:30:24 +0200 Subject: [PATCH 35/92] changed text --- .../godmode/reporting/reporting_builder.item_editor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandora_console/godmode/reporting/reporting_builder.item_editor.php b/pandora_console/godmode/reporting/reporting_builder.item_editor.php index aaed1b0137..5bfdd702fc 100755 --- a/pandora_console/godmode/reporting/reporting_builder.item_editor.php +++ b/pandora_console/godmode/reporting/reporting_builder.item_editor.php @@ -3505,7 +3505,7 @@ function print_SLA_list($width, $action, $idItem=null) From 77aba53c7ee19aa48bbde9f555beb31de53a68ce Mon Sep 17 00:00:00 2001 From: "alejandro.campos@artica.es" Date: Wed, 20 Oct 2021 15:26:16 +0200 Subject: [PATCH 36/92] fix data representation --- pandora_console/include/functions_reporting.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandora_console/include/functions_reporting.php b/pandora_console/include/functions_reporting.php index 5b24d9e166..41d8747f83 100755 --- a/pandora_console/include/functions_reporting.php +++ b/pandora_console/include/functions_reporting.php @@ -8700,8 +8700,8 @@ function reporting_increment($report, $content) $return['data']['message'] = __('The monitor have no data in this range of dates or monitor type is not numeric'); $return['data']['error'] = true; } else if (is_numeric($old_data) && is_numeric($last_data)) { - $return['data']['old'] = $old_data; - $return['data']['now'] = $last_data; + $return['data']['old'] = round(floatval($old_data), $config['graph_precision']); + $return['data']['now'] = round(floatval($last_data), $config['graph_precision']); $increment = ($old_data - $last_data); if ($increment < 0) { From 6520f95fcf7e19288906018886db99365e8ec521 Mon Sep 17 00:00:00 2001 From: Daniel Maya Date: Wed, 20 Oct 2021 17:06:24 +0200 Subject: [PATCH 37/92] #7947 Fixed integria IMS ticket in metaconsole --- pandora_console/godmode/alerts/configure_alert_action.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pandora_console/godmode/alerts/configure_alert_action.php b/pandora_console/godmode/alerts/configure_alert_action.php index e486ccc06b..4d8478c99b 100644 --- a/pandora_console/godmode/alerts/configure_alert_action.php +++ b/pandora_console/godmode/alerts/configure_alert_action.php @@ -237,7 +237,7 @@ $create_ticket_command_id = db_get_value('id', 'talert_commands', 'name', io_saf $sql_exclude_command_id = ''; -if ($config['integria_enabled'] == 0 && $create_ticket_command_id !== false) { +if (!is_metaconsole() && $config['integria_enabled'] == 0 && $create_ticket_command_id !== false) { $sql_exclude_command_id = ' AND id <> '.$create_ticket_command_id; } @@ -597,6 +597,7 @@ $(document).ready (function () { $("#id_command").change (function () { values = Array (); + // No se envia el valor del commando. values.push({ name: "page", value: "godmode/alerts/alert_commands"}); From 07c7c7a38702426196f9051df199745abb42f5e9 Mon Sep 17 00:00:00 2001 From: "alejandro.campos@artica.es" Date: Fri, 22 Oct 2021 09:48:00 +0200 Subject: [PATCH 38/92] prevent from deleting global admin users when removing all of their profiles --- pandora_console/godmode/users/configure_user.php | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/pandora_console/godmode/users/configure_user.php b/pandora_console/godmode/users/configure_user.php index 2757af500e..cc5762fed8 100644 --- a/pandora_console/godmode/users/configure_user.php +++ b/pandora_console/godmode/users/configure_user.php @@ -140,7 +140,9 @@ if (is_ajax()) { $has_profile = db_get_row('tusuario_perfil', 'id_usuario', $id2); - if ($has_profile == false) { + $user_is_global_admin = users_is_admin($id2); + + if ($has_profile === false && $user_is_global_admin === false) { $result = delete_user($id2); if ($result) { @@ -1542,6 +1544,7 @@ $(document).ready (function () { var img_delete = ''; var id_user = ''; var is_metaconsole = ''; + var user_is_global_admin = ''; var data = []; $('input:image[name="add"]').click(function (e) { @@ -1586,7 +1589,7 @@ $(document).ready (function () { $('input:image[name="del"]').click(function (e) { e.preventDefault(); var rows = $("#table_profiles tr").length; - if ((is_metaconsole === '1' && rows <= 4) || (is_metaconsole === '' && rows <= 3)) { + if (((is_metaconsole === '1' && rows <= 4) || (is_metaconsole === '' && rows <= 3)) && user_is_global_admin !== '1') { if (!confirm('' + '. ' + '')) { return; } @@ -1608,8 +1611,11 @@ $(document).ready (function () { success: function (data) { row.remove(); var rows = $("#table_profiles tr").length; - if ((is_metaconsole === '1' && rows <= 3) || (is_metaconsole === '' && rows <= 2)) { + + if (is_metaconsole === '' && rows <= 2 && user_is_global_admin !== '1') { window.location.replace(""); + } else if (is_metaconsole === '1' && rows <= 3 && user_is_global_admin !== '1') { + window.location.replace(""); } } }); @@ -1748,7 +1754,6 @@ function show_double_auth_info () { var $dialogContainer = $("div#dialog-double_auth-container"); $dialogContainer.html($loadingSpinner); -console.log(userID); // Load the info page var request = $.ajax({ url: "", @@ -1913,7 +1918,6 @@ function show_double_auth_deactivation () { }, success: function(data, textStatus, xhr) { - console.log(data); if (data === -1) { $dialogContainer.html("
'.__('Authentication error').'
'; ?>"); } From 40aec564afe84fba5e7c6361efe43491e8689e02 Mon Sep 17 00:00:00 2001 From: "alejandro.campos@artica.es" Date: Fri, 22 Oct 2021 14:38:20 +0200 Subject: [PATCH 39/92] prevent global admins to log in remotely --- pandora_console/include/auth/mysql.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pandora_console/include/auth/mysql.php b/pandora_console/include/auth/mysql.php index 4e8f7caa61..660171fbf5 100644 --- a/pandora_console/include/auth/mysql.php +++ b/pandora_console/include/auth/mysql.php @@ -218,6 +218,11 @@ function process_user_login_remote($login, $pass, $api=false) switch ($config['auth']) { // LDAP case 'ldap': + // Use local authentication if user is global admin. + if (is_user_admin($login) === true) { + return false; + } + $sr = ldap_process_user_login($login, $pass); if (!$sr) { @@ -227,6 +232,11 @@ function process_user_login_remote($login, $pass, $api=false) // Active Directory case 'ad': + // Use local authentication if user is global admin. + if (is_user_admin($login) === true) { + return false; + } + if (enterprise_hook('ad_process_user_login', [$login, $pass]) === false) { $config['auth_error'] = 'User not found in database or incorrect password'; return false; From 05bc15f74c9c98eb466bedafc5480245bc8f4157 Mon Sep 17 00:00:00 2001 From: Daniel Maya Date: Mon, 25 Oct 2021 11:09:24 +0200 Subject: [PATCH 40/92] #8099 Added jquery mobile 1.4.5 --- .../extras/delete_files/delete_files.txt | 4 +- .../include/graphs/functions_flot.php | 2 +- .../include/javascript/jquery.mobile-1.3.1.js | 11191 ----------- .../include/javascript/jquery.mobile-1.4.5.js | 15454 ++++++++++++++++ .../include/style/jquery.mobile-1.3.1.css | 5361 ------ .../include/style/jquery.mobile-1.4.5.css | 5096 +++++ pandora_console/mobile/include/style/main.css | 237 +- pandora_console/mobile/include/ui.class.php | 7 +- pandora_console/mobile/operation/agent.php | 6 +- pandora_console/mobile/operation/events.php | 10 +- pandora_console/mobile/operation/groups.php | 23 +- 11 files changed, 20658 insertions(+), 16733 deletions(-) delete mode 100755 pandora_console/mobile/include/javascript/jquery.mobile-1.3.1.js create mode 100644 pandora_console/mobile/include/javascript/jquery.mobile-1.4.5.js delete mode 100755 pandora_console/mobile/include/style/jquery.mobile-1.3.1.css create mode 100644 pandora_console/mobile/include/style/jquery.mobile-1.4.5.css diff --git a/pandora_console/extras/delete_files/delete_files.txt b/pandora_console/extras/delete_files/delete_files.txt index 8bfef52f3f..888b359278 100644 --- a/pandora_console/extras/delete_files/delete_files.txt +++ b/pandora_console/extras/delete_files/delete_files.txt @@ -111,4 +111,6 @@ enterprise/operation/agentes/pandora_networkmap.view.php enterprise/include/ajax/map_enterprise.ajax.php enterprise/include/javascript/SimpleMapController.js enterprise/include/javascript/tooltipster.bundle.min.js -enterprise/include/styles/tooltipster.bundle.min.css \ No newline at end of file +enterprise/include/styles/tooltipster.bundle.min.css +mobile/include/javascript/jquery.mobile-1.3.1.js +mobile/include/style/jquery.mobile-1.3.1.css \ No newline at end of file diff --git a/pandora_console/include/graphs/functions_flot.php b/pandora_console/include/graphs/functions_flot.php index e0d318e2b1..cf568dbfa6 100644 --- a/pandora_console/include/graphs/functions_flot.php +++ b/pandora_console/include/graphs/functions_flot.php @@ -33,7 +33,7 @@ function include_javascript_dependencies_flot_graph($return=false, $mobile=false if ($mobile === true) { $output .= ' - '; + '; } // NOTE: jquery.flot.threshold is not te original file. Is patched to allow multiple thresholds and filled area diff --git a/pandora_console/mobile/include/javascript/jquery.mobile-1.3.1.js b/pandora_console/mobile/include/javascript/jquery.mobile-1.3.1.js deleted file mode 100755 index 6708d348b1..0000000000 --- a/pandora_console/mobile/include/javascript/jquery.mobile-1.3.1.js +++ /dev/null @@ -1,11191 +0,0 @@ -/* -* jQuery Mobile 1.3.1 -* Git HEAD hash: 74b4bec049fd93e4fe40205e6157de16eb64eb46 <> Date: Wed Apr 10 2013 21:57:23 UTC -* http://jquerymobile.com -* -* Copyright 2010, 2013 jQuery Foundation, Inc. and other contributors -* Released under the MIT license. -* http://jquery.org/license -* -*/ - - -(function ( root, doc, factory ) { - if ( typeof define === "function" && define.amd ) { - // AMD. Register as an anonymous module. - define( [ "jquery" ], function ( $ ) { - factory( $, root, doc ); - return $.mobile; - }); - } else { - // Browser globals - factory( root.jQuery, root, doc ); - } -}( this, document, function ( jQuery, window, document, undefined ) { -(function( $ ) { - $.mobile = {}; -}( jQuery )); -(function( $, window, undefined ) { - var nsNormalizeDict = {}; - - // jQuery.mobile configurable options - $.mobile = $.extend($.mobile, { - - // Version of the jQuery Mobile Framework - version: "1.3.1", - - // Namespace used framework-wide for data-attrs. Default is no namespace - ns: "", - - // Define the url parameter used for referencing widget-generated sub-pages. - // Translates to to example.html&ui-page=subpageIdentifier - // hash segment before &ui-page= is used to make Ajax request - subPageUrlKey: "ui-page", - - // Class assigned to page currently in view, and during transitions - activePageClass: "ui-page-active", - - // Class used for "active" button state, from CSS framework - activeBtnClass: "ui-btn-active", - - // Class used for "focus" form element state, from CSS framework - focusClass: "ui-focus", - - // Automatically handle clicks and form submissions through Ajax, when same-domain - ajaxEnabled: true, - - // Automatically load and show pages based on location.hash - hashListeningEnabled: true, - - // disable to prevent jquery from bothering with links - linkBindingEnabled: true, - - // Set default page transition - 'none' for no transitions - defaultPageTransition: "fade", - - // Set maximum window width for transitions to apply - 'false' for no limit - maxTransitionWidth: false, - - // Minimum scroll distance that will be remembered when returning to a page - minScrollBack: 250, - - // DEPRECATED: the following property is no longer in use, but defined until 2.0 to prevent conflicts - touchOverflowEnabled: false, - - // Set default dialog transition - 'none' for no transitions - defaultDialogTransition: "pop", - - // Error response message - appears when an Ajax page request fails - pageLoadErrorMessage: "Error Loading Page", - - // For error messages, which theme does the box uses? - pageLoadErrorMessageTheme: "e", - - // replace calls to window.history.back with phonegaps navigation helper - // where it is provided on the window object - phonegapNavigationEnabled: false, - - //automatically initialize the DOM when it's ready - autoInitializePage: true, - - pushStateEnabled: true, - - // allows users to opt in to ignoring content by marking a parent element as - // data-ignored - ignoreContentEnabled: false, - - // turn of binding to the native orientationchange due to android orientation behavior - orientationChangeEnabled: true, - - buttonMarkup: { - hoverDelay: 200 - }, - - // define the window and the document objects - window: $( window ), - document: $( document ), - - // TODO might be useful upstream in jquery itself ? - keyCode: { - ALT: 18, - BACKSPACE: 8, - CAPS_LOCK: 20, - COMMA: 188, - COMMAND: 91, - COMMAND_LEFT: 91, // COMMAND - COMMAND_RIGHT: 93, - CONTROL: 17, - DELETE: 46, - DOWN: 40, - END: 35, - ENTER: 13, - ESCAPE: 27, - HOME: 36, - INSERT: 45, - LEFT: 37, - MENU: 93, // COMMAND_RIGHT - NUMPAD_ADD: 107, - NUMPAD_DECIMAL: 110, - NUMPAD_DIVIDE: 111, - NUMPAD_ENTER: 108, - NUMPAD_MULTIPLY: 106, - NUMPAD_SUBTRACT: 109, - PAGE_DOWN: 34, - PAGE_UP: 33, - PERIOD: 190, - RIGHT: 39, - SHIFT: 16, - SPACE: 32, - TAB: 9, - UP: 38, - WINDOWS: 91 // COMMAND - }, - - // Place to store various widget extensions - behaviors: {}, - - // Scroll page vertically: scroll to 0 to hide iOS address bar, or pass a Y value - silentScroll: function( ypos ) { - if ( $.type( ypos ) !== "number" ) { - ypos = $.mobile.defaultHomeScroll; - } - - // prevent scrollstart and scrollstop events - $.event.special.scrollstart.enabled = false; - - setTimeout( function() { - window.scrollTo( 0, ypos ); - $.mobile.document.trigger( "silentscroll", { x: 0, y: ypos }); - }, 20 ); - - setTimeout( function() { - $.event.special.scrollstart.enabled = true; - }, 150 ); - }, - - // Expose our cache for testing purposes. - nsNormalizeDict: nsNormalizeDict, - - // Take a data attribute property, prepend the namespace - // and then camel case the attribute string. Add the result - // to our nsNormalizeDict so we don't have to do this again. - nsNormalize: function( prop ) { - if ( !prop ) { - return; - } - - return nsNormalizeDict[ prop ] || ( nsNormalizeDict[ prop ] = $.camelCase( $.mobile.ns + prop ) ); - }, - - // Find the closest parent with a theme class on it. Note that - // we are not using $.fn.closest() on purpose here because this - // method gets called quite a bit and we need it to be as fast - // as possible. - getInheritedTheme: function( el, defaultTheme ) { - var e = el[ 0 ], - ltr = "", - re = /ui-(bar|body|overlay)-([a-z])\b/, - c, m; - - while ( e ) { - c = e.className || ""; - if ( c && ( m = re.exec( c ) ) && ( ltr = m[ 2 ] ) ) { - // We found a parent with a theme class - // on it so bail from this loop. - break; - } - - e = e.parentNode; - } - - // Return the theme letter we found, if none, return the - // specified default. - - return ltr || defaultTheme || "a"; - }, - - // TODO the following $ and $.fn extensions can/probably should be moved into jquery.mobile.core.helpers - // - // Find the closest javascript page element to gather settings data jsperf test - // http://jsperf.com/single-complex-selector-vs-many-complex-selectors/edit - // possibly naive, but it shows that the parsing overhead for *just* the page selector vs - // the page and dialog selector is negligable. This could probably be speed up by - // doing a similar parent node traversal to the one found in the inherited theme code above - closestPageData: function( $target ) { - return $target - .closest( ':jqmData(role="page"), :jqmData(role="dialog")' ) - .data( "mobile-page" ); - }, - - enhanceable: function( $set ) { - return this.haveParents( $set, "enhance" ); - }, - - hijackable: function( $set ) { - return this.haveParents( $set, "ajax" ); - }, - - haveParents: function( $set, attr ) { - if ( !$.mobile.ignoreContentEnabled ) { - return $set; - } - - var count = $set.length, - $newSet = $(), - e, $element, excluded; - - for ( var i = 0; i < count; i++ ) { - $element = $set.eq( i ); - excluded = false; - e = $set[ i ]; - - while ( e ) { - var c = e.getAttribute ? e.getAttribute( "data-" + $.mobile.ns + attr ) : ""; - - if ( c === "false" ) { - excluded = true; - break; - } - - e = e.parentNode; - } - - if ( !excluded ) { - $newSet = $newSet.add( $element ); - } - } - - return $newSet; - }, - - getScreenHeight: function() { - // Native innerHeight returns more accurate value for this across platforms, - // jQuery version is here as a normalized fallback for platforms like Symbian - return window.innerHeight || $.mobile.window.height(); - } - }, $.mobile ); - - // Mobile version of data and removeData and hasData methods - // ensures all data is set and retrieved using jQuery Mobile's data namespace - $.fn.jqmData = function( prop, value ) { - var result; - if ( typeof prop !== "undefined" ) { - if ( prop ) { - prop = $.mobile.nsNormalize( prop ); - } - - // undefined is permitted as an explicit input for the second param - // in this case it returns the value and does not set it to undefined - if( arguments.length < 2 || value === undefined ){ - result = this.data( prop ); - } else { - result = this.data( prop, value ); - } - } - return result; - }; - - $.jqmData = function( elem, prop, value ) { - var result; - if ( typeof prop !== "undefined" ) { - result = $.data( elem, prop ? $.mobile.nsNormalize( prop ) : prop, value ); - } - return result; - }; - - $.fn.jqmRemoveData = function( prop ) { - return this.removeData( $.mobile.nsNormalize( prop ) ); - }; - - $.jqmRemoveData = function( elem, prop ) { - return $.removeData( elem, $.mobile.nsNormalize( prop ) ); - }; - - $.fn.removeWithDependents = function() { - $.removeWithDependents( this ); - }; - - $.removeWithDependents = function( elem ) { - var $elem = $( elem ); - - ( $elem.jqmData( 'dependents' ) || $() ).remove(); - $elem.remove(); - }; - - $.fn.addDependents = function( newDependents ) { - $.addDependents( $( this ), newDependents ); - }; - - $.addDependents = function( elem, newDependents ) { - var dependents = $( elem ).jqmData( 'dependents' ) || $(); - - $( elem ).jqmData( 'dependents', $.merge( dependents, newDependents ) ); - }; - - // note that this helper doesn't attempt to handle the callback - // or setting of an html element's text, its only purpose is - // to return the html encoded version of the text in all cases. (thus the name) - $.fn.getEncodedText = function() { - return $( "
" ).text( $( this ).text() ).html(); - }; - - // fluent helper function for the mobile namespaced equivalent - $.fn.jqmEnhanceable = function() { - return $.mobile.enhanceable( this ); - }; - - $.fn.jqmHijackable = function() { - return $.mobile.hijackable( this ); - }; - - // Monkey-patching Sizzle to filter the :jqmData selector - var oldFind = $.find, - jqmDataRE = /:jqmData\(([^)]*)\)/g; - - $.find = function( selector, context, ret, extra ) { - selector = selector.replace( jqmDataRE, "[data-" + ( $.mobile.ns || "" ) + "$1]" ); - - return oldFind.call( this, selector, context, ret, extra ); - }; - - $.extend( $.find, oldFind ); - - $.find.matches = function( expr, set ) { - return $.find( expr, null, null, set ); - }; - - $.find.matchesSelector = function( node, expr ) { - return $.find( expr, null, null, [ node ] ).length > 0; - }; -})( jQuery, this ); - - -/*! - * jQuery UI Widget v1.10.0pre - 2012-11-13 (ff055a0c353c3c8ce6e5bfa07ad7cb03e8885bc5) - * http://jqueryui.com - * - * Copyright 2010, 2013 jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/jQuery.widget/ - */ -(function( $, undefined ) { - -var uuid = 0, - slice = Array.prototype.slice, - _cleanData = $.cleanData; -$.cleanData = function( elems ) { - for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { - try { - $( elem ).triggerHandler( "remove" ); - // http://bugs.jquery.com/ticket/8235 - } catch( e ) {} - } - _cleanData( elems ); -}; - -$.widget = function( name, base, prototype ) { - var fullName, existingConstructor, constructor, basePrototype, - namespace = name.split( "." )[ 0 ]; - - name = name.split( "." )[ 1 ]; - fullName = namespace + "-" + name; - - if ( !prototype ) { - prototype = base; - base = $.Widget; - } - - // create selector for plugin - $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) { - return !!$.data( elem, fullName ); - }; - - $[ namespace ] = $[ namespace ] || {}; - existingConstructor = $[ namespace ][ name ]; - constructor = $[ namespace ][ name ] = function( options, element ) { - // allow instantiation without "new" keyword - if ( !this._createWidget ) { - return new constructor( options, element ); - } - - // allow instantiation without initializing for simple inheritance - // must use "new" keyword (the code above always passes args) - if ( arguments.length ) { - this._createWidget( options, element ); - } - }; - // extend with the existing constructor to carry over any static properties - $.extend( constructor, existingConstructor, { - version: prototype.version, - // copy the object used to create the prototype in case we need to - // redefine the widget later - _proto: $.extend( {}, prototype ), - // track widgets that inherit from this widget in case this widget is - // redefined after a widget inherits from it - _childConstructors: [] - }); - - basePrototype = new base(); - // we need to make the options hash a property directly on the new instance - // otherwise we'll modify the options hash on the prototype that we're - // inheriting from - basePrototype.options = $.widget.extend( {}, basePrototype.options ); - $.each( prototype, function( prop, value ) { - if ( $.isFunction( value ) ) { - prototype[ prop ] = (function() { - var _super = function() { - return base.prototype[ prop ].apply( this, arguments ); - }, - _superApply = function( args ) { - return base.prototype[ prop ].apply( this, args ); - }; - return function() { - var __super = this._super, - __superApply = this._superApply, - returnValue; - - this._super = _super; - this._superApply = _superApply; - - returnValue = value.apply( this, arguments ); - - this._super = __super; - this._superApply = __superApply; - - return returnValue; - }; - })(); - } - }); - constructor.prototype = $.widget.extend( basePrototype, { - // TODO: remove support for widgetEventPrefix - // always use the name + a colon as the prefix, e.g., draggable:start - // don't prefix for widgets that aren't DOM-based - widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name - }, prototype, { - constructor: constructor, - namespace: namespace, - widgetName: name, - widgetFullName: fullName - }); - - // If this widget is being redefined then we need to find all widgets that - // are inheriting from it and redefine all of them so that they inherit from - // the new version of this widget. We're essentially trying to replace one - // level in the prototype chain. - if ( existingConstructor ) { - $.each( existingConstructor._childConstructors, function( i, child ) { - var childPrototype = child.prototype; - - // redefine the child widget using the same prototype that was - // originally used, but inherit from the new version of the base - $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto ); - }); - // remove the list of existing child constructors from the old constructor - // so the old child constructors can be garbage collected - delete existingConstructor._childConstructors; - } else { - base._childConstructors.push( constructor ); - } - - $.widget.bridge( name, constructor ); -}; - -$.widget.extend = function( target ) { - var input = slice.call( arguments, 1 ), - inputIndex = 0, - inputLength = input.length, - key, - value; - for ( ; inputIndex < inputLength; inputIndex++ ) { - for ( key in input[ inputIndex ] ) { - value = input[ inputIndex ][ key ]; - if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { - // Clone objects - if ( $.isPlainObject( value ) ) { - target[ key ] = $.isPlainObject( target[ key ] ) ? - $.widget.extend( {}, target[ key ], value ) : - // Don't extend strings, arrays, etc. with objects - $.widget.extend( {}, value ); - // Copy everything else by reference - } else { - target[ key ] = value; - } - } - } - } - return target; -}; - -$.widget.bridge = function( name, object ) { - var fullName = object.prototype.widgetFullName || name; - $.fn[ name ] = function( options ) { - var isMethodCall = typeof options === "string", - args = slice.call( arguments, 1 ), - returnValue = this; - - // allow multiple hashes to be passed on init - options = !isMethodCall && args.length ? - $.widget.extend.apply( null, [ options ].concat(args) ) : - options; - - if ( isMethodCall ) { - this.each(function() { - var methodValue, - instance = $.data( this, fullName ); - if ( !instance ) { - return $.error( "cannot call methods on " + name + " prior to initialization; " + - "attempted to call method '" + options + "'" ); - } - if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) { - return $.error( "no such method '" + options + "' for " + name + " widget instance" ); - } - methodValue = instance[ options ].apply( instance, args ); - if ( methodValue !== instance && methodValue !== undefined ) { - returnValue = methodValue && methodValue.jquery ? - returnValue.pushStack( methodValue.get() ) : - methodValue; - return false; - } - }); - } else { - this.each(function() { - var instance = $.data( this, fullName ); - if ( instance ) { - instance.option( options || {} )._init(); - } else { - $.data( this, fullName, new object( options, this ) ); - } - }); - } - - return returnValue; - }; -}; - -$.Widget = function( /* options, element */ ) {}; -$.Widget._childConstructors = []; - -$.Widget.prototype = { - widgetName: "widget", - widgetEventPrefix: "", - defaultElement: "
", - options: { - disabled: false, - - // callbacks - create: null - }, - _createWidget: function( options, element ) { - element = $( element || this.defaultElement || this )[ 0 ]; - this.element = $( element ); - this.uuid = uuid++; - this.eventNamespace = "." + this.widgetName + this.uuid; - this.options = $.widget.extend( {}, - this.options, - this._getCreateOptions(), - options ); - - this.bindings = $(); - this.hoverable = $(); - this.focusable = $(); - - if ( element !== this ) { - $.data( element, this.widgetFullName, this ); - this._on( true, this.element, { - remove: function( event ) { - if ( event.target === element ) { - this.destroy(); - } - } - }); - this.document = $( element.style ? - // element within the document - element.ownerDocument : - // element is window or document - element.document || element ); - this.window = $( this.document[0].defaultView || this.document[0].parentWindow ); - } - - this._create(); - this._trigger( "create", null, this._getCreateEventData() ); - this._init(); - }, - _getCreateOptions: $.noop, - _getCreateEventData: $.noop, - _create: $.noop, - _init: $.noop, - - destroy: function() { - this._destroy(); - // we can probably remove the unbind calls in 2.0 - // all event bindings should go through this._on() - this.element - .unbind( this.eventNamespace ) - // 1.9 BC for #7810 - // TODO remove dual storage - .removeData( this.widgetName ) - .removeData( this.widgetFullName ) - // support: jquery <1.6.3 - // http://bugs.jquery.com/ticket/9413 - .removeData( $.camelCase( this.widgetFullName ) ); - this.widget() - .unbind( this.eventNamespace ) - .removeAttr( "aria-disabled" ) - .removeClass( - this.widgetFullName + "-disabled " + - "ui-state-disabled" ); - - // clean up events and states - this.bindings.unbind( this.eventNamespace ); - this.hoverable.removeClass( "ui-state-hover" ); - this.focusable.removeClass( "ui-state-focus" ); - }, - _destroy: $.noop, - - widget: function() { - return this.element; - }, - - option: function( key, value ) { - var options = key, - parts, - curOption, - i; - - if ( arguments.length === 0 ) { - // don't return a reference to the internal hash - return $.widget.extend( {}, this.options ); - } - - if ( typeof key === "string" ) { - // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } - options = {}; - parts = key.split( "." ); - key = parts.shift(); - if ( parts.length ) { - curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); - for ( i = 0; i < parts.length - 1; i++ ) { - curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; - curOption = curOption[ parts[ i ] ]; - } - key = parts.pop(); - if ( value === undefined ) { - return curOption[ key ] === undefined ? null : curOption[ key ]; - } - curOption[ key ] = value; - } else { - if ( value === undefined ) { - return this.options[ key ] === undefined ? null : this.options[ key ]; - } - options[ key ] = value; - } - } - - this._setOptions( options ); - - return this; - }, - _setOptions: function( options ) { - var key; - - for ( key in options ) { - this._setOption( key, options[ key ] ); - } - - return this; - }, - _setOption: function( key, value ) { - this.options[ key ] = value; - - if ( key === "disabled" ) { - this.widget() - .toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value ) - .attr( "aria-disabled", value ); - this.hoverable.removeClass( "ui-state-hover" ); - this.focusable.removeClass( "ui-state-focus" ); - } - - return this; - }, - - enable: function() { - return this._setOption( "disabled", false ); - }, - disable: function() { - return this._setOption( "disabled", true ); - }, - - _on: function( suppressDisabledCheck, element, handlers ) { - var delegateElement, - instance = this; - - // no suppressDisabledCheck flag, shuffle arguments - if ( typeof suppressDisabledCheck !== "boolean" ) { - handlers = element; - element = suppressDisabledCheck; - suppressDisabledCheck = false; - } - - // no element argument, shuffle and use this.element - if ( !handlers ) { - handlers = element; - element = this.element; - delegateElement = this.widget(); - } else { - // accept selectors, DOM elements - element = delegateElement = $( element ); - this.bindings = this.bindings.add( element ); - } - - $.each( handlers, function( event, handler ) { - function handlerProxy() { - // allow widgets to customize the disabled handling - // - disabled as an array instead of boolean - // - disabled class as method for disabling individual parts - if ( !suppressDisabledCheck && - ( instance.options.disabled === true || - $( this ).hasClass( "ui-state-disabled" ) ) ) { - return; - } - return ( typeof handler === "string" ? instance[ handler ] : handler ) - .apply( instance, arguments ); - } - - // copy the guid so direct unbinding works - if ( typeof handler !== "string" ) { - handlerProxy.guid = handler.guid = - handler.guid || handlerProxy.guid || $.guid++; - } - - var match = event.match( /^(\w+)\s*(.*)$/ ), - eventName = match[1] + instance.eventNamespace, - selector = match[2]; - if ( selector ) { - delegateElement.delegate( selector, eventName, handlerProxy ); - } else { - element.bind( eventName, handlerProxy ); - } - }); - }, - - _off: function( element, eventName ) { - eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace; - element.unbind( eventName ).undelegate( eventName ); - }, - - _delay: function( handler, delay ) { - function handlerProxy() { - return ( typeof handler === "string" ? instance[ handler ] : handler ) - .apply( instance, arguments ); - } - var instance = this; - return setTimeout( handlerProxy, delay || 0 ); - }, - - _hoverable: function( element ) { - this.hoverable = this.hoverable.add( element ); - this._on( element, { - mouseenter: function( event ) { - $( event.currentTarget ).addClass( "ui-state-hover" ); - }, - mouseleave: function( event ) { - $( event.currentTarget ).removeClass( "ui-state-hover" ); - } - }); - }, - - _focusable: function( element ) { - this.focusable = this.focusable.add( element ); - this._on( element, { - focusin: function( event ) { - $( event.currentTarget ).addClass( "ui-state-focus" ); - }, - focusout: function( event ) { - $( event.currentTarget ).removeClass( "ui-state-focus" ); - } - }); - }, - - _trigger: function( type, event, data ) { - var prop, orig, - callback = this.options[ type ]; - - data = data || {}; - event = $.Event( event ); - event.type = ( type === this.widgetEventPrefix ? - type : - this.widgetEventPrefix + type ).toLowerCase(); - // the original event may come from any element - // so we need to reset the target on the new event - event.target = this.element[ 0 ]; - - // copy original event properties over to the new event - orig = event.originalEvent; - if ( orig ) { - for ( prop in orig ) { - if ( !( prop in event ) ) { - event[ prop ] = orig[ prop ]; - } - } - } - - this.element.trigger( event, data ); - return !( $.isFunction( callback ) && - callback.apply( this.element[0], [ event ].concat( data ) ) === false || - event.isDefaultPrevented() ); - } -}; - -$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { - $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { - if ( typeof options === "string" ) { - options = { effect: options }; - } - var hasOptions, - effectName = !options ? - method : - options === true || typeof options === "number" ? - defaultEffect : - options.effect || defaultEffect; - options = options || {}; - if ( typeof options === "number" ) { - options = { duration: options }; - } - hasOptions = !$.isEmptyObject( options ); - options.complete = callback; - if ( options.delay ) { - element.delay( options.delay ); - } - if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { - element[ method ]( options ); - } else if ( effectName !== method && element[ effectName ] ) { - element[ effectName ]( options.duration, options.easing, callback ); - } else { - element.queue(function( next ) { - $( this )[ method ](); - if ( callback ) { - callback.call( element[ 0 ] ); - } - next(); - }); - } - }; -}); - -})( jQuery ); - -(function( $, undefined ) { - -$.widget( "mobile.widget", { - // decorate the parent _createWidget to trigger `widgetinit` for users - // who wish to do post post `widgetcreate` alterations/additions - // - // TODO create a pull request for jquery ui to trigger this event - // in the original _createWidget - _createWidget: function() { - $.Widget.prototype._createWidget.apply( this, arguments ); - this._trigger( 'init' ); - }, - - _getCreateOptions: function() { - - var elem = this.element, - options = {}; - - $.each( this.options, function( option ) { - - var value = elem.jqmData( option.replace( /[A-Z]/g, function( c ) { - return "-" + c.toLowerCase(); - }) - ); - - if ( value !== undefined ) { - options[ option ] = value; - } - }); - - return options; - }, - - enhanceWithin: function( target, useKeepNative ) { - this.enhance( $( this.options.initSelector, $( target )), useKeepNative ); - }, - - enhance: function( targets, useKeepNative ) { - var page, keepNative, $widgetElements = $( targets ), self = this; - - // if ignoreContentEnabled is set to true the framework should - // only enhance the selected elements when they do NOT have a - // parent with the data-namespace-ignore attribute - $widgetElements = $.mobile.enhanceable( $widgetElements ); - - if ( useKeepNative && $widgetElements.length ) { - // TODO remove dependency on the page widget for the keepNative. - // Currently the keepNative value is defined on the page prototype so - // the method is as well - page = $.mobile.closestPageData( $widgetElements ); - keepNative = ( page && page.keepNativeSelector()) || ""; - - $widgetElements = $widgetElements.not( keepNative ); - } - - $widgetElements[ this.widgetName ](); - }, - - raise: function( msg ) { - throw "Widget [" + this.widgetName + "]: " + msg; - } -}); - -})( jQuery ); - - -(function( $, window ) { - // DEPRECATED - // NOTE global mobile object settings - $.extend( $.mobile, { - // DEPRECATED Should the text be visble in the loading message? - loadingMessageTextVisible: undefined, - - // DEPRECATED When the text is visible, what theme does the loading box use? - loadingMessageTheme: undefined, - - // DEPRECATED default message setting - loadingMessage: undefined, - - // DEPRECATED - // Turn on/off page loading message. Theme doubles as an object argument - // with the following shape: { theme: '', text: '', html: '', textVisible: '' } - // NOTE that the $.mobile.loading* settings and params past the first are deprecated - showPageLoadingMsg: function( theme, msgText, textonly ) { - $.mobile.loading( 'show', theme, msgText, textonly ); - }, - - // DEPRECATED - hidePageLoadingMsg: function() { - $.mobile.loading( 'hide' ); - }, - - loading: function() { - this.loaderWidget.loader.apply( this.loaderWidget, arguments ); - } - }); - - // TODO move loader class down into the widget settings - var loaderClass = "ui-loader", $html = $( "html" ), $window = $.mobile.window; - - $.widget( "mobile.loader", { - // NOTE if the global config settings are defined they will override these - // options - options: { - // the theme for the loading message - theme: "a", - - // whether the text in the loading message is shown - textVisible: false, - - // custom html for the inner content of the loading message - html: "", - - // the text to be displayed when the popup is shown - text: "loading" - }, - - defaultHtml: "
" + - "" + - "

" + - "
", - - // For non-fixed supportin browsers. Position at y center (if scrollTop supported), above the activeBtn (if defined), or just 100px from top - fakeFixLoader: function() { - var activeBtn = $( "." + $.mobile.activeBtnClass ).first(); - - this.element - .css({ - top: $.support.scrollTop && $window.scrollTop() + $window.height() / 2 || - activeBtn.length && activeBtn.offset().top || 100 - }); - }, - - // check position of loader to see if it appears to be "fixed" to center - // if not, use abs positioning - checkLoaderPosition: function() { - var offset = this.element.offset(), - scrollTop = $window.scrollTop(), - screenHeight = $.mobile.getScreenHeight(); - - if ( offset.top < scrollTop || ( offset.top - scrollTop ) > screenHeight ) { - this.element.addClass( "ui-loader-fakefix" ); - this.fakeFixLoader(); - $window - .unbind( "scroll", this.checkLoaderPosition ) - .bind( "scroll", $.proxy( this.fakeFixLoader, this ) ); - } - }, - - resetHtml: function() { - this.element.html( $( this.defaultHtml ).html() ); - }, - - // Turn on/off page loading message. Theme doubles as an object argument - // with the following shape: { theme: '', text: '', html: '', textVisible: '' } - // NOTE that the $.mobile.loading* settings and params past the first are deprecated - // TODO sweet jesus we need to break some of this out - show: function( theme, msgText, textonly ) { - var textVisible, message, $header, loadSettings; - - this.resetHtml(); - - // use the prototype options so that people can set them globally at - // mobile init. Consistency, it's what's for dinner - if ( $.type(theme) === "object" ) { - loadSettings = $.extend( {}, this.options, theme ); - - // prefer object property from the param then the old theme setting - theme = loadSettings.theme || $.mobile.loadingMessageTheme; - } else { - loadSettings = this.options; - - // here we prefer the them value passed as a string argument, then - // we prefer the global option because we can't use undefined default - // prototype options, then the prototype option - theme = theme || $.mobile.loadingMessageTheme || loadSettings.theme; - } - - // set the message text, prefer the param, then the settings object - // then loading message - message = msgText || $.mobile.loadingMessage || loadSettings.text; - - // prepare the dom - $html.addClass( "ui-loading" ); - - if ( $.mobile.loadingMessage !== false || loadSettings.html ) { - // boolean values require a bit more work :P, supports object properties - // and old settings - if ( $.mobile.loadingMessageTextVisible !== undefined ) { - textVisible = $.mobile.loadingMessageTextVisible; - } else { - textVisible = loadSettings.textVisible; - } - - // add the proper css given the options (theme, text, etc) - // Force text visibility if the second argument was supplied, or - // if the text was explicitly set in the object args - this.element.attr("class", loaderClass + - " ui-corner-all ui-body-" + theme + - " ui-loader-" + ( textVisible || msgText || theme.text ? "verbose" : "default" ) + - ( loadSettings.textonly || textonly ? " ui-loader-textonly" : "" ) ); - - // TODO verify that jquery.fn.html is ok to use in both cases here - // this might be overly defensive in preventing unknowing xss - // if the html attribute is defined on the loading settings, use that - // otherwise use the fallbacks from above - if ( loadSettings.html ) { - this.element.html( loadSettings.html ); - } else { - this.element.find( "h1" ).text( message ); - } - - // attach the loader to the DOM - this.element.appendTo( $.mobile.pageContainer ); - - // check that the loader is visible - this.checkLoaderPosition(); - - // on scroll check the loader position - $window.bind( "scroll", $.proxy( this.checkLoaderPosition, this ) ); - } - }, - - hide: function() { - $html.removeClass( "ui-loading" ); - - if ( $.mobile.loadingMessage ) { - this.element.removeClass( "ui-loader-fakefix" ); - } - - $.mobile.window.unbind( "scroll", this.fakeFixLoader ); - $.mobile.window.unbind( "scroll", this.checkLoaderPosition ); - } - }); - - $window.bind( 'pagecontainercreate', function() { - $.mobile.loaderWidget = $.mobile.loaderWidget || $( $.mobile.loader.prototype.defaultHtml ).loader(); - }); -})(jQuery, this); - - -// Script: jQuery hashchange event -// -// *Version: 1.3, Last updated: 7/21/2010* -// -// Project Home - http://benalman.com/projects/jquery-hashchange-plugin/ -// GitHub - http://github.com/cowboy/jquery-hashchange/ -// Source - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.js -// (Minified) - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.min.js (0.8kb gzipped) -// -// About: License -// -// Copyright (c) 2010 "Cowboy" Ben Alman, -// Dual licensed under the MIT and GPL licenses. -// http://benalman.com/about/license/ -// -// About: Examples -// -// These working examples, complete with fully commented code, illustrate a few -// ways in which this plugin can be used. -// -// hashchange event - http://benalman.com/code/projects/jquery-hashchange/examples/hashchange/ -// document.domain - http://benalman.com/code/projects/jquery-hashchange/examples/document_domain/ -// -// About: Support and Testing -// -// Information about what version or versions of jQuery this plugin has been -// tested with, what browsers it has been tested in, and where the unit tests -// reside (so you can test it yourself). -// -// jQuery Versions - 1.2.6, 1.3.2, 1.4.1, 1.4.2 -// Browsers Tested - Internet Explorer 6-8, Firefox 2-4, Chrome 5-6, Safari 3.2-5, -// Opera 9.6-10.60, iPhone 3.1, Android 1.6-2.2, BlackBerry 4.6-5. -// Unit Tests - http://benalman.com/code/projects/jquery-hashchange/unit/ -// -// About: Known issues -// -// While this jQuery hashchange event implementation is quite stable and -// robust, there are a few unfortunate browser bugs surrounding expected -// hashchange event-based behaviors, independent of any JavaScript -// window.onhashchange abstraction. See the following examples for more -// information: -// -// Chrome: Back Button - http://benalman.com/code/projects/jquery-hashchange/examples/bug-chrome-back-button/ -// Firefox: Remote XMLHttpRequest - http://benalman.com/code/projects/jquery-hashchange/examples/bug-firefox-remote-xhr/ -// WebKit: Back Button in an Iframe - http://benalman.com/code/projects/jquery-hashchange/examples/bug-webkit-hash-iframe/ -// Safari: Back Button from a different domain - http://benalman.com/code/projects/jquery-hashchange/examples/bug-safari-back-from-diff-domain/ -// -// Also note that should a browser natively support the window.onhashchange -// event, but not report that it does, the fallback polling loop will be used. -// -// About: Release History -// -// 1.3 - (7/21/2010) Reorganized IE6/7 Iframe code to make it more -// "removable" for mobile-only development. Added IE6/7 document.title -// support. Attempted to make Iframe as hidden as possible by using -// techniques from http://www.paciellogroup.com/blog/?p=604. Added -// support for the "shortcut" format $(window).hashchange( fn ) and -// $(window).hashchange() like jQuery provides for built-in events. -// Renamed jQuery.hashchangeDelay to and -// lowered its default value to 50. Added -// and properties plus document-domain.html -// file to address access denied issues when setting document.domain in -// IE6/7. -// 1.2 - (2/11/2010) Fixed a bug where coming back to a page using this plugin -// from a page on another domain would cause an error in Safari 4. Also, -// IE6/7 Iframe is now inserted after the body (this actually works), -// which prevents the page from scrolling when the event is first bound. -// Event can also now be bound before DOM ready, but it won't be usable -// before then in IE6/7. -// 1.1 - (1/21/2010) Incorporated document.documentMode test to fix IE8 bug -// where browser version is incorrectly reported as 8.0, despite -// inclusion of the X-UA-Compatible IE=EmulateIE7 meta tag. -// 1.0 - (1/9/2010) Initial Release. Broke out the jQuery BBQ event.special -// window.onhashchange functionality into a separate plugin for users -// who want just the basic event & back button support, without all the -// extra awesomeness that BBQ provides. This plugin will be included as -// part of jQuery BBQ, but also be available separately. - -(function( $, window, undefined ) { - // Reused string. - var str_hashchange = 'hashchange', - - // Method / object references. - doc = document, - fake_onhashchange, - special = $.event.special, - - // Does the browser support window.onhashchange? Note that IE8 running in - // IE7 compatibility mode reports true for 'onhashchange' in window, even - // though the event isn't supported, so also test document.documentMode. - doc_mode = doc.documentMode, - supports_onhashchange = 'on' + str_hashchange in window && ( doc_mode === undefined || doc_mode > 7 ); - - // Get location.hash (or what you'd expect location.hash to be) sans any - // leading #. Thanks for making this necessary, Firefox! - function get_fragment( url ) { - url = url || location.href; - return '#' + url.replace( /^[^#]*#?(.*)$/, '$1' ); - }; - - // Method: jQuery.fn.hashchange - // - // Bind a handler to the window.onhashchange event or trigger all bound - // window.onhashchange event handlers. This behavior is consistent with - // jQuery's built-in event handlers. - // - // Usage: - // - // > jQuery(window).hashchange( [ handler ] ); - // - // Arguments: - // - // handler - (Function) Optional handler to be bound to the hashchange - // event. This is a "shortcut" for the more verbose form: - // jQuery(window).bind( 'hashchange', handler ). If handler is omitted, - // all bound window.onhashchange event handlers will be triggered. This - // is a shortcut for the more verbose - // jQuery(window).trigger( 'hashchange' ). These forms are described in - // the section. - // - // Returns: - // - // (jQuery) The initial jQuery collection of elements. - - // Allow the "shortcut" format $(elem).hashchange( fn ) for binding and - // $(elem).hashchange() for triggering, like jQuery does for built-in events. - $.fn[ str_hashchange ] = function( fn ) { - return fn ? this.bind( str_hashchange, fn ) : this.trigger( str_hashchange ); - }; - - // Property: jQuery.fn.hashchange.delay - // - // The numeric interval (in milliseconds) at which the - // polling loop executes. Defaults to 50. - - // Property: jQuery.fn.hashchange.domain - // - // If you're setting document.domain in your JavaScript, and you want hash - // history to work in IE6/7, not only must this property be set, but you must - // also set document.domain BEFORE jQuery is loaded into the page. This - // property is only applicable if you are supporting IE6/7 (or IE8 operating - // in "IE7 compatibility" mode). - // - // In addition, the property must be set to the - // path of the included "document-domain.html" file, which can be renamed or - // modified if necessary (note that the document.domain specified must be the - // same in both your main JavaScript as well as in this file). - // - // Usage: - // - // jQuery.fn.hashchange.domain = document.domain; - - // Property: jQuery.fn.hashchange.src - // - // If, for some reason, you need to specify an Iframe src file (for example, - // when setting document.domain as in ), you can - // do so using this property. Note that when using this property, history - // won't be recorded in IE6/7 until the Iframe src file loads. This property - // is only applicable if you are supporting IE6/7 (or IE8 operating in "IE7 - // compatibility" mode). - // - // Usage: - // - // jQuery.fn.hashchange.src = 'path/to/file.html'; - - $.fn[ str_hashchange ].delay = 50; - /* - $.fn[ str_hashchange ].domain = null; - $.fn[ str_hashchange ].src = null; - */ - - // Event: hashchange event - // - // Fired when location.hash changes. In browsers that support it, the native - // HTML5 window.onhashchange event is used, otherwise a polling loop is - // initialized, running every milliseconds to - // see if the hash has changed. In IE6/7 (and IE8 operating in "IE7 - // compatibility" mode), a hidden Iframe is created to allow the back button - // and hash-based history to work. - // - // Usage as described in : - // - // > // Bind an event handler. - // > jQuery(window).hashchange( function(e) { - // > var hash = location.hash; - // > ... - // > }); - // > - // > // Manually trigger the event handler. - // > jQuery(window).hashchange(); - // - // A more verbose usage that allows for event namespacing: - // - // > // Bind an event handler. - // > jQuery(window).bind( 'hashchange', function(e) { - // > var hash = location.hash; - // > ... - // > }); - // > - // > // Manually trigger the event handler. - // > jQuery(window).trigger( 'hashchange' ); - // - // Additional Notes: - // - // * The polling loop and Iframe are not created until at least one handler - // is actually bound to the 'hashchange' event. - // * If you need the bound handler(s) to execute immediately, in cases where - // a location.hash exists on page load, via bookmark or page refresh for - // example, use jQuery(window).hashchange() or the more verbose - // jQuery(window).trigger( 'hashchange' ). - // * The event can be bound before DOM ready, but since it won't be usable - // before then in IE6/7 (due to the necessary Iframe), recommended usage is - // to bind it inside a DOM ready handler. - - // Override existing $.event.special.hashchange methods (allowing this plugin - // to be defined after jQuery BBQ in BBQ's source code). - special[ str_hashchange ] = $.extend( special[ str_hashchange ], { - - // Called only when the first 'hashchange' event is bound to window. - setup: function() { - // If window.onhashchange is supported natively, there's nothing to do.. - if ( supports_onhashchange ) { return false; } - - // Otherwise, we need to create our own. And we don't want to call this - // until the user binds to the event, just in case they never do, since it - // will create a polling loop and possibly even a hidden Iframe. - $( fake_onhashchange.start ); - }, - - // Called only when the last 'hashchange' event is unbound from window. - teardown: function() { - // If window.onhashchange is supported natively, there's nothing to do.. - if ( supports_onhashchange ) { return false; } - - // Otherwise, we need to stop ours (if possible). - $( fake_onhashchange.stop ); - } - - }); - - // fake_onhashchange does all the work of triggering the window.onhashchange - // event for browsers that don't natively support it, including creating a - // polling loop to watch for hash changes and in IE 6/7 creating a hidden - // Iframe to enable back and forward. - fake_onhashchange = (function() { - var self = {}, - timeout_id, - - // Remember the initial hash so it doesn't get triggered immediately. - last_hash = get_fragment(), - - fn_retval = function( val ) { return val; }, - history_set = fn_retval, - history_get = fn_retval; - - // Start the polling loop. - self.start = function() { - timeout_id || poll(); - }; - - // Stop the polling loop. - self.stop = function() { - timeout_id && clearTimeout( timeout_id ); - timeout_id = undefined; - }; - - // This polling loop checks every $.fn.hashchange.delay milliseconds to see - // if location.hash has changed, and triggers the 'hashchange' event on - // window when necessary. - function poll() { - var hash = get_fragment(), - history_hash = history_get( last_hash ); - - if ( hash !== last_hash ) { - history_set( last_hash = hash, history_hash ); - - $(window).trigger( str_hashchange ); - - } else if ( history_hash !== last_hash ) { - location.href = location.href.replace( /#.*/, '' ) + history_hash; - } - - timeout_id = setTimeout( poll, $.fn[ str_hashchange ].delay ); - }; - - // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv - // vvvvvvvvvvvvvvvvvvv REMOVE IF NOT SUPPORTING IE6/7/8 vvvvvvvvvvvvvvvvvvv - // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv - window.attachEvent && !window.addEventListener && !supports_onhashchange && (function() { - // Not only do IE6/7 need the "magical" Iframe treatment, but so does IE8 - // when running in "IE7 compatibility" mode. - - var iframe, - iframe_src; - - // When the event is bound and polling starts in IE 6/7, create a hidden - // Iframe for history handling. - self.start = function() { - if ( !iframe ) { - iframe_src = $.fn[ str_hashchange ].src; - iframe_src = iframe_src && iframe_src + get_fragment(); - - // Create hidden Iframe. Attempt to make Iframe as hidden as possible - // by using techniques from http://www.paciellogroup.com/blog/?p=604. - iframe = $('