package Yaala::Data::Convert;

use strict;
use warnings;

use Exporter;
use Socket;
use Yaala::Config qw#get_config#;
use Yaala::Data::Setup qw#%DATAFIELDS#;

@Yaala::Data::Convert::ISA = ('Exporter');
@Yaala::Data::Convert::EXPORT_OK = qw#convert#;

my $VERSION = '$Id: Convert.pm,v 1.7 2003/12/07 14:52:22 octo Exp $';
print STDERR $/, __FILE__, ": $VERSION" if ($::DEBUG);

our $CACHE = {};
our $DO_REV_LOOKUP = 0;
our $HOST_WIDTH = 1;
our $URL_FORMAT = 'host';

if (get_config ('reverse_lookup'))
{
	my $conf = get_config ('reverse_lookup');
	if ($conf =~ m/^(true|yes|on)$/i)
	{
		print STDERR $/, __FILE__, ': Will try to do reverse lookups' if ($::DEBUG & 0x40);
		$DO_REV_LOOKUP = 1;
	}
}

{
	my $conf = get_config ('host_width');
	$conf =~ s/\D//g;
	if ($conf ne '')
	{
		$HOST_WIDTH = $conf;
	}
}

if (get_config ('url_format'))
{
	 my $conf = get_config ('url_format');
	 if ($conf =~ m/url/i)
	 {
		 $URL_FORMAT = 'url';
	 }
	 elsif ($conf =~ m/full/)
	 {
		 $URL_FORMAT = 'full';
	 }
 }
		 

return (1);

sub convert
{
	my $key = shift;
	my $val = shift;
	my $retval = $val;

	if (defined ($CACHE->{$key}{$val}))
	{
		return ($CACHE->{$key}{$val});
	}

	if (defined ($DATAFIELDS{$key}))
	{
		my ($class, $type) = split (m/:/, $DATAFIELDS{$key});

		if (!defined ($type) or !$type)
		{
			$CACHE->{$key}{$val} = $retval if ($class eq 'key');
			return ($retval);
		}

		if ($type eq 'bytes')
		{
			$retval = sprintf ("%.1f kByte", $val / 1024) if ($val)
		}
#		elsif ($type eq 'numeric')
#		{
#			$val =~ s/\D//g;
#			if ($val)
#			{
#				$retval = int ($val);
#			}
#			else
#			{
#				$retval = 0;
#			}
#		}
		elsif ($type eq 'host')
		{
			if ($DO_REV_LOOKUP and $val =~ m/^[\d\.]+$/)
			{
				$retval = do_reverse_lookup ($val);
			}
			
			if ($HOST_WIDTH)
			{
				if ($retval =~ m/^[\d\.]+$/)
				{
					if ($DO_REV_LOOKUP)
					{
						$retval = '*UNRESOLVED*';
					}
					else
					{
						my ($c, $d, $e, $f) = split (m/\./, $retval, 4);
						if ($HOST_WIDTH == 1)
						{
							$retval = "$c.0.0.0/8";
						}
						elsif ($HOST_WIDTH == 2)
						{
							$retval = "$c.$d.0.0/16";
						}
						elsif ($HOST_WIDTH == 3)
						{
							$retval = "$c.$d.$e.0/24";
						}
						else
						{
							$retval = "$c.$d.$e.$f/32";
						}
					}
				}
				else
				{
					my @parts = split (m/\./, $retval);
					while (scalar (@parts) > ($HOST_WIDTH + 1))
					{
						shift (@parts);
					}
					$retval = join ('.', @parts);
				}
			}
		}
		elsif ($type eq 'url')
		{
			my $tmpval = $val;
			$tmpval =~ s#^[a-z]+://##i;
			
			if ($tmpval =~ m#^([^:/]+)(?::\d+)?(/[^\?]*)(.*)#)
			{
				my $host = $1;
				my $path = $2;
				my $params = $3;
				
				if ($DO_REV_LOOKUP and $host =~ m/^[\d\.]+$/)
				{
					$host = do_reverse_lookup ($host);
				}

				if ($HOST_WIDTH and $host =~ m/[^\d\.]/)
				{
					my @parts = split (m/\./, $host);
					while (scalar (@parts) > ($HOST_WIDTH + 1))
					{
						shift (@parts);
					}
					$host = join ('.', @parts);
				}

				if ($URL_FORMAT eq 'host')
				{
					$retval = $host;
				}
				elsif ($URL_FORMAT eq 'url')
				{
					$retval = $host . $path;
				}
				elsif ($URL_FORMAT eq 'full')
				{
					$retval = $host . $path . $params;
				}
			}
			elsif ($::DEBUG)
			{
				print STDERR $/, __FILE__, ": Unable to parse URL: '$val'";
			}
		}
		elsif ($type eq 'date')
		{
			# for later use
		}
		elsif ($type eq 'time' and $class eq 'agg')
		{
			my $hour   = 0;
			my $minute = 0;
			my $second = 0;

			$hour   = int ($val / 3600000); $val %= 3600000;
			$minute = int ($val /   60000); $val %=   60000;
			$second = $val / 1000;

			$retval = sprintf ("%02u:%02u:%02.1f", $hour, $minute, $second);
		}
		
		if ($class eq 'key')
		{
			$CACHE->{$key}{$val} = $retval;
		}
	}
	
	return ($retval);
}

sub do_reverse_lookup
{
	my $ip = shift;

	return ($ip) if ($ip !~ m/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/);
	
	print STDERR $/, __FILE__, ": Reverse lookup for $ip" if ($::DEBUG & 0x40);

	my $iaddr = inet_aton ($ip);
	if (!defined ($iaddr))
	{
		print STDERR ': Failed (not a valid IP)' if ($::DEBUG & 0x40);
		return ($ip);
	}

	my $host = gethostbyaddr ($iaddr, AF_INET ());

	if ($host)
	{
		print STDERR ": Success ($host)" if ($::DEBUG & 0x40);
		return ($host);
	}
	else
	{
		print STDERR ': Failed (unknown)' if ($::DEBUG & 0x40);
		return ($ip);
	}
}
