Архивы и защита
Как SDK упаковывает уровень в один файл или закрывает его паролем и как распознаёт, что ему передали
Режимы экспорта
Уровень покидает устройство в одной из форм LevelExportMode:
| Значение | Режим | Что пишется | Защита |
|---|---|---|---|
| 0 | Folder | обычная папка, та же форма, что на диске | нет |
| 1 | FolderProtectedLevel | папка, где зашифрован только level.json.gpg | OpenPGP |
| 2 | TarGz | <имя>.tar.gz | нет |
| 3 | TarGzProtected | <имя>.tar.gz.gpg | OpenPGP |
| 4 | Zip | <имя>.zip | нет |
| 5 | ZipProtected | <имя>.zip.gpg | OpenPGP |
| 6 | ZipEncrypted | <имя>.zip с записями в AES-256 | собственная у zip |
Число - это идентичность режима, оно никогда не меняется. Порядок в выпадающем списке редактора задан отдельно (DisplayOrder)
Каждый формат - открытый стандарт. tar -xzf, gpg -d и любой архиватор открывают их без игры:
gpg -d level.tar.gz.gpg > level.tar.gz
tar -xzf level.tar.gz
Две схемы защиты
ZipEncrypted - способ по умолчанию закрыть уровень паролем. У получателя есть архиватор, а gpg, скорее всего, нет
OpenPGP закрывает документ, папку и архив одной схемой. Только он умеет защитить папку
В FolderProtectedLevel метаданные, обложка и медиа остаются читаемыми. Поэтому браузер уровней всё ещё показывает карточку
Внутреннее расширение остаётся в имени: level.json.gpg. Ровно так файл называет gpg -c level.json, поэтому формат известен без догадок
Что попадает внутрь
LevelArchiveBuilder вычисляет содержимое по модели, а не по списку файлов в папке. Файл, на который уровень не ссылается, остаётся снаружи. Отчёт говорит, сколько таких осталось
Ссылки уровня обрабатываются так:
- ресурс с
AbsolutePathкопируется в архив. Его ссылка переписывается наLevelPath, но только в экспортированной копии DirectUrlостаётся как есть и попадает в отчёт: URL не может ехать внутри файла- отсутствующий файл попадает в отчёт с кодом
archive.resource_missing
Распознавание по байтам
Имя файла может написать кто угодно. Поэтому ArchiveFormatSniffer решает по первым 8 байтам:
| Первые байты | Формат |
|---|---|
1F 8B | TarGz |
50 4B 03 04, 50 4B 05 06, 50 4B 07 08, 50 4B 30 30 | Zip |
37 7A BC AF 27 1C | SevenZip |
| тег пакета OpenPGP, проверяется последним | OpenPgp: расшифровывается и распознаётся заново |
.7z не читается и не пишется. Он распознаётся только затем, чтобы отказ назвал его по имени (Unsupported). Тогда человек перепакует уровень в zip, а не решит, что файл сломан
Чтение
LevelArchiveReader.ReadAsync принимает папку или Stream с поддержкой перемотки. Он возвращает LevelArchiveContent, где LevelArchiveOpenResult - одно из значений:
| Результат | Значение |
|---|---|
Ok | прочитано |
PassphraseRequired | пароля нет, его нужно спросить |
WrongPassphrase | человек уже ввёл пароль, и он неверный |
Damaged | файл повреждён |
NotAnArchive | это не архив |
Unsupported | формат распознан, но не поддерживается |
PeekMetaAsync читает только метаданные, для карточки или каталога
Сервер читает то, что кто-то решил загрузить. Поэтому читатель работает в рамках ArchiveLimits. По умолчанию это:
- 4096 записей
- 512 МиБ на запись
- 1 ГиБ всего
Ничего не распаковывается за пределы хранилища, которое ему дали
Экспорт со стороны редактора - Экспорт и защита