@naanlang/naan 1.3.2 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +1 -1
  3. package/bin/index.js +25 -15
  4. package/dist/naan.min.js +5 -5
  5. package/frameworks/browser/sworker.js +23 -23
  6. package/frameworks/browser/terminals.nlg +26 -11
  7. package/frameworks/browser/ws_client.nlg +1 -1
  8. package/frameworks/client/psm_client.nlg +3 -1
  9. package/frameworks/client/relaycon.nlg +3 -2
  10. package/frameworks/common/common.nlg +5 -2
  11. package/frameworks/common/preferences.nlg +1 -1
  12. package/frameworks/node/apiserver.nlg +3 -3
  13. package/frameworks/node/filesystem.nlg +5 -4
  14. package/frameworks/node/psm_server.nlg +1 -1
  15. package/frameworks/node/shell.nlg +134 -0
  16. package/frameworks/node/worker.nlg +104 -46
  17. package/frameworks/project/build.nlg +1 -2
  18. package/frameworks/project/jszip.js +0 -0
  19. package/frameworks/project/projects.nlg +1 -1
  20. package/frameworks/running/debugnub.nlg +102 -12
  21. package/frameworks/running/debugutil.nlg +30 -13
  22. package/frameworks/running/executors.nlg +64 -28
  23. package/frameworks/running/running.nlg +85 -3
  24. package/frameworks/running/sourcecode.nlg +3 -1
  25. package/frameworks/running/taskexec.nlg +24 -4
  26. package/frameworks/storage/dbt_pouch.nlg +30 -17
  27. package/frameworks/storage/file_manager.nlg +1 -1
  28. package/frameworks/storage/psm.nlg +11 -1
  29. package/frameworks/storage/psm_dbtables.nlg +21 -22
  30. package/frameworks/storage/resources.nlg +12 -4
  31. package/frameworks/storage/storage.nlg +2 -2
  32. package/lib/browser/env_web.js +6 -6
  33. package/lib/browser/env_webworker.js +2 -0
  34. package/lib/core/naanlib.js +5 -5
  35. package/lib/env_nodeworker.js +2 -0
  36. package/package.json +1 -1
  37. package/plugins/gitClient/gitClient.nlg +3 -3
  38. package/plugins/gitClient/gitutils.nlg +2 -2
  39. package/plugins/nodeLib/node_https.nlg +2 -2
  40. package/plugins/openSearch/openSearch.nlg +2 -2
  41. package/plugins/serviceAws/lambda_naan_control.nlg +3 -3
  42. package/plugins/serviceAws/psm_aws.nlg +4 -2
  43. package/plugins/serviceAws/serviceAws.nlg +1 -1
  44. package/plugins/serviceGC/gc_api.nlg +5 -5
  45. package/plugins/serviceGitHub/gitops.nlg +4 -3
  46. package/plugins/serviceGitHub/psm_github.nlg +1 -1
  47. package/plugins/serviceGitHub/serviceGitHub.nlg +1 -1
  48. package/plugins/serviceGitLab/gitops.nlg +2 -1
  49. package/plugins/serviceGitLab/psm_gitlab.nlg +2 -2
  50. package/plugins/serviceGitLab/serviceGitLab.nlg +1 -1
  51. package/plugins/serviceYC/yc_vm.nlg +1 -1
  52. package/test/harness.nlg +9 -9
  53. package/test/test_01_core.nlg +24 -2
  54. package/test/test_02_context.nlg +2 -2
  55. package/test/test_07_lingo.nlg +3 -3
  56. package/plugins/serviceGC/russian_trusted_root_ca_pem.crt +0 -33
@@ -164,6 +164,8 @@ exports.NaanWorkerActivate = function NaanWorkerActivate(cbReady) {
164
164
  naanlib.textLine(msg.text); // keyboard text from terminal
165
165
  else if (msg.id == "start")
166
166
  { // start execution with optional state
167
+ workSelf.workerID = msg.workerID;
168
+ workSelf.workerGUID = msg.workerGUID;
167
169
  if (typeof(__dirname) !== "undefined")
168
170
  naanlib.js.h = naanlib.js.d; // set host directory path
169
171
  if (msg.dirpath)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naanlang/naan",
3
- "version": "1.3.2",
3
+ "version": "1.4.1",
4
4
  "author": "Richard C. Zulch",
5
5
  "description": "Naan™ software platform",
6
6
  "main": "./lib/core/naanlib.js",
@@ -54,9 +54,9 @@ function gitcInit(local manifest) {
54
54
  })
55
55
  nideCommon = require("nideCommon/nideCommon.nlg")
56
56
  letimport(nideCommon)
57
- require("plugins/gitClient/clientops.nlg")
58
- require("plugins/gitClient/gitutils.nlg")
59
- gitcRequireJS("plugins/gitClient/minimatch.js", function(error, result) {
57
+ require("./clientops.nlg")
58
+ require("./gitutils.nlg")
59
+ gitcRequireJS("./minimatch.js", function(error, result) {
60
60
  if error
61
61
  ErrorDebugLog(error)
62
62
  })
@@ -213,7 +213,7 @@ closure GitTree(local fs, reporoot, gtree, repodir, stagedir) {
213
213
  closure fileHash(fspath, callback) {
214
214
  if !callback
215
215
  return (syncAdapter(fileHash, fspath))
216
- fs.readFile(fspath, false, function(error, strdata, local hash) {
216
+ fs.readFile(fspath, false, function(error, strdata) {
217
217
  if error
218
218
  callback(error)
219
219
  else
@@ -1025,7 +1025,7 @@ closure GitTree(local fs, reporoot, gtree, repodir, stagedir) {
1025
1025
 
1026
1026
  // comrecur
1027
1027
  // Recursively copy portions of tree that should be in commit.
1028
- function comrecur(input, parpath, chout, local node, nodout, path, action) {
1028
+ function comrecur(input, parpath, chout, local node, nodout, path) {
1029
1029
  for node in input {
1030
1030
  nodout = { name: node.name }
1031
1031
  path = joinode(parpath, node)
@@ -17,7 +17,7 @@
17
17
  *
18
18
  */
19
19
 
20
- closure HttpsGetJson(hostname, pathname, query, local https, options, pending, req) {
20
+ closure HttpsGetJson(hostname, pathname, query, local options, pending, req) {
21
21
  if query
22
22
  pathname = EncodeQuery(pathname.concat("?"), query)
23
23
  debuglog("HttpsGetJson", hostname, pathname)
@@ -55,7 +55,7 @@ closure HttpsGetJson(hostname, pathname, query, local https, options, pending, r
55
55
  */
56
56
 
57
57
  closure HttpsDownloadFile(hostname, pathname, query, filepath,
58
- local dirpath, error, pending, writeStream, options, req)
58
+ local error, pending, writeStream, options, req)
59
59
  {
60
60
  filepath = nodePath.resolve("/tmp", filepath)
61
61
  if query
@@ -567,8 +567,8 @@ function opseInit(local manifest) {
567
567
 
568
568
  Naan.module.build(module.id, "openSearch", function(modobj, compobj) {
569
569
  compobj.manifest = manifest
570
- require("frameworks/common").LiveImport()
571
- letimport(require("frameworks/node/https_request.nlg"))
570
+ require("naanlib:frameworks/common").LiveImport()
571
+ letimport(require("naanlib:frameworks/node/https_request.nlg"))
572
572
  modobj.exports.OpenSearchClient = OpenSearchClient
573
573
  })
574
574
  } ();
@@ -33,7 +33,7 @@ closure lancoRest(local url, client) {
33
33
  request.addEventListener("error", function reqFailed(event, local errtext) {
34
34
  if request.status == 0
35
35
  errtext = "connectivity"
36
- ellse
36
+ else
37
37
  errtext = "request failed"
38
38
  error = Error(errtext, {
39
39
  status: request.status
@@ -92,7 +92,7 @@ closure lancoWs(local url, laws) {
92
92
  // onmessage
93
93
  // A message was received from the worker via WebSockets.
94
94
 
95
- laws.ws.onmessage = function onmessage(e, local message, msg) {
95
+ laws.ws.onmessage = function onmessage(e) {
96
96
  laws.doMessage(e.data)
97
97
  }
98
98
 
@@ -114,7 +114,7 @@ closure lancoWs(local url, laws) {
114
114
  // doMessage
115
115
  //
116
116
  // Process the specified undecoded message.
117
- laws.doMessage = function doMessage(text, local message, msg) {
117
+ laws.doMessage = function doMessage(text, local message) {
118
118
  try {
119
119
  message = new(JSONparse(text))
120
120
  } catch {
@@ -252,6 +252,8 @@ closure psmaConnector(psm, local connClassID, connector, watch) {
252
252
 
253
253
  connector.connect = function connect(resID, service, args,
254
254
  local error, s3b, db, rootpath, table) {
255
+ if !resID || args && !tuple(args)
256
+ return (list(Error("invalid arguments")))
255
257
  `(error, s3b) = connector.access(resID)
256
258
  if !error
257
259
  `(error, db) = S3DB(s3b, args.1) // get S3 bucket as a database
@@ -262,12 +264,12 @@ closure psmaConnector(psm, local connClassID, connector, watch) {
262
264
  else if service == "NideFS" {
263
265
  rootpath = args.0 // connect to a NideFS filesystem
264
266
  if !rootpath
265
- return (Error("mandatory rootpath missing"))
267
+ return (list(Error("mandatory rootpath missing")))
266
268
  `(error, table) = db.table(rootpath, args.1) // args.1 is table options; see dawsTable
267
269
  if error
268
270
  list(error)
269
271
  else
270
- require("frameworks/storage/psm_dbtables.nlg").FSview(table, rootpath)
272
+ require("naanlib:frameworks/storage/psm_dbtables.nlg").FSview(table, rootpath)
271
273
  } else
272
274
  list(Error("unsupported service", service))
273
275
  }
@@ -23,7 +23,7 @@ function sawsInit(local manifest) {
23
23
 
24
24
  Naan.module.build(module.id, "serviceAws", function(modobj, compobj) {
25
25
  compobj.manifest = manifest
26
- require("frameworks/common").LiveImport()
26
+ require("naanlib:frameworks/common").LiveImport()
27
27
  require("./aws_utils.nlg")
28
28
  function sawsPostload() {
29
29
  if js.g
@@ -26,7 +26,7 @@
26
26
  */
27
27
 
28
28
  closure GcApi(options, local gcapi, cacert, renew, access_token, expires_at) {
29
- global(https, JSpath)
29
+ global(js, https, JSpath)
30
30
  gcapi = new(object, this)
31
31
  if options.preview {
32
32
  gcapi.urlbase = "https://gigachat-preview.devices.sberbank.ru/api/v1/"
@@ -74,7 +74,7 @@ closure GcApi(options, local gcapi, cacert, renew, access_token, expires_at) {
74
74
  //
75
75
  // Make an HTTPS request on the API, renewing the access token first if needed.
76
76
  //
77
- closure request(url, put, local error, data, status) {
77
+ closure request(url, put, sseHook, local error, data, status) {
78
78
  if !(milliseconds() < expires_at - 60000) {
79
79
  `(error, data) = auth(renew)
80
80
  if error
@@ -87,7 +87,7 @@ closure GcApi(options, local gcapi, cacert, renew, access_token, expires_at) {
87
87
  `(Accept, "application/json"),
88
88
  list(`Authorization, "Bearer ".concat(access_token))
89
89
  ]
90
- sseHook: options.sseHook || undefined
90
+ sseHook: sseHook || options.sseHook || undefined
91
91
  })
92
92
  if error
93
93
  list(error)
@@ -172,13 +172,13 @@ closure GcApi(options, local gcapi, cacert, renew, access_token, expires_at) {
172
172
  // object: <string>
173
173
  // }
174
174
  //
175
- gcapi.chatCompletion = closure chatCompletion(query) {
175
+ gcapi.chatCompletion = closure chatCompletion(query, sseHook) {
176
176
  if options.preview {
177
177
  query = new(query)
178
178
  if !query.model.endsWith("-preview")
179
179
  query.model = query.model.concat("-preview")
180
180
  }
181
- request(gcapi.urlbase.concat("chat/completions"), query)
181
+ request(gcapi.urlbase.concat("chat/completions"), query, sseHook)
182
182
  }
183
183
 
184
184
  // uploadFile
@@ -244,7 +244,7 @@ closure GitHubRepo(access, repodict, local gepo, url) {
244
244
  // Return a list of commits in the repo, optionally matching the specified file path.
245
245
  //
246
246
  //
247
- gepo.commits = closure commits(filepath, local pardict, query, error, response, result) {
247
+ gepo.commits = closure commits(filepath, local pardict, query) {
248
248
  pardict = {
249
249
  per_page: 100
250
250
  }
@@ -420,7 +420,8 @@ closure GitHubRepo(access, repodict, local gepo, url) {
420
420
  // ref: <commit> - branch, tag or commit hash, default to main branch
421
421
  // }
422
422
  //
423
- gepo.readfile = closure readfile(filepath, options, local ref, params, query, method, error, response, result) {
423
+ gepo.readfile = closure readfile(filepath, options
424
+ local ref, params, query) {
424
425
  if !string(filepath)
425
426
  return (list(Error("filepath must be a string:", filepath)))
426
427
  ref = options.ref
@@ -489,7 +490,7 @@ closure GitHubRepo(access, repodict, local gepo, url) {
489
490
 
490
491
  gtopParseLinkHeaderRegExp;
491
492
 
492
- function gtopParseLinkHeader(header, local segment, output) {
493
+ function gtopParseLinkHeader(header, local output) {
493
494
  if !jsInstanceOf(gtopParseLinkHeaderRegExp, RegExp.prototype)
494
495
  gtopParseLinkHeaderRegExp = RegExp('<([^?]+\\?[=\\w&?]+page=(\\d+))>;\\s*rel="(\\w+)"', 'g')
495
496
  output = { }
@@ -183,7 +183,7 @@ closure phubConnector(psm, local connClassID, connector, watch) {
183
183
  //
184
184
  // Connect to an ghub bucket filesystem, returning a view.
185
185
 
186
- connector.connect = function connect(resID, service, args, local error, ghub, gitremote, table) {
186
+ connector.connect = function connect(resID, service, args, local error, ghub, gitremote) {
187
187
  `(error, ghub) = connector.access(resID)
188
188
  if !error
189
189
  `(error, gitremote) = GitHubOps(ghub) // get GitHub as a git remote
@@ -60,6 +60,6 @@ function ghubInit(local manifest) {
60
60
  Naan.module.build(module.id, "serviceGitHub", function(modobj, compobj) {
61
61
  compobj.manifest = manifest
62
62
  })
63
- require("frameworks/common", { in: naanlib }).LiveImport()
63
+ require("naanlib:frameworks/common").LiveImport()
64
64
  require("./psm_github.nlg").GitHubConnector(App.psm)
65
65
  } ();
@@ -464,7 +464,8 @@ closure GitLabRepo(access, repodict, local gepo, url) {
464
464
  // head: <boolean> - true to obtain metadata only without contents
465
465
  // }
466
466
  //
467
- gepo.readfile = closure readfile(filepath, options, local ref, params, query, method, error, response, result) {
467
+ gepo.readfile = closure readfile(filepath, options
468
+ local ref, params, query, method) {
468
469
  if !string(filepath)
469
470
  return (list(Error("filepath must be a string:", filepath)))
470
471
  ref = options.ref
@@ -20,7 +20,7 @@
20
20
 
21
21
  closure plabConnector(psm, local connClassID, connector, watch) {
22
22
  connClassID = "GLAB"
23
- require("plugins/serviceGitLab/gitops.nlg")
23
+ require("./gitops.nlg")
24
24
  connector = new(object, this)
25
25
  connector.psm = psm
26
26
  connector.vault = psm.vault(connClassID)
@@ -183,7 +183,7 @@ closure plabConnector(psm, local connClassID, connector, watch) {
183
183
  //
184
184
  // Connect to an GitLab filesystem.
185
185
 
186
- connector.connect = function connect(resID, service, args, local error, glab, gitremote, table) {
186
+ connector.connect = function connect(resID, service, args, local error, glab, gitremote) {
187
187
  `(error, glab) = connector.access(resID)
188
188
  if !error
189
189
  `(error, gitremote) = GitLabOps(glab) // get GitLab as a git remote
@@ -60,6 +60,6 @@ function glabInit(local manifest) {
60
60
  Naan.module.build(module.id, "serviceGitLab", function(modobj, compobj) {
61
61
  compobj.manifest = manifest
62
62
  })
63
- require("frameworks/common", { in: naanlib }).LiveImport()
63
+ require("naanlib:frameworks/common").LiveImport()
64
64
  require("./psm_gitlab.nlg").GitLabConnector(App.psm)
65
65
  } ();
@@ -22,7 +22,7 @@ vmState = false;
22
22
  */
23
23
 
24
24
  closure VmControl(local ycvm) {
25
- global(https, nodeHttp, vmState)
25
+ global(js, https, nodeHttp, vmState)
26
26
  if vmState.ycvm
27
27
  return (vmState.ycvm) // singleton
28
28
  ycvm = new(object, this)
package/test/harness.nlg CHANGED
@@ -83,15 +83,15 @@ closure Parsenv(name, local penv, gohome, lingo, naansym) {
83
83
  `(errors, expr) = lingo.parse(source)
84
84
  for error in errors
85
85
  output.errors.push(penv.lib.ParseErrorString(error))
86
- if expr {
87
- output.exprs.push(expr)
88
- expr = function() { evalactive(expr) }() // return here if return executed outside procedure
89
- output.results.push(expr)
90
- if source.tokenlast().atom == `;>
91
- output.pretty.push(tostring(expr, { quote: true }))
92
- else if source.tokenlast().atom != `;;
93
- output.pretty.push(lingo.print(expr))
94
- }
86
+ output.exprs.push(expr)
87
+ expr = function() { evalactive(expr) }() // return here if return executed outside procedure
88
+ output.results.push(expr)
89
+ if expr === Naan.local.mu
90
+ { }
91
+ else if source.tokenlast().atom == `;>
92
+ output.pretty.push(tostring(expr, { quote: true }))
93
+ else if source.tokenlast().atom != `;;
94
+ output.pretty.push(lingo.print(expr))
95
95
  } finally {
96
96
  sudo(putproc(`exception, savex)) }
97
97
  }
@@ -23,7 +23,7 @@ RegisterTestCategory("core", [
23
23
  // booleans and/or undefined
24
24
  //
25
25
 
26
- [ "false;", "" ],
26
+ [ "false;", "false" ],
27
27
  [ "true;", "true" ],
28
28
  [ "not true;", "false" ],
29
29
  [ "not false;", "true" ],
@@ -61,9 +61,16 @@ RegisterTestCategory("core", [
61
61
  [ "lambda(unintern(\"lambda\"));", "true" ],
62
62
 
63
63
  [ "car(`;);", ";" ],
64
+
65
+ [ "null;", "null" ],
66
+ [ "null();", "(null)" ],
67
+ [ "mu;", "mu" ],
68
+ [ "mu();", "" ],
69
+ [ "mu.tostring;", '"mu"' ],
70
+ [ "mu().tostring;", '"mu"' ],
64
71
 
65
72
  //
66
- // basic lists and dotted pairs
73
+ // basic tuples and dotted pairs
67
74
  //
68
75
 
69
76
  [ "`();>", "false" ],
@@ -82,6 +89,21 @@ RegisterTestCategory("core", [
82
89
  [ "`((a . b) . (c d));>", "((a . b) c d)" ],
83
90
  [ "`((a b) . (c . d));>", "((a b) c . d)" ],
84
91
 
92
+ //
93
+ // tuple manipulation
94
+ //
95
+
96
+ [ "append(`(a,b,c), d, `(e,f));>", "(a b c d e f)" ],
97
+ [ "append(`(3), `((4)));>", "(3 (4))" ],
98
+ [ "append(`(3), 5);>", "(3 5)" ],
99
+ [ "append(3, 4, 5);>", "(3 4 5)" ],
100
+
101
+ [ "subatq(list(a,3), list(a, 4));", "list(4, 3)" ],
102
+ [ "subatq(list(a,3), [list(a, 4)]);", "list(4, 3)" ],
103
+ [ "subatq(function joe(x) { 4*x }, [list(joe, bob), list(x,y)]);>",
104
+ "(Lib::defproc function bob (y) (* 4 y))" ],
105
+ [ "subat(list(a, { b: c }, [d, e]), [list(a,1), list(b,2), list(c,3), list(e,d), list(d,e)]);",
106
+ "(1, { 2: 3 }, [e, d])" ],
85
107
 
86
108
  //
87
109
  // assignment
@@ -38,7 +38,7 @@ RegisterTestCategory("context", [
38
38
  [ "function setNS(ns) { ns=reverse(ns),sudo(nsactive(reverse(ns, defNS))) };", "setNS" ],
39
39
  [ "x;", "x" ],
40
40
  [ "y;", "y" ],
41
- [ "length(symlist(nsactive(true).0));", "171"],
41
+ [ "length(symlist(nsactive(true).0));", "173"],
42
42
  [ "testvar;", "testvar" ],
43
43
  [ "function setTestvar(v) { testvar=v };", "setTestvar" ],
44
44
  [ "naanvar;", "naanvar" ],
@@ -263,7 +263,7 @@ RegisterTestCategory("context", [
263
263
  //
264
264
 
265
265
  [ "closure Xx(y, local xx) { xx = new(object, this) };", "Xx" ],
266
- [ "x = Xx(33);", "Object{0}" ],
266
+ [ "x = Xx(33);", "{object Xx}" ],
267
267
  [ "car(x@\\.closure.proc.2.0)", "33" ],
268
268
  [ "new(object, 3)@*", "false" ]
269
269
  ]);
@@ -646,18 +646,18 @@ RegisterTestCategory("Lingo", [
646
646
  [ "closure myob(initv, local myob) {\n"
647
647
  " myob = new(object)\n"
648
648
  " myob.value = initv\n"
649
- " myob.\\.tostring = function \\.tostring(obj) {\n"
649
+ " myob@\\.tostring = function \\.tostring(obj) {\n"
650
650
  " \"myob-\".concat(myob.value) }\n"
651
651
  " myob };",
652
652
  "myob" ],
653
- [ "myob(3);>", "Object{2}" ],
653
+ [ "myob(3);>", "Object{1}" ],
654
654
  [ "myob(3);", "myob-3" ],
655
655
 
656
656
  //
657
657
  // dialects
658
658
  //
659
659
 
660
- [ "dt = Dialect.derive('test');", "Object{22}" ],
660
+ [ "dt = Dialect.derive('test');", "{object dialect}" ],
661
661
  [ "dt.redefine(`^, function(x,y,local z) {z=1,while y-- > 0 z *= x,z});", "^" ],
662
662
  [ "$$ = dt.parse(new(textstream, '2^9;'));", "(false, 2^9)" ],
663
663
  [ "eval($$);", "(false, 512)" ],
@@ -1,33 +0,0 @@
1
- -----BEGIN CERTIFICATE-----
2
- MIIFwjCCA6qgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwcDELMAkGA1UEBhMCUlUx
3
- PzA9BgNVBAoMNlRoZSBNaW5pc3RyeSBvZiBEaWdpdGFsIERldmVsb3BtZW50IGFu
4
- ZCBDb21tdW5pY2F0aW9uczEgMB4GA1UEAwwXUnVzc2lhbiBUcnVzdGVkIFJvb3Qg
5
- Q0EwHhcNMjIwMzAxMjEwNDE1WhcNMzIwMjI3MjEwNDE1WjBwMQswCQYDVQQGEwJS
6
- VTE/MD0GA1UECgw2VGhlIE1pbmlzdHJ5IG9mIERpZ2l0YWwgRGV2ZWxvcG1lbnQg
7
- YW5kIENvbW11bmljYXRpb25zMSAwHgYDVQQDDBdSdXNzaWFuIFRydXN0ZWQgUm9v
8
- dCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMfFOZ8pUAL3+r2n
9
- qqE0Zp52selXsKGFYoG0GM5bwz1bSFtCt+AZQMhkWQheI3poZAToYJu69pHLKS6Q
10
- XBiwBC1cvzYmUYKMYZC7jE5YhEU2bSL0mX7NaMxMDmH2/NwuOVRj8OImVa5s1F4U
11
- zn4Kv3PFlDBjjSjXKVY9kmjUBsXQrIHeaqmUIsPIlNWUnimXS0I0abExqkbdrXbX
12
- YwCOXhOO2pDUx3ckmJlCMUGacUTnylyQW2VsJIyIGA8V0xzdaeUXg0VZ6ZmNUr5Y
13
- Ber/EAOLPb8NYpsAhJe2mXjMB/J9HNsoFMBFJ0lLOT/+dQvjbdRZoOT8eqJpWnVD
14
- U+QL/qEZnz57N88OWM3rabJkRNdU/Z7x5SFIM9FrqtN8xewsiBWBI0K6XFuOBOTD
15
- 4V08o4TzJ8+Ccq5XlCUW2L48pZNCYuBDfBh7FxkB7qDgGDiaftEkZZfApRg2E+M9
16
- G8wkNKTPLDc4wH0FDTijhgxR3Y4PiS1HL2Zhw7bD3CbslmEGgfnnZojNkJtcLeBH
17
- BLa52/dSwNU4WWLubaYSiAmA9IUMX1/RpfpxOxd4Ykmhz97oFbUaDJFipIggx5sX
18
- ePAlkTdWnv+RWBxlJwMQ25oEHmRguNYf4Zr/Rxr9cS93Y+mdXIZaBEE0KS2iLRqa
19
- OiWBki9IMQU4phqPOBAaG7A+eP8PAgMBAAGjZjBkMB0GA1UdDgQWBBTh0YHlzlpf
20
- BKrS6badZrHF+qwshzAfBgNVHSMEGDAWgBTh0YHlzlpfBKrS6badZrHF+qwshzAS
21
- BgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsF
22
- AAOCAgEAALIY1wkilt/urfEVM5vKzr6utOeDWCUczmWX/RX4ljpRdgF+5fAIS4vH
23
- tmXkqpSCOVeWUrJV9QvZn6L227ZwuE15cWi8DCDal3Ue90WgAJJZMfTshN4OI8cq
24
- W9E4EG9wglbEtMnObHlms8F3CHmrw3k6KmUkWGoa+/ENmcVl68u/cMRl1JbW2bM+
25
- /3A+SAg2c6iPDlehczKx2oa95QW0SkPPWGuNA/CE8CpyANIhu9XFrj3RQ3EqeRcS
26
- AQQod1RNuHpfETLU/A2gMmvn/w/sx7TB3W5BPs6rprOA37tutPq9u6FTZOcG1Oqj
27
- C/B7yTqgI7rbyvox7DEXoX7rIiEqyNNUguTk/u3SZ4VXE2kmxdmSh3TQvybfbnXV
28
- 4JbCZVaqiZraqc7oZMnRoWrXRG3ztbnbes/9qhRGI7PqXqeKJBztxRTEVj8ONs1d
29
- WN5szTwaPIvhkhO3CO5ErU2rVdUr89wKpNXbBODFKRtgxUT70YpmJ46VVaqdAhOZ
30
- D9EUUn4YaeLaS8AjSF/h7UkjOibNc4qVDiPP+rkehFWM66PVnP1Msh93tc+taIfC
31
- EYVMxjh8zNbFuoc7fzvvrFILLe7ifvEIUqSVIC/AzplM/Jxw7buXFeGP1qVCBEHq
32
- 391d/9RAfaZ12zkwFsl+IKwE/OZxW8AHa9i1p4GO0YSNuczzEm4=
33
- -----END CERTIFICATE-----