среда, 31 декабря 2008 г.

Free SVN accounts (бесплатный SVN хостинг)

Надеюсь, что большинство из Вас, всё-таки знает, что такое SVN. Если вы серьёзный разработчик программного обеспечения, и до сих пор не знали что такое Subversion Repository, то вам необходимо срочно разобраться и опробовать его пользу на себе.

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

В общем, если всё-таки заинтересовал, то есть смысл развернуть у себя Subversion сервер локально на машине и наслаждаться его полезностью. Если разработку ведут несколько человек, причём работают они удалённо, то такой вариант, скорее всего, не подойдёт. Готовы регулярно, каждый месяц, выкладывать от $6, – тогда статья не для вас =), иначе читаем дальше.

В интернете встречается много бесплатных сервисов по предоставлению Subversion-хостинга. Попробую сделать краткий обзор наиболее популярных из них.

Начнём с https://opensvn.csie.org/. Этот хостинг предоставляет бесплатный аккаунт, быстрый процесс регистрации. Но, если в вашем проекте много мультимедийных файлов или большие бинарные файлы, то могут возникнуть проблемы. Здесь без предупреждения может быть удалён ваш аккаунт, при малейшем подозрении, что вы используете его не в целях разработки программного обеспечения.

http://cvsdude.com – неплохой хостинг, с большим количеством планов. Есть бесплатный SVN, предоставляют 2Mb дискового пространства, один репозитарий и один пользователь.

Пожалуй, наиболее распространён и раскручен www.assembla.com. Они предоставляют бесплатный SVN & Trac хостинг и при этом неограниченное дисковое пространство. Главный недостаток, что бесплатные аккаунты видны основной аудитории, если не хочется публичной обозримости, то прийдётся покупать private/professional account.

Для open source проектов Google предоставляет свои услуги по Subversion-хостингу http://code.google.com/hosting/.

https://www.bountysource.com/SVN хостинг, вместе с wiki и CMS для управления вашими проектами онлайн. Так же содержит среди своих сервисов tracker для задач.

Широкий спектр бесплатных сервисов по управлению разработкой программного обеспечения предоставляет и http://unfuddle.com/. В бесплатный аккаунт входит 200 Mb дискового пространства, до 2-х пользователей репозитария, Bug Tracking система и ещё несколько приятных мелочей.

http://xp-dev.com/ – как мне кажется, самый большой хостинг, по количеству предоставляемых услуг. Этот сервис предоставляет 1500 Mb бесплатного Subversion пространства под репозитарий, неограниченное количество репозитариев и пользователей для них, а так же полностью бесплатный набор всех необходимых Project Tracking сервисов.

пятница, 26 декабря 2008 г.

Эволюция профессий

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

Эволюция программиста:

Эволюция фотографа:


среда, 24 декабря 2008 г.

Классификация водки в стиле IT

0.1л - demo
0.25л - trial version
0.5л - personal edition
0.7л - professional edition
1.0л - network edition
1.75л - enterprise
- for small business
- corporate edition
Ведро - home edition
“На посошок” - Service pack
Рассол с утра - Recovery tool
Закуска - plugins
Черти - bugs
Пиво - patch
Coca-Cola, Fanta, 7-UP - trojan viruses

вторник, 23 декабря 2008 г.

Получение списка загруженных модулей сервера на Apache 1 из PHP

Думаю, что многие из вас сталкивались с работой с модулями сервера Apache на PHP. Всегда перед началом использования какого-либо серверного модуля необходимо проверить его активность и доступность. Как оказалось, определение загруженных модулей Apache средствами PHP может стать реальной проблемой, с чем я и столкнулся, потратил уйму времени, чтобы придумать решение.

Итак, обо всём по порядку. В PHP есть специализированная функция apache_get_modules(), работает она на PHP 4 >= 4.3.2, PHP 5. Эта функция позволяет получить список загруженных Apache модулей. Конечно, она идеально подходит для этой задачи. Так думал и я, пока не наступил на «грабли совместимости». Как написано в ChangeLog, функция apache_get_modules() с версии 5.0.0 стала доступна в Apache 1, и в PHP Apache 2 filter API. До того, она была доступна лишь при использовании Apache 2 handler API. Но, как показали тесты на разных серверах, – функция не оправдала надежды, она просто отсутствовала в Apache меньше версии 2.

Поставленная задача требовала максимальной совместимости разрабатываемого PHP продукта со всеми Apache серверами, начиная с версии 1.3. Поэтому я продолжил поиски решения. Функция phpinfo() выводит довольно много системной и серверной информации не только о сборке PHP, но и об остальных подключенных модулях и библиотеках. Решил воспользоваться этим шансом. Написал простой парсер для информации выводимой phpinfo(), который разбирал информацию из пункта Loaded Modules раздела apache2handler, если это был Apache 2. Или если это был Apache младше 2-й версии, то искал информацию о подключенных модулях в разделе Environment. Это решение, аналогично, успешно работало только на Apache 2, а на остальных сервер не выводил информацию о всех загруженных модулях, а только о тех, что были скомпилированы на этапе сборки.

Два выше расписанных метода определения не давали мне должной совместимости со всеми серверами и сборками. Я перекопал много информации, чтобы найти способ определения loaded Apache modules средствами простого PHP скрипта, но так и не смог найти готового решения.

Раз нельзя определить средствами PHP, какие из модулей сервера загружены, тогда надо заставить сам Apache передавать эту информацию в исполняемый скрипт. Простейший метод реализации, что мне пришёл в голову, это написать .htaccess скприпт, который бы, при исполнении PHP скрипта, передавал в него список загруженных модулей. Список можно передать в качестве $_GET параметра.

В конфигурационном файле .htaccess есть возможность использовать условную директиву . Она проверяет, если подключен указанный модуль Apache, то исполняет ветку, заключённую между директивами. Допускается использование и вложенных директив.

Для передачи дополнительных параметров PHP скрипту, с сохранением его оригинальных GET параметров, нужен как минимум загруженный модуль mod_rewrite. Он будет производить перехват запроса, добавлять необходимые параметры, если модуль активен, и отдавать его обратно в сприпт. Файл .htaccess даёт возможность объявлять переменные окружения и задавать им значения при помощи ключа [E], который мы добавим в RewriteRule.

Приведу фрагмент .htaccess, который написал:

Order deny,allow
allow from all

<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule .* - [E=MOD_REWRITE_ENABLED:mod_rewrite]
<IfModule mod_env.c>
RewriteRule .* - [E=MOD_ENV_ENABLED:|mod_env]
</IfModule>
<IfModule mod_auth_basic.c>
RewriteRule .* - [E=MOD_AUTH_BASIC_ENABLED:|mod_auth]
</IfModule>
<IfModule mod_proxy.c>
RewriteRule .* - [E=MOD_PROXY_ENABLED:|mod_proxy]
</IfModule>
RewriteRule ^index\.php$ index2.php?modules=%{ENV:MOD_REWRITE_ENABLED}%{ENV:MOD_ENV_ENABLED}​%{ENV:MOD_AUTH_BASIC_ENABLED}%{ENV:MOD_PROXY_ENABLED} [QSA,L]
</IfModule>

Этот файл необходимо положить в одну директорию с файлом index.php. Htaccess перехватит исполнение скрипта index.php. В зависимости от загруженных модулей выставит переменные окружения. Сервер добавит их конкатенацию в качестве переменной $_GET['modules'] к остальным параметрам GET запроса и запустит PHP скрипт на исполнение.

Разобрать строчку modules не составит труда, для этого используем функцию explode("|", $_GET['modules']). В результате получим уже готовый массив с именами загруженных модулей Apache.

Приведенный выше пример .htaccess рассчитан на определение только четырёх модулей Apache: mod_rewrite, mod_env, mod_auth_basic и mod_proxy. Вы довольно легко можете его расширить на любое количество необходимых модулей путём добавления дополнительных директив для проверок. В любом случае, вы ничего не теряете, даже если не загружен основной модуль mod_rewrite.c. Тогда лишь не отработает перенаправление и не будет передан параметр $_GET['modules']).

Надеюсь, вы не потратите столько времени, сколько потратил я, на решение такой, несложной, на первый взгляд, задачи, как детектирование модулей Apache средствами PHP. Если кто-то сталкивался с такой проблемой и смог придумать более оптимальное решение, как это сделать на версии сервера младше Apache 2, то внимательно вас выслушаю.

понедельник, 22 декабря 2008 г.

Сортировка IP адресов на MySQL

Во многих web-приложениях приходится сталкиваться с сортировками данных. Это является несложной задачей, если в качестве данных для сортировки выступают простые фамилии, наименования, даты, суммы, ну и другие строково-числовые данные. Но когда требуется упорядочить более сложные структурные данные, с учётом их логического разбиения, то иногда приходится поломать голову в поисках эффективного и не ресурсоёмкого алгоритма.

Я столкнулся с такой задачей. Нужно было отсортировать ряд IP адресов в порядке убывания или возрастания. Было два инструментария для сортировки, либо сделать это средствами PHP, либо переложить это всё на MySQL сервер. Второй вариант более предпочтителен, так он быстрее и эффективее, потому что выборка всё-равно происходит из базы данных.

Если решать сортировку в лоб, и отсортировать просто в алфавитно-числовом порядке, то IP адрес 135.x.x.x будет стоять перед 88.x.x.x, хотя это логически неправильно. Здесь надо учитывать не строку целиком, а разбивать на четыре отдельных байта – составляющие IP адреса.

Первое что пришло на ум – поискать специализированные функции для работы с IP адресами. Нашёл в manual по MySQL функцию для перевода строки с IP address-ом в числовое значение, то есть в integer, – это функция inet_aton().

SELECT ip, inet_aton(ip) as `IPvINT`
FROM ip_address
ORDER BY `IPvINT` ASC;

Этот метод работает безотказно, но если у вас данные в таблице были проверены и не содержат никаких больше символов, не относящихся к IP адресу.

Передо мной стояла задача немного сложнее, у меня мало того значением выступает IP адрес, он может содержать и маску вида 192.168.1.*, и даже диапазон адресов вида 192.168.1.0-192.168.230.14. Тогда выше приведенный метод не будет работать, потому что функция inet_aton() всегда будет возвращать неправильное значение для масок и диапазонов, и эти адреса будут кучей сбиваться в конце или начале отсортированного списка.

Приведённый ниже SQL запрос сможет отсортировать список значений IP адресов содержащих маски адресов вида 192.168.1.*, или диапазон адресов вида 192.168.1.0-192.168.230.14:

SELECT ip, (SUBSTRING_INDEX(ip, '.', 1)<<24) +
  (SUBSTRING_INDEX(SUBSTRING_INDEX(ip, '.', 2), '.', -1)<<16) +
  (SUBSTRING_INDEX(SUBSTRING_INDEX(ip, '.', -2), '.', 1)<<8) +
  SUBSTRING_INDEX(ip, '.', -1) as `IPvINT`
FROM ip_address
ORDER BY `IPvINT` ASC;

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

Более эффективный поиск картинок от Google

Google ввёл ещё одну инновацию в свой поисковый сервис. Теперь поиск картинок стал ещё более эффективным. Теперь можно фильтровать поиск выбором категории. Сейчас из доступных категорий есть «Новости», «Лица», «Фотографии».

Чтобы сделать поиск ещё более релевантным, компания Mountain View недавно добавила ещё две опции – клипарт (clip art) и штриховой рисунок (line drawings).

Таким образом, компания Google добавила ещё один штрих к своей поисковой системе и сделала поиск информации ещё быстрее и доступнее.

суббота, 20 декабря 2008 г.

Domain names и совместимость с браузерами

Ко мне обратился программист, говорит, мол, не могу понять, почему не работает система авторизации на странице и не запоминает данные логин и пароль после ввода пользователем. Причём не работает, только в отдельных браузерах.

Столкнулся с такой проблемой – на одном и том же PHP-скрипте, но при заходе с разных браузеров, не работал механизм сессий. Так как программное обеспечение пишем кроссбраузерное, то и проверяем один и тот же функционал на разных браузерах и различных конфигурациях сервера. Я вылил на свой хост его скрипт и начал разбираться, в чём дело, но у меня всё работало отлично, данные авторизации успешно сохранялись. Тогда попробовал на другом виртуальном хосте, где были проблемы, и обнаружил, что у меня тоже не работает в Internet Explorer и Safari, хотя при этом Firefox, а так же Opera успешно держали сессию.

Решил, что дело просто в разных настройках браузеров, и что они не сохраняют для отдельных хостов cookie. Всё тщательно перепроверил, но дело было не в этом. Установил себе сниффер и перехватил HTTP заголовки запросов к серверу и его ответов для каждого из браузеров. Для всех вариантов заголовок Set-Cookie имел правильное значение идентификатора сессии PHPSESSID, но IE и Safari упорно не хотели его держать и каждый раз при обращении к серверу он выдавал им новый идентификатор.

Так как сервер был один и тот же для тестирования и стоял у нас локально, а различие было лишь в именах виртуальных хостов, то пошёл к нашему системному администратору, на что тот пожал плечами и сказал что настройки для обоих виртуальных хостов одинаковые. И тут меня осенило, я увидел, что доменное имя виртуального хоста в первом случае содержит подчёркивание «_» в имени, а во втором нет. Это доменное имя было составлено не по стандарту RFC1035 (Domain names - implementation and specification). Отсюда и нерабочий механизм сессий, и отсутствие сохранения cookies в браузере.

Мораль сей басни такова. Этот яркий пример ещё раз показывает, что браузеры Firefox и Opera жёстко соблюдают стандарты, но при этом умеют работать даже в нештатных ситуациях. А Internet Explorer и Safari жутко капризны, перестают работать или интерпретируют код неправильно, даже при малейших отклонениях от стандартов. Будьте внимательны.

четверг, 18 декабря 2008 г.

MailOnPix - отличный Email AntiSpam сервис

Большинство осведомлённых людей на блогах и форумах не указывает email адреса в явном виде, а шифруют его в виде «mailbox (dog) gmail.com» или «mailbox (at) gmail (dot) com». Нашёл отличный сервис, чтобы при указании email адреса, где-нибудь на сайте, защитить его от парсинга роботами и от рассылок спама в дальнейшем. Имя ему – MailOnPix (http://www.mailonpix.com/). Он позволяет, путём вставки симпатичной картинки, реализовать AntiSpam защиту, вместо явного указания на сайте адреса электронной почты.

Чтобы получить такую картинку, достаточно просто зайти на их сайт, ввести адрес электронной почты и нажать на кнопку «Make picture». Сервис выдаст вам сгенерированные ссылки с кодом картинки для вставки на любую вашу страницу. Эта ссылка будет указывать на картинку с нужным вам адресом электронной почты.

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

понедельник, 15 декабря 2008 г.

Смешные издержки перевода

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

Решил собрать по просторам интернета эти самые реплики, чтобы поднять настроение и освежить в памяти. Итак, поехали:

  • How do you do? It's all right! -Как ты это делаешь? Всегда правой!
  • Can You hear me - Ты можешь меня здесь.
  • Undressed custom model - Голая таможенная модель.
  • Manicure - Деньги лечат.
  • I'm just asking - Я всего лишь король жоп (я бы перевёл «чёт я очкую», - прим. webaurum).
  • I have been there - У меня там фасоль.
  • God only knows - Единственный нос бога.
  • We are the champions - Мы шампиньоны.
  • Do You feel alright? - Ты справа всех знаешь?
  • Bye bye baby, baby good bye – Купи купи ребенка, ребёнок хорошая покупка.
  • To be or not to be? - Пчела или не пчела?
  • I fell in love - Я свалился в любовь.
  • Just in case - Только в портфеле.
  • Whatever the case - Что бы в этом кейсе не было.
  • I will never give up - Меня никогда не тошнит.
  • Oh dear - Ах олень.
  • I saw my Honey today - Я пилил мой мед сегодня.
  • I'm going to make you mine - Я иду копать тебе шахту.
  • May God be with you - Майская хорошая пчелка с тобой.
  • Finnish people - Конченные люди.
  • Bad influence - Плохая простуда.
  • Phone seller - Позвони продавцу.
  • Good products - Бог на стороне уток.
  • Let's have a party - Давайте организуем партию. Или: Давайте отымеем партию.
  • Watch out! - Посмотри снаружи!
  • I know his story well - Я знаю твой исторический колодец.
  • Let it be! - Давайте жрать пчел!
  • Press space bar to continue - Космический бар прессы продолжает.
  • I love you baby - Я люблю вас, бабы!
  • I've just saw your balance sheet - Видел я ваш баланс... так себе баланс.
  • I fell in love - Я свалился в любовь.
  • Let it be so - давайте эту пчелу вот так вот.
  • We have a lunch for an hour - мы имели Ланча один час.
  • To be or not to be? - Пчела или не пчела? или: Два пива или не два пива?
  • Just in case - Только в портфеле.
  • I will never give up - Меня никогда не тошнит.
  • By the way - Купи дорогу.
  • Metal fly - бляха-муха.
  • Still life with eggplant - тихая жизнь с баклажаном.
  • Notorious murderer - Нотариус-убийца.
  • I'm not a woman you can trust - Я не женщина, поверь мне.
  • Hungry like the wolf - венгры любят волков.
  • Museum of fine arts - музей хороших искусств.
  • With a holiday! - С праздником!
  • I feel bad - Я чувствую плохо.
  • Spirit is strong, but the flesh is weak - Водка ничего, а мясо протухло.
  • He was hooked - он получил удар хуком.
  • I am not like you - Вы мне не нравитесь.
  • Высшее Техническое - Maximum Technical.
  • Yeah, peace of cake... - Умираю! Дайте кусочек торта!
  • The troops were marching - Трупы маршировали.
  • We're a peaceful race! - Вот это гонка!
  • What is it now! - все по новой!
  • I'm just kidding. - Я всего лишь рожу ребёнка.
  • I would like to see manuals for these two instruments. - Я хочу посмотреть как вы двое это делаете вручную с вашими приборами.
  • Pumps - памперсы.
  • Ladybird - птичка женского пола.
  • Он стоял, стоял, потом взял да и вышел - he stood stood then took yes and went out.
  • If you miss the train - если вы мисс...
  • Danish pastry - Датские спагетти.
  • Лист бумаги - list of paper.
  • High school - высокие скулы.
  • I gotcha... I gotcha... - Я гоча, я гоча.
  • Truly yours - Ваш Трули.
  • Home sweet home - Дом, сладкий дом.
  • Watch Your back! - Посмотри на свою спину.
  • Tunnel washers - автоматические чистилища.
  • Ароматные блинчики - stinky pankaces.
  • Квартирный вопрос - flat question.
  • No smoking! - Пиджаки не вешать!
  • No smoking! - Смокингов нет!
  • As well - как хорошо!
  • Flying saucer - летающая сосиска.
  • Уха - ear soup.
  • Hi, sailor - какой потолок высокий…
  • Oven - Овен.
  • Летучие мыши - flying mouses.
  • Физическое лицо - physical face.
  • Юридическое лицо - legal face.
  • You're welcome back - Вы долгожданная задняя часть.
  • Screws and nuts - шурупы и орешки.
  • Speak for yourself - Разговаривай с собой.
  • They finished with soup. - Они кончили супом.
  • Заводской брак - factory marriage.
  • Ежемесячно – everymonthly.
  • Международная обстановка - international furniture.
  • He was fired from the company - Его фирма сгорела.
  • I wish you came yesterday – Я надеюсь ты зайдешь вчера.
  • I don’t drink, I don’t smoke and I don’t swear – Я не пью, не курю и не даю клятв.
  • Окружающая среда – surrounding Wednesday, surrounding medium.
  • Software - мягкие места компьютера.
  • Power plant - энергия растения.
  • I miss my town badly - Я девушка и живу в плохом городе.
  • Give up smoking - дай закурить!

воскресенье, 14 декабря 2008 г.

Kohana – быстро развивающийся PHP framework

В этой статье хочу рассказать вам об одном быстро развивающемся PHP framework-е. Так уж сложилось, что среди всех знакомых мне фреймворков, больше всего симпатизирует CodeIgniter (CI). На нём я пишу основную массу проектов, он лаконичный и очень лёгкий.

Один мой приятель, в процессе обсуждения инструментариев разработки на PHP скинул мне ссылку, чтобы я почитал про новый движок, довольно быстро развивающийся за счёт своего комьюнити. Открыв ссылку http://kohanaphp.com/, увидел Kohana – The Swift PHP Framework. Ещё больше меня заинтересовал этот движок после прочтения надписи, что он основан на CodeIgniter.

Итак, что же это за зверь, Kohana? Первое что пришло на ум – это разработка наших программистов, уж больно похоже название на одноимённое слово славянского происхождения. Оказалось что нет. Название Kohana было выбрано, когда разработчики начали просматривать словари коренных американцев для того, чтобы выбрать слово, не нарушающее авторские права. Kohana на языке Сиу значит 'быстрый'. Также на японском языке имеет значение 'маленький цветок', а на украинском 'быть любимой' и имя известной косатки (Kohana) – все эти значения не имеют отношения к названию. А изначально Kohana был создан как ветвь PHP фрэймворка CodeIgniter под именем Blue Flame. Главной причиной форка был переход к более открытой для общественности модели разработки, потому, что многие пользователи были недовольны скоростью разработки и исправления ошибок в CodeIgniter. В Июле 2007, Blue Flame был переименован в Kohana для того, чтобы избежать проблем с авторскими правами в будущем.

К особенностям данного PHP5 веб-фреймворка можно отнести:

  • высокие стандарты безопасности;
  • экстремальную легкость;
  • прост понимания и освоения;
  • использование MVC концепции;
  • интернационализация (есть полная поддержка UTF-8);
  • лёгкость расширения и масштабируемость.

Конечно, в своём большинстве эти особенности можно отнести и к CodeIgniter, но в Kohana всё было координально переработано, и местами даже их нельзя так напрямую сравнивать, это уже совершенно разные движки.

Основными системными требованиями для Kohana PHP framework являются:

  • сервер с поддержкой Unicode;
  • PHP версия >= 5.2.0;
  • сервер HTTP, работает на Apache 1.3+, Apache 2.0+, lighttpd, и MS IIS;
  • сервер базы данных (можно подключать различные драйвера, но сейчас встроены MySQL и PostgreSQL);
  • расширения PCRE, iconv, mcrypt, SPL могут потребоваться отдельным функциям ядра;
  • настоятельно рекомендуется поддержка mbstring, которая значительно ускоряет работу Kohana с UTF-8.

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

Swift - мощный PHP Mailer или библиотека для отправки почты

Большинство WEB-проектов требуют работы с почтой. На языке PHP есть инструменты для отсылки почты, но они явно не блещут функционалом. В основном, приходится писать самому мини-библиотеки для работы с e-mail рассылкой. Что касается меня, то я использовал в основном класс PHPMailer.

Совсем недавно в интернете набрёл на довольно интересный класс, предназначенный для работы с почтой, называется Swift (http://www.swiftmailer.org/). Даже наверно будет более правильно назвать его не классом, а полноценной библиотекой для работы с почтой на PHP, потому что она включает в себя несколько отдельных классов связанных между собой.

Swift – это библиотека, полностью написанная на ООП, предназначенная для отсылки почты из PHP скриптов и приложений. Понятное дело, что она не использует стандартную функцию mail(), у которой самым слабым местом является высокое потребление серверных ресурсов во время рассылки нескольких сообщений. Swift напрямую работает с SMTP сервером или MTA (Mail Transfer Agent), что позволяет ему делать рассылку быстро и эффективно.

Ранние версии Swift были сопоставимы с классом PHPMailer, но сейчас библиотека переросла в полностью отлаженный программный комплекс для рассылки почты. Несмотря на богатый функционал, интерфейс остался интуитивно понятным и доступным для освоения.

Самым главным достоинством, на мой взгляд, которое отличает эту библиотеку от остальных – это поддержка плагинов. Механизм взаимодействия плагинов основан на событиях. Они обеспечивают потрясающую гибкость библиотеке Swift. За время развития библиотеки она была неоднократно серьёзно переписана, как утверждает автор, и сейчас максимально совместима с RFC 2822.

Работать со Swift очень легко и удобно, чувствуется детальная проработка интерфейса. В доказательство приведу простенький пример отсылки HTML e-mail:

< ?php

//подключаем библиотеку
require_once "lib/Swift.php";
require_once "lib/Swift/Connection/SMTP.php";

//создаём объект Swift
$swift =& new Swift(new Swift_Connection_SMTP("server.tld", 25));

//формируем непосредственно само письмо
$message =& new Swift_Message("Здесь тема письма", "Непосредственно тело письма в виде HTML текста");
//задаём тип содержимого письма как text/html
$message->setContentType("text/html");

//отсылка письма
if ($swift->send($message, "to@domain.my", "from@home_domain.my"))
{
  echo "Письмо успешно отослано";
}
else
{
  echo "Ошибка отсылки email";
}
 
//Очень желательно это делать, когда работа с почтой закончена
$swift->disconnect();



Напоследок приведу веские аргументы, почему этот класс для работы с почтой лучше остальных конкурентов в своём классе:

  • поддерживается постоянное соединение, увеличивающее быстродействие;
  • расширяемые типы соединений, которые задаются пользователем;
  • поддерживаются разные типы аутентификации SMTP (LOGIN, PLAIN, MD5-CRAM, POP Before SMTP);
  • есть поддержка SSL и TLS (необходимая для Gmail серверов);
  • полный контроль над заголовками и требованиями RFC 2822;
  • поддержка локализации (интернационализация i18n);
  • есть баланс загрузки и управление потоками, поставляется с монитором полосы пропускания;
  • удобная работа с вложениями, корректная работа с любыми типами файлов и любым количеством вложений;
  • полностью включена библиотека MIME 1.0;
  • поддержка пакетной обработки почты;
  • умеет отправлять в письмах вложения любого размера, даже если выставлено 8Mb ограничение в PHP;
  • присутствует защита от header injection;
  • есть возможность выставлять приоритет сообщения;
  • есть анти-flooding защита, необходимая для серверов с ограничением количества писем с одного соединения;
  • и самое главное, на мой взгляд, - расширяемая система плагинов, которые легко писать.

вторник, 9 декабря 2008 г.

Номера кредиток для тестирования

По роду своей программистской деятельности, мне часто приходится иметь дело платёжными системами, требующими наличия номера кредитной карты для совершения транзакции, даже на тестовой учётной записи. Большинство платёжных шлюзов проверяет Credit Card Number на корректность, но для отладки работы скрипта или сервиса существует ряд тестовых номеров кредиток.

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

Список номеров кредитных карт для тестирования:

Credit CardNumber
Visa (13 Digits)4222222222222
Visa (13 Digits)4007000000027
Visa (16 Digits)4111111111111111
Visa (16 Digits)4012888888881881
MasterCard (16 Digits)5111111111111118
MasterCard (16 Digits)5105105105105100
MasterCard (16 Digits)5555555555554444
American Express (15 Digits)311111111111117
American Express (15 Digits)378282246310005
American Express (15 Digits)371449635398431
Amex Corporate (15 Digits)378734493671000
Diners Club (14 Digits)38000000000006
Diners Club (14 Digits)38520000023237
Diners Club (14 Digits)30569309025904
Discover (16 Digits)6111111111111116
Discover (16 Digits)6011111111111117
Discover (16 Digits)6011000990139424
JCB (16 Digits)3530111333300000
JCB (16 Digits)3566002020360505

Mapia – новый сервис: актуальная карта Украины

Проект Mapia представляет собой новый сервис карт Украины с очень удобным и быстрым интерфейсом. Карты очень подробны и при этом регулярно пополняются новыми объектами и уточнениями. На мой взгляд, очень удобной является возможность поиска по адресам и категориям объектов, нужно всего лишь выставить соответствующие пункты меню и они сразу будут подгружены на карту. Раздел «Категории» позволяет производить поиск по супермаркетам, банкоматам, клубам и ресторанам, кинотеатрам, разного рода достопримечательностям, а также получить подробную информацию о них. В целом интерфейс очень сильно похож на Google Maps, но объективно работает быстрее и потребляет меньше трафика.

Сервис также имеет удобную систему поиска, присутствующую на каждой странице. Найдя желаемый адрес, вы можете его детально рассмотреть, детализация позволяет увидеть отдельные дома и маленькие проулки. Есть возможность вывести на печать найденный участок карты. Отдельно хочется отметить раздел «Панорамы», зайдя в который вы сможете увидеть основные достопримечательности, виртуально поворачиваясь на 360 градусов. Довольно эффектно смотрится, если развернуть окно в полноэкранный режим.


Для нормальной работы карт необходим Flash Player 9.0.115 или выше, а так же браузер:
• Opera 9 и выше; 
• FireFox 2 и выше; 
• Internet Explorer 6 и выше; 
• Safari 3 и выше; 
• Google Chrome.

Кроме того, Mapia имеет свой собственный API, позволяющий легко интегрировать сервис с разного рода web-приложениями и сайтами. API позволяет размещать свои метки и наполнять их контактной информацией, адресами, телефонами, email-ами и другой важной для вас информацией. Есть и такая примечательная вещь, как загрузка логотипа или целого набора фотографий. Используя API Mapia, вы получаете подробные карты городов Украины, которые быстро загружаются и могут служить выгодным помощником на вашем сайте для привлечения клиентов. API Mapia предоставляет на выбор три языка — украинский, русский и английский.

пятница, 5 декабря 2008 г.

Смешной календарь (календурь)

Пни недели: поневольник, вздорник, череда, чертверх, потница, своббота, раскисенье (два последних - буходные, остальные - трудни).


КАЛЕНДУРЬ

  1. Пьянварь
  2. Фигвраль
  3. Кошмарт
  4. Сопрель
  5. Сымай
  6. Теплюнь
  7. Жарюль
  8. Авгрусть
  9. Свистябрь (Слюнтябрь)
  10. Моктябрь
  11. Гноябрь
  12. Дубабрь

среда, 3 декабря 2008 г.

Flash Player 10 – теперь Clipboard требует взаимодействия с пользователем

В web-приложениях часто приходится иметь дело с копированием какого-то string-значения в системный буфер обмена. Это становится реальной проблемой, когда нужна кроссбраузерность. Из JavaScript-а работать с буфером обмена можно, но это позволяет лишь Internet Explorer и Firefox, но с некоторыми ограничениями.

Нашёл для себя выход – использовать Flash-объект (вроде, copyToClipboard.swf назывался), встроенный на страницу. На элемент HTML-страницы вешается событие, JavaScript-ом передаётся нужный параметр во Flash-объект, а уже тот в свою очередь имеет доступ к буферу обмена пользователя. Таким образом, можно было положить любую строку из браузера пользователя в буфер обмена операционной системы.

Недавно мой Flash Player 9 нашёл в сети новую версию и предложил обновиться на 10-ю версию, на что я дал утвердительный ответ. Скачал, обновился, проверил flash объекты, все работают, всё функционирует так же, ... но потом обнаружилось, что в буфер обмена не попадает заветная строка.

На сайте adobe нашёл информацию о новом релизе, и начал разбираться, в чём дело. Оказалось, что изменений было много, и самые важные коснулись безопасности нового Flash Player-а, в числе которых и были ограничения на работу с clipboard. В девятой версии плеера ActionScript мог устанавливать значение в системный буфер обмена в любое время. В Flash Player 10 метод System.setClipboard() может быть успешно вызван только через ActionScript вызванный именно взаимодействием пользователя. Это могут быть, как события вызванные мышью, так и события исходящие от клавиатуры. Это нововведение с взаимодействием пользователя так же касается и нового ActionScript 3.0 метода Clipboard.generalClipboard.setData() и метода Clipboard.generalClipboard.setDataHandler().

Таким образом, эти изменения в основном затрагивают все SWF-файлы, которые используют System.setClipboard() метод. Нововведения касаются всех SWF-фалов проигрываемых в версиях Flash Player 10 и старше.

Подведу итог. Если вы хотите, чтобы ваши web-приложения работали адекватно с буфером обмена и в новых версиях Flash Player, то не забудьте обновить логику работы с System.setClipboard(). Этот метод теперь нужно вызывать непосредственно действием пользователя, к примеру, через кнопку, клавишную комбинацию быстрого вызова, или мышь.

пятница, 28 ноября 2008 г.

Регулярное выражение для проверки email адреса

Я думаю, многим приходилось сталкиваться с валидацией данных, введенных пользователем, при помощи регулярных выражений. Например, проверить корректность введеного email адреса. Сегодня нашёл регулярное выражение, которое используется именно для такой проверки  email адреса согласно RFC 2822, взято из исходников на Perl:

(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t]
)+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:
\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(
?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ 
\t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\0
31]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\
](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+
(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:
(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z
|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)
?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\
r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[
 \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)
?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t]
)*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[
 \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*
)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t]
)+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)
*:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+
|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r
\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t
]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031
]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](
?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?
:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?
:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?
:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?
[ \t]))*"(?:(?:\r\n)?[ \t])*)*:(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] 
\000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|
\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>
@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"
(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t]
)*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\
".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?
:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[
\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-
\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(
?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;
:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([
^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\"
.\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\
]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\
[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\
r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] 
\000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]
|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \0
00-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\
.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,
;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?
:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*
(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".
\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[
^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]
]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)(?:,\s*(
?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\
".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(
?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[
\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t
])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t
])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?
:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|
\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:
[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\
]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)
?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["
()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)
?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>
@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[
 \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,
;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t]
)*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\
".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?
(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".
\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:
\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\[
"()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])
*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])
+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\
.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z
|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(
?:\r\n)?[ \t])*))*)?;\s*)

Не удивительно, что многие программисты испытывают сложности с написанием и пониманием регулярных выражений ;). Большинство не будет использовать приведенное выше регулярное выражение, собственно, как и я сам этого не делаю. В основном использую некоторое упрощённое выражение в своих проектах, и с ним, пока, не было проблем. Приведу пример регулярного выражения, взятый из моего PHP кода:

^[a-zA-Z0-9_\.\-]+@([a-zA-Z0-9][a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,6}$

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

четверг, 27 ноября 2008 г.

5 аргументов не использовать inline CSS и JavaScript код

Если вы попали на мой блог, значит, вас интересует веб-программирование. Основой веб-программирования, понятное дело, является HTML, но никакой современный сайт уже не обходится без CSS и JS. В интернете можно встретить много разговоров о стандартах в web-программировании, в каком стиле лучше писать код. Ну а толку с них, - скажете вы, - если есть W3C, который занимается стандартизацией и там всё можно почитать. Конечно, можно, но там тонны информации, которую сложно переварить и надо затратить много времени на её изучение.

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

Итак, что же такое inline JavaScript и CSS, - это когда внутри html страницы идут вперемешку скрипты и описания стилей через строчку с html разметкой. Под JavaScript-ом вперемешку я понимаю не вызовы функций по событиям on_click, а непосредственно объявление этих самых вызываемых функций или объявление переменных между тегами <> < /script>, разбросанное по всей странице. Какая разница? – спросит большинство. А разница всё-таки есть, и я приведу вам 5 аргументов не использовать inline CSS и JavaScript код.


Аргумент 1: Кэширование и большинство оптимизаций не работают.
Большинство браузеров для убыстрения работы и уменьшения перегоняемого трафика используют в своей работе кэширование страниц. HTML страницы никогда не кэшируются. Что же касается графических изображений, внешних каскадных таблиц стилей (CSS) и файлов JS скриптов – то браузер пользователя наоборот, старается сохранить файлы в кэше при первом визите и при последующих запросах этих файлов не загружать их заново. Таким образом, объёмы загружаемой информации резко уменьшаются, перегружается только HTML-код страницы, а всё остальное подгружается из локального кэша браузера.

Аргумент 2: Непонятность кода и сложность нейтрализации ошибок
Допустим, у вас по большой HTML странице разбросаны JavaScript вставки. При наступлении какого-то события с неявно указанным обработчиком вам будет сложно выудить необходимый участок кода и нейтрализовать программные ошибки. А если страница компонуется из нескольких вставок, то обработчик и вовсе не будет отрабатывать, по той простой причине, что этот участок кода был случайно не включён.

Аргумент 3: HTML код становится тяжелее.
На выходе ваш HTML код получится значительно тяжелее и больше по объёму. HTML страница пронизанная JS и CSS вставками будет весить в килобайтах гораздо больше, чем аналогичная страница «чистая» по своей структуре.

Аргумент 4: Сложность модификации.
Лучше код взаимодействия вынести в одно централизованное место, чем просматривать весь текст в поисках однотипных участков кода для изменения, разбросанных по всем страницам сайта. Не каждый программист выдержит поддержку такого кода, разбросанного по всему сайту.

Аргумент 5: Невозможность повторного использования кода.
Если вы реализовали отличный по функционалу элемент интерфейса, то вы наверняка захотите его повторно использовать в остальных своих проектах. Но он намертво «вшит» по всем страницам сайта, и вам придется потратить уйму времени на его выуживание и прикручивание к другому сайту. При реализации, разнесенной по отдельным внешним файлам, всё, на что бы вам пришлось потратить время – это сделать подгрузку этих файлов, и вставить в необходимые места вызовы методов.

Надеюсь, мои 5 аргументов не использовать inline CSS и JavaScript код вас хоть немного убедили, и вы возьмёте их на заметку. Успешного кода, программист, и держи реализацию CSS и JavaScript в отдельных внешних файлах.

вторник, 25 ноября 2008 г.

Фотографии историко-культурного комплекса "Запорожская Сич"

Хочу поделиться фотографиями историко-культурного комплекса "Запорожская Сич", который посетил в эту субботу на о.Хортица. Конечно, не самое лучшее время мы выбрали для экскурсии – вечерело, погода пасмурная, моросил дождь, но всё-таки удалось отснять несколько удачных кадров на «мыльницу». Повезло лишь в том, что людей не было, мы были там единственными посетителями на то вечернее время.


Кстати, строительство историко-культурного комплекса "Запорожская Сич", как точной копии Сичи, существовавшей на о.Хортица, было начато ещё в 2004 году. Но в нашей стране деньги исчезают сразу после того, как их выделили, и вскоре работы прекратились из-за недостатка финансирования и возобновились лишь в июне 2005 года. На сегодняшний день, по некоторым данным, работы по созданию историко-культурного комплекса "Запорожская Сич" выполнены на 80-85 процентов. Вообще приятно видеть исторические памятки в нашем городе, жалко, что власти не хотят развивать идеи в направлении туристического бизнеса на должном уровне.

понедельник, 24 ноября 2008 г.

Странное дерево на о.Хортица


На этих выходных был на острове Хортица, в поле зрения попало вот такое симпатичное дерево. Так как я увлекаюсь фотографией, не удержался сфотографировать его. Под рукой приличного фотоаппарата не было, поэтому пришлось сфотографировать тем, что было (Sony DSC-80). В целом фото удалось, погода была пасмурной и шёл дождь, но от этого, контраста в фотографию только добавилось.

воскресенье, 23 ноября 2008 г.

Статус-коды ответов сервера (Server status-code responses)

В продолжение к предыдущему посту, где рассказывалось об особенностях использования cURL и передачи заголовков, приведу для справки статус-коды ответов сервера (server status-code responses).

[Informational 1xx]
100="Continue"
101="Switching Protocols"

[Successful 2xx]
200="OK"
201="Created"
202="Accepted"
203="Non-Authoritative Information"
204="No Content"
205="Reset Content"
206="Partial Content"

[Redirection 3xx]
300="Multiple Choices"
301="Moved Permanently"
302="Found"
303="See Other"
304="Not Modified"
305="Use Proxy"
306="(Unused)"
307="Temporary Redirect"

[Client Error 4xx]
400="Bad Request"
401="Unauthorized"
402="Payment Required"
403="Forbidden"
404="Not Found"
405="Method Not Allowed"
406="Not Acceptable"
407="Proxy Authentication Required"
408="Request Timeout"
409="Conflict"
410="Gone"
411="Length Required"
412="Precondition Failed"
413="Request Entity Too Large"
414="Request-URI Too Long"
415="Unsupported Media Type"
416="Requested Range Not Satisfiable"
417="Expectation Failed"

[Server Error 5xx]
500="Internal Server Error"
501="Not Implemented"
502="Bad Gateway"
503="Service Unavailable"
504="Gateway Timeout"
505="HTTP Version Not Supported"

Это структурированный список, уже готовый, для того чтобы его с лёгкостью можно было вставить в ini-файл или другой файл конфигурации. Он может использоваться для вывода более информативного сообщения, соответствующего индексу 'http_code' массива, возвращаемого функцией curl_getinfo().

Более информативный и детальный список по определению статус-кодов HTTP/1.1 можно получить на странице W3 консорциума http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html.

суббота, 22 ноября 2008 г.

Особенности использования cURL и передачи заголовков

Здравствуйте, читатели.

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

В данной статье хочу рассказать о библиотеке Libcurl. Libcurl — это кроссплатформенное программное обеспечение, библиотека, клиент использующийся для передачи URL. Она поддерживает огромное множество протоколов, таких как FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, LDAP, LDAPS и FILE. Так же libcurl поддерживает SSL сертификаты, HTTP POST, HTTP PUT, FTP загрузку, HTTP загрузку, основанную на формах, прокси, cookies, и многое другое. Пользователи могут довольно легко встроить её в свои программы при помощи API cURL. cURL действует как автономная обёртка для библиотеки libcurl. Для неё имеется более 30 различных привязок к языкам программирования, но я бы хотел показать механизм работы на примере PHP.

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

Немного почитав документацию по cURL, принялся писать код на PHP, ничего сложного в нём нет, приведу участок ниже.

< ?php
// ...

//если cURL доступен – то используем его
if ( (bool)function_exists("curl_init"))
{
  // создаём новый cURL resource
  $ch = curl_init();
  // выставляем соответствующие опции и требуемый URL
  curl_setopt($ch, CURLOPT_URL, $FILE_URL);
  curl_setopt($ch, CURLOPT_HEADER, 0);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);

  // сделать запрос по URL и вывести в браузер
  curl_exec($ch);

// ...
?>


Перед использованием cURL нужно проверить присутствует ли вообще у вас данный модуль, поэтому следует использовать метод function_exists("curl_init"). Создав новый cURL resource и выставив необходимые опции (подробнее по каждой из них можно узнать здесь: http://php.net/manual/ru/function.curl-setopt.php) мы делаем запрос curl_exec и выводим ответ в браузер.

Запускаем скрипт на исполнение, проверяем на конкретной странице, выставляем параметр CURLOPT_URL равный http://webaurum.dev/index.php. И, о чудо, заработало! Мы получили результат исполнения страницы index.php. Так как мне нужен прокси для получения любого контента, решил проверить и на других видах содержимого, подставил jpg-файл. Задав в качестве запрашиваемого URL изображение http://webaurum.dev/image.jpg, но в ответ получил только каракули в окне браузера, вместо ожидаемой картинки.

Начал разбираться в чём же дело. Перехватив заголовки, получил следующее в Response Headers:

Date Fri, 21 Nov 2008 10:24:00 GMT
Server Apache/2.2.4 (Unix) mod_ssl/2.2.4 OpenSSL/0.9.8e DAV/2 PHP/5.2.3
X-Powered-By PHP/5.2.3
Expires Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma no-cache
Content-Type text/html
Keep-Alive timeout=5, max=100
Connection Keep-Alive


причём и для изображения и для скрипта php в заголовке Content-Type почему-то стояло text/html. Получается curl не передаёт ответ сервера в чистом виде, хотя и получает адекватно содержимое. В документации описана опция CURLOPT_HEADER, там сказано, что при установке этого параметра в ненулевое значение результат будет включать полученные заголовки. Включаем его, и заново проводим эксперимент, подав изображение на вход. В итоге в браузере увидел следующее:

HTTP/1.1 200 OK Date: Fri, 21 Nov 2008 10:24:01 GMT Server: Apache/2.2.4 (Unix) mod_ssl/2.2.4 OpenSSL/0.9.8e DAV/2 PHP/5.2.3 Last-Modified: Fri, 19 Sep 2008 14:23:29 GMT ETag: "4927-4b124-72007a40" Accept-Ranges: bytes Content-Length: 307492 Content-Type: image/jpeg ╪ р� JFIF� �H�H�� с �Exif��MM�*��� � � ���

… и дальше шла куча иероглифов. Как ни странно, но curl смог адекватно определить mime тип запрашиваемого содержимого (Content-Type: image/jpeg), и даже правильно сформировал заголовки. Тем не менее, в респонсе сервера и дальше красовалось Content-Type: text/html. Почему же не выставляются таким образом заголовки, если до того никакого вывода в браузер не было, для меня осталось загадкой.

Недолго думая, решил распарсить эти заголовки вручную, и установить их явно при получении ответа от curl. У библиотеки curl есть мощный механизм для получения технических аспектов отработки запроса – метод curl_getinfo. Он может принимать множество параметров, но нас, в частности, интересует ключ CURLINFO_HEADER_SIZE. При использовании этого ключа, метод возвращает длину заголовков в ответе curl_exec. Зная длину заголовков, можно вырезать их из общего содержимого, установить их явно при помощи функции header(), а потом уже вывести остаток содержимого в бинарном виде. Тогда браузер должен адекватно проинтерпретировать mime тип полученного содержимого. Код приведен ниже.

< ?php
// ...

//если cURL доступен – то используем его
if ( (bool)function_exists("curl_init"))
{
  // создаём новый cURL resource
  $ch = curl_init();
  // выставляем соответствующие опции и требуемый URL
  curl_setopt($ch, CURLOPT_URL, $FILE_URL);
  curl_setopt($ch, CURLOPT_HEADER, 1);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);

  // сделать запрос по URL и вывести в браузер
  $data = curl_exec($ch);

  $headers = substr($data, 0, curl_getinfo($ch, CURLINFO_HEADER_SIZE));
  $data = substr($data, curl_getinfo($ch, CURLINFO_HEADER_SIZE));
  // парсим заголовки
  $headers = explode("\r\n", $headers);
  foreach ($headers as $header)
  {
  // устанавливаем каждую часть заголовка отдельно
  header($header);
  }
  // выводим остатки контента в браузер
  print($data);
  // закрыть cURL ресурс и высвободить системные ресурсы
  curl_close($ch);
}

// ...
?>


Теперь перехватим заголовки ответа сервера, и проверим результат:


Date Fri, 21 Nov 2008 11:12:49 GMT
Server Apache/2.2.4 (Unix) mod_ssl/2.2.4 OpenSSL/0.9.8e DAV/2 PHP/5.2.3
X-Powered-By PHP/5.2.3
Expires Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma no-cache
Last-Modified Fri, 19 Sep 2008 14:23:29 GMT
Etag "4927-4b124-72007a40"
Accept-Ranges bytes
Content-Length 307492
Content-Type image/jpeg
Keep-Alive timeout=5, max=100
Connection Keep-Alive

После запуска PHP скрипта на исполнение мы получили долгожданную картинку в окне браузера, а не набор иероглифов, как было раньше. При желании с помощью метода curl_setopt можно задать любые параметры запроса или передать точную копию cookie пользователя, таким образом, что между запросом пользователя и запросом сервера-посредника (прокси-сервера) почти не будет разницы.

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

Рекоммендую

Попробуйте надёжный хостинг от Scala Hosting