Конвертер текста в JPG

Скрипт переводит текст в картинку. Будет полезно для скрытия e-mail адресов или другой информации от грабберов.
<?php
$text="http://domain.ru";
$pic=ImageCreate(130,30);
$col1=ImageColorAllocate($pic,0,0,0);
$col2=ImageColorAllocate($pic,255,255,255);
ImageFilledRectangle($pic, 0, 0, 500, 30, $col2);
ImageString($pic, 3, 5, 8, $text, $col1);
Header("Content-type: image/jpeg");
ImageJPEG($pic);
ImageDestroy($pic);
?>

Памятка PHP разработчика

Настройки PHP при разработке в качестве рекомендации

1) error_reporting = E_ALL | E_STRICT
2) display_errors = On
3) register_globals,register_long_arrays,magic_quotes off (первые 2 удалены в 5.4)
4) short_open_tag off
5) allow_call_time_pass_reference = off (Удалено в 5.4)
6) safe_mode — все настройки off (Удалено в 5.4)

Типичные уязвимости
Загрузка файлов:
1. Заливка исполняемого файла
2. Исполнение неопределённых Mime Type Apache например file.php.7z
3. Исполнение мета-информации например исполняемый image.gif
4. Уязвимость связки php+nginx (выставить cgi.fix_pathinfo=0)
5. Выставление некорректных прав на загружаемый файл

Код:
1. Ядовитый ноль он же нулевой байт он же символ конца строки %00, позволяет производить php injection
2. Не фильтрованный ввод
3. SQL injection
4. XSS
5. Remote File Inclusion [RFI] (отключаем allow_url_include = Off)
6. Возможность перехвата сессии (привязываем к клиенту)
7. Rainbow Table подбор ( храним пароли в sault md5)
8. Автоматизированное внедрение iframe (иногда помогает вынос точки выхода из приложение в файл отличный от index + exit в конце) (Такая простая мера очень часто меня спасала)
9. CSRF — Cross-Site Request Forgery (имитирование запроса пользователя к стороннему сайту)

Читать дальше →

Основные системные показатели на PHP

Рассматриваться будет работа на Ubuntu Server. Под другие nix-системы тоже должно работать, но, возможно, с доработками. Windows серверы не рассматриваются вовсе.
Все решения сделаны «в лоб», без изысков и фанатичной минимализации/оптимизации. Я использовал jQuery для того, чтобы получить json посредством Ajax, и вывести его на страницу. Примеры простые, и могут быть переделаны под любой другой способ передачи/вывода.

1. Загрузка CPU
Начнем с самого сложного. Сложного потому, что мне не сразу удалось найти способ получения информации о загрузке процессора, а впоследствии, и не сразу найти способ ее обрабатывать. Первой мыслью была «использовать exec(»top -n 1")", однако top не писал в стандартный вывод, а сохранение его (вывод) в файл на диск через '>', приводило к появлению огромного количества 'мусора', что сильно затрудняло последующий парсинг. В итоге, все свелось к чтению нужных файлов в виртуальной файловой системе, подключенной в /proc. Файл, в котором хранится информация о текущем использовании процессора называется /proc/stat. По сути, это не файл, а точка доступа к структурам данных ядра, но нам это знать не обязательно, потому что нам будет достаточно прочитать содержимое, а сделать это можно, как и в случае с простым файлом, через file(). Теперь можно привести кусочек кода, который эту информацию достает. После него я объясню, что было сделано, и зачем.
$file=file("/proc/stat");
$tmp=explode(" ",$file[0]);
$cpu1=$this->session->userdata("cpu1");
$cpu2=$this->session->userdata("cpu2");
$cpu3=$this->session->userdata("cpu3");
$cpu4=$this->session->userdata("cpu4");
$cpu=(100/($tmp[5]-$cpu4))/(($tmp[2]-$cpu1)+($tmp[3]-$cpu2)+($tmp[4]-$cpu3))*100;
       
$this->session->set_userdata(array("cpu1"=>$tmp[2],"cpu2"=>$tmp[3],"cpu3"=>$tmp[4],"cpu4"=>$tmp[5]));

Объяснение начнем с содержимого файла:
> cat /proc/stat
cpu  2255 34 2290 22625563 6290 127 456 0 0
cpu0 1132 34 1441 11311718 3675 127 438 0 0
cpu1 1123 0 849 11313845 2614 0 18 0 0
intr 114930548 113199788 3 0 5 263 0 4 [... еще куча цифр ...]
...

В первой строчке /proc/stat содержится информация о количестве потраченного процессором времени (усредненное для всех ядер/потоков) на выполнение (по порядку): процессов пользователя, высокоприоритетных процессов пользователя, системных процессов, простоя, ожидания ввода/вывода, аппаратных и программных прерываний. В следующих строках, начинающихся на 'cpu', приведены те же данные для каждого ядра/потока в отдельности. В нашем случае вся интересующая информация содержится в первой строке, поэтому дальше разбирать файл не будем.
В приведенном кусочке кода так же есть сохранение этих данных в сессию CodeIgniter. Это сделано для того, чтобы определять разницу (дельту) между текущими и предыдущими значениями показателей. Загрузка процессора представляет собой отношение дельты простоя к сумме дельт затрат на процессы. Другими словами, мы сравниваем количество простоя и работы с момента последнего запроса. Естественно, чем реже будут происходить эти запросы, тем сильнее будет усреднено значение загрузки процессора за это время.

2. Оперативная память
Информацию о количестве свободной оперативной памяти можно найти в файле /proc/meminfo:
> cat /proc/meminfo
MemTotal:        2052604 kB
MemFree:          246012 kB
Buffers:          792332 kB
Cached:           584716 kB
...

Отсюда мы будем брать две первые строчки, и извлекать из них цифры:
$file=file("/proc/meminfo");
$memory["total"]=substr($file[0],strpos($file[0]," "),strrpos($file[0]," ")-strpos($file[0]," "));
$memory["free"]=substr($file[1],strpos($file[1]," "),strrpos($file[1]," ")-strpos($file[1]," "));

Этот и последующие кусочки кода будут проще первого, и обширные пояснения им не потребуются. Здесь, например, все очевидно — мы просто «вырезаем» число, расположенное между двумя пробелами, для первой и второй строчки соответственно.

3. Swap file
Тут еще проще — берем строчку из /proc/swaps:
> cat /proc/swaps
Filename                                Type            Size    Used    Priority
/dev/sda1                               partition       7811064 2732    -1
...

В нем перечислены все подключенные своп-файлы, их типы, объемы и занятое место. Нам просто надо «выдернуть» нужные цифры из нужных строк. В моем случае своп один, и строчку я обрабатываю одну:
$file=file("/proc/swaps");
$tmp=explode("\t",substr($file[1],strpos($file[1],"partition")));
$swap["total"]=$tmp[1];
$swap["free"]=$tmp[1]-$tmp[2];

Здесь пояснения тоже не нужны.

4. Жесткие диски
В моем примере будет приведен код, который извлекает информацию о количестве свободного места на дисках, точки монтирования которых находятся в /mnt. Ухищрения типа чтения и парсинга файлов из /proc здесь использовать не будут — для этой цели достаточно стандартных disk_free_space() и disk_total_space():
$drives=array();
if($dir=opendir("/mnt")){
  while(false !== ($file = readdir($dir))) {
    $arr=array();
    if(($file!=".")&&($file!="..")){
      $arr["path"]="/mnt/".$file;
      $arr["free"]=disk_free_space("/mnt/".$file);
      $arr["total"]=disk_total_space("/mnt/".$file);
      $drives[]=$arr;
    }
  }
}

5. Uptime
В качестве небольшого бонуса получим и продолжительность работы системы с последнего запуска:
$uptime=exec("uptime");
$uptime=explode(",",substr($uptime,strpos($uptime,"up")+3));
$time=explode(":",$uptime[1]);
$uptime=$uptime[0]." ".$time[0]." hours ".$time[1]." minutes";

Совсем банальный подход — вызов exec(), и форматирование результата.

Вывод
Мы смогли получить всю интересующую нас информацию — о заполненности жестких дисков, о загрузке процессора, о состоянии памяти и свопа и даже о продолжительности работы сервера. Как выводить эту информацию, каждый может придумать сам, в зависимости от требований. Я же поделюсь способом, который использую сам.
Сперва я собираю полученные данные в ассоциативный массив и вывожу его как json:
$result["cpu"]=$cpu;
$result["memory"]=$memory;
$result["swap"]=$swap;
$result["uptime"]=$uptime;
json_encode($result);

На выходе получается следующее:
{"uptime":"34 days   5 hours 45 minutes","cpu":1.7361111111111,"memory":{"total":"2052604","free":"191424"},"swap":{"total":"7811064","free":7808332}}

И, уже в браузере, я работаю с результатом при помощи jQuery:
var json=$.parseJSON(data);
$("#systemInfo").html("CPU: "+json.cpu+"<br />Memory free "+json.memory.free+" / "+json.memory.total);


301 редирект – корректная переадресация через htaccess и php header

Простой редирект (в файле .htaccess или httpd.conf для Apache):
Redirect 301 / http://www.you.com/new.htm

где:
Redirect 301 — это инструкция, говорящая что страница перемещена
/ — означает, что все с верхнего уровня сайта, включая все подкаталоги, будет переадресовано
www.you.com/new.htm — новая страница или сайт (не забывайте поставить последний "/", если переадресация идет на сайт).

Чтобы переадресовать только страницу, сохранив PR старой страницы:
Redirect 301 /old/old.htm http://www.you.com/new.htm

где:
/old/old.htm — путь и имя старой страницы

Аналогичный синтаксис для переадресации сайта:
RedirectPermanent / http://www.you.com/


Пример переадресации каталога:
RedirectPermanent /old-directory http://www.domain.com/new-directory/

Например, зашедших в test переадресуем на www.test.com, остальных на enter.test.com (порядок следования записей важен):
Redirect permanent /test    http://www.test.com/
Redirect permanent /        http://enter.test.com/


Использование mod_rewrite (прописывается в файле .htaccess):
Ставшая классической задача слияния имена сайта с www и без него, решается так:
Options +FollowSymLinks
RewriteEngine on
RewriteCond %{HTTP_HOST} ^yoursite\.com
RewriteRule ^(.*)$ http://www.yoursite.com/$1 [R=permanent,L] . 

или альтернативный синтаксис:
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{HTTP_HOST} ^domain\.com$ [NC]
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=301,L]

Обозначение [R=301,L] означает: перенаправить клиента и отправить ему код статуса 301 (R=301) и сделать это правило последним (L).

Редирект старого домена на новый:
Options +FollowSymLinks
RewriteEngine on
RewriteRule (.*) http://www.newdomain.com/$1 [R=301,L]

Например, если необходимо чтобы вместо rewrite.htm загружался файл rewrite.html, добавьте в .htaccess:
RewriteEngine   on
RewriteBase     /
RewriteRule     ^rewrite\.htm$  rewrite.html [R=permanent]

Для замены всех .htm файлов .html файлами:
RewriteEngine  on
RewriteBase     /
RewriteRule     ^(.*)\.htm$  $1.html [R=permanent]

Редирект на PHP:
<?php
header("HTTP/1.1 301 Moved Permanently");
header("Location: http://www.newdomain.ru/newdir/newpage.htm");
exit();
?>

Лучше указать HTTP/1.1, так как более старые не поддерживают виртуальный хостинг. Не забудьте, что до вызова header, ничего не должно выводиться (например, echo или print). Поэтому этот код лучше ставить в начало php-скрипта. Более полный вариант php редиректа с сохранением передаваемой страницы и параметров вызова:
<?
$ref=$_SERVER['QUERY_STRING'];
if ($ref!='') $ref='?'.$ref;
header('HTTP/1.1 301 Moved Permanently');
header('Location: http://newdomain.com/'.$ref);
exit();
?>

Редирект на ASP
<%@ Language=VBScript %>
<% 
Response.Status="301 Moved Permanently"
Response.AddHeader "Location", "http://www.new-url.com"
response.end
%>

Редирект на ASP.NET
<script runat="server">
private void Page_Load(object sender, System.EventArgs e)
{
Response.Status = "301 Moved Permanently";
Response.AddHeader("Location","http://www.new-url.com");
}
</script>

Редирект на ColdFusion
<.cfheader statuscode="301" statustext="Moved permanently">
<.cfheader name="Location" value="http://www.new-url.com">

Редирект с помощью meta refresh
<meta http-equiv='refresh' content='0; url=http://newdomain.com'>

где 0 — задержка переадресации в секундах, newdomain.com -страница, куда переадресуем. Некоторые старые браузеры не поддерживают meta refresh со значением 0, для совместимости можно установить ненулевой значение, хотя, на мой взгляд это уже не актуально. Такой редирект не сможет склеить ваши сайты (с www и без) и передать PR, так как игнорируется поисковыми системами. Он возвращает код 200 OK, что соответствует обычной странице. Эта техника популярна у спамеров, поэтому ее стоит применять только для страниц, которые не будут индексироваться.
Редирект с помощью JavaScript
Варианты переадресации на JavaScript чаще реализуются с использованием функции setTimeout('функция', задержка).
Например, автоматически сделать Click на кнопке «Submit» формы «searchform» через 0.1 сек после загрузки кода:
setTimeout('document.forms["searchform"].Submit.click()', 100);

На кнопку «Submit» можно повесить любое действие, например, открыть новый url в этом окне. Кстати такое редиректы чаще встречаются при организации Дорвеев (DorWay) — браузер Пользователя будет переадресован на другую страницу, а поисковый робот, который «не понимает» JavaScript, будет индексировать эту страницу, недоступную пользователю. На ней дорвейщики размещают текст, напичканный «нужными» ключевыми словами.
Чтобы просто переадресовать на другую страницу можно вставить после один из вариантов кода на JavaScript:
В последнем случае уже нельзя будет вернуться на страницу выполнившую переадресацию, так как ее адрес стирается из history, что нередко и нужною. Если нужна задержка по времени, можно оформить location=«www.newdomain.com»; в виде функции и вставить ее в setTimeout('функция()', задержка_в_мсек); Редирект на JavaScrupt не является 301 редиректом и не передаст PR страницы, не сможет обеспечить ее склейку.
Отметим дополнительно некоторые особенности редиректов:
  • Методы редиректа с .htaccess работают только на Linux серверах, имеющих Apache с включенным модулем Mod-Rewrite.
  • Использование .htaccess создает дополнительную нагрузку на сервер Apache, более эффективно прописывать те же команды в его конфигурационном файле hpptd.conf, но, как правило, к нему нет доступа у вебмастера.
  • 301 редирект, позволяет сберечь трафик и передать PR страницы для поисковых систем (для Google точно).
  • процесс склейки и передачи PR занимает длительное времени — до нескольких месяцев и также зависит от поисковой системы, поэтому не удаляйте старую страницу или сайт, пока не произойдет окончательный перенос.
  • некоторые поисковые системы требуют для склейки сайтов дополнительных настроек, например, для Яндекса нужно дополнительно прописывать robots.txt

Загрузка файлов с помощью SWFUpload и PHP

Индексная
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
 
<head>
    <title>SWFUpload</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
    <h1>SWFUpload</h1>
    <div id="uploadButton"></div>
    <div id="status"></div>
    <div id="images"></div>
    <script type="text/javascript" src="js/jquery-1.4.2.min.js"></script>
    <script type="text/javascript" src="js/swfupload.js"></script>
    <script type="text/javascript" src="js/plugins/swfupload.queue.js"></script>
    <script type="text/javascript" src="js/main.js"></script>
</body>
</html>

uploadButton – предназначен для размещения кнопки загрузчика.
status – здесь мы будем выводить сообщения о процессе загрузки.
images – в этом блоке будут показаны загруженные картинки.

В конце страницы подключены 4 js файла.
  • Первый – библиотека jquery (ее использовать необязательно).
  • Второй – swfupload.js. Это основной скрипт библиотеки SWFUpload. Именно он создает кнопку загрузки.
  • Третий – plugins/swfupload.queue.js. Тоже входит в состав библиотеки. Позволяет загружать несколько файлов одновременно.
  • Четвертый – main.js. Здесь находится код настройки библиотеки и обработчики событий. Его мы сейчас и рассмотрим.
Настраиваем SWFUpload
Для того, чтобы подключить библиотеку, нужно создать объект SWFUpload и передать ему хеш с настройками.
Делается это следующим образом (код из файла main.js).
var swfu = new SWFUpload(
    {
        upload_url : "upload.php",
        flash_url : "swfupload.swf",
        button_placeholder_id : "uploadButton",
       
        file_size_limit : "2 MB",
        file_types : "*.jpg; *.png; *.jpeg; *.gif",
        file_types_description : "Images",
        file_upload_limit : "0",
        debug: false,
 
        button_image_url: "button.png",
        button_width : 100,
        button_height : 30,
        button_text_left_padding: 15,
        button_text_top_padding: 2,
        button_text : "<span class=\"uploadBtn\">Обзор…</span>",
        button_text_style : ".uploadBtn { font-size: 18px; font-family: Arial; background-color: #FF0000; }",
       
        file_dialog_complete_handler : fileDialogComplete,
        upload_success_handler : uploadSuccess,
        upload_complete_handler : uploadComplete,
        upload_start_handler : uploadStart,
        upload_progress_handler : uploadProgress
    }
);

В параметре upload_url мы указываем адрес php скрипта, который принимает файлы.

С помощью параметров flash_url и button_placeholder_id указываем адрес флеш ролика, который создаёт кнопку загрузки и id элемента на странице, в котором эта кнопка будет размещена.

Затем идет несколько параметров, устанавливающих ограничения на загрузку файлов. Здесь указаны допустимые разрешения файлов, их максимальный размер и количество файлов, которые можно загрузить за один раз (0 – любое количество).

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

Т.к. кнопка представляет собой флеш ролик, оформить её напрямую с помощью CSS не получится, но с помощью этих параметров вы можете указать фоновую картинку, шрифт и положения текста.

Оставшиеся параметры устанавливают обработчики событий. Рассмотрим их подробнее.
function uploadSuccess(file, serverData) {
    $('#images').append($(serverData));
}
 
function uploadComplete(file) {
    $('#status').append($('<p>Загрузка ' + file.name + ' завершена</p>'));
}
 
function uploadStart(file) {
    $('#status').append($('<p>Начата загрузка файла ' + file.name + '</p>'));
    return true;
}
 
function uploadProgress(file, bytesLoaded, bytesTotal) {
    $('#status').append($('<p>Загружено ' + Math.round(bytesLoaded/bytesTotal*100) + '% файла ' + file.name + '</p>'));
}
 
function fileDialogComplete(numFilesSelected, numFilesQueued) {
    $('#status').html($('<p>Выбрано ' + numFilesSelected + ' файл(ов), начинаем загрузку</p>'));
    this.startUpload();
}

upload.php
<?php
 
$uploadDir = 'uploads/'; //папка для хранения файлов
 
$allowedExt = array('jpg', 'jpeg', 'png', 'gif');
$maxFileSize = 2 * 1024 * 1024; //1 MB
 
//если получен файл
if (isset($_FILES)) {
    //проверяем размер и тип файла
    $ext = end(explode('.', strtolower($_FILES['Filedata']['name'])));
    if (!in_array($ext, $allowedExt)) {
        return;
    }
    if ($maxFileSize < $_FILES['Filedata']['size']) {
        return;
    }
    if (is_uploaded_file($_FILES['Filedata']['tmp_name'])) {
        $fileName = $uploadDir.$_FILES['Filedata']['name'];
        //если файл с таким именем уже существует…
        if (file_exists($fileName)) {
            //…добавляем текущее время к имени файла
            $nameParts = explode('.', $_FILES['Filedata']['name']);
            $nameParts[count($nameParts)-2] .= time();
            $fileName = $uploadDir.implode('.', $nameParts);
        }
        move_uploaded_file($_FILES['Filedata']['tmp_name'], $fileName);
        echo '<img src="'.$fileName.'" alt="'.$fileName.'" />';
    }
}

Пример загрузки файлов на сервер (upload) на языке php

Код формы (upload.html)
<html>
<head>
  <title>Загрузка файлов на сервер</title>
</head>
<body>
      <h2><p><b> Форма для загрузки файлов </b></p></h2>
      <form action="upload.php" method="post" enctype="multipart/form-data">
      <input type="file" name="filename">
 
      <input type="submit" value="Загрузить">
      </form>
</body>
</html>

Код скрипта обработки формы (upload.php)
<html>
<head>
  <title>Результат загрузки файла</title>
</head>
<body>
<?php
   if($_FILES["filename"]["size"] > 1024*3*1024)
   {
     echo ("Размер файла превышает три мегабайта");
     exit;
   }
   if(copy($_FILES["filename"]["tmp_name"],
     "c:/temp/".$_FILES["filename"]["name"]))
   {
     echo("Файл успешно загружен 
");
     echo("Характеристики файла: 
");
     echo("Имя файла: ");
     echo($_FILES["filename"]["name"]);
     echo("
Размер файла: ");
     echo($_FILES["filename"]["size"]);
     echo("
Каталог для загрузки: ");
     echo($_FILES["filename"]["tmp_name"]);
     echo("
Тип файла: ");
     echo($_FILES["filename"]["type"]);
   } else {
      echo("Ошибка загрузки файла");
   }
?>

</body>
</html>

В некоторых случаях требуется ограничить размер файла, который может быть загружен на сервер. К примеру, чтобы разрешить загрузку на сервер только файлов с размером не более 3 Мбайт, в приведенном скрипте содержится код:
if($_FILES["filename"]["size"] > 1024*3*1024)
{
  echo("Размер файла превышает три мегабайта");
  exit;
}