node-postgres/lib/connection-parameters.js
za-creature c666b20287 Update connection-parameters.js
The current connection url handling fails when the password contains
encoded special characters: After the encodeURI, the special
characters from the password are double encoded, and the password is
rejected by postgres.

Proposed fix handles one level of double encoding, and while it
might break compatibility with passwords like "asdfg%77fgh" (which
would've been escaped to asdfg%2577fgh before this patch), I
strongly feel that maintaining backwards compatibility is in this
case less important than following standards and discouraging bad
coding practices.
2013-04-11 19:57:03 +03:00

74 lines
2.1 KiB
JavaScript

var dns = require('dns');
var path = require('path');
var defaults = require(__dirname + '/defaults');
var val = function(key, config) {
return config[key] ||
process.env['PG' + key.toUpperCase()] ||
defaults[key];
};
var url = require('url');
//parses a connection string
var parse = function(str) {
//unix socket
if(str.charAt(0) === '/') {
return { host: str };
}
// url parse expects spaces encoded as %20
// however, we don't want to double-encode
str = encodeURI(str).replace(/\%25/g, "%");
var result = url.parse(str);
var config = {};
config.host = result.hostname;
config.database = result.pathname ? result.pathname.slice(1) : null;
var auth = (result.auth || ':').split(':');
config.user = auth[0];
config.password = auth[1];
config.port = result.port;
return config;
};
var ConnectionParameters = function(config) {
config = typeof config == 'string' ? parse(config) : (config || {});
this.user = val('user', config);
this.database = val('database', config);
this.port = parseInt(val('port', config), 10);
this.host = val('host', config);
this.password = val('password', config);
this.binary = val('binary', config);
this.ssl = config.ssl || defaults.ssl;
//a domain socket begins with '/'
this.isDomainSocket = (!(this.host||'').indexOf('/'));
};
var add = function(params, config, paramName) {
var value = config[paramName];
if(value) {
params.push(paramName+"='"+value+"'");
}
};
ConnectionParameters.prototype.getLibpqConnectionString = function(cb) {
var params = [];
add(params, this, 'user');
add(params, this, 'password');
add(params, this, 'port');
if(this.database) {
params.push("dbname='" + this.database + "'");
}
if(this.isDomainSocket) {
params.push("host=" + this.host);
return cb(null, params.join(' '));
}
params.push("options=--client_encoding='utf-8'");
dns.lookup(this.host, function(err, address) {
if(err) return cb(err, null);
params.push("hostaddr=" + address);
return cb(null, params.join(' '));
});
};
module.exports = ConnectionParameters;