Inbox Zero

Про «inbox zero» я услышал довольно давно, больше года — точно. Основная идея — в папке «inbox» («входящие») лежат только письма, которые требуют моей реакции, чаще всего их немного, они мозолят глаза и от них не спрятаться. Остальных письма «архивируются» (в почтовых клиентах есть кнопка «архивировать»), в клиенте «Thunderbird» такие письма лежат в папке «Архивы».
Недавно меня допекло — решил перейти на zero inbox, сразу скажу — не пожалел. Главное хранить во «входящих» только те письма, к которым планируется вернуться в скором времени, а не «возможно,
Это работает. Попробуйте.
Москва → Самара → Москва
C восьмого по одиннадцатое октября в Самаре.
Попробовал переползти с ноутбука на стационарное рабочее место
Около полугода я насильно заставлял себя пользоваться только ноутбуком, ограничивал себя и старался не подключаться к внешним клавиатуре, мышке и мониторам.
Научился. Я очень комфортно чувствую себя за ноутом, меня перестал раздражать тачпад, «маленький экран» (который для меня сейчас вполне достаточен), то что его нужно класть на колени и так далее.
Сегодня я решил, что я достаточно научился работать за ноутбуком, чтобы пересесть обратно.
Как я работал за этой высокой клавиатурой? Тянуть за мышью — это же неудобно! А мониторы! Они у меня вертикальные, приходится задирать голову, у меня уже шея болит!
Жена-дао
Жена у меня скрапбукингом занимается, если кто не знает (это открытки ручной работы и всё такое). Так что она одна из немногих людей, которые буду рады если притащить домой пустую почтовую коробку из «такого плотного картона».
Optkit: можно ли автоматизировать мою графику?
Выкладываю optkit — программу (написана на PowerShell v1, это значит — под Windows), которая определяет можно ли оптимизировать графику в форматах PNG, GIF, JPEG в указанной папке. При запуске нужно указать папку.
Примерный вывод есть на скриншоте. Выводится сколько удалось сэкономить, для GIF выводится сколько они будут занимать в PNG (если это даст экономию).
Программа использует ряд других программ, которые должны лежать в папке utils, это:
- SuperGIF 1.5 (должен быть «купленным»)
- GIFLite (можно поискать
FTP-поиском), утилита не используетсядля 64-битных ОС - jpegtran
- optipng
- pngout (нужна command line версия)
Моя программа не использует никаких продвинутых техник (например, не пытается избавиться от прозрачных, но не одноцветных участков), может ещё руки дойдут и сделаю.
Дополнено: Харисов подсказывается, что на Bash есть инструмент интереснее — imgcomp и писался явно не пару вечеров, как мой. Кстати, сравнивая две программы (на Bash и PowerShell) можно сделать интересные выводы о читаемости этих языков и их мощности.
SQL-инъекция в штрих-коде?
А вот ещё идея возникла. Распечатываете этот
штрих-код на стикеры, и незаметно клеите их рядом с ценниками в супермаркетах конкурента.Когда в конце рабочего дня будут производить учет товаров
какой-нибудь доброход-товаровед обязательно посветит на негоштрих-код сканером. :)А там написано *’; DROP TABLE products; —*
P.S. Я и сам принимал участие в разработках программ складского учета с применением сканеров штрихкода. И знаю — никто там, естественно, входные данные не проверяет, чаще всего шпарят прям напрямую запросы с динамическими параметрами
в SQL-базу. А теперь вот задумался,прогресс-то не стоит на месте… :)
Забавно, неужели правда сработает?
«Андроид» 2.2.1
У меня вчера «Андроид» на телефоне обновился, выкачав новую прошивку через EDGE (бедняга, попросил бы, я б WiFi включил). В интернетах пишут, что залатали пару дыр, а из того, что я заметил — появился твёрдый знак на клавиатуре.
Дополнение: поправили ошибку с именованием дней недели.
Собираемся менять фотоаппарат
Мыльница
Последние несколько лет я себе на день рождения дарю сотовый телефон, а в этом году, как назло Nexus One меня всем устраивает, даже удивительно. Придётся поменять фотоаппарат.
Пока думаем брать Canon EOS 550D. Подумаем ещё немного и возьмём.
PHP4 без XML-парсера, плюс XPath
Я недавно написал простенький парсер XML для PHP 4.3+, для случаев, когда никакого встроенного парсера XML на хостинге не оказалось.
Весь XPath я, конечно, реализовывать не буду, да мне столько и не надо. В общем, написал класс, который используется в паре VerySimple_XMLParser. Реализованы получение потомков тега, «*», «node()» и «text()». Это всё, но мне хватит.
// Simple XPath for VerySimple_XMLParser
// /
class VerySimple_XMLParser_Tree
{
var $path;
var $counter;
var $xpath;
function VerySimple_XMLParser_Tree()
{
$this->path = array('/');
$this->counter = 0;
$this->xpath = array();
}
function collect($type, $args)
{
$path = implode($this->path);
switch ($type) {
case 'TEXT':
$this->xpath[$path . $this->counter . '/text()/'] = $args;
$this->counter++;
break;
case 'TAGOPEN':
list($name, $attributes) = $args;
$tag = $this->counter . '/' . $name . '/';
$this->xpath[$path . $tag] = $attributes;
$this->counter = 0;
$this->path[] = $tag;
break;
case 'TAGCLOSE':
$this->counter = 1 + (int) array_pop($this->path);
break;
}
}
function halfxpath($path)
{
$keys = array_keys($this->xpath);
$trans = array(
'\/' => '\/\d+\/',
'\*' => '[^\/()]+',
'node\(\)' => '[^\/]+',
);
$filter = strtr(preg_quote($path, '/'), $trans);
$filtered = preg_grep("/^$filter\/$/su", $keys);
$nodes = array();
foreach ($filtered as $key) {
$nodes[$key] = $this->xpath[$key];
}
return $nodes;
}
}
// а вот так это можно использовать:
$xml =<<<XML
<root>
<a>
<b><c>Xa!</c></b>
<b>Hello</b>
</a>
<a name="value"/>
</root>
XML;
$tree = &new VerySimple_XMLParser_Tree();
$sax = &new VerySimple_XMLParser(array(&$tree, 'collect'));
$sax->parse($xml);
echo '<plaintext>';
var_dump($tree->halfxpath('/*/a/b/text()'));
var_dump($tree->halfxpath('/*/a/b/node()'));
var_dump($tree->halfxpath('/*/a/b/*'));
var_dump($tree->halfxpath('/root/a'));Метод для запросов я назвал «halfxpath», намекая, что это не настоящий XPath, а лишь неполноценная эмуляция.
Основная идея, как видно из кода — не парсить XML в дерево, а помещать каждый элемент по специального вида пути, который потом будет проверен на совпадение по регулярному выражению, приготовленному из запроса.
Ярославль
Ярославль — город, входящий в Золотое кольцо России, наверняка, один из красивейших городов России, жаль у меня не было времени в этом убедиться. Надо будет приехать туда летом.
Ранней осенью, в наших климатических условиях редкий город выглядит достойно. Ярославль под зябким осенним дождём выглядит так же неприглядно, как и любой другой российский город в грязи, мокрых листьях под пасмурным солнцем.
Любить окружающую действительность мне в такую погоду трудно, а город, который в такой момент является частью этой действительности — ещё сложнее. Ярославлю — 1000 лет, об этом в городе написано на каждом столбе, но праздника в городе не ощущается.
Я помню празднование наглого тысячелетия в Казани






Я люблю думать, гуляя по улицам
Кажется, в Ярославле всё те же не прополотые корни прошлого, что и в Москве…




То же народное творчество на стенах…


Те же однообразные и одинаковые по всей стране пятиэтажки и старые дворики…




Те же памятники старины…



То же самое разгильдяйство везде — даже на кладбище…


Конечно, может быть я узнал о том, что не в Москве по многочисленным упоминаниям названия города…


Или по реке, разве река Москва течёт так же несуетно?





Может отличаются люди? Или они везде одинаковые?





Если вы ждёте
Он был не рад мне, а я был не рад промокшим ногам, сырости и холоду. В следующий раз, когда приеду, позвоню заранее, может мы ещё понравимся друг другу.
Тонкости heredoc в PHP
В PHP, как и в некоторых других языках (Bash, Perl) есть конструкция heredoc — это способ задать многострочную строку. Посмотрите как удобно, не нужно экранировать кавычки:
// это PHP
$str = <<<STR
Привет, я строка "в кавычках",
'в апострофах'.
STR;Но меня всегда раздражало, что завершающий ограничитель приходится прижимать к левому краю, пробел и табуляция дают ошибку (хотя в Perl относительно недавно разрешили делать отступы для этой конструкции).
Сегодня, в очередной раз раздражаясь по этому поводу, я решил попробовать использовать неразрывные пробелы (Alt Right+Space в раскладке Бирмана), получилось, работает даже в PHP 4.4.4. Подходит, конечно, для исходников в кодировке
Правда, строки внутри, конечно, менять нельзя, но эта конструкция часто используется вместе с HTML, а ему отступы неинтересны.
$str = <<< HTML
<table>
<tr class="row"><td>'Привет'</td></tr>
</table>
HTML;Только не забудьте, что отступы надо делать и в начальной конструкции, и в конечной.
House M.D.
Сериал «Сообщество» мы посмотрели ещё на прошлой неделе, начали «Доктора Хауса». В шестой серии первого сезона, в отражении стеклянной двери смутно видно съёмочную группу.
3G в Ярославле

Ловил два дня 3G в Ярославле. Кстати, да. В номере «Люкс» есть радиоточка!
Bitrix WTF
Я сейчас в Ярославле слушаю доклад по клиентским сертификатам.
Рядом со мной сидит Коля Мациевский, он один из первых в России начал комплексно исследовать вопрос оптимизации загрузки сайтов и владеет сейчас первой в России компанией «WeBo», которая этим занимается. Коле скоро выступать, а пока он ковыряет исходники своего продукта, а точнее плагина, который встраивает упомянутый продукт в CMS «Bitrix».
Причина в том, что внутренний антивирус «Bitrix»
$ll = strlen(bin2hex($this->body))/2;
if($ll > 500)
{
$val = 9;
$r += $val;
$this->resultrules['rulescriptlenghts_sl'] = $val;
return $r;//только одно правило из блока
}Вот эта странная во всех отношениях (почему не просто strlen?) проверка считает вирусным любой
Пасхальное яйцо в Lixil CMS
Сегодня я случайно обнаружил один из сайтов на той CMS и оказалось, что пасхальное яйцо до сих пор работает, его можно увидеть, если послать
Картинку можно увидеть только в IE, так как не выдаётся
data:text/html,<img src="//old.teletrade.ru/?LRPC=90&args={}">Вставлял я этот кусок кода ради теста — найдут ли программисты компании его в коде и смогут ли понять что он делает.
IE9 и его скорость, по сравнению с другими браузерами
Сижу сейчас на семинаре Михаила Черномордикова из Microsoft «HTML5, CSS3 и новый Internet Explorer 9». На экране — известный тест Flying Images, который Михаил демонстрирует в IE9 бета1 и FF 4 (неизвестной) бете.
У IE9, судя по всему сильное преимущество. Я
Скачал FF 4 beta7pre, включил в конфигурации всё, что относится к аппаратному ускорению, потестировал. В общем, Microsoft… вводит нас в заблуждение (как и статья на «Хабре»). FireFox явно впереди, хоть и незначительно.
PHP4 без XML-парсера
Мне тут по работе пришлось решить странную, по нынешним временам задачу — принимать XML в программе на PHP4.3+, где никакого парсера XML может не оказаться. Таковы реалии продукта и среды, где он будет использоваться (это код внешнего проекта). Поэтому мне пришлось написать небольшой парсер, который, правда, расcчитывает, что XML будет
В качестве иллюстрации я использую в коде крайне простую функцию, которая не строит дерево, а просто собирает вызовы в массив, но понятно, что собрать дерево тоже ничего не стоит.Дальше
<?
// Very Simple XML SAX Parser by Evgeny Stepanischev
// /
class VerySimple_XMLParser
{
var $saxCallback;
function VerySimple_XMLParser($saxCallback)
{
$this->saxCallback = $saxCallback;
}
function parse($xml)
{
if (preg_match_all('#<![CDATA[.*?]]>|</?[^>]*>|[^<]+#us', $xml, $matches)) {
foreach ($matches[0] as $match) {
$this->parseThis($match);
}
}
}
function parseThis($match)
{
$calls = array(
'<!--' => 'COMMENT',
'<?' => 'PI',
'<![CDATA[' => 'CDATA',
'<!' => 'DTD',
'</' => 'TAGCLOSE',
'<' => 'TAGOPEN',
);
foreach ($calls as $need => $type) {
if (strpos($match, $need) === 0) {
return $this->parseByType($type, $match);
}
}
return $this->parseByType('OTHER', $match);
}
function parseByType($type, $text)
{
if ($type == 'COMMENT') {
return $this->addChunk($type, substr($text, 4, -3));
}
if ($type == 'CDATA') {
return $this->addChunk('TEXT', substr($text, 9, -3));
}
if ($type == 'OTHER') {
return $this->addChunk('TEXT', $text);
}
if ($type == 'TAGCLOSE') {
$end = strcspn($text, ' >');
return $this->addChunk('TAGCLOSE', substr($text, 2, $end - 2));
}
if ($type == 'TAGOPEN') {
$this->addChunk('TAGOPEN', $this->parseTag($text));
if (substr($text, -2) == '/>') {
$end = strcspn($text, ' >');
return $this->addChunk('TAGCLOSE', substr($text, 1, $end - 2));
}
}
return '';
}
function parseTag($text)
{
$end = strcspn($text, ' />');
$name = substr($text, 1, $end - 1);
return array($name, $this->parseTagAttributes(substr($text, $end)));
}
function parseTagAttributes($text)
{
$nameStart = '(?:[A-Za-z_:]|[^\x00-\x7F])';
$nameChar = '(?:[A-Za-z0-9_:\.-]|[^\x00-\x7F])';
$attrValue = '(?:\'[^\']*\'|"[^"]*")';
if (preg_match_all("/{$nameStart}{$nameChar}*=$attrValue/us", $text, $matches)) {
return $this->parseAttributes($matches[0]);
}
return array();
}
function parseAttributes($rawAttributes)
{
$attributes = array();
foreach ($rawAttributes as $rawAttr) {
list($name, $value) = explode('=', $rawAttr, 2);
if ($value[0] == '"' || $value[0] == "'") {
$value = substr($value, 1, -1);
}
$attributes[$name] = $value;
}
return $attributes;
}
function addChunk($type, $arg)
{
call_user_func($this->saxCallback, $type, $arg);
}
}
// Пример использования
$xml =<<<XML
<!-- комментарий -->
<?xml version="1.0"?>
<root attribute="a.a" v="a">
<v><![CDATA[data]]></v>
<v>data</v>
<v/>
</root>
XML;
// Понятно, что можно написать класс и передать в качестве
// callback в парсер метод объекта, но я для простоты, как пример,
// написал очень простую функцию
function VerySimple_XMLParser_Collector()
{
static $tree = array();
if (func_num_args() == 2) {
$tree[] = func_get_args();
} else {
return $tree;
}
}
$sax = &new VerySimple_XMLParser('VerySimple_XMLParser_Collector');
$sax->parse($xml);
echo '<plaintext>';
var_dump(VerySimple_XMLParser_Collector());
Гостиница «Которосль» в Ярославле
Номер категории «Люкс» в гостинице «Которосль» — это, ребята, сидячая ванна, механические замки, шумный холодильник «Смоленск» (этакий отбойный молоток в ночи), отсутствие халата, зубной щётки, мусорки, сейфа и интернета. Правда мебель чистенькая и новая, хотя и тошнотворная, но я не понимаю почему это называется «Люкс». Чего тут «люксового»?
Добавлено на следующий день: вот так выглядит спальня в номере, обратите внимание на оригинальную конструкцию лампы. Нет, это не реализация идей Тесла по беспроводной передачи электричества, это просто провод обрезан.

Кстати, на конференции ADD, где я сейчас нахожусь, Windows 7 отказалась подключаться к интернету, пришлось на телефоне («Андроид» подключился без проблема и сразу) посмотреть выданный
PHP и UTF-8: пятый этап
Итак, пятый этап. Точнее на этап, он, пожалуй, не тянет, но после этапов 4,5 и 4,6 мне хочется целых чисел.
В самом деле, если простое взятие символа по индексу в строке с фиксированным размером символа имеет сложность O(1), то Я написал небольшие тесты. Замерял три прохода по тексту объёмом 187,5КБ. Проход по строке с однобайтной кодировкой — 0,2 секунды, по строке Так вот, одна из вещей, которой мало кто пользуется — возможность создать в PHP свой итератор. У меня тут не руководство по итераторам, поэтому я ограничусь лишь кодом и примером использования. Основная идея — если мы двигаемся по строке последовательно, Использовать итератор достаточно просто: Так как в итерации сначала вызывается «current», а потом «next» мне показалось странным терять информацию о положении следующего символа, которую мы в «current» уже знаем, так что я передаю её в «next» через защищённое свойство. Список функций (из моего списка используемых функций), которые я перепишу с итератором (или скорость которых увеличится): trim, ltrim, rtrim, wordwrap, strcspn и strspn, а так же некоторые места в коде проекта.Итак, пятый этап
class UtfString implements Iterator
{
protected $str; // строка
protected $idx; // бинарный индекс строки
protected $pos; // UTF-8-индекс
protected $len; // бинарная длина
protected $next; // бинарный указатель на следующий
protected $idx_start; // бинарный индекс откуда стартуем
protected $pos_start; // UTF-8-индекс откуда стартуем
// проверка — байт не является началом символа
protected function isNotBegin($ch)
{
return (ord($ch) & 192) == 128;
}
public function __construct($str, $pos_start = 0)
{
$this->str = $str;
$this->pos = $this->pos_start = $pos_start;
$this->len = strlen($str);
$this->next = null;
if ($pos_start) {
for ($i = 0; $i<$pos_start; $i++) {
$this->idx_start++;
while ($this->isNotBegin($this->str[$this->idx_start])) {
$this->idx_start++;
}
}
$this->idx = $this->idx_start;
} else {
$this->idx = $this->idx_start = 0;
}
}
public function current()
{
$idx = $this->idx;
$out = $this->str[$idx++];
while ($this->isNotBegin($ch = $this->str[$idx])) {
$out .= $ch; // быстрее, чем массив!
$idx++;
}
$this->next = $idx;
return $out;
}
public function key()
{
return $this->pos;
}
public function next()
{
$this->pos++;
if ($this->next) {
$this->idx = $this->next;
$this->next = null;
} else {
for ($this->idx++; $this->isNotBegin($this->str[$this->idx]); $this->idx++);
}
}
public function rewind()
{
$this->idx = $this->idx_start;
$this->pos = $this->pos_start;
}
public function valid()
{
return $this->idx < $this->len;
}
public function __toString()
{
return $this->str;
}
}$str = str_repeat('Привет', 64000);
foreach (new UtfString($str) as $position => $char) {
// …
}
НАМИ
Ездил сегодня ремонтировать обогреватель «AirComfort». Ничего обогреватель, простенький, потому и ломаться там особо нечему, спираль перегорела. Так бывает, повёз менять. Пишу себе заметку на будущее, если ещё сгорит. Замену осуществляет ровно одна организация — «Ремсервис», располагающаяся на территории НАМИ (это центральный
Работает эта печальная организация с 10 до 17 по рабочим дням. С собой надо иметь паспорт и 1000 рублей. С паспортом идём в бюро пропусков, выписываем временный пропуск, по схеме, на третьем этаже находим «Ремсервис». Это организация из трёх человек — принимающей звонки женщины, мастера, который всё ремонтирует и дядьки, который ходит по комнате и разговаривает.
Замена спирали происходит всё в той же печальной комнате, где принимают клиентов и занимает полчаса. Институт находится на ул. Автомоторная, д. 2 (проезд автобусом №123 с метро Речной вокзал).






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