|


Корпоративний інтернет-лічильник
Анотація
У цій статті розповідається як створити інтернет-лічильник для корпоративного порталу.
Завдання
Лічильник повинен вести докладну інформацію про відвідувачів: адреса, звідки прийшов відвідувач, адреса сторінки, IP-адреса відвідувача, дата, браузер користувача, операційна система.
За IP-адресою можна визначити країну та регіон, звідки прийшов відвідувач.
Крім того, ми повинні мати можливість переглядати статистику відвідувань по днях, кількість нових відвідувачів (та їх IP-адреси), кількість унікальних відвідувачів (та їх IP-адреси), найкращі посилання на нашу інтернет-сторінку, найпопулярніші сторінки тощо.
Схема виконання
Для початку розглянемо схему виконання лічильника.
1. Користувач з Інтернету (Користувач1, Користувач2, Користувач3) заходить на нашу інтернет-сторінку, розташовану на сервері провайдера.
2. На інтернет-сторінці виконується код на PHP, який визначає IP-адресу користувача, URL звідки прийшов, URL сторінки, браузер та операційну систему користувача. Ці дані програма передає на корпоративний інтернет-сервер.
3. На корпоративному інтернет-сервері викликається процедура InterBase, що зберігається, для передачі даних про користувача та отримання статистичної інформації для інтернет-сторінки.
4. Статистично дані передаються до програми на Інтернет-сторінці та виводяться для відвідувача.
Згодом адміністратор підключається до Interbase-сервера за допомогою клієнтської програми (написаної на Delphi) і обробляє інформацію.
Примітка: Корпоративний сервер та InterBase-сервер можна поєднати, але тоді зменшується рівень захисту інформації. Оскільки знаючи пароль та ім'я користувача можна буде підключитися до бази даних з Інтернету.
Структура бази даних
Тепер створимо структуру бази даних.
Таблиця Project призначена для зберігання назви проекту. Таким чином, ми можемо створювати скільки завгодно лічильників.
У таблиці CountData накопичується інформація про відвідувачів:
URLFrom - Звідки прийшов відвідувач,
URLCurr – яку сторінку відвідали,
DateHint – дата (без часу) коли відвідали,
FullDate – повна дата,
IPUser – IP-адреса відвідувача,
Browser – браузер,
SystemUser - операційна система користувача,
SystemVer – версія операційної системи,
CompName – назва комп'ютера відвідувача.
У таблиці IPTable зберігаються адреси унікальних IP-адрес.
Скрипт бази даних
Згенеруємо скрипт бази даних за цією структурою:
CREATE TABLE CountData (
CountDataID INTEGER NOT NULL,
ProjID INTEGER,
URLFrom VARCHAR(1024),
URLCurr VARCHAR(1024),
DateHint DATE,
FullDate DATE,
IPUser VARCHAR(15),
Browser VARCHAR(255),
SystemUser VARCHAR(255),
SystemVer VARCHAR(255)
);
CREATE INDEX IF318CountData ON CountData
(
ProjID
);
CREATE INDEX ak_IP ON CountData
(
IPUser
);
CREATE INDEX ak_DateHint ON CountData
(
DateHint
);
ALTER TABLE CountData
ADD CONSTRAINT PKCountData PRIMARY KEY (CountDataID);
CREATE TABLE IPTable (
IPUser VARCHAR(15) NOT NULL,
DateAdd DATE
);
CREATE INDEX akDateAdd ON IPTable
(
DateAdd
);
ALTER TABLE IPTable
ADD CONSTRAINT PKIPTable PRIMARY KEY (IPUser);
CREATE TABLE Project (
ProjID INTEGER NOT NULL,
ProjName VARCHAR(255),
Comment BLOB SUB_TYPE 1
);
ALTER TABLE Project
ADD CONSTRAINT PKProject PRIMARY KEY (ProjID);
ALTER TABLE CountData
ADD CONSTRAINT Project_CountData
FOREIGN KEY (ProjID)
REFERENCES Project;
CREATE EXCEPTION ERWIN_PARENT_INSERT_RESTRICT "Cannot INSERT Parent table because Child table exists.";
CREATE EXCEPTION ERWIN_PARENT_UPDATE_RESTRICT "Cannot UPDATE Parent table because Child table exists.";
CREATE EXCEPTION ERWIN_PARENT_DELETE_RESTRICT "Cannot DELETE Parent table because Child table exists.";
CREATE EXCEPTION ERWIN_CHILD_INSERT_RESTRICT "Cannot INSERT Child table because Parent table does not exist.";
CREATE EXCEPTION ERWIN_CHILD_UPDATE_RESTRICT "Cannot UPDATE Child table because Parent table does not exist.";
CREATE EXCEPTION ERWIN_CHILD_DELETE_RESTRICT "Cannot DELETE Child table because Parent table does not exist.";
SET TERM ^;
CREATE TRIGGER tI_CountData FOR CountData AFTER INSERT AS
DECLARE VARIABLE numrows INTEGER;
BEGIN
select count(*)
from Project
where
NEW.ProjID = Project.ProjID into numrows;
IF (
NEW.ProjID is not null and
numrows = 0
) THEN
BEGIN
EXCEPTION ERWIN_CHILD_INSERT_RESTRICT;
END
END ^
CREATE TRIGGER tU_CountData FOR CountData AFTER UPDATE AS
DECLARE VARIABLE numrows INTEGER;
BEGIN
select count(*)
from Project
where
NEW.ProjID = Project.ProjID into numrows;
IF (
NEW.ProjID is not null and
numrows = 0
) THEN
BEGIN
EXCEPTION ERWIN_CHILD_UPDATE_RESTRICT;
END
END ^
CREATE TRIGGER tD_Project FOR Project AFTER DELETE AS
DECLARE VARIABLE numrows INTEGER;
BEGIN
select count(*)
from CountData
where
CountData.ProjID = OLD.ProjID into numrows;
IF (numrows > 0) THEN
BEGIN
EXCEPTION ERWIN_PARENT_DELETE_RESTRICT;
END
END ^
CREATE TRIGGER tU_Project FOR Project AFTER UPDATE AS
DECLARE VARIABLE numrows INTEGER;
BEGIN
IF
(OLD.ProjID <> NEW.ProjID) THEN
BEGIN
update CountData
set
CountData.ProjID = NEW.ProjID
where
CountData.ProjID = OLD.ProjID;
END
END ^
Тригера та процедури, що зберігаються
Унікальні IP-адреси
Унікальні IP-адреси будуть автоматично фіксуватися базою даних. Для цього ми напишемо кілька тригерів.
Тригер вставки унікальних IP-адрес:
CREATE TRIGGER RTI_COUNTDATA FOR COUNTDATA BEFORE INSERT POSITION 0 AS
DECLARE VARIABLE CNT INTEGER;
BEGIN
NEW.COUNTDATAID=GEN_ID(GCountDataID,1);
NEW.DATEHINT="TODAY";
NEW.FULLDATE="NOW";
SELECT COUNT(*)
FROM IPTABLE
WHERE (IPUSER=NEW.IPUSER)
AND(PROJID=NEW.PROJID)
INTO CNT;
IF (CNT=0) THEN
INSERT INTO IPTABLE (IPUSER, PROJID)
VALUES (NEW.IPUSER, NEW.PROJID);
END
^
Тригер заповнення дати унікальної IP-адреси:
CREATE TRIGGER RTI_IPTABLE FOR IPTABLE BEFORE INSERT POSITION 0 AS
BEGIN
NEW.DATEADD="TODAY";
END
Реєстрація користувача у базі даних
Тепер створимо процедуру, що зберігається, для реєстрації користувача в базі даних і отримання статистичної інформації про відвідування.
/*********************************************/
/* Процедура реєстрації відвідувача інтернет-сторінки */
/*********************************************/
CREATE PROCEDURE PROC_COUNT_DATA
(PROJID INTEGER,
URLFROM VARCHAR(1024),
URLCURR VARCHAR(1024),
IPUSER VARCHAR(15),
BROWSER VARCHAR(255),
SYSTEMUSER VARCHAR(255),
SYSTEMVER VARCHAR(255),
COMPNAME VARCHAR(255)
)
RETURNS (
MINDATE DATE, /* Дата встановлення лічильника */
NUMBER_ZAGRUZK INTEGER, /* Кількість завантажень */
NUMBER_UN_ZAGRUZK INTEGER, /* Кількість унікальних завантажень */
NUMBER_ZAGR_DATE INTEGER, /* Кількість завантажень сьогодні */
NUMBER_ZAGR_UN_DATE INTEGER) /* Кількість унікальних завантажень */
AS
BEGIN
INSERT INTO COUNTDATA (PROJID, URLFROM, URLCURR, IPUSER,
BROWSER, SYSTEMUSER, SYSTEMVER, COMPNAME)
VALUES (:PROJID, :URLFROM, :URLCURR, :IPUSER,
:BROWSER, :SYSTEMUSER, :SYSTEMVER, :COMPNAME);
/* Час встановлення лічильника */
SELECT MIN(DATEHINT)
FROM COUNTDATA
INTO :MINDATE;
IF (MINDATE IS NULL) THEN MINDATE="TODAY";
/* Кількість завантажень */
SELECT COUNT(*)
FROM COUNTDATA
INTO :NUMBER_ZAGRUZK;
/* Кількість унікальних завантажень */
SELECT COUNT(*)
FROM IPTABLE
INTO :NUMBER_UN_ZAGRUZK;
/* Кількість завантажень сьогодні */
SELECT COUNT(*)
FROM COUNTDATA
WHERE DATEHINT="TODAY"
INTO :NUMBER_ZAGR_DATE;
/* Кількість унікальних завантажень сьогодні */
SELECT COUNT(*)
FROM IPTABLE
WHERE DATEADD="TODAY"
INTO :NUMBER_ZAGR_UN_DATE;
SUSPEND;
END
^
Розшифруємо поля, що передаються процедурі:
PROJID – ID проекту (лічильника),
URLFROM – звідки прийшли,
URLCURR – куди прийшли,
IPUSER – IP-адреса користувача,
BROWSER - браузер,
SYSTEMUSER – операційна система користувача,
SYSTEMVER – версія операційної системи користувача,
COMPNAME – назва комп'ютера.
Процедура повертає статистичну інформацію:
MINDATE - дата встановлення лічильника,
NUMBER_ZAGRUZK INTEGER – загальна кількість завантажень,
NUMBER_UN_ZAGRUZK INTEGER – загальна кількість унікальних завантажень,
NUMBER_ZAGR_DATE INTEGER - кількість завантажень за сьогодні,
NUMBER_ZAGR_UN_DATE (INTEGER) - Кількість унікальних завантажень за сьогодні.
Отримання списку повторних відвідувачів
Збережена процедура для отримання списку повторних відвідувачів
/*****************************************/
/* Процедура для отримання повторних відвідувачів */
/*****************************************/
CREATE PROCEDURE POVTOR_POSETIT
(PROJID INTEGER,
DATEOT DATE,
DATEDO DATE
)
RETURNS (
IPUSER VARCHAR(15)
)
AS
BEGIN
FOR SELECT C.IPUSER
FROM COUNTDATA C
WHERE (C.DATEHINT>=:DATEOT)
AND(C.DATEHINT<=:DATEDO)
AND(C.PROJID>=:PROJID)
AND(C.IPUSER NOT IN (SELECT IT.IPUSER
FROM IPTABLE IT
WHERE (IT.DATEADD>=:DATEOT)
AND(IT.DATEADD<=:DATEDO)
AND(IT.PROJID=:PROJID)
))
GROUP BY C.IPUSER
INTO :IPUSER
DO
BEGIN
SUSPEND;
END
END
^
Процедурі ми передаємо діапазон, за який хочемо подивитися статистику, а вона повертає IP-адреси користувачів, які повторно відвідали наш сайт.
Статистика відвідувань днями
Зберігається процедура для розрахунку статистики відвідувань днями:
/*****************************************/
/* Статистика відвідувань днями */
/*****************************************/
CREATE PROCEDURE STAT_DAY
(PROJID INTEGER,
DATEOT DATE,
DATEDO DATE
)
RETURNS (
DATE_POSETIT DATE, /* Дата відвідування */
KOL_POSESCH INTEGER,/* Кількість відвідувань */
KOL_UNIKALN INTEGER, /* Кількість унікальних завантажень */
KOL_POVTORN_POSET INTEGER /* Кількість відвідувачів повторно */
)
AS
BEGIN
FOR SELECT DATEHINT
FROM COUNTDATA
WHERE (PROJID=:PROJID)
AND(DATEHINT>=:DATEOT)
AND(DATEHINT<=:DATEDO)
GROUP BY DATEHINT
INTO :DATE_POSETIT
DO
BEGIN
/* Кількість завантажень */
SELECT COUNT(*)
FROM COUNTDATA
WHERE DATEHINT=:DATE_POSETIT
INTO :KOL_POSESCH;
/* Кількість унікальних завантажень */
SELECT COUNT(*)
FROM IPTABLE
WHERE DATEADD=:DATE_POSETIT
INTO :KOL_UNIKALN;
SELECT COUNT(*)
FROM POVTOR_POSETIT(:PROJID, :DATE_POSETIT, :DATE_POSETIT)
INTO KOL_POVTORN_POSET;
SUSPEND;
END
END
^
Найкращі посилання на сайт
Збережена процедура для отримання найкращих посилань на сайт
/**************************************/
/* Краще посилання на наш сайт */
/**************************************/
CREATE PROCEDURE BEST_LINK
(PROJID INTEGER,
DATEOT DATE,
DATEDO DATE
)
RETURNS (
URLFROM VARCHAR(1024),
COUNT_URLS INTEGER
)
AS
BEGIN
FOR SELECT URLFROM, COUNT(*) COUNT_URLS
FROM COUNTDATA
where (PROJID=:PROJID)
And(DATEHINT>=:DateOt)
And(DATEHINT<=:DateDo)
GROUP BY URLFROM
INTO :URLFROM, :COUNT_URLS
DO
BEGIN
SUSPEND;
END
END
^
Найкраща інтернет-сторінка
Збережена процедура для отримання статистики відвідуваності наших сторінок:
/*************************************/
/* Краща наша сторінка */
/*************************************/
CREATE PROCEDURE BEST_PAGE
(PROJID INTEGER,
DATEOT DATE,
DATEDO DATE
)
RETURNS (
URLCURR VARCHAR(1024),
COUNT_URLS INTEGER
)
AS
BEGIN
FOR SELECT URLCURR, COUNT(*) COUNT_URLS
FROM COUNTDATA
where (PROJID=:PROJID)
And(DATEHINT>=:DateOt)
And(DATEHINT<=:DateDo)
GROUP BY URLCURR
INTO :URLCURR, :COUNT_URLS
DO
BEGIN
SUSPEND;
END
END
^
На нашому сервері
(код на PHP)
Насамперед, необхідно налаштувати Apache на нашому сервері. Як його встановлювати та налаштовувати Ви можете у численних статтях Інтернету.
Скрипт для підключення до нашої бази даних InterBase, передачі інформації про користувача та отримання статистичної інформації.
acounter.php
<?php
/*include("config.php");*/
include "classdb.php3";
class acounter {
var $config = array();
var $conn;
var $dbname;
var $dbuser;
var $dbpass;
var $NUMBER_ZAGRUZK;
var $NUMBER_UN_ZAGRUZK;
var $NUMBER_ZAGR_DATE;
var $NUMBER_ZAGR_UN_DATE;
var $MINDATE;
var $okrugl;
function acounter () {
/*Підключення до БД*/
include "config.php";
$this->okrugl = $okrugl;
$this->dbname = $dbname;
$this->dbuser = $dbuser;
$this->dbpass = $dbpass;
$this->conn=ibase_connect($this->dbname,$this->dbuser,
$this->dbpass);
/* URL to the digitset */
$this->config['img'] = "http://MySite.com.ua/MyCounter/digits/";
/* URL to the animated digitset */
$this->config['animated_img'] = "http://MySite.com.ua/MyCounter/digits_ani/";
/* How many digits to show */
$this->config['pad'] = 6;
/* digit width and height */
$this->config['width'] = 16;
$this->config['height'] = 22;
/* timeout (minutes) */
$this->config['block_time'] = 15;
}
//Отримує кількість записів у таблиці CountData(кількість відвідувань)
function ibase_fetch_array($res) {
return get_object_vars(ibase_fetch_object($res));
}
function ibase_num_rows($query) {
$i=0;
while (ibase_fetch_row($query)){
$i++;}
return $i;
}
function GetCounterValue() {
$sqlExpr="select * from CountData";
$sth = ibase_query($this->conn,$sqlExpr);
$CounterValue=$this->ibase_num_rows($sth);
return $CounterValue;
}
//
function InsertData($ip='',$urlFrom='',$urlCurr='',$host='') {
//Beru vid brausera, versiu brauzera, platformu mashini;
$info=getenv("HTTP_USER_AGENT");
// $urlFrom=getenv("HTTP_REFERER");
$Gateway=getenv("GATEWAY_INTERFACE");
$Connect=getenv("SERVER_PROTOCOL");
//Beru ip-adres;
// $ip = getenv("REMOTE_ADDR");
$db = new CConnectionIBase();
$sqlExpr="SELECT * FROM PROC_COUNT_DATA(1, '".$urlFrom."'
, '".$urlCurr."', '".$ip."', '', '".$info."', '','".$host."')";
$sth = ibase_query($this->conn,$sqlExpr);
$mas=$this->ibase_fetch_array($sth);
$this->NUMBER_ZAGRUZK = $mas[NUMBER_ZAGRUZK];
$this->NUMBER_UN_ZAGRUZK = $mas[NUMBER_UN_ZAGRUZK];
$this->NUMBER_ZAGR_DATE = $mas[NUMBER_ZAGR_DATE];
$this->NUMBER_ZAGR_UN_DATE = $mas[NUMBER_ZAGR_UN_DATE];
$this->MINDATE = $mas[MINDATE];
}
function create_output($ip='',$urlFrom='',$urlCurr='',$host='') {
$this->InsertData($ip,$urlFrom,$urlCurr,$host);
//Vivogu Col. zagruzok
$html_output = "<table cellpadding=\"0\" cellspacing=
\"0\" border=\"0\"><tr>\n";
$html_output .="<font size='1' color='#0000FF'>
Всього завантажень:</font></tr>\n<tr align=\"center\">\n";
$html_output .= "<font size='3' color='#800080'>
<b>".sprintf($this->okrugl,$this->NUMBER_ZAGRUZK)."</b></font>";
$html_output .= "</tr></table>\n";
//Vivogu col. unikalnih zagruzok
$html_output .= "<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\"><tr>\n";
$html_output .="<font size='1' color='#0000FF'>
Усього унікальних завантажень: </font></tr>\n<tr align=\"center\">\n";
$html_output .= "<font size='3' color='#800080'>
<b>".sprintf($this->okrugl,$this->NUMBER_UN_ZAGRUZK).
"</b></font>";
$html_output .= "</tr></table>\n";
//Vivogu col. zagruzok segodnia
$html_output .= "<table cellpadding=\"0\"
cellspacing=\"0\" border=\"0\"><tr>\n";
$html_output .="<font size='1' color='#0000FF'>
Завантажень за день: </font></tr>\n<tr align=\"center\">\n";
$html_output .= "<font size='3' color='#800080'>
<b>".sprintf($this->okrugl,$this->NUMBER_ZAGR_DATE).
"</b></font>";
$html_output .= "</tr></table>\n";
//Vivogu col. unikalnih zagruzok segodnia
$html_output .= "<table cellpadding=\"0\"
cellspacing=\"0\" border=\"0\"><tr>\n";
$html_output .="<font size='1' color='#0000FF'>
Унікальних завантажень за день:</font></tr>\n
<tr align=\"center\">\n";
$html_output .= "<p align='center'><font size='3' color='#800080'><b>".sprintf($this->okrugl,$this
->NUMBER_ZAGR_UN_DATE)."</b></font></p>";
$html_output .= "</tr></table>\n";
//Vivogu datu ustanovki schetchika
$html_output .= "<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\"><tr>\n";
$html_output .="<font size='1' color='#0000FF'>
Дата встановлення лічильника: </font></tr>\n<tr align=\"center\">\n";
$str=substr($this->MINDATE,0,10);
$html_output .= "<font size='1' color='#800080'>".$str."</font>";
$html_output .= "</tr></table>\n";
return $html_output;
}
}
?>
classdb.php3
<?php
//-------------------------------------------------------------
class CConnection {
var $err_logon = "Can't connect to database %s!";
var $descriptor = 0; // database descriptor
var $result; // result array
var $countRow = 0; // number of records in result array
var $countField = 0; // number of fields in result array
// Clears result array. For internal use.
function freeQuery() {
unset($this->result);
$this->countRow = 0;
$this->countField = 0;
}
// Returns content of specified cell of result array or null if $col or
// $row is wrong.
// $col can to hold the field name or field index
function getData($col, $row) {
if ((0 <= $row) && ($row < $this->countRow)) {
if (!is_string($col)) {
reset($this->result);
for ($fno = 0; $fno < $col; $fno++) next($this->result);
$col = current($this->result);
return $col[$row];
} else return $this->result[strtoupper($col)][$row];
} else return null;
}
// Returns field name by field index or empty string if $col is wrong
function getFieldName($col) {
if (is_integer($col) && (0 <= $col) && ($col < $this->countField)) {
reset($this->result);
for ($fno = 0; $fno < $col; $fno++) next($this->result);
list($key, $val) = each($this->result);
return $key;
} else return "";
}
}
//----------------------------------------------------------------------
class CConnectionIBase extends CConnection {
// Constructor. Creates class.
function CConnectionIBase() {}
// Opens specified database.
// Returns database descriptor.
function open($database, $username = "sysdba",
$password = "masterkey", $charset="WIN1251") {
$this->close();
$this->descriptor = ibase_connect($database,
$username, $password, $charset);
return $this->descriptor;
}
// Closes current database connection
function close() {
if ($this->descriptor) {
$this->freeQuery();
ibase_close($this->descriptor);
$this->descriptor = 0;
}
}
// Prepares data to storing in BLOBs. Used in query & execute functions
// Returns query statement descriptor
function execCode($code, $blobs=0) {
$statement = 0;
$this->freeQuery();
if ($this->descriptor) {
$cmd = "$"."statement = ibase_query("."$".
"this->descriptor, "."$"."code";
if (is_array($blobs) && count($blobs)) {
reset($blobs);
$fno = 0;
while (list($key, $val) = each($blobs)) {
$finfo[$fno] = array("blob_id" =>
ibase_blob_create(), "blob_str" => "");
if (is_string($val)) ibase_blob_add($finfo[$fno]["blob_id"], $val);
else ibase_blob_add($finfo[$fno]["blob_id"],
"Not supported yet, sorry");
$finfo[$fno]["blob_str"] = ibase_blob_close($finfo[$fno]["blob_id"]);
$cmd = $cmd.", $"."finfo[$fno][\"blob_str\"]";
$fno++;
}
}
$cmd = $cmd.");";
eval($cmd);
}
return $statement;
}
// Executes SELECT statement and fills result array by dataset contents
// Returns number of records placed to result array
function query($code, $blobs=0) {
if ($statement = $this->execCode($code, $blobs)) {
while ($row = ibase_fetch_row($statement)) {
while(list($fno, $val) = each($row)) {
// Getting information about fields existing in current row
if ($this->countField < count($row)) $this->countField = count($row);
$finfo = ibase_field_info($statement, $fno);
$fname = $finfo["alias"];
$ftype = $finfo["type"];
unset($finfo);
if (!strcmp($ftype, "BLOB")) {
// Getting data from BLOB field
if (($finfo = ibase_blob_info($val)) &&
($finfo["length"] > 0) &&
($val = ibase_blob_open($val))) {
$blob = ibase_blob_get($val, $finfo["length"]);
ibase_blob_close($val);
} else $blob = "";
$this->result[$fname][$this->countRow] = $blob;
unset($blob);
} else {
// Getting data from another field
if (isset($val)) {
if (is_string($val))
$this->result[$fname][$this->countRow] = trim($val);
else $this->result[$fname][$this->countRow] = $val;
} else $this->result[$fname][$this->countRow] = "";
}
}
$this->countRow++;
// Cleaning temporary variables
unset($row);
unset($fno);
unset($val);
unset($finfo);
unset($fname);
unset($ftype);
}
ibase_free_result($statement);
unset($statement);
}
return $this->countRow;
}
// Executes INSERT, DELETE or UPDATE statements. Result array is empty.
// Returns nonzero if all OK
function execute($code, $blobs=0) {
if ($statement = $this->execCode($code, $blobs)) {
@ibase_free_result($statement);
return 1;
}
return 0;
}
// Commits current transaction
function commit() { ibase_commit(); }
// Rollbacks current transaction
function rollback() { ibase_rollback(); }
}
//------------------------------------------------------------------
class CConnectionOCI extends CConnection {
function CConnectionOCI() {}
function open($database = "", $username = "system",
$password = "manager") {
$this->close();
if (($database) && strlen($database))
$this->descriptor = OCILogon($username, $password, $database);
else $this->descriptor = OCILogon($username, $password);
return $this->descriptor;
}
function close() {
if ($this->descriptor) {
$this->freeQuery();
OCILogOff($this->descriptor);
$this->descriptor = 0;
}
}
function query($code) {
$this->freeQuery();
if ($this->descriptor) {
if ($code && ($statement = OCIParse($this->descriptor, $code))) {
OCIExecute($statement, OCI_DEFAULT);
$this->countRow = OCIFetchStatement($statement, $this->result);
$this->countField = count($this->result);
OCIFreeStatement($statement);
}
}
return $this->countRow;
}
function execute($code, $blob=0) {
$res = 0;
$this->freeQuery();
if ($this->descriptor) {
if ($code) {
if ($blob) $lob = OCINewDescriptor($this->descriptor, OCI_D_LOB);
if ($statement = OCIParse($this->descriptor, $code)) {
if ($blob) OCIBindByName($statement, ":blob", &$lob, -1,
OCI_B_CLOB);
OCIExecute($statement, OCI_DEFAULT);
if ($lob) {
if ($lob->save($blob)) $res = 1;
OCIFreeDescriptor($lob);
} else $res = 1;
OCIFreeStatement($statement);
}
}
}
return $res;
}
function commit() {
if ($this->descriptor) OCICommit($this->descriptor);
}
function rollback() {
if ($this->descriptor) OCIRollback($this->descriptor);
}
}
//----------------------------------------------------------------------
?>
Файл конфігурації лічильника:
config.php
<?
$dbname = "Server:C:\DataBase\Counter.GDB";
$dbuser = "SYSDBA";
$dbpass = "masterkey";
$okrugl = "%07s";
?>
$dbname – назва бази даних,
$dbuser-ім'я користувача InterBase,
$dbpass - пароль,
$okrugl – кількість цифр у лічильники (наприклад, 0000012).
Файл, який викликається з веб-сторінки:
test.php
<?php
include_once "acounter.php";
$ani_counter = new acounter();
echo $ani_counter->create_output($_GET["ip"],$_GET["urlFrom"]
,$_GET["urlCurr"],$_GET["host"]);
?>
На інтернет-сторінці (код на PHP)
Ця частина знаходиться на сервері провайдера (там, де знаходиться наша веб-сторінка).
Створюємо скрипт для визначення даних про користувача:
Counter.inc
<?php
// phpinfo();
//Beru vid brausera, versiu brauzera, platformu mashini;
$info=getenv("HTTP_USER_AGENT");
$urlFrom=getenv("HTTP_REFERER");
$urlCurr=$_SERVER["REQUEST_URI"];
$host=getenv("HTTP_HOST");
//Beru ip-adres;
$ip = getenv("REMOTE_ADDR");
readfile('http://client70.ukrtelebud.com.ua/
RudjukCounter/test.php?ip='.
$ip.'&urlFrom='.$urlFrom.'&urlCurr='.$urlCurr.'&host='.$host);
// readfile('http://MySite.com.ua/MyCounter/test.php?ip='
.$ip.'&urlFrom='.$urlFrom);
// readfile('http://MySite.com.ua/MyCounter/test.php')
?>
На самій інтернет-сторінці прописуємо скрипт, який і запускатиме весь лічильник:
<?php
include ("counter_inc.php")
?>
Примітка: Для того, щоб лічильник працював коректно, необхідно файли інтернет-сторінки називати з розширенням php, а не htm.
Клієнтська частина
Саму обробку статистичних даних найзручніше зробити на Delphi.
Реалізацію на Delphi я залишаю читачеві, наведу лише SQL-запити отримання необхідних даних.
SQL-запити
Отримання детальної інформації про відвідувачів:
select *
from COUNTDATA
where (PROJID=:PROJID)
And(DATEHINT>=:DateOt)
And(DATEHINT<=:DateDo)
ORDER BY COUNTDATAID
Статистика днями:
SELECT *
FROM STAT_DAY(:ProjID, :DateOt, :DateDo) ORDER BY DATE_POSETIT
Найкращі посилання на інтернет-сторінку:
SELECT *
FROM BEST_LINK(:ProjID, :DateOt, :DateDo)
ORDER BY COUNT_URLS DESC
Найкращі інтернет-сторінки:
SELECT *
FROM BEST_PAGE(:ProjID, :DateOt, :DateDo) ORDER BY COUNT_URLS DESC
Унікальні IP-адреси:
select *
from IPTable
where (ProjID=:ProjID)
And(DateAdd>=:DateOt)
And(DateAdd<=:DateDo)
IP-адреси повторних відвідувачів:
SELECT *
FROM POVTOR_POSETIT(:ProjID, :DateOt, :DateDo) ORDER BY IPUSER
Ось що вийшло
Отримання детальної інформації про відвідувачів:
Статистика днями:
Найкращі посилання:
Найкращі сторінки:
Унікальні IP-адреси:
Повторні IP-адреси:
Висновок
У програмі є ряд неточностей, а так само не визначаються країни щодо IP-адресою. Ці завдання я залишаю за читачами.
Завантажити текст Php-програм та SQL-скрипти Ви можете на http://old.rudjuk.kiev.ua/downloads/InetCounter/InetCounter.exe
Автори: Рудюк С.А
Лутай Д.А.

|