DELETED client/1.0/VERSION Index: client/1.0/VERSION ================================================================== --- client/1.0/VERSION +++ client/1.0/VERSION @@ -1,1 +0,0 @@ -1.0 DELETED client/1.0/VERSION.asc Index: client/1.0/VERSION.asc ================================================================== --- client/1.0/VERSION.asc +++ client/1.0/VERSION.asc @@ -1,18 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v2 -Comment: Eagle Package Repository - -iQIcBAABCAAGBQJXt4qVAAoJEFAslq9JXcLZI+IP/iR3JMHwLYyiYjsJogm0YH6z -dU6QaiaZiONne+eIPOFKYeotbJ4pHw3EWnk1XRsmKA+6QfZ2Cmp+V2ANDjncXqC6 -e8SpztuhGIkDC4MoQHviff1MvE9CQK/89xCG+HcBr+a25Lh4vYROSLunn8BMfC58 -khEJTcmhdhdc+up5v20Y1qDR9DM21WguQLfUg0vTB1G+6QAa5tfz5h6r0yWyus3F -Din5TTpBR0if4Fxcbmhub7GCZTaifn2Oc25usYJCiAWBqyxP4foK5oMEkajhBFc6 -78lzo7xlqH0TPPOJP3iOGph1tOG9R0IT0Eduqk2yPkgZ18M9m1StYK7isGI5qUIU -/7XXeqjbtIR3w1V04EZnonKunVPgP2YsB9BowiGWi1igbSt0HzwdHRRBdTsXPwN4 -yqKAiariH7ZU8L7c7yxpf79tR+wHmfbR6BF5KtzN+7jRHJnq803IHYLDwxd/Yiqr -HNewIKTWdRBIAvJE0FR/XLRLUnUz3rGLGKAlF1JQMxKDCSRTFEdpWffRvsg48x8z -NDS2I9SaVwHLL/Zm1eO7zBFt8jvtjxsdXyb8aFMrmcUuh55yjqefoYR+XX9DsS65 -0Tf7fNPg+tgsC2jO1LbJsYksn5NSLMgbo6Gt515WRymJY9uX84NWi+C9Wx0ZyUAa -B19h6sHUadZq9LpGgZds -=5zVB ------END PGP SIGNATURE----- DELETED client/1.0/license.terms Index: client/1.0/license.terms ================================================================== --- client/1.0/license.terms +++ client/1.0/license.terms @@ -1,38 +0,0 @@ -This software is copyrighted by Joe Mistachkin and other parties. The -following terms apply to all files associated with the software unless -explicitly disclaimed in individual files. - -The authors hereby grant permission to use, copy, modify, distribute, -and license this software and its documentation for any purpose, provided -that existing copyright notices are retained in all copies and that this -notice is included verbatim in any distributions. No written agreement, -license, or royalty fee is required for any of the authorized uses. -Modifications to this software may be copyrighted by their authors -and need not follow the licensing terms described here, provided that -the new terms are clearly indicated on the first page of each file where -they apply. - -IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY -FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES -ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY -DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE -IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE -NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR -MODIFICATIONS. - -GOVERNMENT USE: If you are acquiring this software on behalf of the -U.S. government, the Government shall have only "Restricted Rights" -in the software and related documentation as defined in the Federal -Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you -are acquiring the software on behalf of the Department of Defense, the -software shall be classified as "Commercial Computer Software" and the -Government shall have only "Restricted Rights" as defined in Clause -252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the -authors grant the U.S. Government and others acting in its behalf -permission to use and distribute the software in accordance with the -terms specified in this license. DELETED client/1.0/license.terms.asc Index: client/1.0/license.terms.asc ================================================================== --- client/1.0/license.terms.asc +++ client/1.0/license.terms.asc @@ -1,18 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v2 -Comment: Eagle Package Repository - -iQIcBAABCAAGBQJX+TvEAAoJEFAslq9JXcLZHO0QALTJ7noDN6WZ+3vtfO1AtqsA -rsGHk5cdD/O0AJSTjZNTwr88UJ1l4sK3FfETzhZfK86Gyx3D/IhQ/CyPI0BUA/4+ -HIPV9yWGkM1XN+Qmef8Yk4D2hgkhtDV3ZXNIXFEH660w3jro7mNDkEyxw7pnDkPI -HZxMzWR2aK2s0z7iD/7VPUz4AvCNnVXkyDnFMa/pAQxVeju+29c99C50QJ3+KJSD -LaepAyOmUisphO3gKHR1E1l1We6D+egEedH1GD28dPbrt7/eb7E2F/lALU9CGJxK -9A3hRcxsw0xmPKgtm3TLgnxh/yC0fkWaCSjVVk283jtucWtECmyz5se9PyHEmDxm -Fml7WLcNrhJOrLZhvnZ5pyBWqGW8+s/d7+XSD9LUdixog6wimPo4QZ936ZD/qIFv -J7LuHAcZC39H9CvqKsoMkCVEANVL2397e/DQypp1todsldegc4qCBH68Rg/0Mj/k -m+SlChKAKOr2vqWvEeeF6Rddu9qTyaxujJJTtfM7wIM9zT8kDWbGHU1NWl5FP71f -pL4fWA7gyvqDlLnXKHjYc6mGNn9THs8NPTCz47oH0Y/YsHNAwzMyootKFbMELU1v -Zh4c26ojZcrp9gySLD+RMDbwhgtQiw8i2Biz8hehSxQXBPXt/mzzYwAoGM4sHASV -87vIe8SueEgyT+n+ZFIt -=Pkvv ------END PGP SIGNATURE----- ADDED client/1.0/neutral/VERSION Index: client/1.0/neutral/VERSION ================================================================== --- client/1.0/neutral/VERSION +++ client/1.0/neutral/VERSION @@ -0,0 +1,1 @@ +1.0 ADDED client/1.0/neutral/VERSION.asc Index: client/1.0/neutral/VERSION.asc ================================================================== --- client/1.0/neutral/VERSION.asc +++ client/1.0/neutral/VERSION.asc @@ -0,0 +1,18 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2 +Comment: Eagle Package Repository + +iQIcBAABCAAGBQJXt4qVAAoJEFAslq9JXcLZI+IP/iR3JMHwLYyiYjsJogm0YH6z +dU6QaiaZiONne+eIPOFKYeotbJ4pHw3EWnk1XRsmKA+6QfZ2Cmp+V2ANDjncXqC6 +e8SpztuhGIkDC4MoQHviff1MvE9CQK/89xCG+HcBr+a25Lh4vYROSLunn8BMfC58 +khEJTcmhdhdc+up5v20Y1qDR9DM21WguQLfUg0vTB1G+6QAa5tfz5h6r0yWyus3F +Din5TTpBR0if4Fxcbmhub7GCZTaifn2Oc25usYJCiAWBqyxP4foK5oMEkajhBFc6 +78lzo7xlqH0TPPOJP3iOGph1tOG9R0IT0Eduqk2yPkgZ18M9m1StYK7isGI5qUIU +/7XXeqjbtIR3w1V04EZnonKunVPgP2YsB9BowiGWi1igbSt0HzwdHRRBdTsXPwN4 +yqKAiariH7ZU8L7c7yxpf79tR+wHmfbR6BF5KtzN+7jRHJnq803IHYLDwxd/Yiqr +HNewIKTWdRBIAvJE0FR/XLRLUnUz3rGLGKAlF1JQMxKDCSRTFEdpWffRvsg48x8z +NDS2I9SaVwHLL/Zm1eO7zBFt8jvtjxsdXyb8aFMrmcUuh55yjqefoYR+XX9DsS65 +0Tf7fNPg+tgsC2jO1LbJsYksn5NSLMgbo6Gt515WRymJY9uX84NWi+C9Wx0ZyUAa +B19h6sHUadZq9LpGgZds +=5zVB +-----END PGP SIGNATURE----- ADDED client/1.0/neutral/license.terms Index: client/1.0/neutral/license.terms ================================================================== --- client/1.0/neutral/license.terms +++ client/1.0/neutral/license.terms @@ -0,0 +1,38 @@ +This software is copyrighted by Joe Mistachkin and other parties. The +following terms apply to all files associated with the software unless +explicitly disclaimed in individual files. + +The authors hereby grant permission to use, copy, modify, distribute, +and license this software and its documentation for any purpose, provided +that existing copyright notices are retained in all copies and that this +notice is included verbatim in any distributions. No written agreement, +license, or royalty fee is required for any of the authorized uses. +Modifications to this software may be copyrighted by their authors +and need not follow the licensing terms described here, provided that +the new terms are clearly indicated on the first page of each file where +they apply. + +IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY +FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY +DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE +IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE +NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR +MODIFICATIONS. + +GOVERNMENT USE: If you are acquiring this software on behalf of the +U.S. government, the Government shall have only "Restricted Rights" +in the software and related documentation as defined in the Federal +Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you +are acquiring the software on behalf of the Department of Defense, the +software shall be classified as "Commercial Computer Software" and the +Government shall have only "Restricted Rights" as defined in Clause +252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the +authors grant the U.S. Government and others acting in its behalf +permission to use and distribute the software in accordance with the +terms specified in this license. ADDED client/1.0/neutral/license.terms.asc Index: client/1.0/neutral/license.terms.asc ================================================================== --- client/1.0/neutral/license.terms.asc +++ client/1.0/neutral/license.terms.asc @@ -0,0 +1,18 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2 +Comment: Eagle Package Repository + +iQIcBAABCAAGBQJX+TvEAAoJEFAslq9JXcLZHO0QALTJ7noDN6WZ+3vtfO1AtqsA +rsGHk5cdD/O0AJSTjZNTwr88UJ1l4sK3FfETzhZfK86Gyx3D/IhQ/CyPI0BUA/4+ +HIPV9yWGkM1XN+Qmef8Yk4D2hgkhtDV3ZXNIXFEH660w3jro7mNDkEyxw7pnDkPI +HZxMzWR2aK2s0z7iD/7VPUz4AvCNnVXkyDnFMa/pAQxVeju+29c99C50QJ3+KJSD +LaepAyOmUisphO3gKHR1E1l1We6D+egEedH1GD28dPbrt7/eb7E2F/lALU9CGJxK +9A3hRcxsw0xmPKgtm3TLgnxh/yC0fkWaCSjVVk283jtucWtECmyz5se9PyHEmDxm +Fml7WLcNrhJOrLZhvnZ5pyBWqGW8+s/d7+XSD9LUdixog6wimPo4QZ936ZD/qIFv +J7LuHAcZC39H9CvqKsoMkCVEANVL2397e/DQypp1todsldegc4qCBH68Rg/0Mj/k +m+SlChKAKOr2vqWvEeeF6Rddu9qTyaxujJJTtfM7wIM9zT8kDWbGHU1NWl5FP71f +pL4fWA7gyvqDlLnXKHjYc6mGNn9THs8NPTCz47oH0Y/YsHNAwzMyootKFbMELU1v +Zh4c26ojZcrp9gySLD+RMDbwhgtQiw8i2Biz8hehSxQXBPXt/mzzYwAoGM4sHASV +87vIe8SueEgyT+n+ZFIt +=Pkvv +-----END PGP SIGNATURE----- ADDED client/1.0/neutral/pkgIndex.eagle Index: client/1.0/neutral/pkgIndex.eagle ================================================================== --- client/1.0/neutral/pkgIndex.eagle +++ client/1.0/neutral/pkgIndex.eagle @@ -0,0 +1,24 @@ +############################################################################### +# +# pkgIndex.eagle -- +# +# Extensible Adaptable Generalized Logic Engine (Eagle) +# Package Index File +# +# Copyright (c) 2007-2012 by Joe Mistachkin. All rights reserved. +# +# See the file "license.terms" for information on usage and redistribution of +# this file, and for a DISCLAIMER OF ALL WARRANTIES. +# +# RCS: @(#) $Id: $ +# +############################################################################### + +if {![package vsatisfies [package provide Tcl] 8.4]} {return} +if {![package vsatisfies [package provide Eagle] 1.0]} {return} + +package ifneeded Eagle.Package.Repository 1.0 \ + [list source [file join $dir pkgr.eagle]] + +package ifneeded Eagle.Package.Downloader 1.0 \ + [list source [file join $dir pkgd.eagle]] ADDED client/1.0/neutral/pkgIndex.eagle.asc Index: client/1.0/neutral/pkgIndex.eagle.asc ================================================================== --- client/1.0/neutral/pkgIndex.eagle.asc +++ client/1.0/neutral/pkgIndex.eagle.asc @@ -0,0 +1,18 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2 +Comment: Eagle Package Repository + +iQIcBAABCAAGBQJXt2XQAAoJEFAslq9JXcLZ32EQAMPPN6pbNpqtm3OPnEtle0i2 +xXP/0oX1VmdHLpLMDO+DwvlIw4eLB6vDZs2Zmje3t+WxcJPlH2QWgjI4UDmmWS7h +HOt4/EUftPgjKWKUYPNpCj0S1vpVnLv19GWiDp++uYAA+YrdxTu+szeeI/rVaS3k +8dmVdAB7vO+EexhTywB883be5OWNBg1Jr+X7r/362CmXcL0Tdq31VDEP+q6JYTvW +PLM5kf4YMvFREtINhG2eg1s8BZts5Vz4b1NzVmMF9yyngu1pVQ+jkPAgM2A1OM6x +YQTMDTGZlanDDC+l131ts2GE4Lx96PwJBqbPii8Jhbkl+BqBZudDZ+mKhNhehBk5 +nlOJAsKNUNdV+9Zj94AsnqXjNymvocx2n1jI0xJl1mipqJ5S1Awh9s8WyYeXINp0 +WPxyQcamlLOnRz12tic3ht/07kwXjmZXNmy6wfVWX0FyljBhSiOmSxw8z77nLmy+ +hwHB9534Wlg4pEP8x+7N4NP0vu+cyfX9p1DHvNjklpcQLlHxGWAeu8vl87w+uamR +XcJpOnTxLshoVKI6CQunn0/OXAWDk3gi4MuU9+ZtytNfOMErNl85kuFtJLTzP5+H +2p8yGAliXQKET6+1a35u6xiPmjpfa3MABaQH5ooRMPm8Ii9t5pe3Ay3ylq4yB+Zn +IF7GNZh4xmipcTCy/skB +=suyk +-----END PGP SIGNATURE----- ADDED client/1.0/neutral/pkgIndex.eagle.harpy Index: client/1.0/neutral/pkgIndex.eagle.harpy ================================================================== --- client/1.0/neutral/pkgIndex.eagle.harpy +++ client/1.0/neutral/pkgIndex.eagle.harpy @@ -0,0 +1,68 @@ + + + + None + Mistachkin Systems + e1a22fd8-1cd1-4652-b0c9-b340408f1966 + SHA512 + Script + 2016-08-23T04:07:23.6465312Z + -1.00:00:00 + 0x9559f6017247e3e2 + + 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 + + ADDED client/1.0/neutral/pkgIndex.eagle.harpy.asc Index: client/1.0/neutral/pkgIndex.eagle.harpy.asc ================================================================== --- client/1.0/neutral/pkgIndex.eagle.harpy.asc +++ client/1.0/neutral/pkgIndex.eagle.harpy.asc @@ -0,0 +1,18 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2 +Comment: Eagle Package Repository + +iQIcBAABCAAGBQJX3ddfAAoJEFAslq9JXcLZZ64P/1KwUGRntTrhpe1JY7EggZOc +p/CYp3Q/FrWSLA+3Kk3AmQfj0E0JEIHX6rjNNcTX+lK538OxS1wTXL23qx5M7KRD +HesRavZoypr2WrFUHf1zCFBrllkYP/zyeXj6hpz7J+QeTaGAsbiBVRCLVOc82wIf +l+ZYaKevKIoMiivaxn2WmrrdlmP3dsgGdQcZohGwActvON6HGIUE0EeAxpNN0Mw5 +bwPeNl2ldRJ6M4slswYqV3QuAwV68oR6rPGA//bSTfzKM/+RTpX0XscnYcuV48GN +A7Gjzz8YIl4ohAYaSUmIwfS0YhHHWz+GPdchPE9itG0qeltDO3zBqu2ldU6pIRXR +dZizDy+bWh+6fzNV9Pd74aIDiVDHSb3f4PdNrxLj4g2ZrHhJ8fTs4zPP7yHBWCA0 +6G4Rbjz/+P20tcO344LexvFc/qYwx59S8BiXOkbnot9Qu8sD+L192ZoEzKCxE6R3 +fUt8FdNoOBuM2rO4PwqmZr6siYPXA6UTCe04c7uKglUpFEtYHedAvPG0zeRZkHc8 +YhvIpA5CG1WL/Z5RLx2IMfMTGhVh4tKv6rg1HYmLiyHnUk/Yp/hzD9AfGztaig73 +26MZb98eBN9AhlvKfnL9XyQsGNiGPoll/9zK1il4B33Y+dfaqDwROtDbjCjqt3cS +SEJcWOFSMZzAMS6FYQtP +=qmAI +-----END PGP SIGNATURE----- ADDED client/1.0/neutral/pkgIndex.tcl Index: client/1.0/neutral/pkgIndex.tcl ================================================================== --- client/1.0/neutral/pkgIndex.tcl +++ client/1.0/neutral/pkgIndex.tcl @@ -0,0 +1,24 @@ +############################################################################### +# +# pkgIndex.tcl -- +# +# Extensible Adaptable Generalized Logic Engine (Eagle) +# Package Index File +# +# Copyright (c) 2007-2012 by Joe Mistachkin. All rights reserved. +# +# See the file "license.terms" for information on usage and redistribution of +# this file, and for a DISCLAIMER OF ALL WARRANTIES. +# +# RCS: @(#) $Id: $ +# +############################################################################### + +if {![package vsatisfies [package provide Tcl] 8.4]} {return} +if {[string length [package provide Eagle]] > 0} then {return} + +package ifneeded Eagle.Package.Repository 1.0 \ + [list source [file join $dir pkgr.eagle]] + +package ifneeded Eagle.Package.Downloader 1.0 \ + [list source [file join $dir pkgd.eagle]] ADDED client/1.0/neutral/pkgIndex.tcl.asc Index: client/1.0/neutral/pkgIndex.tcl.asc ================================================================== --- client/1.0/neutral/pkgIndex.tcl.asc +++ client/1.0/neutral/pkgIndex.tcl.asc @@ -0,0 +1,18 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2 +Comment: Eagle Package Repository + +iQIcBAABCAAGBQJXt2XQAAoJEFAslq9JXcLZrdcP/joLk0SYgo+rOoLeqzvneJdS +3m4wOn6Dr6xzfT3d9Hmh/U5GeAabG6nGXroqHlF6RCXDlw2MuzxjwyEYn1ZxXQpT +++gzlxaBtJpo7D6j9CbWtghvDkFQyW+5ucruCFKH2rYr/U5akWiAHke4txFeXJMp +C6zFY0paMD39f0Si/prqwK07MdxtiUCM5wNNs2/hl0sbckV4Blit+BhShi1H74My +NPr4k0GmOSAo1QyYmBb6D0ciCkl6AmbCtj6KQuPXzkhPu0rh0eduxAjcImu70jSu +peQ692PVYUV3vtHd5UVyZFKZeWGWUs27n4oIq/WNv60AocaS09QRikVNvf7kyHDy ++zEXF+yjnFnSdpHplVyfwMQdLz9LCjlqUivYq35Ir6n/C9tMLfqiZChUhyHX9hmB +rnyokRFh45mcF8gJLKC/4D/PKDDjBKyjHdbKLQrJ4bH3y7FSUzOvb3iI8K4/Omyt +uS18QYYtlovub0Bkc26TCVqlsytuv9Zc3Y6P8YlrLV7+lxGQs3hhgK6X0xK4GU6h +5aNE964elyYapPC3ToVEqvZaQsDM9vs1avW8SxcCvudixnzAycslcysv8JVaZXnG +u6WPT/zxt65BF+gXOBm5qpeFEQIn34WZdTHqXMgmUslT+uJ7y3cRXIKWGkzkebHZ +1PissA/AN1MgUYPp69ZV +=BbsA +-----END PGP SIGNATURE----- ADDED client/1.0/neutral/pkgd.eagle Index: client/1.0/neutral/pkgd.eagle ================================================================== --- client/1.0/neutral/pkgd.eagle +++ client/1.0/neutral/pkgd.eagle @@ -0,0 +1,1251 @@ +############################################################################### +# +# pkgd.eagle -- +# +# Extensible Adaptable Generalized Logic Engine (Eagle) +# Package Downloader Client +# +# Copyright (c) 2007-2012 by Joe Mistachkin. All rights reserved. +# +# See the file "license.terms" for information on usage and redistribution of +# this file, and for a DISCLAIMER OF ALL WARRANTIES. +# +# RCS: @(#) $Id: $ +# +############################################################################### + +# +# NOTE: Use our own namespace here because even though we do not directly +# support namespaces ourselves, we do not want to pollute the global +# namespace if this script actually ends up being evaluated in Tcl. +# +namespace eval ::PackageDownloader { + # + # NOTE: This procedure sets up the default values for all URN configuration + # parameters used by the package downloader client. If the force + # argument is non-zero, any existing values will be overwritten and + # set back to their default values. + # + proc setupDownloadUrnVars { force } { + # + # NOTE: The URN, relative to the base URI, where a login request may + # be sent. + # + variable loginUrn; # DEFAULT: pkgd_login + + if {$force || ![info exists loginUrn]} then { + set loginUrn pkgd_login + } + + # + # NOTE: The URN, relative to the base URI, where a single package file + # may be found. + # + variable downloadUrn; # DEFAULT: pkgd_file + + if {$force || ![info exists downloadUrn]} then { + set downloadUrn pkgd_file + } + + # + # NOTE: The URN, relative to the base URI, where a logout request may + # be sent. + # + variable logoutUrn; # DEFAULT: pkgd_logout + + if {$force || ![info exists logoutUrn]} then { + set logoutUrn pkgd_logout + } + } + + # + # NOTE: This procedure sets up the default values for all URI configuration + # parameters used by the package downloader client. If the force + # argument is non-zero, any existing values will be overwritten and + # set back to their default values. + # + proc setupDownloadUriVars { force } { + # + # NOTE: The base URI used to build the URIs for the package file server. + # + variable baseUri; # DEFAULT: https://urn.to/r + + if {$force || ![info exists baseUri]} then { + set baseUri https://urn.to/r + } + + # + # NOTE: The URI where a login request may be sent. This should return a + # payload containing the necessary HTTP(S) cookie information. + # + variable loginUri; # DEFAULT: ${baseUri}/${loginUrn}?... + + if {$force || ![info exists loginUri]} then { + set loginUri [appendArgs \ + {${baseUri}/${loginUrn}?} {[uriEscape name $userName]} & \ + {[uriEscape password $password]}] + } + + # + # NOTE: The URI where a single package file may be found. This file will + # belong to a specific version of one package. + # + variable downloadUri; # DEFAULT: ${baseUri}/${downloadUrn}?... + + if {$force || ![info exists downloadUri]} then { + set downloadUri [appendArgs \ + {${baseUri}/${downloadUrn}?download&ci=trunk&} \ + {[uriEscape filename $fileName]}] + } + + # + # NOTE: The URI where a logout request should be sent. This should + # return a payload indicating that the logout was successful. + # + variable logoutUri; # DEFAULT: ${baseUri}/${logoutUrn}?... + + if {$force || ![info exists logoutUri]} then { + set logoutUri [appendArgs \ + {${baseUri}/${logoutUrn}?} {[uriEscape authToken $authToken]}] + } + } + + # + # NOTE: This procedure sets up the default values for all configuration + # parameters used by the package downloader client. The script + # argument is the fully qualified path and file name for the script + # being evaluated. + # + proc setupDownloadVars { script } { + # + # NOTE: What is the fully qualified path to the directory containing the + # package downloader client? + # + variable clientDirectory + + if {![info exists clientDirectory]} then { + set clientDirectory [file dirname $script] + } + + # + # NOTE: This is the HTTP(S) login cookie to use when downloading files + # from the package file server. + # + variable loginCookie; # DEFAULT: NONE + + if {![info exists loginCookie]} then { + set loginCookie [list] + } + + # + # NOTE: Prevent progress messages from being displayed while downloading + # from the repository, etc? By default, this is enabled. + # + variable quiet; # DEFAULT: true + + if {![info exists quiet]} then { + set quiet true + } + + # + # NOTE: The user name for the public account on the package file server. + # If this is an empty string, there is no public account. + # + variable publicUserName; # DEFAULT: public + + if {![info exists publicUserName]} then { + set publicUserName public + } + + # + # NOTE: The password associated with the public account on the package + # file server. If this is an empty string, the public account is + # disabled. This is not considered to be a secret; however, it + # should not be shared with any person or organization that does + # not have access to the package downloader client. + # + variable publicPassword; # DEFAULT: X+NlF2obS5tQFKIsf/q345/naqVSGD67Cg + + if {![info exists publicPassword]} then { + set publicPassword X+NlF2obS5tQFKIsf/q345/naqVSGD67Cg + } + + # + # NOTE: The root directory where any persistent packages will be saved. + # + variable persistentRootDirectory; # DEFAULT: [getPersistentRootDirectory] + + if {![info exists persistentRootDirectory]} then { + set persistentRootDirectory [getPersistentRootDirectory] + } + + # + # NOTE: The root directory where any temporary packages will be written. + # + variable temporaryRootDirectory; # DEFAULT: [getFileTempDirectory PKGD_TEMP] + + if {![info exists temporaryRootDirectory]} then { + set temporaryRootDirectory \ + [::PackageRepository::getFileTempDirectory PKGD_TEMP] + } + + # + # NOTE: Is this package being run by the package installer tool? If so, + # all downloaded packages should be automatically persisted to the + # library path. + # + variable viaInstall; # DEFAULT: false + + if {![info exists viaInstall]} then { + set viaInstall false + } + } + + # + # NOTE: This procedure modifies the URN variables used by the package + # downloader client so that one or more alternative (private?) + # backend file servers may be used. The serverId argument must + # consist only of alphanumeric characters and it must begin with + # a letter. + # + # + proc useServerId { {serverId ""} } { + variable downloadUrn + variable loginUrn + variable logoutUrn + + if {[string length $serverId] > 0 && \ + ![regexp -nocase -- {^[A-Z][0-9A-Z]*$} $serverId]} then { + error "server Id must be alphanumeric and start with a letter" + } + + if {[string length $serverId] > 0} then { + # + # NOTE: Set the URN variables to values that should cause the + # specified server Id to be used (assume the server Id + # itself is valid and active). + # + set loginUrn [appendArgs pkgd_login_ $serverId] + set downloadUrn [appendArgs pkgd_file_ $serverId] + set logoutUrn [appendArgs pkgd_logout_ $serverId] + } else { + # + # NOTE: Forcibly reset URN variables to their default values. + # + setupDownloadUrnVars true + } + } + + # + # NOTE: This procedure escapes a single name/value pair for use in a URI + # query string. The name argument is the name of the parameter. + # The value argument is the value of the parameter. + # + proc uriEscape { name value } { + if {[isEagle]} then { + return [appendArgs \ + [uri escape uri $name] = [uri escape uri $value]] + } else { + package require http 2.0 + + return [::http::formatQuery $name $value] + } + } + + # + # NOTE: This procedure returns the root directory where any packages that + # are downloaded should be saved to permanent storage for subsequent + # use. There are no arguments. + # + proc getPersistentRootDirectory {} { + global env + + # + # NOTE: Allow the persistent root directory to be overridden via the + # environment. Typically, this customization will only be needed + # if multiple instances of Tcl need to share packages. + # + if {[info exists env(PKGD_ROOT)]} then { + return $env(PKGD_ROOT) + } + + # + # NOTE: Fallback to returning a directory parallel to the one containing + # the library directory. + # + return [file join [file dirname [info library]] pkgd] + } + + # + # NOTE: This procedure checks the configured persistent root directory for + # downloaded packages. If any checks fail, a script error is raised. + # There are no arguments. The return value is undefined. + # + proc verifyPersistentRootDirectory {} { + variable persistentRootDirectory + + if {![info exists persistentRootDirectory]} then { + error "persistent root directory not set" + } + + if {[string length $persistentRootDirectory] == 0} then { + error "persistent root directory is invalid" + } + + # + # NOTE: Either the persistent root directory must already exist -OR- we + # must be able to create it. + # + if {![file isdirectory $persistentRootDirectory] && \ + [catch {file mkdir $persistentRootDirectory}]} then { + error "persistent root directory does not exist and could not be created" + } + } + + # + # NOTE: This procedure returns the name of the package index file for the + # language specified by the language argument. An empty string will + # be returned if the language is unsupported or unrecognized. + # + proc getPackageIndexFileName { language } { + if {[string length $language] == 0 || $language eq "eagle"} then { + return pkgIndex.eagle + } elseif {$language eq "tcl"} then { + return pkgIndex.tcl + } else { + return "" + } + } + + # + # NOTE: This procedure, which is only used for native Tcl, generates a + # "master" package index file (i.e. "pkgIndex.tcl") suitable for + # use with native Tcl 8.4 (or higher). It will recursively scan + # for all other native Tcl package index files that are within the + # configured persistent root directory and [source] them, thereby + # causing all packages located within them to become available. + # Since Eagle (by default) already performs recursive searches for + # its package index files, this procedure is not needed for Eagle. + # The return value is undefined. + # + proc maybeCreateMasterTclPackageIndex {} { + variable persistentRootDirectory + + verifyPersistentRootDirectory + set persistentDirectory $persistentRootDirectory + + set fileName [file join $persistentDirectory pkgIndex.tcl] + if {[file exists $fileName]} then {return ""} + + writeFile $fileName [string trim [string map [list \r\n \n] { +############################################################################### +# +# pkgIndex.tcl -- +# +# Extensible Adaptable Generalized Logic Engine (Eagle) +# Generated Recursive Package Index File -- PLEASE DO NOT EDIT +# +# Copyright (c) 2007-2012 by Joe Mistachkin. All rights reserved. +# +# See the file "license.terms" for information on usage and redistribution of +# this file, and for a DISCLAIMER OF ALL WARRANTIES. +# +# RCS: @(#) $Id: $ +# +############################################################################### + +if {![package vsatisfies [package provide Tcl] 8.4]} {return} +if {[string length [package provide Eagle]] > 0} then {return} + +set pkgd(savedDir) $dir; set pkgd(dirs) [list $pkgd(savedDir)] + +for {set pkgd(i) 0} {$pkgd(i) < [llength $pkgd(dirs)]} {incr pkgd(i)} { + set pkgd(dir) [lindex $pkgd(dirs) $pkgd(i)] + + if {$pkgd(i) > 0} then { + set pkgd(file) [file join $pkgd(dir) pkgIndex.tcl] + + if {[file exists $pkgd(file)]} then { + set dir $pkgd(dir); source $pkgd(file) + } + } + + eval lappend pkgd(dirs) \ + [glob -nocomplain -types {d} [file join $pkgd(dir) *]] +} + +set dir $pkgd(savedDir); unset -nocomplain pkgd + }]] + + return "" + } + + # + # NOTE: This procedure returns non-zero if the specified file seems to be + # an OpenPGP signature file. The fileName argument is the name of + # the file to check, which may or may not exist. The nameOnly + # argument should be non-zero to ignore the contents of the file. + # + proc isOpenPgpSignatureFileName { fileName nameOnly } { + if {[string length $fileName] == 0} then { + return false + } + + set extension [file extension $fileName] + + if {$extension eq ".asc"} then { + if {!$nameOnly && [file exists $fileName]} then { + return [::PackageRepository::isOpenPgpSignature \ + [readFile $fileName]] + } else { + return true + } + } else { + return false + } + } + + # + # NOTE: This procedure returns non-zero if the specified file seems to be + # a Harpy script certificate file. The fileName argument is the name + # of the file to check, which may or may not exist. The nameOnly + # argument should be non-zero to ignore the contents of the file. + # + # + proc isHarpyCertificateFileName { fileName nameOnly } { + if {[string length $fileName] == 0} then { + return false + } + + set extension [file extension $fileName] + + if {$extension eq ".harpy"} then { + if {!$nameOnly && [file exists $fileName]} then { + return [::PackageRepository::isHarpyCertificate \ + [readFile $fileName]] + } else { + return true + } + } else { + return false + } + } + + # + # NOTE: This procedure returns the auto-path for the language specified by + # the language argument. An empty list is returned if the auto-path + # does not exist in the target language. This procedure may raise + # script errors. + # + proc getAutoPath { language } { + if {[string length $language] == 0 || $language eq "eagle"} then { + if {[isEagle]} then { + if {![info exists ::auto_path]} then { + return [list] + } + + return $::auto_path + } else { + ::PackageRepository::eagleMustBeReady + + eagle { + if {![info exists ::auto_path]} then { + return [list] + } + + return $::auto_path + } + } + } elseif {$language eq "tcl"} then { + if {[isEagle]} then { + tcl eval [tcl master] { + if {![info exists ::auto_path]} then { + return [list] + } + + return $::auto_path + } + } else { + if {![info exists ::auto_path]} then { + return [list] + } + + return $::auto_path + } + } else { + error "unsupported language, no idea how to query auto-path" + } + } + + # + # NOTE: This procedure adds a directory to the auto-path of the specified + # language (i.e. native Tcl or Eagle). The directory will not be + # 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. + # + if {[string length $language] == 0 || $language eq "eagle"} then { + if {[isEagle]} then { + if {![info exists ::auto_path] || \ + [lsearch -exact $::auto_path $directory] == -1} then { + lappend ::auto_path $directory + } + } else { + ::PackageRepository::eagleMustBeReady + + eagle [string map [list %directory% $directory] { + if {![info exists ::auto_path] || \ + [lsearch -exact $::auto_path {%directory%}] == -1} then { + lappend ::auto_path {%directory%} + } + }] + } + } elseif {$language eq "tcl"} then { + if {[isEagle]} then { + tcl eval [tcl master] [string map [list %directory% $directory] { + if {![info exists ::auto_path] || \ + [lsearch -exact $::auto_path {%directory%}] == -1} then { + lappend ::auto_path {%directory%} + } + }] + } else { + if {![info exists ::auto_path] || \ + [lsearch -exact $::auto_path $directory] == -1} then { + lappend ::auto_path $directory + } + } + } else { + error "unsupported language, no idea how to modify auto-path" + } + } + + # + # NOTE: This procedure adds a directory to the auto-path of the specified + # language (i.e. native Tcl or Eagle). The directory will not be + # 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. The directory will not be added if it falls under + # a directory already in the auto-path. + # + proc maybeAddToAutoPath { language directory } { + # + # NOTE: Verify that the directory to be added is valid and exists. If + # not, do nothing. + # + if {[string length $directory] == 0 || \ + ![file isdirectory $directory]} then { + return false + } + + # + # NOTE: Normalize the specified directory. This is necessary so that + # we can compare apples-to-apples within the auto-path. + # + set directory [file normalize $directory] + set directoryLength [string length $directory] + + # + # NOTE: Query the auto-path for the target language. + # + set autoPath [getAutoPath $language] + + # + # NOTE: Check each directory in the auto-path to see if the specified + # directory is already underneath it. + # + foreach autoDirectory $autoPath { + # + # NOTE: Normalize the auto-path directory. This is necessary so + # that we can compare apples-to-apples with the specified + # directory. + # + set autoDirectory [file normalize $autoDirectory] + set autoDirectoryLength [string length $autoDirectory] + + # + # NOTE: Prefix match is impossible if the length of the specified + # directory is less than the length of this directory in the + # auto-path. + # + if {$directoryLength < $autoDirectoryLength} then { + continue + } + + # + # NOTE: If the initial portion of the specified directory is the + # same as this directory in the auto-path, it must reside + # underneath it. In that case, there is no need to modify + # the auto-path, bail out now. + # + set last [expr {$autoDirectoryLength - 1}] + + if {[string range $directory 0 $last] eq $autoDirectory} then { + return false + } + } + + # + # NOTE: At this point, it is pretty safe to assume that the specified + # directory is not in the auto-path, nor underneath a directory + # within the auto-path. + # + addToAutoPath $language $directory + + return true + } + + # + # NOTE: This procedure verifies the combination of language and version + # specified by the caller. The language argument must be one of the + # literal strings "eagle", "tcl", or "client". The version argument + # must be one of the literal strings "8.4", "8.5", or "8.6" when the + # language is "tcl" -OR- the literal string "1.0" when the language + # is either "eagle" or "client". The varName argument is the name + # of a scalar variable in the context of the immediate caller that + # will receive a boolean value indicating if the specified language + # is actually a reference to the package downloader client itself. + # + proc verifyLanguageAndVersion { language version varName } { + if {[string length $varName] > 0} then { + upvar 1 $varName isClient + } + + set isClient false + + if {[string length $language] == 0 || $language eq "eagle"} then { + if {$version ne "1.0"} then { + error "unsupported Eagle version" + } + } elseif {$language eq "tcl"} then { + if {$version ne "8.4" && $version ne "8.5" && $version ne "8.6"} then { + error "unsupported Tcl version" + } + } elseif {$language eq "client"} then { + if {$version ne "1.0"} then { + error "unsupported client version" + } + + set isClient true + } else { + error "unsupported language" + } + } + + # + # NOTE: This procedure verifies the platform specified by the caller. The + # platform argument must be an empty string -OR- one of the literal + # strings "win32-arm", "win32-x86", "win64-arm64", "win64-ia64", or + # "win64-x64". An empty string means that the associated entity does + # not require a specific platform. Upon failure, a script error will + # be raised. The return value is undefined. + # + proc verifyPlatform { platform varName } { + switch -exact -- $platform { + "" { + # + # NOTE: This platform name is supported; however, the name needs + # to be normalized to "neutral". + # + if {[string length $varName] > 0} then { + upvar 1 $varName newPlatform; set newPlatform neutral + } + } + win32-arm - + win32-x86 - + win64-arm64 - + win64-ia64 - + win64-x64 { + # + # NOTE: This platform name is supported verbatim, do nothing. + # + } + default { + error "unsupported platform" + } + } + } + + # + # NOTE: This procedure issues a request to an HTTP(S) server. It returns + # the raw response data verbatim. It may raise a script error. It + # will always use the currently configured HTTP(S) login cookie, if + # any; therefore, it should really only be used for requests to the + # package file server. The uri argument is the fully qualified URI + # to request. + # + proc getPackageFile { uri } { + variable loginCookie + variable quiet + + if {[isEagle]} then { + if {![object invoke Eagle._Tests.Default \ + TestHasScriptNewWebClientCallback ""]} then { + set error null + + set code [object invoke Eagle._Tests.Default \ + TestSetScriptNewWebClientCallback "" true true error] + + if {$code ne "Ok"} then { + error [getStringFromObjectHandle $error] + } + } + + if {[info exists loginCookie] && [llength $loginCookie] == 2} then { + set script [object create String { + if {[methodName ToString] eq "GetWebRequest"} then { + webRequest Headers.Add Cookie [join $loginCookie =] + } + }] + + return [uri download -inline -webclientdata $script -- $uri] + } else { + return [uri download -inline -- $uri] + } + } else { + set options [list -binary true] + + if {[info exists loginCookie] && [llength $loginCookie] == 2} then { + lappend options -headers [list Cookie [join $loginCookie =]] + } + + return [eval ::PackageRepository::getFileViaHttp \ + [list $uri] [list 20] [list stdout] [list $quiet] $options] + } + } + + # + # NOTE: This procedure returns the prefix for fully qualified variable + # names that MAY be present in the global namespace. There are + # no arguments. + # + proc getDownloadVarNamePrefix {} { + return ::pkgd_; # TODO: Make non-global? + } + + # + # NOTE: This procedure resets the currently configured login cookie, if + # any, and then attempts to login using the configured package + # repository server API key -OR- using the public access account. + # Upon success, it will set the login cookie to the one from the + # raw response data. Upon failure, a script error will be raised. + # There are no arguments. + # + # + proc resetCookieAndLoginSimple {} { + variable publicPassword + variable publicUserName + + set apiKey [lindex [::PackageRepository::getApiKeys \ + [getDownloadVarNamePrefix] true] 0] + + if {[string length $apiKey] > 0} then { + return [resetCookieAndLogin $apiKey $apiKey] + } + + if {[string length $publicUserName] > 0 && \ + [string length $publicPassword] > 0} then { + return [resetCookieAndLogin $publicUserName $publicPassword] + } + + error "missing API keys and no public login credentials configured" + } + + # + # NOTE: This procedure resets the currently configured login cookie, if + # any, and then attempts to login using the specified user name and + # password. Upon success, it will set the login cookie to the one + # from the raw response data. Upon failure, a script error will be + # raised. The userName argument must be the name of a package file + # server user with at least Fossil Check-Out (o) permissions on the + # package file server. The password argument must be the plaintext + # password that is associated with the specified user name. + # + # + proc resetCookieAndLogin { userName password } { + variable baseUri + variable loginCookie + variable loginUri + variable loginUrn + + # + # NOTE: Build the full URI for the login request. + # + set uri [subst $loginUri] + + # + # NOTE: Reset the old login cookie, if any. Then, issue a new login + # request, capturing the raw response data. + # + set loginCookie [list]; set data [getPackageFile $uri] + + # + # NOTE: Attempt to extract the necessary values from the raw response + # data. + # + set pattern(1) {"authToken":"(.*?)"}; # TODO: *HACK* Keep updated. + + if {![regexp -- $pattern(1) $data dummy authToken]} then { + error "login response missing \"authToken\"" + } + + set pattern(2) {"loginCookieName":"(.*?)"}; # TODO: *HACK* Keep updated. + + if {![regexp -- $pattern(2) $data dummy loginCookieName]} then { + error "login response missing \"loginCookieName\"" + } + + # + # NOTE: Set the login cookie to the one freshly extracted from the raw + # response data. + # + set loginCookie [list $loginCookieName $authToken] + + # + # NOTE: Always return an empty string (i.e. and not any response data). + # + return "" + } + + # + # NOTE: This procedure attempts to logout using the currently configured + # login cookie, if any, and then resets the login cookie. There + # are no arguments. This procedure may raise a script error. + # + # + proc logoutAndResetCookie {} { + variable baseUri + variable loginCookie + variable logoutUri + variable logoutUrn + + # + # NOTE: Attempt to verify that we are currently logged in. + # + if {![info exists loginCookie] || [llength $loginCookie] != 2} then { + error "missing or invalid login cookie" + } + + # + # NOTE: Build the full URI for the logout request. + # + set authToken [lindex $loginCookie 1] + set uri [subst $logoutUri] + + # + # NOTE: Reset the old login cookie, if any. Then, issue a new login + # request, capturing the raw response data. + # + set data [getPackageFile $uri] + + # + # NOTE: Attempt to extract the necessary values from the raw response + # data. + # + set pattern(1) {"name":"nobody"}; # TODO: *HACK* Keep updated. + + if {![regexp -- $pattern(1) $data dummy]} then { + error "logout response missing \"name\"" + } + + # + # NOTE: Reset the login cookie. + # + set loginCookie [list] + + # + # NOTE: Always return an empty string (i.e. and not any response data). + # + return "" + } + + # + # NOTE: This procedure checks if there is a higher version available of the + # specified package on the package file server. The language argument + # must be one of the literal strings "eagle", "tcl", or "client". The + # version argument must be one of the literal strings "8.4", "8.5", or + # "8.6" when the language is "tcl" -OR- the literal string "1.0" when + # the language is either "eagle" or "client". The platform argument + # must be an empty string -OR- one of the literal strings "win32-arm", + # "win32-x86", "win64-arm64", "win64-ia64", or "win64-x64". An empty + # string means that the associated package does not require a specific + # platform. The packageName argument is a directory name relative to + # the language and version-specific directory on the package file + # server and may be an empty string. The usePgp argument should be + # non-zero when an OpenPGP signature file needs to be downloaded and + # verified for the downloaded file. + # + # + proc checkForHigherVersion { language version platform packageName usePgp } { + variable clientDirectory + variable persistentRootDirectory + variable temporaryRootDirectory + + verifyLanguageAndVersion $language $version isClient + verifyPlatform $platform platform + + set temporaryDirectory [file join \ + $temporaryRootDirectory [appendArgs \ + pkgd_ver_ [::PackageRepository::getUniqueSuffix]]] + + if {$isClient} then { + set persistentDirectory $clientDirectory + } else { + verifyPersistentRootDirectory + set persistentDirectory $persistentRootDirectory + } + + set fileName [file join $packageName VERSION] + set downloadFileName [file join $temporaryDirectory $fileName] + + file mkdir [file dirname $downloadFileName] + + downloadOneFile $language $version $platform \ + $fileName $downloadFileName $usePgp + + if {$usePgp} then { + downloadOneFile $language $version $platform \ + [appendArgs $fileName .asc] \ + [appendArgs $downloadFileName .asc] $usePgp + } + + set localFileName [file join $persistentDirectory $fileName] + + set compare [package vcompare \ + [string trim [readFile $downloadFileName]] \ + [string trim [readFile $localFileName]]] + + if {[isEagle]} then { + file delete -recursive -- $temporaryDirectory + } else { + file delete -force -- $temporaryDirectory + } + + return [expr {$compare > 0}] + } + + # + # NOTE: This procedure downloads a single file from the package file server, + # writing its contents to the specified local file name. It can also + # verify the OpenPGP signatures. When an OpenPGP signature file is + # downloaded, this procedure assumes the corresponding data file was + # already downloaded (i.e. since OpenPGP needs both to perform the + # signature checks). The language argument must be one of the + # literal strings "eagle", "tcl", or "client". The version argument + # must be one of the literal strings "8.4", "8.5", or "8.6" when the + # language is "tcl" -OR- the literal string "1.0" when the language + # is either "eagle" or "client". The platform argument must be an + # empty string -OR- one of the literal strings "win32-arm", + # "win32-x86", "win64-arm64", "win64-ia64", or "win64-x64". An empty + # string means that the associated package does not require a specific + # platform. The fileName argument is a file name relative to the + # language and version-specific directory on the package file server. + # The localFileName argument is the file name where the downloaded + # file should be written. The usePgp argument should be non-zero when + # an OpenPGP signature file needs to be downloaded and verified for + # the downloaded file. + # + proc downloadOneFile { + language version platform fileName localFileName usePgp } { + variable baseUri + variable downloadUri + variable downloadUrn + + # + # NOTE: First, build the full relative file name to download from + # the remote package repository. + # + set fileName [file join $language $version $platform $fileName] + set uri [subst $downloadUri] + + # + # NOTE: Then, in one step, download the file from the package file + # server and write it to the specified local file. + # + writeFile $localFileName [getPackageFile $uri] + + # + # NOTE: Is use of OpenPGP for signature verification enabled? Also, + # did we just download an OpenPGP signature file? + # + if {$usePgp && [isOpenPgpSignatureFileName $localFileName true]} then { + # + # NOTE: Attempt to verify the OpenPGP signature. If this fails, + # an error is raised. + # + if {![::PackageRepository::verifyOpenPgpSignature $localFileName]} then { + error [appendArgs \ + "bad OpenPGP signature \"" $localFileName \"] + } + } + } + + # + # NOTE: This procedure attempts to download a list of files, optionally + # persistening them for subsequent uses by the target language. + # The language argument must be one of the literal strings "eagle", + # "tcl", or "client". The version argument must be one of the + # literal strings "8.4", "8.5", or "8.6" when the language is "tcl" + # -OR- the literal string "1.0" when the language is either "eagle" + # or "client". The platform argument must be an empty string -OR- + # one of the literal strings "win32-arm", "win32-x86", "win64-arm64", + # "win64-ia64", or "win64-x64". An empty string means that the + # associated package does not require a specific platform. The + # fileNames argument must be a well-formed list of file names to + # download, each one relative to the language and version-specific + # directory on the package file server. The options argument must + # be a dictionary of name/value pairs. The -persistent option should + # be non-zero if the downloaded files should be saved to permanent + # storage for subsequent use. The -usePgp option should be non-zero + # when an OpenPGP signature file needs to be downloaded and verified + # for each downloaded file. The -useAutoPath option should be + # non-zero to modify the auto-path to include the temporary or + # persistent directories containing the downloaded files. The + # -allowUpdate option should be non-zero to allow existing package + # files to be overwritten. + # + # + proc downloadFiles { language version platform fileNames options } { + variable clientDirectory + variable persistentRootDirectory + variable temporaryRootDirectory + variable viaInstall + + verifyLanguageAndVersion $language $version isClient + verifyPlatform $platform platform + + set temporaryDirectory [file join \ + $temporaryRootDirectory [appendArgs \ + pkgd_lib_ [::PackageRepository::getUniqueSuffix]]] + + if {$isClient} then { + set persistentDirectory $clientDirectory + } else { + verifyPersistentRootDirectory + set persistentDirectory $persistentRootDirectory + } + + set persistent [string is true -strict \ + [getDictionaryValue $options -persistent]] + + set usePgp [string is true -strict \ + [getDictionaryValue $options -usePgp]] + + set useAutoPath [string is true -strict \ + [getDictionaryValue $options -useAutoPath]] + + set allowUpdate [string is true -strict \ + [getDictionaryValue $options -allowUpdate]] + + set downloadedFileNames [list] + + foreach fileName $fileNames { + if {[string length $fileName] == 0 || \ + [file pathtype $fileName] ne "relative"} then { + error [appendArgs \ + "bad file name \"" $fileName "\", not relative"] + } + + set directoryParts [file split [file dirname $fileName]] + + if {[llength $directoryParts] == 0} then { + error [appendArgs \ + "bad file name \"" $fileName "\", no directory parts"] + } + + set directory(temporary) [file normalize [eval \ + file join [list $temporaryDirectory] $directoryParts]] + + set directory(persistent) [file normalize [eval \ + file join [list $persistentDirectory] $directoryParts]] + + set fileNameOnly [file tail $fileName] + + set downloadFileName [file normalize [file join \ + $directory(temporary) $fileNameOnly]] + + if {[file exists $downloadFileName]} then { + error [appendArgs \ + "temporary file name \"" $downloadFileName \ + "\" already exists"] + } + + file mkdir [file dirname $downloadFileName] + + downloadOneFile $language $version $platform \ + $fileName $downloadFileName $usePgp + + lappend downloadedFileNames [list \ + $fileNameOnly $directory(temporary) $directory(persistent)] + + if {$usePgp && \ + ![isOpenPgpSignatureFileName $downloadFileName true]} then { + downloadOneFile $language $version $platform \ + [appendArgs $fileName .asc] \ + [appendArgs $downloadFileName .asc] $usePgp + + lappend downloadedFileNames [list \ + [appendArgs $fileNameOnly .asc] $directory(temporary) \ + $directory(persistent)] + } + } + + set downloadDirectories [list] + + foreach downloadedFileName $downloadedFileNames { + set directory(temporary) [lindex $downloadedFileName 1] + + if {$persistent || $viaInstall} then { + set fileNameOnly [lindex $downloadedFileName 0] + set directory(persistent) [lindex $downloadedFileName 2] + + file mkdir $directory(persistent) + set command [list file copy] + + # + # NOTE: When updating the package repository client files, always + # use the -force option to overwrite existing files. Also, + # if we are allow updates, use the -force option. + # + if {$isClient || $allowUpdate} then { + lappend command -force + } + + lappend command -- + lappend command [file join $directory(temporary) $fileNameOnly] + lappend command [file join $directory(persistent) $fileNameOnly] + + eval $command + + lappend downloadDirectories $directory(persistent) + } else { + lappend downloadDirectories $directory(temporary) + } + } + + # + # NOTE: Does the package need to be persisted locally? This can be set + # via the direct caller or via the installer tool. + # + set addPersistentDirectoryToAutoPath false + + if {$persistent || $viaInstall} then { + # + # NOTE: In Eagle, a slightly different command is required to delete + # an entire directory tree. + # + if {[isEagle]} then { + file delete -recursive -- $temporaryDirectory + } else { + file delete -force -- $temporaryDirectory + } + + # + # NOTE: When the target language is native Tcl, try to create the + # master package index, if necessary. + # + if {$language eq "tcl"} then { + maybeCreateMasterTclPackageIndex + set addPersistentDirectoryToAutoPath true + } + } + + # + # NOTE: Sort the list of directories that downloaded files were written + # to, removing any duplicates in the process. + # + set downloadDirectories [lsort -unique $downloadDirectories] + + if {$useAutoPath} then { + # + # NOTE: The auto-path, for whatever language this package belongs to, + # needs to be modified. + # + if {$addPersistentDirectoryToAutoPath} then { + # + # NOTE: The downloaded package was persisted -AND- will be handled + # by the master package index; therefore, just make sure the + # package persistence root directory is in the auto-path and + # then return only that directory in the result. + # + maybeAddToAutoPath $language $persistentDirectory + set downloadDirectories [list $persistentDirectory] + } else { + # + # NOTE: Check each unique download directory for a package index + # file. If a directory has a package index for the target + # language, add to the auto-path for the target language. + # + set packageIndexFileName [getPackageIndexFileName $language] + + if {[string length $packageIndexFileName] > 0} then { + foreach downloadDirectory $downloadDirectories { + if {[file exists [file join \ + $downloadDirectory $packageIndexFileName]]} then { + addToAutoPath $language $downloadDirectory + } + } + } + } + } + + # + # NOTE: Always return the list of directories that were actually added + # to the auto-path, if any. + # + return $downloadDirectories + } + + # + # NOTE: This package requires that support for namespaces, which is an + # optional feature of Eagle, must be enabled. + # + if {[isEagle] && ![namespace enable]} then { + error "namespaces must be enabled for this package" + } + + # + # NOTE: This package requires the package repository client package. + # + package require Eagle.Package.Repository + + # + # NOTE: Attempt to read optional settings file now. This may override + # one or more of the variable setup in the next step. + # + ::PackageRepository::maybeReadSettingsFile [info script] + + # + # NOTE: Setup the variables, within this namespace, used by this script. + # + setupDownloadVars [info script] + + # + # NOTE: Setup the URI and URN variables, within this namespace, used by + # this script. + # + setupDownloadUriVars false; setupDownloadUrnVars false + + # + # NOTE: If necessary, add the package persistence root directory to the + # auto-path for the current language. This will only be done if + # it falls outside of the existing auto-path. + # + variable persistentRootDirectory + + maybeAddToAutoPath [expr {[isEagle] ? "eagle" : "tcl"}] \ + $persistentRootDirectory + + # + # NOTE: Provide the package to the interpreter. + # + package provide Eagle.Package.Downloader \ + [expr {[isEagle] ? [info engine PatchLevel] : "1.0"}] +} + ADDED client/1.0/neutral/pkgd.eagle.asc Index: client/1.0/neutral/pkgd.eagle.asc ================================================================== --- client/1.0/neutral/pkgd.eagle.asc +++ client/1.0/neutral/pkgd.eagle.asc @@ -0,0 +1,18 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2 +Comment: Eagle Package Repository + +iQIcBAABCAAGBQJYEovnAAoJEFAslq9JXcLZGOoP/jvHF0JHjEGMPPYwz0RlskVp +pqIQwnkEZbMe6bqc3BdXPwIV3oLB4/nJ/g0MpmRJrH5X8jZD5X5eRSzncPtb8MrY +ybBcg302IUzdNQ375xMJLi7l9V3ziA2HE46KYYBe1nIjJrSqi3VdlCsCrnAV8jN3 +o1/kpd3b7xci1vrECoN4mgBiWSwR9Pmt6IZM6QkiO9HMFPH0kMbOo3IQxSh1Ea5C +e1fydO9YMQFIHT00234gttos9fRR+mtlGoIPmFicoVYUCO+B7mh565TUKpUzvAmf +bmScTA1njVlwwftxiRSBAzM4FhcczD98adatT14Scm++2TfPuQGydVoo8V5UKS/W +yNifJx2Z1nvl6XwvK0YJkNm+PHF+/Itg3oTB4uiKsYyu0dcuGDWvX0+eOGvnEXmr +Rg617S4MZU741lfAnmDvyw7qdoAgpdVcRWZ4bmzeSObfrECurqbkRBgyn2H/DWri +erPtK7BwnkygL6IISm5dn5rLRWrUGlByhi5SNVrg/5oAbdCXhfG3+EdIrf2wjYnt +2wV4upfxs5qONN/h6HKDcEiUAhBlJXVXy4MkdlTBKsohV4Be03/Irk/21SOc2PQM +36aqnipbjOsRIHn8ptjUbN9Fp6kj7urQ8n+dPVHR/Dxjg+7lusLW1gTIed9LXTAN +LVnajL/bzzePXuSzSlDO +=Jxit +-----END PGP SIGNATURE----- ADDED client/1.0/neutral/pkgd.eagle.harpy Index: client/1.0/neutral/pkgd.eagle.harpy ================================================================== --- client/1.0/neutral/pkgd.eagle.harpy +++ client/1.0/neutral/pkgd.eagle.harpy @@ -0,0 +1,68 @@ + + + + None + Mistachkin Systems + 3748f75c-202b-423f-a9ab-5e84b913e624 + SHA512 + Script + 2016-10-27T23:20:48.2421406Z + -1.00:00:00 + 0x9559f6017247e3e2 + + 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 + + ADDED client/1.0/neutral/pkgd.eagle.harpy.asc Index: client/1.0/neutral/pkgd.eagle.harpy.asc ================================================================== --- client/1.0/neutral/pkgd.eagle.harpy.asc +++ client/1.0/neutral/pkgd.eagle.harpy.asc @@ -0,0 +1,18 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2 +Comment: Eagle Package Repository + +iQIcBAABCAAGBQJYEovpAAoJEFAslq9JXcLZwi4QAKX3E7kVEtSZS0jIIJDpOYRU +GF+La2EgmEMiHuavCwSoZ9+Il2ATaZ7ohQUkNKj6o+tyG8Z+9s3TpQwi1q5/Jyw4 +99C7Fm+nuikDV+l6GJOoQGyA5e6gvQES1Tgx96PW1WZv16HJUGVcF0VgTVbtC5RQ +Gq6a2pvoLWMR+v8SXgxV7XYoVFciyLexBQMWnTWZOy4rxhC9gDgdRMPkojNZLfN3 +mKmBDK4fvKF8mmeyw+yxQLm6xDvt6Ljxy+91KcfF0eKhZzJme9FFhihObr+miKWa +E5J9ePF/R2K1eVqyh1sjfUY67bgDuiyjFXFZoO+Svohb1ZP2oqfL+H65KJGgO8m2 +XWz6T8MACFD/7JJB13wCW89L3UW1bVSTXR/8jTK+ArshHSok5lTkjfCJLzdZjqWa +Z1wfSAvAum62H5DrZPNUPDG9qfXpt3p1RnDW2ZWaBgKbBEKdogTyC/0WgqVpSE2H +ka6L5ZAQG7RT0TEPPvD8TUJ2BPLAfJKDc0SjOqqUz3l781jK/pkEfa1rDOIQaOun +VTuisBmMd1n2+8+8YDCpEcwdrUxADyVbqyAcYw2Rb5NmDEpS1jd3qMOZfrXetVo4 +W3H830MlAWsTJ/Ct8qKPEMz05REvUu8KwSczeSahgR4GU/gIriVm43edr6c85m23 +Rv1rijrRSb3MOvJtHqmf +=RqcK +-----END PGP SIGNATURE----- ADDED client/1.0/neutral/pkgd.settings.mistachkin.eagle Index: client/1.0/neutral/pkgd.settings.mistachkin.eagle ================================================================== --- client/1.0/neutral/pkgd.settings.mistachkin.eagle +++ client/1.0/neutral/pkgd.settings.mistachkin.eagle @@ -0,0 +1,18 @@ +############################################################################### +# +# pkgd.settings.mistachkin.eagle -- +# +# Extensible Adaptable Generalized Logic Engine (Eagle) +# Package Downloader Client Settings +# +# Copyright (c) 2007-2012 by Joe Mistachkin. All rights reserved. +# +# See the file "license.terms" for information on usage and redistribution of +# this file, and for a DISCLAIMER OF ALL WARRANTIES. +# +# RCS: @(#) $Id: $ +# +############################################################################### + +variable quiet false +variable persistentRootDirectory [file join $::env(TEMP) pkgd_override] ADDED client/1.0/neutral/pkgd.settings.mistachkin.eagle.asc Index: client/1.0/neutral/pkgd.settings.mistachkin.eagle.asc ================================================================== --- client/1.0/neutral/pkgd.settings.mistachkin.eagle.asc +++ client/1.0/neutral/pkgd.settings.mistachkin.eagle.asc @@ -0,0 +1,18 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2 +Comment: Eagle Package Repository + +iQIcBAABCAAGBQJYBZuOAAoJEFAslq9JXcLZ+asP+QH8YjtxxMMcqFvFMe7+ZLfN +BDdyhUBVARMgpckWghtlz7A2S6EwzcouF0RkoO9RZKqonIJ/rlv/lpC/b5GD4beh +eThgTRSPja473RNN4Cp5Rl0mDmPw+8Y4UESAqaAh81jYiI7NiIeotO6vff5SN9/7 +MS6fSp45aoFLrKuwUbyT2Ii0Aqcn1i4JvLaYDoVQKbAOnSgpskfk+/JhK1wKPABH +lkQicDBINh5/fM3p25dK9zFma8EDqRtv8+FNdckipE7BR9eu41C73fzfeAUjN8jw +ahcjdRA52TSa4Nkofyo+gRam3xmLjSBd+LKCm99Rc1kQGH5yFCRWYtvB1cAPzhoQ +I4d1We2ZWXvsa3rlgrMcvX1yNcLWr2DRIGen4EoN25n9wgPTwhnftxgbxnJytP2A +1zNdZDowOkRtxrVG8KFwM5hw1TSbKcyW/0fFwzcibA/fd4CwldXnGpODW6Vpnhug +DAW26+VLR1tptC+Ayre3an8sFE4GLYo/9zai6sLZbT8YMCmnodJ2rcS7Y3s7Fk7f +yMCG1YRFtAJIXywCR0zpfkYyuvEvtLtcNfe6dHN8oLTtTwYyugasz7bABx2uUUz8 +ZaKKX0FEz7otMCkKxvk3c/+zvY9mqAt+EybIfb5ppERV48QOUKvmH++2XOaP2PQY +Ed5/j/JzHY+SyoxlgHby +=t4Hi +-----END PGP SIGNATURE----- ADDED client/1.0/neutral/pkgd.settings.mistachkin.eagle.harpy Index: client/1.0/neutral/pkgd.settings.mistachkin.eagle.harpy ================================================================== --- client/1.0/neutral/pkgd.settings.mistachkin.eagle.harpy +++ client/1.0/neutral/pkgd.settings.mistachkin.eagle.harpy @@ -0,0 +1,68 @@ + + + + None + Mistachkin Systems + a4a30140-8aec-40b7-89af-44cecdef8193 + SHA512 + Script + 2016-10-18T03:47:22.9220000Z + -1.00:00:00 + 0x9559f6017247e3e2 + + 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 + + ADDED client/1.0/neutral/pkgd.settings.mistachkin.eagle.harpy.asc Index: client/1.0/neutral/pkgd.settings.mistachkin.eagle.harpy.asc ================================================================== --- client/1.0/neutral/pkgd.settings.mistachkin.eagle.harpy.asc +++ client/1.0/neutral/pkgd.settings.mistachkin.eagle.harpy.asc @@ -0,0 +1,18 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2 +Comment: Eagle Package Repository + +iQIcBAABCAAGBQJYBZuUAAoJEFAslq9JXcLZLDIP/A6ivrbT1LbbwSA9jGkTUfvL +wHjAxMdv8+mihbLywpebj8u1Ly8B2CuZnfRF9mhYmYNajCNDUbVhOYsNcxGGi9BI +WjAaLAAQsoaHBmIeTgYzWbeExcAgYlVymhh075JoIvBuhqpwtgjcFB7zWb7HQjZt +Dwro5aPCDvB0EBUXpizRGS2pFUMwCgDFWcv9WSyya3YOVabSJpTnz7H0rmLOJWNN +38TyiiQbv0W5p8T75/1sDwhq0C54kb3JIxAOpMhkXvKcZ7vt6Z78nw0MtQTTbOZb +4EKjCoHa4flVfCS/C/NdGAxypJG47PgNXpzZey7afrWZorggDUeI8v5IDT9Jz7FE +DsIS020kruF9SGlUQKMPYCimIHi23vjCrg+qNXl/UTHMlzCUyESrwSoy47YRhMtZ +KtxOi8873PrN6oC0C3ln519Sc6GowWiO6uREofHp1GJELC/3Pf8W3wrnQUZVtDOX +BlbKDfsp3vb9JB7IkXdRjgBCIZuFGSBZJK1uflq0NFM4zSq6gM6Em9W0/KQ6HVaN +0l3FtKATttXZA4SLV/54Eb6/50AE+/4BwmVw6wOWU8biG8BHzJ0peZcQXXV9VhWo +gOwgiTzDCBz+f3NGXVqw+FWfycom0qhXUmrd16S4dSvBgdPo/n8vPBH/+snFD33y +lxrGtuiqivSTAu8og6Pk +=8BVz +-----END PGP SIGNATURE----- ADDED client/1.0/neutral/pkgr.eagle Index: client/1.0/neutral/pkgr.eagle ================================================================== --- client/1.0/neutral/pkgr.eagle +++ client/1.0/neutral/pkgr.eagle @@ -0,0 +1,2206 @@ +############################################################################### +# +# pkgr.eagle -- +# +# Extensible Adaptable Generalized Logic Engine (Eagle) +# Package Repository Client +# +# Copyright (c) 2007-2012 by Joe Mistachkin. All rights reserved. +# +# See the file "license.terms" for information on usage and redistribution of +# this file, and for a DISCLAIMER OF ALL WARRANTIES. +# +# RCS: @(#) $Id: $ +# +############################################################################### + +# +# NOTE: Use our own namespace here because even though we do not directly +# support namespaces ourselves, we do not want to pollute the global +# namespace if this script actually ends up being evaluated in Tcl. +# +namespace eval ::PackageRepository { + # + # NOTE: If there is an "Eagle1.0" sub-directory present right beneath where + # this script was evaluated from, add it to the auto-path; otherwise, + # we assume that we are running from inside the source tree. In that + # case, modify the auto-path to include the "Eagle1.0" sub-directory + # within "externals". Only native Tcl needs to be able to locate the + # packages from the sub-directory being added to the auto-path here + # because they were already shipped in the Eagle core script library + # (as of Beta 37). The expression used for Eagle detection here was + # stolen from the Eagle core script library [isEagle] procedure. + # + variable pkgr_path; # DEFAULT: + + if {![info exists ::tcl_platform(engine)] || \ + [string compare -nocase eagle $::tcl_platform(engine)] != 0} then { + set pkgr_path [file normalize [file dirname [info script]]] + + if {[file isdirectory [file join $pkgr_path Eagle1.0]]} then { + lappend ::auto_path [file join $pkgr_path Eagle1.0] + } else { + lappend ::auto_path [file join [file dirname [file dirname \ + $pkgr_path]] externals Eagle lib Eagle1.0] + } + } + + # + # NOTE: This package requires several packages from the Eagle core script + # library, even when it is being used by native Tcl. If necessary, + # prior to evaluating this file in native Tcl, its auto-path should + # be modified to include an "Eagle1.0" directory (i.e. a directory + # containing the Eagle core script library files "auxiliary.eagle", + # "file1.eagle", and "platform.eagle"). + # + package require Eagle.Platform + package require Eagle.Auxiliary + package require Eagle.File + + # + # NOTE: This block is intended to be evaluated successfully by native Tcl + # only. It serves two purposes: + # + # 1. Import the Eagle core script library procedures that are used + # by this package into the global namespace. + # + # 2. Unset the "pkgr_path" (namespace) variable that was created by + # the auto-path adjustment script fragment (above). + # + if {[info exists pkgr_path]} then { + catch { + ::Eagle::exportAndImportPackageCommands ::Eagle \ + [list appendArgs getDictionaryValue isEagle \ + isWindows readFile writeFile] false false + } + + unset -nocomplain pkgr_path + } + + # + # NOTE: This procedure is used to provide a TIP #194 compatible [apply] + # command to the native Tcl 8.4 interpreter. Eagle and native Tcl + # 8.5 (or higher) have this command built-in. The lambdaExpr + # argument must be a list with two or three elements. The first + # element is the list of arguments to the procedure. The second + # element is the body of the procedure. The third element is the + # target namespace for the procedure. If the third element is not + # specified, the global namespace is used. Any remaining arguments + # are passed to the procedure verbatim. + # + if {[llength [info commands ::apply]] == 0} then { + proc ::apply { lambdaExpr args } { + set length [llength $lambdaExpr] + + if {$length < 2 || $length > 3} { + error [appendArgs \ + "can't interpret \"" $lambdaExpr "\" as a lambda expression"] + } + + foreach {procArgs procBody procNamespace} $lambdaExpr {break} + + set procNameSuffix [::PackageRepository::getUniqueSuffix 2] + set procName [appendArgs :: $procNamespace ::lambda_ $procNameSuffix] + set procPreBody {rename [lindex [info level 0] 0] "";} + + proc $procName $procArgs [appendArgs $procPreBody $procBody] + + return [uplevel 1 [list $procName] $args] + } + } + + # + # NOTE: This procedure returns a formatted, possibly version-specific, + # package name, for use in logging. The package argument is the + # name of the package. The version argument is the version of the + # package. + # + proc formatPackageName { package version } { + return [string trim [appendArgs $package " " $version]] + } + + # + # NOTE: This procedure returns a formatted script result. If the string + # result is empty, only the return code is used. The code argument + # must be an integer Tcl return code (e.g. from [catch]) and the + # result argument is the script result or error message. + # + proc formatResult { code result } { + switch -exact -- $code { + 0 {set codeString ok} + 1 {set codeString error} + 2 {set codeString return} + 3 {set codeString break} + 4 {set codeString continue} + default {set codeString [appendArgs unknown( $code )]} + } + + if {[string length $result] > 0} then { + return [appendArgs \ + "code " $codeString ", result " [list $result]] + } else { + return $codeString + } + } + + # + # NOTE: This procedure emits a message to the package repository client + # log. The string argument is the content of the message to emit. + # + proc pkgLog { string } { + catch { + tclLog [appendArgs [pid] " : " [clock seconds] " : pkgr : " $string] + } + } + + # + # NOTE: This procedure attempts to determine if a string is a valid list + # and returns non-zero when that is true. The value argument is + # the string to check. + # + proc stringIsList { value } { + if {[isEagle]} then { + return [string is list $value] + } else { + global tcl_version + + if {[info exists tcl_version] && $tcl_version >= 8.5} then { + return [string is list $value] + } elseif {[catch {llength $value}] == 0} then { + return true + } else { + return false + } + } + } + + # + # NOTE: This procedure returns non-zero if the specified string value + # looks like a Harpy (script) certificate. The value argument is + # the string to check. The value 14 used within this procedure is + # the length of the literal string "". + # + # + proc isHarpyCertificate { value } { + set value [string trim $value] + set length [string length $value] + + if {$length == 0 || ([string first [string trim { + + }] $value] == 0 && [string first [string trim { + + }] $value] == ($length - 14))} then { + return true + } else { + return false + } + } + + # + # NOTE: This procedure returns non-zero if the specified string value + # looks like an OpenPGP signature. The value argument is the string + # to check. The value 27 used within this procedure is the length + # of the literal string "-----END PGP SIGNATURE-----". + # + # + proc isOpenPgpSignature { value } { + set value [string trim $value] + set length [string length $value] + + if {$length == 0 || ([string first [string trim { + -----BEGIN PGP SIGNATURE----- + }] $value] == 0 && [string first [string trim { + -----END PGP SIGNATURE----- + }] $value] == ($length - 27))} then { + return true + } else { + return false + } + } + + # + # NOTE: This procedure returns the fully qualified name of the directory + # where temporary files should be written. The envVarName argument + # is an optional extra environment variable to check (first). + # + # + proc getFileTempDirectory { {envVarName ""} } { + global env + + if {[string length $envVarName] > 0 && \ + [info exists env($envVarName)]} then { + return $env($envVarName) + } elseif {[info exists env(TEMP)]} then { + return $env(TEMP) + } elseif {[info exists env(TMP)]} then { + return $env(TMP) + } else { + if {[string length $envVarName] > 0} then { + set defEnvVarName $envVarName + } elseif {[isWindows]} then { + set defEnvVarName TEMP + } else { + set defEnvVarName TMP + } + + error [appendArgs \ + "please set the \"" $defEnvVarName \ + "\" environment variable to the path of a temporary directory"] + } + } + + # + # NOTE: This procedure returns a unique temporary file name. A script + # error is raised if this task cannot be accomplished. There are + # no arguments. + # + proc getFileTempName {} { + if {[isEagle]} then { + return [file tempname] + } else { + set directory [getFileTempDirectory PKGR_TEMP] + set counter [expr {[pid] ^ int(rand() * 0xFFFF)}] + + while {1} { + set fileNameOnly [format tcl%04X.tmp $counter] + set fileName [file join $directory $fileNameOnly] + + if {![file exists $fileName]} then { + return $fileName + } + + incr counter + } + } + } + + # + # NOTE: This procedure attempts to verify the OpenPGP signature contained + # in the specified (named) file. Non-zero is only returned if the + # OpenPGP signature is verified successfully. A script error should + # not be raised by this procedure. The fileName argument must be + # the fully qualified path and file name of the OpenPGP signature + # file to verify. + # + # + proc verifyOpenPgpSignature { fileName } { + variable openPgpCommand + + if {[isEagle]} then { + set fileName [appendArgs \" $fileName \"] + + if {[catch { + eval exec -success Success [subst $openPgpCommand] + }] == 0} then { + return true + } + } else { + if {[catch { + eval exec [subst $openPgpCommand] 2>@1 + }] == 0} then { + return true + } + } + + return false + } + + # + # NOTE: This procedure returns the prefix for fully qualified variable + # names that MAY be present in the global namespace. There are + # no arguments. + # + proc getLookupVarNamePrefix {} { + return ::pkgr_; # TODO: Make non-global? + } + + # + # NOTE: This procedure returns a name suffix (directory, variable, etc) + # that is unique to the running process at the current point in + # time. It is used (internally) to avoid name collisions with any + # preexisting variables or commands that may be present in the + # global namespace. The paranoia argument represents the relative + # level of paranoia required by the caller; the higher this level, + # the more uniqueness is required. + # + # + proc getUniqueSuffix { {paranoia 1} } { + set result [string trim [pid] -] + + if {$paranoia > 0} then { + append result _ [string trim [clock seconds] -] + } + + if {$paranoia > 1} then { + append result _ [string trim \ + [clock clicks -milliseconds] -]; # TODO: Bad? + } + + return $result + } + + # + # NOTE: This procedure returns the list of API keys to use when looking + # up packages via the package repository server. An empty list + # is returned if no API keys are currently configured. The prefix + # argument is an extra variable name prefix to check prior to any + # that are already configured. The prefixOnly argument should be + # non-zero to exclude any API keys other than those based on the + # prefix specified by the caller. + # + # + proc getApiKeys { {prefix ""} {prefixOnly false} } { + global env + variable autoApiKeys + + # + # NOTE: If the caller specified a variable name prefix, try to use it + # first. + # + set prefixes [list] + + if {[string length $prefix] > 0} then { + lappend prefixes $prefix + } + + # + # NOTE: Next, fallback to the variable name prefix for this package, + # unless the caller has forbidden us to do so. + # + if {!$prefixOnly} then { + lappend prefixes [getLookupVarNamePrefix] + } + + # + # NOTE: Try each variable name prefix, in order, until a set of API + # keys is found. + # + foreach prefix $prefixes { + # + # NOTE: If an empty prefix is seen, force it to use the "api_keys" + # variable from the global namespace. + # + if {[string length $prefix] == 0} then { + set prefix ::; # TODO: Make non-global? + } + + # + # NOTE: Check for the variable, in whatever namespace it resides, + # and return its value verbatim if it exists. + # + set varName [appendArgs $prefix api_keys] + + if {[info exists $varName]} then { + return [set $varName] + } + + # + # NOTE: Fallback to using an environment variable with the same + # base name and returns its value verbatim if it exists. + # + set varName [string trim $varName :] + + if {[info exists env($varName)]} then { + return $env($varName) + } + } + + # + # NOTE: If there is a default list of API keys, just return it, + # unless the caller has forbidden us to do so. + # + if {!$prefixOnly && \ + [info exists autoApiKeys] && [llength $autoApiKeys] > 0} then { + return $autoApiKeys + } + + # + # NOTE: Otherwise, return the system default, which is "anonymous" + # packages only (i.e. those without any owners). + # + return [list] + } + + # + # NOTE: This procedure returns the base URI for the package repository + # server. There are no arguments. + # + proc getLookupBaseUri {} { + set varName [appendArgs [getLookupVarNamePrefix] base_uri] + + if {[info exists $varName]} then { + return [set $varName] + } + + global env + set varName [string trim $varName :] + + if {[info exists env($varName)]} then { + return $env($varName) + } + + return https://urn.to/r/pkg; # NOTE: System default. + } + + # + # NOTE: This procedure returns the full URI to use when looking up a + # specific package via the package repository server. The apiKeys + # argument is the list of API keys to use -OR- an empty list if a + # public package is being looked up. The package argument is the + # name of the package being looked up, it cannot be an empty + # string. The version argument is the specific version being + # looked up -OR- an empty string for any available version. There + # are no HTTP requests issued by this procedure; it simply returns + # the URI to use. + # + proc getLookupUri { apiKeys package version } { + set baseUri [getLookupBaseUri] + + if {[string length $baseUri] == 0} then { + return "" + } + + # + # NOTE: Build the HTTP request URI using the specified query parameter + # values, escaping them as necessary. Also, include the standard + # query parameters with constant values for this request type. + # + set anonymousApiKey "" + + if {[isEagle]} then { + if {[llength $apiKeys] > 0} then { + return [appendArgs \ + $baseUri ?raw=1&method=lookup&apiKeys= [uri escape uri \ + [join $apiKeys ,]] &package= [uri escape uri $package] \ + &version= [uri escape uri $version]] + } else { + return [appendArgs \ + $baseUri ?raw=1&method=lookup&apiKey= [uri escape uri \ + $anonymousApiKey] &package= [uri escape uri $package] \ + &version= [uri escape uri $version]] + } + } else { + package require http 2.0 + + if {[llength $apiKeys] > 0} then { + return [appendArgs \ + $baseUri ? [::http::formatQuery raw 1 method lookup \ + apiKeys [join $apiKeys ,] package $package version \ + $version]] + } else { + return [appendArgs \ + $baseUri ? [::http::formatQuery raw 1 method lookup \ + apiKey $anonymousApiKey package $package version \ + $version]] + } + } + } + + # + # NOTE: This procedure returns the version of the package that should be + # used to lookup the associated [package ifneeded] script -OR- an + # empty string if no such version exists. 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. + # + proc getIfNeededVersion { package version } { + if {[string length $version] > 0} then { + return $version + } + + return [lindex [package versions $package] 0] + } + + # + # NOTE: This procedure accepts a package requirement (spec) and returns + # a simple package version, if possible. An empty string will be + # returned, if appropriate (i.e. any version should be allowed). + # The requirement argument must be a package specification that + # conforms to TIP #268. + # + proc packageRequirementToVersion { requirement } { + set result $requirement + + if {[set index [string first - $result]] != -1} then { + incr index -1; set result [string range $result 0 $index] + } + + if {[set index [string first a $result]] != -1 || \ + [set index [string first b $result]] != -1} then { + incr index -1; set result [string range $result 0 $index] + } + + if {$result eq "0"} then { + set result "" + } elseif {[regexp -- {^\d+$} $result]} then { + append result .0 + } + + return $result + } + + # + # NOTE: This procedure issues an HTTP request that should return metadata + # that can be used to load and/or provide the specified package. + # The apiKeys argument is the list of API keys to use -OR- an empty + # list 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. All line-endings are normalized to Unix-style; + # therefore, all script signatures must assume this. + # + proc getLookupData { apiKeys package version } { + variable verboseUriDownload + + set uri [getLookupUri $apiKeys $package $version] + + if {[string length $uri] == 0} then { + return "" + } + + if {$verboseUriDownload} then { + pkgLog [appendArgs \ + "attempting to download URI \"" $uri \"...] + } + + if {[isEagle]} then { + set data [uri download -inline $uri] + } else { + set data [getFileViaHttp \ + $uri 20 stdout [expr {!$verboseUriDownload}] -binary true] + } + + if {$verboseUriDownload} then { + pkgLog [appendArgs \ + "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 trim $data] + + return $data + } + + # + # NOTE: This procedure attempts to extract the lookup code from the raw + # HTTP response data. The data argument is the raw HTTP response + # data. An empty string is returned if no lookup code is available. + # + proc getLookupCodeFromData { data } { + if {![stringIsList $data] || [llength $data] < 1} then { + return "" + } + + return [lindex $data 0] + } + + # + # NOTE: This procedure attempts to extract the lookup result from the raw + # HTTP response data. The data argument is the raw HTTP response + # data. An empty string is returned if no lookup result is available. + # + proc getLookupResultFromData { data } { + if {![stringIsList $data] || [llength $data] < 2} then { + return "" + } + + return [lindex $data 1] + } + + # + # NOTE: This procedure returns non-zero if the specified lookup response + # code indicates success. The code argument is the extracted HTTP + # lookup response code. + # + proc isLookupCodeOk { code } { + # + # NOTE: The code must be the literal string "OK" for the package lookup + # request to be considered successful. + # + return [expr {$code eq "OK"}] + } + + # + # NOTE: This procedure was stolen from the "common.tcl" script used by the + # package repository server. It has been modified to support both + # native Tcl and Eagle. It should be noted here that TIP #268 syntax + # is not supported by Eagle. For native Tcl, the requirement argument + # must be a package version or requirement conforming to the TIP #268 + # syntax. For Eagle, the requirement argument must be a simple dotted + # package version, with up to four components, without any 'a' or 'b'. + # The emptyOk argument should be non-zero if an empty string should be + # considered to be valid by the caller. The rangeOk argument should + # be non-zero if the version range syntax is allowed; this argument is + # ignored for Eagle because it requires TIP #268 support. + # + proc isValidPackageRequirement { requirement rangeOk {emptyOk false} } { + if {$emptyOk && [string length $requirement] == 0} then { + return true + } + + if {[isEagle]} then { + # + # NOTE: Eagle does not support TIP #268. Use the built-in sub-command + # that checks a version number. + # + return [string is version -strict $requirement] + } else { + # + # HACK: If a version range is not allowed, make sure that the dash + # character is not present. + # + if {!$rangeOk && [string first - $requirement] != -1} then { + return false + } + + # + # HACK: There is no direct way to check if a package requirement + # that uses the TIP #268 syntax is valid; however, we can + # purposely "misuse" the [package present] command for this + # purpose. We know the "Tcl" package is always present; + # therefore, if an error is raised here, then the package + # requirement is probably invalid. Unfortunately, the error + # message text has to be checked as well; otherwise, there + # is no way to verify version numbers that happen to be less + # than the running patch level of Tcl. + # + if {[catch {package present Tcl $requirement} error] == 0} then { + return true + } else { + # + # TODO: Maybe this will require updates in the future? + # + set pattern(1) "expected version number but got *" + set pattern(2) "expected versionMin-versionMax but got *" + + if {![string match $pattern(1) $error] && \ + ![string match $pattern(2) $error]} then { + return true + } else { + return false + } + } + } + } + + # + # NOTE: This procedure attempts to extract the package lookup metadata from + # the lookup result. The result argument is the lookup result. The + # varName argument is the name of an array variable, in the call frame + # of the immediate caller, that should receive the extracted package + # lookup metadata. The caller argument must be an empty string -OR- + # the literal string "handler". + # + proc extractAndVerifyLookupMetadata { result varName caller } { + variable strictUnknownLanguage + + # + # NOTE: Grab the returned patch level. It cannot be an empty string + # and it must conform to the TIP #268 requirements for a single + # package version. + # + set patchLevel [getDictionaryValue $result PatchLevel] + + if {[string length $patchLevel] == 0} then { + error "missing patch level" + } + + if {![isValidPackageRequirement $patchLevel false]} then { + error "bad patch level" + } + + # + # NOTE: Grab the language for the package script. It must be an empty + # string, "Tcl", or "Eagle". If it is an empty string, "Eagle" + # will be assumed. + # + set language [getDictionaryValue $result Language] + + if {[lsearch -exact [list "" Tcl Eagle] $language] == -1} then { + error "unsupported language" + } + + # + # NOTE: Grab the package script. If it is an empty string, then the + # package cannot be loaded and there is nothing to do. In that + # case, just raise an error. + # + set script [getDictionaryValue $result Script] + + if {[string length $script] == 0} then { + error "missing script" + } + + # + # NOTE: Grab the package script certificate. If it is an empty string + # then the package script is unsigned, which is not allowed by + # this client. In that case, just raise an error. + # + set certificate [getDictionaryValue $result Certificate] + + if {[string length $certificate] == 0} then { + error "missing script certificate" + } + + # + # NOTE: Are we being called from the [package unknown] handler + # in "strict" mode? + # + if {$strictUnknownLanguage && $caller eq "handler"} then { + # + # NOTE: If so, the package script must be targeted at the this + # language; otherwise, there exists the possibility that + # the package may not be provided to this language. + # + if {[isEagle]} then { + if {$language ne "Eagle"} then { + error "repository package is not for Eagle" + } + } else { + if {$language ne "Tcl"} then { + error "repository package is not for Tcl" + } + } + } + + # + # NOTE: If the caller wants the package lookup metadata, use their + # array variable name. + # + if {[string length $varName] > 0} then { + upvar 1 $varName metadata + + set metadata(patchLevel) $patchLevel + set metadata(language) $language + set metadata(script) $script + set metadata(certificate) $certificate + } + } + + # + # NOTE: This procedure, which may only be used from an Eagle script, checks + # if a native Tcl library is loaded and ready. If not, a script error + # is raised. There are no arguments. + # + proc tclMustBeReady {} { + # + # NOTE: This procedure is useless when running in native Tcl; therefore, + # forbid its use there. + # + if {![isEagle]} then { + error "already running in Tcl language" + } + + # + # NOTE: This procedure is not allowed to actually load a native Tcl + # library; therefore, one must already be loaded. + # + if {![tcl ready]} then { + error "cannot use Tcl language, supporting library is not loaded" + } + } + + # + # NOTE: This procedure is designed for Eagle. It attempts to load the + # "best" native Tcl library. It may raise any number of script + # errors. There are no arguments. + # + proc makeTclReady {} { + # + # NOTE: This procedure is useless when running in native Tcl; therefore, + # forbid its use there. + # + if {![isEagle]} then { + error "already running in Tcl language" + } + + # + # NOTE: Load a native Tcl library. It absolutely must be signed with a + # valid Authenticode signature. + # + tcl load -findflags +TrustedOnly -loadflags +SetDllDirectory + + # + # NOTE: Verify that the native Tcl library appears to have beed loaded + # into this interpreter. + # + tclMustBeReady + } + + # + # NOTE: This procedure, which may only be used from a native Tcl script, + # checks if Garuda and Eagle are loaded and ready. If not, a script + # error is raised. There are no arguments. + # + proc eagleMustBeReady {} { + # + # NOTE: This procedure is useless when running in Eagle; therefore, + # forbid its use there. + # + if {[isEagle]} then { + error "already running in Eagle language" + } + + # + # NOTE: This procedure is not allowed to actually load Garuda (and + # Eagle); therefore, they must already be loaded. + # + if {[llength [info commands eagle]] == 0} then { + error "cannot use Eagle language, supporting package is not loaded" + } + } + + # + # NOTE: This procedure is designed for native Tcl. It attempts to load + # the Garuda package and gain access to Eagle. It may raise any + # number of script errors. There are no arguments. + # + proc makeEagleReady {} { + # + # NOTE: This procedure is useless when running in Eagle; therefore, + # forbid its use there. + # + if {[isEagle]} then { + error "already running in Eagle language" + } + + # + # TODO: Assume the Garuda package is trusted? How can we verify it + # at this point? + # + package require Garuda + + # + # NOTE: Verify that the Garuda package appears to have been fully and + # successfully loaded into this interpreter. + # + eagleMustBeReady + } + + # + # NOTE: This procedure returns non-zero if the current script is being + # evaluated in Eagle with signed-only script security enabled. + # There are no arguments. + # + proc eagleHasSecurity {} { + # + # NOTE: If possible, check if the current interpreter has security + # enabled. + # + if {[isEagle] && [llength [info commands object]] > 0} then { + if {[catch { + object invoke -flags +NonPublic Interpreter.GetActive HasSecurity + } security] == 0 && $security} then { + return true + } + } + + return false + } + + # + # NOTE: This procedure uses the package lookup metadata. If the package + # script is properly signed, an attempt will be made to evaluate it + # in the target language. If the script was signed using OpenPGP, + # then a conforming implementation of the OpenPGP specification (e.g. + # gpg2) must be installed locally. If the script was signed using + # Harpy then Garuda, Eagle, and Harpy must be installed locally. + # This procedure is designed to work for both native Tcl and Eagle + # packages. Additionally, it is designed to work when evaluated + # using either native Tcl or Eagle; however, it is up to the package + # script itself to either add the package or provide the package to + # the language(s) supported by that package. The varName argument + # is the name of an array variable in the call frame of the + # immediate caller, that contains the package lookup metadata. This + # procedure may raise script errors. + # + proc processLookupMetadata { varName } { + # + # NOTE: If the metadata variable name appears to be invalid, fail. + # + if {[string length $varName] == 0} then { + error "bad metadata" + } + + # + # NOTE: This procedure requires that the metadata array variable is + # present in the call frame immediately above this one. + # + upvar 1 $varName metadata + + # + # NOTE: If the entire package metadata array is missing, fail. + # + if {![info exists metadata]} then { + error "missing metadata" + } + + # + # NOTE: If the patch level for the package is mising, fail. + # + if {![info exists metadata(patchLevel)]} then { + error "missing patch level" + } + + # + # NOTE: If the language for the package script is mising, fail. + # + if {![info exists metadata(language)]} then { + error "missing language" + } + + # + # NOTE: If the package script is mising, fail. + # + if {![info exists metadata(script)]} then { + error "missing script" + } + + # + # NOTE: If the package script certificate is mising, fail. + # + if {![info exists metadata(certificate)]} then { + error "missing script certificate" + } + + # + # NOTE: Create common cleanup script block that deletes any temporary + # files created for the script verification process. + # + set script(cleanup) { + if {[string length $fileName(2)] > 0 && \ + [file exists $fileName(2)] && [file isfile $fileName(2)]} then { + if {![info exists ::env(pkgr_keep_files)]} then { + catch {file delete $fileName(2)} + } + unset -nocomplain fileName(2) + } + + if {[string length $fileName(1)] > 0 && \ + [file exists $fileName(1)] && [file isfile $fileName(1)]} then { + if {![info exists ::env(pkgr_keep_files)]} then { + catch {file delete $fileName(1)} + } + unset -nocomplain fileName(1) + } + } + + # + # NOTE: Figure out the "type" of script certificate we are now dealing + # with. + # + if {[isHarpyCertificate $metadata(certificate)]} then { + # + # NOTE: Attempt to create a completely unique array variable name to + # hold the package metadata in this scripting language as well + # as possibly in the other necessary scripting language(s). + # + set newVarName(1) [appendArgs \ + [getLookupVarNamePrefix] metadata_ [getUniqueSuffix 2]] + + set newVarName(2) [appendArgs \ + [getLookupVarNamePrefix] cleanup_ [getUniqueSuffix 2]] + + set newProcName(1) [appendArgs \ + [getLookupVarNamePrefix] eagleHasSecurity_ [getUniqueSuffix 2]] + + set newProcName(2) [appendArgs \ + [getLookupVarNamePrefix] getFileTempName_ [getUniqueSuffix 2]] + + set newProcName(3) [appendArgs \ + [getLookupVarNamePrefix] tclMustBeReady_ [getUniqueSuffix 2]] + + # + # NOTE: Create the Eagle script block that will be used to securely + # evaluate a signed package script. This must be evaluated in + # Eagle because it uses several plugins only available there. + # + set script(outer) [string map [list \ + %metadata% $newVarName(1) %cleanup% $newVarName(2) \ + %eagleHasSecurity% $newProcName(1) %getFileTempName% \ + $newProcName(2) %tclMustBeReady% $newProcName(3)] { + try { + # + # NOTE: If there is no package script, there is nothing we + # can do here. + # + if {[string length ${%metadata%(script)}] > 0} then { + # + # NOTE: Save the security state for the interpreter. Then, attempt + # to enable it. This will fail if one of the needed plugins + # cannot be loaded. + # + set savedSecurity [{%eagleHasSecurity%}] + if {!$savedSecurity} then {source enableSecurity} + + try { + # + # NOTE: Figure out temporary file name for the downloaded script + # and its associated script certificate. + # + set fileName(1) [{%getFileTempName%}] + set fileName(2) [appendArgs $fileName(1) .harpy] + + try { + # + # NOTE: Write downloaded script to a temporary file. + # + writeFile $fileName(1) ${%metadata%(script)} + + # + # NOTE: Write downloaded script certificate to a temporary + # file. + # + if {[string length ${%metadata%(certificate)}] > 0} then { + writeFile $fileName(2) ${%metadata%(certificate)} + } + + # + # NOTE: This seems stupid. Why are we reading the downloaded + # script from the temporary file when we already had it + # in memory? The reason is that we need to make sure + # that the Harpy policy engine has a chance to check the + # downloaded script against its associated certificate. + # This will raise a script error if the script signature + # is missing or invalid. + # + set script(inner) [interp readorgetscriptfile -- \ + "" $fileName(1)] + + # + # NOTE: Determine the target language for the package script, + # which may or may not be the language that is currently + # evaluating this script (Eagle). The default language, + # when one was not explicitly specified, is Eagle. In + # the future, this may be changed, e.g. to use the file + # extension of the client script. + # + switch -exact -- ${%metadata%(language)} { + "" - + Eagle { + # + # NOTE: The target language is Eagle, which is evaluating + # this script. No special handling is needed here. + # + return [uplevel #0 $script(inner)] + } + Tcl { + # + # NOTE: The target language is Tcl; therefore, a bit of + # special handling is needed here. + # + {%tclMustBeReady%}; return [tcl eval [tcl master] [list \ + uplevel #0 $script(inner)]] + } + default { + error "unsupported language" + } + } + } finally { + # + # NOTE: Perform any necessary cleanup steps. + # + eval ${%cleanup%} + } + } finally { + # + # NOTE: Restore the saved security state for the interpreter. + # + if {!$savedSecurity} then {source disableSecurity} + unset -nocomplain savedSecurity + } + } + } finally { + rename {%tclMustBeReady%} "" + rename {%getFileTempName%} "" + rename {%eagleHasSecurity%} "" + + unset -nocomplain {%cleanup%} + unset -nocomplain {%metadata%} + } + }] + + # + # NOTE: Copy the package metadata into the fresh array variable, + # if necessary, marshalling it from native Tcl to Eagle. + # + if {[isEagle]} then { + array set $newVarName(1) [array get metadata] + set $newVarName(2) $script(cleanup) + + proc $newProcName(1) {} [info body [appendArgs \ + [namespace current] ::eagleHasSecurity]] + + proc $newProcName(2) {} [info body [appendArgs \ + [namespace current] ::getFileTempName]] + + proc $newProcName(3) {} [info body [appendArgs \ + [namespace current] ::tclMustBeReady]] + + return [eval $script(outer)] + } else { + eagleMustBeReady + + eagle [list array set $newVarName(1) [array get metadata]] + eagle [list set $newVarName(2) $script(cleanup)] + + eagle [list proc $newProcName(1) {} [info body [appendArgs \ + [namespace current] ::eagleHasSecurity]]] + + eagle [list proc $newProcName(2) {} [info body [appendArgs \ + [namespace current] ::getFileTempName]]] + + eagle [list proc $newProcName(3) {} [info body [appendArgs \ + [namespace current] ::tclMustBeReady]]] + + return [eagle $script(outer)] + } + } elseif {[isOpenPgpSignature $metadata(certificate)]} then { + # + # NOTE: If there is no package script, there is nothing we + # can do here. + # + if {[string length $metadata(script)] > 0} then { + # + # NOTE: Figure out temporary file name for the downloaded script + # and its associated OpenPGP signature. + # + set fileName(1) [getFileTempName] + set fileName(2) [appendArgs $fileName(1) .asc] + + # + # NOTE: Write downloaded script to a temporary file. + # + writeFile $fileName(1) $metadata(script) + + # + # NOTE: Write downloaded script OpenPGP signature a temporary file. + # + if {[string length $metadata(certificate)] > 0} then { + writeFile $fileName(2) $metadata(certificate) + } + + # + # NOTE: Attempt to verify the OpenPGP signature for the package + # script. + # + if {[verifyOpenPgpSignature $fileName(2)]} then { + # + # NOTE: Delete the temporary files that we created for the + # OpenPGP signature verification. + # + eval $script(cleanup) + } else { + # + # NOTE: Delete the temporary files that we created for the + # OpenPGP signature verification. + # + eval $script(cleanup) + + # + # NOTE: OpenPGP signature verification failed. Raise an error + # and do not proceed with evaluating the package script. + # + error "bad OpenPGP signature" + } + + # + # NOTE: The OpenPGP signature was verified; use the downloaded + # package script verbatim. + # + set script(inner) $metadata(script) + + # + # NOTE: Determine the target language for the package script, which + # may or may not be the language that is currently evaluating + # this script (Eagle). The default language, when one was not + # explicitly specified, is Eagle. In the future, this may be + # changed, e.g. to use the file extension of the client script. + # + switch -exact -- $metadata(language) { + "" - + Eagle { + if {[isEagle]} then { + return [uplevel #0 $script(inner)] + } else { + eagleMustBeReady + + return [eagle [list uplevel #0 $script(inner)]] + } + } + Tcl { + if {[isEagle]} then { + tclMustBeReady; return [tcl eval [tcl master] [list \ + uplevel #0 $script(inner)]] + } else { + return [uplevel #0 $script(inner)] + } + } + default { + error "unsupported language" + } + } + } + } else { + error "unsupported script certificate" + } + } + + # + # NOTE: This procedure returns non-zero if the specified package appears to + # be present. The package argument is the name of the package being + # sought, it cannot be an empty string. The version argument must be + # a specific version -OR- a package specification that conforms to TIP + # #268. + # + proc isPackagePresent { package version } { + variable verboseUnknownResult + + set command [list package present $package] + if {[string length $version] > 0} then {lappend command $version} + + if {[set code [catch $command result]] == 0} then { + if {$verboseUnknownResult} then { + pkgLog [appendArgs \ + "package \"" [formatPackageName $package $version] \ + "\" was loaded: " [formatResult $code $result]] + } + + return true + } else { + if {$verboseUnknownResult} then { + pkgLog [appendArgs \ + "package \"" [formatPackageName $package $version] \ + "\" was not loaded: " [formatResult $code $result]] + } + + return false + } + } + + # + # NOTE: This procedure returns non-zero if the specified package appears to + # be available. The package argument is the name of the package being + # sought, it cannot be an empty string. The version argument must be + # a specific version -OR- a package specification that conforms to TIP + # #268. + # + proc isPackageAvailable { package version } { + variable verboseUnknownResult + + set packageVersions [package versions $package] + + if {[llength $packageVersions] == 0} then { + if {$verboseUnknownResult} then { + pkgLog [appendArgs \ + "package \"" [formatPackageName $package $version] \ + "\" is not available: no versions"] + } + + return false + } + + if {[string length $version] == 0} then { + if {$verboseUnknownResult} then { + pkgLog [appendArgs \ + "package \"" [formatPackageName $package $version] \ + "\" is available: no version"] + } + + return true + } + + foreach packageVersion $packageVersions { + if {[package vsatisfies $packageVersion $version]} then { + if {$verboseUnknownResult} then { + pkgLog [appendArgs \ + "package \"" [formatPackageName $package $version] \ + "\" is available: version satisfied by \"" \ + [formatPackageName $package $packageVersion] \"] + } + + return true + } + } + + if {$verboseUnknownResult} then { + pkgLog [appendArgs \ + "package \"" [formatPackageName $package $version] \ + "\" is not available: version not satisfied"] + } + + return false + } + + # + # NOTE: This procedure returns non-zero if the specified package can be + # downloaded, i.e. because it is not required for the downloading + # process itself to be functional, etc. The package argument is + # the name of the package to check. + # + proc canDownloadPackage { package } { + # + # NOTE: Since all the functionality needed by this package is built-in + # to Eagle, there are no download restrictions when it is being + # used. + # + if {[isEagle]} then { + return true + } + + # + # NOTE: Since the "http" and "tls" packages are required from within + # the custom [package unknown] itself, in order to locate and + # download the requested package, we must return false here to + # prevent needless recursion. + # + if {[lsearch -exact [list http tls] $package] != -1} then { + return false + } + + # + # NOTE: Currently, all other packages, including Garuda, are legal to + # handle from the custom [package unknown] handler. + # + return true + } + + # + # NOTE: This procedure performs initial setup of the package repository + # client, using the current configuration parameters. There are + # no arguments. It may load the Garuda package when evaluated in + # native Tcl. It may load a native Tcl library when evaluated in + # Eagle. It may install the [package unknown] hook. + # + proc setupPackageUnknownHandler {} { + variable autoApiKeys + variable autoHook + variable autoLoadTcl + variable autoRequireGaruda + + # + # NOTE: Should we attempt to automatically load the Garuda package for + # native Tcl? + # + if {$autoRequireGaruda && ![isEagle] && [isWindows]} then { + makeEagleReady + } + + # + # NOTE: Should we attempt to automatically load a native Tcl library + # for Eagle? + # + if {$autoLoadTcl && [isEagle]} then { + makeTclReady + } + + # + # NOTE: Should we attempt to hook the [package unknown] handler. This + # is done for both native Tcl and Eagle. + # + if {$autoHook && ![isPackageUnknownHandlerHooked]} then { + # + # NOTE: Install our [package unknown] handler and save the original + # one for our use as well. + # + hookPackageUnknownHandler + } + } + + # + # NOTE: This procedure returns non-zero if the [package unknown] handler + # has already been hooked by the package repository client. There + # are no arguments. + # + proc isPackageUnknownHandlerHooked {} { + return [info exists [appendArgs \ + [getLookupVarNamePrefix] saved_package_unknown]] + } + + # + # NOTE: This procedure attempts to hook the [package unknown] handler. It + # will raise a script error if this has already been done. The old + # [package unknown] handler is saved and will be used by the new one + # as part of the overall package loading process. There are no + # arguments. + # + proc hookPackageUnknownHandler {} { + set varName [appendArgs [getLookupVarNamePrefix] saved_package_unknown] + + if {[info exists $varName]} then { + error "package unknown handler already hooked" + } + + set $varName [package unknown] + package unknown [appendArgs [namespace current] ::packageUnknownHandler] + } + + # + # NOTE: This procedure attempts to unhook the [package unknown] handler. + # It will raise a script error if the [package unknown] handler is + # not hooked. The old [package unknown] handler is restored and + # the saved [package unknown] handler is cleared. There are no + # arguments. + # + proc unhookPackageUnknownHandler {} { + set varName [appendArgs [getLookupVarNamePrefix] saved_package_unknown] + + if {![info exists $varName]} then { + error "package unknown handler is not hooked" + } + + package unknown [set $varName] + unset $varName + } + + # + # NOTE: The procedure runs the saved [package unknown] handler. Any script + # errors are raised to the caller. The package and version arguments + # are passed in from the current [package unknown] handler verbatim. + # + proc runSavedPackageUnknownHandler { package version } { + # + # NOTE: See if there is a saved [package unknown] handler. If so, then + # attempt to use it. + # + set varName [appendArgs [getLookupVarNamePrefix] saved_package_unknown] + set oldHandler [expr {[info exists $varName] ? [set $varName] : ""}] + + if {[string length $oldHandler] > 0} then { + lappend oldHandler $package $version; uplevel #0 $oldHandler + } + } + + # + # NOTE: This procedure is the [package unknown] handler entry point called + # by native Tcl and Eagle. The package argument is the name of the + # package being sought, it cannot be an empty string. The version + # argument must be a specific version -OR- a package specification + # that conforms to TIP #268. This version argument must be optional + # here, because Eagle does not add a version argument when one is + # not explicitly supplied to the [package require] sub-command. + # + proc packageUnknownHandler { package {version ""} } { + variable verboseUnknownResult + + # + # NOTE: First, run the saved [package unknown] handler. + # + set code(1) [catch { + runSavedPackageUnknownHandler $package $version + } result(1)] + + if {$verboseUnknownResult} then { + pkgLog [appendArgs \ + "initial saved handler results for package \"" \ + [formatPackageName $package $version] "\" are " \ + [formatResult $code(1) $result(1)]] + } + + # + # NOTE: Did the saved [package unknown] handler succeed? + # + if {$code(1) == 0} then { + # + # NOTE: Is the package now available -OR- somehow already present? + # + if {[isPackagePresent $package $version] || \ + [isPackageAvailable $package $version]} then { + # + # NOTE: Skip using the package repository. + # + return + } + } + + # + # NOTE: Next, run our special [package unknown] handler. + # + if {[canDownloadPackage $package]} then { + set code(2) [catch { + getPackageFromRepository $package $version handler + } result(2)] + + if {$verboseUnknownResult} then { + pkgLog [appendArgs \ + "repository handler results for package \"" \ + [formatPackageName $package $version] "\" are " \ + [formatResult $code(2) $result(2)]] + } + } + + # + # NOTE: Next, run the saved [package unknown] handler. + # + set code(3) [catch { + runSavedPackageUnknownHandler $package $version + } result(3)] + + if {$verboseUnknownResult} then { + pkgLog [appendArgs \ + "subsequent saved handler results for package \"" \ + [formatPackageName $package $version] "\" are " \ + [formatResult $code(3) $result(3)]] + } + + # + # NOTE: Maybe check for the package and then optionally log results. + # + if {$verboseUnknownResult} then { + set ifNeededVersion [getIfNeededVersion \ + $package [packageRequirementToVersion $version]] + + if {[string length $ifNeededVersion] > 0} then { + set command [list package ifneeded $package $ifNeededVersion] + + if {[set code(4) [catch $command result(4)]] == 0 && \ + [string length $result(4)] > 0} then { + pkgLog [appendArgs \ + "package script for \"" [formatPackageName $package \ + $ifNeededVersion] "\" was added: " [formatResult \ + $code(4) $result(4)]] + } else { + pkgLog [appendArgs \ + "package script for \"" [formatPackageName $package \ + $ifNeededVersion] "\" was not added: " [formatResult \ + $code(4) $result(4)]] + } + } else { + pkgLog [appendArgs \ + "package script for \"" [formatPackageName $package \ + $ifNeededVersion] "\" was not added"] + } + + # + # NOTE: Check (and log) if the package is now present. The return + # value here is ignored. + # + isPackagePresent $package $version + } + } + + # + # NOTE: This procedure evaluates the package repository client settings + # script file, if it exists. Any script errors raised are not + # masked. The script argument must be the fully qualified path + # and file name for the primary package repository client script + # file. + # + # + proc maybeReadSettingsFile { script } { + global tcl_platform + + if {[string length $script] == 0 || \ + ![file exists $script] || ![file isfile $script]} then { + return + } + + foreach prefix [list $tcl_platform(user) ""] { + if {[string length $prefix] > 0} then { + set prefix [appendArgs . $prefix] + } + + set fileName [appendArgs \ + [file rootname $script] .settings $prefix [file extension \ + $script]] + + if {[file exists $fileName] && [file isfile $fileName]} then { + uplevel 1 [list source $fileName] + } + } + } + + # + # NOTE: This procedure sets up the default values for all configuration + # parameters used by the package repository client. There are no + # arguments. + # + proc setupPackageUnknownVars {} { + # + # NOTE: Should the HTTP request processor attempt to force the use of + # HTTPS for URIs that were originally HTTP? This setting is only + # applicable to native Tcl. + # + variable forceSecureUri; # DEFAULT: true + + if {![info exists forceSecureUri]} then { + set forceSecureUri true + } + + # + # NOTE: Is this HTTP request processor allowed to use plain HTTP if/when + # the "tls" package is not available? This should only be changed + # if the "tls" package cannot be easily installed for use with the + # native Tcl interpreter in use. It should be noted here that the + # official package repository server reserves the right to refuse + # plain HTTP connections, which means that changing this setting + # may be totally pointless. + # + variable allowInsecureUri; # DEFAULT: false + + if {![info exists allowInsecureUri]} then { + set allowInsecureUri false + } + + # + # NOTE: Emit diagnostic messages when the [::http::geturl] procedure is + # about to be called? + # + variable verboseGetUrl; # DEFAULT: false + + if {![info exists verboseGetUrl]} then { + set verboseGetUrl false + } + + # + # NOTE: Is this HTTP request processor allowed to use plain HTTP if/when + # the server responds with an HTTP redirect location to an original + # URI that was HTTPS? Otherwise, a script error will result. + # + variable allowInsecureRedirect; # DEFAULT: false + + if {![info exists allowInsecureRedirect]} then { + set allowInsecureRedirect false + } + + # + # NOTE: What is the default set of API keys if none were set explicitly? + # This list is subject to change at any time -AND- may be empty or + # may contain non-working API keys, please do not rely on it. + # + variable autoApiKeys; # DEFAULT: 0000000000000000000000000000000000000000 + + if {![info exists autoApiKeys]} then { + set autoApiKeys [list 0000000000000000000000000000000000000000] + } + + # + # NOTE: Automatically install our [package unknown] handler when this + # package is loaded? + # + variable autoHook; # DEFAULT: true + + if {![info exists autoHook]} then { + set autoHook true + } + + # + # NOTE: Automatically [tcl load] when this package is loaded from the + # Eagle language? + # + variable autoLoadTcl; # DEFAULT: + + if {![info exists autoLoadTcl]} then { + # + # TODO: Better automatic detection of native Tcl installs here? + # + if {[isEagle] && \ + [catch {tcl select -architecture}] == 0} then { + set autoLoadTcl true + } else { + set autoLoadTcl false + } + } + + # + # NOTE: Automatically [package require Garuda] when this package is + # loaded from the Tcl language? + # + variable autoRequireGaruda; # DEFAULT: + + if {![info exists autoRequireGaruda]} then { + # + # TODO: Better automatic detection of Garuda here? + # + if {![isEagle] && \ + [llength [package versions Garuda]] > 0} then { + set autoRequireGaruda true + } else { + set autoRequireGaruda false + } + } + + # + # NOTE: The command to use when verifying OpenPGP signatures for the + # downloaded package scripts. + # + variable openPgpCommand; # DEFAULT: gpg2 --verify {${fileName}} + + if {![info exists openPgpCommand]} then { + set openPgpCommand {gpg2 --verify {${fileName}}} + } + + # + # NOTE: Verify that the package script matches the current language + # when called from the [package unknown] handler? + # + variable strictUnknownLanguage; # DEFAULT: true + + if {![info exists strictUnknownLanguage]} then { + set strictUnknownLanguage true + } + + # + # NOTE: Emit diagnostic messages when a [package unknown] handler + # is called? + # + variable verboseUnknownResult; # DEFAULT: false + + if {![info exists verboseUnknownResult]} then { + set verboseUnknownResult false + } + + # + # NOTE: Emit diagnostic messages when a URI is fetched? + # + variable verboseUriDownload; # DEFAULT: false + + if {![info exists verboseUriDownload]} then { + set verboseUriDownload false + } + } + + # + # NOTE: This procedure is the primary entry point to the package repository + # client. It attempts to lookup the specified package using the + # currently configured package repository server. The package + # argument is the name of the package being sought, it cannot be an + # empty string. The version argument must be a specific version -OR- + # a package specification that conforms to TIP #268. The caller + # argument must be an empty string -OR- the literal string "handler". + # + # + proc getPackageFromRepository { package version caller } { + # + # NOTE: Get the list of API keys and try each one, in order, until + # the package is found. + # + set apiKeys [getApiKeys] + + # + # NOTE: Issue the non-anonymous lookup request to the remote + # package repository. + # + set data [getLookupData $apiKeys $package $version] + + # + # NOTE: Attempt to grab the lookup code from the non-anonymous + # response data. + # + set code [getLookupCodeFromData $data] + + # + # NOTE: If necessary, fallback with to an anonymous request. + # + if {![isLookupCodeOk $code]} then { + # + # NOTE: Issue the anonymous lookup request to the remote + # package repository. + # + set data [getLookupData [list] $package $version] + + # + # NOTE: Attempt to grab the lookup code from the anonymous + # response data. + # + set code [getLookupCodeFromData $data] + } + + # + # NOTE: Attempt to grab the lookup data from the response data. + # Upon failure, this should contain the error message. + # + set result [getLookupResultFromData $data] + + # + # NOTE: Did the lookup operation fail? + # + if {![isLookupCodeOk $code]} then { + # + # NOTE: Is there an error message? + # + if {[string length $result] > 0} then { + # + # NOTE: Yes. Use the returned error message verbatim. + # + error $result + } else { + # + # NOTE: No. Use the whole response data string as the error + # message. + # + error $data + } + } + + # + # NOTE: Process the lookup data into the pieces of metadata that we + # need to load the requested package. + # + extractAndVerifyLookupMetadata $result metadata $caller + + # + # NOTE: Attempt to load the requested package using the metadata + # extracted in the previous step. + # + processLookupMetadata metadata + } + + if {![isEagle]} then { + ########################################################################### + ############################# BEGIN Tcl ONLY ############################## + ########################################################################### + + # + # NOTE: This procedure was stolen from the "getEagle.tcl" script. It is + # designed to emit a message to the console. The channel argument + # is the channel where the message should be written. The string + # argument is the content of the message to emit. + # + proc pageOut { channel string } { + catch { + puts -nonewline $channel $string; flush $channel + } + } + + # + # NOTE: This procedure was stolen from the "getEagle.tcl" script. It is + # designed to emit a message to the HTTP client log. The string + # argument is the content of the message to emit. + # + proc pageLog { string } { + catch { + tclLog [appendArgs [pid] " : " [clock seconds] " : http : " $string] + } + } + + # + # NOTE: This procedure was stolen from the "getEagle.tcl" script. It is + # designed to emit a progress indicator while an HTTP request is + # being processed. The channel argument is the Tcl channel where + # the progress indicator should be emitted. The type argument is + # the single-character progress indicator. The milliseconds + # argument is the number of milliseconds to wait until the next + # periodic progress indicator should be emitted. This procedure + # reschedules its own execution. + # + proc pageProgress { channel type milliseconds } { + # + # NOTE: This variable is used to keep track of the currently scheduled + # (i.e. pending) [after] event. + # + variable afterForPageProgress + + # + # NOTE: Show that something is happening... + # + pageOut $channel $type + + # + # NOTE: Make sure that we are scheduled to run again, if requested. + # + if {$milliseconds > 0} then { + set afterForPageProgress [after $milliseconds \ + [namespace code [list pageProgress $channel $type \ + $milliseconds]]] + } else { + unset -nocomplain afterForPageProgress + } + } + + # + # NOTE: This procedure was stolen from the "getEagle.tcl" script. It is + # designed to process a single HTTP request, including any HTTP + # 3XX redirects (up to the specified limit), and return the raw + # HTTP response data. It may raise any number of script errors. + # + # + proc getFileViaHttp { uri redirectLimit channel quiet args } { + # + # NOTE: This variable is used to determine if plain HTTP URIs should be + # converted to HTTPS, if the "tls" package is available. + # + variable forceSecureUri + + # + # NOTE: This variable is used to determine if plain HTTP is allowed if + # the "tls" package is not available. + # + variable allowInsecureUri + + # + # NOTE: This variable is used to determine if a diagnostic message is + # emitted when [::http::geturl] is about to be called. + # + variable verboseGetUrl + + # + # NOTE: This variable is used to determine if plain HTTP is allowed if + # an HTTP redirect response contains an HTTP URI and the original + # URI was HTTPS. + # + variable allowInsecureRedirect + + # + # NOTE: This variable is used to keep track of the currently scheduled + # (i.e. pending) [after] event. + # + variable afterForPageProgress + + # + # NOTE: This procedure requires the modern version of the HTTP package, + # which is typically included with the Tcl core distribution. + # + package require http 2.0 + + # + # NOTE: If the 'tls' package is available, always attempt to use HTTPS; + # otherwise, only attempt to use HTTP if explicitly allowed. + # + if {[catch {package require tls}] == 0} then { + ::http::register https 443 [list ::tls::socket -tls1 true] + + if {$forceSecureUri} then { + if {[string range $uri 0 6] eq "http://"} then { + set uri [appendArgs https:// [string range $uri 7 end]] + } + } + } else { + if {$allowInsecureUri} then { + if {[string range $uri 0 7] eq "https://"} then { + set uri [appendArgs http:// [string range $uri 8 end]] + } + } + } + + # + # NOTE: Unless the caller forbids it, display progress messages during + # the download. + # + if {!$quiet} then { + pageProgress $channel . 250 + } + + # + # NOTE: All downloads are handled synchronously, which is not ideal; + # however, it is simple. Keep going as long as there are less + # than X redirects. + # + set redirectCount 0 + + while {1} { + # + # NOTE: Issue the HTTP request now, grabbing the resulting token. + # + if {$verboseGetUrl} then { + # + # NOTE: Emit important diagnostic information related to this + # HTTP request here. This may be enhanced in the future. + # + pageLog [appendArgs \ + "attempting to download URL \"" $uri \"...] + } + + set token [eval [list ::http::geturl $uri] $args] + + # + # NOTE: Grab the HTTP response code and data now as they are needed + # in almost all cases. + # + set code [::http::ncode $token]; set data [::http::data $token] + + # + # NOTE: Check the HTTP response code, in order to follow any HTTP + # redirect responses. + # + switch -glob -- $code { + 100 - + 101 - + 102 { + ::http::cleanup $token; error [appendArgs \ + "unsupported informational HTTP response status code " \ + $code ", data: " $data] + } + 200 - + 201 - + 202 - + 203 - + 204 - + 205 - + 206 - + 207 - + 208 - + 226 { + # + # NOTE: Ok, the HTTP response is actual data of some kind (which + # may be empty). + # + ::http::cleanup $token; break + } + 301 - + 302 - + 303 - + 307 - + 308 { + # + # NOTE: Unless the caller forbids it, display progress messages + # when an HTTP redirect is returned. + # + if {!$quiet} then { + pageProgress $channel > 0 + } + + # + # NOTE: We hit another HTTP redirect. Stop if there are more + # than X. + # + incr redirectCount + + # + # TODO: Maybe make this limit more configurable? + # + if {$redirectCount > $redirectLimit} then { + # + # NOTE: Just "give up" and raise a script error. + # + ::http::cleanup $token; error [appendArgs \ + "redirection limit of " $redirectLimit " exceeded"] + } + + # + # NOTE: Grab the metadata associated with this HTTP response. + # + array set meta [::http::meta $token] + + # + # NOTE: Is there actually a new URI (location) to use? + # + if {[info exist meta(Location)]} then { + # + # NOTE: Ok, grab it now. Later, at the top of the loop, + # it will be used in the subsequent HTTP request. + # + set location $meta(Location); unset meta + + # + # NOTE: For security, by default, do NOT follow an HTTP + # redirect if it attempts to redirect from HTTPS + # to HTTP. + # + if {!$allowInsecureRedirect && \ + [string range $uri 0 7] eq "https://" && \ + [string range $location 0 7] ne "https://"} then { + # + # NOTE: Just "give up" and raise a script error. + # + ::http::cleanup $token; error [appendArgs \ + "refused insecure redirect from \"" $uri "\" to \"" \ + $location \"] + } + + # + # NOTE: Replace the original URI with the new one, for + # use in the next HTTP request. + # + set uri $location + + # + # NOTE: Cleanup the current HTTP token now beause a new + # one will be created for the next request. + # + ::http::cleanup $token + } else { + # + # NOTE: Just "give up" and raise a script error. + # + ::http::cleanup $token; error [appendArgs \ + "redirect from \"" $uri "\" missing location, code " \ + $code ", data: " $data] + } + } + 300 - + 304 - + 305 - + 306 { + ::http::cleanup $token; error [appendArgs \ + "unsupported redirection HTTP response status code " $code \ + ", data: " $data] + } + 4?? { + ::http::cleanup $token; error [appendArgs \ + "client error HTTP response status code " $code ", data: " \ + $data] + } + 5?? { + ::http::cleanup $token; error [appendArgs \ + "server error HTTP response status code " $code ", data: " \ + $data] + } + default { + ::http::cleanup $token; error [appendArgs \ + "unrecognized HTTP response status code " $code ", data: " \ + $data] + } + } + } + + # + # NOTE: If there is a currently scheduled [after] event, cancel it. + # + if {[info exists afterForPageProgress]} then { + catch {after cancel $afterForPageProgress} + unset -nocomplain afterForPageProgress + } + + # + # NOTE: If progress messages were emitted, start a fresh line. + # + if {!$quiet} then { + pageOut $channel [appendArgs " " $uri \n] + } + + return $data + } + + ########################################################################### + ############################## END Tcl ONLY ############################### + ########################################################################### + } + + # + # NOTE: This package requires that support for namespaces, which is an + # optional feature of Eagle, must be enabled. + # + if {[isEagle] && ![namespace enable]} then { + error "namespaces must be enabled for this package" + } + + # + # NOTE: Attempt to read optional settings file now. This may override + # one or more of the variable setup in the next step. + # + maybeReadSettingsFile [info script] + + # + # NOTE: Setup the variables, within this namespace, used by this script. + # + setupPackageUnknownVars + + # + # NOTE: Setup for our [package unknown] handler, which may involve a few + # different operations. + # + setupPackageUnknownHandler + + # + # NOTE: Provide the package to the interpreter. + # + package provide Eagle.Package.Repository \ + [expr {[isEagle] ? [info engine PatchLevel] : "1.0"}] +} + ADDED client/1.0/neutral/pkgr.eagle.asc Index: client/1.0/neutral/pkgr.eagle.asc ================================================================== --- client/1.0/neutral/pkgr.eagle.asc +++ client/1.0/neutral/pkgr.eagle.asc @@ -0,0 +1,18 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2 +Comment: Eagle Package Repository + +iQIcBAABCAAGBQJYD+PZAAoJEFAslq9JXcLZclAP/i7g22I9YZRHfNP+q/UyrIL8 +F+gPmRy2X1mP9QZQX+N0WStBoepR/jsfPI///8dRhljIqWf8QxXy+d/zi9sCIIOB +x4sY/b2c5s7Ao8EhtqUSnwkkDUCk12Ofw88JmRNPxtvUtDR5rd82rRfBr0kI+LGx +IN6c0Wtx4BpxYOhRD1NtSBExyCUMmW16x8CJ6naIlkkl2xxOTdf/HblnLSIfAszM +y73JtbAV0danPvHTZ65QZli0P9ZzZNJ7eBOH4X9vuX3d9+TO7cerlyaCVZgIu3V6 +6l95Fh7OLfLiDXei0mLCLh7nQZyvRb0Ude1uN//Isk78vBKYaOYZZ9Hu5oROx4BL +LCSHEH9dOBpdK3hzYSOeYUoYmV3lwkfHYyVBTAxLUHNXyCpDm9nvBIdURwnHEPv5 ++uyP3YAqxpllJHB6/lPUe85SZMTcAyZBksOlDmM2IHF1OVMbLBK8rB1MI1yGYMHB +dswyovXsn5jBjmBMK5eBkbvvpU20Sc8f6qxW0LfQtXyh7cQSWjoBBU++Yax63tW1 +E3j8PQ5G/E3f/6hIxJHjeChg/I4XUgqr5jPynsOHFXZQVnBp45hpjfuu/y5WvKdX +4fZlqN0JdDsEMXhk/5gr9Rtr0/nZpNZfzQznaT98rw8QiH2VsH9YCPrMfO9bWhsV +z+K95Tyspz0QwRKpb1+C +=LAEu +-----END PGP SIGNATURE----- ADDED client/1.0/neutral/pkgr.eagle.harpy Index: client/1.0/neutral/pkgr.eagle.harpy ================================================================== --- client/1.0/neutral/pkgr.eagle.harpy +++ client/1.0/neutral/pkgr.eagle.harpy @@ -0,0 +1,68 @@ + + + + None + Mistachkin Systems + c8c90246-6344-4855-ab6d-1fcfa00eae47 + SHA512 + Script + 2016-10-25T22:59:06.8710469Z + -1.00:00:00 + 0x9559f6017247e3e2 + + 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 + + ADDED client/1.0/neutral/pkgr.eagle.harpy.asc Index: client/1.0/neutral/pkgr.eagle.harpy.asc ================================================================== --- client/1.0/neutral/pkgr.eagle.harpy.asc +++ client/1.0/neutral/pkgr.eagle.harpy.asc @@ -0,0 +1,18 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2 +Comment: Eagle Package Repository + +iQIcBAABCAAGBQJYD+PbAAoJEFAslq9JXcLZpp8P/A6nC2lb6osifnBNVvQE0/2H +swK6JhVNbSfLRxVTBJP+SYd6htKkXu74/41JMeXe4fqnyxHEeFnYHp+BWplseoMg +O1ZhpeOYlfCVakGqA6Pc0MVrVIy85/Z8CR/06UvGdAwUA91s8UFpHa/LjjfDXTDb +eMZe2WVBG+UzsI4nKsXt9MWnPjMGTHWHU9zs67idO12BFZ2Z37O4H42mzzvdMVWu +X0SbqAEozavvRI5M6WR/Gxfg+hYH+nacEL7pfW0/lOGj6eqQe7YPTQhCdjzIKjFu +kNHPalXOjODe0z1yqu5bI7RNhglVCK/lblvziDVlCSaUIkqNJCuPXsx4PAfH3yoq +uENO8v675hG+HBMBKQxBBHleNQk4X1KCvVgLrOQsPNq3usJoZIgwUP6DeESLaJn6 +PD/JnsnC/KCgiAjF27PY8kX3HWAQD9Gpe7PIlgxO8wYYK0hhlcm4zyMZD+Oet1VZ +g/qEjmQ4ulJcOWrDPPMJD4Tvq36ryAtpMHWJR2cI+WQ7r9qtmCQRN7DBDHfgi2Sr +1ccqMOI6SdXCrUlFi9SEDHZg6UnA0xbXBo/ZnXhQXq1NyQR3SpD/2/bZB51OJUaY +sseXOErRPd8XN5Px4xsto4tbzMByXQnAniLv6cX90oO5naZNhmA2NSgsfSGTZgqr +etZXrF2EBBnDuaZ3uCgR +=BVw9 +-----END PGP SIGNATURE----- ADDED client/1.0/neutral/pkgr.settings.mistachkin.eagle Index: client/1.0/neutral/pkgr.settings.mistachkin.eagle ================================================================== --- client/1.0/neutral/pkgr.settings.mistachkin.eagle +++ client/1.0/neutral/pkgr.settings.mistachkin.eagle @@ -0,0 +1,23 @@ +############################################################################### +# +# pkgr.settings.mistachkin.eagle -- +# +# Extensible Adaptable Generalized Logic Engine (Eagle) +# Package Repository Client Settings +# +# Copyright (c) 2007-2012 by Joe Mistachkin. All rights reserved. +# +# See the file "license.terms" for information on usage and redistribution of +# this file, and for a DISCLAIMER OF ALL WARRANTIES. +# +# RCS: @(#) $Id: $ +# +############################################################################### + +# TODO: Set this to your list of API keys. +# set ::pkgr_api_keys [list 0000000000000000000000000000000000000000] + +variable strictUnknownLanguage false +variable verboseGetUrl true +variable verboseUnknownResult true +variable verboseUriDownload true ADDED client/1.0/neutral/pkgr.settings.mistachkin.eagle.asc Index: client/1.0/neutral/pkgr.settings.mistachkin.eagle.asc ================================================================== --- client/1.0/neutral/pkgr.settings.mistachkin.eagle.asc +++ client/1.0/neutral/pkgr.settings.mistachkin.eagle.asc @@ -0,0 +1,18 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2 +Comment: Eagle Package Repository + +iQIcBAABCAAGBQJYBVUUAAoJEFAslq9JXcLZZeEP/1OIZqUc2pS7lcN4FutRuqh4 +3uB13RzJvjBNU/urSxqfuM9oJWl3GXndP/bmLJ2Qo8wXndBbpZR+YOAB3uiPYqHu +0UqauAWjKwvF0u3RqYBIU2oMYB5mxnh4Yvo9f7T3rC0cAjPmbrgpH7wYlCiml1k7 +UmoVIbN+V3LQV3mkfkv1aXFOWBrSVoz1bq8ngfBcup5R5+kGe+mqZkYMtDQQwKze +wgJdCd1hOQEMdaZlMXmD9lf8uXRC1lBYc8eJyqZsmAxwONoA67NMjazyRydhu4kE +Dx/ObuNYr8kiREjXkPLd65LKbMyFSqc/2GzJylB1T1jjuvcXbH+GYlf4rvfJhN1o +mt8LSdx9Blqxzu5X52KQFCOYH60zO84oX087IPxxPnrdzy688Pzd2Glfmit1NhOr +L6TmwtAh4Y4Lc+ohSkvz5zpKD50N0VN272vWsZCZ2TfIvk7zn0Xa6X1UAOyWhuTc +cFZnGuo7v5XvLxUp5A1EGmGg0JBoJbOgsrXFtD6jEWS61H5SEvMqlPlfctNnoKli +B+3jtV6wAO6Qpc25j1XztbJu73m/fHn9KHNW/ZmVcwG9BVqUSk5qUzsKkIfGnpS2 +ekbycPUDL8UZ2IiqxPKsoRQ2RYPOQt7NI1psTi8j3BwYq3ppIhDMuOfU49LPNK1J +ir9Lzx5tFwbA0azEOxT5 +=78ho +-----END PGP SIGNATURE----- ADDED client/1.0/neutral/pkgr.settings.mistachkin.eagle.harpy Index: client/1.0/neutral/pkgr.settings.mistachkin.eagle.harpy ================================================================== --- client/1.0/neutral/pkgr.settings.mistachkin.eagle.harpy +++ client/1.0/neutral/pkgr.settings.mistachkin.eagle.harpy @@ -0,0 +1,68 @@ + + + + None + Mistachkin Systems + 2585a4fc-8467-4d93-99d6-11c5afbcb752 + SHA512 + Script + 2016-10-17T22:47:03.9483672Z + -1.00:00:00 + 0x9559f6017247e3e2 + + MHVBfTDFrlbDB3EjQLeyc2sSm6S7m7NXImi1C1tIEK+yrh+WwAJNnRG0hw6efZ2aUWvFX6oUZRQJ + X+KlY+ujsuxHFdWcWaktZIynQ+SRIYP2nW2YXVBU+BEpmcCIJSwlDSw0/+PYb9J1mVQuIeCgCIt9 + vVrjSxZ7hkHdGqeRzH4oOFD1CyQR4cZ1tFaR4G++M6kT333Hx8H+5j2OYPloPLU5oz2k7nnIDW/w + zTrKBkp/HLOogY0jSmspwu9LbWuHf6TnTTi4ltzvGrw8DDzfQDKfcDOW4CspiFZU06fOjPSOapQZ + mMaGTxT+ZkVqUZITLoVtsFVp4AZkB2RrMEPndTRNEP05v/xEBs0FE2WpKZTQbFNI9vqpnbPkpFzQ + vNa4Xl/YjTjUGLqUc8Fa7pqVSoHog4WBye3v0Y/aWiJ4JtTLC98fA/sqJF9nwfy9uxb3V19yn+6l + vDbEUmpQI0c3OYVRrqhaBgreyNRN8JMhhoIJcR5o9pVqIEXaxX36y6gl4jYS8uI0/Gr6aTON/1FX + TVC4OekdoPzrtIUI36RKoQA3BhPf912p360rsmPsrAy6zHKl14qCJbcLheF9HYzFPJFFrI6p3Lj2 + uAAAUhQl4iQ16ykG6dewrkxdudo0QB7gY0wOSLNpWLHbMbeLKAHHNlNG7PKIkkV8TR+NysBjrZ33 + qfn50HSIc3gQtdzRdaw8C9bU2iajUYscyBg/o7F76YOqs6cwXj/TBbv/SwRQu/AtBzMfeh/8+Gd5 + 21homMufCPxWU/80Y3awIBHSBXSMWd4fVo/ZJCBY2z5MThysA6TQYAiNSVesEbAFWcHQ2rz77UUp + a+/k0oB5coaNZbc0ae8E5Xo6xlBoSVkrZN+NIiNIZKSQj93bp8U8H1jM7Ygl07Htbj4sOHUNokZT + z8jl4Ikpf//muD+iBlXFcYgc5eDGZthsFTh/hwE0bFST/p6D7oBPXrR844Qg167yRVnx31GXnG1W + pQAnJcwoyni1MbAgQRJUK2sza25/QU/fll6zsWA8MzrXwe/khjwCmMCx2JurhS0sSPOZA+2n2Xef + bw+M3MofOaWCdNzQeEfifPJAKvYfxM0pIf0FypnT6DNQOVsZ+i5j8Uj31sn75cg0KvYkHCMILHG+ + iKHmWTC+gs2yICd+5nJ+Nw7ICTrO0hiFyBP4PaWZEGaIXdkHIVEuFvu/L9JtmpHj6x7lIG3nZYGr + faPl9TVgRcDmgDk8ySjaIF9g88U9KRJoKwPzOVEb0JZceBhh9WdTpWy1mZCc+zCBZAtRzFM8AgJj + ijzHia6rCn/5200lmycvjzx2o9lUGsOqHbN8ckaTKQ+5r+WIu1/voBkktxkKZMWZmwPyFI2/PmcC + 7kuDz6r5gVsjWs+8r4ARqft1bafsF6TNOt9MwqZYyWltcVLKqfjlVDg1aVROFWFRCBR/CnAtyN8s + QxqWFrv+MDDAv49nMJkeoaJpmBdz2Bs+l5xShyGPUisHRJ9NqPpWC2wUYupg51IX6Weyl5jUPd/W + gBhiYoZGzvsVopFsdkb1VjJJUkugnXnlZx9X1z/Jz9h0BBSC1qFcC2nK6a5HOpgMOJvGgy0K+kKY + irx+bdDvaljqcJW2fvx/7yAVbs5EaP3MFj6CmuQoD9Il/R/T+tWkpkm8fpQ3KywPAFTmhkLLdbZ/ + GnQ5QBj3AQelUGy8TB2gaNO9JzkqCQEctEIOKkUYOgJs+LgOikXyk8vzFqwLM0sYKdt3obn1Fgag + zkNPdgzWlBt5OLG0vjM54dA/P9UYjAbzaykce9fX4uilVBJWotlgUM8vq+qSsTTuEDWgXVtie6+G + YoVw9FV1BCeT1MhLKYAaAEk+WaZ33bMPGBh5QNKVICQL+y3kmMEzZlAuTGuKmFAzaryCFPztRvYf + y7XyMtXcmXUg0ppOgMGacCFl5izwqjTr50kotXP2xuLrGgzNoqKyzjTJKPPBPxLX1UZGwrPLEd0J + qGvSmLTgyGKcU92M6VNF59mNCAxEpNkKdJBqgn22BLGGGdbua9Q/EVBYAbFkfzEwPTp/b6d6tcFG + VkLyPS7XRvo/TijB7PrUfS6svcqKEmscalvuTBFEQo7AE+jpCf5QupixaxmfVwMSXlsAPz0eKp8t + pn4K0cYeN6F+aLi2DMq18FT/BACd8AhnvuP7b8MoRh+qjeSgJtWYB9ItAzQYUlau3IOPOa4ArPgd + c6MrGV8hsc69XBQBqMiUteYWHnQUQvYdQiFPjkIHlXTBKEUE1a2Ll3lx1vnI++flxT2qLb7qhA5+ + HBOWnugQd/K9xWDrZ7yavRHEm8Bw2iHKALxFNH6RNqkOxUb9HZBF7mYRvJG5DhVLnrfrFb4cK1Xs + sT4GXbkMD7zuHs4cWoZuYWfD3Nv9MKSWB9L/icnwbQBnxXPMTwA5jvalD3mCF7IX/Uld55QjLCtP + gtTpXREjLPSlGBao+ulrKOf/eiJYS/2oL02QSKcTT/cybZpOvxihwHAsQDduezMV8LCe7sXq+ryy + cJQ4Po+FYf9KmXJ99t6Us+LqD45fNAo+5eEhaV76BdKXdUNuPeaH//mJXfRCvqFme1JFEkWBEYrD + C+E0rUfruaWudO5gV52k810ECIULIZDqre4ZE3aUYOVvvQxrMM2lXCh+NFmOcM0iZLfRClDIStyu + 1rZpbGpLB3CS74YaxutlVX22XpzJvPRTeb737NUsxCokjIET6xB9prvUhOrn8psS/cCYmvI= + + ADDED client/1.0/neutral/pkgr.settings.mistachkin.eagle.harpy.asc Index: client/1.0/neutral/pkgr.settings.mistachkin.eagle.harpy.asc ================================================================== --- client/1.0/neutral/pkgr.settings.mistachkin.eagle.harpy.asc +++ client/1.0/neutral/pkgr.settings.mistachkin.eagle.harpy.asc @@ -0,0 +1,18 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2 +Comment: Eagle Package Repository + +iQIcBAABCAAGBQJYBVUVAAoJEFAslq9JXcLZfIkQAJqfAprPlgwMVMU0V2toQ8jp +DCRcfvIus9pFpEOOpVEdOiesT4BxWPhTONWnXqfx+xVu4uXtRaUEhRZsdIcHZdC1 +mLjd6eTbrPBh56/5DGEXI8elSEa67OHICaE4bhYqSGKFoJnETBwsI3WrLV6xbSwh +eKI1OLt1bao+hpaztfVMi3MU2UVfJBgCjdmvlol+rNHBJ0UJuTY/v+cDA59D3KoD +uw5iQrjyAMNrKVlJBMWWkO2nfSH786gf7bLFHzH989n2B41mA74TjqjaqdHeJYLL ++iq/bl8VkyTK6Cr2GObpsxG5+RKCTYt5slnwhi5NGZT2J96iR2ahVkLkRgSfKwqs +bEJqyIXqKPAVJzP3hPv6ntg9eMjUU6svjvlU8LmlBE0xdDrd6WKO9UQ2Zi4rE3Q/ +yn1M3gSMMVdfHEwTvaeoVYUJ51iFKJaj8Ug0EMSyBYX+9T2QKQGuU5EXOoBhR9XY +xKoMUBwcS18wHSDyTLaN7+BaZDr06VHaZoewKtyFvoiRCKkI0bgWeOq2oW67wipA +HWHLXo/GZlOgB33XW+ZFiDhcXGtlb6xVs48Gt4TuXYDdGcNQu4aaF2SOvxzoHv0G +kF0DpQQd2o/nJS6zFAYdcg0v7GeVsqXDmlW9vfSArfj50frfDVSNcB6e4aXBLicX +m2OtTsrvB7gjJ9yKJJag +=UFjj +-----END PGP SIGNATURE----- ADDED client/1.0/neutral/pkgr_install.eagle Index: client/1.0/neutral/pkgr_install.eagle ================================================================== --- client/1.0/neutral/pkgr_install.eagle +++ client/1.0/neutral/pkgr_install.eagle @@ -0,0 +1,206 @@ +############################################################################### +# +# pkgr_install.eagle -- +# +# Extensible Adaptable Generalized Logic Engine (Eagle) +# Package Repository Client (Package Installer) +# +# Copyright (c) 2007-2012 by Joe Mistachkin. All rights reserved. +# +# See the file "license.terms" for information on usage and redistribution of +# this file, and for a DISCLAIMER OF ALL WARRANTIES. +# +# RCS: @(#) $Id: $ +# +############################################################################### + +# +# NOTE: Use our own namespace here because even though we do not directly +# support namespaces ourselves, we do not want to pollute the global +# namespace if this script actually ends up being evaluated in Tcl. +# +namespace eval ::PackageInstaller { + # + # NOTE: This procedure is used to report errors that prevent this tool + # from running to completion (e.g. invalid command line arguments, + # etc). It may be used to report a specifically error. It will + # always emits the command line option and argument information. + # + proc usage { {error ""} } { + if {[string length $error] > 0} then {puts stdout $error} + + puts stdout "usage:\ + [file tail [info nameofexecutable]]\ + [file tail [info script]] \[version\] \[language\]" + + exit 1 + } + + # + # NOTE: Figure out the fully qualified path to the current script file. + # If necessary, add it to the auto-path for the interpreter. The + # necessary supporting packages (i.e. the Package Repository and + # Package Downloader packages) are assumed to exist in the same + # directory as the current script file. + # + variable pkgr_path; # DEFAULT: + + if {![info exists pkgr_path]} then { + set pkgr_path [file normalize [file dirname [info script]]] + + if {![info exists ::auto_path] || \ + [lsearch -exact $::auto_path $pkgr_path] == -1} then { + lappend ::auto_path $pkgr_path + } + } + + # + # NOTE: *TODO* Pre-create the namespace for the Package Repository Client + # package and then forcibly adjust various settings to the values + # necessary for this tool. In the future, this section may need to + # be tweaked to account for changes to the Package Repository Client + # package. + # + namespace eval ::PackageRepository { + variable autoHook true + variable autoLoadTcl false + variable autoRequireGaruda false + variable verboseUnknownResult true + variable verboseUriDownload true + } + + # + # NOTE: *TODO* Pre-create the namespace for the Package Downloader Client + # package and then forcibly adjust various settings to the values + # necessary for this tool. In the future, this section may need to + # be tweaked to account for changes to the Package Downloader Client + # package. Technically, the package being handled by this tool may + # not actually use the downloader; however, if it does, this should + # make sure the downloaded package files are persisted locally. + # + namespace eval ::PackageDownloader { + variable quiet false + variable viaInstall true + } + + # + # NOTE: Load the Package Repository Client package now. This will install + # the [package unknown] hook and prepare it for use. + # + package require Eagle.Package.Repository + + # + # NOTE: Verify that the number of command line arguments meets the basic + # requirements of this tool. + # + if {[info exists ::argv] && \ + [llength $::argv] >= 2 && [llength $::argv] <= 4} then { + # + # NOTE: Get the API key. This is always required. If this API key is + # not valid or cannot be found by the server, execution of this + # tool will fail. + # + set apiKey [lindex $::argv 0] + + # + # NOTE: Get the package name. This is always required. If this package + # name is invalid or cannot be found by the server, execution of + # this tool will fail. + # + set package [lindex $::argv 1] + + # + # NOTE: Grab the package version (or requirement?). This is optional. + # If this package version is specified, it must conform with TIP + # #268 when the target language is native Tcl. For Eagle, only + # the dotted decimal version syntax, with between 2 to 4 numbers, + # is supported. + # + if {[llength $::argv] >= 3} then { + set version [lindex $::argv 2] + + if {[isEagle] && ![string is version -strict $version]} then { + set pattern {^\d+\.\d+\.\d+\.\d+$} + + error [appendArgs \ + "version must match regular expression: " $pattern] + } + } else { + set version "" + } + + # + # NOTE: Grab the target language. This is optional. Without this, it + # is assumed that the target language is the one evaluating the + # current script file. The only supported target languages are + # native Tcl ("Tcl") and Eagle ("Eagle"), both case-sensitive. + # If the target language differs from the current language, this + # tool will attempt to gain access to the target language and a + # script error will be raised if that attempt fails. + # + if {[llength $::argv] >= 4} then { + set language [lindex $::argv 3] + } else { + set language "" + } + + # + # NOTE: If the target language was specified, attempt to gain access to + # it, if necessary. If the current language matches the target + # language, nothing is done. + # + if {[string length $language] > 0} then { + switch -exact -- $language { + Eagle { + if {![isEagle]} then { + ::PackageRepository::makeEagleReady + } + } + Tcl { + if {[isEagle]} then { + ::PackageRepository::makeTclReady + } + } + default { + error "unsupported language: must be Tcl or Eagle" + } + } + } + + # + # NOTE: If a non-empty API key was specified on the command line then + # add it to the global list now. + # + if {[string length $apiKey] > 0} then { + lappend ::pkgr_api_keys $apiKey + } + + # + # NOTE: For Eagle, make sure that the [package unknown] handler will be + # used for the current interpreter. + # + if {[isEagle]} then { + object invoke -flags +NonPublic Interpreter.GetActive InterpreterFlags \ + [appendArgs [object invoke -flags +NonPublic Interpreter.GetActive \ + InterpreterFlags] " -NoPackageUnknown"] + } + + # + # NOTE: Attempt to require the target package now. If this succeeds + # -AND- the Package Downloader Client was used, the package will + # be persisted locally; otherwise, the [package ifneeded] script + # may still be evaluated; however, the effects may not actually + # cause anything to persist. + # + if {[string length $version] > 0} then { + set result [package require $package $version] + } else { + set result [package require $package] + } + + puts stdout [appendArgs "package require result: " $result] + } else { + usage + } +} + ADDED client/1.0/neutral/pkgr_install.eagle.asc Index: client/1.0/neutral/pkgr_install.eagle.asc ================================================================== --- client/1.0/neutral/pkgr_install.eagle.asc +++ client/1.0/neutral/pkgr_install.eagle.asc @@ -0,0 +1,18 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2 +Comment: Eagle Package Repository + +iQIcBAABCAAGBQJX1JI+AAoJEFAslq9JXcLZfiQQAMjinGkIW+7Cj4cbXztobxW/ +VNs3jN3vuI/c7F37s2NHa1B9JhnoSz4oDT9goEkpouzSpiEbpwKSKmivEpKjadIE +jTNgqt0KmNVEAv6FTGzomyPw319dZMSUZZj1btI8QpuV+5ntssRd/EzcgRsp/qOj +mzlZRPBIRUj5Jom6U495D3gelUBTZocN+zMCr2IKTDtyzOoxg4f3mMva6bjCmh6X +suC7wIiXqAfUhKA96o3QJ2yiJEAXAho2yi/lcoQYdNrKXsdWoEQvcXeqpkOMvVeV +yYxuG5JRX5z+/fZXKijFDffHKiuzPiM9ho+np2nJBgsaIl9t7a7+XGvMdAJbKCO8 +eW2dXJr/FkoElU3p/woBmy0uCEGS8Ku9GNuyXeQmvayo68pCcQJ4JaHrYEfqi5km +i83Pmn6t5z/rVLT95ZPq7AiL1J50yYJg0ofWR8w/oBHOpwoNiPtZzTdpZwoNWmoj +crfd7CDbWTzhf8nGyE6YGtFdtqF1nUXYW+FACTPv3DlI51bgygFvGMX+u2w7ueuV +NfrV9GTgUswkZEMBzl/rQwrDyz09wLkXIw7eze8Zydc35zekwQ2EljjArMH+V2I5 +fd1inJH5rXcMjxd2nhjAyHu8KDx8uWqRwrp7i+iG2ZOHm9ICmrqm60Q0l5z6vrbP +7BD2bn8+QfF/kvn+JuoU +=LBzM +-----END PGP SIGNATURE----- ADDED client/1.0/neutral/pkgr_install.eagle.harpy Index: client/1.0/neutral/pkgr_install.eagle.harpy ================================================================== --- client/1.0/neutral/pkgr_install.eagle.harpy +++ client/1.0/neutral/pkgr_install.eagle.harpy @@ -0,0 +1,68 @@ + + + + None + Mistachkin Systems + 1a70ab30-3266-4e44-8b1e-f176343462bf + SHA512 + Script + 2016-09-10T22:53:48.6018672Z + -1.00:00:00 + 0x9559f6017247e3e2 + + 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 + + ADDED client/1.0/neutral/pkgr_install.eagle.harpy.asc Index: client/1.0/neutral/pkgr_install.eagle.harpy.asc ================================================================== --- client/1.0/neutral/pkgr_install.eagle.harpy.asc +++ client/1.0/neutral/pkgr_install.eagle.harpy.asc @@ -0,0 +1,18 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2 +Comment: Eagle Package Repository + +iQIcBAABCAAGBQJX1JJAAAoJEFAslq9JXcLZp80P/R4hkhprINlRKSyQrfff/Rpw +mHGCzhRqPBox1zyosrjq4l+3bNLQiZLrPQlRMbcXB1RJBNrBTNjeaDsG9bG7DfSa +R99Iz2BVMj/1E1bwawO8C4XlaFYhlOduMKbEg6NysGEjH+nG6wJ5AdoHZ5hfYlJ6 +BD8joxs2CW16rkJEyXKMOfj2lSDm3DBnv/U5VpcdJYRuUxJ13IDpNeMRq44yYpnL +sd9+1QJV21I9CR7isd+PCL9Tc0LjcdkfuLEaAek7anzwcVJVfvNWNoE4VuWi4d63 +SfcrgFqg/+SHcgJcUZSy4ODNIu+nX7Ef3eVKHMFT73suo2jinYYAyTdSmUbX1/QZ +CABIbAsOX7YRvT6qCi2tcG5y2wFm9xsTPg0sgsm2BDHvYaZwyVk95qcotfyGqcRB +v06SjbSLqgOdsM6bqE4gJKcfuwtBJf/iEeQUYFZ2lIH2IKLVjtGJJSVS1xnED4i6 +tRp0nWK87lzAHP0bef3ZmRWw4GAfVZYvw8iYs2giWoGxSyM22zUHAP3tz4Sz23lq +wIq171291MF2S3hYs0KCpFzUivMtmA2fVK0bhJHt29cra7v8L+CnGq+qW9Pp6R9h +/bvic2MifHo0DhdzOMHxvjqAnWzryC8nE31YJfEjRGc3RVnv16htxbV+lF6LgR5u +0oXbqCvBS4+E2Eqc4sSK +=Pn6m +-----END PGP SIGNATURE----- DELETED client/1.0/pkgIndex.eagle Index: client/1.0/pkgIndex.eagle ================================================================== --- client/1.0/pkgIndex.eagle +++ client/1.0/pkgIndex.eagle @@ -1,24 +0,0 @@ -############################################################################### -# -# pkgIndex.eagle -- -# -# Extensible Adaptable Generalized Logic Engine (Eagle) -# Package Index File -# -# Copyright (c) 2007-2012 by Joe Mistachkin. All rights reserved. -# -# See the file "license.terms" for information on usage and redistribution of -# this file, and for a DISCLAIMER OF ALL WARRANTIES. -# -# RCS: @(#) $Id: $ -# -############################################################################### - -if {![package vsatisfies [package provide Tcl] 8.4]} {return} -if {![package vsatisfies [package provide Eagle] 1.0]} {return} - -package ifneeded Eagle.Package.Repository 1.0 \ - [list source [file join $dir pkgr.eagle]] - -package ifneeded Eagle.Package.Downloader 1.0 \ - [list source [file join $dir pkgd.eagle]] DELETED client/1.0/pkgIndex.eagle.asc Index: client/1.0/pkgIndex.eagle.asc ================================================================== --- client/1.0/pkgIndex.eagle.asc +++ client/1.0/pkgIndex.eagle.asc @@ -1,18 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v2 -Comment: Eagle Package Repository - -iQIcBAABCAAGBQJXt2XQAAoJEFAslq9JXcLZ32EQAMPPN6pbNpqtm3OPnEtle0i2 -xXP/0oX1VmdHLpLMDO+DwvlIw4eLB6vDZs2Zmje3t+WxcJPlH2QWgjI4UDmmWS7h -HOt4/EUftPgjKWKUYPNpCj0S1vpVnLv19GWiDp++uYAA+YrdxTu+szeeI/rVaS3k -8dmVdAB7vO+EexhTywB883be5OWNBg1Jr+X7r/362CmXcL0Tdq31VDEP+q6JYTvW -PLM5kf4YMvFREtINhG2eg1s8BZts5Vz4b1NzVmMF9yyngu1pVQ+jkPAgM2A1OM6x -YQTMDTGZlanDDC+l131ts2GE4Lx96PwJBqbPii8Jhbkl+BqBZudDZ+mKhNhehBk5 -nlOJAsKNUNdV+9Zj94AsnqXjNymvocx2n1jI0xJl1mipqJ5S1Awh9s8WyYeXINp0 -WPxyQcamlLOnRz12tic3ht/07kwXjmZXNmy6wfVWX0FyljBhSiOmSxw8z77nLmy+ -hwHB9534Wlg4pEP8x+7N4NP0vu+cyfX9p1DHvNjklpcQLlHxGWAeu8vl87w+uamR -XcJpOnTxLshoVKI6CQunn0/OXAWDk3gi4MuU9+ZtytNfOMErNl85kuFtJLTzP5+H -2p8yGAliXQKET6+1a35u6xiPmjpfa3MABaQH5ooRMPm8Ii9t5pe3Ay3ylq4yB+Zn -IF7GNZh4xmipcTCy/skB -=suyk ------END PGP SIGNATURE----- DELETED client/1.0/pkgIndex.eagle.harpy Index: client/1.0/pkgIndex.eagle.harpy ================================================================== --- client/1.0/pkgIndex.eagle.harpy +++ client/1.0/pkgIndex.eagle.harpy @@ -1,68 +0,0 @@ - - - - None - Mistachkin Systems - e1a22fd8-1cd1-4652-b0c9-b340408f1966 - SHA512 - Script - 2016-08-23T04:07:23.6465312Z - -1.00:00:00 - 0x9559f6017247e3e2 - - VTCX5PM4xY1rUWOY1UK7m4fOPnDX7tlvznr4+HwiBsdA0X1oUdyIVTUWDR3NhmpB+C0kydA3ZmVJ - qaecSRvXCdGBWM7NgJ/kLiROwd3hnL/u7VgHwLmQGGrlyAqIksNchnTsm37BG29GEMpb1fOErbFX - F4kx6OIy1bRjMFOTp1mP2WD2XD+xq1YZayiSdLaI+a4ZoDJZm1TR3Xm/KeLKyUi+DVk4vr65FsvQ - /aMLCHmMzzoGlCnuHHrUx3Xskm6NPVEDB8aibjGgYaPz3o6KyrORW9bbFhZj1ndcRkD/rHGTJvy0 - TtTeqV2667jtlgbJ+gD4CXF8wXgnJkq0oU8MDO/YMuGQDa7NRUFbjBIzPcIl5cBNc3SEsEof4jBp - xixgKplXaIwDGs6g0Nsvteo8b+4WoFiqm0ey9eTuIYGcd6FqISZ+L7fisxdQ47lBf/gbKze3w6p/ - w0T/QP4dWeIbiB4oKcjQt5tggyV8ubmocgY53xLY0c+tkGPDyMxSPX4FdJxsmymRlKiwfkpMughi - 0iQaCNHUx77tuF/Zn8pr1WjSa1xvsQxcuMt3rtAucPRKcgLn+WjOLZQyTTtr4I74LLIIadfYWcWe - +cZwVumTe53eserwfRNfNfk3q83k+a1K1DHmWH6S+/sO1ZsNayEuH7ISycv9sYaIUFDRq/VYiUVT - ++Yh9GVdBoOODPUA5uxGojZcd7/MLXHIoLuF46SsrecPDxSc0eHkXK9R4boSqv0qkZHIMRTheZOm - 31JxcFmm/Lf6P98BDMQv/MC3Kyspx5Qkh6ijt8GjCUQRyQ1cSJsTKF0bYGJYEEzggTSvKdObegeN - ICaKgsOcJ5wOh4dwYCiYVpv8GJuZQXsTrmpRMafHk2H9i1RwRElKpqWgF3agEre/S7iulI9pG1g0 - jX36G+X9Lf89tTsadyEjYUj995WOPK4EUmRbrsvnxu/nZmLZz5ruQSR53UHRDdfAhIR3ZLQmccZ2 - SKsZk+9xu93ebEBrD0Y/5wIoOyDxgByf91Eg1p7MlVfnpC2evBl3F6SJh3UVTMhLDwzYC+FnkPew - Grt+6i5ie4+QrcJE8rd1w7GzNy7ePtQ9RowiCRLs69+AkFInFqHNp0KIoDGy/vzBd7Syz/RcIX7i - Q9uIaHjx3gK+BH/enn2aKT8kkuywMUXVkjFQFnCLePj8lrJq6NqADRoQS7SbtNUIel3rStgGE2Vk - lUigt3rMIxCfxKnpeOxjnMU8TUdgYwEmdKAbEoxtmxJy2pE5DvZ1vy37uNekKF1++Tz4LmyJUJcT - ll7AemtwdFwzp/Yz8O2mvQLyhdY9HPU1Ydzzrf4KEkjhb6W+bO63JgzcrjmnarhzWl+FVYIx4JF8 - GKolCDMGGtqmui0K+82WnHfCL09BCOIFTf4VyklScASLJusaymU6jb2P3G5VvMO69zHKXnc6F57e - PJCnYOheIQ0BvZRdpb5Izk8cCRLMyvGB6QS6hO09fc+f2YRgcZ7Pw1W342oZ1ZYJRM7NsVgKMLBi - woBHh1jDj66HnVGWgPeoIeQpkk8bt+l6e5WA05dwRijurRPj8EGN5IIbfE4OJAcxUShtB92LWQLZ - psfXAnROya7fT9dIBFlE9hmDUdWeP4EMKrHvqJEi0YXOvkdHNmfswhE41nrvmM1VN1c9DHmy7CJw - 0kVNIvNp2tNVE+xXq4PLR0SBIJcMXeJU8j3Q/eVAsiB9yStY+q1nT9WjDq83UbPIgl6Guv/DUpxP - 5dL+CfbrPqDoDSY7/uQ7TSGRQwEFbl6rcvYmn4AFGJPY+solTuZQoQMoKQuiAq3ll9Qlpe3aqYaw - H27wBsP6yq179xwFMhrR0gbqZvs2jjoDH0A95LakAQOoi95XL2qu0WMVr0hcko9AnJoWIVDxDTBy - GwIozcv5wDIOi9N1NaXlGu3fDkYp9aJU5kfVqv1WE6cHZ8uyyo+SUNFggWYwiJ5EOhmnRDp5gz5Y - PGG0qpSPHvdKg/xUJE0bTU2AJTOFf8W3j/g64WKwM0+YCs5hk5oBb9mp1m/B41GLRtzoXG8bpNZT - Np+qHMbxi2dZsgw4dxxwYOv1Keqp4If69X45ZKni1+a3B9OrjBHIOjCpgM8lR/zjymOSdE2tVj1Y - UxpU8OW0OUqIoiKLEVzCtWFvPq0XI96MfI4z2ZAa8uzBuzcFe/8Jv3nivEew24Ti+lpa70NsRnbN - 7vGqGxBbwbJFUhrssBvOeiLNyYSfCIDPDXdN/j/D00gQf0A0urmAiqumqh8O3duzs1L0xAIDUSWE - tevvdj5pdqZ6UN2OTnVEN9dFhqndVdqd1IkRi0tMHBaML/LveCVxOTghlEigCG80KROFZABSqAwK - O1AGnal3yu1NC1QiA8xQUlVliC1dT6OijGJ1V0nOrPB0ekh6j5ej6p/nnm030jPgsEVZAMcH1i4N - ZVvkmZVK8ZbxkJmg/PwCRqY59tur2WLcTT0HzwwAbBoOFgqw9E/xxe3PNBfDMPBzvqgHxTH5E2Sc - BJjCnqMDKjYZzHM6drYeMUupQ6GRs2WSRlE1PN5S4BbpPg29m8sjDxiJltBeqtaf6zv1p2oqqtog - GymlORpPfBHswWxWlLhAGML0ivIQGNoTdAJMCObdWaOiil9CfWlOOvcWRtcSflacIghgsV7NKG5a - QeYAMHjiuG4GB06miZL+tRIAg9NAW593+2eZwTweYl+En022nCDdI34pAhzO7jGevfaZsQg= - - DELETED client/1.0/pkgIndex.eagle.harpy.asc Index: client/1.0/pkgIndex.eagle.harpy.asc ================================================================== --- client/1.0/pkgIndex.eagle.harpy.asc +++ client/1.0/pkgIndex.eagle.harpy.asc @@ -1,18 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v2 -Comment: Eagle Package Repository - -iQIcBAABCAAGBQJX3ddfAAoJEFAslq9JXcLZZ64P/1KwUGRntTrhpe1JY7EggZOc -p/CYp3Q/FrWSLA+3Kk3AmQfj0E0JEIHX6rjNNcTX+lK538OxS1wTXL23qx5M7KRD -HesRavZoypr2WrFUHf1zCFBrllkYP/zyeXj6hpz7J+QeTaGAsbiBVRCLVOc82wIf -l+ZYaKevKIoMiivaxn2WmrrdlmP3dsgGdQcZohGwActvON6HGIUE0EeAxpNN0Mw5 -bwPeNl2ldRJ6M4slswYqV3QuAwV68oR6rPGA//bSTfzKM/+RTpX0XscnYcuV48GN -A7Gjzz8YIl4ohAYaSUmIwfS0YhHHWz+GPdchPE9itG0qeltDO3zBqu2ldU6pIRXR -dZizDy+bWh+6fzNV9Pd74aIDiVDHSb3f4PdNrxLj4g2ZrHhJ8fTs4zPP7yHBWCA0 -6G4Rbjz/+P20tcO344LexvFc/qYwx59S8BiXOkbnot9Qu8sD+L192ZoEzKCxE6R3 -fUt8FdNoOBuM2rO4PwqmZr6siYPXA6UTCe04c7uKglUpFEtYHedAvPG0zeRZkHc8 -YhvIpA5CG1WL/Z5RLx2IMfMTGhVh4tKv6rg1HYmLiyHnUk/Yp/hzD9AfGztaig73 -26MZb98eBN9AhlvKfnL9XyQsGNiGPoll/9zK1il4B33Y+dfaqDwROtDbjCjqt3cS -SEJcWOFSMZzAMS6FYQtP -=qmAI ------END PGP SIGNATURE----- DELETED client/1.0/pkgIndex.tcl Index: client/1.0/pkgIndex.tcl ================================================================== --- client/1.0/pkgIndex.tcl +++ client/1.0/pkgIndex.tcl @@ -1,24 +0,0 @@ -############################################################################### -# -# pkgIndex.tcl -- -# -# Extensible Adaptable Generalized Logic Engine (Eagle) -# Package Index File -# -# Copyright (c) 2007-2012 by Joe Mistachkin. All rights reserved. -# -# See the file "license.terms" for information on usage and redistribution of -# this file, and for a DISCLAIMER OF ALL WARRANTIES. -# -# RCS: @(#) $Id: $ -# -############################################################################### - -if {![package vsatisfies [package provide Tcl] 8.4]} {return} -if {[string length [package provide Eagle]] > 0} then {return} - -package ifneeded Eagle.Package.Repository 1.0 \ - [list source [file join $dir pkgr.eagle]] - -package ifneeded Eagle.Package.Downloader 1.0 \ - [list source [file join $dir pkgd.eagle]] DELETED client/1.0/pkgIndex.tcl.asc Index: client/1.0/pkgIndex.tcl.asc ================================================================== --- client/1.0/pkgIndex.tcl.asc +++ client/1.0/pkgIndex.tcl.asc @@ -1,18 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v2 -Comment: Eagle Package Repository - -iQIcBAABCAAGBQJXt2XQAAoJEFAslq9JXcLZrdcP/joLk0SYgo+rOoLeqzvneJdS -3m4wOn6Dr6xzfT3d9Hmh/U5GeAabG6nGXroqHlF6RCXDlw2MuzxjwyEYn1ZxXQpT -++gzlxaBtJpo7D6j9CbWtghvDkFQyW+5ucruCFKH2rYr/U5akWiAHke4txFeXJMp -C6zFY0paMD39f0Si/prqwK07MdxtiUCM5wNNs2/hl0sbckV4Blit+BhShi1H74My -NPr4k0GmOSAo1QyYmBb6D0ciCkl6AmbCtj6KQuPXzkhPu0rh0eduxAjcImu70jSu -peQ692PVYUV3vtHd5UVyZFKZeWGWUs27n4oIq/WNv60AocaS09QRikVNvf7kyHDy -+zEXF+yjnFnSdpHplVyfwMQdLz9LCjlqUivYq35Ir6n/C9tMLfqiZChUhyHX9hmB -rnyokRFh45mcF8gJLKC/4D/PKDDjBKyjHdbKLQrJ4bH3y7FSUzOvb3iI8K4/Omyt -uS18QYYtlovub0Bkc26TCVqlsytuv9Zc3Y6P8YlrLV7+lxGQs3hhgK6X0xK4GU6h -5aNE964elyYapPC3ToVEqvZaQsDM9vs1avW8SxcCvudixnzAycslcysv8JVaZXnG -u6WPT/zxt65BF+gXOBm5qpeFEQIn34WZdTHqXMgmUslT+uJ7y3cRXIKWGkzkebHZ -1PissA/AN1MgUYPp69ZV -=BbsA ------END PGP SIGNATURE----- DELETED client/1.0/pkgd.eagle Index: client/1.0/pkgd.eagle ================================================================== --- client/1.0/pkgd.eagle +++ client/1.0/pkgd.eagle @@ -1,1196 +0,0 @@ -############################################################################### -# -# pkgd.eagle -- -# -# Extensible Adaptable Generalized Logic Engine (Eagle) -# Package Downloader Client -# -# Copyright (c) 2007-2012 by Joe Mistachkin. All rights reserved. -# -# See the file "license.terms" for information on usage and redistribution of -# this file, and for a DISCLAIMER OF ALL WARRANTIES. -# -# RCS: @(#) $Id: $ -# -############################################################################### - -# -# NOTE: Use our own namespace here because even though we do not directly -# support namespaces ourselves, we do not want to pollute the global -# namespace if this script actually ends up being evaluated in Tcl. -# -namespace eval ::PackageDownloader { - # - # NOTE: This procedure sets up the default values for all URN configuration - # parameters used by the package downloader client. If the force - # argument is non-zero, any existing values will be overwritten and - # set back to their default values. - # - proc setupDownloadUrnVars { force } { - # - # NOTE: The URN, relative to the base URI, where a login request may - # be sent. - # - variable loginUrn; # DEFAULT: pkgd_login - - if {$force || ![info exists loginUrn]} then { - set loginUrn pkgd_login - } - - # - # NOTE: The URN, relative to the base URI, where a single package file - # may be found. - # - variable downloadUrn; # DEFAULT: pkgd_file - - if {$force || ![info exists downloadUrn]} then { - set downloadUrn pkgd_file - } - - # - # NOTE: The URN, relative to the base URI, where a logout request may - # be sent. - # - variable logoutUrn; # DEFAULT: pkgd_logout - - if {$force || ![info exists logoutUrn]} then { - set logoutUrn pkgd_logout - } - } - - # - # NOTE: This procedure sets up the default values for all URI configuration - # parameters used by the package downloader client. If the force - # argument is non-zero, any existing values will be overwritten and - # set back to their default values. - # - proc setupDownloadUriVars { force } { - # - # NOTE: The base URI used to build the URIs for the package file server. - # - variable baseUri; # DEFAULT: https://urn.to/r - - if {$force || ![info exists baseUri]} then { - set baseUri https://urn.to/r - } - - # - # NOTE: The URI where a login request may be sent. This should return a - # payload containing the necessary HTTP(S) cookie information. - # - variable loginUri; # DEFAULT: ${baseUri}/${loginUrn}?... - - if {$force || ![info exists loginUri]} then { - set loginUri [appendArgs \ - {${baseUri}/${loginUrn}?} {[uriEscape name $userName]} & \ - {[uriEscape password $password]}] - } - - # - # NOTE: The URI where a single package file may be found. This file will - # belong to a specific version of one package. - # - variable downloadUri; # DEFAULT: ${baseUri}/${downloadUrn}?... - - if {$force || ![info exists downloadUri]} then { - set downloadUri [appendArgs \ - {${baseUri}/${downloadUrn}?download&ci=trunk&} \ - {[uriEscape filename $fileName]}] - } - - # - # NOTE: The URI where a logout request should be sent. This should - # return a payload indicating that the logout was successful. - # - variable logoutUri; # DEFAULT: ${baseUri}/${logoutUrn}?... - - if {$force || ![info exists logoutUri]} then { - set logoutUri [appendArgs \ - {${baseUri}/${logoutUrn}?} {[uriEscape authToken $authToken]}] - } - } - - # - # NOTE: This procedure sets up the default values for all configuration - # parameters used by the package downloader client. The script - # argument is the fully qualified path and file name for the script - # being evaluated. - # - proc setupDownloadVars { script } { - # - # NOTE: What is the fully qualified path to the directory containing the - # package downloader client? - # - variable clientDirectory - - if {![info exists clientDirectory]} then { - set clientDirectory [file dirname $script] - } - - # - # NOTE: This is the HTTP(S) login cookie to use when downloading files - # from the package file server. - # - variable loginCookie; # DEFAULT: NONE - - if {![info exists loginCookie]} then { - set loginCookie [list] - } - - # - # NOTE: Prevent progress messages from being displayed while downloading - # from the repository, etc? By default, this is enabled. - # - variable quiet; # DEFAULT: true - - if {![info exists quiet]} then { - set quiet true - } - - # - # NOTE: The user name for the public account on the package file server. - # If this is an empty string, there is no public account. - # - variable publicUserName; # DEFAULT: public - - if {![info exists publicUserName]} then { - set publicUserName public - } - - # - # NOTE: The password associated with the public account on the package - # file server. If this is an empty string, the public account is - # disabled. This is not considered to be a secret; however, it - # should not be shared with any person or organization that does - # not have access to the package downloader client. - # - variable publicPassword; # DEFAULT: X+NlF2obS5tQFKIsf/q345/naqVSGD67Cg - - if {![info exists publicPassword]} then { - set publicPassword X+NlF2obS5tQFKIsf/q345/naqVSGD67Cg - } - - # - # NOTE: The root directory where any persistent packages will be saved. - # - variable persistentRootDirectory; # DEFAULT: [getPersistentRootDirectory] - - if {![info exists persistentRootDirectory]} then { - set persistentRootDirectory [getPersistentRootDirectory] - } - - # - # NOTE: The root directory where any temporary packages will be written. - # - variable temporaryRootDirectory; # DEFAULT: [getFileTempDirectory PKGD_TEMP] - - if {![info exists temporaryRootDirectory]} then { - set temporaryRootDirectory \ - [::PackageRepository::getFileTempDirectory PKGD_TEMP] - } - - # - # NOTE: Is this package being run by the package installer tool? If so, - # all downloaded packages should be automatically persisted to the - # library path. - # - variable viaInstall; # DEFAULT: false - - if {![info exists viaInstall]} then { - set viaInstall false - } - } - - # - # NOTE: This procedure modifies the URN variables used by the package - # downloader client so that one or more alternative (private?) - # backend file servers may be used. The serverId argument must - # consist only of alphanumeric characters and it must begin with - # a letter. - # - # - proc useServerId { {serverId ""} } { - variable downloadUrn - variable loginUrn - variable logoutUrn - - if {[string length $serverId] > 0 && \ - ![regexp -nocase -- {^[A-Z][0-9A-Z]*$} $serverId]} then { - error "server Id must be alphanumeric and start with a letter" - } - - if {[string length $serverId] > 0} then { - # - # NOTE: Set the URN variables to values that should cause the - # specified server Id to be used (assume the server Id - # itself is valid and active). - # - set loginUrn [appendArgs pkgd_login_ $serverId] - set downloadUrn [appendArgs pkgd_file_ $serverId] - set logoutUrn [appendArgs pkgd_logout_ $serverId] - } else { - # - # NOTE: Forcibly reset URN variables to their default values. - # - setupDownloadUrnVars true - } - } - - # - # NOTE: This procedure escapes a single name/value pair for use in a URI - # query string. The name argument is the name of the parameter. - # The value argument is the value of the parameter. - # - proc uriEscape { name value } { - if {[isEagle]} then { - return [appendArgs \ - [uri escape uri $name] = [uri escape uri $value]] - } else { - package require http 2.0 - - return [::http::formatQuery $name $value] - } - } - - # - # NOTE: This procedure returns the root directory where any packages that - # are downloaded should be saved to permanent storage for subsequent - # use. There are no arguments. - # - proc getPersistentRootDirectory {} { - global env - - # - # NOTE: Allow the persistent root directory to be overridden via the - # environment. Typically, this customization will only be needed - # if multiple instances of Tcl need to share packages. - # - if {[info exists env(PKGD_ROOT)]} then { - return $env(PKGD_ROOT) - } - - # - # NOTE: Fallback to returning a directory parallel to the one containing - # the library directory. - # - return [file join [file dirname [info library]] pkgd] - } - - # - # NOTE: This procedure checks the configured persistent root directory for - # downloaded packages. If any checks fail, a script error is raised. - # There are no arguments. The return value is undefined. - # - proc verifyPersistentRootDirectory {} { - variable persistentRootDirectory - - if {![info exists persistentRootDirectory]} then { - error "persistent root directory not set" - } - - if {[string length $persistentRootDirectory] == 0} then { - error "persistent root directory is invalid" - } - - # - # NOTE: Either the persistent root directory must already exist -OR- we - # must be able to create it. - # - if {![file isdirectory $persistentRootDirectory] && \ - [catch {file mkdir $persistentRootDirectory}]} then { - error "persistent root directory does not exist and could not be created" - } - } - - # - # NOTE: This procedure returns the name of the package index file for the - # language specified by the language argument. An empty string will - # be returned if the language is unsupported or unrecognized. - # - proc getPackageIndexFileName { language } { - if {[string length $language] == 0 || $language eq "eagle"} then { - return pkgIndex.eagle - } elseif {$language eq "tcl"} then { - return pkgIndex.tcl - } else { - return "" - } - } - - # - # NOTE: This procedure, which is only used for native Tcl, generates a - # "master" package index file (i.e. "pkgIndex.tcl") suitable for - # use with native Tcl 8.4 (or higher). It will recursively scan - # for all other native Tcl package index files that are within the - # configured persistent root directory and [source] them, thereby - # causing all packages located within them to become available. - # Since Eagle (by default) already performs recursive searches for - # its package index files, this procedure is not needed for Eagle. - # The return value is undefined. - # - proc maybeCreateMasterTclPackageIndex {} { - variable persistentRootDirectory - - verifyPersistentRootDirectory - set persistentDirectory $persistentRootDirectory - - set fileName [file join $persistentDirectory pkgIndex.tcl] - if {[file exists $fileName]} then {return ""} - - writeFile $fileName [string trim [string map [list \r\n \n] { -############################################################################### -# -# pkgIndex.tcl -- -# -# Extensible Adaptable Generalized Logic Engine (Eagle) -# Generated Recursive Package Index File -- PLEASE DO NOT EDIT -# -# Copyright (c) 2007-2012 by Joe Mistachkin. All rights reserved. -# -# See the file "license.terms" for information on usage and redistribution of -# this file, and for a DISCLAIMER OF ALL WARRANTIES. -# -# RCS: @(#) $Id: $ -# -############################################################################### - -if {![package vsatisfies [package provide Tcl] 8.4]} {return} -if {[string length [package provide Eagle]] > 0} then {return} - -set pkgd(savedDir) $dir; set pkgd(dirs) [list $pkgd(savedDir)] - -for {set pkgd(i) 0} {$pkgd(i) < [llength $pkgd(dirs)]} {incr pkgd(i)} { - set pkgd(dir) [lindex $pkgd(dirs) $pkgd(i)] - - if {$pkgd(i) > 0} then { - set pkgd(file) [file join $pkgd(dir) pkgIndex.tcl] - - if {[file exists $pkgd(file)]} then { - set dir $pkgd(dir); source $pkgd(file) - } - } - - eval lappend pkgd(dirs) \ - [glob -nocomplain -types {d} [file join $pkgd(dir) *]] -} - -set dir $pkgd(savedDir); unset -nocomplain pkgd - }]] - - return "" - } - - # - # NOTE: This procedure returns non-zero if the specified file seems to be - # an OpenPGP signature file. The fileName argument is the name of - # the file to check, which may or may not exist. The nameOnly - # argument should be non-zero to ignore the contents of the file. - # - proc isOpenPgpSignatureFileName { fileName nameOnly } { - if {[string length $fileName] == 0} then { - return false - } - - set extension [file extension $fileName] - - if {$extension eq ".asc"} then { - if {!$nameOnly && [file exists $fileName]} then { - return [::PackageRepository::isOpenPgpSignature \ - [readFile $fileName]] - } else { - return true - } - } else { - return false - } - } - - # - # NOTE: This procedure returns non-zero if the specified file seems to be - # a Harpy script certificate file. The fileName argument is the name - # of the file to check, which may or may not exist. The nameOnly - # argument should be non-zero to ignore the contents of the file. - # - # - proc isHarpyCertificateFileName { fileName nameOnly } { - if {[string length $fileName] == 0} then { - return false - } - - set extension [file extension $fileName] - - if {$extension eq ".harpy"} then { - if {!$nameOnly && [file exists $fileName]} then { - return [::PackageRepository::isHarpyCertificate \ - [readFile $fileName]] - } else { - return true - } - } else { - return false - } - } - - # - # NOTE: This procedure returns the auto-path for the language specified by - # the language argument. An empty list is returned if the auto-path - # does not exist in the target language. This procedure may raise - # script errors. - # - proc getAutoPath { language } { - if {[string length $language] == 0 || $language eq "eagle"} then { - if {[isEagle]} then { - if {![info exists ::auto_path]} then { - return [list] - } - - return $::auto_path - } else { - ::PackageRepository::eagleMustBeReady - - eagle { - if {![info exists ::auto_path]} then { - return [list] - } - - return $::auto_path - } - } - } elseif {$language eq "tcl"} then { - if {[isEagle]} then { - tcl eval [tcl master] { - if {![info exists ::auto_path]} then { - return [list] - } - - return $::auto_path - } - } else { - if {![info exists ::auto_path]} then { - return [list] - } - - return $::auto_path - } - } else { - error "unsupported language, no idea how to query auto-path" - } - } - - # - # NOTE: This procedure adds a directory to the auto-path of the specified - # language (i.e. native Tcl or Eagle). The directory will not be - # 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. - # - if {[string length $language] == 0 || $language eq "eagle"} then { - if {[isEagle]} then { - if {![info exists ::auto_path] || \ - [lsearch -exact $::auto_path $directory] == -1} then { - lappend ::auto_path $directory - } - } else { - ::PackageRepository::eagleMustBeReady - - eagle [string map [list %directory% $directory] { - if {![info exists ::auto_path] || \ - [lsearch -exact $::auto_path {%directory%}] == -1} then { - lappend ::auto_path {%directory%} - } - }] - } - } elseif {$language eq "tcl"} then { - if {[isEagle]} then { - tcl eval [tcl master] [string map [list %directory% $directory] { - if {![info exists ::auto_path] || \ - [lsearch -exact $::auto_path {%directory%}] == -1} then { - lappend ::auto_path {%directory%} - } - }] - } else { - if {![info exists ::auto_path] || \ - [lsearch -exact $::auto_path $directory] == -1} then { - lappend ::auto_path $directory - } - } - } else { - error "unsupported language, no idea how to modify auto-path" - } - } - - # - # NOTE: This procedure adds a directory to the auto-path of the specified - # language (i.e. native Tcl or Eagle). The directory will not be - # 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. The directory will not be added if it falls under - # a directory already in the auto-path. - # - proc maybeAddToAutoPath { language directory } { - # - # NOTE: Verify that the directory to be added is valid and exists. If - # not, do nothing. - # - if {[string length $directory] == 0 || \ - ![file isdirectory $directory]} then { - return false - } - - # - # NOTE: Normalize the specified directory. This is necessary so that - # we can compare apples-to-apples within the auto-path. - # - set directory [file normalize $directory] - set directoryLength [string length $directory] - - # - # NOTE: Query the auto-path for the target language. - # - set autoPath [getAutoPath $language] - - # - # NOTE: Check each directory in the auto-path to see if the specified - # directory is already underneath it. - # - foreach autoDirectory $autoPath { - # - # NOTE: Normalize the auto-path directory. This is necessary so - # that we can compare apples-to-apples with the specified - # directory. - # - set autoDirectory [file normalize $autoDirectory] - set autoDirectoryLength [string length $autoDirectory] - - # - # NOTE: Prefix match is impossible if the length of the specified - # directory is less than the length of this directory in the - # auto-path. - # - if {$directoryLength < $autoDirectoryLength} then { - continue - } - - # - # NOTE: If the initial portion of the specified directory is the - # same as this directory in the auto-path, it must reside - # underneath it. In that case, there is no need to modify - # the auto-path, bail out now. - # - set last [expr {$autoDirectoryLength - 1}] - - if {[string range $directory 0 $last] eq $autoDirectory} then { - return false - } - } - - # - # NOTE: At this point, it is pretty safe to assume that the specified - # directory is not in the auto-path, nor underneath a directory - # within the auto-path. - # - addToAutoPath $language $directory - - return true - } - - # - # NOTE: This procedure verifies the combination of language and version - # specified by the caller. The language argument must be one of the - # literal strings "eagle", "tcl", or "client". The version argument - # must be one of the literal strings "8.4", "8.5", or "8.6" when the - # language is "tcl" -OR- the literal string "1.0" when the language - # is either "eagle" or "client". The varName argument is the name - # of a scalar variable in the context of the immediate caller that - # will receive a boolean value indicating if the specified language - # is actually a reference to the package downloader client itself. - # - proc verifyLanguageAndVersion { language version varName } { - if {[string length $varName] > 0} then { - upvar 1 $varName isClient - } - - set isClient false - - if {[string length $language] == 0 || $language eq "eagle"} then { - if {$version ne "1.0"} then { - error "unsupported Eagle version" - } - } elseif {$language eq "tcl"} then { - if {$version ne "8.4" && $version ne "8.5" && $version ne "8.6"} then { - error "unsupported Tcl version" - } - } elseif {$language eq "client"} then { - if {$version ne "1.0"} then { - error "unsupported client version" - } - - set isClient true - } else { - error "unsupported language" - } - } - - # - # NOTE: This procedure issues a request to an HTTP(S) server. It returns - # the raw response data verbatim. It may raise a script error. It - # will always use the currently configured HTTP(S) login cookie, if - # any; therefore, it should really only be used for requests to the - # package file server. The uri argument is the fully qualified URI - # to request. - # - proc getPackageFile { uri } { - variable loginCookie - variable quiet - - if {[isEagle]} then { - if {![object invoke Eagle._Tests.Default \ - TestHasScriptNewWebClientCallback ""]} then { - set error null - - set code [object invoke Eagle._Tests.Default \ - TestSetScriptNewWebClientCallback "" true true error] - - if {$code ne "Ok"} then { - error [getStringFromObjectHandle $error] - } - } - - if {[info exists loginCookie] && [llength $loginCookie] == 2} then { - set script [object create String { - if {[methodName ToString] eq "GetWebRequest"} then { - webRequest Headers.Add Cookie [join $loginCookie =] - } - }] - - return [uri download -inline -webclientdata $script -- $uri] - } else { - return [uri download -inline -- $uri] - } - } else { - set options [list -binary true] - - if {[info exists loginCookie] && [llength $loginCookie] == 2} then { - lappend options -headers [list Cookie [join $loginCookie =]] - } - - return [eval ::PackageRepository::getFileViaHttp \ - [list $uri] [list 20] [list stdout] [list $quiet] $options] - } - } - - # - # NOTE: This procedure returns the prefix for fully qualified variable - # names that MAY be present in the global namespace. There are - # no arguments. - # - proc getDownloadVarNamePrefix {} { - return ::pkgd_; # TODO: Make non-global? - } - - # - # NOTE: This procedure resets the currently configured login cookie, if - # any, and then attempts to login using the configured package - # repository server API key -OR- using the public access account. - # Upon success, it will set the login cookie to the one from the - # raw response data. Upon failure, a script error will be raised. - # There are no arguments. - # - # - proc resetCookieAndLoginSimple {} { - variable publicPassword - variable publicUserName - - set apiKey [lindex [::PackageRepository::getApiKeys \ - [getDownloadVarNamePrefix] true] 0] - - if {[string length $apiKey] > 0} then { - return [resetCookieAndLogin $apiKey $apiKey] - } - - if {[string length $publicUserName] > 0 && \ - [string length $publicPassword] > 0} then { - return [resetCookieAndLogin $publicUserName $publicPassword] - } - - error "missing API keys and no public login credentials configured" - } - - # - # NOTE: This procedure resets the currently configured login cookie, if - # any, and then attempts to login using the specified user name and - # password. Upon success, it will set the login cookie to the one - # from the raw response data. Upon failure, a script error will be - # raised. The userName argument must be the name of a package file - # server user with at least Fossil Check-Out (o) permissions on the - # package file server. The password argument must be the plaintext - # password that is associated with the specified user name. - # - # - proc resetCookieAndLogin { userName password } { - variable baseUri - variable loginCookie - variable loginUri - variable loginUrn - - # - # NOTE: Build the full URI for the login request. - # - set uri [subst $loginUri] - - # - # NOTE: Reset the old login cookie, if any. Then, issue a new login - # request, capturing the raw response data. - # - set loginCookie [list]; set data [getPackageFile $uri] - - # - # NOTE: Attempt to extract the necessary values from the raw response - # data. - # - set pattern(1) {"authToken":"(.*?)"}; # TODO: *HACK* Keep updated. - - if {![regexp -- $pattern(1) $data dummy authToken]} then { - error "login response missing \"authToken\"" - } - - set pattern(2) {"loginCookieName":"(.*?)"}; # TODO: *HACK* Keep updated. - - if {![regexp -- $pattern(2) $data dummy loginCookieName]} then { - error "login response missing \"loginCookieName\"" - } - - # - # NOTE: Set the login cookie to the one freshly extracted from the raw - # response data. - # - set loginCookie [list $loginCookieName $authToken] - - # - # NOTE: Always return an empty string (i.e. and not any response data). - # - return "" - } - - # - # NOTE: This procedure attempts to logout using the currently configured - # login cookie, if any, and then resets the login cookie. There - # are no arguments. This procedure may raise a script error. - # - # - proc logoutAndResetCookie {} { - variable baseUri - variable loginCookie - variable logoutUri - variable logoutUrn - - # - # NOTE: Attempt to verify that we are currently logged in. - # - if {![info exists loginCookie] || [llength $loginCookie] != 2} then { - error "missing or invalid login cookie" - } - - # - # NOTE: Build the full URI for the logout request. - # - set authToken [lindex $loginCookie 1] - set uri [subst $logoutUri] - - # - # NOTE: Reset the old login cookie, if any. Then, issue a new login - # request, capturing the raw response data. - # - set data [getPackageFile $uri] - - # - # NOTE: Attempt to extract the necessary values from the raw response - # data. - # - set pattern(1) {"name":"nobody"}; # TODO: *HACK* Keep updated. - - if {![regexp -- $pattern(1) $data dummy]} then { - error "logout response missing \"name\"" - } - - # - # NOTE: Reset the login cookie. - # - set loginCookie [list] - - # - # NOTE: Always return an empty string (i.e. and not any response data). - # - return "" - } - - # - # NOTE: This procedure checks if there is a higher version available of the - # specified package on the package file server. The language argument - # must be one of the literal strings "eagle", "tcl", or "client". The - # version argument must be one of the literal strings "8.4", "8.5", or - # "8.6" when the language is "tcl" -OR- the literal string "1.0" when - # the language is either "eagle" or "client". The packageName argument - # is a directory name relative to the language and version-specific - # directory on the package file server and may be an empty string. The - # usePgp argument should be non-zero when an OpenPGP signature file - # needs to be downloaded and verified for the downloaded file. - # - # - proc checkForHigherVersion { language version packageName usePgp } { - variable clientDirectory - variable persistentRootDirectory - variable temporaryRootDirectory - - verifyLanguageAndVersion $language $version isClient - - set temporaryDirectory [file join \ - $temporaryRootDirectory [appendArgs \ - pkgd_ver_ [::PackageRepository::getUniqueSuffix]]] - - if {$isClient} then { - set persistentDirectory $clientDirectory - } else { - verifyPersistentRootDirectory - set persistentDirectory $persistentRootDirectory - } - - set fileName [file join $packageName VERSION] - set downloadFileName [file join $temporaryDirectory $fileName] - - file mkdir [file dirname $downloadFileName] - downloadOneFile $language $version $fileName $downloadFileName $usePgp - - if {$usePgp} then { - downloadOneFile $language $version [appendArgs $fileName .asc] \ - [appendArgs $downloadFileName .asc] $usePgp - } - - set localFileName [file join $persistentDirectory $fileName] - - set compare [package vcompare \ - [string trim [readFile $downloadFileName]] \ - [string trim [readFile $localFileName]]] - - if {[isEagle]} then { - file delete -recursive -- $temporaryDirectory - } else { - file delete -force -- $temporaryDirectory - } - - return [expr {$compare > 0}] - } - - # - # NOTE: This procedure downloads a single file from the package file server, - # writing its contents to the specified local file name. It can also - # verify the OpenPGP signatures. When an OpenPGP signature file is - # downloaded, this procedure assumes the corresponding data file was - # already downloaded (i.e. since OpenPGP needs both to perform the - # signature checks). The language argument must be one of the - # literal strings "eagle", "tcl", or "client". The version argument - # must be one of the literal strings "8.4", "8.5", or "8.6" when the - # language is "tcl" -OR- the literal string "1.0" when the language - # is either "eagle" or "client". The fileName argument is a file - # name relative to the language and version-specific directory on the - # package file server. The localFileName argument is the file name - # where the downloaded file should be written. The usePgp argument - # should be non-zero when an OpenPGP signature file needs to be - # downloaded and verified for the downloaded file. - # - proc downloadOneFile { language version fileName localFileName usePgp } { - variable baseUri - variable downloadUri - variable downloadUrn - - # - # NOTE: First, build the full relative file name to download from - # the remote package repository. - # - set fileName [file join $language $version $fileName] - set uri [subst $downloadUri] - - # - # NOTE: Then, in one step, download the file from the package file - # server and write it to the specified local file. - # - writeFile $localFileName [getPackageFile $uri] - - # - # NOTE: Is use of OpenPGP for signature verification enabled? Also, - # did we just download an OpenPGP signature file? - # - if {$usePgp && [isOpenPgpSignatureFileName $localFileName true]} then { - # - # NOTE: Attempt to verify the OpenPGP signature. If this fails, - # an error is raised. - # - if {![::PackageRepository::verifyOpenPgpSignature $localFileName]} then { - error [appendArgs \ - "bad OpenPGP signature \"" $localFileName \"] - } - } - } - - # - # NOTE: This procedure attempts to download a list of files, optionally - # persistening them for subsequent uses by the target language. - # The language argument must be one of the literal strings "eagle", - # "tcl", or "client". The version argument must be one of the - # literal strings "8.4", "8.5", or "8.6" when the language is "tcl" - # -OR- the literal string "1.0" when the language is either "eagle" - # or "client". The fileNames argument must be a well-formed list - # of file names to download, each one relative to the language and - # version-specific directory on the package file server. The - # options argument must be a dictionary of name/value pairs. The - # -persistent option should be non-zero if the downloaded files - # should be saved to permanent storage for subsequent use. The - # -usePgp option should be non-zero when an OpenPGP signature file - # needs to be downloaded and verified for each downloaded file. The - # -useAutoPath option should be non-zero to modify the auto-path to - # include the temporary or persistent directories containing the - # downloaded files. The -allowUpdate option should be non-zero to - # allow existing package files to be overwritten. - # - # - proc downloadFiles { language version fileNames options } { - variable clientDirectory - variable persistentRootDirectory - variable temporaryRootDirectory - variable viaInstall - - verifyLanguageAndVersion $language $version isClient - - set temporaryDirectory [file join \ - $temporaryRootDirectory [appendArgs \ - pkgd_lib_ [::PackageRepository::getUniqueSuffix]]] - - if {$isClient} then { - set persistentDirectory $clientDirectory - } else { - verifyPersistentRootDirectory - set persistentDirectory $persistentRootDirectory - } - - set persistent [string is true -strict \ - [getDictionaryValue $options -persistent]] - - set usePgp [string is true -strict \ - [getDictionaryValue $options -usePgp]] - - set useAutoPath [string is true -strict \ - [getDictionaryValue $options -useAutoPath]] - - set allowUpdate [string is true -strict \ - [getDictionaryValue $options -allowUpdate]] - - set downloadedFileNames [list] - - foreach fileName $fileNames { - if {[string length $fileName] == 0 || \ - [file pathtype $fileName] ne "relative"} then { - error [appendArgs \ - "bad file name \"" $fileName "\", not relative"] - } - - set directoryParts [file split [file dirname $fileName]] - - if {[llength $directoryParts] == 0} then { - error [appendArgs \ - "bad file name \"" $fileName "\", no directory parts"] - } - - set directory(temporary) [file normalize [eval \ - file join [list $temporaryDirectory] $directoryParts]] - - set directory(persistent) [file normalize [eval \ - file join [list $persistentDirectory] $directoryParts]] - - set fileNameOnly [file tail $fileName] - - set downloadFileName [file normalize [file join \ - $directory(temporary) $fileNameOnly]] - - if {[file exists $downloadFileName]} then { - error [appendArgs \ - "temporary file name \"" $downloadFileName \ - "\" already exists"] - } - - file mkdir [file dirname $downloadFileName] - downloadOneFile $language $version $fileName $downloadFileName $usePgp - - lappend downloadedFileNames [list \ - $fileNameOnly $directory(temporary) $directory(persistent)] - - if {$usePgp && \ - ![isOpenPgpSignatureFileName $downloadFileName true]} then { - downloadOneFile $language $version [appendArgs $fileName .asc] \ - [appendArgs $downloadFileName .asc] $usePgp - - lappend downloadedFileNames [list \ - [appendArgs $fileNameOnly .asc] $directory(temporary) \ - $directory(persistent)] - } - } - - set downloadDirectories [list] - - foreach downloadedFileName $downloadedFileNames { - set directory(temporary) [lindex $downloadedFileName 1] - - if {$persistent || $viaInstall} then { - set fileNameOnly [lindex $downloadedFileName 0] - set directory(persistent) [lindex $downloadedFileName 2] - - file mkdir $directory(persistent) - set command [list file copy] - - # - # NOTE: When updating the package repository client files, always - # use the -force option to overwrite existing files. Also, - # if we are allow updates, use the -force option. - # - if {$isClient || $allowUpdate} then { - lappend command -force - } - - lappend command -- - lappend command [file join $directory(temporary) $fileNameOnly] - lappend command [file join $directory(persistent) $fileNameOnly] - - eval $command - - lappend downloadDirectories $directory(persistent) - } else { - lappend downloadDirectories $directory(temporary) - } - } - - # - # NOTE: Does the package need to be persisted locally? This can be set - # via the direct caller or via the installer tool. - # - set addPersistentDirectoryToAutoPath false - - if {$persistent || $viaInstall} then { - # - # NOTE: In Eagle, a slightly different command is required to delete - # an entire directory tree. - # - if {[isEagle]} then { - file delete -recursive -- $temporaryDirectory - } else { - file delete -force -- $temporaryDirectory - } - - # - # NOTE: When the target language is native Tcl, try to create the - # master package index, if necessary. - # - if {$language eq "tcl"} then { - maybeCreateMasterTclPackageIndex - set addPersistentDirectoryToAutoPath true - } - } - - # - # NOTE: Sort the list of directories that downloaded files were written - # to, removing any duplicates in the process. - # - set downloadDirectories [lsort -unique $downloadDirectories] - - if {$useAutoPath} then { - # - # NOTE: The auto-path, for whatever language this package belongs to, - # needs to be modified. - # - if {$addPersistentDirectoryToAutoPath} then { - # - # NOTE: The downloaded package was persisted -AND- will be handled - # by the master package index; therefore, just make sure the - # package persistence root directory is in the auto-path and - # then return only that directory in the result. - # - maybeAddToAutoPath $language $persistentDirectory - set downloadDirectories [list $persistentDirectory] - } else { - # - # NOTE: Check each unique download directory for a package index - # file. If a directory has a package index for the target - # language, add to the auto-path for the target language. - # - set packageIndexFileName [getPackageIndexFileName $language] - - if {[string length $packageIndexFileName] > 0} then { - foreach downloadDirectory $downloadDirectories { - if {[file exists [file join \ - $downloadDirectory $packageIndexFileName]]} then { - addToAutoPath $language $downloadDirectory - } - } - } - } - } - - # - # NOTE: Always return the list of directories that were actually added - # to the auto-path, if any. - # - return $downloadDirectories - } - - # - # NOTE: This package requires that support for namespaces, which is an - # optional feature of Eagle, must be enabled. - # - if {[isEagle] && ![namespace enable]} then { - error "namespaces must be enabled for this package" - } - - # - # NOTE: This package requires the package repository client package. - # - package require Eagle.Package.Repository - - # - # NOTE: Attempt to read optional settings file now. This may override - # one or more of the variable setup in the next step. - # - ::PackageRepository::maybeReadSettingsFile [info script] - - # - # NOTE: Setup the variables, within this namespace, used by this script. - # - setupDownloadVars [info script] - - # - # NOTE: Setup the URI and URN variables, within this namespace, used by - # this script. - # - setupDownloadUriVars false; setupDownloadUrnVars false - - # - # NOTE: If necessary, add the package persistence root directory to the - # auto-path for the current language. This will only be done if - # it falls outside of the existing auto-path. - # - variable persistentRootDirectory - - maybeAddToAutoPath [expr {[isEagle] ? "eagle" : "tcl"}] \ - $persistentRootDirectory - - # - # NOTE: Provide the package to the interpreter. - # - package provide Eagle.Package.Downloader \ - [expr {[isEagle] ? [info engine PatchLevel] : "1.0"}] -} - DELETED client/1.0/pkgd.eagle.asc Index: client/1.0/pkgd.eagle.asc ================================================================== --- client/1.0/pkgd.eagle.asc +++ client/1.0/pkgd.eagle.asc @@ -1,18 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v2 -Comment: Eagle Package Repository - -iQIcBAABCAAGBQJYBrjcAAoJEFAslq9JXcLZSGgP/RVui2Xa4k1YcgF6QVACMzit -6s6uRh+ArmPiNdOzicBIkscIjlz9zeGNK7EYuFuCssSY//gzljMIUxqfXTzDxAxw -y0VB6AdfcHWNCDIN1IIFvuITNeHcJ57m0CKxQmYvmI+0wcNK7CD4+2tvoaHAvt+D -TwXA4FaZe6A6gYqnmNCvjIT2QKjA7KLQqwm74keh9bL4NY6eOWFrRpq2FkH6o75q -J/X0WErNeO856eqBxGtmPG+Q1298OLLsre06AIoL8qMijGWjCWbDPE6ydoZ9Oqh8 -wp8f9dZFIW9b2vngMjiviiyMwBHBaSEPJ9He7hMomaXcMo9sHigT7+AZ5N5e3V70 -qFsoNO01l6gupEQ0jzlYiOUh8KTtEFfzAKVX0oOyBeFQPVa7wHKY3cand/0Lj/8q -3MMtuLttWamh5nPMfzrP+pgN7YQhAp2fNS5POnTKgwzg7vggKZIUf6E0Ga+kdlx6 -BxpPuOpf7jMMkFSa4uvbO2DQhpkoQqRiqnok/vk+eL87nmYnM6ehGa/Yve+2A7Z3 -If/pLTgTbu+w34Mtv6uYk7xY+pQe2buoIuElrMsaCOOJ9g0GF51G0HCz+tQt6bNR -b1ggG8ZQM93vh281mPYA/hZMyUqeaFX1SMIsRJYga9NuLTpkliLjpeq29zVXKEBn -re8Q1YHJHjcQlyhiqUVt -=yIaN ------END PGP SIGNATURE----- DELETED client/1.0/pkgd.eagle.harpy Index: client/1.0/pkgd.eagle.harpy ================================================================== --- client/1.0/pkgd.eagle.harpy +++ client/1.0/pkgd.eagle.harpy @@ -1,68 +0,0 @@ - - - - None - Mistachkin Systems - 167e825c-3f92-4b50-b472-ca33369ed2ba - SHA512 - Script - 2016-10-19T00:04:51.1466094Z - -1.00:00:00 - 0x9559f6017247e3e2 - - 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 - - DELETED client/1.0/pkgd.eagle.harpy.asc Index: client/1.0/pkgd.eagle.harpy.asc ================================================================== --- client/1.0/pkgd.eagle.harpy.asc +++ client/1.0/pkgd.eagle.harpy.asc @@ -1,18 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v2 -Comment: Eagle Package Repository - -iQIcBAABCAAGBQJYBrjeAAoJEFAslq9JXcLZiNEQAJCXuhQfmKg91lVoZCdLkS8v -hRwZCG2WL+XuN0Vm7KMRtkY1km70gWULdXZZbwBMg8UEVC++QbLDttQEVEsuFxrP -vfABrVAGJ3USsYm3/dIV87kZuaHd/LB//PzJ4f7gjFLVE4+G62VA5yqZItliWE1f -hcPj410oo5wX+N3bTspEtDUGjNYh5i5eq4V0m+EM77QuV+d3e2pmP6yLumRzUfvN -6BKqno/Tom0mT9uaa2y4N3dJ3OICdmfHSKc5FCgODQ8qTjsIpk2P0fUIj5qad1+v -icUDnUEUaOaMIGXx0/GXUmIzz/fUQZOC0AGV65q57bLt0IsMjhkfZNXDVYUakXqx -Fnn/dP12XVbSIfsC8i9wBcf+pRvo9etiMByss0sRcm3o2uhwFWIwuCsSVWZexU7U -vV6HA2mDWpgMOhY39BMxpiKRzZv3hqHjPLjQXUQ+iiqBuc0vHKu0CWbY+po4L++a -kbgEvIl020ymwBjLzsPcjxBlY+pRd27RfaaQX9zVEX6ZvdH3UP7EdlcOU3fGuL/h -2bGaJBbzyXrPUkzw7VTED4hbYpi/BfyPUXts2zzB4hu/JBRfPMshiL1txMh5u1E6 -dCi2E+gcGWaJZ50hLn07ae1COGtqFrcErzFAgO7IJUCb4Xb4T7HPCE198PIUbD3m -S3SMU02ISH2RNdlOPrWF -=2VdE ------END PGP SIGNATURE----- DELETED client/1.0/pkgd.settings.mistachkin.eagle Index: client/1.0/pkgd.settings.mistachkin.eagle ================================================================== --- client/1.0/pkgd.settings.mistachkin.eagle +++ client/1.0/pkgd.settings.mistachkin.eagle @@ -1,18 +0,0 @@ -############################################################################### -# -# pkgd.settings.mistachkin.eagle -- -# -# Extensible Adaptable Generalized Logic Engine (Eagle) -# Package Downloader Client Settings -# -# Copyright (c) 2007-2012 by Joe Mistachkin. All rights reserved. -# -# See the file "license.terms" for information on usage and redistribution of -# this file, and for a DISCLAIMER OF ALL WARRANTIES. -# -# RCS: @(#) $Id: $ -# -############################################################################### - -variable quiet false -variable persistentRootDirectory [file join $::env(TEMP) pkgd_override] DELETED client/1.0/pkgd.settings.mistachkin.eagle.asc Index: client/1.0/pkgd.settings.mistachkin.eagle.asc ================================================================== --- client/1.0/pkgd.settings.mistachkin.eagle.asc +++ client/1.0/pkgd.settings.mistachkin.eagle.asc @@ -1,18 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v2 -Comment: Eagle Package Repository - -iQIcBAABCAAGBQJYBZuOAAoJEFAslq9JXcLZ+asP+QH8YjtxxMMcqFvFMe7+ZLfN -BDdyhUBVARMgpckWghtlz7A2S6EwzcouF0RkoO9RZKqonIJ/rlv/lpC/b5GD4beh -eThgTRSPja473RNN4Cp5Rl0mDmPw+8Y4UESAqaAh81jYiI7NiIeotO6vff5SN9/7 -MS6fSp45aoFLrKuwUbyT2Ii0Aqcn1i4JvLaYDoVQKbAOnSgpskfk+/JhK1wKPABH -lkQicDBINh5/fM3p25dK9zFma8EDqRtv8+FNdckipE7BR9eu41C73fzfeAUjN8jw -ahcjdRA52TSa4Nkofyo+gRam3xmLjSBd+LKCm99Rc1kQGH5yFCRWYtvB1cAPzhoQ -I4d1We2ZWXvsa3rlgrMcvX1yNcLWr2DRIGen4EoN25n9wgPTwhnftxgbxnJytP2A -1zNdZDowOkRtxrVG8KFwM5hw1TSbKcyW/0fFwzcibA/fd4CwldXnGpODW6Vpnhug -DAW26+VLR1tptC+Ayre3an8sFE4GLYo/9zai6sLZbT8YMCmnodJ2rcS7Y3s7Fk7f -yMCG1YRFtAJIXywCR0zpfkYyuvEvtLtcNfe6dHN8oLTtTwYyugasz7bABx2uUUz8 -ZaKKX0FEz7otMCkKxvk3c/+zvY9mqAt+EybIfb5ppERV48QOUKvmH++2XOaP2PQY -Ed5/j/JzHY+SyoxlgHby -=t4Hi ------END PGP SIGNATURE----- DELETED client/1.0/pkgd.settings.mistachkin.eagle.harpy Index: client/1.0/pkgd.settings.mistachkin.eagle.harpy ================================================================== --- client/1.0/pkgd.settings.mistachkin.eagle.harpy +++ client/1.0/pkgd.settings.mistachkin.eagle.harpy @@ -1,68 +0,0 @@ - - - - None - Mistachkin Systems - a4a30140-8aec-40b7-89af-44cecdef8193 - SHA512 - Script - 2016-10-18T03:47:22.9220000Z - -1.00:00:00 - 0x9559f6017247e3e2 - - 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 - - DELETED client/1.0/pkgd.settings.mistachkin.eagle.harpy.asc Index: client/1.0/pkgd.settings.mistachkin.eagle.harpy.asc ================================================================== --- client/1.0/pkgd.settings.mistachkin.eagle.harpy.asc +++ client/1.0/pkgd.settings.mistachkin.eagle.harpy.asc @@ -1,18 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v2 -Comment: Eagle Package Repository - -iQIcBAABCAAGBQJYBZuUAAoJEFAslq9JXcLZLDIP/A6ivrbT1LbbwSA9jGkTUfvL -wHjAxMdv8+mihbLywpebj8u1Ly8B2CuZnfRF9mhYmYNajCNDUbVhOYsNcxGGi9BI -WjAaLAAQsoaHBmIeTgYzWbeExcAgYlVymhh075JoIvBuhqpwtgjcFB7zWb7HQjZt -Dwro5aPCDvB0EBUXpizRGS2pFUMwCgDFWcv9WSyya3YOVabSJpTnz7H0rmLOJWNN -38TyiiQbv0W5p8T75/1sDwhq0C54kb3JIxAOpMhkXvKcZ7vt6Z78nw0MtQTTbOZb -4EKjCoHa4flVfCS/C/NdGAxypJG47PgNXpzZey7afrWZorggDUeI8v5IDT9Jz7FE -DsIS020kruF9SGlUQKMPYCimIHi23vjCrg+qNXl/UTHMlzCUyESrwSoy47YRhMtZ -KtxOi8873PrN6oC0C3ln519Sc6GowWiO6uREofHp1GJELC/3Pf8W3wrnQUZVtDOX -BlbKDfsp3vb9JB7IkXdRjgBCIZuFGSBZJK1uflq0NFM4zSq6gM6Em9W0/KQ6HVaN -0l3FtKATttXZA4SLV/54Eb6/50AE+/4BwmVw6wOWU8biG8BHzJ0peZcQXXV9VhWo -gOwgiTzDCBz+f3NGXVqw+FWfycom0qhXUmrd16S4dSvBgdPo/n8vPBH/+snFD33y -lxrGtuiqivSTAu8og6Pk -=8BVz ------END PGP SIGNATURE----- DELETED client/1.0/pkgr.eagle Index: client/1.0/pkgr.eagle ================================================================== --- client/1.0/pkgr.eagle +++ client/1.0/pkgr.eagle @@ -1,2206 +0,0 @@ -############################################################################### -# -# pkgr.eagle -- -# -# Extensible Adaptable Generalized Logic Engine (Eagle) -# Package Repository Client -# -# Copyright (c) 2007-2012 by Joe Mistachkin. All rights reserved. -# -# See the file "license.terms" for information on usage and redistribution of -# this file, and for a DISCLAIMER OF ALL WARRANTIES. -# -# RCS: @(#) $Id: $ -# -############################################################################### - -# -# NOTE: Use our own namespace here because even though we do not directly -# support namespaces ourselves, we do not want to pollute the global -# namespace if this script actually ends up being evaluated in Tcl. -# -namespace eval ::PackageRepository { - # - # NOTE: If there is an "Eagle1.0" sub-directory present right beneath where - # this script was evaluated from, add it to the auto-path; otherwise, - # we assume that we are running from inside the source tree. In that - # case, modify the auto-path to include the "Eagle1.0" sub-directory - # within "externals". Only native Tcl needs to be able to locate the - # packages from the sub-directory being added to the auto-path here - # because they were already shipped in the Eagle core script library - # (as of Beta 37). The expression used for Eagle detection here was - # stolen from the Eagle core script library [isEagle] procedure. - # - variable pkgr_path; # DEFAULT: - - if {![info exists ::tcl_platform(engine)] || \ - [string compare -nocase eagle $::tcl_platform(engine)] != 0} then { - set pkgr_path [file normalize [file dirname [info script]]] - - if {[file isdirectory [file join $pkgr_path Eagle1.0]]} then { - lappend ::auto_path [file join $pkgr_path Eagle1.0] - } else { - lappend ::auto_path [file join [file dirname [file dirname \ - $pkgr_path]] externals Eagle lib Eagle1.0] - } - } - - # - # NOTE: This package requires several packages from the Eagle core script - # library, even when it is being used by native Tcl. If necessary, - # prior to evaluating this file in native Tcl, its auto-path should - # be modified to include an "Eagle1.0" directory (i.e. a directory - # containing the Eagle core script library files "auxiliary.eagle", - # "file1.eagle", and "platform.eagle"). - # - package require Eagle.Platform - package require Eagle.Auxiliary - package require Eagle.File - - # - # NOTE: This block is intended to be evaluated successfully by native Tcl - # only. It serves two purposes: - # - # 1. Import the Eagle core script library procedures that are used - # by this package into the global namespace. - # - # 2. Unset the "pkgr_path" (namespace) variable that was created by - # the auto-path adjustment script fragment (above). - # - if {[info exists pkgr_path]} then { - catch { - ::Eagle::exportAndImportPackageCommands ::Eagle \ - [list appendArgs getDictionaryValue isEagle \ - isWindows readFile writeFile] false false - } - - unset -nocomplain pkgr_path - } - - # - # NOTE: This procedure is used to provide a TIP #194 compatible [apply] - # command to the native Tcl 8.4 interpreter. Eagle and native Tcl - # 8.5 (or higher) have this command built-in. The lambdaExpr - # argument must be a list with two or three elements. The first - # element is the list of arguments to the procedure. The second - # element is the body of the procedure. The third element is the - # target namespace for the procedure. If the third element is not - # specified, the global namespace is used. Any remaining arguments - # are passed to the procedure verbatim. - # - if {[llength [info commands ::apply]] == 0} then { - proc ::apply { lambdaExpr args } { - set length [llength $lambdaExpr] - - if {$length < 2 || $length > 3} { - error [appendArgs \ - "can't interpret \"" $lambdaExpr "\" as a lambda expression"] - } - - foreach {procArgs procBody procNamespace} $lambdaExpr {break} - - set procNameSuffix [::PackageRepository::getUniqueSuffix 2] - set procName [appendArgs :: $procNamespace ::lambda_ $procNameSuffix] - set procPreBody {rename [lindex [info level 0] 0] "";} - - proc $procName $procArgs [appendArgs $procPreBody $procBody] - - return [uplevel 1 [list $procName] $args] - } - } - - # - # NOTE: This procedure returns a formatted, possibly version-specific, - # package name, for use in logging. The package argument is the - # name of the package. The version argument is the version of the - # package. - # - proc formatPackageName { package version } { - return [string trim [appendArgs $package " " $version]] - } - - # - # NOTE: This procedure returns a formatted script result. If the string - # result is empty, only the return code is used. The code argument - # must be an integer Tcl return code (e.g. from [catch]) and the - # result argument is the script result or error message. - # - proc formatResult { code result } { - switch -exact -- $code { - 0 {set codeString ok} - 1 {set codeString error} - 2 {set codeString return} - 3 {set codeString break} - 4 {set codeString continue} - default {set codeString [appendArgs unknown( $code )]} - } - - if {[string length $result] > 0} then { - return [appendArgs \ - "code " $codeString ", result " [list $result]] - } else { - return $codeString - } - } - - # - # NOTE: This procedure emits a message to the package repository client - # log. The string argument is the content of the message to emit. - # - proc pkgLog { string } { - catch { - tclLog [appendArgs [pid] " : " [clock seconds] " : pkgr : " $string] - } - } - - # - # NOTE: This procedure attempts to determine if a string is a valid list - # and returns non-zero when that is true. The value argument is - # the string to check. - # - proc stringIsList { value } { - if {[isEagle]} then { - return [string is list $value] - } else { - global tcl_version - - if {[info exists tcl_version] && $tcl_version >= 8.5} then { - return [string is list $value] - } elseif {[catch {llength $value}] == 0} then { - return true - } else { - return false - } - } - } - - # - # NOTE: This procedure returns non-zero if the specified string value - # looks like a Harpy (script) certificate. The value argument is - # the string to check. The value 14 used within this procedure is - # the length of the literal string "". - # - # - proc isHarpyCertificate { value } { - set value [string trim $value] - set length [string length $value] - - if {$length == 0 || ([string first [string trim { - - }] $value] == 0 && [string first [string trim { - - }] $value] == ($length - 14))} then { - return true - } else { - return false - } - } - - # - # NOTE: This procedure returns non-zero if the specified string value - # looks like an OpenPGP signature. The value argument is the string - # to check. The value 27 used within this procedure is the length - # of the literal string "-----END PGP SIGNATURE-----". - # - # - proc isOpenPgpSignature { value } { - set value [string trim $value] - set length [string length $value] - - if {$length == 0 || ([string first [string trim { - -----BEGIN PGP SIGNATURE----- - }] $value] == 0 && [string first [string trim { - -----END PGP SIGNATURE----- - }] $value] == ($length - 27))} then { - return true - } else { - return false - } - } - - # - # NOTE: This procedure returns the fully qualified name of the directory - # where temporary files should be written. The envVarName argument - # is an optional extra environment variable to check (first). - # - # - proc getFileTempDirectory { {envVarName ""} } { - global env - - if {[string length $envVarName] > 0 && \ - [info exists env($envVarName)]} then { - return $env($envVarName) - } elseif {[info exists env(TEMP)]} then { - return $env(TEMP) - } elseif {[info exists env(TMP)]} then { - return $env(TMP) - } else { - if {[string length $envVarName] > 0} then { - set defEnvVarName $envVarName - } elseif {[isWindows]} then { - set defEnvVarName TEMP - } else { - set defEnvVarName TMP - } - - error [appendArgs \ - "please set the \"" $defEnvVarName \ - "\" environment variable to the path of a temporary directory"] - } - } - - # - # NOTE: This procedure returns a unique temporary file name. A script - # error is raised if this task cannot be accomplished. There are - # no arguments. - # - proc getFileTempName {} { - if {[isEagle]} then { - return [file tempname] - } else { - set directory [getFileTempDirectory PKGR_TEMP] - set counter [expr {[pid] ^ int(rand() * 0xFFFF)}] - - while {1} { - set fileNameOnly [format tcl%04X.tmp $counter] - set fileName [file join $directory $fileNameOnly] - - if {![file exists $fileName]} then { - return $fileName - } - - incr counter - } - } - } - - # - # NOTE: This procedure attempts to verify the OpenPGP signature contained - # in the specified (named) file. Non-zero is only returned if the - # OpenPGP signature is verified successfully. A script error should - # not be raised by this procedure. The fileName argument must be - # the fully qualified path and file name of the OpenPGP signature - # file to verify. - # - # - proc verifyOpenPgpSignature { fileName } { - variable openPgpCommand - - if {[isEagle]} then { - set fileName [appendArgs \" $fileName \"] - - if {[catch { - eval exec -success Success [subst $openPgpCommand] - }] == 0} then { - return true - } - } else { - if {[catch { - eval exec [subst $openPgpCommand] 2>@1 - }] == 0} then { - return true - } - } - - return false - } - - # - # NOTE: This procedure returns the prefix for fully qualified variable - # names that MAY be present in the global namespace. There are - # no arguments. - # - proc getLookupVarNamePrefix {} { - return ::pkgr_; # TODO: Make non-global? - } - - # - # NOTE: This procedure returns a name suffix (directory, variable, etc) - # that is unique to the running process at the current point in - # time. It is used (internally) to avoid name collisions with any - # preexisting variables or commands that may be present in the - # global namespace. The paranoia argument represents the relative - # level of paranoia required by the caller; the higher this level, - # the more uniqueness is required. - # - # - proc getUniqueSuffix { {paranoia 1} } { - set result [string trim [pid] -] - - if {$paranoia > 0} then { - append result _ [string trim [clock seconds] -] - } - - if {$paranoia > 1} then { - append result _ [string trim \ - [clock clicks -milliseconds] -]; # TODO: Bad? - } - - return $result - } - - # - # NOTE: This procedure returns the list of API keys to use when looking - # up packages via the package repository server. An empty list - # is returned if no API keys are currently configured. The prefix - # argument is an extra variable name prefix to check prior to any - # that are already configured. The prefixOnly argument should be - # non-zero to exclude any API keys other than those based on the - # prefix specified by the caller. - # - # - proc getApiKeys { {prefix ""} {prefixOnly false} } { - global env - variable autoApiKeys - - # - # NOTE: If the caller specified a variable name prefix, try to use it - # first. - # - set prefixes [list] - - if {[string length $prefix] > 0} then { - lappend prefixes $prefix - } - - # - # NOTE: Next, fallback to the variable name prefix for this package, - # unless the caller has forbidden us to do so. - # - if {!$prefixOnly} then { - lappend prefixes [getLookupVarNamePrefix] - } - - # - # NOTE: Try each variable name prefix, in order, until a set of API - # keys is found. - # - foreach prefix $prefixes { - # - # NOTE: If an empty prefix is seen, force it to use the "api_keys" - # variable from the global namespace. - # - if {[string length $prefix] == 0} then { - set prefix ::; # TODO: Make non-global? - } - - # - # NOTE: Check for the variable, in whatever namespace it resides, - # and return its value verbatim if it exists. - # - set varName [appendArgs $prefix api_keys] - - if {[info exists $varName]} then { - return [set $varName] - } - - # - # NOTE: Fallback to using an environment variable with the same - # base name and returns its value verbatim if it exists. - # - set varName [string trim $varName :] - - if {[info exists env($varName)]} then { - return $env($varName) - } - } - - # - # NOTE: If there is a default list of API keys, just return it, - # unless the caller has forbidden us to do so. - # - if {!$prefixOnly && \ - [info exists autoApiKeys] && [llength $autoApiKeys] > 0} then { - return $autoApiKeys - } - - # - # NOTE: Otherwise, return the system default, which is "anonymous" - # packages only (i.e. those without any owners). - # - return [list] - } - - # - # NOTE: This procedure returns the base URI for the package repository - # server. There are no arguments. - # - proc getLookupBaseUri {} { - set varName [appendArgs [getLookupVarNamePrefix] base_uri] - - if {[info exists $varName]} then { - return [set $varName] - } - - global env - set varName [string trim $varName :] - - if {[info exists env($varName)]} then { - return $env($varName) - } - - return https://urn.to/r/pkg; # NOTE: System default. - } - - # - # NOTE: This procedure returns the full URI to use when looking up a - # specific package via the package repository server. The apiKeys - # argument is the list of API keys to use -OR- an empty list if a - # public package is being looked up. The package argument is the - # name of the package being looked up, it cannot be an empty - # string. The version argument is the specific version being - # looked up -OR- an empty string for any available version. There - # are no HTTP requests issued by this procedure; it simply returns - # the URI to use. - # - proc getLookupUri { apiKeys package version } { - set baseUri [getLookupBaseUri] - - if {[string length $baseUri] == 0} then { - return "" - } - - # - # NOTE: Build the HTTP request URI using the specified query parameter - # values, escaping them as necessary. Also, include the standard - # query parameters with constant values for this request type. - # - set anonymousApiKey "" - - if {[isEagle]} then { - if {[llength $apiKeys] > 0} then { - return [appendArgs \ - $baseUri ?raw=1&method=lookup&apiKeys= [uri escape uri \ - [join $apiKeys ,]] &package= [uri escape uri $package] \ - &version= [uri escape uri $version]] - } else { - return [appendArgs \ - $baseUri ?raw=1&method=lookup&apiKey= [uri escape uri \ - $anonymousApiKey] &package= [uri escape uri $package] \ - &version= [uri escape uri $version]] - } - } else { - package require http 2.0 - - if {[llength $apiKeys] > 0} then { - return [appendArgs \ - $baseUri ? [::http::formatQuery raw 1 method lookup \ - apiKeys [join $apiKeys ,] package $package version \ - $version]] - } else { - return [appendArgs \ - $baseUri ? [::http::formatQuery raw 1 method lookup \ - apiKey $anonymousApiKey package $package version \ - $version]] - } - } - } - - # - # NOTE: This procedure returns the version of the package that should be - # used to lookup the associated [package ifneeded] script -OR- an - # empty string if no such version exists. 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. - # - proc getIfNeededVersion { package version } { - if {[string length $version] > 0} then { - return $version - } - - return [lindex [package versions $package] 0] - } - - # - # NOTE: This procedure accepts a package requirement (spec) and returns - # a simple package version, if possible. An empty string will be - # returned, if appropriate (i.e. any version should be allowed). - # The requirement argument must be a package specification that - # conforms to TIP #268. - # - proc packageRequirementToVersion { requirement } { - set result $requirement - - if {[set index [string first - $result]] != -1} then { - incr index -1; set result [string range $result 0 $index] - } - - if {[set index [string first a $result]] != -1 || \ - [set index [string first b $result]] != -1} then { - incr index -1; set result [string range $result 0 $index] - } - - if {$result eq "0"} then { - set result "" - } elseif {[regexp -- {^\d+$} $result]} then { - append result .0 - } - - return $result - } - - # - # NOTE: This procedure issues an HTTP request that should return metadata - # that can be used to load and/or provide the specified package. - # The apiKeys argument is the list of API keys to use -OR- an empty - # list 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. All line-endings are normalized to Unix-style; - # therefore, all script signatures must assume this. - # - proc getLookupData { apiKeys package version } { - variable verboseUriDownload - - set uri [getLookupUri $apiKeys $package $version] - - if {[string length $uri] == 0} then { - return "" - } - - if {$verboseUriDownload} then { - pkgLog [appendArgs \ - "attempting to download URI \"" $uri \"...] - } - - if {[isEagle]} then { - set data [uri download -inline $uri] - } else { - set data [getFileViaHttp \ - $uri 20 stdout [expr {!$verboseUriDownload}] -binary true] - } - - if {$verboseUriDownload} then { - pkgLog [appendArgs \ - "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 trim $data] - - return $data - } - - # - # NOTE: This procedure attempts to extract the lookup code from the raw - # HTTP response data. The data argument is the raw HTTP response - # data. An empty string is returned if no lookup code is available. - # - proc getLookupCodeFromData { data } { - if {![stringIsList $data] || [llength $data] < 1} then { - return "" - } - - return [lindex $data 0] - } - - # - # NOTE: This procedure attempts to extract the lookup result from the raw - # HTTP response data. The data argument is the raw HTTP response - # data. An empty string is returned if no lookup result is available. - # - proc getLookupResultFromData { data } { - if {![stringIsList $data] || [llength $data] < 2} then { - return "" - } - - return [lindex $data 1] - } - - # - # NOTE: This procedure returns non-zero if the specified lookup response - # code indicates success. The code argument is the extracted HTTP - # lookup response code. - # - proc isLookupCodeOk { code } { - # - # NOTE: The code must be the literal string "OK" for the package lookup - # request to be considered successful. - # - return [expr {$code eq "OK"}] - } - - # - # NOTE: This procedure was stolen from the "common.tcl" script used by the - # package repository server. It has been modified to support both - # native Tcl and Eagle. It should be noted here that TIP #268 syntax - # is not supported by Eagle. For native Tcl, the requirement argument - # must be a package version or requirement conforming to the TIP #268 - # syntax. For Eagle, the requirement argument must be a simple dotted - # package version, with up to four components, without any 'a' or 'b'. - # The emptyOk argument should be non-zero if an empty string should be - # considered to be valid by the caller. The rangeOk argument should - # be non-zero if the version range syntax is allowed; this argument is - # ignored for Eagle because it requires TIP #268 support. - # - proc isValidPackageRequirement { requirement rangeOk {emptyOk false} } { - if {$emptyOk && [string length $requirement] == 0} then { - return true - } - - if {[isEagle]} then { - # - # NOTE: Eagle does not support TIP #268. Use the built-in sub-command - # that checks a version number. - # - return [string is version -strict $requirement] - } else { - # - # HACK: If a version range is not allowed, make sure that the dash - # character is not present. - # - if {!$rangeOk && [string first - $requirement] != -1} then { - return false - } - - # - # HACK: There is no direct way to check if a package requirement - # that uses the TIP #268 syntax is valid; however, we can - # purposely "misuse" the [package present] command for this - # purpose. We know the "Tcl" package is always present; - # therefore, if an error is raised here, then the package - # requirement is probably invalid. Unfortunately, the error - # message text has to be checked as well; otherwise, there - # is no way to verify version numbers that happen to be less - # than the running patch level of Tcl. - # - if {[catch {package present Tcl $requirement} error] == 0} then { - return true - } else { - # - # TODO: Maybe this will require updates in the future? - # - set pattern(1) "expected version number but got *" - set pattern(2) "expected versionMin-versionMax but got *" - - if {![string match $pattern(1) $error] && \ - ![string match $pattern(2) $error]} then { - return true - } else { - return false - } - } - } - } - - # - # NOTE: This procedure attempts to extract the package lookup metadata from - # the lookup result. The result argument is the lookup result. The - # varName argument is the name of an array variable, in the call frame - # of the immediate caller, that should receive the extracted package - # lookup metadata. The caller argument must be an empty string -OR- - # the literal string "handler". - # - proc extractAndVerifyLookupMetadata { result varName caller } { - variable strictUnknownLanguage - - # - # NOTE: Grab the returned patch level. It cannot be an empty string - # and it must conform to the TIP #268 requirements for a single - # package version. - # - set patchLevel [getDictionaryValue $result PatchLevel] - - if {[string length $patchLevel] == 0} then { - error "missing patch level" - } - - if {![isValidPackageRequirement $patchLevel false]} then { - error "bad patch level" - } - - # - # NOTE: Grab the language for the package script. It must be an empty - # string, "Tcl", or "Eagle". If it is an empty string, "Eagle" - # will be assumed. - # - set language [getDictionaryValue $result Language] - - if {[lsearch -exact [list "" Tcl Eagle] $language] == -1} then { - error "unsupported language" - } - - # - # NOTE: Grab the package script. If it is an empty string, then the - # package cannot be loaded and there is nothing to do. In that - # case, just raise an error. - # - set script [getDictionaryValue $result Script] - - if {[string length $script] == 0} then { - error "missing script" - } - - # - # NOTE: Grab the package script certificate. If it is an empty string - # then the package script is unsigned, which is not allowed by - # this client. In that case, just raise an error. - # - set certificate [getDictionaryValue $result Certificate] - - if {[string length $certificate] == 0} then { - error "missing script certificate" - } - - # - # NOTE: Are we being called from the [package unknown] handler - # in "strict" mode? - # - if {$strictUnknownLanguage && $caller eq "handler"} then { - # - # NOTE: If so, the package script must be targeted at the this - # language; otherwise, there exists the possibility that - # the package may not be provided to this language. - # - if {[isEagle]} then { - if {$language ne "Eagle"} then { - error "repository package is not for Eagle" - } - } else { - if {$language ne "Tcl"} then { - error "repository package is not for Tcl" - } - } - } - - # - # NOTE: If the caller wants the package lookup metadata, use their - # array variable name. - # - if {[string length $varName] > 0} then { - upvar 1 $varName metadata - - set metadata(patchLevel) $patchLevel - set metadata(language) $language - set metadata(script) $script - set metadata(certificate) $certificate - } - } - - # - # NOTE: This procedure, which may only be used from an Eagle script, checks - # if a native Tcl library is loaded and ready. If not, a script error - # is raised. There are no arguments. - # - proc tclMustBeReady {} { - # - # NOTE: This procedure is useless when running in native Tcl; therefore, - # forbid its use there. - # - if {![isEagle]} then { - error "already running in Tcl language" - } - - # - # NOTE: This procedure is not allowed to actually load a native Tcl - # library; therefore, one must already be loaded. - # - if {![tcl ready]} then { - error "cannot use Tcl language, supporting library is not loaded" - } - } - - # - # NOTE: This procedure is designed for Eagle. It attempts to load the - # "best" native Tcl library. It may raise any number of script - # errors. There are no arguments. - # - proc makeTclReady {} { - # - # NOTE: This procedure is useless when running in native Tcl; therefore, - # forbid its use there. - # - if {![isEagle]} then { - error "already running in Tcl language" - } - - # - # NOTE: Load a native Tcl library. It absolutely must be signed with a - # valid Authenticode signature. - # - tcl load -findflags +TrustedOnly -loadflags +SetDllDirectory - - # - # NOTE: Verify that the native Tcl library appears to have beed loaded - # into this interpreter. - # - tclMustBeReady - } - - # - # NOTE: This procedure, which may only be used from a native Tcl script, - # checks if Garuda and Eagle are loaded and ready. If not, a script - # error is raised. There are no arguments. - # - proc eagleMustBeReady {} { - # - # NOTE: This procedure is useless when running in Eagle; therefore, - # forbid its use there. - # - if {[isEagle]} then { - error "already running in Eagle language" - } - - # - # NOTE: This procedure is not allowed to actually load Garuda (and - # Eagle); therefore, they must already be loaded. - # - if {[llength [info commands eagle]] == 0} then { - error "cannot use Eagle language, supporting package is not loaded" - } - } - - # - # NOTE: This procedure is designed for native Tcl. It attempts to load - # the Garuda package and gain access to Eagle. It may raise any - # number of script errors. There are no arguments. - # - proc makeEagleReady {} { - # - # NOTE: This procedure is useless when running in Eagle; therefore, - # forbid its use there. - # - if {[isEagle]} then { - error "already running in Eagle language" - } - - # - # TODO: Assume the Garuda package is trusted? How can we verify it - # at this point? - # - package require Garuda - - # - # NOTE: Verify that the Garuda package appears to have been fully and - # successfully loaded into this interpreter. - # - eagleMustBeReady - } - - # - # NOTE: This procedure returns non-zero if the current script is being - # evaluated in Eagle with signed-only script security enabled. - # There are no arguments. - # - proc eagleHasSecurity {} { - # - # NOTE: If possible, check if the current interpreter has security - # enabled. - # - if {[isEagle] && [llength [info commands object]] > 0} then { - if {[catch { - object invoke -flags +NonPublic Interpreter.GetActive HasSecurity - } security] == 0 && $security} then { - return true - } - } - - return false - } - - # - # NOTE: This procedure uses the package lookup metadata. If the package - # script is properly signed, an attempt will be made to evaluate it - # in the target language. If the script was signed using OpenPGP, - # then a conforming implementation of the OpenPGP specification (e.g. - # gpg2) must be installed locally. If the script was signed using - # Harpy then Garuda, Eagle, and Harpy must be installed locally. - # This procedure is designed to work for both native Tcl and Eagle - # packages. Additionally, it is designed to work when evaluated - # using either native Tcl or Eagle; however, it is up to the package - # script itself to either add the package or provide the package to - # the language(s) supported by that package. The varName argument - # is the name of an array variable in the call frame of the - # immediate caller, that contains the package lookup metadata. This - # procedure may raise script errors. - # - proc processLookupMetadata { varName } { - # - # NOTE: If the metadata variable name appears to be invalid, fail. - # - if {[string length $varName] == 0} then { - error "bad metadata" - } - - # - # NOTE: This procedure requires that the metadata array variable is - # present in the call frame immediately above this one. - # - upvar 1 $varName metadata - - # - # NOTE: If the entire package metadata array is missing, fail. - # - if {![info exists metadata]} then { - error "missing metadata" - } - - # - # NOTE: If the patch level for the package is mising, fail. - # - if {![info exists metadata(patchLevel)]} then { - error "missing patch level" - } - - # - # NOTE: If the language for the package script is mising, fail. - # - if {![info exists metadata(language)]} then { - error "missing language" - } - - # - # NOTE: If the package script is mising, fail. - # - if {![info exists metadata(script)]} then { - error "missing script" - } - - # - # NOTE: If the package script certificate is mising, fail. - # - if {![info exists metadata(certificate)]} then { - error "missing script certificate" - } - - # - # NOTE: Create common cleanup script block that deletes any temporary - # files created for the script verification process. - # - set script(cleanup) { - if {[string length $fileName(2)] > 0 && \ - [file exists $fileName(2)] && [file isfile $fileName(2)]} then { - if {![info exists ::env(pkgr_keep_files)]} then { - catch {file delete $fileName(2)} - } - unset -nocomplain fileName(2) - } - - if {[string length $fileName(1)] > 0 && \ - [file exists $fileName(1)] && [file isfile $fileName(1)]} then { - if {![info exists ::env(pkgr_keep_files)]} then { - catch {file delete $fileName(1)} - } - unset -nocomplain fileName(1) - } - } - - # - # NOTE: Figure out the "type" of script certificate we are now dealing - # with. - # - if {[isHarpyCertificate $metadata(certificate)]} then { - # - # NOTE: Attempt to create a completely unique array variable name to - # hold the package metadata in this scripting language as well - # as possibly in the other necessary scripting language(s). - # - set newVarName(1) [appendArgs \ - [getLookupVarNamePrefix] metadata_ [getUniqueSuffix 2]] - - set newVarName(2) [appendArgs \ - [getLookupVarNamePrefix] cleanup_ [getUniqueSuffix 2]] - - set newProcName(1) [appendArgs \ - [getLookupVarNamePrefix] eagleHasSecurity_ [getUniqueSuffix 2]] - - set newProcName(2) [appendArgs \ - [getLookupVarNamePrefix] getFileTempName_ [getUniqueSuffix 2]] - - set newProcName(3) [appendArgs \ - [getLookupVarNamePrefix] tclMustBeReady_ [getUniqueSuffix 2]] - - # - # NOTE: Create the Eagle script block that will be used to securely - # evaluate a signed package script. This must be evaluated in - # Eagle because it uses several plugins only available there. - # - set script(outer) [string map [list \ - %metadata% $newVarName(1) %cleanup% $newVarName(2) \ - %eagleHasSecurity% $newProcName(1) %getFileTempName% \ - $newProcName(2) %tclMustBeReady% $newProcName(3)] { - try { - # - # NOTE: If there is no package script, there is nothing we - # can do here. - # - if {[string length ${%metadata%(script)}] > 0} then { - # - # NOTE: Save the security state for the interpreter. Then, attempt - # to enable it. This will fail if one of the needed plugins - # cannot be loaded. - # - set savedSecurity [{%eagleHasSecurity%}] - if {!$savedSecurity} then {source enableSecurity} - - try { - # - # NOTE: Figure out temporary file name for the downloaded script - # and its associated script certificate. - # - set fileName(1) [{%getFileTempName%}] - set fileName(2) [appendArgs $fileName(1) .harpy] - - try { - # - # NOTE: Write downloaded script to a temporary file. - # - writeFile $fileName(1) ${%metadata%(script)} - - # - # NOTE: Write downloaded script certificate to a temporary - # file. - # - if {[string length ${%metadata%(certificate)}] > 0} then { - writeFile $fileName(2) ${%metadata%(certificate)} - } - - # - # NOTE: This seems stupid. Why are we reading the downloaded - # script from the temporary file when we already had it - # in memory? The reason is that we need to make sure - # that the Harpy policy engine has a chance to check the - # downloaded script against its associated certificate. - # This will raise a script error if the script signature - # is missing or invalid. - # - set script(inner) [interp readorgetscriptfile -- \ - "" $fileName(1)] - - # - # NOTE: Determine the target language for the package script, - # which may or may not be the language that is currently - # evaluating this script (Eagle). The default language, - # when one was not explicitly specified, is Eagle. In - # the future, this may be changed, e.g. to use the file - # extension of the client script. - # - switch -exact -- ${%metadata%(language)} { - "" - - Eagle { - # - # NOTE: The target language is Eagle, which is evaluating - # this script. No special handling is needed here. - # - return [uplevel #0 $script(inner)] - } - Tcl { - # - # NOTE: The target language is Tcl; therefore, a bit of - # special handling is needed here. - # - {%tclMustBeReady%}; return [tcl eval [tcl master] [list \ - uplevel #0 $script(inner)]] - } - default { - error "unsupported language" - } - } - } finally { - # - # NOTE: Perform any necessary cleanup steps. - # - eval ${%cleanup%} - } - } finally { - # - # NOTE: Restore the saved security state for the interpreter. - # - if {!$savedSecurity} then {source disableSecurity} - unset -nocomplain savedSecurity - } - } - } finally { - rename {%tclMustBeReady%} "" - rename {%getFileTempName%} "" - rename {%eagleHasSecurity%} "" - - unset -nocomplain {%cleanup%} - unset -nocomplain {%metadata%} - } - }] - - # - # NOTE: Copy the package metadata into the fresh array variable, - # if necessary, marshalling it from native Tcl to Eagle. - # - if {[isEagle]} then { - array set $newVarName(1) [array get metadata] - set $newVarName(2) $script(cleanup) - - proc $newProcName(1) {} [info body [appendArgs \ - [namespace current] ::eagleHasSecurity]] - - proc $newProcName(2) {} [info body [appendArgs \ - [namespace current] ::getFileTempName]] - - proc $newProcName(3) {} [info body [appendArgs \ - [namespace current] ::tclMustBeReady]] - - return [eval $script(outer)] - } else { - eagleMustBeReady - - eagle [list array set $newVarName(1) [array get metadata]] - eagle [list set $newVarName(2) $script(cleanup)] - - eagle [list proc $newProcName(1) {} [info body [appendArgs \ - [namespace current] ::eagleHasSecurity]]] - - eagle [list proc $newProcName(2) {} [info body [appendArgs \ - [namespace current] ::getFileTempName]]] - - eagle [list proc $newProcName(3) {} [info body [appendArgs \ - [namespace current] ::tclMustBeReady]]] - - return [eagle $script(outer)] - } - } elseif {[isOpenPgpSignature $metadata(certificate)]} then { - # - # NOTE: If there is no package script, there is nothing we - # can do here. - # - if {[string length $metadata(script)] > 0} then { - # - # NOTE: Figure out temporary file name for the downloaded script - # and its associated OpenPGP signature. - # - set fileName(1) [getFileTempName] - set fileName(2) [appendArgs $fileName(1) .asc] - - # - # NOTE: Write downloaded script to a temporary file. - # - writeFile $fileName(1) $metadata(script) - - # - # NOTE: Write downloaded script OpenPGP signature a temporary file. - # - if {[string length $metadata(certificate)] > 0} then { - writeFile $fileName(2) $metadata(certificate) - } - - # - # NOTE: Attempt to verify the OpenPGP signature for the package - # script. - # - if {[verifyOpenPgpSignature $fileName(2)]} then { - # - # NOTE: Delete the temporary files that we created for the - # OpenPGP signature verification. - # - eval $script(cleanup) - } else { - # - # NOTE: Delete the temporary files that we created for the - # OpenPGP signature verification. - # - eval $script(cleanup) - - # - # NOTE: OpenPGP signature verification failed. Raise an error - # and do not proceed with evaluating the package script. - # - error "bad OpenPGP signature" - } - - # - # NOTE: The OpenPGP signature was verified; use the downloaded - # package script verbatim. - # - set script(inner) $metadata(script) - - # - # NOTE: Determine the target language for the package script, which - # may or may not be the language that is currently evaluating - # this script (Eagle). The default language, when one was not - # explicitly specified, is Eagle. In the future, this may be - # changed, e.g. to use the file extension of the client script. - # - switch -exact -- $metadata(language) { - "" - - Eagle { - if {[isEagle]} then { - return [uplevel #0 $script(inner)] - } else { - eagleMustBeReady - - return [eagle [list uplevel #0 $script(inner)]] - } - } - Tcl { - if {[isEagle]} then { - tclMustBeReady; return [tcl eval [tcl master] [list \ - uplevel #0 $script(inner)]] - } else { - return [uplevel #0 $script(inner)] - } - } - default { - error "unsupported language" - } - } - } - } else { - error "unsupported script certificate" - } - } - - # - # NOTE: This procedure returns non-zero if the specified package appears to - # be present. The package argument is the name of the package being - # sought, it cannot be an empty string. The version argument must be - # a specific version -OR- a package specification that conforms to TIP - # #268. - # - proc isPackagePresent { package version } { - variable verboseUnknownResult - - set command [list package present $package] - if {[string length $version] > 0} then {lappend command $version} - - if {[set code [catch $command result]] == 0} then { - if {$verboseUnknownResult} then { - pkgLog [appendArgs \ - "package \"" [formatPackageName $package $version] \ - "\" was loaded: " [formatResult $code $result]] - } - - return true - } else { - if {$verboseUnknownResult} then { - pkgLog [appendArgs \ - "package \"" [formatPackageName $package $version] \ - "\" was not loaded: " [formatResult $code $result]] - } - - return false - } - } - - # - # NOTE: This procedure returns non-zero if the specified package appears to - # be available. The package argument is the name of the package being - # sought, it cannot be an empty string. The version argument must be - # a specific version -OR- a package specification that conforms to TIP - # #268. - # - proc isPackageAvailable { package version } { - variable verboseUnknownResult - - set packageVersions [package versions $package] - - if {[llength $packageVersions] == 0} then { - if {$verboseUnknownResult} then { - pkgLog [appendArgs \ - "package \"" [formatPackageName $package $version] \ - "\" is not available: no versions"] - } - - return false - } - - if {[string length $version] == 0} then { - if {$verboseUnknownResult} then { - pkgLog [appendArgs \ - "package \"" [formatPackageName $package $version] \ - "\" is available: no version"] - } - - return true - } - - foreach packageVersion $packageVersions { - if {[package vsatisfies $packageVersion $version]} then { - if {$verboseUnknownResult} then { - pkgLog [appendArgs \ - "package \"" [formatPackageName $package $version] \ - "\" is available: version satisfied by \"" \ - [formatPackageName $package $packageVersion] \"] - } - - return true - } - } - - if {$verboseUnknownResult} then { - pkgLog [appendArgs \ - "package \"" [formatPackageName $package $version] \ - "\" is not available: version not satisfied"] - } - - return false - } - - # - # NOTE: This procedure returns non-zero if the specified package can be - # downloaded, i.e. because it is not required for the downloading - # process itself to be functional, etc. The package argument is - # the name of the package to check. - # - proc canDownloadPackage { package } { - # - # NOTE: Since all the functionality needed by this package is built-in - # to Eagle, there are no download restrictions when it is being - # used. - # - if {[isEagle]} then { - return true - } - - # - # NOTE: Since the "http" and "tls" packages are required from within - # the custom [package unknown] itself, in order to locate and - # download the requested package, we must return false here to - # prevent needless recursion. - # - if {[lsearch -exact [list http tls] $package] != -1} then { - return false - } - - # - # NOTE: Currently, all other packages, including Garuda, are legal to - # handle from the custom [package unknown] handler. - # - return true - } - - # - # NOTE: This procedure performs initial setup of the package repository - # client, using the current configuration parameters. There are - # no arguments. It may load the Garuda package when evaluated in - # native Tcl. It may load a native Tcl library when evaluated in - # Eagle. It may install the [package unknown] hook. - # - proc setupPackageUnknownHandler {} { - variable autoApiKeys - variable autoHook - variable autoLoadTcl - variable autoRequireGaruda - - # - # NOTE: Should we attempt to automatically load the Garuda package for - # native Tcl? - # - if {$autoRequireGaruda && ![isEagle] && [isWindows]} then { - makeEagleReady - } - - # - # NOTE: Should we attempt to automatically load a native Tcl library - # for Eagle? - # - if {$autoLoadTcl && [isEagle]} then { - makeTclReady - } - - # - # NOTE: Should we attempt to hook the [package unknown] handler. This - # is done for both native Tcl and Eagle. - # - if {$autoHook && ![isPackageUnknownHandlerHooked]} then { - # - # NOTE: Install our [package unknown] handler and save the original - # one for our use as well. - # - hookPackageUnknownHandler - } - } - - # - # NOTE: This procedure returns non-zero if the [package unknown] handler - # has already been hooked by the package repository client. There - # are no arguments. - # - proc isPackageUnknownHandlerHooked {} { - return [info exists [appendArgs \ - [getLookupVarNamePrefix] saved_package_unknown]] - } - - # - # NOTE: This procedure attempts to hook the [package unknown] handler. It - # will raise a script error if this has already been done. The old - # [package unknown] handler is saved and will be used by the new one - # as part of the overall package loading process. There are no - # arguments. - # - proc hookPackageUnknownHandler {} { - set varName [appendArgs [getLookupVarNamePrefix] saved_package_unknown] - - if {[info exists $varName]} then { - error "package unknown handler already hooked" - } - - set $varName [package unknown] - package unknown [appendArgs [namespace current] ::packageUnknownHandler] - } - - # - # NOTE: This procedure attempts to unhook the [package unknown] handler. - # It will raise a script error if the [package unknown] handler is - # not hooked. The old [package unknown] handler is restored and - # the saved [package unknown] handler is cleared. There are no - # arguments. - # - proc unhookPackageUnknownHandler {} { - set varName [appendArgs [getLookupVarNamePrefix] saved_package_unknown] - - if {![info exists $varName]} then { - error "package unknown handler is not hooked" - } - - package unknown [set $varName] - unset $varName - } - - # - # NOTE: The procedure runs the saved [package unknown] handler. Any script - # errors are raised to the caller. The package and version arguments - # are passed in from the current [package unknown] handler verbatim. - # - proc runSavedPackageUnknownHandler { package version } { - # - # NOTE: See if there is a saved [package unknown] handler. If so, then - # attempt to use it. - # - set varName [appendArgs [getLookupVarNamePrefix] saved_package_unknown] - set oldHandler [expr {[info exists $varName] ? [set $varName] : ""}] - - if {[string length $oldHandler] > 0} then { - lappend oldHandler $package $version; uplevel #0 $oldHandler - } - } - - # - # NOTE: This procedure is the [package unknown] handler entry point called - # by native Tcl and Eagle. The package argument is the name of the - # package being sought, it cannot be an empty string. The version - # argument must be a specific version -OR- a package specification - # that conforms to TIP #268. This version argument must be optional - # here, because Eagle does not add a version argument when one is - # not explicitly supplied to the [package require] sub-command. - # - proc packageUnknownHandler { package {version ""} } { - variable verboseUnknownResult - - # - # NOTE: First, run the saved [package unknown] handler. - # - set code(1) [catch { - runSavedPackageUnknownHandler $package $version - } result(1)] - - if {$verboseUnknownResult} then { - pkgLog [appendArgs \ - "initial saved handler results for package \"" \ - [formatPackageName $package $version] "\" are " \ - [formatResult $code(1) $result(1)]] - } - - # - # NOTE: Did the saved [package unknown] handler succeed? - # - if {$code(1) == 0} then { - # - # NOTE: Is the package now available -OR- somehow already present? - # - if {[isPackagePresent $package $version] || \ - [isPackageAvailable $package $version]} then { - # - # NOTE: Skip using the package repository. - # - return - } - } - - # - # NOTE: Next, run our special [package unknown] handler. - # - if {[canDownloadPackage $package]} then { - set code(2) [catch { - getPackageFromRepository $package $version handler - } result(2)] - - if {$verboseUnknownResult} then { - pkgLog [appendArgs \ - "repository handler results for package \"" \ - [formatPackageName $package $version] "\" are " \ - [formatResult $code(2) $result(2)]] - } - } - - # - # NOTE: Next, run the saved [package unknown] handler. - # - set code(3) [catch { - runSavedPackageUnknownHandler $package $version - } result(3)] - - if {$verboseUnknownResult} then { - pkgLog [appendArgs \ - "subsequent saved handler results for package \"" \ - [formatPackageName $package $version] "\" are " \ - [formatResult $code(3) $result(3)]] - } - - # - # NOTE: Maybe check for the package and then optionally log results. - # - if {$verboseUnknownResult} then { - set ifNeededVersion [getIfNeededVersion \ - $package [packageRequirementToVersion $version]] - - if {[string length $ifNeededVersion] > 0} then { - set command [list package ifneeded $package $ifNeededVersion] - - if {[set code(4) [catch $command result(4)]] == 0 && \ - [string length $result(4)] > 0} then { - pkgLog [appendArgs \ - "package script for \"" [formatPackageName $package \ - $ifNeededVersion] "\" was added: " [formatResult \ - $code(4) $result(4)]] - } else { - pkgLog [appendArgs \ - "package script for \"" [formatPackageName $package \ - $ifNeededVersion] "\" was not added: " [formatResult \ - $code(4) $result(4)]] - } - } else { - pkgLog [appendArgs \ - "package script for \"" [formatPackageName $package \ - $ifNeededVersion] "\" was not added"] - } - - # - # NOTE: Check (and log) if the package is now present. The return - # value here is ignored. - # - isPackagePresent $package $version - } - } - - # - # NOTE: This procedure evaluates the package repository client settings - # script file, if it exists. Any script errors raised are not - # masked. The script argument must be the fully qualified path - # and file name for the primary package repository client script - # file. - # - # - proc maybeReadSettingsFile { script } { - global tcl_platform - - if {[string length $script] == 0 || \ - ![file exists $script] || ![file isfile $script]} then { - return - } - - foreach prefix [list $tcl_platform(user) ""] { - if {[string length $prefix] > 0} then { - set prefix [appendArgs . $prefix] - } - - set fileName [appendArgs \ - [file rootname $script] .settings $prefix [file extension \ - $script]] - - if {[file exists $fileName] && [file isfile $fileName]} then { - uplevel 1 [list source $fileName] - } - } - } - - # - # NOTE: This procedure sets up the default values for all configuration - # parameters used by the package repository client. There are no - # arguments. - # - proc setupPackageUnknownVars {} { - # - # NOTE: Should the HTTP request processor attempt to force the use of - # HTTPS for URIs that were originally HTTP? This setting is only - # applicable to native Tcl. - # - variable forceSecureUri; # DEFAULT: true - - if {![info exists forceSecureUri]} then { - set forceSecureUri true - } - - # - # NOTE: Is this HTTP request processor allowed to use plain HTTP if/when - # the "tls" package is not available? This should only be changed - # if the "tls" package cannot be easily installed for use with the - # native Tcl interpreter in use. It should be noted here that the - # official package repository server reserves the right to refuse - # plain HTTP connections, which means that changing this setting - # may be totally pointless. - # - variable allowInsecureUri; # DEFAULT: false - - if {![info exists allowInsecureUri]} then { - set allowInsecureUri false - } - - # - # NOTE: Emit diagnostic messages when the [::http::geturl] procedure is - # about to be called? - # - variable verboseGetUrl; # DEFAULT: false - - if {![info exists verboseGetUrl]} then { - set verboseGetUrl false - } - - # - # NOTE: Is this HTTP request processor allowed to use plain HTTP if/when - # the server responds with an HTTP redirect location to an original - # URI that was HTTPS? Otherwise, a script error will result. - # - variable allowInsecureRedirect; # DEFAULT: false - - if {![info exists allowInsecureRedirect]} then { - set allowInsecureRedirect false - } - - # - # NOTE: What is the default set of API keys if none were set explicitly? - # This list is subject to change at any time -AND- may be empty or - # may contain non-working API keys, please do not rely on it. - # - variable autoApiKeys; # DEFAULT: 0000000000000000000000000000000000000000 - - if {![info exists autoApiKeys]} then { - set autoApiKeys [list 0000000000000000000000000000000000000000] - } - - # - # NOTE: Automatically install our [package unknown] handler when this - # package is loaded? - # - variable autoHook; # DEFAULT: true - - if {![info exists autoHook]} then { - set autoHook true - } - - # - # NOTE: Automatically [tcl load] when this package is loaded from the - # Eagle language? - # - variable autoLoadTcl; # DEFAULT: - - if {![info exists autoLoadTcl]} then { - # - # TODO: Better automatic detection of native Tcl installs here? - # - if {[isEagle] && \ - [catch {tcl select -architecture}] == 0} then { - set autoLoadTcl true - } else { - set autoLoadTcl false - } - } - - # - # NOTE: Automatically [package require Garuda] when this package is - # loaded from the Tcl language? - # - variable autoRequireGaruda; # DEFAULT: - - if {![info exists autoRequireGaruda]} then { - # - # TODO: Better automatic detection of Garuda here? - # - if {![isEagle] && \ - [llength [package versions Garuda]] > 0} then { - set autoRequireGaruda true - } else { - set autoRequireGaruda false - } - } - - # - # NOTE: The command to use when verifying OpenPGP signatures for the - # downloaded package scripts. - # - variable openPgpCommand; # DEFAULT: gpg2 --verify {${fileName}} - - if {![info exists openPgpCommand]} then { - set openPgpCommand {gpg2 --verify {${fileName}}} - } - - # - # NOTE: Verify that the package script matches the current language - # when called from the [package unknown] handler? - # - variable strictUnknownLanguage; # DEFAULT: true - - if {![info exists strictUnknownLanguage]} then { - set strictUnknownLanguage true - } - - # - # NOTE: Emit diagnostic messages when a [package unknown] handler - # is called? - # - variable verboseUnknownResult; # DEFAULT: false - - if {![info exists verboseUnknownResult]} then { - set verboseUnknownResult false - } - - # - # NOTE: Emit diagnostic messages when a URI is fetched? - # - variable verboseUriDownload; # DEFAULT: false - - if {![info exists verboseUriDownload]} then { - set verboseUriDownload false - } - } - - # - # NOTE: This procedure is the primary entry point to the package repository - # client. It attempts to lookup the specified package using the - # currently configured package repository server. The package - # argument is the name of the package being sought, it cannot be an - # empty string. The version argument must be a specific version -OR- - # a package specification that conforms to TIP #268. The caller - # argument must be an empty string -OR- the literal string "handler". - # - # - proc getPackageFromRepository { package version caller } { - # - # NOTE: Get the list of API keys and try each one, in order, until - # the package is found. - # - set apiKeys [getApiKeys] - - # - # NOTE: Issue the non-anonymous lookup request to the remote - # package repository. - # - set data [getLookupData $apiKeys $package $version] - - # - # NOTE: Attempt to grab the lookup code from the non-anonymous - # response data. - # - set code [getLookupCodeFromData $data] - - # - # NOTE: If necessary, fallback with to an anonymous request. - # - if {![isLookupCodeOk $code]} then { - # - # NOTE: Issue the anonymous lookup request to the remote - # package repository. - # - set data [getLookupData [list] $package $version] - - # - # NOTE: Attempt to grab the lookup code from the anonymous - # response data. - # - set code [getLookupCodeFromData $data] - } - - # - # NOTE: Attempt to grab the lookup data from the response data. - # Upon failure, this should contain the error message. - # - set result [getLookupResultFromData $data] - - # - # NOTE: Did the lookup operation fail? - # - if {![isLookupCodeOk $code]} then { - # - # NOTE: Is there an error message? - # - if {[string length $result] > 0} then { - # - # NOTE: Yes. Use the returned error message verbatim. - # - error $result - } else { - # - # NOTE: No. Use the whole response data string as the error - # message. - # - error $data - } - } - - # - # NOTE: Process the lookup data into the pieces of metadata that we - # need to load the requested package. - # - extractAndVerifyLookupMetadata $result metadata $caller - - # - # NOTE: Attempt to load the requested package using the metadata - # extracted in the previous step. - # - processLookupMetadata metadata - } - - if {![isEagle]} then { - ########################################################################### - ############################# BEGIN Tcl ONLY ############################## - ########################################################################### - - # - # NOTE: This procedure was stolen from the "getEagle.tcl" script. It is - # designed to emit a message to the console. The channel argument - # is the channel where the message should be written. The string - # argument is the content of the message to emit. - # - proc pageOut { channel string } { - catch { - puts -nonewline $channel $string; flush $channel - } - } - - # - # NOTE: This procedure was stolen from the "getEagle.tcl" script. It is - # designed to emit a message to the HTTP client log. The string - # argument is the content of the message to emit. - # - proc pageLog { string } { - catch { - tclLog [appendArgs [pid] " : " [clock seconds] " : http : " $string] - } - } - - # - # NOTE: This procedure was stolen from the "getEagle.tcl" script. It is - # designed to emit a progress indicator while an HTTP request is - # being processed. The channel argument is the Tcl channel where - # the progress indicator should be emitted. The type argument is - # the single-character progress indicator. The milliseconds - # argument is the number of milliseconds to wait until the next - # periodic progress indicator should be emitted. This procedure - # reschedules its own execution. - # - proc pageProgress { channel type milliseconds } { - # - # NOTE: This variable is used to keep track of the currently scheduled - # (i.e. pending) [after] event. - # - variable afterForPageProgress - - # - # NOTE: Show that something is happening... - # - pageOut $channel $type - - # - # NOTE: Make sure that we are scheduled to run again, if requested. - # - if {$milliseconds > 0} then { - set afterForPageProgress [after $milliseconds \ - [namespace code [list pageProgress $channel $type \ - $milliseconds]]] - } else { - unset -nocomplain afterForPageProgress - } - } - - # - # NOTE: This procedure was stolen from the "getEagle.tcl" script. It is - # designed to process a single HTTP request, including any HTTP - # 3XX redirects (up to the specified limit), and return the raw - # HTTP response data. It may raise any number of script errors. - # - # - proc getFileViaHttp { uri redirectLimit channel quiet args } { - # - # NOTE: This variable is used to determine if plain HTTP URIs should be - # converted to HTTPS, if the "tls" package is available. - # - variable forceSecureUri - - # - # NOTE: This variable is used to determine if plain HTTP is allowed if - # the "tls" package is not available. - # - variable allowInsecureUri - - # - # NOTE: This variable is used to determine if a diagnostic message is - # emitted when [::http::geturl] is about to be called. - # - variable verboseGetUrl - - # - # NOTE: This variable is used to determine if plain HTTP is allowed if - # an HTTP redirect response contains an HTTP URI and the original - # URI was HTTPS. - # - variable allowInsecureRedirect - - # - # NOTE: This variable is used to keep track of the currently scheduled - # (i.e. pending) [after] event. - # - variable afterForPageProgress - - # - # NOTE: This procedure requires the modern version of the HTTP package, - # which is typically included with the Tcl core distribution. - # - package require http 2.0 - - # - # NOTE: If the 'tls' package is available, always attempt to use HTTPS; - # otherwise, only attempt to use HTTP if explicitly allowed. - # - if {[catch {package require tls}] == 0} then { - ::http::register https 443 [list ::tls::socket -tls1 true] - - if {$forceSecureUri} then { - if {[string range $uri 0 6] eq "http://"} then { - set uri [appendArgs https:// [string range $uri 7 end]] - } - } - } else { - if {$allowInsecureUri} then { - if {[string range $uri 0 7] eq "https://"} then { - set uri [appendArgs http:// [string range $uri 8 end]] - } - } - } - - # - # NOTE: Unless the caller forbids it, display progress messages during - # the download. - # - if {!$quiet} then { - pageProgress $channel . 250 - } - - # - # NOTE: All downloads are handled synchronously, which is not ideal; - # however, it is simple. Keep going as long as there are less - # than X redirects. - # - set redirectCount 0 - - while {1} { - # - # NOTE: Issue the HTTP request now, grabbing the resulting token. - # - if {$verboseGetUrl} then { - # - # NOTE: Emit important diagnostic information related to this - # HTTP request here. This may be enhanced in the future. - # - pageLog [appendArgs \ - "attempting to download URL \"" $uri \"...] - } - - set token [eval [list ::http::geturl $uri] $args] - - # - # NOTE: Grab the HTTP response code and data now as they are needed - # in almost all cases. - # - set code [::http::ncode $token]; set data [::http::data $token] - - # - # NOTE: Check the HTTP response code, in order to follow any HTTP - # redirect responses. - # - switch -glob -- $code { - 100 - - 101 - - 102 { - ::http::cleanup $token; error [appendArgs \ - "unsupported informational HTTP response status code " \ - $code ", data: " $data] - } - 200 - - 201 - - 202 - - 203 - - 204 - - 205 - - 206 - - 207 - - 208 - - 226 { - # - # NOTE: Ok, the HTTP response is actual data of some kind (which - # may be empty). - # - ::http::cleanup $token; break - } - 301 - - 302 - - 303 - - 307 - - 308 { - # - # NOTE: Unless the caller forbids it, display progress messages - # when an HTTP redirect is returned. - # - if {!$quiet} then { - pageProgress $channel > 0 - } - - # - # NOTE: We hit another HTTP redirect. Stop if there are more - # than X. - # - incr redirectCount - - # - # TODO: Maybe make this limit more configurable? - # - if {$redirectCount > $redirectLimit} then { - # - # NOTE: Just "give up" and raise a script error. - # - ::http::cleanup $token; error [appendArgs \ - "redirection limit of " $redirectLimit " exceeded"] - } - - # - # NOTE: Grab the metadata associated with this HTTP response. - # - array set meta [::http::meta $token] - - # - # NOTE: Is there actually a new URI (location) to use? - # - if {[info exist meta(Location)]} then { - # - # NOTE: Ok, grab it now. Later, at the top of the loop, - # it will be used in the subsequent HTTP request. - # - set location $meta(Location); unset meta - - # - # NOTE: For security, by default, do NOT follow an HTTP - # redirect if it attempts to redirect from HTTPS - # to HTTP. - # - if {!$allowInsecureRedirect && \ - [string range $uri 0 7] eq "https://" && \ - [string range $location 0 7] ne "https://"} then { - # - # NOTE: Just "give up" and raise a script error. - # - ::http::cleanup $token; error [appendArgs \ - "refused insecure redirect from \"" $uri "\" to \"" \ - $location \"] - } - - # - # NOTE: Replace the original URI with the new one, for - # use in the next HTTP request. - # - set uri $location - - # - # NOTE: Cleanup the current HTTP token now beause a new - # one will be created for the next request. - # - ::http::cleanup $token - } else { - # - # NOTE: Just "give up" and raise a script error. - # - ::http::cleanup $token; error [appendArgs \ - "redirect from \"" $uri "\" missing location, code " \ - $code ", data: " $data] - } - } - 300 - - 304 - - 305 - - 306 { - ::http::cleanup $token; error [appendArgs \ - "unsupported redirection HTTP response status code " $code \ - ", data: " $data] - } - 4?? { - ::http::cleanup $token; error [appendArgs \ - "client error HTTP response status code " $code ", data: " \ - $data] - } - 5?? { - ::http::cleanup $token; error [appendArgs \ - "server error HTTP response status code " $code ", data: " \ - $data] - } - default { - ::http::cleanup $token; error [appendArgs \ - "unrecognized HTTP response status code " $code ", data: " \ - $data] - } - } - } - - # - # NOTE: If there is a currently scheduled [after] event, cancel it. - # - if {[info exists afterForPageProgress]} then { - catch {after cancel $afterForPageProgress} - unset -nocomplain afterForPageProgress - } - - # - # NOTE: If progress messages were emitted, start a fresh line. - # - if {!$quiet} then { - pageOut $channel [appendArgs " " $uri \n] - } - - return $data - } - - ########################################################################### - ############################## END Tcl ONLY ############################### - ########################################################################### - } - - # - # NOTE: This package requires that support for namespaces, which is an - # optional feature of Eagle, must be enabled. - # - if {[isEagle] && ![namespace enable]} then { - error "namespaces must be enabled for this package" - } - - # - # NOTE: Attempt to read optional settings file now. This may override - # one or more of the variable setup in the next step. - # - maybeReadSettingsFile [info script] - - # - # NOTE: Setup the variables, within this namespace, used by this script. - # - setupPackageUnknownVars - - # - # NOTE: Setup for our [package unknown] handler, which may involve a few - # different operations. - # - setupPackageUnknownHandler - - # - # NOTE: Provide the package to the interpreter. - # - package provide Eagle.Package.Repository \ - [expr {[isEagle] ? [info engine PatchLevel] : "1.0"}] -} - DELETED client/1.0/pkgr.eagle.asc Index: client/1.0/pkgr.eagle.asc ================================================================== --- client/1.0/pkgr.eagle.asc +++ client/1.0/pkgr.eagle.asc @@ -1,18 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v2 -Comment: Eagle Package Repository - -iQIcBAABCAAGBQJYD+PZAAoJEFAslq9JXcLZclAP/i7g22I9YZRHfNP+q/UyrIL8 -F+gPmRy2X1mP9QZQX+N0WStBoepR/jsfPI///8dRhljIqWf8QxXy+d/zi9sCIIOB -x4sY/b2c5s7Ao8EhtqUSnwkkDUCk12Ofw88JmRNPxtvUtDR5rd82rRfBr0kI+LGx -IN6c0Wtx4BpxYOhRD1NtSBExyCUMmW16x8CJ6naIlkkl2xxOTdf/HblnLSIfAszM -y73JtbAV0danPvHTZ65QZli0P9ZzZNJ7eBOH4X9vuX3d9+TO7cerlyaCVZgIu3V6 -6l95Fh7OLfLiDXei0mLCLh7nQZyvRb0Ude1uN//Isk78vBKYaOYZZ9Hu5oROx4BL -LCSHEH9dOBpdK3hzYSOeYUoYmV3lwkfHYyVBTAxLUHNXyCpDm9nvBIdURwnHEPv5 -+uyP3YAqxpllJHB6/lPUe85SZMTcAyZBksOlDmM2IHF1OVMbLBK8rB1MI1yGYMHB -dswyovXsn5jBjmBMK5eBkbvvpU20Sc8f6qxW0LfQtXyh7cQSWjoBBU++Yax63tW1 -E3j8PQ5G/E3f/6hIxJHjeChg/I4XUgqr5jPynsOHFXZQVnBp45hpjfuu/y5WvKdX -4fZlqN0JdDsEMXhk/5gr9Rtr0/nZpNZfzQznaT98rw8QiH2VsH9YCPrMfO9bWhsV -z+K95Tyspz0QwRKpb1+C -=LAEu ------END PGP SIGNATURE----- DELETED client/1.0/pkgr.eagle.harpy Index: client/1.0/pkgr.eagle.harpy ================================================================== --- client/1.0/pkgr.eagle.harpy +++ client/1.0/pkgr.eagle.harpy @@ -1,68 +0,0 @@ - - - - None - Mistachkin Systems - c8c90246-6344-4855-ab6d-1fcfa00eae47 - SHA512 - Script - 2016-10-25T22:59:06.8710469Z - -1.00:00:00 - 0x9559f6017247e3e2 - - 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 - - DELETED client/1.0/pkgr.eagle.harpy.asc Index: client/1.0/pkgr.eagle.harpy.asc ================================================================== --- client/1.0/pkgr.eagle.harpy.asc +++ client/1.0/pkgr.eagle.harpy.asc @@ -1,18 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v2 -Comment: Eagle Package Repository - -iQIcBAABCAAGBQJYD+PbAAoJEFAslq9JXcLZpp8P/A6nC2lb6osifnBNVvQE0/2H -swK6JhVNbSfLRxVTBJP+SYd6htKkXu74/41JMeXe4fqnyxHEeFnYHp+BWplseoMg -O1ZhpeOYlfCVakGqA6Pc0MVrVIy85/Z8CR/06UvGdAwUA91s8UFpHa/LjjfDXTDb -eMZe2WVBG+UzsI4nKsXt9MWnPjMGTHWHU9zs67idO12BFZ2Z37O4H42mzzvdMVWu -X0SbqAEozavvRI5M6WR/Gxfg+hYH+nacEL7pfW0/lOGj6eqQe7YPTQhCdjzIKjFu -kNHPalXOjODe0z1yqu5bI7RNhglVCK/lblvziDVlCSaUIkqNJCuPXsx4PAfH3yoq -uENO8v675hG+HBMBKQxBBHleNQk4X1KCvVgLrOQsPNq3usJoZIgwUP6DeESLaJn6 -PD/JnsnC/KCgiAjF27PY8kX3HWAQD9Gpe7PIlgxO8wYYK0hhlcm4zyMZD+Oet1VZ -g/qEjmQ4ulJcOWrDPPMJD4Tvq36ryAtpMHWJR2cI+WQ7r9qtmCQRN7DBDHfgi2Sr -1ccqMOI6SdXCrUlFi9SEDHZg6UnA0xbXBo/ZnXhQXq1NyQR3SpD/2/bZB51OJUaY -sseXOErRPd8XN5Px4xsto4tbzMByXQnAniLv6cX90oO5naZNhmA2NSgsfSGTZgqr -etZXrF2EBBnDuaZ3uCgR -=BVw9 ------END PGP SIGNATURE----- DELETED client/1.0/pkgr.settings.mistachkin.eagle Index: client/1.0/pkgr.settings.mistachkin.eagle ================================================================== --- client/1.0/pkgr.settings.mistachkin.eagle +++ client/1.0/pkgr.settings.mistachkin.eagle @@ -1,23 +0,0 @@ -############################################################################### -# -# pkgr.settings.mistachkin.eagle -- -# -# Extensible Adaptable Generalized Logic Engine (Eagle) -# Package Repository Client Settings -# -# Copyright (c) 2007-2012 by Joe Mistachkin. All rights reserved. -# -# See the file "license.terms" for information on usage and redistribution of -# this file, and for a DISCLAIMER OF ALL WARRANTIES. -# -# RCS: @(#) $Id: $ -# -############################################################################### - -# TODO: Set this to your list of API keys. -# set ::pkgr_api_keys [list 0000000000000000000000000000000000000000] - -variable strictUnknownLanguage false -variable verboseGetUrl true -variable verboseUnknownResult true -variable verboseUriDownload true DELETED client/1.0/pkgr.settings.mistachkin.eagle.asc Index: client/1.0/pkgr.settings.mistachkin.eagle.asc ================================================================== --- client/1.0/pkgr.settings.mistachkin.eagle.asc +++ client/1.0/pkgr.settings.mistachkin.eagle.asc @@ -1,18 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v2 -Comment: Eagle Package Repository - -iQIcBAABCAAGBQJYBVUUAAoJEFAslq9JXcLZZeEP/1OIZqUc2pS7lcN4FutRuqh4 -3uB13RzJvjBNU/urSxqfuM9oJWl3GXndP/bmLJ2Qo8wXndBbpZR+YOAB3uiPYqHu -0UqauAWjKwvF0u3RqYBIU2oMYB5mxnh4Yvo9f7T3rC0cAjPmbrgpH7wYlCiml1k7 -UmoVIbN+V3LQV3mkfkv1aXFOWBrSVoz1bq8ngfBcup5R5+kGe+mqZkYMtDQQwKze -wgJdCd1hOQEMdaZlMXmD9lf8uXRC1lBYc8eJyqZsmAxwONoA67NMjazyRydhu4kE -Dx/ObuNYr8kiREjXkPLd65LKbMyFSqc/2GzJylB1T1jjuvcXbH+GYlf4rvfJhN1o -mt8LSdx9Blqxzu5X52KQFCOYH60zO84oX087IPxxPnrdzy688Pzd2Glfmit1NhOr -L6TmwtAh4Y4Lc+ohSkvz5zpKD50N0VN272vWsZCZ2TfIvk7zn0Xa6X1UAOyWhuTc -cFZnGuo7v5XvLxUp5A1EGmGg0JBoJbOgsrXFtD6jEWS61H5SEvMqlPlfctNnoKli -B+3jtV6wAO6Qpc25j1XztbJu73m/fHn9KHNW/ZmVcwG9BVqUSk5qUzsKkIfGnpS2 -ekbycPUDL8UZ2IiqxPKsoRQ2RYPOQt7NI1psTi8j3BwYq3ppIhDMuOfU49LPNK1J -ir9Lzx5tFwbA0azEOxT5 -=78ho ------END PGP SIGNATURE----- DELETED client/1.0/pkgr.settings.mistachkin.eagle.harpy Index: client/1.0/pkgr.settings.mistachkin.eagle.harpy ================================================================== --- client/1.0/pkgr.settings.mistachkin.eagle.harpy +++ client/1.0/pkgr.settings.mistachkin.eagle.harpy @@ -1,68 +0,0 @@ - - - - None - Mistachkin Systems - 2585a4fc-8467-4d93-99d6-11c5afbcb752 - SHA512 - Script - 2016-10-17T22:47:03.9483672Z - -1.00:00:00 - 0x9559f6017247e3e2 - - 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 - - DELETED client/1.0/pkgr.settings.mistachkin.eagle.harpy.asc Index: client/1.0/pkgr.settings.mistachkin.eagle.harpy.asc ================================================================== --- client/1.0/pkgr.settings.mistachkin.eagle.harpy.asc +++ client/1.0/pkgr.settings.mistachkin.eagle.harpy.asc @@ -1,18 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v2 -Comment: Eagle Package Repository - -iQIcBAABCAAGBQJYBVUVAAoJEFAslq9JXcLZfIkQAJqfAprPlgwMVMU0V2toQ8jp -DCRcfvIus9pFpEOOpVEdOiesT4BxWPhTONWnXqfx+xVu4uXtRaUEhRZsdIcHZdC1 -mLjd6eTbrPBh56/5DGEXI8elSEa67OHICaE4bhYqSGKFoJnETBwsI3WrLV6xbSwh -eKI1OLt1bao+hpaztfVMi3MU2UVfJBgCjdmvlol+rNHBJ0UJuTY/v+cDA59D3KoD -uw5iQrjyAMNrKVlJBMWWkO2nfSH786gf7bLFHzH989n2B41mA74TjqjaqdHeJYLL -+iq/bl8VkyTK6Cr2GObpsxG5+RKCTYt5slnwhi5NGZT2J96iR2ahVkLkRgSfKwqs -bEJqyIXqKPAVJzP3hPv6ntg9eMjUU6svjvlU8LmlBE0xdDrd6WKO9UQ2Zi4rE3Q/ -yn1M3gSMMVdfHEwTvaeoVYUJ51iFKJaj8Ug0EMSyBYX+9T2QKQGuU5EXOoBhR9XY -xKoMUBwcS18wHSDyTLaN7+BaZDr06VHaZoewKtyFvoiRCKkI0bgWeOq2oW67wipA -HWHLXo/GZlOgB33XW+ZFiDhcXGtlb6xVs48Gt4TuXYDdGcNQu4aaF2SOvxzoHv0G -kF0DpQQd2o/nJS6zFAYdcg0v7GeVsqXDmlW9vfSArfj50frfDVSNcB6e4aXBLicX -m2OtTsrvB7gjJ9yKJJag -=UFjj ------END PGP SIGNATURE----- DELETED client/1.0/pkgr_install.eagle Index: client/1.0/pkgr_install.eagle ================================================================== --- client/1.0/pkgr_install.eagle +++ client/1.0/pkgr_install.eagle @@ -1,206 +0,0 @@ -############################################################################### -# -# pkgr_install.eagle -- -# -# Extensible Adaptable Generalized Logic Engine (Eagle) -# Package Repository Client (Package Installer) -# -# Copyright (c) 2007-2012 by Joe Mistachkin. All rights reserved. -# -# See the file "license.terms" for information on usage and redistribution of -# this file, and for a DISCLAIMER OF ALL WARRANTIES. -# -# RCS: @(#) $Id: $ -# -############################################################################### - -# -# NOTE: Use our own namespace here because even though we do not directly -# support namespaces ourselves, we do not want to pollute the global -# namespace if this script actually ends up being evaluated in Tcl. -# -namespace eval ::PackageInstaller { - # - # NOTE: This procedure is used to report errors that prevent this tool - # from running to completion (e.g. invalid command line arguments, - # etc). It may be used to report a specifically error. It will - # always emits the command line option and argument information. - # - proc usage { {error ""} } { - if {[string length $error] > 0} then {puts stdout $error} - - puts stdout "usage:\ - [file tail [info nameofexecutable]]\ - [file tail [info script]] \[version\] \[language\]" - - exit 1 - } - - # - # NOTE: Figure out the fully qualified path to the current script file. - # If necessary, add it to the auto-path for the interpreter. The - # necessary supporting packages (i.e. the Package Repository and - # Package Downloader packages) are assumed to exist in the same - # directory as the current script file. - # - variable pkgr_path; # DEFAULT: - - if {![info exists pkgr_path]} then { - set pkgr_path [file normalize [file dirname [info script]]] - - if {![info exists ::auto_path] || \ - [lsearch -exact $::auto_path $pkgr_path] == -1} then { - lappend ::auto_path $pkgr_path - } - } - - # - # NOTE: *TODO* Pre-create the namespace for the Package Repository Client - # package and then forcibly adjust various settings to the values - # necessary for this tool. In the future, this section may need to - # be tweaked to account for changes to the Package Repository Client - # package. - # - namespace eval ::PackageRepository { - variable autoHook true - variable autoLoadTcl false - variable autoRequireGaruda false - variable verboseUnknownResult true - variable verboseUriDownload true - } - - # - # NOTE: *TODO* Pre-create the namespace for the Package Downloader Client - # package and then forcibly adjust various settings to the values - # necessary for this tool. In the future, this section may need to - # be tweaked to account for changes to the Package Downloader Client - # package. Technically, the package being handled by this tool may - # not actually use the downloader; however, if it does, this should - # make sure the downloaded package files are persisted locally. - # - namespace eval ::PackageDownloader { - variable quiet false - variable viaInstall true - } - - # - # NOTE: Load the Package Repository Client package now. This will install - # the [package unknown] hook and prepare it for use. - # - package require Eagle.Package.Repository - - # - # NOTE: Verify that the number of command line arguments meets the basic - # requirements of this tool. - # - if {[info exists ::argv] && \ - [llength $::argv] >= 2 && [llength $::argv] <= 4} then { - # - # NOTE: Get the API key. This is always required. If this API key is - # not valid or cannot be found by the server, execution of this - # tool will fail. - # - set apiKey [lindex $::argv 0] - - # - # NOTE: Get the package name. This is always required. If this package - # name is invalid or cannot be found by the server, execution of - # this tool will fail. - # - set package [lindex $::argv 1] - - # - # NOTE: Grab the package version (or requirement?). This is optional. - # If this package version is specified, it must conform with TIP - # #268 when the target language is native Tcl. For Eagle, only - # the dotted decimal version syntax, with between 2 to 4 numbers, - # is supported. - # - if {[llength $::argv] >= 3} then { - set version [lindex $::argv 2] - - if {[isEagle] && ![string is version -strict $version]} then { - set pattern {^\d+\.\d+\.\d+\.\d+$} - - error [appendArgs \ - "version must match regular expression: " $pattern] - } - } else { - set version "" - } - - # - # NOTE: Grab the target language. This is optional. Without this, it - # is assumed that the target language is the one evaluating the - # current script file. The only supported target languages are - # native Tcl ("Tcl") and Eagle ("Eagle"), both case-sensitive. - # If the target language differs from the current language, this - # tool will attempt to gain access to the target language and a - # script error will be raised if that attempt fails. - # - if {[llength $::argv] >= 4} then { - set language [lindex $::argv 3] - } else { - set language "" - } - - # - # NOTE: If the target language was specified, attempt to gain access to - # it, if necessary. If the current language matches the target - # language, nothing is done. - # - if {[string length $language] > 0} then { - switch -exact -- $language { - Eagle { - if {![isEagle]} then { - ::PackageRepository::makeEagleReady - } - } - Tcl { - if {[isEagle]} then { - ::PackageRepository::makeTclReady - } - } - default { - error "unsupported language: must be Tcl or Eagle" - } - } - } - - # - # NOTE: If a non-empty API key was specified on the command line then - # add it to the global list now. - # - if {[string length $apiKey] > 0} then { - lappend ::pkgr_api_keys $apiKey - } - - # - # NOTE: For Eagle, make sure that the [package unknown] handler will be - # used for the current interpreter. - # - if {[isEagle]} then { - object invoke -flags +NonPublic Interpreter.GetActive InterpreterFlags \ - [appendArgs [object invoke -flags +NonPublic Interpreter.GetActive \ - InterpreterFlags] " -NoPackageUnknown"] - } - - # - # NOTE: Attempt to require the target package now. If this succeeds - # -AND- the Package Downloader Client was used, the package will - # be persisted locally; otherwise, the [package ifneeded] script - # may still be evaluated; however, the effects may not actually - # cause anything to persist. - # - if {[string length $version] > 0} then { - set result [package require $package $version] - } else { - set result [package require $package] - } - - puts stdout [appendArgs "package require result: " $result] - } else { - usage - } -} - DELETED client/1.0/pkgr_install.eagle.asc Index: client/1.0/pkgr_install.eagle.asc ================================================================== --- client/1.0/pkgr_install.eagle.asc +++ client/1.0/pkgr_install.eagle.asc @@ -1,18 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v2 -Comment: Eagle Package Repository - -iQIcBAABCAAGBQJX1JI+AAoJEFAslq9JXcLZfiQQAMjinGkIW+7Cj4cbXztobxW/ -VNs3jN3vuI/c7F37s2NHa1B9JhnoSz4oDT9goEkpouzSpiEbpwKSKmivEpKjadIE -jTNgqt0KmNVEAv6FTGzomyPw319dZMSUZZj1btI8QpuV+5ntssRd/EzcgRsp/qOj -mzlZRPBIRUj5Jom6U495D3gelUBTZocN+zMCr2IKTDtyzOoxg4f3mMva6bjCmh6X -suC7wIiXqAfUhKA96o3QJ2yiJEAXAho2yi/lcoQYdNrKXsdWoEQvcXeqpkOMvVeV -yYxuG5JRX5z+/fZXKijFDffHKiuzPiM9ho+np2nJBgsaIl9t7a7+XGvMdAJbKCO8 -eW2dXJr/FkoElU3p/woBmy0uCEGS8Ku9GNuyXeQmvayo68pCcQJ4JaHrYEfqi5km -i83Pmn6t5z/rVLT95ZPq7AiL1J50yYJg0ofWR8w/oBHOpwoNiPtZzTdpZwoNWmoj -crfd7CDbWTzhf8nGyE6YGtFdtqF1nUXYW+FACTPv3DlI51bgygFvGMX+u2w7ueuV -NfrV9GTgUswkZEMBzl/rQwrDyz09wLkXIw7eze8Zydc35zekwQ2EljjArMH+V2I5 -fd1inJH5rXcMjxd2nhjAyHu8KDx8uWqRwrp7i+iG2ZOHm9ICmrqm60Q0l5z6vrbP -7BD2bn8+QfF/kvn+JuoU -=LBzM ------END PGP SIGNATURE----- DELETED client/1.0/pkgr_install.eagle.harpy Index: client/1.0/pkgr_install.eagle.harpy ================================================================== --- client/1.0/pkgr_install.eagle.harpy +++ client/1.0/pkgr_install.eagle.harpy @@ -1,68 +0,0 @@ - - - - None - Mistachkin Systems - 1a70ab30-3266-4e44-8b1e-f176343462bf - SHA512 - Script - 2016-09-10T22:53:48.6018672Z - -1.00:00:00 - 0x9559f6017247e3e2 - - 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 - - DELETED client/1.0/pkgr_install.eagle.harpy.asc Index: client/1.0/pkgr_install.eagle.harpy.asc ================================================================== --- client/1.0/pkgr_install.eagle.harpy.asc +++ client/1.0/pkgr_install.eagle.harpy.asc @@ -1,18 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v2 -Comment: Eagle Package Repository - -iQIcBAABCAAGBQJX1JJAAAoJEFAslq9JXcLZp80P/R4hkhprINlRKSyQrfff/Rpw -mHGCzhRqPBox1zyosrjq4l+3bNLQiZLrPQlRMbcXB1RJBNrBTNjeaDsG9bG7DfSa -R99Iz2BVMj/1E1bwawO8C4XlaFYhlOduMKbEg6NysGEjH+nG6wJ5AdoHZ5hfYlJ6 -BD8joxs2CW16rkJEyXKMOfj2lSDm3DBnv/U5VpcdJYRuUxJ13IDpNeMRq44yYpnL -sd9+1QJV21I9CR7isd+PCL9Tc0LjcdkfuLEaAek7anzwcVJVfvNWNoE4VuWi4d63 -SfcrgFqg/+SHcgJcUZSy4ODNIu+nX7Ef3eVKHMFT73suo2jinYYAyTdSmUbX1/QZ -CABIbAsOX7YRvT6qCi2tcG5y2wFm9xsTPg0sgsm2BDHvYaZwyVk95qcotfyGqcRB -v06SjbSLqgOdsM6bqE4gJKcfuwtBJf/iEeQUYFZ2lIH2IKLVjtGJJSVS1xnED4i6 -tRp0nWK87lzAHP0bef3ZmRWw4GAfVZYvw8iYs2giWoGxSyM22zUHAP3tz4Sz23lq -wIq171291MF2S3hYs0KCpFzUivMtmA2fVK0bhJHt29cra7v8L+CnGq+qW9Pp6R9h -/bvic2MifHo0DhdzOMHxvjqAnWzryC8nE31YJfEjRGc3RVnv16htxbV+lF6LgR5u -0oXbqCvBS4+E2Eqc4sSK -=Pn6m ------END PGP SIGNATURE----- DELETED eagle/1.0/data1.0/data.eagle Index: eagle/1.0/data1.0/data.eagle ================================================================== --- eagle/1.0/data1.0/data.eagle +++ eagle/1.0/data1.0/data.eagle @@ -1,1139 +0,0 @@ -############################################################################### -# -# data.eagle -- -# -# Extensible Adaptable Generalized Logic Engine (Eagle) -# Data Utility Package -# -# Copyright (c) 2007-2012 by Joe Mistachkin. All rights reserved. -# -# See the file "license.terms" for information on usage and redistribution of -# this file, and for a DISCLAIMER OF ALL WARRANTIES. -# -# RCS: @(#) $Id: $ -# -############################################################################### - -# -# NOTE: Use our own namespace here because even though we do not directly -# support namespaces ourselves, we do not want to pollute the global -# namespace if this script actually ends up being evaluated in Tcl. -# -namespace eval ::Eagle { - # - # NOTE: This procedure is used to report errors during the various data - # processing operations. In "strict" mode, these errors are always - # fatal; otherwise, the errors are kept in a global "errors" variable - # for later reporting. - # - proc report { {message ""} {data ""} {strict 0} } { - if {$strict} then { - error [list message $message data $data] - } else { - lappend ::errors [list message $message data $data] - - if {[lindex [info level -1] 0] ne "fail"} then { - if {[string length $message] > 0} then { - host result Error [appendArgs \n "message: " $message \n] - } - - if {[string length $data] > 0} then { - host result Error [appendArgs \n "data: " $data \n] - } - } - } - } - - proc fail { {error ""} } { - report $error "" 0; # NOTE: Non-strict, report only. - - if {[string length $error] > 0} then { - putsStdout $error - } - - if {[info exists ::usage]} then { - putsStdout $::usage - } - - error $error - } - - proc getArchitecture {} { - if {[info exists ::tcl_platform(machine)] && \ - [string length $::tcl_platform(machine)] > 0} then { - # - # NOTE: Check for the "amd64" (i.e. "x64") architecture. - # - if {$::tcl_platform(machine) eq "amd64"} then { - return x64 - } - - # - # NOTE: Check for the "ia32_on_win64" (i.e. "WoW64") architecture. - # - if {$::tcl_platform(machine) eq "ia32_on_win64"} then { - return x86 - } - - # - # NOTE: Check for the "ia64" architecture. - # - if {$::tcl_platform(machine) eq "ia64"} then { - return ia64 - } - - # - # NOTE: Check for the "intel" (i.e. "x86") architecture. - # - if {$::tcl_platform(machine) eq "intel"} then { - return x86 - } - - # - # NOTE: We do not support this architecture. - # - putsStdout [appendArgs "Machine \"" $::tcl_platform(machine) \ - "\" is unsupported."] - - return unknown - } - - putsStdout [appendArgs "Machine detection failed."] - - return none - } - - # - # NOTE: With the native library pre-loading feature and a proper application - # local deployment of System.Data.SQLite, as shown here: - # - # * \System.Data.SQLite.dll (managed-only core assembly) - # * \x86\SQLite.Interop.dll (x86 native interop assembly) - # * \x64\SQLite.Interop.dll (x64 native interop assembly) - # - # -OR- - # - # * \System.Data.SQLite.dll (managed-only core assembly) - # * \x86\sqlite3.dll (x86 native library) - # * \x64\sqlite3.dll (x64 native library) - # - # Using this procedure is no longer necessary. - # - proc setupForSQLite { path } { - # - # NOTE: The toolPath is the directory where the caller is running from. - # - set toolPath $path - - putsStdout [appendArgs "Tool path is \"" $toolPath "\"."] - - # - # NOTE: The externalsPath is the parent of the application root directory, - # which should be the Externals directory (i.e. the one containing - # the "sqlite3" and "System.Data.SQLite" directories). If this is - # not the case, append "Externals" to the directory and try there. - # - set externalsPath [file dirname $toolPath] - - if {[file tail $externalsPath] ne "Externals"} then { - set externalsPath [file join $externalsPath Externals] - } - - putsStdout [appendArgs "Externals path is \"" $externalsPath "\"."] - - # - # NOTE: This is the list of file names we need to copy into the - # application binary directory. Currently, this includes the - # "sqlite3.dll" and "System.Data.SQLite.dll" files, which are - # necessary when using SQLite from Eagle. - # - set fileNames [list \ - [file join $externalsPath sqlite3 [getArchitecture] sqlite3.dll] \ - [file join $externalsPath System.Data.SQLite System.Data.SQLite.dll]] - - # - # NOTE: The binaryPath is the directory where the application is running - # from. - # - set binaryPath [info binary] - - putsStdout [appendArgs "Binary path is \"" $binaryPath "\"."] - - # - # NOTE: Attempt to copy each of the files we need to the application - # binary directory. Hopefully, the CLR will be able to load them - # from there. - # - foreach fileName $fileNames { - if {![file exists $fileName]} then { - # - # NOTE: It seems the source file does not exist, skip it. - # - putsStdout [appendArgs "File \"" $fileName "\" does not exist."] - - continue - } - - set justFileName [file tail $fileName] - set newFileName [file join $binaryPath $justFileName] - - if {$justFileName eq "sqlite3.dll"} then { - set magic 0 - set error null - - if {![object invoke Eagle._Components.Private.FileOps \ - CheckPeFileArchitecture $fileName magic error]} then { - # - # NOTE: The "sqlite3.dll" file does not match the current operating - # system architecture (e.g. 32-bit DLL on 64-bit Windows). - # - fail [object invoke $error ToString] - } else { - putsStdout [appendArgs "File \"" $fileName "\" PE magic OK (" \ - [string format "0x{0:X}" $magic] ")."] - } - } - - if {![file exists $newFileName]} then { - # - # NOTE: The destination file does not exist, copy it. - # - file copy $fileName $newFileName - - putsStdout [appendArgs "Copied \"" $fileName "\" to \"" \ - $newFileName "\"."] - } else { - # - # NOTE: It seems the destination file already exists, skip it. - # - putsStdout [appendArgs "File \"" $newFileName "\" exists."] - } - } - } - - proc showTime { name script } { - putsStdout [appendArgs "\n\nStarted " $name " at " \ - [clock format [clock seconds]] .] - - set elapsed [time {uplevel 1 $script}] - - putsStdout [appendArgs "\n\nStopped " $name " at " \ - [clock format [clock seconds]] .] - - putsStdout [appendArgs "Completed in " \ - $elapsed .] - } - - proc haveChannel { name } { - if {![info exists ::haveChannel($name)]} then { - set ::haveChannel($name) \ - [expr {[lsearch -exact [file channels] $name] != -1}] - } - - return $::haveChannel($name) - } - - proc putsStdout { args } { - # - # NOTE: Is the 'stdout' channel available? - # - if {[haveChannel stdout]} then { - # - # NOTE: Do we need to emit a trailing newline? - # - if {[llength $args] == 2 && \ - [lindex $args 0] eq "-nonewline"} then { - # - # NOTE: Output the second argument with no newline. - # - catch { - puts -nonewline stdout [lindex $args 1] - flush stdout - } - } else { - # - # NOTE: Output the first argument with a newline. - # - catch { - puts stdout [lindex $args 0] - flush stdout - } - } - } else { - # - # HACK: Since there is no 'stdout' channel, this procedure is - # totally useless; therefore, we simply redefine it to do - # nothing. - # - proc putsStdout { args } {} - } - } - - proc readBadFile { fileName {readProc readFile} } { - # - # HACK: This "text" file (as exported by MySQL) has a bad mixture of - # utf-8 and windows-1252 code points in it. At a bare minimum, - # we want to change the utf-8 code points that are used in the - # data as column and row delimiters and change them to valid - # windows-1252 code points. - # - return [string map [list \xC3\xBF \xFF \xC3\xBE \xFE] \ - [$readProc $fileName]] - } - - # - # WARNING: Do not use this procedure unless you know exactly what it does. - # - proc readUtf8File { fileName } { - set file_id [open $fileName RDONLY] - fconfigure $file_id -encoding utf-8 -translation auto - set result [read $file_id] - close $file_id - return $result - } - - proc executeSQLite { fileName sql {strict 0} } { - try { - set connection [sql open -type SQLite \ - [subst {Data Source=${fileName}}]] - - if {[catch {sql execute $connection $sql} error] != 0} then { - report [appendArgs "sql statement error: " $error] \ - [list $sql] $strict - } - } finally { - if {[info exists connection]} then { - sql close $connection; unset connection - } - } - } - - proc scanAsciiChars { - fileName {readProc readFile} {startIndex 0} {skip ""} {strict 0} } { - # - # NOTE: Read all the data from the file into memory using the - # specified procedure. - # - # BUGFIX: *PERF* Use a real System.String object here (via an - # opaque object handle) and query each byte in the loop - # below as necessary. This prevents the whole string - # from being needlessly copied back and forth in memory - # repeatedly (i.e. during command invocation). - # - set data [object create -alias String [$readProc $fileName]] - set length [$data Length] - set chunk 1024 - - putsStdout [appendArgs "Scanning " $length " bytes of data (" \ - $chunk " bytes per chunk)...\n"] - - for {set index $startIndex} {$index < $length} {incr index} { - # - # NOTE: Grab the byte value of the specified "character" in - # the string from the opaque object handle. - # - set value [string ordinal [$data get_Chars $index] 0] - - if {[lsearch -integer $skip $value] != -1} then { - continue - } - - if {$value < 32 || $value == 127} then { - report [appendArgs "found control character " $value " (" \ - [string format "0x{0:X}" $value] ") at index " $index] "" \ - $strict - } elseif {$value > 126} then { - report [appendArgs "found bad character " $value " (" \ - [string format "0x{0:X}" $value] ") at index " $index] "" \ - $strict - } - - if {$index % $chunk == 0} then { - putsStdout -nonewline 0 - } - } - } - - proc importDelimited { - fileName tableName {readProc readFile} {columnDelimiter \t} - {rowDelimiter \r\n} {strict 0} } { - # - # NOTE: Read all the data from the file into memory using the - # specified procedure. - # - # BUGFIX: *PERF* Use a real System.String object here (via an - # opaque object handle) and query each byte in the loop - # below as necessary. This prevents the whole string - # from being needlessly copied back and forth in memory - # repeatedly (i.e. during command invocation). - # - set data [object create -alias String [$readProc $fileName]] - - # - # HACK: Check for a detached header file. This should contain - # exactly one row (including the trailing row delimter) - # with just the column names [separated by the column - # delimiter]. - # - set headerFileName [file join [file dirname $fileName] \ - [appendArgs header_ [file tail $fileName]]] - - if {[file exists $headerFileName]} then { - putsStdout [appendArgs "Found detached header file \"" \ - $headerFileName "\" for data file \"" $fileName \ - "\", reading..."] - - set headerData [object create -alias String [$readProc \ - $headerFileName]] - } - - # - # NOTE: Split the data using the row delimiter. We use the - # -string option here to allow for the use of a - # multi-character row delimiters. For data containing - # literal cr/lf characters, a non-cr/lf row delimiter - # must be used. - # - set rowDelimiters [object create -alias String\[\] 1] - $rowDelimiters SetValue $rowDelimiter 0 - set lines [$data -create -alias Split $rowDelimiters None] - - # - # NOTE: Determine how many rows of data there are. There must - # be more than zero to continue. - # - set rowCount [$lines Length] - - # - # NOTE: We cannot proceed if there are no rows of data. - # - if {$rowCount == 0} then { - fail "no rows of data" - } - - # - # NOTE: If we read the header data from the detached header file, - # use it; otherwise, grab the first line of the data. This - # line must be the header line (i.e. it must contain the - # column names and nothing else). - # - if {[info exists headerData]} then { - set headerLine [$headerData ToString] - - # - # NOTE: All data rows are actually data; therefore, start on - # the first row. - # - set rowIndex 0 - } else { - set headerLine [$lines GetValue 0] - - # - # NOTE: The first data row is really the header line; therefore, - # start on the second row. - # - set rowIndex 1 - } - - # - # NOTE: We cannot proceed if the header line is empty. - # - if {[string length $headerLine] == 0} then { - fail "invalid file header" - } - - putsStdout [appendArgs "\n\nAttempting to import " $rowCount \ - " rows starting at index " $rowIndex "...\n"] - - # - # NOTE: Unquote the column name (i.e. removes single and - # double quotation marks). Technically, this may - # be too liberal since it will remove all leading - # and trailing single and double quotes; however, - # these are the column names, not data, and should - # not contain any single or double quotes. - # - set unquote [list [list x] { return [string trim $x '\"] }] - - # - # NOTE: Split the header line using the column delimiter. - # We use the -string option here to allow for the - # use of a multi-character column delimiter. For - # data containing literal tab characters, a non-tab - # column delimiter must be used. - # - set headerColumns [map \ - [split $headerLine $columnDelimiter -string] \ - {apply $unquote}] - - set columnCount [llength $headerColumns] - - # - # NOTE: We cannot proceed if there are no column names. - # - if {$columnCount == 0} then { - fail "no columns in header" - } - - # - # NOTE: Using the table name, access the in-memory table - # from the calling context. By convention, the - # variable name will be "_rows". - # - upvar 1 [appendArgs $tableName _rows] table - - # - # NOTE: Set the necessary metadata used by the export - # procedure into the table array. - # - set table(columns) $headerColumns - set table(imported) 0 - set table(startIndex) $rowIndex - - # - # NOTE: There is no loop initializer here, see above. - # - for {} {$rowIndex < $rowCount} {incr rowIndex} { - # - # NOTE: Grab the previous line of data, if available. - # - if {$rowIndex > 0} then { - set previousLine [$lines GetValue [expr {$rowIndex - 1}]] - } else { - set previousLine "" - } - - # - # NOTE: Grab the current line of data. - # - set line [$lines GetValue $rowIndex] - - # - # NOTE: Is the current line of data empty? - # - if {[string length $line] == 0} then { - # - # NOTE: We do not care if the final row of data is - # empty. - # - if {$rowIndex + 1 < $rowCount} then { - # - # NOTE: An empty row of data could indicate a corrupt - # data dump; however, it is almost always safe - # to simply ignore blank lines. - # - report [appendArgs "row #" $rowIndex " is empty"] \ - [list previous $previousLine] $strict - } - - continue - } - - # - # NOTE: Split the current line using the column delimiter. - # We use the -string option here to allow for the - # use of a multi-character column delimiter. For - # data containing literal tab characters, a non-tab - # column delimiter must be used. - # - set columns [split $line $columnDelimiter -string] - set count [llength $columns] - - # - # NOTE: Did we find some columns in the current line of - # data? Given the check for an empty line of data - # above, this should almost always succeed. - # - if {$count == 0} then { - # - # NOTE: A row of data with no columns could indicate a - # corrupt data dump. - # - report [appendArgs "row #" $rowIndex " has no columns"] \ - [list previous $previousLine current $line] $strict - - continue - } - - # - # NOTE: Does the current line of data contain the correct - # number of columns (based on the header)? If the - # data dump is subtly corrupted in some way, this - # is the most likely error to be seen. - # - if {$count != $columnCount} then { - # - # NOTE: A row of data with an incorrect number of columns - # almost certainly indicates at least some level of - # data dump corruption. We can ignore it and proceed; - # however, each of these errors should be individually - # investigated at the very least. - # - report [appendArgs "row #" $rowIndex " has " $count \ - " columns, expected " $columnCount] [list current $line] $strict - - continue - } - - # - # NOTE: Process each column value for this row and add it - # to the in-memory table. - # - set columnIndex 0 - - for {} {$columnIndex < $count} {incr columnIndex} { - set columnName [lindex $headerColumns $columnIndex] - set columnValue [lindex $columns $columnIndex] - - # - # NOTE: Is the first character a single or double quote? - # - if {[string index $columnValue 0] eq "'" || \ - [string index $columnValue 0] eq "\""} then { - # - # NOTE: Ok, remove the first character. - # - set columnValue [string range $columnValue 1 end] - } - - # - # NOTE: Is the last character a single or double quote? - # - if {[string index $columnValue end] eq "'" || \ - [string index $columnValue end] eq "\""} then { - # - # NOTE: Ok, remove the last character. - # - set columnValue [string range $columnValue 0 end-1] - } - - set table($rowIndex,$columnName) $columnValue - } - - incr table(imported) - putsStdout -nonewline . - } - - set table(count) $table(imported) - } - - proc exportFixedLength { - tableName fileName fields {maps ""} {regsubs ""} {strict 0} } { - # - # NOTE: Using the table name, access the in-memory table - # from the calling context. By convention, the - # variable name will be "_rows". - # - upvar 1 [appendArgs $tableName _rows] table - - set headerColumns $table(columns) - set columnCount [llength $headerColumns] - - # - # NOTE: So far, we have not exported any rows. - # - set table(exported) 0 - - # - # NOTE: Grab the necessary metadata from the table array. - # - set rowCount $table(count) - set startIndex $table(startIndex) - set rowIndex $startIndex - - putsStdout [appendArgs "\n\nAttempting to export " $rowCount \ - " rows starting at index " $rowIndex "...\n"] - - # - # NOTE: Process each row in the passed-in array. There is no - # loop initializer here, see above. - # - set data "" - - for {} {$rowIndex < $rowCount + $startIndex} {incr rowIndex} { - # - # NOTE: Start out with an empty row value. After all the fields - # are processed, this will be added to the overall data block - # to export. - # - set rowValue "" - - # - # NOTE: Process each field in the passed-in list. - # - set fieldIndex 0 - - for {} {$fieldIndex < [llength $fields]} {incr fieldIndex} { - # - # NOTE: What is the length of this row so far? - # - set rowLength [string length $rowValue] - - # - # NOTE: Grab the field [definition] from the list. - # - set field [lindex $fields $fieldIndex] - - # - # NOTE: Make sure the field has the required elements. - # - if {[llength $field] < 3} then { - report [appendArgs \ - "field #" $fieldIndex " has " [llength $field] \ - " elements, expected at least 3"] "" $strict - - continue - } - - # - # NOTE: Extract and validate the field identifier. This element is - # always required and must be a valid integer. - # - set fieldId [string trim [lindex $field 0]] - - if {![string is integer -strict $fieldId]} then { - report [appendArgs \ - "field #" $fieldIndex " has an invalid identifier \"" \ - $fieldId \"] "" $strict - - continue - } - - # - # NOTE: Extract and validate the field name. This element is - # always required. - # - set fieldName [string trim [lindex $field 1]] - - if {[string length $fieldName] == 0} then { - report [appendArgs \ - "field #" $fieldIndex " has an empty name"] "" $strict - - continue - } - - # - # NOTE: Extract and validate the field width. This element is - # always required and must be a valid integer greater than - # zero. - # - set fieldWidth [string trim [lindex $field 2]] - - if {![string is integer -strict $fieldWidth]} then { - report [appendArgs \ - "field #" $fieldIndex " has an invalid width \"" \ - $fieldWidth \"] "" $strict - - continue - } - - # - # NOTE: The field width must be positive and greater than zero. - # - if {$fieldWidth <= 0} then { - report [appendArgs \ - "field #" $fieldIndex " has width \"" $fieldWidth \ - "\", which is less than or equal to zero"] "" $strict - - continue - } - - # - # NOTE: Extract and validate the field start. This element is - # optional; if specified, it must be an integer. - # - set fieldStart [string trim [lindex $field 3]] - - if {[string length $fieldStart] == 0} then { - set fieldStart $rowLength - } - - if {![string is integer -strict $fieldStart]} then { - report [appendArgs \ - "field #" $fieldIndex " has an invalid start \"" \ - $fieldStart \"] "" $strict - - continue - } - - # - # NOTE: The field start cannot occur before the current position in - # the row being built (i.e. fields are always processed in the - # order they occur in the list provided by the caller). - # - if {$fieldStart < $rowLength} then { - report [appendArgs \ - "field #" $fieldIndex " cannot start at \"" $fieldStart \ - "\", already beyond that point"] "" $strict - - continue - } - - # - # NOTE: Extract and validate the field alignment. This element is - # optional; if specified, it must be either "left" or "right". - # - set fieldAlignment [string trim [lindex $field 4]] - - if {[string length $fieldAlignment] == 0} then { - set fieldAlignment right - } - - if {$fieldAlignment ni [list left right]} then { - report [appendArgs \ - "field #" $fieldIndex " has an invalid alignment \"" \ - $fieldAlignment "\", must be \"left\" or \"right\""] "" \ - $strict - - continue - } - - # - # NOTE: Extract and validate the field type. This element is - # optional; if specified, it must be either "string", - # "number", or "datetime". - # - set fieldType [string trim [lindex $field 5]] - - if {[string length $fieldType] == 0} then { - set fieldType string - } - - if {$fieldType ni [list string number datetime]} then { - report [appendArgs \ - "field #" $fieldIndex " has an invalid type \"" $fieldType \ - "\", must be \"string\", \"number\", or \"datetime\""] "" \ - $strict - - continue - } - - # - # NOTE: Extract and validate the field format. This element is - # optional. - # - set fieldFormat [lindex $field 6]; # NOTE: No trim. - - # - # NOTE: Search for the column in the list of columns. If it cannot - # be found, use an empty string for the column name and value. - # We cannot simply skip the column because the format string - # may simply be a literal string that does not require the - # column value. - # - set columnIndex [lsearch -exact $headerColumns $fieldName] - - if {$columnIndex != -1} then { - set columnName [lindex $headerColumns $columnIndex] - set columnValue $table($rowIndex,$columnName) - } else { - set columnName "" - set columnValue "" - } - - # - # HACK: Perform any replacements specified by the caller. This is - # done in two phases. Typically, the first phase is used to - # escape characters (e.g. by converting them to HTML entities) - # and the second phase is [optionally] used to undo any double - # escapes that may have been created during the first phase. - # - if {[llength $maps] > 0} then { - foreach map $maps { - if {[llength $map] > 0} then { - set columnValue [string map $map $columnValue] - } - } - } - - # - # HACK: Perform any regular expression replacements specified by the - # caller. - # - if {[llength $regsubs] > 0} then { - foreach regsub $regsubs { - # - # NOTE: Each element in the list must have exactly 2 elements. - # The first element must be the regular expression. The - # second element must be the replacement pattern. - # - if {[llength $regsub] == 2} then { - regsub -all -- [lindex $regsub 0] $columnValue \ - [lindex $regsub 1] columnValue - } - } - } - - # - # NOTE: Check if an explicit format string was specified. If so, - # use the appropriate formatting command for the data type. - # - if {[string length $fieldFormat] > 0} then { - switch -exact -- $fieldType { - string { - set columnValue [object invoke String Format \ - $fieldFormat $columnValue] - } - number { - set columnValue [format $fieldFormat $columnValue] - } - datetime { - if {[string length $columnValue] > 0 && \ - ![string is integer -strict $columnValue]} then { - # - # NOTE: The value is not an integer; therefore, - # try to scan it as a date and/or time. - # - set columnValue [clock scan $columnValue] - } - - set columnValue [clock format $columnValue \ - -format $fieldFormat] - } - default { - report [appendArgs \ - "field #" $fieldIndex " has bad type \"" \ - $fieldAlignment \"] "" $strict - - continue - } - } - } - - # - # NOTE: Check the formatted column length against the field width. - # If the formatted column length is greater, it must be - # truncated. Otherwise, if the formatted column length is - # less, it must be padded according to the field alignment. - # - set columnLength [string length $columnValue] - - if {$columnLength > $fieldWidth} then { - # - # NOTE: Truncate the string; otherwise, it will not fit within - # the field. - # - if {$fieldAlignment eq "left"} then { - set columnValue [string range $columnValue \ - [expr {$columnLength - $fieldWidth}] end] - } else { - set columnValue [string range $columnValue \ - 0 [expr {$fieldWidth - 1}]] - } - - report [appendArgs \ - "column \"" $columnName "\" value at row #" $rowIndex \ - " (length " $columnLength ") exceeds width of field #" \ - $fieldIndex " (width " $fieldWidth "), truncated"] "" \ - $strict - } else { - set padding [string repeat " " \ - [expr {$fieldWidth - $columnLength}]] - - if {$fieldAlignment eq "left"} then { - set columnValue [appendArgs $columnValue $padding] - } else { - set columnValue [appendArgs $padding $columnValue] - } - } - - # - # NOTE: If this field starts at some point after the end of the - # row value built so far, pad it. - # - if {$fieldStart > $rowLength} then { - set padding [string repeat " " \ - [expr {$fieldStart - $rowLength}]] - } else { - set padding "" - } - - # - # NOTE: Append the necessary padding and the final column value - # to the row value. - # - append rowValue $padding $columnValue - } - - # - # NOTE: Append the row value to the overall data block to export. - # - append data $rowValue - - incr table(exported) - putsStdout -nonewline * - } - - writeFile $fileName $data - } - - proc exportSQLite { - tableName fileName {sql ""} {maps ""} {regsubs ""} {strict 0} } { - # - # NOTE: Export the in-memory table to the specified SQLite - # database file. - # - try { - set connection [sql open -type SQLite \ - [subst {Data Source=${fileName}}]] - - # - # NOTE: If custom SQL was specified, execute it against - # the database connection now. - # - if {[string length $sql] > 0} then { - sql execute $connection $sql - } - - # - # NOTE: Using the table name, access the in-memory table - # from the calling context. By convention, the - # variable name will be "_rows". - # - upvar 1 [appendArgs $tableName _rows] table - - set headerColumns $table(columns) - set columnCount [llength $headerColumns] - - # - # NOTE: Wraps the column name in square brackets. - # - set wrap [list [list x] { return [appendArgs \[ $x \]] }] - - # - # NOTE: Build the parameterized SQL statement to execute an - # INSERT (or UPDATE) of a single row. - # - set rowSql [appendArgs \ - "INSERT OR REPLACE INTO \[" $tableName "\] (" \ - [join [map $headerColumns {apply $wrap}] ,] ") VALUES(" \ - [join [lrepeat $columnCount ?] ,] ");"] - - # - # NOTE: Build the per-row script to evaluate for adding or - # updating a row in the database. - # - set script {eval sql execute -verbatim \ - [list $connection] [list $rowSql] $columnParams} - - # - # NOTE: So far, we have not exported any rows. - # - set table(exported) 0 - - # - # NOTE: Grab the necessary metadata from the table array. - # - set rowCount $table(count) - set startIndex $table(startIndex) - set rowIndex $startIndex - - putsStdout [appendArgs "\n\nAttempting to export " $rowCount \ - " rows starting at index " $rowIndex "...\n"] - - # - # NOTE: Process each row in the passed-in array. There is no loop - # initializer here, see above. - # - for {} {$rowIndex < $rowCount + $startIndex} {incr rowIndex} { - set columnParams [list] - - # - # NOTE: Process each column value for this row and add it to the - # list of parameters for the SQL statement to execute. - # - set columnIndex 0 - - for {} {$columnIndex < $columnCount} {incr columnIndex} { - set columnName [lindex $headerColumns $columnIndex] - set columnValue $table($rowIndex,$columnName) - - # - # HACK: Perform any replacements specified by the caller. This is - # done in two phases. Typically, the first phase is used to - # escape characters (e.g. by converting them to HTML entities) - # and the second phase is [optionally] used to undo any double - # escapes that may have been created during the first phase. - # - if {[llength $maps] > 0} then { - foreach map $maps { - if {[llength $map] > 0} then { - set columnValue [string map $map $columnValue] - } - } - } - - # - # HACK: Perform any regular expression replacements specified by the - # caller. - # - if {[llength $regsubs] > 0} then { - foreach regsub $regsubs { - # - # NOTE: Each element in the list must have exactly 2 elements. - # The first element must be the regular expression. The - # second element must be the replacement pattern. - # - if {[llength $regsub] == 2} then { - regsub -all -- [lindex $regsub 0] $columnValue \ - [lindex $regsub 1] columnValue - } - } - } - - # - # HACK: Make dates conform to the format needed by SQLite. - # - if {[regexp -- {^\d{4}/\d{1,2}/\d{1,2}$} $columnValue]} then { - set dateTime [object invoke -alias DateTime Parse $columnValue] - set columnValue [$dateTime ToString yyyy-MM-dd] - } - - # - # NOTE: Make sure to omit the parameter value if the column value - # needs to be a literal NULL. - # - set columnParam [list [appendArgs param $columnIndex] String] - - if {$columnValue ne "NULL"} then { - lappend columnParam $columnValue - } - - # - # NOTE: Add the parameter for this column to the list of parameters - # to pass to the command. - # - lappend columnParams $columnParam - } - - # - # NOTE: Evaluate the per-row script used to actually insert or - # update a row in the database. Catch and report on any - # errors we encounter. - # - if {[catch $script error] != 0} then { - report [appendArgs "sql statement error: " $error] \ - [list $rowSql $columnParams] $strict - } else { - # - # NOTE: We successfully imported another row. - # - incr table(exported) - } - - putsStdout -nonewline * - } - } finally { - if {[info exists connection]} then { - sql close $connection; unset connection - } - } - } - - # - # NOTE: Provide the Eagle library package to the interpreter. - # - package provide Eagle.Data \ - [expr {[isEagle] ? [info engine PatchLevel] : "1.0"}] -} - DELETED eagle/1.0/data1.0/data.eagle.asc Index: eagle/1.0/data1.0/data.eagle.asc ================================================================== --- eagle/1.0/data1.0/data.eagle.asc +++ eagle/1.0/data1.0/data.eagle.asc @@ -1,18 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v2 -Comment: Eagle Package Repository - -iQIcBAABCAAGBQJX1JQWAAoJEFAslq9JXcLZnPcQAKjLrT+W439ps4nNxAMcCcgC -5p6UoMXwr9+34ffTi41jK3tN5cptUOe8PKhROG6FTJrJclNZFqkRJagVGKdcs3ED -ykGKDLOSwI547jJNGKqfhrd199GsVr+cmhEI64+6j9U5RltKQtF+whJx89werTWd -tRPedr09ET4QOW/W66Q0s7UjljEZZqkz2ErepBFhPLWbCWroYi6H795FxPA6nAlO -15PlR9z1p8DAF4YpKC4zRK0NMUtEh8OnH1hJQ3E+n/1gJpvYV4el2hA7Z+uZ07xP -NHT9nSKbJ8EwmVYy3+HCBduMp0X81VzMXM2kyzpeZF/tSxwi23SGZtXmc75icRa2 -iRj93h1jqhnB5+1OF7C+ezC3JesVPyngNXydPPOmKNi9AqRgUOSBRSzitBBFqE5C -Pjl/rtzDOtdrcifv1+iRYwvF3W/EGNL2b8EY+g7/rYNUFrOcEaGMWx3ID/dw4xs1 -XeEWTi0lfuiyFs6CuleCGOAqV+IgU2se4mWZ0t2A/ZihQQ9FuektGCpAeeqBqIai -KEgtZP2Chq8JBArlWc4qnMckdGyMLeJzp4ecBnWOI2yx+K0bxTHn0QxnLTvKUT0C -qr1S0l1E3TwnHiNLIuS6soDPUHevgDDSJEARiLIcT7U5N9q0pbdJCCJKDqoK1NQ+ -0W3DKj684Zcn+SYzGDQ3 -=UI7f ------END PGP SIGNATURE----- DELETED eagle/1.0/data1.0/data.eagle.harpy Index: eagle/1.0/data1.0/data.eagle.harpy ================================================================== --- eagle/1.0/data1.0/data.eagle.harpy +++ eagle/1.0/data1.0/data.eagle.harpy @@ -1,68 +0,0 @@ - - - - None - Mistachkin Systems - 53cac383-800a-4e1a-ac9f-54d79a848e29 - SHA512 - Script - 2016-08-23T04:09:36.0449687Z - -1.00:00:00 - 0x9559f6017247e3e2 - - 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 - - DELETED eagle/1.0/data1.0/data.eagle.harpy.asc Index: eagle/1.0/data1.0/data.eagle.harpy.asc ================================================================== --- eagle/1.0/data1.0/data.eagle.harpy.asc +++ eagle/1.0/data1.0/data.eagle.harpy.asc @@ -1,18 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v2 -Comment: Eagle Package Repository - -iQIcBAABCAAGBQJX1JQYAAoJEFAslq9JXcLZeJQQALuSwisANovxPGdhduKX0r+r -E54ESvS08wGUsQTWvlb+SuvEhScTbtZevQXgXCX60CqFRYLbskeaMkZkNl8JeXks -SoiD0OqEnuDMgOjF9CgnRTnsxK3y7jR4birycxH2IvVbS8TpTD/6Wl+A61zb0mwD -9NB1R0DE6Ty0R4a5TDa6SWKRKwhE1hQOIm9X4ZGnL+zXYc90vBjeIaeYb9hlTDMU -v6qvwok20JPaaOdDzNVVSDY25/p4q8HPsntTFBKEnlzjtMXoj2WhPpLi0uzFFRhI -wpFpMeNVRUiQuEE0k5eHPFgSGzpEggObHEbEElPAySnWqvmCsEMdqqCDFKa0Rlkp -go9Ab3YnXLQZcsm7NOM+uan+U0giglxWNY27+Lna6QpLGIg3UZsTFbpdpSVrCxMt -zdOMfl+KYQt8NIvZwbX6OEURXYvgrJrIPQkrFH2LxgGT5Bx999ZFSSnyqjXN3Cb+ -XbJyoMWhuFY6dGkkCZLyitUz/esCn700EvVjmyKyM7gmUyPMSnVmQ3YNiY6GLF+6 -Pg2SJU6uFKsgSQoyHHzaJtrSyi2oA+Qu7KaqF/sfDcPPXTxrztwGn1xLhsHvFTiT -F4+0Jj2+1iclj+STMDbkUcn5MZQS7JeP90Mr1UAvCWA3gDPA0ZyLgbVPddc7Kadj -R+b87Ovem+vY4CKtpy7L -=5Nek ------END PGP SIGNATURE----- DELETED eagle/1.0/data1.0/pkgIndex.eagle Index: eagle/1.0/data1.0/pkgIndex.eagle ================================================================== --- eagle/1.0/data1.0/pkgIndex.eagle +++ eagle/1.0/data1.0/pkgIndex.eagle @@ -1,20 +0,0 @@ -############################################################################### -# -# pkgIndex.eagle -- -# -# Extensible Adaptable Generalized Logic Engine (Eagle) -# Package Index File -# -# Copyright (c) 2007-2012 by Joe Mistachkin. All rights reserved. -# -# See the file "license.terms" for information on usage and redistribution of -# this file, and for a DISCLAIMER OF ALL WARRANTIES. -# -# RCS: @(#) $Id: $ -# -############################################################################### - -if {![package vsatisfies [package provide Tcl] 8.4]} {return} -if {![package vsatisfies [package provide Eagle] 1.0]} {return} - -package ifneeded Eagle.Data 1.0 [list source [file join $dir data.eagle]] DELETED eagle/1.0/data1.0/pkgIndex.eagle.asc Index: eagle/1.0/data1.0/pkgIndex.eagle.asc ================================================================== --- eagle/1.0/data1.0/pkgIndex.eagle.asc +++ eagle/1.0/data1.0/pkgIndex.eagle.asc @@ -1,18 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v2 -Comment: Eagle Package Repository - -iQIcBAABCAAGBQJX1JQcAAoJEFAslq9JXcLZZL0QAKPsxh3L1x5LYZ5r2KNO6hPZ -P5T/7zFPyRLoIbqRvBdgeKMH4+yYlvYHVgPO4oiUNz9g03CZoh/GLZHt21twXVA2 -gzMlf68e1L2aNHpiqeR9LXbC1UpHPLFoCv28Gnk7F2UUk4cR/9CkcK38J2kMRNVD -2sAWJM/bNsVJ3rz3A/b9dGIemAQZjZ4SRB3M1ecZaFqGo9wrhCGfMcDavoGHkR+7 -VX3dy3qvLWEEgnuBb10QdyAx2ORAry45UtrmuTUVFfQIk5f775vvefe5gxjKGNW3 -+8eYPPuIwWMgx3VANL0J7xf7sOxuA0MjdQhCnpAV2aIIlhY07rEZtdsY65LNF68d -hExh2fGQeVzAayM8/zl8Tcy8nnInQag8lDOcfOchd8gae+f34HJ5ENxUVCTZUrPz -gNlQq5FQwUvAbv5jvozXqARlBdCSwYgMdxYzfOKDVN49h4wpsZ4L6AjmeMOQLGzh -l3Uem+1ToOXrbw7VFx1xUKZnzjSFbSsSNiU+F1DIfrRV1x2wloyeze63nZRmZVtn -3A96nqPEr0BdP6E0kEn1f8LEgCHGefBgq83e/O4PnvZl8BKfuM1VMRb4ohno6f0k -SgX3eMpB00ADK8mFI/TO/jrz0X33SWxlNZQpa46qRAt6pny7np/3Dpirt8I4r+fK -A2PxwRU+4e4Va3dz5/s1 -=8Sv6 ------END PGP SIGNATURE----- DELETED eagle/1.0/data1.0/pkgIndex.eagle.harpy Index: eagle/1.0/data1.0/pkgIndex.eagle.harpy ================================================================== --- eagle/1.0/data1.0/pkgIndex.eagle.harpy +++ eagle/1.0/data1.0/pkgIndex.eagle.harpy @@ -1,68 +0,0 @@ - - - - None - Mistachkin Systems - 092bc755-f131-430f-8c7e-6ce47756ec69 - SHA512 - Script - 2016-08-23T04:43:50.7227031Z - -1.00:00:00 - 0x9559f6017247e3e2 - - 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 - - DELETED eagle/1.0/data1.0/pkgIndex.eagle.harpy.asc Index: eagle/1.0/data1.0/pkgIndex.eagle.harpy.asc ================================================================== --- eagle/1.0/data1.0/pkgIndex.eagle.harpy.asc +++ eagle/1.0/data1.0/pkgIndex.eagle.harpy.asc @@ -1,18 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v2 -Comment: Eagle Package Repository - -iQIcBAABCAAGBQJX1JQeAAoJEFAslq9JXcLZvMgQAJQ1QsszDIonrCXgSV78HpR+ -+fQQkemMyGkTKIkNz9Xd+6TwOxImLlUnPympAJ4KdlpXfpYisAAS9PxsKm1Xqdml -D2xJ1rsirXEWmt7O04+xLB/V2M3esKtDnr4dXu3m9Fv8wyC9Vujrnrr8qiftLK5h -RaQEVEAlScY67BLLQ9SX9qNYSDgA4WsLIY78pCJ6ml2eBiHRH+hJr8V1mKzxEqIK -vYP2PJ+iOkuSHuKt/JML+4QOwvG3ISMQCaGKMMFLgdMwvZmesxIGQAK2zevbMawq -LH0pdlf+XIqoRdKAhFixgpX6O8vTi0RGhGJd4uscQWpC16P/v34ZSgTsj+2ZngH9 -1aicJF6274IdQwXTvuqKy6nE27KZrHe33o+IVJQyDrtBRtpW4huFx47EEnlnDATC -L0vQnMUEfAWCz3AG+ySV3lFHBPcNixK6xet4DjP9e5xml0fRyXt5VPgVYUwKB964 -4ibQYDku5IU6DsbEISb8r67Da3AMRHrYgez1OozpIlgAt65AD4CYdLh1ZpUhIurh -pSIcFRnIfSav5xB0MuDtsBYTHUim8BhH3BPEM2a8PgLUhZzXoC+/JhH9H1QVJm3y -glkM6sMCJQcD0jIbH2O3Xdfq7JYsK/XpZVeKISEy0+qx8wzsw19wGD2tsoUQKN1H -PZzOU1KiLC4Y4D2AbIdv -=UaG8 ------END PGP SIGNATURE----- ADDED eagle/1.0/neutral/data1.0/data.eagle Index: eagle/1.0/neutral/data1.0/data.eagle ================================================================== --- eagle/1.0/neutral/data1.0/data.eagle +++ eagle/1.0/neutral/data1.0/data.eagle @@ -0,0 +1,1139 @@ +############################################################################### +# +# data.eagle -- +# +# Extensible Adaptable Generalized Logic Engine (Eagle) +# Data Utility Package +# +# Copyright (c) 2007-2012 by Joe Mistachkin. All rights reserved. +# +# See the file "license.terms" for information on usage and redistribution of +# this file, and for a DISCLAIMER OF ALL WARRANTIES. +# +# RCS: @(#) $Id: $ +# +############################################################################### + +# +# NOTE: Use our own namespace here because even though we do not directly +# support namespaces ourselves, we do not want to pollute the global +# namespace if this script actually ends up being evaluated in Tcl. +# +namespace eval ::Eagle { + # + # NOTE: This procedure is used to report errors during the various data + # processing operations. In "strict" mode, these errors are always + # fatal; otherwise, the errors are kept in a global "errors" variable + # for later reporting. + # + proc report { {message ""} {data ""} {strict 0} } { + if {$strict} then { + error [list message $message data $data] + } else { + lappend ::errors [list message $message data $data] + + if {[lindex [info level -1] 0] ne "fail"} then { + if {[string length $message] > 0} then { + host result Error [appendArgs \n "message: " $message \n] + } + + if {[string length $data] > 0} then { + host result Error [appendArgs \n "data: " $data \n] + } + } + } + } + + proc fail { {error ""} } { + report $error "" 0; # NOTE: Non-strict, report only. + + if {[string length $error] > 0} then { + putsStdout $error + } + + if {[info exists ::usage]} then { + putsStdout $::usage + } + + error $error + } + + proc getArchitecture {} { + if {[info exists ::tcl_platform(machine)] && \ + [string length $::tcl_platform(machine)] > 0} then { + # + # NOTE: Check for the "amd64" (i.e. "x64") architecture. + # + if {$::tcl_platform(machine) eq "amd64"} then { + return x64 + } + + # + # NOTE: Check for the "ia32_on_win64" (i.e. "WoW64") architecture. + # + if {$::tcl_platform(machine) eq "ia32_on_win64"} then { + return x86 + } + + # + # NOTE: Check for the "ia64" architecture. + # + if {$::tcl_platform(machine) eq "ia64"} then { + return ia64 + } + + # + # NOTE: Check for the "intel" (i.e. "x86") architecture. + # + if {$::tcl_platform(machine) eq "intel"} then { + return x86 + } + + # + # NOTE: We do not support this architecture. + # + putsStdout [appendArgs "Machine \"" $::tcl_platform(machine) \ + "\" is unsupported."] + + return unknown + } + + putsStdout [appendArgs "Machine detection failed."] + + return none + } + + # + # NOTE: With the native library pre-loading feature and a proper application + # local deployment of System.Data.SQLite, as shown here: + # + # * \System.Data.SQLite.dll (managed-only core assembly) + # * \x86\SQLite.Interop.dll (x86 native interop assembly) + # * \x64\SQLite.Interop.dll (x64 native interop assembly) + # + # -OR- + # + # * \System.Data.SQLite.dll (managed-only core assembly) + # * \x86\sqlite3.dll (x86 native library) + # * \x64\sqlite3.dll (x64 native library) + # + # Using this procedure is no longer necessary. + # + proc setupForSQLite { path } { + # + # NOTE: The toolPath is the directory where the caller is running from. + # + set toolPath $path + + putsStdout [appendArgs "Tool path is \"" $toolPath "\"."] + + # + # NOTE: The externalsPath is the parent of the application root directory, + # which should be the Externals directory (i.e. the one containing + # the "sqlite3" and "System.Data.SQLite" directories). If this is + # not the case, append "Externals" to the directory and try there. + # + set externalsPath [file dirname $toolPath] + + if {[file tail $externalsPath] ne "Externals"} then { + set externalsPath [file join $externalsPath Externals] + } + + putsStdout [appendArgs "Externals path is \"" $externalsPath "\"."] + + # + # NOTE: This is the list of file names we need to copy into the + # application binary directory. Currently, this includes the + # "sqlite3.dll" and "System.Data.SQLite.dll" files, which are + # necessary when using SQLite from Eagle. + # + set fileNames [list \ + [file join $externalsPath sqlite3 [getArchitecture] sqlite3.dll] \ + [file join $externalsPath System.Data.SQLite System.Data.SQLite.dll]] + + # + # NOTE: The binaryPath is the directory where the application is running + # from. + # + set binaryPath [info binary] + + putsStdout [appendArgs "Binary path is \"" $binaryPath "\"."] + + # + # NOTE: Attempt to copy each of the files we need to the application + # binary directory. Hopefully, the CLR will be able to load them + # from there. + # + foreach fileName $fileNames { + if {![file exists $fileName]} then { + # + # NOTE: It seems the source file does not exist, skip it. + # + putsStdout [appendArgs "File \"" $fileName "\" does not exist."] + + continue + } + + set justFileName [file tail $fileName] + set newFileName [file join $binaryPath $justFileName] + + if {$justFileName eq "sqlite3.dll"} then { + set magic 0 + set error null + + if {![object invoke Eagle._Components.Private.FileOps \ + CheckPeFileArchitecture $fileName magic error]} then { + # + # NOTE: The "sqlite3.dll" file does not match the current operating + # system architecture (e.g. 32-bit DLL on 64-bit Windows). + # + fail [object invoke $error ToString] + } else { + putsStdout [appendArgs "File \"" $fileName "\" PE magic OK (" \ + [string format "0x{0:X}" $magic] ")."] + } + } + + if {![file exists $newFileName]} then { + # + # NOTE: The destination file does not exist, copy it. + # + file copy $fileName $newFileName + + putsStdout [appendArgs "Copied \"" $fileName "\" to \"" \ + $newFileName "\"."] + } else { + # + # NOTE: It seems the destination file already exists, skip it. + # + putsStdout [appendArgs "File \"" $newFileName "\" exists."] + } + } + } + + proc showTime { name script } { + putsStdout [appendArgs "\n\nStarted " $name " at " \ + [clock format [clock seconds]] .] + + set elapsed [time {uplevel 1 $script}] + + putsStdout [appendArgs "\n\nStopped " $name " at " \ + [clock format [clock seconds]] .] + + putsStdout [appendArgs "Completed in " \ + $elapsed .] + } + + proc haveChannel { name } { + if {![info exists ::haveChannel($name)]} then { + set ::haveChannel($name) \ + [expr {[lsearch -exact [file channels] $name] != -1}] + } + + return $::haveChannel($name) + } + + proc putsStdout { args } { + # + # NOTE: Is the 'stdout' channel available? + # + if {[haveChannel stdout]} then { + # + # NOTE: Do we need to emit a trailing newline? + # + if {[llength $args] == 2 && \ + [lindex $args 0] eq "-nonewline"} then { + # + # NOTE: Output the second argument with no newline. + # + catch { + puts -nonewline stdout [lindex $args 1] + flush stdout + } + } else { + # + # NOTE: Output the first argument with a newline. + # + catch { + puts stdout [lindex $args 0] + flush stdout + } + } + } else { + # + # HACK: Since there is no 'stdout' channel, this procedure is + # totally useless; therefore, we simply redefine it to do + # nothing. + # + proc putsStdout { args } {} + } + } + + proc readBadFile { fileName {readProc readFile} } { + # + # HACK: This "text" file (as exported by MySQL) has a bad mixture of + # utf-8 and windows-1252 code points in it. At a bare minimum, + # we want to change the utf-8 code points that are used in the + # data as column and row delimiters and change them to valid + # windows-1252 code points. + # + return [string map [list \xC3\xBF \xFF \xC3\xBE \xFE] \ + [$readProc $fileName]] + } + + # + # WARNING: Do not use this procedure unless you know exactly what it does. + # + proc readUtf8File { fileName } { + set file_id [open $fileName RDONLY] + fconfigure $file_id -encoding utf-8 -translation auto + set result [read $file_id] + close $file_id + return $result + } + + proc executeSQLite { fileName sql {strict 0} } { + try { + set connection [sql open -type SQLite \ + [subst {Data Source=${fileName}}]] + + if {[catch {sql execute $connection $sql} error] != 0} then { + report [appendArgs "sql statement error: " $error] \ + [list $sql] $strict + } + } finally { + if {[info exists connection]} then { + sql close $connection; unset connection + } + } + } + + proc scanAsciiChars { + fileName {readProc readFile} {startIndex 0} {skip ""} {strict 0} } { + # + # NOTE: Read all the data from the file into memory using the + # specified procedure. + # + # BUGFIX: *PERF* Use a real System.String object here (via an + # opaque object handle) and query each byte in the loop + # below as necessary. This prevents the whole string + # from being needlessly copied back and forth in memory + # repeatedly (i.e. during command invocation). + # + set data [object create -alias String [$readProc $fileName]] + set length [$data Length] + set chunk 1024 + + putsStdout [appendArgs "Scanning " $length " bytes of data (" \ + $chunk " bytes per chunk)...\n"] + + for {set index $startIndex} {$index < $length} {incr index} { + # + # NOTE: Grab the byte value of the specified "character" in + # the string from the opaque object handle. + # + set value [string ordinal [$data get_Chars $index] 0] + + if {[lsearch -integer $skip $value] != -1} then { + continue + } + + if {$value < 32 || $value == 127} then { + report [appendArgs "found control character " $value " (" \ + [string format "0x{0:X}" $value] ") at index " $index] "" \ + $strict + } elseif {$value > 126} then { + report [appendArgs "found bad character " $value " (" \ + [string format "0x{0:X}" $value] ") at index " $index] "" \ + $strict + } + + if {$index % $chunk == 0} then { + putsStdout -nonewline 0 + } + } + } + + proc importDelimited { + fileName tableName {readProc readFile} {columnDelimiter \t} + {rowDelimiter \r\n} {strict 0} } { + # + # NOTE: Read all the data from the file into memory using the + # specified procedure. + # + # BUGFIX: *PERF* Use a real System.String object here (via an + # opaque object handle) and query each byte in the loop + # below as necessary. This prevents the whole string + # from being needlessly copied back and forth in memory + # repeatedly (i.e. during command invocation). + # + set data [object create -alias String [$readProc $fileName]] + + # + # HACK: Check for a detached header file. This should contain + # exactly one row (including the trailing row delimter) + # with just the column names [separated by the column + # delimiter]. + # + set headerFileName [file join [file dirname $fileName] \ + [appendArgs header_ [file tail $fileName]]] + + if {[file exists $headerFileName]} then { + putsStdout [appendArgs "Found detached header file \"" \ + $headerFileName "\" for data file \"" $fileName \ + "\", reading..."] + + set headerData [object create -alias String [$readProc \ + $headerFileName]] + } + + # + # NOTE: Split the data using the row delimiter. We use the + # -string option here to allow for the use of a + # multi-character row delimiters. For data containing + # literal cr/lf characters, a non-cr/lf row delimiter + # must be used. + # + set rowDelimiters [object create -alias String\[\] 1] + $rowDelimiters SetValue $rowDelimiter 0 + set lines [$data -create -alias Split $rowDelimiters None] + + # + # NOTE: Determine how many rows of data there are. There must + # be more than zero to continue. + # + set rowCount [$lines Length] + + # + # NOTE: We cannot proceed if there are no rows of data. + # + if {$rowCount == 0} then { + fail "no rows of data" + } + + # + # NOTE: If we read the header data from the detached header file, + # use it; otherwise, grab the first line of the data. This + # line must be the header line (i.e. it must contain the + # column names and nothing else). + # + if {[info exists headerData]} then { + set headerLine [$headerData ToString] + + # + # NOTE: All data rows are actually data; therefore, start on + # the first row. + # + set rowIndex 0 + } else { + set headerLine [$lines GetValue 0] + + # + # NOTE: The first data row is really the header line; therefore, + # start on the second row. + # + set rowIndex 1 + } + + # + # NOTE: We cannot proceed if the header line is empty. + # + if {[string length $headerLine] == 0} then { + fail "invalid file header" + } + + putsStdout [appendArgs "\n\nAttempting to import " $rowCount \ + " rows starting at index " $rowIndex "...\n"] + + # + # NOTE: Unquote the column name (i.e. removes single and + # double quotation marks). Technically, this may + # be too liberal since it will remove all leading + # and trailing single and double quotes; however, + # these are the column names, not data, and should + # not contain any single or double quotes. + # + set unquote [list [list x] { return [string trim $x '\"] }] + + # + # NOTE: Split the header line using the column delimiter. + # We use the -string option here to allow for the + # use of a multi-character column delimiter. For + # data containing literal tab characters, a non-tab + # column delimiter must be used. + # + set headerColumns [map \ + [split $headerLine $columnDelimiter -string] \ + {apply $unquote}] + + set columnCount [llength $headerColumns] + + # + # NOTE: We cannot proceed if there are no column names. + # + if {$columnCount == 0} then { + fail "no columns in header" + } + + # + # NOTE: Using the table name, access the in-memory table + # from the calling context. By convention, the + # variable name will be "_rows". + # + upvar 1 [appendArgs $tableName _rows] table + + # + # NOTE: Set the necessary metadata used by the export + # procedure into the table array. + # + set table(columns) $headerColumns + set table(imported) 0 + set table(startIndex) $rowIndex + + # + # NOTE: There is no loop initializer here, see above. + # + for {} {$rowIndex < $rowCount} {incr rowIndex} { + # + # NOTE: Grab the previous line of data, if available. + # + if {$rowIndex > 0} then { + set previousLine [$lines GetValue [expr {$rowIndex - 1}]] + } else { + set previousLine "" + } + + # + # NOTE: Grab the current line of data. + # + set line [$lines GetValue $rowIndex] + + # + # NOTE: Is the current line of data empty? + # + if {[string length $line] == 0} then { + # + # NOTE: We do not care if the final row of data is + # empty. + # + if {$rowIndex + 1 < $rowCount} then { + # + # NOTE: An empty row of data could indicate a corrupt + # data dump; however, it is almost always safe + # to simply ignore blank lines. + # + report [appendArgs "row #" $rowIndex " is empty"] \ + [list previous $previousLine] $strict + } + + continue + } + + # + # NOTE: Split the current line using the column delimiter. + # We use the -string option here to allow for the + # use of a multi-character column delimiter. For + # data containing literal tab characters, a non-tab + # column delimiter must be used. + # + set columns [split $line $columnDelimiter -string] + set count [llength $columns] + + # + # NOTE: Did we find some columns in the current line of + # data? Given the check for an empty line of data + # above, this should almost always succeed. + # + if {$count == 0} then { + # + # NOTE: A row of data with no columns could indicate a + # corrupt data dump. + # + report [appendArgs "row #" $rowIndex " has no columns"] \ + [list previous $previousLine current $line] $strict + + continue + } + + # + # NOTE: Does the current line of data contain the correct + # number of columns (based on the header)? If the + # data dump is subtly corrupted in some way, this + # is the most likely error to be seen. + # + if {$count != $columnCount} then { + # + # NOTE: A row of data with an incorrect number of columns + # almost certainly indicates at least some level of + # data dump corruption. We can ignore it and proceed; + # however, each of these errors should be individually + # investigated at the very least. + # + report [appendArgs "row #" $rowIndex " has " $count \ + " columns, expected " $columnCount] [list current $line] $strict + + continue + } + + # + # NOTE: Process each column value for this row and add it + # to the in-memory table. + # + set columnIndex 0 + + for {} {$columnIndex < $count} {incr columnIndex} { + set columnName [lindex $headerColumns $columnIndex] + set columnValue [lindex $columns $columnIndex] + + # + # NOTE: Is the first character a single or double quote? + # + if {[string index $columnValue 0] eq "'" || \ + [string index $columnValue 0] eq "\""} then { + # + # NOTE: Ok, remove the first character. + # + set columnValue [string range $columnValue 1 end] + } + + # + # NOTE: Is the last character a single or double quote? + # + if {[string index $columnValue end] eq "'" || \ + [string index $columnValue end] eq "\""} then { + # + # NOTE: Ok, remove the last character. + # + set columnValue [string range $columnValue 0 end-1] + } + + set table($rowIndex,$columnName) $columnValue + } + + incr table(imported) + putsStdout -nonewline . + } + + set table(count) $table(imported) + } + + proc exportFixedLength { + tableName fileName fields {maps ""} {regsubs ""} {strict 0} } { + # + # NOTE: Using the table name, access the in-memory table + # from the calling context. By convention, the + # variable name will be "_rows". + # + upvar 1 [appendArgs $tableName _rows] table + + set headerColumns $table(columns) + set columnCount [llength $headerColumns] + + # + # NOTE: So far, we have not exported any rows. + # + set table(exported) 0 + + # + # NOTE: Grab the necessary metadata from the table array. + # + set rowCount $table(count) + set startIndex $table(startIndex) + set rowIndex $startIndex + + putsStdout [appendArgs "\n\nAttempting to export " $rowCount \ + " rows starting at index " $rowIndex "...\n"] + + # + # NOTE: Process each row in the passed-in array. There is no + # loop initializer here, see above. + # + set data "" + + for {} {$rowIndex < $rowCount + $startIndex} {incr rowIndex} { + # + # NOTE: Start out with an empty row value. After all the fields + # are processed, this will be added to the overall data block + # to export. + # + set rowValue "" + + # + # NOTE: Process each field in the passed-in list. + # + set fieldIndex 0 + + for {} {$fieldIndex < [llength $fields]} {incr fieldIndex} { + # + # NOTE: What is the length of this row so far? + # + set rowLength [string length $rowValue] + + # + # NOTE: Grab the field [definition] from the list. + # + set field [lindex $fields $fieldIndex] + + # + # NOTE: Make sure the field has the required elements. + # + if {[llength $field] < 3} then { + report [appendArgs \ + "field #" $fieldIndex " has " [llength $field] \ + " elements, expected at least 3"] "" $strict + + continue + } + + # + # NOTE: Extract and validate the field identifier. This element is + # always required and must be a valid integer. + # + set fieldId [string trim [lindex $field 0]] + + if {![string is integer -strict $fieldId]} then { + report [appendArgs \ + "field #" $fieldIndex " has an invalid identifier \"" \ + $fieldId \"] "" $strict + + continue + } + + # + # NOTE: Extract and validate the field name. This element is + # always required. + # + set fieldName [string trim [lindex $field 1]] + + if {[string length $fieldName] == 0} then { + report [appendArgs \ + "field #" $fieldIndex " has an empty name"] "" $strict + + continue + } + + # + # NOTE: Extract and validate the field width. This element is + # always required and must be a valid integer greater than + # zero. + # + set fieldWidth [string trim [lindex $field 2]] + + if {![string is integer -strict $fieldWidth]} then { + report [appendArgs \ + "field #" $fieldIndex " has an invalid width \"" \ + $fieldWidth \"] "" $strict + + continue + } + + # + # NOTE: The field width must be positive and greater than zero. + # + if {$fieldWidth <= 0} then { + report [appendArgs \ + "field #" $fieldIndex " has width \"" $fieldWidth \ + "\", which is less than or equal to zero"] "" $strict + + continue + } + + # + # NOTE: Extract and validate the field start. This element is + # optional; if specified, it must be an integer. + # + set fieldStart [string trim [lindex $field 3]] + + if {[string length $fieldStart] == 0} then { + set fieldStart $rowLength + } + + if {![string is integer -strict $fieldStart]} then { + report [appendArgs \ + "field #" $fieldIndex " has an invalid start \"" \ + $fieldStart \"] "" $strict + + continue + } + + # + # NOTE: The field start cannot occur before the current position in + # the row being built (i.e. fields are always processed in the + # order they occur in the list provided by the caller). + # + if {$fieldStart < $rowLength} then { + report [appendArgs \ + "field #" $fieldIndex " cannot start at \"" $fieldStart \ + "\", already beyond that point"] "" $strict + + continue + } + + # + # NOTE: Extract and validate the field alignment. This element is + # optional; if specified, it must be either "left" or "right". + # + set fieldAlignment [string trim [lindex $field 4]] + + if {[string length $fieldAlignment] == 0} then { + set fieldAlignment right + } + + if {$fieldAlignment ni [list left right]} then { + report [appendArgs \ + "field #" $fieldIndex " has an invalid alignment \"" \ + $fieldAlignment "\", must be \"left\" or \"right\""] "" \ + $strict + + continue + } + + # + # NOTE: Extract and validate the field type. This element is + # optional; if specified, it must be either "string", + # "number", or "datetime". + # + set fieldType [string trim [lindex $field 5]] + + if {[string length $fieldType] == 0} then { + set fieldType string + } + + if {$fieldType ni [list string number datetime]} then { + report [appendArgs \ + "field #" $fieldIndex " has an invalid type \"" $fieldType \ + "\", must be \"string\", \"number\", or \"datetime\""] "" \ + $strict + + continue + } + + # + # NOTE: Extract and validate the field format. This element is + # optional. + # + set fieldFormat [lindex $field 6]; # NOTE: No trim. + + # + # NOTE: Search for the column in the list of columns. If it cannot + # be found, use an empty string for the column name and value. + # We cannot simply skip the column because the format string + # may simply be a literal string that does not require the + # column value. + # + set columnIndex [lsearch -exact $headerColumns $fieldName] + + if {$columnIndex != -1} then { + set columnName [lindex $headerColumns $columnIndex] + set columnValue $table($rowIndex,$columnName) + } else { + set columnName "" + set columnValue "" + } + + # + # HACK: Perform any replacements specified by the caller. This is + # done in two phases. Typically, the first phase is used to + # escape characters (e.g. by converting them to HTML entities) + # and the second phase is [optionally] used to undo any double + # escapes that may have been created during the first phase. + # + if {[llength $maps] > 0} then { + foreach map $maps { + if {[llength $map] > 0} then { + set columnValue [string map $map $columnValue] + } + } + } + + # + # HACK: Perform any regular expression replacements specified by the + # caller. + # + if {[llength $regsubs] > 0} then { + foreach regsub $regsubs { + # + # NOTE: Each element in the list must have exactly 2 elements. + # The first element must be the regular expression. The + # second element must be the replacement pattern. + # + if {[llength $regsub] == 2} then { + regsub -all -- [lindex $regsub 0] $columnValue \ + [lindex $regsub 1] columnValue + } + } + } + + # + # NOTE: Check if an explicit format string was specified. If so, + # use the appropriate formatting command for the data type. + # + if {[string length $fieldFormat] > 0} then { + switch -exact -- $fieldType { + string { + set columnValue [object invoke String Format \ + $fieldFormat $columnValue] + } + number { + set columnValue [format $fieldFormat $columnValue] + } + datetime { + if {[string length $columnValue] > 0 && \ + ![string is integer -strict $columnValue]} then { + # + # NOTE: The value is not an integer; therefore, + # try to scan it as a date and/or time. + # + set columnValue [clock scan $columnValue] + } + + set columnValue [clock format $columnValue \ + -format $fieldFormat] + } + default { + report [appendArgs \ + "field #" $fieldIndex " has bad type \"" \ + $fieldAlignment \"] "" $strict + + continue + } + } + } + + # + # NOTE: Check the formatted column length against the field width. + # If the formatted column length is greater, it must be + # truncated. Otherwise, if the formatted column length is + # less, it must be padded according to the field alignment. + # + set columnLength [string length $columnValue] + + if {$columnLength > $fieldWidth} then { + # + # NOTE: Truncate the string; otherwise, it will not fit within + # the field. + # + if {$fieldAlignment eq "left"} then { + set columnValue [string range $columnValue \ + [expr {$columnLength - $fieldWidth}] end] + } else { + set columnValue [string range $columnValue \ + 0 [expr {$fieldWidth - 1}]] + } + + report [appendArgs \ + "column \"" $columnName "\" value at row #" $rowIndex \ + " (length " $columnLength ") exceeds width of field #" \ + $fieldIndex " (width " $fieldWidth "), truncated"] "" \ + $strict + } else { + set padding [string repeat " " \ + [expr {$fieldWidth - $columnLength}]] + + if {$fieldAlignment eq "left"} then { + set columnValue [appendArgs $columnValue $padding] + } else { + set columnValue [appendArgs $padding $columnValue] + } + } + + # + # NOTE: If this field starts at some point after the end of the + # row value built so far, pad it. + # + if {$fieldStart > $rowLength} then { + set padding [string repeat " " \ + [expr {$fieldStart - $rowLength}]] + } else { + set padding "" + } + + # + # NOTE: Append the necessary padding and the final column value + # to the row value. + # + append rowValue $padding $columnValue + } + + # + # NOTE: Append the row value to the overall data block to export. + # + append data $rowValue + + incr table(exported) + putsStdout -nonewline * + } + + writeFile $fileName $data + } + + proc exportSQLite { + tableName fileName {sql ""} {maps ""} {regsubs ""} {strict 0} } { + # + # NOTE: Export the in-memory table to the specified SQLite + # database file. + # + try { + set connection [sql open -type SQLite \ + [subst {Data Source=${fileName}}]] + + # + # NOTE: If custom SQL was specified, execute it against + # the database connection now. + # + if {[string length $sql] > 0} then { + sql execute $connection $sql + } + + # + # NOTE: Using the table name, access the in-memory table + # from the calling context. By convention, the + # variable name will be "_rows". + # + upvar 1 [appendArgs $tableName _rows] table + + set headerColumns $table(columns) + set columnCount [llength $headerColumns] + + # + # NOTE: Wraps the column name in square brackets. + # + set wrap [list [list x] { return [appendArgs \[ $x \]] }] + + # + # NOTE: Build the parameterized SQL statement to execute an + # INSERT (or UPDATE) of a single row. + # + set rowSql [appendArgs \ + "INSERT OR REPLACE INTO \[" $tableName "\] (" \ + [join [map $headerColumns {apply $wrap}] ,] ") VALUES(" \ + [join [lrepeat $columnCount ?] ,] ");"] + + # + # NOTE: Build the per-row script to evaluate for adding or + # updating a row in the database. + # + set script {eval sql execute -verbatim \ + [list $connection] [list $rowSql] $columnParams} + + # + # NOTE: So far, we have not exported any rows. + # + set table(exported) 0 + + # + # NOTE: Grab the necessary metadata from the table array. + # + set rowCount $table(count) + set startIndex $table(startIndex) + set rowIndex $startIndex + + putsStdout [appendArgs "\n\nAttempting to export " $rowCount \ + " rows starting at index " $rowIndex "...\n"] + + # + # NOTE: Process each row in the passed-in array. There is no loop + # initializer here, see above. + # + for {} {$rowIndex < $rowCount + $startIndex} {incr rowIndex} { + set columnParams [list] + + # + # NOTE: Process each column value for this row and add it to the + # list of parameters for the SQL statement to execute. + # + set columnIndex 0 + + for {} {$columnIndex < $columnCount} {incr columnIndex} { + set columnName [lindex $headerColumns $columnIndex] + set columnValue $table($rowIndex,$columnName) + + # + # HACK: Perform any replacements specified by the caller. This is + # done in two phases. Typically, the first phase is used to + # escape characters (e.g. by converting them to HTML entities) + # and the second phase is [optionally] used to undo any double + # escapes that may have been created during the first phase. + # + if {[llength $maps] > 0} then { + foreach map $maps { + if {[llength $map] > 0} then { + set columnValue [string map $map $columnValue] + } + } + } + + # + # HACK: Perform any regular expression replacements specified by the + # caller. + # + if {[llength $regsubs] > 0} then { + foreach regsub $regsubs { + # + # NOTE: Each element in the list must have exactly 2 elements. + # The first element must be the regular expression. The + # second element must be the replacement pattern. + # + if {[llength $regsub] == 2} then { + regsub -all -- [lindex $regsub 0] $columnValue \ + [lindex $regsub 1] columnValue + } + } + } + + # + # HACK: Make dates conform to the format needed by SQLite. + # + if {[regexp -- {^\d{4}/\d{1,2}/\d{1,2}$} $columnValue]} then { + set dateTime [object invoke -alias DateTime Parse $columnValue] + set columnValue [$dateTime ToString yyyy-MM-dd] + } + + # + # NOTE: Make sure to omit the parameter value if the column value + # needs to be a literal NULL. + # + set columnParam [list [appendArgs param $columnIndex] String] + + if {$columnValue ne "NULL"} then { + lappend columnParam $columnValue + } + + # + # NOTE: Add the parameter for this column to the list of parameters + # to pass to the command. + # + lappend columnParams $columnParam + } + + # + # NOTE: Evaluate the per-row script used to actually insert or + # update a row in the database. Catch and report on any + # errors we encounter. + # + if {[catch $script error] != 0} then { + report [appendArgs "sql statement error: " $error] \ + [list $rowSql $columnParams] $strict + } else { + # + # NOTE: We successfully imported another row. + # + incr table(exported) + } + + putsStdout -nonewline * + } + } finally { + if {[info exists connection]} then { + sql close $connection; unset connection + } + } + } + + # + # NOTE: Provide the Eagle library package to the interpreter. + # + package provide Eagle.Data \ + [expr {[isEagle] ? [info engine PatchLevel] : "1.0"}] +} + ADDED eagle/1.0/neutral/data1.0/data.eagle.asc Index: eagle/1.0/neutral/data1.0/data.eagle.asc ================================================================== --- eagle/1.0/neutral/data1.0/data.eagle.asc +++ eagle/1.0/neutral/data1.0/data.eagle.asc @@ -0,0 +1,18 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2 +Comment: Eagle Package Repository + +iQIcBAABCAAGBQJX1JQWAAoJEFAslq9JXcLZnPcQAKjLrT+W439ps4nNxAMcCcgC +5p6UoMXwr9+34ffTi41jK3tN5cptUOe8PKhROG6FTJrJclNZFqkRJagVGKdcs3ED +ykGKDLOSwI547jJNGKqfhrd199GsVr+cmhEI64+6j9U5RltKQtF+whJx89werTWd +tRPedr09ET4QOW/W66Q0s7UjljEZZqkz2ErepBFhPLWbCWroYi6H795FxPA6nAlO +15PlR9z1p8DAF4YpKC4zRK0NMUtEh8OnH1hJQ3E+n/1gJpvYV4el2hA7Z+uZ07xP +NHT9nSKbJ8EwmVYy3+HCBduMp0X81VzMXM2kyzpeZF/tSxwi23SGZtXmc75icRa2 +iRj93h1jqhnB5+1OF7C+ezC3JesVPyngNXydPPOmKNi9AqRgUOSBRSzitBBFqE5C +Pjl/rtzDOtdrcifv1+iRYwvF3W/EGNL2b8EY+g7/rYNUFrOcEaGMWx3ID/dw4xs1 +XeEWTi0lfuiyFs6CuleCGOAqV+IgU2se4mWZ0t2A/ZihQQ9FuektGCpAeeqBqIai +KEgtZP2Chq8JBArlWc4qnMckdGyMLeJzp4ecBnWOI2yx+K0bxTHn0QxnLTvKUT0C +qr1S0l1E3TwnHiNLIuS6soDPUHevgDDSJEARiLIcT7U5N9q0pbdJCCJKDqoK1NQ+ +0W3DKj684Zcn+SYzGDQ3 +=UI7f +-----END PGP SIGNATURE----- ADDED eagle/1.0/neutral/data1.0/data.eagle.harpy Index: eagle/1.0/neutral/data1.0/data.eagle.harpy ================================================================== --- eagle/1.0/neutral/data1.0/data.eagle.harpy +++ eagle/1.0/neutral/data1.0/data.eagle.harpy @@ -0,0 +1,68 @@ + + + + None + Mistachkin Systems + 53cac383-800a-4e1a-ac9f-54d79a848e29 + SHA512 + Script + 2016-08-23T04:09:36.0449687Z + -1.00:00:00 + 0x9559f6017247e3e2 + + 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 + + ADDED eagle/1.0/neutral/data1.0/data.eagle.harpy.asc Index: eagle/1.0/neutral/data1.0/data.eagle.harpy.asc ================================================================== --- eagle/1.0/neutral/data1.0/data.eagle.harpy.asc +++ eagle/1.0/neutral/data1.0/data.eagle.harpy.asc @@ -0,0 +1,18 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2 +Comment: Eagle Package Repository + +iQIcBAABCAAGBQJX1JQYAAoJEFAslq9JXcLZeJQQALuSwisANovxPGdhduKX0r+r +E54ESvS08wGUsQTWvlb+SuvEhScTbtZevQXgXCX60CqFRYLbskeaMkZkNl8JeXks +SoiD0OqEnuDMgOjF9CgnRTnsxK3y7jR4birycxH2IvVbS8TpTD/6Wl+A61zb0mwD +9NB1R0DE6Ty0R4a5TDa6SWKRKwhE1hQOIm9X4ZGnL+zXYc90vBjeIaeYb9hlTDMU +v6qvwok20JPaaOdDzNVVSDY25/p4q8HPsntTFBKEnlzjtMXoj2WhPpLi0uzFFRhI +wpFpMeNVRUiQuEE0k5eHPFgSGzpEggObHEbEElPAySnWqvmCsEMdqqCDFKa0Rlkp +go9Ab3YnXLQZcsm7NOM+uan+U0giglxWNY27+Lna6QpLGIg3UZsTFbpdpSVrCxMt +zdOMfl+KYQt8NIvZwbX6OEURXYvgrJrIPQkrFH2LxgGT5Bx999ZFSSnyqjXN3Cb+ +XbJyoMWhuFY6dGkkCZLyitUz/esCn700EvVjmyKyM7gmUyPMSnVmQ3YNiY6GLF+6 +Pg2SJU6uFKsgSQoyHHzaJtrSyi2oA+Qu7KaqF/sfDcPPXTxrztwGn1xLhsHvFTiT +F4+0Jj2+1iclj+STMDbkUcn5MZQS7JeP90Mr1UAvCWA3gDPA0ZyLgbVPddc7Kadj +R+b87Ovem+vY4CKtpy7L +=5Nek +-----END PGP SIGNATURE----- ADDED eagle/1.0/neutral/data1.0/pkgIndex.eagle Index: eagle/1.0/neutral/data1.0/pkgIndex.eagle ================================================================== --- eagle/1.0/neutral/data1.0/pkgIndex.eagle +++ eagle/1.0/neutral/data1.0/pkgIndex.eagle @@ -0,0 +1,20 @@ +############################################################################### +# +# pkgIndex.eagle -- +# +# Extensible Adaptable Generalized Logic Engine (Eagle) +# Package Index File +# +# Copyright (c) 2007-2012 by Joe Mistachkin. All rights reserved. +# +# See the file "license.terms" for information on usage and redistribution of +# this file, and for a DISCLAIMER OF ALL WARRANTIES. +# +# RCS: @(#) $Id: $ +# +############################################################################### + +if {![package vsatisfies [package provide Tcl] 8.4]} {return} +if {![package vsatisfies [package provide Eagle] 1.0]} {return} + +package ifneeded Eagle.Data 1.0 [list source [file join $dir data.eagle]] ADDED eagle/1.0/neutral/data1.0/pkgIndex.eagle.asc Index: eagle/1.0/neutral/data1.0/pkgIndex.eagle.asc ================================================================== --- eagle/1.0/neutral/data1.0/pkgIndex.eagle.asc +++ eagle/1.0/neutral/data1.0/pkgIndex.eagle.asc @@ -0,0 +1,18 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2 +Comment: Eagle Package Repository + +iQIcBAABCAAGBQJX1JQcAAoJEFAslq9JXcLZZL0QAKPsxh3L1x5LYZ5r2KNO6hPZ +P5T/7zFPyRLoIbqRvBdgeKMH4+yYlvYHVgPO4oiUNz9g03CZoh/GLZHt21twXVA2 +gzMlf68e1L2aNHpiqeR9LXbC1UpHPLFoCv28Gnk7F2UUk4cR/9CkcK38J2kMRNVD +2sAWJM/bNsVJ3rz3A/b9dGIemAQZjZ4SRB3M1ecZaFqGo9wrhCGfMcDavoGHkR+7 +VX3dy3qvLWEEgnuBb10QdyAx2ORAry45UtrmuTUVFfQIk5f775vvefe5gxjKGNW3 ++8eYPPuIwWMgx3VANL0J7xf7sOxuA0MjdQhCnpAV2aIIlhY07rEZtdsY65LNF68d +hExh2fGQeVzAayM8/zl8Tcy8nnInQag8lDOcfOchd8gae+f34HJ5ENxUVCTZUrPz +gNlQq5FQwUvAbv5jvozXqARlBdCSwYgMdxYzfOKDVN49h4wpsZ4L6AjmeMOQLGzh +l3Uem+1ToOXrbw7VFx1xUKZnzjSFbSsSNiU+F1DIfrRV1x2wloyeze63nZRmZVtn +3A96nqPEr0BdP6E0kEn1f8LEgCHGefBgq83e/O4PnvZl8BKfuM1VMRb4ohno6f0k +SgX3eMpB00ADK8mFI/TO/jrz0X33SWxlNZQpa46qRAt6pny7np/3Dpirt8I4r+fK +A2PxwRU+4e4Va3dz5/s1 +=8Sv6 +-----END PGP SIGNATURE----- ADDED eagle/1.0/neutral/data1.0/pkgIndex.eagle.harpy Index: eagle/1.0/neutral/data1.0/pkgIndex.eagle.harpy ================================================================== --- eagle/1.0/neutral/data1.0/pkgIndex.eagle.harpy +++ eagle/1.0/neutral/data1.0/pkgIndex.eagle.harpy @@ -0,0 +1,68 @@ + + + + None + Mistachkin Systems + 092bc755-f131-430f-8c7e-6ce47756ec69 + SHA512 + Script + 2016-08-23T04:43:50.7227031Z + -1.00:00:00 + 0x9559f6017247e3e2 + + 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 + + ADDED eagle/1.0/neutral/data1.0/pkgIndex.eagle.harpy.asc Index: eagle/1.0/neutral/data1.0/pkgIndex.eagle.harpy.asc ================================================================== --- eagle/1.0/neutral/data1.0/pkgIndex.eagle.harpy.asc +++ eagle/1.0/neutral/data1.0/pkgIndex.eagle.harpy.asc @@ -0,0 +1,18 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2 +Comment: Eagle Package Repository + +iQIcBAABCAAGBQJX1JQeAAoJEFAslq9JXcLZvMgQAJQ1QsszDIonrCXgSV78HpR+ ++fQQkemMyGkTKIkNz9Xd+6TwOxImLlUnPympAJ4KdlpXfpYisAAS9PxsKm1Xqdml +D2xJ1rsirXEWmt7O04+xLB/V2M3esKtDnr4dXu3m9Fv8wyC9Vujrnrr8qiftLK5h +RaQEVEAlScY67BLLQ9SX9qNYSDgA4WsLIY78pCJ6ml2eBiHRH+hJr8V1mKzxEqIK +vYP2PJ+iOkuSHuKt/JML+4QOwvG3ISMQCaGKMMFLgdMwvZmesxIGQAK2zevbMawq +LH0pdlf+XIqoRdKAhFixgpX6O8vTi0RGhGJd4uscQWpC16P/v34ZSgTsj+2ZngH9 +1aicJF6274IdQwXTvuqKy6nE27KZrHe33o+IVJQyDrtBRtpW4huFx47EEnlnDATC +L0vQnMUEfAWCz3AG+ySV3lFHBPcNixK6xet4DjP9e5xml0fRyXt5VPgVYUwKB964 +4ibQYDku5IU6DsbEISb8r67Da3AMRHrYgez1OozpIlgAt65AD4CYdLh1ZpUhIurh +pSIcFRnIfSav5xB0MuDtsBYTHUim8BhH3BPEM2a8PgLUhZzXoC+/JhH9H1QVJm3y +glkM6sMCJQcD0jIbH2O3Xdfq7JYsK/XpZVeKISEy0+qx8wzsw19wGD2tsoUQKN1H +PZzOU1KiLC4Y4D2AbIdv +=UaG8 +-----END PGP SIGNATURE----- ADDED tcl/8.4/neutral/tcllib1.15/aes/aes.tcl Index: tcl/8.4/neutral/tcllib1.15/aes/aes.tcl ================================================================== --- tcl/8.4/neutral/tcllib1.15/aes/aes.tcl +++ tcl/8.4/neutral/tcllib1.15/aes/aes.tcl @@ -0,0 +1,628 @@ +# aes.tcl - +# +# Copyright (c) 2005 Thorsten Schloermann +# Copyright (c) 2005 Pat Thoyts +# Copyright (c) 2013 Andreas Kupries +# +# A Tcl implementation of the Advanced Encryption Standard (US FIPS PUB 197) +# +# AES is a block cipher with a block size of 128 bits and a variable +# key size of 128, 192 or 256 bits. +# The algorithm works on each block as a 4x4 state array. There are 4 steps +# in each round: +# SubBytes a non-linear substitution step using a predefined S-box +# ShiftRows cyclic transposition of rows in the state matrix +# MixColumns transformation upon columns in the state matrix +# AddRoundKey application of round specific sub-key +# +# ------------------------------------------------------------------------- +# See the file "license.terms" for information on usage and redistribution +# of this file, and for a DISCLAIMER OF ALL WARRANTIES. +# ------------------------------------------------------------------------- + +package require Tcl 8.2 + +namespace eval ::aes { + variable version 1.1.1 + variable rcsid {$Id: aes.tcl,v 1.7 2010/07/06 19:39:00 andreas_kupries Exp $} + variable uid ; if {![info exists uid]} { set uid 0 } + + namespace export {aes} + + # constants + + # S-box + variable sbox { + 0x63 0x7c 0x77 0x7b 0xf2 0x6b 0x6f 0xc5 0x30 0x01 0x67 0x2b 0xfe 0xd7 0xab 0x76 + 0xca 0x82 0xc9 0x7d 0xfa 0x59 0x47 0xf0 0xad 0xd4 0xa2 0xaf 0x9c 0xa4 0x72 0xc0 + 0xb7 0xfd 0x93 0x26 0x36 0x3f 0xf7 0xcc 0x34 0xa5 0xe5 0xf1 0x71 0xd8 0x31 0x15 + 0x04 0xc7 0x23 0xc3 0x18 0x96 0x05 0x9a 0x07 0x12 0x80 0xe2 0xeb 0x27 0xb2 0x75 + 0x09 0x83 0x2c 0x1a 0x1b 0x6e 0x5a 0xa0 0x52 0x3b 0xd6 0xb3 0x29 0xe3 0x2f 0x84 + 0x53 0xd1 0x00 0xed 0x20 0xfc 0xb1 0x5b 0x6a 0xcb 0xbe 0x39 0x4a 0x4c 0x58 0xcf + 0xd0 0xef 0xaa 0xfb 0x43 0x4d 0x33 0x85 0x45 0xf9 0x02 0x7f 0x50 0x3c 0x9f 0xa8 + 0x51 0xa3 0x40 0x8f 0x92 0x9d 0x38 0xf5 0xbc 0xb6 0xda 0x21 0x10 0xff 0xf3 0xd2 + 0xcd 0x0c 0x13 0xec 0x5f 0x97 0x44 0x17 0xc4 0xa7 0x7e 0x3d 0x64 0x5d 0x19 0x73 + 0x60 0x81 0x4f 0xdc 0x22 0x2a 0x90 0x88 0x46 0xee 0xb8 0x14 0xde 0x5e 0x0b 0xdb + 0xe0 0x32 0x3a 0x0a 0x49 0x06 0x24 0x5c 0xc2 0xd3 0xac 0x62 0x91 0x95 0xe4 0x79 + 0xe7 0xc8 0x37 0x6d 0x8d 0xd5 0x4e 0xa9 0x6c 0x56 0xf4 0xea 0x65 0x7a 0xae 0x08 + 0xba 0x78 0x25 0x2e 0x1c 0xa6 0xb4 0xc6 0xe8 0xdd 0x74 0x1f 0x4b 0xbd 0x8b 0x8a + 0x70 0x3e 0xb5 0x66 0x48 0x03 0xf6 0x0e 0x61 0x35 0x57 0xb9 0x86 0xc1 0x1d 0x9e + 0xe1 0xf8 0x98 0x11 0x69 0xd9 0x8e 0x94 0x9b 0x1e 0x87 0xe9 0xce 0x55 0x28 0xdf + 0x8c 0xa1 0x89 0x0d 0xbf 0xe6 0x42 0x68 0x41 0x99 0x2d 0x0f 0xb0 0x54 0xbb 0x16 + } + # inverse S-box + variable xobs { + 0x52 0x09 0x6a 0xd5 0x30 0x36 0xa5 0x38 0xbf 0x40 0xa3 0x9e 0x81 0xf3 0xd7 0xfb + 0x7c 0xe3 0x39 0x82 0x9b 0x2f 0xff 0x87 0x34 0x8e 0x43 0x44 0xc4 0xde 0xe9 0xcb + 0x54 0x7b 0x94 0x32 0xa6 0xc2 0x23 0x3d 0xee 0x4c 0x95 0x0b 0x42 0xfa 0xc3 0x4e + 0x08 0x2e 0xa1 0x66 0x28 0xd9 0x24 0xb2 0x76 0x5b 0xa2 0x49 0x6d 0x8b 0xd1 0x25 + 0x72 0xf8 0xf6 0x64 0x86 0x68 0x98 0x16 0xd4 0xa4 0x5c 0xcc 0x5d 0x65 0xb6 0x92 + 0x6c 0x70 0x48 0x50 0xfd 0xed 0xb9 0xda 0x5e 0x15 0x46 0x57 0xa7 0x8d 0x9d 0x84 + 0x90 0xd8 0xab 0x00 0x8c 0xbc 0xd3 0x0a 0xf7 0xe4 0x58 0x05 0xb8 0xb3 0x45 0x06 + 0xd0 0x2c 0x1e 0x8f 0xca 0x3f 0x0f 0x02 0xc1 0xaf 0xbd 0x03 0x01 0x13 0x8a 0x6b + 0x3a 0x91 0x11 0x41 0x4f 0x67 0xdc 0xea 0x97 0xf2 0xcf 0xce 0xf0 0xb4 0xe6 0x73 + 0x96 0xac 0x74 0x22 0xe7 0xad 0x35 0x85 0xe2 0xf9 0x37 0xe8 0x1c 0x75 0xdf 0x6e + 0x47 0xf1 0x1a 0x71 0x1d 0x29 0xc5 0x89 0x6f 0xb7 0x62 0x0e 0xaa 0x18 0xbe 0x1b + 0xfc 0x56 0x3e 0x4b 0xc6 0xd2 0x79 0x20 0x9a 0xdb 0xc0 0xfe 0x78 0xcd 0x5a 0xf4 + 0x1f 0xdd 0xa8 0x33 0x88 0x07 0xc7 0x31 0xb1 0x12 0x10 0x59 0x27 0x80 0xec 0x5f + 0x60 0x51 0x7f 0xa9 0x19 0xb5 0x4a 0x0d 0x2d 0xe5 0x7a 0x9f 0x93 0xc9 0x9c 0xef + 0xa0 0xe0 0x3b 0x4d 0xae 0x2a 0xf5 0xb0 0xc8 0xeb 0xbb 0x3c 0x83 0x53 0x99 0x61 + 0x17 0x2b 0x04 0x7e 0xba 0x77 0xd6 0x26 0xe1 0x69 0x14 0x63 0x55 0x21 0x0c 0x7d + } +} + +# aes::Init -- +# +# Initialise our AES state and calculate the key schedule. An initialization +# vector is maintained in the state for modes that require one. The key must +# be binary data of the correct size and the IV must be 16 bytes. +# +# Nk: columns of the key-array +# Nr: number of rounds (depends on key-length) +# Nb: columns of the text-block, is always 4 in AES +# +proc ::aes::Init {mode key iv} { + switch -exact -- $mode { + ecb - cbc { } + cfb - ofb { + return -code error "$mode mode not implemented" + } + default { + return -code error "invalid mode \"$mode\":\ + must be one of ecb or cbc." + } + } + + set size [expr {[string length $key] << 3}] + switch -exact -- $size { + 128 {set Nk 4; set Nr 10; set Nb 4} + 192 {set Nk 6; set Nr 12; set Nb 4} + 256 {set Nk 8; set Nr 14; set Nb 4} + default { + return -code error "invalid key size \"$size\":\ + must be one of 128, 192 or 256." + } + } + + variable uid + set Key [namespace current]::[incr uid] + upvar #0 $Key state + array set state [list M $mode K $key I $iv Nk $Nk Nr $Nr Nb $Nb W {}] + ExpandKey $Key + return $Key +} + +# aes::Reset -- +# +# Reset the initialization vector for the specified key. This permits the +# key to be reused for encryption or decryption without the expense of +# re-calculating the key schedule. +# +proc ::aes::Reset {Key iv} { + upvar #0 $Key state + set state(I) $iv + return +} + +# aes::Final -- +# +# Clean up the key state +# +proc ::aes::Final {Key} { + # FRINK: nocheck + unset $Key +} + +# ------------------------------------------------------------------------- + +# 5.1 Cipher: Encipher a single block of 128 bits. +proc ::aes::EncryptBlock {Key block} { + upvar #0 $Key state + if {[binary scan $block I4 data] != 1} { + return -code error "invalid block size: blocks must be 16 bytes" + } + + if {[string equal $state(M) cbc]} { + if {[binary scan $state(I) I4 iv] != 1} { + return -code error "invalid initialization vector: must be 16 bytes" + } + for {set n 0} {$n < 4} {incr n} { + lappend data2 [expr {0xffffffff & ([lindex $data $n] ^ [lindex $iv $n])}] + } + set data $data2 + } + + set data [AddRoundKey $Key 0 $data] + for {set n 1} {$n < $state(Nr)} {incr n} { + set data [AddRoundKey $Key $n [MixColumns [ShiftRows [SubBytes $data]]]] + } + set data [AddRoundKey $Key $n [ShiftRows [SubBytes $data]]] + + # Bug 2993029: + # Force all elements of data into the 32bit range. + set res {} + foreach d $data { + lappend res [expr {$d & 0xffffffff}] + } + set data $res + + return [set state(I) [binary format I4 $data]] +} + +# 5.3: Inverse Cipher: Decipher a single 128 bit block. +proc ::aes::DecryptBlock {Key block} { + upvar #0 $Key state + if {[binary scan $block I4 data] != 1} { + return -code error "invalid block size: block must be 16 bytes" + } + + set n $state(Nr) + set data [AddRoundKey $Key $state(Nr) $data] + for {incr n -1} {$n > 0} {incr n -1} { + set data [InvMixColumns [AddRoundKey $Key $n [InvSubBytes [InvShiftRows $data]]]] + } + set data [AddRoundKey $Key $n [InvSubBytes [InvShiftRows $data]]] + + if {[string equal $state(M) cbc]} { + if {[binary scan $state(I) I4 iv] != 1} { + return -code error "invalid initialization vector: must be 16 bytes" + } + for {set n 0} {$n < 4} {incr n} { + lappend data2 [expr {0xffffffff & ([lindex $data $n] ^ [lindex $iv $n])}] + } + set data $data2 + } else { + # Bug 2993029: + # Force all elements of data into the 32bit range. + # The trimming we see above only happens for CBC mode. + set res {} + foreach d $data { + lappend res [expr {$d & 0xffffffff}] + } + set data $res + } + + set state(I) $block + return [binary format I4 $data] +} + +# 5.2: KeyExpansion +proc ::aes::ExpandKey {Key} { + upvar #0 $Key state + set Rcon [list 0x00000000 0x01000000 0x02000000 0x04000000 0x08000000 \ + 0x10000000 0x20000000 0x40000000 0x80000000 0x1b000000 \ + 0x36000000 0x6c000000 0xd8000000 0xab000000 0x4d000000] + # Split the key into Nk big-endian words + binary scan $state(K) I* W + set max [expr {$state(Nb) * ($state(Nr) + 1)}] + set i $state(Nk) + set h $state(Nk) ; incr h -1 + set j 0 + for {} {$i < $max} {incr i; incr h; incr j} { + set temp [lindex $W $h] + if {($i % $state(Nk)) == 0} { + set sub [SubWord [RotWord $temp]] + set rc [lindex $Rcon [expr {$i/$state(Nk)}]] + set temp [expr {$sub ^ $rc}] + } elseif {$state(Nk) > 6 && ($i % $state(Nk)) == 4} { + set temp [SubWord $temp] + } + lappend W [expr {[lindex $W $j] ^ $temp}] + } + set state(W) $W + return +} + +# 5.2: Key Expansion: Apply S-box to each byte in the 32 bit word +proc ::aes::SubWord {w} { + variable sbox + set s3 [lindex $sbox [expr {(($w >> 24) & 255)}]] + set s2 [lindex $sbox [expr {(($w >> 16) & 255)}]] + set s1 [lindex $sbox [expr {(($w >> 8 ) & 255)}]] + set s0 [lindex $sbox [expr {( $w & 255)}]] + return [expr {($s3 << 24) | ($s2 << 16) | ($s1 << 8) | $s0}] +} + +proc ::aes::InvSubWord {w} { + variable xobs + set s3 [lindex $xobs [expr {(($w >> 24) & 255)}]] + set s2 [lindex $xobs [expr {(($w >> 16) & 255)}]] + set s1 [lindex $xobs [expr {(($w >> 8 ) & 255)}]] + set s0 [lindex $xobs [expr {( $w & 255)}]] + return [expr {($s3 << 24) | ($s2 << 16) | ($s1 << 8) | $s0}] +} + +# 5.2: Key Expansion: Rotate a 32bit word by 8 bits +proc ::aes::RotWord {w} { + return [expr {(($w << 8) | (($w >> 24) & 0xff)) & 0xffffffff}] +} + +# 5.1.1: SubBytes() Transformation +proc ::aes::SubBytes {words} { + set r {} + foreach w $words { + lappend r [SubWord $w] + } + return $r +} + +# 5.3.2: InvSubBytes() Transformation +proc ::aes::InvSubBytes {words} { + set r {} + foreach w $words { + lappend r [InvSubWord $w] + } + return $r +} + +# 5.1.2: ShiftRows() Transformation +proc ::aes::ShiftRows {words} { + for {set n0 0} {$n0 < 4} {incr n0} { + set n1 [expr {($n0 + 1) % 4}] + set n2 [expr {($n0 + 2) % 4}] + set n3 [expr {($n0 + 3) % 4}] + lappend r [expr {( [lindex $words $n0] & 0xff000000) + | ([lindex $words $n1] & 0x00ff0000) + | ([lindex $words $n2] & 0x0000ff00) + | ([lindex $words $n3] & 0x000000ff) + }] + } + return $r +} + + +# 5.3.1: InvShiftRows() Transformation +proc ::aes::InvShiftRows {words} { + for {set n0 0} {$n0 < 4} {incr n0} { + set n1 [expr {($n0 + 1) % 4}] + set n2 [expr {($n0 + 2) % 4}] + set n3 [expr {($n0 + 3) % 4}] + lappend r [expr {( [lindex $words $n0] & 0xff000000) + | ([lindex $words $n3] & 0x00ff0000) + | ([lindex $words $n2] & 0x0000ff00) + | ([lindex $words $n1] & 0x000000ff) + }] + } + return $r +} + +# 5.1.3: MixColumns() Transformation +proc ::aes::MixColumns {words} { + set r {} + foreach w $words { + set r0 [expr {(($w >> 24) & 255)}] + set r1 [expr {(($w >> 16) & 255)}] + set r2 [expr {(($w >> 8 ) & 255)}] + set r3 [expr {( $w & 255)}] + + set s0 [expr {[GFMult2 $r0] ^ [GFMult3 $r1] ^ $r2 ^ $r3}] + set s1 [expr {$r0 ^ [GFMult2 $r1] ^ [GFMult3 $r2] ^ $r3}] + set s2 [expr {$r0 ^ $r1 ^ [GFMult2 $r2] ^ [GFMult3 $r3]}] + set s3 [expr {[GFMult3 $r0] ^ $r1 ^ $r2 ^ [GFMult2 $r3]}] + + lappend r [expr {($s0 << 24) | ($s1 << 16) | ($s2 << 8) | $s3}] + } + return $r +} + +# 5.3.3: InvMixColumns() Transformation +proc ::aes::InvMixColumns {words} { + set r {} + foreach w $words { + set r0 [expr {(($w >> 24) & 255)}] + set r1 [expr {(($w >> 16) & 255)}] + set r2 [expr {(($w >> 8 ) & 255)}] + set r3 [expr {( $w & 255)}] + + set s0 [expr {[GFMult0e $r0] ^ [GFMult0b $r1] ^ [GFMult0d $r2] ^ [GFMult09 $r3]}] + set s1 [expr {[GFMult09 $r0] ^ [GFMult0e $r1] ^ [GFMult0b $r2] ^ [GFMult0d $r3]}] + set s2 [expr {[GFMult0d $r0] ^ [GFMult09 $r1] ^ [GFMult0e $r2] ^ [GFMult0b $r3]}] + set s3 [expr {[GFMult0b $r0] ^ [GFMult0d $r1] ^ [GFMult09 $r2] ^ [GFMult0e $r3]}] + + lappend r [expr {($s0 << 24) | ($s1 << 16) | ($s2 << 8) | $s3}] + } + return $r +} + +# 5.1.4: AddRoundKey() Transformation +proc ::aes::AddRoundKey {Key round words} { + upvar #0 $Key state + set r {} + set n [expr {$round * $state(Nb)}] + foreach w $words { + lappend r [expr {$w ^ [lindex $state(W) $n]}] + incr n + } + return $r +} + +# ------------------------------------------------------------------------- +# ::aes::GFMult* +# +# some needed functions for multiplication in a Galois-field +# +proc ::aes::GFMult2 {number} { + # this is a tabular representation of xtime (multiplication by 2) + # it is used instead of calculation to prevent timing attacks + set xtime { + 0x00 0x02 0x04 0x06 0x08 0x0a 0x0c 0x0e 0x10 0x12 0x14 0x16 0x18 0x1a 0x1c 0x1e + 0x20 0x22 0x24 0x26 0x28 0x2a 0x2c 0x2e 0x30 0x32 0x34 0x36 0x38 0x3a 0x3c 0x3e + 0x40 0x42 0x44 0x46 0x48 0x4a 0x4c 0x4e 0x50 0x52 0x54 0x56 0x58 0x5a 0x5c 0x5e + 0x60 0x62 0x64 0x66 0x68 0x6a 0x6c 0x6e 0x70 0x72 0x74 0x76 0x78 0x7a 0x7c 0x7e + 0x80 0x82 0x84 0x86 0x88 0x8a 0x8c 0x8e 0x90 0x92 0x94 0x96 0x98 0x9a 0x9c 0x9e + 0xa0 0xa2 0xa4 0xa6 0xa8 0xaa 0xac 0xae 0xb0 0xb2 0xb4 0xb6 0xb8 0xba 0xbc 0xbe + 0xc0 0xc2 0xc4 0xc6 0xc8 0xca 0xcc 0xce 0xd0 0xd2 0xd4 0xd6 0xd8 0xda 0xdc 0xde + 0xe0 0xe2 0xe4 0xe6 0xe8 0xea 0xec 0xee 0xf0 0xf2 0xf4 0xf6 0xf8 0xfa 0xfc 0xfe + 0x1b 0x19 0x1f 0x1d 0x13 0x11 0x17 0x15 0x0b 0x09 0x0f 0x0d 0x03 0x01 0x07 0x05 + 0x3b 0x39 0x3f 0x3d 0x33 0x31 0x37 0x35 0x2b 0x29 0x2f 0x2d 0x23 0x21 0x27 0x25 + 0x5b 0x59 0x5f 0x5d 0x53 0x51 0x57 0x55 0x4b 0x49 0x4f 0x4d 0x43 0x41 0x47 0x45 + 0x7b 0x79 0x7f 0x7d 0x73 0x71 0x77 0x75 0x6b 0x69 0x6f 0x6d 0x63 0x61 0x67 0x65 + 0x9b 0x99 0x9f 0x9d 0x93 0x91 0x97 0x95 0x8b 0x89 0x8f 0x8d 0x83 0x81 0x87 0x85 + 0xbb 0xb9 0xbf 0xbd 0xb3 0xb1 0xb7 0xb5 0xab 0xa9 0xaf 0xad 0xa3 0xa1 0xa7 0xa5 + 0xdb 0xd9 0xdf 0xdd 0xd3 0xd1 0xd7 0xd5 0xcb 0xc9 0xcf 0xcd 0xc3 0xc1 0xc7 0xc5 + 0xfb 0xf9 0xff 0xfd 0xf3 0xf1 0xf7 0xf5 0xeb 0xe9 0xef 0xed 0xe3 0xe1 0xe7 0xe5 + } + return [lindex $xtime $number] +} + +proc ::aes::GFMult3 {number} { + # multliply by 2 (via GFMult2) and add the number again on the result (via XOR) + return [expr {$number ^ [GFMult2 $number]}] +} + +proc ::aes::GFMult09 {number} { + # 09 is: (02*02*02) + 01 + return [expr {[GFMult2 [GFMult2 [GFMult2 $number]]] ^ $number}] +} + +proc ::aes::GFMult0b {number} { + # 0b is: (02*02*02) + 02 + 01 + #return [expr [GFMult2 [GFMult2 [GFMult2 $number]]] ^ [GFMult2 $number] ^ $number] + #set g0 [GFMult2 $number] + return [expr {[GFMult09 $number] ^ [GFMult2 $number]}] +} + +proc ::aes::GFMult0d {number} { + # 0d is: (02*02*02) + (02*02) + 01 + set temp [GFMult2 [GFMult2 $number]] + return [expr {[GFMult2 $temp] ^ ($temp ^ $number)}] +} + +proc ::aes::GFMult0e {number} { + # 0e is: (02*02*02) + (02*02) + 02 + set temp [GFMult2 [GFMult2 $number]] + return [expr {[GFMult2 $temp] ^ ($temp ^ [GFMult2 $number])}] +} + +# ------------------------------------------------------------------------- + +# aes::Encrypt -- +# +# Encrypt a blocks of plain text and returns blocks of cipher text. +# The input data must be a multiple of the block size (16). +# +proc ::aes::Encrypt {Key data} { + set len [string length $data] + if {($len % 16) != 0} { + return -code error "invalid block size: AES requires 16 byte blocks" + } + + set result {} + for {set i 0} {$i < $len} {incr i 1} { + set block [string range $data $i [incr i 15]] + append result [EncryptBlock $Key $block] + } + return $result +} + +# aes::DecryptBlock -- +# +# Decrypt a blocks of cipher text and returns blocks of plain text. +# The input data must be a multiple of the block size (16). +# +proc ::aes::Decrypt {Key data} { + set len [string length $data] + if {($len % 16) != 0} { + return -code error "invalid block size: AES requires 16 byte blocks" + } + + set result {} + for {set i 0} {$i < $len} {incr i 1} { + set block [string range $data $i [incr i 15]] + append result [DecryptBlock $Key $block] + } + return $result +} + +# ------------------------------------------------------------------------- +# Fileevent handler for chunked file reading. +# +proc ::aes::Chunk {Key in {out {}} {chunksize 4096}} { + upvar #0 $Key state + + #puts ||CHUNK.X||i=$in|o=$out|c=$chunksize|eof=[eof $in] + + if {[eof $in]} { + fileevent $in readable {} + set state(reading) 0 + } + + set data [read $in $chunksize] + + #puts ||CHUNK.R||i=$in|o=$out|c=$chunksize|eof=[eof $in]||[string length $data]||$data|| + + # Do nothing when data was read at all. + if {![string length $data]} return + + if {[eof $in]} { + #puts CHUNK.Z + set data [Pad $data 16] + } + + #puts ||CHUNK.P||i=$in|o=$out|c=$chunksize|eof=[eof $in]||[string length $data]||$data|| + + if {$out == {}} { + append state(output) [$state(cmd) $Key $data] + } else { + puts -nonewline $out [$state(cmd) $Key $data] + } +} + +proc ::aes::SetOneOf {lst item} { + set ndx [lsearch -glob $lst "${item}*"] + if {$ndx == -1} { + set err [join $lst ", "] + return -code error "invalid mode \"$item\": must be one of $err" + } + return [lindex $lst $ndx] +} + +proc ::aes::CheckSize {what size thing} { + if {[string length $thing] != $size} { + return -code error "invalid value for $what: must be $size bytes long" + } + return $thing +} + +proc ::aes::Pad {data blocksize {fill \0}} { + set len [string length $data] + if {$len == 0} { + set data [string repeat $fill $blocksize] + } elseif {($len % $blocksize) != 0} { + set pad [expr {$blocksize - ($len % $blocksize)}] + append data [string repeat $fill $pad] + } + return $data +} + +proc ::aes::Pop {varname {nth 0}} { + upvar 1 $varname args + set r [lindex $args $nth] + set args [lreplace $args $nth $nth] + return $r +} + +proc ::aes::Hex {data} { + binary scan $data H* r + return $r +} + +proc ::aes::aes {args} { + array set opts {-dir encrypt -mode cbc -key {} -in {} -out {} -chunksize 4096 -hex 0} + set opts(-iv) [string repeat \0 16] + set modes {ecb cbc} + set dirs {encrypt decrypt} + while {([llength $args] > 1) && [string match -* [set option [lindex $args 0]]]} { + switch -exact -- $option { + -mode { set opts(-mode) [SetOneOf $modes [Pop args 1]] } + -dir { set opts(-dir) [SetOneOf $dirs [Pop args 1]] } + -iv { set opts(-iv) [CheckSize -iv 16 [Pop args 1]] } + -key { set opts(-key) [Pop args 1] } + -in { set opts(-in) [Pop args 1] } + -out { set opts(-out) [Pop args 1] } + -chunksize { set opts(-chunksize) [Pop args 1] } + -hex { set opts(-hex) 1 } + -- { Pop args ; break } + default { + set err [join [lsort [array names opts]] ", "] + return -code error "bad option \"$option\":\ + must be one of $err" + } + } + Pop args + } + + if {$opts(-key) == {}} { + return -code error "no key provided: the -key option is required" + } + + set r {} + if {$opts(-in) == {}} { + + if {[llength $args] != 1} { + return -code error "wrong \# args:\ + should be \"aes ?options...? -key keydata plaintext\"" + } + + set data [Pad [lindex $args 0] 16] + set Key [Init $opts(-mode) $opts(-key) $opts(-iv)] + if {[string equal $opts(-dir) "encrypt"]} { + set r [Encrypt $Key $data] + } else { + set r [Decrypt $Key $data] + } + + if {$opts(-out) != {}} { + puts -nonewline $opts(-out) $r + set r {} + } + Final $Key + + } else { + + if {[llength $args] != 0} { + return -code error "wrong \# args:\ + should be \"aes ?options...? -key keydata -in channel\"" + } + + set Key [Init $opts(-mode) $opts(-key) $opts(-iv)] + + set readcmd [list [namespace origin Chunk] \ + $Key $opts(-in) $opts(-out) \ + $opts(-chunksize)] + + upvar 1 $Key state + set state(reading) 1 + if {[string equal $opts(-dir) "encrypt"]} { + set state(cmd) Encrypt + } else { + set state(cmd) Decrypt + } + set state(output) "" + fileevent $opts(-in) readable $readcmd + if {[info commands ::tkwait] != {}} { + tkwait variable [subst $Key](reading) + } else { + vwait [subst $Key](reading) + } + if {$opts(-out) == {}} { + set r $state(output) + } + Final $Key + } + + if {$opts(-hex)} { + set r [Hex $r] + } + return $r +} + +# ------------------------------------------------------------------------- + +package provide aes $::aes::version + +# ------------------------------------------------------------------------- +# Local variables: +# mode: tcl +# indent-tabs-mode: nil +# End: ADDED tcl/8.4/neutral/tcllib1.15/aes/aes.tcl.asc Index: tcl/8.4/neutral/tcllib1.15/aes/aes.tcl.asc ================================================================== --- tcl/8.4/neutral/tcllib1.15/aes/aes.tcl.asc +++ tcl/8.4/neutral/tcllib1.15/aes/aes.tcl.asc @@ -0,0 +1,18 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2 +Comment: Eagle Package Repository + +iQIcBAABCAAGBQJXtl6FAAoJEFAslq9JXcLZenMQAKEdxioTYCPWs5wEYERfn/8x +GklZUR/LGTNV0w0JO13BxwUsrwOC0BMI3iRhFGBNyd6J7RqkvulbfEADdzZoTofF +INfhpT+sJoXScmg1pzcJmZdUGP7vBmG6+askcVSkafZmesp6DR03lPI3x323A6dm +kJPIy87UMCB+g2L+V/+BhWJgrQloekWNUKsElcWBc3N+K3lWbx48jgkcLow5K2St +qg0paqW5T6doT6Ig27JKy71SRreMi2OsJs/HA+KxND9diC2hfVC87dkVGyoKHOJG +fsX6j+Fz3Eygg7sw+U3EIIMOj/eQiWZJ/eCn1UbxvCcGORHiQnDztTpfEIETM+dz +TNAvjWlC2ISDDJAyc1C02ok+ee+6chfJhe8aH9Fj/AK4tmJ9xXyF6FMz0yZ/F/3k +LCggJlO0eVnngjwDwGuz6czJ7VccRDgwdXtpkMJtq4yJtZOHaoYXUr6fgGoW4i3r +yOQu2Ajk/ZU9l8tTXbXWhexn+x+TbbhLUuOckEu8Mk7ID+Z2EMA4AyzvfwytbCbk +8Wi4J0gDa/cV2JvncQAlcZ6u+4mgWhMyUg8gq2bMsYwJd6/8XzEIaF4752UFiUiV +AeOdPeGeqfELAlUagLAQOuHiFAK22VU0jPTp0f8MNvSITdheI7EeUNY7gM0a7odI +hf4M9GphdltjwhC1p4FI +=kVUR +-----END PGP SIGNATURE----- ADDED tcl/8.4/neutral/tcllib1.15/aes/pkgIndex.tcl Index: tcl/8.4/neutral/tcllib1.15/aes/pkgIndex.tcl ================================================================== --- tcl/8.4/neutral/tcllib1.15/aes/pkgIndex.tcl +++ tcl/8.4/neutral/tcllib1.15/aes/pkgIndex.tcl @@ -0,0 +1,5 @@ +if {![package vsatisfies [package provide Tcl] 8.2]} { + # PRAGMA: returnok + return +} +package ifneeded aes 1.1.1 [list source [file join $dir aes.tcl]] ADDED tcl/8.4/neutral/tcllib1.15/aes/pkgIndex.tcl.asc Index: tcl/8.4/neutral/tcllib1.15/aes/pkgIndex.tcl.asc ================================================================== --- tcl/8.4/neutral/tcllib1.15/aes/pkgIndex.tcl.asc +++ tcl/8.4/neutral/tcllib1.15/aes/pkgIndex.tcl.asc @@ -0,0 +1,18 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2 +Comment: Eagle Package Repository + +iQIcBAABCAAGBQJXtl6JAAoJEFAslq9JXcLZSf4QAKFsBhYHqlALRprs1hhXArfc +jamjLJCUFZRrsU1exvmbiU/2SCsFwveL8gDHtRGvHrKZpepVSSh1vAK1DFAEW5zR +2/bnMRnmYKfbdmLe7bd8xZqRDQjgMRIq/rs5Op9bgb+AstasiQLbjvNNJt2Q56d0 +wYWSH4w5qkniJSfakXSf+4HyFcU8kSG+rvkqOqGrKqQTY0DhJVTsjAZHA6+gE3T+ +xx6mUXiJjrnU429pht4mry5d8bSEIbARYi6B9AIbaboqlgcDTaMTmNpHRDpVx+VO +F1Q/JtRsI0tMvbMhHFITzOVP+HyEax1tTm+bMArdnYvECvawwQ+rG7IudNFInZPE +EXNg+qunEUpcR+bgdhnQDqZDpslmA4ZThIxDRyAYwx6e1NddVF3uhdL2/Fatdmrs +WS1HwzZFN5nQtnKo0l9yTnp3TAo2Zjx9HhEQNo5zMAzFy5bnLrIbz2xSRL9xBIJ9 +N4EtBvPWW+IKfyLxz/mP5dkYrhUDvAxbThsR/li2HI3dhwfU7aSXVkuBMDBvrklz +8W3SHNcTHDeoB5dE9z4JTSKgZoxKBQwD5dstsSbYeykxuHVBcjL1EkLjr1iCduIu +NBCPuaLpxEEVREyN3QeHObH4+QrXPKsgE8sm5V6a2rVyfS6koBAOX+eDIlfXdo8N +B0KCHquWJYaanWwDdOTK +=53sI +-----END PGP SIGNATURE----- DELETED tcl/8.4/tcllib1.15/aes/aes.tcl Index: tcl/8.4/tcllib1.15/aes/aes.tcl ================================================================== --- tcl/8.4/tcllib1.15/aes/aes.tcl +++ tcl/8.4/tcllib1.15/aes/aes.tcl @@ -1,628 +0,0 @@ -# aes.tcl - -# -# Copyright (c) 2005 Thorsten Schloermann -# Copyright (c) 2005 Pat Thoyts -# Copyright (c) 2013 Andreas Kupries -# -# A Tcl implementation of the Advanced Encryption Standard (US FIPS PUB 197) -# -# AES is a block cipher with a block size of 128 bits and a variable -# key size of 128, 192 or 256 bits. -# The algorithm works on each block as a 4x4 state array. There are 4 steps -# in each round: -# SubBytes a non-linear substitution step using a predefined S-box -# ShiftRows cyclic transposition of rows in the state matrix -# MixColumns transformation upon columns in the state matrix -# AddRoundKey application of round specific sub-key -# -# ------------------------------------------------------------------------- -# See the file "license.terms" for information on usage and redistribution -# of this file, and for a DISCLAIMER OF ALL WARRANTIES. -# ------------------------------------------------------------------------- - -package require Tcl 8.2 - -namespace eval ::aes { - variable version 1.1.1 - variable rcsid {$Id: aes.tcl,v 1.7 2010/07/06 19:39:00 andreas_kupries Exp $} - variable uid ; if {![info exists uid]} { set uid 0 } - - namespace export {aes} - - # constants - - # S-box - variable sbox { - 0x63 0x7c 0x77 0x7b 0xf2 0x6b 0x6f 0xc5 0x30 0x01 0x67 0x2b 0xfe 0xd7 0xab 0x76 - 0xca 0x82 0xc9 0x7d 0xfa 0x59 0x47 0xf0 0xad 0xd4 0xa2 0xaf 0x9c 0xa4 0x72 0xc0 - 0xb7 0xfd 0x93 0x26 0x36 0x3f 0xf7 0xcc 0x34 0xa5 0xe5 0xf1 0x71 0xd8 0x31 0x15 - 0x04 0xc7 0x23 0xc3 0x18 0x96 0x05 0x9a 0x07 0x12 0x80 0xe2 0xeb 0x27 0xb2 0x75 - 0x09 0x83 0x2c 0x1a 0x1b 0x6e 0x5a 0xa0 0x52 0x3b 0xd6 0xb3 0x29 0xe3 0x2f 0x84 - 0x53 0xd1 0x00 0xed 0x20 0xfc 0xb1 0x5b 0x6a 0xcb 0xbe 0x39 0x4a 0x4c 0x58 0xcf - 0xd0 0xef 0xaa 0xfb 0x43 0x4d 0x33 0x85 0x45 0xf9 0x02 0x7f 0x50 0x3c 0x9f 0xa8 - 0x51 0xa3 0x40 0x8f 0x92 0x9d 0x38 0xf5 0xbc 0xb6 0xda 0x21 0x10 0xff 0xf3 0xd2 - 0xcd 0x0c 0x13 0xec 0x5f 0x97 0x44 0x17 0xc4 0xa7 0x7e 0x3d 0x64 0x5d 0x19 0x73 - 0x60 0x81 0x4f 0xdc 0x22 0x2a 0x90 0x88 0x46 0xee 0xb8 0x14 0xde 0x5e 0x0b 0xdb - 0xe0 0x32 0x3a 0x0a 0x49 0x06 0x24 0x5c 0xc2 0xd3 0xac 0x62 0x91 0x95 0xe4 0x79 - 0xe7 0xc8 0x37 0x6d 0x8d 0xd5 0x4e 0xa9 0x6c 0x56 0xf4 0xea 0x65 0x7a 0xae 0x08 - 0xba 0x78 0x25 0x2e 0x1c 0xa6 0xb4 0xc6 0xe8 0xdd 0x74 0x1f 0x4b 0xbd 0x8b 0x8a - 0x70 0x3e 0xb5 0x66 0x48 0x03 0xf6 0x0e 0x61 0x35 0x57 0xb9 0x86 0xc1 0x1d 0x9e - 0xe1 0xf8 0x98 0x11 0x69 0xd9 0x8e 0x94 0x9b 0x1e 0x87 0xe9 0xce 0x55 0x28 0xdf - 0x8c 0xa1 0x89 0x0d 0xbf 0xe6 0x42 0x68 0x41 0x99 0x2d 0x0f 0xb0 0x54 0xbb 0x16 - } - # inverse S-box - variable xobs { - 0x52 0x09 0x6a 0xd5 0x30 0x36 0xa5 0x38 0xbf 0x40 0xa3 0x9e 0x81 0xf3 0xd7 0xfb - 0x7c 0xe3 0x39 0x82 0x9b 0x2f 0xff 0x87 0x34 0x8e 0x43 0x44 0xc4 0xde 0xe9 0xcb - 0x54 0x7b 0x94 0x32 0xa6 0xc2 0x23 0x3d 0xee 0x4c 0x95 0x0b 0x42 0xfa 0xc3 0x4e - 0x08 0x2e 0xa1 0x66 0x28 0xd9 0x24 0xb2 0x76 0x5b 0xa2 0x49 0x6d 0x8b 0xd1 0x25 - 0x72 0xf8 0xf6 0x64 0x86 0x68 0x98 0x16 0xd4 0xa4 0x5c 0xcc 0x5d 0x65 0xb6 0x92 - 0x6c 0x70 0x48 0x50 0xfd 0xed 0xb9 0xda 0x5e 0x15 0x46 0x57 0xa7 0x8d 0x9d 0x84 - 0x90 0xd8 0xab 0x00 0x8c 0xbc 0xd3 0x0a 0xf7 0xe4 0x58 0x05 0xb8 0xb3 0x45 0x06 - 0xd0 0x2c 0x1e 0x8f 0xca 0x3f 0x0f 0x02 0xc1 0xaf 0xbd 0x03 0x01 0x13 0x8a 0x6b - 0x3a 0x91 0x11 0x41 0x4f 0x67 0xdc 0xea 0x97 0xf2 0xcf 0xce 0xf0 0xb4 0xe6 0x73 - 0x96 0xac 0x74 0x22 0xe7 0xad 0x35 0x85 0xe2 0xf9 0x37 0xe8 0x1c 0x75 0xdf 0x6e - 0x47 0xf1 0x1a 0x71 0x1d 0x29 0xc5 0x89 0x6f 0xb7 0x62 0x0e 0xaa 0x18 0xbe 0x1b - 0xfc 0x56 0x3e 0x4b 0xc6 0xd2 0x79 0x20 0x9a 0xdb 0xc0 0xfe 0x78 0xcd 0x5a 0xf4 - 0x1f 0xdd 0xa8 0x33 0x88 0x07 0xc7 0x31 0xb1 0x12 0x10 0x59 0x27 0x80 0xec 0x5f - 0x60 0x51 0x7f 0xa9 0x19 0xb5 0x4a 0x0d 0x2d 0xe5 0x7a 0x9f 0x93 0xc9 0x9c 0xef - 0xa0 0xe0 0x3b 0x4d 0xae 0x2a 0xf5 0xb0 0xc8 0xeb 0xbb 0x3c 0x83 0x53 0x99 0x61 - 0x17 0x2b 0x04 0x7e 0xba 0x77 0xd6 0x26 0xe1 0x69 0x14 0x63 0x55 0x21 0x0c 0x7d - } -} - -# aes::Init -- -# -# Initialise our AES state and calculate the key schedule. An initialization -# vector is maintained in the state for modes that require one. The key must -# be binary data of the correct size and the IV must be 16 bytes. -# -# Nk: columns of the key-array -# Nr: number of rounds (depends on key-length) -# Nb: columns of the text-block, is always 4 in AES -# -proc ::aes::Init {mode key iv} { - switch -exact -- $mode { - ecb - cbc { } - cfb - ofb { - return -code error "$mode mode not implemented" - } - default { - return -code error "invalid mode \"$mode\":\ - must be one of ecb or cbc." - } - } - - set size [expr {[string length $key] << 3}] - switch -exact -- $size { - 128 {set Nk 4; set Nr 10; set Nb 4} - 192 {set Nk 6; set Nr 12; set Nb 4} - 256 {set Nk 8; set Nr 14; set Nb 4} - default { - return -code error "invalid key size \"$size\":\ - must be one of 128, 192 or 256." - } - } - - variable uid - set Key [namespace current]::[incr uid] - upvar #0 $Key state - array set state [list M $mode K $key I $iv Nk $Nk Nr $Nr Nb $Nb W {}] - ExpandKey $Key - return $Key -} - -# aes::Reset -- -# -# Reset the initialization vector for the specified key. This permits the -# key to be reused for encryption or decryption without the expense of -# re-calculating the key schedule. -# -proc ::aes::Reset {Key iv} { - upvar #0 $Key state - set state(I) $iv - return -} - -# aes::Final -- -# -# Clean up the key state -# -proc ::aes::Final {Key} { - # FRINK: nocheck - unset $Key -} - -# ------------------------------------------------------------------------- - -# 5.1 Cipher: Encipher a single block of 128 bits. -proc ::aes::EncryptBlock {Key block} { - upvar #0 $Key state - if {[binary scan $block I4 data] != 1} { - return -code error "invalid block size: blocks must be 16 bytes" - } - - if {[string equal $state(M) cbc]} { - if {[binary scan $state(I) I4 iv] != 1} { - return -code error "invalid initialization vector: must be 16 bytes" - } - for {set n 0} {$n < 4} {incr n} { - lappend data2 [expr {0xffffffff & ([lindex $data $n] ^ [lindex $iv $n])}] - } - set data $data2 - } - - set data [AddRoundKey $Key 0 $data] - for {set n 1} {$n < $state(Nr)} {incr n} { - set data [AddRoundKey $Key $n [MixColumns [ShiftRows [SubBytes $data]]]] - } - set data [AddRoundKey $Key $n [ShiftRows [SubBytes $data]]] - - # Bug 2993029: - # Force all elements of data into the 32bit range. - set res {} - foreach d $data { - lappend res [expr {$d & 0xffffffff}] - } - set data $res - - return [set state(I) [binary format I4 $data]] -} - -# 5.3: Inverse Cipher: Decipher a single 128 bit block. -proc ::aes::DecryptBlock {Key block} { - upvar #0 $Key state - if {[binary scan $block I4 data] != 1} { - return -code error "invalid block size: block must be 16 bytes" - } - - set n $state(Nr) - set data [AddRoundKey $Key $state(Nr) $data] - for {incr n -1} {$n > 0} {incr n -1} { - set data [InvMixColumns [AddRoundKey $Key $n [InvSubBytes [InvShiftRows $data]]]] - } - set data [AddRoundKey $Key $n [InvSubBytes [InvShiftRows $data]]] - - if {[string equal $state(M) cbc]} { - if {[binary scan $state(I) I4 iv] != 1} { - return -code error "invalid initialization vector: must be 16 bytes" - } - for {set n 0} {$n < 4} {incr n} { - lappend data2 [expr {0xffffffff & ([lindex $data $n] ^ [lindex $iv $n])}] - } - set data $data2 - } else { - # Bug 2993029: - # Force all elements of data into the 32bit range. - # The trimming we see above only happens for CBC mode. - set res {} - foreach d $data { - lappend res [expr {$d & 0xffffffff}] - } - set data $res - } - - set state(I) $block - return [binary format I4 $data] -} - -# 5.2: KeyExpansion -proc ::aes::ExpandKey {Key} { - upvar #0 $Key state - set Rcon [list 0x00000000 0x01000000 0x02000000 0x04000000 0x08000000 \ - 0x10000000 0x20000000 0x40000000 0x80000000 0x1b000000 \ - 0x36000000 0x6c000000 0xd8000000 0xab000000 0x4d000000] - # Split the key into Nk big-endian words - binary scan $state(K) I* W - set max [expr {$state(Nb) * ($state(Nr) + 1)}] - set i $state(Nk) - set h $state(Nk) ; incr h -1 - set j 0 - for {} {$i < $max} {incr i; incr h; incr j} { - set temp [lindex $W $h] - if {($i % $state(Nk)) == 0} { - set sub [SubWord [RotWord $temp]] - set rc [lindex $Rcon [expr {$i/$state(Nk)}]] - set temp [expr {$sub ^ $rc}] - } elseif {$state(Nk) > 6 && ($i % $state(Nk)) == 4} { - set temp [SubWord $temp] - } - lappend W [expr {[lindex $W $j] ^ $temp}] - } - set state(W) $W - return -} - -# 5.2: Key Expansion: Apply S-box to each byte in the 32 bit word -proc ::aes::SubWord {w} { - variable sbox - set s3 [lindex $sbox [expr {(($w >> 24) & 255)}]] - set s2 [lindex $sbox [expr {(($w >> 16) & 255)}]] - set s1 [lindex $sbox [expr {(($w >> 8 ) & 255)}]] - set s0 [lindex $sbox [expr {( $w & 255)}]] - return [expr {($s3 << 24) | ($s2 << 16) | ($s1 << 8) | $s0}] -} - -proc ::aes::InvSubWord {w} { - variable xobs - set s3 [lindex $xobs [expr {(($w >> 24) & 255)}]] - set s2 [lindex $xobs [expr {(($w >> 16) & 255)}]] - set s1 [lindex $xobs [expr {(($w >> 8 ) & 255)}]] - set s0 [lindex $xobs [expr {( $w & 255)}]] - return [expr {($s3 << 24) | ($s2 << 16) | ($s1 << 8) | $s0}] -} - -# 5.2: Key Expansion: Rotate a 32bit word by 8 bits -proc ::aes::RotWord {w} { - return [expr {(($w << 8) | (($w >> 24) & 0xff)) & 0xffffffff}] -} - -# 5.1.1: SubBytes() Transformation -proc ::aes::SubBytes {words} { - set r {} - foreach w $words { - lappend r [SubWord $w] - } - return $r -} - -# 5.3.2: InvSubBytes() Transformation -proc ::aes::InvSubBytes {words} { - set r {} - foreach w $words { - lappend r [InvSubWord $w] - } - return $r -} - -# 5.1.2: ShiftRows() Transformation -proc ::aes::ShiftRows {words} { - for {set n0 0} {$n0 < 4} {incr n0} { - set n1 [expr {($n0 + 1) % 4}] - set n2 [expr {($n0 + 2) % 4}] - set n3 [expr {($n0 + 3) % 4}] - lappend r [expr {( [lindex $words $n0] & 0xff000000) - | ([lindex $words $n1] & 0x00ff0000) - | ([lindex $words $n2] & 0x0000ff00) - | ([lindex $words $n3] & 0x000000ff) - }] - } - return $r -} - - -# 5.3.1: InvShiftRows() Transformation -proc ::aes::InvShiftRows {words} { - for {set n0 0} {$n0 < 4} {incr n0} { - set n1 [expr {($n0 + 1) % 4}] - set n2 [expr {($n0 + 2) % 4}] - set n3 [expr {($n0 + 3) % 4}] - lappend r [expr {( [lindex $words $n0] & 0xff000000) - | ([lindex $words $n3] & 0x00ff0000) - | ([lindex $words $n2] & 0x0000ff00) - | ([lindex $words $n1] & 0x000000ff) - }] - } - return $r -} - -# 5.1.3: MixColumns() Transformation -proc ::aes::MixColumns {words} { - set r {} - foreach w $words { - set r0 [expr {(($w >> 24) & 255)}] - set r1 [expr {(($w >> 16) & 255)}] - set r2 [expr {(($w >> 8 ) & 255)}] - set r3 [expr {( $w & 255)}] - - set s0 [expr {[GFMult2 $r0] ^ [GFMult3 $r1] ^ $r2 ^ $r3}] - set s1 [expr {$r0 ^ [GFMult2 $r1] ^ [GFMult3 $r2] ^ $r3}] - set s2 [expr {$r0 ^ $r1 ^ [GFMult2 $r2] ^ [GFMult3 $r3]}] - set s3 [expr {[GFMult3 $r0] ^ $r1 ^ $r2 ^ [GFMult2 $r3]}] - - lappend r [expr {($s0 << 24) | ($s1 << 16) | ($s2 << 8) | $s3}] - } - return $r -} - -# 5.3.3: InvMixColumns() Transformation -proc ::aes::InvMixColumns {words} { - set r {} - foreach w $words { - set r0 [expr {(($w >> 24) & 255)}] - set r1 [expr {(($w >> 16) & 255)}] - set r2 [expr {(($w >> 8 ) & 255)}] - set r3 [expr {( $w & 255)}] - - set s0 [expr {[GFMult0e $r0] ^ [GFMult0b $r1] ^ [GFMult0d $r2] ^ [GFMult09 $r3]}] - set s1 [expr {[GFMult09 $r0] ^ [GFMult0e $r1] ^ [GFMult0b $r2] ^ [GFMult0d $r3]}] - set s2 [expr {[GFMult0d $r0] ^ [GFMult09 $r1] ^ [GFMult0e $r2] ^ [GFMult0b $r3]}] - set s3 [expr {[GFMult0b $r0] ^ [GFMult0d $r1] ^ [GFMult09 $r2] ^ [GFMult0e $r3]}] - - lappend r [expr {($s0 << 24) | ($s1 << 16) | ($s2 << 8) | $s3}] - } - return $r -} - -# 5.1.4: AddRoundKey() Transformation -proc ::aes::AddRoundKey {Key round words} { - upvar #0 $Key state - set r {} - set n [expr {$round * $state(Nb)}] - foreach w $words { - lappend r [expr {$w ^ [lindex $state(W) $n]}] - incr n - } - return $r -} - -# ------------------------------------------------------------------------- -# ::aes::GFMult* -# -# some needed functions for multiplication in a Galois-field -# -proc ::aes::GFMult2 {number} { - # this is a tabular representation of xtime (multiplication by 2) - # it is used instead of calculation to prevent timing attacks - set xtime { - 0x00 0x02 0x04 0x06 0x08 0x0a 0x0c 0x0e 0x10 0x12 0x14 0x16 0x18 0x1a 0x1c 0x1e - 0x20 0x22 0x24 0x26 0x28 0x2a 0x2c 0x2e 0x30 0x32 0x34 0x36 0x38 0x3a 0x3c 0x3e - 0x40 0x42 0x44 0x46 0x48 0x4a 0x4c 0x4e 0x50 0x52 0x54 0x56 0x58 0x5a 0x5c 0x5e - 0x60 0x62 0x64 0x66 0x68 0x6a 0x6c 0x6e 0x70 0x72 0x74 0x76 0x78 0x7a 0x7c 0x7e - 0x80 0x82 0x84 0x86 0x88 0x8a 0x8c 0x8e 0x90 0x92 0x94 0x96 0x98 0x9a 0x9c 0x9e - 0xa0 0xa2 0xa4 0xa6 0xa8 0xaa 0xac 0xae 0xb0 0xb2 0xb4 0xb6 0xb8 0xba 0xbc 0xbe - 0xc0 0xc2 0xc4 0xc6 0xc8 0xca 0xcc 0xce 0xd0 0xd2 0xd4 0xd6 0xd8 0xda 0xdc 0xde - 0xe0 0xe2 0xe4 0xe6 0xe8 0xea 0xec 0xee 0xf0 0xf2 0xf4 0xf6 0xf8 0xfa 0xfc 0xfe - 0x1b 0x19 0x1f 0x1d 0x13 0x11 0x17 0x15 0x0b 0x09 0x0f 0x0d 0x03 0x01 0x07 0x05 - 0x3b 0x39 0x3f 0x3d 0x33 0x31 0x37 0x35 0x2b 0x29 0x2f 0x2d 0x23 0x21 0x27 0x25 - 0x5b 0x59 0x5f 0x5d 0x53 0x51 0x57 0x55 0x4b 0x49 0x4f 0x4d 0x43 0x41 0x47 0x45 - 0x7b 0x79 0x7f 0x7d 0x73 0x71 0x77 0x75 0x6b 0x69 0x6f 0x6d 0x63 0x61 0x67 0x65 - 0x9b 0x99 0x9f 0x9d 0x93 0x91 0x97 0x95 0x8b 0x89 0x8f 0x8d 0x83 0x81 0x87 0x85 - 0xbb 0xb9 0xbf 0xbd 0xb3 0xb1 0xb7 0xb5 0xab 0xa9 0xaf 0xad 0xa3 0xa1 0xa7 0xa5 - 0xdb 0xd9 0xdf 0xdd 0xd3 0xd1 0xd7 0xd5 0xcb 0xc9 0xcf 0xcd 0xc3 0xc1 0xc7 0xc5 - 0xfb 0xf9 0xff 0xfd 0xf3 0xf1 0xf7 0xf5 0xeb 0xe9 0xef 0xed 0xe3 0xe1 0xe7 0xe5 - } - return [lindex $xtime $number] -} - -proc ::aes::GFMult3 {number} { - # multliply by 2 (via GFMult2) and add the number again on the result (via XOR) - return [expr {$number ^ [GFMult2 $number]}] -} - -proc ::aes::GFMult09 {number} { - # 09 is: (02*02*02) + 01 - return [expr {[GFMult2 [GFMult2 [GFMult2 $number]]] ^ $number}] -} - -proc ::aes::GFMult0b {number} { - # 0b is: (02*02*02) + 02 + 01 - #return [expr [GFMult2 [GFMult2 [GFMult2 $number]]] ^ [GFMult2 $number] ^ $number] - #set g0 [GFMult2 $number] - return [expr {[GFMult09 $number] ^ [GFMult2 $number]}] -} - -proc ::aes::GFMult0d {number} { - # 0d is: (02*02*02) + (02*02) + 01 - set temp [GFMult2 [GFMult2 $number]] - return [expr {[GFMult2 $temp] ^ ($temp ^ $number)}] -} - -proc ::aes::GFMult0e {number} { - # 0e is: (02*02*02) + (02*02) + 02 - set temp [GFMult2 [GFMult2 $number]] - return [expr {[GFMult2 $temp] ^ ($temp ^ [GFMult2 $number])}] -} - -# ------------------------------------------------------------------------- - -# aes::Encrypt -- -# -# Encrypt a blocks of plain text and returns blocks of cipher text. -# The input data must be a multiple of the block size (16). -# -proc ::aes::Encrypt {Key data} { - set len [string length $data] - if {($len % 16) != 0} { - return -code error "invalid block size: AES requires 16 byte blocks" - } - - set result {} - for {set i 0} {$i < $len} {incr i 1} { - set block [string range $data $i [incr i 15]] - append result [EncryptBlock $Key $block] - } - return $result -} - -# aes::DecryptBlock -- -# -# Decrypt a blocks of cipher text and returns blocks of plain text. -# The input data must be a multiple of the block size (16). -# -proc ::aes::Decrypt {Key data} { - set len [string length $data] - if {($len % 16) != 0} { - return -code error "invalid block size: AES requires 16 byte blocks" - } - - set result {} - for {set i 0} {$i < $len} {incr i 1} { - set block [string range $data $i [incr i 15]] - append result [DecryptBlock $Key $block] - } - return $result -} - -# ------------------------------------------------------------------------- -# Fileevent handler for chunked file reading. -# -proc ::aes::Chunk {Key in {out {}} {chunksize 4096}} { - upvar #0 $Key state - - #puts ||CHUNK.X||i=$in|o=$out|c=$chunksize|eof=[eof $in] - - if {[eof $in]} { - fileevent $in readable {} - set state(reading) 0 - } - - set data [read $in $chunksize] - - #puts ||CHUNK.R||i=$in|o=$out|c=$chunksize|eof=[eof $in]||[string length $data]||$data|| - - # Do nothing when data was read at all. - if {![string length $data]} return - - if {[eof $in]} { - #puts CHUNK.Z - set data [Pad $data 16] - } - - #puts ||CHUNK.P||i=$in|o=$out|c=$chunksize|eof=[eof $in]||[string length $data]||$data|| - - if {$out == {}} { - append state(output) [$state(cmd) $Key $data] - } else { - puts -nonewline $out [$state(cmd) $Key $data] - } -} - -proc ::aes::SetOneOf {lst item} { - set ndx [lsearch -glob $lst "${item}*"] - if {$ndx == -1} { - set err [join $lst ", "] - return -code error "invalid mode \"$item\": must be one of $err" - } - return [lindex $lst $ndx] -} - -proc ::aes::CheckSize {what size thing} { - if {[string length $thing] != $size} { - return -code error "invalid value for $what: must be $size bytes long" - } - return $thing -} - -proc ::aes::Pad {data blocksize {fill \0}} { - set len [string length $data] - if {$len == 0} { - set data [string repeat $fill $blocksize] - } elseif {($len % $blocksize) != 0} { - set pad [expr {$blocksize - ($len % $blocksize)}] - append data [string repeat $fill $pad] - } - return $data -} - -proc ::aes::Pop {varname {nth 0}} { - upvar 1 $varname args - set r [lindex $args $nth] - set args [lreplace $args $nth $nth] - return $r -} - -proc ::aes::Hex {data} { - binary scan $data H* r - return $r -} - -proc ::aes::aes {args} { - array set opts {-dir encrypt -mode cbc -key {} -in {} -out {} -chunksize 4096 -hex 0} - set opts(-iv) [string repeat \0 16] - set modes {ecb cbc} - set dirs {encrypt decrypt} - while {([llength $args] > 1) && [string match -* [set option [lindex $args 0]]]} { - switch -exact -- $option { - -mode { set opts(-mode) [SetOneOf $modes [Pop args 1]] } - -dir { set opts(-dir) [SetOneOf $dirs [Pop args 1]] } - -iv { set opts(-iv) [CheckSize -iv 16 [Pop args 1]] } - -key { set opts(-key) [Pop args 1] } - -in { set opts(-in) [Pop args 1] } - -out { set opts(-out) [Pop args 1] } - -chunksize { set opts(-chunksize) [Pop args 1] } - -hex { set opts(-hex) 1 } - -- { Pop args ; break } - default { - set err [join [lsort [array names opts]] ", "] - return -code error "bad option \"$option\":\ - must be one of $err" - } - } - Pop args - } - - if {$opts(-key) == {}} { - return -code error "no key provided: the -key option is required" - } - - set r {} - if {$opts(-in) == {}} { - - if {[llength $args] != 1} { - return -code error "wrong \# args:\ - should be \"aes ?options...? -key keydata plaintext\"" - } - - set data [Pad [lindex $args 0] 16] - set Key [Init $opts(-mode) $opts(-key) $opts(-iv)] - if {[string equal $opts(-dir) "encrypt"]} { - set r [Encrypt $Key $data] - } else { - set r [Decrypt $Key $data] - } - - if {$opts(-out) != {}} { - puts -nonewline $opts(-out) $r - set r {} - } - Final $Key - - } else { - - if {[llength $args] != 0} { - return -code error "wrong \# args:\ - should be \"aes ?options...? -key keydata -in channel\"" - } - - set Key [Init $opts(-mode) $opts(-key) $opts(-iv)] - - set readcmd [list [namespace origin Chunk] \ - $Key $opts(-in) $opts(-out) \ - $opts(-chunksize)] - - upvar 1 $Key state - set state(reading) 1 - if {[string equal $opts(-dir) "encrypt"]} { - set state(cmd) Encrypt - } else { - set state(cmd) Decrypt - } - set state(output) "" - fileevent $opts(-in) readable $readcmd - if {[info commands ::tkwait] != {}} { - tkwait variable [subst $Key](reading) - } else { - vwait [subst $Key](reading) - } - if {$opts(-out) == {}} { - set r $state(output) - } - Final $Key - } - - if {$opts(-hex)} { - set r [Hex $r] - } - return $r -} - -# ------------------------------------------------------------------------- - -package provide aes $::aes::version - -# ------------------------------------------------------------------------- -# Local variables: -# mode: tcl -# indent-tabs-mode: nil -# End: DELETED tcl/8.4/tcllib1.15/aes/aes.tcl.asc Index: tcl/8.4/tcllib1.15/aes/aes.tcl.asc ================================================================== --- tcl/8.4/tcllib1.15/aes/aes.tcl.asc +++ tcl/8.4/tcllib1.15/aes/aes.tcl.asc @@ -1,18 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v2 -Comment: Eagle Package Repository - -iQIcBAABCAAGBQJXtl6FAAoJEFAslq9JXcLZenMQAKEdxioTYCPWs5wEYERfn/8x -GklZUR/LGTNV0w0JO13BxwUsrwOC0BMI3iRhFGBNyd6J7RqkvulbfEADdzZoTofF -INfhpT+sJoXScmg1pzcJmZdUGP7vBmG6+askcVSkafZmesp6DR03lPI3x323A6dm -kJPIy87UMCB+g2L+V/+BhWJgrQloekWNUKsElcWBc3N+K3lWbx48jgkcLow5K2St -qg0paqW5T6doT6Ig27JKy71SRreMi2OsJs/HA+KxND9diC2hfVC87dkVGyoKHOJG -fsX6j+Fz3Eygg7sw+U3EIIMOj/eQiWZJ/eCn1UbxvCcGORHiQnDztTpfEIETM+dz -TNAvjWlC2ISDDJAyc1C02ok+ee+6chfJhe8aH9Fj/AK4tmJ9xXyF6FMz0yZ/F/3k -LCggJlO0eVnngjwDwGuz6czJ7VccRDgwdXtpkMJtq4yJtZOHaoYXUr6fgGoW4i3r -yOQu2Ajk/ZU9l8tTXbXWhexn+x+TbbhLUuOckEu8Mk7ID+Z2EMA4AyzvfwytbCbk -8Wi4J0gDa/cV2JvncQAlcZ6u+4mgWhMyUg8gq2bMsYwJd6/8XzEIaF4752UFiUiV -AeOdPeGeqfELAlUagLAQOuHiFAK22VU0jPTp0f8MNvSITdheI7EeUNY7gM0a7odI -hf4M9GphdltjwhC1p4FI -=kVUR ------END PGP SIGNATURE----- DELETED tcl/8.4/tcllib1.15/aes/pkgIndex.tcl Index: tcl/8.4/tcllib1.15/aes/pkgIndex.tcl ================================================================== --- tcl/8.4/tcllib1.15/aes/pkgIndex.tcl +++ tcl/8.4/tcllib1.15/aes/pkgIndex.tcl @@ -1,5 +0,0 @@ -if {![package vsatisfies [package provide Tcl] 8.2]} { - # PRAGMA: returnok - return -} -package ifneeded aes 1.1.1 [list source [file join $dir aes.tcl]] DELETED tcl/8.4/tcllib1.15/aes/pkgIndex.tcl.asc Index: tcl/8.4/tcllib1.15/aes/pkgIndex.tcl.asc ================================================================== --- tcl/8.4/tcllib1.15/aes/pkgIndex.tcl.asc +++ tcl/8.4/tcllib1.15/aes/pkgIndex.tcl.asc @@ -1,18 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v2 -Comment: Eagle Package Repository - -iQIcBAABCAAGBQJXtl6JAAoJEFAslq9JXcLZSf4QAKFsBhYHqlALRprs1hhXArfc -jamjLJCUFZRrsU1exvmbiU/2SCsFwveL8gDHtRGvHrKZpepVSSh1vAK1DFAEW5zR -2/bnMRnmYKfbdmLe7bd8xZqRDQjgMRIq/rs5Op9bgb+AstasiQLbjvNNJt2Q56d0 -wYWSH4w5qkniJSfakXSf+4HyFcU8kSG+rvkqOqGrKqQTY0DhJVTsjAZHA6+gE3T+ -xx6mUXiJjrnU429pht4mry5d8bSEIbARYi6B9AIbaboqlgcDTaMTmNpHRDpVx+VO -F1Q/JtRsI0tMvbMhHFITzOVP+HyEax1tTm+bMArdnYvECvawwQ+rG7IudNFInZPE -EXNg+qunEUpcR+bgdhnQDqZDpslmA4ZThIxDRyAYwx6e1NddVF3uhdL2/Fatdmrs -WS1HwzZFN5nQtnKo0l9yTnp3TAo2Zjx9HhEQNo5zMAzFy5bnLrIbz2xSRL9xBIJ9 -N4EtBvPWW+IKfyLxz/mP5dkYrhUDvAxbThsR/li2HI3dhwfU7aSXVkuBMDBvrklz -8W3SHNcTHDeoB5dE9z4JTSKgZoxKBQwD5dstsSbYeykxuHVBcjL1EkLjr1iCduIu -NBCPuaLpxEEVREyN3QeHObH4+QrXPKsgE8sm5V6a2rVyfS6koBAOX+eDIlfXdo8N -B0KCHquWJYaanWwDdOTK -=53sI ------END PGP SIGNATURE-----