Monday, February 9, 2009

Валидность домена с точкой на конце

Адреса вида server.ru./page.htm (с точкой после имени домена) тоже правильные, в чем можно убедиться, посетив, например, http://www.google.com./search?hl=en&q=hello. Возникла задача - проверяя урл на правильность домена, не забыть про точку и убрать ее из адреса. Как сделать эффективнее проверку наличия точки? Вот в чем вопрос.

Быстренько накидал тесты очевидных решений:
$h = "subdomain.server.ru." ;

function test1($h)
{

if( !preg_match("|^([a-zA-Z0-9\.\-]+\.[a-zA-Z]{2,6})(\.?)$|", $h, $m) ) {
return 0;
}
if($m[2]) return $m[1];
return $h;

}

function test2($h)
{
if( !preg_match("|^[a-zA-Z0-9\.\-]+\.[a-zA-Z]{2,6}\.?$|", $h) ) {
return 0;
}
if(substr($h, -1) == '.') return substr($h, 0, -1);
return $h;
}


Время выполнения 100.000 итераций каждого теста (PHP v5.2.5 Win32):
test1 - 0.53170919418335 sec
test2 - 0.44983506202698 sec

А если пресловутой точки нет в адресе, то второй тест отработает еще быстрее.

Thursday, August 14, 2008

Сжатие вывода Smarty

У smarty есть возможность установить пользововательские фильтры для выводимого содержимого через register_outputfilter(). Например так можно сжать страницу:
...
$smarty->register_outputfilter('output_compress');
...
function output_compress($tpl_output, &$smarty)
{
if(headers_sent()) return $tpl_output;
header('Content-Encoding: deflate');
return gzdeflate($tpl_output, 4);
}

Но если при выполнении кода случится вывод Warning (т.е. display_errors = On), то вы не получите ожидаемого результата (Firefox 3 ругается на неподдерживаемый метод сжатия), т.к. текст этого предупреждения не попадает в $tpl_output и остается в буфере. В результате, на выходе часть содержимого будет не сжата, а заголовок сжатия будет послан.

Чтобы избежать этого, использую такой подход:
...
function output_compress($tpl_output, &$smarty)
{
if(headers_sent()) return $tpl_output;
if($t = ob_get_contents()) {
$tpl_output = $t . $tpl_output;
ob_clean();
}
header('Content-Encoding: deflate');
return gzdeflate($tpl_output, 4);
}

Friday, January 25, 2008

Производительность хэш-функций в PHP 5.2

Неожиданно для себя обнаружил что в PHP (от v5.1.2) оказывается есть функция hash(), котороя поддерживает различные алгоритмы хэширования, в том числе md5 и sha1. Но, функция md5() работает медленнее чем эквивалентная hash('md5'). Решил проверить и заодно узнать какие алгоритмы поддерживаются (на примере v5.2.5 под vista).

Проверял примерно вот так:
$a =  hash_algos();
$exclude = array('');

test_md5();
print "\n";

foreach($a as $v)
{
if(!in_array($v, $exclude))
test_algo($v);
}

#=== procs ==
function test_algo($algo)
{
$time = microtime(1);
$s = '';
for($i=0; $i<150000; $i++)
$s = hash($algo, 'is this string too long? maybe not! strlen=45');

$time = microtime(1)-$time;
print "$algo (" . strlen($s) . " bytes) - " . (number_format($time, 4)) ." s\n";
}

function test_md5()
{
$time = microtime(1);
$s = '';
for($i=0; $i<150000; $i++)
$s = md5('is this string too long? maybe not! strlen=45');
$time = microtime(1)-$time;
print "function md5() - " . (number_format($time, 4)) ." s\n";
}


Результаты:
function md5() - 0.2412 s

md2 (32 bytes) - 7.2568 s
md4 (32 bytes) - 0.2991 s
md5 (32 bytes) - 0.3149 s
sha1 (40 bytes) - 0.3436 s
sha256 (64 bytes) - 0.4768 s
sha384 (96 bytes) - 1.2349 s
sha512 (128 bytes) - 1.2481 s
ripemd128 (32 bytes) - 0.5023 s
ripemd160 (40 bytes) - 0.5224 s
ripemd256 (64 bytes) - 0.4766 s
ripemd320 (80 bytes) - 0.5418 s
whirlpool (128 bytes) - 1.5320 s
tiger128,3 (32 bytes) - 0.4329 s
tiger160,3 (40 bytes) - 0.4403 s
tiger192,3 (48 bytes) - 0.4572 s
tiger128,4 (32 bytes) - 0.4657 s
tiger160,4 (40 bytes) - 0.4757 s
tiger192,4 (48 bytes) - 0.4854 s
snefru (64 bytes) - 1.4405 s
gost (64 bytes) - 1.3708 s
adler32 (8 bytes) - 0.3449 s
crc32 (8 bytes) - 0.2813 s
crc32b (8 bytes) - 0.2896 s
haval128,3 (32 bytes) - 0.5591 s
haval160,3 (40 bytes) - 0.5566 s
haval192,3 (48 bytes) - 0.5714 s
haval224,3 (56 bytes) - 0.5747 s
haval256,3 (64 bytes) - 0.5768 s
haval128,4 (32 bytes) - 0.6543 s
haval160,4 (40 bytes) - 0.6726 s
haval192,4 (48 bytes) - 0.6576 s
haval224,4 (56 bytes) - 0.6546 s
haval256,4 (64 bytes) - 0.6607 s
haval128,5 (32 bytes) - 0.7046 s
haval160,5 (40 bytes) - 0.7097 s
haval192,5 (48 bytes) - 0.7188 s
haval224,5 (56 bytes) - 0.7197 s
haval256,5 (64 bytes) - 0.7221 s


Действительно, так и есть (разница на 30%). Также проверил Fedora 8 с предустановленным PHP v5.2.4 - cоотношение примерно такое же (20%). Причем в PHP v5.2.0 под виндой производительноcnь md5() оказывается ниже в 3 (!) раза.

Wednesday, June 20, 2007

Шаблоны и движок: проблемы версий

В прошлом посте я упомянул о проблеме совместимости шаблонов разных версий скрипта. Имеется в виду ситуация, когда пользователь скрипта v1.0 изменил шаблоны, но появляется версия 1.5, где ряд шаблонов изменен (возможно существенно). И ему приходится вручную все переделывать, сравнивая разные версии шаблонов.

Итак я пришел к следующим выводам.
1. Не зашивать дизайн жестко в код скрипта.
2. Не использовать XSL/XSLT, т.к. юзер наверняка не умеет с этим работать.
3. Использовать Smarty в качестве шаблонизатора.
4. Максимально загрузить CSS при верстке дизайна, как например на Хабре.

Такой расклад меня полностью устраивает. Надеюсь, что пользователей тоже.

Tuesday, June 5, 2007

Атрибуты нормального скрипта для продажи.

Что я думаю о том, какие возможности должен предоставлять коммерческий скрипт/движок.

1. Удобный установщик.
- скачиваем архив скрипта, распаковываем и заливаем папку на сервак;
- залезаем через браузер на будущий сайт (или что там будет), где тут же выскакивает конфигуратор/установщик;
- указываем данные по доступу к БД плюс некий минимум для работы, жмем "Next"
- автоматом создаются все необходимые таблицы в БД, проверяются зависимости библиотек, доступность каталогов для записи и пр. В случае неудачи показывается описание ошибок и кнопка "Retry";
- итак, финальное окно, возможно, с просьбой удалить какие-нибудь файлы установщика.

2. Все настройки скрипта производятся только на сайте, т.е. не надо лезть в текстовые конфиги и править параметры там руками. Хотя сами настройки в таком файле и хранятся. :)

3. Отделение кода обработки данных от представления данных, т.е. дизайн хранить в шаблонах, и использовать, например, smarty для отображения.

4. Для удобства локализации на другие языки, вынести все возможные моменты в некие переменные и хранить их отдельно, например, в файле. Редактирование этих переменных, пожалуй, можно делать вручную.

Вот тут есть неприятный момент, когда пользователь изменит шаблон под себя (я сторонник предоствления ему полного контроля отображения), а в новой версии скрипта какие-нибудь шаблоны будут изменены... И что после этого полноценную CMS делать?

Хотя на создании различных дизайнов шаблонов тоже бизнес делать можно. :) Вообщем у меня на этот счет есть кучка мыслей, когда определюсь окончательно - выложу.

5. Поддержка скрипта.
- написание мануалов по установке и использованию;
- отслеживание возможных багов, да и просто на вопросы юзверей отвечать.

...

Sunday, April 22, 2007

Eclipse + Subversion. Начало.

Давно хотел попробовать что-то из серии CVS, но как говорится "руки не доходили". Понадобилось это мне потому, что периодически возникает ситуация при разработке проекта, когда нужно вести разработку новой версии одновременно с текущей, а потом новую версию сливать в текущую.

Остановился на Subversion, не знаю даже почему, т.к. в этом деле новичок. Доку по ней можно почитать тут: http://svnbook.red-bean.com. Все установки производил на компе под управлением Windows XP SP2.

Бинарники Subversion под винду берем здесь. Мне попался svn-1.4.3-setup.exe, который я поставил в c:\Subversion. В процессе установки отказался от пункта модификации конфига апача.

Если брать zip-архив, то придется создать переменную окружения APR_ICONV_PATH = c:\subversion\iconv, и в PATH добавить путь c:\subversion\bin.

Настраиваем Apache. В httpd.conf включим модули DAV, добавим 2 модуля SVN и прописываем Location с указанием хранилища репозиториев:
LoadModule dav_module modules/mod_dav.so
LoadModule dav_fs_module modules/mod_dav_fs.so
LoadModule dav_svn_module "C:/Subversion/bin/mod_dav_svn.so"
LoadModule authz_svn_module "C:/Subversion/bin/mod_authz_svn.so"

...
<Location /svn>
DAV svn
SVNParentPath d:\repos
</Location>


Создание репозитория делается с помощью команды
svnadmin create --fs-type fsfs testproject
(вместо fsfs можно bdb), текущим каталогом при этом должен быть SVNParentPath, т.е. d:\repos.

Теперь добавим поддержку SVN в Eclipse. Для этого используем плагин subclipse. Там все расписано и установка не займет проблем. В случае отсутствия инета можно использовать zipped-версию, скачанную на другом компе. Я брал site-1.2.0.zip и устанавливал как "New archived Site".

В eclipse появится перспектива SVN Repository Exploring, и там указываем наш тестовый репозиторий проекта: http://localhost/svn/testproject. Через "New remote folder" в контекстном меню создаем нужные папки/ветки разработки:
trunk - текущая (основная) разработка,
tags - тут будут папки с релизами,
branches - а тут будут временные ветки будущих версий (они потом сольются в trunk).

Чтобы поместить существующий проект Eclipse в SVN используем контекстное меню "Team - Share project" в окне, скажем, "Navigator". Выбираем тип репозитория SVN. В качестве Repository Location указываем существующее http://localhost/svn/testproject, потом имя/папку проекта, небольшой коммент по импорту, жмем Finish и выбираем файлы для commit.

Управление SVN ведется через контекстное меню Team. Основные команды - update и commit. Но об этом в другой раз.

Saturday, April 21, 2007

Why?

Зачем открыл блог? Вообще говоря, планирую его использовать как интернет-блокнот. Чтобы не держать в голове описания некоторых не часто встречающихся операций и прочей ерунды, и иметь к ним доступ из любого места: домашнего или рабочего компов, ноутбука, кпк и бог знает откуда еще.

Еще думаю, что эти записи могут кому-нибудь пригодиться. И дабы сильно не заморачиваться с синхронизацией всех этих девайсов и было принято решение о создании блога.

Почему на Blogger? Да потому что я постоянно залогинен у гугла: Google Reader, GMail, etc. И мне удобно иметь один аккаунт на все. Ну и пусть "большой брат все видит"... :) Тем более, что немного поигравшись с livejournal.com мне показалось, что медленноват он, местами черезчур.

Собственно пока все.