2008-10-02

Zip и UnZip на PHP

Сегодня встала задача сделать поддержку компрессии и декомпрессии в программе на PHP. На первый взгляд задача простая т.к. PHP5 уже содержит методы для работы с архивами ZIP. Во первых это функции вида zip_open, zip_read. Во вторых - есть шикарный класс ZipArchive который выполнит за вас всю грязную работу.

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

Нашел два решения данной проблемы - оба в использовании библиотеки gzip.

Первое решение состоит в использовании PhpConcept Library Zip - написанная Винсентом Блаветом и распространяемая по лицензии GNU/LGPL

Второе решение нашел совершенно случайно в phpMyAdmin - если глянуть в папку /libraries/ то там можно найти два файла zip.lib.php и unzip.lib.php которые содержат классы для паковки и распаковки zip файлов соответственно.

 

Коментариев: 1

 
  2008-09-16

как обработать BMP изображение используя PHP

Как известно библиотека GD не поддерживает возможность прочитать файлы формата BMP а пользователи (особенно малограмотные пользователи) часто так и норовят закачать на сайт фото или картинку в формате BMP. Как быть если закачать нельзя но очень хочется? Оказывается есть способ.

Здесь работающая демка а здесь сходник

Собственно всю грязную работу выполняет класс написанный Джеймсом Хайнрихом (James Heinrich) для своего проекта getID3(). Что интересно, в последних версиях проекта класс уже не умеет преобразовывать BMP в GD а только читает метаинформацию. На старую версию класса наткнулся совершенно случайно - она есть в phpThumb уже в полном варианте. Большое спасибо Джемс :)

 

Коментариев: 4

 
  2008-05-01

Как используя GnuPG зашифровать сообщение из программы на PHP?

Встала задача - закодировать мейлы посылаемные с сервера крипростойким образом.

В принципе что сложного - ставим на сервер GnuPG, на рабочую станцию PGP импортируем на сервер открытый ключ с рабочей станции и дело в шляпе. Одна загвосдка - GnuPG - это консольная утилита которой для того чтобы зашифровать файл нужно его передать через stdin, результат будет выдан на stdout. Как вызвать ее из программы на PHP? Можно конечно создать временный файл и уже через переадресацию ввода вывода залить его в программу, но это то как то не секьюрно.

Оказывается в PHP есть отличная функция - proc_open, которая позволяет реализовать переадресацию стандартных потоков через pipes - просто и элегантно.

Вот что получилось:

$s = "string to encrypt"; $descriptorspec = array( 0 => array("pipe", "r"), // stdin is a pipe that the child will read from 1 => array("pipe", "w"), // stdout is a pipe that the child will write to 2 => array("pipe", "w") // stderr is a file to write to ); $cmd = 'gpg -e --always-trust -r USERID'; $cwd = '/tmp'; $env = array('HOME' => '/tmp'); $process = proc_open($cmd, $descriptorspec, $pipes, $cwd, $env); if (is_resource($process)) { // $pipes now looks like this: // 0 => writeable handle connected to child stdin // 1 => readable handle connected to child stdout // Any error output will be appended to /tmp/error-output.txt fwrite($pipes[0], $s); fclose($pipes[0]); echo stream_get_contents($pipes[1]); fclose($pipes[1]); $error = stream_get_contents($pipes[2]); echo $error; fclose($pipes[2]); // It is important that you close any pipes before calling // proc_close in order to avoid a deadlock $return_value = proc_close($process); echo "command returned $return_value\n"; }
 

Коментариев: 2

 
  2008-04-14

Полезная функция для валидации email на JavaScript

function validateEmail(elementValue){ 
    var emailPattern = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;  
    return emailPattern.test(elementValue);  
}
 

Оставить комментарий

 
  2008-02-15

Error Reporting

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

Для того чтобы погасить вывод ошибок на экран этот оператор просто локально меняет значение error_reporting а затем возвращает его в предыдущее значение.

Чтобы проверить этот факт создал простейший скрипт:

error_reporting(E_ALL); function test(){ print "inside ".error_reporting()."<br />"; } print "outside: ".error_reporting()."<br />"; @test();

вывод на экран:

outside: 6143 inside 0

Что и требовалось доказать.

 

Оставить комментарий

 
  2007-12-26

Странное поведение eval

eval('$c = "test;'); print $c;

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

Чтобы вылавливать подобные ошибки пришлось сделать буффер и смотреть не вываливает ли eval что нибудь на экран.

Так выглядит готовая функция для приобразования PHP строки в переменную:

function str2php($value){ $c = null; ob_start(); eval('$c ='.$value.";"); $error = ob_get_contents(); ob_end_clean(); if (!empty($error)) return null; return $c; }
 

Оставить комментарий

 
  2007-12-15

(Казнить [нельзя) помиловать]

Только что пришлось покапаться в исходниках vBulletin - ребята курят очень неслабую траву, весьма забористую...

После очередной модификации сайта при регистрации пользователя стало перебрасывать на совершенно экзистенциальный url вида :/forum/admincp.php - т.е. кудато пропал http из пути.

После часа ковыряний нашел следующее:

define('REQ_PROTOCOL', (isset($_SERVER['HTTPS']) AND (($_SERVER['HTTPS'] == 'on' OR $_SERVER['HTTPS'] == '1')) ? 'https' : 'http'));

Индийские программисты очень умные, очень наблюдательные, очень усидчевые... задницы, но всеже пару скобок проглядели... В результате REQ_PROTOCOL принимает значение false вместо положенного http.

 

Коментариев: 2

 
  2007-11-27

PHP4: это не баг, это системная функция

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

Не работает:

class SomeClass { function singleton(){ static $instance = null; if ($instance==null){ $instance =& new SomeClass(); } } }

Работает:

class SomeClass { function singleton(){ static $instance = null; if ($instance==null){ $instance = new SomeClass(); } } }

В пятом PHP будет работать только первый вариант, второй правда хотя и со скрипом, то тоже будет (будет ругаться чтобы к функции поставили модификатор static и не использовали никаких амперсандов у оператора new)

 

Оставить комментарий

 
  2007-11-15

Перебираем XML ноды

Обычно я использлую цикл while когда нужно сделать итерацию по дочерним элементам XML нода, а тут решил что цикл for для этих целей подходит гораздо лучше.

было:

var item = element.firstChild; while(item!=null){ if ((item.nodeType==1) and (item.nodeName=='tagname') { //здесь код } item = item.nextSibling; }

стало:

for(var item = element.firstChild;item!=null;item = item.nextSibling;){ if ((item.nodeType==1) and (item.nodeName=='tagname') { //здесь код } }
 

Оставить комментарий

 
  2007-11-10

Статические пременные класса vs. суперглобальных переменных

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

В PHP есть также т.н. суперглобальные переменные - $_POST, $_GET.

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

Захотелось мне сделать свои суперглобальные переменные куда я хочу поместить значения из $_POST и $_GET, но без magic_quotes.

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

Как быть? Суперглобальные переменные нельзя создать - они накрепко зашиты в PHP и новые суперглобальные переменные сделать невозможно, но я нашел один выход из данной ситуации.

PHP5 позволяет создавать статические переменные класса, т.к. область видимости класса - весь код, то и полученная переменная ведет себя как суперглобальная. Красота.

class Site{ static $POST; static $GET; static $COOKIE; static function stripslashes($val){ $type = gettype($val); if ($type=='string'){ return stripslashes($val); } elseif($type=='array'){ $var1 = array(); foreach($val as $key=>$value){ $var1[$key] = Site::stripslashes($val[$key]); } return $var1; } else { return $val; } } static function initSite(){ if (ini_get('magic_quotes_gpc')){ Site::$GET = Site::stripslashes($_GET); Site::$POST = Site::stripslashes($_POST); Site::$COOKIE = Site::stripslashes($_COOKIE); } else { Site::$GET = $_GET; Site::$POST = $_POST; Site::$COOKIE = $_COOKIE; } } } Site::initSite();

При этом полученные переменные Site::$POST и Site::$GET ведут себя также как и аналогичные классические аналоги $_POST и $_GET.

 

Оставить комментарий