Логи

Я сейчас скажу некоторое количество банальностей.

Раньше, до создания своего сайта, я думал, что когда у тебя небольшой сайт, тебя никто не будет взламывать. Это ведь никому не нужно. Теперь я так не думаю. Если посмотреть логи сайта, то там будет видна куча записей с обращениями на несуществующие страницы. Видно, что боты просто проверяют наличие какого-то стандартного программного обеспечения с известными уязвимостями: a вдруг получится сломать еще один сайт и поиметь с него какого-нибудь профита. Особенно часто любят проверять наличие phpMyAdmin по стандартным адресам. Вывод: не расслабляемся, если что-то и используем, то меняем хотя бы имена.

UPD: Вот, кстати, свежее:

120.107.174.225 - - [27/Sep/2012:17:27:43 +0000] "GET /muieblackcat HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:43 +0000] "GET //index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:44 +0000] "GET //admin/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:44 +0000] "GET //admin/pma/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:45 +0000] "GET //admin/phpmyadmin/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:45 +0000] "GET //db/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:45 +0000] "GET //dbadmin/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:46 +0000] "GET //myadmin/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:46 +0000] "GET //mysql/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:46 +0000] "GET //mysqladmin/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:47 +0000] "GET //typo3/phpmyadmin/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:47 +0000] "GET //phpadmin/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:47 +0000] "GET //phpMyAdmin/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:48 +0000] "GET //phpmyadmin/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:48 +0000] "GET //phpmyadmin1/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:49 +0000] "GET //phpmyadmin2/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:49 +0000] "GET //pma/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:49 +0000] "GET //web/phpMyAdmin/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:50 +0000] "GET //xampp/phpmyadmin/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:50 +0000] "GET //web/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:50 +0000] "GET //php-my-admin/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:51 +0000] "GET //websql/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:51 +0000] "GET //phpmyadmin/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:52 +0000] "GET //phpMyAdmin/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:52 +0000] "GET //phpMyAdmin-2/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:52 +0000] "GET //php-my-admin/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:53 +0000] "GET //phpMyAdmin-2.2.3/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:53 +0000] "GET //phpMyAdmin-2.2.6/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:53 +0000] "GET //phpMyAdmin-2.5.1/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:54 +0000] "GET //phpMyAdmin-2.5.4/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:54 +0000] "GET //phpMyAdmin-2.5.5-rc1/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:55 +0000] "GET //phpMyAdmin-2.5.5-rc2/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:55 +0000] "GET //phpMyAdmin-2.5.5/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:55 +0000] "GET //phpMyAdmin-2.5.5-pl1/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:56 +0000] "GET //phpMyAdmin-2.5.6-rc1/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:56 +0000] "GET //phpMyAdmin-2.5.6-rc2/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:56 +0000] "GET //phpMyAdmin-2.5.6/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:57 +0000] "GET //phpMyAdmin-2.5.7/index.php HTTP/1.1" 404 - - "-"
120.107.174.225 - - [27/Sep/2012:17:27:57 +0000] "GET //phpMyAdmin-2.5.7-pl1/index.php HTTP/1.1" 404 - - "-"
Source map

Итак, у вас очень много JavaScript-кода. А значит, вы его сжимаете перед тем, как отдавать клиенту. Наверняка даже используете YUI Compressor или Google Closure Compiler. А может, вы пишете свой client-side код на чем-нибудь модном: на Dart или CoffeeScript? В любом случае вы наверняка сталкивались с проблемой отладки и поиска ошибки в браузере. Попробуй угадать, почему в 3-й строчке на 100501 позиции значение переменной aAz вдруг стало undefined. А ведь до компиляции скрипта всё работало как надо! Я в таких случаях начинаю добавлять в код много инструкций console.log, чтобы хоть как-то проследить процесс выполнения кода.

Ну что ж, у меня для вас хорошие новости. В Google знают о ваших проблемах и даже придумали решение — source map. Идея проста: компилятор должен создавать специальный файл с информацией о соответствии скомпилированного кода не скомпилированному, а браузер должен брать информацию из этого файла и показывать красоту вместо абракадабры.

Расскажу, какие шаги мне пришлось проделать, чтобы source map заработал в этом блоге. Сразу предупреждаю, что на рабочем сайте вы его не найдете, он существует только на моей локальной машине, но вы можете попробовать собрать всё из исходников сами.

  1. Включаем генерацию source map в Google Closure Compiler. Для этого используется опция компилятора --create_source_map=./script.js.map.
  2. Файл получили. Но в нем скорее всего прописаны неправильные пути к исходным файлам, особенно если ваш корень сервера не совпадает с корнем проекта. Придется их поправить, например, вот такой unix-командой: sed -i 's/"static\//"\//g' static/js/script.js.map.
  3. Чтобы браузер знал о наличии файла с картой, нужно добавить комментарий в конец скомпилированного js-фала: echo "//@ sourceMappingURL=script.js.map" >> static/js/script.testing.js.
  4. Ну и последний этап, нужно включить поддержку source map в Google Chrome. Для этого открываем Developer Tools (Ctrl+Shift+I), нажимаем на кнопку настроек в правом нижнем углу и ставим галочку напротив «Enable source maps».

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

А теперь ложка дегтя. Она одна, но зато большая: поддержка. Как это обычно бывает с новыми технологиями, не все успевают или не все хотят реализовывать всякие экспериментальные поделки. Поэтому мы будем довольствоваться только одним браузером — Google Chrome. Ребята из Mozilla тоже трудятся над поддержкой source maps, но работающего результата у них пока нет. А вот запрос «ie source maps» ожидаемо выдает 0 релевантных результатов.

Та же беда с Source Maps и в языках и компиляторах. Я нашел поддержку только в Google Closure Compiler и Dart, а так же зачатки в CoffeeScript. Если знаете еще кого-нибудь, кто поддерживает — добро пожаловать в комментарии.

Скажу, что спецификация так же предусматривает source map и для CSS файлов, но я пока не тестировал эту возможность.

Ну и напоследок пара ссылок: на спецификацию и на обзор.

last.fm

Как-то совершенно неожиданно весьма ожидаемо счетчик прослушиваний в last.fm перевалил за 100000. Это большое количество песен я прослушал за 5 лет, начиная с 2007. Честно говоря, я не сразу понял, зачем этот сервис вообще нужен, и только где-то через год я обнаружил бесплатное персональное радио. А может, я и сразу его обнаружил, но скорости тогдашнего интернета не позволяли им полноценно пользоваться. В любом случае, где-то через год я стал активным слушателем их радио. И очень расстроился, когда они объявили, что халявы больше не будет. Так расстроился, что даже купил себе подписку на несколько месяцев. К сожалению, last.fm принимает только PayPal, которого у меня как не было, так и нет, я не стал больше искать кого-нибудь, кто поможет мне оплачивать их услуги. И в дальнейшем стал использовать last.fm только для статистики. Ну или как вспоминалку названия той чудесной песенки, что я слышал пару дней назад и которая до сих пор крутится у меня в голове.

Кстати, о статистике. Мой персональный all-time top 10 исполнителей:

  1. The Beatles
  2. Pink Floyd
  3. Porcupine Tree
  4. Enigma
  5. Mike Oldfield
  6. Queen
  7. Akira Yamaoka
  8. David Bowie
  9. Björk
  10. Sia

И (тадам!) top 10 песен:

  1. Pink Floyd — The Great Gig in the Sky
  2. Pink Floyd — Money
  3. Pink Floyd — Time
  4. Pink Floyd — Brain Damage
  5. Pink Floyd — Eclipse
  6. Pink Floyd — On the Run
  7. Pink Floyd — Us and Them
  8. Pink Floyd — Any Colour You Like
  9. Pink Floyd — Wish You Were Here
  10. Pink Floyd — Comfortably Numb

Похоже, что раньше ничего кроме Pink Floyd и их Dark Side of the Moon я не слушал. Что ж, пусть так, я до сих пор считаю это их творение одним из самых лучших.

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

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

Какой-то невнятный пост получился. Придется мораль написать отдельно, иначе опять никто ничего не поймет.

TL;DR: слушайте хорошую музыку и любите друг друга.

Просто так

Что-то давно я ничего не постил в блог. Не хорошо получается. Поэтому расскажу вкратце, чем же таким я занимался всё это время. Во-первых, я переписываю javascript часть блога с jQuery на Google Closure. Почему? Потому что таким образом значительно уменьшится размер и количество js-файлов (в идеале, остаться должен только один). Ну и плюс к этому лучше проникаюсь концепциями, скрытыми в архитектуре этого фреймворка.

Во-вторых, поставил себе TeamCity и пытаюсь разобраться, как применить CI к разработке на Haskell. В конце концов, хотелось бы получить автоматическое обновление сайта после обновления ветки production на GitHub.

А еще недавно случился день программиста. По этому поводу я посетил новый офис Prontosoft и полюбовался, как у них теперь хорошо:

Prontosoft

Prontosoft

Обновление блога

Развитие блога не прекращается ни на минуту (ну почти). На этот раз я сделал meta-теги в заголовке страницы для Facebook. Теперь, если добавить ссылку на мой блог, то в блок в Facebook попадет начало поста. Кстати, совершенно внезапно, вконтактик тоже правильно стал отображать описание, что не может не радовать.

В очередной раз впечатлился выразительностью Хаскеля: cколько всего можно написать одной строчкой. Вот, например, кусочек из свеженаписанного:

getDescription :: Node -> Text
getDescription = maybe emptyDescription 
  (until (not . T.null) (\_ -> emptyDescription) . getDescription') . 
  findChild (checkMainDiv . current) . fromNode

getDescription' :: Cursor -> Text
getDescription' = cutDescription . transformDescription .
  T.intercalate " " . map nodeText . filter checkParagraph .
  maybe [] siblings . firstChild

Можете сравнить с примерной калькой на JavaScript:

var getDescription_ = function (cursor) {
    var fc = firstChild(cursor)
    return cutDescription(transformDescription(
        (fc ? siblings(fc) : []).filter(checkParagraph).map(nodeText).join(" ")
    ));
}
var getDescription = function (node) {
    var mainDiv = findChild(function (cursor) {
        return checkMainDiv(current(cursor))
    }, fromNode(node));
    return mainDiv ? getDescription_(mainDiv) || emptyDescription : emptyDescription;
}

Хотя да, и в JS есть своя прелесть.

← СтаршеМоложе →