Архив за месяц: Март 2009

Yii на ru.wikipedia.org

До сегодняшнего дня на ru.wikipedia.org не было страницы о Yii (может конечно я плохо искал 🙁 )….
Теперь она там есть http://ru.wikipedia.org/wiki/Yii!
В качестве моего бонуса — оставил ссылку на свой блог!

p.s. то моя первая статья на вики — так что прошу сильно не пинать!

День Ubuntu!

Сегодня у меня день linux!

Выдался свободный денек (правда я приболел немного). и я решил поставить Linux на свою домашнюю машину, а так же на свой любимый Asus. Долгое время (начиная с версии 10, кажется) я пользовался Open Suse Linux, но 11 версия меня разочаровала — постоянные глюки и зависания (на форуме сказали,что скорее всего дело в моем оборудовании и несовместимости с данной версией ОС….в 11.1 обещали испарвить) Однако решил сменить дистрибутив и попробывать, хвалимую всеми Ubuntu!

Не буду описывать процесс установки, все и так прекрасно знают!!!!

На свою домашнюю машину поставил — Ubuntu 8.10 и еще некоторый софт:

LAMP (Perl,Php,Python)

JDK 1.6

NetBeans IDE

Subversion

После всего этого мой рабочий стол стал похож на что-то вроде этого:

ubuntu 8.10

ubuntu 8.10

Если при выборе дистрибутива для домашнего компьютера есть большой выбор дистрибутивов, можно поставить Mandriva, Suse, Fedora и другие….То для eeepc лучше (хотя и не обязательно) ставить специально собранный для него, их тоже достаточно много. Я остановился так же на убунту (а именно сборка http://www.geteasypeasy.com/). После установки пришлось поставить несколько (3) дополнительных пакета после чего все (wifi, web-камера) прекрасно заработало!

И вот такой получился рабочий стол:

screenshot1

ubuntu easypeasy

Вот такие вот дела!

p.s. Поставил MysqlWorkbench….что могу сказать……файл созданный в версии для Windows — коряво открывается РАБОТАТЬ ПРОСТО НЕВОЗМОЖНО!!!!

Ошибочки и интересные факты

Добрый день, уважаемые читатели!

Данная статья положит начало серии  статей.

Я хочу собрать коллекцию скриншотов с интересными сообщениями об ошибках, ну или просто с сообщениями об ошибках на популярных ресурсах сети.

Сегодня хочу представить Вашему вниманию сразу 2 экземпляра.

Ошибка сертификата у Google

Ошибка сертификата у Google

Вот такое вот замечательное сообщение получил я, попытавшись зайти в раздел статистики Google Analytics. Может, конечно, может быть,  моя машина захвачена чудовищными вирусами (лицензия на KIS недавно закончилась :-)).

Второе менее страшное, да же, я  бы сказал, более веселое — отличился всеми любимый хабр.

Хабр жжет!

Хабр жжет!

Даже если в этот момент хабр действительно «лежал», такое сообщение оставило приятное впечатление!

Думаю это не последняя моя заметка на эту тему, ведь не существует идеальных разработок 🙁     🙂

Yii, создаем свою CMS. База данных.

Краткое содержание предыдущих серий

1 Вступление

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

Когда я приступаю к разработке нового приложения или сайта, и уже более или менее понятно с какими сущностями придется работать и какие данные хранить, лично я, предпочитаю нарисовать схему базы данных, которая в будущем будет хранить всю информацию приложения. Такая схема позволит более наглядно представить все объекты, разрабатываемого приложения и взаимосвязи между ними. Для рисования таких схем, можно воспользоваться любым инструментом, начиная от листа бумаги и карандаша, заканчивая специализированным ПО, типа MS VISIO. Однако, я предпочитаю программное обеспечение, специально предназначенное для этих целей. Довольно давно, я пользуюсь Mysql Workbench, для проектирования баз данных Mysql, подробнее узнать про эту программу и скачать ее, можно тут.

Примерно за 40 минут работы, у меня получилась вот такая вот схема БД.

Схема бвзы данных

Сейчас постараюсь подробно рассказать про назначение каждой таблицы и каждого столбца.

И так поехали!

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

  • userId — идентификатор пользователя;
  • name   — имя пользователя;
  • email  — email пользователя;
  • password — пароль пользователя;
  • creationDate — дата регистрации пользователя (пока система однопользовательская — особого смысла в этом поле нет);
  • status  — 0 — пользователь активен 1 — пользователь заблокирован;
  • accessLevel — 0 — простой пользователь 1 — администратор (может управлять контентом и совершать административные действия)

System — таблица для хранения всех системных параметров.

  • systemId   — идентификатор записи
  • siteUrl  — основной url сайта
  • siteInfo— информация о сайте
  • siteDescription — описание сайта
  • ownerInfo            — информация о владельце
  • ownerEmail        — email администратора сайта
  • userId                      — пользователь создавший настройку (в однопользовательской работе на учитывается)

Content — данная таблица будет содержать все записи (посты), страницы и все остальное наполнение нашего движка.

  • contentId — идентификатор записи
  • title  — заголовок записи
  • alias  — строка Url данного записи
  • content — содержимое поста
  • status  — 0 — черновик, 1 — опубликовано
  • keywords — ключевые слова для записи (meta)
  • description — описание записи (meta)
  • createdBy   — идентификатор пользователя создавшего запись
  • creationDate — дата создания
  • active       — признак того что эта запись является самой последней (актуальной)
  • canComment   — разрешены ли комментарии для данной записи
  • isPrivate    — пост доступен только авторизованным пользователям (в версии 1 нашего движка это работать не будет)
  • publishDate  — дата публикации
  • revision — номер версии записи
  • contentParentId — идентификатор, изначально созданной записи
  • revisionParentId — идентификатор, предыдущей ревизии
  • contentType — тип контента  2 — запись (пост) 1 — страница
  • modifyDate — дата изменения
  • modifyBy                   — кем изменено
  • commentCnt          — количество комментариев

Comment — таблица хранит комментарии к постам и страницам (?).

  • commentId — идентификатор комментария
  • parentId  — родительский комментарий (в первой версии движка мы его использовать скорее всего не будем)
  • postId    — идентификатор поста, к которому относится комментарий
  • comment   — текст комментария
  • creationDate — дата создания комментария
  • userName     — имя пользователя, создавшего комментарий
  • userEmail    — email пользователя, создавшего комментарий
  • userUrl      — url пользователя, создавшего комментарий
  • userIp       — ip-адрес пользователя оставившего комментарий
  • status       — 0 — комментарий не подтвержден, 1 — комментарий одобрен, 2 — спам


Tag —
таблица хранит тэги.

  • tagId — идентификатор тэга
  • tag   — название тэга

TagContent- таблица предназначена для хранения отношения тегов и постов

  • tagContentId — идентификатор контента
  • contentId    — идентификатор записи
  • tagId     — идентификатор тэга

Я думаю, что в процессе разработки, придется корректировать и дополнять эту схему, но для начала работы она вполне подойдет.

Если есть какие-то замечание или предложения — прошу высказываться в комментариях.

p.s. Названия движка, пока так и не выбрано — любые варианты приветствуются!

Основной сайт Юпи! — http://yupe.ru

Исходный код — https://github.com/yupe/yupe

Присоединяйтесь!

Yii, пишем фильтр для предотвращения XSS атак.

Начну с небольшого отступления.

И все таки правильно говорят, а на некторых форумах (особенно UNIX-овых), прямо кричат — RTFM! Кто не понял очем идет речь — RTFM в переводе означает «читай эту чертову документацию!».  Это все я собственно вот к чему: изучая и что-то пытаясь написать на фреймворке Yii,  возникла задача фильтрации входных данных от различного рода «зловредных» символов (аля XSS-атака) и первое что пришло в голову — это написать свой фильтр (что я все таки и сделал), однако creocoder, на форуме Yii , совершенно спрпаведливо заметил, что не зачем изобретать велосипед, все уже есть готовое, необходимо только RTFM! Речь шла о классе CHtmlPurifier, который является оберткой для библиотеки HTML Purifier , и выполняет все те функции, которые мне необходимы (правда я так и не попробывал его в действии, может и зря конечно). Но раз уж я начал писать свой фильтр — решил все таки это дело завершить, да и просто написать статью о фильтрах в Yii.

И так!

Фильтры — фрагменты кода, которые могут быть выполнены до и\или после выполнения экшена  контроллера.  Фильтры, при необходимости, могут  не допустить выполнения запрошенного экшена.

Фильтры могут быть как методами текущего контроллера, так и отдельными классами — что позволяет повторно их использовать. Если фильтр реализуется как метод класса, он должен иметь префикс «filter».

Пример:

public function filterAccessControl()
{
 .......
}

Фильтр, реализованный в виде отдельного класса, должен быть наследником класса CFilter.

Пример:

class XssFilter extends CFilter
{
   // код который выполнится до выполнения экшена
 public function preFilter()
 {
  .......
 }
 // код который выполнится после выполнения экшена
 public function postFilter()
 {
 .......
 }
}

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

Пример:

public function filters()
{
 return array(
           'accessControl',
           array(
             'application.filters.XssFilter',
             'clean' => 'all'
          )
  );
}

В этом примере ‘accessControl’ — фильтр, реализованный как метод контроллера, а ‘application.filters.XssFilter’ — фильтр, реализованный в виде отдельного класса, который хранится в каталоге /protected/filters/. ‘clean’ — устанавливаем свойство фильтра.

Это была краткая справка  по фильтрам в Yii, более подробно можно почитать тут.

Теперь непосредственно приступим к реализации нашего фильтра. Функцию очистки данных, которая и выполняет всю работу — я взял из фреймворка Kohana. Ну на этом достаточно слов, приведу сам код фильтра — он  совсем простой, так что думаю проблем быть не должно.

  /**
   *  @author  Opeykin A. <andrey.opeykin.ru&; <aopeykin@gmail.com>
   *  @version 0.0.1
   *  @package filters
   *
   * Фильтр предназначен для фильтрации входных данных, c целью предотвратить xss атаки.
   * Для фильтрации используются регулярные выражения из фреймворка Kohana 2.3.1
   * @example
   *
   *  public function filters()
   *  {
   *         return array(
   *                 array('application.filters.XssFilter',
   *                       'clean' =>; 'all'
   *                 )
   *         );
   *
   *   }
   *
   *   В качетве параметра 'clean' могут быть:
   *  - 'all' - фильтруются GET,POST,COOKIE,FILES массивы;
   *  - '*'   - аналог ALL;
   *  - так же возможно сочетание любых из параметров, например GET,COOKIE или POST,FILES
   */

class XssFilter extends CFilter
{
   public  $clean = 'all';

  protected function preFilter($filterChain)
  {
  $this->clean  = trim(strtoupper($this->clean));
  $data = array(
  'GET'    =>&$_GET,
  'POST'   =>&$_POST,
  'COOKIE' =>&$_COOKIE,
  'FILES'  =>&$_FILES
  );

  if($this->clean === 'ALL' || $this->clean === '*')
  {
    $this->clean = 'GET,POST,COOKIE,FILES';
  }
  $dataForClean = split(',',$this->clean);
  if(count($dataForClean))
  {
     foreach ($dataForClean as $key => $value)
     {
        if(isset ($data[$value]) && count($data[$value]))
        {
           $this->doXssClean($data[$value]);
        }
     }
 }
return true;
}

  protected function postFilter($filterChain)
  {
    // logic being applied after the action is executed
  }

  private function doXssClean(&$data)
  {
     if(is_array($data) && count($data))
  {
    foreach($data as $k => $v)
  {
     $data[$k] = $this->doXssClean($v);
  }
     return $data;
}

if(trim($data) === '')
{
return $data;
}

// xss_clean function from Kohana framework 2.3.1
$data = str_replace(array('&amp;','&lt;','&gt;'), array('&amp;amp;','&amp;lt;','&amp;gt;'), $data);
$data = preg_replace('/(&#*\w+)[\x00-\x20]+;/u', '$1;', $data);
$data = preg_replace('/(&#x*[0-9A-F]+);*/iu', '$1;', $data);
$data = html_entity_decode($data, ENT_COMPAT, 'UTF-8');
// Remove any attribute starting with "on" or xmlns
$data = preg_replace('#(<[^>]+?[\x00-\x20"\'])(?:on|xmlns)[^>]*+>#iu', '$1>', $data);
// Remove javascript: and vbscript: protocols
$data = preg_replace('#([a-z]*)[\x00-\x20]*=[\x00-\x20]*([`\'"]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2nojavascript...', $data);
$data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2novbscript...', $data);
$data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#u', '$1=$2nomozbinding...', $data);
// Only works in IE: <span style="width: expression(alert('Ping!'));"></span>
$data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?expression[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
$data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?behaviour[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
$data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:*[^>]*+>#iu', '$1>', $data);
// Remove namespaced elements (we do not need them)
$data = preg_replace('#</*\w+:\w[^>]*+>#i', '', $data);
do
{
// Remove really unwanted tags
$old_data = $data;
$data = preg_replace('#</*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|i(?:frame|layer)|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|title|xml)[^>]*+>#i', '', $data);
}
while ($old_data !== $data);
return $data;
}

}

Я совсем немного протестировал это фильтр — на первый взгляд — все работает!

Любые замечания и комментарии приветствуются!

Хочу добавить свои замечания к реализации фильтров в Yii…

Мне кажется было удобно иметь метод, который вызывается перед выполнением preFilter и postFilter, например init() — который выполняет инициализацию фильтра, при этом в нем должны быть доступны параметры, передавемые в фильтр из контроллера  (по этой причине невозможно использовать __construct). Конечно можно расширить CFilter для этих целей, но «родная» возможность сделать это была бы лучшим вариантом.

Надеюсь, описанный материал окажется полезен!

Ищите разработчиков на Yii ?

Мы решим Ваши задачи!

Скачать xssfilter