diff --git a/pandora_server/ChangeLog b/pandora_server/ChangeLog index 1d5909fe97..b7b5fb88a6 100644 --- a/pandora_server/ChangeLog +++ b/pandora_server/ChangeLog @@ -1,3 +1,10 @@ +2013-03-01 Ramon Novoa + + * lib/PandoraFMS/Core.pm, + lib/PandoraFMS/DB.pm, + lib/PandoraFMS/DataServer.pm: Refactored some GIS code. Still needs + testing. + 2013-02-28 Sancho Lerena * Config.pm: updated version. diff --git a/pandora_server/lib/PandoraFMS/Core.pm b/pandora_server/lib/PandoraFMS/Core.pm index a12fd4bec5..cfbc48b21a 100644 --- a/pandora_server/lib/PandoraFMS/Core.pm +++ b/pandora_server/lib/PandoraFMS/Core.pm @@ -1878,90 +1878,122 @@ defined also the parent is updated. =cut ########################################################################## -sub pandora_update_agent ($$$$$$$;$$$$$$) { +sub pandora_update_agent ($$$$$$$;$$) { my ($pa_config, $agent_timestamp, $agent_id, $os_version, $agent_version, $agent_interval, $dbh, $timezone_offset, - $longitude, $latitude, $altitude, $position_description, $parent_agent_id) = @_; - - my $timestamp = strftime ("%Y-%m-%d %H:%M:%S", localtime()); - + $parent_agent_id) = @_; # No access update for data without interval. - # Single modules from network server, for example. This could be very - # Heavy for Pandora FMS + # Single modules from network server, for example. This could be very Heavy for Pandora FMS if ($agent_interval != -1){ pandora_access_update ($pa_config, $agent_id, $dbh); + } else { + + # Do not update the agent interval + $agent_interval = undef; } - # No update for interval, timezone and position fields (some old agents don't support it) - if ($agent_interval == -1){ - db_do($dbh, 'UPDATE tagente SET agent_version = ?, ultimo_contacto_remoto = ?, ultimo_contacto = ?, os_version = ? WHERE id_agente = ?', - $agent_version, $agent_timestamp, $timestamp, $os_version, $agent_id); - + # Update tagente + my $timestamp = strftime ("%Y-%m-%d %H:%M:%S", localtime()); + my ($set, $values) = db_update_get_values ({'agent_version' => $agent_version, + 'intervalo' => $agent_interval, + 'ultimo_contacto_remoto' => $agent_timestamp, + 'ultimo_contacto' => $timestamp, + 'os_version' => $os_version, + 'timezone_offset' => $timezone_offset, + 'id_parent' => $parent_agent_id, + }); + + db_do ($dbh, "UPDATE tagente SET $set WHERE id_agente = ?", @{$values}, $agent_id); +} + +########################################################################## +=head2 C<< pandora_update_gis_data (I<$pa_config>, I<$dbh>, I<$agent_id>, I<$longitude>, I<$latitude>, I<$altitude>) >> + +Update agent GIS information. + +=cut +########################################################################## +sub pandora_update_gis_data ($$$$$$$$) { + my ($pa_config, $dbh, $agent_id, $agent_name, $longitude, $latitude, $altitude, $position_description, $timestamp) = @_; + + logger($pa_config, "Updating GIS data for agent $agent_name (long: $longitude lat: $latitude alt: $altitude)", 10); + + # Check for valid longitude and latitude + if (!defined($longitude) || $longitude !~ /[-+]?[0-9,11,12]/ || + !defined($latitude) || $latitude !~ /[-+]?[0-9,11,12]/) { return; } - - if ( defined ($timezone_offset)) { - if (defined($parent_agent_id)) { - # Update the table tagente with all the new data and set the new parent - db_do ($dbh, 'UPDATE tagente SET intervalo = ?, agent_version = ?, ultimo_contacto_remoto = ?, ultimo_contacto = ?, os_version = ?, - timezone_offset = ?, id_parent = ? WHERE id_agente = ?', $agent_interval, $agent_version, $agent_timestamp, - $timestamp, $os_version, $timezone_offset, $parent_agent_id, $agent_id); - } - else { - # Update the table tagente with all the new data - db_do ($dbh, 'UPDATE tagente SET intervalo = ?, agent_version = ?, ultimo_contacto_remoto = ?, ultimo_contacto = ?, os_version = ?, - timezone_offset = ? WHERE id_agente = ?', $agent_interval, $agent_version, $agent_timestamp, $timestamp, $os_version, $timezone_offset, $agent_id); - } - } - else { - if (defined($parent_agent_id)) { - # Update the table tagente with all the new data and set the new parent - db_do ($dbh, 'UPDATE tagente SET intervalo = ?, agent_version = ?, ultimo_contacto_remoto = ?, ultimo_contacto = ?, os_version = ?, id_parent = ? - WHERE id_agente = ?', $agent_interval, $agent_version, $agent_timestamp, $timestamp, $os_version, $parent_agent_id, $agent_id); - } - else { - # Update the table tagente with all the new data - db_do ($dbh, 'UPDATE tagente SET intervalo = ?, agent_version = ?, ultimo_contacto_remoto = ?, ultimo_contacto = ?, os_version = ? WHERE id_agente = ?', - $agent_interval, $agent_version, $agent_timestamp, $timestamp, $os_version, $agent_id); - } - } - - my $update_gis_data= get_db_value ($dbh, 'SELECT update_gis_data FROM tagente WHERE id_agente = ?', $agent_id); - #Test if we have received the optional position parameters - if (defined ($longitude) && defined ($latitude) && $pa_config->{'activate_gis'} == 1 && $update_gis_data == 1 ){ - # Get the last position to see if it has moved. - my $last_agent_position= get_db_single_row ($dbh, 'SELECT * FROM tgis_data_status WHERE tagente_id_agente = ?', $agent_id); - if(defined($last_agent_position)) { - - logger($pa_config, "Old Agent data: current_longitude=". $last_agent_position->{'current_longitude'}. " current_latitude=" - .$last_agent_position->{'current_latitude'}. " current_altitude=". $last_agent_position->{'current_altitude'}. " ID: $agent_id ", 10); - - # If the agent has moved outside the range stablised as location error - if (distance_moved($pa_config, $last_agent_position->{'stored_longitude'}, $last_agent_position->{'stored_latitude'}, - $last_agent_position->{'stored_altitude'}, $longitude, $latitude, $altitude) > $pa_config->{'location_error'}) { - #Archive the old position and save new one as status - archive_agent_position($pa_config, $last_agent_position->{'start_timestamp'},$timestamp,$last_agent_position->{'stored_longitude'}, $last_agent_position->{'stored_latitude'}, - $last_agent_position->{'stored_altitude'},$last_agent_position->{'description'}, $last_agent_position->{'number_of_packages'},$agent_id, $dbh); - if(!defined($altitude) ) { - $altitude = 0; - } - # Save the agent position in the tgis_data_status table - update_agent_position($pa_config, $longitude, $latitude, $altitude, $agent_id, $dbh, $longitude, $latitude, $altitude, $timestamp, $position_description); - } - else { #the agent has not moved enougth so just update the status table - update_agent_position ($pa_config, $longitude, $latitude, $altitude, $agent_id, $dbh); - } - } - else { - logger($pa_config, "There was not previous positional data, storing first positioal status",8); - save_agent_position($pa_config, $longitude, $latitude, $altitude, $agent_id, $dbh, $timestamp, $position_description); - } - } - else { - logger($pa_config, "Agent id $agent_id positional data ignored (update_gis_data = $update_gis_data)",10); - } + # Altitude is optional + if (!defined($altitude) || $altitude !~ /[-+]?[0-9,11,12]/) { + $altitude = ''; + } + + # Get position description + if ((!defined($position_description))) { + + # This code gets description (Reverse Geocoding) from a current GPS coordinates using Google maps API + # This requires a connection to internet and could be very slow and have a huge impact in performance. + # Other methods for reverse geocoding are OpenStreetmaps, in nternet or in a local server + + if ($pa_config->{'google_maps_description'}){ + my $content = get ('http://maps.google.com/maps/geo?q='.$latitude.','.$longitude.'&output=csv&sensor=false'); + my @address = split (/\"/,$content); + $position_description = $address[1]; + } + elsif ($pa_config->{'openstreetmaps_description'}){ + # Sample Query: http://nominatim.openstreetmap.org/reverse?format=csv&lat=40.43197&lon=-3.6993818&zoom=18&addressdetails=1&email=info@pandorafms.org + # Email address is sent by courtesy to OpenStreetmaps people. + # I read the API :-), thanks guys for your work. + # Change here URL to make request to a local openstreetmap server + my $content = get ('http://nominatim.openstreetmap.org/reverse?format=csv&lat='.$latitude.'&lon='.$longitude.'&zoom=18&addressdetails=1&email=info@pandorafms.org'); + + if ((defined($content)) && ($content ne "")){ + + # Yep, I need to parse the XML output. + my $xs1 = XML::Simple->new(); + my $doc = $xs1->XMLin($content); + $position_description = safe_input ($doc->{result}{content}); + } else { + $position_description = ""; + } + + } + + if (!defined($position_description)){ + $position_description = ""; + } + + logger($pa_config, "Getting GIS Data=longitude=$longitude latitude=$latitude altitude=$altitude position_description=$position_description", 10); + } + + # Get the last position to see if it has moved. + my $last_agent_position= get_db_single_row ($dbh, 'SELECT * FROM tgis_data_status WHERE tagente_id_agente = ?', $agent_id); + if(defined($last_agent_position)) { + + logger($pa_config, "Old Agent data: current_longitude=". $last_agent_position->{'current_longitude'}. " current_latitude=".$last_agent_position->{'current_latitude'}. " current_altitude=". $last_agent_position->{'current_altitude'}. " ID: $agent_id ", 10); + + # If the agent has moved outside the range stablised as location error + if (distance_moved($pa_config, $last_agent_position->{'stored_longitude'}, $last_agent_position->{'stored_latitude'}, $last_agent_position->{'stored_altitude'}, $longitude, $latitude, $altitude) > $pa_config->{'location_error'}) { + + #Archive the old position and save new one as status + archive_agent_position($pa_config, $last_agent_position->{'start_timestamp'}, $timestamp,$last_agent_position->{'stored_longitude'}, $last_agent_position->{'stored_latitude'}, $last_agent_position->{'stored_altitude'},$last_agent_position->{'description'}, $last_agent_position->{'number_of_packages'},$agent_id, $dbh); + + $altitude = 0 if (!defined($altitude)); + + # Save the agent position in the tgis_data_status table + update_agent_position($pa_config, $longitude, $latitude, $altitude, $agent_id, $dbh, $longitude, $latitude, $altitude, $timestamp, $position_description); + } + # The agent has not moved enougth so just update the status table + else { + update_agent_position ($pa_config, $longitude, $latitude, $altitude, $agent_id, $dbh); + } + } + else { + logger($pa_config, "There was not previous positional data, storing first positioal status", 10); + save_agent_position($pa_config, $longitude, $latitude, $altitude, $agent_id, $dbh, $timestamp, $position_description); + } } ########################################################################## @@ -2372,40 +2404,38 @@ sub pandora_create_agent ($$$$$$$$$$;$$$$$$$) { $longitude, $latitude, $altitude, $position_description, $custom_id, $url_address) = @_; - if (!defined($custom_id)) { - $custom_id = ''; - } - - if (!defined($url_address)) { - $url_address = ''; - } - + logger ($pa_config, "Server '$server_name' creating agent '$agent_name' address '$address'.", 10); if (!defined($group_id)) { $group_id = $pa_config->{'autocreate_group'}; - } - logger ($pa_config, "Server '$server_name' creating agent '$agent_name' address '$address'.", 10); - - $description = "Created by $server_name" unless ($description ne ''); - my $agent_id; - # Test if the optional positional parameters are defined or GIS is disabled - if (!defined ($timezone_offset) ) { - $agent_id = db_insert ($dbh, 'id_agente', 'INSERT INTO tagente (nombre, direccion, comentarios, id_grupo, id_os, server_name, intervalo, id_parent, modo, custom_id, url_address) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?)', safe_input($agent_name), $address, $description, $group_id, $os_id, $server_name, $interval, $parent_id, $custom_id, $url_address); - } - else { - $agent_id = db_insert ($dbh, 'id_agente', 'INSERT INTO tagente (nombre, direccion, comentarios, id_grupo, id_os, server_name, intervalo, id_parent, - timezone_offset, modo, custom_id, url_address) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?)', safe_input($agent_name), $address, - $description, $group_id, $os_id, $server_name, $interval, $parent_id, $timezone_offset, $custom_id, $url_address); - } - if (defined ($longitude) && defined ($latitude ) && $pa_config->{'activate_gis'} == 1 ) { - if (!defined($altitude)) { - $altitude = 0; + if (! defined (get_group_name ($dbh, $group_id))) { + logger($pa_config, "Group id $group_id does not exist (check autocreate_group config token)", 3); + return; } + } + + $description = "Created by $server_name" unless ($description ne ''); + my ($columns, $values) = db_insert_get_values ({ 'nombre' => safe_input($agent_name), + 'direccion' => $address, + 'comentarios' => $description, + 'id_grupo' => $group_id, + 'id_os' => $os_id, + 'server_name' => $server_name, + 'intervalo' => $interval, + 'id_parent' => $parent_id, + 'modo' => 1, + 'custom_id' => $custom_id, + 'url_address' => $url_address, + 'timezone_offset' => $timezone_offset + }); + + my $agent_id = db_insert ($dbh, 'id_agente', "INSERT INTO tagente $columns", @{$values}); + + # Save GIS data + if (defined ($longitude) && defined ($latitude ) && $pa_config->{'activate_gis'} == 1 ) { + # Save the first position - my $utimestamp = time (); - my $timestamp = strftime ("%Y-%m-%d %H:%M:%S", localtime ($utimestamp)); - + my $timestamp = strftime ("%Y-%m-%d %H:%M:%S", localtime (time ())); save_agent_position($pa_config, $longitude, $latitude, $altitude, $agent_id, $dbh, $timestamp, $position_description) ; } @@ -3223,25 +3253,24 @@ Saves a new agent GIS information record in B table. sub save_agent_position($$$$$$;$$) { my ($pa_config, $current_longitude, $current_latitude, $current_altitude, $agent_id, $dbh, $start_timestamp, $description) = @_; - if (!defined($description)) { - $description = ''; - } logger($pa_config, "Updating agent position: longitude=$current_longitude, latitude=$current_latitude, altitude=$current_altitude, start_timestamp=$start_timestamp agent_id=$agent_id", 10); - - if (defined($start_timestamp)) { - # Upadate the timestamp of the received agent - db_do ($dbh, 'INSERT INTO tgis_data_status (tagente_id_agente, current_longitude , current_latitude, current_altitude, - stored_longitude , stored_latitude, stored_altitude, start_timestamp, description) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)', - $agent_id, $current_longitude, $current_latitude, $current_altitude, $current_longitude, - $current_latitude, $current_altitude, $start_timestamp, $description); - } - else { - # Upadate the data of the received agent using the default timestamp - db_do ($dbh, 'INSERT INTO tgis_data_status (tagente_id_agente, current_longitude , current_latitude, current_altitude, - stored_longitude , stored_latitude, stored_altitude, description) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ', - $agent_id, $current_longitude, $current_latitude, $current_altitude, $current_longitude, - $current_latitude, $current_altitude, , $description); - } + + # Set some default values + $description = '' if (!defined($description)); + $current_altitude = 0 if (!defined($current_altitude)); + + my ($columns, $values) = db_insert_get_values ({ 'tagente_id_agente' => $agent_id, + 'current_longitude' => $current_longitude, + 'current_latitude' => $current_latitude, + 'current_altitude' => $current_altitude, + 'stored_longitude' => $current_longitude, + 'stored_latitude' => $current_latitude, + 'stored_altitude' => $current_altitude, + 'start_timestamp' => $start_timestamp, + 'description' => $description + }); + + db_do ($dbh, "INSERT INTO tgis_data_status $columns", @{$values}); } ########################################################################## @@ -3255,6 +3284,7 @@ Updates agent GIS information in B table. sub update_agent_position($$$$$$;$$$$$) { my ($pa_config, $current_longitude, $current_latitude, $current_altitude, $agent_id, $dbh, $stored_longitude, $stored_latitude, $stored_altitude, $start_timestamp, $description) = @_; + if (defined($stored_longitude) && defined($stored_latitude) && defined($start_timestamp) ) { # Upadate all the position data of the agent logger($pa_config, "Updating agent position: current_longitude=$current_longitude, current_latitude=$current_latitude, @@ -3607,7 +3637,7 @@ sub pandora_group_statistics ($$) { # Update the record. db_do ($dbh, "DELETE FROM tgroup_stat WHERE id_group = $group"); - db_do ($dbh, "INSERT INTO tgroup_stat (id_group, modules, normal, critical, warning, unknown, " . db_reserved_word ('non-init') . ", alerts, alerts_fired, agents, agents_unknown, utimestamp) VALUES ($group, $modules, $normal, $critical, $warning, $unknown, $non_init, $alerts, $alerts_fired, $agents, $agents_unknown, UNIX_TIMESTAMP())"); + db_do ($dbh, "INSERT INTO tgroup_stat (id_group, modules, normal, critical, warning, unknown, " . $PandoraFMS::DB::RDBMS_QUOTE . 'non-init' . $PandoraFMS::DB::RDBMS_QUOTE . ", alerts, alerts_fired, agents, agents_unknown, utimestamp) VALUES ($group, $modules, $normal, $critical, $warning, $unknown, $non_init, $alerts, $alerts_fired, $agents, $agents_unknown, UNIX_TIMESTAMP())"); } diff --git a/pandora_server/lib/PandoraFMS/DB.pm b/pandora_server/lib/PandoraFMS/DB.pm index d520267784..ff7cacda2d 100644 --- a/pandora_server/lib/PandoraFMS/DB.pm +++ b/pandora_server/lib/PandoraFMS/DB.pm @@ -37,12 +37,13 @@ our @EXPORT = qw( db_disconnect db_do db_insert + db_insert_get_values db_process_insert db_process_update - db_reserved_word db_string db_text db_update + db_update_get_values get_action_id get_addr_id get_agent_addr_id @@ -80,18 +81,26 @@ our @EXPORT = qw( get_agent_modules get_agentmodule_status get_agentmodule_data + $RDBMS + $RDBMS_QUOTE ); +# Relational database management system in use +our $RDBMS = ''; + +# Character used to quote reserved words in the current RDBMS +our $RDBMS_QUOTE = ''; + ########################################################################## ## Connect to the DB. ########################################################################## -my $RDBMS = ''; sub db_connect ($$$$$$) { my ($rdbms, $db_name, $db_host, $db_port, $db_user, $db_pass) = @_; if ($rdbms eq 'mysql') { $RDBMS = 'mysql'; - + $RDBMS_QUOTE = '`'; + # Connect to MySQL my $dbh = DBI->connect("DBI:mysql:$db_name:$db_host:$db_port", $db_user, $db_pass, { RaiseError => 1, AutoCommit => 1 }); return undef unless defined ($dbh); @@ -106,6 +115,7 @@ sub db_connect ($$$$$$) { } elsif ($rdbms eq 'postgresql') { $RDBMS = 'postgresql'; + $RDBMS_QUOTE = '"'; # Connect to PostgreSQL my $dbh = DBI->connect("DBI:Pg:dbname=$db_name;host=$db_host;port=$db_port", $db_user, $db_pass, { RaiseError => 1, AutoCommit => 1 }); @@ -114,6 +124,7 @@ sub db_connect ($$$$$$) { return $dbh; } elsif ($rdbms eq 'oracle') { $RDBMS = 'oracle'; + $RDBMS_QUOTE = '"'; # Connect to Oracle my $dbh = DBI->connect("DBI:Oracle:dbname=$db_name;host=$db_host;port=$db_port;sid=pandora", $db_user, $db_pass, { RaiseError => 1, AutoCommit => 1 }); @@ -616,11 +627,11 @@ sub db_insert ($$$;@) { } # PostgreSQL elsif ($RDBMS eq 'postgresql') { - $insert_id = get_db_value ($dbh, $query . ' RETURNING ' . db_reserved_word ($index), @values); + $insert_id = get_db_value ($dbh, $query . ' RETURNING ' . $RDBMS_QUOTE . $index . $RDBMS_QUOTE, @values); } # Oracle elsif ($RDBMS eq 'oracle') { - my $sth = $dbh->prepare($query . ' RETURNING ' . db_reserved_word (uc ($index)) . ' INTO ?'); + my $sth = $dbh->prepare($query . ' RETURNING ' . $RDBMS_QUOTE . (uc ($index)) . $RDBMS_QUOTE . ' INTO ?'); for (my $i = 0; $i <= $#values; $i++) { $sth->bind_param ($i+1, $values[$i]); } @@ -776,8 +787,13 @@ sub db_do ($$;@) { my ($dbh, $query, @values) = @_; #DBI->trace( 3, '/tmp/dbitrace.log' ); - +use Carp; +eval { $dbh->do($query, undef, @values); +}; +if ($@) { + print "QUERY: $query\n"; +} } ######################################################################## @@ -794,21 +810,6 @@ sub is_agent_address ($$$) { return (defined ($id_ag)) ? $id_ag : 0; } -######################################################################## -## Escape the given reserved word. -######################################################################## -sub db_reserved_word ($) { - my $reserved_word = shift; - - # MySQL - return '`' . $reserved_word . '`' if ($RDBMS eq 'mysql'); - - # PostgreSQL - return '"' . $reserved_word . '"' if ($RDBMS eq 'postgresql' || $RDBMS eq 'oracle'); - - return $reserved_word; -} - ########################################################################## ## Quote the given string. ########################################################################## @@ -885,6 +886,65 @@ sub get_priority_name ($) { return ''; } +######################################################################## +## Get the set string and array of values to perform un update from a hash. +######################################################################## +sub db_update_get_values ($) { + my ($set_ref) = @_; + + my $set = ''; + my @values; + while (my ($key, $value) = each (%{$set_ref})) { + + # Not value for the given column + next if (! defined ($value)); + + $set .= "$key = ?,"; + push (@values, $value); + } + + # Remove the last , + chop ($set); + + return ($set, \@values); +} + +######################################################################## +## Get the string and array of values to perform an insert from a hash. +######################################################################## +sub db_insert_get_values ($) { + my ($insert_ref) = @_; + + my $columns = '('; + my @values; + while (my ($key, $value) = each (%{$insert_ref})) { + + # Not value for the given column + next if (! defined ($value)); + + $columns .= $PandoraFMS::DB::RDBMS_QUOTE . "$key" . $PandoraFMS::DB::RDBMS_QUOTE . ","; + push (@values, $value); + } + + # Remove the last , and close the parentheses + chop ($columns); + $columns .= ')'; + + # No columns + if ($columns eq '()') { + return; + } + + # Add placeholders for the values + $columns .= ' VALUES (' . ("?," x ($#values + 1)); + + # Remove the last , and close the parentheses + chop ($columns); + $columns .= ')'; + + return ($columns, \@values); +} + # End of function declaration # End of defined Code diff --git a/pandora_server/lib/PandoraFMS/DataServer.pm b/pandora_server/lib/PandoraFMS/DataServer.pm index 1bd3813ab8..f8e7a5a601 100644 --- a/pandora_server/lib/PandoraFMS/DataServer.pm +++ b/pandora_server/lib/PandoraFMS/DataServer.pm @@ -213,7 +213,7 @@ sub process_xml_data ($$$$$) { # Timezone offset must be an integer beween -12 and +12 if (!defined($timezone_offset) || $timezone_offset !~ /[-+]?[0-9,11,12]/) { - $timezone_offset = 0; # Default value + $timezone_offset = 0; } # Parent Agent Name @@ -227,69 +227,6 @@ sub process_xml_data ($$$$$) { logger($pa_config,"Parent_agent_name: $parent_agent_name parent_id: $parent_id",10); } - my $valid_position_data = 1; - - # Get GIS information - my ($longitude, $latitude, $altitude, $position_description) = ( - $data->{'longitude'}, $data->{'latitude'}, $data->{'altitude'}, - $data->{'position_description'}); - - if ($pa_config->{'activate_gis'}) { - - # Validate the GIS informtation - - if (!defined($altitude) || $altitude !~ /[-+]?[0-9,11,12]/) { - $altitude = ''; # Default value - # This could be a valid position data, not always will get altitude - } - - if (!defined($longitude) || $longitude !~ /[-+]?[0-9,11,12]/) { - $longitude = ''; # Default value - $valid_position_data = 0; - } - - if (!defined($latitude) || $latitude !~ /[-+]?[0-9,11,12]/) { - $latitude = ''; # Default value - $valid_position_data = 0; - } - - if ((!defined($position_description)) && ($latitude ne '')) { #FIXME: Validate the data with a regexp - - # This code gets description (Reverse Geocoding) from a current GPS coordinates using Google maps API - # This requires a connection to internet and could be very slow and have a huge impact in performance. - # Other methods for reverse geocoding are OpenStreetmaps, in nternet or in a local server - - if ($pa_config->{'google_maps_description'}){ - my $content = get ('http://maps.google.com/maps/geo?q='.$latitude.','.$longitude.'&output=csv&sensor=false'); - my @address = split (/\"/,$content); - $position_description = $address[1]; - } - elsif ($pa_config->{'openstreetmaps_description'}){ - # Sample Query: http://nominatim.openstreetmap.org/reverse?format=csv&lat=40.43197&lon=-3.6993818&zoom=18&addressdetails=1&email=info@pandorafms.org - # Email address is sent by courtesy to OpenStreetmaps people. - # I read the API :-), thanks guys for your work. - # Change here URL to make request to a local openstreetmap server - my $content = get ('http://nominatim.openstreetmap.org/reverse?format=csv&lat='.$latitude.'&lon='.$longitude.'&zoom=18&addressdetails=1&email=info@pandorafms.org'); - - if ((defined($content)) && ($content ne "")){ - # Yep, I need to parse the XML output. - my $xs1 = XML::Simple->new(); - my $doc = $xs1->XMLin($content); - $position_description = safe_input ($doc->{result}{content}); - } else { - $position_description = ""; - } - - } - } - - if (!defined($position_description)){ - $position_description = ""; - } - - logger($pa_config, "Getting GIS Data=timezone_offset=$timezone_offset longitude=$longitude latitude=$latitude altitude=$altitude position_description=$position_description", 8); - } - # Unknown agent! if (! defined ($agent_name) || $agent_name eq '') { logger($pa_config, "$file_name has data from an unnamed agent", 3); @@ -300,26 +237,25 @@ sub process_xml_data ($$$$$) { if ( $data->{'timestamp'} =~ /AUTO/ ){ $timestamp = strftime ("%Y/%m/%d %H:%M:%S", localtime()); } - else { - if ($timezone_offset != 0) { + # Apply an offset to the timestamp + elsif ($timezone_offset != 0) { + # Modify the timestamp with the timezone_offset - logger($pa_config, "Unmodified timestamp = $timestamp", 5); - $timestamp =~ /(\d+)[\/|\-](\d+)[\/|\-](\d+) +(\d+):(\d+):(\d+)/; - logger($pa_config, "Unmodified timestamp = $1/$2/$3 $4:$5:$6", 5); - my $utimestamp = ($timezone_offset * 3600); - eval { - $utimestamp += timelocal($6, $5, $4, $3, $2 -1 , $1 - 1900); - }; - if ($@) { - logger($pa_config,"WARNING: Invalid timestamp ($@) using server timestamp.", 4); - $timestamp = strftime ("%Y/%m/%d %H:%M:%S", localtime()); - } - logger($pa_config, "Seconds timestamp = $timestamp modified timestamp in seconds $utimestamp with timezone_offset = $timezone_offset", 5); - $timestamp = strftime ("%Y-%m-%d %H:%M:%S", localtime($utimestamp)); + logger($pa_config, "Applied a timezone offset of $timestamp to agent " . $data->{'agent_name'}, 10); + + # Calculate the start date to add the offset + my $utimestamp = 0; + eval { + if ($timestamp =~ /(\d+)[\/|\-](\d+)[\/|\-](\d+) +(\d+):(\d+):(\d+)/) { + $utimestamp = timelocal($6, $5, $4, $3, $2 -1 , $1 - 1900); + } + }; + + # Apply the offset if there were no errors + if (! $@ && $utimestamp != 0) { + $timestamp = strftime ("%Y-%m-%d %H:%M:%S", localtime($utimestamp + ($timezone_offset * 3600))); } - logger($pa_config, "Modified timestamp = $timestamp with timezone_offset = $timezone_offset", 5); } - # Check some variables $interval = 300 if (! defined ($interval) || $interval eq ''); @@ -351,21 +287,9 @@ sub process_xml_data ($$$$$) { my $description = ''; $description = $data->{'description'} if (defined ($data->{'description'})); - - # Create the agent - if ($valid_position_data == 1 && $pa_config->{'activate_gis'} != 0 ) { - logger($pa_config, "Creating agent $agent_name at long: $longitude lat: $latitude alt: $altitude", 5); - } - else { # Ignore agent positional data - logger($pa_config, "Creating agent $agent_name", 5); - $longitude = undef; - $latitude = undef; - $altitude = undef; - $position_description = undef; - } $agent_id = pandora_create_agent($pa_config, $pa_config->{'servername'}, $agent_name, $address, $group_id, $parent_id, $os, - $description, $interval, $dbh, $timezone_offset, $longitude, $latitude, $altitude, $position_description, $custom_id, $url_address); + $description, $interval, $dbh, $timezone_offset, undef, undef, undef, undef, $custom_id, $url_address); if (! defined ($agent_id)) { return; @@ -419,12 +343,16 @@ sub process_xml_data ($$$$$) { $agent_version = $agent->{'agent_version'}; $timezone_offset = $agent->{'timezone_offset'}; $parent_id = $agent->{'id_parent'}; - } - else { # Learning mode + } + # Learning mode + else { + # Update agent address if necessary if ($address ne '' && $address ne $agent->{'direccion'}) { + # Update the main address pandora_update_agent_address ($pa_config, $agent_id, $agent_name, $address, $dbh); + # Update the addres list if necessary pandora_add_agent_address($pa_config, $agent_id, $address, $dbh); } @@ -479,23 +407,16 @@ sub process_xml_data ($$$$$) { } } - - # Update GIS data only if is allowed and is valid position - if ($valid_position_data == 1 && $pa_config->{'activate_gis'} != 0) { - logger($pa_config, "Updating agent $agent_name at long: $longitude lat: $latitude alt: $altitude parent_id: $parent_id", 5); - } - else { - $longitude = undef; - $latitude = undef; - $altitude = undef; - $position_description = undef; - } # Update agent information - pandora_update_agent($pa_config, $timestamp, $agent_id, $os_version, $agent_version, $interval, $dbh, $timezone_offset, - $longitude, $latitude, $altitude, $position_description, $parent_id); - + pandora_update_agent($pa_config, $timestamp, $agent_id, $os_version, $agent_version, $interval, $dbh, $timezone_offset, $parent_id); + + # Update GIS data + if ($pa_config->{'activate_gis'} != 0 && $agent->{'update_gis_data'} == 1) { + pandora_update_gis_data ($pa_config, $dbh, $agent_id, $agent_name, $data->{'longitude'}, $data->{'latitude'}, $data->{'altitude'}, $data->{'position_description'}, $timestamp); + } + # Update keep alive modules pandora_module_keep_alive ($pa_config, $agent_id, $agent_name, $server_id, $dbh); # Process modules