Геометрические задачи на плоскости................ 5 Все, что хотел узнать о плагинах................. 11 «И вот они столкнулись…»......................... 26 CodeIgniter: Обзор фреймворка для PHP............ 49 Ох уж эти спамеры................................ 64 Первое впечатление об IT-шнике................... 66 Советы начинающим sys. админам и не только....... 68 Знакомимся с Jabber.............................. 72 Учимся делать иконки............................. 76 Поднимаем интернет-шлюз.......................... 87
ИНТРО Идея: Фленов Михаил
Почти три месяца прошло с момента выхода последнего номера нашего журнала. Некоторым опять показалось, что мы «заглохли» и легли на дно, но в реале мы хоть и медленно, но работали и вот результат нашего труда. Сразу хочется поблагодарить всех тех людей, которые выделели время и специально для нашего журнала написали статьи. Если такие авторы будут появляться каждый месяц, то с уверенностью могу сказать, что журнал будет выходить намного чаще J. Не могу также сказать об одной особенности этого номера. В этом номере целых две статьи, которые написаны по заказу наших читателей. Ты тоже можешь попытаться «заказать» статью. Пришли мне на мыло желаемую тему и если у нас будет возможность, то мы обязательно подготовим по ней материал.
Редактор номера: Антонов Игорь (antonov.igor@live.ru) Графика в журнале: Васючков Андрей aka Soffrick (soffrick@mail.ru) Текущий состав VR-Team: Horrific, Neon_Kaligula, LittleBudda, Soffrick, Egoiste, FrIToOll, Lord_of_fear, Vatanaba, Spider_NET Вопросы и предложения по журналу: antonov.igor@live.ru
Все, больше не буду ничего писать, а просто пожелаю тебе приятного чтения! P.S. Как обычно, мне очень интересно твое мнение касательного нашего журнала. Поэтому все твои комментарии я жду к себе на почту – antonov.igor@live.ru. P.S.1. Мы еще продолжаем раздавать мыльники в нашем домене. Если ты давно мечтал о красивом мыльнике, то пиши мне на почту и я с радостью сделаю для тебя аккаунт. Также напомню. Теперь наша почта располагается на гугле, а значит, получив наше мыло, ты получаешь весь качественный сервис и фишки от gMail. Торопись! Количество ящиков ограничено!
Геометрические задачи на плоскости В свете проходящей Всероссийской олимпиады по информатике решился написать эту статью по методам решения некоторых геометрических задач. Задачи по геометрии, как водится, вызывают повышенную сложность (особенно для тех, кто в школе прогуливал геометрию – прим. редактора). Связано это с их спецификой: вместо конкретного расположения «в тетрадке» разношерстых линий нам дают их координаты. Часто – декартовые (что, кстати, положительный момент). Частные положения обычно неприменимы к фигурам. Например, дан треугольник и надо найти его площадь. Пока будем определять, равнобедренный он или прямоугольный, мы затратим много строк кода и времени. Решение это может работать быстрее общего, но писать его – дольше. Поэтому необходимо знать формулы нахождения площади для всех треугольников.
теоремы, но на практике – полный ноль. Надо знать частные его интерпретации.
Задачи в пространстве даются на олимпиадах крайне редко из-за того, что их часто очень сложно решать, особенно школьникам. Ограничимся только плоскостными.
Часто нам известны координаты какойлибо точки и угловой коэффициент прямой (довольно часто). И надо «сделать» уравнение этой прямой. Для его изготовления есть такая формула: , где и – координаты точки, а – угловой коэффициент.
Расстояние между двумя точками Если декартовой расстоянием
и системе
– две точки в координат, то будет .
. Ее проекцию на ось Проведем прямую абсцисс обзовем OP, на ось ординат – KL. С легкостью можно заметить, что проекции эти вкупе с прямой образуют прямоугольный треугольник, а - его гипотенуза. , Теперь еще проще догадаться, что формула 1 справедлива. Уравнения прямых линий на плоскости Общее
уравнение прямой линии – . Понятно, что такое общее уравнение крайне неудобно в плане его использования. На нем хорошо отрабатывать
Наиболее
известное в этом плане: . Его очень плодотворно учат в школе. Не надо разъяснять, что , α – уголь между прямой и осью абсцисс; b – ордината точки пересечения прямой с осью ординат (OY).
Еще чаще известны координаты двух точек, через которые требуется провести прямую линию. Для этого случая существует формула: . Можно заприметить, что здесь, в отличии от предыдущей формулы, угловой коэффициент k заменен на выражение . «Иксы» и «игреки» с индексами – координаты точек соответственно. Еще есть хитрое уравнение
. «В
отрезках» его фамилия. Тут a – абсцисса точки пересечения прямой с осью абсцисс, а b – ордината с осью ординат. Уравнение этой прямой не может быть записано в приведенной форме, если прямая проходит через начало координат или параллельна одной из координатных осей.
Получили мегасистему двух уравнений Пред-предпоследнее и предпоследнее уравнения не могут быть записаны в их приведенной форме, если прямые, соответствующие им, перпендикулярны оси абсцисс. Для такого случая есть более простое уравнение: . Для прямых, перпендикулярных оси ординат, более простым будет . Угол между двумя прямыми Угол между двумя прямыми равен разности угла второй прямой, повернутой относительно первой, и первой. Углом между двумя прямыми будет наименьший угол. Для уравнений прямых линий нужны угловые коэффициенты. Для них имеется такая формула: , где – угловой коэффициент между двумя прямыми; β и α – углы второй и первой прямой соответственно. и на Раскрыв правую часть и заменив и
, получим, что
.
, причем
(прямые
не параллельны). Такая система и будет служить способом нахождения координат точки пересечения в уравнениях такого типа. Для других – аналогично. Расстояние от точки до прямой Разделив обе части общее уравнения прямой ( ) на , получим нормированное уравнение, которого равен свободный член расстоянию от начала координат до прямой. Чтобы определить расстояние от точки до прямой, надо в ее нормированное уравнение подставить координаты этой точки и взять абсолютное значения результата. По какую сторону от прямой лежит точка?
Кстати, если прямые параллельны, то их угловые коэффициенты равны. Если перпендикулярны, то – обратны по величине и противоположны по знаку.
Пусть даны координаты двух точек прямой: . И еще одной точки .
Точка пересечения двух прямых
Способ номер раз
Для нахождения координат точки пересечения двух прямых надо решить систему уравнений с их участием. Например,
даны нам два уравнения: и . Ну, то есть два общих уравнения прямых. Решим их систему:
Уравнение
прямой
линии будет Как уже
знаем, у параллельных прямых равны их угловые коэффициенты. Следовательно, уравнение прямой, проходящей через точку C параллельно первой имеет такой вид
Делаем вывод: точка C будет лежать слева от прямой AB, если свободный член 2 уравнения больше свободного члена первого; справа – если меньше; на прямой – если равны.
Но
не может быть равно нулю! Когда ? Тогда, когда прямая AB перпендикулярна оси абсцисс. В связи с этим будем действовать следующим образом: если , то просто проверяем, как расположена точка относительно прямой . Свободный член первого уравнения равен , второго – .
Пусть
, очевидно
.
Способ номер два
Пусть имеем два вектора .
Их
произведением
и будет
. Из формулы произведения видим, что когда второй вектор левее первого – произведение их будет больше нуля; когда правее – меньше. Выразим координаты векторов через точки: ,
.
Если , то точка C лежит левее прямой AB; если равно 0 – на прямой; иначе – справа. Отмечу отдельно, что второй способ в реализации легче и работает быстрее. Как найти площадь треугольника? Способ номер раз
Площадь треугольника находится по формуле , где Герона: , а a, b, c – величины сторон треугольника. Способ номер два
Пусть , , - вершины треугольника. Пусть ,а , а углы, образованные этими сторонами, равны α и β. Тогда проекции c и b на оси координат будут следующие:
Получили формулу площади треугольника. Замечу: если все три точки лежат на одной прямой, то формула будет генерировать ноль. Модуль в выражении нарисован неспроста. Иной раз площадь получается отрицательной (площадь треугольника же должна быть строго положительна). Положение точки относительно треугольника Способ номер раз
Алгоритм прост: если точка лежит в треугольнике, то она левее или правее всех его сторон (правее, если обходим по часовой стрелке, левее – иначе). Способ номер два
Если точка внутри треугольника, то сумма площадей треугольников, на которые точка разбивает его, равна его собственной. Первый способ работает быстрее. Геометрические задачи на плоскости Коротко – о главном. В первой части статьи было дана общая теория, необходимая для решения задач. Теперь посмотрим, что мы сможем сделать, применяя ее.
Пара окружностей Задача. Даны две окружности ( ). Пересекаются ли они? Решение. Нам известны координаты центров окружностей и их радиусы. Понятно, что расстояние r между центрами будет
Другая пара окружностей Задача. Даны координаты центров двух окружностей и радиус. Радиусы обеих окружностей равны. Они образуют фигуру. Чему равна площадь этой фигуры?
Окружности пересекаются, если существует ∆
После первого просмотра задачи сразу обрисовывается алгоритм: окружности тогда и только тогда пересекаются, когда сумма их радиусов не больше расстояния их центров. Это – неправильно. Нам даны не круги, а окружности. При ином расположении (например, вторая окружность находится в первой и не касается ее краев) мы обнаружим пересечения, каких нет. Можно заметить, что при пересечении окружностей в двух точках (как на рисунке) мы свободно можем построить треугольник из двух радиусов и r – расстояния между окружностями. Когда окружности будут касаться в единственной точке, то треугольник получится вырожденным (сумма двух сторон не меньше третьей). Значит, окружности пересекаются при следовании этим условиям:
Решение. Рассмотрим случаи расположения окружностей и зависящую от этого площадь фигуры, образованной ими. • Если окружности не пересекаются или пересекаются в одной точке, то площадь фигуры будет равна сумме их площадей (удвоенной площади одной окружности). • Если их центры совпадают, то площадь фигуры – площадь одной окружности.
. Код решения на Pascal: var x1, y1, r1, x2, y2, r2, d: real; begin //координаты расположены в файле. assign(input, 'input.txt'); reset(input); assign(output, 'output.txt'); rewrite(output); readln(x1, y1, r1); readln(x2, y2, r2); d := sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); if (r1 + r2 >= d) and (r1 + d >= r2) and (r2 + d >= r1) then write('YES') //пересекаются else write('NO'); //не пересекаются end.
• Если окружности пересекаются в двух точках, то площадь фигуры – удвоенная площадь одной окружности минус площадь общей части. Площадь окружности вычисляется по формуле: . Наибольшую сложность вызывает вторая подзадача, когда окружности пересекаются. Посмотрим на рисунок справа. Он, как Окружности пересекаются в двух точках. легко можно догадаться, иллюстрирует вторую подзадачу.
Здесь O и O` - центры окружностей, точка P – середина отрезка OO`. Отрезок, соединяющий точки пересечения перпендикулярен OO`.
окружностей
Получили прямоугольный треугольник <точка пересечения окружностей>PO. Измерить площадь совместной части можно по формуле: . Но вот незадача: угол
α нам-то неизвестен! Найти его можно из прямоугольного треугольника <т. п. о.>PO.
После нахождения угла нетрудно найти площадь общей части окружностей.
Площадь фигуры, очевидно, будет
Код решения на Pascal: uses math; var x1, y1, x2, y2, p, r, alpha, s_fig: real; begin assign(input, 'input.txt'); reset(input); assign(output, 'output.txt'); rewrite(output); readln(x1, y1); readln(x2, y2); readln(r); s_fig := 2 * pi * r * r; p := sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); if (r + r > p) and (r + p > r) then begin //пересекаются в двух точка alpha:= arccos((p * p)/(2 * r * r)- 1); s_fig := s_fig - r * r * (alphasin(alpha)); end
else if abs(p) < 0.0000001 then //"сливаются" s_fig := s_fig * 0.5; write(s_fig:0:2); end.
Треугольник и точка Задача. На плоскости заданы координаты трех точек – вершины треугольника и еще одной. Надо определить, где расположена точка относительно треугольника: внутри или снаружи? Решение. Алгоритм решения этой задачи мы уже рассматривали. Выберем второй способ, потому что неизвестно как расположены координаты (по часовой стрелке, против часовой стрелки или произвольно). Код решения на Pascal: function s_tr(x1, y1, x2, y2, x3, y3: real): real; begin result := 0.5 * abs((y3 - y1) * (x2 x1) - (x3 - x1) * (y2 - y1)); end; var x1, y1, x2, y2, x3, y3, x, y, s_all, s1, s2, s3: real; begin assign(input, 'input.txt'); reset(input); assign(output, 'output.txt'); rewrite(output); readln(x1, y1); readln(x2, y2); readln(x3, y3); readln(x, y); s1 := s2 := s3 := s_all
s_tr(x1, y1, x2, y2, x, s_tr(x2, y2, x3, y3, x, s_tr(x3, y3, x1, y1, x, := s_tr(x1, y1, x2, y2,
y); y); y); x3, y3);
if abs(s_all - s1 - s2 - s3) < 0.0000001 then write('In') else write('Out'); end.
Лучи Задача. Нарисовали N точек. Точки – в декартовой системе координат. Хотят
узнать, какое минимальное количество лучей нужно провести из начала координат, чтобы вычеркнуть ими все точки. Координаты точки не могут быть одновременно равны нулю. Решение. Если разобраться, то задача окажется очень простой. Луч имеет уравнение . - координаты любой точки. Подставляя вместо x и y другие точки будет определять, находятся ли они на этой прямой. Чтобы проверить, являются ли они точками луча, этого явно недостаточно, т. к. луч проходить только через одну квадранту системы координат, а не через две. Дополнительное условие: , где ! – логическое НЕ; xor – исключающее ИЛИ. Код решения на Pascal: var n, i, j, k: integer; m: array of array [0..1] of integer; procedure null(i: integer); begin m[i][0] := 0; m[i][1] := 0; end;
assign(output, 'output.txt'); rewrite(output); readln(n); setlength(m, n); for i := 0 to n - 1 do readln(m[i][0], m[i][1]); k := 0; for i := 0 to n - 1 do begin if (m[i][0] = 0) and (m[i][1] = 0) then continue; for j := i + 1 to n - 1 do if (m[i][0] * (m[j][1] - m[i][1]) = m[i][1] * (m[j][0] - m[i][0])) and ((not (m[i][0] > 0) xor (m[j][0] > 0)) and (not (m[i][1] > 0) xor (m[j][1] > 0))) then null(j); null(i); k := k + 1; end; write(k); end.
Итого Пожалуй, цели статьи я уже достиг – рассказал тебе основные идеи решения геометрических задач. Смекалка и логика – вот твои верные союзники в царстве геометрии. Действуй!
begin assign(input, 'input.txt'); reset(input);
Исходники к статье ищи в папке «Геометрические задачи на плоскости»
Written by Сергей Чередниченко aka CLS E-mail: sergey.c@hotmail.com
Все, что хотел узнать о плагинах Сегодня я наконец-то собрался с мыслями, силами, сигаретами и т.д. и решил написать статью под гордым названием «ВСЕ, ЧТО ТЫ ХОТЕЛ УЗНАТЬ О ПЛАГИНАХ». Итак, начнем с постановки задачи. Задача: разработать приложение, позволяющее динамически подгружать plugIns, написанных на с++ builder и Delphi. Время действовать
3 – не передавать в/из dll динамический массив 4 – не передавать в/из dll указатель на динамический массив
Что имеем: • •
CodeGear RAD Studio 2007 Enterprise С++ builder 6
Создаем новый проект и сохраняем его. Перед тем как приступить к кодингу, надо кое о чем условиться. 1 – не передавать в/из dll класс 2 – не передавать в/из dll указатель на класс
Почему? Давайте разберем на примере. Я передал в библиотеку переменную типа string, да, dll написанная на Delphi с парой модулей поймет что это такое и знает как с ней работать, а вот с++ builder нет…там нет такого типа…и как быть? Как обеспечить взаимосвязь? Только таким вот способом, и кстати во всеми любимом MSDN черным по белому написано как и что можно передавать в dll.
Рисунок 1 (Типичная форма) Обычная форма, все стандартно. Проект обозвал DynamicLoader, но это ваше мнение, как хотите так и обзывайте. Итак, куда будем отображать плагины?
Предлагаю слева строить что-то типа дерева, вверху вывести toolbar с кнопочками (рис. 2).
Рисунок 2 (Прикрутил ToolBar и TreeView) Слева обычный TTreeView вверху обычный ToolBar.Думаю понадобится нам ActionList, мало ли еще и MainMenu. Создадим один
Action по которому будет происходить выход из программы (рис. 3).
Рисунок 3 (Лямаем меню) Теперь самое вкусное. Добавим к проекту простой и пустой unit и назовем его Interfaces. Этот модуль, мы будем использовать для описания интерфейса.
Итак, половина призадумалась, что такое INTERFACE(IUNKNOWN). Поднимем хелп и почитаем. У кого проблемы с чтением хелпа, расскажу простыми словами J.
В самом общем случае это некий указатель на область памяти, где будут лежать наши методы. Представляет собой PACKED RECORD. В с++ есть такое понятие как множественная наследуемость, в Delphi же такого нет, но наш ответ Чемберлену – интерфейсы, думаю даже намного изящней решение, нежели множественная наследуемость, и к тому же с++ очень
перегруженный язык, и всем функционал никто не пользуется, как собственно и в Delphi. Создадим интерфейс и назовем его IinitPlg. Каждый интерфейс идентифицируется GUID, сгенерировать который можно нажав, «CTRL+SHIFT+G». В результате всех действий получается вот такая картинка:
unit Interfaces; interface uses sysutils; type IinitPlg = interface(IUnknown) ['{8BAA7621-D0D7-4D36-B693-9B5298BA0162}'] end; implementation end.
Я говорили, что в интерфейсе буду определены некоторые методы, поэтому самое время, их определить: function CreateMainNode (AName : pchar) : integer;stdcall;
Эта функция будет создать нам NODE в нашем TreеView и возвращать его номер. procedure AddPlgUnderMainNode (NumMainNode : integer;AName : pchar;AProcName : pchar);stdcall;
Процедура добавляет подуровень к узлу, номер которого передается в первом параметре. procedure AddPluginOnToolBar(AName : pchar;AProcName : pchar);stdcall;
На эту процедуру будет возложена миссия по созданию кнопочки на ToolBar. procedure AddNewPage(AName : pchar;var PageH : HWND);stdcall;
Наше приложение будет многодокументным. Пока просто опиши этот метод, а чуть позже мы вернемся к этому разговору.
После описания методов текст твоего модуля должен стать примерно таким:
unit Interfaces; interface uses sysutils,windows; type IinitPlg = interface(IUnknown) ['{8BAA7621-D0D7-4D36-B693-9B5298BA0162}']
function CreateMainNode (AName:pchar):integer;stdcall; procedure AddPlgUnderMainNode (NumMainNode:integer; AName: pchar; AProcName:pchar);stdcall; procedure AddPluginOnToolBar(AName:pchar;AProcName:pchar);stdcall; procedure AddNewPage(AName:pchar; var PageH:HWND); stdcall; end; implementation end.
Почему в конце этих методов стоит stdcall? Есть в природе некоторые соглашения о вызовах, в частности sdcall, cdecl, pascal и т.д. Они определяют что-то вроде загрузки в стэк. Если посмотреть, например юнит Forms, там тоже объявлено куча интерфейсов и везде в конце стоит sdtcall,
да, можно и не ставить, ошибки не будет, ну думаю, сделаем по образу и подобию. Приступаем к реализации нашего интерфейса. Вернемся в нашу головную форму и сразу после описания класса формы, после запятой добавим название нашего интерфейса.
type TDynamicLoader = class(TForm,IinitPlg)
В секциях private public добавьте protected и скопируйте все методы из модуля интерфейсов и перенесите в раздел protected. Для чего так сделано? Собственно
для повышения защищенности, да и смысла хранить, их в другом разделе нет, обращения будут происходить через интерфейс, и для наглядности. Вот мой код
private {наши глобальные переменные} FPluginList : TStrings; FIinitPlg : IinitPlg; protected {здесь лежат методы интерфейсов} function CreateMainNode (AName : pchar) : integer;stdcall; procedure AddPlgUnderMainNode (NumMainNode : integer;AName : pchar;AProcName : pchar); stdcall; procedure AddPluginOnToolBar(AName : pchar;AProcName : pchar); stdcall; procedure AddNewPage(AName : pchar; var PageH : HWND);stdcall; public end;
Сразу в классе объявите пару глобальных переменных, они нам вскоре пригодятся. Теперь встанем на раздел protected, на любой метод и нажмем «CTRL+SHIFT+C»,
Delphi автоматом создаст заготовки для методов. Опишем их. Вначале на событие создания формы напишите следующий код:
FPluginList := TStringList.Create;
В этом листике будем хранить наши загруженные библиотеки, точнее адреса. Итак, функция CreateMainNode: function TDynamicLoader.CreateMainNode(AName: pchar): integer; var Node : TTreeNode; i : integer;
begin Result := -1; MainPlgList.FullCollapse; for I := 0 to MainPlgList.Items.Count - 1 do begin if ANSIUPPERCASE(MainPlgList.TopItem.Text) = ANSIUPPERCASE(AName) then begin Result := i; exit; end; end; Node := TTreeNode.Create(MainPlgList.Items); Node.HasChildren := true; Node.ImageIndex := 0; MainPlgList.Items.AddFirst(Node,AName); Result := Node.AbsoluteIndex; end;
Проверяем имя, если такой узел уже есть, то отдаем его индекс, иначе создаем новый и
возвращаем его индекс. Процедура AddPlgUnderMainNode у меня выглядит так:
procedure TDynamicLoader.AddPlgUnderMainNode(NumMainNode: integer; AName,AProcName: pchar); var Node : TTreeNode; i : integer; begin MainPlgList.FullCollapse; for I := 0 to MainPlgList.Items.Count - 1 do begin if ((MainPlgList.Items.Item[i].IsFirstNode) and (MainPlgList.Items.Item[i].Index = NumMainNode)) then begin Node := TTreeNode.Create(MainPlgList.Items); Node := MainPlgList.Items.AddChildFirst(MainPlgList.Items.Item[i],AName); Node.ImageIndex := 1; Node.Data := AProcName; end; end; end;
Все как всегда, нашли узелок, добавили в него дочерний узел, самое интересное, что в данные узла записали имя процедуры,
которую нам любезно даст плагин. Теперь рассмотрим код метода AddPluginOnToolBar:
procedure TDynamicLoader.AddPluginOnToolBar(AName, AProcName: pchar); var tb : TToolButton; i : integer; begin tb := TToolButton.Create(MainPlgToolBar); tb.Caption := Aname; for I := 0 to FPluginList.Count - 1 do begin if GetProcAddress(Cardinal(FPluginList.Objects[i]),AProcName) <> nil then begin @tb.OnClick := GetProcAddress(Cardinal(FPluginList.Objects[i]),AProcName); tb.Style := tbsTextButton; tb.Parent := MainPlgToolBar; break; end;
end; end;
Пояснять тут собственно и нечего - создаем кнопочку, кладем её на тулбар, на клик её даем ей адрес плагина и имя процедуры,
которую даст нам плагин. И наконец, мы подошли к рассмотрению кода последнего метода:
procedure TDynamicLoader.AddNewPage(AName: pchar; var PageH: HWND); var i : integer; Page : TTabSheet; begin for I := 0 to MainPages.PageCount - 1 do begin if ANSIUPPERCASE(MainPages.Pages[i].Caption) = AnsiUpperCAse(AName) then begin PageH := MainPages.Pages[i].Handle; exit; end; end; Page := TTabSheet.Create(MainPages); Page.Caption := AName; Page.PageControl := MainPages; {отдаем хэндл} PageH := Page.Handle; end;
В этом методе создаем страничку, возвращаем рукоять на неё. Заголовок страницы получаем из плагина. Итак, теперь
соглашения о процедурах в DLL. Собственно у каждого они могут быть свои, я для примера сделал такие:
{это и есть наши правила для плагинов Delphi} TLoadDelphiDll = procedure(AIinitPlg : IinitPlg);stdcall; //Загрузка TUnLoadDelphiDll = procedure();stdcall; //Выгрузка
При загрузке на вход даем интерфейс. При выгрузке, просто вызываем этот метод плагина, а что там, в плагине будет происходить – не наше дело. Так, теперь необходимо загрузить плагины. Я создал
новый Action с hotkey F11 и написал следующий код, загружающий плагины, то есть библиотеки, которые лежат рядом с файлом EXE.
procedure TDynamicLoader.aLoadExecute(Sender: TObject); var sr : TSearchRec; FCall : cardinal; LoadDll : TLoadDelphiDll; Begin GetInterface(IinitPlg,FIinitPlg); //Получаем ссылку на наш интерфейс FPluginList.Clear; MainPlgList.Items.Clear; if FindFirst(ExtractFileDir(Application.ExeName)+'\*.dll',faAnyFile,sr) = 0 then repeat if ANSIUPPERCASE(ExtractFileExt(sr.Name)) = '.DLL' then begin FCall := LoadLibrary(pchar(sr.Name)); {обязательно проверимся на наличие этой процедуры в библиотеке} if GetProcAddress(Fcall,'InitPlugin') <> nil then begin {сохранимся в листик, чтобы потом обратится к dll}
FPluginList.AddObject(sr.Name,TObject(FCall)); try @LoadDll := GetProcAddress(Fcall,'InitPlugin'); LoadDll(FIinitPlg); except // end; end; end; end; until FindNext(sr) <> 0; findclose(sr); end;
Так, вроде загрузили, передали, получили. Теперь опишем выгрузку плагинов. То же самое, новый актион… procedure TDynamicLoader.aUnloadExecute(Sender: TObject); var i : integer; Unload : TUnLoadDelphiDll; begin for I := 0 to FPluginList.Count - 1 do begin {ВЫГРУЗКА DLL DELPHI} if GetProcAddress(Cardinal(FPluginList.Objects[i]),'UnloadDll') <> nil then begin Unload := GetProcAddress(Cardinal(FPluginList.Objects[i]),'UnloadDll'); Unload; FreeLibrary(Cardinal(FPluginList.Objects[i])); end; end; MainPlgList.Items.Clear; FPluginList.Clear; {убиваем все кнопки на тулбаре} while MainPlgToolBar.ComponentCount <> 0 do (MainPlgToolBar.Components[0] as TToolButton).Destroy; {уничтожаем страницы} while MainPages.PageCount <> 0 do MainPages.Pages[0].Destroy; end;
Выгрузка вроде удалась. Теперь модифицируем загрузку, вдруг пользователь уже загрузил плагины и решил еще раз их
загрузить, проверку:
а
они
уже
есть.
Добавим
if FPluginList.Count > 0 then aUnload.Execute; procedure TDynamicLoader.aLoadExecute(Sender: TObject); var sr : TSearchRec; FCall : cardinal; LoadDll : TLoadDelphiDll; Begin if FPluginList.Count > 0 then aUnload.Execute; GetInterface(IinitPlg,FIinitPlg); //Получаем ссылку на наш интерфейс FPluginList.Clear; MainPlgList.Items.Clear; if FindFirst(ExtractFileDir(Application.ExeName)+'\*.dll',faAnyFile,sr) = 0 then
repeat if ANSIUPPERCASE(ExtractFileExt(sr.Name)) = '.DLL' then begin FCall := LoadLibrary(pchar(sr.Name)); {обязательно проверимся на наличие этой процедуры в библиотеке} if GetProcAddress(Fcall,'InitPlugin') <> nil then begin {сохранимся в листик, чтобы потом обратится к dll} FPluginList.AddObject(sr.Name,TObject(FCall)); try @LoadDll := GetProcAddress(Fcall,'InitPlugin'); LoadDll(FIinitPlg); except // end; end; end; end; until FindNext(sr) <> 0; findclose(sr); end;
Вроде все, надо бы откомпилироваться. Клацаем контрол+ф9. Ошибок у меня нет, если у вас появились, посмотрите синтаксис, я копипастом мог что-то пропустить. Так, еще одно НО. Коль библиотеки загружены, мы должны быть
точно уверены в том, что они выгрузятся, поэтому выполнение action выгрузки надо бы повесить на закрытие формы, с маленькими проверочками:
{перед закрытием надо проверить, вдруг плагины не выгружены} procedure TDynamicLoader.FormClose(Sender: TObject; var Action: TCloseAction); begin if FPluginList.Count > 0 then aUnload.Execute; FPluginList.Free; end;
Так, вроде пока все. Пора попробовать сотворить первый плагин. Создаем новый проект, только не application , а DLL. Удаляем не нужный текст, который, и говорит, об использовании модуля sharemem. Подключаем к проекту наш юнит
Interfaces. Сразу добавьте одну форму с кнопочкой, на нажатие которой, сделайте банальный вызов ShowMessage. Вот что у меня получилось + я сразу описал те процедуры, как мы и договорились в соглашениях о вызовах.
library Plugin1; uses SysUtils, Classes, windows, graphics, forms, Interfaces in '..\..\Interfaces.pas', Unit1 in 'Unit1.pas' {Form1}; {$R *.res} //а вот самое интересное procedure InitPlugin(AIinitPlg : IinitPlg);stdcall;
begin end;
procedure UnloadDll;stdcall; begin end; exports InitPlugin, UnloadDll; begin end.
На вход мы получили не класс, и не динамический массив, а ссылку на интерфейс. Давайте воспользуемся им и
создадим 2 процедуры для тестирования нашего интерфейса, а заодно и самого плагина. Мой код ниже:
var FfrmList : TStrings; FIinitPlg : IinitPlg; procedure InitPlugin(AIinitPlg : IinitPlg);stdcall; var i : integer; begin {а вот тут самое интресное} FIinitPlg := AIinitPlg; i := FIinitPlg.CreateMainNode('Главный узелок'); {создали главный узелок в листике} FIinitPlg.AddPlgUnderMainNode(i,'Простая модальная форма','SHowSimpleForm'); {добавили узелок} FIinitPlg.AddPlgUnderMainNode(i,'Показать форму в странице','ShowInnerForm'); {еще один} FIinitPlg.AddPluginOnToolBar('Кнопочка','ShowInnerForm'); {заодно протестируем и кнопки} end;
procedure SHowSimpleForm;stdcall; var f : TForm1; begin {покажем обычную формочку} f := TForm1.Create(nil); try f.Position := poScreenCenter; f.BorderStyle := bsSizeToolWin; f.ShowModal; finally f.Free; end; end;
procedure ShowInnerForm;stdcall; var f : TForm1; H : HWND; begin {собственно зачем нам много одинаковых форм, для примера достаточно и одной} if FfrmList.Count = 0 then
begin FIinitPlg.AddNewPage('Форма внутри страницы',H); f := TForm1.Create(nil); FfrmList.AddObject('',TObject(f)); f.BorderStyle := bsNone; f.ParentWindow := H; f.WindowState := wsMaximized; f.Color := clInfoBk; f.Show; end; end; procedure UnloadDll;stdcall; var i : integer; begin {убиваем созданные формы} for I := 0 to FfrmList.Count - 1 do (FfrmList.Objects[i] as TForm1).Free; FfrmList.Free; end; exports InitPlugin, SHowSimpleForm, ShowInnerForm, UnloadDll; begin {сразу создадим листик для хранения открытой формы} FfrmList := TStringList.Create; end.
Компилируем и кладем рядом с EXE. Запускаем EXE, жмем F11 вуаля - наш
плагин загрузился (Рис. 4). Отлично! А как же быть с процедурами? Как вызвать их?
Рисунок 4 (Успешно загрузившейся плагин)
Плагин нам пока больше не нужен, давайте вернемся в нашу оболочку и на двойной клик по дереву добавим код. {вызов процедуры из плагина} procedure TDynamicLoader.MainPlgListDblClick(Sender: TObject); var i : integer; s : string; b : TButton; begin if MainPlgList.Selected <> nil then SetString(s, pchar(MainPlgList.Selected.Data), length(pchar(MainPlgList.Selected.Data))); if s <> '' then begin for I := 0 to FPluginList.Count - 1 do begin if GetProcAddress(Cardinal(FPluginList.Objects[i]),pchar(s)) <> nil then begin b := TButton.Create(nil); @b.OnClick := GetProcAddress(Cardinal(FPluginList.Objects[i]),pchar(s)); b.Click; break; end end; end; end;
Согласен, можно и по-другому, но мне больше нравится именно этот способ. Так, что мы теперь видим: 1. Проверка на то, что выделили узелок
2. Получаем данные, что записали. Если что-то было, ищем в листике эту процедуру и вызываем её. Вроде все, компилируем и запускаем на выполнение. Круто J. Наши плагины работают как кремлевские куранты J. Мой результат на рисунке 5.
Рисунок 5 (Результат первого тестирования)
Теперь попробуем закрыть форму. Отлично, все загруженные DLL выгрузились, не забыв вызвать методы выгрузки «UnloadDll». Ошибок вроде нет. На этом можно считать, что с делфи закончили и пора переходить к с++ builder 6.
билдере. В с++ я не силен, поэтому сделаю, как знаю. На ум ничего другого не пришло как использовать сишные структуры и делфийские рекорды. Итак, сначала опятьтаки соглашения о вызовах. Попытаемся преобразовать структуру в рекорд
Итак, с с++ есть небольшие проблемки, но постараемся не обидеть разработчиков на type CStruct = packed record NameMainNode : Pchar; NameSubNode : Pchar; NameProc : Pchar; NameButton : PChar; end;
TLoadС_Dll = function() : pointer;stdcall; TUnLoadС_Dll = procedure();stdcall;
var DynamicLoader: TDynamicLoader; Struct : ^CStruct;
Вот самый смак, указатель на наш пакед рекорд. TLoadС_Dll = function():pointer;stdcall;
Означает, что сишная dll должна нам вернуть указатель на структуру, которую мы преобразуем в наш рекорд и воспользуемся. Напишем сишную dll.
Открываем билдер..создаем новый проект, выставляем опции дебаггера.Сразу добавим форму с кнопочкой, ну и по традиции ShowMessage. Вот что у меня вышло.
#include <vcl.h> #include <windows.h> #include <CfrmUnit.h> #pragma hdrstop #pragma argsused
struct str { PChar NameMainNode, NameSubNode, NameProc, NameButton; } mystruct; {наша структура которую мы вернем, точнее указатель} BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID lpvReserved) { return 1; }
//--------------------------------------------------------------------------extern "C" Pointer __export InitStruct() //так будет инициализироваться загрузка { mystruct.NameMainNode = "Плагин с++ Билдера"; mystruct.NameSubNode = "Покажем форму из с++ плагина"; mystruct.NameProc = "_ShowC_Frm"; //тут особое внимание, на подчеркивание впереди имени функции mystruct.NameButton = "Кнопка С++"; return &mystruct; };
extern "C" void __export ShowC_Frm() { TForm1 *f; f = new TForm1(NULL); try { f->ShowModal();} __finally {delete (f);}; }; extern "C" void __export UnloadDll() { // то что нужно выполнить при выгрузке dll };
Можно и по-другому, это ваше дело, я просто показал пути. Компилим, вернемся в
нашу оболочку и модифицируем загрузку плагинов:
procedure TDynamicLoader.aLoadExecute(Sender: TObject); var sr : TSearchRec; FCall : cardinal; LoadDll : TLoadDelphiDll; LoadC_Dll : TLoadС_Dll; begin if FPluginList.Count > 0 then aUnload.Execute; GetInterface(IinitPlg,FIinitPlg); FPluginList.Clear; MainPlgList.Items.Clear; if FindFirst(ExtractFileDir(Application.ExeName)+'\*.dll',faAnyFile,sr) = 0 then repeat if ANSIUPPERCASE(ExtractFileExt(sr.Name)) = '.DLL' then begin FCall := LoadLibrary(pchar(sr.Name)); {обязательно проверимся на наличие этой процедуры в библиотеке} if GetProcAddress(Fcall,'InitPlugin') <> nil then begin {сохранимся в листик, чтобы потом обратится к dll} FPluginList.AddObject(sr.Name,TObject(FCall)); try @LoadDll := GetProcAddress(Fcall,'InitPlugin'); LoadDll(FIinitPlg); except // end; end;
{подключаем dll с++} if GetProcAddress(Fcall,'_InitStruct') <> nil then begin FPluginList.AddObject(sr.Name,TObject(FCall)); try @LoadC_Dll := GetProcAddress(Fcall,'_InitStruct'); Struct := LoadC_Dll; if ((Struct^.NameMainNode <> nil) and (Struct^.NameSubNode <> nil)) then AddPlgUnderMainNode(CreateMainNode(Struct^.NameMainNode),Struct^.NameSubNode ,Struct^.NameProc); if Struct^.NameButton <> nil then begin AddPluginOnToolBar(Struct^.NameButton,Struct^.NameProc); end; except // end; end; end; until FindNext(sr) <> 0; findclose(sr); end; {выгрузка библиотек} procedure TDynamicLoader.aUnloadExecute(Sender: TObject); var i : integer; Unload : TUnLoadDelphiDll; UnloadC : TUnLoadС_Dll; begin for I := 0 to FPluginList.Count - 1 do begin {ВЫГРУЗКА DLL DELPHI} if GetProcAddress(Cardinal(FPluginList.Objects[i]),'UnloadDll') <> nil then begin Unload := GetProcAddress(Cardinal(FPluginList.Objects[i]),'UnloadDll'); Unload; FreeLibrary(Cardinal(FPluginList.Objects[i])); end; {ВЫГРУЗКА DLL С++} if GetProcAddress(Cardinal(FPluginList.Objects[i]),'_UnloadDll') <> nil then begin Unload := GetProcAddress(Cardinal(FPluginList.Objects[i]),'_UnloadDll'); Unload; FreeLibrary(Cardinal(FPluginList.Objects[i])); end; end; MainPlgList.Items.Clear; FPluginList.Clear; {убиваем все кнопки на тулбаре} while MainPlgToolBar.ComponentCount <> 0 do (MainPlgToolBar.Components[0] as TToolButton).Destroy; {уничтожаем страницы} while MainPages.PageCount <> 0 do MainPages.Pages[0].Destroy; end;
На этом кодинг окончен, а раз так, то пришло время для финального
тестирования. Компилируй проект и
запускай. Результат работы моего примера
можешь глянуть на рисунке 6.
Рисунок 6 (Приложение готово и работает!) На этой самой ноте хочу откланяться и пожелать всем удачи! Если что-то не
получилось, то не беда, присылай мне свои вопросы на мыло.
Исходники к статье ищи в папке «Все, что ты хотел знать о плагинах» Written by Tigrillo E-mail: qkiller7@yandex.ru
«И вот они столкнулись…» Топологические отношения между 3D объектами в теории и на практике Перед человеком, решившим заняться трехмерной графикой, очень скоро (обычно сразу же после появления на экране первой созданной самостоятельно сцены) встает вопрос, определения факта столкновения объектов или говоря научным языком – установление топологических отношений между объектами сцены. Вообще, топология - раздел математики, изучающий топологические свойства фигур, то есть свойства, не изменяющиеся при любых деформациях, производимых без разрывов и склеивания. Топологическое отношение – правило взаимного расположения пространственных объектов карты, сохраняющееся при выполнении аффинных преобразований над объектами, участвующими в топологическом отношении. Установление топологических отношений 3D объектов полезно и важно для ГИС, в которых подразумевается работа с различными объектами (элементами). Например, при работе, с объектами многослойных карт ГИС трудно расположить новый объект изза большого числа пространственных данных. Как правило, на начальном этапе создания новых элементов карты не возникает сложностей при определении положения объекта, но с увеличением их количества на карте процесс становится все более трудоемким. Поэтому возникает задача автоматизации процесса контроля размещения объектов на карте с учетом топологических отношений. Между объектами можно установить фиксированный набор правил взаимного расположения – топологических отношений. Топологические отношения рассматривались Горбачевым В. Г., который ввел термин концептуальные топологические отношения между классами Ставим цель Перед тем как схватить вилы и ринуться в бой, определим цели и задачи, собственно
объектов. Однако модель данных, которая бы их предусматривала, отсутствует. В связи с этим нет единого подхода при проектировании той части ГИС, которая отвечает за пространственное расположение картографических объектов. Поэтому является актуальной задача построения модели взаимодействия пространственных объектов. В этой статье мы попробуем проговорить необходимый минимум теории и самое главное попробовать на практике разработать систему установления топологических отношений между 3D объектами, образованными плоскостными элементами. Инфы будет достаточно много, поэтому усаживайся удобнее и заранее сбегай на кухню за кофе с плюшками, чтобы не уснуть от обилия новых знаний, да и попросту лишний раз не отвлекаться J. А инфа на самом деле полезная и важная (прим.: Egoiste). P.S. Сразу сделаю ремарку. В заголовках скриншотов проги (далее по тексту) ты увидишь: «Установление топологии by ASoter & tE!». Не пугайся J - просто, разработав эту прогу в качестве задания на научную работу в инсте, Я её с челом под ником ASoter сдавал (tE! – это иное написание моего ника) J Так что так… ради которых все это дело затевалось. Итак, самой главной задачей у нас будет – разработка системы управления топологическими отношениями между 3D объектами, образованными плоскостными
элементами. Разработанное нами решение, в дальнейшем можно будет использовать для построения более сложных систем контроля размещения объектов на основе концептуальных топологических отношений (далее ТО). Не понятно, где это можно использовать…? – Ok! Скажу тебе по дружескому секрету, что разрабатываемая система может использоваться в качестве дополнительного модуля (плагина?) для существующих геоинформационных систем (ГИС), а эта тема, кто не в курсе, очень и очень перспективна. Она…хотя…СТОП! Сегодня речь не о достоинствах ГИС J В нашем примере мы реализуем сразу два вида ТО: изолированность и расстояние. Кроме того, наше приложение обязательно должно уметь: 1. Предоставлять возможность изменения 3D объектов и вращение трехмерной сцены (изменение положения мировой системы координат). 2. Динамически определять расстояние между объектами сцены. 3. Определять факт столкновения (наложения) объектов (то есть, иначе, есть столкновение или его нет). Проверять работоспособность нашего творения будем на основе следующих тестов: 1. сцена: Параллелепипед-Параллелепипед (AABB-AABB); 2. сцена: Параллелепипед-Сфера (AABBSphere); Сфера не является плоскостным объектом, однако она может быть представлена в виде бесконечного множества связанных Разрабатываем формальную модель Для программной реализации поставленной задачи необходимо сначала разработать формальную модель решения. Все объекты в программе имеют векторное представление. Вообще, вектор в геометрии
плоскостных элементов, от которых зависит ее степень гладкости. 3. сцена: Параллелепипед-Линия (AABBLine Segment) В данном случае подразумевается линия, имеющая конечные точки. Линию можно представить как вырожденный параллепипед, у которого осталась только одно измерение и, соответственно, одна ось (она же направление линии). 4. сцена: Сфера-Сфера (Sphere-Sphere); 5. сцена: Произвольно ориентированный параллелепипед - Произвольно ориентированный параллелепипед (ОBBОBB); 6. сцена: Произвольно ориентированный параллелепипед - Параллелепипед (ОBBААBB); 7. сцена: Произвольно ориентированный параллелепипед - Сфера (ОBB-Sphere); 8. сцена: Произвольно ориентированный параллелепипед - Линия (ОBB -Line Segment); 9. сцена: Произвольно ориентированный параллелепипед - Треугольник (ОBB Triangle). Цель определена, а значит, возвращаемся к нашим вилам и вперед !!! J Кстати, сегодня мы заюзаем не типичные огородные вилы модели «Delphi» от колхоза «CodeGear», а проверенную временем модель Visual C++ (6-ой по счёту версии) от широко известного бренда «Мелкомягкий сад и огород». А в качестве удобрения для нашего будущего плода мы будем использовать OpenGL (эхх.., ну и лексикон у нас огородно-садовый сегодня подобрался J… ну да ладно…). это всякий направленный отрезок (если слово «вектор» слышишь впервые, то не поленись скачать учебник по геометрии – прим. редактора). Построение объектов происходит по точкам. Построение любой точки в пространстве можно определить тремя
координатами. Например, пусть мы имеем точку M. Проведём через эту точку MP, MQ, MR (рисунок 1), соответственно параллельные плоскостям XOY, YOZ и ZOX. В пересечении с осями получаем точки P, Q и R. Числа x (абсцисса), y (ордината), z (аппликата), измеряющие отрезки OP, OQ, OR в избранном масштабе,
называются (прямоугольными) координатами точки M. Они берутся положительными или отрицательными в зависимости от того, имеют ли векторы OP, OQ, OR соответственно те же направления, что и основные векторы i, j, k, или противоположные.
Рисунок 1 (Представление точки в пространстве) В программе оси систем координат объектов, а также их стороны будут представлять собой вектора, которые будут задаваться тремя своими компонентами x, y, z (координатами). Прямоугольными координатами вектора m называются алгебраические проекции вектора m на оси координат. Координаты вектора обозначаются большими буквами X, Y, Z.
При определении расстояний используются векторные произведения. В нашей программе векторные произведения выражаются через координаты сомножителей. Объясним это математически. Если a1 = {X1, Y1, Z1} и a2 = {X2, Y2, Z2}, то
Выражения, окаймлённые вертикальными чертами, - определители второго порядка. Иначе это запишется так: a1*a2 = { Y1*Z2-Y2*Z1, Z1*X2-Z2*X1, X1*Y2-X2*Y1} Результатом векторного произведения всегда является вектор. Пример кода, реализующего векторное произведение двух векторов: mVector operator^(const mVector& Other) const { return mVector( y * Other.z - z * Other.y, z * Other.x - x * Other.z, x * Other.y - y * Other.x ); }
Опишем математически все алгоритмы нахождения расстояний между объектам сцены.
Для тестов, где вычисляются расстояния между параллелепипедами, произвольно ориентированными к осям мировой системы координат и со сторонами, параллельными к
осям координат (AABB-AABB, OBB-OBB, OBB-AABB) необходимо найти расстояние между максимальными и минимальными точками. В программе они представлены векторами vMin и vMax соответственно. Вычесть вектор a1 (вычитаемое) из вектора a2 (уменьшаемое) значит найти новый вектор x (разность), который в сумме с вектором a1 даёт вектор a2. Так как векторы
у нас представлены своими координатами, то для нахождения расстояния между ними может быть применена формула: x=a2-a1. Координаты вектора x будут следующие: Х=X2-X1, Y=Y2-Y1, Z=Z2-Z1. Здесь представлены вектора a1{ X1, Y1, Z1} и a2{ X2, Y2, Z2}. Программно это будет записано следующим образом:
mVector operator-(const mVector &Other) const { return mVector(x - Other.x, y - Other.y, z - Other.z); }
Рассмотрим вычисление расстояния между параллелепипедом, со сторонами параллельными осям мировой системы координат и сегментом линии, а также между произвольно ориентированным параллелепипедом и сегментом линии. Здесь нахождение производится с использованием аналогичной формулы. Правда разность ищется между одной из точек параллелепипеда (vMin или vMax) и
точкой-вектором, являющейся серединой линии. Расстояние между любым параллелепипедом и сферой рассматривается как разность квадрата расстояния между ближайшей вершиной параллелепипеда и центра сферы и квадрата радиуса сферы. Рассмотрим один из возможных вариантов расположения сферы по отношению к параллелепипеду.
Рисунок 2 (Расстояние между параллелепипедом и сферой) Обозначим расстояние от вершины до центра сферы (на рисунке 2 диагональ прямоугольника) через вектор, радиус сферы – через r, а искомое расстояние между объектами – через d. Тогда, чтобы найти искомое расстояние необходимо сначала вычислить по уже известной формуле разность векторов, обозначающих ближайшую к сфере вершину параллелепипеда (в данном случае vMax) и центр сферы: a=sphere.P - aabb.vMax Теперь разность квадрата полученного ранее расстояния и квадрата радиуса сферы
даст нам значение искомого расстояния между объектами: d=a2-r2. Также как и вершины параллелограмма, вершины треугольника представлены векторами, а значит, для нахождения расстояния между этими объектами снова необходимо использовать математический аппарат векторной геометрии, в частности рассмотренную выше формулу нахождения разности двух векторов. Для данных объектов они (векторы) будут представлять собой ближайшую к треугольнику вершину параллелограмма и первую точку треугольника (рисунок 3).
Рисунок 3 (Расстояние между параллелограммом и треугольником) Расстояние найдётся по следующей формуле: D=vMax-P2. И наконец, определение расстояния между двумя сферами (рисунок 4)
На рисунке 3 ближайшей точкой к треугольнику является правая верхняя (обозначим её как vMax), а ближайшей точкой треугольника является вершина P2. B A
R
D
R x
T Рисунок 4 (Расстояние между двумя сферами) Обозначения следующие: T-расстояние между центрами сфер, D-искомое расстояние между объектами, R1 и R2радиусы соответственно сфер A и B. Из рисунка видно, что для нахождения расстояния D между данными объектами необходимо найти разность расстояния T между центрами сфер и суммой их радиусов R1 + R2. Таким образом, конечная формула для расчета величины удалённости объектов
друг от друга будет иметь следующий вид: D=T-(R1+R2). Необходимо заметить, что все использованные здесь величины представляют собой вектора и к ним должна быть применена формула векторной разности.
Делаем алгоритм
Однако, такое решение достаточно ресурсоемкое. Его необходимо использовать лишь в случаях, когда имеется подходящее аппаратное обеспечение, либо когда самым важным критерием определения столкновения является точность, а не скорость определения. Отсутствие точности проявляется как столкновение объектов, которые визуально все еще находятся друг от друга на некотором расстоянии или, напротив, уже давно должны были столкнуться. Вот такие вот ограничения J.
Основа решения задачи (вычисление расстояния между 3D объектами и определение факта их столкновения) строится на аппроксимации объектов моделируемой сцены. В качестве объектов сравнения будут использоваться так называемые ограниченные области в пространстве (Bounding Volumes), такие как: сфера (Bounding Sphere) и параллелепипед (Bounding Box). Одним из вариантов решения задачи является определение столкновения именно объектов, а не окружающих их областей.
За основу решения поставленной задачи возьмём алгоритмы установления столкновения объектов (Collision Detection),
так как при определении факта столкновения приходится неявным образом определять геометрическую удалённость объектов друг от друга. Рассмотрим, что же это такое. Bounding Volume - это ограниченная область в пространстве. Для целей определения столкновения (Collision Detection) подразумевается, что эта область "твердая", т.е. сквозь нее не могут проходить другие объекты. Ограниченная область в пространстве (Bounding Volume) может иметь любую форму (чаще всего выпуклую), но поскольку определение столкновения сложных объектов - процесс достаточно непростой, который к тому же может
занимать довольно много времени, часто сложные объекты заменяются на более простые области (Bounding Volumes) сферы (Bounding Sphere), параллелепипеды (Bounding Box) или выпуклые многогранники (Convex Polyhedron). При этом получается, что объект как бы окружен непроницаемой оболочкой, которая более или менее повторяет его контуры. Bounding Sphere - это ограниченная область в пространстве (Bounding Volume) в виде сферы. Использование сферы (Bounding Sphere) (рисунок 5) - это простой, быстрый и самый грубый (если, конечно, объект сам по себе не является сферой) способ вычислить расстояние между объектами и узнать, столкнулись они или нет.
Рисунок 5 (Пример сферы (Bounding Sphere)) Bounding Box – это опять же ограниченная область в пространстве (Bounding Volume), но только в виде прямоугольного параллелепипеда (рисунок 6). Обычно, параллелепипед более точно, чем сфера, повторяет форму объектов, к тому же проверка на столкновения с помощью
прямоугольного параллелепипедов все еще достаточно простая и быстрая, поэтому они наиболее часто используются для решения задач установления некоторых топологических отношений. Существует два варианта прямоугольных параллелепипедов (Bounding Box-ов): AABB и OBB.
Рисунок 6 (Пример прямоугольного параллелепипеда (Bounding Box)) Теперь давай займемся описанием видов прямоугольных параллелепипедов (Bounding Box-ов).
AABB (Axis-Aligned Bounding Box) - это прямоугольный параллелепипед (Bounding Box) со сторонами, параллельными осям координат в мировой системе (рисунок 7).
Рисунок 7 (Примеры AABB) Как можно видеть, при вращении объекта AABB изменяет свои размеры, но всегда остается ориентированным по осям координат. Второй вариант AABB - это использовать в качестве прямоугольного параллелепипеда (Bounding Box-а) куб со сторонами равными максимальному размеру объекта. Таким образом, в любом положении объект не выйдет за пределы
AABB, хотя, конечно, при этом теряется точность. Проверка на столкновения с помощью AABB выполняется очень просто и быстро. OBB (Oriented Bounding Box) - это произвольно ориентированный прямоугольный параллелепипед (Bounding Box) (рисунок 8).
Рисунок 8 (Примеры OBB) В отличие от AABB, OBB вращается вместе с объектом и не меняет своих размеров. Проверка на столкновения с помощью OBB несколько сложнее и медленнее, чем с помощью AABB, но чаще она более предпочтительна. В разрабатываемом нами решении предполагается реализовать 9 тестов: AABB-AABB, AABB-Sphere, AABB-Line Segment, Sphere-Sphere, OBB-OBB, OBBAABB, OBB-Sphere, OBB-Line Segment, OBB-Triangle. Теперь давай перейдем к рассмотрению необходимых алгоритмов –
опиишем математическую основу для установления топологических отношений указанных объектов. Для начала необходимо общее представление о работе с объектом AABB. Хранить AABB лучше в виде двух векторов - позиции в пространстве (P) и размеров (E), но если планируется находить расстояние до другого объекта, можно также сохранить и минимальную (vMin) и максимальную (vMax) точки (рисунок 9).
Рисунок 9 (Пример AABB в 2D) Здесь размеры AABB указываются относительно позиции в пространстве. Сразу глянем на пример класса AABB: #ifndef __AABB_H__ #define __AABB_H__ #include "vMath.h" class cdSphere; class cdOBB; class cdAABB { public: mVector mVector mVector
Color; P, E; // положение в пространстве и размеры vMin, vMax; // минимальная и максимальная точки
void Create(const mVector &Pos, const mVector &Ext, const mVector Col=mVector(1,1,1)); void Move(const mVector &Step); void Draw() const; void Rotate(const mVector &Angle); const const const const
BOOL BOOL BOOL BOOL
OverlapsAABB(const cdAABB &aabb) const; OverlapsOBB(const cdOBB &obb) const; OverlapsSphere(const cdSphere &sphere) const; OverlapsLineSegment( const mVector &mid, const mVector &dir, const Scalar hl) const;
}; #endif //__AABB_H__
Для того, чтобы построить AABB для объекта, нужно всего лишь найти размеры объекта по осям координат, т.е. границы объекта. Это можно сделать, например,
следующим образом (предполагается, что Vertices - это массив, в котором находятся уже трансформированные в мировое пространство вершины объекта):
void cdAABB::CreateFromVertices(const TArray<mVector> &Vertices) { vMin = vMax = Vertices[0]; // ищем минимальную/максимальную точки for (int i=1;i<Vertices.Num();i++)
{ // проходим по осям x,y,z for (int t=0;t<3;t++) { vMax[t] = max(vMax[t], Vertices[i][t]); vMin[t] = min(vMin[t], Vertices[i][t]); } } // вычисляем размеры E = (vMax - vMin) / 2.f; // и положение в пространстве P = vMin + E; }
Легко заметить, что на проверку всех вершин объекта (которых может быть несколько сотен или даже тысяч) может уйти огромное количество времени строить AABB придется каждый кадр, т.к. при вращении объекта размеры AABB меняются. Обойти это проблему можно, если воспользоваться OBB - построить один раз прямоугольный параллелепипед (Bounding
Box) и вращать его вместе с объектом, а для создания AABB использовать только 8 точек этого OBB. Таким образом, всего за 8 трансформаций мы получаем AABB и теряем точность проверки (рисунок 10). Для OBB кроме позиции в пространстве и размеров необходимо хранить также матрицу поворота (или, по крайней мере, ссылку на матрицу поворота объектахозяина). Все остальное идентично AABB.
Рисунок 10 (К вопросу о точности) На рисунке изображены следующие объекты: OBB; оптимальный AABB; AABB, построенный с помощью OBB. Теперь посмотрим на пример класса для OBB: #ifndef __OBB_H__ #define __OBB_H__ #include "vMath.h" class cdAABB; class cdSphere; class cdOBB { public: mVector mVector mMatrix3 mVector
M;
Color; P, E; // положение в пространстве и размеры // матрица поворота vMin, vMax; // минимальная и максимальная точки
void Create(const mVector &Pos, const mVector &Ext, const mVector Col=mVector(1,1,1)); void Move(const mVector &Step);
void Rotate(const mVector &Angle); void Draw() const; const const const const
BOOL BOOL BOOL BOOL
OverlapsAABB(const cdAABB &aabb) const; OverlapsOBB(const cdOBB &obb) const; OverlapsSphere(const cdSphere &sphere) const; OverlapsSphere2(const cdSphere &sphere) const;
const BOOL OverlapsLineSegment(const mVector &mid, const mVector &dir, const Scalar hl) const; const BOOL OverlapsTriangle(const mVector &pnt1, const mVector &pnt2, const mVector &pnt3) const; }; #endif //__OBB_H__
Также можно в качестве AABB использовать куб такого размера, чтобы объект в любом положении не выходил за его пределы. Разумеется, в этом случае вообще ничего пересчитывать не надо, но зато точность проверки существенно снижается. Итак, полученный с помощью вышеперечисленных махинаций AABB иногда более чем в два раза превышает размеры самого объекта – это сложно. Измеряем расстояние между объектами
Для того, чтобы найти расстояние между двумя объектами, необходимо вычислить: расстояние между ближайшими точками– для тестов AABB-AABB, OBB-OBB, OBBAABB. Расстояние между case ctAABB_AABB : { FLOAT oi=0; float d = 0, a ; // проходим по осям X,Y,Z for (int i=0;i<3;i++) { if (aabb1.vMax[i] < aabb2.vMin[i]) { a = aabb1.vMax[i] - aabb2.vMin[i]; d += a; } if (aabb1.vMin[i] > aabb2.vMax[i]) { a = aabb1.vMin[i] - aabb2.vMax[i];
Проще сразу использовать OBB и не использовать различные преобразования. Однако проверка на столкновения с AABB с практической точки зрения быстрее, чем любая другая. AABB рекомендуется использовать для предварительной грубой проверки перед более точной и более медленной.
параллелепипедами вычисляется ледующим образом: определяется, какие точки объектов являются ближайшими (по каждой оси), затем находятся расстояния между точками и, в результате суммирования, вычисляется искомое расстояние. Пример вычисления расстояния для AABB_AABB:
d += a; } } }
Для тестов AABB-Line Segment, OBB-Line Segment расстояние вычисляется по аналогии с предыдущим алгоритмом. Отличием является то, что расстояние рассчитывается между ближайшей точкой параллелепипеда и центром линии. В тестах AABB-Sphere, OBB-Sphere – расстояние
между ближайшей точкой параллелепипеда и сферой. В тесте Sphere-Sphere вычисляется разность расстояния между центрами сферы и суммой их радиусов. В тесте OBB-Triangle вычисляется расстояние между ближайшей точкой параллелепипеда и первой точкой треугольника.
Определяем отношения между AABB–AABB
(которые выровнены в мировой системе координат) осей всего три - X, Y и Z и если прямоугольные параллелепипеды (Bounding Box-ы) не пересекаются, по крайней мере, одна из них является разделяющей. Рассмотрим пример в 2D и проверку по оси Х (рисунок 11).
Вычислить расстояние между двумя объектами AABB, а значит, и определить факт их столкновения не сложно. Нужно всего лишь проверить существование разделяющей оси. В случае с AABB
Рисунок 11 (Проверка по оси X) В данном случае AABB не пересекаются ось Х является разделяющей, т.к. |Tx| > (Ax + Bx). Проще говоря, если расстояние между центрами двух AABB по определенной оси больше, чем сумма их
размеров по этой оси, то данная ось является разделяющей и эти AABB не пересекаются. Вот небольшой кусок кода, реализующий эту проверку:
const bool cdAABB::OverlapsAABB(const cdAABB &aabb) const { const mVector T = aabb.P - P; return fabs(T.x) <= (E.x + aabb.E.x) && fabs(T.y) <= (E.y + aabb.E.y) && fabs(T.z) <= (E.z + aabb.E.z); }
Определяем отношения AABBSphere, ОBB-Sphere Для вычисления расстояния до сферы и для проверки на пересечение со сферой достаточно будет вычислить квадрат расстояния. Принцип следующий проверяем по всем осям, попадает ли центр
сферы в AABB, и если нет, то вычисляем расстояние по этой оси от границы AABB до центра сферы. Сумма квадратов расстояний по осям даст нам квадрат расстояния от AABB до центра сферы (рисунок 12).
Рисунок 12 (Расстояние до сферы) И если полученный квадрат расстояния меньше квадрата радиуса, то сфера накладывается на AABB. Опять же, взглянем на код: const bool cdAABB::OverlapsSphere(const cdSphere &sphere) const { float d = 0, a; // проходим по осям X,Y,Z for (int i=0;i<3;i++) { // если центр сферы лежит перед AABB, if (sphere.P[i] < vMin[i]) { // то вычисляем квадрат расстояния по этой оси a = sphere.P[i] - vMin[i]; d += a * a; } // если центр сферы лежит после AABB, if (sphere.P[i] > vMax[i]) { // то вычисляем квадрат расстояния по этой оси a = sphere.P[i] - vMax[i]; d += a * a; } } return d <= (sphere.R * sphere.R); }
Для обнаружения столкновения OBB-Sphere необходимо трансформировать сферу в систему координат OBB, затем отношения определяются также, как в ААBB-Sphere. Пример класса Sphere: #ifndef __SPHERE_H__ #define __SPHERE_H__ #include "vMath.h" class cdAABB; class cdOBB; class cdSphere { private: GLUquadricObj *Quadric; public: mVector Color; mVector P; // позиция
Scalar R; // радиус void Create(const mVector &Pos, const Scalar Rad, const mVector Col=mVector(1,1,1)); void Move(const mVector &Step); void Draw() const; const BOOL OverlapsAABB(const cdAABB &aabb) const; const BOOL OverlapsOBB(const cdOBB &obb) const; const BOOL OverlapsSphere(const cdSphere &sphere) const; }; #endif __SPHERE_H__
Определяем отношение для AABB-Line, ОBB-Line В данном случае подразумевается линия, имеющая конечные точки. Линию можно представить как вырожденный OBB, у которого осталась только одно измерение и, соответственно, одна ось (она же направление линии), таким образом,
проверка опять же сводится к поиску разделяющей оси (рисунок 13). Поскольку линия может быть направлена в любую сторону, кроме X,Y,Z придется проверить также их векторные произведения с вектором направления линии. Всего получается 6 проверок того, является ли какая-либо ось разделяющей.
Рисунок 13 (Пересечение AABB и линии)
Пример кода: const bool cdAABB::OverlapsLineSegment( const mVector &mid, // средняя точка линии сonst mVector &dir, // направление линии const Scalar hl) const // полудлина линии { const mVector T = P - mid; float r; // проверяем, является ли одна из осей X,Y,Z разделяющей if ( (fabs(T.x) > E.x + hl*fabs(dir.x)) || (fabs(T.y) > E.y + hl*fabs(dir.y)) || (fabs(T.z) > E.z + hl*fabs(dir.z)) ) return false; // проверяем X ^ dir r = E.y*fabs(dir.z) + E.z*fabs(dir.y); if ( fabs(T.y*dir.z - T.z*dir.y) > r ) return false; // проверяем Y ^ dir r = E.x*fabs(dir.z) + E.z*fabs(dir.x); if ( fabs(T.z*dir.x - T.x*dir.z) > r ) return false; // проверяем Z ^ dir r = E.x*fabs(dir.y) + E.y*fabs(dir.x); if ( fabs(T.x*dir.y - T.y*dir.x) > r ) return false; return true; }
Для обнаружения столкновения OBB-Line необходимо трансформировать линию в систему координат OBB, затем отношения определяются также, как в ААBB-Line.
рассмотренному алгоритму в случае AABBAABB. То есть объекты не пересекаются, если есть разделяющая ось. |dC| > (R1 + R2)
Определяем отношение SphereSphere Если мы имеем в качестве аппроксимирующих объектов две сферы, то здесь используется алгоритм, аналогичный
Проще говоря, если расстояние между центрами двух сфер по определенной оси больше, чем сумма их радиусов по этой оси, то данная ось является разделяющей, и эти сферы не пересекаются.
Определяем отношение OBBOBB, OBB-ААBB Принципы остаются теми же, что и при работе с AABB - чтобы обнаружить столкновение двух OBB нужно проверить наличие разделяющей оси. Основная сложность в данном случае состоит в том, что каждый OBB находится в собственной
системе координат, а это несколько увеличивает количество возможных вариантов - 3 + 3 базовых оси двух OBB + 3 * 3 их векторных произведений. Итого - 15 вариантов. Перед проверкой трансформируем второй OBB в систему координат первого - это немного упростит расчеты.
Рисунок 14 (проверка столкновения двух OBB) const BOOL cdOBB::OverlapsOBB(const cdOBB &obb) const { mVector a = E, b = obb.E, Pa = P, Pb = obb.P; mMatrix3 A = (mMatrix3)M, B = (mMatrix3)obb.M; //смещение в мировой системе координат mVector v = Pb - Pa; //смещение в системе координат А mVector T = A * v; //создаем матрицу поворота B относительно А const mMatrix3 R(A * B.Transpose()); float ra, rb, t; long i, k; //система координат А for( i=0 ; i<3 ; i++ ) { ra = a[i]; rb = b[0]*fabs(R[i][0]) + b[1]*fabs(R[i][1]) + b[2]*fabs(R[i][2]); t = fabs( T[i] ); if ( t > ra + rb ) return FALSE; } //система координат B for( k=0 ; k<3 ; k++ ) { ra = a[0]*fabs(R[0][k]) + a[1]*fabs(R[1][k]) + a[2]*fabs(R[2][k]); rb = b[k]; t = fabs( T[0]*R[0][k] + T[1]*R[1][k] + T[2]*R[2][k] );
if ( t > ra + rb ) return FALSE; } //9 векторных произведений //L = A0 x B0 ra = a[1]*fabs(R[2][0]) + a[2]*fabs(R[1][0]); rb = b[1]*fabs(R[0][2]) + b[2]*fabs(R[0][1]); t = fabs( T[2]*R[1][0] - T[1]*R[2][0] ); if ( t > ra + rb ) return FALSE; //L = A0 x B1 ra = a[1]*fabs(R[2][1]) + a[2]*fabs(R[1][1]); rb = b[0]*fabs(R[0][2]) + b[2]*fabs(R[0][0]); t = fabs( T[2]*R[1][1] - T[1]*R[2][1] ); if ( t > ra + rb ) return FALSE; //L = A0 x B2 ra = a[1]*fabs(R[2][2]) + a[2]*fabs(R[1][2]); rb = b[0]*fabs(R[0][1]) + b[1]*fabs(R[0][0]); t = fabs( T[2]*R[1][2] - T[1]*R[2][2] ); if ( t > ra + rb ) return FALSE; //L = A1 x B0 ra = a[0]*fabs(R[2][0]) + a[2]*fabs(R[0][0]); rb = b[1]*fabs(R[1][2]) + b[2]*fabs(R[1][1]); t = fabs( T[0]*R[2][0] - T[2]*R[0][0] ); if ( t > ra + rb ) return FALSE; //L = A1 x B1 ra = a[0]*fabs(R[2][1]) + a[2]*fabs(R[0][1]); rb = b[0]*fabs(R[1][2]) + b[2]*fabs(R[1][0]); t = fabs( T[0]*R[2][1] - T[2]*R[0][1] ); if ( t > ra + rb ) return FALSE; //L = A1 x B2 ra = a[0]*fabs(R[2][2]) + a[2]*fabs(R[0][2]); rb = b[0]*fabs(R[1][1]) + b[1]*fabs(R[1][0]); t = fabs( T[0]*R[2][2] - T[2]*R[0][2] ); if ( t > ra + rb ) return FALSE; //L = A2 x B0 ra = a[0]*fabs(R[1][0]) + a[1]*fabs(R[0][0]); rb = b[1]*fabs(R[2][2]) + b[2]*fabs(R[2][1]); t = fabs( T[1]*R[0][0] - T[0]*R[1][0] ); if ( t > ra + rb ) return FALSE; //L = A2 x B1 ra = a[0]*fabs(R[1][1]) + a[1]*fabs(R[0][1]); rb = b[0] *fabs(R[2][2]) + b[2]*fabs(R[2][0]); t = fabs( T[1]*R[0][1] - T[0]*R[1][1] ); if ( t > ra + rb ) return FALSE; //L = A2 x B2 ra = a[0]*fabs(R[1][2]) + a[1]*fabs(R[0][2]); rb = b[0]*fabs(R[2][1]) + b[1]*fabs(R[2][0]);
t = fabs( T[1]*R[0][2] - T[0]*R[1][2] ); if ( t > ra + rb ) return FALSE; return TRUE; }
Определяем отношение OBBTriangle Чтобы обнаружить пересечение OBBTriangle, нужно, как и всегда в случае с прямоугольными параллелепипедами (Bounding Box-ами) попытаться найти разделяющую ось.
На этот раз нужно проверить 13 вариантов: 1 нормаль треугольника + 3 оси OBB + 3 * 3 (векторные произведения осей OBB и сторон треугольника). Также, в качестве "расстояния между центрами" объектов, лучше брать расстояние от центра OBB до первой точки треугольника.
Рисунок 15 (Проверка столкновения OBB и треугольника) const BOOL cdOBB::OverlapsTriangle( const mVector &pnt1, const mVector &pnt2, const mVector &pnt3) const { DWORD i; mVector n; // проверяемая ось Scalar p, // расстояние от pnt1 до центра OBB вдоль оси d0, d1, // + к p для pnt2, pnt3 R; // "радиус" OBB вдоль оси // расстояние от pnt1 до центра OBB mVector D = pnt1 - P; // стороны mVector E0 E1 E2
треугольника = pnt2 - pnt1, = pnt3 - pnt1, = E1 - E0;
// нормаль треугольника n = E0 ^ E1; // проверяем нормаль треугольника if (Math->Abs(n | D) > (E.x * Math->Abs(n | M[0]) + E.y * Math->Abs(n | M[1]) + E.z * Math->Abs(n | M[2])) ) return FALSE; // проверяем оси OBB for (i=0;i<3;i++) { p = M[i] | D;
d0 = M[i] | E0; d1 = M[i] | E1; R = E[i]; if ((min(p, min(p+d0, p+d1)) > R) || (max(p, max(p+d0,p+d1)) < -R)) return FALSE; } // проверяем M[0] ^ E0 n = M[0] ^ E0; p = n | D; d0 = n | E1; R = E[1] * Math->Abs(M[2] | E0) + E[2] * Math->Abs(M[1] | E0); if ((min(p, p+d0) > R) || (max(p,p+d0) < -R)) return FALSE; // проверяем M[0] ^ E1 n = M[0] ^ E1; p = n | D; d0 = n | E0; R = E[1] * Math->Abs(M[2] | E1) + E[2] * Math->Abs(M[1] | E1); if ((min(p, p+d0) > R) || (max(p,p+d0) < -R)) return FALSE; // проверяем M[0] ^ E2 n = M[0] ^ E2; p = n | D; d0 = n | E0; R = E[1] * Math->Abs(M[2] | E2) + E[2] * Math->Abs(M[1] | E2); if ((min(p, p+d0) > R) || (max(p,p+d0) < -R)) return FALSE; // проверяем M[1] ^ E0 n = M[1] ^ E0; p = n | D; d0 = n | E1; R = E[0] * Math->Abs(M[2] | E0) + E[2] * Math->Abs(M[0] | E0); if ((min(p, p+d0) > R) || (max(p,p+d0) < -R)) return FALSE; // проверяем M[1] ^ E1 n = M[1] ^ E1; p = n | D; d0 = n | E0; R = E[0] * Math->Abs(M[2] | E1) + E[2] * Math->Abs(M[0] | E1); if ((min(p, p+d0) > R) || (max(p,p+d0) < -R)) return FALSE;
// проверяем M[1] ^ E2 n = M[1] ^ E2; p = n | D; d0 = n | E0; R = E[0] * Math->Abs(M[2] | E2) + E[2] * Math->Abs(M[0] | E2); if ((min(p, p+d0) > R) || (max(p,p+d0) < -R)) return FALSE; // проверяем M[2] ^ E0 n = M[2] ^ E0; p = n | D; d0 = n | E1; R = E[0] * Math->Abs(M[1] | E0) + E[1] * Math->Abs(M[0] | E0); if ((min(p, p+d0) > R) || (max(p,p+d0) < -R)) return FALSE; // проверяем M[2] ^ E1 n = M[2] ^ E1; p = n | D; d0 = n | E0; R = E[0] * Math->Abs(M[1] | E1) + E[1] * Math->Abs(M[0] | E1); if ((min(p, p+d0) > R) || (max(p,p+d0) < -R)) return FALSE; // проверяем M[2] ^ E2 n = M[2] ^ E2; p = n | D; d0 = n | E0; R = E[0] * Math->Abs(M[1] | E2) + E[1] * Math->Abs(M[0] | E2); if ((min(p, p+d0) > R) || (max(p,p+d0) < -R)) return FALSE; return TRUE; }
Итого В этом разделе обычно пишут: чего достигли, как улучшить разработку и прочие умозаключения. Итак… Напишу так… J. На этом моя статья подошла к концу и пора подвести какие-нибудь итоги. В рамках статьи мы разработали полноценную систему установления топологических отношений между 3D объектами. Описанный мною пример можно использовать как в качестве
самостоятельного продукта, так и для основы разработки создания модулей геоинформационных систем, анализирующих результаты обработки каких-либо объектов (например, элементы карт). Ты же можешь не останавливаться на достигнутом и попробовать реализовать в проекте другие типы топологических отношений, типа: соседство, вложенность, близость, удаленность и т.д. Если ты все это
замутишь, то это будет хорошим фундаментом для разработки полноценной ГИС, работающей с 3D объектами. О как!
В общем, желаю тебе успехов в нашем нелегком деле! Все свои вопросы можешь слать мне на мыло.
Written by Никита Плеханов aka Egoiste (tE!) E-mail: egoiste@vr-online.ru
CodeIgniter: Обзор фреймворка для PHP Для разработки современных WEB-приложений «голого» языка программирования уже давно недостаточно. Если вы привыкли разрабатывать проекты на php, то вам хороша, известна ситуация, когда приходится писать/переносить кучу повторяющегося рутинного кода для очередного проекта. Из этого положения каждый девелопер выкручиваться по-своему – одни создают свои шаблоны и используют их повсеместно, другие - выбирают всевозможные надстройки для языка – CMF (Content Management Framework). Почему нужно использоваться фреймворки? Переходить к использованию фреймворков заставляет не дань моде, скорее это неизбежный шаг, который рано или поздно вынужден совершить любой WEBпрограммист. Приложения «из браузера» каждый день усложняются, и по функционалу уже давно не уступают многим десктопным вариантам. Разобраться со всеми современными технологиями, используемыми для разработки таких сложных приложений достаточно трудно, а иногда и вовсе невозможно, поскольку появляются они крайне динамично. Чтобы всегда оставаться на коне приходится выбирать CMF, которые упрощают процесс адаптации к новым технологиям. Но не будем петь хвалебных песен CMF, а сразу назовем пять причин, по которым стоит распрощаться со стереотипами и начать использовать фреймворки в своих проектах: 1. Постоянная структура. При использовании фреймворков требуется четкое разделение ролей для каждого файла проекта. Например, если фреймворк построен на архитектуре MVC, то все созданные вами контроллеры, представления и модели будут лежать по разным папкам. При постоянной разработке новых, а также поддержки старых проектов не нужно ломать голову над вопросом: «А куда же я положил такой то сценарий?» или «Где у меня реализована такая-то функция». Кроме того, дальнейшую поддержку таких проектов гораздо проще передавать другим программистам. Ведь чтобы они смогли разобраться в коде и принципах его построения, им достаточно взглянуть на документацию фреймворка.
2. Никаких велосипедов. Пожалуй, каждый программист хоть раз да умудрялся изобрести свой велосипед. Причин может быть много, но самая распространенная – невозможность найти готовое решение. При использовании фреймворков все намного проще, т.к. почти все CMF несут на своем борту кучу библиотек/плагинов с готовым кодом и еще кучу всевозможных полезностей валяются на просторах интернета. 3. Скорость и качество. Самостоятельно решенные задачи решаются не всегда идеально, зачастую полученный результат поддается тотальной оптимизации, но по разным причинам, к ней (оптимизации) прибегают в самую последнюю очередь. Если вообще прибегают. С CMF все проще, поскольку все входящие в него функции тщательно тестируются многотысячной армией программистов (если, конечно, фреймворк популярен) и в случае обнаружения слабых мест, оптимизация последует незамедлительно и более качественное решение войдет в следующую версию фреймворка. 4. Повышение безопасности. При разработке приложений с использованием фреймворков, на порядок повышается безопасность разрабатываемого решения. Практически все фреймворки содержат функции/библиотеки или безопасные классы для решения поставленных задач. Такой подход позволяет избавиться от потерь времени на создание всевозможных проверок и написание соответствующих функций-фильтров, сосредоточившись на логике приложения.
5. Оперативная помощь. Получить квалифицированную помощь при использовании фреймворка просто и быстро. Любой популярный и
функциональный CMF имеет сообщества, постоянно занимающиеся тестированием и поддержкой.
Разрешите представить – Code Igniter
чересчур сложны в использовании и изучении (например, фреймворк от Zend) разработка приложений с помощью таких продуктов не упрощалась, а усложнялась. Усложнения мне были не нужны, поэтому я продолжал искать альтернативу. К счастью она нашлась, - ей стал Code Igniter.
За свою практику разработки приложений для WEB мне пришлось перепробовать несколько фреймворков. Некоторые из протестированных мной CMF были
Рисунок 1 (Официальный сайт CodeIgniter) Возможности CodeIgniter Code Igniter – бесплатный функциональный фреймворк для php программистов. Среди ключевых возможностей этого продукта можно выделить: 1. Полная совместимость с php 4. Хоть сейчас это не столь актуально, но пару лет назад, когда у большинства хостеров была установлена четвертая версия этого интерпретатора, Code Igniter выгодно отличался на фоне конкурентов. Так, что
если вы до сих пор застряли во вчерашнем дне или использоваться php4 вас обязывают другие причины, то теперь вы сможете это делать вместе с Code Igniter. 2. Простой в изучении. Сравнивая Code Igniter с альтернативными решениями можно смело сказать, что он наиболее прост. Помимо хорошо продуманной архитектуры проекта, разработчики не схалтурили и снабдили свое детище отличной документацией. Действительно, документация у CI написана подробно,
хорошо структурирована обновляется.
и
оперативно
3. Безопасность. Проблемы в системе безопасности присущи всем WEB-проектам, однако с CI многие из них решаются автоматически. Например, для точной фильтрации полученных данных на предмет XSS есть встроенная функция, которая позволяет не только удалить, но и сохранить в лог опасные данныеь. Очень удобно. 4. Расширяемость. CI очень гибок и хорошо поддается расширению. Научить фреймворк новым возможностям – пара пустяков. Достаточно подключить нужный плагин/хелпер/библиотеку и начать радоваться новому функционалу. 5. Богатые возможности. Вместе с CI поставляются библиотеки, плагины, хелперы, которые позволяют сразу перейти к решению задач и не заморачиваться изобретением велосипедов. Не нужно заниматься кодокопанием, достаточно воспользоваться специальным механизмом, позволяющим без танцев с бубном «перевоспитать» CI. 6. Active Record. В CI используется модифицированная версия паттерна Active Record Database. С помощью Active Record, работа с базой данных превращается в сплошное удовольствие. Больше не придется писать многочисленные «SELECT» для выбора данных, достаточно лишь воспользоваться методами этого класса, а это всего две небольшие строчки MVC Model View Controller (MVC) - архитектура программного обеспечения, позволяющая разделить модель данных, пользовательский интерфейс и управляющую логику на три отдельные составляющее. Причем разделить ее так, что изменение одного не повлияет на работу других компонентов. Использовать эту архитектуру очень удобно при разработке больших проектов, работа над которыми идете в команде. Например, работая над проектом, программистам не нужно заботиться о будущем интерфейсе. Их цель - получить и обработать данные, а
кода. Помимо упрощенного доступа к БД, этот класс позволяет забыть об используемой СУБД. Вы можете построить приложение, используя MySQL, а потом также легко запустить его под Oracle. И это еще не все. Ко всему прочему, AR позволяет хоть немного, но обезопасить работу с СУБД, т.к. при составлении запросов все значения экранируются. 7. Высокая производительность. Столь большие возможности ничуть не повлияли на производительность фреймворка. Работает он действительно шустро. Такое быстродействие достигается за счет очень «легкого» ядра. Все дополнительные библиотеки подключаются лишь по мере необходимости. 8. Архитектура MVC. CI заточен под архитектуру MVC (Model-View-Controller), позволяющую отделить логику от отображения. При работе в команде (программисты + дизайнеры), такой подход будет весьма востребован. 9. Поддержка шаблонизатора. Несмотря, на то, что CI не требует обязательного использования шаблонизатора, при желании им можно воспользоваться. 10. Дружественность к поисковикам. Благодаря своим URL’ам, Code Igniter отлично дружит с поисковыми система и поддается индексации. потом отправить их пользователю. Вид, в котором пользователь получит эти данные, программистов волновать не должен. Это уже работа дизайнеров и верстальщиков, которые могут параллельно создавать представления для полученных данных. Что же касается программистов, то они тоже могут распараллеливать свою работу например, часть разработчиков может сосредоточиться на разработке логике программы, а другая - на проектировании структуры базы данных. Как видно из примеров, при использовании MVC становится возможным распараллелить работу команды, тем самым повысить
общую производительность. Итак, MVC состоит из сущностей: 1. Model (модель) – служит для предоставления данных. Как правило, в модели описываются функции, классы для работы с базой данных. 2. View (представление) – отвечает за передачу пользователю обработанных данных. 3. Controller (Контроллер) – занимается интерпретацией запрашиваемых/отправленных
Установка Code Igniter Свежий дистрибутив фреймворка вы всегда можете взять с www.codeigniter.com. Разработчики достаточно часто обновляют свой продукт, поэтому я советую подписаться на RSS и постоянно быть в курсе всех последних изменений. Итак, предположим, что вы скачали дистрибутив
пользователем данных, взаимодействует с моделью для их получения. Важно заменить, что Code Igniter, в отличие от других MVC-фреймворков не заставляет использовать MVC в полной мере. Если вам не удобно делить код на три составляющие, то это делать вовсе необязательно. Для создания рабочего приложения вы можете ограничиться одним лишь контроллером, организовав в нем все логику и работу с СУБД. Тем немее, понимание MVC, позволит вам в будущем с легкостью осваивать альтернативные фреймворки (список их можно увидеть в соответствующей врезке).
фреймворка. Теперь можно распаковать архив в папку DocumentRoot web-сервера Apache. Вследствие этих нехитрых действий фрейморк становится готов к работе, в чем легко можно убедиться, зайдя на ваш сайт. Если фреймворк работает успешно, то в браузере появится картинка примерно такая, как на рисунке 2.
Рисунок 2 (Фреймворк готов!)
Базовая настройка Пока работоспособность фреймворка не представляет ничего интересного (такое окно и средствами php недолго вывести), поэтому двинемся дальше и посмотрим на структуру каталогов, которая у нас получилась после распаковки файлов дистрибутива. В корне папке Document Root у нас появилось два каталога и один файл (index.php). Откроем этот файл в php редакторе. Настройки этого файла влияют на работу всего проекта, созданного на основе CI. Итак, давайте посмотрим на наиболее важные переменные, доступные для изменения в этом файле. $sytem_folder – название и путь к папке, содержащей все внутренности CI. $aplication_folder – путь к папке с приложением. Значение этих переменных можно оставить по умолчанию, но при использовании CI в реальных
проектах я вам рекомендую переименовать эти папки и изменить путь. Это необходимо делать в целях безопасности. Незачем никому знать в какой папке вы храните файлы вашего приложения. По своему опыту работы с этим фреймворком, я рекомендую создать отдельную папку, в которой вам предстоит хранить все свои проекты. Например: project/application1, prroject/application2. Таким образом, вы сможете на одной копии фреймворка создавать и поддерживать несколько отдельных проектов. Помимо изменений путей к папкам, в файле index.php вы также можете изменить вид отображения ошибок (error_reporting()). По умолчанию будут отображаться все ошибки, но опять же, в реальном приложении лучше ничего не отображать. Теперь перейдем в папку приложения - system/application. В ней содержится несколько каталогов:
/config – здесь хранятся все настройки для текущего проекта. /controllers – в эту папку нужно сохранять все созданные вами контроллеры. /error шаблоны для страниц-ошибок. /helpers – папка предназначена для хранения созданных вами хелперов. /hooks – директория для «ловушек». /language – папка для хранения языковых файлов. /libraries – все созданные вами библиотеки должны быть здесь. /models – папка с моделями данных. /views – директория для хранения представлений вашего проекта. Изучая дерево директорий проекта Code Igniter, вы наверняка обратили внимание на незнакомые названия. Чтобы не путаться и говорить друг с другом на одном языке, давайте дадим им определения. Итак, в платформе CI, существуют следующие сущности: Helpers (Хелперы) – коллекции функций. В каждом вашем проекте может возникнуть необходимость объявить что-нибудь специфическое. Вот все эти функции лучше всего объявлять в хелперах. Для удобства
использования, хелперы обычно группируют по входящим в них функциям. Например, файловый хелпер, в него входят функции для работы с файлами. Hooks (Ловушки) – встроенная в CI технология, позволяющая изменить поведения работы фреймворка без внесения изменений в ядро. Libraries (Библиотеки) – ваши собственные классы. Все свои классы, выполняющее универсальный код, в CI принято определять как библиотеки.
Практика Чтобы продемонстрировать реальные возможности Code Igniter, я решил на практике рассмотреть процесс создания такого популярного сервиса как «Блог». Сегодня вести блоги чрезвычайно модно, поэтому пример весьма актуален. Итак, приступим. Первым делом подготовьте фреймворк к работе – распакуйте его дистрибутив в папку DocumentRoot WEBсервера Apache. Откройте файл /system/application/config/config.php, найдите в нем определение base_url (базовый урл) и укажите полный путь к папке, в которой расположен CI. Если вы распаковали его в корень директории DocumentRoot и будете разрабатывать проект на локальной машине, то просто укажите здесь: http://127.0.0.1. Все, больше нам config.php не понадобится и потому его можно закрывать. Теперь нам нужно определить контроллер, который будет загружаться по умолчанию (т.е. когда пользователи будут обращаться к http://127.0.0.1). Несмотря на то, что мы еще ничего и не создали, но скоро точно создадим, а создадим мы контроллер с именем Blog, поэтому давайте сразу пропишем к его в маршрут по умолчанию. Все маршруты
описываются в файле routes.php, который расположен в папке config. Открываем этот файл, находим $route[‘default_controller’] и присваиваем ему значение Blog. Сохраняем. При разработке нашего первого проекта, нам потребуется возможность обращаться к разным хелперам. Поэтому нам необходимо указать, чтобы эти хелперы запускались автоматически (хотя их инициализацию можно производить прямо в коде). Чтобы определить объекты, которые должны инициализироваться при старте, нужно отредактировать еще один файл настроек – autoload.php. Откроем этот файл и найдем секцию, в которой происходит описание автозагрузки хелперов (Auto-load Helper Files). Следуя шаблону из комментария, опишеме следующие хелперы: html, url, typography. На этом можно считать, что базовые настройки мы сделали. Сейчас остается лишь установить настройки для соединения с базой данных, после чего сразу перейти к разработке. Все настройки подключения к базе данных хранятся в файле database.php. Откроем его и пропишем все необходимые настройки. Я не буду комментировать редактирование этого файла, т.к. сложного в этом ничего нет, и если вы хоть раз работали с базами данных, то проблем возникнуть не должно.
Рисунок 3 (Разработка в самом разгаре) Создаем базу данных Для сегодняшнего примера нам потребуется база данных. В ней мы будем хранить все топики блога, а также комментарии оставленные пользователями. Имя базы вы
должны были уже выбрать (когда настраивали соединение), теперь вам нужно ее создать физически. В своем примере я использую базу данных с именем test и содержащую две таблицы:
1. tblcomments – комментарии, оставленные пользователями: CREATE TABLE `tblcomments` ( `id` int(11) NOT NULL auto_increment, `author` varchar(25) NOT NULL default 'Unknown', `date` datetime NOT NULL default '0000-00-00 00:00:00', `text` text NOT NULL, `recordId` int(11) NOT NULL default '0', `ip` varchar(15) NOT NULL default '0.0.0.0', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2. tblrecords – таблица будет содержать все записи блога: CREATE TABLE `tblrecords` ( `id` int(11) NOT NULL auto_increment, `author` varchar(25) NOT NULL default 'Unknown', `date` datetime NOT NULL default '0000-00-00 00:00:00', `text` text NOT NULL, `caption` varchar(155) NOT NULL default 'Unknown', `extext` text NOT NULL, PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
Рисунок 4 (Макет базы данных) Готовим модель Итак, создадим новый файл для будущей модели, перепишем в него код из первого листинга, сохраните в файл mblog.php: Листинг 1. Модель <?php class MBlog extends Model { function MBlog () { parent::Model(); } //получение записей с таблицы function get_last_record () { $this -> db -> order_by('date', 'desc'); $query = $this -> db -> get ('tblrecords', 10); return $query -> result(); } //Добавление записей function insert_new_topic ($data) { $this -> db -> insert ('tblrecords', $data); }
} ?>
Описание любой модели в CodeIgniter начинается с определения нового классанаследника от Model. Самое первое, что я делаю после объявления класса – вызываю конструктор. Обратите внимание, что для определения конструктора я использую функцию с именем таким же как и у класса. Этот метод используется в php4, а для php5 мы должны использовать __contruct(). По идее, для этой модели нам не нужно использовать конструктор, его объявление я привел только для демонстрации. Когда в реальном приложении вам потребуется описать конструктор, то не забудьте в самом начале указать parent::Model. Это необходимо делать для того, чтобы, конструктор вашего класса не перекрывал конструктор класса Model. Итак, давайте взглянем на функцию с именем get_last_record();. В первой строчке тела этой функции я обращаюсь к классу db и вызываю функцию order_by(). Эта функция позволяет установить оператор ORDER BY для будущего запроса. В качестве параметров, функции нужно передать:
Делаем контроллер Мы создали модель, теперь нам предстоит создать контроллер, который сможет плодотворно с ней работать. Создайте
•
• •
поле, по которому нужно упорядочить данные - направление упорядочивания. В блогах принято, чтобы новые записи были в самом верху, поэтому в качестве имени поля я передаю «date», хранящий дату публикуемого топика, а во втором параметре указываю desc (по убыванию). Установив Order by, можно смело выполнять запрос. Для простого получения данных в AR есть метод get(), который принимает два параметра: имя таблицы, из которой выбирать данные количество записей для выборки
Думаю, с выборкой данных все понятно и вы уже смогли прочувствовать прелести использования ActiveRecords, теперь давайте взглянем на то, как делается добавление новых записей в таблицу. А делается она очень просто. Для вставки используется метод insert() класса db. Методу нужно передать всего лишь два параметра: • •
имя таблицы массив данных, в котором ключ – это имя поля в таблице
новый файл и перепишите в него код из листинга 2. Хочу сразу предупредить, что во втором листинге приведен лишь отрывок кода, полный исходный текст вы можете получить по ссылке в конце статьи.
Листинг 2. Контроллер. class Blog extends Controller { function index() { $this -> load -> model('MBlog', '', TRUE); $data['data'] = $this -> MBlog -> get_last_record(); $this -> load -> view ('vblog', $data); } }
Первое, с чего начинается новый контроллер – с описания нового класса-
наследника от Controller. Для нашего примера я объявил класс Blog. В самом
классе, нам нужно описывать функции, имена которых будут с url’ами. Например, объявив функцию foo(), и обратившись по адресу http://localhost/index.php/blog/foo мы спровоцируем ее выполнение. Но вернемся к нашему листингу. Сразу после описания класса, у меня идет объявление функции index(). Функция с таким именем будет автоматически вызывать при обращении к нашему контроллеру (http://localhost/index.php/blog). В теле этой функции, я в первую очередь инициализирую созданную нами модель. Для инициализации используется loader load -> model. В качестве параметров я передаю ему имя созданной нами модели и также значение true, указывающее на то, что установка с БД должна произвестись автоматически. После инициализации модели я сразу обращаюсь к одной из ее функций – get_last_record(). Как вы помните, после выполнения, эта функция возвратит все имеющиеся в ней записи. Полученные данные нужно отправить пользователю, для этого я загружаю представление vblog. Для загрузки представлений используется
конструкция load -> view(). Из параметров нужно передать: • •
Имя представления Данные, из которых будет формироваться страница для пользователя.
Пример исходного текста представления вы можете посмотреть в листинге 3. Я не буду подробно расписывать содержимое листинга, поскольку все, что в нем происходит – печать данных стандартными средствами php. Единственное, что нуждается в объяснении – получение имен переменных. Как ты помнишь, при вызове представления, в качестве третьего параметра мы передавали массив с данными. Получение значений осуществляется через переменные, имена которых равны именам ключей передаваемого массива. Например, если у нас есть массив array с ключом sample ($array[‘sample’]), то для того, чтобы получить доступ из представления к значению sample, нам нужно из представления всего лишь на всего обратиться к переменной $sample.
Листинг 3. Первое представление <html><head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <?php echo link_tag('style/style.css') ?> <title>Блог на CodeIgniter</title> </head><body> <div id = "content"> <!-- Топик --> <div class = "post"> <?php foreach ($data as $row): ?> <h1 class = "title"><?php echo $row -> caption ?></h1> <div class="entry"><p> <?php echo $row -> text; if ($row -> extext) { print (" { <a href= \"" . base_url() . "index.php/blog/viewfull/" . $row->id . "\" class = more>Читать дальше</a> }"); }?></p> <p class="byline"><?php print($row -> author . ", " . $row -> date); ?></p> </div> <?php endforeach; ?>
<!-- Топик --> </div></br> </br> <a href = " <?php print(base_url() . ' index.php/blog/add">' . img('images/addbtn.png') . '</a>');?> </div></div></body></html>
Тестируем пример Уже сейчас вы можете запустить и увидеть работоспособность нашего простенького
блога. Перед тем как запускать сей дневник, добавьте в базу данных пару записей, иначе при после запуска блога вы увидите чистую страницу.
Рисунок 5 (Блог в действии) Некрасивые url Посмотрев наш «блог» вы наверняка заметили в адресной строке url вроде http://localhost/index.php/blog. Такой url выглядит ужасно и совершенно не годится для реального проекта. Для улучшения внешнего вида url, я рекомендую вам воспользоваться возможностями плагина mod_rewriter WEB-сервера Apache. С его
помощью вы быстро должному виду.
приведете url к
Заключение К сожалению, рассмотреть все возможности Code Igniter в рамках одной статьи простонапросто невозможно, да и не нужно. Моя цель была рассказать вам про такой интересный продукт как Code Igniter и я
думаю, что эта задача выполнена. Все, что сегодня осталось за кадром, вы всегда сможете почерпнуть из официальной документации. Мне остается пожелать вам только удачи!
ВРЕЗКИ Документация по CI
http://www.codeigniter.com/ - официальная документация. http://www.codeigniter.com/wiki/ - официальное Wiki http://www.code-igniter.ru/ - официальная документация, переведенная на русский http://www.simplecoding.org/category/code-igniter - познавательные статьи по CI http://www.alexajax.com/ - xAjax + CodeIgniter http://www.phpeveryday.com/ - отличный информационный ресурс по php и CodeIgniter в частности. Содержит множество тем и примеров кода. Дополнения к CI
http://codeigniter.com/wiki/Simple_Authorization_Lib/ - библиотека для автоматизации процесса авторизации. http://www.codeigniter.com/wiki/PHPSession/ - работа с сессиями упрощается в разы, если воспользоваться этой библиотекой. http://codeigniter.com/wiki/XAJAX/ - достаточно популярная библиотека для использование Ajax в ваших проектах. http://codeigniter.com/wiki/jQuery/ - еще одна библиотека для работы с Ajax. http://codeigniter.com/wiki/Form_Library/ - библиотека упрощает работу с формами. http://codeigniter.com/wiki/Yet_Another_Template_System/ - отличный шаблонизатор http://codeigniter.com/wiki/FCKeditor/ - удобный WYSIWIG TOP 5 CMF
1. CakePHP (http://cakephp.org/) – бесплатный фреймворк для быстрого создания WEBприложений. Главное его отличие от всех подобных продуктов – необычайная похожесть на известный каждому Ruby программисту фреймворк Ruby On Rails. Разработчики CakePHP приложили максимум усилий, чтобы приблизиться ко всем известному RoR. Поэтому этот фреймворк рекомендуется попробовать всем, кто разрабатывает на PHP, но мечтает постичь мощь RoR. 2. Mzz (http://mzz.ru) – молодой, но уже успевший завоевать популярность фрейморк от российских разработчиков. Как и подобает «правильному» CMF, платформа Mzz основа на классической архитектуре разделения бизнес-логики и представлений (MVC). Помимо этого Mzz это: гибкость конфигурирования, собственный ORM на базе The Data Mapper Pattern, высокая скорость работы. 3. Adept (http://adept-project.com) – нестандартный CMF, обладающий широкими возможностями, высокой скоростью работы и стабильностью. Нестандартность этого проекта в том, что он не использует повсеместно популярную модель представления данных (MVC), а использует компонентный подход. По сути, Adept – это куча полезных компонент, без которых не обходится ни один, более-менее профессиональный WEB-проект. 4. PHP Compiler CMF 2.4.5 (http://www.phpc.ru/) – функциональный фреймворк, позволяющий даже непрофессиональным программистом создавать «произведения искусства». Из наиболее
интересных возможностей выделяются: полная совместимость с php4 и php5, плагинов, поддержка шаблонов, разделение дизайна и кода, генерация ЧПУ.
поддержка
5. Symfony 1.2 (http://www.symfony-project.org) – профессиональный фреймворк на основе MVC. Некоторые считают это продукт весьма сложным для обучения, другие наоборот восхищаются его продуманностью, но Вам я рекомендую самим попрактиваться с этим «чудо зверем». Среди возможностей наиболее выделяются: написан полностью с учетом всех возможностей PHP5, достаточно охватывающая документация и примеров кода (правда, на английском), хорошая скорость работы. Почему именно Code Igniter?
1. Полностью бесплатен и свободен. 2. Простой в обучении. 3. Легко расширяем. 4. Высокая скорость работы. 5. Прекрасно документирован.
Исходники к статье ищи в папке «CodeIgniter» Written by Антонов Игорь aka Spider_NET Email: antonov.igor@live.ru; spider_net@vr-online.ru
Ох уж эти спамеры Как знакома всем ситуация, когда почтовый ящик набит до отказа письмами, из них лишь два, три от друзей, а остальные нам прислали всякие дяди Феди, занимающиеся спамом. Сколько времени и драгоценного трафика нам приходится тратить, чтобы убрать результат работы дяди Феди. Наверняка, не всем нравится удалять письма со спамом в корзину. Ладно бы один раз, а то и каждый день. Лично мне это порядком надоело и я взялся писать эту статью, дабы помочь в нелегком деле борьбы со спамерами. Итак, вы открываете электронную почту, а там письма с предложениями всякого рода услуг, вы удаляете это письмо, но через несколько дней приходит такое же письмо. Неприятно? Мне тоже. А как же быть? Что ж все по порядку. Зачем все это нужно спамерам? Да все просто, они получают за рассылку спама выгоду, а точнее когда вы кликаете по рекламе, а потом что-либо заказываете из предложенного товара, то естественно вы должны будете оплатить товар. На таком примитивной примере я объяснил вам назначение спама. Поэтому первое что нужно помнить и соблюдать в ситуации, когда вам в ящик попал спам – это не кликайте по ссылкам. Одно дело, если это будет ссылка на безобидный сайт с порно, а что если это ссылка передаст управление скрипту, вирусу, трояну и т.п. Тогда вы можете распрощаться со всеми своими паролями, номерами кредитных карт. Все зависит от изобретательства и сообразительности спамеров. Можно конечно отметить письмо и нажать на кнопку с надписью «Спам» или что-то в этом духе, но я на своей практике проверил бесполезность этой функции. Не секрет, что некоторые почтовики продают базы адресов электронной почты спамерам. А вы думали откуда у них ваш адрес. Нет, ну конечно же вы могли его оставить на каком-нибудь сайте при регистрации или в качестве контактной информации. А если вы несколько дней назад завели новый почтовый ящик, да и еще со сложным
аккаунтом, но ваш новый ящик снова забит до отказа, тут уже по неволе начинаешь задумываться об продажности почтового сервера. Ладно, теория одно, а практика еще лучше. Вот основные приемы борьбы со спамерами: 1. Иногда дядя Федя заводит себе отдельный ящик для рассылки спама. В этом случае можно посмотреть на его адрес и написать в администрации сервера на котором зарегистрирован спамер. Но если письмо приходит от вашей симпатичной подружки, то это еще не значит что нужно звонить ей на мобильник и вспоминать всех ее родственников. В этом случае ваша подруга могла таким же образом получить письмо от спамеров и кликнуть ссылку или запустить прикрепленный файл. Этот файл, в свою очередь мог быть вирусом или трояном. Таким образом ее компьютер превратился в зомби, а это значит что нужно запасаться цветами и коробкой конфет и идти к подруге и лечить комп от вирусов, но это уже другая история. 2. Второй способ заключается в перенятии методов дяди Феди, а именно можно посмотреть на адрес спамера и идти в ближайший интернет-центр и с помощью почтового бомбера забомбить ящик спамера. Можно использовать специальные услуги сайтов, которые позволяют отправлять заданное количество писем. Главное чтобы бомбардировка велась не со своего компа, иначе вас занесут в черный список, а как вам известно, за спам могут дать срок. 3. Третий способ является продолжением второго, но не его повторением. Итак, у вас есть адрес спамера, идите на ближайший
порно сайт и везде, где только возможно оставляйте почтовый адрес дяди Феди. Сочувствую ему: после того как его коллеги найдут оставленный вами адрес, спамеры заполнят его ящик мусором. Ну так что ж, пусть дядя Федя сам получает спам и разгребает его. Надо прочувствовать вкус и все прелести своей работы. 4. Опять же разновидность описанных мною способов, но опять же способ имеет все основания быть написанным под другой цифрой. Дело обстоит так: берете адрес спамера, а иногда дядя Федя оставляет номер телефона, причем почти всегда реальный и бегом на сайт знакомств. Эх, чуть не забыл, найдите фотку симпатичной девченки и для полного счастья фотку парня. Со всем этим вооружением идем на сайт знакомств регистрироваться. Как? Вы указали свои данные? Немедленно исправляйте. Пишите в анкете в таком плане: симпатичная девушка хочет познакомиться для серьезных (или не очень серьезных J) отношений и т.п. Звонить желательно после 22-23 часов. Оставляете фотку, да не перебощите, а то выберете фотку известной модели и эффект будет уже не тот. А как же быть с фоткой парня? Да так же. Только в анкете пишите: симпатичный гей……Дальше дело вашей фантазии.
Written by Sergio_Black E-mail: assaults@bk.ru
Представляете, когда на почту спамера идут различного рода предложения, а если в анкете телефон фирмы еще и с именем сотрудника, то спамеру придется несладко. 5. Для самых отпетых как спамеров так и пользователей, я предлагаю вычислить адрес, в данном случае место жительства, и приехать в конторку или домой к спамеру и набить ему морду. Но это противозаконно так же как и распространение спама и тут может вступить в силу УК РФ. Так что в этом случае нужно подумать прежде чем что-то делать. 6. И напоследок самое интересное. Мы же хакеры, что нам ящик, да пятиминутное дело – взломаем. В общем, если ты силен в хакинге, то можешь взломать ящик спамера, его сайт или его аську. Так что многое зависит и от нас самих. На мой взгляд, спам будет существовать еще долго, ведь он приносит прибыль, а нам неудобства. И неизвестно когда в сети будет порядок. P.S. Уважаемые спамеры, я уверен что после написания этой статьи я подвергнусь вашей усиленной атаки. Словом, можете не пытаться, ваши действия могут быть направлены против вас же самих. Кто к нам со спамом придет, тот от спама и погибнет.
Первое впечатление об IT-шнике Для начала давайте определимся, кто такой айтишник. Многие, не имеют четкого представления о том, кто такой IT-шник и чем он занимается. А знаете, я даже специально загуглил вопрос, и первое что меня поразило – это то, что айтишника обозвали ботаником. Этот ответ я нашел в социальных сетях одного почтового сервера, не буду показывать пальцем, сами догадаетесь. Плохим тоном в таких сетях являются неправильные ответы на вопросы. Я даже не понимаю, зачем отвечать на вопрос, причем адресованный главным образом не тебе, а компетентным пользователям. Хорошо, каждый старается помочь, но зачем писать «лишь бы написать»? Этого я никогда не понимал и не понимаю. Для начала определимся с терминологией. Многие знают такое понятие как «информационные технологии», другим словом «IT». Почему же не все отталкиваются не от этого понятия, а от ботаника? Ладно, с ботаником мы разберемся чуть позже. Как я уже сказал нужно отталкиваться от «информационных технологий». Информационные технологии подразумевают под собой широкий спектр дисциплин и деятельности, связанных с вычислительной техникой. Другим словом, информационные технологии – это все то, что связано с компьютерами. Как видите, ничего сложного и про ботаников здесь не упоминается. Следовательно, айтишник – человек, занимающийся информационными технологиями. А для тех, кто еще не в танке: айтишник – это программист, системный администратор, системный аналитик, специалист по безопасности, специалист по ремонту компьютеров, человек занимающийся установкой и сопровождением софта. Все предельно просто. А вот теперь разберемся с ботаниками, а точнее с теми, кто называет айтишников ботаниками. Каждый человек в своем развитии проходит стадии развития, взросления. То есть, достигнув 7-летнего возраста, ребенок идет
в школу, после школы поступает в колледж, институт. В институте или колледже каждый выбирает себе специальность. После окончания соответствующего заведения здравомыслящий человек ищет работу. Если работа человеку не нравится, то соответственно атмосфера накаливается, человек постоянно срывается на коллег, обвиняя во всем не в чем неповинных людей. В итоге ему приходится искать другую работу или уходить в другую сферу деятельности. Иначе дело обстоит с теми, кому нравится работа. Человек всегда доволен жизнью, приятная рабочая атмосфера и он согласен работать за любую, пусть даже низкую заработную плату. Но это еще не предел. Человеку нравится его работа, он продолжает развиваться дальше. Для этого ему необходима пища, но не та, которую готовит жена, а духовная. Да, именно духовная. Что я хочу сказать? А хочу я сказать, что необходимо читать книги. Но так как я говорю про айтишников, то многие поймут о чем я. Дело в том, что информационные технологии не стоят на месте, а постоянно идет движение вперед, соответственно для повышения своего уровня знаний необходимо читать что-то новое. Так вот, многие видят что айтишники постоянно что-то штудируют, целыми сутками сидят за компьютерами, едят только за компьютером и лишь отрываются от него только для того, чтобы пару часиков поспать (сужу по себе). Благодаря такому ложному видению, многие думают что айтишники помешаны на компьютерах. Но это далеко не так. Как я уже сказал, информационные технологии охватывают широкий спектр дисциплин и деятельности, следовательно, айтишнику просто не хватает времени для лучшего изучения компьютера.
Written by Sergio_Black E-mail: assaults@bk.ru
Советы начинающим sys. админам и не только Так уже получилось, что в январе этого года мне пришлось сменить работу. Нет, дело не в кризисе. Меня не сократили, я просто ушел сам. Причины банальные: предложили более оплачиваемую работу и должность. Честно говоря, я сначала не хотел соглашаться, но, к сожалению деньги, сделали свое (семью кормить то надо) и я решился. Вот так я и превратился из простого программиста в начальника отдела программного обеспечения. Название должности многого обещающее, но сначала я стал и начальником и подчиненным в одном лице. Дело в том, что в компании раньше вообще не было такого отдела, и я должен его в последствии сформировать и набрать людей. С чего все началось Найти людей не проблема, вопрос только во времени. А вот его всегда не хватает. Так уж вышло, что предыдущие системные администраторы не сильно жаждали работать, поэтому состояние всех компов на время моего прихода было не просто отвратительным, а ужасным. Суди сам, никаких антивирусных программ (пардон, на парочке машин я обнаружил AVP от 2003 года J), при слове backup все пожимали плечами, на большинстве ПК установлена XP с SP (попалось парочка компов с XP вообще без SP) и т.д. Отсутствие антивируса давало о себе знать постоянно. Компы периодически ребутились и виснули. Одним словом – кошмар. Когда я увидел все это в первый день, то мне стало жутко. Первая мысль в голове: «Куда я попал?». К концу дня я был измученный бесконечными бегами по офису (ну не признавал предыдущий админ софт для удаленного администрирования) и тупыми вопросами пользователей. Повторюсь, до этого я к системному администрированию имел посредственное отношение. До этого мне не приходилось этим профессионально заниматься, были лишь теоретические знания и опыт, полученный на «домашних» экспериментах. На второй день я принял кардинальное решение все изменить и автоматизировать по полной программе. Идея «бегать как белка в колесе» меня не прельщала, и я принялся за дело. Сейчас я не могу сказать на сколько мои решения были рациональными, но во всяком случае я
избавился от бесконечных жалоб и самое главное беготни. Тем самым я смог выкроить время на другие, более интересные проекты для компании. И теперь хочу дать несколько советов именно начинающим администраторам, которые в начале своей «админской» карьере могут попасть в такую же ситуацию как я. Совет №1: Научись планировать
Правильно и рационально использовать свое рабочее время – это самая первая и важная по приоритету задача. Причем это относится абсолютно к любой должности, а не только для «сис. админа». Я говорил, что сначала я был сам себе хозяин и слуга, следовательно, на меня ложились задачи абсолютно все задачи (поддержка пользователей, отчеты для начальства, проекты и т.д.). Если не расписывать каждый день, то запросто можно сильно увлечься одним делом и совершенно не успеть сделать другое. Поэтому рекомендую сразу же завести ежедневник и планировать каждый час рабочего дня. До этого я никогда не пользовался такими книжечками, но теперь просто тащусь. Несомненно, бумажный ежедневник вариант чертовски не гиковский, но в некоторых случаях бумагу тяжело заменить всякими гаджетами. Особенно на всяких планерках и конференциях. Как ни крути, но пометки лучше делать обычной ручкой, нежели юзать клаву нетбука или КПК/Коммуникатор. Я вообще сейчас работаю по такому принципу. Каждый
вечер составляю план на завтрашний день и записываю в ежедневник, а потом забиваю в свой коммуникатор все встречи. Для встреч и собраний приоритет особенный и уж лучше перестраховаться. Коммуникатор все-таки всегда со мной и он обязательно напомнит сигналом, что меня ждет босс или кто еще J. Совет №2: Проведи инвентаризацию имеющегося оборудования
Как правило в любой компании есть запасной резерв всевозможных ком. запчастей, мониторов и т.д. Обычно (сужу по трем отделам автоматизации, которые я видел) все это хозяйство валяется в неупорядоченном виде и если срочно требуется найти какую-нибудь зап. часть, то можно обломаться. А каждый облом стоит денег (ведь если нет, нужно покупать) и времени. Хорошо когда что-то сломалось о обычного юзера и он может посидеть и потерпеть пока ты сходишь/закажешь в магазине нужный девайс, а если у глав. буха погорела оперативка или блок питания? А ему как назло сдавать отчетность! При таком раскладе будет много криков и тебе придется сломя голову нестись в ближайший комп. магазин и покупать испорченный девайс. Удовольствие от этого процесса весьма сомнительное и сразу начинаешь задумываться, а хорошо было бы если бы имелся минимальный набор запчастей. Тогда все можно было быстренько заменить и вернуться к более интересным делам. Думаю, ты понял к чему я клоню. Уберись на "складе" и по возможности закупи необходимые зап. части - блок. питания, винт, память и т.д. Если начальство не хочет тебя спонсировать на это дело, то попытайся объяснить все суть проблем, которые могут возникнуть если прибегнуть к экономии. Слова "штраф", "опоздать сдать в налоговую документы" обычно хорошо помогают изменить мнение жадного босса. Больше ничего не могу предложить, т.к. у меня начальник в этом плане меня понимает и не скупится на зап. железо.
Совет №3: Картридж и еще раз картридж
В конторе которой я работаю все пользователи без устали печатают. Документооборот большой и на распечатывание документации картридж уходит особенно быстро. Например, в неделю я стабильно меняю 5-8 картриджей по всей компании (35 раб. мест). Пользователи чья работа напрямую зависит от возможности "печатать" очень не любят, когда кончается картридж и его нечем оперативно заменить. Последствия возникают самые разные, начиная от простого легкого крика, заканчивая жалобами вышестоящему начальнику. Поэтому настоятельно рекомендую иметь 23 штуки заправленного каждого вида картриджа в запасе. Израсходованные за неделю картриджи лучше сразу же нести в заправку, чтобы к след. рабочей неделе опять был необходимый резерв. Совет №4: Семь раз отмерь, один раз нажми "Ok"
Перед тем как выполнить очень важную операцию всегда несколько раз подумай. Вполне возможно бывает, что по запарке можно понадеяться на машинальную память и тупо кликать по кнопкам, а потом окажется, что при разбиение диска был выбран не тот диск и все важные данные улетели в тар-тарары. Звучит бредовая и ты конечно можешь возразить, что так лохануться это последнее дело, но уверяю тебя, когда у многих что-то не работает и разрывается телефон, то по-неволе начинаешь торопиться и обращать минимум внимания. Самое обидное, что озарение приходит тогда, когда действие нельзя отменить. Чтобы не ломать голову над исправлением проблемы, лучше быть чуточку внимательней и свести к минимуму возможность совершения ошибки. Совет №5: Если что-то можно автоматизировать – автоматизируй!
Я уже говорил, что моя основная работа всегда была связана с программированием. И честно говоря во мне уже сложился принцип - человек не должен делать рутинную работу. Ведь именно для этого и придумывали изначально компьютеры. К чему, это я. Ах, да! В любой компании администратору поручают рутинные задания. Например, сделать бэкап базы, выложить обмен и т.д. Хорошо когда программа, в которой должны выполнятся эти операции имеет встроенный планировщик и позволяет запрограммировать нужную операцию на ежедневный запуск и забыть об этом. А если нет? Что тогда? Делать руками? Если тебе никуда тратить время, то можно делать и руками, а я люблю тратить время с умом и с пользой, поэтому в таких случаях использую самописные сценарии. Практически любую последовательность операций можно выполнить с использованием возможностей командной строки (в unix-like системах вообще все можно), поэтому настоятельно рекомендую покурить соответствующей документации и закодить скрипты под свои нужды. Например, для обмена данными между филиалами по протоколу FTP я написал простейший сценарий, задача которого сводится к отправке и закачки пару файликов. Добавил запуск сценария в планировщик и все. Процедура выполняется три раза в день и я в это время занимаюсь своими делами. Очень удобно, а главное не сложно. Совет №6: Корпоративная почта
Если в твоей компании больше от 10 и больше ПК, то не поленись и подними внутренний почтовый сервер. Плюсов в этом решении множество: 1. Отмазка пользователей: "Я отправил, а письмо не дошло" - становится не актуальной. Ты всегда можешь глянуть логи и узнать, кто-куда и во сколько по времени отправил.
2. Быстрый обмен информацией внутри компании. Я очень люблю использовать почту, для отправки каких-либо документов сотрудникам сидящим в соседнем кабинете. Создал письмо, кинул пару файликов и все готова. Когда есть внутренний сервак, то проблема расходования трафика и скорости доставки становится неактуальной. 3. Рули сервером по своему усмотрению. Когда почта располагается на серверах провайдера, то автоматически возникает проблема фильтрации на спам. Ладно, если ты пользуешься услугами от Google. У них пожалуй самый продвинутый спам фильтр, поэтому есть гарантии, что спама будет очень мало. А если твой провайдер - это небольшая провинциальная компания? В этом случае через несколько дней, ящики юзеров будут наполнятся свежим и тепленьким спамом. Ведь многие провайдеры не дают особой власти администраторам и предоставляют минимум настроек для управления фильтром. Со своим почтовым сервером ситуация с точностью да наоборот. Здесь ты бог и хозяин и можешь делать все что угодно. Совет №7: Научись грамотно излагать свои мысли
В 99% главный босс (н-р, генеральный директор) плохо разбирается в компьютерах и все что с ними связано. Это логично. Ему не нужно знать что-такое северный мост или нюансы протокола TCP, его цель руководить коллективом, а твоя грамотно с ним взаимодействовать (в случае если все задачи идут напрямую от него). Одна из основных стен, которые возникают между сис. админами/нач. отделов автоматизаций вопросы выделения финансовых средств на что-либо. Ладно, если требуется купить лишний системник. Обычно с этим проблем нет. Ведь если у кого-то из сотрудников не будет ПК, то он не сможет работать приносить пользу компании. Совсем иная ситуацию при необходимости закупки дорогих и неизвестных боссу девайсов. Возьму пример из своей опять же
недолгой практики. Я живу на Дальнем Востоке и у нас супер быстрый и дешевый интернет только набирает обороты. В некоторых городках наблюдается проблема с провайдером (во многих городках их всегда по одному штуке), а в тех, где проблем с выбором поставщика услуг нет, вопрос упирается в конечную стоимость предоставляемых услуг. На моей новой работе в качестве доступа в инет - обычный DSL (ширина канала до 2Мбит). Стоимость этого "удовольствия" ~10 тыс. руб (за 5 ГБ трафика). На момент моего прихода компания потребляла в месяц 6-7 гектар. После моего прихода эта цифра увеличилась (Обновления, софт и т.д.). Я принял решение перейти на бизлимит. Из всех имеющихся предложений на рынке я нашел самый оптимальный вариант - 20 тыс. за ширину канала 1Мбит. Обрадовался я и пошел к боссу рассказывать про свою находку. Стоило мне сказать цифру, как с лица босса стал спадать энтузиазм на выделение денежек. Причина тому отнюдь не сумма, а цель приобретение анлима. В итоге мне пришлось подготовить бумаги, в которых я расписал цели, причины и выгоду, которую мы получим выбрав предложенный путь. Вот после знакомства с ними босс без лишних вопросов все подписал. К чему это я собственно распинаюсь. Да к тому, что нужно не боятся отстаивать свою точку зрения и обосновать свое решение человеку, который не является специалистом в данных вопросах. К сожалению (сужу по пред. админу) это делать научились еще не все. Результат этому - постоянные непонятки с руководством и проклинание ламеров :). Поэтому, если хочешь, чтобы босс тебя понимал правильно, не поленись и подготовься к переговорам. Найди причины по которым предстоящая сделка будет выгодна в первую очередь компании.
Written by Aнтонов Игорь E-mail: antonov.igor@live.ru
Совет №8: Backup - основа основ
По идее этот совет можно поставить вторым по счету, но мне захотелось сделать его 8 :). Запомни, backup важных файлов - это самое главное правило, которым должен руководствоваться системный администратор. Никто не скажет тебе спасибо за чудные сервисы в сети, если у бухгалтера посыпится жесткий диск и все данные улетят в небытие. Поэтому обязательно выдели отельный винт для файлообменника и регулярно бэкапь на него особо важные данные. Не нужно полагаться на авось (хотя из-за постоянной загруженности на него и и приходиться полагаться), лучше сразу принять необходимые меры и спать спокойно. Совет № 9: Только нужные права
Помни, что у пользователей должны быть только те права, которые им реально нужно. Если пользователю требуется только просматривать общедоступный документ, то значит, ни в коем случае он не должен иметь права изменять его. Пусть документ сегодня не представляет особой важности, но завтра все может измениться и если неродивый пользователь его случайно удалит, то задачи по восстановлению скорей всего возложат именно на тебя. Совет № 10: Ремонтируй только то, что нуждается в ремонте
Суть этого правила проста как две копейки. Если нет поломки, то не стоит пытаться это отремонтировать! Очень часто, многие нач. сисадмины пытаются произвести улучшения, выигрыш от которых на самом деле минимальный, а вот допущенные ошибки при этом могут дорого стоить.
Знакомимся с Jabber Пришло время, чтобы ознакомить Вас с системой обмена мгновенными сообщениями, которая в последнее время набирает большие обороты, но до сих пор еще многим неизвестна, в силу своей специфичности и необычности. Данная система носит гордое название - Jabber, (переводится как "болтун", "трепач"). Она относится к категории открытых систем, что уже является немаловажным критерием в дальнейшем развитии, тем более, что она построена на основе, опять же, открытого протокола XMPP, а это говорит о возможности расширения данной системы. LiveJournal, Google Talk, Gizmo и другие крупные компании, давно открыли свои сервера, в основе которых стоит протокол XMPP (чуть ниже мы рассмотрим простой способ взаимодействия ЖЖ с жабберклиентом). Система jabber является децентрализованной, т.е. любой желающий может открыть свой сервер мгновенных сообщений, при этом существует возможность взаимодействия с другими серверами jabber, ну и конечно возможна регистрация пользователей на своем созданном сервере. Это будет удобно в первую очередь организациям, которые могут оградиться от общедоступного сервера - корпоративная сеть. Ну и для любой организации важна безопасность большинство реализованных серверов используют SSL/TSL, а также возможно шифрование с помощью PGP/GPG, последнее доступно внутри протокола. Как я говорил выше, протокол XMPP расширяем, это возможно благодаря тому, что в его основе лежит язык XML, и с помощью пространств имен можно "заточить" протокол jabber, для своих конкретных задач и целей. Для того чтобы идентифицировать пользователей в jabber, используется уникальный идентификатор, называемый JID, который похож на адрес электронного ящика - user@server.ru, содержит имя пользователя, а после символа @ - доменное имя сервера. Один пользователь может иметь несколько подключений, но для этого введено дополнение для JID'а, которое называется ресурсом, оно добавляется в конец идентификатора через слэш -
user@server.ru/myresourse. Здесь надо запомнить одно правило: сообщение отправленное для пользователя user@server.ru, дойдут на указанный адрес, вне зависимости от имени ресурса и сообщение отправленное для user@server.ru/myresourse, дойдет только на этот адрес, притом, что данный ресурс будет подключен. Есть еще одна особенность адреса JID могут также использоваться без явного указания имени пользователя (с указанием имени ресурса или без такового) для системных сообщений и для контроля специальных возможностей на сервере. Расширяемость протокола возможна благодаря его открытости, в отличие от коммерческих, любому пользователю доступны библиотеки с открытыми исходными кодами, поэтому просторы для экспериментов просто огромны. Не лишним будет сказать, что jabber-сообщество многообразно, поэтому существует большое количество проектов с открытыми исходными кодами, большой набор серверов и все больше и больше компаний, разрабатывающие ПО, используют протокол jabber. Есть поддержка так называемых шлюзов в другие IM-сети, но, увы, пока их реализация зависит от конкретного Jabber-сервера, и во многом нестабильность данной симбиоза, связана с закрытостью коммерческих сервисов. Каждый пользователь может создать огромное количество тематических конференций, к примеру, таких как в IRC, но при условии, что jabber-сервер поддерживает данную функцию, кроме этого, конференции можно подключать как транспорт.
Разбавим немного, "сухую" теорию, историей развития jabber'а. Свое начало jabber берет еще (хотел сказать в далеком, но проект то совсем молодой!), с 1998 года, и все началось с разработки сервера jabberd. Но только 4 января 1999 года Slashdot опубликовал первое сообщение о проекте, после чего к проекту начали стягиваться разработчики, закипела работа над сервером jabberd и клиентами jabber для Windows и GNU/Linux, несколько позже началась работа над шлюзами в основные системы IM (AIM, ICQ, MSN, и Yahoo). В этом же году, Webb Interactive Services активно спонсирует разработчиков, что приводит к ускорению процесса развития проекта. Уже тогда появляется основа протокола Jabber, а также сервер jabberd и ранние клиенты, такие, как WinJab, который получил свое развитие в Exodus, и Gabber. Постоянные изменения закончились лишь в мае 2000 с выпуском jabberd 1.0., но в 2001 году контроль над проектом получает Jabber Software Foundation и начинается новый виток в развитии протокола jabber - в 2003 году было четыре реализации сервера, выложены несколько библиотек для разных языков программирования, созданы клиенты для многих платформ от Amiga до Microsoft Windows. 16 января 2007 года, "Jabber Software Foundation" меняет свое название на "XMPP Standards Foundation", для того чтобы более точно отразить род своей работы развития расширений собственно протокола. В марте 2008, инвесторами проекта уже являются France Telecom, Jona, Inc., Intel Capital, и Webb Interactive Services. История у данного проекта давольно богата, поэтому существует большое количество клиентов поддерживающих протокол jabber. Рассмотрим некоторые из них. Клиент LJTalk предназначен для обмена сообщениями по протоколу XMPP проекта Livejournal. Использовав в качестве JID'а аккаунт с LiveJournal, вы имеете возможность постить сообщения в свой журнал через данный клиент, а также общаться с пользователями ЖЖ, но только с теми, которые являются вашими
"френдами". Другой клиент - Google Talk, кроме передачи сообщений по протоколу XMPP, имеет возможность голосового общения. Еще один клиент, набирающий обороты Я.Онлайн, уведомляет пользователей о новых письмах. Не обделены и пользователи мобильных устройств, для них создан клиент Talkonaut - удобный клиент с поддержкой Java, для обмена сообщениями по протоколу Jabber, Google Talk и Gizmo Project, с возможностью использования IP-телефонии (VoIP). Достаточно приемлемым к использованию является Psi (свободная программа для обмена сообщениями по протоколу Jabber), Gajim (тоже предоставляющая возможность общения по протоколу jabber и основанная на Python и PyGTK). Отдельное место в этом списке клиентов занимают многофункциональные клиенты, которые поддерживают различные протоколы: Trillian, QIP Infium, Adium, Kopete и др. В jabber-клиентах организован инструмент для мониторинга входящих и исходящих сообщений (станз). Станза представляет себой законченный элемент XML-потока, содержащий в себе необходимую управляющую информацию: <message to="leksey" id="5"> <subject>Заголовок</subject> <body>Текст сообщения</body> </message>
Прямо из консоли можно отправить свою станзу, но следует учесть, что при неверном синтаксисе станзы будет показано сообщение и произойдет отключение. В заключении хочу сказать, что если всетаки мне не удалось вас убедить использовать jabber-систему (а данной целью я не задовался), то рекомендую просто испробовать ее на "вкус" ради любопытства, уверяю, вы найдете в ней много нового и интересного для себя. К тому же, что может быть лучше развития и познания, новых вещей, вне зависимости от того, пригодятся ли они в будущем или нет.
Written by Jimmy Jonezz www: www.Liveofpc.3dn.ru
ГРАФИКА •
Учимся рисовать иконки
Учимся делать иконки Привет! Сегодня мы будем рисовать иконки в photoshop’е. Для чего это нужно, я думаю, объяснять не стоит. И так всё понятно – и для программы, и для интерфейса той же программы, для докеров, для виджетов, для той же венды, в общем, применений сегодняшней работе можно найти массу. Не будем отвлекаться и сразу начнём – открывай наш главный инструмент на сегодня (я про photoshop, если что ;) ). Создавай новый документ размерами 256х256. Это довольно большой размер для иконки, но ведь уменьшить всегда проще, чем увеличить. Да и при маленьком размере сложновато рисовать мелкие детали будет. Я бы даже посоветовал сделать разрешение изображения не 72 точки на дюйм (72 – это
стандартное значение photoshop’а), а где-то 150-200, но от этого увеличится размер иконки, а это не очень то и хорошо, так что это дело каждого. Но я, например, оставил 72.
Нарисовать её можно несколькими способами, например линиями или даже карандашом. Но я рисовал своим любимым
и ИМХО самым простым способом – сначала при помощи Rectangular Marquee Tool создаю прямоугольное выделение,
Итак, первой мы будем рисовать иконку монитора, которую можно и применить как иконку Моего компьютера. На пустом слое рисуй вот такую рамку белого цвета:
заливаю его нужным цветом (в данном случае белым), затем иду в Select-Transform Selection и чуть-чуть уменьшаю размер выделенного поля, затем жму кнопку Del, и ненужная часть удаляется, остаётся только рамка.
Рамка нарисована, теперь немного придадим ей объёма. Идём в Layer Style слоя с рамкой и применяем Bevel and Emboss с настройками, как на скринах ниже:
Теперь нарисуем наш экран. Это будет просто чёрный прямоугольник на новом слое, под слоем с рамкой монитора.
Далее нарисуем блик на мониторе. Для этого создавай новый слой над слоем с экраном. Вооружайся инструментом перо
(Pen tool) и рисуй примерно вот такую загогулину:
Теперь делай из получившейся фигуры выделение и выбирай инструмент Gradient Tool, цвета выбирай от белого к
прозрачному и заливай выделение так, чтобы получилось что-то похожее на это:
Отменяй выделение (Ctrl+D), щёлкай левой кнопкой мыши по слою с экраном, удерживая Ctrl, создастся выделение, нажимай Ctrl+Shift+I, для инвертирования
выделения, и нажимай кнопку Del, удалится ненужная часть нашего блика, останется только на экране:
Теперь будем рисовать ножку, на которой наш монитор будет стоять. На скрине выше она уже показана. Рисовал я её при помощи прямоугольного выделения, на новом слое, естественно (слой я разместил ниже остальных). Применил Bevel and Emdoss с такими же настройками, как и у рамки монитора, и градиентную заливку от светло
серого к белому (всё это я делал в свойствах слоя). Ножка готова, давай поставим её на подставку. Подставку я представляю в виде овала, так я и нарисую J На новом слое рисую овал при помощи Elliptical Marquee Tool. Применяю Bevel and Emdoss с теми же настройками, что и к ножке.
На скрине видно, что я немного подрисовал чёрной кисточкой на овале. Это я сделал для указания того, что в этом месте ножка входит в подставку. При увеличении это смотрится не очень то и красиво, но ведь это иконка и она будет довольно маленькой, так что при маленьком размере всё смотрится хорошо. Теперь нарисуем тень. Опять же можно это сделать многими способами: можно
Дальше подрисуем кнопочки, как это сделать я описывать не буду, потому что это очень просто))). При таком маленьком размере достаточно выделить их немного другим цветом.
нарисовать овал, залить его чёрным, немного размыть края, можно создать выделение овала подставки, чуть-чуть его увеличить, размыть края выделения (1) и опять же залить чёрным и понизить непрозрачность слоя. Но я поступил другим способом – создал отдельный слой, выбрал кисточку с мягкими краями и подрисовал где нужно, потом понизил непрозрачность слоя до 57%.
Я просто покажу свой вариант в маленьком размере, чтобы ты увидел разницу между иконкой в процессе рисования и в конечном итоге.
Теперь сохраняй свой результат в *.png и всё готово! (1) Размыть края выделения – я имел ввиду следующую последовательность действий: Select-Modify-Feather (Alt+Ctrl+D). Это делает края мягкими, т.е. при заливке такого выделения мы получим нечто похожее на кисточку с мягкими краями (в зависимости
от радиуса размытия). Так же этот приём можно использовать при фотомонтаже. Например, необходимо вырезать фигуру с фотографии и поместить её на другой рисунок, но фоны кардинально различаются. Если просто вырезать и вставить фигуру, то получится слишком резкий переход краёв. Для смягчения и применяют Feather.
Иконка с 3D текстом Продолжаем рисовать иконки. Следующую мы будем рисовать способом, про который я уже рассказывал – отрисовкой. Поэтому я не буду подробно описывать свои действия, лишь покажу основные моменты.
(Подробнее про отрисовку ты можешь прочитать в предыдущих выпусках vronline). Создавай новый документ размерами 256х256 и пиши свой текст (ведь в основе этой иконки будет текстJ ).
Я немного придал перспективы тексту при помощи Edit-Transform-Skew. Далее будет самая нудная и долгая работа – отрисовка. Но и на этом мы не остановимся. Чтобы
придать 3D объём тексту придётся некоторые линии подрисовать самому. Вот, что получилось у меня:
Далее начинаем разукрашивать наш текст. Для это при помощи волшебной палочки выделяй нужную плоскость, создавай новый слой и заливай цветом или градиентом (я пользовался градиентной заливкой от
красного к белому). Но некоторые грани текста стоит залить просто чёрным или серым цветом, те на которые не может попадать много света. Ниже мой вариант:
Почти всё готово! Теперь сливай все слои в один, создавай новый, выше слоя с 3Dтекстом. На нём мы будем рисовать блик. При помощи Elliptical Marquee Tool создавай выделение, заливай его белым цветом. Щёлкай левой кнопкой мыши по слою с текстом, удерживая Ctrl, создастся
выделение, нажимай Ctrl+Shift+I, для инвертирования выделения, и нажимай кнопку Del, удалится ненужная часть нашего блика. Можно просто понизить непрозрачность блика, а можно и поменять способ наложения. Я выбрал второй вариант и поставил Soft Light.
Вот почти всё и готово! Осталось только нарисовать тень (которую ты сможешь нарисовать сам, прочитав прошлые уроки) и если хочется можно нарисовать отражение. Да, и ещё! Контур
я рисовал чёрным, но в итоге больше склонился б белому. И чтобы сделать сам контур чуть пожирнее, я сделал обводку белым цветом в 1 пексел.
Written by Васючков Андрей aka Soffrick Email: soffrick@mail.ru; soffrick@vr-online.ru
SOFT •
Поднимаем интернет шлюз....
Поднимаем интернет-шлюз В абсолютно любой организации рано или поздно возникает необходимость организовать доступ во всемирную паутину для всех сотрудников. Понятное дело, что компания имеет в основном один интернетканал и нужно как-то ухитриться поделить его на всех. К счастью задача это совсем несложная и сегодня ее можно решить даже стандартными средствами Windows. Вот только такой вариант нельзя назвать гибким, т.к. при его использовании пользователи получают полную свободу доступа: их трафик не учитывается, инет доступен в полном объеме (нет ограничений на используемые протоколы и т.д.), нельзя выставлять ограничения для конкретных пользователей и т.д. В связи с этим нужно подыскивать более приемлемый вариант. Всезнайки и любители Unix-like систем сейчас закричат в один голос: «Для организации грамотных шлюзов есть FreeBSD и другие nix!». Несомненно, они правы, и я сам склоняюсь к такой же точки зрения. Действительно, настроить полноценный интернет-шлюз на FreeBSD не так уж и сложно для человека, который
имеет с этим опыт работы, а вот начинающим системным администратором, привыкшим использовать Windows – эта задача показаться достаточно сложной. Поэтому в своей статье я хочу подробно рассмотреть организацию шлюза именно на Windows с помощью проверенного временем продукта Kerio WinRoute Firewall.
Kerio Technologies?
Перед тем как перейти к рассмотрению установки и настройки этого продукта, я немного расскажу о его возможностях и о самой компании Kerio. После этого тебе будет проще определиться с вопросом: «Стоит ли его внедрять или нет». Начнем знакомство с родителя WinRoute – компании Kerio. Свое начало компания берет с уже далекого 1997 года. Именно в тот год компания впервые вышла на рынок программного обеспечения и представила, первый свой продукт – WinRoute Pro. Долго ждать популярности не пришлось. Разработанное приложение сразу стало завоевывать популярность и любовь среди администраторов Windows систем. Да, в то время были и альтернативные продукты, но большинство из них были сугубо под Unixlike и само собой они были достаточно сложны в изучении и поддержки. Продукт от Kerio был наоборот – достаточно производительным, безопасным и самое главное очень простым в использовании. Чуть позже в различных IT журналах стали публиковаться статьи, интервью с разработчиками и другие обзорноА что умеет WinRoute Firewall?
рекламные материалы. Это позволило разработчикам подняться еще на одну ступень славы. А дальше пошло поехало… В июне 2000 года, Kerio Technologies получает сертификацию ICSA и уже уверенно позиционирует на рынке как компания выпускающая действительно простой, богатый возможностями и что самое главное не дорогой (в плане цены) продукт для обеспечения безопасности. Сегодня компания Kerio продолжает развивать свой основной продукт, регулярно выпуская обновленные версии, а также вести разработку своего второго детища – Kerio Mail Server. Нетрудно догадаться, что это почтовый сервер, который как и WinRoute обладает дружественным интерфейсом и богатыми возможностями. Да что там говорить, ведь KMS рекомендуется как альтернатива всем известному почтовому серверу от MS – Exchange. Сейчас не буду вдаваться в возможности и прелести KMS, т.к. в этой статье нас интересует именно WinRoute, а о почтовике от Kerio я возможно расскажу в следующих номерах нашего журнала.
Перед установкой любого серьезного продукта нужно хорошенько изучить его возможности и если все устраивает, то выбор будет точно правильным. Итак, посмотрим Kerio со стороны потребителя J. 1. Брандмауэр. Как ни крути, а представить шлюз без возможности управлять трафиком – нереально. Одному пользователю нужен лишь доступ pop3, другому SSH, почтовику требуется принимать входящие соединения от других smtp – типичный список задач любой среднестатистической конторы. Kerio Winroute Firewall выполняет роль полноценной огненной стенки (еще бы, смотри на название J). Брандмауэр работает на уровне сетевых драйверов Windows и позволяет создавать гибкие правила по управлению трафиком. Добавлять новые правила просто, с этим нехитрым процессом может, справиться любой начинающий администратор не говоря уже о профи. Для тех, у кого всетаки возникли проблемы, разработчики предусмотрели специального мастера. Несколько элементарных ответов и типичные правила будут созданы. 2. IPS. Сегодня хацкеров пруд пруди. Только и делают, что пытаются просканить сервис на предмет наличия бажных сервисов. Kerio умеет анализировать наиболее типичные виды хакерских атак и вовремя пресекать попытки взлома и оповещать администратора. Нельзя сказать, что на эту систему можно положиться на 100%, но от недоучек она «защитит» наверняка. 3. Управление шириной канала. Каким бы широким интернет-канал не был его всегда мало, ведь всегда найдутся любители «тяжелых» закачек, которые махом забьют весь канал, оставляя остальных пользователей не удел, или хуже того – за бортом останутся важные сервисы (например, почтовый сервис). В Kerio WinRoute Firewall предусмотрены опции, позволяющие установить максимально
возможную скорость закачки, как для всех сервисов, так и лишь для пользователей. 4. VPN сервер. Без VPN туннеля сегодня трудно обойтись. Точнее обойтись то можно, но вот о безопасности в этом случае можно забыть. В KWF реализован как сам серверный компонент, так и клиент. Работать с этой фишкой чрезвычайно приятно и не приходится париться с поиском альтернативных решений. 5. Антивирусная проверка на лету. KWF поставляется сразу в двух версиях: со встроенным антивирусом и без него. Если ты выбираешь первый вариант, то все передаваемые/принимаемые данные будут автоматически проверяться антивирусом McAfee. Штука удобная, но за на нее придется доплатить отдельно. Тем, кто не желает тратить лишние деньги, может не отчаиваться. С KWF можно подружить и бесплатные антивирусы. 6. Фильтрация контента. На весь WEBконтент KWF позволяет создать свои правила для фильтрации. Таким образом, легко исключить «не нужные» сайты социальных сетей из списка разрешенных для сотрудников. Не стоит полагать, что фильтрация контента ограничивается лишь отсеиванием левых сайтой. Вовсе нет. Ее запросто можно настроить на проверку использования p2p сетей, ftp и т.д. Так что любители торрентов не останутся незамеченными J. 7. Квоты. Каждому пользователю в KWF может быть определена квота на потребление интернет трафика. Квоты можно устанавливать как на входящий, так и на исходящий. При превышении определенной нормы есть возможность, как полностью заблокировать дальнейшую интернет-активность, так и просто ее ограничивать по скорости. Последний вариант очень удобен, когда сотруднику обязательно нужен интернет для дел и требуется уменьшить его аппетиты по закачке.
8. Отчетность. Админы любят функциональность и безопасность, а руководителям нравится читать красивые и информативные отчеты. KWF в этом плане очень хорош и позволяет в несколько кликов сформировать подробные отчеты как по конкретному, так и по всем пользователям. В отчетах присутствуют различные диаграммы, топ посещаемых сайтов и другая архи полезная инфа. 9. Интеграция с AD. Сегодня в большинстве случаев win-админы активно используют службу ActiveDirectory. В этом нет ничего удивительного. Администрировать кучу пользователей с ее помощью становится
намного проще и приятней. KWF умеет работать с AD и позволяет с легкостью перенести всех имеющихся пользователей, либо создавать их по запросу. 10. Несколько интернет-каналов. Если у тебя имеется несколько каналов, то KWF может научиться рационально, использовать их. Например, если один канал накрывается медным тазом, то все пользователи будут автоматом переброшены на резервный. Это лишь самые основные и значимые возможности KWF. Про остальные ты узнаешь если решишься опробовать столь ценный продукт J.
За качество и удобство придется заплатить
Ты уже понял, что Kerio – это продукт с большими возможностями, ну а как ты знаешь – за качество нужно платить. Если вдруг ты решишься на внедрении данного зверька в своей компании, то будь готов раскрутить директора на n-сумму денег. Не расстраивайся, по сравнению с продуктами MS, WinRoute стоит намного дешевле, а значит, на него стоит обратить внимание как альтернативу MS ISA Server, обладающего большими возможностями, но и более высокой ценой. Например, стоимость WinRoute Firewall без интегрированного антивируса на 100 пользователей стоит всего 1888 евро, а если ты приобретаешься сразу два продукта (Kerio WinRoute + Kerio
Mail Server), то вообще сможешь нехило сэкономить. Например, лицензия WinRoute Firewall (10 пользователей) + Kerio Mail Server (10 пользователей) обойдется тебе всего лишь в 625 евриков. Как видишь, цены достаточно низкие. Ради интереса, сбегай на сайт MS и сравни цены с ISA Server. Если мне не изменяет память, то за сам продукт они просят ~800$ + пользовательские лицензии (~100$/пользователь). Разница очевидна (обязательно проверь цены у MS, они могут отличаться!) и нет смысла платить больше, если многие из возможностей ISA Server или MS Exchange тебе не нужны.
Ставим KWF
Теперь пришло время познакомиться с KWF на практике. Сейчас мы рассмотрим установку и базовую настройку WinRoute. Сбегай на официальный сайт и скачай последнюю trial-версию KWF. На момент написания статьи, номер последней версии был 6.6.0. Именно на примере ее мы и будем рассматривать установку. Запускай загруженный файл и перед тобой появится типичное окно приветствия мастера установки. Жми next, потом принимай условия лицензионного соглашения (конечно не забыв его
полностью прочитать) и опять клацай на next. В следующем окне, тебе будет предложен выбор варианта установки. Советую выбрать «Полная» и клацнуть на next. В следующем окне тебе предложат создать учетную запись администратора. Вбей желаемое имя и пароль и опять нажми на next. В очередном окне тебе предложат указать тип установки (локальную или удаленную). Мы ставим KWF локально, поэтому никаких галочек ставить не нужно, просто жмем next. Следующее шаг выполняет информативную функцию и все, что нам остается сделать – нажать
«Установить». Установка проходит шустро, но после нее придется перезагрузить комп. Быстренько выполняй это нехитрое действие и возвращайся обратно J.
После выполнения ребута беги в «Пуск» -> «Программы» -> «Kerio» и выбирай Kerio Adminstration Console. Перед тобой откроется окно как на рисунке 1.
Рисунок 1 (Логинимся в KWF) Как не трудно догадаться, в этом окне тебе необходимо ввести имя пользователя и пароль для доступа к KWF. Эти данные ты вбивал в мастере установки. Вводи их в это окно и нажимай «Установить соединение». Если ты успешно залогинился, то откроется консоль администрирования и мастер настройки сетевых правил. Этим мастером нам и предстоит воспользоваться (хотя, можно было отказаться и сделать все ручками). Нажми «Далее» и мастер предложит нам выбрать тип подключения к сети интернет (рисунок 3). Тебе доступно несколько вариантов: 1. Обычная связь с Интернет – постоянный доступ. Если для доступа в инет ты не
используешь Dial-UP, то смело выбирай этот тип соединения. 2. Обычная связь с Интернет – дозвон по запросу. Этот вариант подойдет тем, кто до сих пор бороздит сеть на обычном модеме. 3. Несколько подключений к интернет – переподключение при отказе. Если у тебя есть в наличии резервный канал в инет и ты хочешь чтобы он использовался в случае отказа основного, то выбирай этот вариант. 4. Несколько подключений к интернет – распределение нагрузки на каналы. Опять же, если у тебя имеется в наличии несколько интернет-каналов и ты хочешь равномерно распределять на них нагрузку, то этот вариант – твой выбор.
Рисунок 2 (Мастер настройки)
Рисунок 3 (Выбора типа интернет-подключения)
У меня дома доступ в инет через локальную сеть, поэтому я выбираю самый первый вариант – «Обычная свзяь с Интернет – Постоянный доступ». Какой вариант использовать тебе – решай сам. Как определишься с выбором, жми «Далее». На третьем шаге настройки мастер установки
попросит выбрать сетевой интерфейс (рисунок 4), подключенный к сети интернет. Если у тебя всего лишь один интернетканал, то в 99% мастер сам сможет его определить. Тебе остается только проверить правильность его выбора и перейти на следующий шаг.
Рисунок 4 (Определяем интерфейс, подключенный к инету) В очередном окне (рисунок 5) мастер поинтересуется у нас об ограничениях, которые мы хотим наложить на доступ различным интернет службам. Если ты не планируешь как-то ограничивать, то выбирай «Разрешить доступ ко всем службам (Без ограничений)». Меня такой вариант не устраивает, поэтому я выбираю «Разрешить доступ только к следующим службам», а среди списка служб выберу лишь HTTP, HTTPS и DNS. В реальной ситуации, на этом шаге нужно выбирать
лишь те службы, которые однозначно нужны всем пользователям. В большинстве случаев таковыми являются http и HTTPS. Определившись с выбором, нажимай уже привычную кнопку «Далее». Новое окно (рисунок 6) и вновь новый вопрос – теперь касательно настройки VPN. В рамках статьи мы не будем рассматривать настройку VPN сервера, поэтому можно просто снять флажки и нажать «Далее».
Рисунок 5 (Определяем список разрешенных служб)
Рисунок 6 (Определение настройки VPN сервера)
Вот мы и добрались до предпоследнего шага мастера настройки, а значит, до конца ждать осталось недолго. Итак, на шестом шаге нам нужно определить сервера и их службы, которые должны быть доступны извне. Дома у меня таких серверов понятное
дело нет, поэтому я просто жму «Далее». Если ты выполняешь установку в реальной сети, где имеется, например почтовый сервер, то в этом окне тебе как раз и нужно указать адрес своего почтового сервера и соответствующие службы.
Рисунок 7 (Политика входящего трафика) Нажимаем «Далее» и переходим на последний шаг настройки. Он несет лишь информативную функцию, поэтому просто жмем завершить. Через несколько секунд
мастер закончит генерирования правил и предоставит нам возможность произвести дальнейшую настройку, используя консоль администрирования.
Проверяем интернет
Перед тем как пробежаться по всевозможным настройкам проведем первый тест-драйв – проверем работоспособность прокси-сервера. Для этого я взял свой нетбук, подключил его к своей локалке по Wi-fi и установил в браузере в качестве прокси-сервера адрес Устанавливаем аутентификацию
ПК на котором установлен Kerio, а в качестве порта выбрал 3128. FireFox на секунду задумался и отобразил запрошенный мной сайт. Делаем вывод, proxy успешно работает и можно переходить к дальнейшей настройки.
Прокси-сервер успешно заработал и уже может выполнять возложенные на него функции. Казалось бы, что еще нужно! На самом деле во всей этой радостной картине есть маленькая проблема. В настоящее время нашим проксиком может воспользоваться любой, кто пропишет в своем браузере адрес нашего шлюза. Это неправильно и сейчас мы исправим положение дел. Начнем с создания пользователей. Перейди в консоли администрирования в раздел
«Пользователи и группы». В правой части окна отобразится список имеющихся пользователей. У нас он пока всего лишь один. Ничего, сейчас мы добавим еще одного. Нажми кнопку «Добавить». Перед тобой откроется окно (рисунок 8) создания нового пользователя. Заполни все предложенные поля и несколько раз нажми на кнопку «Далее». Пока нас не интересует установка квот и прочего добра.
Рисунок 8 (Создание нового пользователя) Так, пользователь у нас создан, теперь настроим аутентификацию. В разделе «Пользователи и группы», в правой части окна перейди на закладку «Параметры аутентификации». Найди и установи
галочку «Всегда требовать аутентификацию польз. при доступе к веб-страницам». Затем установи «Автоматический конец сеанса» значение 30 минут. Это будет означать, что сеанс пользователя будет автоматически
завершаться по истечению указанного времени. Вот собственно и все. Теперь если ты попробуешь подключиться к прокси-
серверу, то в своем браузере увидишь окно для ввода логина и пароля.
Добавляем правила
Мастер настройки сетевых правил оказал нам большую помощь и помог сгенерировать начальные правила. Это все хорошо, но сам понимаешь, стандартные правила они на то и стандартные и в реальной ситуации лишь ими не обойтись. Поэтому рано или поздно тебе придется
создавать правила самостоятельно. Не волнуйся, в KWF это делается несложно. Новые правила создаются в разделе «Политика трафика». Перейди в этот раздел и посмотри, что сейчас у тебя уже создано несколько правил.
Рисунок 9 (Правила созданные мастером) Для создания правила достаточно кликнуть по кнопке «Добавить». В списке правил появится новая строка, колонки которой и необходимо заполнить. Рассказывать про назначение каждой колонки нет смысла, т.к. их имена говорят сами за себя. Давай просто рассмотрим пример создания произвольного правила. Для начала установим себе вымышленную задачу. Представь, что ты поднял свой почтовый сервер и теперь тебе
требуется открыть к нему доступ извне. Другими словами, при установке соединения с твоим шлюзом на 25 порт, входящее соединение должно переадресовывать на почтовый сервер, расположенный в локальной сети и имеющий IP адрес – 192.168.1.25. Нажми кнопку добавить и поочередно заполняй каждую из колонок созданного правила. Для заполнения просто кликай два раза мышкой
по нужной из граф. Результатом действия будет появление различных диалоговых окон, в которых и нужно вносить значения. Итак, начнем:
принимать? Собственно здесь нам и нужно определиться с дальнейшей судьбой этого коннекта. В нашем случае мы выберем «Разрешить».
1. Имя. В имени можешь писать все что угодно. Это необходимо лишь для того, чтобы в будущем ты не забыл для чего предназначено именно это правило. Поэтому не ленись и давай понятные имена. Для нашего тестового правила я установил имя: «smtp for mail-server».
6. Журнал. Всю активность по данному правилу мы можем записывать в журнал событий. Для этого примера мы установим запись всех событий.
2. Источник. Как и следует из названия, в этой колонке мы должны определить источник соединения. Здесь мы можем указать как конкретный хост, так и группу интерфейсов. В нашем случае, мы не можем знать IP почтовых серверов, поэтому просто укажем интернет-интерфейс (Сеть подключенная к интерфейсу -> Интернет интерфейсы). 3. Назначение. В этой колонке нам необходимо указать внешний наш внешний IP, который известен почтовым серверам. 4. Служба. Почтовые сервера будут пытаться установить соединение на 25 порт, следовательно, для этой колонке нам нужно выбрать smtp. 5. Действия. Запрос на соединение получен и, что с ним делать? Запрещать или
7. Трансляция. В нашем случае, входящее соединение нужно транслировать на адрес нашего почтового сервера. Устанавливаем флажок «Включить адрес трансляции NAT» и в поле «Транслировать в следующий хост:» вбиваем адрес нашего вымышленного почтовика (192.168.1.25). Кроме адреса нам также нужно установить флажок «Транслировать порт в…» и указать порт №25. Все на этом можно считать, что правило готово. Остается только нажать кнопку применить и проверить соединение. Если у тебя нет почтового сервера, то не отчаивайся. Попробуй создать свое правило по такому же принципу. Возьми, например программу для удаленного администрирования и попытайся создать правило, чтобы можно было подключаться к серверной части извне. Или поступи еще проще. Создай правило, пропускающее соединение из локальной сети в инет.
To be continued…
На этом первая статья о KWF окончена. Мы рассмотрели возможности продукта, установили его и даже выполнили базовую настройку. Само собой на этом
возможности KWF не заканчиваются, и в следующий раз мы продолжим рассматривать нюансы по его конфигурированию. До встречи, увидимся!
P.S. Я планирую в будущем сделать целый цикл статей по KWF и если у тебя возникнут предложения, то я с удовольствием приму их к себе на мыло.
Written by Антонов Игорь E-mail: antonov.igor@live.ru