Биллинговая система NoDeny. Программирование



Информация для разработчиков



Программирование веб-админки NoDeny (в разработке...)


Основные служебные подпрограммы находятся в calls.pl. Обратите внимание, что некоторые подпрограммы используют глобальные переменные! Так очень часто используется глобальная переменная $dbh.


sql_select_line предназначена для выборки одной строки из таблицы БД.

Вход:

   0 - ссылка dbh
   1 - sql-запрос
   2 - [комментарий]
   3 - [скрытый запрос]

Обязательны только параметры 0 и 1. Комментарий будет выведен главному администратору в специальной области где отображаются все выполняющиеся sql-запросы. Если у администратора нет прав на просмотр sql-запросов либо он отключил их вывод, то комментарий игнорируется. Если комментарий выводится, то перед sql-запросом. Если параметр 3 установлен, то вместо реального sql-запроса выводится этот (3й) параметр. Предназначено для скрытия запросов, в которых участвуют пароли. Если комментарий равен 0 (символ `ноль`), то все данные по запросу будут выведены мелким шрифтом в одну строку.


Возврат:

0 - ссылка fetchrow_hashref или false, если ошибка либо пустая выборка

Пример:

$p=&sql_select_line($dbh,"SELECT unix_timestamp()",'Получим время на сервере БД');
&Error("Не удалось получить время из БД!") unless $p;
$t=$p->{'unix_timestamp()'};

Либо:

$p=&sql_select_line($dbh,"SELECT passwd FROM xxx WHERE id=5",0,'Получим пароль, запрос не показываем');
$passwd=$p? $p->{passwd} : '12345';

Обратите внимание, что sql_select_line предназначен для выборки только одной строки. Для выбора нескольких строк используйте:

sql

Вход: тоже, что и у sql_select_line

Выход: ссылка на ->execute или false, если ошибка


Пример:

$sth=&sql($dbh,"SELECT * FROM users",'Получим список всех клиентов');
while ($p=$sth->fetchrow_hashref)
  {
   $OUT.="ip: $p->{ip}<br>";
  }




sql_do предназначена для выполнения запросов обновления (INSERT, UPDATE, DELETE).

Вход: тоже, что и у sql_select_line.

Выход: количество обновленных строк либо ноль, если ошибка.

Обратите внимание, что количество обновленных строк может быть равно нулю, но это не будет означать ошибку, т.е. условию будет соответствовать 0 строк. Эта ситуация разруливается стандартным методом (придумано не в NoDeny):

если ошибки нет и обновлено 0 строк, то возвращается значение, которое НЕ является нулем, однако при сравнении РАВНО нулю. Возможно, это выглядит как хак, однако это вполне неормально для perl.

Пример:

$rows=&sql_do($dbh,"UPDATE users SET balance=balance-1 WHERE id=1 LIMIT 1");
&Error('Баланс не обновлен, проблема с БД.') unless $rows;
&Error('Баланс не обновлен - клиент с id=1 не найден в БД!') if $rows<1;
&OkMess('Баланс обновлен. Все ок');

Комментарии:

Хотя поле id таблицы users является уникальным, мы использовали LIMIT 1. Это является стилем автора, который вполне логично обосновывается: операции обновления/удаления являются относительно опасными, поскольку ошибись программист и не укажи условие или укажи его неправильно - есть риск обновить/удалить всю таблицу. В данном случае, при ошибке мы получим обновление только одной строки.

Условие unless $rows выполняется, когда $rows будет = 0. Когда обновлено 0 строк, в $rows содержится значение не 0, поэтому это условие не будет срабатывать. С другой стороны, при стравнении с единицей $rows будет являться нулем. Т.е. будет выполнено условие $rows<1.



Подпрограммы-фильтры.
Фильтры предназначены для отсеивания или замены специальных символов в передаваемых переменных для того чтобы исключить вредное либо непрогнозируемое действие этих спецсимволов.

С NoDeny существует 2 вида фильтров: для mysql и для web.


Для web:

Filtr_out фильтрует символы, которые являются управляющими для html.

Применять всегда, когда необходимо вывести какие-либо данные в html-страницу клиента.

Пример:

$p=&sql_select_line($dbh,"SELECT fio FROM user WHERE id=5");
&Error('Ошибка получения данных клиента') unless $p;
$OUT.='Фамилия клиента: '.&Filtr_out($p->{fio});

Если не произвести фильтрацию, то после того, как любопытный диспетчер даст клиенту имя «<h1>Иванов</h1>», мы получим вывод его имени большими буквами. Это простейший пример, а можно еще и javascript ввести...