| 33 |  | $fqdn | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 34 |  | $pidfile | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 35 |  | $retry_wait | 
 
 
 
 
 
 
 
 | 36 | + | $ostype | 
 
 
 
 
 
 
 
 | 37 | + | $key | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 38 |  | @data | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 39 |  | ); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 40 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 48 |  | $seq_no = 1; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 49 |  | $retry_wait = 60; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 50 |  |  | 
 
 
 
 
 
 
 
 | 51 | + | # work out our platform, if we can. | 
 
 
 
 
 
 
 
 | 52 | + | $ostype = `uname -s`; | 
 
 
 
 
 
 
 
 | 53 | + | chomp $ostype; | 
 
 
 
 
 
 
 
 | 54 | + | $ostype = "unknown" if not defined $ostype; | 
 
 
 
 
 
 
 
 | 55 | + |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 56 |  | # write our PID to a file | 
 
 
 
 
 
 
 
 
 
 
 | 57 | < | $pidfile = "/var/tmp/ihost.pid"; | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 57 | > | # use home dir by default | 
 
 
 
 
 | 58 | > | #$pidfile = $ENV{"HOME"}; | 
 
 
 
 
 | 59 | > | # or drop it in /var/tmp if we can't find HOME | 
 
 
 
 
 | 60 | > | $pidfile = "/var/tmp" if not defined $pidfile; | 
 
 
 
 
 | 61 | > | $pidfile .= "/.ihost.pid"; | 
 
 
 
 
 
 
 
 
 
 
 | 62 |  | &write_pid(); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 63 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 64 |  | &tcp_configure(); | 
 
 
 
 
 
 
 
 | 65 | + | &send_tcp_heartbeat(); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 66 |  | &send_udp_packet(); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 67 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 68 |  | $last_udp_time = time; | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 142 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 143 |  | print $sock "LASTMODIFIED\n"; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 144 |  | $response = <$sock>; | 
 
 
 
 
 
 
 
 
 
 
 | 145 | < | if (!$response) { | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 146 | < | print "The i-scream server did not return anything for the LASTMODIFIED command.\n"; | 
 
 
 
 
 
 
 
 
 | 145 | > | if (!$response || $response eq "ERROR\n") { | 
 
 
 
 
 | 146 | > | print "The i-scream server did not provide the LASTMODIFIED value.\n"; | 
 
 
 
 
 
 
 
 
 
 
 | 147 |  | close($sock); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 148 |  | wait_then_retry(); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 149 |  | next; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 150 |  | } | 
 
 
 
 
 
 
 
 
 
 
 | 151 | < | chop $response; | 
 
 
 
 
 
 
 
 
 | 151 | > | chomp $response; | 
 
 
 
 
 
 
 
 
 
 
 | 152 |  | $last_modified = $response; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 153 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 154 |  | print "Config last modified: ". (scalar localtime $last_modified/1000) . "\n"; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 155 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 156 |  | print $sock "FILELIST\n"; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 157 |  | $response = <$sock>; | 
 
 
 
 
 
 
 
 
 
 
 | 158 | < | if (!$response) { | 
 
 
 
 
 
 
 
 
 | 158 | > | if (!$response || $response eq "ERROR\n") { | 
 
 
 
 
 
 
 
 
 
 
 | 159 |  | print "The i-scream server did not provide a configuration file list.\n"; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 160 |  | close($sock); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 161 |  | wait_then_retry(); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 162 |  | next; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 163 |  | } | 
 
 
 
 
 
 
 
 
 
 
 | 164 | < | chop $response; | 
 
 
 
 
 
 
 
 
 | 164 | > | chomp $response; | 
 
 
 
 
 
 
 
 
 
 
 | 165 |  | $file_list = $response; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 166 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 167 |  | print "File list obtained: $file_list\n"; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 168 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 169 |  | print $sock "FQDN\n"; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 170 |  | $response = <$sock>; | 
 
 
 
 
 
 
 
 
 
 
 | 171 | < | if (!$response) { | 
 
 
 
 
 
 
 
 
 | 171 | > | if (!$response || $response eq "ERROR\n") { | 
 
 
 
 
 
 
 
 
 
 
 | 172 |  | print "The i-scream server did not tell us our FQDN.\n"; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 173 |  | close($sock); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 174 |  | wait_then_retry(); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 175 |  | next; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 176 |  | } | 
 
 
 
 
 
 
 
 
 
 
 | 177 | < | chop $response; | 
 
 
 
 
 
 
 
 
 | 177 | > | chomp $response; | 
 
 
 
 
 
 
 
 
 
 
 | 178 |  | $fqdn = $response; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 179 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 180 |  | print "FQDN returned: $fqdn\n"; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 181 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 182 |  | print $sock "UDPUpdateTime\n"; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 183 |  | $response = <$sock>; | 
 
 
 
 
 
 
 
 
 
 
 | 184 | < | if (!$response) { | 
 
 
 
 
 
 
 
 
 | 184 | > | if (!$response || $response eq "ERROR\n") { | 
 
 
 
 
 
 
 
 
 
 
 | 185 |  | print "The i-scream server did not give us a UDPUpdateTime.\n"; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 186 |  | close($sock); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 187 |  | wait_then_retry(); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 188 |  | next; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 189 |  | } | 
 
 
 
 
 
 
 
 
 
 
 | 190 | < | chop $response; | 
 
 
 
 
 
 
 
 
 | 190 | > | chomp $response; | 
 
 
 
 
 
 
 
 
 
 
 | 191 |  | $udp_update_time = $response; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 192 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 193 |  | print $sock "TCPUpdateTime\n"; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 194 |  | $response = <$sock>; | 
 
 
 
 
 
 
 
 
 
 
 | 195 | < | if (!$response) { | 
 
 
 
 
 
 
 
 
 | 195 | > | if (!$response || $response eq "ERROR\n") { | 
 
 
 
 
 
 
 
 
 
 
 | 196 |  | print "The i-scream server did not give us a TCPUpdateTime.\n"; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 197 |  | close($sock); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 198 |  | wait_then_retry(); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 199 |  | next; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 200 |  | } | 
 
 
 
 
 
 
 
 
 
 
 | 201 | < | chop $response; | 
 
 
 
 
 
 
 
 
 | 201 | > | chomp $response; | 
 
 
 
 
 
 
 
 
 
 
 | 202 |  | $tcp_update_time = $response; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 203 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 204 |  | print "UDP packet period: $udp_update_time seconds.\nTCP heartbeat period: $tcp_update_time seconds.\n"; | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 222 |  | wait_then_retry(); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 223 |  | next; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 224 |  | } | 
 
 
 
 
 
 
 
 
 
 
 | 225 | < | chop $response; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 214 | < | $response =~ /^(.*);(.*);(.*)/; | 
 
 
 
 
 
 
 
 
 | 225 | > | chomp $response; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 226 |  | if ($response eq "ERROR") { | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 227 |  | print "There are no active configured filters for your host.\n"; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 228 |  | close($sock); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 229 |  | wait_then_retry(); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 230 |  | next; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 231 |  | } | 
 
 
 
 
 
 
 
 | 232 | + | $response =~ /^(.*);(.*);(.*)/; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 233 |  | ($filter_addr, $udp_port, $tcp_port) = ($1, $2, $3); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 234 |  | unless (defined($filter_addr) && defined($udp_port) && defined($tcp_port)) { | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 235 |  | print "Failed: Filter address response from server did not make sense: $response\n"; | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 274 |  | opendir PLUGINS, $plugins_dir; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 275 |  | my(@plugins) = readdir PLUGINS; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 276 |  | foreach my $plugin (@plugins) { | 
 
 
 
 
 
 
 
 
 
 
 | 277 | < | push @data, `$plugins_dir/$plugin` if -x "$plugins_dir/$plugin" && -f "$plugins_dir/$plugin"; | 
 
 
 
 
 
 
 
 
 | 277 | > | push @data, `$plugins_dir/$plugin $ostype` if -x "$plugins_dir/$plugin" && -f "$plugins_dir/$plugin"; | 
 
 
 
 
 
 
 
 
 
 
 | 278 |  | } | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 279 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 280 |  | # get some extra data | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 283 |  | $ip = inet_ntoa(scalar(gethostbyname(hostname())) || 'localhost') or $ip = 'localhost'; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 284 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 285 |  | # add some extra data to the array | 
 
 
 
 
 
 
 
 
 
 
 | 286 | < | push(@data, "packet.attributes.seq_no=$seq_no"); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 287 | < | push(@data, "packet.attributes.machine_name=$fqdn"); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 288 | < | push(@data, "packet.attributes.date=$date"); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 289 | < | push(@data, "packet.attributes.type=data"); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 290 | < | push(@data, "packet.attributes.ip=$ip"); | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 286 | > | push(@data, "packet.attributes.seq_no $seq_no"); | 
 
 
 
 
 | 287 | > | push(@data, "packet.attributes.machine_name $fqdn"); | 
 
 
 
 
 | 288 | > | push(@data, "packet.attributes.date $date"); | 
 
 
 
 
 | 289 | > | push(@data, "packet.attributes.type data"); | 
 
 
 
 
 | 290 | > | push(@data, "packet.attributes.ip $ip"); | 
 
 
 
 
 | 291 | > | push(@data, "packet.attributes.key $key"); | 
 
 
 
 
 
 
 
 
 
 
 | 292 |  |  | 
 
 
 
 
 
 
 
 | 293 | + | # sort the data | 
 
 
 
 
 
 
 
 | 294 | + | @data = sort(grep(!/^$/, grep(/^packet\./, @data))); | 
 
 
 
 
 
 
 
 | 295 | + |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 296 |  | # turn the array into some nice XML | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 297 |  | my($xml) = &make_xml("", ""); | 
 
 
 
 
 
 
 
 
 
 
 | 298 | < |  | 
 
 
 
 
 
 
 
 
 | 298 | > |  | 
 
 
 
 
 
 
 
 
 
 
 | 299 |  | my($sock) = new IO::Socket::INET ( | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 300 |  | PeerPort => $udp_port, | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 301 |  | PeerAddr => $filter_addr, | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 305 |  | print $sock $xml or die "Could not send UDP packet: $!\n"; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 306 |  | close($sock); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 307 |  | $seq_no++; | 
 
 
 
 
 
 
 
 
 
 
 | 308 | < | print "-: $xml\n"; | 
 
 
 
 
 
 
 
 
 | 308 | > | print "-"; | 
 
 
 
 
 
 
 
 
 
 
 | 309 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 310 |  | return; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 311 |  | } | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 377 |  | return; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 378 |  | } | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 379 |  |  | 
 
 
 
 
 
 
 
 | 380 | + | print $sock "KEY\n"; | 
 
 
 
 
 
 
 
 | 381 | + | $key = <$sock>; | 
 
 
 
 
 
 
 
 | 382 | + |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 383 |  | print $sock "ENDHEARTBEAT\n"; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 384 |  | $response = <$sock>; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 385 |  | if (!$response eq "OK\n") { | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 418 |  | sub make_xml() { | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 419 |  | my($curlevel, $curline) = @_; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 420 |  | my($xmltemp) = ""; my($curtag) = ""; my($attributes) = ""; | 
 
 
 
 
 
 
 
 
 
 
 | 421 | < | while(true) { | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 422 | < | $curline = shift(@data) if $curline eq ""; chomp $curline; | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 421 | > | while(1) { | 
 
 
 
 
 | 422 | > | $curline = shift(@data) if $curline eq ""; | 
 
 
 
 
 | 423 | > | return $xmltemp if not defined $curline; | 
 
 
 
 
 | 424 | > | chomp $curline; | 
 
 
 
 
 | 425 | > | # dealing with nest (or attributes) | 
 
 
 
 
 
 
 
 
 
 
 | 426 |  | if($curline =~ /^$curlevel([^\.\s]+\.)/) { | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 427 |  | $curtag=$1; | 
 
 
 
 
 
 
 
 | 428 | + | if($curline =~ /^$curlevel$curtag([^\.\s]+)\s+(.*)$/) { | 
 
 
 
 
 
 
 
 | 429 | + | $xmltemp .= &make_xml("$curlevel$curtag", $curline); | 
 
 
 
 
 
 
 
 | 430 | + | } | 
 
 
 
 
 
 
 
 | 431 | + | elsif($curline =~ /^$curlevel$curtag(attributes)\.([^\.\s]+)\s+(.*)$/) { | 
 
 
 
 
 
 
 
 | 432 | + | $attributes .= " $2=\"$3\""; | 
 
 
 
 
 
 
 
 | 433 | + | } | 
 
 
 
 
 
 
 
 | 434 | + | else { | 
 
 
 
 
 
 
 
 | 435 | + | $xmltemp .= &make_xml("$curlevel$curtag", $curline); | 
 
 
 
 
 
 
 
 | 436 | + | } | 
 
 
 
 
 
 
 
 | 437 | + | my($nextline) = $data[0]; chomp $nextline if defined $nextline; | 
 
 
 
 
 
 
 
 | 438 | + | $curtag =~ s/(.*)\./$1/; | 
 
 
 
 
 
 
 
 | 439 | + | if((defined $nextline) && ($nextline =~ /^$curlevel$curtag\./)) { | 
 
 
 
 
 
 
 
 | 440 | + | $curline = ""; | 
 
 
 
 
 
 
 
 | 441 | + | } | 
 
 
 
 
 
 
 
 | 442 | + | else { | 
 
 
 
 
 
 
 
 | 443 | + | $xmltemp = "<$curtag$attributes>$xmltemp</$curtag>" unless $curtag eq ""; | 
 
 
 
 
 
 
 
 | 444 | + | return $xmltemp; | 
 
 
 
 
 
 
 
 | 445 | + | } | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 446 |  | } | 
 
 
 
 
 
 
 
 
 
 
 | 447 | < | if($curline =~ /^$curlevel$curtag([^\.\s]+)\s+(.*)$/) { | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 448 | < | $xmltemp .= "<$1$attributes>$2</$1>"; | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 447 | > | # dealing with value | 
 
 
 
 
 | 448 | > | elsif($curline =~ /^$curlevel([^\.\s]+)\s+(.*)$/) { | 
 
 
 
 
 | 449 | > | $curtag=$1; | 
 
 
 
 
 | 450 | > | $xmltemp=$2; | 
 
 
 
 
 | 451 | > | my($nextline) = $data[0]; chomp $nextline if defined $nextline; | 
 
 
 
 
 | 452 | > | if(defined $nextline && ($nextline =~ /^$curlevel$curtag\./ || $nextline =~ /^$curlevel$curtag\s+/)) { | 
 
 
 
 
 | 453 | > | $curline = ""; | 
 
 
 
 
 | 454 | > | } | 
 
 
 
 
 | 455 | > | else { | 
 
 
 
 
 | 456 | > | $xmltemp = "<$curtag$attributes>$xmltemp</$curtag>" unless $curtag eq ""; | 
 
 
 
 
 | 457 | > | return $xmltemp; | 
 
 
 
 
 | 458 | > | } | 
 
 
 
 
 
 
 
 
 
 
 | 459 |  | } | 
 
 
 
 
 
 
 
 
 
 
 | 460 | < | elsif($curline =~ /^$curlevel$curtag(attributes)\.([^\.=]+)=(.*)$/) { | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 461 | < | $attributes .= " $2=\"$3\""; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 462 | < | } | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 463 | < | else { | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 464 | < | $xmltemp .= &make_xml("$curlevel$curtag", $curline); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 465 | < | } | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 466 | < | my($nextline) = $data[0]; chomp $nextline if defined $nextline; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 467 | < | $curtag =~ s/(.*)\./$1/; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 468 | < | if(defined $nextline && $nextline =~ /^$curlevel$curtag\./) { | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 469 | < | $curline = ""; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 420 | < | } | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 421 | < | else { | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 422 | < | $xmltemp = "<$curtag$attributes>$xmltemp</$curtag>" unless $curtag eq ""; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 423 | < | return $xmltemp; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 424 | < | } | 
 
 
 
 
 
 
 
 
 | 460 | > | # dealing with a null value | 
 
 
 
 
 | 461 | > | elsif($curline =~ /^$curlevel([^\.\s]+)$/) { | 
 
 
 
 
 | 462 | > | # simply adding a space makes the above elsif deal with it :) | 
 
 
 
 
 | 463 | > | # just level with an empty tag in the XML | 
 
 
 
 
 | 464 | > | $curline .= " "; | 
 
 
 
 
 | 465 | > | } | 
 
 
 
 
 | 466 | > | # failing all that, skip the line | 
 
 
 
 
 | 467 | > | else { | 
 
 
 
 
 | 468 | > | $curline = ""; | 
 
 
 
 
 | 469 | > | } | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 470 |  | } | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 471 |  | } |