...

суббота, 17 августа 2013 г.

Perl6 — Обработка исключений

1. Особенности работы с переменными и литералами в Perl6

2. Perl6 — Операции над переменными, анонимные блоки

3. Perl6 — Условные операторы, циклы

4. Perl6 — Работа с функциями

5. Perl6 — Классы

6. Perl6 — Ввод-вывод, модули

7. Perl6 — Комментарии, пробельные символы, скобки

8. Perl6 — Перегрузка операторов

9. Perl6 — Работа с типами данных

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


И так, имеем следующий кусок кода:



sub Func($a)
{
my $temp = $a*2;
}

Func "Test";


Как вы уже могли догадаться, мы получим исключение при попытке получить из строки «Test» десятичное число.

Чтобы добавить обработчика исключений мы должны добавить следующую конструкцию:



sub Func($a)
{
my $temp = $a*2;
say "Test work";

CATCH
{
default
{
say "Something is wrong!";
}
}
}

Func "Test";
say "Another test work";


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



Something is wrong!
Another test work




Иначе говоря, блок, в котором происходит исключение останавливает свою работу (и всетаки немного неправильно так говорить, но об этом поговорим потом), и начинается работа блока CATCH, в которой производится вывод строки Something is wrong. После выполнения блока CATCH скрипт продолжает выполнение начиная со следующей команды, идущей за блоком, в котором произошло исключение. Именно поэтому мы не видим на экране надписи «Test work».

Фактически, наш блок CATCH является обычным «свитчем» И мы можем добавить следующее:



sub Func($a)
{
my $temp = $a*2;
say "Test work";

CATCH
{
when X::Syntax::Name::Null
{
say "I will never say it =(";
}
default
{
say "Something is wrong! "~$_.WHAT.gist;
}
}
}

Func "Test";
say "Another test work";




Однако текст для выбранного нами исключения гласит «Я никогда не скажу этого». Это потому что в нашем случае в функции не выполняется таких действий, в которых бы возникло данное исключение. Чтобы всетаки понять какое же исключение нам попадается, я добавил "$_.WHAT.gist". При входе в блок CATCH в переменную $_ заносится пойманный нами объект исключения. Потом мы берем его type object'а и приводим его к строке (.gist функция для дебага, позволяющая посмотреть внутренности объекта, описывать её здесь не буду).

Таким образом мы теперь получаем такой вывод:

Something is wrong! (X::Str::Numeric)
Another test work




Теперь мы знаем какое именно исключение словили. Копируем его имя и идем смотреть в Синопсах описание нашего исключения. (Вот прямая ссылка на неше исключение). После чего мы можем добавить ещё один блок when:

sub Func($a)
{
my $temp = $a*2;
say "Test work";

CATCH
{
when X::Syntax::Name::Null
{
say "I will never say it =(";
}
when X::Str::Numeric
{
say "String convertation error!";
}
default
{
say "Something is wrong! "~$_.WHAT.gist;
}
}
}

Func "Test";
say "Another test work";


В результате чего увидем вывод:



String convertation error!
Another test work


Естественно мы можем через переменную $_ обращаться ко всем полям объекта. Поля опять же смотрим в описании исключения.


-Уфф, что-то я устал охотиться, может ловушек поставим, да передохнём?




Есть так же специальный блок try {}, внутри которого есть «невидимый» блок CATCH, и если внутри этого блока произойдет исключение, то работа скрипта не остановится, и выполнение продолжится со следующей инструкции после этого самого блока. Таким образом можно просто игнорировать все исключения которые нам попадутся.

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


-А если попытается сбежать?




Вполне возможен вариант, что во время обработки одного исключения мы можем получить ещё одно. Однако стоит отметить, что блок when или default, в котором происходит обработка являются самыми обычными блоками, внутрь которых опять же можно поместить блок CATCH:

sub Func($a)
{
try
{
my $temp = $a*2;
say "Test work";

CATCH
{
when X::Str::Numeric
{
die "test";
CATCH
{
default
{
say "Another die action";
}
}
}
default
{
say "Something is wrong! "~$_.WHAT.gist;
}
}
}
}

Func "Test";
say "Another test work";


-А давай попытаемся приручить парочку исключений?




Пожалуй у нас найдется парачка способов, как можно самостоятельно создать исключение:

Первый способ это как вы уже заметили оператор 'die':



{
die "I'm diying...";
CATCH
{
default
{
say "I will save you!";
}
}
}


Второй способ — это вызов метода throw:



{
X::Str::Numeric.throw;
CATCH
{
default
{
say "More exception!?!";
}
}
}


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


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


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends: 'You Say What You Like, Because They Like What You Say' - http://www.medialens.org/index.php/alerts/alert-archive/alerts-2013/731-you-say-what-you-like-because-they-like-what-you-say.html


Используете ли вы оператор нестрогого сравнения ("==") в PHP?


сегодня в 22:13


Из-за того, что в PHP при сравнении строк оператор "==" пытается сначала преобразовать их в числа [1][2] (даже, если оба операнда — строки), результат порой может оказаться неожиданным:

<?php
var_dump('123' == ' 123'); // true
var_dump('1e3' == '1000'); // true
var_dump('+74951112233' == '74951112233'); // true
var_dump('00000020' == '0000000000000000020'); // true
var_dump('0X1D' == '29E0'); // true
var_dump('0xafebac' == '11529132'); // true
var_dump('0xafebac' == '0XAFEBAC'); // true
var_dump('0xeb' == '+235e-0'); // true
var_dump('0.235' == '+.235'); // true
var_dump('0.2e-10' == '2.0E-11'); // true
var_dump('61529519452809720693702583126814' == '61529519452809720000000000000000'); // true в php < 5.4.4




Подобное сравнение также используется и в некоторых функциях. Например, в in_array:

<?php
$_GET['fileId'] = '0X1D';
// ...
$privateFileIds = array('29E0');
if (in_array(@$_GET['fileId'], $privateFileIds))
{
print 'Access deny';
exit;
}

// Выведет "Access deny", т.к. параметр "$strict" у функции "in_array" по умолчанию равен "false"




Решением проблемы может служить использование строгой проверки на соответствие:

// Использование оператора идентичности совместно с явным приведением операндов к строковому типу
(string) $aaa === (string) $bbb;

// Использование функции "strcmp"
strcmp($aaa, $bbb) == 0;

// Использование параметра "$strict" со значением "true" в соответствующих функциях
in_array((string) $aaa, $array, true);




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


Используете ли вы для сравнения строк нестрогую проверку на соответствие (оператор "==", параметр "$strict" со значением false и т.п.)?





















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


Проголосовало 56 человек. Воздержалось 17 человек.







Developers, stick with Russians – work in London




Переводы с

карты на карту


Переводы

через QR-Код


Новая функция

«Мой контроль»




Возьми Lumia 925 на тест-драйв сейчас.




Впечатляющие возможности

в стильном тонком корпусе из металла



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


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends: 'You Say What You Like, Because They Like What You Say' - http://www.medialens.org/index.php/alerts/alert-archive/alerts-2013/731-you-say-what-you-like-because-they-like-what-you-say.html


3D сканер от MakerBot поступит в продажу уже на следующей неделе


Компания MakerBot достаточно известна на рынке 3D печати. Ее принтер Replicator стал популярным очень быстро, вследствие не очень высокой цены и относительно простой эксплуатации. Кроме того, компания не так давно сообщила о намерении выпустить на рынок и 3D сканер, при помощи которого можно было бы получать модель небольшого реального объекта, и эту же модель отправлять на 3D-принтер, для создания копии (не такой качественной, как оригинал, может быть, но тем не менее). И теперь этот сканер готов, и будет представлен на следующей неделе.


Сканер получил название Digitizer, изображен он на анонсной фотографии. Как и говорилось выше, Digitizer позволяет отсканировать объемный объект, получить компьютерную модель (CAD), и при необходимости отправить файл на «печать». Пока что о модели высокого разрешения и речи не идет. Но то, что получается в результате, вполне заслуживает похвалы разработчикам. Ниже показан оригинальный объект, его модель, и копия объекта, отпечатанная на принтере.



Стоит отметить, что ПО сканера позволяет исправлять погрешности изображения, используя цифровую«магию».



Все это — результаты работы команды MakerBot, и результаты эти, как видим, неплохие. К слову, модель можно распечатывать в разном масштабе. В качестве примера показаны сережки, «напечатанные» на 3D-принтере, в качестве модели для них служила фигурка сиамской кошки.



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


Кстати, вот видео работы прототипа устройства, показанного на мартовской конференции MakerBot:



Via MakerBot


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends: 'You Say What You Like, Because They Like What You Say' - http://www.medialens.org/index.php/alerts/alert-archive/alerts-2013/731-you-say-what-you-like-because-they-like-what-you-say.html


Дайджест интересных материалов из мира веб-разработки и IT за последнюю неделю №70 (11 — 17 августа 2013)

Предлагаем вашему вниманию очередную подборку с ссылками на новости, интересные материалы и полезные ресурсы.





Горячая семерка


JavaScript уверенно продолжает своё шествие и теперь настал черёд железа. . Встречаем Tessel – микроконтроллер, программируемый на JavaScript

Предлагаем вашему вниманию обзорную статью, где автор в пяти пунктах пытается рассказать об основных возможностях, которые предоставляет вебу HTML5. Кстати, адрес www.w3.org/TR/html/ с недавних пор ведет не на XHTML 1.0, как много лет до сих пор, а на HTML5.0

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

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







Telegram Messenger



Telegram Messenger — первый проект американской компании Павла Дурова. Приложение является бесплатным и доступно для загрузки в App Store. Еще один небольшой обзор плюс дайджест мобильных мессенджеров

Наверное, все успели оценить функциональность песочницы CodePen. Предлагаем вашему вниманию подборку любимых демо Криса Койера, который и является создателем этого замечательного сервиса

У Google появилась информационная страничка, где подробно рассказано о работе и создании Street View — сервисе, которым периодически пользуется наверное каждый из нас

Веб-разработка




CSS




JavaScripts




Браузеры




Новости




Сервисы




Демо




Сайты с интересным дизайном и функциональностью




Дизайн




Подборка бесплатных дизайнерских печенек







Занимательное


Дайджест за прошлую неделю.

Материал подготовили dersmoll и alekskorovin


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends: 'You Say What You Like, Because They Like What You Say' - http://www.medialens.org/index.php/alerts/alert-archive/alerts-2013/731-you-say-what-you-like-because-they-like-what-you-say.html


ICANN отклонил идею Google о доменах без точки

image

ICANN проголосовал против возможности создания доменных имён без точки, положив конец идее Google о доменах http://search, http://app, http://blog и http://cloud, пишет The Verge.


Google хотел, чтобы такие домены перенаправляли пользователей на определённый ими же сайт через «новый технический стандарт», на разработку которого компания потратила несколько месяцев. Например, Google хотел, чтобы по запросу http://search открывалась поисковая система, выбранная пользователем — будь то Google, Bing, Yahoo или какая-либо ещё.


Аналогичным образом, если бы идея Google была реализована, http://blog направлял бы пользователя на выбранную им блог-платформу, в то время как http://cloud делал бы то же самое для облачных сервисов, а http://app — для магазинов мобильных и десктопных приложений.


В своей резолюции, принятой на этой неделе, ICANN заявил, что введение доменов без точки будет представлять существенные риски безопасности и стабильности. Отказ от доменов без точки в принципе неудивителен, учитывая нерешительность ICANN в изменении статус-кво.


Хотя организация говорит о планах запустить почти 2000 новых доменных имён, процесс идёт относительно медленно. Наиболее значительные изменения в этом году произошли в июле, когда ICANN запустил четыре домена верхнего уровня: .شبكة («веб» по-арабски), .游戏 («игра» по-китайски), .онлайн и .сайт.


Между тем, Google также подал заявки на .search, .app, .blog, .cloud и .map, Amazon подал заявки на .book и .amazon, но ICANN всё ещё не рассмотрел запросы на эти домены.


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends: 'You Say What You Like, Because They Like What You Say' - http://www.medialens.org/index.php/alerts/alert-archive/alerts-2013/731-you-say-what-you-like-because-they-like-what-you-say.html


[Опрос] Пользуетесь ли вы нелицензионным контентом?


сегодня в 17:45


На волне очередного спора про копирайт на Хабре и ярой позиции «защитников копирайта» мне интересно выяснить, сколько абсолютно честных и правопослушных пользователей, которые пользуются только лицензионными продуктами. Сюда относится всё:



— Книги (и их сканы)

— Фильмы

— ПО/Игры

— Музыка


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


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





Developers, stick with Russians – work in London




Переводы с

карты на карту


Переводы

через QR-Код


Новая функция

«Мой контроль»




Возьми Lumia 925 на тест-драйв сейчас.




Впечатляющие возможности

в стильном тонком корпусе из металла



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


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends: 'You Say What You Like, Because They Like What You Say' - http://www.medialens.org/index.php/alerts/alert-archive/alerts-2013/731-you-say-what-you-like-because-they-like-what-you-say.html


Небольшой опрос об операционных системах


сегодня в 17:21


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



Developers, stick with Russians – work in London




Переводы с

карты на карту


Переводы

через QR-Код


Новая функция

«Мой контроль»




Возьми Lumia 925 на тест-драйв сейчас.




Впечатляющие возможности

в стильном тонком корпусе из металла



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


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends: 'You Say What You Like, Because They Like What You Say' - http://www.medialens.org/index.php/alerts/alert-archive/alerts-2013/731-you-say-what-you-like-because-they-like-what-you-say.html


[unable to retrieve full-text content]


Методы анонимности в сети. Просто о сложном



«Бывают наивны, как малые дети,

Те, кто верит в анонимность в интернете».

М. Сандомирский

Привет, хабраюзеры!


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

Чтобы было проще, разделим анонимность в Интеренте на два направления:



  • «Социальная анонимность» — это то, что человек сам осознанно или неосознанно рассказывает о себе в Сети.

  • «Техническая анонимность» — когда утечка деанонимизирующих данных связана с используемыми техническими средствами и приложениями.




Мы сконцентрируемся именно на Технической анонимности.

Прокси-серверы




Глобально, когда говорят прокси-сервер, то имеют в виду что-то, выступающее посредником между клиентом и адресатом.

В разрезе же обеспечения анонимности прокси-серверы бывают:


  • HTTP-(веб)-прокси-серверы. Такие серверы пропускают через себя только HTTP-траффик, по умолчанию добавляя в передаваемый траффик данные о применении прокси;

  • SOCKS-прокси-серверы. В отличие от HTTP-прокси-серверов, SOCKS передаёт всю информацию, ничего не добавляя от себя. Протокол SOCKS находится на сеансовом уровне модели OSI, этим достигается независимость от высокоуровневых протоколов: HTTP, FTP, РОРЗ и др., что и позволяет SOCKS пропускать через весь траффик, а не только HTTP;

  • CGI-прокси или «анонимайзеры», реализуемые с помощью скриптов на веб-сервере и представляющие клиенту веб-страницу, где он вводит адрес ресурса. После открывается страница запрошенного сайта, но в адресной строке браузера виден адрес CGI-прокси.




Схему работы прокси-серверов вы видите на картинке, тут всё просто:


Плюсы прокси-серверов:



  • прокси дешевы, в сети можно найти много бесплатных прокси.




Минусы прокси-серверов:


  • надо доверять прокси-серверу;

  • для http-прокси надо фильтровать HTTP-заголовки: «HTTP_X_FORWARDED_FOR: client, ip1...», HTTP_VIA, HTTP_FORWARDED и др.;

  • никакие протоколы прокси НЕ поддерживают шифрование между HTTP/SOCKS/Elite/Anonymous-прокси и клиентом. А SSL-прокси означает лишь то, что клиент может работать с https-ресурсами;

  • цепочки прокси неэффективны: "Привет Proxy1, отправишь моё сообщение:«forward to Proxy3; forward to Proxy4; forward to encrypted.google.com/c8e8df895c2cae-что-нибудь-ещё-здесь-зашифрованное-166baf' для Proxy2?» Спасибо!;

  • необходимость настройки прокси-сервера для каждого приложения либо использование отдельных программ-соксификаторов, например, Proxifier.




VPN/SSH




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

Схема работы VPN показана на картинке:



В настоящее время коммерческими провайдерами предлагаются следующие протоколы VPN:


  • PPTP – используется наиболее широко, быстрый, легко настраивается, однако считается «наименее защищённым» по сравнению с остальными;

  • L2TP + IPSec. L2TP обеспечивает транспорт, а IPSec отвечает за шифрование. Данная связка имеет более сильное шифрование, чем PPTP, устойчива к уязвимостям PPTP, обеспечивает также целостность сообщений и аутентификацию сторон;

  • OpenVPN – открытый и безопасный протокол, требует отдельного клиента для подключения;

  • SSTP – наиболее защищённый протокол, использующий SSL 3.0 со всеми его плюсами, в частности, это позволяет обходить многие блокировки VPN на уровне провайдера.




Практически все коммерческие VPN-провайдеры предлагаю выбор из двух протоколов: OpenVPN и PPTP. Реже предлагается протокол L2TP+IPSec. И совсем единицы предлагают протокол SSTP.

Отдельно стоит отметить сервисы, предоставляющие «DoubleVPN», когда перед тем, как выйти в Интернет, траффик проходит 2 разных VPN-сервера в разных странах, или даже «QuadVPN», когда используется 4 сервера, которые пользователь может выбрать сам и расположить в произвольном порядке.

Любопытное исследование, касающееся анонимности и надёжности коммерческих VPN-серверов, было проведено ресурсом torrentfreak.com: torrentfreak.com/vpn-services-that-take-your-anonymity-seriously-2013-edition-130302

VPN-провайдерам были заданы вопросы:


  • Храните ли вы журналы, позволяющие вам или третьим лицам сопоставить ip-адрес или временную отметку с вашим клиентом? Если да, то какие данные вы храните?

  • Под какой юрисдикцией работает ваша компания, и при каких обстоятельствах вы раскроете данные третьей стороне?

  • В случае, если вы получите DMCA-уведомление или его европейский аналог, что вы с ним сделаете?

  • С какими платежными системами Вы работаете, и как они связаны с учетными записями пользователей?




Резюмируя, стоит отметить, что большинство VPN-провайдеров в своих ответах единодушны: «Журналы не хранятся, а если и хранятся, то очень недолго, по ним вычислить абонента нельзя. На нас очень трудно надавить и заставить выдать хоть что-то». Разумеется, других ответов от сервисов, главной целью которых является обеспечения анонимности пользователей, ожидать не приходится.

Плюсы VPN/SSH:



  • быстро и удобно, не надо отдельно настраивать приложения.




Минусы VPN/SSH:


  • нужно доверять VPN/SSH-серверу/провайдеру.




Отмечу, что большинство тематических дополнений для браузеров и «программ для анонимности» используют в своей основе именно прокси-серверы и VPN-серверы для скрытия ip-адреса клиента.

Tor. Великий и ужасный




О Tor говорилось уже много, но я попытаюсь рассказать просто :)

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

Сейчас Tor — это 10 авторитетных (управляющих) узлов, около 4200 узлов-посредников, в том числе примерно 900 выходных узлов.

На картинке упрощённая схема работы Тоr



Отмечу, что обратно траффик идет в открытом виде, на выходном узле он зашифровывается временным симметричным ключом и передается по цепочке (да-да, непосредственно сам траффик шифруется на симметричных ключах, а эти ключи шифруются уже на ассиметричных ключах).

Тоr ругают потому, что требуют от него слишком многого: безопасно передавать в сеть траффик любых приложений, защиты от глобального наблюдателя, конфиденциальности передаваемых данных и пр. Но он решает главную задачу при своей модели угроз: достаточно высокий уровень анонимности клиента при передаче только http-траффика при соблюдении всех обязательных правил: www.torproject.org/download/download-easy.html.en

Плюсы Tor:



  • высокая степень анонимности клиента при соблюдении всех правил;

  • простота использования (скачал Tor Browser Bundle, запустил и пользуйся).




Минусы Tor:


  • выходной траффик прослушивается;

  • низкая скорость;

  • наличие управляющих серверов.




На одном из форумов я нашёл опрос, касающийся Tor. Количество опрошенных не говорит о достоверности результатов, однако победивший ответ весьма правильный :)



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

I2P




Про I2P было сказано много слов, буду лаконичен и постараюсь объяснить все наглядно.

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

В I2P есть два главных понятия:


  • «туннель» – это временный однонаправленный путь через некоторый список узлов. Туннели бывают входящие и исходящие;

  • «сетевая база NetDb», которая в той или иной мере распределена по всем клиентам I2P. Её цель – хранение информации о том, как клиенту соединиться с определенным адресатом.




База NetDb хранит в себе:


  • RouterInfos – контактные данные роутеров (клиентов), используются для построения туннелей (упрощая, они представляют собой криптографические идентификаторы каждого узла);

  • LeaseSets – контактные данные адресатов, используются для связи исходящих и входящих туннелей.




На начало 2013 года I2P включала в себя 25.000 роутеров и 3.000 LeaseSets.

Расскажу про алгоритм взаимодействия узлов:

Шаг первый. Узел «Kate» строит исходящие туннели. Она обращается к NetDb за данными о роутерах и строит туннель с их участием.



Шаг второй. «Boris» строит входной туннель аналогично тому, как и строится исходящий туннель. Затем он публикует свои координаты или так называемый «LeaseSet» в NetDb (здесь отметьте, что LeaseSet передается через исходящий туннель).



Шаг третий. Когда «Kate» хочет оправить сообщение «Boris’у», она запрашивает в NetDb LeaseSet «Boris’а». И по исходящим туннелям пересылает сообщение к шлюзу адресата.



У I2P есть возможность выхода в Интернет через специальные Outproxy, но они неофициальные и по совокупности факторов даже хуже выходных узлов Тоr. Разработчики I2P говорят: «Хотите Интернет – используйте Тоr».

Плюсы I2P:



  • высокая степень анонимности клиента;

  • полная децентрализация, что ведёт к устойчивости сети;

  • конфиденциальность данных: сквозное шифрование между клиентом и адресатом.




Минусы I2P:


  • низкая скорость;

  • «свой Интернет».




Подробно об I2P, в том числе и о механизмах защиты, а с ними у I2P всё хорошо, я тоже расскажу в следующих статьях цикла.

Иные средства




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

Отдельным интересным примером анонимных сетей являются сети, построенные на основе Wi-Fi. Тогда как при традиционном подходе транспортные функции любой анонимной сети выполняет Интернет, использование беспроводных решений позволяет достичь независимости от Интернет-провайдеров:

Заключение




В заключение приведу цитату с главной страницы проекта I2P: «У анонимности нет однозначного порога, после которого можно расслабиться — мы не пытаемся создать нечто «абсолютно анонимное», но работаем над тем чтобы атаки на такую сеть становились бы всё более и более «дорогими» для злоумышленников».

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

PS. Если в комментариях увижу желание людей, то в следующих статья мы поговорим о:

1. Том, как с технической точки зрения работают Tor, I2P и о разнице между SOCKS 4, 4a, 5 с точки зрения анонимности.

2. Плюсах и минусах комбинирования Tor и VPN и о других, менее популярных, и даже экзотических схемах анонимности.

3. Конкретных утечках деанонимизирующих данных.

Также задавайте вопросы, высказывайте комментарии, с удовольствием отвечу на них. Спасибо!


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends: 'You Say What You Like, Because They Like What You Say' - http://www.medialens.org/index.php/alerts/alert-archive/alerts-2013/731-you-say-what-you-like-because-they-like-what-you-say.html


Stack: сканер для стопок бумаги


сегодня в 14:34



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



Сканер Stack должен помочь компаниям оцифровать большое количество документов, которое не погружается ни в какие лотки. Такое устройство можно оставить на ночь в офисе — и оно будет спокойно работать.


Конструкция аппарата показана на иллюстрациях: толщина сканера составляет всего 5 см.






Ямамото сейчас ищет компанию, которая могла бы воплотить в жизнь его идею. Кроме того, проект нуждается в некотором совершенствовании: в частности, «загребающие» бумагу колёсики должны работать идеально, тут не обойтись от экспериментов с различными материалами.





Developers, stick with Russians – work in London




Переводы с

карты на карту


Переводы

через QR-Код


Новая функция

«Мой контроль»




Возьми Lumia 925 на тест-драйв сейчас.




Впечатляющие возможности

в стильном тонком корпусе из металла



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


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends: 'You Say What You Like, Because They Like What You Say' - http://www.medialens.org/index.php/alerts/alert-archive/alerts-2013/731-you-say-what-you-like-because-they-like-what-you-say.html


[Из песочницы] Как я нашел уязвимость на phpclub.ru

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


С чего все начиналось



А все началось с того, что я перешел с Debian семейства к семейству RHEL. Примерно неделю назад я первый раз своими руками(не могу сказать что на Ubuntu это было своими руками) поднял сервер для разработки проекта. Я своими руками правил конфиги nginx, apache, php — раньше на Ubuntu все ставилось в пару команд и работало само. Впрочем правя конфиги я стал лучше понимать, как оно там все работает. Наверное это меня и подтолкнуло к мысли о memcached.
Поиск цели



Сначала я конечно проэкспериментировал(поставил memcached из rpm и забыл) на своей машине и не был удивлен результатом, так как сама технология подразумевает масштабирование серверами. Но я сильно сомневался, что кто-то оставит такую дыру в реальном проекте. Но мне ничто не мешало проверить это. В качестве сканера портов я использовал nmap. Да простит меня НЛО первым в очереди был habrahabr.ru, но он достойно прошел испытание, а вот попытка номер 4:


11211 порт открыт. К действию



Я написал маленький скрипт на локальной машине и успех:



Малость доработав скрипт:

Вот и он


$t= new Memcached ();
$t->addServer('phpclub.ru', 11211);
$z=$t->getAllKeys();
foreach($z as $k=>$v){
var_dump($t->get($v));
echo $v,'---',$k,"\n";
}





Был получен очень перспективный для хакера результат: все данные были сериализованны. Я принялся анализировать данные, в них мне удалось распознать кеш для меню раздела faq.

А вот и он:

linktracking|i:0;bookmarks|a:5:{i:0;s:11:"((Каталог))";i:1;s:13:"((Изменения))";i:2;s:20:"((НовыеКомментарии))";i:3;s:16:"((Пользователи))";i:4;s:27:"((Регистрация Регистрация))";}bookmarklinks|a:5:{i:0;s:7:"katalog";i:1;s:10:"izmenenija";i:2;s:16:"novyekommentarii";i:3;s:12:"pol_zovateli";i:4;s:12:"registracija";}bookmarksfmt|s:157:"ўўКаталог ==КаталогЇЇ | ўўИзменения ==ИзмененияЇЇ | ўўНовыеКомментарии ==НовыеКомментарииЇЇ | ўўХакИрФсимагущий ==рулит!!!ЇЇ | ўўРегистрация ==РегистрацияЇЇ";show_comments|a:1:{s:24:"qhelp/HowToDisplayErrors";i:0;}'




Честно-честно, он прямо вот так и выглядел! Любые совпадения считать случайностью.

А вот как выглядит страничка с таким кешем:



А что дальше?



А что не происходило дальше и как я не применял магические методы toString и destruct рассказано не будет, мораль не в этом ;)

Естественно, я сразу попытался выйти на связь с админом, сообщил об уязвимости и на данный момент она закрыта.

Мораль:

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


И не надейтесь на то, что ваш ip(даже без привязанного к нему домена) адрес не просканируют.



Сотни джедаев habrauser'ов уже в пути, а за ними и армия клонов ботов.

P.S.

И кто знает сколько еще велосипедов построено на просторах интернета и сколько из них закрыли доступ к memcached с внешних ip…

Кто знает…


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends: 'You Say What You Like, Because They Like What You Say' - http://www.medialens.org/index.php/alerts/alert-archive/alerts-2013/731-you-say-what-you-like-because-they-like-what-you-say.html


Реализация выборки, кэширования и отрисовки фотографий на карте в фото-сервисе gfranq.com

Я являюсь .NET разработчиком стартапа, фото-сервиса http://gfranq.com/ и в данной статье решил описать как была реализована функциональность выборки и отображения фотографий на определенном участке карты, как и обещал в предыдущей статье.


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


Итак, в данной статье будут затронуты следующие проблемы:



  1. Хранение и выборка фотографий из БД и помещение их в серверный кэш (SQL, C#).

  2. Загрузка необходимых фотографий на стороне клиента и помещение их в клиентский кэш (JavaScript).

  3. Перерасчет фотографий, которые нужно скрыть или отобразить при каждом изменении окна просмотра (JavaScript).






Серверная часть




Были придуманы следующие способы выборки и хранения геоинформации в БД:


  • Встроенных географические типы SQL Server.

  • Обычная выборка с ограничениями.

  • Использование дополнительной таблицы.




Далее эти способы будут рассмотрены подробно.
Встроенные геотипы



Как известно, в SQL Server 2008 появилась поддержка типов geography и geometry, которые позволяют задавать географическую (на сфере) и геометрическую (на плоскости) информацию, такие как точки, линии, многоугольники и т.д. И для того, чтобы получить все фотографии, заключенные прямоугольником с координатами (lngMin latMin) и (latMax lngMax), можно воспользоваться следующим запросом:

DECLARE @h geography;
DECLARE @p geography;
SET @rect =
geography::STGeomFromText('POLYGON((lngMin latMin, lngMax latMin, lngMax latMax, lngMin latMax, lngMin latMin))', 4326);
SELECT TOP @cound id, image75Path, geoTag.Lat as Lat, geoTag.Long as Lng, popularity, width, height
FROM Photo WITH (INDEX(IX_Photo_geoTag))
WHERE @rect.STContains(geoTag) = 1
ORDER BY popularity DESC




Обратите внимание, что полигон обходится против часовой стрелке и используется пространственный индекс IX_Photo_geoTag, построенный по координатам (кстати, пространственные индексы также работают по принципу B-деревьев ).

Однако оказалось, что в Microsoft SQL Server 2008 пространственные индексы не работают в случае, если колонка с геотипами может принимать NULL значения, а также составной индекс не может содержать в себе колонку с типом geography, и этот вопрос был затронут на stackoverflow. Из-за этого производительность таких запросов (без индексов) становится очень низкой.


В качестве решения такой проблемы можно предложить следующее:


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


Обычная выборка



Выборку фотографий из области, ограниченной координатами (lngMin latMin) и (latMax lngMax), несложно реализовать с помощью следующего запроса:

SELECT TOP @Count id, url, ...
FROM Photo
WHERE latitude > @latMin AND longitude > @lngMin AND latitude < @latMax AND longitude < @lngMax
ORDER BY popularity DESC




Стоит отметить, что для полей latitude и longitude в данном случае можно создавать любые индексы (в отличие от первого варианта), поскольку они являются обычными типами float. Однако в данной выборке присутствует 4 сравнения.
Использование дополнительной таблицы с кэшами



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


SQL запрос при этом приобретает следующий вид (zn — текущий уровень зума):



DECLARE @hash float;
SET @hash = (@latMin + 90) + (@lngMin + 180) * 180 + (@latMax + 90) * 64800 + (@lngMax + 180) * 11664000;
SELECT TOP @Count id, url, ...
FROM Photo WHERE id = (SELECT id FROM Zooms WHERE zn = @hash)




Недостатком такого подхода является то, что дополнительная таблица занимает дополнительное место в памяти.

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


Сохранение фотографий в кэш на сервер при многопоточном доступе



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

private static object SyncObject = new object();
...
List<Photo> photos = (List<Photo>)CachedAreas[hash];
if (photos == null)
{
// Использование блокировки для не того, чтобы не случилось ситуации извлечения и вставки в кэш более 1 раза.
lock (SyncObject)
{
photos = (List<Photo>)CachedAreas[hash];
if (photos == null)
{
photos = PhotoList.GetAllFromRect(latMin, lngMin, latMax, lngMax, count);
// Добавление информации о фотографиях в кэш с временем хранения 2 минуты с высоким приоритетом хранения.
CachedAreas.Add(hash, photos, null, DateTime.Now.AddSeconds(120), Cache.NoSlidingExpiration, CacheItemPriority.High, null);
}
}
}
// Дальнейшее использование CachedAreas[hash]




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

Клиентская часть




Для визуализации карты и фотографий на ней использовалось Googla Maps API. Для начала карту у пользователя нужно переместить в определенное подходящее место.
Инициализация карты



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


function detectRegion() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(success);
} else {
map.setZoom(defaultZoom);
map.setCenter(defaultPoint);
}
}

function success(position) {
...
map.setZoom(defaultZoom);
map.setCenter(new google.maps.LatLng(position.coords.latitude, position.coords.longitude));
}




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



Инициализация карты производится в следующем участке исходного кода, в котором bounds — координаты региона (насленного пункта, области или страны), возращенные сервером. Определение приблизительного уровня зума определяется по алгоритму, приведенному в функции getZoomFromBounds (позаимствовано из stackoverflow).

var northEast = bounds.getNorthEast();
var southWest = bounds.getSouthWest();
var myOptions = {
zoom: getZoomFromBounds(northEast, southWest),
center: new google.maps.LatLng((northEast.lat() + southWest.lat()) / 2, (northEast.lng() + southWest.lng()) / 2),
mapTypeId: google.maps.MapTypeId.ROADMAP,
minZoom: 3,
maxZoom: 19
}
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);



function getZoomFromBounds(ne, sw) {
var GLOBE_WIDTH = 256; // a constant in Google's map projection
var west = sw.lng();
var east = ne.lng();
var angle = east - west;
if (angle < 0) {
angle += 360;
}
return Math.round(Math.log($('#map_canvas').width() * 360 / angle / GLOBE_WIDTH) / Math.LN2);
}


Для агрегации всех координат границ для каждого региона использовался google geocoding api. (Хотя использование такой информации в оффлайне не является правомерным, кроме того там есть ограничение на 2500 запросов в день). Для каждого города, области и страны из нашей базы данных формировался запрос следующего типа, который возвращал искомые границы viewport и bounds (Они кстати различны только для больших областей, которые не могут полностью поместиться в окно просмотра). При этом если возвращался ответ с ошибкой, то использовались другие запросы, в котором комбинировалось написание на родном для этого региона языке или английском, убиралась часть {Населенный пункт} и т. д.



http://maps.googleapis.com/maps/api/geocode/xml?address={Страна},{Область/Штат},{Населенный пункт}&sensor=false



Например для такого запроса:

http://maps.googleapis.com/maps/api/geocode/xml?address=Россия, Ивановская%20область, Иваново&sensor=false
Будет возвращаться следующее (фрагмент)


...
<location>
<lat>56.9951313</lat>
<lng>40.9796047</lng>
</location>
<location_type>APPROXIMATE</location_type>
<viewport>
<southwest>
<lat>56.9420231</lat>
<lng>40.8765941</lng>
</southwest>
<northeast>
<lat>57.0703221</lat>
<lng>41.0876169</lng>
</northeast>
</viewport>
<bounds>
<southwest>
<lat>56.9420231</lat>
<lng>40.8765941</lng>
</southwest>
<northeast>
<lat>57.0703221</lat>
<lng>41.0876169</lng>
</northeast>
</bounds>
...







Расчет прямоугольных областей с фотографиями, перекрывающихся текущим окном просмотра



Расчет размера кэширующих областей



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

// Первоначальное окошко, при котором вычислялось initMapSizeLat и initMapSizeLng
var initDefaultDimX = 1000, var initDefaultDimY = 800;
// Текущее окно просмотра по умолчанию, которое зависит на размер областей.
var currentDefaultDimX = 1080, var currentDefaultDimY = 500;
var initMapSizeLat = 0.0003019; var initMapSizeLng = 0.00067055;
// Коэффициент уменьшения(увеличения) размера.
var initRatio = 0.75;

// Для вычисления этого размера наименьшей кэширующей области карта была приближена до максимального уровня зума
// Т.е. initMapSizeLat и initMapSizeLng были вычислены эмпирически.
var initZoomSize = new google.maps.Size(
initMapSizeLat / initDefaultDimX * currentDefaultDimX * initRatio,
initMapSizeLng / initDefaultDimY * currentDefaultDimY * initRatio);

// Все последующие размеры областей можно вычислить, основываясь только на наименьшей (путем умножения каждого размера на 2, потому что при увеличении уровня зума на 1, линейные размеры увеличиваются в 2 раза, а квадратичные - в 4).
function initZoomSizes() {
zoomSizes = [];
var coef = 1;
for (var i = 21; i >= 0; i--) {
zoomSizes[i] = new google.maps.Size(initZoomSize.width * coef, initZoomSize.height * coef);
coef *= 2;
}
}


Таким образом, на каждом уровне зума, размер прямоугольной области по площади составляет 0.75^2=0.5625 от текущего окна просмотра, если его ширина = 1080px и высота = 500px.


Пересчет видимых фотографий при изменении размеров окна просмотра с задержкой



Так как перерисовка всех фотографий на карте не очень быстрая операция (как будет показано позже), то решено было ее сделать с определенной задержкой после пользовательского ввода:

google.maps.event.addListener(map, 'bounds_changed', function () {
if (boundsChangedInverval != undefined)
clearInterval(boundsChangedInverval);

var zoom = map.getZoom();
boundsChangedInverval = setTimeout(function () {
boundsChanged();
}, prevZoom === zoom ? moveUpdateDelay : zoomUpdateDelay);

prevZoom = zoom;
});




Расчет координат и хешей всех кэширующих областей, перекрывающихся с окном просмотра



Расчет координат и хешей всех прямоугольников, перекрывающих видимое окно с координатами (latMin, lngMin) и размерами, вычисленных по алгоритму, описанным ранее, производится следующим образом:



var s = zoomSizes[zoom];
var beginLat = Math.floor((latMin - initPoint.x) / s.width) * s.width + initPoint.x;
var beginLng = Math.floor((lngMin - initPoint.y) / s.height) * s.height + initPoint.y;
var lat = beginLat;
var lng = beginLng;

if (lngMax <= beginLng)
beginLng = beginLng - 360;

while (lat <= maxlat) {
lng = beginLng;
while (lng <= maxLng) {
// Координаты lat и normalizeLng(lng) являются координатами перекрывающихся прямоугольников.
// Нормализация долготы используется из-за того, что правая граница может быть больше чем 180 или левая меньше чем -180.
loadIfNeeded(lat, normalizeLng(lng));
lng += s.height;
}
lat += s.width;
}

function normalizeLng(lng)
{
var rtn = lng % 360;
if (rtn <= 0)
rtn += 360;
if (rtn > 180)
rtn -= 360;
return rtn;
}




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

function loadIfNeeded(lat, lng) {
var hash = calculateHash(lat, lng, zoom);
if (!(hash in items)) {
// Сделать запрос к БД и занести данную ячейку в клиентский кэш.
} else {
// Не производить никаких действий.
}
}

function calculateHash(lat, lng, zoom) {
// lat: [-90..90]
// lng: [-180..180]
return (lat + 90) + ((lng + 180) * 180) + (zoom * 64800);
}




Перерисовка отображаемых фотографий (маркеров)



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

  • Извлечение всех видимых фотографий из клиентского кэша в массив visMarks. Расчет данных областей с фотографиями был описаны выше.

  • Сортировка полученных маркеров по популярности.

  • Определение перекрывающихся маркеров с использованием markerSize, smallMarkerSize, minPhotoDistRatio и функции pixelDistance.

  • Создание массивов из больших маркеров с количеством maxBigVisPhotosCount и маленьких с количеством maxSmlVisPhotosCount.

  • Определение старых маркеров, которые нужно скрыть и занесение их в smlMarksToHide и bigMarksToHide c помощью refreshMarkerArrays

  • Обновление видимости и индекса глубины (zIndex) для новых маркеров, которых нужно отобразить с помощью updateMarkersVis

  • Добавление фотографий, которые стали видимыми в текущий момент времени в ленту сверху с помощью addPhotoToRibbon




Алгоритм пересчета видимых маркеров


function redraw() {
isRedrawing = true;

var visMarker;
var visMarks = [];
var visBigMarks2;
var visSmlMarks2;
var bigMarksToHide = [];
var smlMarksToHide = [];

var photo;
var i, j;

var bounds = map.getBounds();
var northEast = bounds.getNorthEast();
var southWest = bounds.getSouthWest();
var latMin = southWest.lat();
var lngMin = southWest.lng();
var latMax = northEast.lat();
var lngMax = northEast.lng();
var ratio = (latMax - latMin) / $("#map_canvas").height();

var zoom = map.getZoom();
visMarks = [];
var k = 0;

var s = zoomSizes[zoom];
var beginLat = Math.floor((latMin - initPoint.x) / s.width) * s.width + initPoint.x;
var beginLng = Math.floor((lngMin - initPoint.y) / s.height) * s.height + initPoint.y;
var lat = beginLat;
var lng = beginLng;

i = 0;
if (lngMax <= beginLng)
beginLng = beginLng - 360;

// Извлечение всех видимых маркеров.
while (lat <= latMax) {
lng = beginLng;
while (lng <= lngMax) {
var hash = calcHash(lat, normLng(lng), zoom);
if (!(hash in curItems)) {
}
else {
var item = curItems[hash];
for (photo in item.photos) {
if (bounds.contains(item.photos[photo].latLng)) {
visMarks[i] = item.photos[photo];
visMarks[i].overlapCount = 0;
i++;
}
}
}
k++;
lng += s.height;
}
lat += s.width;
}

// Сортировка маркеров по популярности.
visMarks.sort(function (a, b) {
if (b.priority !== a.priority) {
return b.priority - a.priority;
} else if (b.popularity !== a.popularity) {
return b.popularity - a.popularity;
} else {
return b.id - a.id;
}
});

// Определение перекрывающихся маркеров и маркеров, превышающих определенное заданное количество.
var curInd;
var contains;
var contains2;
var dist;
visBigMarks2 = [];
visSmlMarks2 = [];
for (i = 0; i < visMarks.length; i++) {
contains = false;
contains2 = false;
visMarker = visMarks[i];

for (j = 0; j < visBigMarks2.length; j++) {
dist = pixelDistance(visMarker.latLng, visBigMarks2[j].latLng, zoom);
if (dist <= markerSize * minPhotoDistRatio) {
contains = true;
if (contains && contains2)
break;
}
if (dist <= (markerSize + smallMarkerSize) / 2) {
contains2 = true;
if (contains && contains2)
break;
}
}

if (!contains) {
if (visBigMarks2.length < maxBigVisPhotosCount) {
smlMarksToHide[smlMarksToHide.length] = visMarker;
visBigMarks2[visBigMarks2.length] = visMarker;
}
} else {
bigMarksToHide[bigMarksToHide.length] = visMarker;
if (!contains2 && visSmlMarks2.length < maxSmlVisPhotosCount) {
visSmlMarks2[visSmlMarks2.length] = visMarker;
} else {
visBigMarks2[j].overlapCount++;
}
}
}

// Занесение маркеров, которые нужно скрыть в smlMarksToHide и bigMarksToHide соответственно.
refreshMarkerArrays(visibleSmallMarkers, visSmlMarks2, smlMarksToHide);
refreshMarkerArrays(visibleBigMarkers, visBigMarks2, bigMarksToHide);

// Сокрытие невидимых и отображение видимых маркеров с изменение zIndex.
var curZInd = maxBigVisPhotosCount + 1;
curZInd = updateMarkersVis(visBigMarks2, bigMarksToHide, true, curZInd);
curZInd = 0;
curZInd = updateMarkersVis(visSmlMarks2, smlMarksToHide, false, curZInd);

visibleBigMarkers = visBigMarks2;
visibleSmallMarkers = visSmlMarks2;

// Добавление видимых фотографий в ленту.
trPhotosOnMap.innerHTML = '';
for (var marker in visBigMarks2) {
addPhotoToRibbon(visBigMarks2[marker]);
}

isRedrawing = false;
}

function refreshMarkerArrays(oldArr, newArr, toHide) {
for (var j = 0; j < oldArr.length; j++) {
contains = false;
var visMarker = oldArr[j];
for (i = 0; i < newArr.length; i++) {
if (newArr[i].id === visMarker.id) {
contains = true;
break;
}
}
if (!contains) {
toHide[toHide.length] = visMarker;
}
}
}

function updateMarkersVis(showArr, hideArr, big, curZInd) {
var marker;
var bounds = map.getBounds();

for (var i = 0; i < showArr.length; i++) {
var photo = showArr[i];
if (big) {
marker = photo.bigMarker;
$('#divOvlpCount' + photo.id).html(photo.overlapCount);
} else {
marker = photo.smlMarker;
}
marker.setZIndex(++curZInd);
if (marker.getMap() === null) {
marker.setMap(map);
}
}

for (i = 0; i < hideArr.length; i++) {
marker = big ? hideArr[i].bigMarker : hideArr[i].smlMarker;
if (marker.getMap() !== null) {
marker.setMap(null);
marker.setZIndex(0);
if (!bounds.contains(hideArr[i].latLng))
hideArr[i].priority = 0;
}
}

return curZInd;
}

function addPhotoToRibbon(marker) {
var td = createColumn(marker);

if (isLatLngValid(marker.latLng)) {
trPhotosOnMap.appendChild(td);
} else {
trPhotosNotOnMap.appendChild(td);
if (photoViewMode == 'user') {
var img = $("#photo" + marker.id).children()[0];
$('#photo' + marker.id).draggable({
helper: 'clone',
appendTo: $('#map_canvas'),
stop: function (e) {
var mapBoundingRect = document.getElementById("map_canvas").getBoundingClientRect();
var point = new google.maps.Point(e.pageX - mapBoundingRect.left, e.pageY - mapBoundingRect.top);

var latLng = overlay.getProjection().fromContainerPixelToLatLng(point);
marker.latLng = latLng;
marker.priority = ++curPriority;
placeMarker(marker);
},
containment: 'parent',
distance: 5
});
}
}
}







Расстояние между двумя точками на карте в пикселях.



Используется при перерасчете видимых маркеров и вычисляется следующим образом. Данная функция тоже была найдена на просторах stackoverflow.

var Offset = 268435456;
var Radius = 85445659.4471;

function pixelDistance(latLng1, latLng2, zoom) {
var x1 = lonToX(latLng1.lng());
var y1 = latToY(latLng1.lat());
var x2 = lonToX(latLng2.lng());
var y2 = latToY(latLng2.lat());
return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)) >> (21 - zoom);
}

function lonToX(lng) {
return Math.round(Offset + Radius * lng * Math.PI / 180);
}

function latToY(lat) {
return Math.round(Offset - Radius * Math.log((1 + Math.sin(lat * Math.PI / 180)) / (1 - Math.sin(lat * Math.PI / 180))) / 2);
}




Для стилизации маркеров (чтобы они выглядели как кружки с фотографиями как вконтакте) использовался плагин richmarker с добавление произвольного стиля элементу div.

Посмотреть как работает разработанная функциональность можно например по данной ссылке: http://gfranq.com/vlada#map


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


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends: 'You Say What You Like, Because They Like What You Say' - http://www.medialens.org/index.php/alerts/alert-archive/alerts-2013/731-you-say-what-you-like-because-they-like-what-you-say.html


[recovery mode] Удобный интерфейс Хабра? Легко!


сегодня в 11:20


Добрый день, после прочтения этого топика я твердо решил освоить написание расширений для Google Chrome.

Не люблю длинные речи, потому встречайте:

ХабраРедизайнер alpha делает шапку сайта похожей на концепты grokru.


Расширение конечно сырое и многое хотелось бы обдумать и добавить, потому жду багрепосты и новые (нескучные) идеи.

Скачать расширение для хрома

Скачать исходный код





Developers, stick with Russians – work in London




Переводы с

карты на карту


Переводы

через QR-Код


Новая функция

«Мой контроль»




Возьми Lumia 925 на тест-драйв сейчас.




Впечатляющие возможности

в стильном тонком корпусе из металла



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


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends: 'You Say What You Like, Because They Like What You Say' - http://www.medialens.org/index.php/alerts/alert-archive/alerts-2013/731-you-say-what-you-like-because-they-like-what-you-say.html


Русский интернет-бизнес: набрать пользователей и забыть продлить домен. На примере ULogin

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

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


Очевидно, что будет дальше: команда напишет извинения, домен будет спешно оплачен, многие будут решать для себя, хотят ли они дальше использовать uLogin или нет. А применяли его отнюдь не только любительские проекты, но и достаточно серьёзные — например, наш партнёр рекламная сеть AdEasy, через которую Roem.ru продаёт часть рекламы.


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


Вот весь список:



  1. Сторонний CDN для статики

  2. Рекламная крутилка AdFox

  3. Счётчик Liveinternet

  4. Rambler Top100

  5. «Яндекс.Метрика

  6. Кнопки соцсетей: ВКонтакте

  7. Facebook

  8. twitter

  9. »Мой Мир"

  10. «Одноклассники»




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

Отдельный вопрос: почему в Рунете нельзя продлевать домен больше чем на год? Большая часть проблем этим решалась бы


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends: 'You Say What You Like, Because They Like What You Say' - http://www.medialens.org/index.php/alerts/alert-archive/alerts-2013/731-you-say-what-you-like-because-they-like-what-you-say.html


Почему балансирует бухгалтерский баланс?

image

Если вам известно, что такое бухгалтерский баланс, можете закончить чтение на этом. Если же баланс ускользнул от внимания, тогда, возможно, вас заинтересует его нехитрое, вместе с тем неординарное устройство.


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



Начну с того, что бухгалтерия регистрирует используемые в хозяйственной деятельности вещи.


Ну регистрирует и регистрирует, при чем здесь баланс? При том, что вещи поступают на предприятие и выбывают с него, тем самым регистрация вещи осуществляется дважды: по приходу и расходу. У каждой регистрируемой в бухгалтерии вещи имеется приход – момент поступления на предприятие (условный +), и расход – момент выбытия с предприятия (условный –).


image


В общем случае приход одной вещи соседствует с расходом другой. Это обусловлено одной из двух причин:

• либо законом сохранения материи (применительно к бухгалтерии случаем, когда вещь переименовывается в связи с изменением характеристик, при этом считается, что одна вещь выбыла, а другая взамен нее поступила),

• либо торговым обменом, когда одна вещь обменивается на другую де-факто.


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


image


Приход одной вещи и одновременный расход другой – это, в совокупности, бухгалтерская запись, или бухгалтерская проводка с их знаменитыми дебетом и кредитом.


image


В подобной одновременной регистрации одной вещи по приходу (дебету) и второй по расходу (кредиту) заключается сущность т.н. двойной записи – но это к слову.


А что же бухгалтерский баланс? Он показывает объекты, которые значатся на предприятии на настоящий момент. Такие объекты называются инвентарем. То есть инвентарь – это вещи, зарегистрированные по приходу (те, которые уже поступили на предприятие) и не зарегистрированные по расходу (те, которые с предприятия еще не выбыли).


image


Обозначим список таких вещей графически, в виде списка.


image


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


Но погодите.


В хозяйственной деятельности учитываются не только наличные вещи, то есть инвентарь, но и вещи будущие, поступление которых ожидается, – допустим, в связи с заключенным договором. Формальное отличие от инвентаря: регистрация не текущего поступления, а будущего, – наличная вещь (инвентарь) уже поступила, а будущая вещь только ожидается к поступлению, но все равно регистрируется.


image


Правда, имеется одна тонкость, и существенная. Бухгалтерия не умеет регистрировать объекты будущей датой: в рамках одной бухгалтерской записи-проводки дата должна быть одна – текущая. Поэтому вместо будущего прихода объекта регистрируется текущее обязательство.


image


Инвентарь – то, что предприятие имеет, а дебиторское обязательство, или попросту дебиторка – то, что предприятие должно получить. Такого объекта как дебиторка в природе не существует, однако под ней подразумевается вполне себе существующая вещь, которая в соответствии с юридическими нормами должна поступить на предприятие (в будущем).


Понятное дело, одно должно быть отделено от другого.


image


Почему дебиторка, а не просто обязательства? Потому что помимо дебиторки существует еще кредиторка – кредиторские обязательства: то, что предприятие в соответствии с юридическими нормами должно отдать.


По сути, это будущий расход объекта.


image


Но в связи с названными выше обстоятельствами регистрируется не будущий расход объекта, а обязательство – на этот раз кредиторское.


image


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


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


image


Ответьте, присутствует здесь баланс (равенство между двумя колонками – положительной и отрицательной)? Не присутствует и присутствовать не может.


В рамках отдельного предприятия три рассмотренных типа объектов никак между собой не коррелируют. Соотношение может быть любым – таким, к примеру (благоприятным):


image


Или таким (менее благоприятным):


image


Или даже таким (что означает: предприятие – фактический банкрот, поскольку, даже распродав все имущество и сполна получив от должников, не сможет расплатиться с кредиторами):


image


Если равенство положительной и отрицательной колонок и имеет место, то это чистая случайность, никак не закономерность.


Нет баланса, короче. Но конечно, только в рамках одного предприятия. Если все балансы всех предприятий и физических лиц совместить в одном балансе (как говорят в бухгалтерии, консолидировать), то получится… что, по-вашему? Баланс, в котором имеется один инвентарь.


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


image


Вот еще любопытная, чисто бухгалтерская фича.


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


Ничего странного не замечаете? Зарегистрирован (в прошлом) приход холодильника и должен быть зарегистрирован его же, этого самого холодильника, будущий расход.


image


Однако по бухгалтерии, благодаря ее извращенной методологии, проходит два объекта, вроде бы не имеющих друг к другу отношения: наличный объект (холодильник) и кредиторское обязательство (по передаче холодильника покупателю).


image


Во как: холодильник один, но регистрируется два объекта, один положительный (по приходу), второй отрицательный (по расходу)!


Но хватит о поэтическом, вернемся к бухгалтерскому балансу, до которого непонятно как добраться. Как было сказано, баланса нет и не предвидится – имеются две противоположные по знаку, но категорически отказывающиеся уравниваться колонки:


image


Откуда же берется баланс?


Вы не поверите: он создается искусственно. Недостающая часть, под названием капитала, помещается в меньшую колонку – и дело в шляпе.


image


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


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


Допустим, вещь испортилась, пришлось ее выбросить. Имеет место, с одной стороны, уменьшение инвентаря, а с другой стороны… как ни крути, вторая вещь отсутствует.


Вторая вещь отсутствует в природе и хозяйственной практике, но только не в бухгалтерии, в которой регистрируется подставной объект под названием капитал: подставной – потому что просто подставляется взамен отсутствующего объекта, и все. Поскольку суммы по приходу и расходу (дебету и кредиту) бухгалтерской проводки всегда равны, возникает баланс положительной и отрицательной колонок, с самой первой бухгалтерской проводки, какой бы она ни была. Допустим, с такой:


image


Никакие последующие изменения не могут данный баланс поколебать, поскольку воздействуют на колонки баланса всегда равнозначно:

либо уменьшают и одновременно увеличивают одну из колонок (такие изменения называются пермутациями);


image


либо равнозначно уменьшают или увеличивают одновременно обе колонки (такие изменения баланса называются модификациями).


image


Как вы понимаете, равенство сохраняется за счет того, что колонки баланса имеют разные знаки.


А теперь еще раз повторяю: бухгалтерский баланс – искусственное образование, не имеющее ничего общего с хозяйственными реалиями. В реальном предприятии никакого баланса нет, он достигается за счет искусственного, в методологических целях, восполнения недостающей разницы посредством регистрации несуществующего объекта – капитала.


Лишь одна цитата, известного в начале прошлого века Г.А. Бахчисарайцева:


«Тут поразительное отсутствие всякого здравого смысла. Еще удивительнее то, что «разнеся» обороты по закону двойной записи, эти бухгалтера получают равные итоги по «Дебету» и «Кредиту» счетов и восторгаются, заявляя: «Вот еще один основной закон бухгалтерии! Итог левых сторон равен итогу правых сторон» (счетов). И этот «самостоятельный» (!), с их, конечно, точки зрения, закон они называют «законом Баланса» или «законом Баланса счетов». Может ли быть что-нибудь наивнее! К двум равным величинам прибавить поровну, получить в итоге поровну и… кричать: «основной закон счетоводства – закон Баланса, как следствие (?!) закона двойной записи»! Господа! математика подобные истины называет просто «аксиомами», и вы напрасно увлекаетесь (и других увлекаете) своими краткохвостыми законами».


Справедливости ради стоит заметить, что существуют десятки т.н. счетных теорий, пытающихся обосновать существование бухгалтерского баланса в качестве объективного феномена. Нет смысла обсуждать их с неспециалистами, поскольку «объективность» бухгалтерского баланса очевидна. Кто-нибудь сомневается в том, что, в случае официальной отмены бухгалтерского баланса предприниматели прекратят им пользоваться?


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


image


Такова форма объективного, а не надуманного баланса. Но конечно, именовать данную отчетную форму балансом окажется уже невозможным.


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends: 'You Say What You Like, Because They Like What You Say' - http://www.medialens.org/index.php/alerts/alert-archive/alerts-2013/731-you-say-what-you-like-because-they-like-what-you-say.html