Приватный режим в Сафари под iOS

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

function isPrivateMode() {
    var s = window.sessionStorage, key = '';

    try {
        s.setItem(key, '');
        s.removeItem(key);
    } catch (e) {
        if (e.code === DOMException.QUOTA_EXCEEDED_ERR && !s.length) {
            return true;
        } else {
            throw e;
        }
    }
    return false;
}

// приватный режим включен?
alert(isPrivateMode());

Оригинальный код основан на следующем факте — в приватном режиме мобильный Сафари запрещает доступ к sessionStorage. Я только обернул скрипт в функцию и переименовал переменные.

2 комментария

Яблокораздирающая история

«Макрадар» цитирует Джонатана Айва:

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

Это насколько ранний прототип-то? Примерно 8—10 лет назад я видел какой-то сотовый телефон (кажется, это была какая-то модель «Эрикссона»), у которого подобный датчик был и работал он стабильно. Там он отключал громкую связь, стоило телефон подвести к уху. Может и ещё что-то отключалось, я не помню уже.

10 комментариев

Защита от внедрения PHP-кода в картинки (JPEG, GIF, PNG)

На «Хабре» всплыла тема атаки, старой как мир — заливаем на сайт картинку, у которой внутри (в поле комментариев) есть ПХП-код, потом всякими трюками этот код запускаем. Валидатор картинок на сайте такую картинку пропускает — это вполне валидная картинка.

Во всех форматах принятых в вебе, есть поле, позволяющее вставить такие данные. В JPEG есть специальные секции APPn и COM, в PNG — iTXt, tEXt и можно создавать произвольные секции, в GIF — блоки расширений, в SVG можно использовать обычный XML-комментарий.

В качестве абсолютного метода защиты на «Хабре» предлагается пропустить картинку через какую-либо графическую программу, чтобы убедиться, что все дополнительные данные исчезли. Мне кажется, плохой способ — медленный, а в случае JPEG это ещё и скажется на качестве.

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

Мне кажется, я придумал более удачный метод защиты.

В загруженный файл можно добавить первой секцией (сразу после заголовка) свой собственный кусок ПХП-кода с вызовом __halt_compiler эта специальная конструкция останавливает интерпретатор в этой точке и всё остальное содержимое файла дальше не интерпретируется:

# смотрим что внутри файла
bolk@Bolk ~ $ hexdump -Cn128 sample.jpg 
00000000  ff d8 ff e0 00 10 4a 46  49 46 00 01 01 00 00 01  |......JFIF......|
00000010  00 01 00 00 ff fe 00 1a  3c 3f 70 68 70 20 5f 5f  |........<?php __|
00000020  68 61 6c 74 5f 63 6f 6d  70 69 6c 65 72 28 29 3b  |halt_compiler();|
00000030  ff db 00 43 00 02 02 02  02 02 01 02 02 02 02 03  |...C............|
00000040  02 02 03 03 06 04 03 03  03 03 07 05 05 04 06 08  |................|
00000050  07 09 08 08 07 08 08 09  0a 0d 0b 09 0a 0c 0a 08  |................|
00000060  08 0b 0f 0b 0c 0d 0e 0e  0f 0e 09 0b 10 11 10 0e  |................|
00000070  11 0d 0e 0e 0e ff db 00  43 01 02 03 03 03 03 03  |........C.......|

# запускаем
bolk@Bolk ~ $ php sample.jpg
????JFIF??

Т. е. на экран выводится бинарный заголовок JPEG, первая секция, а потом интерпретатор дальше просто не идёт. Будет дальше ход хакера или нет, он не проинтерпретируется.

17 комментариев

Код для защиты GIF, PNG и JPEG (к предыдущей статье)

В коментариях к предыдущей заметке о моём предложении по защите графических форматов от внедрённого кода один из читателей попросил привести код, который показывал бы как моё предложение работает.

Для форматов GIF, JPEG и PNG я за полчаса написал следующее (язык — PHP 5.4 и выше):

<?
// //bolknote.ru август 2012
// Защищаем изображения, возращает false в случае неудачи
function ProtectPicture($inname, $outname)
{
    // типы изображения, которые мы можем защитить и функции защиты
    $enabled = [
        IMAGETYPE_JPEG => 'Jpeg',
        IMAGETYPE_PNG  => 'Png',
        IMAGETYPE_GIF  => 'Gif',
    ];

    if (list(,, $type) = @getimagesize($inname)) {
        if (isset($enabled[$type])) {
            if ($fi = @fopen($inname, 'rb')) {
                flock($fi, LOCK_SH);

                if ($fo = @fopen($outname, 'wb')) {
                    flock($fo, LOCK_EX);
                    // если все файлы удалось открыть, то вызываем функцию защиты
                    $ret = call_user_func('ProtectPicture'.$enabled[$type], $fi, $fo, filesize($inname));

                    fclose($fo);
                    fclose($fi);

                    if (!$ret) {
                        unlink($outname);
                    }

                    return $ret;
                } else {
                    fclose($fi);
                }
            }
        }
    }
    
    return false;
}

/* Private functions */

function ProtectPictureJpeg($fi, $fo, $controllen)
{
    // заголовок JPEG
    if (!@fwrite($fo, fread($fi, 2))) return false;

    $protect = '<?php __halt_compiler();';
    $length  = pack('n', strlen($protect) + 2);

    // дописываю секцию COM (comment)
    if (!@fwrite($fo, "\xFF\xFE$length$protect")) return false;

    // остаток файла
    if (@stream_copy_to_stream($fi, $fo) != $controllen - 2) return false;

    return true;
}

function ProtectPicturePng($fi, $fo, $controllen)
{
    // заголовок PNG
    if (!@fwrite($fo, fread($fi, 8))) return false;

    // пропускаем кусок IHDR (он должен быть первым))
    $len  = unpack('N', $lenbin = fread($fi, 4))[1] + 8;
    $ihdr = $lenbin . fread($fi, $len);

    // Смотрим, не написал ли в этот кусок хакер свой код
    if (($pos = strpos($ihdr, '<?')) !== false) {
        // в стандарте перечислены поля, которые есть в этом куске — там должно быть 13 байт (+4 — длина)
        if ($len != 17) return false;

        // эта комбинация может встретиться только в первых восьми байтах заголовка — дальше поля не
        // могут принимать такие большие значения
        if ($pos > 11) return false;

        // если разрешены короткие теги, нужно присмотреться к этому коду
        // в столь ограниченном пространстве вред можно натворить только через запуск
        // чего-то внешнего
        if (ini_get('short_open_tag') && strpos($ihdr, '`', $pos + 2) !== false) {
            return false;
        }
    } 

    if (!@fwrite($fo, $ihdr)) return false;

    // кусок iTXt (text) с нашим кодом
    $protect = "<?php __halt_compiler();";
    $length  = pack('N', strlen($protect));
    $sum     = pack('N', sprintf('%u', crc32($protect)));

    if (!@fwrite($fo, "{$length}iTXt{$protect}{$sum}")) return false;

    // остаток файла
    if (@stream_copy_to_stream($fi, $fo) != $controllen - 8 - 4 - $len) return false;

    return true;
}

function ProtectPictureGif($fi, $fo, $controllen)
{
    $protect = "<?php __halt_compiler();";

    // заголовок GIF
    if (!@fwrite($fo, fread($fi, 6))) return false;

    // поле Logical Screen Descriptor
    $lsd  = fread($fi, 7);
    $flag = ord($lsd[4]);

    // указана ли Global Color Table?
    if ($flag & 128) {
        $pixel = 1 + ($flag & 0b111);
        $colors = pow(2, $pixel);
        $gctlen = $colors * 3;

        // читаем Global Color Table
        $gct = fread($fi, $gctlen);

        // не вставил ли уже туда злоумышленник „<?“?
        // меняем у такой комбинации последний бит — это малозаметно,
        // безопасность важнее!
        if (strpos($gct, '<?') !== false) {
            $gct = str_replace('<', '=', $gct);
        }

        if (!@fwrite($fo, $lsd . $gct)) return false;
    } else {
        $gctlen = 0;

        if (!@fwrite($fo, $lsd)) return false;   
    }

    // пишем комментарий с куском защиты
    fwrite($fo, "!\xfe" . chr(strlen($protect)) . $protect . "\0");

    if (@stream_copy_to_stream($fi, $fo) != $controllen - 6 - 7 - $gctlen) return false;

    return true;
}

В коде есть два места где я ищу не встретилась ли комбинация <? раньше, чем я вставляю защиту — это в заголовочном куске (IHDR) в ПНГ и в глобальной таблице цветов у ГИФа.

В случае ПНГ я анализирую заголовок, чтобы понять как там оказалась эта комбинация, она валидна только в первых восьми байтах (на зло остаётся всего 6 байт), кроме того, в этом случае я контролирую размер заголовка, в стандарте там указано 13 байт, хотя, кажется, размер не ограничивается. В общем, в шести байтах особо не разгуляешься, всё что я придумал туда засунуть — `rm *`, т. е. очистка текущего каталога. На этот случай, я контролирую появление символа `. На мой взгляд, вероятность встретить в нормальном ПНГ в заголовке <? после которого идёт ` ничтожно мала.

С ГИФом проще — меняю младший бит у цвета, это вряд ли будет заметно, а безопасность важнее.

10 комментариев

Льняная свадьба

Мужчина в жилете и бабочке и женщина в синем платье с перьями на шляпе сидят в креслах у стола с букетом и серебряным подносом, на стене — картина и лампа.

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

Съёмки проходили в доме-музее Арбузова, спасибо сотрудницам музея — Наталье и Маргарите, которые позволили провести фотосессию в этом замечательном музее и даже надеть некоторые вещи! Платье жене и бо́льшую часть моего костюма (один из сюртуков мы позаимствовали у музея) сшила непревзойдённая Рашида Сахипзянова (у неё есть анкета во «Вконтакте»).

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

Также спасибо за трость (видели бы вы как я её красил из балончика с краской) Индире Файзрахмановой, за часы Елене Козаковой и Мире Абраровой, Лилии Ясиной за букет и Инне Каражаковой за причёску жены.

Жена, ты такая молодец, что смогла это всё организовать!

19 комментариев

Динозавр в храме Ангкор-Ват

Храм Ангкор-Ват (អង្គរវត្ត) в Камбодже известен, кроме своей нереальной красоты о которой как-нибудь в другой раз, стегозавром в барельефе одного из храмов. Мы там были в мае, всем туристам его обязательно показывают, показали и нам.

Причём окружающие животные нарисованы очень натурально, безо всяких фантазий, а тут — динозавр. У меня такой вопрос — не знает ли кто-нибудь научную теорию о том откуда он там взялся? Интернет завален личными мнениями, которые мне не интересны.

Каменная резьба с изображением стегозавура в круглом медальоне, окружённого растительным орнаментом и фигурой змеи.

Что ещё интересно, стегозавр нарисован ровно так, как будто художник его видел, т. е. без устрашающих излишеств, которыми снабжали чудовищ на старинных гравюрах.

15 комментариев

Сжатый несжатый GIF

Как многие знают, браузер нативно понимает сжатие gzip (алгоритм DEFLATE). Наконец-то браузеры научились с ним правильно работать, после стольких лет мучений — сжимать можно что угодно, достаточно просто указать правильный заголовок.

Графический файлы обычно так не сжимают — внутри у них свой алгоритм сжатия, например в ПНГ используется тот же DEFLATE. Но с ГИФом ситуация хуже — у него внутри более старый алгоритм LZW, к тому же нет никаких оптимизационных техник (например, ПНГ использует так называемые «фильтры», которые позволяют эффективно сжимать градиенты.

Вот я и подумал — нельзя ли как-то заменить алгоримт сжатия ГИФа с внутреннего LZW на внешний gzip? Если было бы нельзя, я бы эту заметку не писал.

Смотрите, слева у вас на экране ГИФ, сжатый при помощи gzip (так и грузится с сервера), справа — ПНГ.

Пиксельная снежинка с розовыми, оранжевыми и бирюзовыми лучами

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


В каждом из них равное количество уникальных цветов, ПНГ пропущен через все оптимизаторы, которые я только нашёл. При этом ПНГ занимает 1374 байта, а гзипованный ГИФ — 1347, на 27 байт меньше. Дело тут конечно, не в паре десятков байт, а в принципе — если бы я выбрал картинку побольше, выигрыш, возможно, был бы существеннее.

Почему же LZW внутри ГИФа, плюс DEFLATE снаружи сделали файл меньше, чем оптимизирующие просто DEFLATE, плюс фильтры в случае ПНГ? Обычно наложение одного сжимающего алгоритма на другой делает файл больше сравнению с применением одного, более удачного алгоритам из двоих.

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

Самый простой, по моему мнению, способ получить такой файл — пропустить его через утилиту gifinter из набора libungif — библиотеки и набора утилит для работы с несжатыми файлами ГИФ.

Утилиты эти отлично скомпилировались под мой «Мак» и обрабатывал я ГИФ следующим образом: для начала оптимизировал его при помощи giflite (эта старая утилита под DOS, которую я запускаю из-под dosbox, творит с ГИФами чудеса), потом пропустил через утилиту, вырезающую из ГИФа комментарии (их туда вставил giflite), только после этого пропустил файл через gifinter и сжал при помощи gzip:

gifinter optimized.gif > non-compressed.gif
gzip -9n non-compressed.gif

Дальше я переименовал файл в 2012.08.08.gif-gz и добавил в конфигурацию своего «Апача» следующие строки:

AddEncoding gzip .gif-gz
AddType image/gif .gif-gz

Теперь при запросе сервер будет выдавать все необходимые заголовки:

bolk@Bolk ~  $ telnet bolknote.ru 80
Trying 91.230.61.15...
Connected to bolknote.ru.
Escape character is '^]'.
HEAD /imgs/2012.08.08.gif-gz HTTP/1.0
Host: bolknote.ru
Accept-encoding: gzip

HTTP/1.1 200 OK
Server: nginx
Date: Wed, 08 Aug 2012 06:12:14 GMT
Content-Type: image/gif
Content-Length: 1347
Connection: close
Accept-Ranges: bytes
Cache-Control: max-age=2592000
Expires: Fri, 07 Sep 2012 06:12:14 GMT
Content-Encoding: gzip

Если интересно как устроен несжатый ГИФ, об этом можно прочитать в Википедии, откуда я взял картинку, там интересная уличная магия, перепечатывать «Википедию» не очень-то интересно.

Готовой разгадки почему сжатый несжатый ГИФ обогнал ПНГ у меня нет, но есть одно возможное соображение — ГИФ чуть-чуть компактнее ПНГ, кроме того, ГИФ сжат целиком, тогда как в ПНГ сжата только картинка. Если моё предположение правда, то хорошего выигрыша ждать не сто́ит, но списывать формат ГИФ со счетов тоже не нужно.

По-настоящему опыт ценен, если удасться сделать несжатую ГИФ-анимацию (этого я ещё не пробовал) и сжать её при помощи gzip. Если удасться, это будет очень полезно, буду держать вас в курсе.

14 комментариев

Сжатая несжатая ГИФ-анимация

В догонку к предыдущей статье: мне удалось сделать несжатый анимированный ГИФ c сжатием через DEFLATE, вот он ниже (анимация не закциклена):

Шесть цифр на белом фоне: 1, 2, 3, 3, 2, 1.

Там шесть несжатых кадров (цифры «1», «2», «3», «3», «2» и «1») с небольшой задержкой, таблица из 16 цветов, в этом формате (несжатый ГИФ+DEFLATE) файл занял 619 байт:

bolk@Bolk ~  $ telnet bolknote.ru 80
Trying 91.230.61.15...
Connected to bolknote.ru.
Escape character is '^]'.
HEAD /imgs/2012.08.08.1.gif-gz HTTP/1.0
Host: bolknote.ru
Accept-encoding: gzip

HTTP/1.1 200 OK
Content-Type: image/gif
Content-Length: 619
Content-Encoding: gzip

Собранная при помощи gifsicle анимация в формате «обычного» ГИФа занимает 1028 байт, разница в полтора раза. Права, я выключил в gifsicle оптимизацию — иначе gifsicle исключит из изображений повторящиеся части и эксперимент будет нечистым.

17 комментариев

Поддержи антитабачный закон!

Попросили опубликовать. Поскольку я поддерживаю эту инициативу, с удовольствием у себя публикую (ниже текст не мой).

Антитабачный закон (10.42КиБ)

Интернет-демократия в действии! Газета «Московский Комсомолец» начала сбор подписей в поддержку законопроекта «О защите здоровья населения от последствий потребления табака». Законопроект уже поддержали профессор Леонид Рошаль, депутат Госдумы Николай Валуев, врачи-онкологи со всего мира.

Согласно предвыборной программе Владимира Путина, законопроект, собравший 100 000 подписей в Интернете, будет рассмотрен властями. Подписи, собранные на сайте МК, будут переданы в Государственную Думу и Правительство РФ.

При нынешнем уровне потребления табака Россия теряет около 400 000 человек из-за связанных с курением причин ежегодно. Эти смерти можно предотвратить, вводя эффективные меры борьбы с курением. Например, полный запрет курения в общественных и на рабочих местах позволит сократить количество госпитализаций из-за инфарктов на 30% в первые три года после вступления запрета в силу.

По данным Всероссийского опроса взрослого населения об отношении к мерам борьбы с табакокурением, 95% россиян считают курение вредным (72%, включая курильщиков, говорят, что это очень вредно). 80% населения страны поддерживают национальную политику борьбы с табачной эпидемией. В том числе за запрет на рекламу табачных изделий высказались 86% опрошенных, за финансирование программ профилактики потребления табака выступают 85%. Более действенные предупреждения на пачках сигарет нужны 81% россиян. Полный запрет на курение в общественных местах и на рабочих местах, включая рестораны и бары, поддерживают 82% жителей страны.

Поддержи антитабачный законопроект Минздрава! Поставь свою подпись на сайте «МК» и расскажи об этой акции друзьям!

42 комментария

Прогресс по несжатому ГИФу

Написал половину требуемого, чтобы попробовать эффективно конвертировать анимированный ГИФ в несжатый формат — разбор ГИФа на Пайтоне. Сначала я раскладываю ГИФ на информационные блоки, потом дербаню на кадры при помощи gifsicle, прогоняю каждый через gifinter и вытаскиваю (той же программой на Пайтоне) бинарное содержимое картинки.

Работает медленно, но мне больше нужна наглядность, а не скорость, с тем рассчётом всё и писал — вынимаю почти максимум, большинство данных даже не использую. На анимации в 47КБ (23 кадра) работает 4 секунды на моём слабеньком ноуте. Львиную часть времени (≈75%) занимает выемка бинарного тела картинки.

Вечером буду писать штуку, которая упаковывает полученное обратно в ГИФ.

Ни один браузер, кстати, не умеет отображать всё, что написано в стандарте ГИФа.

Оставить комментарий

Конвертор в несжатый GIF

Сделал я конвертор из обычного ГИФа в несжатый формат сжатый gzip, выложил на ГитХабе. Основное (разбор ГИФа) написано на Пайтоне, утилита, которая всё запускает — на Шеле. Для работы требуются ImageMagick (предпочтительнее) или gifsicle, gitinter (из libungif) и интерпретатор Пайтона.

Кажется, эксперимент провалился, я ещё буду вертеть различные ГИФы, но вряд ли что-то получится. По сравнению с анимированными ГИФами, где не используется оптимизация (не убираюся из следующих кадров статические куски, не используется фокусы с прозрачностью и наложением) выигрыш бывает, но по сравнению с оптимизированными, ещё не видел, чтобы испытываемый формат выигрывал.

Из плюсов для себя: детально для себя разобрал формат GIF, освежил знания Пайтона (которые уже начинают тускнеть), Шела, поработал над интересной идеей.

11 комментариев

Сжатие GIF через gzip

Эксперимент мой сжатию несжатых ГИФ, по сути, провалился — если статические изображения иногда оказываются меньше (или сравнимы) с PNG, то с анимированными изображениями, ради которых всё и затевалось, всё плохо, я не сумел подобрать условия, при которых новоявленный метод обгоняет обычные соптимизированные ГИФы.

Зато я попутно выяснил, что ГИФ, вопреки моим ожиданиям, иногда жмётся gzip, на первой попавшейся анимации я получил выигрыш порядка 9%. Так что вот он метод ещё больше утоптать файлы ГИФ:

#!/bin/sh

which -s defluff
if [ $? -eq 0 ]; then
    gifsicle -O3 "$1" |  gzip -9nc | defluff 2>&- > "$2".temp
else
    gifsicle -O3 "$1" |  gzip -9nc > "$2".temp
fi

size=( $(ls -l "$2".temp) )

# срезаем заголовок gzip и контрольную сумму
let 'size=size[4]-10-8'

dd if="$2".temp of="$2" bs=1 skip=10 count=$size 2>&-
rm -f "$2".temp

В настройки Апача надо добавить новое расширение файла:

AddEncoding deflate .gif-def
AddType image/gif .gif-def

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

Утилита defluff , которая у меня упоминается — это оптимизатор кодов Хаффмана для gzip, PNG и zip, иногда даёт выигрыш в размере.

25 комментариев

Многотарифные счётчики воды

Кто-нибудь ставил сабжевые счётчики? Всё ок, всякие ЖКХ не упираются рогом в какие-нибудь неведомые вчерамимжесочинённые бумажки?

4 комментария

Всякая мелочь одним постом-9

В заметке в ЖЖ «Бред сивой кобылы» собраны фотографии и описания советских клонов IBM PC.

В конце 80-х в СССР началась перестройка с ускорением. Может, если только ускорение, или только перестройка, и обошлось бы, но перестраиваться и ускоряться редкий Боливар такое вынесет… На фоне этого могучая электронная промышленность СССР и стран СЭВа, следуя руководящим документам эпохи осчастливила нас автохтонными ПК.

Итак сегодня маленький обзорчик советских клонов IBM PC — ПЭВМ.

На сайте «Мурмолка» есть интересная статья, вынесенная из закрытой «Лепры», про стажировку в Отделе Технического Контроля Управления Делами Президента.

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

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

В ЖЖ Олега Лурье рассказ об расформированном в начале 90-х годов подразделении, занимавшимся спасением подводников, которое могло бы спасти тех, кто утонул в подлодке «Курск».

Глубина-то совсем небольшая — 104 метра минус тридцать метров сама лодка, итого получается семьдесят четыре- семьдесят два метра. Это же элементарно для моих ребят. Вся операция вывода подводников занимает около трех часов. Итого получается, что мы бы затратили на спасение оставшихся в живых моряков «Курска» не более 5—6 часов, а значит, какая-то, и, я думаю, немалая, часть подводников была бы спасена.

«Зачем исследовать космос» — перевод письма 1970 года отправленного монахине из Замбии, Марие Юкуда, заместителем директора по научной части в Центре космических полетов NASA, в ответ на вопрос о текущих исследованиях Марса.

В своем письме Вы спросили как я могу предлагать расходовать миллиарды долларов на путешествие на Марс, в то время, когда многие дети на Земле умирают от голода. Я знаю, что вы не ожидаете такого ответа, как «О, я и не знал, что есть дети, умирающие от голода, но теперь я буду воздерживаться от любых космических исследований пока человечество не решит эту проблему!»

На самом деле, я знал о голодающих детях задолго до того, как я узнал, что путешествие на планету Марс технически возможно. Тем не менее, я считаю, как и многие мои друзья, что путешествие на Луну и, в конечном итоге, на Марсе и другие планеты, это рискованное начинание, которое мы должны предпринять, и я даже считаю, что этот проект, в конечном счете, будет способствовать решению более серьезных проблем, с которыми мы сталкиваемся здесь, на Земле, чем многие другие потенциальные проекты помощи, которые обсуждались и обсуждаются год за годом, и которые очень медленно приносят осязаемые результаты.

Оставить комментарий

Казань тридцатых годов

Чёрно-белое фото: верблюды тянут телегу с бочками по улице города; на фоне здания вывеска «Госшвеймашина» и другие надписи, люди на тротуаре.
Черно-белое фото: толпа людей у здания с арочными окнами и крышей, часть людей стоит на лестнице, другие — на земле; видна деревянная конструкция и куча снега или мусора слева.
Черно-белое фото: улица с трамвайными путями, толпой людей, зданиями и павильоном; на правом здании видна надпись «ДЮК» и цифры «10».
Чёрно-белое фото: башня с портретом Ленина, надписью «АССР» и датой 1930, рядом — купола церкви, люди на площади, облачное небо.
Черно-белое фото: здание с надписью «АТССР» на крыше и «10-летие УССР» на фасаде, перед ним толпа людей, справа видна церковь.
Чёрно-белое фото: на холме возвышается монастырский комплекс с куполами и колокольней, внизу — деревянные дома и открытая местность.
Чёрно-белое фото: уличный макет с надписями «ЛЕТ АГРЕГ» и «Данная продукция почти вся», установленный перед зданием с арочным входом и балконом.
Чёрно-белое фото: на переднем плане — деревянная плотина или дамба на реке, за ней — земляной вал с белой стеной и башней с шпилем, видны церкви и здания на фоне неба.
Группа людей в военной и гражданской одежде стоит вокруг деревянной телеги с лошадью на фоне разрушенного здания; на переднем плане — ведро, корзина и другие предметы.
Старик в длинной одежде и шапке держит счёты на фоне толпы людей у кирпичного здания; на земле лежат ящики с товарами.
Чёрно-белое фото: группа людей в длинных одеждах и платках стоит в очереди у входа в здание с вывеской «КУРК» и «ПЕЧЕНЬЕ», на улице — собаки, грязь и камни.
Портрет пожилой женщины в белом платке и клетчатой рубашке на фоне деревянной стены; чёрно-белое фото с видимыми царапинами и следами времени.
Девушка в платке и одежде начала XX века несёт плетёную корзину с овощами по брусчатой улице, на фоне здания с вывеской «СЕГА» и другого человека с ведром.
Мужчины осматривают оружие на прилавке среди руин зданий.
Группа людей осматривает и сортирует крупные кучи металлолома на фоне разрушенного здания.
Чёрно-белое фото: на развалинах люди торгуют старыми вещами и инструментами, разложенными на земле; в центре — женщина в пальто, мужчина с тележкой, сидящий старик с тростью.
Чёрно-белое фото: женщины в платках и дети у лавок с вывесками «Парикмахерская» и «Механическая мастерская», люди сидят на тротуаре, одна девочка идёт мимо.
Чёрно-белое фото: улица с трамвайными рельсами, люди в движении, кареты и верблюды с грузом, здания с вывесками, электрические провода.
Черно-белое фото: улица с толпой людей, пожарная лестница у здания, шланги на мокром асфальте, надписи «Т.В.Б.» и «ПОЧТА» на фасадах.
Чёрно-белое фото: верблюды тянут телегу с бочками по улице города; на фоне здания вывеска «Госшвеймашина» и другие надписи, люди на тротуаре.
Плакат с надписью «ЗАЙМЫ — ОПОРЫ ИНДУСТРИАЛИЗАЦИИ» и изображением заводов, кранов и рабочих; на заднем плане — другой плакат с кричащим человеком и текстом «ТЫ ДОЛЖЕН ИМЕЕМ ЗАЕМ!
Чёрно-белое фото: толпа людей на улице с деревянными домами, некоторые несут ведра, другие стоят в очереди или разговаривают; видна вывеска «ПРИЁМНАЯ» на здании справа.
Группа людей сидит и стоит у деревянной стены на улице, рядом с мешками и круглыми лепёшками; мужчина в центре стоит, улыбаясь, другие общаются или отдыхают.
Чёрно-белое фото: верблюды тянут телегу с бочками по улице города; на фоне здания вывеска «Госшвеймашина» и другие надписи, люди на тротуаре.
Группа людей стоит вокруг телеги с корзиной на мощёной улице; слева видна лошадь и мужчина в фуражке, справа — женщины в пальто и платках, одна из них держит ребёнка.
Группа людей стоит у входа в двухэтажное кирпичное здание с вывеской «МАГАЗИН», на заднем плане — деревянные дома и деревья.
Две фигуры идут по широкой булыжной улице старого города, по обеим сторонам которой стоят деревянные и каменные здания в стиле XIX века.
Чёрно-белое фото: каменная арка с деревянными воротами, через которую виден двор; справа сидит мальчик, слева — потрёпанная стена с окном и дверью.
Чёрно-белое фото: у деревянной лавки с вывеской «ХЛЕБНАЯ ТОРГОВЛЯ» стоят три человека — двое мужчин и женщина в платке; внутри видна женщина-продавец.
Чёрно-белая фотография: длинная очередь людей у деревянного здания с крыльцом и вывеской, на фоне других домов и пыльной улицы; видны женщины в платках, дети, мужчина с тележкой.

В ЖЖ Аксанова Нияза фотографии Казани 1930 года, сделанные Франком Уитсоном Феттером, университетским профессором, экономистом, который путешествовал по России весной того года.

7 комментариев

WEBP в PHP

WEBP (31.41КиБ)

Когда я делал биндинг GD для языка «Гугл Гоу», заметил, что в ПХП появилась поддержка формата WEBP. О самом формате как-нибудь в другой раз (пока можно почитать «Википедию»), скажу только, что многообещающий формат картинок для веба, который в настоящий момент поддерживается «Хромом» и «Оперой» (а в ФФ можно дёшево добавить поддержку через Джаваскрипт).

Чтобы поддержка формата (пока довольно куцая) появилась, нужно установить библиотеку libvpx и пересобрать ПХП с ключом —with-vpx-dir. У меня на «Маке» это выглядит так:

./configure --with-vpx-dir=/usr/local/Cellar/libvpx/1.1.0 \
… остальные опции
make
sudo make install

Правда в phpinfo информация как у меня на картинке не появится (это я сам немного пропатчил исходники), не пугайтесь — так должно быть, проверить наличие поддержки WEBP можно следующим образом:

var_dump(function_exists('imagewebp'));

Собственно, в языке появятся две новые функции: imagecreatefromwebp и imagewebp. У первой только одни аргумент — имя файла из которого надо создать ресурс GD (по действию ничем не отличается от любой другой подобной функции, например imagecreatefromjpeg), вторая принимает два параметра — ресурс и необязательные имя файла и качество, описание функции полностью совпадает с imagejpeg, с той только разницей, что сохраняет она формат WEBP.

Параметр качества изменяется от 0 до 100 и соотвествует параметру VP8 QP кодека в диапазоне от 1 до 63.

15 комментариев

Немного статистики по дереву родственников

Ввёл новый тег, myheritage для своего хобби — составления дерева родственников и предков.

На настоящий момент максимальная глубина дерева — 7, это начиная на одно поколение ниже моего (у меня детей нет, но у многих родственников моего поколения — есть), заканчивая прапрапрадедушками (и реже — -бабушками). Т. е. если считать с меня, то это на 5 поколений назад.

Я считаю, что глубина не бог весть какая, но знакомые-исследователи говорят, что это неплохой результат. По датам рождения это примерно 1840-е гг., т. е. середина 19-го века. Для многих архивов это почти предел, если род не именитый (как в моём случае).

Всего людей в дереве сейчас — 956 человек.

8 комментариев

Google Go GD binding

Исправил свой биндинг графической библиотеки GD к языку «Гоу» так, чтобы он работал под первой версией языка. Теперь изменился способ его установки и использования.

Ставить его теперь намного проще, достаточно выполнить следующую команду (в системе должна быть установлена библиотека GD):

go get github.com/bolknote/go-gd

Способ подключения бибилиотеки так же изменился (см. sample.go):

import gd "github.com/bolknote/go-gd"

Надеюсь, больше «Гугл» библиотеки языка и способ сборки менять не будет.

Добавлено позднее: заодно портировал на Go 1 и свою программу MakeCorner, ставиться, опять же, стала попроще, а вот размер сильно вырос. Версия r60 компилировала файл размером 1,6МБ, версия 1 компилирует уже в 2,2МБ. Безобразие!

Оставить комментарий

Знак «Опасный переезд»

Опасный, очень опасный переезд (94.66КиБ)

Лучший знак, предупреждающий об опасности, который я видел — около железнодорожной станции села Акбаш (Бугульминский район, Татарстан), он на фото.

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

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

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

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

7 комментариев

УК РФ разжигает ненависть к социальным группам насильников и убийц

На антифашиста завели дело о возбуждении ненависти к «скинхедам»

Владимирские следователи сочли экстремизмом демонстрацию фильма, содержащего «негативные оценки сторонников националистических взглядов»

Это из «Ведомостей». Божемой, ЧТО?!

28 комментариев

Морей

Наткнулся в своих исследованиях дерева предков на Прасковью Мореевну — вероятную родственницу по браку двоюродной бабушки. Всё хорошо — но что за отчество такое «Мореевна»? Какому имени соответствует, излазил весь интернет — ничего не нашёл.

Вроде должен «Морей» получаться, но интернет молчит, а хочется узнать как было образовано это отчество. Догадался вбить это отчество в базу военных потерь ОБД «Мемориал» и, вуаля!, у двух солдат с таким отчеством нашлось указание на отца. Действительно — Морей.

Морей (34.61КиБ)

Поиск по различным энциклопедиям имён даёт невнятное «(английское имя) законопослушный» с вариантами «Морс» и «Морри» и только. Неизвестно откуда родом Прасковья Мореевна и как её девичья фамилия, но откуда у неё папа-англичанин? Непонятно.

9 комментариев

Способ повалить Safari 6.0

Случайно нашёл способ как повалить браузер «Сафари» шестой версии (под «Мак»), другие версии не пробовал — не у меня их. Падает от такого HTML-кода:

<style>
* {
   background: -webkit-image-set(url(BOLK!) 1x), url(BOOM!)
}
</style>

3 комментария

До чего техника дошла

Вастрик-бокс

До чего техника дошла! У меня друг экзамен сдавал, когда упомянул про наушник, куда одногрупники будут начитывать билет, я, как мне показалось резонно, сказал ему, что не прокатит — волосы-то у него короткие. Он мне показал как выглядят современные наушники для списывания.

Найдите на картинке сам излучатель. Я попозже в комментариях расскажу что где.

22 комментария

Удаляем расладку «U.S. English» из «Мака»

Артём Поликарпов написал рецепт как можно удалить из «Мака» раскладку «U.S. English». Она очень мешается и совершенно не нужна, если поставить великолепную раскладку Ильи Бирмана (кстати, если вы почему-то ей не пользуетесь, то вы делаете большую ошибку).

Но рецепт Артёма мне не нравится тем, что для его выполнения приходится иметь у себя редактор Xcode, который ещё и несколько гигабайт весит. Поэтому я, как водится, написал скрипт, который нужно выполнить из «Терминала» (после его выполнения придётся опять залогиниться в систему) и ненужной раскладки уже не будет.

Меню с опциями: «Russian – Ilya Birman Typography», «English – Ilya Birman Typography», «Показать имя источника ввода» и «Открыть настройки языка и текста...
Ничего ненужного

Какое счастье!

Проще всего скрипт запускать из «Терминала» вот так:

bash  <(curl -fsSkL raw.github.com/bolknote/shellgames/master/us_layout_remover.sh)

Чтобы вернуть всё обратно достаточно запустить программу ещё раз.

Добавлено позднее: удалению раскладки может мешать Punto Switcher.

59 комментариев

Екатериновка, Пестречинский район

В мае мы были в Камбодже, ужасались тому как живёт местное население — грязно, бедно.

В России я относительно часто бываю в различных городах, иногда в маленьких (недавно был в Бавлах, это около 23 тысяч человек населения), я привык к цивилизации и если где-то сталкиваюсь с её отсутствием, то в виде временной трудности. А тут я решил прогулять по крошечной деревне Екатериновке Пестречинского района Татарстана — тут всего несколько десятков домов, разной степени изношенности. Хотя встречаются и новые, но среднее состояние дома тут такое:

Старый деревянный дом с резными наличниками и покосившейся крышей за ветхим забором под облачным небом.

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

Фрагмент фасада здания из красного кирпича с белым верхним этажом, тремя окнами в голубых рамах и белой надписью «1975» на стене, частично перекрытой проводами и столбом.
Белая статуя Ленина на постаменте в парке, мужчина в костюме стоит, протянув правую руку вперёд, на фоне берёз и деревянного забора с синей табличкой.

Есть свой Дом Культуры, с 19:00 до 23:00 — дискотека, я был там рядом как раз в это время, дискотеки не наблюдалось.

Жёлтая вывеска «ДОБРО ПОЖАЛОВАТЬ» над входом в зелёно-синее деревянное здание; на стене — табличка «ЕКАТЕРИНОВСКИЙ СДК» с расписанием работы методработы и дискотеки.

Да и плясать особо некому. Бо́льшая часть жителей — бабушки и их пьяненькие мужья. Кстати, распространены браки на пенсионерках, тогда как мужчина намного младше — пенсию бабулька получает, кормит, с глупостями не пристаёт, а у бабульки мужик при хозяйстве. Симбиоз. После комунизма и ядерной войны в деревне глухой христианское язычество. Вот эта плачущая бабушка расстроилась, так как глядя на меня, вспомнила, что её внучку «сгубил» какой-то фотограф — сглазил, сфотографировал в младенчестве. Слово «фотографировать» она не знает, говорит «стрелять». Такие верования.

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

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

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

Следы былой роскоши видны и на памятнике героям войны — вон сколько людей пало, правда это с Екатериновки и ещё шести окресных деревень.

Мемориальная стена с надписью «НИКТО НЕ ЗАБЫТ, НИЧТО НЕ ЗАБЫТО!», барельефом солдата и танка, а также списками имён погибших.

Вообще непонятно, деревня погибает или оживает — тут, к слову, два магазина, вот один из них:

Белый автомобиль Lada стоит перед деревянным строением с вывеской «МАГАЗИН ПРОДУКТЫ», рядом — синий холодильник Pepsi, квадроцикл и спящая собака на траве.

Как водится, вокруг кругом полно всякой живности:

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

И машины, не роскошь, а рабочие лошадки:

Старый синий трактор стоит за деревянным забором у двух деревянных домов с крышами из профнастила, окружённых зеленью и травой под пасмурным небом.
Ржавый жёлтый автомобиль ВАЗ-2101 стоит на траве у деревянного забора, за которым видна старая деревянная постройка с разбитым окном.
Человек в чёрной куртке и красной шапке сидит на мотоцикле спиной к камере на грунтовой дороге у деревянного дома и зелёного забора.

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

42 комментария

Слова-паразиты

Другое отношение к «словам-паразитам». Для чего они нужны и вредны ли. Посмотрите, ролик минут на 10. Кстати, когда нас в университете учили английскому, нас учили и словам-паразитам: well, so, позже я сам из «Бивиса и Баттхеда» почерпнул or something, and stuff.

13 комментариев

Opera 12.50 CSS hack

Ребята из «Оперы» уже трудятся над весьма интересной версией 12.50 и у меня уже готов ЦСС-хак для неё:

@media (-o-min-device-pixel-ratio: 1/100) {
    @media all {
         body {
            background: red; /* Opera 12.50+ */
        }
    }
}

И ещё вариант:

_:-o-prefocus:fullscreen, body {
    background: red; /* Opera 12.50+ */
}

Вместо body надо подставить нужный вам селектор.

11 комментариев

ICC-профили в GIF

Формат ГИФ почему-то окружён каким-то нереальным количеством мифов, хотя до недавнего времени он был очень популярен, а для анимации до сих пор остаётся единственным универсальным форматом.

Например, считается, что анимация появилась только в версии 89a (неправда, она была уже в версии 87a, в 89а её возможности были расширены), что ГИФ может использовать не более 256 цветов (не совсем так — не более 256 цветов на кадр, кадры могут накладываться друг на друга, давая любое отображаемое компьютером количество цветов).

Другое распространённое заблуждение — что ГИФ не поддерживает цветовые профили (ICC).

В самом деле, если посмотреть спецификацию формата, то слово «ICC» там не найдётся, но не найдётся там и слова «loop» (здесь: количество повторов), тем не менее, вы видели анимации, где указано определённое количество повторений и браузеры как-то это понимают.

Дело в том, что формат ГИФ поддерживает расширения. Расширения в спецификацию формата не входят.

Упомянутое количество повторов анимации задаётся в расширении, которое было когда-то предложено фирмой «Нетскейп» и потому имеет заголовок «NETSCAPE2.0», у расширения, которое содержит цветовой профиль заголовок другой — «ICCRGBG1012». ГИФ всегда разбит на блоки, и блок расширения (любого) помечен специальным флагом; заголовок расширения позволяет просмотрщику (в нашем случае — браузеру) решить с каким из расширений формата он имеет дело.

Вот начало файла ГИФ с внедрённым профилем:

00000000 47 49 46 38 39 61 01 00 01 00 f0 00 00 fe 00 02 |GIF89a……….|
00000010 00 00 00 21 f9 04 00 00 00 00 00 21 ff 0b 49 43 |…!…….!..IC|
00000020 43 52 47 42 47 31 30 31 32 ff 00 00 03 f0 55 43 |CRGBG1012…..UC|
00000030 43 4d 02 40 00 00 6d 6e 74 72 52 47 42 20 58 59 |CM.@..mntrRGB XY|

Пока не все браузеры умеют поддерживать цветовые профили ГИФ (как и профили любого другого формата), так ФФ не научился делать это до сих пор, а «Опера» научится это делать в новой версии 12.50.

Проверить поддерживает ли браузер цветовые профили можно и через Джаваскрипт. Принцип такой: я загружаю ГИФ-изображение 1×1 с цветовым профилем в тег CANVAS, потом проверяю цвет точки, он должен быть определённого цвета. Проверить поддерживает ли ваш браузер цветовой профиль четвёртой версии ГИФ можно у меня на сайте, в разделе «Храню».

7 комментариев

← сюда туда →