Архив января 2008

Полупрозрачный фон в Internet Explorer

Воскресенье, 6 января, 2008

MSIE 6 не поддерживает свойство прозрачности opacity. Однако добиться прозрачности в нем все же возможно с помощью двух специальных фильтров: Alpha и AlphaImageLoader. Фильтр Alpha позволяет отображать изображения с определенной степенью прозрачности (и применим только к тегу img), фильтр AlphaImageLoader — загружать фоновое изображение (точнее, располагаемое между фоном и передним планом).

Использование выглядит следующим образом:
в CSS для броузеров, поддерживающих полупрозрачные PNG, пишем:

.trans { background: url('images/trans.png'); }

Или, если нам достаточно равномерной однотонной прозрачности:

.trans { background: цвет; opactity: значение }

Здесь значение — степень непрозрачности от 0.0 до 1.0. Такой подход позволяет одно обращение к серверу (не нужно подгружать файл с полупрозрачной картинкой).

Для отображения прозрачного фона в Internet Explorer в head-части HTML-страницы пишем

<!--[if lt ie 7.0]>
<style type="text/css">
.trans { background: none; filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/trans.png', SizingMethod="scale" )}
</style>-->

Здесь SizingMethod=”scale” растягивает рисунок до размеров элемента. Если этот параметр не указать, элемент сожмется до размеров рисунка, что в нашем случае нежелательно.

Таким образом, мы создали класс .trans, применение которого к блочным элементам будет делать их полупрозрачными. Файл images/trans.png в простейшем случае должен быть пикселем 1×1

Гораздо удобнее иметь полупрозрачность в виде отдельного класса, и указывать при необходимости два класса для элемента (делается это так: class=”class1 trans”, где class1 — имя другого класса), чем приписывать ее ко всем классам элементов, которые ее используют.

Оффтопик: Также хотелось бы заметить, что в Сети существует статья (причем растиражированная в огромном количестве экземпляров) с опечатками в названии фильтра AlphaImageLoader и параметра SizingMethod. Названия фильтров должны писаться именно так, как они написаны здесь.

Предварительная загрузка изображений при наведении курсора на картинку

Воскресенье, 6 января, 2008

Очень часто при создании сайтов используется эффект наложения изображения при наведении курсора мыши на него. Хотя на первый взгляд, он реализуется предельно просто — замена this.src при наступлении событий onmouserover и onmouseout, но это создает один весьма неприятный эффект: подгрузка изображения с сервера может занять достаточно существенное время (1-2 секунды), что раздражает некоторых пользователей.

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

<script type="text/javascript">
var imgs = document.images;
function preload() {
  if (imgs) { var count = imgs.length; }
  else { var count=0; }
  var i=0;
  for (i=0; i<count; i++) {
    if (imgs[i].name!='') {
      imgs[imgs[i].name+'_over'] = new Image(imgs[i].height,imgs[i].width);
      imgs[imgs[i].name+'_over'].src=imgs[imgs[i].name].src.replace(/\.(.*?)$/,"_over.$1");
    }
  }
}

function on(pic) {
  pic.src=imgs[pic.name+'_over'].src;
}

function off(pic) {
  pic.src=pic.src.replace(/_over\.(.*?)$/i,\".$1\");
}
</script>

Код точно работает в MSIE 6, FireFox 1.5, Opera 9. Изображение должно обязательно иметь аттрибут name (это сделано для того, чтобы отделить изображния, являющиеся ссылками/кнопками, от изображений — элементов дизайна), а картинка, появляющееся при наведении — иметь то же имя, но с добавлением _over перед расширением (например, b1.gif и b1_over.gif).

Для корректной работы скрипта нужно повесить вызов функции preload на событие onLoad:
<body onLoad=”preload()”>
и задать события для самого изображения: <img src=”buttons/b1.gif” alt=”" onmouseover=”on(this)” onmouseout=”off(this)”>

О защите от XSS-атак

Воскресенье, 6 января, 2008

При разработке систем, в которых у пользователя есть возможность авторизации и отправки сообщений, существует ряд уязвимостей, с помощью которых можно организовать XSS-атаку путем внедрения JavaScript для отсылки cookies (или URL с идентификатором сессии).

Типичными способами являются следующие:

1. Самый очевидный и наиболее просто блокируемый: вставка тега <script> (отслеживается регулярным выражением вида

preg_replace('|<script(.*?)</script(.*?)>|is','',$buffer)

2. Добавление тега с обработчиком JavaScript-события (конструкции вида <div onMouseOver=”alert(’test’)”></div>. Такие регулярные выражения можно отследить следующим куском кода:

$events = array('onLoad','onClick'); // массив событий
$count=preg_ match_all('|<\w+(\s+[^>]*)>|s',$buffer,$matches);
for ($i=0; $i<$count; $i++) {
  $oldbuf=$matches[0][$i];
  foreach ($events as $curevent) {
    preg_replace('|\s+'.$curevent.'=".*?"|is','',$matches[1][$i]); // вместо '' можно вставить какое-нибудь уведомление о замене
    preg_replace('|\s+'.$curevent.'=\'.*?\'|is','',$matches[1][$i]);
    preg_replace('|\s+'.$curevent.'=\S*|is','',$matches[1][$i]);
  }
  $buffer=str_replace($oldbuf,$matches[0][$i],buffer); // замена исходной строки на очищенную от некорретных обработчиков
}

3. Добавление JavaScript в адрес ссылки или рисунка: (<a href=”javascript:alert(’test’)”></a>).
Корректируется следующим регулярными выражениями:

preg_replace('|<a href="\w+script:.*?"[^>]+>.*?</a>|is','',$buffer);
preg_replace('|<a href=\'\w+script:.*?\'[^>]+>.*?</a>|is','',$buffer);
preg_replace('|<a href=\w+script:\S*[^>]+>.*?</a>|is','',$buffer);

4. Добавление JavaScript в url внутри параметра style, например: <div sytle=”background: url(’javascript:alert(\’test\’)')”></div>

Корректируется следующим куском кода:

$count=preg_ match_all('|<\w+(\s+[^>]*)>|s',$buffer,$matches);
for ($i=0; $i<$count; $i++) {
  $oldbuf=$matches[0][$i];
  preg_replace('|\s+style=".*?"|is','',$matches[1][$i]); // вместо '' можно вставить какое-нибудь уведомление о замене
  preg_replace('|\s+style=\'.*?\'|is','',$matches[1][$i]);
  preg_replace('|\s+style=\S*|is','',$matches[1][$i]);
  $buffer=str_replace($oldbuf,$matches[0][$i],buffer); // замена исходной строки на очищенную от некорретных обработчиков
}

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

1. Броузер MSIE позволяет писать название протокола не только слитно, но и через символы табуляции (а также, возможно, перевода строки), т.е. ссылка вида <a href=”javas cript:alert(’test’)”>Тест</a> в нем будет работоспособна. Поэтому имеет смысл сначала проводить удаление символов табуляции внутри ссылок

2. В броузере MSIE, кроме JavaScript, существует еще и Visual Basic Script, который также может быть внедрен в URL ссылок и рисунков. Он обозначается vbscript (код в примере 3 написан с учетом его возможного наличия).

3. Если пользователю разрешается добавлять прикрепленные файлы и они сохраняются на диск в доступном для просмотра с помощью броузера месте с расширениями .htm, .html , то возможна атака следующего типа: в HTML-файл помещается код JavaScript, и затем атакуемому с помощью средств социальной инженерии предлагается перейти по ссылке, ведущей на этот файл напрямую, вместо того, чтобы скачать его скриптом.

Кроме того, даже если существует проверка на то, что загружаемый файл является графическим, внедрение JavaScript-кода в файл все равно возможно через так называемые EXIF-параметры (например. вместо имени автора можно прописать <script>alert(’test’)</script>), если файл сохраняется на диск с расширениями .html или .htm.

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


Rambler's Top100