mysql2 3.0.0-rc.1 → 3.0.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.
package/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
  [![Windows Build][appveyor-image]][appveyor-url]
9
9
  [![License][license-image]][license-url]
10
10
 
11
- [简体中文 Simplified Chinese](./documentation_zh-cn/)
11
+ English | [简体中文](./documentation_zh-cn/)
12
12
 
13
13
  > MySQL client for Node.js with focus on performance. Supports prepared statements, non-utf8 encodings, binary log protocol, compression, ssl [much more](https://github.com/sidorares/node-mysql2/tree/master/documentation)
14
14
 
package/index.d.ts CHANGED
@@ -164,13 +164,6 @@ export interface Pool extends mysql.Connection {
164
164
  config: mysql.PoolOptions;
165
165
  }
166
166
 
167
- type authPlugins = (pluginMetadata: {
168
- connection: Connection;
169
- command: string;
170
- }) => (
171
- pluginData: Buffer
172
- ) => Promise<string> | string | Buffer | Promise<Buffer> | null;
173
-
174
167
  export interface ConnectionOptions extends mysql.ConnectionOptions {
175
168
  charsetNumber?: number;
176
169
  compress?: boolean;
@@ -191,7 +184,7 @@ export interface ConnectionOptions extends mysql.ConnectionOptions {
191
184
  queueLimit?: number;
192
185
  waitForConnections?: boolean;
193
186
  authPlugins?: {
194
- [key: string]: authPlugins;
187
+ [key: string]: mysql.AuthPlugin;
195
188
  };
196
189
  }
197
190
 
package/index.js CHANGED
@@ -43,6 +43,7 @@ exports.createServer = function(handler) {
43
43
  };
44
44
 
45
45
  exports.PoolConnection = require('./lib/pool_connection');
46
+ exports.authPlugins = require('./lib/auth_plugins');
46
47
  exports.escape = SqlString.escape;
47
48
  exports.escapeId = SqlString.escapeId;
48
49
  exports.format = SqlString.format;
@@ -0,0 +1,8 @@
1
+ 'use strict';
2
+
3
+ module.exports = {
4
+ caching_sha2_password: require('./caching_sha2_password'),
5
+ mysql_clear_password: require('./mysql_clear_password'),
6
+ mysql_native_password: require('./mysql_native_password'),
7
+ sha256_password: require('./sha256_password'),
8
+ };
@@ -1,12 +1,17 @@
1
- 'use strict'
1
+ 'use strict';
2
2
 
3
- module.exports = pluginOptions => ({ connection, command }) => {
4
- const password =
5
- command.password || pluginOptions.password || connection.config.password;
3
+ function bufferFromStr(str) {
4
+ return Buffer.from(`${str}\0`);
5
+ }
6
6
 
7
- const cleartextPassword = function(password) {
8
- return Buffer.from(`${password}\0`)
7
+ const create_mysql_clear_password_plugin = pluginOptions =>
8
+ function mysql_clear_password_plugin({ connection, command }) {
9
+ const password =
10
+ command.password || pluginOptions.password || connection.config.password;
11
+
12
+ return function (/* pluginData */) {
13
+ return bufferFromStr(password);
14
+ };
9
15
  };
10
16
 
11
- return cleartextPassword(password)
12
- };
17
+ module.exports = create_mysql_clear_password_plugin;
package/lib/connection.js CHANGED
@@ -55,6 +55,10 @@ class Connection extends EventEmitter {
55
55
  // Enable keep-alive on the socket. It's disabled by default, but the
56
56
  // user can enable it and supply an initial delay.
57
57
  this.stream.setKeepAlive(true, this.config.keepAliveInitialDelay);
58
+
59
+ // Enable TCP_NODELAY flag. This is needed so that the network packets
60
+ // are sent immediately to the server
61
+ this.stream.setNoDelay(true);
58
62
  }
59
63
  // if stream is a function, treat it as "stream agent / factory"
60
64
  } else if (typeof opts.config.stream === 'function') {
@@ -70,7 +74,7 @@ class Connection extends EventEmitter {
70
74
  this._paused_packets = new Queue();
71
75
  this._statements = new LRU({
72
76
  max: this.config.maxPreparedStatements,
73
- dispose: function(key, statement) {
77
+ dispose: function(statement) {
74
78
  statement.close();
75
79
  }
76
80
  });
@@ -96,6 +100,10 @@ class Connection extends EventEmitter {
96
100
  }
97
101
  this.packetParser.execute(data);
98
102
  });
103
+ this.stream.on('end', () => {
104
+ // emit the end event so that the pooled connection can close the connection
105
+ this.emit('end');
106
+ });
99
107
  this.stream.on('close', () => {
100
108
  // we need to set this flag everywhere where we want connection to close
101
109
  if (this._closing) {
@@ -342,6 +350,9 @@ class Connection extends EventEmitter {
342
350
  minVersion: this.config.ssl.minVersion
343
351
  });
344
352
  const rejectUnauthorized = this.config.ssl.rejectUnauthorized;
353
+ const verifyIdentity = this.config.ssl.verifyIdentity;
354
+ const host = this.config.host;
355
+
345
356
  let secureEstablished = false;
346
357
  const secureSocket = new Tls.TLSSocket(this.stream, {
347
358
  rejectUnauthorized: rejectUnauthorized,
@@ -349,6 +360,9 @@ class Connection extends EventEmitter {
349
360
  secureContext: secureContext,
350
361
  isServer: false
351
362
  });
363
+ if (typeof host === 'string') {
364
+ secureSocket.setServername(host);
365
+ }
352
366
  // error handler for secure socket
353
367
  secureSocket.on('_tlsError', err => {
354
368
  if (secureEstablished) {
@@ -359,7 +373,15 @@ class Connection extends EventEmitter {
359
373
  });
360
374
  secureSocket.on('secure', () => {
361
375
  secureEstablished = true;
362
- onSecure(rejectUnauthorized ? secureSocket.ssl.verifyError() : null);
376
+ let callbackValue = null;
377
+ if (rejectUnauthorized) {
378
+ callbackValue = secureSocket.ssl.verifyError()
379
+ if (!callbackValue && typeof host === 'string' && verifyIdentity) {
380
+ const cert = secureSocket.ssl.getPeerCertificate(true);
381
+ callbackValue = Tls.checkServerIdentity(host, cert)
382
+ }
383
+ }
384
+ onSecure(callbackValue);
363
385
  });
364
386
  secureSocket.on('data', data => {
365
387
  this.packetParser.execute(data);
@@ -401,6 +423,10 @@ class Connection extends EventEmitter {
401
423
  err.code = code || 'PROTOCOL_ERROR';
402
424
  this.emit('error', err);
403
425
  }
426
+
427
+ get fatalError() {
428
+ return this._fatalError;
429
+ }
404
430
 
405
431
  handlePacket(packet) {
406
432
  if (this._paused) {
@@ -587,7 +613,7 @@ class Connection extends EventEmitter {
587
613
  const key = Connection.statementKey(options);
588
614
  const stmt = this._statements.get(key);
589
615
  if (stmt) {
590
- this._statements.del(key);
616
+ this._statements.delete(key);
591
617
  stmt.close();
592
618
  }
593
619
  return stmt;
@@ -814,14 +840,23 @@ class Connection extends EventEmitter {
814
840
  );
815
841
  }
816
842
 
817
- writeTextResult(rows, columns) {
843
+ writeBinaryRow(column) {
844
+ this.writePacket(
845
+ Packets.BinaryRow.toPacket(column, this.serverConfig.encoding)
846
+ );
847
+ }
848
+
849
+ writeTextResult(rows, columns, binary=false) {
818
850
  this.writeColumns(columns);
819
851
  rows.forEach(row => {
820
852
  const arrayRow = new Array(columns.length);
821
853
  columns.forEach(column => {
822
854
  arrayRow.push(row[column.name]);
823
855
  });
824
- this.writeTextRow(arrayRow);
856
+ if(binary) {
857
+ this.writeBinaryRow(arrayRow);
858
+ }
859
+ else this.writeTextRow(arrayRow);
825
860
  });
826
861
  this.writeEof();
827
862
  }
@@ -2,6 +2,7 @@
2
2
 
3
3
  // Certificate for Amazon RDS (Updated for 2019)
4
4
  // https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html
5
+ // https://docs.amazonaws.cn/en_us/AmazonRDS/latest/AuroraUserGuide/UsingWithRDS.SSL.html
5
6
  // https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless.html#aurora-serverless.tls
6
7
  exports['Amazon RDS'] = {
7
8
  ca: [
@@ -1104,6 +1105,279 @@ exports['Amazon RDS'] = {
1104
1105
  'o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU\n' +
1105
1106
  '5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy\n' +
1106
1107
  'rqXRfboQnoZsG4q5WTP468SQvvG5\n' +
1108
+ '-----END CERTIFICATE-----\n',
1109
+ '-----BEGIN CERTIFICATE-----\n' +
1110
+ 'MIIEDDCCAvSgAwIBAgIJAMy5uCBvP5roMA0GCSqGSIb3DQEBCwUAMIGSMQswCQYD\n' +
1111
+ 'VQQGEwJVUzEQMA4GA1UEBwwHU2VhdHRsZTETMBEGA1UECAwKV2FzaGluZ3RvbjEi\n' +
1112
+ 'MCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNlcywgSW5jLjETMBEGA1UECwwKQW1h\n' +
1113
+ 'em9uIFJEUzEjMCEGA1UEAwwaQW1hem9uIFJEUyBDTiBSb290IDIwMTkgQ0EwHhcN\n' +
1114
+ 'MTkwOTA5MTY1NzIyWhcNMjQwOTA5MTY1NzIyWjCBkjELMAkGA1UEBhMCVVMxEDAO\n' +
1115
+ 'BgNVBAcMB1NlYXR0bGUxEzARBgNVBAgMCldhc2hpbmd0b24xIjAgBgNVBAoMGUFt\n' +
1116
+ 'YXpvbiBXZWIgU2VydmljZXMsIEluYy4xEzARBgNVBAsMCkFtYXpvbiBSRFMxIzAh\n' +
1117
+ 'BgNVBAMMGkFtYXpvbiBSRFMgQ04gUm9vdCAyMDE5IENBMIIBIjANBgkqhkiG9w0B\n' +
1118
+ 'AQEFAAOCAQ8AMIIBCgKCAQEAzxl9K4p06ZTZ9eZmEXyTHe9Ut8OIZR86t6A8b8g0\n' +
1119
+ 'nhqMe+y4ee+UfqxumVAVyXwNXOiGQVbuJhScLaJ39/Ol4YzIGjdoD8MUvsf4BuET\n' +
1120
+ 'udQh2sJL8OnlXuqSICKpecN5ud4UQvoMVZ9FGJ+e8TvXczW14rGO62sPfYM/WrMD\n' +
1121
+ 'R7P4fhQfmWFzkc24/hZGRL1nkvwMdtiwuI2TYobhlwZQOdsNcZ9Ek+PcSI4oqgXN\n' +
1122
+ 'SqpYy85JzrRZiR5iFGw1CnJtGlC0oatXFzw/B8XOd9wvLTlJhyLo7zw9j3zedKbv\n' +
1123
+ '33fTdjfvpGvcfw9CYggwrbsVmUeUhVDfMntTc9z9MRccmwIDAQABo2MwYTAOBgNV\n' +
1124
+ 'HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU/Z0g+hUMGQou\n' +
1125
+ 'hsbyFgSxc5jsbaowHwYDVR0jBBgwFoAU/Z0g+hUMGQouhsbyFgSxc5jsbaowDQYJ\n' +
1126
+ 'KoZIhvcNAQELBQADggEBAAlGPCq1D/PGkWoZZpAK3V94EOByklp2HkUPEZ0PPv3Z\n' +
1127
+ '/euD2wUPkXnf27FC1XJE0pJX96B97ZXIEHl4S4obBRSlybzuvmfH4gyu+b+7Tebv\n' +
1128
+ 'VmfsAodyfYCm90heAYADWkc/XKDj+oe3NkbR+LokrM+5aOB71f5mMLnFgYHQW/dI\n' +
1129
+ 'IRDziUSpP0LMr+YNKvM7qytrobPS2TOWtweWpXesNBBeiLTHZpTEu8DYcE+4e2tj\n' +
1130
+ 'O0spF3HuoF0Oc7ioVy2exE+HV1oJOquHGSanZSdMHCAEDMfKUmlT7/zcwC877UT/\n' +
1131
+ 'sysqYU/fl6vX48QDfalZuBYj+d1dUxIb1sx6q4Iw4+s=\n' +
1132
+ '-----END CERTIFICATE-----\n',
1133
+ '-----BEGIN CERTIFICATE-----\n' +
1134
+ 'MIIEDDCCAvSgAwIBAgIDAIMzMA0GCSqGSIb3DQEBCwUAMIGSMQswCQYDVQQGEwJV\n' +
1135
+ 'UzEQMA4GA1UEBwwHU2VhdHRsZTETMBEGA1UECAwKV2FzaGluZ3RvbjEiMCAGA1UE\n' +
1136
+ 'CgwZQW1hem9uIFdlYiBTZXJ2aWNlcywgSW5jLjETMBEGA1UECwwKQW1hem9uIFJE\n' +
1137
+ 'UzEjMCEGA1UEAwwaQW1hem9uIFJEUyBDTiBSb290IDIwMTkgQ0EwHhcNMTkwOTA5\n' +
1138
+ 'MjAzMjM3WhcNMjQwOTA5MTY1NzIyWjCBlTELMAkGA1UEBhMCVVMxEzARBgNVBAgM\n' +
1139
+ 'Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUFtYXpvbiBX\n' +
1140
+ 'ZWIgU2VydmljZXMsIEluYy4xEzARBgNVBAsMCkFtYXpvbiBSRFMxJjAkBgNVBAMM\n' +
1141
+ 'HUFtYXpvbiBSRFMgY24tbm9ydGgtMSAyMDE5IENBMIIBIjANBgkqhkiG9w0BAQEF\n' +
1142
+ 'AAOCAQ8AMIIBCgKCAQEA1QX8vbiba8pa4b2CLVBNhqFFYwsuekptFPv/RTixRZ6K\n' +
1143
+ 'a1fZ/vp/d7xhfhwU9DKXyQ3ONhwOVKnFuvQuWXQiPc2cRkxM+TF7yF6hoPrIOOzr\n' +
1144
+ 's6ANmR2k/n9X0aOO7sqx4q7A73ueIDJst3IjfaFgt1jaqfC7tcSSROB/+vZZTNGP\n' +
1145
+ 'KgFvd02ut2mCtLgohzavVDicUc0V8H1sV5Ah4n0VafW7Fqru9ehiPO79JXJKIS7W\n' +
1146
+ 'gcgOOiK6YDqxaQRN+LTNYdZ+DZ1+Gx8NBN80fVOO2hpRFpb662k/hQH8onYkvXaY\n' +
1147
+ 'kr9ouDTjfr5t8E8CEvkO/Y/B3/lt7mVjEGqImCwJawIDAQABo2YwZDAOBgNVHQ8B\n' +
1148
+ 'Af8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUXJaoUok7ROtv\n' +
1149
+ '5/2xeuaRqelnejIwHwYDVR0jBBgwFoAU/Z0g+hUMGQouhsbyFgSxc5jsbaowDQYJ\n' +
1150
+ 'KoZIhvcNAQELBQADggEBAIiPRsCpaiMsWUq7liRV6NDgljzjVOMzUsDnfusGUQtO\n' +
1151
+ 'fa3tCI+sx5j92jFzlS0GwseB/3FjVQDRll/kFTqbVwpHw2kaLeAbVvquxZAoD/91\n' +
1152
+ '6gBGSF3qmLestFpf02kNHlv9skqnMrBLYkQ4kckgt4Y8E8pNLSeNtJykbp7XCf7H\n' +
1153
+ 'A+izbITBxNHxLUqMStEtk8RhIWUmiAbp5ENHwYCL5h9g4VV7X4TsW/1Q4KgEstWa\n' +
1154
+ '1t65VWr3p7NnKpMX5CL/v5FGCYq0TDdr3qmHKbXbofmUKltZ7VxSAh5LFrfLuGzt\n' +
1155
+ 'MtXQkd0NDvVqMNHAjEkj7/MtlYyridWrKsiUc3ALBR4=\n' +
1156
+ '-----END CERTIFICATE-----\n',
1157
+ '-----BEGIN CERTIFICATE-----\n' +
1158
+ 'MIIGADCCA+igAwIBAgIQfFbtOHNGJtTnXjvwddAHjTANBgkqhkiG9w0BAQwFADCB\n' +
1159
+ 'mDELMAkGA1UEBhMCVVMxIjAgBgNVBAoMGUFtYXpvbiBXZWIgU2VydmljZXMsIElu\n' +
1160
+ 'Yy4xEzARBgNVBAsMCkFtYXpvbiBSRFMxCzAJBgNVBAgMAldBMTEwLwYDVQQDDChB\n' +
1161
+ 'bWF6b24gUkRTIGNuLW5vcnRoLTEgUm9vdCBDQSBSU0E0MDk2IEcxMRAwDgYDVQQH\n' +
1162
+ 'DAdTZWF0dGxlMCAXDTIxMDUyNTIzMTg1MloYDzIxMjEwNTI2MDAxODUyWjCBmDEL\n' +
1163
+ 'MAkGA1UEBhMCVVMxIjAgBgNVBAoMGUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4x\n' +
1164
+ 'EzARBgNVBAsMCkFtYXpvbiBSRFMxCzAJBgNVBAgMAldBMTEwLwYDVQQDDChBbWF6\n' +
1165
+ 'b24gUkRTIGNuLW5vcnRoLTEgUm9vdCBDQSBSU0E0MDk2IEcxMRAwDgYDVQQHDAdT\n' +
1166
+ 'ZWF0dGxlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0OO5+lCMwInN\n' +
1167
+ 'tMJ19bv+uyEE74uE5vHQHtla5sI1Hp+A8DhTURgJvIHRxv3Tgtk6ja4v/VcbLcVr\n' +
1168
+ 'R4OkZBY9b5RKHMGDK1ljwo/MxMFuK/TGkHcrjhiZcgYyNm2oxK33/YafLqq18a8p\n' +
1169
+ 'HREEZwz7wSi6DY8Mf9heH8a2T3ZDlUovj5JUVIDu7kSGYHw16eUi9twX7MtO0b43\n' +
1170
+ 'ociygADBSoZeyMKZHisYdyf4D/LLDYgh7ja+Ncu4k3ErMmxGN5cZN+USyquxmnr8\n' +
1171
+ 'uXkl2t9VH0BhB0kej/vO9DhLdpKJRVaML1A9Wg3pd0U37xOJhTU6wCm23zdga3kR\n' +
1172
+ 'bf9azdS68zDK9tYiDrGc7kRkj7SOUWLY7fagyKv3rESWXrGkV8lzsK7xseomAKvL\n' +
1173
+ 'fHEfL0QUD63kEk4W8VH8XY7NwXZD6Je5hiQtLu8/uxed96FWwZ1DJrzojW4mKFQF\n' +
1174
+ 'eECHU5b5jza4gjZ/pOeeqRmx3iojjYf2ZVm0+0SRFd+BWWPpqyeVUvC9gVZ+VMPr\n' +
1175
+ 'SUqgIrHZ2GMNJXIHt9TR3oq4XnXVcvsPuKQCWg8HIgczfDc//zaYhLdcVQbsTVEo\n' +
1176
+ 'I8nLqs6FygTnhyPSbJG9n9fF+RpTowXVb1UNovCTR/UBvR9l8JobnaqKUFMI1W2d\n' +
1177
+ 'Dy98l55+LFT1VYm+rbvxJlVJm9kw6usCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB\n' +
1178
+ '/zAdBgNVHQ4EFgQUfVNPfvq3BkZRL2qrVKEvMbPBSHAwDgYDVR0PAQH/BAQDAgGG\n' +
1179
+ 'MA0GCSqGSIb3DQEBDAUAA4ICAQBZ9hDaGcZFSxEyV4Yk7ynJrpKznaLWaq8T72lb\n' +
1180
+ 'sXcgnGGnTYQtUhdR2atA6KVtc2D8UCxDiP4kE8xC+voGKgRRt3WvIX/KRiYH4Rr/\n' +
1181
+ '8DS/wux6MYYEaXjoCil1xNTOyhMCmtEPIFo8LDStbaur/PmE5VGVr45XcqNdNt5A\n' +
1182
+ 'S8esMGK5aI7D2zQEfGN940+U2sUCVYnvuaR1nbcMkgMzzdL2yCCZ1mlyk2KvSsF7\n' +
1183
+ 'b0P772MnZ3x4mP3IcUh0/6XSSIxWMAB6r6s1nCZd2JGGIyVSc2YLsB2jib2gYyfT\n' +
1184
+ 'zq2SL040aatsOAecrfYDG6UbeL0OUXivhOzycvS92FhEDU0BNB44wEO0Qg/zAc2C\n' +
1185
+ 'JlkPCMKIZc9g70RhHQ9VV9kc/SCjVRu1PauryzTmXEfr+ItrbZVW33JQg7ZOmgfj\n' +
1186
+ 'jgpKF9q7sG2VJBDCRdp2nfeA1Bblc36yC0LodZ7voSzcJI7nnv1aO3U1CvQl0Mha\n' +
1187
+ 'fMjZqd0kPIX6d0G4C5SImvMCF59annWwt4V1sbWrgEvqdICe0kVsofUtEW35kX3C\n' +
1188
+ 'W344OxVkmhhFuniTFWYCyuQNlhIIdA0I5trZPtRaWsV2cTkNIzfe2vHGXuMnwd6V\n' +
1189
+ 'CwxPaPdyvKB7n6x6tF5RUOXq0EZQf9XOmdOiCTua1WT+vobRX18RtJLaOa/n5AKo\n' +
1190
+ 'LlYzqw==\n' +
1191
+ '-----END CERTIFICATE-----\n',
1192
+ '-----BEGIN CERTIFICATE-----\n' +
1193
+ 'MIIEATCCAumgAwIBAgIRAN9d6r2p5Wg5Gwl1bK3+WfkwDQYJKoZIhvcNAQELBQAw\n' +
1194
+ 'gZgxCzAJBgNVBAYTAlVTMSIwIAYDVQQKDBlBbWF6b24gV2ViIFNlcnZpY2VzLCBJ\n' +
1195
+ 'bmMuMRMwEQYDVQQLDApBbWF6b24gUkRTMQswCQYDVQQIDAJXQTExMC8GA1UEAwwo\n' +
1196
+ 'QW1hem9uIFJEUyBjbi1ub3J0aC0xIFJvb3QgQ0EgUlNBMjA0OCBHMTEQMA4GA1UE\n' +
1197
+ 'BwwHU2VhdHRsZTAgFw0yMTA1MjUyMzE1MDdaGA8yMDYxMDUyNjAwMTUwN1owgZgx\n' +
1198
+ 'CzAJBgNVBAYTAlVTMSIwIAYDVQQKDBlBbWF6b24gV2ViIFNlcnZpY2VzLCBJbmMu\n' +
1199
+ 'MRMwEQYDVQQLDApBbWF6b24gUkRTMQswCQYDVQQIDAJXQTExMC8GA1UEAwwoQW1h\n' +
1200
+ 'em9uIFJEUyBjbi1ub3J0aC0xIFJvb3QgQ0EgUlNBMjA0OCBHMTEQMA4GA1UEBwwH\n' +
1201
+ 'U2VhdHRsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKvw4zHfM3cU\n' +
1202
+ 'yFI9KFITDF4feeon2P49qXx8YX8KUEYzNbkNQhPSt1J91kvy0ddHLrxxNd+LoQFi\n' +
1203
+ 'A5vu7a51VmX1MtKYs7SzEIUdrON3FKK/2cci2yCnwzoc3kam3jXvPUu56op+aH35\n' +
1204
+ '0JHEco0i+NUjh7n5UV/yWc1+8kPLBQr+VMV3ndp85ik209esvCRWgQ+iWuADqHbf\n' +
1205
+ 'vjrFm/zjFIiwuX5qapkDtSRVwM6FwIfjSEF6udhZjsermfD2AoTesptZEiNIPRzV\n' +
1206
+ 'et6s/U5gMjvAhc+MQgjjdCLBlhbXWR1CPtXOMp6o8Pjn2Et3eiM6G1T0jUO28BGP\n' +
1207
+ '3/iq3JOXFj8CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUEoBo\n' +
1208
+ 'nXIxui+T8RXYqgzikVat82EwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUA\n' +
1209
+ 'A4IBAQAk4XdDesWKYgE35KMqg2+tCY/gbBrKVMdvZzy2kAv9QH8bwCcojeMw4wGh\n' +
1210
+ 'u0mjfX0vawoot2bNY6Yu0+mVxBtkelhay7enN+mA5g5DfkyKkLb6Jg/9N7m95w4N\n' +
1211
+ 'ICQwM3Yb9OsuquxBPPE7JkrZv10AzVz2Xqu/OHDyDpfnkcCfNusHyIAycjxq/ZEF\n' +
1212
+ '7LOSBv3S20sJU72EKfrNGSfMDv9qvnusum/vTYKuSNCTR0vARxbB7LLVZZ/Pg2w8\n' +
1213
+ '22RQK9zr+u5WkfTGMqF4NnbuJGphU21QHUIZYY8QAnte0hbK+AbTUyeKGHxqRDun\n' +
1214
+ 'BQn6/GvgP2tPDKj/Huauo/CVSd+M\n' +
1215
+ '-----END CERTIFICATE-----\n',
1216
+ '-----BEGIN CERTIFICATE-----\n' +
1217
+ 'MIICrzCCAjWgAwIBAgIQTEq2iHmd2QzeVBzmBUbAUTAKBggqhkjOPQQDAzCBlzEL\n' +
1218
+ 'MAkGA1UEBhMCVVMxIjAgBgNVBAoMGUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4x\n' +
1219
+ 'EzARBgNVBAsMCkFtYXpvbiBSRFMxCzAJBgNVBAgMAldBMTAwLgYDVQQDDCdBbWF6\n' +
1220
+ 'b24gUkRTIGNuLW5vcnRoLTEgUm9vdCBDQSBFQ0MzODQgRzExEDAOBgNVBAcMB1Nl\n' +
1221
+ 'YXR0bGUwIBcNMjEwNTI1MjMyMjQ4WhgPMjEyMTA1MjYwMDIyNDhaMIGXMQswCQYD\n' +
1222
+ 'VQQGEwJVUzEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNlcywgSW5jLjETMBEG\n' +
1223
+ 'A1UECwwKQW1hem9uIFJEUzELMAkGA1UECAwCV0ExMDAuBgNVBAMMJ0FtYXpvbiBS\n' +
1224
+ 'RFMgY24tbm9ydGgtMSBSb290IENBIEVDQzM4NCBHMTEQMA4GA1UEBwwHU2VhdHRs\n' +
1225
+ 'ZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABBV1FSsxoXGFDBIMj6b+EfJvLINkTtVv\n' +
1226
+ 'UucbGUqZMidNfuHoUWTlhwZuX5kMv9hlbQbDxrnHCePo1heHkdqovIi2D77lhvhn\n' +
1227
+ '7UgMupcFx9Tjki+5QhKLW3n7W8dmreJLw6NCMEAwDwYDVR0TAQH/BAUwAwEB/zAd\n' +
1228
+ 'BgNVHQ4EFgQUFwPUFTDrjPqdIMjuYGif1wkAtr8wDgYDVR0PAQH/BAQDAgGGMAoG\n' +
1229
+ 'CCqGSM49BAMDA2gAMGUCMQCrAtoyWILR++OEhFmuJhSR8cgEW/rGyf+lMDwq9dcA\n' +
1230
+ 'eJPK7l9S8iT30JOo++hWwYcCMFl9MWvoQU3iUDH+j33I26+whkvZ6LLw2dajww1X\n' +
1231
+ '0MPXbT3P9P0Jk/Vv+gand92fAw==\n' +
1232
+ '-----END CERTIFICATE-----\n',
1233
+ '-----BEGIN CERTIFICATE-----\n' +
1234
+ 'MIIEDDCCAvSgAwIBAgIJAMy5uCBvP5roMA0GCSqGSIb3DQEBCwUAMIGSMQswCQYD\n' +
1235
+ 'VQQGEwJVUzEQMA4GA1UEBwwHU2VhdHRsZTETMBEGA1UECAwKV2FzaGluZ3RvbjEi\n' +
1236
+ 'MCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNlcywgSW5jLjETMBEGA1UECwwKQW1h\n' +
1237
+ 'em9uIFJEUzEjMCEGA1UEAwwaQW1hem9uIFJEUyBDTiBSb290IDIwMTkgQ0EwHhcN\n' +
1238
+ 'MTkwOTA5MTY1NzIyWhcNMjQwOTA5MTY1NzIyWjCBkjELMAkGA1UEBhMCVVMxEDAO\n' +
1239
+ 'BgNVBAcMB1NlYXR0bGUxEzARBgNVBAgMCldhc2hpbmd0b24xIjAgBgNVBAoMGUFt\n' +
1240
+ 'YXpvbiBXZWIgU2VydmljZXMsIEluYy4xEzARBgNVBAsMCkFtYXpvbiBSRFMxIzAh\n' +
1241
+ 'BgNVBAMMGkFtYXpvbiBSRFMgQ04gUm9vdCAyMDE5IENBMIIBIjANBgkqhkiG9w0B\n' +
1242
+ 'AQEFAAOCAQ8AMIIBCgKCAQEAzxl9K4p06ZTZ9eZmEXyTHe9Ut8OIZR86t6A8b8g0\n' +
1243
+ 'nhqMe+y4ee+UfqxumVAVyXwNXOiGQVbuJhScLaJ39/Ol4YzIGjdoD8MUvsf4BuET\n' +
1244
+ 'udQh2sJL8OnlXuqSICKpecN5ud4UQvoMVZ9FGJ+e8TvXczW14rGO62sPfYM/WrMD\n' +
1245
+ 'R7P4fhQfmWFzkc24/hZGRL1nkvwMdtiwuI2TYobhlwZQOdsNcZ9Ek+PcSI4oqgXN\n' +
1246
+ 'SqpYy85JzrRZiR5iFGw1CnJtGlC0oatXFzw/B8XOd9wvLTlJhyLo7zw9j3zedKbv\n' +
1247
+ '33fTdjfvpGvcfw9CYggwrbsVmUeUhVDfMntTc9z9MRccmwIDAQABo2MwYTAOBgNV\n' +
1248
+ 'HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU/Z0g+hUMGQou\n' +
1249
+ 'hsbyFgSxc5jsbaowHwYDVR0jBBgwFoAU/Z0g+hUMGQouhsbyFgSxc5jsbaowDQYJ\n' +
1250
+ 'KoZIhvcNAQELBQADggEBAAlGPCq1D/PGkWoZZpAK3V94EOByklp2HkUPEZ0PPv3Z\n' +
1251
+ '/euD2wUPkXnf27FC1XJE0pJX96B97ZXIEHl4S4obBRSlybzuvmfH4gyu+b+7Tebv\n' +
1252
+ 'VmfsAodyfYCm90heAYADWkc/XKDj+oe3NkbR+LokrM+5aOB71f5mMLnFgYHQW/dI\n' +
1253
+ 'IRDziUSpP0LMr+YNKvM7qytrobPS2TOWtweWpXesNBBeiLTHZpTEu8DYcE+4e2tj\n' +
1254
+ 'O0spF3HuoF0Oc7ioVy2exE+HV1oJOquHGSanZSdMHCAEDMfKUmlT7/zcwC877UT/\n' +
1255
+ 'sysqYU/fl6vX48QDfalZuBYj+d1dUxIb1sx6q4Iw4+s=\n' +
1256
+ '-----END CERTIFICATE-----\n',
1257
+ '-----BEGIN CERTIFICATE-----\n' +
1258
+ 'MIIEEDCCAvigAwIBAgIDAJJhMA0GCSqGSIb3DQEBCwUAMIGSMQswCQYDVQQGEwJV\n' +
1259
+ 'UzEQMA4GA1UEBwwHU2VhdHRsZTETMBEGA1UECAwKV2FzaGluZ3RvbjEiMCAGA1UE\n' +
1260
+ 'CgwZQW1hem9uIFdlYiBTZXJ2aWNlcywgSW5jLjETMBEGA1UECwwKQW1hem9uIFJE\n' +
1261
+ 'UzEjMCEGA1UEAwwaQW1hem9uIFJEUyBDTiBSb290IDIwMTkgQ0EwHhcNMTkwOTE3\n' +
1262
+ 'MTY0OTE3WhcNMjQwOTA5MTY1NzIyWjCBmTELMAkGA1UEBhMCVVMxEzARBgNVBAgM\n' +
1263
+ 'Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoMGUFtYXpvbiBX\n' +
1264
+ 'ZWIgU2VydmljZXMsIEluYy4xEzARBgNVBAsMCkFtYXpvbiBSRFMxKjAoBgNVBAMM\n' +
1265
+ 'IUFtYXpvbiBSRFMgY24tbm9ydGh3ZXN0LTEgMjAxOSBDQTCCASIwDQYJKoZIhvcN\n' +
1266
+ 'AQEBBQADggEPADCCAQoCggEBAMr4bvXQVykL0RHtBALyP7FycubzLJM178wMw5vK\n' +
1267
+ 'QS/1IVlQlbdZ8bNYmSMqa2IlGoWdjvLonES0jD0T8LCOYJy0uPN0DfiH6I9v9th8\n' +
1268
+ 'TvG/hAD9pe01xLOUAOTzuikbzcxEf9XX6mG/xAh5rREHsLbQE9R7D4RkqdeJbQBc\n' +
1269
+ 'KVcWWrejW9XaleCr+iEuwSqzXYDXNyfJoYic8aNYA8bADG5YPWTPblxA8MCik+zD\n' +
1270
+ 'q9r5wMNafUKmdOAFP6qeYo0zA5o9ESM2xJdYqa2gF7lAYsMagtWZWfEW27ZUrYmf\n' +
1271
+ 'tlMXu5xF2zZ1z2n7GKBXa8kA+e/dzalUA5ONHZUDIpU51k8CAwEAAaNmMGQwDgYD\n' +
1272
+ 'VR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFCV3kNIC\n' +
1273
+ '8e01zUu6tXl0/ig8Va5OMB8GA1UdIwQYMBaAFP2dIPoVDBkKLobG8hYEsXOY7G2q\n' +
1274
+ 'MA0GCSqGSIb3DQEBCwUAA4IBAQDHKrXWXsv6KKb06XhuC6RrMsLW+fmQXbrU9x4V\n' +
1275
+ 'b46VEaHN8lvKx6QWmRKSdnCa7nYZkPUbGdcQtgThfEjkc+UEfJxx/Q2Hb1OslPcj\n' +
1276
+ 'Egx5M7NFCGoBbaSKOGnVexEKRfxA2zkPCMi7bDe2m8cgThyBHfsTJSVGJkXsf6VJ\n' +
1277
+ 'JKWJULYiHMjF31Npg++eB4iN42bqhPfP5nKloGjOs/TNYdT2rAcI8xZRsd+G+0Aw\n' +
1278
+ 'qlQ0VdPmxIK7M0Sv2StGD0244OXbq6A3Ojx4t7/Kl41+FuyaGlnALDvdiYF96Zu1\n' +
1279
+ 'VpA/pPn4AC3+/wrXOefZDFJ3dC1uKlIoh63Vv378oI2VQvw3\n' +
1280
+ '-----END CERTIFICATE-----\n',
1281
+ '-----BEGIN CERTIFICATE-----\n' +
1282
+ 'MIIECTCCAvGgAwIBAgIRAOf+QbXXDGRJ7MW8j6FZ5ncwDQYJKoZIhvcNAQELBQAw\n' +
1283
+ 'gZwxCzAJBgNVBAYTAlVTMSIwIAYDVQQKDBlBbWF6b24gV2ViIFNlcnZpY2VzLCBJ\n' +
1284
+ 'bmMuMRMwEQYDVQQLDApBbWF6b24gUkRTMQswCQYDVQQIDAJXQTE1MDMGA1UEAwws\n' +
1285
+ 'QW1hem9uIFJEUyBjbi1ub3J0aHdlc3QtMSBSb290IENBIFJTQTIwNDggRzExEDAO\n' +
1286
+ 'BgNVBAcMB1NlYXR0bGUwIBcNMjEwNTI1MjI1NjEyWhgPMjA2MTA1MjUyMzU2MTJa\n' +
1287
+ 'MIGcMQswCQYDVQQGEwJVUzEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNlcywg\n' +
1288
+ 'SW5jLjETMBEGA1UECwwKQW1hem9uIFJEUzELMAkGA1UECAwCV0ExNTAzBgNVBAMM\n' +
1289
+ 'LEFtYXpvbiBSRFMgY24tbm9ydGh3ZXN0LTEgUm9vdCBDQSBSU0EyMDQ4IEcxMRAw\n' +
1290
+ 'DgYDVQQHDAdTZWF0dGxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\n' +
1291
+ '0XBh/AY4j5RP9XUbYGMaCaBuG4FAbHU/Qfz/hHBNfy/QMi2hF4LQECGqp+j/8fML\n' +
1292
+ '45c6b0NyCLvZuIfB4F1s+dctJpqauDqzYacw3/fMmxNyzgkrYa8VhoRdPWH6ZX2e\n' +
1293
+ '0VNfTOJo64ShJaePdizBAoBnfX+xvDyZ6BLGtdUsvsfdDSCTt2fgTAk8DBTmHode\n' +
1294
+ 'hCC3EfVcAjk99+Fe0RWPnDBXQkA8VrbgSxXPN8Gfag1wIzS44BcxhxHDiwQoL4Ao\n' +
1295
+ 'FfOwvgRJANeUGcqnL5IpF8xxU3lk7nMcXuQu17597+UGwTiFLAT0bnVK/TgakefX\n' +
1296
+ 'M3ZH9gUi0Di3dJNIKtq/3wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud\n' +
1297
+ 'DgQWBBTX4eJfUNknv33QnNNfkDsrYrO1uzAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZI\n' +
1298
+ 'hvcNAQELBQADggEBAKIlgCuSJYIgvHK2zoT9PugiyBE5vvo5HyrTOJIhPknB2aY7\n' +
1299
+ 'x2Gwbv7YlXzncpQM+aPA88PlIvwPmGj0Nb8ph6vZ55DOxWrBE8LuXMR/+71vMYaF\n' +
1300
+ 'M9iTud2OyRLa2EIpS7nq3jWKjiDFkfrkUg8JmLCWHv0qEANX8XJ5NVhrRSAJzvDA\n' +
1301
+ 'MArXq2k5oJZoRJxyGlz6dSoU/rxsQF/oTihpcH/cEbL6ZD8sZ5xLJpCHTJcnBAEZ\n' +
1302
+ 'L18sYc8F/91akqXn1re/7/K3NwT9usyh89e5pegx/U2ySI3KJuc464HmCV7YZ0iJ\n' +
1303
+ 'EQYsQRGFZr/Miu5V4hrpuggsrnmi/RagWYJGPfQ=\n' +
1304
+ '-----END CERTIFICATE-----\n',
1305
+ '-----BEGIN CERTIFICATE-----\n' +
1306
+ 'MIIGCTCCA/GgAwIBAgIRAJ3YjujPNbJWN/domX9EvW8wDQYJKoZIhvcNAQEMBQAw\n' +
1307
+ 'gZwxCzAJBgNVBAYTAlVTMSIwIAYDVQQKDBlBbWF6b24gV2ViIFNlcnZpY2VzLCBJ\n' +
1308
+ 'bmMuMRMwEQYDVQQLDApBbWF6b24gUkRTMQswCQYDVQQIDAJXQTE1MDMGA1UEAwws\n' +
1309
+ 'QW1hem9uIFJEUyBjbi1ub3J0aHdlc3QtMSBSb290IENBIFJTQTQwOTYgRzExEDAO\n' +
1310
+ 'BgNVBAcMB1NlYXR0bGUwIBcNMjEwNTI1MjMwMDE1WhgPMjEyMTA1MjYwMDAwMTVa\n' +
1311
+ 'MIGcMQswCQYDVQQGEwJVUzEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNlcywg\n' +
1312
+ 'SW5jLjETMBEGA1UECwwKQW1hem9uIFJEUzELMAkGA1UECAwCV0ExNTAzBgNVBAMM\n' +
1313
+ 'LEFtYXpvbiBSRFMgY24tbm9ydGh3ZXN0LTEgUm9vdCBDQSBSU0E0MDk2IEcxMRAw\n' +
1314
+ 'DgYDVQQHDAdTZWF0dGxlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA\n' +
1315
+ 'y8Wy3CndOV9n8V3yZ3aOTm6sKlxmtS7GYlAiguNjyqS2ERP6x3l6JlkuKyAtYut/\n' +
1316
+ 'UOJL6TBWQNLUsNpFJnLkomaqWRYNjSSogSLt2F6BIr/fM8pOmXvBHg9OB/I24DUE\n' +
1317
+ '6bKuVbe+qrGN6ypTAsrfZJ94ED0wmMb8RMOlXOBgB3GxbuQjUFN0XLXurJygj9k7\n' +
1318
+ 'SM3RQggoaO94T1qoi4LD/NS/4/Z3eUksLZgkC19fSSVnuUfu845x+MXlVhLeHcLo\n' +
1319
+ '9IIONonUJvkKPS90TQtB2spSqFd+MkiX3izPDii1kHfFHsl2CzwcdbxvcAZ742np\n' +
1320
+ 'MjDFpE4Zl6Nf28jGm6ODg6F/yZIiqWpvDemfnHfgkv1SFJnMpIAnLEIRnD5iZPRY\n' +
1321
+ 'vP9tJVxGo/kB7ogYLKboOtQyzQC5G6KIbkblJ+MjVcf5iQIUn5Ir7s91/7s6uVRT\n' +
1322
+ 'OY76S3SppFQltNwh1yW5s7Ppc9XR5cp0F37NfEm90g+r2JMH6da+Zd0zd+oG4JUJ\n' +
1323
+ 'GQWAIhvoOo2jjfX33GqxJI5QrhyVFQpIGs6WU3Z7uZou6/orDaEzAkedMC4w53aZ\n' +
1324
+ 'KmJevk2btsWRcGTYyJxf5GZ9HnUcDApcZ9QZ/9f7iIrGPTO4W6BJ9wzzc5PoenlD\n' +
1325
+ 'oubhx9fofSIepk822gD/93fakRUJlYXKNvxJC8qXRn8CAwEAAaNCMEAwDwYDVR0T\n' +
1326
+ 'AQH/BAUwAwEB/zAdBgNVHQ4EFgQUbApE7vMSJDpJph7Lrq6rAMCwQF4wDgYDVR0P\n' +
1327
+ 'AQH/BAQDAgGGMA0GCSqGSIb3DQEBDAUAA4ICAQBSTbw8jIpZyAwQiJv5D6B9g4fX\n' +
1328
+ '9PsTFTmb2eszZZZO/i0T8hbqAA3DmjjM5QqUdbjXiq4aLec04aH/ltc/12b6lypX\n' +
1329
+ 'sfhtUJd5rgVyEyi9VpZwL+3LrV8CC9rel1v1euOvQ+6ojsoU9PKVLSw5G1Owzy8x\n' +
1330
+ 'pQwJU9ZTIMgz0TdlFUugaccLH54uy/c7FclO8HpOwHbwMtuMrsEt3p9vea7UoSn3\n' +
1331
+ '54usb0p8ex2brMrOxKmLXXQOGoDFF8U5JCivdQaYuG7LO9NocaeyLNkc22MrxvhV\n' +
1332
+ '1x3I1CE5Y1vMEqf0B8mMl2tAZ6l68r8qv1SoIrvm3ioZpdDBNkyyYVfRLpvmQBw4\n' +
1333
+ 'F0NQIW5wAumqbyHLRKMf/wmeuBwYjWrAeJdwDTsNVDPnhXpTOobKH432+i7v5U8n\n' +
1334
+ '1dcrLdYwzRMXxY2+Wrmgte2JdsvfNkcDou9ZnjqTt8u5L7eFd5kWOLnZAWtsIef5\n' +
1335
+ '2QzfKFjpbg9q/zt9RcNULAUaMB0twG1G6eO9stPElE2B0k3wM0FCTXfrh8v0FWEx\n' +
1336
+ 'Zbnef3OwiiHHQ6EBHYvbZm0qwuYdBz8KtwurYwEUpgldls5hcj9eI3pDCjTzJncP\n' +
1337
+ 'GpVjJTtIE0CGOcAgIt5G6idQ1oQudW8DMb/M0QXibI5fjqEXYoYQEnjko9AqLdzI\n' +
1338
+ 'pn++DGngGu3NLeSVfA==\n' +
1339
+ '-----END CERTIFICATE-----\n',
1340
+ '-----BEGIN CERTIFICATE-----\n' +
1341
+ 'MIICtjCCAj2gAwIBAgIQHBx4LmhvEVmG1P6tMGhI8DAKBggqhkjOPQQDAzCBmzEL\n' +
1342
+ 'MAkGA1UEBhMCVVMxIjAgBgNVBAoMGUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4x\n' +
1343
+ 'EzARBgNVBAsMCkFtYXpvbiBSRFMxCzAJBgNVBAgMAldBMTQwMgYDVQQDDCtBbWF6\n' +
1344
+ 'b24gUkRTIGNuLW5vcnRod2VzdC0xIFJvb3QgQ0EgRUNDMzg0IEcxMRAwDgYDVQQH\n' +
1345
+ 'DAdTZWF0dGxlMCAXDTIxMDUyNTIzMDM1NVoYDzIxMjEwNTI2MDAwMzU1WjCBmzEL\n' +
1346
+ 'MAkGA1UEBhMCVVMxIjAgBgNVBAoMGUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4x\n' +
1347
+ 'EzARBgNVBAsMCkFtYXpvbiBSRFMxCzAJBgNVBAgMAldBMTQwMgYDVQQDDCtBbWF6\n' +
1348
+ 'b24gUkRTIGNuLW5vcnRod2VzdC0xIFJvb3QgQ0EgRUNDMzg0IEcxMRAwDgYDVQQH\n' +
1349
+ 'DAdTZWF0dGxlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEJxUculiPchcuEWMgFK+T\n' +
1350
+ 'jmYSVKrpF0NbDteKKJ45BbTzhwwCSKyEY3vVCqwMQ+wYiJZ87OyxLU1cqq/WCg3s\n' +
1351
+ '7aD8Ro9DezvR+Fu+/AV61BLCgeSLr9S1ZCC6cpn5l0a4o0IwQDAPBgNVHRMBAf8E\n' +
1352
+ 'BTADAQH/MB0GA1UdDgQWBBSK4CT2IBuyX0nXmkC15OHfxtqh8zAOBgNVHQ8BAf8E\n' +
1353
+ 'BAMCAYYwCgYIKoZIzj0EAwMDZwAwZAIwQB38Wg42v48d5O1i53hg2qF/H0QW/8eO\n' +
1354
+ '/xVtA8PK2ztDgQm+O0vKb34nj6X4Kcn8AjBSJmft8t7LMN/UwnhptyYINerpDMzZ\n' +
1355
+ 'g0OtBwn1QMWWlkFNf8ajLURXKGg9e2mfkpw=\n' +
1356
+ '-----END CERTIFICATE-----\n',
1357
+ '-----BEGIN CERTIFICATE-----\n' +
1358
+ 'MIIEIjCCAwqgAwIBAgIQI2AINKjtLFqXO+5mqmHJOzANBgkqhkiG9w0BAQsFADCB\n' +
1359
+ 'nDELMAkGA1UEBhMCVVMxIjAgBgNVBAoMGUFtYXpvbiBXZWIgU2VydmljZXMsIElu\n' +
1360
+ 'Yy4xEzARBgNVBAsMCkFtYXpvbiBSRFMxCzAJBgNVBAgMAldBMTUwMwYDVQQDDCxB\n' +
1361
+ 'bWF6b24gUkRTIGNuLW5vcnRod2VzdC0xIFJvb3QgQ0EgUlNBMjA0OCBHMTEQMA4G\n' +
1362
+ 'A1UEBwwHU2VhdHRsZTAeFw0yMTEwMjAyMjE5NTBaFw0yNjEwMjAyMzE5NTBaMIGU\n' +
1363
+ 'MQswCQYDVQQGEwJVUzEQMA4GA1UEBwwHU2VhdHRsZTETMBEGA1UECAwKV2FzaGlu\n' +
1364
+ 'Z3RvbjEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNlcywgSW5jLjETMBEGA1UE\n' +
1365
+ 'CwwKQW1hem9uIFJEUzElMCMGA1UEAwwcQW1hem9uIFJEUyBjbi1ub3J0aHdlc3Qt\n' +
1366
+ 'MSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMk+1qHD+w3Wns8f\n' +
1367
+ 'WNs6ZKtd6r8eJSilT8SKdhuvZ77C2a5CRaWhihwTznGW1vCaR9+O4OIJZCJj3iV+\n' +
1368
+ '75arKXK5XJTPNJo8aW5pW9ljh/KsudkT7gzURQ3n3xFiv9vQwPRSE9gPn20Cad8U\n' +
1369
+ '64KPl20DvA1XD3CoaACafRz5BlZwGJAi6xI9DqdiQRGEcNlwBzMSv9E0MqkW9pDN\n' +
1370
+ '+goGEkVyfLA83hUM58zXr7AwUEw7RH64rNZcoWYT89AVKvUQnyyEs6hZvIIVwTQm\n' +
1371
+ 'v/YpYEH3BsN/SshaQpmh1scN/aHurVfBn0ZaY2EaTBv/u1YsalhbnZglFX6581X7\n' +
1372
+ '9UkEocECAwEAAaNmMGQwEgYDVR0TAQH/BAgwBgEB/wIBADAfBgNVHSMEGDAWgBTX\n' +
1373
+ '4eJfUNknv33QnNNfkDsrYrO1uzAdBgNVHQ4EFgQUfGOsnDYUtkLIlP6gKPd/lkbh\n' +
1374
+ 'sn4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4IBAQCxYKgzCB6gcrYi\n' +
1375
+ '1op0n615lk/hLD5LEmpNYYgqtOOAPf7mGF1VLu+GtDmyAqRnQjr80hFO2Tvdv614\n' +
1376
+ 'u0D5joapjD+aAQIb+OeVVmXYPm3UfUotnUkHGalkofEWkS/7h/dUzKARBdpsKBP9\n' +
1377
+ 'ezSf8GBVRd0EDP8PLK5iplX4B+aQxmIBgYNIXSlgjaNX8SfjzKsRiLPmumWrb7gi\n' +
1378
+ 'lbqkdRuafQ3hj6K+I2JbgEEz2ggNBgUiwJRr+2B511RWHu3wEW86aEbl0+f5crJA\n' +
1379
+ 'XNn0nVq3tl8XMkorbAD+/8dbxMxV5wtMHY7nWsG8TlJ+8Vb9FwC5vIWSYun8u3Rh\n' +
1380
+ 'tOoQ3GAy\n' +
1107
1381
  '-----END CERTIFICATE-----\n'
1108
1382
  ]
1109
1383
  };
@@ -10,8 +10,55 @@ class BinaryRow {
10
10
  this.columns = columns || [];
11
11
  }
12
12
 
13
- toPacket() {
14
- throw new Error('Not implemented');
13
+ static toPacket(columns, encoding) {
14
+ // throw new Error('Not implemented');
15
+ const sequenceId = 0; // TODO remove, this is calculated now in connecton
16
+ let length = 0;
17
+ columns.forEach(val => {
18
+ if (val === null || typeof val === 'undefined') {
19
+ ++length;
20
+ return;
21
+ }
22
+ length += Packet.lengthCodedStringLength(val.toString(10), encoding);
23
+ });
24
+
25
+ length = length + 2;
26
+
27
+ const buffer = Buffer.allocUnsafe(length + 4);
28
+ const packet = new Packet(sequenceId, buffer, 0, length + 4);
29
+ packet.offset = 4;
30
+
31
+ packet.writeInt8(0);
32
+
33
+ let bitmap = 0;
34
+ let bitValue = 1;
35
+ columns.forEach(parameter => {
36
+ if (parameter.type === Types.NULL) {
37
+ bitmap += bitValue;
38
+ }
39
+ bitValue *= 2;
40
+ if (bitValue === 256) {
41
+ packet.writeInt8(bitmap);
42
+ bitmap = 0;
43
+ bitValue = 1;
44
+ }
45
+ });
46
+ if (bitValue !== 1) {
47
+ packet.writeInt8(bitmap);
48
+ }
49
+
50
+ columns.forEach(val => {
51
+ if (val === null) {
52
+ packet.writeNull();
53
+ return;
54
+ }
55
+ if (typeof val === 'undefined') {
56
+ packet.writeInt8(0);
57
+ return;
58
+ }
59
+ packet.writeLengthCodedString(val.toString(10), encoding);
60
+ });
61
+ return packet;
15
62
  }
16
63
 
17
64
  // TODO: complete list of types...
@@ -43,7 +43,7 @@ function setMaxCache(max) {
43
43
  }
44
44
 
45
45
  function clearCache() {
46
- parserCache.reset();
46
+ parserCache.clear();
47
47
  }
48
48
 
49
49
  module.exports = {
@@ -85,8 +85,15 @@ function compile(fields, options, config) {
85
85
  db: field.schema,
86
86
  table: field.table,
87
87
  name: field.name,
88
- string: function() {
89
- return _this.packet.readLengthCodedString(field.encoding);
88
+ string: function(encoding = field.encoding) {
89
+ if (field.columnType === Types.JSON && encoding === field.encoding) {
90
+ // Since for JSON columns mysql always returns charset 63 (BINARY),
91
+ // we have to handle it according to JSON specs and use "utf8",
92
+ // see https://github.com/sidorares/node-mysql2/issues/1661
93
+ console.warn(`typeCast: JSON column "${field.name}" is interpreted as BINARY by default, recommended to manually set utf8 encoding: \`field.string("utf8")\``);
94
+ }
95
+
96
+ return _this.packet.readLengthCodedString(encoding);
90
97
  },
91
98
  buffer: function() {
92
99
  return _this.packet.readLengthCodedBuffer();
@@ -172,7 +179,7 @@ function compile(fields, options, config) {
172
179
  } else {
173
180
  parserFn(`${lvalue} = ${readCode};`);
174
181
  }
175
- }
182
+ }
176
183
  }
177
184
 
178
185
  parserFn('return result;');
@@ -191,7 +198,7 @@ function compile(fields, options, config) {
191
198
  }
192
199
  if (typeof options.typeCast === 'function') {
193
200
  return parserFn.toFunction({wrap});
194
- }
201
+ }
195
202
  return parserFn.toFunction();
196
203
  }
197
204
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mysql2",
3
- "version": "3.0.0-rc.1",
3
+ "version": "3.0.1",
4
4
  "description": "fast mysql driver. Implements core protocol, prepared statements, ssl and compression in native JS",
5
5
  "main": "index.js",
6
6
  "directories": {
@@ -38,7 +38,7 @@
38
38
  ],
39
39
  "files": [
40
40
  "lib",
41
- "typings",
41
+ "typings/mysql",
42
42
  "index.js",
43
43
  "index.d.ts",
44
44
  "promise.js",
@@ -55,34 +55,34 @@
55
55
  "author": "Andrey Sidorov <sidorares@yandex.ru>",
56
56
  "license": "MIT",
57
57
  "dependencies": {
58
- "@types/chai": "^4.3.3",
59
- "chai": "^4.3.6",
60
- "denque": "^2.0.1",
58
+ "denque": "^2.1.0",
61
59
  "generate-function": "^2.3.1",
62
60
  "iconv-lite": "^0.6.3",
63
- "long": "^4.0.0",
64
- "lru-cache": "^6.0.0",
65
- "mocha": "^10.0.0",
66
- "named-placeholders": "^1.1.2",
61
+ "long": "^5.2.1",
62
+ "lru-cache": "^7.14.1",
63
+ "named-placeholders": "^1.1.3",
67
64
  "seq-queue": "^0.0.5",
68
65
  "sqlstring": "^2.3.2"
69
66
  },
70
67
  "devDependencies": {
71
- "@types/mocha": "^9.1.1",
68
+ "@types/chai": "^4.3.4",
69
+ "@types/mocha": "^10.0.0",
72
70
  "@types/node": "^18.7.1",
73
- "@typescript-eslint/eslint-plugin": "^4.33.0",
74
- "@typescript-eslint/parser": "^4.33.0",
71
+ "@typescript-eslint/eslint-plugin": "^5.42.1",
72
+ "@typescript-eslint/parser": "^5.42.1",
75
73
  "assert-diff": "^3.0.2",
76
74
  "benchmark": "^2.1.4",
77
75
  "c8": "^7.10.0",
76
+ "chai": "^4.3.7",
78
77
  "error-stack-parser": "^2.0.3",
79
- "eslint": "^7.32.0",
80
- "eslint-config-prettier": "^8.3.0",
78
+ "eslint": "^8.27.0",
79
+ "eslint-config-prettier": "^8.5.0",
81
80
  "eslint-plugin-async-await": "0.0.0",
82
- "eslint-plugin-markdown": "^2.2.1",
83
- "husky": "^7.0.2",
81
+ "eslint-plugin-markdown": "^3.0.0",
82
+ "husky": "^8.0.2",
84
83
  "is-async-supported": "^1.2.0",
85
- "lint-staged": "^11.2.0",
84
+ "lint-staged": "^13.0.3",
85
+ "mocha": "^10.0.0",
86
86
  "portfinder": "^1.0.28",
87
87
  "prettier": "^2.4.1",
88
88
  "progress": "^2.0.3",
package/promise.d.ts CHANGED
@@ -145,6 +145,7 @@ export function createConnection(connectionUri: string): Promise<Connection>;
145
145
  export function createConnection(
146
146
  config: ConnectionOptions
147
147
  ): Promise<Connection>;
148
+ export function createPool(connectionUri: string): Pool;
148
149
  export function createPool(config: PoolOptions): Pool;
149
150
 
150
151
  export interface PreparedStatementInfo {
@@ -1,3 +1,4 @@
1
+ import * as crypto from 'crypto';
1
2
 
2
3
  import BaseConnection = require('./lib/Connection');
3
4
  import {ConnectionOptions, SslOptions} from './lib/Connection';
@@ -43,4 +44,32 @@ export interface PoolConnection extends BasePoolConnection {}
43
44
  export interface Pool extends BasePool {}
44
45
  export interface PoolCluster extends BasePoolCluster {}
45
46
  export interface Query extends BaseQuery {}
46
- export interface Prepare extends BasePrepare {}
47
+ export interface Prepare extends BasePrepare {}
48
+
49
+ export type AuthPlugin = (pluginMetadata: {
50
+ connection: Connection;
51
+ command: string;
52
+ }) => (
53
+ pluginData: Buffer
54
+ ) => Promise<string> | string | Buffer | Promise<Buffer> | null;
55
+
56
+ type AuthPluginDefinition<T> = (pluginOptions?: T) => AuthPlugin
57
+
58
+ export const authPlugins: {
59
+ caching_sha2_password: AuthPluginDefinition<{
60
+ overrideIsSecure?: boolean,
61
+ serverPublicKey?: crypto.RsaPublicKey | crypto.RsaPrivateKey | crypto.KeyLike,
62
+ jonServerPublicKey?: (data: Buffer) => void;
63
+ }>,
64
+ mysql_clear_password: AuthPluginDefinition<{
65
+ password?: string;
66
+ }>,
67
+ mysql_native_password: AuthPluginDefinition<{
68
+ password?: string;
69
+ passwordSha1?: string;
70
+ }>,
71
+ sha256_password: AuthPluginDefinition<{
72
+ serverPublicKey?: crypto.RsaPublicKey | crypto.RsaPrivateKey | crypto.KeyLike,
73
+ joinServerPublicKey?: (data: Buffer) => void;
74
+ }>,
75
+ }
@@ -130,7 +130,7 @@ declare namespace Connection {
130
130
  * Enabling both supportBigNumbers and bigNumberStrings forces big numbers (BIGINT and DECIMAL columns) to be
131
131
  * always returned as JavaScript String objects (Default: false). Enabling supportBigNumbers but leaving
132
132
  * bigNumberStrings disabled will return big numbers as String objects only when they cannot be accurately
133
- * represented with [JavaScript Number objects] (http://ecma262-5.com/ELS5_HTML.htm#Section_8.5)
133
+ * represented with [JavaScript Number objects](https://262.ecma-international.org/5.1/#sec-8.5)
134
134
  * (which happens when they exceed the [-2^53, +2^53] range), otherwise they will be returned as Number objects.
135
135
  * This option is ignored if supportBigNumbers is disabled.
136
136
  */
@@ -227,6 +227,12 @@ declare namespace Connection {
227
227
  * Configure the minimum supported version of SSL, the default is TLSv1.2.
228
228
  */
229
229
  minVersion?: string;
230
+
231
+ /**
232
+ * You can verify the server name identity presented on the server certificate when connecting to a MySQL server.
233
+ * You should enable this but it is disabled by default right now for backwards compatibility.
234
+ */
235
+ verifyIdentity?: boolean;
230
236
  }
231
237
  }
232
238
 
@@ -272,7 +278,9 @@ declare class Connection extends EventEmitter {
272
278
 
273
279
  rollback(callback: (err: Query.QueryError | null) => void): void;
274
280
 
275
- execute(sql: string, values: Array<any>, cb: (err: any, rows: Array<any>, fields: Array<any>) => any): any;
281
+ execute(sql: string, callback?: (err: any, rows: Array<any>, fields: Array<any>) => any): any;
282
+
283
+ execute(sql: string, values: any | any[] | { [param: string]: any }, callback?: (err: any, rows: Array<any>, fields: Array<any>) => any): any;
276
284
 
277
285
  unprepare(sql: string): any;
278
286
 
@@ -1,45 +0,0 @@
1
- 'use strict';
2
-
3
- // get the client
4
- import * as mysql from 'mysql2';
5
- import ConnectionType = require('../mysql/lib/Connection');
6
- import { expect } from 'chai'
7
-
8
- // create the connection to database
9
- const connection: ConnectionType = mysql.createConnection({
10
- host: 'localhost',
11
- user: 'root',
12
- database: 'test'
13
- });
14
-
15
- describe('Connection', () => {
16
- it('execute', (done) => {
17
- connection.execute(
18
- 'select ?+1 as qqq, ? as rrr, ? as yyy',
19
- [1, null, 3],
20
- (err, rows, fields) => {
21
- expect(rows[0].qqq).to.equal(2);
22
- expect(err).to.be.null;
23
-
24
- connection.execute(
25
- 'select ?+1 as qqq, ? as rrr, ? as yyy',
26
- [3, null, 3],
27
- (err, rows, fields) => {
28
- expect(rows[0].qqq).to.equal(4);
29
- expect(err).to.be.null;
30
- connection.unprepare('select ?+1 as qqq, ? as rrr, ? as yyy');
31
- connection.execute(
32
- 'select ?+1 as qqq, ? as rrr, ? as yyy',
33
- [3, null, 3],
34
- (err, rows, fields) => {
35
- expect(rows[0].qqq).to.equal(4);
36
- expect(err).to.be.null;
37
- done();
38
- }
39
- );
40
- }
41
- );
42
- }
43
- );
44
- })
45
- })
@@ -1,38 +0,0 @@
1
- 'use strict';
2
-
3
- const portfinder = require('portfinder');
4
- import { createPool } from '../../index';
5
- import { Pool, PoolOptions, PromisePoolConnection } from '../../promise';
6
- import { expect } from 'chai'
7
-
8
- portfinder.getPort(async (err: any, port: number) => {
9
- const pool: Pool = createPool({
10
- user: 'test_user',
11
- password: 'test',
12
- database: 'test_database',
13
- port: port,
14
- } as PoolOptions).promise();
15
-
16
- describe('Pool.promise()', () => {
17
-
18
- it('exposes escape', () => {
19
- expect(pool.escape(123)).to.equal('123')
20
- })
21
-
22
- it('exposes escapeId', () => {
23
- expect(pool.escapeId('table name')).to.equal('`table name`')
24
- })
25
-
26
- it('exposes format', () => {
27
- const params = ['table name', 'thing'];
28
- expect(pool.format('SELECT a FROM ?? WHERE b = ?', params)).to.equal("SELECT a FROM `table name` WHERE b = 'thing'")
29
- })
30
-
31
- it('promise connection config', (done) => {
32
- pool.getConnection().then((connection: PromisePoolConnection) => {
33
- expect(connection.config.user).to.equal('test_user');
34
- done();
35
- }).catch(done);
36
- })
37
- });
38
- });
@@ -1,16 +0,0 @@
1
- import { expect } from 'chai'
2
- const Server = require('../../lib/server');
3
- import ServerType = require('../mysql/lib/Server');
4
-
5
- describe('Server', () => {
6
- it('createServer', (done) => {
7
- const server: ServerType = new Server()
8
-
9
- server.on('connection', (arg: any) => {
10
- expect(arg).to.equal(1)
11
- done()
12
- })
13
-
14
- server.emit('connection', 1)
15
- })
16
- })