11package deploys
22
33import (
4- "archive/zip "
4+ "archive/tar "
55 "errors"
66 "fmt"
77 "io"
@@ -52,22 +52,22 @@ func (cd *CertDeployer) DeployCertificate(domain, url string) error {
5252 // 处理泛域名,将 * 转换为 _
5353 safeDomain := SanitizeDomain (domain )
5454
55- // 文件名格式为 {domain}_certificates.zip
56- fileName := fmt .Sprintf ("%s_certificates.zip " , safeDomain )
57- zipFile := filepath .Join (CertsDir , fileName )
55+ // 文件名格式为 {domain}_certificates.tar
56+ fileName := fmt .Sprintf ("%s_certificates.tar " , safeDomain )
57+ tarFile := filepath .Join (CertsDir , fileName )
5858
59- // 下载zip文件
60- if err := cd .downloadFunc (url , zipFile ); err != nil {
59+ // 下载tar文件
60+ if err := cd .downloadFunc (url , tarFile ); err != nil {
6161 return fmt .Errorf ("下载证书失败: %w" , err )
6262 }
6363
64- logger .Info ("证书下载完成" , "file" , zipFile )
64+ logger .Info ("证书下载完成" , "file" , tarFile )
6565
6666 // 确保下载失败时清理
6767 defer func () {
68- if _ , err := os .Stat (zipFile ); err == nil {
69- // 部署成功后删除zip文件
70- os .Remove (zipFile )
68+ if _ , err := os .Stat (tarFile ); err == nil {
69+ // 部署成功后删除tar文件
70+ os .Remove (tarFile )
7171 }
7272 }()
7373
@@ -80,16 +80,16 @@ func (cd *CertDeployer) DeployCertificate(domain, url string) error {
8080 onePanelEnabled := sslConfig .OnePanel != nil && sslConfig .OnePanel .URL != ""
8181
8282 if nginxPath == "" && apachePath == "" && rustFSPath == "" && ! feiNiuEnabled && ! onePanelEnabled {
83- logger .Info ("未配置SSL目录,证书已下载" , "file" , zipFile )
83+ logger .Info ("未配置SSL目录,证书已下载" , "file" , tarFile )
8484 return nil
8585 }
8686
8787 // 证书文件夹名(使用处理后的安全域名)
8888 folderName := safeDomain
8989 extractDir := filepath .Join (CertsDir , folderName )
9090
91- // 1. 解压zip文件
92- if err := ExtractZip ( zipFile , extractDir ); err != nil {
91+ // 1. 解压tar文件
92+ if err := ExtractTar ( tarFile , extractDir ); err != nil {
9393 // 清理失败的解压文件
9494 os .RemoveAll (extractDir )
9595 return fmt .Errorf ("解压证书失败: %w" , err )
@@ -167,76 +167,87 @@ func (cd *CertDeployer) DeployCertificate(domain, url string) error {
167167 return nil
168168}
169169
170- // ExtractZip 解压zip文件
171- func ExtractZip ( zipFile , extractDir string ) error {
170+ // ExtractTar 解压tar文件
171+ func ExtractTar ( tarFile , extractDir string ) error {
172172 // 创建解压目录
173173 if err := os .MkdirAll (extractDir , 0755 ); err != nil {
174174 return fmt .Errorf ("创建解压目录失败: %w" , err )
175175 }
176176
177- // 打开zip文件
178- reader , err := zip . OpenReader ( zipFile )
177+ // 打开tar文件
178+ reader , err := os . Open ( tarFile )
179179 if err != nil {
180- return fmt .Errorf ("打开zip文件失败 : %w" , err )
180+ return fmt .Errorf ("打开tar文件失败 : %w" , err )
181181 }
182182 defer reader .Close ()
183183
184+ tarReader := tar .NewReader (reader )
185+
184186 // 解压所有文件
185- for _ , file := range reader .File {
186- if err := extractZipFile (file , extractDir ); err != nil {
187+ for {
188+ header , err := tarReader .Next ()
189+ if errors .Is (err , io .EOF ) {
190+ return nil
191+ }
192+ if err != nil {
193+ return fmt .Errorf ("读取tar文件失败: %w" , err )
194+ }
195+
196+ if err := extractTarFile (header , tarReader , extractDir ); err != nil {
187197 return err
188198 }
189199 }
190-
191- return nil
192200}
193201
194- // extractZipFile 解压单个zip文件条目
195- func extractZipFile (file * zip.File , extractDir string ) error {
202+ // extractTarFile 解压单个tar文件条目
203+ func extractTarFile (header * tar.Header , reader io.Reader , extractDir string ) error {
204+ if header == nil || header .Name == "" {
205+ return nil
206+ }
207+
196208 // 使用 filepath.Rel 安全地检查路径
197- targetPath := filepath .Join (extractDir , file .Name )
209+ targetPath := filepath .Join (extractDir , header .Name )
198210
199211 // 清理路径并检查符号链接
200212 cleanTarget := filepath .Clean (targetPath )
201213 rel , err := filepath .Rel (extractDir , cleanTarget )
202214 if err != nil || strings .HasPrefix (rel , ".." ) || strings .Contains (rel , ".." + string (filepath .Separator )) {
203- return fmt .Errorf ("不安全的文件路径: %s" , file .Name )
215+ return fmt .Errorf ("不安全的文件路径: %s" , header .Name )
204216 }
205217
206218 // 使用清理后的路径
207219 targetPath = cleanTarget
208220
209- // 创建目录
210- if file .FileInfo ().IsDir () {
211- return os .MkdirAll (targetPath , file .FileInfo ().Mode ())
221+ mode := os .FileMode (header .Mode )
222+ switch header .Typeflag {
223+ case tar .TypeDir :
224+ return os .MkdirAll (targetPath , mode )
225+ case tar .TypeReg , tar .TypeRegA :
226+ // 继续处理普通文件
227+ default :
228+ // 跳过符号链接、硬链接和设备文件等特殊条目
229+ return nil
212230 }
213231
214232 // 创建文件目录
215233 if err := os .MkdirAll (filepath .Dir (targetPath ), 0755 ); err != nil {
216234 return fmt .Errorf ("创建文件目录失败: %w" , err )
217235 }
218236
219- // 打开zip文件中的文件
220- rc , err := file .Open ()
221- if err != nil {
222- return fmt .Errorf ("打开zip中的文件失败: %w" , err )
223- }
224- defer rc .Close ()
225-
226237 // 创建目标文件
227- outFile , err := os .Create (targetPath )
238+ outFile , err := os .OpenFile (targetPath , os . O_CREATE | os . O_WRONLY | os . O_TRUNC , mode )
228239 if err != nil {
229240 return fmt .Errorf ("创建文件失败: %w" , err )
230241 }
231242 defer outFile .Close ()
232243
233244 // 复制文件内容
234- if _ , err := io .Copy (outFile , rc ); err != nil {
245+ if _ , err := io .Copy (outFile , reader ); err != nil {
235246 return fmt .Errorf ("复制文件内容失败: %w" , err )
236247 }
237248
238249 // 设置文件权限
239- if err := os .Chmod (targetPath , file . FileInfo (). Mode () ); err != nil {
250+ if err := os .Chmod (targetPath , mode ); err != nil {
240251 return fmt .Errorf ("设置文件权限失败: %w" , err )
241252 }
242253
0 commit comments