home

IT Runs

text

Imagick и аватарки

Последние несколько дней посвящены изучению загрузки и обработки аватарок. Умнее я себя не чувствую, но я определенно накопал несколько интересных вещей. Конечно же, для обработки используется горячо любимая ImageMagick и ее объектный API для php. Проблема этого API только одна - оно практически не документировано. В таком количестве функций черт ногу сломит, а к большинству из них нет даже элементарного описания того, что они делают. Ну, да не об этом речь.

Вот целый блог гражданина, который, по всей видимости, серьезно занимается этой библиотекой:

http://valokuva.org/

Вот небольшая заметка о том, как делать симпатичные превьюшки (thumbnail) для картинок:

<?php
$thumb = new Imagick();

//читаем картинку по полному пути
$thumb->readImage($fullpath)

//создаем белый фон
$canvas = new Imagick();
$canvas->newImage($width, $height, new ImagickPixel(“white”));

//делаем превью, размер меньше, чем у фона, чтобы было куда впихнуть тень
$thumb->thumbnailImage($width-10, $height-10);

//наводим резкость, если превью мелкое
if ($width < 300) $thumb->sharpenImage(4, 1);

//делаем копию превьюхи, чтобы сделать тень
$shadow = $thumb->clone();

//цвет тени
$shadow->setImageBackgroundColor(new ImagickPixel(‘black’));

//собственно, делаем тень
$shadow->shadowImage(80, 2.5, 5, 5);

//накладываем тень на фон
$canvas->compositeImage($shadow, $shadow->getImageCompose(), 0, 0);

//накладываем превью на фон
$canvas->compositeImage($thumb, $thumb->getImageCompose(), 0, 0);

//убираем комменты и т.п. из картинки
$canvas->stripImage();

//записываем картинку
$canvas->writeImage($writeTo);

//подчищаем за собой
$canvas->destroy();
$shadow->destroy();
$thumb->destroy();

?>

via http://habrahabr.ru/blogs/php/43511/

Надо только отметить, что этот метод плохо работает с GIF’ами (видимо, с PNG тоже), у которых есть прозрачный цвет. Ибо тень в таком случае получается очень коряво. Я потратил еще несколько часов на попытки адаптировать его под работу с GIF’ами, но так ничего и не получилось. В другой раз, видимо.

2 years ago

April 4, 2010
text

Необходимый фокус с кодировками

Итак, все настроено для работы с UTF-8:

  • в заголовке страницы есть <meta http-equiv=”Content-Typecontent=”text/html; charset=UTF-8“>
  • в базе данных указана кодировка по умолчанию utf-8
  • apache настроен отдавать страницы в utf-8

Остается только одно: когда данные формы передаются в php и затем помещаются в базу данных, через phpmyadmin они выглядят как не понятно что. И все вроде бы хорошо, потому что если через тот же php вывести данные из БД, то они отображаются нормально. Но эта фигня в phpmyadmin режет глаза.

Решается оно вот как. После подключения к базе данных, вписываем следующие строчки:

mysql_query (“set character_set_client=’utf8’”);
mysql_query (“set character_set_results=’utf8’”);
mysql_query (“set collation_connection=’utf8_general_ci’”);

Ну или какая там кодировка, соответственно. Эти строчки настраивают соответствие кодировок клиента и сервера MySQL, и приводят этот бардак в порядок.

2 years ago

April 3, 2010
text

И еще последствия перехода на UTF-8

И конечно же, с мультибайтовыми строками обламываются стандартные функции для работы со строками. Облом заключается в том, что один символ они начинают считать за два. Исправляется, опять же, использованием расширения mb_string:

http://ru2.php.net/manual/en/ref.mbstring.php

Лично я просто заменил функции:

strlen = mb_strlen

substr =mb_substr

и все чудесным образом исцелилось.

2 years ago

March 3, 2010
text

Еще одно решение проблемы mail в php

Поступило еще одно решение проблемы с темой (subject) письма, отправляемого функцией mail в php (подробности здесь: http://itruns.ru/post/422397378/sendmail). За решение спасибо ereptoris:

$subject = '=?UTF-8?'; //Говорим, что у нас в теме текст в соответствующей кодировке

$subject .= 'B?'; //А текст зашифрован алгоритмом base64

$subject .= base64_encode($content) . '?='; // Кодируем текст и дописываем завершающее выражение

Нечто похожее описано на той же странице на php.net. Может быть кому-то так и удобнее, не спорю. Лично для меня, более простой и очевидный способ я описал в предыдущей заметке, тем более, mb_string в любом случае подключен и никакой его глючности я пока что не заметил.

2 years ago

March 3, 2010
text

Новые потрясающие выкрутасы с sendmail

В темпе вальса переводим все письма в UTF-8! И, само собой, ничто никогда не работает сразу так, как хочется =).

Если в header просто заменить кодировку на UTF-8:

Content-type: text/html; charset=utf-8

само тело письма преобразуется нормально. Однако тема (subject) продолжает подражать самым изысканным иероглифам. На сайте php.net нашлась вот такая строчка:

$subject= mb_encode_mimeheader($subject, “UTF-8”, “B”, “\n”);

Сработало. Почему-то, не с первого раза, но это я уже не в силах объяснить.

2 years ago

March 2, 2010
text

geoip

В общем, нужно было отфильтровать американцев от всех остальных, по IP. Один вариант это сделать - установить модуль для веб-сервера. В этом случае в глобальном массиве $_SERVER появляются несколько переменных, которые, соответственно, можно просто использовать в коде.

Другой вариант - PECL-расширение для php. Тут просто набор функций, которым передается IP юзера, и они возвращают что надо:

http://ru2.php.net/manual/en/book.geoip.php

К нему надо еще установить сишную библиотеку geoip, затем установить само PECL-расширение, а потом не забыть добавить extension=geoip.so в php.ini. Более точно и подробно процесс описан тут:

http://www.outofcontrol.ca/2009/02/10/installing-pecl-geoip-problem/

Не знаю, кстати, чего там требует способ №1 - этим занимаюсь не я. Но мне кажется, он гораздо удобнее второго.

2 years ago

February 18, 2010
text

imagick загрузка картинок

Просто кусок кода, который берет картинку из файла, изменяет ее размер и записывает в файл. Для работы нужен imagick с объектным интерфейсом.

$image = new Imagick($_FILES[‘userfile’][‘tmp_name’]);

$width = $image->getImageWidth();
if ($width > 100) {
$image->thumbnailImage(100, null, 0);
}

$height = $image->getImageHeight();
if ($height > 100) {
$image->thumbnailImage(null, 100, 0);
}

//$image->thumbnailImage(100, 100, true);
//$image->resizeImage(100, 100, imagick::FILTER_LANCZOS, 1);
$image->writeImage($uploadfile);

$image->clear();
$image->destroy();

2 years ago

February 17, 2010
text

Ветви

При создании CLI скриптов часто приходится делать разветвленные программы чтобы ускорить обработку чего-либо (можно использовать в кэшерах и спайдерах). При этом основной процесс должен запускать дочерние в бэкграунде (с & на конце). Проблема в том, что как только основной процесс запустил все дочерние, сам он завершается. А хотелось бы чтобы он дождался пока все дочерние тоже закончат и записал общее время работы и т.д. в лог.

Для этого был придуман вот такой кусок кода:

$flag = true;
while($flag){
$str = `ps aux | grep ИМЯ_ДОЧЕРНЕГО_ПРОЦЕССА`;
$num_arr = explode(“\n”, $str);
$proc_count = 0;
foreach($num_arr as $strin){
if(strpos($strin,”/usr/local/bin/php”) !== false) $proc_count++;
}
if($proc_count > 0) sleep(60);
else $flag = false;
}

Оно ставиться в конец основного скрипта и тормозит его до тех пор, пока все дочерние не закончат. while(true) - не очень красиво и не очень безопасно. Но служит мне верой и правдой уже год. Как-нибудь сяду и напишу функцию, чтобы было короче.

2 years ago

February 17, 2010
text

Переменные переменных

Большего бреда в жизни не слышал. Но штука забавная =))

Переменные переменных

РНР предоставляет еще один тип переменных — т.н. переменные переменных. Переменные переменных позволяют динамически изменять имена переменных. (Как видите, РНР допускает очень большую свободу в этом вопросе — все языки разрешают изменять значение переменной, но лишь немногие позволяют изменять тип переменной, а уж совсем немногие — имя переменной.)

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

$varname = “tireqty”;

Затем вместо $tireqty можно использовать $$varname, например, так:

$$varname = 5;

Это может показаться несколько запутанным, однако позже мы еще вернемся к этому вопросу. Вместо того чтобы перечислять и использовать каждую переменную формы отдельно, можно организовать цикл и переменную для автоматической обработки всех из них. Пример, иллюстрирующий такой метод, приводится в разделе, посвященном циклам for.

via

2 years ago

February 17, 2010
text

Анти-brute

Только что наткнулся на интересную мысль, на сайте php, в комментах к функции sleep:

Very useful to prevent password brute forcing! Simply add few seconds timeout to login script and the probability to guess the password decreases a lot!

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

Хотя эффективнее делать ограничение числа ввода пароля, имхо.

2 years ago

February 17, 2010
text

Комменты в Eclipse

Только что в порыве страсти к своему коду случайно нашел горячие клавиши для комментариев в Eclipse:

CTRL+/  - комметирует строчку или выделенный кусок с помощью // комментария

CTRL+SHIFT+/ - берет выделенный кусок в /* */ комментарий

text

ООП на PHP

Нашел замечательную коротенькую статью:

Итак, семь хороших объектно-ориентированных привычек при программировании на PHP:

  1. Будьте скромны.
  2. Будьте хорошим соседом.
  3. Не смотрите на Медузу Горгону.
  4. Применяйте самое слабое связывание.
  5. Обеспечьте высокое сцепление.
  6. Поддерживайте семейственность.
  7. Мыслите шаблонами.

Продолжение и подробности:

Семь хороших объектно-ориентированных привычек при программировании на PHP

2 years ago

February 17, 2010
text

Оповещения

Еще одна проблема, возникшая сегодня - оповещения об ошибках. Ситуация такая: на сервере живет около 30 php-скриптов, которые запускаются кроном. Некоторые из них собирают информацию с других сайтов и кладут ее в базу данных. Когда на внешнем сайте неожиданно меняется структура html, скрипт обламывается и выдает ошибку. Или просто не собирает ничего. Происходит такое не часто, но когда случается, шума из-за этого много. Но ходить и каждый день руками проверять, все ли работают не хочется.

Старое решение:

Пишется функция, которая проверяет данные, которые собирает скрипт. Если данные не подходят по формату, функция останавливает скрипт и отсылает письмо админу с сообщением, что что-то не так. Решение работает, но есть несколько проблем:

  • для каждого нового скрипта нужна новая функция проверки формата данных
  • получается сильное нагромождение кода со всеми конструкциями if-else и так далее
  • если скрипт обламывается много-много раз подряд, то почта админа сильно засоряется, не говоря уже о том, что большие очереди sendmail могут серьезно перегрузить сервер.

Последнее, собственно и произошло, после чего было принято решение изобрести другой метод оповещения.

Новое решение (еще не опробовано):

Все скрипты в процессе работы создают файлы с расширением .script_log, ну или вообще каким угодно, кладут их в папочки, и забывают об оповещениях об ошибках. Если в процессе выполнения возникает ошибка, то скрипт просто записывает ее в лог, а перед ней ставит что-то вроде “scripterror: “. Раз в сутки (2 раза в сутки - не важно) запускается скрипт, который выполняет команду

grep “scripterror” /siteroot/*.script_log

которая находит все файлы, в которых есть строчка “scripterror”. Остается только слегка обработать эту информацию и подсчитать количество ошибок. И можно отсылать письмо админу. Таким образом, имеем ежедневный отчет о происходящем на сервере.

2 years ago

February 17, 2010
text

Кусочек кода

Сегодня уже в который раз столкнулся с такой проблемой: есть сайт, с которого нужно нагло содрать какую-то информацию. На этом сайте html-сущности закодированы не очень понятно чем и выглядят на подобии &#x26; (представление амперсанда). Вроде интуитивно понятно, что к чему. Вот только обычными функциями php это не возьмешь. Нашелся вот такой кусочек кода:

$str = preg_replace(‘~&#x([0-9a-f]+);~ei’, ‘chr(hexdec(“\1”))’, $str);
$str = preg_replace(‘~&#([0-9]+);~e’, ‘chr(“\1”)’, $str);

Он работает. Лежал на самом видном месте - в примерах к функции html_entity_decode.

Кстати, скорее всего пригодиться при работе со всякими языками вроде китайского.

2 years ago

February 17, 2010