Code

Updated locales
[gosa.git] / gosa-si / modules / GosaSupportDaemon.pm
index f90c149cc35f52a310b41bb80f0c035177f7dadc..651bd57d7a1d914fec06b226d69cbdfd08d60014 100644 (file)
@@ -1,15 +1,34 @@
-package GOSA::GosaSupportDaemon;
+package GOsaSI::GosaSupportDaemon;
 
+use strict;
+use warnings;
+
+use IO::Socket::INET;
+use Crypt::Rijndael;
+use Digest::MD5  qw(md5 md5_hex md5_base64);
+use MIME::Base64;
+use XML::Quote qw(:all);
+use XML::Simple;
+use Data::Dumper;
+use Net::DNS;
+use Net::ARP;
+
+use DateTime;
 use Exporter;
-@ISA = qw(Exporter);
+
+our @ISA = qw(Exporter);
+
 my @functions = (
     "create_passwd",
     "create_xml_hash",
+    "createXmlHash",
+    "myXmlHashToString",
     "get_content_from_xml_hash",
     "add_content2xml_hash",
     "create_xml_string",
     "transform_msg2hash",
     "get_time",
+    "get_utc_time",
     "build_msg",
     "db_res2xml",
     "db_res2si_msg",
@@ -26,23 +45,18 @@ my @functions = (
     "get_ip",
     "get_interface_for_ip",
     "get_interfaces",
+    "get_mac_for_interface",
+    "get_local_ip_for_remote_ip",
     "is_local",
     "run_as",
     "inform_all_other_si_server",
     "read_configfile",
     "check_opsi_res",
-    ); 
-@EXPORT = @functions;
-use strict;
-use warnings;
-use IO::Socket::INET;
-use Crypt::Rijndael;
-use Digest::MD5  qw(md5 md5_hex md5_base64);
-use MIME::Base64;
-use XML::Simple;
-use Data::Dumper;
-use Net::DNS;
-
+    "calc_timestamp",
+    "opsi_callobj2string",
+    );
+    
+our @EXPORT = @functions;
 
 my $op_hash = {
     'eq' => '=',
@@ -61,7 +75,7 @@ END {}
 
 ### Start ######################################################################
 
-my $xml = new XML::Simple();
+our $xml = new XML::Simple();
 
 sub daemon_log {
     my ($msg, $level) = @_ ;
@@ -107,6 +121,91 @@ sub create_xml_hash {
     return $hash
 }
 
+sub createXmlHash {
+       my ($header, $source, $target) = @_;
+       return { header=>$header, source=>$source, target=>$target};
+}
+
+sub _transformHashToString {
+       my ($hash) = @_;
+       my $s = "";
+
+       while (my ($tag, $content) = each(%$hash)) {
+
+               if (ref $content eq "HASH") {
+                       $s .= "<$tag>".&_transformHashToString($content)."</$tag>";
+               } elsif ( ref $content eq "ARRAY") {
+                       $s .= &_transformArrayToString($tag, $content);
+               } else {
+                       $content = defined $content ? $content : "";
+                       $s .= "<$tag>".&xml_quote($content)."</$tag>";
+               }
+       }
+       return $s;
+}
+
+sub _transformArrayToString {
+       my ($tag, $contentArray) = @_;
+       my $s = "";
+       foreach my $content (@$contentArray) {
+               if (ref $content eq "HASH") {
+                       $s .= "<$tag>".&_transformHashToString($content)."</$tag>";
+               } else {
+                       $content = defined $content ? $content : "";
+                       $s .= "<$tag>".&xml_quote($content)."</$tag>";
+               }
+       }
+       return $s;
+}
+
+
+#===  FUNCTION  ================================================================
+#         NAME:  myXmlHashToString
+#   PARAMETERS:  xml_hash - hash - hash from function createXmlHash
+#      RETURNS:  xml_string - string - xml string representation of the hash
+#  DESCRIPTION:  Transforms the given hash to a xml wellformed string. I.e.:
+#                   {
+#                   'header' => 'a'
+#                   'source' => 'c',
+#                   'target' => 'b',
+#                   'hit' => [ '1',
+#                              '2',
+#                              { 
+#                                'hit31' => 'ABC',
+#                               'hit32' => 'XYZ'
+#                              }
+#                            ],
+#                   'res0' => {
+#                      'res1' => {
+#                         'res2' => 'result'
+#                      }
+#                   },
+#               };
+#           
+#                               will be transformed to 
+#                               <xml>
+#                                      <header>a</header>
+#                                      <source>c</source>
+#                                      <target>b</target>
+#                                      <hit>1</hit>
+#                                      <hit>2</hit>
+#                                      <hit>
+#                                              <hit31>ABC</hit31>
+#                                              <hit32>XYZ</hit32>
+#                                      </hit>
+#                                      <res0>
+#                                              <res1>
+#                                                      <res2>result</res2>
+#                                              </res1>
+#                                      </res0>
+#                              </xml>
+#
+#===============================================================================
+sub myXmlHashToString {
+       my ($hash) = @_;
+       return "<xml>".&_transformHashToString($hash)."</xml>";
+}
+
 
 #===  FUNCTION  ================================================================
 #         NAME:  create_xml_string
@@ -176,17 +275,23 @@ sub add_content2xml_hash {
 
 
 sub get_time {
-    my ($seconds, $minutes, $hours, $monthday, $month,
-            $year, $weekday, $yearday, $sommertime) = localtime(time);
-    $hours = $hours < 10 ? $hours = "0".$hours : $hours;
-    $minutes = $minutes < 10 ? $minutes = "0".$minutes : $minutes;
-    $seconds = $seconds < 10 ? $seconds = "0".$seconds : $seconds;
-    $month+=1;
-    $month = $month < 10 ? $month = "0".$month : $month;
-    $monthday = $monthday < 10 ? $monthday = "0".$monthday : $monthday;
-    $year+=1900;
-    return "$year$month$monthday$hours$minutes$seconds";
+       my ($seconds, $minutes, $hours, $monthday, $month,
+               $year, $weekday, $yearday, $sommertime) = localtime;
+       $hours = $hours < 10 ? $hours = "0".$hours : $hours;
+       $minutes = $minutes < 10 ? $minutes = "0".$minutes : $minutes;
+       $seconds = $seconds < 10 ? $seconds = "0".$seconds : $seconds;
+       $month+=1;
+       $month = $month < 10 ? $month = "0".$month : $month;
+       $monthday = $monthday < 10 ? $monthday = "0".$monthday : $monthday;
+       $year+=1900;
+       return "$year$month$monthday$hours$minutes$seconds";
+}
+
 
+sub get_utc_time {
+    my $utc_time = qx(date --utc +%Y%m%d%H%M%S);
+    $utc_time =~ s/\s$//;
+    return $utc_time;
 }
 
 
@@ -234,7 +339,7 @@ sub db_res2xml {
             if( $column_name eq "xmlmessage" ) {
                 $xml_content = &encode_base64($column_value);
             } else {
-                $xml_content = $column_value;
+                $xml_content = defined $column_value ? $column_value : "";
             }
             $xml .= $xml_content;
             $xml .= "</$column_name>"; 
@@ -410,8 +515,8 @@ sub get_orderby_statement {
 sub get_dns_domains() {
         my $line;
         my @searches;
-        open(RESOLV, "</etc/resolv.conf") or return @searches;
-        while(<RESOLV>){
+        open(my $RESOLV, "<", "/etc/resolv.conf") or return @searches;
+        while(<$RESOLV>){
                 $line= $_;
                 chomp $line;
                 $line =~ s/^\s+//;
@@ -423,7 +528,7 @@ sub get_dns_domains() {
                         push(@searches, split(/ /, $1));
                 }
         }
-        close(RESOLV);
+        close($RESOLV);
 
         my %tmp = map { $_ => 1 } @searches;
         @searches = sort keys %tmp;
@@ -512,7 +617,13 @@ sub import_events {
 
     if ($error == 0) {
         while (defined (my $event = readdir ($DIR))) {
-            if( $event eq "." || $event eq ".." ) { next; }  
+            if( $event eq "." || $event eq ".." || ($event =~ /^\.pm$/)) { next; }  
+
+                       # Check config file to exclude disabled event plugins (i.e. Opsi)
+                       if ($event eq "opsi_com.pm" &&  $main::opsi_enabled ne "true")  { 
+                               &main::daemon_log("0 WARNING: opsi-module is installed but not enabled in config file, please set under section '[OPSI]': 'enabled=true'", 3);  
+                               next; 
+                       }
 
             # try to import event module
             eval{ require $event; };
@@ -582,6 +693,15 @@ sub get_ip {
 sub get_interface_for_ip {
        my $result;
        my $ip= shift;
+
+       if($ip =~ /^[a-z]/i) {
+               my $ip_address = inet_ntoa(scalar gethostbyname($ip));
+               if(defined($ip_address) && $ip_address =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/) {
+                       # Write ip address to $source variable
+                       $ip = $ip_address;
+               }
+       }
+
        if ($ip && length($ip) > 0) {
                my @ifs= &get_interfaces();
                if($ip eq "0.0.0.0") {
@@ -608,12 +728,12 @@ sub get_interfaces {
        my @result;
        my $PROC_NET_DEV= ('/proc/net/dev');
 
-       open(PROC_NET_DEV, "<$PROC_NET_DEV")
+       open(my $FD_PROC_NET_DEV, "<", "$PROC_NET_DEV")
                or die "Could not open $PROC_NET_DEV";
 
-       my @ifs = <PROC_NET_DEV>;
+       my @ifs = <$FD_PROC_NET_DEV>;
 
-       close(PROC_NET_DEV);
+       close($FD_PROC_NET_DEV);
 
        # Eat first two line
        shift @ifs;
@@ -629,6 +749,75 @@ sub get_interfaces {
        return @result;
 }
 
+sub get_local_ip_for_remote_ip {
+       my $remote_ip= shift;
+       my $result="0.0.0.0";
+
+    if($remote_ip =~ /^(\d\d?\d?\.){3}\d\d?\d?$/) {
+        my $PROC_NET_ROUTE= ('/proc/net/route');
+
+        open(my $FD_PROC_NET_ROUTE, "<", "$PROC_NET_ROUTE")
+            or die "Could not open $PROC_NET_ROUTE";
+
+        my @ifs = <$FD_PROC_NET_ROUTE>;
+
+        close($FD_PROC_NET_ROUTE);
+
+        # Eat header line
+        shift @ifs;
+        chomp @ifs;
+        my $iffallback = ''; 
+
+        # linux-vserver might have * as Iface due to hidden interfaces, set a default 
+        foreach my $line(@ifs) { 
+            my ($Iface,$Destination,$Gateway,$Flags,$RefCnt,$Use,$Metric,$Mask,$MTU,$Window,$IRTT)=split(/\s/, $line); 
+            if ($Iface =~ m/^[^\*]+$/) { 
+                 $iffallback = $Iface; 
+            } 
+        }
+        foreach my $line(@ifs) {
+            my ($Iface,$Destination,$Gateway,$Flags,$RefCnt,$Use,$Metric,$Mask,$MTU,$Window,$IRTT)=split(/\s/, $line);
+            my $destination;
+            my $mask;
+            my ($d,$c,$b,$a)=unpack('a2 a2 a2 a2', $Destination);
+            if ($Iface =~ m/^[^\*]+$/) { 
+                 $iffallback = $Iface;
+            } 
+            $destination= sprintf("%d.%d.%d.%d", hex($a), hex($b), hex($c), hex($d));
+            ($d,$c,$b,$a)=unpack('a2 a2 a2 a2', $Mask);
+            $mask= sprintf("%d.%d.%d.%d", hex($a), hex($b), hex($c), hex($d));
+            if(new NetAddr::IP($remote_ip)->within(new NetAddr::IP($destination, $mask))) {
+                # destination matches route, save mac and exit
+                #$result= &get_ip($Iface);
+
+                if ($Iface =~ m/^\*$/ ) { 
+                    $result= &get_ip($iffallback);    
+                } else { 
+                    $result= &get_ip($Iface); 
+                } 
+                last;
+            }
+        }
+    } 
+
+       return $result;
+}
+
+
+sub get_mac_for_interface {
+       my $ifreq= shift;
+       my $result;
+       if ($ifreq && length($ifreq) > 0) {
+               if($ifreq eq "all") {
+                       $result = "00:00:00:00:00:00";
+               } else {
+        $result = Net::ARP::get_mac($ifreq);
+               }
+       }
+       return $result;
+}
+
 
 #===  FUNCTION  ================================================================
 #         NAME:  is_local
@@ -671,10 +860,12 @@ sub run_as {
                &main::daemon_log("ERROR: The sudo utility is not available! Please fix this!");
        }
        my $cmd_line= "$sudo_cmd su - $uid -c '$command'";
-       open(PIPE, "$cmd_line |");
-       my $result = {'resultCode' => $?};
-       $result->{'command'} = $cmd_line;
-       push @{$result->{'output'}}, <PIPE>;
+       open(my $PIPE, "$cmd_line |");
+       my $result = {'command' => $cmd_line};
+       push @{$result->{'output'}}, <$PIPE>;
+       close($PIPE);
+       my $exit_value = $? >> 8;
+       $result->{'resultCode'} = $exit_value;
        return $result;
 }
 
@@ -718,7 +909,7 @@ sub read_configfile {
     my $cfg;
     if( defined( $cfg_file) && ( (-s $cfg_file) > 0 )) {
         if( -r $cfg_file ) {
-            $cfg = Config::IniFiles->new( -file => $cfg_file );
+            $cfg = Config::IniFiles->new( -file => $cfg_file, -nocase => 1 );
         } else {
             print STDERR "Couldn't read config file!";
         }
@@ -741,17 +932,66 @@ sub check_opsi_res {
         if ($res->is_error) {
             my $error_string;
             if (ref $res->error_message eq "HASH") { 
+                               # for different versions
                 $error_string = $res->error_message->{'message'}; 
+                               $_ = $res->error_message->{'message'};
             } else { 
+                               # for different versions
                 $error_string = $res->error_message; 
+                               $_ = $res->error_message;
             }
             return 1, $error_string;
         }
     } else {
+               # for different versions
+               $_ = $main::opsi_client->status_line;
         return 1, $main::opsi_client->status_line;
     }
     return 0;
 }
 
+sub calc_timestamp {
+    my ($timestamp, $operation, $value, $entity) = @_ ;
+       $entity = defined $entity ? $entity : "seconds";
+    my $res_timestamp = 0;
+    
+    $value = int($value);
+    $timestamp = int($timestamp);
+    $timestamp =~ /(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/;
+    my $dt = DateTime->new( year   => $1,
+            month  => $2,
+            day    => $3,
+            hour   => $4,
+            minute => $5,
+            second => $6,
+            );
+
+    if ($operation eq "plus" || $operation eq "+") {
+        $dt->add($entity => $value);
+        $res_timestamp = $dt->ymd('').$dt->hms('');
+    }
+
+    if ($operation eq "minus" || $operation eq "-") {
+        $dt->subtract($entity => $value);
+        $res_timestamp = $dt->ymd('').$dt->hms('');
+    }
+
+    return $res_timestamp;
+}
+
+sub opsi_callobj2string {
+    my ($callobj) = @_;
+    my @callobj_string;
+    while(my ($key, $value) = each(%$callobj)) {
+        my $value_string = "";
+        if (ref($value) eq "ARRAY") {
+            $value_string = join(",", @$value);
+        } else {
+            $value_string = $value;
+        }
+        push(@callobj_string, "$key=$value_string")
+    }
+    return join(", ", @callobj_string);
+}
 
 1;