Рецепт
«Ложка в меду».
Это блюдо делается в глубокой посуде. Натуральный мёд переложить в приготовленную посуду, чайную ложку (можно взять столовую, по вкусу) положить в мёд, чуть утопить. Блюдо готово, можно подавать к столу.
Анализ
Показательный пример
Small HTTP server: поиск блох
Small HTTP server 3.0395
Один знакомый спросил меня по аське — что я думаю по поводу Small HTTP server. Я его отправил к статьям годичной давности (смотреть тут, тут, тут и тут). «Ну, хорошо,» — сказал он — «а что ты думаешь по этому поводу сейчас?». Ничего по этому поводу «сейчас» я не думал, моего знакомого интересовала HTTP-составляющая этого сервера, поэтому я пообещал ему произвести
Из дальнейшей беседы я понял, что производительность сервера моего знакомого не волнует, зато сильно интересует вопрос безопасности и наличия багов. Я произвёл тестирование до той кондиции, когда мой знакомый решил, что я своё обещание выполнил. А когда произвёл, понял, что результаты тестирования могут быть интересны более широкой публике — людям, использующим этот сервер в своих повседневных задачах или не знакомым с ним вовсе.
Эти результаты, оформленные должным образом, я и предлагаю вашему вниманию.
Давненько я не рассматривал замечательный продукт нашего программиста Макса Феоктистова Small HTTP server (SHS) на предмет багов и уязвимостей (в прошлом я это делал
Small HTTP server — в прошлом HTTP-сервер, а в нынешней своей ипостаси — HTTP-, DNS-, Proxy-, FTP, POP3— и SMTP-сервер с поддержкой сервера динамических перенаправлений, виртуальных хостов, SSI, ISA и CGI-скриптов. Более всего продукт замечателен тем, что при своих возможностях он занимает всего 103 (!) килобайта.
В прошлом я периодически находил в нем уязвимости различного рода, Макс их исправлял, в частности, путём введения различных ограничений и проверок в код программы. В итоге, код так оброс различными коррективами, что в обработке запросов появились натуральные баги.
Сервер я запускал в установками по умолчанию, в корень сайта положил
Первая ошибка связана с обработкой GET-запроса к индексному файлу. Вообще, если сервер обнаруживает, что запрос пришел не конкретному файлу,
Все запросы, равно как и их содержание, в этом случае передаётся индексному файлу. Каким образом сервер отличает индексный файл от любого другого зависит от настроек сервера, собственно, как и его поведение в случае, если такой файл не найден.
Так вот, в случае SHS, GET-запрос к директории
Наверное, одна из самых распространённых ошибок доморощенных
SHS до жути боится двух точек в URL’e, так совершенно безвредные запросы
http://127.0.0.1/Folder../
http://127.0.0.1/file.shml?/..
http://127.0.0.1/file.shml?../
вызовут у него неадекватное bad reques (хотя ничего bad в таких requests нет).
Другая проблема SHS — негативное его отношение к слешам в конце запроса. Не то, чтобы они ему совсем не нравятся, но некоторые манипуляции с ними кажутся SHS чересчур подозрительными. Запросы ниже порождают уже знакомый «bad request».
http://127.0.0.1/file.shml?./
http:127.0.0.1/file.shml?
Другая беда — трансляция переменных запроса в переменные языка SSI. Видимо, преобразование URL к «нормальному» виду и отсечение всего подозрительного выполняются раньше любых других манипуляций. Так что после запроса
http://127.0.0.1/index.shtm?word/
в QUERY_STRING оказывается word\index.shtm, а после
http://127.0.0.1/index.shtm?/a
переменная QUERY_STRING содержит \a
Такое искажение данных недопустимо, если пытаться использовать вместе с SHS
Собственно, даже при использовании SSI любое искажение входных данных может приводить к неожиданным, неприятным последствиям. SHS, помимо стандартной переменной QUERY_STRING, помещает данные запросы ещё и в переменные окружения, подобно тому, как это делает язык PHP. Например, запрос ?bar=1&foo=2 приведет к появлению двух переменных — bar со значением 1 и foo со значением 2.
Это очень удобно, так как позволяет использовать язык SSI для более широкого круга задач. К сожалению, и тут есть небольшой баг, искажающий внешние данные. Так запрос
http://127.0.0.1/index.shtm?var==value
порождает переменную var со значением value, хотя, по логике var должна содержать строку =value.
http://127.0.0.1/index.shtm?var=1=2
этот запрос, как не странно, порождает переменную var со значением… 2.
http://127.0.0.1/index.shtm?&
Косметический баг. В переменных окружения — пара переменных с пустыми именами и значениями.
Теперь, что касается уязвимостей. Сразу скажу, серьезно в этом плане я сервер не тестировал. Просто попробовал несколько первых комбинаций, из тех, что сразу пришли в голову.
Начнем с локальных уязвимостей. Оставим в стороне CGI/ISA и другие «внешние» вещи и займемся SSI.
Несложная команда, не лишенная логики
<!--#echo var="\"\"" -->
заставляет сервер подвисать после выполнения нескольких запросов к файлу, её содержащему.
Так же SHS не переваривает команду
<!--#exec cmd="\s.exe" --> после неё сервер выполняет недопустимую операцию и, с приличествующим шумом, умирает.
Сходная с предыдущей, команда
<!--#exec cmd="\"" -->
вводит сервер в прострацию — он зависает.
Удалённая уязвимость, связанная, по всей видимости, с переполнением буфера (в этом легко убедиться, несколько сократив количество знаков & в запросе). Её я приберег на сладкое.
Как уже было сказано, запрос с одним амперсандом, порождает две пустые переменные, а вот запрос длиной в 40 амперсандов
http://127.0.0.1/index.shtm?&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
кончается для сервера фатально. По крайней мере, в моей Windows XP. Возможно, под другими операционками сакральное число этих знаков в запросе будет другим.
И, что самое интересное, судя по всему, вполне можно попытаться изготовить эксплоит, которых бы использовал эту уязвимость для выполнения вредоносного кода на атакуемой машине.
Повторюсь: все тесты выполнялись над версией 3.0395 под Windows XP. В качестве инструмента для всех запросов использовался браузер Internet Explorer 6.0. Сервер ставился в стандартной конфигурации, в корне сайта лежала
Вывод: Small HTTP server — безусловно отличный продукт, заслуживающий всяких похвал, но, к сожалению, недостаточно оттестированный. Для хостинга сайта, в силу постоянно обнаруживаемых ошибок в разборе HTTP-запроса, я бы его использовать не рекомендовал.
С другой стороны, в программе есть и другие сервера, которые, возможно окажутся более защищенными. Кроме того, у сервера есть неоспоримое преимущество — его размер в 103 килобайта,
Кстати, до версии 1.22 обновился [ Photoshop’s Crap Remover ]. Всем, кому интересно, качайте новую версию.
Пишите!
Почувствуй себя счастливым
Если сегодня с утра ты проснулся здоровым, ты счастливее, чем 1 миллион человек, которые не доживут до следующей недели.
Если ты никогда не переживал войну, одиночество тюремного заключения, агонию пыток или голод, ты счастливее, чем 500 миллионов человек в этом мире.
Если ты можешь пойти в церковь без страха и угрозы заключения или смерти, ты счастливее, чем 3 миллиарда человек в этом мире.
Если в твоём холодильнике есть еда, ты одет, у тебя есть крыша над головой и постель, ты богаче, чем 75% людей в этом мире.
Если у тебя есть счёт в банке, деньги в кошельке и немного мелочи в копилке, ты принадлежишь к 8% обеспеченных людей в этом мире.
99 бутылок: NSIS, Photoshop JavaScript
Сериал «99 бутылок пива» продолжается. Сегодня — 36
36. Nullsoft (SuperPiMP|Scriptable) Install System. NSIS — настраиваемый инсталлятор от компании «Nullsoft», позволяющий создать пакет для инсталляции и деинсталляции вашего собственного продукта. Выходной файл представляет собой обычную программу. Для сжатия данных NSIS может использовать алгоритмы Zip и Bzip2, так что весь код получается довольно компактным.
Весь процесс установки и удаления продукта описывается на собственном языке программирования, где есть опции управления внешним видом инсталлятора, команды использования внешних плагинов, поддержки нескольких языков, команды предпроцессора и собственно язык с поддержкой функций, секций, ветвления, файлового
Я использовал версию 2.0b2. Язык инсталлятора крайне простой, поэтому не поддерживает локальных переменных и параметров у пользовательских функций — вместо них приходится использовать глобальные пользовательские переменные (их 20 штук) или стек. Кстати, и параметры плагинам передаются именно через стек.
Все имена переменных начинаются с доллара, программист для своих собственных целей может использовать лишь двадцать переменных — $0..$9, $R0..$R9, переменные не типизированы, в строках выполняется интерполяция, в качестве ограничителей строк подходят любые кавычки. Ветвление выполняется командами сравнения, которые в качестве аргумента принимают три ссылки, по одной из которых происходит переход в зависимости от результата сравнения.
Операции с числами так же выглядят несколько неожиданно. Вообще, даже прочитав полностью документацию, без примеров достаточно просто оставить без внимания некоторые возможности, которые становятся очевидными при просмотре примеров. Так что будете писать инсталлятор для своего продукта — загляните ещё и в примеры.
В любом случае, NSIS — достаточно надежный продукт, появился он не один год назад и используется, например, для инсталляции достаточно известного проигрывателя WinAMP.
Программа, выводящая песню о пиве (beer.nsi)
; Beer song. Written by Evgeny Stepanischev
Name "Beer song"
Caption "Beer song"
OutFile "beer99.exe"
BrandingText "Beer song (Evgeny Stepanischev)"
ShowInstDetails show
!macro c
StrCpy $2 ""
Call PrintBeer
!macroend
Function PrintBeer
IntCmp $1 0 no "" ""
StrCpy $2 "$2$1"
Goto +2
no:
StrCpy $2 "$2No"
StrCpy $2 "$2 bottle"
IntCmp $1 1 nos "" ""
StrCpy $2 "$2s"
nos:
StrCpy $2 "$2 of beer"
FunctionEnd
Section ""
StrCpy $1 99
loop:
!insertmacro c
StrCpy $2 "$2 on the wall, "
Call PrintBeer
DetailPrint "$2."
DetailPrint "Take one and pass around,"
IntOp $1 $1 - 1
!insertmacro c
DetailPrint "$2 on the wall."
DetailPrint ""
IntCmp $1 0 "" loop loop
DetailPrint "No more bottles of beer..."
DetailPrint "Go to the store and buy some more..."
DetailPrint "99 bottles of beer."
SectionEnd37. JavaScript for Adobe Photoshop (Photoshop 7.0 Scripting
Описывать JavaScript не интересно — базовые конструкции стандартные, добавлены лишь специфические объекты для управления всем тем, что есть в Photoshop, соответственно и объектная модель отличается от той, что принята, например, в браузерах.
Одним словом — полное управление всем, до чего можно дотянуться в бесконечных меню и опциях Adobe Photoshop (включая фильтры), из скриптового языка. Грандиозные возможности для дизайнеров, пробующих себя в программировании, или программистов, пытающихся заняться дизайном. :)
Программа, выводящая песню о пиве (beer.js)
preferences.rulerUnits = Units.POINTS
preferences.typeUnits = TypeUnits.POINTS
var docRef = documents.add(640, 480)
displayDialogs = DialogModes.NO
var textColor = new SolidColor
textColor.rgb.red = textColor.rgb.green = textColor.rgb.blue = 0
var TextLayer = docRef.artLayers.add()
TextLayer.kind = LayerKind.TEXT;
TextLayer.textItem.font = "Tahoma"
TextLayer.textItem.position = Array(10, 10)
TextLayer.textItem.size = 12
TextLayer.textItem.color = textColor
var content = ''
function WriteLn(str)
{
content += '\r'+str
}
function PrintBeer(n)
{
return (n ? n : 'No') + ' bottle' + (n-1 ? 's' : '') + ' of beer'
}
for (i = 99; i>0;)
{
WriteLn (PrintBeer(i) + ' on the wall, '+PrintBeer(i)+'.')
WriteLn ('Take one and pass around,')
WriteLn (PrintBeer(--i) + ' on the wall.')
WriteLn ('')
}
WriteLn ('No more bottles of beer...')
WriteLn ('Go to the store and buy some more...')
WriteLn ('99 bottles of beer.')
TextLayer.textItem.contents = content
docRef = textColor = TextLayer = nullФантасты были правы
География Ехо
Это — кусок карты мира Ехо, мира придуманного писательницей, пишущей под псевдонимом «Макс Фрай». Представляю себе, как главному герою Максу, который попал в Ехо, рассказывают о географии этого мира: «А это, Макс, у нас Вуки, нах, а это — горы, нах».
Программа CSV SQL Monitor
Некоторое время назад, испробовав различные программы для обработки логов Squid, я убедился, что ни одна из них не отвечает моим требованиям и написал свою. Простенький, однозадачный вариант на языке Perl. В качестве базы данных я выбрал модуль для Perl, который позволяет делать SQL-запросы к файлу в формате CSV (Comma Separated Values).
Это уже потом я узнал, что в CSV SQL нет агрегатных функций, LIMIT, да и скорость работы модуля оставляет желать лучшего и переписал всё с использованием DB_File::Lock и fork. Но от времён, когда я использовал CSV у меня осталась программа, которую я написал для удобства работы с SQL-запросами.
Назвал я её незатейливо — CSV SQL monitor, текущая версия 1.06. Возможно,
Итак, CSV SQL monitor. Для функционирования требуются модули Term::ReadLine (лучше Term::ReadLine::Gnu), Text::Tabs, Cwd, DBI и DBD::CSV. При запуске можно указать необязательный параметр — местоположение каталога с CSV-файлами, если этот параметр не указан этим этим каталогом считается рабочий каталог программы. Все файлы в нём считаются таблицами, к которым, при ограничениях описанных ниже, можно делать запросы.
SQL-команды полностью идентичны обычному SQL за исключением накладываемых модулем DBD::CSV ограничений. В мониторе вместе с SELECT-запросом можно использоваться LIMIT — его я эмулирую, пропуская и возвращая указанное число строк. LIMIT работает в режиме MySQL, т. е. команда
SELECT * FROM file LIMIT 1,2Пропустив одну, покажет две строки, с условием, конечно, что в файле есть хотя бы 3 строки данных. Кроме того, я реализовал ряд специфических команд, которые позволяют получить
SHOW TABLES
Показывает имена «таблиц» в каталоге, указанном как каталог с CSV-файлами.
BIND TABLE <имя таблицы> <имя файла>
Так как файлы у вас могут называться как угодно (например, «my document.csv»), а SQL не допускает использование имен таблиц с пробелами, точками и другими подобными символами, но использовать эти файлы в качестве таблиц всё равно нужно, Monitor позволяет «привязать» к «неудобному» имени любое другое, которые SQL примет как удовлетворяющее стандартам.
BIND TABLE log log.txt
VAR FOR <имя таблицы> <имя переменной > <значение переменной>
Позволяет настроить некоторые специфические параметры для таблиц, например, символ, который будет считаться разделителем строк или полей. Подробнее о значении каждого параметра можно прочитать в документации по DBD::CSV, а я лишь приведу пример, который позволит понять, каким образом удалось получить картинку, как не скриншоте.
Я использовал три команды:
VAR FOR passwd eol \\n
VAR FOR passwd sep_char :
VAR FOR passwd col_names name,pass,uid,gid,comment,home,shell
После чего, можно спокойно назначать каталог /etc рабочим и делать запросы к таблице passwd (для людей, не знакомых с Unix, сделаю пояснение: в файле /etc/passwd Unix, в традиционной конфигурации, хранит основные данные о пользователях). Если требуется удалить
Кстати, отсюда можно увидеть, что все экранирующие слеши (\) должны быть экранированы таким же слешем, чтобы отличать случаи их упоминания от специальных команд, речь о которых пойдет ниже.
Специальные команды нужны, чтобы сообщить «Монитору», что именно вы хотите, чтобы он сделал. Думаю, они будут хорошо знакомы всем, кто хотя бы раз использовал mysql-монитор, работающий из командной строки. Специальные команды используются либо в конце SQL-запроса, либо сами по себе, для выполнения
Примеры использования специальных команд:
SHOW TABLES\G
\r /etc
Полный список этих команд вы, в любой момент, можете получить командами \? или \h, я приведу их тут с подробной расшифровкой их действия.
\h или \? — как я уже сказал, позволяет получить список всех доступных специальных команд.
\c — очищает буфер команды. Если вы набрали
\r [<каталог>] — закрывает текущее соединение с каталогом и открывает новое. С аргументом «каталог» действие аналогично команде \u.
\g — выполнить текущий SQL-запрос. Синоним этой команды — ;.
\G — выполнить текущий SQL-запрос и вывести результат вертикально. Что это такое я объяснять не буду — достаточно один раз применить эту команду, чтобы понять о чём идёт речь. :)
\u <каталог> — сменить каталог с CSV-файлами.
\q — выйти из Монитора.
Если вы используете модуль Term::ReadLine::Gnu, вам будет доступны такие возможности как пролистывание команд (стрелки «вверх» и «вниз») и автодополнение команд.
Автодополнение команд я постарался сделать зависимым от контекста. Так, если вы введете S и нажмёте Tab, то получите список из двух команд — SELECT и SHOW TABLES, далее, если ввести ещё и E и нажать Tab строка дополнится до SELECT . В нужном месте Tab выведет вам список файлов в текущей директории, в случае команды VAR FOR покажет список её параметров и так далее.
Конечно, я не учитывал все случаи, но Tab существенно облегчит вам жизнь во многих случаях. Кстати, если вы связали (BIND TABLE)
SHOW TABLES) покажет вам имя таблицы, а не имя файла.
Скачать CSV SQL Monitor можно у меня со страницы. Объём в архиве — 2,8КБ, язык — Perl.
Пишите!
Лимон
Это не ручка маленькая, это лимон такой большой. Мутант был куплен мной сегодня в магазине «Эрком» по улице Космонавтов, причём даже сами продавцы были весьма удивлены его внешним видом; таких там ещё много. Вечером планируется дегустация этой жертвы космической радиации.
Татарский шрифт своими руками, PHP 4.3.0+GD 2.0.x
Доброе время!
Несмотря на то, что татары перешли некоторое время назад с кириллицы на латиницу, латиница ещё настолько непривычна, что многие до сих пор читают и пишут «по старинке». Соответственно, большинство, за редким исключением, сайтов с информацией на татарском языке, предоставляют её в кириллице и будут предоставлять её ещё долго — не у всех есть время и желание переучиваться на непонятную им латиницу.
А значит, будет открыта проблема представления татарских национальных символов
Упомянутые татарские национальные символы очень похожи на буквы кириллического и латинского алфавитов, условно — «h с хвостиком», «ж с хвостиком», «н с хвостиком», «о с горизонтальной чертой», «укороченная у» и «перевёрнутая е».
Мне пришло в голову попробовать средствами CSS «дорисовать» существующие буквы, чтобы получилось
Другие варианты не сработали — давали отступ после буквы, порождали проблемы с переносом
Opera 6.02, Mozilla 1.2a, Netscape Navigator 7.0 и Microsoft Internet Explorer 6.0 отображают эти буквы нормально:
’h ’ж -o ..э .v ’н
Netscape Navigator 4.80 отобразить не смог, естественно, не отобразят их и неграфические Lynx и Links. Но это не страшно — первый уже вымирает, а последние не отобразят такие буквы и любым другим способом.
Способ имеет свои недостатки — если на текста экране много, Internet Explorer несколько «подтормаживает» при рендеринге, остальные браузеры справляются с этой задачей куда лучше.
Для представления этих символов в кириллице, до перевода их форму пригодную для вывода я использовал сочетания х’, ж’, о’, е’, у’ и н’. Способов автоматического перевода из указанных сочетаний в HTML минимум три: назначить собственный обработчик для HTML-файлов, который будет осуществлять трансляцию, создать в Apache новую раскладку, скажем tat, директивами CharsetDecl и CharsetWideRecodeTable или осуществлять весь вывод через собственные скрипты, не используя статических файлов, например, так как это сделано ниже.
<?php
function Tat_Recode($str)
{
$trans = array (
"х'" => '<span style="margin-left:-3;margin-right:0"><span style="position:relative;top:9;left:8">\'</span>h</span>',
"ж'" => '<span style="margin-left:-3;margin-right:0"><span style="position:relative;top:9;left:11">\'</span>ж</span>',
"о'" => '<span style="margin-left:-4;margin-right:0"><span style="position:relative;top:0;left:5">-</span>o</span>',
"е'" => '<span style="margin-left:-7;margin-right:0"><span style="position:relative;top:-1;left:6">.</span><span style="position:relative;top:-2;left:2">.</span>э</span>',
"у'" => '<span style="margin-left:-4;margin-right:0"><span style="position:relative;top:2;left:5">.</span>v</span>',
"н'" => '<span style="margin-left:-3;margin-right:0"><span style="position:relative;top:9;left:8">\'</span>н</span>');
return strtr ($str, $trans);
};
ob_start(Tat_Recode);
?>
<span style="font-family: Tahoma; font-size: 12px">
Татарстан Президенты Минтимер Ше'ймиев шушы ко'нне'рде' Башкортстан Президенты Мортаза Ре'химовнын' республикада президентлык постын юкка чыгару турында е'йтке'н идеясе ун'аеннан аптырашта калуын белдерде.
«Мортаза Гобе'йдулла улы Ре'химовнын' республикада хакимият структурасын у'зге'рту'ге' кагылышлы те'къдимне'ре ж'авапларга караганда ку'бре'к сораулар тудыра, х'е'м минде' гене' ту'гел", - диде М.Ше'ймиев пе'нж'еше'мбе ко'нне "Интерфакста бирге'н интервьюсында. Анын' фикеренче', Башкортстан ж'ите'кчесенен' бу фикерне нигезле'ве "бик каршылыклы».
«е'мма мондый белдеру'ле'рнен' се'бе'бе нинди булуга карамастан, бу очракта мин шуны гына е'йте' алам: аларны Татарстан Президентынын' белдерме'ве е'йбе'т», — диде М.Ше'ймиев.
</span>
<?
ob_end_flush();
?>Скрипт средствами PHP 4 перехватывает весь вывод и пропускает его через функцию Tat_Recode, которая осуществляет необходимые замены. Думаю, метод пригодится для представления букв и на других языках. Как осуществляется изготовление отдельной буквы можно легко понять, взглянув на HTML-код.
Если вы попробовали скомпилировать PHP 4.2.0 или 4.3.0pre1 с
Дело состоит, видимо, в различиях GD API, описанного в документации и реального положения дел. В документации утверждается, что структура gdIOCtx содержит, помимо всего прочего метод free, который используют два файла из дистрибутива PHP: gd.c и gd_ctx.c. На самом же деле метод free в gdIOCtx не описан, зато там содержится gd_free, который с успехом выполняет требуемые функции.
Таким образом, чтобы скомпилировать текущую версию PHP с
[root@x gd]# diff gd.old.c gd.c
1036c1036
< io_ctx->free(io_ctx);
---
> io_ctx->gd_free(io_ctx);
1039c1039
< io_ctx->free(io_ctx);
---
> io_ctx->gd_free(io_ctx);
1216c1216
< io_ctx->free(io_ctx);
---
> io_ctx->gd_free(io_ctx);
[root@x gd]# diff gd_ctx.c gd_ctx.old.c
70c70
< ctx->gd_free = _php_image_output_ctxfree;
---
> ctx->free = _php_image_output_ctxfree;
98c98
< ctx->gd_free(ctx);
---
> ctx->free(ctx);Загадка для программистов от Dead Emotion. У меня Perl’e получилась одна строка кода. :)
есть текстовый файл, довольно большой, настолько, что целиком в доступную память не влезет, количество строк в нем заранее не известно. собственно задача — вывести случайную строку из этого файла, зачитав его только один раз. (с вероятностью 1/n, где n — количество строк в этом самом файле)
Письмо от Fedor «FAx» Axenoff.
Спасибо за чистилку JPEG!!!
Знаешь какая ещё проблема в мире дизайна?
нет и не будет конвертора угробищного Corel Draw формата в что либо
типа EPS\AI. С самим CDR всё может и сложно, но вот его CMX\CCX\CXX
картинки — вполне должны конвертиться, если с этим разобраться.Я слышал что
кто-то с этим ковырялся и сказал что сделать можно, но
для этого потребуются все dllCorel-овских фильтров. Да хрен с ними,
пусть будут — лишь бы конвертил. Официальные кореловцы мне сказали что
конвертора не будет никогда и это их маркетинговые соображения.Не то что бы я как то сильно не любил Корел (Ну да, я заказал себе
майку «Corel Killer» и что с того?8-)) но все шлют макеты именно в
нём, а его поставить на машину — как продать родину.8-) ps. Я пользуюсь XaraX или AI.
pss. Это отнюдь не «заказ». Если у самого нет желания — просто умомяни
на сайте — может кто возьмётся…8-/
У меня, к сожалению, нет времени, чтобы реализовать такой конвертор, может быть
Пишите!
Дурацкий вопрос
Беда с этим хлебцами

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