Pular para o conteúdo
Documentação
Nesta página

Arquivos compactados e proteção

Um nível é exportado como pasta, tar.gz ou zip, opcionalmente com senha: zip com AES-256 ou OpenPGP. O SDK detecta o formato de um arquivo recebido pelos primeiros bytes, não pelo nome

Modos de exportação

Um nível sai do dispositivo em uma das formas de LevelExportMode:

ValorModoO que é gravadoProteção
0Folderuma pasta comum, com a mesma forma que no disconenhuma
1FolderProtectedLeveluma pasta em que só level.json.gpg é criptografadoOpenPGP
2TarGz<name>.tar.gznenhuma
3TarGzProtected<name>.tar.gz.gpgOpenPGP
4Zip<name>.zipnenhuma
5ZipProtected<name>.zip.gpgOpenPGP
6ZipEncrypted<name>.zip com entradas em AES-256a do próprio zip

O número é a identidade do modo e nunca muda. A ordem na lista suspensa do editor é definida à parte (DisplayOrder)

Todo formato é um padrão aberto. tar -xzf, gpg -d e qualquer compactador os abrem sem o jogo:

gpg -d level.tar.gz.gpg > level.tar.gz
tar -xzf level.tar.gz

Dois esquemas de proteção

ZipEncrypted é o jeito padrão de trancar um nível com senha. Quem recebe tem um compactador, mas muito provavelmente não tem o gpg

O OpenPGP tranca um documento, uma pasta e um arquivo compactado com um só esquema. Só ele consegue proteger uma pasta

Em FolderProtectedLevel os metadados, a capa e a mídia continuam legíveis. Por isso o navegador de níveis ainda mostra o cartão

A extensão interna fica no nome: level.json.gpg. É exatamente o nome que gpg -c level.json dá ao arquivo, então o formato é conhecido sem adivinhação

O que vai dentro

LevelArchiveBuilder calcula o conteúdo a partir do modelo, não da lista de arquivos da pasta. Um arquivo que o nível não referencia fica de fora. O relatório diz quantos arquivos assim ficaram

As referências do nível são tratadas assim:

  • um recurso com AbsolutePath é copiado para o arquivo compactado. A referência dele é reescrita para LevelPath, mas só na cópia exportada
  • DirectUrl fica como está e vai para o relatório: uma URL não pode viajar dentro de um arquivo
  • um arquivo ausente vai para o relatório com o código archive.resource_missing

Detecção pelos bytes

Qualquer um pode escrever um nome de arquivo. Por isso ArchiveFormatSniffer decide pelos primeiros 8 bytes:

Primeiros bytesFormato
1F 8BTarGz
50 4B 03 04, 50 4B 05 06, 50 4B 07 08, 50 4B 30 30Zip
37 7A BC AF 27 1CSevenZip
uma tag de pacote OpenPGP, verificada por últimoOpenPgp: descriptografado e detectado de novo
Aviso

.7z não é lido nem gravado. Ele só é detectado para que a recusa diga o nome dele (Unsupported). Então a pessoa recompacta o nível como zip em vez de concluir que o arquivo está quebrado

Leitura

LevelArchiveReader.ReadAsync recebe uma pasta ou um Stream com suporte a seek. Ele devolve LevelArchiveContent, em que LevelArchiveOpenResult é um destes valores:

ResultadoSignificado
Oklido
PassphraseRequirednão há senha, é preciso pedi-la
WrongPassphrasea pessoa já digitou uma senha, e ela está errada
Damagedo arquivo está danificado
NotAnArchiveisto não é um arquivo compactado
Unsupportedo formato é reconhecido, mas não é suportado

PeekMetaAsync lê só os metadados, para um cartão ou um catálogo

Um servidor lê o que quer que alguém tenha decidido enviar. Por isso o leitor trabalha dentro de ArchiveLimits. Por padrão, os limites são:

  • 4096 entradas
  • 512 MiB por entrada
  • 1 GiB no total

Nada é descompactado fora do armazenamento que foi dado ao leitor

A exportação pelo lado do editor - Exportação e proteção