Archive

Archive for the ‘Web-development’ Category

Построение высокопроизводительных веб-приложений

April 30th, 2010

Защищаем gif файлы от атаки хакеров

October 29th, 2009

Нашел очень неплохое решение проблемы инъекций php кода в gif файлы

1
2
3
4
5
$file = 'image.gif.php';

Header('Content-Type: image/gif');

readfile('images/'.basename($file));

Источник идеи: http://www.phpclasses.org/blog/post/67-PHP-security-exploit-with-GIF-images.html

Dorian Gray PHP5, Web-Security, Web-development

Убираем мертвые стили из CSS

October 7th, 2009

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

Для решения этой проблемы может подойти аддон к FireFox CSS Usage

C помощью этого дополнения для FireBug можно отследить какие стили у нас не используются.

Dorian Gray Web-development , ,

HTTP сниффер HTTPFox (плагин для FireFox)

August 31st, 2009

Собственно установил себе такой плагин.  Попробую проанализировать им свои проекты.

Вот что про него питу в инете:

HttpFox 0.8.2 – плагин для Firefox. Плагин будет анализировать HTTP заголовки в вашем браузере. С этим плагином вы сможете просмотреть запросы между вашим браузером и просматриваемым сайтом: POST параметры, отправленные и полученные cookies и многую другую полезную информацию. Плагин будет полезен вебмастерам и владельцам сайтов желающим проанализировать работу их сайтов. Плагин не требует настройки и работает со всеми версиями браузера Firefox.
Автор Martin Theimer

Dorian Gray Web-development

Возможная архитектура веб-фреймворка

August 27th, 2009

Для начинающих «велосипедистов» иль просто любопытствующих…

Данная статья не призыв к действию, а лишь небольшая зарисовка на тему «Как бы я это сделал». На данный момент у меня в отделе активно используется Zend Framework, и именно с ним я лучше всего знаком, поэтому не пугайтесь параллелей, это не реклама, ведь большинство фреймворков в равной степени сочетают в себе плюсы и минусы, а нам нужны лишь преимущества…

Правила

Начал бы с регламентирования правил:

  • Стандарты кодирования — лучше воспользоваться существующими, советую стандарты Zend Framework’а
  • Процесс добавления кода в репозиторий (даже если вы сами в проекте — это будет хорошо дисциплинировать), только не перегибайте палку, иначе это замедлит развитие проекта

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

Архитектура

Надеюсь большинство читателей уже знакома с патерном MVC (Model-View-Controller) — так давайте на нем и базировать наш фреймворк, использования чего-то иного, боюсь, будет отпугивать пользователей (тут я подразумеваю программистов :) ).

Model

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

Давайте представим как может выглядеть модель:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// модель User использует в качестве хранилища БД
class Model_User extends Framework_Model_Database
{
$_table = "users";
$_pkey = "id";

function getByLogin($login) { /*...*/ }
function getByEmail($email) { /*...*/ }
}

// модель MainConfig использует в качестве хранилища ini файл
class Model_MainConfig extends Framework_Model_Ini
{
protected $_file = "application.ini";

function setOption($key) { /*...*/ }
function getOption($key) { /*...*/ }
}

// модель Registry использует в качестве хранилища память - некая альтернатива глобальным переменным
class Model_Registry extends Framework_Model_Memory
{
function setOption($key) { /*...*/ }
function getOption($key) { /*...*/ }
}

// модель Session использует в качестве хранилища файлы сессии
class Model_Session extends Framework_Model_Session
{
protected $_namespace = "global";

function setOption($key) { /*...*/ }
function getOption($key) { /*...*/ }
}

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

View

Каковы нынче требования к шаблонизатору? Лично для меня нативный PHP синтаксис, поддержка различного рода хелперов и фильтров. Так же должен быть реализован паттерн «двухэтапного представления» (Two Step View pattern), в ZF для этого служат два компонента — Zend_View и Zend_Layout.

Приведу пример такого представления:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    <?php if ($this->books): ?>
        <!-- Таблица из нескольких книг. -->
        <table>
            <tr>
                <th>Author</th>
                <th>Title</th>
            </tr>
            <?php foreach ($this->books as $key => $val): ?>
            <tr>
                <td><?php echo $this->escape($val['author']) ?></td>
                <td><?php echo $this->escape($val['title']) ?></td>
            </tr>
            <?php endforeach; ?>
        </table>
    <?php else: ?>
        <p>Нет книг для отображения.</p>
    <?php endif; ?>

Пример использование layout’ов (взят из документации по Zend_Layout):

Layout Example

Controller

Контроллер должен выполнять свои обязанности — обрабатывать запрос, пинать модель и представление — дабы пользователь получил желаемый результат.

Давайте попробуем среагировать на запрос пользователя следующего вида: example.com/?controller=users&action=profile&id=16

Так, проведем разбор — у нас просят показать профайл пользователя с id=16. Соответственно напрашивается существование контроллера users с методом profile, который бы смог получить в качестве параметра некий id:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    // название контроллера должно содержать префикс - дабы чего не напутать
    class Controller_Users extends Framework_Controller_Action
    {
        public function actionProfile()
        {
            // получаем данные из запроса
            $id = $this->request->get('id');
     
            // пинаем модель
            $user = new Model_User();
            $user -> getById($id);
     
            // закидываем данные в представление
            $this->view->user = $user;
        }
    }

Естественно, на плечи контроллера так же ложится обязанность изменять формат представление, т.е. если нам надо вернуть данные в JSON формате, то никакого иного вывода быть не должно (это и так подразумевается самим MVC, но стоит лишний раз напомнить).

Routers

Теперь немного о требованиях со стороны конечных пользователей — в частности о ЧПУ. Сравните следующие варианты ссылок:

example.com/?controller=users&action=profile&id=16
example.com/users/profile/id/16/ // стандартная схема построения URL’a в ZF
example.com/users/profile/16/ // CodeIgniter
example.com/profile/16/ // возможное пожелание заказчика, и его нужно выполнять

Для генерации/разбора подобного входящего запроса в ZF используются роутеры — по факту — это правила построения URL’ов, нам так же придется их реализовать — и с этим сложно поспорить.

Мне больше по душе передача именнованых параметров — такой URL легче читаем, сравните:
example.com/users/list/page/2/limit/20/filter/active
и
example.com/users/list/2/20/active

Вы наверное захотите сразу засунуть данный функционал непосредственно в класс Request, но не спешите, ведь нам еще потребуется генерировать правильные URL во View — а вызывать там объект Request — немного не логично, давайте таки оставим это на совести отдельного класса, к которому может обращаться как Request так и View

Request & Response

С назначением класса Request думаю проблем не возникает — в его функции входит не так много:

  • обработка входящих параметров всеми правилами из Router’а
  • отдавать параметры в контроллер по требованию

Но есть еще Response — о нем я как то не упоминал ранее, что же он должен делать:

  • формировать заголовок ответа
  • формировать ответ — т.е. брать view, оборачивать в некий layout и на выход

Modules

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

Core

Теперь стоит перейти к самому вкусному — непосредственно к ядру системы, его функционал мы практически уже описали, стоит лишь подвести черту:

  1. При инициализации входящий запрос должен быть обработан всеми правилами Router’ов, дабы объект Request мог вернуть нам запрашиваемое значение по ключу
  2. Объект Request так же должен знать, какой модуль/контроллер/экшен запрашивается
  3. Ядро должно подгрузить необходимый контроллер и вызвать запрашиваемый экшен (метод контроллера)
  4. После отработки контроллера вызывается Response и ставит точку

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

Вспомогательный классы

Если вы захотите потренироваться в написании «велосипедов», то можете начать отсюда:

  • Работа с БД — необходима поддержка MySQL, SQLite, PostgreSQL (это минимум), а в целом стоит уделить этому пункту много внимания, т.к. он один может привлечь множество пользователей
  • Валидаторы — необходимая вещь, для экономии времени при написании форм (см. Zend_Validate)
  • Транслятор — для реализации мультиязычности в системе, возможно хватит и gettext’a, но не стоит на это надеяться
  • Почта — можно обойтись лишь функцией mail, но это как-то не по-взрослому
  • Пагинатор — для решения тривиальной задачи — разбиение по страницам (см. Zend_Paginator)
  • Навигатор — построение меню, карты сайта и «хлебных крошек» (см. Zend_Navigation)
  • Кэширование — без него никуда (см. Zend_Cache)
  • Конфигурационные файлы — Zend_Config слишком большой для того, чтобы обрабатывать лишь один ini файл, тут можете попрактиковаться, но все же посматривайте на Zend_Config_Ini
  • Автозагрузчик — очень полезная вещь, и главное удобное — Zend_Loader
  • ACL — возможно потребуется — по крайней мере, распределение прав по запросу модуль/контроллер/экшен лучше пусть будет зашит в системе

Тривиальные задачи

В фреймворке должен быть заложен функционал для решения следующих тривиальных задач (мелких и не очень):

  • Redirect — самый обычный, вызывается из контроллера
  • Forward — это пересылка с одного модуль/контроллер/экшен на другой без перезагрузки страницы
  • Messages — различные сообщения, с возможностью получения их после перезагрузки страницы
  • Scaffold — быстрый способ построения приложения для редактирования записей в базе данных (утрированно)

Еще лучше, если с фреймворком будет поставляться готовая к использованию CMS система — она позволит популяризировать ваше детище, и возможно привлечет сторонних разработчиков.

Структура каталога

И так, что у нас получается, если взглянуть на файловую систему (в document_root должна лежать лишь папка public):

project
|-- application
|    |-- configs
|    |-- layouts
|    |-- controllers
|    |-- models
|    |-- views
|    `-- modules
|         `-- <module_name>
|              |-- layouts
|              |-- controllers
|              |-- models
|              `-- views
|-- data
|    |-- cache
|    |-- logs
|    `-- sessions
|-- library
|    `-- Framework
|-- public
|    |-- styles
|    |-- scripts
|    |-- images
|    |-- uploads
|    |-- .htaccess
|    `-- index.php
`-- tests

Это лишь мое пожелание, какой же она будет у вас — решать вам…

Вывод

To Be Or Not To Be — решать вам, как по мне — можно смириться с недостатками какого-то одного фреймворка, и наслаждаться его преимуществами. Возможно, вы попытаетесь написать свое решение или скрестить существующие, но не забываете — написание такого рода приложения влечет за собой ответственность по его поддержке.

RSS моего блога доступен по адресу http://anton.shevchuk.name/feed/, а твиттер тут http://twitter.com/AntonShevchuk

Dorian Gray Web-development

Условное выполнение html кода для говноброузера Интернет Эксплоит (Internet Explorer)

August 27th, 2009

Делаетеся так:

1
2
3
4
    <img src="data:image/png;base64,..." alt="График" title="График"/>
    <!--[if IE]>
    <img src="chart.png" alt="График" title="График"/>
   <![endif]-->

Dorian Gray Web-development

Отличия между гавноброузером Internet Explorer 8 и Internet Explorer 7

August 27th, 2009

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

http://blogs.msdn.com/ie/archive/2009/03/12/site-compatibility-and-ie8.aspx

Dorian Gray Web-development

Принудительное включение совместимости с IE7 в IE8

August 21st, 2009
1
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7"/>

Dorian Gray Web-development

Верстаем в Html5

August 14th, 2009

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

Итак, новый doctype выглядит превосходно! Можно выучить наизусть.

В HTML5 введены некоторые структурные элементы, о которых многие наверное слышали, но все же кратко:

<section>

Элемент группирует тематические блоки. section могут быть вложены друг в друга.

<header>

Содержит в себе заголовок какой либо секции, таблицы и т.д.

<footer>

Обычно включает в себя копирайт или контактную информацию.

<nav>

Определяет область навигации, обычно список ссылок.

<article>

Отдельная запись в блоге или статья на сайте.

<aside>

Вторичный контент, обычно находится в стороне от основного.

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

1
2
3
4
5
6
7
8
<script type="text/javascript"><!--
  document.createElement('header');
  document.createElement('nav');
  document.createElement('section');
  document.createElement('article');
  document.createElement('aside');
  document.createElement('footer');
// --></script>

Тот же код можно загрузить с google:

1
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>

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

1
<span style="color: black;">header, nav, section, article, aside, footer { display: block }</span>

Подготовка закончена, приступим: Сделаем классическую схему для блога: В реализации на html5 это выглядит примерно так:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 Simple HTML5 blog     <!--[if IE]> <mce:script type="text/javascript"><!              document.createElement('header');             document.createElement('nav');             document.createElement('section');             document.createElement('article');             document.createElement('aside');             document.createElement('footer');          // -->
<!--[endif]-->
<!--
styles
-->

blog header

navigation

Article header

Article

Article header

Article

sidebar content

copyright

Рабочий пример

Источник: http://habrahabr.ru/blogs/webdev/67049/#habracut

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

Dorian Gray Web-development ,

Чеклист запуска сайта

July 29th, 2009

Перед запуском

Контент и стиль

● Типографика
◦ Корректные символы. Проставить корректные символы тире, кавычек и апострофов, в зависимости от языка сайта
◦ Переносы слов. Проставить в важных местах неразрывные пробелы между инициалами, тире, перед последними словами
◦ Для английского: Лигатуры. Проставить лигатуры в заголовках, если требуется
● Вычитать тексты и проверить правописание
● Связность текстов
◦ Проверить регистр в важных текстах и заголовках
◦ Обеспечить единый стиль текстов
◦ Единство повторяющихся фраз (т.е. «Узнать больше», «Читать далее», «N комментариев» и др.)
◦ Пунктуация в списках (напр. если пункт списка заканчивается точкой, следующий пункт должен начинаться с заглавной буквы и наоборот для точки-запятой)
● Проверить нет ли на сайте вшитых ссылок на dev-сервер (т.е. после запуска ссылки должны вести на сайт «в миру»)
● Проверить не осталось ли на сайте тестового контента
● Проверить печатные версии важных страниц
● При редизайне или изменении информационной архитектуры, проверить стоят ли редиректы со старых адресов разделов на новые
● Проверить скрытые текст (e.g. alt/title атрибуты HTML тегов, тексты в Javascript функциях)

Стандарты и валидация

● Доступность для людей с ограниченными возможностями (не препятствуют ли нарушения восприятия цвета, звука и т.д. навигации по сайту)
● HTML валидация
● Javascript валидация
● CSS валидация

Доступность в поисковиках, SEO и статистика

● Заголовки страниц очень важны; убедиться, что они осмысленны и содержат важные ключевые слова
● Заполнить мета-тег «description» для важных страниц
● Привести ссылки на главную страницу к единому виду (т.е. выбрать что-то одно из вариаций site.ru www.site.ru www.site.ru/index.html)
● Гарантировать предыдущий пункт редиректом на выбранную версию (напр. редирект с www.site.ru/* на site.ru/*)
● Убедиться в семантически-грамотном использовании HTML тегов (

1
&lt;h1&gt;

,

1
&lt;h2&gt;

,… и т.д.)
● Проверить наличие важных ключевых слов в контенте
● Привести формат ссылок к читабельному виду (напр. site.ru/blog/how-to-make-coffee, site.ru/user/vasya и т.д.)
● Прикрутить Google Analytics, FeedBurner, и/или другие системы измерения статистики
● Создать XML Sitemap
● Добавить сайт в Google Webmaster Tools

Тестирование функциональности

● Проверить весь заказанный/особый/сложный функционал
● Проверить работу поиска (включая релевантность)
● Проверить работу сайта в разных браузерах (Internet Explorer, Firefox, Opera, Safari, Chrome etc.), версиях (6, 7, 2.2, 3.1 etc.) и платформах (Windows, OSX, Linux)
● Проверить вид сайта на разных разрешениях экрана (1280×1024, 1024×768, 1920×1200, 800×600…)
● Протестировать все формы (контактов, комментариев, фидбека, …), поставить на них капчу или другую защиту
● Проверить все e-mail шаблоны
● Проверить работоспособность сайта с выключенным Javascript, Flash, и другими компонентами
● Проверить работоспособность внешних ссылок

Безопасность/Риски

● Настроить бекапы по расписанию, и проверить восстановление из них.
● Проверить нет ли у посетителей доступа к служебным/секретным/закрытым страницам
● Закрыть поисковикам доступ к служебным/секретным/закрытым разделам сайта, используя robots.txt
● Отключить вывод ошибок на экран
● Проверить количество доступного дискового пространства и вычислить на сколько его хватит
● Настроить email/SMS уведомления о неработоспособности сайта/сервера;

Производительность

● Провести нагрузочное тестирование
● Провести оптимизацию изображений/графики
● Проверить и реализовать кэширование где это необходимо
● Проверить общий размер/скорость загрузки страниц сайта
● Минимизировать/сжать статику (Javascript/HTML/CSS)
● Оптимизировать CSS: короткие пути к изображениям; использовать «каскадную» природу стилей, и т.д.
● Проверить наличие индексов в таблицах БД
● Проверить другие настройки производительности на всех уровнях (Сервера, БД, CMS и т.д.)
● Включить логи ошибок/производительности на сервере

Финальные штрихи

● Создать свои страницы 404/403
● Создать страницу «Сайт на обслуживании»
● Создать favicon

После запуска

Маркетинг

● Добавить сайт в социальные медиа: Twitter, ВКонтакте, LinkedIn, Facebook, и т.д.
● Добавить сайт в поисковики
● Настроить PPC/Google Adwords кампании, если требуется
● Проверить форматирование сайта в результатах выдачи поисковиков

Другое

● Мониторить фидбек (прямой с сайта, на Социальных Медиа, в выдаче Google и т.д.)
● Отлавливать в статистике возможные проблемы с некоторыми разделами/страницами сайта
● Обновлять контент

Источник:  http://habrahabr.ru/blogs/webdev/65674/#habracut

Dorian Gray Web-development