包格式
简介
应用程序管理器使用一个非常简单的包格式:一个标准的UNIX gzip压缩的TAR存档。元数据作为正常文件嵌入,但使用保留名称前缀--PACKAGE-
。尽管USTAR tar存档支持很多特性,但应用程序管理器仅支持具有相对路径的标准文件和目录(路径中使用../
不允许)。除了所有者的x
位外,模式将被忽略。
这使得编写自定义打包器以及自定义app-store服务器后端变得非常容易,因为TAR存档处理可以作为任何编程语言的实用库使用。
注意:目前gzip是硬编码的,但由于压缩和解压缩是通过libarchive完成的,因此可以轻松替换为bzip2或xz压缩。这两种方法都会在Windows上导致额外的第三方依赖。
以下是一些重要的包文件
文件 | 说明 |
---|---|
--PACKAGE-HEADER-- | 确切的一个YAML文档,必须是包中的第一个文件——下面将描述其格式。此文件用作格式选择器。 |
info.yaml | 应用程序的清单。打包工具需要确保此文件位于tar存档的前10个条目中。请参阅清单定义以了解文件格式的文档。 |
icon.png | 用于app-store的应用程序图标,也可以用作设备上启动菜单中的应用程序图标:请参阅info.yaml。打包工具需要确保此文件位于tar存档的前10个条目中。 |
--PACKAGE-FOOTER-- | 一个或多个必须放在包最后一个文件(项)的YAML文档(项)——下面将描述其格式。如果需要添加多个页脚(例如,通过app-store服务器添加store签名),则可以在文件名中附加任意字符串(例如--PACKAGE-FOOTER--storesig )。这样做更容易对包进行故障排除,因为您可以使用标准的tar命令行工具轻松提取它们。 |
总之,以下是一些不允许在包中出现的项目
- 不允许文件名以
--PACKAGE-
开头 - 不允许使用绝对路径
- 不允许在相对路径中使用
../
- 不允许有符号链接、硬链接、设备文件、套接字等。
- 文件模式(除所有者的
x
位外)将被忽略。
校验和算法
所有包数据以及重要的元数据都通过SHA256摘要进行保护。这个校验和有两个用途:它能够保护数据传输过程中的错误,并且通过加密这个校验和来完成包的签名。
这个校验和的实际计算方法如下:
- 对于不是
--PACKAGE-*
元数据文件的每一个文件,它的完整内容都会添加到摘要中。之后,以下UTF-8编码的字符串也会添加到摘要中:"F/<文件大小(字节>/<文件路径>"
(例如,一个大小为250字节的foo/test.qml
文件将生成F/250/foo/test.qml
)。 - 对于每一个目录,以下UTF-8编码的字符串会被添加到摘要中:
"D/0/<目录路径>"
(例如,foo/images
目录将生成D/0/foo/images
)。
生成的摘要会被放入--PACKAGE-FOOTER--
中,作为一个32字节的十六进制编码字符串。
签名算法
当前包格式支持两种签名:开发者签名(在上传到appstore服务器之前由开发者生成)和商店签名(在客户端实际下载包之前由appstore服务器生成)。
这两种签名以相同的方式进行计算,并按相同的方式附加到包的元数据中:使用二进制摘要作为输入创建一个分离的PKCS7签名。然后,将这个PKCS7签名进行BASE64编码,并存储在--PACKAGE-FOOTER--
字段中,无论是developerSignature
还是storeSignature
字段。
如果您想自己实现这个签名算法,请查看以下四个现有实现:
- C++ OpenSSL,基于
src/crypto-lib/signature_openssl.cpp
- C++ WinCrypt,基于
src/crypto-lib/signature_win.cpp
(仅限Windows) - C++ SecurityFramework,基于
src/crypto-lib/signature_macos.cpp
(仅限macOS) - Python m2crypt,基于appstore服务器参考实现。
头部和尾部文件格式
--PACKAGE-FOOTER--
和--PACKAGE-HEADER--
文件头部(第一个YAML文档)中的字段如下:
字段名称 | 类型 | 说明 |
---|---|---|
formatVersion | int | 必需。当前总是2 。 |
formatType | string | 必需。对于头部始终是am-package-header ,对于尾部始终是am-package-footer 。 |
--PACKAGE-FOOTER--
和--PACKAGE-HEADER--
数据(第二个YAML文档)中的字段如下:
字段名称 | 类型 | 说明 |
---|---|---|
id | string | 包的唯一标识符。这必须与伴随的info.yaml 清单文件中描述的包ID相匹配。 |
icon | string | 必需。图标的文件名。该文件必须位于与info.yaml 相同的目录中,并且可以是Qt支持的任何图像格式。 |
注意:旧格式(5.14之前)将formatVersion头部字段设置为1
,并且使用applicationId
字段代替packageId
字段。
示例包
这是一个最小QML应用程序包的示例。可以通过使用以下命令将这些文件压缩成tar文件来创建实际的包:
tar cvzf qmlapp.appkg ./--PACKAGE-HEADER-- info.yaml icon.png main.qml ./--PACKAGE-FOOTER--
文件 | 内容 |
---|---|
--PACKAGE-HEADER-- | %YAML 1.1 --- formatType: am-package-header formatVersion: 2 --- packageId: com.pelagicore.minimal diskSpaceUsed: 1000 |
info.yaml | %YAML 1.1 --- formatType: am-package formatVersion: 1 --- id: 'com.pelagicore.minimal' icon: 'icon.png' name: en: 'Minimal App' applications: - id: com.pelagicore.minimalapp code: 'main.qml' runtime: 'qml' |
icon.png | 一个标准的png图像 |
main.qml | 您的QML应用程序 |
--PACKAGE-FOOTER-- | %YAML 1.1 --- formatType: am-package-footer formatVersion: 2 --- # SHA256 digest in 32 char hex representation digest: '9df5635bb50e93846954c6377468c07835119e2835475ec90b3e9a9f7261cf27' |
© 2024 The Qt Company Ltd。此处包含的文档贡献均为各自所有者的版权。所提供的文档根据由自由软件基金会发布的GNU自由文档许可证的1.3版条款许可。 Qt及其相关标志是The Qt Company Ltd.在芬兰及/或全球其他国家的商标。所有其他商标均为其各自所有者的财产。