ZRCola/bin/ZRCUpdate.wsf

656 lines
27 KiB
XML

<?xml version="1.0"?>
<!--
Copyright 2016 Amebis
This file is part of ZRCola.
ZRCola is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ZRCola is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with ZRCola. If not, see <http://www.gnu.org/licenses/>.
-->
<package>
<job id="CharImport">
<runtime>
<description>Unicode Character Description Update - Amebis, Copyright © 2016</description>
<unnamed name="&lt;ZRCola.mdb&gt;" required="true" helpstring="ZRCola database"/>
<unnamed name="&lt;UnicodeData.txt&gt;" required="true" helpstring="Unicode character database (from http://www.unicode.org/Public/UNIDATA/UnicodeData.txt)"/>
<named name="F" type="simple" required="false" helpstring="Force overwrite of existing data"/>
</runtime>
<reference object="ADODB.Connection"/>
<reference object="ADODB.Command"/>
<reference object="ADODB.Recordset"/>
<reference object="Scripting.FileSystemObject"/>
<script language="JScript"><![CDATA[
if (WScript.Arguments.Unnamed.Length < 2) {
WScript.Arguments.ShowUsage();
WScript.Quit(1);
}
var force = WScript.Arguments.Named.Exists("F") ? true : false;
// Open ZRCola database.
var db = WScript.CreateObject("ADODB.Connection");
db.Open("Driver={Microsoft Access Driver (*.mdb)};Dbq=" + WScript.Arguments.Unnamed(0) + ";Uid=;Pwd=;");
try {
// Open Unicode Data file.
var
fso = WScript.CreateObject("Scripting.FileSystemObject"),
f = fso.OpenTextFile(WScript.Arguments.Unnamed(1), ForReading);
try {
var
now = new Date(),
com = WScript.CreateObject("ADODB.Command"), param_znak,
rs = WScript.CreateObject("ADODB.Recordset");
com.Prepared = true;
com.ActiveConnection = db;
com.CommandType = adCmdText;
com.CommandText = "SELECT TOP 1 * FROM [VRS_CharList] WHERE [znak]=?";
com.Parameters.Append(param_znak = com.CreateParameter("znak", adChar, adParamInput, 4));
rs.CursorLocation = adUseClient;
rs.CursorType = adOpenDynamic;
rs.LockType = adLockOptimistic;
db.BeginTrans();
try {
// Parse Unicode Data file.
while (!f.AtEndOfStream) {
var
line = f.ReadLine(),
fields = line.split(";"),
unicode = parseInt(fields[0], 16),
v;
if (unicode < 0x0020 || 0xffff < unicode) {
// Skip characters outside of 0020-FFFF range.
continue;
}
// Convert Unicode HEX code to uppercase for consistent database experience.
fields[ 0] = fields[ 0].toUpperCase();
fields[12] = fields[12] != "" ? fields[12].toUpperCase() : fields[ 0];
fields[13] = fields[13] != "" ? fields[13].toUpperCase() : fields[ 0];
fields[14] = fields[14] != "" ? fields[14].toUpperCase() : fields[12];
var
desc_en = fields[1] != "<control>" ? fields[1] : fields[10],
dig_dec = fields[6] != "" ? parseInt(fields[6], 10) : null,
digit = fields[7] != "" ? parseInt(fields[7], 10) : null,
mirror = fields[9] == "Y" || fields[9] == "y";
if (fields[1].charAt(0) == "<") {
// Skip range start and stop descriptors.
continue;
}
// Search the character.
param_znak.Value = fields[0];
rs.Open(com);
try {
if (rs.EOF) {
// If a character does not exist yet, create it.
rs.AddNew();
rs("znak" ).Value = fields[0];
rs("znakZRCOLA" ).Value = String.fromCharCode(unicode);
rs("opis_en" ).Value = desc_en;
rs("kat" ).Value = fields[2];
rs("komb" ).Value = parseInt(fields[3], 10);
rs("stevka10" ).Value = dig_dec;
rs("stevka" ).Value = digit;
rs("stevilo" ).Value = fields[8];
rs("zrcali" ).Value = mirror ? 1 : 0;
rs("znak_v" ).Value = fields[12];
rs("znakZRCOLA_v" ).Value = String.fromCharCode(parseInt(fields[12], 16));
rs("znak_m" ).Value = fields[13];
rs("znakZRCOLA_m" ).Value = String.fromCharCode(parseInt(fields[13], 16));
rs("znak_tc" ).Value = fields[14];
rs("znakZRCOLA_tc").Value = String.fromCharCode(parseInt(fields[14], 16));
rs.Update();
} else {
var updated = false;
if (force || (v = rs("opis_en").Value) == null || v == "") { rs("opis_en" ).Value = desc_en; updated = true; }
if (force || (v = rs("kat" ).Value) == null || v == "") { rs("kat" ).Value = fields[2]; updated = true; }
if (force || (v = rs("komb" ).Value) == null ) { rs("komb" ).Value = parseInt(fields[3], 10); updated = true; }
if (force ) { rs("stevka10").Value = dig_dec; updated = true; }
if (force ) { rs("stevka" ).Value = digit; updated = true; }
if (force ) { rs("stevilo" ).Value = fields[8]; updated = true; }
if (force ) { rs("zrcali" ).Value = mirror ? 1 : 0; updated = true; }
if (force ) { rs("znak_v" ).Value = fields[12]; rs("znakZRCOLA_v" ).Value = String.fromCharCode(parseInt(fields[12], 16)); updated = true; }
if (force ) { rs("znak_m" ).Value = fields[13]; rs("znakZRCOLA_m" ).Value = String.fromCharCode(parseInt(fields[13], 16)); updated = true; }
if (force ) { rs("znak_tc" ).Value = fields[14]; rs("znakZRCOLA_tc").Value = String.fromCharCode(parseInt(fields[14], 16)); updated = true; }
if (updated) {
// Changing [updat] field causes Microsoft Cursor Engine: Row cannot be located for updating. Some values may have been changed since it was last read.
//rs("updat").Value = (new Date(now.getTime() + now.getTimezoneOffset()*60*1000)).getVarDate();
rs.Update();
}
}
} finally {
rs.Close();
}
}
db.CommitTrans();
} catch (err) {
db.RollbackTrans();
throw err;
}
} finally {
f.Close();
}
} finally {
db.Close();
}
WScript.Quit(0);
]]></script>
</job>
<job id="CharDescGenerate">
<runtime>
<description>Dynamic Character Description Generator - Amebis, Copyright © 2016</description>
<unnamed name="&lt;ZRCola.mdb&gt;" required="true" helpstring="ZRCola database"/>
<named name="F" type="simple" required="false" helpstring="Force overwrite of existing data"/>
</runtime>
<reference object="ADODB.Connection"/>
<reference object="ADODB.Command"/>
<reference object="ADODB.Recordset"/>
<script language="JScript"><![CDATA[
if (WScript.Arguments.Unnamed.Length < 1) {
WScript.Arguments.ShowUsage();
WScript.Quit(1);
}
function ZRColaDecompositionParser(db)
{
// Prepare query for existing character description search.
this.com_desc = WScript.CreateObject("ADODB.Command");
this.com_desc.Prepared = true;
this.com_desc.ActiveConnection = db;
this.com_desc.CommandType = adCmdText;
this.com_desc.CommandText = "SELECT TOP 1 [opis_en] FROM [VRS_CharList] WHERE [znak]=?";
this.com_desc.Parameters.Append(this.param_desc_znak = this.com_desc.CreateParameter("znak", adChar, adParamInput, 4));
this.rs_desc = WScript.CreateObject("ADODB.Recordset");
this.rs_desc.CursorLocation = adUseClient;
this.rs_desc.CursorType = adOpenStatic;
this.rs_desc.LockType = adLockReadOnly;
}
ZRColaDecompositionParser.prototype.nextChar = function()
{
if (!this.decomposed.length) {
this.sym = null;
this.desc = null;
return;
}
// Get next character.
this.sym = this.decomposed.shift();
// Get character's description.
this.param_desc_znak.Value = this.sym;
this.rs_desc.Open(this.com_desc);
try {
if (!this.rs_desc.EOF) {
var v;
if ((v = this.rs_desc("opis_en").Value) != null && v != "")
this.desc = v;
else
throw new Error(this.sym + " character has no description.");
} else
throw new Error(this.sym + " character not found.");
} finally {
this.rs_desc.Close();
}
}
ZRColaDecompositionParser.prototype.modifiers = function()
{
var desc = "";
for (;;) {
if (
this.sym >= "E000" && this.sym <= "E05B" || // 1st Set of Modifiers
this.sym >= "E063" && this.sym <= "E0BB" || // 2nd Set of Modifiers
this.sym == "003A" || // Colon
this.sym == "2019") // Right Single Quotation Mark
{
desc += (desc.length ? " AND " : "") + this.desc;
this.nextChar();
} else if (this.sym >= "02B0" && this.sym <= "02FF") {
// Standard Unicode Modifiers
if (this.desc.indexOf("MODIFIER LETTER ") == 0)
this.desc = this.desc.substring(16);
desc += (desc.length ? " AND " : "") + this.desc;
this.nextChar();
} else
break;
}
return desc.length ? desc : null;
}
ZRColaDecompositionParser.prototype.envelopes = function()
{
var desc = "";
for (;;) {
if (
this.sym == "E0C0" || // Circle
this.sym == "E0C2" || // Square
this.sym == "E0CA") // Diamond
{
desc += (desc.length ? " AND " : "") + this.desc;
this.nextChar();
} else
break;
}
return desc.length ? desc : null;
}
ZRColaDecompositionParser.prototype.parentheses = function(open, close, desc)
{
if (this.sym == open) {
// Parenthesis Start
this.nextChar();
var desc_p = desc + " " + this.expression();
if (this.sym == close) {
// Parenthesis End
this.nextChar();
} else
throw new Error(this.sym + " is unexpected. Should end with " + close + ".");
return desc_p;
} else
return null;
}
ZRColaDecompositionParser.prototype.character = function()
{
var desc;
if (desc = this.parentheses("E0C5", "E0C6", "SUPERSCRIPTED")) {
// Superscript
return desc;
} else if (desc = this.parentheses("E2E0", "E2E1", "EVA DOUBLED")) {
// EVA Double
return desc;
} else if (desc = this.parentheses("E2E2", "E2E3", "EVA CONDENSED")) {
// EVA Condensed
return desc;
} else if (desc = this.parentheses("E2E4", "E2E5", "EVA EMPHASIZED")) {
// EVA Emphasis
return desc;
} else if (desc = this.parentheses("E2E6", "E2E7", "EVA STRIKED")) {
// EVA Strike
return desc;
} else if (desc = this.parentheses("E2E8", "E2E9", "EVA UNDEALED")) {
// EVA Undeal
return desc;
} else if (desc = this.parentheses("E2EA", "E2EB", "EVA ITALIC")) {
// EVA Italic
return desc;
} else if (desc = this.parentheses("E2EC", "E2ED", "EVA SUPERSCRIPTED")) {
// EVA Superscript
return desc;
} else if (desc = this.parentheses("E2EE", "E2EF", "EVA SUBSCRIPTED")) {
// EVA Subscript
return desc;
} else if (this.sym < "E000" || this.sym > "E0FC") {
// Base Character
desc = this.desc;
this.nextChar();
var has_with = desc.indexOf(" WITH ") >= 0;
for (;;) {
var desc2;
if (desc2 = this.modifiers()) {
desc += (has_with ? " AND " : " WITH ") + desc2;
has_with = true;
} else if (desc2 = this.envelopes()) {
desc += " IN " + desc2;
has_with = false;
} else
break;
}
return desc;
} else
throw new Error("Syntax error");
}
ZRColaDecompositionParser.prototype.term = function()
{
var desc = new Array(this.character());
while (this.sym == "E0C4") {
// Ligature
this.nextChar();
desc.push(this.character());
}
if (desc.length == 1) {
return desc[0];
} else if (desc.length == 2) {
if (desc[0] == desc[1])
return "DOUBLE " + desc[0];
} else if (desc.length == 3) {
if (desc[0] == desc[1] && desc[0] == desc[2])
return "TRIPLE " + desc[0];
}
return desc.join(" AND ") + " LIGATURE";
}
ZRColaDecompositionParser.prototype.expression = function()
{
var desc = "";
if (this.sym >= "E0F0" && this.sym <= "E0FC") {
// Prefix modifier
desc += this.desc + " ";
this.nextChar();
}
desc += this.term();
while (
this.sym >= "E05C" && this.sym <= "E062" ||
this.sym == "E0C1" || this.sym == "E0C3" || this.sym == "E0C7" || this.sym == "E0CB" || this.sym == "E0D0" || this.sym == "E0D1")
{
// Joiner
desc += " " + this.desc + " WITH ";
this.nextChar();
var desc2 = "";
for (;;) {
var desc3;
if (desc3 = this.modifiers())
desc2 += (desc2.length ? " AND " : " WITH ") + desc3;
else if (desc3 = this.envelopes())
desc2 += " IN " + desc3;
else
break;
}
desc += this.term();
desc += desc2;
}
return desc;
}
ZRColaDecompositionParser.prototype.parse = function(decomposed)
{
this.decomposed = decomposed.slice(0); // Duplicate array.
this.nextChar();
var desc = this.expression();
if (this.sym != null)
throw new Error("Unexpected trailing characters.");
return desc;
}
var force = WScript.Arguments.Named.Exists("F") ? true : false;
// Open ZRCola database.
var db = WScript.CreateObject("ADODB.Connection");
db.Open("Driver={Microsoft Access Driver (*.mdb)};Dbq=" + WScript.Arguments.Unnamed(0) + ";Uid=;Pwd=;");
try {
// Prepare query for character decomposition.
var com_comp = WScript.CreateObject("ADODB.Command"), param_comp_znak;
com_comp.Prepared = true;
com_comp.ActiveConnection = db;
com_comp.CommandType = adCmdText;
com_comp.CommandText = "SELECT UCase([komb]) AS [kombUC] FROM [VRS_ReplChar] WHERE [znak]=? ORDER BY [rang_znak] ASC";
com_comp.Parameters.Append(param_comp_znak = com_comp.CreateParameter("znak", adChar, adParamInput, 4));
db.BeginTrans();
try {
// Query all private-use characters.
var rs = WScript.CreateObject("ADODB.Recordset");
rs.CursorLocation = adUseClient;
rs.Open("SELECT * FROM [VRS_CharList] WHERE 'E000'<=[znak] AND [znak]<='F8FF' AND [kat] IS NULL", db, adOpenDynamic, adLockOptimistic, adCmdText);
try {
var rs_comp = WScript.CreateObject("ADODB.Recordset");
rs_comp.CursorLocation = adUseClient;
rs_comp.CursorType = adOpenStatic;
rs_comp.LockType = adLockReadOnly;
var parser = new ZRColaDecompositionParser(db);
for (; !rs.EOF; rs.MoveNext()) {
var v;
if (!force && (v = rs("opis_en").Value) != null && v != "") {
// This character already has the description.
continue;
}
// Decompose character.
var chr = rs("znak").Value;
param_comp_znak.Value = chr;
rs_comp.Open(com_comp);
try {
for (; !rs_comp.EOF; rs_comp.MoveNext()) {
var
decomposed = (v = rs_comp("kombUC").Value) != null ? (new String(v)).split("+") : new Array(),
n = decomposed.length;
if (n > 0) {
try {
var desc = parser.parse(decomposed);
rs("opis_en").value = desc;
rs.update();
break;
} catch (err) {
// We couldn't generate character description according to decomposition.
WScript.Echo(chr + " >> " + decomposed.join("+") + ": " + err.message);
}
};
}
} finally {
rs_comp.Close();
}
}
} finally {
rs.Close();
}
db.CommitTrans();
} catch (err) {
db.RollbackTrans();
throw err;
}
} finally {
db.Close();
}
WScript.Quit(0);
]]></script>
</job>
<signature>
** SIG ** MIIXmAYJKoZIhvcNAQcCoIIXiTCCF4UCAQExCzAJBgUr
** SIG ** DgMCGgUAMGcGCisGAQQBgjcCAQSgWTBXMDIGCisGAQQB
** SIG ** gjcCAR4wJAIBAQQQcAVhGs441BGiowAQS9NQkAIBAAIB
** SIG ** AAIBAAIBAAIBADAhMAkGBSsOAwIaBQAEFPhq7XksMSKn
** SIG ** 4Rdbedv+eKDdjJ50oIISyDCCA+4wggNXoAMCAQICEH6T
** SIG ** 6/t8xk5Z6kuad9QG/DswDQYJKoZIhvcNAQEFBQAwgYsx
** SIG ** CzAJBgNVBAYTAlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENh
** SIG ** cGUxFDASBgNVBAcTC0R1cmJhbnZpbGxlMQ8wDQYDVQQK
** SIG ** EwZUaGF3dGUxHTAbBgNVBAsTFFRoYXd0ZSBDZXJ0aWZp
** SIG ** Y2F0aW9uMR8wHQYDVQQDExZUaGF3dGUgVGltZXN0YW1w
** SIG ** aW5nIENBMB4XDTEyMTIyMTAwMDAwMFoXDTIwMTIzMDIz
** SIG ** NTk1OVowXjELMAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5
** SIG ** bWFudGVjIENvcnBvcmF0aW9uMTAwLgYDVQQDEydTeW1h
** SIG ** bnRlYyBUaW1lIFN0YW1waW5nIFNlcnZpY2VzIENBIC0g
** SIG ** RzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
** SIG ** AQCxrLNJVEuXHBIK2CV5kSJXKm/cuCbEQ3Nrwr8uUFr7
** SIG ** FMJ2jkMBJUO0oeJF9Oi3e8N0zCLXtJQAAvdN7b+0t0Qk
** SIG ** a81fRTvRRM5DEnMXgotptCvLmR6schsmTXEfsTHd+1Fh
** SIG ** AlOmqvVJLAV4RaUvic7nmef+jOJXPz3GktxK+Hsz5HkK
** SIG ** +/B1iEGc/8UDUZmq12yfk2mHZSmDhcJgFMTIyTsU2sCB
** SIG ** 8B8NdN6SIqvK9/t0fCfm90obf6fDni2uiuqm5qonFn1h
** SIG ** 95hxEbziUKFL5V365Q6nLJ+qZSDT2JboyHylTkhE/xni
** SIG ** RAeSC9dohIBdanhkRc1gRn5UwRN8xXnxycFxAgMBAAGj
** SIG ** gfowgfcwHQYDVR0OBBYEFF+a9W5czMx0mtTdfe8/2+xM
** SIG ** gC7dMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcwAYYW
** SIG ** aHR0cDovL29jc3AudGhhd3RlLmNvbTASBgNVHRMBAf8E
** SIG ** CDAGAQH/AgEAMD8GA1UdHwQ4MDYwNKAyoDCGLmh0dHA6
** SIG ** Ly9jcmwudGhhd3RlLmNvbS9UaGF3dGVUaW1lc3RhbXBp
** SIG ** bmdDQS5jcmwwEwYDVR0lBAwwCgYIKwYBBQUHAwgwDgYD
** SIG ** VR0PAQH/BAQDAgEGMCgGA1UdEQQhMB+kHTAbMRkwFwYD
** SIG ** VQQDExBUaW1lU3RhbXAtMjA0OC0xMA0GCSqGSIb3DQEB
** SIG ** BQUAA4GBAAMJm495739ZMKrvaLX64wkdu0+CBl03X6ZS
** SIG ** nxaN6hySCURu9W3rWHww6PlpjSNzCxJvR6muORH4KrGb
** SIG ** sBrDjutZlgCtzgxNstAxpghcKnr84nodV0yoZRjpeUBi
** SIG ** JZZux8c3aoMhCI5B6t3ZVz8dd0mHKhYGXqY4aiISo1EZ
** SIG ** g362MIIEozCCA4ugAwIBAgIQDs/0OMj+vzVuBNhqmBsa
** SIG ** UDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEd
** SIG ** MBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xMDAu
** SIG ** BgNVBAMTJ1N5bWFudGVjIFRpbWUgU3RhbXBpbmcgU2Vy
** SIG ** dmljZXMgQ0EgLSBHMjAeFw0xMjEwMTgwMDAwMDBaFw0y
** SIG ** MDEyMjkyMzU5NTlaMGIxCzAJBgNVBAYTAlVTMR0wGwYD
** SIG ** VQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjE0MDIGA1UE
** SIG ** AxMrU3ltYW50ZWMgVGltZSBTdGFtcGluZyBTZXJ2aWNl
** SIG ** cyBTaWduZXIgLSBHNDCCASIwDQYJKoZIhvcNAQEBBQAD
** SIG ** ggEPADCCAQoCggEBAKJjCzlEuLsjp0RJuw7/ofBhClOT
** SIG ** sJjbrSwPSsVu/4Y8U1UPFc4EPyv9qZaW2b5heQtbyUyG
** SIG ** duXgQ0sile7CK0PBn9hotI5AT+6FOLkRxSPyZFjwFTJv
** SIG ** TlehroikAtcqHs1L4d1j1ReJMluwXplaqJ0oUA4X7pbb
** SIG ** YTtFUR3PElYLkkf8q672Zj1HrHBy55LnX80QucSDZJQZ
** SIG ** vSWA4ejSIqXQugJ6oXeTW2XD7hd0vEGGKtwITIySjJEt
** SIG ** nndEH2jWqHR32w5bMotWizO92WPISZ06xcXqMwvS8aMb
** SIG ** 9Iu+2bNXizveBKd6IrIkri7HcMW+ToMmCPsLvalPmQjh
** SIG ** EChyqs0CAwEAAaOCAVcwggFTMAwGA1UdEwEB/wQCMAAw
** SIG ** FgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwDgYDVR0PAQH/
** SIG ** BAQDAgeAMHMGCCsGAQUFBwEBBGcwZTAqBggrBgEFBQcw
** SIG ** AYYeaHR0cDovL3RzLW9jc3Aud3Muc3ltYW50ZWMuY29t
** SIG ** MDcGCCsGAQUFBzAChitodHRwOi8vdHMtYWlhLndzLnN5
** SIG ** bWFudGVjLmNvbS90c3MtY2EtZzIuY2VyMDwGA1UdHwQ1
** SIG ** MDMwMaAvoC2GK2h0dHA6Ly90cy1jcmwud3Muc3ltYW50
** SIG ** ZWMuY29tL3Rzcy1jYS1nMi5jcmwwKAYDVR0RBCEwH6Qd
** SIG ** MBsxGTAXBgNVBAMTEFRpbWVTdGFtcC0yMDQ4LTIwHQYD
** SIG ** VR0OBBYEFEbGaaMOShQe1UzaUmMXP142vA3mMB8GA1Ud
** SIG ** IwQYMBaAFF+a9W5czMx0mtTdfe8/2+xMgC7dMA0GCSqG
** SIG ** SIb3DQEBBQUAA4IBAQB4O7SRKgBM8I9iMDd4o4QnB28Y
** SIG ** st4l3KDUlAOqhk4ln5pAAxzdzuN5yyFoBtq2MrRtv/Qs
** SIG ** JmMz5ElkbQ3mw2cO9wWkNWx8iRbG6bLfsundIMZxD82V
** SIG ** dNy2XN69Nx9DeOZ4tc0oBCCjqvFLxIgpkQ6A0RH83Vx2
** SIG ** bk9eDkVGQW4NsOo4mrE62glxEPwcebSAe6xp9P2ctgwW
** SIG ** K/F/Wwk9m1viFsoTgW0ALjgNqCmPLOGy9FqpAa8VnCwv
** SIG ** SRvbIrvD/niUUcOGsYKIXfA9tFGheTMrLnu53CAJE3Hr
** SIG ** ahlbz+ilMFcsiUk/uc9/yb8+ImhjU5q9aXSsxR08f5Lg
** SIG ** w7wc2AR1MIIEzjCCA7agAwIBAgIQMHo2eqo+aIGm+U8I
** SIG ** yzs5ZDANBgkqhkiG9w0BAQsFADB/MQswCQYDVQQGEwJV
** SIG ** UzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24x
** SIG ** HzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsx
** SIG ** MDAuBgNVBAMTJ1N5bWFudGVjIENsYXNzIDMgU0hBMjU2
** SIG ** IENvZGUgU2lnbmluZyBDQTAeFw0xNTEwMDkwMDAwMDBa
** SIG ** Fw0xODExMDcyMzU5NTlaMGExCzAJBgNVBAYTAlNJMREw
** SIG ** DwYDVQQIEwhTbG92ZW5pYTEPMA0GA1UEBxMGS2Ftbmlr
** SIG ** MRYwFAYDVQQKFA1BbWViaXMgZC5vLm8uMRYwFAYDVQQD
** SIG ** FA1BbWViaXMgZC5vLm8uMIIBIjANBgkqhkiG9w0BAQEF
** SIG ** AAOCAQ8AMIIBCgKCAQEAl/LoF3DHaSrIaG1pgBmBwDyl
** SIG ** Yt7sRvIuoEdGr/yMhV9RfUIft+xsTPVQOAirvgG+KUbc
** SIG ** E3KMnGH+VuK7Y+vYzRp3dYTLinSQz1NKYAELyTdVzmmY
** SIG ** mU3LX764yk3ABtSZsZwPoiCy+TXE9ZsCkugB2c7Qp9N/
** SIG ** O9EjjQDRwZlUa3nLoY96Y3qNPwkCn04ppYiqPeIXTRz8
** SIG ** XBLs4Nl/bD9wymEuNSV75vzobJ7BUYQwRU7lmNL2SwRY
** SIG ** ENaf0DpdiyFLBsNafHjGYiXQHgNxZUBpj7OoRDNBvMQY
** SIG ** L+LM8OrjhGIK1uGL5CqBD/p81ebeFsAZVxg9hrgnkPVQ
** SIG ** w77U0LZw8wIDAQABo4IBYjCCAV4wCQYDVR0TBAIwADAO
** SIG ** BgNVHQ8BAf8EBAMCB4AwKwYDVR0fBCQwIjAgoB6gHIYa
** SIG ** aHR0cDovL3N2LnN5bWNiLmNvbS9zdi5jcmwwZgYDVR0g
** SIG ** BF8wXTBbBgtghkgBhvhFAQcXAzBMMCMGCCsGAQUFBwIB
** SIG ** FhdodHRwczovL2Quc3ltY2IuY29tL2NwczAlBggrBgEF
** SIG ** BQcCAjAZDBdodHRwczovL2Quc3ltY2IuY29tL3JwYTAT
** SIG ** BgNVHSUEDDAKBggrBgEFBQcDAzBXBggrBgEFBQcBAQRL
** SIG ** MEkwHwYIKwYBBQUHMAGGE2h0dHA6Ly9zdi5zeW1jZC5j
** SIG ** b20wJgYIKwYBBQUHMAKGGmh0dHA6Ly9zdi5zeW1jYi5j
** SIG ** b20vc3YuY3J0MB8GA1UdIwQYMBaAFJY7U/B5M5evfYPv
** SIG ** LivMyreGHnJmMB0GA1UdDgQWBBT3B72WgJotdMR/DD09
** SIG ** J93UkAqfzDANBgkqhkiG9w0BAQsFAAOCAQEAinEvQC+1
** SIG ** yttKEsqAjt2YufpYlul3OQH17YKbUy4AAiKiAsUXWfTu
** SIG ** XRVdkT6CrEYcHyOLaHfe36jVHw8vLIiR2cyEcB3vweyr
** SIG ** JnNpt+Za4I/XZMoG/vvCJmSltOj8C/7PRKWklGgynPNe
** SIG ** HI8+0d1vLzRtK77hFeV7CIMIfnpoYThJKTSLxdr0kn+j
** SIG ** M8otfdLN2aDonnxe0Mf+2rkrX8AFIIHPpIXZj2X2VEmk
** SIG ** ZdyFINgI+KlJVQY/RY9BFMM2htLAIkNcDP1QVzFajhGH
** SIG ** yj+C+UtZQf5PceGYtJHNeq3cm6omjnEfyzi8/NwYFlkW
** SIG ** hvzJEH3woPqKgUramNFFLD0W5zCCBVkwggRBoAMCAQIC
** SIG ** ED141/l2SWCyYX308B7KhiowDQYJKoZIhvcNAQELBQAw
** SIG ** gcoxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2ln
** SIG ** biwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3Qg
** SIG ** TmV0d29yazE6MDgGA1UECxMxKGMpIDIwMDYgVmVyaVNp
** SIG ** Z24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s
** SIG ** eTFFMEMGA1UEAxM8VmVyaVNpZ24gQ2xhc3MgMyBQdWJs
** SIG ** aWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
** SIG ** eSAtIEc1MB4XDTEzMTIxMDAwMDAwMFoXDTIzMTIwOTIz
** SIG ** NTk1OVowfzELMAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5
** SIG ** bWFudGVjIENvcnBvcmF0aW9uMR8wHQYDVQQLExZTeW1h
** SIG ** bnRlYyBUcnVzdCBOZXR3b3JrMTAwLgYDVQQDEydTeW1h
** SIG ** bnRlYyBDbGFzcyAzIFNIQTI1NiBDb2RlIFNpZ25pbmcg
** SIG ** Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
** SIG ** AQCXgx4AFq8ssdIIxNdok1FgHnH24ke021hNI2JqtL9a
** SIG ** G1H3ow0Yd2i72DarLyFQ2p7z518nTgvCl8gJcJOp2lwN
** SIG ** TqQNkaC07BTOkXJULs6j20TpUhs/QTzKSuSqwOg5q1PM
** SIG ** IdDMz3+b5sLMWGqCFe49Ns8cxZcHJI7xe74xLT1u3LWZ
** SIG ** Qp9LYZVfHHDuF33bi+VhiXjHaBuvEXgamK7EVUdT2bMy
** SIG ** 1qEORkDFl5KK0VOnmVuFNVfT6pNiYSAKxzB3JBFNYoO2
** SIG ** untogjHuZcrf+dWNsjXcjCtvanJcYISc8gyUXsBWUgBI
** SIG ** zNP4pX3eL9cT5DiohNVGuBOGwhud6lo43ZvbAgMBAAGj
** SIG ** ggGDMIIBfzAvBggrBgEFBQcBAQQjMCEwHwYIKwYBBQUH
** SIG ** MAGGE2h0dHA6Ly9zMi5zeW1jYi5jb20wEgYDVR0TAQH/
** SIG ** BAgwBgEB/wIBADBsBgNVHSAEZTBjMGEGC2CGSAGG+EUB
** SIG ** BxcDMFIwJgYIKwYBBQUHAgEWGmh0dHA6Ly93d3cuc3lt
** SIG ** YXV0aC5jb20vY3BzMCgGCCsGAQUFBwICMBwaGmh0dHA6
** SIG ** Ly93d3cuc3ltYXV0aC5jb20vcnBhMDAGA1UdHwQpMCcw
** SIG ** JaAjoCGGH2h0dHA6Ly9zMS5zeW1jYi5jb20vcGNhMy1n
** SIG ** NS5jcmwwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUF
** SIG ** BwMDMA4GA1UdDwEB/wQEAwIBBjApBgNVHREEIjAgpB4w
** SIG ** HDEaMBgGA1UEAxMRU3ltYW50ZWNQS0ktMS01NjcwHQYD
** SIG ** VR0OBBYEFJY7U/B5M5evfYPvLivMyreGHnJmMB8GA1Ud
** SIG ** IwQYMBaAFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG
** SIG ** SIb3DQEBCwUAA4IBAQAThRoeaak396C9pK9+HWFT/p2M
** SIG ** XgymdR54FyPd/ewaA1U5+3GVx2Vap44w0kRaYdtwb9oh
** SIG ** BcIuc7pJ8dGT/l3JzV4D4ImeP3Qe1/c4i6nWz7s1LzNY
** SIG ** qJJW0chNO4LmeYQW/CiwsUfzHaI+7ofZpn+kVqU/rYQu
** SIG ** Kd58vKiqoz0EAeq6k6IOUCIpF0yH5DoRX9akJYmbBWsv
** SIG ** tMkBTCd7C6wZBSKgYBU/2sn7TUyP+3Jnd/0nlMe6NQ6I
** SIG ** Sf6N/SivShK9DbOXBd5EDBX6NisD3MFQAfGhEV0U5eK9
** SIG ** J0tUviuEXg+mw3QFCu+Xw4kisR93873NQ9TxTKk/tYuE
** SIG ** r2Ty0BQhMYIEPDCCBDgCAQEwgZMwfzELMAkGA1UEBhMC
** SIG ** VVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9u
** SIG ** MR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3Jr
** SIG ** MTAwLgYDVQQDEydTeW1hbnRlYyBDbGFzcyAzIFNIQTI1
** SIG ** NiBDb2RlIFNpZ25pbmcgQ0ECEDB6NnqqPmiBpvlPCMs7
** SIG ** OWQwCQYFKw4DAhoFAKBwMBAGCisGAQQBgjcCAQwxAjAA
** SIG ** MBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisG
** SIG ** AQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMCMGCSqGSIb3
** SIG ** DQEJBDEWBBTtnq9nJTyuGwPUm/NL7IROjIWVujANBgkq
** SIG ** hkiG9w0BAQEFAASCAQBFZwe6d/h0FY6FPwyAJvEIjoFa
** SIG ** QzBNIjLHoMLr+qLIqOvAOj07kwp4+eb19gKa4V3ePaH+
** SIG ** g8ZXDLRIMWZEtpEuqKYxW5RnOd/iHg4h+PfVhtU4cixr
** SIG ** NK731fhhcYeDWrzPiAKVWqkdHcHFMSRdFNXrGtbpKWMR
** SIG ** 38T9CeAoC7whXK/N61WhBZOs2WqBn2e2bxsCMLPJzpez
** SIG ** 57mYjk8Zlk1d8DkaxiamkmDkpnzL+eFuKiEZSuvgZ7il
** SIG ** UDmtbdOvpUHTQqdZpNksZSUTGX87TvqGh7wxV5xPV0Bj
** SIG ** kRHYIbDoncD99xleC4H7En7aAS1CPOwsGi6ydHjYr6Mk
** SIG ** XKIxeI6ioYICCzCCAgcGCSqGSIb3DQEJBjGCAfgwggH0
** SIG ** AgEBMHIwXjELMAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5
** SIG ** bWFudGVjIENvcnBvcmF0aW9uMTAwLgYDVQQDEydTeW1h
** SIG ** bnRlYyBUaW1lIFN0YW1waW5nIFNlcnZpY2VzIENBIC0g
** SIG ** RzICEA7P9DjI/r81bgTYapgbGlAwCQYFKw4DAhoFAKBd
** SIG ** MBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZI
** SIG ** hvcNAQkFMQ8XDTE2MDQyNjEzMjQ1MlowIwYJKoZIhvcN
** SIG ** AQkEMRYEFOCXzSMTEghkr0AunGczGHuQzCc+MA0GCSqG
** SIG ** SIb3DQEBAQUABIIBAJHp1Wtc6YKicRqFnBN/mw7NsTNB
** SIG ** fYvf1CYHBhl6JX6aRlvehLeXJO4rF46tXV0lSAVONEMs
** SIG ** Cjxc8j2AqEPlHbmL+uiZEwuHquZv+nS1yM1ulNDEiwou
** SIG ** FxUtdRSg3y1KuQ1aTKUhHQ//mxiLhIGzvw8lZcJDqayo
** SIG ** a/0AEkgc8LPbFs5wp+jrNEAxDvTU38ERPjSm6LeCrCeR
** SIG ** pLRkbCAyayCyE+S0Y8dP2Yv1TS0dbPeL5pnBEsr/ym7F
** SIG ** 5DP1tBIm2Rbjl0pxGwTq502wqKGGdJakoxu4wr5xuUXk
** SIG ** BCZCD4OPmggdTYANy+fdmDfv/d0VxgOBmXJKE4nHBGtz
** SIG ** KWx/g/Q=
</signature>
</package>