You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

210 lines
6.5 KiB

var urlParse = require('url').parse;
var ClientConstants = require('./protocol/constants/client');
var Charsets = require('./protocol/constants/charsets');
var SSLProfiles = null;
module.exports = ConnectionConfig;
function ConnectionConfig(options) {
if (typeof options === 'string') {
options = ConnectionConfig.parseUrl(options);
}
this.host = options.host || 'localhost';
this.port = options.port || 3306;
this.localAddress = options.localAddress;
this.socketPath = options.socketPath;
this.user = options.user || undefined;
this.password = options.password || undefined;
this.database = options.database;
this.connectTimeout = (options.connectTimeout === undefined)
? (10 * 1000)
: options.connectTimeout;
this.insecureAuth = options.insecureAuth || false;
this.supportBigNumbers = options.supportBigNumbers || false;
this.bigNumberStrings = options.bigNumberStrings || false;
this.dateStrings = options.dateStrings || false;
this.debug = options.debug;
this.trace = options.trace !== false;
this.stringifyObjects = options.stringifyObjects || false;
this.timezone = options.timezone || 'local';
this.flags = options.flags || '';
this.queryFormat = options.queryFormat;
this.pool = options.pool || undefined;
this.ssl = (typeof options.ssl === 'string')
? ConnectionConfig.getSSLProfile(options.ssl)
: (options.ssl || false);
this.localInfile = (options.localInfile === undefined)
? true
: options.localInfile;
this.multipleStatements = options.multipleStatements || false;
this.typeCast = (options.typeCast === undefined)
? true
: options.typeCast;
if (this.timezone[0] === ' ') {
// "+" is a url encoded char for space so it
// gets translated to space when giving a
// connection string..
this.timezone = '+' + this.timezone.substr(1);
}
if (this.ssl) {
// Default rejectUnauthorized to true
this.ssl.rejectUnauthorized = this.ssl.rejectUnauthorized !== false;
}
this.maxPacketSize = 0;
this.charsetNumber = (options.charset)
? ConnectionConfig.getCharsetNumber(options.charset)
: options.charsetNumber || Charsets.UTF8_GENERAL_CI;
// Set the client flags
var defaultFlags = ConnectionConfig.getDefaultFlags(options);
this.clientFlags = ConnectionConfig.mergeFlags(defaultFlags, options.flags);
}
ConnectionConfig.mergeFlags = function mergeFlags(defaultFlags, userFlags) {
var allFlags = ConnectionConfig.parseFlagList(defaultFlags);
var newFlags = ConnectionConfig.parseFlagList(userFlags);
// Merge the new flags
for (var flag in newFlags) {
if (allFlags[flag] !== false) {
allFlags[flag] = newFlags[flag];
}
}
// Build flags
var flags = 0x0;
for (var flag in allFlags) {
if (allFlags[flag]) {
// TODO: Throw here on some future release
flags |= ClientConstants['CLIENT_' + flag] || 0x0;
}
}
return flags;
};
ConnectionConfig.getCharsetNumber = function getCharsetNumber(charset) {
var num = Charsets[charset.toUpperCase()];
if (num === undefined) {
throw new TypeError('Unknown charset \'' + charset + '\'');
}
return num;
};
ConnectionConfig.getDefaultFlags = function getDefaultFlags(options) {
var defaultFlags = [
'-COMPRESS', // Compression protocol *NOT* supported
'-CONNECT_ATTRS', // Does *NOT* send connection attributes in Protocol::HandshakeResponse41
'+CONNECT_WITH_DB', // One can specify db on connect in Handshake Response Packet
'+FOUND_ROWS', // Send found rows instead of affected rows
'+IGNORE_SIGPIPE', // Don't issue SIGPIPE if network failures
'+IGNORE_SPACE', // Let the parser ignore spaces before '('
'+LOCAL_FILES', // Can use LOAD DATA LOCAL
'+LONG_FLAG', // Longer flags in Protocol::ColumnDefinition320
'+LONG_PASSWORD', // Use the improved version of Old Password Authentication
'+MULTI_RESULTS', // Can handle multiple resultsets for COM_QUERY
'+ODBC', // Special handling of ODBC behaviour
'-PLUGIN_AUTH', // Does *NOT* support auth plugins
'+PROTOCOL_41', // Uses the 4.1 protocol
'+PS_MULTI_RESULTS', // Can handle multiple resultsets for COM_STMT_EXECUTE
'+RESERVED', // Unused
'+SECURE_CONNECTION', // Supports Authentication::Native41
'+TRANSACTIONS' // Expects status flags
];
if (options && options.localInfile !== undefined && !options.localInfile) {
// Disable LOCAL modifier for LOAD DATA INFILE
defaultFlags.push('-LOCAL_FILES');
}
if (options && options.multipleStatements) {
// May send multiple statements per COM_QUERY and COM_STMT_PREPARE
defaultFlags.push('+MULTI_STATEMENTS');
}
return defaultFlags;
};
ConnectionConfig.getSSLProfile = function getSSLProfile(name) {
if (!SSLProfiles) {
SSLProfiles = require('./protocol/constants/ssl_profiles');
}
var ssl = SSLProfiles[name];
if (ssl === undefined) {
throw new TypeError('Unknown SSL profile \'' + name + '\'');
}
return ssl;
};
ConnectionConfig.parseFlagList = function parseFlagList(flagList) {
var allFlags = Object.create(null);
if (!flagList) {
return allFlags;
}
var flags = !Array.isArray(flagList)
? String(flagList || '').toUpperCase().split(/\s*,+\s*/)
: flagList;
for (var i = 0; i < flags.length; i++) {
var flag = flags[i];
var offset = 1;
var state = flag[0];
if (state === undefined) {
// TODO: throw here on some future release
continue;
}
if (state !== '-' && state !== '+') {
offset = 0;
state = '+';
}
allFlags[flag.substr(offset)] = state === '+';
}
return allFlags;
};
ConnectionConfig.parseUrl = function(url) {
url = urlParse(url, true);
var options = {
host : url.hostname,
port : url.port,
database : url.pathname.substr(1)
};
if (url.auth) {
var auth = url.auth.split(':');
options.user = auth.shift();
options.password = auth.join(':');
}
if (url.query) {
for (var key in url.query) {
var value = url.query[key];
try {
// Try to parse this as a JSON expression first
options[key] = JSON.parse(value);
} catch (err) {
// Otherwise assume it is a plain string
options[key] = value;
}
}
}
return options;
};