Проверка даты

<?php
/**
 * Проверка даты.
 * автор: Nc_Soft
 * 11.06.08
 */

/*для проверки корректности даты в формате ДД.ММ.ГГГГ ЧЧ:ММ
можно применить следующую функцию.
если знаете подобную из стандартных, то сообщите в комментах.
*/

function ext_check_date($data)
{
	//проверка формата
	$parse = date_parse ( $data );
	if ( $parse['error_count'] != 0 )
	return 0;

	//проверка по грегорианскому календарю
	if (!(checkdate($parse['month'], $parse['day'], $parse['year'])))
	return 0;

	return $data;
}

$data = '30.02.2008 12:59';
$data = ext_check_date($data);

if (!$data)
echo 'дата не верна';
?>
11 июня 2008, 18:30

Автоматическое подключение файлов к скриптам

# Автоматическое подключение файлов к скриптам
# автор: Nc_Soft
# 21.05.08

#часто бывает необходимо подключать одни и теже файлы
#чтобы не писать каждый раз include можно прописать в .htaccess

php_value auto_prepend_file c:\WebServers\home\snippets\www\verx.php 

#auto_prepend_file означает подключение до скрипта

php_value auto_append_file c:\WebServers\home\snippets\www\niz.php 

#auto_append_file означает подключение после скрипта
21 мая 2008, 20:09

Подсветка php кода с нумерацией строк

<?php
/**
 * Посветка php кода с нумерацией строк
 * автор: Nc_Soft
 * 21.05.08
 */

//файл для подсвечивания
$f=highlight_file('c:\WebServers\home\snippets\test.php',1);

/*
можно $f=highlight_string()
*/

//первая строка
$str=1;

//замена по регулярному выражению с функцией обратного вызова
$f=preg_replace_callback('|<br />|sU','stroka',$f);

//первая строчка + код
echo '<span style="background-color:black;color:white">01</span> '.$f;

function stroka($v)
{
     GLOBAL $str;
     $str++;
     
     return $v[0].'<span style="background-color:black;color:white">'.sprintf("%02d", $str).'</span> ';
}

?>
21 мая 2008, 16:23

Подсчет размера каталога с подкаталогами при помощи SPL

<?php 
/**
 * Подсчет размера каталога с подкаталогами при помощи PSL 
 * автор: Nc_Soft 
 * 20.05.08 
 */ 

//нам понадобится php5 с PSL

//путь к директории
$path='.';

//используем RecursiveDirectoryIterator
$files=new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path) );

//размер
$size=0;

foreach ($files as $element)
{
	//визуально контролируем
	echo $element.' '.$files->getSize($element)." <br />\n";
	
	//подсчет
	$size+=$files->getSize($element);
}

//выводим
echo $size;

//как видите, php5+PSL очень упрощают рутинные операции

?>
20 мая 2008, 15:10

Постраничный вывод из Mysql

<?php
/**
 * Постраничный вывод из Mysql
 * автор: Nc_Soft
 * 20.05.08
 */

/*
Для более удобного вывода нам потребуется класс навигатор
скачать его можно по ссылке
http://snippets.pp.ru/class/Navigator.class.txt
необходимо переименовать его рассширение в php и подключить к скрипту
*/

//полключаем навигатор
require_once('Navigator.class.php');

/*
пусть у нас такая таблица в БД
id | user | msg
*/

//общее число записей
$q=mysql_query(" SELECT count(*) FROM our_table ");
$all=mysql_result($q,0,0);

//если есть записи, то включаем навигатор

if ($all)
{
	//записей на страницу
	$pnumber=10;
	
	//создаем объект
	$n=new Navigator($all,$pnumber);
	
	//запрос
	$q=mysql_query("SELECT * FROM our_table LIMIT {$n->start()},$pnumber ");
	
	//выводим результаты
	while (false!==($res=mysql_fetch_assoc($q)))
	{
		echo '<div>';
		echo 'id = '.$res['id'].'<br />';
		echo 'user = '.$res['user'].'<br />';
		echo 'msg = '.$res['msg'];
		echo '</div>';
	}
	
	//печатаем навигацию
	echo $n->navi();
}

?>
20 мая 2008, 01:06

Клиентский сервер на Php

<?php
/*
* Клиентский сервер на Php
* прислано: Антон Крупников
* 12.05.2008
*/

### Для работы скрипта требуется установленная на хосте библиотека php_sockets и должен быть отключен безопасный режим (safe_mode off)
$host = "127.0.0.1"; // IP
$port = 80; // Порт
set_time_limit(0)or die("Error! Safe mode on.\n"); // работаем бесконечно
$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create socket\n"); // создаём сокет
$result = socket_bind($socket, $host, $port) or die("Could not bind to socket\n"); // привязываем сокет
$result = socket_listen($socket, 3) or die("Could not set up socket listener\n"); // слушаем сокет
while($socket){ // Работаем пока $socket возвращает TRUE
$spawn = socket_accept($socket) or die("Could not accept incoming connection\n");
$input = socket_read($spawn, 1024) or die("Could not read input\n"); // Читаем сокет
echo $input; // выводим все, что прочли, в браузер
$output = "Hello, World!"; // Текст ответа
socket_write($spawn, $output, strlen ($output)) or die("Could not write output\n"); // Отправляем клиенту Hello, World!
socket_close($spawn); // Завершаем работу с клиентом
}
socket_close($socket); // Закрываем сокет
?>
12 мая 2008, 23:07

Защита файлов от просмотра браузером

#Запрет к определенному файлу
<Files config.php> 
  deny from all 
</Files>

#Запрет к группе файлов по рассширению
<Files "*.ini"> 
  deny from all 
</Files> 

#Запрет к нескольким типам файлов по рассширению
<Files ~ ".(inc|conf|cfg)$"> 
  deny from all 
</Files>
3 мая 2008, 13:29

Jad генератор

<?php
/**
 * Jad генератор
 * автор: Nc_Soft
 * 29.04.08
 */

/*
jar это zip архив, поэтому потребуется class PclZip
http://snippets.pp.ru/class/PclZip.class.txt
*/

require_once('PclZip.class.php');

//jar файл
$file='test.jar';

//создаем объект
$jar=new PclZip($file);

//то , что извлеч
$mf='META-INF/MANIFEST.MF';

$jad=$jar->extract(PCLZIP_OPT_BY_NAME, $mf, PCLZIP_OPT_EXTRACT_AS_STRING);

$jad=$jad[0]['content'];

/*
А вообще, можно извлечь манифест еще проще 
$jad = file_get_contents("zip://$file#META-INF/MANIFEST.MF");
*/

//далее надо приписать урл и размер в байтах
$jad.="\nMIDlet-Jar-Size: ".filesize($file)."\nMIDlet-Jar-URL: $file";

/*
всё, можно либо сохранять
file_put_contents('test.jad',$jad);
либо выдавать скриптом

header("Content-type: text/vnd.sun.j2me.app-descriptor");
header('Content-Disposition: ; filename=test.jad');

*/

?>
29 апреля 2008, 22:34

Вывод содержимого каталога с подкаталогами при помощи SPL

<?php
/**
 * Вывод содержимого каталога с подкаталогами при помощи SPL
 * автор: Nc_Soft
 * 28.04.08
 */

//нам понадобится php5 с PSL

//путь к директории
$path='.';

//используем RecursiveDirectoryIterator
$files=new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path) );

//выводим с учетом вложенности
foreach ($files as $element)
echo str_repeat('-',$files->getDepth())."$element <br />\n";

//как видите, php5+PSL очень упрощают рутинные операции

?>
28 апреля 2008, 19:16

Скачка удаленного файла при помощи CURL

<?php
/**
 * Скачка удаленного файла при помощи CURL
 * автор: Nc_Soft
 * 27.04.08
 */

//открываем сеанс
$curl = curl_init('http://example.com/file.zip');

//задаем параметры
curl_setopt($curl, CURLOPT_USERAGENT, 'Boroda/2.0 J2ME/MIDP');

//открываем файловый дескриптор (куда сохранять файл)
$fp =fopen('save.zip','w+b');

//сохраняем файл
curl_setopt($curl, CURLOPT_FILE, $fp);

//запускаем сеанс
curl_exec($curl);

//закрываем сеанс
curl_close($curl);

//закрываем дескриптор
fclose($fp);

?>
27 апреля 2008, 00:52

Создание Html документа при помощи DOM

<?php
/**
 * Создание Html документа при помощи DOM
 * автор: Nc_Soft
 * 25.04.08
 */

/*
правильный хтмл документ (well-formed) по сути является xml документов и
"конструктор" у нас в кармане, главное чтобы хостинг поддерживал DOM
*/

//создаем объект
$doc = new DOMDocument("1.0","UTF-8");

//добавим тэг html
$html = $doc->createElement("html");

//добавим тег body
$body = $doc->createElement("body");

//добавим тэг h1 и надпись
$h1 = $doc->createElement("h1","Тестовая надпись");

//сформируем html
$body->appendChild($h1);
$html->appendChild($body);
$doc->appendChild($html);

//вывод на экран
echo $doc->saveHTML();

/*
Пример создан для демонстрации возможности, сразу не понравилось то,
что русская надпись выглядит так
Тестовая
*/
?>
25 апреля 2008, 11:09

Выдача файла скриптом

<?php
/*
* Выдача файла скриптом
* автор: nc_soft
* 20.04.08
*/

//путь к файлу для выдачи
$file='./example.gif';

//Mime тип (в данном случаи image/gif)
$mime='image/gif';

//формируем заголовки

//MIME
header('Content-type:'.$mime);

//размер файла
header('Content-Length: '.filesize($file));

//указываем имя файла
header('Content-Disposition: attachment; filename='.basename($file));

/*
примечание: если так выдавать картинку, то мой сиеменс пытается сохранить ее
как имя_скрипта.gif, пробовал вот так
header('Content-Disposition: ; filename='.basename($file));
тоже самое.
С компа все в порядке.
Если кто знает как выдать для мобильника чтобы имя файла по умолчанию было какое указано
просьба отписаться.
*/

//вываливаем файл в браузер
readfile($file);

?>
20 апреля 2008, 13:09

Кэширование данных

<?php
/*
* Кэширование данных
* автор: Nc_Soft
* 15.04.08
*/

/*
Предположим, у нас есть некий скрипт, который собирает инфу с другого сайта,
(тоесть граббер страницы например http://example.com).
Пусть инфа на том гипотетическом сайте меняется например раз в час,
в данной ситуации довольно расточительно коннектиться к этому сайту при каждом запросе,
гораздо логичнее кэшировать данные, а чтобы они занимали меньше места, то и сжимать их.
И для этого совсем необязательно использовать класс Pclzip, вот предложу такой вариант:
*/

//урл
$url='http://example.com';

//путь к файлу-кэшу
$cache='./cache.gz';

//если нет файла-кэша или он устарел (1 час и более), то коннектимся
if (!file_exists($cache) || time() - filemtime($cache) > 3600 )
{
	//получение инфы
	$info=file_get_contents($url);

	//кэширование инфы с максимальным сжатием (level 9)
	$zp = gzopen($cache, 'w9');
	gzwrite($zp, $info);
	gzclose($zp);
}
else
{
	//берем $info из кэша, предварительно распаковав
	$info=gzfile($cache);
	$info=implode($info);
}

//выводим данные
echo $info;

/*
Таким образом, значительно сокращается число запросов к сайту-источнику, а если эта информация текстовая, 
то сжатие позволяет уменьшить ее объем до 10раз, тем самым хранение такого кэша не займет много места.
*/

?>
15 апреля 2008, 02:27

Кодирование сообщения по ключу

<?php
/*
* Кодирование сообщения по ключу
* автор: nc_soft
* 26.03.08
*/

$key="это ключ, если его не знать ничего не расшифровать";

$text="кодируемое сообщение";

//закодируем
$code=mcrypt_ecb(MCRYPT_DES,$key,$text,MCRYPT_ENCRYPT);

//сообщени закодировано, приняло вид бессмысленного набора байтов
echo "<p>сообщение закодировано: <b>$code</b></p>";

//раскодируем (надо применить ключ к этому набору байтов)
$decode=mcrypt_ecb(MCRYPT_DES,$key,$code,MCRYPT_DECRYPT);

echo "<p>сообщение раскодировано: <b>$decode</b></p>";

/*
что же делать, если на хостинге нет библиотеки для шифрования?
конечно же можно воспользоваться самопальными функциями их комментов сайта php.net или 
написать свою функцию :)
*/

function encrypt($string, $key) {
	$result = '';
	for($i=0; $i<strlen($string); $i++) {
		$char = substr($string, $i, 1);
		$keychar = substr($key, ($i % strlen($key))-1, 1);
		$char = chr(ord($char)+ord($keychar));
		$result.=$char;
	}

	return base64_encode($result);
}

function decrypt($string, $key) {
	$result = '';
	$string = base64_decode($string);

	for($i=0; $i<strlen($string); $i++) {
		$char = substr($string, $i, 1);
		$keychar = substr($key, ($i % strlen($key))-1, 1);
		$char = chr(ord($char)-ord($keychar));
		$result.=$char;
	}

	return $result;
}

//закодируем
$code=encrypt($text,$key);

//сообщени закодировано
echo "<p>сообщение закодировано: <b>$code</b></p>";

//раскодируем
$decode=decrypt($code,$key);

echo "<p>сообщение раскодировано: <b>$decode</b></p>";

?>
26 марта 2008, 17:27

Организация полнотекстового поиска в MYSQL

<?php
/*
* Организация полнотекстового поиска в MYSQL
* автор: Nc_soft
* 25.03.08
*/

//что ищем
$search='поисковая строка';

/*
Для организации поиска при небольшой нагрузки и коротких текстах отлично подходит оператор LIKE, пример
*/
$q=mysql_query("SELECT * FROM tablica WHERE pole LIKE '%$search%' ");

/*
Тут вроде бы все нормально, но когда количество записей и их объем сильно возрастет 
вы заметите, что поиск начинает занимать довольно много времени, и в итоге может достичь 
недопустимых пределов.
В таких случаях необходимо воспользоваться ИНДЕКСАМИ, например, сделаем через 
phpMyAdmin полнотекстовый индекс для ячейки pole, sql дамп создания таблицы приведен ниже

CREATE TABLE `tablica` (
  `id` int(11) NOT NULL auto_increment,
  `pole` TEXT,
  PRIMARY KEY  (`id`),
  FULLTEXT KEY `kluch` (`pole`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8

обратите внимание на FULLTEXT KEY `kluch` (`pole`), индекс повешен на ячейку pole, 
как нетрудно заметить, размер базы данных из-за индекса увеличился примерно вдвое (за все надо платить).

Теперь искать по такой базе надо вот так:
*/

$q=mysql_query("SELECT * FROM tablica WHERE MATCH pole AGAINST ('$search') ");

/*
Скорость поиска возрастет минимум в 10раз, так же из плюсов то, что результаты будут отсортированы
по релевантности (тоесть сначала вся фраза, потом по частоте попадания слов)! (если не применять ORDER BY для иной сортировки конечно)

Также есть и минусы:
1. слова менее 4 символов не учитываются (как не имеющие "веса")
2. русские фразы находятся без учета морфологии
3. размер базы увеличивается из-за индекса
4. операции INSERT и UPDATE выполняются медленнее из-за индекса

если у вас в таблице более 10000 строчек и размер бд более 5мб наверное стоит перейти на полнотекстовый поиск
*/

?>
25 марта 2008, 18:42

ЗАПИСЬ В MYSQL данных из формы

<?php 
/* 
*ЗАПИСЬ В MYSQL данных из формы 
*автор: nc_soft 
*24.03.08 
*/ 

//переменная ошибок 
$error=array(); 

//обработчик формы 
if (!empty($_POST)) 
{ 
    //проверка параметра (удаляем лишние слэши и экранируем всё для записи в базу данных)
    $var=mysql_escape_string(stripslashes(trim($_POST['var'])));
	 
    if (empty($var)) 
    $error['empty']='не введен параметр'; 
     
    //если все нормально записываем
    if (empty($error)) 
    { 
		mysql_query("INSERT INTO tablica SET var='$var' ");
         
        /*переадресация , чтобы сбросить пост, это нужно чтобы при нажатии кнопки обновить  
         данные не добавились вновь*/ 
        header('Location: '.$_SERVER['SCRIPT_NAME'].'?ok=1'); 
        die(); 
    } 
} 

//если есть ошибки выводим 
if (!empty($error)) 
echo '<p>'.implode('<br />',$error).'</p>'; 

if (isset($_GET['ok'])) 
echo '<p>данные записаны</p>'; 

//сама форма 
?> 
<form action="<?=$_SERVER['SCRIPT_NAME'];?>" method="post"> 
<p> 
введите параметр:<br /> 
<input name="var" value="<?=isset($_POST['var']) ? htmlspecialchars(stripslashes(trim($_POST['var']))) : '';?>" /><br /> 
<input type="submit" value="отправить" /> 
</p> 
</form> 

<?php 
/* 
Примечания: 

Для сбора ошибок используется именно массив, потому что удобно впоследствии выводить их через <br /> или списком,  
в ключе ммассива также можно указать причину $error['empty']='не введен параметр'; 

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

*/ 
?>
25 марта 2008, 01:24

Как инклудить при запуске cron'om

<?php
/*
* Как инклудить при запуске cron'om
* автор: Nc_soft
* 24.03.08
*/

/*
Во-первых опеределимся с командой для крона
/usr/local/bin/php -f /home/USER/domains/DOMEN/public_html/cript.php
(вместо USER и DOMEN пишем свои данные)
Далее может быть проблема, когда скрипт подключает другие файлы, способы типа
require_once('./file.php');
require_once($_SERVER['DOCUMENT_ROOT'].'/file.php');
могут не проканать, надо явно задавать путь
require_once("/home/USER/domains/DOMEN/public_html/file.php");
надеюсь это поможет вам съэкономить немного времени при попытки понять почему же не работает cron :)

ну и приведу пример отладочного скрипта
*/

//ошибки включаем
error_reporting(7);

//делаем буфер
ob_start('buff');

/*
далее идет скрипт
*/
echo 2+2;
echo 2+2;
echo 2+2;

//функция для сброса буфера
function buff($v)
{
    //можно отправить содержимое буфера себе на мыло или записать в файл
    mail('admin@site.ru','cron',$v);
}

/*
таким образом вы точно будете знать что выдает скрипт, когда запускается кроном
*/

?>
24 марта 2008, 22:05

Создание директории по ftp

<?php
/*
* Создание директории по ftp
* автор: nc_soft
* 17.03.08
*/

$user='test_login';
$pass='*******';
$host='ftp.site.ru';

//коннектимся
$ftp=ftp_connect($host) OR die("коннект невозможен");

//логинимся
if (!ftp_login($ftp,$user,$pass)) die('залогиниться неудалось');

//посмотрим файлы в корне ( / )
$flist=ftp_rawlist($ftp,'/');
print_r($flist);

/*изменим текущую директорию (проще говоря перейдем в каталог)
путь /domains/site.ru/public_html показан для примера и может отличаться от вашего хостига,
но обычно это самый распространенный вариант*/
ftp_chdir($ftp,'/domains/site.ru/public_html');

//посмотрим список в public_html
$flist=ftp_rawlist($ftp,'/domains/site.ru/public_html');
print_r($flist);

//создадим в /domains/site.ru/public_html папку с названием test
ftp_mkdir($ftp,'test');

//еще раз посмотрим список в public_html, там должна появиться папка test
$flist=ftp_rawlist($ftp,'/domains/site.ru/public_html');
print_r($flist);

//закрываем ftp соединение
ftp_quit($ftp);

?>
17 марта 2008, 16:28

изменение битрейта mp3

<?php
/*
* изменение битрейта mp3
* автор: Nc_soft
* 10.03.08
*/

/*
для этого нам потребуется поддержка Lame на хостинге и
разрешение выполнять команды ОС (функция exec )
а так в этом нет ничего сложного ;)
*/

//файл, который конвертим
$input_file='file_name.mp3';

//требуемый битрейт
$bit=64;

//куда сохранить выходной файл
$output_file='out.mp3';

//выполняем команду
exec("lame '".escapeshellcmd($input_file)."' -b $bit --mp3input '".escapeshellcmd($output_file)."' ");

/*
подробнее о LAME и на русском можно почитать тут:
http://www.allok.ru/?id=15
*/

?>
10 марта 2008, 23:21

Варианты выдачи страниц на php

<?php
/* 
* Варианты выдачи страниц на php
* автор: nc_soft
* 26.02.08
*/

//для начала заголовок
header('Content-type: application/vnd.wap.xhtml+xml;charset=utf-8');

//далее могут быть варианты

//вариант 1, всё через echo или принт
echo '<?xml version="1.0" encoding="UTF-8"?>';
echo '<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">';
echo '<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
<p>Ваш ip: '.$_SERVER['REMOTE_ADDR'].'</p></body></html>';
/*вот такой вариант, на мой взгляд самый худший :)*/

//вариант 2, непосредственный вывод в браузер
//это обычно требуется через echo, потому что если включены short tags могут быть ошибки
echo '<?xml version="1.0" encoding="UTF-8"?>';
//далее закрываем php и выводим просто html код
?>
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head></head>
<body>
<p>Ваш ip: <?=$_SERVER['REMOTE_ADDR'];?></p>
</body>
</html>
<?php

/*
очень хороший вариант, 
php код вкрапливается в html разметку, вроде бы идеальный способ,
но не годится для работы дизайнера, дизайнеру может быть сложно понять что к чему.
Для этого придумали ШАБЛОНЫ, вот пример простейшего:
Создаем файл шаблона, например index.tpl следующего содержания

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
<p>Ваш ip: {{IP}}</p>
</body>
</html>

для дизайнера просто идеально, никакого php нет и в помине.
далее выводим шаблон
*/

echo strtr(file_get_contents('index.tpl'),array('{{IP}}'=>$_SERVER['REMOTE_ADDR']));

/*
как видите мы просто заменили в шаблоне {{IP}} на $_SERVER['REMOTE_ADDR'],
создается массив замены, а не строка, потому что замен может быть несколько.
Преимущества этого способа в том, что в шаблоне нет php кода, а в скрипте нет html
*/

?>
26 февраля 2008, 13:18