Легенда:
новое сообщение
закрытая нитка
новое сообщение
в закрытой нитке
старое сообщение
|
- Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
- Новичкам также крайне полезно ознакомиться с данным документом.
Оптимизация PCRE, фильтрующих URL... 18.11.05 21:25
Автор: kstati <Евгений Борисов> Статус: Elderman Отредактировано 18.11.05 21:30 Количество правок: 2
|
Доброго здоровья!
Многие уже сталкивались с вопросом фильтрации тегов. Задача в основном одна - реализовать возможность использования правильно составленных структур, не влияющих на безопасность сайта. Я к ним отношу, например, простые ссылки на http/https/ftp ресурсы.
Для правильной фильтрации решил ознакомиться с соответствующими стандартами.
Нашел доходчивое описание формата URL в RFC1738
В качестве "фильтра" решил использовать PCRE.
Первая версия регулярного выражения была написана, что называется "в лоб"
Как описано в RFC, так и задаю в пкре-регкспе. Результат потрясающий - партен более полутора килобайт.
Решил оптимизировать конструкции. Например в пятом разделе (это страница 17) описывается непосредственно формат URL. Пример:
toplabel = alpha | alpha *[ alphadigit | "-" ] alphadigit ---
буквально можно описать так:
toplabel =/([a-zA-Z]|([a-zA-Z]([a-zA-Z0-9])*[a-zA-Z0-9])/ ---
Но это же полная лабуда. Намного эффективнее будет конструкция:
/[a-zA-Z]+([a-zA-Z0-9\-]*[a-zA-Z0-9])?/ ---
Аналогично упрощается и путь. В качестве примера беру ftp, так как он чуть-чуть "навороченее".
ftpurl = "ftp://" login [ "/" fpath [ ";type=" ftptype ]]
fpath = fsegment *[ "/" fsegment ]
ftourl_opt = "ftp://" login [ fpath_opt [ ";type=" ftptype ]]
fpath_opt = * ["/" fsegment]
---
Подобными изменениями удалось "сжать" партен ftp-url до 352 байт.
Так вот в чем собственно вопрос.
Где еще можно оптимизировать этот партен?
<<<<<<<<<<<<<<<<<<<<<<<<<<<<
user & password =(?:[a-zA-Z0-9-$_.+!*'(),;?&=][0-9A-Fa-f]{2})+
hostport =
(?:(?:(?:(?:(?:[a-zA-Z0-9](?:[-a-zA-Z0-9]*[-a-zA-Z0-9])?)\.)* (?:[a-zA-Z](?:[-a-zA-Z0-9]*[a-zA-Z])?)) (?:[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+))(?:\:[0-9]+)?)
Он же - в более читаемом виде:
(?:
(?:
(?:
(?:[a-zA-Z0-9]
(?:[-a-zA-Z0-9]*[a-zA-Z0-9]
)?
)\.
)*
(?:[a-zA-Z]
(?:[-a-zA-Z0-9]*[a-zA-Z]
)?
)
)
|
(?:[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+
)
)
(?:\:[0-9]+
)?
---
login =/(?:(?:(?:[a-zA-Z0-9-.+'(),;?&=]|%[0-9A-Fa-f]{2})+(?:\:(?:[a-zA-Z0-9-$+!*'(),;?&=]|%[0-9A-Fa-f]{2})+)@)?(?:(?:(?:(?:(?:[a-zA-Z0-9](?:[-a-zA-Z0-9]*[-a-zA-Z0-9])?)\.)?:[a-zA-Z](?:[-a-zA-Z0-9]*[a-zA-Z])?))?:[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+))(?:\:[0-9]+)?))/
fsegment =/(?:[a-zA-Z0-9-$_.+'(),\?:@&=][0-9A-Fa-f]{2})
fpath =/(?:\/(?:[a-zA-Z0-9-$_.+'(),\?:@&=][0-9A-Fa-f]{2})*)
ftptype= [AIDaid]
ftpurl=
(ftp:\/\/
(?:(?:(?:[a-zA-Z0-9-.+'(),;?&=]|%[0-9A-Fa-f]{2})+(?:\:(?:[a-zA-Z0-9-$+!(),;?&=][0-9A-Fa-f]{2})+)@)?
(?:(?:(?:(?:(?:[a-zA-Z0-9](?:[-a-zA-Z0-9]*[-a-zA-Z0-9])?)\.)*(?:[a-zA-Z](?:[-a-zA-Z0-9]*[a-zA-Z])?))?:[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+))(?:\:[0-9]+)?))
(?:(?:\/(?:[a-zA-Z0-9-$_.+'(),\?:@&=][0-9A-Fa-f]{2})*) (?:\;=type[AIDaid]{1}
)?
)?
)
--- ftpurl=/(ftp:\/\/(?:(?:[a-zA-Z0-9-.+'(),;?&=]|%[0-9A-Fa-f]{2})+(?:\:(?:[a-zA-Z0-9-$_.+!*'(),;?&=]|%[0-9A-Fa-f]{2})+)@)?(?:(?:(?:(?:(?:[a-zA-Z0-9](?:[-a-zA-Z0-9]*[-a-zA-Z0-9])?)\.)*(?:[a-zA-Z](?:[-a-zA-Z0-9]*[a-zA-Z])?))|(?:[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+))(?:\:[0-9]+)?)(?:(?:\/(?:[a-zA-Z0-9-$+!*'(),\?:@&=][0-9A-Fa-f]{2})*)?:\;=type[AIDaid]{1})?)?)/
<<<<<<<<<<<<<<<<<<<<<<<<<<<<
C http/s дела примерно такие же как и с ftp - около 350 символов.
Ну, и в довесок проверка мыла. Её скорость не так уж критична - используется на много реже. Может быть пригодится кому-либо.
************************************ test for RFC822 &; RFC1738 email syntax
++ only visibled chars used
++ ip as host not allowed */
/^[^][\0-\x20()&;lt;&;gt;@,;:\\".\x80-\xff](?:[^][\0-\x20()&;lt;&;gt;@,;:\\"\x80-\xff]*?[^][\0-\x20()&;lt;&;gt;@,;:\\".\x80-\xff]@(?:(?:(?:[a-zA-Z0-9](?:[-a-zA-Z0-9]*[-a-zA-Z0-9])?)\.)?:[a-zA-Z](?:[-a-zA-Z0-9]*[a-zA-Z])?))$/
Вот и возникает вопрос.
Что бы отбросить, для уменьшения размера партенов - следовательно - увеличения скорости работы?
Конечно же, оптимальный по скорости вариант - "/<a\shref=(.*?) >(.*?)<\/a>/" , Но его качество оставляет желать лучшего.
Может быть все не так уж и плохо? и регексп на четыре сотни символов это не "ужас" ? ;)
|
|
походу так всё и есть 22.11.05 00:26
Автор: NKritsky <Nickolay A. Kritsky> Статус: Elderman
|
И тебе поздорову!
> Доброго здоровья! > Многие уже сталкивались с вопросом фильтрации тегов. Задача > в основном одна - реализовать возможность использования > правильно составленных структур, не влияющих на > безопасность сайта. Я к ним отношу, например, простые > ссылки на http/https/ftp ресурсы. > Для правильной фильтрации решил ознакомиться с > соответствующими стандартами. > Нашел доходчивое описание формата URL в RFC1738 > В качестве "фильтра" решил использовать PCRE. > Первая версия регулярного выражения была написана, что > называется "в лоб" > Как описано в RFC, так и задаю в пкре-регкспе. Результат > потрясающий - партен более полутора килобайт. > Решил оптимизировать конструкции. Например в пятом разделе > (это страница 17) описывается непосредственно формат URL. > Пример:
<skipped>
> Вот и возникает вопрос. > Что бы отбросить, для уменьшения размера партенов > - следовательно - увеличения скорости работы? > Конечно же, оптимальный по скорости вариант - > "/<a\shref=(.*?) > >(.*?)<\/a>/" , > Но его качество оставляет желать лучшего. > Может быть все не так уж и плохо? и регексп на четыре сотни > символов это не "ужас" ? ;)
Я почитал, посмотрел, - похоже что не ужас. Просто в BNF это всё немножко прикольней читается за чет использования "макросов". А что скорость парсинга - есть претензии? Тестировал?
|
| |
На девелоперской машине - летает. Но на сайте - (VDS) - ресурсов этак на порядок меньше (150 попугаев, 32RAM) - подтормаживать может. В принципе, уже и из этого выход нашел - фильтровать однажды - при добавлении текста. 22.11.05 13:25
Автор: kstati <Евгений Борисов> Статус: Elderman
|
|
|
|