Index: client/pkgd.eagle ================================================================== --- client/pkgd.eagle +++ client/pkgd.eagle @@ -84,10 +84,11 @@ # added if it is already present. The language argument must be the # literal string "eagle" or the literal string "tcl". The directory # argument is the fully qualified path for the directory to add to # the auto-path. # + # proc addToAutoPath { language directory } { # # NOTE: Add the specified directory to the auto-path if not already # present. # @@ -135,13 +136,20 @@ # the literal string "1.0" when the language is "eagle". The # fileNames argument must be a well-formed list of file names to # download, each one relative to the language/version-specific # directory on the package file server. The persistent argument # should be non-zero if the downloaded files should be saved to - # permanent storage for subsequent use. + # permanent storage for subsequent use. The usePgp argument + # should be non-zero when an OpenPGP signature file needs to be + # downloaded and verified for each downloaded file. The + # useAutoPath argument should be non-zero to modify the auto-path + # to include the temporary or persistent directories containing + # the downloaded files. # - proc downloadFiles { language version fileNames persistent } { + # + proc downloadFiles { + language version fileNames persistent usePgp useAutoPath } { variable baseUri variable downloadUri variable persistentDirectory variable quiet @@ -156,23 +164,29 @@ } else { error "unsupported language" } if {$persistent} then { - set downloadRootDirectory [file join $persistentDirectory] + set downloadRootDirectory $persistentDirectory } else { + set directoryNameOnly [appendArgs \ + pkgd_ [string trim [pid] -] _ [string trim [clock seconds] -]] + global env if {[info exists env(PKGD_TEMP)]} then { - set downloadRootDirectory [file join $env(PKGD_TEMP) pkgr] + set downloadRootDirectory $env(PKGD_TEMP) } elseif {[info exists env(TEMP)]} then { - set downloadRootDirectory [file join $env(TEMP) pkgr] + set downloadRootDirectory $env(TEMP) } elseif {[info exists env(TMP)]} then { - set downloadRootDirectory [file join $env(TMP) pkgr] + set downloadRootDirectory $env(TMP) } else { error "please set PKGD_TEMP (via environment) to temporary directory" } + + set downloadRootDirectory [file join \ + $downloadRootDirectory $directoryNameOnly] } set downloadDirectories [list] foreach fileName $fileNames { @@ -187,40 +201,72 @@ if {[llength $directoryParts] == 0} then { error [appendArgs \ "bad file name \"" $fileName "\", no directory parts"] } - set downloadDirectory [eval file join \ - [list $downloadRootDirectory] $directoryParts] + set downloadDirectory [file normalize [eval file join \ + [list $downloadRootDirectory] $directoryParts]] - set downloadFileName [file join $downloadDirectory \ - [file tail $fileName]] + set downloadFileName [file normalize [file join \ + $downloadDirectory [file tail $fileName]]] if {!$persistent} then { catch {file delete $downloadFileName} } file mkdir [file dirname $downloadFileName] + set savedFileName $fileName set fileName [file join $language $version $fileName] set uri [subst $downloadUri] + set fileName $savedFileName if {[isEagle]} then { - writeFile $downloadFileName [interp readorgetscriptfile -- "" $uri] + writeFile $downloadFileName \ + [interp readorgetscriptfile -- "" $uri] } else { - writeFile $downloadFileName [::PackageRepository::getFileViaHttp \ - $uri 10 stdout $quiet] + writeFile $downloadFileName \ + [::PackageRepository::getFileViaHttp $uri 10 stdout $quiet] + } + + if {$usePgp} then { + set downloadSignatureFileName [appendArgs $downloadFileName .asc] + + set savedFileName $fileName + set fileName [file join \ + $language $version [appendArgs $fileName .asc]] + + set uri [subst $downloadUri] + set fileName $savedFileName + + if {[isEagle]} then { + writeFile $downloadSignatureFileName \ + [interp readorgetscriptfile -- "" $uri] + } else { + writeFile $downloadSignatureFileName \ + [::PackageRepository::getFileViaHttp $uri 10 stdout $quiet] + } + + if {![::PackageRepository::verifyPgpSignature \ + $downloadSignatureFileName]} then { + error [appendArgs \ + "bad PGP signature \"" $downloadSignatureFileName \"] + } } - lappend downloadDirectories [file dirname $downloadDirectory] + lappend downloadDirectories $downloadDirectory } set downloadDirectories [lsort -unique $downloadDirectories] - foreach downloadDirectory $downloadDirectories { - addToAutoPath $language $downloadDirectory + if {$useAutoPath} then { + foreach downloadDirectory $downloadDirectories { + addToAutoPath $language $downloadDirectory + } } + + return $downloadDirectories } # # NOTE: Setup the variables, within this namespace, used by this script. # Index: client/pkgd.eagle.harpy ================================================================== --- client/pkgd.eagle.harpy +++ client/pkgd.eagle.harpy @@ -19,32 +19,32 @@ None Mistachkin Systems - 2c09ab50-08d8-47a0-8d50-96529e4cf6fd + df73bc96-0ad4-43ed-9653-7f8f36169967 SHA512 Script - 2016-08-17T22:38:23.1247578Z + 2016-08-19T01:42:14.2969219Z -1.00:00:00 0x2c322765603b5278 - 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 Index: client/pkgr.eagle ================================================================== --- client/pkgr.eagle +++ client/pkgr.eagle @@ -338,11 +338,12 @@ # The apiKey argument is the API key to use -OR- an empty string if # a public package is being looked up. The package argument is the # name of the package, it cannot be an empty string. The version # argument is the specific version being looked up -OR- an empty # string for any available version. This procedure may raise script - # errors. + # errors. All line-endings are normalized to Unix-style; therefore, + # all script signatures must assume this. # proc getLookupData { apiKey package version } { variable verboseUriDownload set uri [getLookupUri $apiKey $package $version] @@ -368,11 +369,10 @@ "raw response data is: " $data] } set data [string map [list <\; < >\; > "\; \" &\; &] $data] set data [string map [list \r\n \n \r \n] $data] - set data [string map [list \n \r\n] $data] set data [string trim $data] return $data } Index: client/pkgr.eagle.harpy ================================================================== --- client/pkgr.eagle.harpy +++ client/pkgr.eagle.harpy @@ -19,32 +19,32 @@ None Mistachkin Systems - ba94806a-9b8d-4e88-bab7-13bf861cac0d + 4e5a63d2-af93-4521-9477-bd723121aa3a SHA512 Script - 2016-08-19T00:09:46.0088359Z + 2016-08-19T01:36:23.6406719Z -1.00:00:00 0x2c322765603b5278 - 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