1616package resources
1717
1818import (
19+ "context"
20+ "errors"
1921 "net/url"
2022 "path"
2123 "strings"
@@ -25,6 +27,7 @@ import (
2527 "github.com/arduino/arduino-cli/arduino/security"
2628 rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
2729 "github.com/arduino/go-paths-helper"
30+ "github.com/codeclysm/extract/v3"
2831 "go.bug.st/downloader/v2"
2932)
3033
@@ -56,8 +59,42 @@ func (res *IndexResource) Download(destDir *paths.Path, downloadCB rpc.DownloadP
5659 return & arduino.FailedDownloadError {Message : tr ("Error downloading index '%s'" , res .URL ), Cause : err }
5760 }
5861
62+ var signaturePath , tmpSignaturePath * paths.Path
63+ hasSignature := false
64+
5965 // Expand the index if it is compressed
60- if strings .HasSuffix (indexFileName , ".gz" ) {
66+ if strings .HasSuffix (indexFileName , ".tar.bz2" ) {
67+ indexFileName = strings .TrimSuffix (indexFileName , ".tar.bz2" ) + ".json" // == package_index.json
68+ signatureFileName := indexFileName + ".sig"
69+ signaturePath = destDir .Join (signatureFileName )
70+
71+ // .tar.gz may contain both index and signature
72+
73+ // Extract archive in a tmp/archive subdirectory
74+ f , err := tmpIndexPath .Open ()
75+ if err != nil {
76+ return & arduino.PermissionDeniedError {Message : tr ("Error extracting %s" , tmpIndexPath ), Cause : err }
77+ }
78+ defer f .Close ()
79+ tmpArchivePath := tmp .Join ("archive" )
80+ _ = tmpArchivePath .MkdirAll ()
81+ if err := extract .Bz2 (context .Background (), f , tmpArchivePath .String (), nil ); err != nil {
82+ return & arduino.PermissionDeniedError {Message : tr ("Error extracting %s" , tmpIndexPath ), Cause : err }
83+ }
84+
85+ // Look for index.json
86+ tmpIndexPath = tmpArchivePath .Join (indexFileName )
87+ if ! tmpIndexPath .Exist () {
88+ err := errors .New (tr ("%s not found" , indexFileName ))
89+ return & arduino.FailedDownloadError {Message : tr ("Invalid index archive" ), Cause : err }
90+ }
91+
92+ // Look for signature
93+ if t := tmpArchivePath .Join (signatureFileName ); t .Exist () {
94+ tmpSignaturePath = t
95+ hasSignature = true
96+ }
97+ } else if strings .HasSuffix (indexFileName , ".gz" ) {
6198 indexFileName = strings .TrimSuffix (indexFileName , ".gz" ) // == package_index.json
6299 tmpUnzippedIndexPath := tmp .Join (indexFileName )
63100 if err := paths .GUnzip (tmpIndexPath , tmpUnzippedIndexPath ); err != nil {
@@ -67,7 +104,6 @@ func (res *IndexResource) Download(destDir *paths.Path, downloadCB rpc.DownloadP
67104 }
68105
69106 // Check the signature if needed
70- var signaturePath , tmpSignaturePath * paths.Path
71107 if res .SignatureURL != nil {
72108 // Compose signature URL
73109 signatureFileName := path .Base (res .SignatureURL .Path )
@@ -79,6 +115,10 @@ func (res *IndexResource) Download(destDir *paths.Path, downloadCB rpc.DownloadP
79115 return & arduino.FailedDownloadError {Message : tr ("Error downloading index signature '%s'" , res .SignatureURL ), Cause : err }
80116 }
81117
118+ hasSignature = true
119+ }
120+
121+ if hasSignature {
82122 // Check signature...
83123 if valid , _ , err := security .VerifyArduinoDetachedSignature (tmpIndexPath , tmpSignaturePath ); err != nil {
84124 return & arduino.PermissionDeniedError {Message : tr ("Error verifying signature" ), Cause : err }
@@ -109,12 +149,12 @@ func (res *IndexResource) Download(destDir *paths.Path, downloadCB rpc.DownloadP
109149 if err := tmpIndexPath .CopyTo (indexPath ); err != nil {
110150 return & arduino.PermissionDeniedError {Message : tr ("Error saving downloaded index" ), Cause : err }
111151 }
112- if res . SignatureURL != nil {
152+ if hasSignature {
113153 if err := tmpSignaturePath .CopyTo (signaturePath ); err != nil {
114154 return & arduino.PermissionDeniedError {Message : tr ("Error saving downloaded index signature" ), Cause : err }
115155 }
116156 }
117- oldIndex .Remove ()
118- oldSignature .Remove ()
157+ _ = oldIndex .Remove ()
158+ _ = oldSignature .Remove ()
119159 return nil
120160}
0 commit comments