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

<?php
/**
 * Выдача удаленного файла скриптом с докачкой
 * автор: Nc_Soft
 * 26.10.09
 */

//урл удаленного файла
$url = 'http://snippets.pp.ru/1.mp3';

//инициализация сеанса curl
$ch = curl_init($url);

//если клиент запрашивает докачку
if(isset($_SERVER['HTTP_RANGE'])) {
	curl_setopt($ch, CURLOPT_RANGE, str_replace('bytes=', '', $_SERVER['HTTP_RANGE']));
}

//бинарные данные
curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);

//функция обратного вызова для заголовков (выдает такие же заголовки как и удаленный сервер)
curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'curlHeaderCallback');

//падаем в случаи ошибки
curl_setopt($ch, CURLOPT_FAILONERROR, 1);

//браузер
curl_setopt($ch, CURLOPT_USERAGENT, 'Opera/9.80 (Windows NT 5.1; U; ss; MRA 5.4 (build 02647); ru) Presto/2.2.15 Version/10.00');

//accept браузера
$info = array(
'Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1',
'Accept-Language: ru-RU,ru;q=0.9,en;q=0.8',
'Accept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1',
);
curl_setopt($ch, CURLOPT_HTTPHEADER, $info);

//запуск
curl_exec($ch);

function curlHeaderCallback($ch, $strHeader) {
	//выдаем такой же заголовок, как и удаленный сервер, где лежит файл.
	//заголовки идут по порядку
	header($strHeader);
	return strlen($strHeader);
}

//запустив скрипт вы можете выдать удаленный файл через свой сайт.
//а чтобы файл нормально сохранялся, а не с адресом скрипта, 
//надо настроить mod_rewrite, чтобы на запрос блаблабла/file.mp3 выдавался этот скрипт
26 октября 2009, 03:58

Определение корректности кодировки

<?php
/**
 * Определение корректности кодировки
 * автор: Nc_Soft
 * 20.10.09
 */

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

$text = 'здесь текст';

if (!mb_check_encoding($text, 'utf-8')) {
	echo 'Символы некорректны для utf-8';
}

/*этот метод не определяет кодировку, но зато 
может определить когда она неверна*/
20 октября 2009, 19:02

Использование счетчика liveinternet.ru на wap сайте

<?php
/**
 * Использование счетчика liveinternet.ru на wap сайте
 * автор: Nc_Soft
 * 28.09.09
 */

/*
Думаю все встречали этот счетчик хоть раз в вебе.
При уёбищном дизайне он даёт отличные статистические данные по сайту, но
из-за ява скрипта в коде счетчика его использование на wap сайте не предоставляется возможным.
Давайте поправим эту оплошность

Оригинальный код счетчика можно получить на 
http://www.liveinternet.ru/code?nick=ВАШ_САЙТ

<!--LiveInternet counter-->
          <script type="text/javascript"><!--
document.write("<a href='http://www.liveinternet.ru/click' "+
"target=_blank><img src='http://counter.yadro.ru/hit?t52.5;r"+
escape(document.referrer)+((typeof(screen)=="undefined")?"":
";s"+screen.width+"*"+screen.height+"*"+(screen.colorDepth?
screen.colorDepth:screen.pixelDepth))+";u"+escape(document.URL)+
";"+Math.random()+
"' alt='' title='LiveInternet: показано число просмотров и"+
" посетителей за 24 часа' "+
"border=0 width=88 height=31><\/a>")//--></script>
          <!--/LiveInternet-->

Теперь реализуем это всё без ява скрипта и наслаждаемся результатом
*/

echo '<a href="http://www.liveinternet.ru/click">
<img src="http://counter.yadro.ru/hit?t25.10;r'.urlencode($_SERVER['HTTP_REFERER']).';uhttp%3A//'.urlencode($_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']).';0.'.rand(12345, 893855).'" alt="" /></a>';

//примечательно то, что нигде не фигурирует имя домена явно
28 сентября 2009, 00:10

Защита от sql инъекций

<?php
/**
 * Защита от sql инъекций
 * автор: Nc_Soft
 * 15.09.2009
 */

/*
Почему-то разработчики PHP не сделали функцию для работы с бд,
которая принимает запросы с параметрами.
Это сильно бы помогло в безопасности.
*/

//эта функция экранирует параметры
function qw() {
	$args = func_get_args();

	$query = array_shift($args);
	$args = array_map('mysql_real_escape_string', $args);
	array_unshift($args, $query);
	$query = call_user_func_array('sprintf', $args);
	
	if (!$query) die('неверный запрос');
	
	return mysql_query($query);
}

//пример использования
$q = qw("SELECT * FROM tbl WHERE login='%s' AND pass='%s' ", "лог'ин", "пар'оль");
//в этом запросе все кавычки будут экранированы, инъекция невозможна

/*вместо %s в функцию подставляется параметр, обработанный через mysql_real_escape_string
поэтому нет никакой необходимости предварительно обрабатывать данные , можно писать сразу
qw("SELECT FROM tbl WHERE id='%s' ", $_GET['id']);
Главное не забыть поместить %s в кавычки.
*/
15 сентября 2009, 20:13

Sitemap генератор для мобильных устройств при помощи simplexml

<?php
/**
 * Sitemap генератор для мобильных устройств при помощи simplexml
 * автор: Nc_Soft
 * 09.09.09
 */

/*
Пару слов зачем это нужно:
Позволяет ускорить индексацию поисковиками труднодоступных мест,
сообщая конкретные урл страниц.

http://www.google.com/support/webmasters/bin/answer.py?hl=ru&answer=34627
http://www.google.com/support/webmasters/bin/topic.py?topic=8493
*/

/*
Перейдем к реализации:
К примеру, имеется массив из 10 элементов, эмулирующий ид из бд
array(1, 2, ... , 10)
*/
$ids = range(1, 10);

//пусть каждому элементу соответствуем страница на сайте http://site.ru/$id.html

//собственно, генерация
$sitemap = simplexml_load_string('<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0"></urlset>');

foreach ($ids as $id) {
	$url = $sitemap->addChild('url');
	$url->loc = "http://site.ru/$id.html";
	$url->addChild('mobile', null, 'http://www.google.com/schemas/sitemap-mobile/1.0');
}

header('Content-type: text/xml; charset=utf-8');
echo $sitemap->asXML();

/*
Sitemap готов, сохраняете его как sitemap.php и добавляете в гугл как тут сказано
http://www.google.com/support/webmasters/bin/answer.py?answer=40348

также вы можете добавить доп.инфу в sitemap для каждой страницы
http://www.google.com/support/webmasters/bin/answer.py?answer=71936
*/
9 сентября 2009, 10:05

Мультипоточное скачивание через CURL

<?php
/**
 * Мультипоточное скачивание через CURL
 * 01.09.09
 * автор: Nc_Soft 
 */

//В php5 можно скачивать данные в несколько потоков

//инициализация
$ch1 = curl_init();
$ch2 = curl_init();

//адреса страниц (файлов) и опции
curl_setopt($ch1, CURLOPT_URL, 'kmx.ru');
curl_setopt($ch1, CURLOPT_HEADER, 1);
curl_setopt($ch2, CURLOPT_URL, 'wen.ru');
curl_setopt($ch2, CURLOPT_HEADER, 1);

//мульти загрузка
$mh = curl_multi_init();

//добавляем ресурсы в мультизагрузку
curl_multi_add_handle($mh, $ch1);
curl_multi_add_handle($mh, $ch2);

//число запущенных загрузок
$running=null;

//грузим!
do {
	curl_multi_exec($mh, $running);
} while ($running > 0);


//освобождаем ресурсы и память
curl_multi_remove_handle($mh, $ch1);
curl_multi_remove_handle($mh, $ch2);
curl_multi_close($mh);

?>
1 сентября 2009, 12:10

Получение представления таблицы mysql

<?php
/**
 * Получение представления таблицы mysql
 * автор: Nc_Soft
 * 31.08.09
 */

$q = mysql_query("SELECT * FROM tbl");

$thead = false;
echo '<table border="1">';
while (false !== $res=mysql_fetch_assoc($q)) {
	if ($thead === false) {
		$thead = true;
		echo '<tr>';
		foreach (array_keys($res) as $v) {
			echo '<td>'.$v.'</td>';
		}
		echo '</tr>';
	}

	echo '<tr>';
	foreach ($res as $ceil) {
		echo '<td>'.$ceil.'</td>';
	}
	echo '</tr>';
}
echo '</table>';
31 августа 2009, 15:19

Получение множественной формы русского слова

<?php
/**
 * Получение множественной формы русского слова
 * автор: Nc_Soft
 * 18.08.09
 * 
 */

/**
 * $n - число
 * $form1 - для одной штуки
 * $form2 - для двух штук
 * $form5 - для пяти штук
 */
function pluralForm($n, $form1, $form2, $form5) {
	$n = abs($n) % 100;
	$n1 = $n % 10;
	if ($n > 10 && $n < 20) return $form5;
	if ($n1 > 1 && $n1 < 5) return $form2;
	if ($n1 == 1) return $form1;
	return $form5;
}

//пример
echo '38 ' . pluralForm(38, 'попугай', 'попугая', 'попугаев');
?>
18 августа 2009, 12:54

Удаление пустых элементов из массива

<?php
/**
 * Удаление пустых элементов из массива
 * автор: Nc_Soft
 * 23.07.09
 */

/*встроенной функции, которая это делает вроде как не существует, 
но можно обойтись комбинацией их двух встроенных*/
$array = array('aa', 'bb', 'cc', '', 'dd', ' ', 3, 5, 'ee');

//вариант 1
$array1 = array_filter($array, 'trim');

//вариант 2
$array2 = array_diff($array, array('', ' '));

print_r($array1);
print_r($array2);
23 июля 2009, 21:47

Отображение php ошибок и предупреждений

/*
* Отображение php ошибок и предупреждений
* автор: Nc_Soft
* 19.07.09
*/

//в рабочем проекте это должно быть выведено в 0
php_value display_errors 1
php_value error_reporting 2047
19 июля 2009, 03:46

Исправление кодировки букв "ш" и "И" в MYSQL

/*
* Исправление кодировки букв "ш" и "И" в MYSQL
* автор: Nc_Soft
* 18.07.09
*/

/*
Частенько встречается при переносе бд, либо при шаманстве с кодировками
буквы "ш" и "И" оказываются битыми (речь идет о utf-8 конечно)
буква "ш" = chr(209).chr(63) / правильно chr(209).chr(136)
буква "И" = chr(208).chr(63) / правильно chr(208).chr(152)
Чтобы пофиксить делаем 2 запроса
*/

UPDATE `tbl` SET `pole` = REPLACE(
`pole`, 
CONCAT( CHAR(209), CHAR(63) ), 
CONCAT( CHAR(209), CHAR(136) )
);

UPDATE `tbl` SET `pole` = REPLACE(
`pole`, 
CONCAT( CHAR(208), CHAR(63) ), 
CONCAT( CHAR(208), CHAR(152) )
);
18 июля 2009, 22:31

Установка предопределенного значения autoincrement

<?php
/**
 * Установка предопределенного значения autoincrement
 * автор: Nc_Soft
 * 08.07.09
*/

/*
часто бывает нужно выставить вразумительно значение автоиндекса,
поэтому публикую запрос, чтобы не забыть
(в phpmyadmin: операции - параметры таблицы - AUTO_INCREMENT)
*/

mysql_query ("alter table tbl auto_increment=10");
?>
8 июля 2009, 04:15

Защита от прямых ссылок

# Защита от прямых ссылок
# автор: Nc_Soft
# 05.07.09
# Это позволит скачать ваш файл только с вашего сайта.
# надо создать вот такой .htaccess

RewriteEngine on
RewriteBase / 

# если надо разрешить скачку при пустом рефере раскомментируйте это
# RewriteCond %{HTTP_REFERER} !^$

# Дальше список идет набор разрешенных доменов
RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?snippets.pp.ru [NC]
RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?wen.ru [NC]

# Форматы файлов, для которых устанавливается защита (например, mp3)
RewriteRule .(mp3)$ http://ya.ru

#Все запросы на http://snippets.pp.ru/1.mp3 перекинутся на http://ya.ru
5 июля 2009, 02:10

Google translate переводчик

<?php
/**
* Google translate переводчик
* автор: Nc_Soft, Soft_Land
* 22.06.09
*/

class GoogleTranslate {  
     
    static function translate($text, $source, $dest) { 
        $text    =    urlencode($text); 
        $ch        =    curl_init('http://translate.google.ru'); 
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
        curl_setopt($ch, CURLOPT_POST,1); 
        curl_setopt($ch, CURLOPT_POSTFIELDS, "text=$text&sl=$source&tl=$dest"); 
        curl_setopt($ch, CURLOPT_HEADER, 1); 
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.0.3) Gecko/2008092417'); 

        $r        =    curl_exec($ch); 

        $arr    =    array(); 
        preg_match("|<textarea name=utrans wrap=SOFT dir=\"ltr\" id=suggestion style=\"width:80%;margin:5px 0;overflow:auto\">(.*)</textarea>|sU", $r, $arr); 

        return strip_tags(str_replace('<br>', "\n", htmlspecialchars_decode($arr[1]))); 
    } 
     
}

echo GoogleTranslate::translate('Read this fucking manual', 'eng', 'ru');

//ps Спасибо SL за подробный языковой массив.
?>
22 июня 2009, 08:48

Вызов preg_replace_callback в классе

<?php
/**
 * Вызов preg_replace_callback в классе
 * автор: Nc_Soft
 * 11.06.09
 */

/* Рассмотрим на примере смайлов
условия: смайлов должно быть не более 3 в одном сообщении
смайлы вызываются как-то так :smile:
*/

class Smiles {
	//счетчик смайлов
	static $smc=0;

	//список смайлов
	static $smiles=array(
	'smile', 'hi', 'yes', 'bad', //итд
	);

	//функция печатающая текст (обратите внимание на callback вызов)
	static function pr($str) {
		return preg_replace_callback('`:([^\s]+):`U', array('self', 'cbs'), $str);
	}

	//функция обратного вызова для регулярного выражения
	//проверяет список смайлов и их количество
	static function cbs($v) {

		if (self::$smc<3) {
			if (in_array(strtolower($v[1]), self::$smiles)) {
				self::$smc++;
				return '<img src="/smiles/'.$v[1].'.gif" alt="'.$v[1].'"/>';
			}
		}

		return $v[0];
	}
}

//пример
echo Smiles::pr('Тут текст со смайлами (неверный смайл :error: )
:smile: :hi: :yes: :bad: ');
11 июня 2009, 17:04

Распаковка страницы в gzip

<?php
/**
 * Распаковка страницы в gzip
 * автор: Nc_Soft
 * 29.05.09
 * 
*/

//получаем страницу, где поддерживается сжатие
$ch=curl_init('http://snippets.pp.ru/');

//настраиваем, чтобы сеанс выводился не в браузер, а в переменную
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

//заголовки тут ни к чему
//curl_setopt($ch, CURLOPT_HEADER, 1);

//задаем заголовок для сжатия Accept-Encoding: gzip, deflate
//и еще несколько заголовков за компанию (необязательно)
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Accept-Encoding: gzip, deflate',
'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language: ru,en-us;q=0.7,en;q=0.3',
'Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7',
));

//выполняем запрос
$res = curl_exec($ch);

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

//в переменной $res у нас сжатые данные в "кракозябрах", проверка
echo $res;

//разделитель для читабельности
echo "<br /><br />\n\n";

/*самое важное: чтобы раскодировать данные надо применить функцию
gzinflate, обрезав при этом первые 10 байт!*/
echo gzinflate(substr($res, 10));

/*
Результат можно увидеть запустив snippet.
Что нам это дает?
С серверов, где поддерживается сжатие можно тащить примерно в 10 раз
меньше данных, чем раньше, тоесть грабберы будут работать шустрее.

Ну и конечно, snippets не появляются из ниоткуда, 
каждый snippet решает проблему из "жизни", пример:
echo file_get_contents('http://radiorecord.ru/charts/');
Почему-то хоть убей выдается не вся страница, а примерно половина.
Запрос с использованием заголовка Accept-Encoding: gzip, deflate
позволяет получить страницу целиком, хоть и в сжатом виде.
*/
29 мая 2009, 03:02

Время в iso формате

<?php
/**
 * Время в iso формате
 * автор: Nc_Soft
 * 27.05.09
 */

/*Функция форматирует дату из бд (поле timestamp или datetime) в формат iso
с учетом временного сдвига.
Сдвиг отсчитывается от локального времени системы, а не по Гринвичу*/

function date_iso($data, $shift='+0') {
	
	$data=date('Y-m-d H:i:s', strtotime("$data $shift hour"));
	$p=date_parse($data);

	if ($p['error_count']) return ;

	static $m_collation=array(
	'января',
	'февраля',
	'марта',
	'апреля',
	'мая',
	'июня',
	'июля',
	'августа',
	'сентября',
	'октября',
	'ноября',
	'декабря',
	);

	return '<span class="time">'.$p['day'].' '.
	$m_collation[$p['month']-1].' '.
	$p['year'].', '.
	sprintf('%02d', $p['hour']).':'.sprintf('%02d', $p['minute']).'</span>';
}

echo '<br />Дата на пробу<br />';
echo date_iso('2009-05-27 01:53:32');

echo '<br />А теперь сдвинем на час вперед<br />';
echo date_iso('2009-05-27 01:53:32', '+1');

echo '<br />И на 3 часа назад<br />';
echo date_iso('2009-05-27 01:53:32', '-3');
27 мая 2009, 02:03

Настройка .htaccess для wap сайта

# Настройка .htaccess для wap сайта
# автор: Nc_Soft
# 18.05.09

#отключаем глобальные переменные
php_value register_globals off

#отключаем экранирование данных
php_value magic_quotes_gpc off

#автоматически цепляем сессию, если она используется
php_value session.use_trans_sid on

#используем кукис в сессиях
php_value session.use_cookies 1

#некоторые мобилы кукис не держат, поэтому создаем альтернативу
php_value session.use_only_cookies 0

#полезно для валидатора
php_value arg_separator.output "&"

#цепляем сид к следующим параметрам
php_value url_rewriter.tags  "a=href,area=href,img=src,fieldset="

#ну и несколько mime типов для примера
AddType text/vnd.sun.j2me.app-descriptor .jad
AddType application/java-archive .jar
AddType application/vnd.eri.thm .thm
AddType application/vnd.nok.s40theme .nth
AddType application/vnd.siemens-mp.theme .sdt
AddType application/vnd.smaf .mmf
AddType application/vnd.symbian.install .sis
AddType video/3gpp .3gp
AddType video/mp4 .mp4
AddType video/x-msvideo .avi
18 мая 2009, 14:26

Определение баланса сайта на bn.wen.ru через xml интерфейс

<?php
/**
 * Определение баланса сайта на bn.wen.ru через xml интерфейс
 * автор: Nc_Soft
 * 12.04.09
 */

//формируем запрос
$xml='<?xml version="1.0" encoding="utf-8"?>
<request login="ваш логин" password="ваш пароль" do="balance">
<site>ид сайта</site>
</request>';

//шлем данные
$ch=curl_init('http://bn.wen.ru/');
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_POST,1);
curl_setopt($ch,CURLOPT_POSTFIELDS,'body='.urlencode($xml));
echo $s=curl_exec($ch);

$s=simplexml_load_string($s);
//выводим баланс
echo $s->balance;

//полное описание на http://b.wen.ru/xml.txt, здесь лишь практический пример
12 апреля 2009, 23:52

Определение параметров mp3 файла

<?php
/**
 * Определение параметров mp3 файла
 * автор: Nc_Soft
 * 12.04.09
 */

/*Не знаю как вас, а меня бесит библа getid,
поэтому параметры я определяю через ffmpeg*/

$ff=new ffmpeg_movie('file.mp3');

//длительность (с)
echo $ff->getDuration();

//аудио битрейт
echo $ff->getAudioBitRate();

//Возвратит поле "авторское право" из аудио или видео файла
echo $ff->getCopyright();

//Возвратит ID3 поле "Артист" из mp3 файла
echo $ff->getArtist();

//Возвратит ID3 поле "Жанр" из mp3 файла
echo $ff->getGenre();

//Возвратит ID3 поле "номер дорожки" из mp3 файла
echo $ff->getTrackNumber();

//Возвратит ID3 поле "Год" из mp3 файла
echo $ff->getYear();

//Возвратит  название  аудио  кодека  который использован видео файл как строку
echo $ff->getAudioCodec();

//Возвратит  количество  аудио каналов (1 моно 2 стерео и т д) как целое число
echo $ff->getAudioChannels();

/*моя функция форматирования времени трека*/
function dur($d) {
	if ($d<60) {
		return '00:'.sprintf('%02d',$d);
	}

	$s=$d%60;
	return sprintf('%02d',($d-$s)/60).':'.sprintf('%02d',$s);
}
//пример 
echo dur('105'); //01:45
12 апреля 2009, 23:39