Информация о нас Разработанные нами программы Наши интернет-разработки Фотогалерея наших работ Документация к программам, наши статьи, а так же перезентации наших программ

Вышла новая версия программы склад.


 Исправлено большое количество ошибок.


 Возмоность отключения запрета отрицательных чистел в текущих остатках.


Наши координаты

Эл. почта
rudjuk@ukr.net
rs@corp2.net

Телефон: +38 (067) 901-63-22

Skype: rudjuk

 

Вызов форума

Динамическая интернет-страничка

 


 

Другие ссылки


Другие страницы

Программы
Корпорация

Склад
Корпорация
Бухгалтерия
Зарплата


Программы
Экзамен
Расчёт шкафов
Репликатор
Редактор
VDoc
Календарь
Калькулятор
Буфер
Рассылка почты
Голосование по сети
Инсталлятор
Планировщик
Администратор портала
R-броузер

Документация
Ответы на вопросы
Вся документация
Склад
Расчёт шкафов
Экзамен
Репликатор
Инсталлятор

Докумнтация склада
Установка программы

Введение
Ввод остатков
Заказ (покупка)
Заявка
Внешняя счёт-фактура
Приход товара на склад
Расход товара со склада
Налоговая накладная
Внутреннее перемещение
Списание товара
Возврат товара
Заказ на закупку
Реализация и консигнация
Отсрочка платежа
Резервирование товаров
Счёт-фактура без рез.
Копирование документов
Журналы документов
Платёжные документы
Заборный лист
Карточка продукции
Калькуляция
Отбраковка товаров
Переоценка товаров
Бронирование услуг
Аннулирование услуг
Счёт
Журналы документов


Справочник фирм
Справочник активов
Технологические карты
Прайс-листы
Единицы измерения
Нормы расхода
Месторасположение товара
План счетов
Сервисные центры
Сотрудники
Курсы валют
Системные справочники
Фразы

Текущие остатки
Отчёт по внутреннему перемещению
Отчёт по продажам
Взаиморасчёты
Движение материалов

Поиск информации
Штрих-коды, шифры, партии

Объединение фирм
Объединение товаров
Работа в сети и интернет
Определение прав
Создание и настройка пользователя
Скрипт настройки пользователя
Настройка фирмы
Настройка складов
Настройка языков
Типы документов
Настройка меню
Версии программ и история
Проверка расчётов
Создание и изменение отчётов
Создание тени (зеркала) базы данных
Восстановление базы данных
Резервное копирование базы данных

Информация о программе
Работа с окнами
Работа с таблицами
Экспорт данных в таблицах
Импорт данных в таблицах
Работа с деревьями
Экспорт из дизайнера отчётов
Описание дизайнера отчётов FastReport

Статьи
Счётчик
Как сэкономить на лицензиях
Восстановление баз данных Interbase

Услуги
Веб-дизайн
Покупка программ

Другое
Фотогалерея


 

 


Вышла новая версиия программы "Корпорация" (ROffice).

 

 

Просмотреть все новости

 

 

 

 

 








Корпоративный интернет-счётчик

 

Аннотация

 

В данной статье рассказывается как создать интернет-счётчик для корпоративного портала.

 

Задача

Счётчик должен вести подробную информацию о посетителях: адрес откуда пришёл посетитель, адрес страницы, 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-адреса:

Повторные IP-адреса

 

Заключение

В программе есть ряд неточностей, а так же не определяются страны по IP-адресу. Эти задачи я оставляю за читателями.

Скачать текст Php-программ и SQL-скрипты Вы можете на http://old.rudjuk.kiev.ua/downloads/InetCounter/InetCounter.exe

 

Авторы: Рудюк С.А
Лутай Д.А.