Spaces:
Running
Running
; | |
const CommandCode = require('../constants/commands.js'); | |
const ClientConstants = require('../constants/client.js'); | |
const Packet = require('../packets/packet.js'); | |
const auth41 = require('../auth_41.js'); | |
const CharsetToEncoding = require('../constants/charset_encodings.js'); | |
// https://dev.mysql.com/doc/internals/en/com-change-user.html#packet-COM_CHANGE_USER | |
class ChangeUser { | |
constructor(opts) { | |
this.flags = opts.flags; | |
this.user = opts.user || ''; | |
this.database = opts.database || ''; | |
this.password = opts.password || ''; | |
this.passwordSha1 = opts.passwordSha1; | |
this.authPluginData1 = opts.authPluginData1; | |
this.authPluginData2 = opts.authPluginData2; | |
this.connectAttributes = opts.connectAttrinutes || {}; | |
let authToken; | |
if (this.passwordSha1) { | |
authToken = auth41.calculateTokenFromPasswordSha( | |
this.passwordSha1, | |
this.authPluginData1, | |
this.authPluginData2 | |
); | |
} else { | |
authToken = auth41.calculateToken( | |
this.password, | |
this.authPluginData1, | |
this.authPluginData2 | |
); | |
} | |
this.authToken = authToken; | |
this.charsetNumber = opts.charsetNumber; | |
} | |
// TODO | |
// ChangeUser.fromPacket = function(packet) | |
// }; | |
serializeToBuffer(buffer) { | |
const isSet = flag => this.flags & ClientConstants[flag]; | |
const packet = new Packet(0, buffer, 0, buffer.length); | |
packet.offset = 4; | |
const encoding = CharsetToEncoding[this.charsetNumber]; | |
packet.writeInt8(CommandCode.CHANGE_USER); | |
packet.writeNullTerminatedString(this.user, encoding); | |
if (isSet('SECURE_CONNECTION')) { | |
packet.writeInt8(this.authToken.length); | |
packet.writeBuffer(this.authToken); | |
} else { | |
packet.writeBuffer(this.authToken); | |
packet.writeInt8(0); | |
} | |
packet.writeNullTerminatedString(this.database, encoding); | |
packet.writeInt16(this.charsetNumber); | |
if (isSet('PLUGIN_AUTH')) { | |
// TODO: read this from parameters | |
packet.writeNullTerminatedString('mysql_native_password', 'latin1'); | |
} | |
if (isSet('CONNECT_ATTRS')) { | |
const connectAttributes = this.connectAttributes; | |
const attrNames = Object.keys(connectAttributes); | |
let keysLength = 0; | |
for (let k = 0; k < attrNames.length; ++k) { | |
keysLength += Packet.lengthCodedStringLength(attrNames[k], encoding); | |
keysLength += Packet.lengthCodedStringLength( | |
connectAttributes[attrNames[k]], | |
encoding | |
); | |
} | |
packet.writeLengthCodedNumber(keysLength); | |
for (let k = 0; k < attrNames.length; ++k) { | |
packet.writeLengthCodedString(attrNames[k], encoding); | |
packet.writeLengthCodedString( | |
connectAttributes[attrNames[k]], | |
encoding | |
); | |
} | |
} | |
return packet; | |
} | |
toPacket() { | |
if (typeof this.user !== 'string') { | |
throw new Error('"user" connection config property must be a string'); | |
} | |
if (typeof this.database !== 'string') { | |
throw new Error('"database" connection config property must be a string'); | |
} | |
// dry run: calculate resulting packet length | |
const p = this.serializeToBuffer(Packet.MockBuffer()); | |
return this.serializeToBuffer(Buffer.allocUnsafe(p.offset)); | |
} | |
} | |
module.exports = ChangeUser; | |