#!/usr/bin/perl -w

use strict;
$|=1;
use Proc::Daemon;
use Proc::PID::File;
use Sys::Syslog;
use DBI;
use HTTP::Date qw( str2time time2iso );
use HTML::Entities;
use Data::Uniqid qw ( luniqid );
use Date::Manip;
use Socket;
use Digest::MD5 qw(md5);
use Math::Round;
use JSON::XS;
use URI::Escape;

use constant TYPE_ACTION_URL   => 1;
use constant TYPE_OUTLINK  => 2;
use constant TYPE_DOWNLOAD => 3;
use constant TYPE_ACTION_NAME => 4;
use constant TYPE_ECOMMERCE_ITEM_SKU => 5;
use constant TYPE_ECOMMERCE_ITEM_NAME => 6;
use constant TYPE_ECOMMERCE_ITEM_CATEGORY => 7;

use constant LENGTH_HEX_ID_STRING => 16;
use constant LENGTH_BINARY_ID => 8;

# SQL
my $hostname = '127.0.0.1';
my $port = '3306';
my $database = 'pwk';
my $password = 'pass';
my $user = 'piwik';
my $driver = 'mysql';

# Daemonize
Proc::Daemon::Init();

$SIG{INT} = \&SHUTDOWN;
$SIG{TERM} = \&SHUTDOWN;

if (Proc::PID::File->running()) {
	print "Already running\n";
	exit 0;
}

my $logfile = "/var/log/piwik_tracker.fifo";
openlog("parser", "ndelay,pid", "local1");

#SQL Query
my $action_id = q{
    SELECT
        idaction,
        type,
        name
    FROM
        piwik_log_action
    WHERE
        (hash = CRC32(?) AND name = ? AND type = '4' )
        OR
        (hash = CRC32(?) AND name = ? AND type = '1')
};

my $visit = q{
    SELECT
        idvisitor,
        visit_last_action_time,
        visit_first_action_time,
        idvisit,
        visit_exit_idaction_url,
        visit_exit_idaction_name,
        visitor_returning,
        visitor_days_since_first,
        visitor_days_since_order,
        referer_name,
        referer_keyword,
        referer_type,
        visitor_count_visits,
        visit_goal_buyer,
        custom_var_k1,custom_var_v1,
        custom_var_k2,custom_var_v2,
        custom_var_k3,custom_var_v3,
        custom_var_k4,custom_var_v4,
        custom_var_k5,custom_var_v5
    FROM
        piwik_log_visit
    WHERE
        visit_last_action_time >= ?
        AND
        idsite = ?
        AND
        config_id = ?
    ORDER BY visit_last_action_time DESC LIMIT 1
};

my $know_visit = q{
    UPDATE
        piwik_log_visit
    SET
        visit_total_actions = visit_total_actions + 1,
        visit_exit_idaction_url = ?,
        visit_exit_idaction_name = ?,
        visit_last_action_time = ?,
        visit_total_time = ?,
        idvisitor = ?,
        visit_goal_buyer = ?
    WHERE
        idsite = ?
        AND
        idvisit = ?
};

my $link_visit_action = q{
    INSERT INTO
        piwik_log_link_visit_action
    (idvisit, idsite, idvisitor, server_time, idaction_url, idaction_name, idaction_url_ref, idaction_name_ref, time_spent_ref_action)
    VALUES
        (?,?,?,?,?,?,?,?,?)
};

my %CountryList = (
   		'ad' => 'eur',
   		'ae' => 'asi',
   		'af' => 'asi',
   		'ag' => 'amc',
   		'ai' => 'amc',
   		'al' => 'eur',
   		'am' => 'asi',
   		'ao' => 'afr',
   		'aq' => 'ant',
   		'ar' => 'ams',
   		'as' => 'oce',
   		'at' => 'eur',
   		'au' => 'oce',
   		'aw' => 'amc',
   		'ax' => 'eur',
   		'az' => 'asi',
   		'ba' => 'eur',
   		'bb' => 'amc',
   		'bd' => 'asi',
   		'be' => 'eur',
   		'bf' => 'afr',
   		'bg' => 'eur',
   		'bh' => 'asi',
   		'bi' => 'afr',
   		'bj' => 'afr',
   		'bl' => 'amc',
   		'bm' => 'amc',
   		'bn' => 'asi',
   		'bo' => 'ams',
   		'bq' => 'amc',
   		'br' => 'ams',
   		'bs' => 'amc',
   		'bt' => 'asi',
   		'bv' => 'ant',
   		'bw' => 'afr',
   		'by' => 'eur',
   		'bz' => 'amc',
   		'ca' => 'amn',
   		'cc' => 'asi',
   		'cd' => 'afr',
   		'cf' => 'afr',
   		'cg' => 'afr',
   		'ch' => 'eur',
   		'ci' => 'afr',
   		'ck' => 'oce',
   		'cl' => 'ams',
   		'cm' => 'afr',
   		'cn' => 'asi',
   		'co' => 'ams',
   		'cr' => 'amc',
   		'cu' => 'amc',
   		'cv' => 'afr',
   		'cw' => 'amc',
   		'cx' => 'asi',
   		'cy' => 'eur',
   		'cz' => 'eur',
   		'de' => 'eur',
   		'dj' => 'afr',
   		'dk' => 'eur',
   		'dm' => 'amc',
   		'do' => 'amc',
   		'dz' => 'afr',
   		'ec' => 'ams',
   		'ee' => 'eur',
   		'eg' => 'afr',
   		'eh' => 'afr',
   		'er' => 'afr',
   		'es' => 'eur',
   		'et' => 'afr',
   		'fi' => 'eur',
   		'fj' => 'oce',
   		'fk' => 'ams',
   		'fm' => 'oce',
   		'fo' => 'eur',
   		'fr' => 'eur',
   		'ga' => 'afr',
   		'gb' => 'eur',
   		'gd' => 'amc',
   		'ge' => 'asi',
   		'gf' => 'ams',
   		'gg' => 'eur',
   		'gh' => 'afr',
   		'gi' => 'eur',
   		'gl' => 'amn',
   		'gm' => 'afr',
   		'gn' => 'afr',
   		'gp' => 'amc',
   		'gq' => 'afr',
   		'gr' => 'eur',
   		'gs' => 'ant',
   		'gt' => 'amc',
   		'gu' => 'oce',
   		'gw' => 'afr',
   		'gy' => 'ams',
   		'hk' => 'asi',
   		'hm' => 'ant',
   		'hn' => 'amc',
   		'hr' => 'eur',
   		'ht' => 'amc',
   		'hu' => 'eur',
   		'id' => 'asi',
   		'ie' => 'eur',
   		'il' => 'asi',
   		'im' => 'eur',
   		'in' => 'asi',
   		'io' => 'asi',
   		'iq' => 'asi',
   		'ir' => 'asi',
   		'is' => 'eur',
   		'it' => 'eur',
   		'je' => 'eur',
   		'jm' => 'amc',
   		'jo' => 'asi',
   		'jp' => 'asi',
   		'ke' => 'afr',
   		'kg' => 'asi',
   		'kh' => 'asi',
   		'ki' => 'oce',
   		'km' => 'afr',
   		'kn' => 'amc',
   		'kp' => 'asi',
   		'kr' => 'asi',
   		'kw' => 'asi',
   		'ky' => 'amc',
   		'kz' => 'asi',
   		'la' => 'asi',
   		'lb' => 'asi',
   		'lc' => 'amc',
   		'li' => 'eur',
   		'lk' => 'asi',
   		'lr' => 'afr',
   		'ls' => 'afr',
   		'lt' => 'eur',
   		'lu' => 'eur',
   		'lv' => 'eur',
   		'ly' => 'afr',
   		'ma' => 'afr',
   		'mc' => 'eur',
   		'md' => 'eur',
   		'me' => 'eur',
   		'mf' => 'amc',
   		'mg' => 'afr',
   		'mh' => 'oce',
   		'mk' => 'eur',
   		'ml' => 'afr',
   		'mm' => 'asi',
   		'mn' => 'asi',
   		'mo' => 'asi',
   		'mp' => 'oce',
   		'mq' => 'amc',
   		'mr' => 'afr',
   		'ms' => 'amc',
   		'mt' => 'eur',
   		'mu' => 'afr',
   		'mv' => 'asi',
   		'mw' => 'afr',
   		'mx' => 'amn',
   		'my' => 'asi',
   		'mz' => 'afr',
   		'na' => 'afr',
   		'nc' => 'oce',
   		'ne' => 'afr',
   		'nf' => 'oce',
   		'ng' => 'afr',
   		'ni' => 'amc',
   		'nl' => 'eur',
   		'no' => 'eur',
   		'np' => 'asi',
   		'nr' => 'oce',
   		'nu' => 'oce',
   		'nz' => 'oce',
   		'om' => 'asi',
   		'pa' => 'amc',
   		'pe' => 'ams',
   		'pf' => 'oce',
   		'pg' => 'oce',
   		'ph' => 'asi',
   		'pk' => 'asi',
   		'pl' => 'eur',
   		'pm' => 'amn',
   		'pn' => 'oce',
   		'pr' => 'amc',
   		'ps' => 'asi',
   		'pt' => 'eur',
   		'pw' => 'oce',
   		'py' => 'ams',
   		'qa' => 'asi',
   		're' => 'afr',
   		'ro' => 'eur',
   		'rs' => 'eur',
   		'ru' => 'eur',
   		'rw' => 'afr',
   		'sa' => 'asi',
   		'sb' => 'oce',
   		'sc' => 'afr',
   		'sd' => 'afr',
   		'se' => 'eur',
   		'sg' => 'asi',
   		'sh' => 'afr',
   		'si' => 'eur',
   		'sj' => 'eur',
   		'sk' => 'eur',
   		'sl' => 'afr',
   		'sm' => 'eur',
   		'sn' => 'afr',
   		'so' => 'afr',
   		'sr' => 'ams',
   		'st' => 'afr',
   		'sv' => 'amc',
   		'sx' => 'amc',
   		'sy' => 'asi',
   		'sz' => 'afr',
   		'tc' => 'amc',
   		'td' => 'afr',
   		'tf' => 'ant',
   		'tg' => 'afr',
   		'th' => 'asi',
   		'tj' => 'asi',
   		'tk' => 'oce',
   		'tl' => 'asi',
   		'tm' => 'asi',
   		'tn' => 'afr',
   		'to' => 'oce',
   		'tr' => 'eur',
   		'tt' => 'amc',
   		'tv' => 'oce',
   		'tw' => 'asi',
   		'tz' => 'afr',
   		'ua' => 'eur',
   		'ug' => 'afr',
   		'um' => 'oce',
   		'us' => 'amn',
   		'uy' => 'ams',
   		'uz' => 'asi',
   		'va' => 'eur',
   		'vc' => 'amc',
   		've' => 'ams',
   		'vg' => 'amc',
   		'vi' => 'amc',
   		'vn' => 'asi',
   		'vu' => 'oce',
   		'wf' => 'oce',
   		'ws' => 'oce',
   		'ye' => 'asi',
   		'yt' => 'afr',
   		'za' => 'afr',
   		'zm' => 'afr',
   		'zw' => 'afr',
   		'xx' => 'unk',
   	);

my $new_visit = q{
    INSERT INTO
        piwik_log_visit
    
        (   idsite,
            visitor_localtime,
            idvisitor,
            visitor_returning,
            visitor_count_visits,
            visitor_days_since_last,
            visitor_days_since_order,
            visitor_days_since_first,
            visit_first_action_time,
            visit_last_action_time,
            visit_entry_idaction_url,
            visit_entry_idaction_name,
            visit_exit_idaction_url,
            visit_exit_idaction_name,
            visit_total_actions,
            visit_total_time,
            visit_goal_converted,
            visit_goal_buyer,
            referer_type,
            referer_name,
            referer_url,
            referer_keyword,
            config_id,
            config_os,
            config_browser_name,
            config_browser_version,
            config_resolution,
            config_pdf,
            config_flash,
            config_java,
            config_director,
            config_quicktime,
            config_realplayer,
            config_windowsmedia,
            config_gears,
            config_silverlight,
            config_cookie,
            location_ip,
            location_browser_lang,
            location_country,
            location_provider,
            location_continent)
    VALUES
        (   ?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
};

sub getConfigHash
{
    my $hash = md5( @_ );
    return substr($hash,0,LENGTH_BINARY_ID);
}

sub SHUTDOWN() {
    #unlink($pidfile);
    closelog();
    exit;
}

sub try (&@) {
    my($try,$catch) = @_;
    eval { &$try };
    if ($@) {
        local $_ = $@;
        &$catch;
    }
}

sub catch (&) { $_[0] }

sub getRequest
{
    my $json_string = shift;
    my %request = %{ decode_json( $json_string ) };
    return %request;
}

sub parseURL
{
    my $url = shift;
    my $parse_query = shift;

    $url =~ /
            \s*
            (?:
                # scheme:subscheme:\/\/
                ([a-z]+) : (?: ([a-z]*) : )? \/\/
            )?
            (?:
                # username:password@
                ( [^:@]* ) (?: : ([^:@]*) )? @
            )?
            (
                # hostname|localhost|IP
                (?: [a-z0-9_-]+ \. )+ [a-z]{2,}
                |
                localhost
                |
                (?: (?: [01]?\d\d? | 2[0-4]\d | 25[0-5] ) \. ){3}
                (?: (?: [01]?\d\d? | 2[0-4]\d | 25[0-5] ) )
            )
            (?:
                # :port
                : (\d+)
            )?
            (?:
                # \/path
                ([^:\?\#]+)
            )?
            (?:
                # ?query
                \? ([^\#]+)
            )?
            (?:
                # #fragment
                \# ([^\s]+)
            )?
            \s*
    /ix;
    return () unless defined $5;
    my %result = (
                scheme                => $1 || '',
                subscheme        => $2 || '',
                user                => $3 || '',
                pass                => $4 || '',
                host                => $5,
                port                => $6 || '',
                path                => $7 || '',
                query                => $8 || '',
                fragment        => $9 || '',
        );

    return %result unless $parse_query;

    my %query = ();
    for my $par (split('&', $result{query})) {
        next unless ( $par =~ /([^=]+)=(.*)/ );
        $query{$1} = $2;
    }
    $result{query} = \%query;

    return %result;
}


sub getRefererInformation
{
    use constant REFERER_TYPE_DIRECT_ENTRY		=> 1;
	use constant REFERER_TYPE_SEARCH_ENGINE	    => 2;
	use constant REFERER_TYPE_WEBSITE			=> 3;
	use constant REFERER_TYPE_CAMPAIGN			=> 6;

	my $refererUrl = shift;
	my $currentUrl = shift;
	my $idSite = shift;

	# default values for the referer_* fields
	my %refererUrlParse;
	% refererUrlParse = parseURL($refererUrl) if $refererUrl;

	my %currentUrlParse;
	%currentUrlParse = parseURL($currentUrl) if $currentUrl;
	my $typeRefererAnalyzed = REFERER_TYPE_DIRECT_ENTRY;
	my $nameRefererAnalyzed = '';
	my $keywordRefererAnalyzed = '';
	my $refererHost = '';

	$refererHost = $refererUrlParse{'host'} if(defined $refererUrlParse{'host'});
	my $refererDetected = 0;
#TODO Companies are not supported yet!
#	if( defined( $currentUrlParse{'host'} ) &&	getCampaignParameters )
#	{
#		$refererDetected = 1;
#	}
	unless($refererDetected)
	{
        my $SearchEngine = 0;
        my $DirectEntry = 0;
        if($refererHost =~ /^$/)
        {
           	#is the referer host the current host?
            if(defined $currentUrlParse{'host'})
            {
            	my $currentHost = lc($currentUrlParse{'host'});
            	if($currentHost eq lc($refererHost))
            	{
            		$typeRefererAnalyzed = REFERER_TYPE_DIRECT_ENTRY;
            		my $DirectEntry = 1;
            	}
            }
#TODO This feature is not yet implemented.
#           if(isHostKnownAliasHost($refererHost, $idsite))
#           {
#           	$typeRefererAnalyzed = REFERER_TYPE_DIRECT_ENTRY;
#           	my $DirectEntry = 1;
#           }
        }

        if(%refererUrlParse)
        {
            $typeRefererAnalyzed = REFERER_TYPE_SEARCH_ENGINE;
            $nameRefererAnalyzed = $refererUrlParse{'host'};
            $keywordRefererAnalyzed = $refererUrlParse{'query'};
            $SearchEngine = 1;
        }
	$refererDetected = 1 if( $DirectEntry || $SearchEngine );
	}
	if( !($refererHost =~ /^$/) && !$refererDetected)
	{
		$typeRefererAnalyzed = REFERER_TYPE_WEBSITE;
		$nameRefererAnalyzed = lc($refererHost);
	}
	my %refererInformation = (
		'referer_type' 		=> $typeRefererAnalyzed,
		'referer_name' 		=> $nameRefererAnalyzed,
		'referer_keyword' 	=> $keywordRefererAnalyzed,
		'referer_url' 		=> $refererUrl,
	);
	return %refererInformation;
}


sub getVisitorUniqueId
{
    return md5(luniqid);
}

sub getUserSettingsInformation
{
    my( $request, $visitorIP) = @_;

    my $plugin_Flash 			= $$request{'fla'} || 0;
    my $plugin_Java 			= $$request{'java'} || 0;
    my $plugin_Director 		= $$request{'dir'} || 0;
    my $plugin_Quicktime		= $$request{'qt'} || 0;
    my $plugin_RealPlayer 		= $$request{'realp'} || 0;
    my $plugin_PDF 			    = $$request{'pdf'} || 0;
    my $plugin_WindowsMedia 	= $$request{'wma'} || 0;
    my $plugin_Gears			= $$request{'gears'} || 0;
    my $plugin_Silverlight		= $$request{'ag'} || 0;
    my $plugin_Cookie           = $$request{'cookie'} || 0;
	my $browserName	            = $$request{'browserName'}||'UNK';
    my $browserVersion	        = $$request{'browserVersion'}||'';
    my $os				        = $$request{'os'}||'UNK';
    my $resolution		        = $$request{'res'}||'unknown';
    my $browserLang	            = $$request{'browserLang'};
    my $config_id = getConfigHash($os.$browserName.$browserVersion.$plugin_Flash.$plugin_Java.$plugin_Director.$plugin_Quicktime.$plugin_RealPlayer.$plugin_PDF.$plugin_WindowsMedia.$plugin_Gears.$plugin_Silverlight.$plugin_Cookie.$visitorIP.$browserLang);
    my %userSettingsInformation = ( 		'config_id' 			=> $config_id,
                                  			'config_os' 			=> $os,
                                  			'config_browser_name' 	=> $browserName,
                                  			'config_browser_version' => $browserVersion,
                                  			'config_resolution' 	=> $resolution,
                                  			'config_pdf' 			=> $plugin_PDF,
                                  			'config_flash' 			=> $plugin_Flash,
                                  			'config_java' 			=> $plugin_Java,
                                  			'config_director' 		=> $plugin_Director,
                                  			'config_quicktime' 		=> $plugin_Quicktime,
                                  			'config_realplayer' 	=> $plugin_RealPlayer,
                                  			'config_windowsmedia' 	=> $plugin_WindowsMedia,
                                  			'config_gears'	 		=> $plugin_Gears,
                                  			'config_silverlight'	=> $plugin_Silverlight,
                                  			'config_cookie' 		=> $plugin_Cookie,
                                  			'location_browser_lang' => $browserLang
                                  );
    return %userSettingsInformation;
}


my $dbh = DBI->connect("DBI:$driver:database=$database;host=$hostname", $user, $password) or die print "Can't connect";
my $sth = $dbh->do( "SET NAMES utf8" ) || die "Can't prepare statement: $DBI::errstr";

my @row = ();

my $succsess = 0;
my $skip = 0;
my $unknowURL = 0;
my $unknowName = 0;
my $jsonErr = 0;
syslog("debug", "Parser started!");
my $part = "";
open FIL, "+< $logfile" or syslog("debug", "The FIFO file \"$logfile\" is missing, and this program can't run without it.:$!"); 
while (my $s=<FIL>)
{
    while ($s=~s/.*save,(.*)//)
    {
        my $visitorKnow = 0;
        my $isLastActionInTheSameVisit = 0;
        my $idActionUrl;
        my $idActionName;
        my $err = 0;
        my $data = $1;
#        syslog("debug", $data);
        if($data=~s/.*part:(.*)//)
        {
            unless($part)
            {
                $part .="$1";
                next;
            }
            $data = $part.$1;
            $part = "";
        }
        my %request =();
        try{
            %request = getRequest($data);
        }catch{
            $err = 1;
        };
        if( $err )
        {
            $jsonErr++;
            next;
        }
        my $visitorIP = inet_aton( $request{'ipString'} );

        my $visitTimestamp = $request{'dateTime'};
        my $visitTime = time2iso($visitTimestamp);

        my %userInfo = getUserSettingsInformation(\%request, $visitorIP );
        #TODO Check whether there is 'custom variables', to get information and set a flag in case of

        #Get from the database id for the actionName and actionUrl
        $sth = $dbh->prepare( $action_id ) || die "Can't prepare statement: $DBI::errstr";
        
        my $url = $request{'url'};
        if( !($url = ~/^$/) && defined($request{'action_name'}))
        {
            $url =~s/\?&/\?/g;
            $sth->execute($request{'action_name'},$request{'action_name'},$url,$url);
            while (@row = $sth->fetchrow_array)
            {
                $idActionUrl = $row[0] if $row[1] == TYPE_ACTION_URL;
                $idActionName = $row[0] if $row[1]== TYPE_ACTION_NAME;
            }
            $sth->finish;
            unless($idActionUrl)
            {
                $sth->prepare("INSERT INTO pwk_log_action ( name, hash, type ) VALUES (?,CRC32(?),?)");
                $sth->execute($url,$url,TYPE_ACTION_URL);
                $idActionUrl = $sth->{mysql_insertid};
                $sth->finish;
            }
            unless($idActionName)
            {
                $sth->prepare("INSERT INTO pwk_log_action ( name, hash, type ) VALUES (?,CRC32(?),?)");
                $sth->execute($request{'action_name'},$request{'action_name'},TYPE_ACTION_NAME);
                $idActionName = $sth->{mysql_insertid};
                $sth->finish;
            }
        }
        else
        {
            $idActionUrl=0;
        }
        $idActionName = 0 unless $idActionName;
        #Check whether the earlier visit and get the last visit
        my $visit_time = time2iso($visitTimestamp - 1800);
        $sth = $dbh->prepare($visit ) || die "Can't prepare statement: $DBI::errstr";
        $sth->execute( $visit_time, $request{'idsite'}, $userInfo{'config_id'});
        my $rows = $sth->rows;
        my @visitorInfo = ();
        if($rows>0)
        {
            while (@row = $sth->fetchrow_array){
                for my $key (0..(scalar @row)-1){
                   push(@visitorInfo, ${ $sth->{NAME} }[$key]);
                   push(@visitorInfo, (defined $row[$key])?$row[$key]:"");
                }
            }
            $visitorKnow=1;
        }
        my %visitorInfo = @visitorInfo;
        $#visitorInfo = -1;
        $sth->finish;
        if( defined $visitorInfo{'visit_last_action_time'} )
        {
            my $visit_time = DateCalc($visitTime,"30 minutes ago");
            my $last_visit_time = ParseDate($visitorInfo{'visit_last_action_time'});
            my $tmp = Date_Cmp($visit_time, $last_visit_time);
            if($tmp < 1)
            {
                $isLastActionInTheSameVisit = 1;
            }
        }
        if($visitorKnow && $isLastActionInTheSameVisit)
        {
            my $totalTime = $visitTimestamp  -  str2time($visitorInfo{'visit_first_action_time'});
            my $timeSpentRefererAction= $visitTimestamp  -  str2time($visitorInfo{'visit_last_action_time'});
            $visitorInfo{'time_spent_ref_action'} = $timeSpentRefererAction;
            last if $totalTime < 0;
            $sth = $dbh->prepare( $know_visit ) || die "Can't prepare statement: $DBI::errstr";
            $sth->execute(  $idActionUrl,
                            $idActionName,
                            $visitTime,
                            $totalTime,
                            $visitorInfo{'idvisitor'},
                            $visitorInfo{'visit_goal_buyer'},
                            $request{'idsite'},
                            $visitorInfo{'idvisit'},
                          ) || die "Can't prepare statement: $DBI::errstr";
        }
        if(!$visitorKnow || !$isLastActionInTheSameVisit)
        {
            ( $request{'h'}, $request{'m'}, $request{'s'} ) = UnixDate($visitTimestamp, "%H", "%M", "%S") unless ( $request{'h'} && $request{'m'} && $request{'s'} ) ;
            my $localTime = $request{'h'}.":".$request{'m'}.":".$request{'s'};
            my $idcookie;
            $idcookie = $visitorInfo{'idvisitor'} if $visitorKnow;
            if(!$idcookie)
            {
                $idcookie = pack("H*", substr(getVisitorUniqueId, 0, LENGTH_HEX_ID_STRING));
                $visitorInfo{'idvisitor'} = $idcookie;
            }
            my $defaultTimeOnePageVisit = 0;
            #Days since first visit
            my $cookieFirstVisitTimestamp = $request{'_idts'};
            $cookieFirstVisitTimestamp = $visitTimestamp unless($cookieFirstVisitTimestamp);

            my $daysSinceFirstVisit = round(($visitTimestamp - $cookieFirstVisitTimestamp)/86400);
            $daysSinceFirstVisit = 0 if( $daysSinceFirstVisit < 0);

            #Number of Visits
            my $visitCount = $request{'_idvc'} || 1;

            # Days since last visit
            my $daysSinceLastVisit = 0;
            my $lastVisitTimestamp = $request{'_viewts'};
            if($lastVisitTimestamp)
            {
                $daysSinceLastVisit = round(($visitTimestamp - $lastVisitTimestamp)/86400);
                $daysSinceLastVisit = 0 if( $daysSinceLastVisit < 0);
            }
            my $daysSinceLastOrder = 0;
            my $isReturningCustomer = 0;

            my $lastOrderTimestamp = $request{'_ects'};
            if($lastOrderTimestamp)
            {
                $daysSinceLastOrder = round(($visitTimestamp - $lastOrderTimestamp)/86400);
                $daysSinceLastOrder = 0 if($daysSinceLastOrder < 0);
                $isReturningCustomer = 1;
            }

            #User settings
            my $refererUrl	= $request{'urlref'} || "";
            my $currentUrl	= $request{'url'} || "";
            $visitorInfo{'time_spent_ref_action'} = 0;
            $visitorInfo{'visit_exit_idaction_url'} = 0;
            $visitorInfo{'visit_exit_idaction_name'} = 0;

            #referep raser
            my %refererInfo = getRefererInformation($refererUrl, $currentUrl, $request{'idsite'});

            my $location_provider = gethostbyaddr($visitorIP, AF_INET);
            $location_provider = "Ip" unless $location_provider;

            $sth = $dbh->prepare( $new_visit ) || die "Can't prepare statement: $DBI::errstr";
            $sth->execute(  $request{'idsite'},
                            $localTime,
                            $idcookie,
                            $isReturningCustomer ? 2 : ( $visitCount > 1 || $visitorKnow ),
                            $visitCount,
                            $daysSinceLastVisit,
                           	$daysSinceLastOrder,
                           	$daysSinceFirstVisit,
                            $visitTime,
                            $visitTime,
                            $idActionUrl,
                            $idActionName,
                            $idActionUrl,
                            $idActionName,
                            1,
                            $defaultTimeOnePageVisit,
                            0,
                            0,
                            $refererInfo{'referer_type'},
                            $refererInfo{'referer_name'},
                            $refererInfo{'referer_url'},
                            $refererInfo{'referer_keyword'},
                            $userInfo{'config_id'},
                            $userInfo{'config_os'},
                            $userInfo{'config_browser_name'},
                            $userInfo{'config_browser_version'},
                            $userInfo{'config_resolution'} || 'unknown',
                            $userInfo{'config_pdf'},
                            $userInfo{'config_flash'},
                            $userInfo{'config_java'},
                            $userInfo{'config_director'},
                            $userInfo{'config_quicktime'},
                            $userInfo{'config_realplayer'},
                            $userInfo{'config_windowsmedia'},
                            $userInfo{'config_gears'},
                            $userInfo{'config_silverlight'},
                            $userInfo{'config_cookie'},
                            $visitorIP,
                            $userInfo{'location_browser_lang'},
                            $request{'country'},
                            $location_provider,
                            $CountryList{$request{'country'}}
                          ) || die "Can't prepare statement: $DBI::errstr";
        }

        # Update the information of Visitor activity.
        $visitorInfo{'idvisit'} = $sth->{mysql_insertid} unless( defined $visitorInfo{'idvisit'});
        $sth = $dbh->prepare( $link_visit_action ) || die "Can't prepare statement: $DBI::errstr";
        $sth->execute(  $visitorInfo{'idvisit'},
                        $request{'idsite'},
                        $visitorInfo{'idvisitor'},
                        $visitTime,
                        $idActionUrl,
                        $idActionName,
                        $visitorInfo{'visit_exit_idaction_url'},
                        $visitorInfo{'visit_exit_idaction_name'},
                        $visitorInfo{'time_spent_ref_action'}
                     ) || die "Can't prepare statement: $DBI::errstr";
        $succsess ++;
    }
}
$dbh->disconnect;
close FIL;
exit(0)

