Overview
Comment: | Add initial packages, mostly for the purposes of testing the repository. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
36ce453d8f80b4c3904547a0a25e82d7 |
User & Date: | mistachkin on 2016-08-13 19:20:57 |
Other Links: | manifest | tags |
Context
2016-08-13
| ||
19:59 | Add the initial, experimental version of the Eagle Package Repository Client. check-in: 8f37fe36be user: mistachkin tags: trunk | |
19:20 | Add initial packages, mostly for the purposes of testing the repository. check-in: 36ce453d8f user: mistachkin tags: trunk | |
18:57 | initial empty check-in check-in: b9ed44d466 user: mistachkin tags: trunk | |
Changes
Added .fossil-settings/crnl-glob version [b462aee1c6].
> | 1 | * |
Added eagle/1.0/data1.0/data.eagle version [48b8596db7].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 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: # # * <bin>\System.Data.SQLite.dll (managed-only core assembly) # * <bin>\x86\SQLite.Interop.dll (x86 native interop assembly) # * <bin>\x64\SQLite.Interop.dll (x64 native interop assembly) # # -OR- # # * <bin>\System.Data.SQLite.dll (managed-only core assembly) # * <bin>\x86\sqlite3.dll (x86 native library) # * <bin>\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 "<tableName>_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 "<tableName>_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 "<tableName>_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/data1.0/data.eagle.harpy version [1981f236f0].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | <?xml version="1.0" encoding="utf-8"?> <!-- Eagle Enterprise Edition Script Certificate The format of this file is proprietary and may not be reverse engineered. This certificate file is subject to the terms of the license agreement located at: https://eagle.to/enterprise/license.html By using this file and/or the associated software, you agree to abide by the terms of the license agreement. PLEASE DO NOT EDIT THIS FILE. THE ASSOCIATED SOFTWARE MAY NOT WORK PROPERLY IF THIS FILE IS ALTERED. --> <Certificate xmlns="https://eagle.to/2011/harpy" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Protocol>None</Protocol> <Vendor>Mistachkin Systems</Vendor> <Id>b75d0391-1361-4486-bfa0-df753175f4d0</Id> <HashAlgorithm>SHA512</HashAlgorithm> <EntityType>Script</EntityType> <TimeStamp>2016-08-13T19:15:04.6484375Z</TimeStamp> <Duration>-1.00:00:00</Duration> <Key>0x2c322765603b5278</Key> <Signature> Y+UzAa7YnCZOYYIlbcsE8RPzewFUWniBPAcUVubl6JMpOrqfq31tEEfn3J0IVgXRSWL2iBqWCiW4 3xmG86Ah6AFTVXdlsXFzuDaA6v+YfDR4DYlKbieFJfLN0MW9SYuvjVYB6+qSwZ0o3Gedepc1ouRf P9sk1f4ZTxZcRhDhZ6At7DHml13gShCujXzeUYFQXP8m53wXptyO3DlNJnHH1fiQZv4Qz24JZIX9 9QgF/Aweav05haV/gt8bXyqslCdnWbrEdyujYbhVkL0CX2JZ4+j0l+AerFyUMWFLSkpa8qqGl4EM 9lK2T5c/r7Yu2/t+BtHHFAjVaiDcPRB1SvyQsWv8pHwDWpsA2sE429Lgu/Cu+GWj80NYgydd1Ub2 pAEL73BpzkH6yp/8GfjExS/FQCYVK6XitMOMxkldjYrjzPlox3sQ0Qx3y+nmd8RveHcbgcDhhc0T PZJC4Rb2027E4GhMWTIZbzX26TOnYc9MfiXBgrabVtmmuj2sT9PZ2zVXq1ES5xW1BiLaKya9Tgzs A22WNiMyfFXvVUDvn61nvsZyX7tUJbUCA9FHFdeH98kPxu2R5Pk/gi8Q5JdB62MaP5jWVHoQBfkz zkAZVhSETenG8EnjPDbf8ORkc/SfcOwyMLKloifGDbovDfRPvt/Dohw7fXndkLqmw1SCNvudxz2K nhaetZUv9SKIwAYxcHzH4ms1mmSNq6GsjROTja9VLWymvNjBPxk8DSYEb8J5ojx3TkELvzj6JvlO zgYQlWCu/KXQPphwbIxsPpKppYrNbyqv842E7AHjCJQF5f0vMFWFuE7lBc7wM6vz395pbvefPMaI uAFwrLcF5mDN10f9Lt67o3UZJhX7Rp+wdNYBY1bUzyLAooqBClpTTI/GNMMA+TAAg99WqiuPQSRS N1tadjhWZPfHDCM6LyrfMVjduCWoylakhy775+VPIr7vXHN1y0MGxhf0Ma5EQg2kTYj4GsQ42dZW 7P4PVS5Wmv93Ydp74o81H+nesDUMgd0DrklNxB/NynVwhx2lJqRpV8Tov3UrzU8vpqhyVZNKrZ56 XP68F/Z4QUIFFk1H9sLhF5bx6qXComO7qi8HxkiLK1XLvPBXt9BrePmZgKTm5VJHr5y8YmOGqxV3 azlswBa4x2ifJ5si7VjB0jfVpBZgIWmclu96X3+VCJNAw50dBMZgmPmr7N5U2/zqh5ppvbZ+8Euh BLMW5mGL9nfv9yP3dm3HdA6e6NsOO9kVDcaeMaCagHFRF7ZzQHnAtDZJR20J5K6MUOPYXk25i16B ySOEc2SApQOfZhkQ3afLowEZqbvtrcOm9VB+NtPTx55qSVilDs4vx03XWxR3o+St1O272qUdHQ== </Signature> </Certificate> |
Added eagle/1.0/data1.0/pkgIndex.eagle version [bf518069aa].
> > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 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/data1.0/pkgIndex.eagle.harpy version [dcd5dfc9e7].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | <?xml version="1.0" encoding="utf-8"?> <!-- Eagle Enterprise Edition Script Certificate The format of this file is proprietary and may not be reverse engineered. This certificate file is subject to the terms of the license agreement located at: https://eagle.to/enterprise/license.html By using this file and/or the associated software, you agree to abide by the terms of the license agreement. PLEASE DO NOT EDIT THIS FILE. THE ASSOCIATED SOFTWARE MAY NOT WORK PROPERLY IF THIS FILE IS ALTERED. --> <Certificate xmlns="https://eagle.to/2011/harpy" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Protocol>None</Protocol> <Vendor>Mistachkin Systems</Vendor> <Id>617c385d-49a3-4b98-b06c-80bad63311a4</Id> <HashAlgorithm>SHA512</HashAlgorithm> <EntityType>Script</EntityType> <TimeStamp>2016-08-13T19:15:17.8593750Z</TimeStamp> <Duration>-1.00:00:00</Duration> <Key>0x2c322765603b5278</Key> <Signature> iqyBnSPDUq5sZ4vpnLDtMb65Q7wuukZDFgR1W8MGANA8s6vCsR8Yhs/Qc8gQxGrbyl3N+1SdBSJ2 vNC4MJHIWYUPYWo6T0BoLb42ryhZ5g/Cp4cqtm9vJosQyKWQ304vIetxQ+sh39B1nIcK28j5dicY /wmUXd3bL+MKeM7P96XhnhQinftc37HHGQmn9hbYSrhVX04+E+X/q4jsUDIDnDpcqdRQlhzDDGsC R7yfXttPNQbkRzTeevW5qcZPY7hGjyplgTcXoeBVUVT8qsxlD4F4g/kb/hzKeAtH5Py2793edrKz ujUKKBvEUNIZyf7SPLSg8yTjM5aoQu7EdjwDYVGj8BHnUIHrDc+X4kksWUvXPEwdjmg61OP7QjCI Hpfax/SEXznCzYVRiPy8jPDagsbHt62ASx0fcvbHryUNMv/WpucDI9yfPVCmmZFf0l2rnxEBxzA+ nPfDQCdLjY8/cCh/H7iasxDHyoI/tzUj1zQG+ltDKKLd3iLiuUMuyqN3RchHVmqQFkeUT3HKyVxa 0B5BSHsym2VKZqlSjKQPWMTaa4fSUplgmST+fbMLjEWDwZ2oW3HHCzdf/N7OiownDC4lcCnBiyw4 NXVqqR59trJ/26hiw+W7/FqEpNo1zaC+Y8LFsaTv0tekQWz6AG3Kfu7E4VzgssbwYrY2mMj5+oqV 5tNVMg28fp4ZnE0y7ZE2j3T6RqrEIrF8MPdtuFjUMMAOFnqXWSmG+aCi94K7hac4Sp7ADU2Ac43/ NP1gdkr3e/d1GzKpN9PFMrLYmHpFTpiFWnTbdDMh4EgdL4I/KpFhLC3mA+dJAmpxEktdoAcstymI jZYV0YsOBTxtdyHrVyG6XrhKX52D5LYbjITpU061pLt84pF6JPZBFOJXgu9YeYlWqoGVypv+bREy LgfJ4wLqrs65yJNroeW2ScdPL9wv2FtbpocJUVWj7TnvMdNC6kp8+M5cbslAz4AWUOppkVP+S31B RVCbqwDQC7sfDz4AKdl4I72l6TyJhtI8ULRqUiBwXr84wMYwTqrjKJ6HZybEBRjU+lIyKCakUWaN QehWuRy57FuJXvPggffEJ9Jl4xn89V7k8uvBHrjqAMuIwd5Uozzg+GEXUweH5hiim1K7geqVa4Mm Y+TBuML2zL3Vx8A6uQVO8IS622UrdqlrFOGEBz8e1WL07HDBcugvGE3AsWLIugDWtMTwxCY67UHj yUhVw+iUXwR+vuhLc9VkI4F/3QYH6WjYk/chiy2uooM4+VhmP5kbkSxGNqFbO7mk+Ilw0ieovuMz vJgHrxOezOQZSuMt/ienIyGYBSflxKeAKtw6cDnnu9+jPJEBQYMelkuSSLZ9wkkVRy7NBfWdRA== </Signature> </Certificate> |
Added tcl/8.4/tcllib1.15/aes/aes.tcl version [50edc324c0].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 | # aes.tcl - # # Copyright (c) 2005 Thorsten Schloermann # Copyright (c) 2005 Pat Thoyts <patthoyts@users.sourceforge.net> # 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/tcllib1.15/aes/aes.tcl.harpy version [95848449f5].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | <?xml version="1.0" encoding="utf-8"?> <!-- Eagle Enterprise Edition Script Certificate The format of this file is proprietary and may not be reverse engineered. This certificate file is subject to the terms of the license agreement located at: https://eagle.to/enterprise/license.html By using this file and/or the associated software, you agree to abide by the terms of the license agreement. PLEASE DO NOT EDIT THIS FILE. THE ASSOCIATED SOFTWARE MAY NOT WORK PROPERLY IF THIS FILE IS ALTERED. --> <Certificate xmlns="https://eagle.to/2011/harpy" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Protocol>None</Protocol> <Vendor>Mistachkin Systems</Vendor> <Id>eae21bc1-3c8a-498e-afcc-409d1b85a149</Id> <HashAlgorithm>SHA512</HashAlgorithm> <EntityType>Script</EntityType> <TimeStamp>2016-08-13T19:13:37.4687500Z</TimeStamp> <Duration>-1.00:00:00</Duration> <Key>0x2c322765603b5278</Key> <Signature> L+xL4YJ9xs42ZDA0h53VGaXagPlf/CEO9ygwQBOjbDPZZpDxLEano0iGryqh4jSQ6xFnVcU4RnLg MRVx5YwVsufu6BH1A5O1xpSzX8Xm55PCJlS2fSk7CUPhPsNZR1E9tYluwdjTBdv2OiVYvfpjeDgG omBWkBgx1zGckACbzNNOZcFih1BR+XsIKxP7HbRmVjFSro7fqHnsuTUbq1UY+kYfKyrjqfvz7n5e jFYx5hoaRSbCjoGumbUKgflZ2Hn1vy9+4+pcVwBuB4VWixQ5hecD2xbBmOZYOimwYXy/aCNnyvHf YooV6fF0v+1JC0MX6QFhr8V9p6ol4uVAig97Dt1ww9ZqqmA7dUXczrMTcJcWFbsS39red8eeWmkm Guy9rrsNTw7yrtOjrWagQgC3Bi2UwoUr4ALgk7TzAt4gWckMqA+nAJ5HmBf1q2iCMzeKT/rqNe9Q YeR0o3cdRmWSNYVOGNcgmZaBGrZQjzxD1n3ATKZokdXyx5bPt1iz8JUD573uIy6ovGUY1/UfuDWu uhnY7EPxVStgwS0v/2yPkx0wLWWqYQCBzNr7POVJZLHRFsKf39EQ+DZuqgUSKkwfXqqkijpuqYBM InKZBGoBIiHTWPlzNfttGrdLnMInZbhA2AtcljwxEbDuzsttvgutYJX6CrGpYlKqJezu3g2Lm1dQ 4SeD54aL4Od3GhTh4VWxBBLSpDTLYfryFgmqWtZC+wGdcom4wnQMXty9GcqeTaMPAazh0fvo2Lmc TajmmNY+HYkPlQ9tHVWa3OiRl5L42ItiwC0WYgXnT4rLxVWT6/URnlMgFSx8NrMNkZNp+yeCdYJy oH03nYttPoT0e6IDqj88foy7KoEHi3EOsTJdQAUSIebLlATPluDhCaaF55x0YillJ8l020neisBb OEhf89zCLhwHxzXYvJhIKUW3quaQrkefApbYW3Y7Th7kI4HeDzn4IDEEE2uJS0eM265Ck7wTcotu RsetH6L6JY4JM/z5rR0++dPekPHSL5F60FONE3hcut2JNNammaZ3odUQBjlXOGSjOPu8yUjQjBsD qlInio0EUzxdV1FzqbqbFJPeM85P4769ewVGZzqyBdqdoQH3rllmQvDv1OFTBCFxvC6+TbofNgGA aXR22N54EvyTMVA4rcOg9ZQJ2q1TtAkDoicoYuDfiDY7TtrKJKDBnsNO74aPemxKHuZAI8O5kzvi MmG9ZHYNV+yilMYgDFiFACUuzFWrphqgrVZ7cbNM9WAb2OOEPEB91JMYRTsFU3NMg+1pcGTBWCIP BWrRRqp1DLJXxWzeY/pESef1JNKM7Q6xfCyyss6luq90SKufagZZG1WU0ltG1eM8B5H73OsWRw== </Signature> </Certificate> |
Added tcl/8.4/tcllib1.15/aes/pkgIndex.tcl version [cb678b1c13].
> > > > > | 1 2 3 4 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/tcllib1.15/aes/pkgIndex.tcl.harpy version [a09a0c1eb4].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | <?xml version="1.0" encoding="utf-8"?> <!-- Eagle Enterprise Edition Script Certificate The format of this file is proprietary and may not be reverse engineered. This certificate file is subject to the terms of the license agreement located at: https://eagle.to/enterprise/license.html By using this file and/or the associated software, you agree to abide by the terms of the license agreement. PLEASE DO NOT EDIT THIS FILE. THE ASSOCIATED SOFTWARE MAY NOT WORK PROPERLY IF THIS FILE IS ALTERED. --> <Certificate xmlns="https://eagle.to/2011/harpy" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Protocol>None</Protocol> <Vendor>Mistachkin Systems</Vendor> <Id>8a806368-bf22-47be-8bef-5600be931cb2</Id> <HashAlgorithm>SHA512</HashAlgorithm> <EntityType>Script</EntityType> <TimeStamp>2016-08-13T19:13:47.8515625Z</TimeStamp> <Duration>-1.00:00:00</Duration> <Key>0x2c322765603b5278</Key> <Signature> FMzWAxor84OdXxLHTUUerNdIrtmL4cHa4OshraWMKQsKCgEdIG99VekBRZhrLQjgKpvyZ8I25QW3 dLGZeveW7J9GAlEj2iIgq215IRiCK8H4adhjKqlo/H3CpkQRxt2/uvHwqAfKuXYn8Z87y+U/ojMA P0MLuv+ARS3QY8AC5QGG8Q3FUnEVo0EFRuQxQHD+x4WlbnoRWDE6mRDr4f6WvPvakDzIiEr5DL1r maFWwW0CYn57o0GlAeqHoXBnS7sZq8qweCF+W3HGpWMwoh+6VKrwX6zGSwTL4oEtRTJ6Wb9+8YP+ EftWsJ80nAWGIE5w2C4ljgAvFD2tcUSMycFxKWT3SBySsZGmkOZBxvMJJej8kF6TCJ1BXoZVY+Ja gLDU9yQqLQC5gCPgoav4wMV9kis5g7hTs4S/i9K569DPICvly2Acfunc3gpm7ubTXNnW+1M5pH56 OENMJ+u7HLA3EF2L5fpIsEMhWIznqlJ68EiIkC9inmfYxV/R30F58DLzkvyOqkwrjJIV8zi4mm5Q 19u0zNoeFqHDPeD+f9YhA76Ah9Pawgv9hZvcpka1rd3VxvLhS8tdSmXJvDzVMXxO4BPoy5rV89rV 7h06bUmLda3UHKQlzUCSQ4SpMzHKyDzMyGzVBn6XZxppjtk7AcpzJL5FIZOeue/c4ott3iECOsWb pXgIoABA0bNbIFrkOjvcaEIWeLhTPUcbSCBYeVwUrcVi87mCiETam+kSSCnVC4jfbKm5DCL2OMsj QyEIxNrNKKddWXS9rTEAhxCoAdYpiUtGB2Jpup88l/BdJgX1Qyi0zqMoCk2sYeHErheCmAy+KV1M CrrL9p8ta9WxEHSX1ROl/pmnJo284wC47bNIKbxljHvT035kkUfyQuFxZ7AbV82kosCnUbzAZYf/ i1bUp4krXH60IrMBxaYjmo8itMHMTDYEJQ6O29NNV+TXdDFjRH3ur8iUQfoPnUvwpdtPt9ZfEEN+ OO6xTJ55tM5uCbzGV/9i8a1EHBQqkhjjnG/z6Am8yeJmLRGmxIaO1hScf82EwF27UDxutWUrTmev w63VgokcK1WKLDOzeNx/DmRRCjNViYtwkvi3GuwGVaNqAwYjxEZyo4y9ZauPw7oFbGa3hAQjrb2o tPAGnirvAR2ryqI3psAPfRgn5I+IKPgsLb3KN8YCmJXCtfXvEsAHvXUcRUhIQlFtPBDzOXRN4aWE 1RXReJf66zxMDT00lIiEL3/qOHz2aE3KUPlU7fgysQ5VmH8MOv7kQ/l3+BWxhWsOWQZwl2gogc7Q ypsWnCCu+PBGMvTWuPaHGFrSBmH56xjc75g0C+oQh9N0DHeUvO+afOa7eyl5WG/eA+uIlSIgKQ== </Signature> </Certificate> |