Platon Technologies
not logged in Login Registration
EnglishSlovak
open source software development celebrating 10 years of open source development! Thursday, March 28, 2024

File: [Platon] / phpWebLogAnalyzer / phpWebLogAnalyzer.inc.php (download)

Revision 1.53, Fri May 27 16:30:34 2005 UTC (18 years, 10 months ago) by nepto


Changes since 1.52: +4 -4 lines

Updated copyright year, e-mail address and URL.

<?php

/*
 * phpWebLogAnalyzer - powerful weblog and analyzer
 *
 * phpWebLogAnalyzer.inc.php - main file of PHP API
 * ____________________________________________________________
 *
 * Developed by Ondrej Jombik <nepto@platon.sk>
 * Copyright (c) 2001-2005 Platon SDG, http://platon.sk/
 * All rights reserved.
 *
 * See README file for more information about this software.
 * See COPYING file for license information.
 *
 * Download the latest version from
 * http://platon.sk/projects/phpWebLogAnalyzer/
 */

/* $Platon: phpWebLogAnalyzer/phpWebLogAnalyzer.inc.php,v 1.52 2005/03/23 18:14:52 nepto Exp $ */

define('WEB_LOG_VALUE_SUBSTR_LENGTH',          255);
define('WEB_LOG_SESSION_TIMEOUT_DEFAULT',     1800);
define('WEB_LOG_RAW_LOG_DEFAULT',                1);
define('WEB_LOG_TRUNCATE_NAMES_DEFAULT',         0);
define('WEB_LOG_TRUNCATE_QUERY_STRINGS_DEFAULT', 1);
define('WEB_LOG_CACHE_MAX_PROPERTY_COUNT',    6000);

/* Internally used for _getCount() */
define('WEB_LOG_SESSIONS_COUNT_TYPE',    1);
define('WEB_LOG_ACCESSES_COUNT_TYPE',    2);

/*
 * Pear libraries
 */

require_once 'DB.php';
require_once 'Net/Ident.php';

class Web_Log
{

    /* Session variables

       $_session_timeout - maximum delay between two click from the same site
                           with the same user agent to count it as one session
       $_session_keys - keys of properties (keys to $_props array) which define
                        session; for each session all values of particular key
                        are the same
     */

    var $_session_timeout;
    var $_session_keys = array('remote_addr', 'http_user_agent');

    /* Ident variables

       $_ident_timeout - timeout for retrieving ident data from socket
     */
    var $_ident_timeout;

    /* Raw log variable

       $_raw_log - use raw log table for logging (it is faster than normal
                   logging, but it needs some job to transform data from
                   raw log table to normal table, for example via cron)
     */

    var $_raw_log;

    /* Short host names variable

       $_truncate_names - replace the last component of IP and the first
                          component of hostname if exists address with '*'
                          character
     */

    var $_truncate_names;

    /* Truncated query strings

       $_truncate_qstrings - flag to truncate query strings
       $_truncate_qstrings_keys - keys to truncate (case unsensitive)
     */

    var $_truncate_qstrings;
    var $_truncate_qstrings_keys = array(/*'session',*/ 'PHPSESSID');

    /* Database variables

       $_db - PEAR DB object
       $_dsn - database connection URI (db_type://user:pass@host/db_name)
     */

    var $_db;
    var $_dsn;

    /* Cache variables

       $_cache_active_sessions - cached result of active sessions query
       $_cache_inactive_sessions - cached result of inactive sessions query
     */

    //var $_cache_sessions_count;
    //var $_cache_raw_log_sessions_count;

    var $_cache_active_sessions;
    var $_cache_raw_log_active_sessions;
    var $_cache_inactive_sessions;
    var $_cache_raw_log_inactive_sessions;

    /* $_props - properties array                 {{{

       keys:    identifiers (when user is specifing some property for some
                special action (ingnore property or add property to list
                of session definers), it is provided via this identifiers)

       values:  arrays; keys of each array are described below

       key      description
       ------   -----------
       column   column name in main accesses table
       table    table name for values storing (in accesses table will be only
                ID to this table stored)
       var      how to get property value; if starts with '$' character, than
                it is eval()-ed, if not, than is string passed to getenv()
                function to obtain value
       value    value of property
       id       id of property; defined only if value is stored in its own
                separate table
       enabled  if empty, property is disabled; no action with that property
                is done; by default, all properties are enabled (not disabled)
     */

    var $_props = array(
            'id' => array(
                'column' => 'id',
                'table' => '',
                'var' => '' ),
            'datetime' => array(
                'column' => 'datetime',
                'table' => '',
                'var' => '' ),
            'value' => array(
                'column' => 'value_id',
                'table' => 'weblog_values',
                'var' => '' ),
            'request_method' => array(
                'column' => 'request_method_id',
                'table' => 'weblog_request_methods',
                /*'var' => '$HTTP_SERVER_VARS["REQUEST_METHOD"]' ),*/
                'var' => 'REQUEST_METHOD' ),
            'query_string' => array(
                'column' => 'query_string_id',
                'table' => 'weblog_query_strings',
                /*'var' => '$HTTP_SERVER_VARS["QUERY_STRING"]' ),*/
                'var' => 'QUERY_STRING' ),
            'path_info' => array(
                    'column' => 'path_info_id',
                    'table' => 'weblog_path_infos',
                    'var' => 'PATH_INFO' ),
            'path_translated' => array( /* must be retrieved from SERVER_VARS */
                    'column' => 'path_translated_id',
                    'table' => 'weblog_paths_translated',
                    'var' => '$HTTP_SERVER_VARS["PATH_TRANSLATED"]' ),
            'content_type' => array(
                    'column' => 'content_type_id',
                    'table' => 'weblog_content_types',
                    'var' => '$HTTP_SERVER_VARS["CONTENT_TYPE"]' ),
            'content_length' => array(
                    'column' => 'content_length',
                    'table' => '',
                    'var' => '$HTTP_SERVER_VARS["CONTENT_LENGTH"]' ),
            'script_name' => array(
                    'column' => 'script_name_id',
                    'table' => 'weblog_script_names',
                    /*'var' => '$HTTP_SERVER_VARS["SCRIPT_NAME"]' ),*/
                    'var' => 'SCRIPT_NAME' ),
            'server_name' => array(
                    'column' => 'server_name_id',
                    'table' => 'weblog_server_names',
                    'var' => '$HTTP_SERVER_VARS["SERVER_NAME"]' ),
            'server_port' => array(
                    'column' => 'server_port',
                    'table' => '',
                    'var' => '$HTTP_SERVER_VARS["SERVER_PORT"]' ),
            'server_software' => array(
                    'column' => 'server_software_id',
                    'table' => 'weblog_server_softwares',
                    'var' => '$HTTP_SERVER_VARS["SERVER_SOFTWARE"]' ),
            'server_protocol' => array(
                    'column' => 'server_protocol_id',
                    'table' => 'weblog_server_protocols',
                    'var' => '$HTTP_SERVER_VARS["SERVER_PROTOCOL"]' ),
            'gateway_interface' => array(
                    'column' => 'gateway_interface_id',
                    'table' => 'weblog_gateway_interfaces',
                    'var' => '$HTTP_SERVER_VARS["GATEWAY_INTERFACE"]' ),
            'proxy_addr' => array(
                    'column' => 'proxy_addr_id',
                    'table' => 'weblog_remote_addrs',
                    'var' => '' ),
            'proxy_host' => array(
                    'column' => 'proxy_host_id',
                    'table' => 'weblog_remote_hosts',
                    'var' => '' ),
            'remote_addr' => array(
                    'column' => 'remote_addr_id',
                    'table' => 'weblog_remote_addrs',
                    'var' => '' ),
            'remote_host' => array(
                    'column' => 'remote_host_id',
                    'table' => 'weblog_remote_hosts',
                    'var' => '' ),
            'remote_port' => array(
                    'column' => 'remote_port',
                    'table' => '',
                    'var' => '$HTTP_SERVER_VARS["REMOTE_PORT"]' ),
            'auth_type' => array(
                    'column' => 'auth_type_id',
                    'table' => 'weblog_auth_types',
                    'var' => 'AUTH_TYPE' ),
            'remote_user' => array(
                    'column' => 'remote_user_id',
                    'table' => 'weblog_remote_users',
                    'var' => '$HTTP_SERVER_VARS["REMOTE_USER"]' ),
            'remote_ident' => array(
                    'column' => 'remote_ident_id',
                    'table' => 'weblog_remote_idents',
                    'var' => '' ),
            'document_root' => array(
                    'column' => 'document_root_id',
                    'table' => 'weblog_document_roots',
                    'var' => '$HTTP_SERVER_VARS["DOCUMENT_ROOT"]' ),
            'http_accept' => array(
                    'column' => 'http_accept_id',
                    'table' => 'weblog_http_accepts',
                    'var' => '$HTTP_SERVER_VARS["HTTP_ACCEPT"]' ),
            'http_accept_charset' => array(
                    'column' => 'http_accept_charset_id',
                    'table' => 'weblog_http_accept_charsets',
                    'var' => '$HTTP_SERVER_VARS["HTTP_ACCEPT_CHARSET"]' ),
            'http_accept_encoding' => array(
                    'column' => 'http_accept_encoding_id',
                    'table' => 'weblog_http_accept_encodings',
                    'var' => '$HTTP_SERVER_VARS["HTTP_ACCEPT_ENCODING"]' ),
            'http_accept_language' => array(
                    'column' => 'http_accept_language_id',
                    'table' => 'weblog_http_accept_languages',
                    'var' => '$HTTP_SERVER_VARS["HTTP_ACCEPT_LANGUAGE"]' ),
            'http_connection' => array(
                    'column' => 'http_connection_id',
                    'table' => 'weblog_http_connections',
                    'var' => '$HTTP_SERVER_VARS["HTTP_CONNECTION"]' ),
            'http_host' => array(
                    'column' => 'http_host_id',
                    'table' => 'weblog_http_hosts',
                    'var' => '$HTTP_SERVER_VARS["HTTP_HOST"]' ),
            'http_referer' => array(
                    'column' => 'http_referer_id',
                    'table' => 'weblog_http_referers',
                    'var' => '$HTTP_SERVER_VARS["HTTP_REFERER"]' ),
            'http_user_agent' => array(
                    'column' => 'http_user_agent_id',
                    'table' => 'weblog_http_user_agents',
                    'var' => '$HTTP_SERVER_VARS["HTTP_USER_AGENT"]' ),
            'script_filename' => array(
                    'column' => 'script_filename_id',
                    'table' => 'weblog_script_filenames',
                    'var' => '$HTTP_SERVER_VARS["SCRIPT_FILENAME"]' ),
            'server_admin' => array(
                    'column' => 'server_admin_id',
                    'table' => 'weblog_server_admins',
                    'var' => '$HTTP_SERVER_VARS["SERVER_ADMIN"]' ),
            'server_signature' => array(
                    'column' => 'server_signature_id',
                    'table' => 'weblog_server_signatures',
                    'var' => '$HTTP_SERVER_VARS["SERVER_SIGNATURE"]' ),
            'request_uri' => array(
                    'column' => 'request_uri_id',
                    'table' => 'weblog_request_uris',
                    'var' => '$HTTP_SERVER_VARS["REQUEST_URI"]' ),
            'ident_username' => array(
                    'column' => 'ident_username_id',
                    'table' => 'weblog_ident_usernames',
                    'var' => '' ),
            'ident_ostype' => array(
                    'column' => 'ident_ostype_id',
                    'table' => 'weblog_ident_ostypes',
                    'var' => '' ),
            'session_id' => array(
                    'column' => 'session_id',
                    'table' => '',
                    'var' => '' )
                );    /* }}} */

    /*
     * Web_Log()
     *
     * Object constructor.
     */

    function Web_Log($dsn = '', $session_timeout = 0, $ident_timeout = 0) /* {{{ */
    {

        if (empty($session_timeout))
            $session_timeout = WEB_LOG_SESSION_TIMEOUT_DEFAULT;

        $this->_session_timeout   = intval($session_timeout);
        $this->_ident_timeout     = intval($ident_timeout);
        $this->_raw_log           = WEB_LOG_RAW_LOG_DEFAULT;
        $this->_truncate_names    = WEB_LOG_TRUNCATE_NAMES_DEFAULT;
        $this->_truncate_qstrings = WEB_LOG_TRUNCATE_QUERY_STRINGS_DEFAULT;

        unset($this->_db);
        unset($this->_dsn);
        //unset($this->_cache_sessions_count);
        //unset($this->_cache_raw_log_sessions_count);
        unset($this->_cache_active_sessions);
        unset($this->_cache_raw_log_active_sessions);
        unset($this->_cache_inactive_sessions);
        unset($this->_cache_raw_log_inactive_sessions);

        if (! empty($dsn)) {
            $this->setDSN($dsn);
        }

        foreach (array_keys($this->_props) as $prop) {
            $this->_props[$prop]['enabled']       = true;
            $this->_props[$prop]['enabled_cache'] = false;
        }
    } /* }}} */

    /*
     * destroy()
     *
     * Destructor. Must be called.
     */

    function destroy() /* {{{ */
    {
        if (isset($this->_db)) {
            $this->_db->disconnect();
            unset($this->_db);
        }
    } /* }}} */

    /*
     * setSessionTimeout(), getSessionTimeout()
     *
     * Sets/gets session timeout. Session timeout is a maximum delay between
     * two click from the same site with the same user agent to count it as
     * one session.
     */

    function setSessionTimeout($timeout) /* {{{ */
    {
        $this->_session_timeout = intval($timeout);
    } /* }}} */

    function getSessionTimeout() /* {{{ */
    {
        return $this->_session_timeout;
    } /* }}} */

    /*
     * setSessionKeys(), getSessionKeys()
     *
     * Sets/gets session keys.
     * If string specified, value will be appended to array.
     */

    function setSessionKeys($keys) /* {{{ */
    {
        if (is_array($keys)) {
            $this->_session_keys = $keys;
        } elseif (is_string($keys)) {
            array_push($this->_session_keys, $keys);
        }
    } /* }}} */

    function getSessionKeys() /* {{{ */
    {
        return $this->_session_keys;
    } /* }}} */

    /*
     * enableRawLog(), disableRawLog()
     *
     * Enable/disable of logging to raw acesses table.
     */

    function enableRawLog() /* {{{ */
    {
        $this->_raw_log = 1;
    } /* }}} */

    function disableRawLog() /* {{{ */
    {
        $this->_raw_log = 0;
    } /* }}} */

    /*
     * enableTruncateNames(), disableTruncateNames()
     *
     * Enable/disable of short IP addresses and hostnames usage.
     */

    function enableTruncateNames() /* {{{ */
    {
        $this->_truncate_names = 1;
    } /* }}} */

    function disableTruncateNames() /* {{{ */
    {
        $this->_truncate_names = 0;
    } /* }}} */

    /*
     * enableTruncateQueryStrings(), disableTruncateQueryStrings()
     * setTruncateQueryStringsKeys(), getTruncateQueryStringsKeys()
     *
     * Enable/disable trincating of query strings according to specified
     * query strings keys.
     *
     * Sets/gets truncate query strings keys.  If string specified, value
     * will be appended to array.
     */

    function enableTruncateQueryStrings() /* {{{ */
    {
        $this->_truncate_qstrings = 1;
    } /* }}} */

    function disableTruncateQueryStrings() /* {{{ */
    {
        $this->_truncate_qstrings = 1;
    } /* }}} */

    function setTruncateQueryStringsKeys($keys) /* {{{ */
    {
        if (is_array($keys)) {
            $this->_truncate_qstrings_keys = $keys;
        } elseif (is_string($keys)) {
            array_push($this->_truncate_qstrings_keys, $keys);
        }
    } /* }}} */

    function getTruncateQueryStringsKeys() /* {{{ */
    {
        return $this->_truncate_qstrings_keys;
    } /* }}} */

    /*
     * enablePropertyCache(), disablePropertyCache()
     * TODO: getPropertyCache(), setPropertyCache() - ???
     * enableAllPropertyCaches(), disableAllPropertyCaches()
     *
     * Enable/disable of specific property cache.
     */

    function enablePropertyCache($property) /* {{{ */
    {
        if (isset($this->_props[$property]))
            $this->_props[$property]['enabled_cache'] = true;
    } /* }}} */

    function disablePropertyCache($property) /* {{{ */
    {
        if (isset($this->_props[$property]))
            $this->_props[$property]['enabled_cache'] = false;
    } /* }}} */

    function enableAllPropertyCaches() /* {{{ */
    {
        foreach (array_keys($this->_props) as $property) {
            $this->_props[$property]['enabled_cache'] = true;
        }

        return true;
    } /* }}} */

    function disableAllPropertyCaches() /* {{{ */
    {
        foreach (array_keys($this->_props) as $property) {
            $this->_props[$property]['enabled_cache'] = false;
        }

        return true;
    } /* }}} */

    /*
     * enableProperty(), disableProperty()
     *
     * Enable/disable loging of specific property.
     */

    function enableProperty($property) /* {{{ */
    {
        if (isset($this->_props[$property]))
            $this->_props[$property]['enabled'] = true;
    } /* }}} */

    function disableProperty($property) /* {{{ */
    {
        if (isset($this->_props[$property]))
            $this->_props[$property]['enabled'] = false;
    } /* }}} */

    /*
     * enableAllProperties(), disableAllProperties()
     *
     * Enable/disable loging of all properties.
     */

    function enableAllProperties() /* {{{ */
    {
        foreach (array_keys($this->_props) as $property) {
            $this->_props[$property]['enabled'] = true;
        }

        return true;
    } /* }}} */

    function disableAllProperties() /* {{{ */
    {
        foreach (array_keys($this->_props) as $property) {
            $this->_props[$property]['enabled'] = false;
        }

        return true;
    } /* }}} */

    /*
     * getPropertyValue(), setPropertyValue(), clearPropertyValue()
     *
     * Gets/sets specific property value. Property cannot be disabled.
     */

    function getPropertyValue($prop_name) /* {{{ */
    {
        if (isset($this->_props[$prop_name])) {
            if (! $this->_props[$prop_name]['enabled'])
                return false;

            return isset($this->_props[$prop_name]['value'])
                ? $this->_props[$prop_name]['value']
                : false;
        }

        return false;
    } /* }}} */

    function setPropertyValue($prop_name, $value) /* {{{ */
    {
        if (isset($this->_props[$prop_name])) {
            $this->_props[$prop_name]['value'] = $value;
            return true;
        }

        return false;
    } /* }}} */

    function clearPropertyValue($value) /* {{{ */
    {
        if (isset($this->_props[$prop_name])) {
            if (isset($this->_props[$prop_name]['value']))
                unset($this->_props[$prop_name]['value']);
            return true;
        }

        return false;
    } /* }}} */

    /*
     * setAllPropertyValues(), clearAllPropertyValues()
     * setAllPropertyIDs(), clearAllPropertyIDs()
     * setAllProperties(), clearAllProperties()
     *
     * Set/clear all properties.
     */

    function setAllPropertyValues() /* {{{ */
    {
        /* TODO: this should set only values, not IDs
           there should exists also:
           1. setAllPropertyIDs() for setting up IDs
           2. setAllProperties() for setting up values and than IDs
         */
        $this->setStaticValues();
        return $this->setDynamicValues();
    } /* }}} */

    function clearAllPropertyValues() /* {{{ */
    {
        foreach (array_keys($this->_props) as $property) {
            if (isset($this->_props[$property]['value']))
                unset($this->_props[$property]['value']);
        }

        return true;
    } /* }}} */

/* NOT IMPLEMENTED YET, see comment above

    function setAllPropertyIDs()
    {
        return $this->setValues();
    }
*/

    function clearAllPropertyIDs() /* {{{ */
    {
        foreach (array_keys($this->_props) as $property) {
            if (isset($this->_props[$property]['id']))
                unset($this->_props[$property]['id']);
        }

        return true;
    } /* }}} */

    function setAllProperties() /* {{{ */
    {
        /* TODO: see comment above */
        $this->setStaticValues();
        return $this->setDynamicValues();
    } /* }}} */

    function clearAllProperties() /* {{{ */
    {
        $ret  = true;
        $ret &= $this->clearAllPropertyValues();
        $ret &= $this->clearAllPropertyIDs();

        return $ret;
    } /* }}} */

    /*
     * getPropertiesArray()
     *
     * Gets whole properties array.
     */

    function getPropertiesArray() /* {{{ */
    {
        return $this->_props;
    } /* }}} */

    /*
     * setDSN()
     *
     * Gets/sets DSN (db_type://user:pass@host/db_name)
     * for database connection.
     */

    function getDSN($dsn) /* {{{ */
    {
        return $this->_dsn;
    } /* }}} */

    function setDSN($dsn) /* {{{ */
    {
        $this->_dsn = $dsn;
    } /* }}} */

    /*
     * _checkDB()
     *
     * Checks if $this->_db is a valid PEAR DB object. If not it creates a new
     * one using $this->_dsn variable.
     */

    function _checkDB() /* {{{ */
    {
        if (isset($this->_db)) {
            if (DB::isError($this->_db))
                return false;
        } else {
            $this->_db = DB::connect($this->_dsn);

            if (DB::isError($this->_db))
                return false;

            $this->_db->setFetchMode(DB_FETCHMODE_ASSOC);
        }

        return true;
    } /* }}} */

    /**
     * Reconnects to database.
     *
     * @return  mixed   true on success, PEAR_Error on error
     * @access  public
     */
    function reconnect() /* {{{ */
    {
        unset($this->_db);
        if ($this->_checkDB() == false) {
            return $this->_db;
        }
        return true;
    } /* }}} */

    /*
     * _resolveIP()
     *
     * Resolves IP address to hostname.
     */

    function _resolveIP($addr) /* {{{ */
    {
        $host     = '';
        $addr_ar  = strchr($addr, ',') ? explode(',', $addr) : array($addr);
        $addr_idx = count($addr_ar);

        while ($addr_idx > 0) {
            $addr_idx--;
            $addr_ar[$addr_idx] = trim($addr_ar[$addr_idx]);

            if (preg_match('/^(\d{1,3}\.){3}\d{1,3}$/', $addr_ar[$addr_idx])) {
                $host = @gethostbyaddr($addr_ar[$addr_idx]);
                if (! strcmp($host, $addr_ar[$addr_idx]))
                    $host = '';
                break;
            }
        }

        return $host;
    } /* }}} */

    /*
     * _truncateName()
     *
     * Truncates hostname or IP address.
     */

    function _truncateName($name) /* {{{ */
    {
        $name_ar = explode('.', $name);

        if (count($name_ar) > 2) {
            if (is_numeric($name_ar[0])) {
                array_pop($name_ar);
                $name = join('.', $name_ar) . '.*';
            } else {
                array_shift($name_ar);
                $name = '*.' . join('.', $name_ar);
            }
        }

        return $name;
    } /* }}} */

    function _truncateQueryString($qstring) /* {{{ */
    {
        $ar_out = array();
        $ar = explode('&', $qstring);

        foreach ($ar as $part) {
            $match = 0;

            foreach ($this->_truncate_qstrings_keys as $key) {
                if (! strncasecmp($part, $key, strlen($key))) {
                    $match = 1;
                    break;
                }
            }

            if ($match == 0)
                $ar_out[] = $part;
        }

        return join('&', $ar_out);
    } /* }}} */

    /*
    * _setXxxValues()
    *
    * Sets properties values.
    */

    function _setBasicValues() /* {{{ */
    {
        global $HTTP_SERVER_VARS;
        global $HTTP_ENV_VARS;

        /*
         * Sets $_props values according appropriate 'var' if defined.
         */

        foreach (array_keys($this->_props) as $prop_name) {

            if (! $this->_props[$prop_name]['enabled'])
                continue;

            if (! empty($this->_props[$prop_name]['var'])) {
                $this->_props[$prop_name]['value'] = stripslashes(
                        $this->_props[$prop_name]['var'][0] == '$'
                        ? eval('return'
                            . ' (isset('.$this->_props[$prop_name]['var'].')'
                            . ' ? '.$this->_props[$prop_name]['var'].' : false);')
                            : getenv($this->_props[$prop_name]['var']));
            }
        }

        if ($this->_truncate_qstrings) {
            $req_uri_ar  = explode('?', $this->_props['request_uri']['value'], 2);
            $http_ref_ar = explode('?', $this->_props['http_referer']['value'], 2);

            if (count($this->_truncate_qstrings_keys) == 0) {
                $this->_props['query_string']['value'] = '';
                $req_uri_ar[1] = '';

                $url_ar = parse_url($http_ref_ar[0]);
                if (! strcasecmp($url_ar['host'],
                        $HTTP_SERVER_VARS['HTTP_HOST']))
                $http_ref_ar[1] = '';
            } else {
                $this->_props['query_string']['value'] =
                    $this->_truncateQueryString($this->_props['query_string']['value']);

                if (isset($req_uri_ar[1]))
                    if (($req_uri_ar[1] = $this->_truncateQueryString(
                                    $req_uri_ar[1])) == '')
                        array_pop($req_uri_ar);
                
                if (isset($http_ref_ar[1]))
                    if (($http_ref_ar[1] = $this->_truncateQueryString(
                                    $http_ref_ar[1])) == '')
                        array_pop($http_ref_ar);
            }

            $this->_props['request_uri']['value']  = join('?', $req_uri_ar);
            $this->_props['http_referer']['value'] = join('?', $http_ref_ar);
        }

        return true;
    } /* }}} */

    function _setHostValues() /* {{{ */
    {
        global $HTTP_SERVER_VARS;

        /*
         * IP address & proxy server getting.
         */

        $remote_addr = '';
        $remote_host = '';
        $proxy_addr = '';
        $proxy_host = '';

        if (! empty($HTTP_SERVER_VARS["HTTP_X_FORWARDED_FOR"])) {  
            $remote_addr = stripslashes($HTTP_SERVER_VARS["HTTP_X_FORWARDED_FOR"]);
            $proxy_addr = stripslashes($HTTP_SERVER_VARS["REMOTE_ADDR"]);
        }
        else {
            $remote_addr = stripslashes($HTTP_SERVER_VARS["REMOTE_ADDR"]);
        }

        /* REMOVE ME */
        //$remote_addr .= ", 192.168.1.3, 111.111.2., unknown";

        if ($this->_props['remote_addr']['enabled'])
            $this->_props['remote_addr']['value'] = $this->_truncate_names
                ? $this->_truncateName($remote_addr)
                : $remote_addr;

        if ($this->_props['proxy_addr']['enabled'])
            $this->_props['proxy_addr']['value'] = $this->_truncate_names
                ? $this->_truncateName($proxy_addr)
                : $proxy_addr;

        /*
         * Host names resolving.
         */

        if ($this->_props['remote_host']['enabled']) {
            $remote_host = empty($HTTP_SERVER_VARS["REMOTE_HOST"])
                ? $this->_resolveIP($remote_addr)
                : stripslashes($HTTP_SERVER_VARS["REMOTE_HOST"]);

            $this->_props['remote_host']['value'] = $this->_truncate_names
                ? $this->_truncateName($remote_host)
                : $remote_host;
        }

        if ($proxy_addr) {
            /* XXX: there was a bug, I fixed it, but it is really OK now?
               Nepto [26/4/2002] */
            if ($this->_props['proxy_host']['enabled']) {
                $proxy_host = $this->_resolveIP($proxy_addr);
                $this->_props['proxy_host']['value'] = $this->_truncate_names
                    ? $this->_truncateName($proxy_host)
                    : $proxy_host;
            }
        }

        return true;
    } /* }}} */

    function _setIdentValues() /* {{{ */
    {
        global $HTTP_SERVER_VARS;

        $remote_addr = stripslashes(
                ! empty($HTTP_SERVER_VARS['HTTP_X_FORWARDED_FOR'])
                ? $HTTP_SERVER_VARS['HTTP_X_FORWARDED_FOR']
                : $HTTP_SERVER_VARS['REMOTE_ADDR']
                );

        /* if multiple hosts presents, get the first one */
        if (strchr($remote_addr, ',')) {
            $remote_addr = explode(',', $remote_addr);
            $remote_addr = trim($remote_addr[0]);
        }

        /*
         * Ident protocol stuff.
         */

        if ($this->_props['ident_username']['enabled']
                || $this->_props['ident_username']['enabled']) {

            $ident = new Net_Ident($remote_addr,
                    stripslashes($HTTP_SERVER_VARS['REMOTE_PORT']),
                    stripslashes($HTTP_SERVER_VARS['SERVER_PORT']),
                    0 /* default */, $this->_ident_timeout);

            if (PEAR::isError($ident->query())) {
                // print "Ident query failed: " . $ident->error() . ".<br>";
            } else {
                if ($this->_props['ident_username']['enabled'])
                    $this->_props['ident_username']['value']
                        = $ident->getUser();
                if ($this->_props['ident_ostype']['enabled'])
                    $this->_props['ident_ostype']['value']
                        = $ident->getOsType();
            }
        }

        return true;
    } /* }}} */

    function _setValueValue($value = 0) /* {{{ */
    {
        if ($this->_props['value']['enabled'])
            $this->_props['value']['value'] = $value;

        return true;
    } /* }}} */

    function _setIDs() /* {{{ */
    {
        // Counting IDs according to values.
        foreach (array_keys($this->_props) as $prop_name) {
            if (isset($this->_props[$prop_name]['value'])) {

                if (! empty($this->_props[$prop_name]['table'])) {
                    $id = $this->_getID($prop_name);
                    if (DB::isError($id))
                        return $id;
                    if (intval($id))
                        $this->_props[$prop_name]['id'] = $id;
                } else {
                    $this->_props[$prop_name]['id'] =
                        $this->_props[$prop_name]['value'];
                }
            }
        }
        return true;
    } /* }}} */

    function _setSessionIDValue() /* {{{ */
    {
        if ($this->_props['session_id']['enabled']) {
            $session_id = $this->_getSessionID();

            if (DB::isError($session_id))
                return $session_id;

            if (intval($session_id))
                $this->_props['session_id']['id'] =
                    $this->_props['session_id']['value'] =
                    $session_id;
        }

        return true;
    } /* }}} */

    function _setDatetimeValue() /* {{{ */
    {
        /* TODO: make this database independent (or sysdate() is?) */
        if ($this->_props['datetime']['enabled'])
            $this->_props['datetime']['id'] =
                $this->_props['datetime']['value'] =
                'SYSDATE()';
    } /* }}} */


    /*
     * setStaticValues()
     *
     * Set all enabled properties values.
     */

    function setStaticValues($value = 0) /* {{{ */
    {
        // Set basic values
        $this->_setBasicValues();
        // Setting basic host values such as remote_host, remote_addr,
        //   proxy_host, proxy_addr
        $this->_setHostValues();
        // Setting ident protocol values: ident_username, ident_ostype
        $this->_setIdentValues();
        // Value property
        $this->_setValueValue($value);
    } /* }}} */

    /*
     * setDynamicValues()
     *
     * Set all enabled properties values.
     */

    function setDynamicValues() /* {{{ */
    {
        if ($this->_checkDB() == false)
            return $this->_db;
        // If raw log is enabled, set appropriate IDs according to values
        if (! $this->_raw_log) {
            $this->_setIDs();
        }
        // Session property. It is counted according to other IDs,
        //   so it must be after others IDs counting loop above.
        $this->_setSessionIDValue();
        // Datetime property. It doesn't contain real value,
        //   but SQL clausule for getting datetime.
        $this->_setDatetimeValue();

        return true;
    } /* }}} */

    /*
     * registerAccess()
     *
     * Register access. Set values and write them into web log.
     */

    function registerAccess($value = 0) /* {{{ */
    {
        /* NOTES: containing variable parts
           query_string, request_uri, http_referer
         */
        $this->setStaticValues();
        $ret = $this->setDynamicValues($value);
        if ($ret != true)
            return $ret;

        /*
         * Writting values
         */
        return $this->writeValues();
    } /* }}} */

    /**
     * Inserts one record to accesses table. Also inserts records into another
     * tables if raw is turned off and it is also neccessary.
     *
     * @return  mixed   true on success, PEAR_Error on DB error
     * @access  public
     */

    function writeValues() /* {{{ */
    {
        if ($this->_checkDB() == false)
            return $this->_db;

        $keys = '';
        $vals = '';

        foreach (array_keys($this->_props) as $prop_name) {
            $sep = ($keys == '' ? '' : ', ');
            $val = '';

            if ($this->_raw_log) {
                if (isset($this->_props[$prop_name]['value'])
                        && ! empty($this->_props[$prop_name]['value'])) {
                    if (! empty($this->_props[$prop_name]['table'])) {
                        $val = $this->_props[$prop_name]['value'];
                        $val = substr($val, 0, WEB_LOG_VALUE_SUBSTR_LENGTH);
                        $val = $this->_db->quoteString($val);
                        $val = "'$val'";
                    } else {
                        $val = $this->_props[$prop_name]['value'];
                    }
                } else {
                    $val = 0;
                }
            } else {
                if (isset($this->_props[$prop_name]['id'])
                        && ! empty($this->_props[$prop_name]['id'])) {
                    $val = $this->_props[$prop_name]['id'];
                    // FIXME: nasty datetime quoting hack
                    if ($prop_name == 'datetime' && strcasecmp('sysdate()',
                            $this->_props[$prop_name]['value'])) {
                        $val = "'$val'";
                    }
                } else {
                    $val = 0;
                }
            }

            if ($val) {
                $keys .= $sep . $this->_props[$prop_name]['column'];
                $vals .= $sep . $val;
            }
        }

        $accesses_table = $this->_raw_log
            ? 'weblog_accesses_raw'
            : 'weblog_accesses';

        $query = "INSERT INTO $accesses_table ($keys) VALUES ($vals)";

        //print "<hr>$query<br>\n";

        if (DB::isError($result = $this->_db->query($query))) {
            return $result;
        }

        return true;
    } /* }}} */

    /**
     * Performs remote log via HTTP protocol. Remote script shoud returns
     * text/plain content type and print 1 on success and 0 on error followed
     * by error message on next line(s).
     *
     * @param   string  $url    URL where to log; data will be passed using
     *                          HTTP POST request method
     * @param   string  $value  value to log
     * @return  mixed           true on success, PEAR_Error on failure
     * @access  public
     */

    function remoteLog($url, $value = 0) /* {{{ */
    {
        $this->setStaticValues($value);
        $data = 'data='.rawurlencode(serialize($this));
        $host = parse_url($url);
        $port = isset($host['port']) ? $host['port'] : 80;
        $host = $host['host'];
        $response = false;
        $request  = "POST $url HTTP/1.0\r\n"
            ."Host: $host\r\n"
            ."Accept: text/plain\r\n"
            ."Accept-Language: en\r\n"
            ."User-Agent: phpWebLogAnalyzer::remoteLog()\r\n"
            ."Content-type: application/x-www-form-urlencoded\r\n"
            ."Content-length: ".strlen($data)."\r\n\r\n".$data;
        $fp = fsockopen($host, $port);

        if ($fp) {
            fputs($fp, $request);
            if (strpos(fgets($fp, 1024), '200 ')) {
                do {
                    $line = fgets($fp, 1024);
                } while ($line != "\r\n");

                $response = array();
                while ($line = fgets($fp, 1024)) {
                    $response[] = $line;
                }
                fclose($fp);
            }
        }
        if ($response == false || count($response) <= 0) {
            return new PEAR_Error('Connection error ('.$url.')'); // )
        }
        $error_code = intval($response[0]);
        if ($error_code != 0) {
            return true;
        }
        unset($response[0]);
        $error_message = count($response) > 0
            ? join("\n", $response) : 'Unknown remote log error';
        return new PEAR_Error($error_message);
    } /* }}} */
     
    /*
     * _getID()
     *
     * Return ID of $value in $table. 
     * If $value is not in table, record will be inserted and ID returned.
     */

    function _getID($property) /* {{{ */
    {
        $table         = $this->_props[$property]['table'];
        $value         = $this->_props[$property]['value'];
        $enabled_cache = $this->_props[$property]['enabled_cache'];

        if ($enabled_cache) {
            if (! isset($this->_props[$property]['cache'])) {
                $count = $this->getPropertyCount($property);
                if (DB::isError($count)) {
                    return $count;
                }
                $count = intval($count);
                if ($count <= 0 || $count > WEB_LOG_CACHE_MAX_PROPERTY_COUNT) {
                    // setting empty cache
                    $this->_props[$property]['cache'] = array();
                } else {
                    $query = 'SELECT id, value FROM ' . $table;
                    if (DB::isError($cache = $this->_db->getAssoc($query)))
                        return $cache;
                    $this->_props[$property]['cache'] = $cache;
                    unset($cache);
                }
            }

            $ret = array_search($value, $this->_props[$property]['cache']);
            if ($ret !== false)
                return $ret;
        }

        for ($i = 0; $i < 2; $i++) {

            $query = sprintf('SELECT id FROM %s WHERE value = "%s"',
                    $table, $this->_db->quoteString(
                        substr($value, 0, WEB_LOG_VALUE_SUBSTR_LENGTH)));

            if (DB::isError($id = $this->_db->getOne($query)))
                return $id;

            if ($id) {
                if ($enabled_cache)
                    $this->_props[$property]['cache'][$id] = $value;

                return $id;
            }

            /* Important note:

               We cannot count id before insert (for example with: select
               max(id) from $table) because there can be also another connection
               to the same database. It queries the same maximal id and insert
               appropriate record into table. And our insert will fail.
             */

            $query = sprintf('INSERT INTO %s (id, value) VALUES (0, "%s")',
                    $table, $this->_db->quoteString($value));

            if ($i == 0) {
                $this->_db->expectError(DB_ERROR_ALREADY_EXISTS);
                $result = $this->_db->query($query);
                $this->_db->popExpect();
            } else {
                $result = $this->_db->query($query);
            }

            /*
             * There is a possibility of insert failure. Paraller connection
             * could insert the same record into table as we. So if it was
             * the first fail, go once again and check if it is record already
             * inserted. If it will fails again, than raise error.
             */

            if (DB::isError($result)) {
                if ($i == 0 && $result->getCode() == DB_ERROR_ALREADY_EXISTS) {
                    /* This is an expected error. If it will be returned
                       again we will count it seriously. */
                } else {
                    return $result;
                }
            } else {
                /* No errors, insert succeed. */
                break;
            }
        }

        // TODO: LAST_INSERT_ID() is MySQL dependent? Yes it is!
        // use appropriate PEAR DB method
        $query = 'SELECT LAST_INSERT_ID()';
        if (DB::isError($id = $this->_db->getOne($query)))
            return $id;

        if ($id) {
            if ($enabled_cache)
                $this->_props[$property]['cache'][$id] = $value;

            return $id;
        }

        return 0;
    } /* }}} */

    /*
     * _getSessionID()
     *
     * Returns session_id according to session variables of object. Session
     * variables are $_session_timeout and $_session_keys.
     */
    function _getSessionID() /* {{{ */
    {
        $where = '';
        foreach ($this->_session_keys as $session_key) {
            if (isset($this->_props[$session_key])) {
                $where .= ($where == '' ? "WHERE " : " AND ");

                $where .= $this->_props[$session_key]['column'];
                $where .= $this->_raw_log
                    ? (isset($this->_props[$session_key]['value'])
                            ? " = '" . $this->_db->quoteString(substr(
                                    $this->_props[$session_key]['value'],
                                    0, WEB_LOG_VALUE_SUBSTR_LENGTH)) . "'"
                            : ' is NULL')
                    : (isset($this->_props[$session_key]['id'])
                            ? " = '" . $this->_props[$session_key]['id'] . "'"
                            : ' is NULL');
            }
        }

        $accesses_table = $this->_raw_log
            ? 'weblog_accesses_raw'
            : 'weblog_accesses';

        $query = 'SELECT id, session_id,'
            .' UNIX_TIMESTAMP(SYSDATE()) - UNIX_TIMESTAMP(datetime) AS diff_sec'
            .' FROM '.$accesses_table.' '.$where
            .' ORDER BY datetime DESC'
            .' LIMIT 1';

        if (DB::isError($row = $this->_db->getRow($query)))
            return $row;

        if (is_array($row)
                && ($row['diff_sec'] < $this->_session_timeout)
                && ($row['session_id'])) {

            return $row['session_id'];
        }

        /*
         * If raw logging is enabled first look into raw accesses table and
         * than if no max session ID cannot be counted look into normal
         * accesses table. If raw logging is disabled look only in normal 
         * table. If although no max session ID is not present returns 1.
         */

        foreach (($this->_raw_log
                    ? array('weblog_accesses_raw', 'weblog_accesses')
                    : array('weblog_accesses')) as $table) {

            $query = 'SELECT MAX(session_id) + 1 AS new_session_id'
                .' FROM ' . $table;

            if (DB::isError($id = $this->_db->getOne($query)))
                return $id;

            if ($id)
                return $id;
        }

        /* Returns starting session ID with value of 1. */
        return 1;
    } /* }}} */

    /*
     * getPropertyCount()
     *
     * Return number of items in DB for particular property.
     */

    function getPropertyCount($prop_name) /* {{{ */
    {
        if ($this->_checkDB() == false)
            return $this->_db;
        if (! isset($this->_props[$prop_name])) {
            return false;
        }
        if ($this->_raw_log) {
            $column = @$this->_props[$prop_name]['column'];
            if (strlen($column) <= 0) {
                return false;
            }
            $query = "SELECT COUNT(DISTINCT $column) FROM weblog_accesses_raw";
        } else {
            $table = @$this->_props[$prop_name]['table'];
            if (strlen($table) <= 0) {
                return false;
            }
            $query = "SELECT COUNT(*) FROM $table";
        }
        if (DB::isError($count = $this->_db->getOne($query)))
            return $count;
        if (isset($count))
            return $count;
        return false;
    } /* }}} */

    /*
     * getSessionsCount()
     * getAccessesCount()
     *
     * Returns counts of sessions/accesses in database
     * for defined conditions in $array.
     */

    function getSessionsCount($array = '') /* {{{ */
    {
        return $this->_getCount($array, WEB_LOG_SESSIONS_COUNT_TYPE);
    } /* }}} */

    function getAccessesCount($array = '') /* {{{ */
    {
        return $this->_getCount($array, WEB_LOG_ACCESSES_COUNT_TYPE);
    } /* }}} */

    function _getCount($array = '', $type) /* {{{ */
    {
        if ($this->_checkDB() == false)
            return $this->_db;

        $accesses_table = $this->_raw_log
            ? 'weblog_accesses_raw'
            : 'weblog_accesses';

        $list_tables = '';
        $list_where  = '';

        if (is_array($array)) {

            foreach ($array as $key => $val) {

                if (! $this->_raw_log && isset($this->_props[$key]['table'])) {
                    $list_where .= ($list_where == '' ? '' : ' and ');
                    $list_where .= $accesses_table.'.' 
                        . $this->_props[$key]['column'] . ' = '
                        . $this->_props[$key]['table'] . '.id AND '
                        . $this->_props[$key]['table'] . '.value LIKE '
                        . $this->_db->quote($val);

                    $list_tables .= ($list_tables == '' ? '' : ', ');
                    $list_tables .= $this->_props[$key]['table'];
                } elseif (isset($this->_props[$key])) {
                    $list_where .= ($list_where == '' ? '' : ' and ');
                    $list_where .= $this->_props[$key]['column'] . ' LIKE '
                        . $this->_db->quote($val);
                }
            }
        }

        switch ($type) {
            case WEB_LOG_SESSIONS_COUNT_TYPE:
                $select_field = "COUNT(DISTINCT $accesses_table.session_id)";
                break;
            case WEB_LOG_ACCESSES_COUNT_TYPE:
                $select_field = "COUNT($accesses_table.id)";
                break;
            default:
                return false; // error
        }

        $query = "SELECT $select_field FROM $accesses_table";

        if (strlen($list_tables) > 0)
            $query .= ", $list_tables";

        if (strlen($list_where) > 0)
            $query .= " WHERE $list_where";
        //echo '[['.$query . ']]<hr>';

        if (DB::isError($count = $this->_db->getOne($query)))
            return $count;

        if (isset($count))
            return $count;

        return false;
    } /* }}} */

    /*
     * getSessions()
     *
     * Returns session IDs.
     *
     * TODO:
     * For $state equal 0 all sessions, -1 for inactive sessions, 1 for active.
     */

    function _getSessions($active = true) /* {{{ */
    {
        if ($this->_checkDB() == false)
            return $this->_db;

        $accesses_table = $this->_raw_log
            ? 'weblog_accesses_raw'
            : 'weblog_accesses';

        $query = sprintf('SELECT session_id FROM %s'
                .' GROUP BY session_id'
                .' HAVING UNIX_TIMESTAMP(SYSDATE())'
                .' - UNIX_TIMESTAMP(MAX(datetime)) %s %s'
                .' ORDER BY session_id ASC',
                $accesses_table,
                $active ? '<' : '>=',
                $this->_session_timeout);

        return $this->_db->getCol($query);
    } /* }}} */

    /*
     * getActiveSessions()
     *
     * Returns array with IDs of active sessions.
     */

    function getActiveSessions() /* {{{ */
    {
        if ($this->_raw_log) {
            if (isset($this->_cache_raw_log_active_sessions))
                return $this->_cache_active_sessions;
        } else {
            if (isset($this->_cache_active_sessions))
                return $this->_cache_active_sessions;
        }

        $active_sessions = $this->_getSessions(true);
        if (DB::isError($active_sessions))
            return $active_sessions;

        if ($this->_raw_log) {
            $this->_cache_raw_log_active_sessions = $active_sessions;
        } else {
            $this->_cache_active_sessions = $active_sessions;
        }

        return $active_sessions;
    } /* }}} */

    /*
     * getInactiveSessions()
     *
     * Returns array with IDs of inactive sessions.
     */

    function getInactiveSessions() /* {{{ */
    {
        if ($this->_raw_log) {
            if (isset($this->_cache_raw_log_inactive_sessions))
                return $this->_cache_inactive_sessions;
        } else {
            if (isset($this->_cache_inactive_sessions))
                return $this->_cache_inactive_sessions;
        }

        $inactive_sessions = $this->_getSessions(false);
        if (DB::isError($inactive_sessions))
            return $inactive_sessions;

        if ($this->_raw_log) {
            $this->_cache_raw_log_inactive_sessions = $inactive_sessions;
        } else {
            $this->_cache_inactive_sessions = $inactive_sessions;
        }

        return $inactive_sessions;
    } /* }}} */

    /*
     * Optimize raw table
     */
    function optimizeRawTable() /* {{{ */
    {
        if ($this->_checkDB() == false)
            return $this->_db;

        if ($this->_db->phptype != 'mysql')
            return false;

        return $this->_db->query('OPTIMIZE TABLE weblog_accesses_raw');
    } /* }}} */
    
    /*
     * Raw converting functions
     */

    function getAccessesOfSession($session_id) /* {{{ */
    {
        if ($this->_checkDB() == false)
            return $this->_db;

        if (is_array($session_id)) {
            for ($i = 0; $i < count($session_id); $i++)
                $session_id[$i] = intval($session_id[$i]);
        }

        $accesses_table = $this->_raw_log
            ? 'weblog_accesses_raw'
            : 'weblog_accesses';

        $query = "SELECT id FROM $accesses_table WHERE session_id ";
        $query .= is_array($session_id)
            ? 'IN (' . join(', ', $session_id) . ')'
                    : (intval($session_id) == 0
                        ? 'IS NULL'
                        : '= ' . intval($session_id));

        if (DB::isError($ids = $this->_db->getCol($query)))
            return $ids;

        return $ids;
    } /* }}} */

    function readIntoValues($access_id) /* {{{ */
    {
        if (! $this->_raw_log) {
            die("readIntoValues(): not implemented for normal log\n");
        }

        if ($this->_checkDB() == false)
            return $this->_db;

        /* TODO: Note: we are selecting all from DB, but probably better will
           be to select only enabled properties. */    

        $query = sprintf('SELECT * FROM %s WHERE id = %s',
                'weblog_accesses_raw', intval($access_id));

        if (DB::isError($ar = $this->_db->getRow($query)))
            return $ar;

        foreach (array_keys($this->_props) as $prop) {
            //echo "DEBUG: checking property $prop - ";
            if (isset($ar[$this->_props[$prop]['column']])) {
                $this->_props[$prop]['value'] =
                    $ar[$this->_props[$prop]['column']];
                //echo " is set: ";
                //echo $this->_props[$prop]['value'];
                //echo "\n";
            } else {
                //echo " is NOT set\n";
            }
        }

        return true;
    } /* }}} */

    function deleteSession($session_id) /* {{{ */
    {
        if ($this->_checkDB() == false)
            return $this->_db;

        if (is_array($session_id)) {
            for ($i = 0; $i < count($session_id); $i++)
                $session_id[$i] = intval($session_id[$i]);
        }

        $accesses_table = $this->_raw_log
            ? 'weblog_accesses_raw'
            : 'weblog_accesses';

        $query = "DELETE FROM $accesses_table WHERE session_id ";
        $query .= is_array($session_id)
            ? 'IN (' . join(', ', $session_id) . ')'
                    : (intval($session_id) == 0
                        ? 'IS NULL'
                        : '= ' . intval($session_id));

        if (DB::isError($res = $this->_db->query($query)))
            return $ids;

        return true;
    } /* }}} */

    function convert($debug = 0) /* {{{ */
    {
        $this->enableRawLog();
        $inactive_sessions = $this->getInactiveSessions();

        if (DB::isError($inactive_sessions))
            return $inactive_sessions;

        if ($debug) {
            echo "Active sessions:   [" . implode($this->getActiveSessions(), '][') . "]\n";
            echo "Inactive sessions: [" . implode($inactive_sessions, '][') . "]\n";
        }


        if (count($inactive_sessions) < 2) {
            return true;
        }

        /* The highest session ID will remain. */
        array_pop($inactive_sessions);
        $this->enableAllPropertyCaches();

        foreach ($inactive_sessions as $sid) {

            if ($debug) {
                echo "[$sid]::";
            }

            $ids = $this->getAccessesOfSession($sid);
            if (DB::isError($ids))
                return $ids;

            foreach ($ids as $id) {
                $this->enableRawLog();
                $this->clearAllProperties();
                if (DB::isError($res = $this->readIntoValues($id)))
                    return res;
                $this->setPropertyValue('id', 0);
                $this->disableRawLog();
                if (DB::isError($res = $this->_setIDs()))
                    return $res;
                if (DB::isError($res = $this->writeValues()))
                    return $res;

                if ($debug) {
                    echo "[$id]";
                }
            }

            $this->enableRawLog();
            if (DB::isError($res = $this->deleteSession($sid)))
                return $res;

            if ($debug) {
                echo "\n";
            }
        }

        $this->optimizeRawTable();
    } /* }}} */
}

/* vim: set expandtab tabstop=4 shiftwidth=4:
 * vim600: fdm=marker fdl=0 fdc=0
 */

?>

Platon Group <platon@platon.org> http://platon.org/
Copyright © 2002-2006 Platon Group
Site powered by Metafox CMS
Go to Top