mail() logging for PHP

Ilia Alshanetsky выложил интересный патч для PHP. Суть его в том, чтобы логировать вызовы функции mail – добавлением дополнительного заголовка в письмо, в котором будет путь к скрипту и uid вызвавшего процесса(в режиме mod_php имхо бесполезный), и записью в лог с подробными данными о вызвавшем скрипте и параметрах функции mail. Патч будет интересен в первую очередь сисадминам публичных хостингов для борьбы с нерадивыми клиентами.

А я ставить этот патч не буду, потому как успешно борюсь со спамом более активными мерами и аналогичные логи веду другим способом.

Technorati Tags: , ,

14.12.06  |   | стань первым

smarty_outputfilter_trimwhitespace

Довольно странно что в течении трёх лет ни разу не наткнулся на этот “баг” – вышеназванный (обожаю словечки из бюрократического прошлого) фильтр тупо сжирает весь $source этой строчкой:

$source = preg_replace(“!<script[^>]+>.*?</script>!is”,
‘@@@SMARTY:TRIM:SCRIPT@@@’, $source);

Причина в модификаторе “s”.

Осталось понять повлияло ли обновление php до 5.2.0RC5 или конкретный шаблон содержит нечто “вкусное” для этого рег.выр.

Update: причина в preg_* новой версии PHP. Локализую для bug-репорта.

Technorati Tags: , , ,

09.10.06  |   | стань первым

Phing Is Not GNU

Таким образом программист может за три часа написать программу, которая сделает за пять минут то, что другой человек делал бы целый час…
© Кто-то

“Дорогая, а гладить ты умеешь?”

Много слышал и читал про phing, но пощупать досконально нехватало времени и желания. И вот наконец моё свободное время было потрачено (и не зря) на изучение сего монстра

“Монстром” я называю phing в “хорошем” смысле этого слова – это настоящий кухонный комбайн, СВЧ-печь и стиральная машина в одном флаконе архиве.

Что же это всё-таки такое?. Phing это Ant воссозданный на php. (Вопросы “Чё эта?” и “а нахер?” Вы можете задать непосредственно разработчикам того и другого, а я продолжу…).

Тем кто знает что такое Ant вероятнее всего phing не нужен,тем кто не знает, но интересуется, могу посоветовать хорошую вводную статью, а остальным попытаюсь объяснить вкратце суть явления.

“Но есть способ лучше!”

В процессе разработки чего-либо возникают невероятное количество однообразных операций, которые порядком утомляют.
Как пример из собственной практики – удаление “ненужных” файлов (очистка всемозможных кешей, временных файлов и т.п.), создание структуры директорий (расстановка необходимых прав доступа), удаление debug-кода из скриптов(массовый search-n-replace в определённом наборе файлов), компоновка кучи мелких “инклюдов” в общий файл и много-много подобных мелочей…

Можно конечно всё сделать “вручную”. А можно рутинную работу поручить машине. Одним из способов это сделать являются build-файлы для phing. build-файл представляет собой xml-ку в которой указан проект – совокупность задач (target-ов), которые следует выполнить, а так же последовательность (зависимость – depends в терминах phing) их выполения.

<project name="make_release" basedir=".." default="build">
   <taskdef classname="phing.tasks.ext.PhpStripCommentsTask" name="phpstripcomments" />
   <taskdef classname="phing.tasks.ext.JsLintTask" name="jslint" />
   <target name="clear_cache_dir">
       <delete>
          <fileset dir="cache">
              <include name="*" />
          </fileset>
      </delete>
   </target>
   <target name="lint_before_strip">
      <jslint jslbinary="/usr/bin/jslint" failonerror="true">
          <fileset dir=".">
              <include name="**/*.js"/>
              <exclude name="**/.old_site/**" />
          </fileset>
      </jslint>
    <!-- skip -->
    </target>
    <!-- ....skip -->
    <target name="build" depends="prepare,clear_cache_dir,lint_before_strip,dump_db,copy_src,cleanup_src,remove_debugging,lint_after_strip,simpletests">
    <!-- skip -->
        <mail to="me@mydomain.tld" subject="build complete">
              The build process is a success...
        </mail>
    </target>
</project>

После запуска phing начнёт выполнять default task (в примере – build), и поскольку его выполнить нельзя пока не выполнены depends, то начнёт их делать по указанному порядку… ну и на радостях отправит мне письмо (что конечно лишнее)

“Но и это ещё не всё…”
Спектр задач которые в настоящий момент способен решать phing довольно широк (от файловых операций и строковых манипуляций, до работы с svn, simpletest и phpdoc). Для тех кому зазо исходного набора окажется недостаточно есть замечательная возможность плодить task-и самостоятельно – просто наследуйте новый класс от базового Task и вперёд.
Мне не хватило jslint, jscompress и zndenc – на создание коих было бесследно утрачено минут 15 драгоценного времени. В настоящий момент (ага вот прямо сейчас) обдумываю написание самого аццкого таска – ftpupload (или ftpsync).

Интересный момент – target-ы выполняются строго по порядку и если произойдёт некая непредвиденная ситуация(файл нельзя записать или например как в примере выше в проверяемом коде обнаружится синтаксическая ошибка) другие таргеты выполнятся не будут, выполнение будет прервано exception-ом. Собственно момент интересен тем что можно создавать собственный обработчик этих самых exception-ов, в которых делать “правильные выводы” о том стоит ли продолжать работу или смело “to die if necessary…”.

Другая интересная возможность – делать собственные logger-ы – потому как наблюдать за бурной рабочей деятельностью phing-а в консоли не больно удобно. В стандартной поставки для примера есть AnsiColorLogger, который слегка “приукрашивает” серые терминальные будни. А можно пойти дальше – складывать логи в sqlite например.

“А вы поменяете две пачки обычного порошка на одну пачку необычного?”

Чем хорош именно phing – он написан на php5 – я могу исправить, дополнить и добавить недостающие фичи (Ant несомненно хорош, имеет кучу готовых плагинов, но написан на java, которую я совсем не знаю). Стандартный (g)make откровенно бесит синтаксисом makefile-ов, pake (идея видимо нагло стырена с rake)тоже ничего (хорошего), но уж слишком прост и расширять его возможности довольно муторно :) .
Тонна мелких и крупных shell-perl-php-cmd скриптов, которые я ранее использовал для решения сиюминутных насущных проблем тоже порядком задолбали.
Чем плох – xml как формат build-файлов (хотя на вскидку лучшего предложить ничего не могу, но “аллергия” на xml ещё не прошла) и написан на php5 ;o) – скорость работы оставляет желать лучшего (18 минут на сборку,проверку и упаковку 10-ти мегабайтного проекта на мой взгляд это много).
Но “удобность” всё-таки решает. Так что:

$> pear channel-discover pear.phing.info$> pear install phing/phing

И вперёд…

Technorati Tags: , , ,

20.09.06  |   | 3 comments

Xpath vs regexp.

Стояла задача – собрать некую их статичных html-файлов,в основном табличные данные и ещё немного всего по вершкам. Вёрстка не ахти, поэтому встал вопрос о том что некоторые страницы придётся “парсить вручную”… Закономерности есть, но слишком много условностей (где-то есть class,где-то id, где-то в table есть tbody и т.п.) …

Казалось бы ничего сложного – регулярные выражения вроде бы просто созданы для этого… но мне как-то неулыбалось их составлять… И тут я вспомнил что совсем недавно, исследуя mozdev.org наткнулся на плагин к firefox-у, который зовётся Xpather.Он помимо основной своей функции (показывать нужные ноды по пути и путь выбранной ноды), имеет кратенькую справку, которая открыла глаза на лёгкость написания “непонятных заборов и закорючек”.

  “Отлично” – подумал я – “так тому и быть…”. Осталось преобразовать имеющуюся в наличии совсем невалидную html-ку в xml. Tidy мне помочь отказался (или, что вернее,я не умею его готовить) , tidy_clean_repair предлагал мне “исправить” разметку и т.д. и т.п. Тут же вспомнился замечательный класс SafeHTML ( он так же проживает в PEAR::HTML_Safe ), который помог расчистить разнообразный хлам и выдал мне xhtml. Ну а далее DOMDocument::loadHTML. Но ёлки-палки… ругается на nobr ещё на что-то… но дерево выдаёт. Поставить соб@ку ? ну уж нет… SafeHTML имеет в свойствах массив $deleteTags, туда и добавил nobr и ещё парочку совсем ненужных мне тегов (img например). И так у меня есть dom-дерево, у меня есть функция simplexml_import_dom и есть чёткая уверенность в том что в третьей таблице, во всех рядах начиная с третьего, во второй ячейке есть необходимые мне данные, но они являются необходимыми если среди текста этой ячейки есть ключевое слово (пусть это будет “keyword”). Я конечно “не боюсь” регулярных выражений, но не настолько хорошо их знаю чтобы написать нужное мне. А вот xpath тут как нельзя кстати :

$xpath = “//table[position() = 3]//tr[position() >=3]//td[position() = 2 and contains(text(),"keyword")]/text()”;

  После выполнения $simplexml->xpath($xpath); я получаю массив, который содержит текст из искомых ячеек.

  Итого: избавил товарищей от долгой и нудной,ручной подготовки данных, ещё раз убедился что xpath это вам не пряники на кладбище тырить не только страшная абревиатура, но полезная штука…

P.S.
 Я ни в коем случае не предлагаю повсеместно применять подобную технику (построение dom-дерева операция очень “памятеёмкая”, xpath вероятнее всего тоже), но в ряде случаев использовать такой метод проще и понятнее иных методов…

И название поста “дурацкое”, но на другое не хватает буйности фантазии…

Technorati Tags: , , , ,

20.07.06  |   | стань первым

Selenium Remote Control

Про Selenium я уже писал и не раз.. В очередной раз решил узнать на чём остановилась разработка этого проекта.

Оказалось она вовсе не остановилась… – движется семимильными шагами в сторону автоматизации автоматизированного ;o)
Новое детище товарищей из OpenQA TeamSelenium Remote Control. Это сервер, который в ответ на HTTP запросы может запускать-прибивать браузер, выполнять команды(тесты) selenium-а,выдавать результат,сохранять результат в файл .

Кто-то скажет (кто-то уже сказал) “- и на кой ляд это нужно?” – а нужно это в первую очередь для автоматизированной проверки работы “сложных” UI на рабоспособность в разных браузерах. В комплекте с сервером идут примеры коннекторов на ruby, .NET, python, perl (из последнего легко понять как можно на ходу посылать команды разным браузерам и проверять результат.

Видимо отсутствие коннектора для php “вынудило” товарища Shin Ohno исправить эту оплошность и он “зачал” своё детище – PEAR::Selenium

пример использования это чуда инженерной мысли можно посмотреть здесь.

О себя хочу сказать что использование этой связки в тестовом окружении вызвало дикие тормоза. Похоже проблема кроется где-то глубоко в исходниках сервера(Shin похоже об этом писал , но я в ипонском не силён), поэтому пока использую selenium-rc в batch-режиме – скармливаю ему файл со списком тестов и прогоняю их 3 раза (в IE, FF и Opera) :

>selenuim-rc.cmd project
java -jar selenium-server.jar -htmlSuite “*firefox” “http://project.lan” “Z:\project\public_html\.tests\.cases\htmlSuite.html” “Z:\project\public_html\.tests\.cases\result_firefox.html”
[..]
Killing Firefox…
Tests failed
Shutting down…
[..]
Killing Opera…
Tests failed
Shutting down…
[..]

Некогда “простенький” инструмент потихоньку обрастает “фичами”, буду надеятся что не зря…

Technorati Tags: , ,

24.06.06  |   | стань первым

Памятка кинолог@м

Повесть об операторе управления ошибками

Предисловие.
А началось всё с того, что надо “переносить” множество сайтов с одного сервера на другой. По такому случаю решил-таки установить на новом сервере php5.1(раньше это делать боялся – несколько сотен проектов – и все проверить на работоспособность после апгрейда нет возможности долгая и нудная операция). Так собственно и сделал – по мере переноса сайтов, проверяю что и как работает и при необходимости либо настраиваю php_flag-ами нужные переменные для обратной совместимости, либо правлю проблемный код вручную.

Часть первая
Ошибки и warning-и возникали в основном из-за register_long_arrays Off и присвоения неинициализированным переменным. Потихоньку исправляю. И вот сегодня при переносе очередного сайта обнаружил, что на новом сервере он отказался функционировать должным образом. Ну и ладно… error_reporting E_ALL, display_errors On… – нет не видно ошибок. Нет их в логах php, нет в логах apache и в браузере их тоже нет… тысяча чертей…

Часть вторая.
Пошли дальше – открываю index.php и начинаю var_dump-ить переменные. Методом научного тыка нашёл проблемный файл. Методом всё того же тыка(который научный) вычислил, что проблемы создаёт adodb. Полез в его дебри…

К слову сказать – описываемый сайт сделан не мной (и не моими коллегами), посему разбираться что именно не работает и кто “накосячил” удовольствие приносило сомнительное. Движок какой-то ***nuke, повсюда коментарии в стиле “holy hack”,”fix me” и т.д. – т.е. взять и тупо обновиться до current-версии движка трудновато – приходиться делать всё по-дедовски…

И так я в дебрях adodb. Задумал его обновить, но заметив коментарий в коде “patched for ***nuke version x.y.z” передумал. Стал “дебажить” вручную. Красота кода поражает своей безалаберностью ;o) – сразу вспоминается старый добрый мультфильм о Простоквашино и письме, которое писал Дядя Фёдор…
После 10-ти минутного поиска, я-таки нашёл причину отсутствия ошибок в логах.

Часть третья.
Причиной служила собака. Не овчарка, не бульдог. А аттавизм, доставшийся современному php от первых его версий оператор “@”. Adodb подгружала драйвер для типа СУБД следующим образом: @include ‘/path/to/driver_’.$type.’.php’;
Тут надо брызгать слюнями и сыпать проклятия в адрес разработчиков adodb и обещания вступить в сексуальную связь с их родственниками…. Но я этого делать не буду…
PHP сделал ровно то, о чём его просили – подавил ошибку, которая возникла при include файла. Но на этом не остановился… подавил все ошибки(в том числе и фатальные, которые случились после выполнения кода в Include).

Ошибку в итоге нашёл и исправил (два раза декларировалось одно и тоже свойство в объекте), а вот про собак больше молчать не могу – много раз уже обсуждалась их полезность и бесполезность, много доводов и выводов из этих обсуждений выносилось в факи и книги… А я отныне считаю, что они должны быть низвергнуты! Ибо невинная болонка, сиротливо охраняющая операцию типа @fopen(‘not_existen.file’,'r’) может попортить мегабайт невостановимых нервных клеток и увеличить время отладки до вечности.

Эпилог.

Всех соб@к на хозяйственное электронное мыло. Там им почёт и слава… а в коде (php-коде) им больше места нет! Да будет так. Алюминий.

Technorati Tags: , ,

24.02.06  |   | 2 comments

NTLM-авторизация,браузеры и негодяи…

Нарисовалась интересная задачка – авторизовывать пользователя через AD.
Собственно задачка для меня не нова – в нескольких сервисах я её уже реализовал – через LDAP, на одном, доступ к которому есть из “внешнего мира”, – через mod_auth_pam (winbindd на сервере установлен, настроен и работает как часы “Слава”) – т.е. как бы задачка – казалось бы вовсе не задачка…. Но! Но хочется людЯм чтоб “не выскакивало это окошечко”… Обратили внимание на SharePoint сервер, который (якобы) не спрашивает логин-пароль – объясняю – на самом деле спрашивает, просто этого не видно – говорят – ну и сделай так же – ну и делаю так же… НО! но “без проблем” это делать умеет только IE (Mozilla “в принципе” тоже умеет), а как же Ёпера, она же, убогая, не умеет ВАЩЕ NTLM ?
Забить на Оперу Допустим что Оперой не пользуются… а в принципе.. безопастна ли NTLM-авторизация? посмотрел на PHP NTLM GET LOGIN… судя по реализации можно смело предположить, что потенциальный негодяй может “завернуть” в base64_encode любой логин… (аналогичная история получится с mod_ntlm – первые версии своих “сервисов” делал через него, но после перестановки системы на сервере, он начал “конфликтовать” с разными модулями апача и мне надоело его править)…
Пока оставляю всё как есть – “клиент: форма -> клиент: des_encrypt ->сервер: ldap_connect->сервер: ldap_bind-> сервер: return (true || false) ”

В такой схеме (на мой взгляд) безопасно передаются данные и безопасно(а главное “честно”) проверяется пара логин-пароль согласно всем политикам AD – всякие блокировки по времени, expires и т.д. тогда как при NTLM можно с лёгкостью обойти все эти механизмы

А собственно вопрос – а верно ли я понял, что NTLM – “АЦтой” ? А есть ли способ использовать NTLM прозрачно для клиента и безопасно для сервера?

27.12.05  |   | стань первым

Performance Optimization WordPress Plugins by W3 EDGE