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
+
+ ksEq7OEzUOjr5Ho79adlCVFlff5zP2NTYqHtBO+xOxgJ6eQI5nl9lxtMGPwGXDrd6q7sG4YrRomB
+ t92gHy3ChatZSIZ1PkH9tF4HUU8WCIkSAefLfWa/fH7uK5ZU6f4FtsPQ0HQTdEmJ5tvQVRqwR0uC
+ vQZurOiO5zPoAlsri7Vlx7N1pFF4kA75QIdIaM/nXfZn/9qwhpqrnyH6PebHVg/M3PjrjOAMK4GX
+ 6b/K9sf3WviE4zqQpYtHFMAGeaNFIIfMMvb86unkIex/vkimN81vSERbqNvTBVBtoW3mVefjAx1+
+ uOjyy726scDCCjWpyYF3MQwprKMGU2EAQW0FyzdlO+8bpTwC7qiTYQ7ae+PsQNmsehvDjhWwdiPP
+ TMNyY4Nvs9qSX0KlslK/35MZoVL7JMVGZ3fEtpV7+Dhw4YRb3ITUaPjHjuI+8rgxszLe6k5o7jgW
+ RSLZ8l7fbPjii91k6sYbA5v8YWrWwTIR9tcOr0qEuZhsU/GezKmqddcdZzbZsrFqHAcwKQh/UEJl
+ vXG3qR2p757TYPnLMfnp9dLjTspgOgNDYQaf6yPDasErpz1v0n+oAfu6Il4yy3Z70+TdRaqJ3ADg
+ AGZIivH+4aJk7tI8VN9b/JqcIgM0TcfrgRGgWiS6lPMtnxzOIjRYydYimb37oYrLmh/ljQEvrwjp
+ i1g/we9h8ehC+XNV0Kadqtr7NvsOicLLrneKCtwUSMlctrNf8vnqM6Ewz3Y3Km+AgBTWhNu/c36I
+ ilHZ5hFs1rF6crkY4yuGYmg0/vF8cmVjqtvdSo6PpgSXjopYWAKpd7x0uTnvnzV26g6wSQruVDqF
+ 8EQ6NQ8hPyRCQvLkvtcANdzRFtmi508k9SLPY2iNx7fGKVZzLqaGFn6NDSFkbtfvNCxSR1qZOUTw
+ bxXXviVkEEjTTu59WBal2S63wjgO59xnVOkJYbG/xdMqZ0KTPZdXZehQ6Bj9r+BHrbeyUCXQUy58
+ WAVvAerS0Mp2RSMS0wYRMSp8/nWe5jiQ+4vjSD7FxN/EHQsLeGTn4d+nZTGadVMxTTfT1yUgcTW3
+ RnV+shDe0CizMuHXyNVO50tKga71ve3d+7uf3wY+k9kY3Oobq4fTtReNlzDdsMlYPPT0XFVKS6Pt
+ SmDmhUJRxvYyclzCutoOjMoTotvxsUcKz/69WZ6GPYQJvKmt/c4YAmAaMG6/8Vo0wW309hZDIpIK
+ cD1ROCSBXEMvIDtQVkdoRtKxkudEHmTroVcIC+7nJIA87zCiTe+AOJ4JV5iFKb+2CJt+1X41D+Do
+ s5dxPpZwYSxG6BEz1RDlCHI/eI09mZKmwhdG6HL3DZZs8Dip/IlwQwihx1VpSwzCpngMOcF32Hiw
+ HPoAX6gOBTArl2nFlBqkaT4ijNkl/pj44GSyh9hDXL+0QzrpqOUZ2ktYD/0FMVTLr7ZWoeosOqRs
+ cc63DxpHdL2NoYkrshaRm2y55zhDy3cgGHKZnzu3aByEWeh4j5pcVcBsgJvDm3mecvrGgFVexxRG
+ IJarUNjud2JBjF5xxbncuX1c2ev1boHn7/9doC7gCyx1P1p+NrceY/TxXeUYViPevWU3L6IAQJYM
+ iSqzhtJCvGgPD5ByVlPxD5ehqlWka0CdZJfc2Duy8JOLyvltE+NHKsPBEc5xzDK4QMz9XPUH8VzU
+ 3It78WSCe6+f7UdaXIqmCve7JlnEBVzjELY92Rx2ylO26HkqvmxaXufGtZWwAuheRXy0vv4kW0nc
+ YIgrE1A5ioFmDMHYFHrC89IufAOQpUfsOe6Hjpy3DnkRwj/Ozp3fuWktqyR4JWddj+sYpy8+YdIN
+ PBLPf4QdGDZKp4sUpXxN6/eSV0zGMkPtxph6bWbmLegiUzt1tJ3Iy2A2GbqPnk62qUhNd8nwnqNd
+ DmKcgoxYUTPcdoFIsZA4rUzO1ZOkM2nCA7OKrZ2HVQCMoZR2NQy2rzNvhvVY3AieOXIm8Nxc5yhW
+ fgi/G8oDWfFVzg09CYDwDkL+1Az+ogGJkUNGAGTKOfvnKKJpxuW0xh1yLYo4Nue5oyaJNlsg20TP
+ cFKCigooi0onMl8zjd7419/RTfFYHBC1AFNmAduQGM4FKT6rU6bQMorBLnKLHmnmi19SMcC96/vz
+ CtpvHi44M43upNos4vZVeLCPsWDwO/HLZ/kLra0AwtFYlnV72ZHjzCJrBI4NT6yhlI6Dp3d7MmJH
+ ZLd9InHVylUPE82B/nKuY22aIe1Q7URYTA6Hqgym3xgHbwIiNNECIicJS+a1HA6fbQvcGNcJqwDu
+ PceJCfv+TTELXPrYqCrch+nKmAN/PF0SHE7vF7HZZdKQ5a46ePC2vip5+ZX34AH8EEC9aF3313iT
+ 6B9dvPDDw6S4DLLk9bGXptpt9+THVWB/PV+Z4vl+c4HQaXTHSEXFAqvhZG7g7SPpg6t0Pl0IESR+
+ iBPQbrx0t5KeD2MuihH+xwEO5fuvpg8JQEGJxtz97Ux6zErk2+mSllj73qFRFhOSAWJ4LrADRks/
+ fDkvACXRPBzojmf3M5oJSt6bM0DZ+xejkYJ3XzaFgMXH0x0jIJKIXLdj+Yk8Ofy9NWt5FfCWRpEe
+ JRPUcRO5aojSBYwvQDDkNB9gMbjjuuoSEl7Zajw/KoTFwk3++VIkJksfv77yEl1n8IpmlFc3JVKa
+ cXNb9HO5yyS2A6Jp6XHsjbeS5K0Dg2yEZB8pRCYmxEPMi6YoqQFD7tW0yh80Uv7o+IruV0c=
+
+
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
+
+ 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
+
+
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
-
- 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
-
-
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
+
+ qWSUmAwQawmj4AqAdy4DFQXAYAqZkikidSwK7BMz+pMiT0qSN/aiKnHq/yE3ERsVuZ1wwFlE6vOu
+ dRJ9TfPCZNoaeQuMZj7lNAxumG8d125mSTUEdzkU+FH/DXXV4VSlROPCmf3k/kzG+jkqfx2VUJAu
+ pkg7TqnqKDEWeYJoFMxKXmwxrSxui2g39EXqJoj7qBY7EVEQOpmAgspE13uD+8N08o1M8oor5jsm
+ Akb4X2zCRZ1hEroQ9sb0FTTgfxYhyJMIVy9QnecNL9/cQ6pn30kX0ADzDK8oxIaR0wANDf8hscWW
+ RPVEQStqnz97Px/5ljL2STmzXuhY7BUo+nClZclZ7B4tyk4fT/kjOI1CGYLOXN993N/6jycf2I9P
+ ZP3+humf7Hd3iTi+QKsnc5bqFepzndgFFBDRI8cX6tTxz5qKx6bVF5070E04yUZWBePKWLjE6Skd
+ XVdxyUNCea3Od4INbpkOUSbXPoNunn2ScDB2F8rdEU5WZr592uEgLGE53FUW4Z1b3sY2P21O1JrS
+ fJYVm0+XV+57lZ43R1sL2C8Dc7PbBURrpX/Ex6al/b2KWFvcmAKTlFg/FAtaMer70VRLZtzeR5QS
+ /j+ilnoxXODT+vYeaRzYxhA7ME+RJnPF6sjw+e5L+f31IznVARMBeoL8KhVrDfI71syrxAwlAPLg
+ 6q50DUJ/LKfCpXo4x3966sg78xi/1hqCqW004UAZLM8pSvfirTSrsDw0jeCRgvUGD6p9QtQnjUr/
+ wO0sn4JoanN4+0jas8WuRDd2VCuSqM8+402bWYyfUUd094dGqyfIQFo/hoLcqug2gm6cyfjQjK7W
+ PrAGkFXgwf0EG7wULuk0ypUXRH/UJHHlQddicfn0GPt+GV8LoTjyg6YQb0DuolnPj2j0pquxO7In
+ TKG/pVh3FjlEna328azrONLHkC7w2sE8w1O3+qPJ4hCm1lMBX8RTZAYfnR+VDBk4p0RoLoPz33fi
+ TEuSabaZWmp6wpMcyp90L4E3RzAzh1E8M/J2u+KiEE3/vh7yIgdPg3/ZdTgHHhREy8Tm19TllMuj
+ fJHw0hDNkT2c/Irhx+05zBJ5Nj37nCd3RwpjXy+HODakSYHqKks/OyQPofFbYGF4g2No01ELsFpb
+ YDc9BG1zCPiM8KyO4U+LTvX0rbY1EpY1N17WZz7TOSkiTV4v44Ky7KQGbjhR5x8Y8yLignfSCAyr
+ jQuiT7HbQVkYL43s3y61ufYfOHn7ehDZeRNv/c8o5MbLbj9ZxdY8R8gv0nLiXrLRjXomCgMqFi5W
+ XA32sFCBJgiFj0A/ixJO6LOaHVpxt27kzrJ76YeOv0qbgDYA3bHYO7gO4XJ/qaS/HpJkrPIO/wvK
+ bDmThd8kDqx9Xs+kYKVKI1MbtaQA1A3Ual5o2N1UaAUuhX00z9SgEKZOOx2Hhy+2PZ103ccoti/1
+ 3lgy8kyf9XZng4SHp5Y7eoLSCPjYO5IBQ/cxTp9XWZBYpHvD4vohaCU7o4tgYCOyJr7p2FvPWen1
+ a9X5NR7skFBsUVQfGgKoL9OOFsKuodXwD6cPZlJjrIJcAmRoTjH1DAew4HkjfHEng/VXhz6PQRV0
+ 2D2h0P2T9HCajgQ8/MnpQU3g4XmNNI1AujsdNRSCo6fixjmzs0nGVD96Xy8mHSTMhL/LlGNHAvm6
+ 7CFxIzGvVrGq3jjZ4lpqCO0r4301AxBnw3N/54WwgEtojmzACeVq2epqGzdGTBiCSng+V1+scntH
+ JrK6rTCplsENc55UdaQCznXy/CfR31LX4pugvXZOFbVE1JC7X08bsZ0PygUYtTvogO9PdLPAO8iw
+ 7yR/1oF1D+eO/xsoVZpd6XYLkcJNe8stMgw0qr7fy0Pq90KQU7qxvt6rndrzQJ4uscg7tuzes9xb
+ hVF3RCi65h3FYcWEK/fk+QGtlecJcDVEWd4wGNMxpEuBCqQDZKQSt1/aKob0zMeJJHqK7cXShARZ
+ 9vYSlJKwZFtnkQTvt5lOkhTdYWC3hGh/enWuVUrSK5IVyyyYBae1bMaxUcm2JtGEFgiTo2mL2GT+
+ jE3jpNg5TxIKQ5CH27w4lfuPXbdiKA3o2aK5vgzkbwwi6xHRLGaQzvpxYma+ge4az03jSAXwktbm
+ Id5XjqHVJPXxdciaUtEez750NTp6ucmxnoJrziTeoz4f5zXaUNg52sbd45bqx/QAJzBPS77cElL6
+ sfSS0A4EjMXDG/y75NSGEt79aYTrfhpiT0Bu8hfCR6jIa7953Ok/VAhXG2vtdTbvuiiCjbj5v/1v
+ ARGY+chtR577qdgsPlps1YwNErjTHQFxXmCgDT55XWVaw0UD4stRCMnMvbM+fwPDWfV3dMI/jAco
+ Xlk4qfMKuU+eqpTO3qMS1t4he0RoCW3hO7BjtSWdyCoXmFFf/wMxqADDbpfIr7r6xYqJY5tuQrhw
+ YPJ9hF6FZpa+yy2wfdRU+avuuDD2BZB52Up2x46OE7xzlwDkeIzCoSxdZOa13by7OqLgEwGCtrvm
+ UcVl8EHlnCTT0a29OE7N2yO9lKiDZbmsrJfJ9APy7MA7RTPVpZcMkAZ1upxH2zNCnT9WpHXtadBb
+ vlh5A9YY3UrS8hmku+/5A51OiKUFo+26R3c3lf2/cavo40C4n+BTY0y/pweixbUmCTrSsY85HcPD
+ bYeqV9kxa88/ilHM5WC3XA4QdD8a5eTDYHH0VbKvcq6D1fgqvVnNiwlbnipk+FoW5GAH8kI=
+
+
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-----