LINUX.ORG.RU

Сообщения firkax

 

Команда Devuan просрочила основной ключ подписи репозиториев

Новости — Безопасность
Группа Безопасность

Ключ, которым подписываются все системные обновления, выпущенный в 2017 году, был действителен до 2 сентября 2022 года. Сегодня пользователи дистрибутива столкнулись с невозможностью штатного обновления системы через apt в связи с отсутствием действительного ключа. Разработчики дистрибутива, судя по всему, узнали о просрочке из жалобы на форуме и сгенерировали новый пакет devuan-keyring, который предлагают скачать через http (поскольку apt неработоспособен) и без каких-либо проверок сразу установить.

wget http://deb.devuan.org/devuan/pool/main/d/devuan-keyring/devuan-keyring_2022.09.04_all.deb
dpkg -i devuan-keyring_2022.09.04_all.deb
Впрочем, какую-никакую проверку провести всё-таки можно, на странице пакета (по https) указан sha256-хэш deb-файла: 96c4a206e8dfdc21138ec619687ef9acf36e1524dd39190c040164f37cc3468d, который можно сравнить так:
sha256sum devuan-keyring_2022.09.04_all.deb
перед тем как запускать dpkg -i.

Старый ключ:

/etc/apt/trusted.gpg.d/devuan-keyring-2017-archive.gpg
------------------------------------------------------
pub   rsa4096 2017-09-04 [SC] [просрочен с: 2022-09-03]
      E032 601B 7CA1 0BC3 EA53  FA81 BB23 C00C 61FC 752C
uid         [  просрочен ] Devuan Repository (Amprolla3 on Nemesis) <repository@devuan.org>
Новый ключ:
/etc/apt/trusted.gpg.d/devuan-keyring-2022-archive.gpg
------------------------------------------------------
pub   rsa4096 2017-09-04 [SC] [   годен до: 2023-09-03]
      E032 601B 7CA1 0BC3 EA53  FA81 BB23 C00C 61FC 752C
uid         [ неизвестно ] Devuan Repository (Amprolla3 on Nemesis) <repository@devuan.org>
sub   rsa4096 2017-09-04 [E] [   годен до: 2023-09-03]

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

>>> Подробности

 , ,

firkax
()

немонотонные таймстампы коммитов в свн

Форум — Development

Свн позволяет редактировать timestamp в свойствах ревизии (так же как и остальные метаданные). Если я поставлю таймстампы немонотонными, какие это может вызвать проблемы в работе штатных утилит?

Ну то есть, например, есть репозиторий, в нём уже коммиты за 2022 год есть, и я хочу туда импортировать (с датами коммитов) что-то ещё старое откуда-то из другого места (имеется ввиду не заменить этим имеющиеся файлы а положить рядом - это другой код, просто я хочу его хранить в том же репозитории), с датами коммитов например 2010 год. При этом номера ревизий этих импортированных коммитов, разумеется, будут идти после уже существующих за 2022. Ничего не сломается от такого фокуса?

Перемещено hobbit из general

 , ,

firkax
()

Планируется выход FreeBSD 12.4

Форум — General

Зашёл на freebsd.org и к своему удивлению обнаружил 12.4 в списке планируемых. Что очень радует, т.к. означает продление официальной поддержки 12.х ветки и дальнейшую возможность малыми силами избегать глючную 13.х. Но с чего это они вдруг, кто знает? Планировали же 12.3 последней.

 

firkax
()

быстрая инкрементальная сборка ядра FreeBSD

Форум — Development

Там есть опция KERNFAST=1 чтобы не пересобирать всё, но он всё равно лазит по исходникам всех модулей в поисках изменённых файлов, хоть ничего и не компилируя в них, но всё равно долго (целых 3 минуты вместо 15 секунд), при том что перекомпилировать надо только один файл в kern/. Можно ли это штатно и просто исправить? Аналогично в installkernel - он заново ставит все неизменившиеся модули.

 , ,

firkax
()

Найти race condition

Форум — Development

Только что случившийся со мной случай.

Есть некий объект, упрощённое описание:

typedef struct {
  int status;
  int status2;
  void *data;
  rwlock lock1;
  rwlock lock2;
}
Предполагается, что разрешённые его состояния такие:
(1) status==0, status2==0, data==NULL
(2) status==0, status2==0, data!=NULL
(3) status!=0, status2==0, data==NULL
(4) status!=0, status2 [1..3], data==NULL
(5) status==0, status2==4, data!=NULL

Переходы между состояниями такие:

1->2, 1->3, 1->4, 4->5 делаются под write-lock1'ом

5->2 без write-lock1'а

внутри состояния 4 может меняться status2 - без write-lock1'а

status2 меняется между 0 и 4, а так же между 1-2-3 без write-lock1'а, потому что от этих изменений не зависит поведение остальных частей кода (интересующихся status'ом и data), а ещё у status2 есть lock2, который защищает от race между разными его переключалками (то есть именно тем кодом, чья логика завязана именно на него), тут он для упрощения не показан.

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

READ_LOCK(obj->lock1);
if(obj->status!=0) {
  .....
} else {
  assert(!obj->status2 || obj->status2==4 && obj->data);
  ...
}
READ_UNLOCK(obj->lock1);

Так вот, этот ассерт иногда падал. Кто угадает в чём причина?

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

 , , , ,

firkax
()

Ещё одна занимательная задача по теорверу

Форум — Talks

По мотивам Не могу ответить в теме, про вопрос из тервер Занимательная задачка по ТВ

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

Достаём из кармана монетку, полученную на сдачу во время последнего похода в магазин, и проводим над ней серию из 100 опытов: подбрасываем и смотрим какой стороной она упала. Если падает не плоской стороной - итерация считается недействительной и повторяется. Так вот, известно, что из 100 раз как минимум 99 раз она упала орлом вверх. Вопрос: какова вероятность, что она упала орлом все 100 раз из 100?

Добавлено 5 августа 13:25: поскольку некоторые придираются, уточняю: всё, что написано перед вопросительным предложением - условие к нему. Вероятность надо найти именно при условии выполнения всего того, что написано до вопроса.

Добавлено 5 августа 13:22: сегодня вечером наверно напишу свой вариант решения (с обоснованием почему именно он верный) и разбор ошибок всех неправильных решений. Пока что в подробностях никто правильное решение не написал, хотя правильные мысли были и не раз, но не оформленные в решение.

Добавлено 6 августа 13:08: мои ответы тут Ещё одна занимательная задача по теорверу (комментарий) Ещё одна занимательная задача по теорверу (комментарий)

 , , ,

firkax
()

Улучшение вида синей темы

Форум — Linux-org-ru
div.msg_body {
    font-weight: bold !important;
}

предлагаю сделать официально

 

firkax
()

ipfw fwd loopback + tcpdump

Форум — Admin

Всё происходит без участия внешних сетевых интерфейсов.

Есть правило ipfw fwd, перенаправляющее исходящий трафик на определённый адрес на локальный слушающий порт. Как его теперь увидеть в tcpdump? Ни на lo0, ни на одном из ethernet-интерфейсов, ни на созданном ipfw0 его не видно.

Условно (убрал ненужные подробности), есть правило

ipfw fwd 192.168.1.10,1005 tcp from 192.168.1.10 to 192.168.1.10 1005
и
tcpdump -i lo0 -n port 1005
telnet 192.168.1.10 1005
На порте 1005 никто не слушает. telnet пишет ошибку коннекта, tcpdump видит ответный RST (он не попадает в это правило а попадает в какое-то allow). А вот SYN - не видит.

 , , ,

firkax
()

Совместимость zlib и gpl лицензий

Форум — General

https://directory.fsf.org/wiki/License:Zlib

Конкретно интересует пункт 2. Вроде бы в лицензии GPL такого требования нет, а значит zlib налагает дополнительный запрет и не может быть в составе gpl-продукта. С другой стороны, авторитетный источник ( https://www.gnu.org/licenses/license-list.html#ZLib ) говорит что совместима. Я где-то ошибаюсь?

 , ,

firkax
()

Приоритеты поиска имён в shared objects

Форум — Development

Предположим, у меня есть два варианта одной so-библиотеки, с одинаковыми названиями функций но разными реализациями. lib1.so и lib1_a.so. Есть библиотека lib2.so которая скомпилена с зависимостью от lib1.so. Есть бинарник, которому нужно lib2.so и lib1_a.so. Есть ли надёжный способ сделать (или оно по-дефолту так и будет) чтобы импорты lib2.so резолвились в lib1_a.so, подгруженную для бинарника, а не в lib1.so, которая указана в самом lib2?

Я знаю что есть LD_PRELOAD который такое гарантированно делает, но тут речь про то, чтобы всё сделать в бинарнике и без доп. костылей.

И ещё дополнение: обратная ситуация, в бинарнике зависимость от lib1.so, в lib2 - от lib1_a.so, надо чтобы всё резолвилось опять в lib1_a.so. Можно обобщить как «lib1_a.so имеет больший приоритет чем lib1.so, если они оказываются вместе».

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

 ,

firkax
()

Слежение за изменениями состояния питания

Форум — Development

Есть такая штука /sys/class/power_supply/ и в ней состояния питания от сети и от батареи. Есть ли возможность следить за событиями оттуда, кроме как вручную читать эти файлы раз в секунду? Если какой-то готовый демон уже занимается чтением раз в секунду и создаёт на этой основе события - это не в счёт, это тоже ручное чтение, речь идёт именно про ядерное API.

acpi_listen ничего не показывает на втыкание/вытыкание питания

Нашёл тут https://unix.stackexchange.com/questions/227918/system-event-on-ac-adapter-in... советы запустить `udevadm monitor`, он тоже ничего не показывает.

 ,

firkax
()

fwmx 1.2 — лёгкий оконный менеджер для x11

Новости — Open Source
fwmx 1.2 — лёгкий оконный менеджер для x11
Группа Open Source

Вышла версия 1.2 набора программ fwmx, включающих в себя собственно оконный менеджер (fwm), меню запуска приложений и регулятор громкости. В качестве индикатора раскладки используется xxkb.

Чего нового с момента прошлого релиза (v1.1 в октябре 2021):

  1. Улучшения в календаре:
  • его геометрия теперь может динамически сжиматься на слишком узких экранах;
  • теперь показываются дни от соседних месяцев до полной недели;
  • поддерживается список праздников (раньше только суббота/воскресенье);
  1. Панель задач теперь следит за изменениями разрешения экрана и подстраивается;
  2. Улучшения к регуляторе громкости:
  • новый формат командной строки;
  • шаги громче/тише теперь равны друг другу (раньше вверх делалось меньше из-за ошибок округления);
  • теперь следит за изменениями разрешения экрана аналогично панели задач;
  1. Добавлено меню запуска приложений (раньше весь запуск предполагался через хоткеи, что в общем-то вполне хорошо, но надо давать пользователю выбор).

Проект нацелен на максимальную простоту при наличии необходимой функциональности.

Поддерживается ведение списка окон, присвоение им статусов «всегда сверху», «сверху когда активно» и просто визуальное выделение цветом кнопки на панели задач. Кнопки можно передвигать. Управление самими окнами (не в панели задач) — мышкой при нажатом Super, заголовки и т.п. не рисуются.

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

Найденное вменяемое место где можно брать списки праздников: xmlcalendar.ru. Или тут список для России за 2022 год.

Меню отображает дерево директорий из заданного места (или нескольких мест параллельно) на структуру меню и подменю. Обычные файлы для запуска — просто исполняемые (chmod +x) скрипты, бинарники или симлинки на них. Так же имеется базовая поддержка формата файлов .desktop для совместимости с имеющимися системами. Меню находится на стадии бета-версии, однако касается это в основном недостаточной аккуратности исходного кода и почти отсутствия настроек. Явных багов быть не должно.

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

Программа распространяется в виде исходных кодов (в основном GPLv2), есть так же готовые пакеты для Debian-based дистрибутивов.

>>> Подробности

 ,

firkax
()

debian, nvidia-kernel-dkms i386 & amd64

Форум — Desktop

Возможно ли одновременно иметь dkms и для 32-битных и для 64-битных ядер? Чтобы он сам собирал модули к обеим разрядностям автоматически, как это делается если есть только одна разрядность?

Проблема:

# apt-get install nvidia-legacy-390xx-kernel-dkms:amd64
Рекомендуемые пакеты:
  nvidia-legacy-390xx-driver:amd64 | libnvidia-legacy-390xx-cuda1:amd64
Следующие пакеты будут УДАЛЕНЫ:
  nvidia-legacy-390xx-kernel-dkms
Следующие НОВЫЕ пакеты будут установлены:
  nvidia-legacy-390xx-kernel-dkms:amd64

Он хочет снести 32-битный dkms при установке 64-битного. Или 64-битный сможет для обоих ядер всё скомпилить?

 , ,

firkax
()

Почему начало блокчейна приписывают биткоинам а не гиту?

Форум — Talks

Ведь гит был намного раньше и в нём самый настоящий блокчейн, хоть и на не совсем современной хэш-функции (sha1). А может даже и гит был не первым - я не изучал, сам ли Линус придумал этот способ хранения коммитов или позаимствовал откуда-то, ведь до гита он пользовался какой-то другой системой контроля версий, может в ней было.

Вобщем, возможно изобретатель блокчейна это Линус Торвальдс, на 4 года раньше чем появились биткоины, а может и ещё кто-то раньше. Нечестно что не его за это хвалят.

 , , ,

firkax
()

обновление debian -> devuan, костылинг dpkg/apt в середине

Форум — General

Есть у меня комп с установленной на него debian wheezy (7), ядром от jessie (8). Решил его обновить и перейти заодно на devuan т.к. вспомнил что обновление до нового дебиана установит туда гадостный systemd.

Начал с того что поставил туда apt от stretch (9) с локальных проверенных .deb-пакетов т.к. в более ранних была уязвимость https://lists.debian.org/debian-security-announce/2019/msg00010.html позволяющая RCE через mitm незащищённого соединения к репе. Для того чтобы apt от stretch поставился в wheezy и не ругался, пришлось немного покостылить libstdc++6, убрав из него строчки Breaks: и Depends: (чтобы он просто молча установился и не пытался мне снести пол-системы). Также, чтобы пакеты из новых релизов нормально конфигурировались, (об этом узнал позже, см ниже! ***) пришлось сделать фикс к пакету init-system-helpers-1.48 (от stretch), убрав из него всё что конфликтовало с wheezy, оставив скрипты deb-systemd-helper и deb-systemd-invoke (они нужны в preinst/postinst хуках новых пакетов в т.ч. в devuan), почистив метаданные от конфликтов и зависимостей и заменив версию на 1.47.999 чтобы потом он сам мог дальше обновиться. Получившийся дебиан (wheezy с добавками jessie/stretch) работал нормально.

После этого я установил вручную скаченный и проверенный devuan-keyring, заменил репы на «devuan ascii» (это аналог stretch-а из дебиановских версий, прыгать через 3 версии сразу до beowulf или тем более через 4 до chimaera не хотелось) и начал плавно обновляться. Начал с apt-get update / upgrade.

Вот тут случилась сомнительная ситуация. apt-get upgrade упал в середине настройки из-за отсутствующего deb-systemd-helper. Я этот файл ему организовал (см. выше про хак с init-system-helpers ***), запустил заново apt-get upgrade и вроде оно продолжилось. [!] Первый вопрос - он ничего при таком падении в середине не мог потерять? По виду было всё норм.

Дальше - почистил ненужные остатки вручную, делаю apt-get install eudev, он хочет снести пол-системы, потыкался как сделать эту операцию более щадящими способами, особо не нашёл, единственное заметил что его «план установки» выглядит менее варварским если сделать apt-get install eudev apt-file. Делаю (список удалённых/установленных пакетов запомнил в файл чтобы потом их перепроверить на предмет нужности). И он в середине опять падает :( На настройке какого-то perlmagick. Что именно в нём сломалось выяснить не удалось - потому что повторно уже даже не запускается, пишет что не может составить план установки из-за битых зависимостей. [!] Как так?! Он же уже начал исполнять этот запрос, раньше знал как его выполнить а теперь забыл? Вобщем, apt-get стал нерабочим, т.к. на любые команды он теперь ругается на нерезолвленные зависимости, половину пакетов, которые он собирался удалить, он удалил, какие-то не удалил, может быть что-то поставил. Советует apt-get install -f но тот так же не работает. Ну, я среди его ругани обнаружил остатки ненужного мне гнома, разбираться с конфликтами ненужных пакетов не хочу - поэтому просто вручную потёр их через dpkg --purge (это apt сломался а dpkg работает норм, правда пришлось вручную список к удалению составлять т.к. рекурсивно удалять он не умеет). И ещё несколько пакетов пришлось так удалить (потом поставлю заново), после чего apt-get install -f наконец соизволил придумать что он может сделать. Запускаю, он что-то удаляет/ставит. [!] Третий вопрос: после такого (упавший в неконсистентном состоянии apt, ручная чистка мусора через dpkg, опять запуск apt) apt тоже ничего не «потеряет»? Не мог он какие-то хуки в итоге забыть запустить от пакетов которые он в первый раз недоустановил?

apt-get опять падает, на этот раз на настройке lintian, с странным сообщением об ошибке, дословно не вспомню, но что-то типа «apt ожидал от dpkg 4 действия а тот сделал 0». Исправилось после запуска «dpkg-reconfigure lintian» (который кажется ничего не сделал), после чего apt-get install -f тоже стал ничего не делать и не ругаться. [!] Четвёртый вопрос: тут он тоже ничего не потерял? Судя по его логу до падения от lintian, он только начал этап настроек, а пакетов та было много, но после фикса lintian'а почему-то он ничего делать не продолжил. Впрочем, запущеный после этого ещё раз apt-get upgrade отработал уже нормально, ещё кучу всего обновил и ни разу неупал. Ребут компа тоже прошёл норм, правда иксы не запускаются, но это другая тема, ведь обновление ещё не закончено (ну, я надеюсь что это не связано с вопросами выше и не придётся вручную их чинить).

Если что, на сайте devuan нет гайда ни по обновлению с debian wheezy до чего угодно (минимум jessie), ни по обновлению с чего угодно до devuan ascii (к нему только чистая установка описана, а обновления до beowulf и chimaera - то более поздние релизы). Надеюсь это не потому что там возникают неразрешимые проблемы. ---- Вопросы (всего 4) помечены знаками «[!]» чтобы их было лучше видно в этой простыне.

 , , ,

firkax
()

Ручной тюнинг ModeLine, можно ли что-то повредить?

Форум — Linux-hardware

Благодаря китайцам, сэкономившим пару копеек на жилах для EDID в мониторном кабеле, занялся настройкой видеорежимов в xorg.conf.

Начал с того, что сдампил режимы, которые получаются с хорошим кабелем где монитор детектится, внёс их в xorg.conf - всё норм. Они почему-то отличаются от тех, что выдаёт cvt, на отличия я и обратил внимание, и решил потюнить длины строк/кадров вручную. Урезал где можно длину сигналов развёртки и промежутков между развёрткой и данными. Таким образом получилось, не меня пиксельную частоту (148.4МГц), поднять частоту кадров с 60Гц до 67Гц.

Режимы (как видно, у cvt меньше пиксельная частота и меньше межстрочные синхро-интервалы, я решил совместить большую частоту на нативном режиме и маленькие интервалы, а потом ещё их сократил):

# cvt -r
ModeLine "1920x1080MR" 138.50 1920 1968 2000 2080 1080 1083 1088 1111 +hsync -vsync
# autodetected
ModeLine  "1920x1080" 148.50 1920 2008 2052 2200 1080 1084 1089 1125 +hsync +vsync
# 67hz
ModeLine "1920x1080F" 148.50 1920 1955 1960 1980 1080 1084 1089 1120 +hsync +vsync

Вопрос - вредно ли это для чего-нить? Для видеокарты - вряд ли, думаю она и больше может. А вот монитор декларирует режим с 60Гц, а 67 официально не поддерживает, хоть и показывает на нём хорошо. Может есть какие-то подводные камни?

Я просто совершенно не уверен, что разницу между 60 и 67 хоть где-то замечу, но теоретически 67 чуточку лучше (меньше мерцание - меньше будет усталость глаз, вроде так?), и если это можно сделать полностью без какого-то побочного вреда, то почему бы и нет. А если если хоть какие-то причины этого не делать, то лучше не буду.

 

firkax
()

fproxy v80 — локальный прокси-сервер для фильтрации http(s)-трафика

Новости — Интернет
Группа Интернет

Опубликована 80-я версия кэширующего и антиспамного прокси-сервера для персонального использования c гибкими настройками.

( читать дальше... )

>>> Подробности

 , , ,

firkax
()

Версия firefox-esr в debian 11

Форум — General

Непонятно. С одной стороны тут

https://packages.debian.org/search?keywords=firefox-esr

вот такая и других нет

bullseye (stable) (web): веб-браузер Mozilla Firefox — версия с долгосрочной поддержкой
78.15.0esr-1~deb11u1: amd64 arm64 armhf i386 mips64el mipsel ppc64el s390x

сейчас у меня на i386 архитектуре ставится именно она.

С другой - недавно на одном компе с amd64 поставился 91.5.0 deb11u1. На сайте его тогда тоже не было. Но вижу что в debian 10 там имеется разделение - для amd64 91.5, для i386 78.15.

А вот тут http://security.debian.org/debian-security/pool/updates/main/f/firefox-esr/ вижу пакеты 91.5 и для i386 и для amd64.

Это баг или я чего-то упустил?

 ,

firkax
()

Дырявый докер

Форум — Security

TLDR: скопрометированный не-рут может стать рутом, если ему поможет скомпрометированный рут из другого контейнера.

Возможно это баян и ещё более возможно всем пофиг, но при наличии двух контейнеров, могущих общаться через UNIX-сокет (который через файлы типа «socket») они могут «делиться» друг с другом рут-правами (и другими). Общение через UNIX-сокет вполне может быть заложено штатно (например, nginx + php-fpm в разных контейнерах, связанные через локальный сокет), либо легко делается самостоятельно, если у двух контейнеров есть общий volume (в нём один может создать сокет а второй - подключиться к нему). На самом деле, в случае с volume всё может оказаться проще - один создаст suid-root бинарник а второй запустит, но кто-то может поставить туда nosuid/noexec и думать что этого достаточно - но нет.

Как поделиться правами: есть такая штука как SCM_RIGHTS, с помощью неё можно слать через сокет файловые дескрипторы. Допустим у нас есть контейнер A, в котором запущен с ограниченными правами злонамеренный, скомпрометированный либо просто принимающий внешние команды в роли демки (с расчётом на «он никуда не вылезет») софт. И есть контейнер B, в котором злонамеренный софт как-то смог получить рут-права. Непривилегированный процесс в контейнере A делает open(«/»), шлёт через сокет полученный файловый дескриптор привилегированному процессу в контейнере B, после чего привилегированный процесс из контейнера B через функции openat() и подобные получает полный рут-доступ к файловой системе контейнера A.

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

 ,

firkax
()

Одобряете ли вы действия Марака Сквайрса по внесению деструктивных изменений в свои популярные npm-пакеты colors и faker?

Голосования — Голосования(не подтверждено)

История происшествия тут: Разработчик внёс деструктивные изменения в NPM-пакеты colors и faker, применяемые в 20 тысячах проектах

 , faker, ,

firkax
()

RSS подписка на новые темы