###############################################################################
## OCSINVENTORY-NG
## Copyleft Pascal DANEK 2008
## Web : http://www.ocsinventory-ng.org
##
## This code is open source and may be copied and modified as long as the source
## code is always made freely available.
## Please refer to the General Public Licence http://www.gnu.org/ or Licence.txt
################################################################################
package Apache::Ocsinventory::Server::Inventory::Update;
use Apache::Ocsinventory::Server::Inventory::Cache;
use Apache::Ocsinventory::Server::Inventory::Update::Hardware;
use Apache::Ocsinventory::Server::Inventory::Update::AccountInfos;
use strict;
use Encode;
require Exporter;
our @ISA = qw /Exporter/;
our @EXPORT = qw / _update_inventory /;
use Apache::Ocsinventory::Server::System qw / :server /;
use Apache::Ocsinventory::Server::Inventory::Data;
sub _update_inventory{
my ( $sectionsMeta, $sectionsList ) = @_;
my $section;
&_reset_inventory_cache( $sectionsMeta, $sectionsList ) if $ENV{OCS_OPT_INVENTORY_CACHE_ENABLED};
# Call special sections update
#if(&_hardware() or &_accountinfo()){
# return 1;
#}
# Call the _update_inventory_section for each section
for $section (@{$sectionsList}){
if(_update_inventory_section($section, $sectionsMeta->{$section})){
return 1;
}
}
}
sub _update_inventory_section{
my ($section, $sectionMeta) = @_;
my @bind_values;
my $deviceId = $Apache::Ocsinventory::CURRENT_CONTEXT{'DATABASE_ID'};
my $result = $Apache::Ocsinventory::CURRENT_CONTEXT{'XML_ENTRY'};
my $dbh = $Apache::Ocsinventory::CURRENT_CONTEXT{'DBI_HANDLE'};
# The computer exists.
# We check if this section has changed since the last inventory (only if activated)
# We delete the previous entries
# if($Apache::Ocsinventory::CURRENT_CONTEXT{'EXIST_FL'}){
# if($ENV{'OCS_OPT_INVENTORY_DIFF'}){
# if( _has_changed($section) ){
# &_log( 113, 'inventory', "u:$section") if $ENV{'OCS_OPT_LOGLEVEL'};
# $sectionMeta->{hasChanged} = 1;
# }
# else{
# return 0;
# }
# }
# else{
# $sectionMeta->{hasChanged} = 1;
# }
# if( $sectionMeta->{delOnReplace} && !($sectionMeta->{writeDiff} && $ENV{'OCS_OPT_INVENTORY_WRITE_DIFF'}) ){
# if(!$dbh->do("DELETE FROM $section WHERE HARDWARE_ID=?", {}, $deviceId)){
# return(1);
# }
# }
# }
# DEL AND REPLACE, or detect diff on elements of the section (more load on frontends, less on DB backend)
#if($Apache::Ocsinventory::CURRENT_CONTEXT{'EXIST_FL'} && $ENV{'OCS_OPT_INVENTORY_WRITE_DIFF'} && $sectionMeta->{writeDiff}){
if(1){
my @fromDb;
my @fromXml;
my $refXml = $result->{CONTENT}->{uc $section};
my $sth = $dbh->prepare($sectionMeta->{sql_select_string});
$sth->execute($deviceId) or return 0;
while(my @row = $sth->fetchrow_array){
push @fromDb, [ @row ];
}
for my $line (@$refXml){
&_get_bind_values($line, $sectionMeta, /@bind_values);
push @fromXml, [ @bind_values ];
@bind_values = ();
}
# my $sql2="insert into test(content,transdatetime,strdesc) values('".$section."',now(),'".$sectionMeta->{name}."')";
# my $sth2=$dbh->prepare($sql2);
# $sth2->execute() or return 1;
#TODO: Sorting XML entries, to compare more quickly with DB elements
my $new=0;
my $del=0;
for my $l_xml (@fromXml){
my $found = 0;
for my $i_db (0..$#fromDb){
next unless $fromDb[$i_db];
my @line = @{$fromDb[$i_db]};
my $comp_xml = join '', @$l_xml;
my $comp_db = join '', @line[2..$#line];
$comp_db = encode("iso-8859-1",decode("utf-8",$comp_db));
#$comp_xml = encode("iso-8859-1",decode("gb2312",$comp_xml));
#special for drives ,remove string 0000-00-00 00:00:00
if($sectionMeta->{name} eq "drives") {
substr($comp_db,index($comp_db,"0000-00-00 00:00:00"),19)="";
}
# my $sql2="insert into comp(db,xml) values('".$comp_db."','".$comp_xml."')";
# my $sth3=$dbh->prepare($sql2);
# $sth3->execute() or return 1;
# my $sql2="insert into test(content,transdatetime,strdesc) values('".@$l_xml[0]."',now(),'".$sectionMeta->{name}."')";
# my $sth2=$dbh->prepare($sql2);
# $sth2->execute() or return 1;
if( $comp_db eq $comp_xml ){
$found = 1;
# my $sql3="insert into comp(db,xml) values('".$comp_db."','".$comp_xml."')";
# my $sth3=$dbh->prepare($sql3);
# $sth3->execute() or return 1;
# The value has been found, we have to delete it from the db list
# (elements remaining will be deleted)
delete $fromDb[$i_db];
last;
}
else{
# my $sql4="insert into comp_diff(db,xml) values('".$comp_db."','".$comp_xml."')";
# my $sth4=$dbh->prepare($sql4);
# $sth4->execute() or return 1;
}
}
if(!$found){
$new++;
# my $sql="insert into test(content,transdatetime,strdesc) values('".@$l_xml[0]."',now(),'".$sectionMeta->{name}."')";
# my $sth2=$dbh->prepare($sql);
# $sth2->execute() or return 1;
my $strflag='Add';
my $new_sql_insert_string;
$new_sql_insert_string=($sectionMeta->{sql_insert_string});
substr($new_sql_insert_string,0)=~ s/$sectionMeta->{name}/new_$sectionMeta->{name}/g; #replace table name
substr($new_sql_insert_string,rindex($new_sql_insert_string,"`"))=~ s/`/`,`STRFLAG`/g; #add field STRFLAG
substr($new_sql_insert_string,rindex($new_sql_insert_string,","))=~ s/,/,?,/g; # add field value position
substr($new_sql_insert_string,rindex($new_sql_insert_string,"`"))=~ s/`/`,`TRANSDATETIME`/g; #add field TRANSDATETIME
substr($new_sql_insert_string,rindex($new_sql_insert_string,","))=~ s/,/,?,/g; # add field value position
# my $sql2="insert into test(content,transdatetime,strdesc) values('".$new_sql_insert_string."',now(),'".$sectionMeta->{name}."')";
# my $sth2=$dbh->prepare($sql2);
# $sth2->execute() or return 1;
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
my $yyyymmdd=sprintf("%04d-%02d-%02d",$year+1900,$mon+1,$mday);
my $hhmmss=sprintf("%02d:%02d:%02d",$hour,$min,$sec);
my $transdatetime=$yyyymmdd." ".$hhmmss;
$dbh->do( $new_sql_insert_string, {}, $deviceId, @$l_xml,$strflag,$transdatetime ) or return 1;
$dbh->do( $sectionMeta->{sql_insert_string}, {}, $deviceId, @$l_xml ) or return 1;
if( $ENV{OCS_OPT_INVENTORY_CACHE_ENABLED} && $sectionMeta->{cache} ){
&_cache( 'add', $section, $sectionMeta, $l_xml );
}
}
}
# Now we have to delete from DB elements that still remain in fromDb
for (@fromDb){
next if !defined (${$_}[0]);
$del++;
# my $sql2="insert into test(content,transdatetime,strdesc) values('".$sectionMeta->{sql_delete_string}."',now(),'".$sectionMeta->{name}."')";
# my $sth2=$dbh->prepare($sql2);
# $sth2->execute() or return 1;
my $strflag='Delete';
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
my $yyyymmdd=sprintf("%04d-%02d-%02d",$year+1900,$mon+1,$mday);
my $hhmmss=sprintf("%02d:%02d:%02d",$hour,$min,$sec);
my $transdatetime=$yyyymmdd." ".$hhmmss;
my $sql3="insert into new_".$sectionMeta->{name}." select *,'".$strflag."' as STRFLAG,'".$transdatetime."' as TRANSDATETIME from ".$sectionMeta->{name}." where hardware_id='".$deviceId."' and id='".${$_}[0]."'";
my $sth3=$dbh->prepare($sql3);
$sth3->execute() or return 1;
$dbh->do( $sectionMeta->{sql_delete_string}, {}, $deviceId, ${$_}[0]) or return 1;
my @ldb = @$_;
@ldb = @ldb[ 2..$#ldb ];
if( $ENV{OCS_OPT_INVENTORY_CACHE_ENABLED} && $sectionMeta->{cache} && !$ENV{OCS_OPT_INVENTORY_CACHE_KEEP}){
&_cache( 'del', $section, $sectionMeta, /@ldb );
}
}
if( $new||$del ){
# my $sql="insert into test(strdesc,transdatetime) values('".$section."',now())";
# my $sth2=$dbh->prepare($sql);
# $sth2->execute();
#
&_log( 113, 'write_diff', "ch:$section(+$new-$del)") if $ENV{'OCS_OPT_LOGLEVEL'};
}
}
else{
# Processing values
my $sth = $dbh->prepare( $sectionMeta->{sql_insert_string} );
# Multi lines (forceArray)
my $refXml = $result->{CONTENT}->{uc $section};
if($sectionMeta->{multi}){
for my $line (@$refXml){
&_get_bind_values($line, $sectionMeta, /@bind_values);
if(!$sth->execute($deviceId, @bind_values)){
return(1);
}
if( $ENV{OCS_OPT_INVENTORY_CACHE_ENABLED} && $sectionMeta->{cache} ){
&_cache( 'add', $section, $sectionMeta, /@bind_values );
}
@bind_values = ();
}
}
# One line (hash)
else{
&_get_bind_values($refXml, $sectionMeta, /@bind_values);
if( !$sth->execute($deviceId, @bind_values) ){
return(1);
}
if( $ENV{OCS_OPT_INVENTORY_CACHE_ENABLED} && $sectionMeta->{cache} ){
&_cache( 'add', $section, $sectionMeta, /@bind_values );
}
}
}
$dbh->commit unless $ENV{'OCS_OPT_INVENTORY_TRANSACTION'};
0;
}
1;