книги хакеры / журнал хакер / 107_Optimized
.pdf
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-xcha |
|
|
|
|
Форма второго примера
Результат работы первого примера
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
C |
E |
|
|
|||
|
|
X |
|
|
|
|
|||
|
- |
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
NOW! |
o |
|||
>> codingto BUY |
|
|
|||||||
|
|
|
|
m |
|||||
w Click |
|
|
|
|
|
||||
w |
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
g |
|
|
|
|
|
|
df |
|
n |
e |
|
||
|
|
|
|
-x cha |
|
|
|
|
— технология поиска текстовых фрагментов в электронных документах, соответствующих определенным правилам.
Основы основ
Перед тем как начать использовать регулярные выражения, стоит разобраться с некоторыми понятиями. Начнем с литералов. Литерал — это любой отдельный символ. Например: а, b, с, d — литералы. Думаю, с этим все ясно. Едем дальше. Из одних литералов кашу не сваришь, поэтому на помощь приходят метасимволы (специальные символы, которые выполняют какое-либо дополнительное действие). Наверняка тебе не раз приходилось использовать метасимволы при работе в командной строке (неважно, Windows ли эта консоль или UNIX). Например, чтобы вывести в
Windows список файлов определенного каталога, в cmd можно применить команду dir. Как быть, если мне нужно отобразить все имена файлов, у которых расширение html и htm? Можно выполнить команду dir и сломать глаза, выискивая нужные файлы, а можно воспользоваться конструкцией «dir *.htm?». В этой записи присутствует два метасимвола — «*» и »?». Звездочкой мы указываем на то, что имя файла может состоять из любых символов (литералов), затем мы определяем расширение и ставим знак вопроса, который говорит, что после m может не быть ничего или быть один любой символ. Для нашей задачи этого вполне достаточно.
«*» и »?» не единственные метасимволы. К метасимволам также относятся: «^» — определяет начало строки; «$» — конец строки; «.» — любой литерал в строке; \w — все буквы и цифры, а также символ нижнего подчеркивания; \W — все, что не относится к \w; \d — любая цифра от 0 до 9; \D — все символы, не являющиеся цифрами; \s — любой пробельный символ; \S — не \s; «+» — повторение один или более раз.
Вроде все ясно, но чувствуется, что не хватает практики. Попробуем составить простенькие примеры, чтобы закрепить полученные знания. Ты можешь тренироваться на бумажке с карандашом, но лучше скачать какой-нибудь редактор для тестирования регулярных выражений. Самый простой и удобный — TRegExpr Studio. Он написан для тестирования регулярных выражений с использованием класса TRegExpr, с помощью которого становится возможным применение регулярных выражений в Delphi. Можно скачать столь полезную программу с сайта разработчиков
(www.regexpstudio.com) или взять с нашего диска.
Итак, запусти программку и внимательно оглядись. Нас интересует только первая закладка — Expression. Окно поделено на две части. В верхнем поле ввода тебе нужно будет описывать регулярное выражение, а в нижнем — входную строку, то есть текст, на котором и будет тестироваться выражение.
Попробуем написать пробный пример. В поле для регулярного выражения мы вводим одно лишь слово «Пример», а в качестве пробного текста пишем: «Это простой Пример использования регулярных выражений».
Кодпроцедуры findMailUtils
var
_tempFile:TStringList; _regexp:TRegExpr;
i, b:integer; begin
// Инициализируем объект для работы с регулярками
_regexp:=TRegExpr.Create;
//Устанавливаем шаблон поиска в зависимости от
условия
case mode of
//Будем искать мыльник
0: _regexp.Expression:= '[\w\d-.]+@([\w\d-]+(\.[\w\-]+)+)';
// Будем искать URL
1: _regexp.Expression:= '(http|ftp)://([\w\d- ]+(\.[\w\d\-]+)+)(([\w\d\-=\?\\\./]+)+)*';
End;
_tempFile:=TStringList.Create; _tempFile.LoadFromFile(file_name); ProgressBar1.Max:=_tempFile.Count;
b:=StrToInt(CountMailLAbel.Caption);
for i:=0 to _tempFile.Count-1 do begin
progressBar1.Position:=i;
if (_regexp.Exec(_tempFile.Strings[i])) then repeat
ResultMemo1.Lines.Add(_regexp.Match[0]); Inc(b); CountMailLabel.Caption:=IntToStr(b);
until not _regexp.ExecNext; end;
//Освобождаем память
_regexp.Free; _tempFile.Free;
xàêåð 11 /107/ 07 |
109 |
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
C |
E |
|
|
|||
|
|
X |
|
|
|
|
|||
|
- |
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|||
w Click |
to BUY |
|
>> coding |
||||||
|
|
|
|
|
m |
||||
w |
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
g |
|
|
|
|
|
|
df |
|
n |
e |
|
||
|
|
|
|
-xcha |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x cha |
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Тестируем регулярные выражения
Жмем на Exec и видим, как во входном тексте выделилось слово «Пример». После нажатия на пимпу ExecNext программой будет произведена попытка поиска следующего фрагмента текста, соответствующего шаблону. В нашем случае регулярное выражение больше не сработает,
Перегонныйкуб
var
_regexp:TRegExpr; _tempFile:TStringList; I:Integer;
begin
if not (OpenDialog1.Execute) then Exit;
ListView1.Items.Clear;
Edit2.Text:=OpenDialog1.FileName; _regexp:=TRegExpr.Create; _regexp.Expression:='([^\s]+)\s([^\s]+)\s([\d\.]+)\
s([\d\+-]+)';
_tempFile:=TStringList.Create; _tempFile.LoadFromFile(OpenDialog1.FileName);
for i:=0 to _tempFile.Count-1 do begin _regexp.Exec(_tempFile.Strings[i]); if (_regexp.Exec) then
with ListView1.Items.Add do begin
Caption:=_regexp.Match[1]; SubItems.Add(_regexp.Match[2]); SubItems.Add(_regexp.Match[3]); SubItems.Add(_regexp.Match[4]);
end;
end; _regexp.Free; _tempFile.Free;
Второй пример в действии
поскольку слова «Пример» больше нигде нет. Шаблон получился очень простым. Если бы регулярные выражения предназначались только для этого, от них не было бы толку.
Попробуем усложнить пример. В качестве входной строки определим: «Первый мой номер: +7-924-111-11-34, а второй: +7-231-331-55-55».
Наша с тобой задача будет найти в этом тексте все номера телефонов. Первое, что приходит на ум, — это описать телефоны в качестве шаблона. К сожалению, этот способ не подойдет. Его нельзя назвать универсальным. Стоит изменить номер телефона, и шаблон станет бесполезным. Введем
вкачестве шаблона «\+[0-9 ]+». Попробуем запустить поиск. Работает? А почему? Для понимания сути дела разобьем шаблон на части:
1.\+ — явно указываем, что первым символом должен быть «+». Поскольку символ «+» относится к метасимволам, то просто взять и поставить его мы не можем. Нам придется экранировать его с помощью слэша (слэш перед метасимволом превращает его в обычный литерал).
2.[0-9 ]—вквадратныхскобкахпринятоописыватьсимвольныеклассы (интервалылитералов),которыеназываются«квантификаторами».Чтобы описатькакой-нибудьинтервал,нужнопростоуказатьначальныйиконеч- ныйсимвол.Например,0-9соответствуетвсемцифрамот0до9.Такимже способомможнозадаватьибуквенныеинтервалы:a-z(вселатинскиебуквы
внижнемрегистре),a-zA-Z(латинскиебуквыкаквнижнем,такивверхнем регистрах).Мысобираемсяискатьномерателефонов,аонимогутсостоять изцифризнака«-»,которыйихразделяет.Большебытьничегонедолжно. 3.«+» — в данном случае знак плюса играет роль метасимвола.
Теперь мне бы хотелось обратить твое внимание на описание символьных классов. В квадратных скобках все перечисленные символы действуют совершенно по-другому. Так, если внутри квадратных скобок перед символами поставить метасимвол «^», то это будет означать уже не начало строки, а отрицание. Например, [^abc] — все символы, кроме abc. Остальные метасимволы, указанные в символьном классе, теряют свою силу и становятся обычными литералами.
Рассмотрим такую задачку. Имеются две строки, в которых содержатся буквы и цифры. Задача состоит в том, что необходимо выбрать часть строки, в которой сначала идут подряд три латинские буквы, а за ними
— цифры в интервале от 3 до 6. Строки следующие:
abdajD345bhad5124jjdaabc3456
abdj23456kfej3456fe
Попробуй решить эту задачку самостоятельно с опорой на полученные знания. Мое решение будет выглядеть так: [a-z]{3}[3-6]{4}. Наиболее
110 |
xàêåð 11 /107/ 07 |
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-xcha |
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
C |
E |
|
|
|||
|
|
X |
|
|
|
|
|||
|
- |
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
NOW! |
o |
|||
>> codingto BUY |
|
|
|||||||
|
|
|
|
|
|||||
w Click |
|
|
|
|
|
m |
|||
w |
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
g |
|
|
|
|
|
|
df |
|
n |
e |
|
||
|
|
|
|
-x cha |
|
|
|
|
удобным способом решения этой задачи является установка ограничений на количество находимых символов. Итак, нам нужно найти три латинские буквы. Можно, конечно, три раза записать класс [a-z], а можно просто указать в фигурных скобках их количество. Это я и сделал. Следующее условие — цифры от 3 до 6. Указываем их в классе, не забыв о количестве. Вот и все. В результате поиска по этому шаблону в первой строке будет выбрано abc3456, а во второй — fej3456.
Регулярные выражения в Delphi
В Delphi нет модуля/компонента для работы с регулярными выражениями. На мой взгляд, это существенное упущение Borland (теперь Code Gear).
К счастью, так считаю не только я, но и тот перец, который закодил класс, благодаря которому перед нами открываются безграничные возможности использования регэпсов. Итак, скачай с сайта разработчиков (www. regexpstudio.com) или слей с нашего диска архив с модулем и примерами. После подключения к своему проекту RegExpr (именно так он называется) тебе становится доступным для создания новый объект типа TRegExpr.
Собираем свой антиспам-лист
Вкачествепервогопрактическогопримераярешилсделатьчто-нибудькрай- неполезное.Первое,чтомнепришловголову,—этонаписатьтулзудлявыди- ранияеmail-адресовсHTML-страниц,чтобыточнознать,накакиемыльники тыникогдавжизнинесоберешьсяпослатьнежелательнуюкорреспонденцию. Сделаемтак,чтобынашапрограммаумеланетольковыдергиватьмыльники, ноисобиратьпонашемуприказулинки(чтобыихвпоследствиинепосещать).
Вкачествевходныхпараметровсофтинабудетполучатьпутькпапке,вкоторой хранятсяhtml-иhtm-файлы.Итак,включаемсявпроцесс.
Как обычно, создаем в Delphi новый проект и сразу же подключаем недавно скачанный нами модуль. После этого рисуем простенькую форму, внешний вид которой ты можешь наблюдать на соответствующей иллюстрации.
Принцип действия примера следующий. По нажатию кнопки перед пользователем должен появляться диалог выбора директории. После выбора каталога управление передается самописной процедуре FindFiles(). Ее код приведен в соответствующей врезке. В этой процедуре реализован алгоритм рекурсивного поиска файлов по маске. Для поиска используется функция FindFirst(), в качестве параметров ей нужно передать:
1)директорию, в которой нужно искать файлы, соответствующие маске; 2)атрибутыискомыхфайлов(системный,архивный,толькодлячтения, любой);
3)структуру типа TSearchRec, в которую попадут результаты поиска. Для прохода по всем вложенным папкам используется рекурсия (вызов
процедурой самой себя). Если вместо директории нашелся нужный файл, значит можно смело передавать работу процедуре findMailsUtils(), которая в зависимости от последнего параметра будет искать либо мыльники, либо URL’ы. Код процедуры findMailUtils приведен во врезке, по названию которой ты никогда не догадаешься о ее содержимом :).
Взглянем на вторую врезку. Перед использованием объекта для работы с регулярными выражениями его нужно инициализировать, после чего можно приступать и к составлению регулярного выражения. Поскольку мы собираемся сделать более или менее универсальную тулзу, придется проверить передаваемый в процедуру параметр mode. Значение 0 будет свидетельствовать о том, что нам требуется распотрошить файлы на предмет мыльников, а 1 — что нужны только URL-адреса. Для отлова email-адресов я устанавливаю вот такой шаблон: [\w\d-.]+@([\w\d-]+(\.[\ w\-]+)+). С первого взгляда он абсолютно непонятен. Давай разбираться:
1.[\w\d-.]+ — эта часть описывает адрес электронной почты до знака собачки. В соответствии со стандартом, здесь могут быть любые буквы (\w), цифры от 0 до 9 (\d), знак «-» и точка. После описания символьного класса нужно поставить метасимвол «+», иначе под эту часть шаблона у тебя будут попадать одиночные символы.
2.«@» — понятно, что email-адрес не может быть без значка собачки, поэтому нам необходимо его описать.
3.([\w\d-]+(\.[\w\-]+)+) — в этом небольшом кусочке описывается доменная часть email-адреса. Все используемые здесь метасимволы должны быть тебе уже известны, поэтому я не буду повторяться. Просто внимательно посмотри на эту часть, и все встанет на свои места. Единственное, о чем я тебе не рассказывал, так это о скобках. В регулярных выражениях они играют двойную роль: описывают группы литералов и сохраняют эти группы в специально предопределенных переменных. В рассматриваемом выражении я буду сохранять отдельно имя домена и доменную зону. Вот и все, одной строчкой мы описали шаблон для поиска мыльника. Классно, правда? Но не стоит забывать, что если mode = 1, то нужно искать URL’ы. Шаблон для определения ссылки выглядит более громоздко: (http|ftp)://([\w\d-]+(\.[\w\d\-]+)+)(([\w\d\-=\?\\\./]+)+)*. Опять же попробуем разобраться с его внутренностями.
1.(http|ftp):// — описываем возможные протоколы. Любой адрес для обращения к узлу с помощью протокола HTTP или FTP должен начинаться с http:// или ftp:// соответственно. В скобках я указываю сначала приставку
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
C |
E |
|
|
|||
|
|
X |
|
|
|
|
|||
|
- |
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|||
w Click |
to BUY |
|
>> coding |
||||||
|
|
|
|
|
m |
||||
w |
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
g |
|
|
|
|
|
|
df |
|
n |
e |
|
||
|
|
|
|
-xcha |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x cha |
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Получаем только нужные файлы
http, затем вертикальную черту, которая соответствует логическому «ИЛИ», и уже после нее вторую возможную приставку — ftp. В итоге наш шаблон будет срабатывать на ссылки как FTP-, так и HTTP-ресурсов.
2.([\w\d-]+(\.[\w\d\-]+)+)—воттакимобразомможноописатьадресузла. Этаконструкциябудетодинаковохорошосрабатыватьинаадресавида http://192.168.0.1,тоестьIP-адреса,инасимвольныеадреса.Скобками группируемусловия,таккакеслипростонаписатьдиапазонлитераловводномклассеипоставитьметасимвол«+»,товыражениенебудетправильно работать.Советуюпоупражнятьсяипопробоватьсоставитьдругойшаблон.
3.(([\w\d\-=\?\\\./]+)+)* — поскольку линк может вести на какой-нибудь файл, мы обязаны это предусмотреть. В пути могут присутствовать различные символы: «/», «?», «=» и т.д. Поскольку часть из них является метасимволами, мы должны их экранировать, поставив перед ними еще один слэш. Установив шаблон, можно открывать наш файл, запускать перебор по строкам, получая результат поиска. Для большей информативности я показываю количество найденных совпадений в одном из label.
Еще один полезный примерчик
Представим себе такую ситуацию. Ты нашел базу номеров своего оператора. Только вот незадача — вся она хранится в обычном текстовом файле. Было бы здорово перегнать все эти данные в какую-нибудь БД и потом сортировать, производя поиск удобными средствами. Для перегонки (блин, крутое слово, напоминает мне о деревенском самогоне) можно написать и отладить свой алгоритм, но лучше и проще воспользоваться регулярными выражениями.
Итак, новая задачка. У нас имеется текстовый файл с записями вида: «Василий Петрович 12.02.1975 +7-912-455-24-14». Наша цель — разделить информацию в строке и записать в колонки: «Имя», «Фамилия», «Дата рождения», «Номер телефона». Для решения поставленной задачи я создал в своем проекте еще одну закладку и придал ей следующий вид (смотри картинку). По нажатию кнопки, предназначенной для открытия файла, накатай код из врезки (которая называется «Перегонный куб») и возвращайся к тексту статьи за объяснениями.
Как и в прошлом примере, перед тем как использовать объект TRegExpr, его нужно инициализировать. Далее присваиваем текст регулярного выражения. Для решения этой задачки можно составить вот такой шаблон: ([^\s]+)\s([^\s]+)\s([\d\.]+)\s([\d\+-]+). Разберем его.
1.([^\s]+) — в имени могут содержаться любые символы, кроме пробела, поэтому при описании символьного класса я явно указываю на это («^»
— отрицание, \s — разделитель). По условию мы должны сохранить найденное имя, поэтому берем всю конструкцию в скобки.
2.\s(^\s)+) — после имени обязательно должен идти разделитель, а
раз так, то нужно его указать (\s). Далее следует шаблон для выделения фамилии. Он идентичен шаблону определения имени.
3.\s([\d\.]+) — шаблон для вычленения даты рождения. В дате не могут использоваться буквы, поэтому устанавливаем лишь набор цифр (\d) и точку, которая служит разделителем.
4.\s([\d\+-]+) — пробел, цифры, знаки «+» и «–» задают номер телефо-
Форма программы
на. Все легко и просто. При положительном выполнении метода Exec в свойстве Match у нас будут все разделенные данные, доступ к которым осуществляется через объект_рег_выражений.match[n], где n — номер вхождения. Итак, данные разделены, а значит, пора их сохранять. Ты можешь сохранить их сразу в БД, а я в своем примере сохраню их в ListView.
Итог
Использовать регулярные выражения удобно и не так сложно, как может показаться на первый взгляд. Сегодняшние простые, но в то же время полезные примеры — лишнее тому подтверждение. К сожалению, в рамках одной статьи мы не в состоянии рассказать тебе все о регулярных выражениях. Тема настолько обширна, что для полноценного ее изучения требуется прочитать немало умных книг. Мы в тебя верим и знаем, что при большом желании ты во всем разберешься. Ну а пока можешь задавать свои вопросы мне на мыло. z
Кодпроцедуры
FindFiles
var
_se:TSearchRec; begin
//Если в директории для поиска отсутствует слэш, то нужно его добавить
if dir[length(dir)]<>'\' then dir:=dir+'\';
//Начинаем поиск
if FindFirst(dir+'*.htm?', faAnyFile, _se)=0 then repeat
findMailsUrls(dir+_se.Name, mode); until FindNext(_se)<>0;
//Если нашли поддиректорию, то начинаем поиск в ней if FindFirst(dir+’*.*’, faDirectory, _se)=0 then begin
repeat
if ((_se.Attr and faDirectory)=faDirectory) and (_se.Name[1]<>'.') then
FindFiles(dir+_se.Name+'\', mode); until FindNext(_se)<>0; FindClose(_se);
end;
112 |
xàêåð 11 /107/ 07 |
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-xcha |
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x cha |
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
E |
|
|
||||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
NOW! |
o |
||||
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
||||
w Click |
to BUY |
|
>> coding |
|||||||
|
|
|
|
|
|
m |
||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-xcha |
|
|
|
|
Николай Байбородин
/ baiborodin@gmail.com /
Броня дляВисты
Создание безопасного кода для Windows Vista
О нововведениях в Windows Vista не гово-
рил только ленивый. Набили оскомину и рассуждения о том, насколько трудно разработчикам софта обес-
печить совместимость их програм-
мных продуктов с новой концепци-
ей безопасности, реализованной в этой ОС. Но хватит нытья, пора заставить работать систему на себя, использовав средства обеспе-
чения безопасности Windows Vista
в своем ПО. Сегодня мы погово-
рим о том, как новая система помогает бороться с атаками на переполнение.
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x cha |
|
|
|
|
Новая концепция безопасности
По сравнению с Windows XP, Vista более устойчива перед такими ошибками (читай: атаками), как переполнение буфера. Ряд технологий позволяет избежать этой досадной неприятности или хотя бы смягчить ее последствия. Ты легко можешь реализовать поддержку всех этих новых средств защиты программного кода в своих проектах. При этом все, что от тебя потребуется,
— это включить соответствующие опции компоновщика.
Однако вышесказанное вовсе не означает, что теперь для разработчиков программного обеспечения настало безмятежное золотое время и больше не надо ломать голову. Любое из предлагаемых Microsoft средств защиты при желании относительно легко можно обойти. Тем не менее как средство защиты от случайных ошибок и действий пионеров рассмотренные ниже способы, безусловно, будут эффективны. Тем более что от тебя, как от разработчика, не требуется никаких особых усилий — в большинстве случаев
достаточно указать соответствующе ключи компоновщика на этапе сборки проекта.
Мы рассмотрим такие технологии защиты от переполнения, как ASLR, случайная адресация стека и кучи, NX, GS и SafeSEH. Некоторые из них являются принципиально новыми, другие представляют собой улучшенные версии технологий, входящих в состав Windows XP SP2 и Windows Server 2003. Большинство из рассмотренных технологий имеет реализацию не только от самой Microsoft, но и от других производителей как программного обеспечения, так и железа.
Введение в ASLR
Технология случайного распределения адресного пространства, или ASLR (Address Space Layout Randomization), нацелена на то, чтобы защитить системный API от различной нечисти. Принцип действия этой технологии
114 |
xàêåð 11 /107/ 07 |