Skip to content

Commit

Permalink
Bugfix
Browse files Browse the repository at this point in the history
- behaves more like libpq (reading password from 4th colon to EOL)
- setting PGPASS_NO_DEESCAPE switches of de-escaping

fixes: #1
  • Loading branch information
hoegaarden committed Apr 9, 2014
1 parent 08fffcd commit 149db9f
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 33 deletions.
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
## Install

```sh
npm install --save hoegaarden/pgpass
npm install pgpass
```

## Usage
Expand All @@ -17,8 +17,6 @@ var connInfo = {
'user' : 'the_user_name' ,
};


// ---- async ----
pgPass(connInfo, function(pass){
conn_info.password = pass;
// connect to postgresql server
Expand All @@ -27,7 +25,7 @@ pgPass(connInfo, function(pass){

## Description

This module tries to read the `~/.pgpass` file (or the equivalent for windows systems). If the environment variable `PGPASSFILE` is set, this file is used instead. If everything goes right, the password from said file is to the callback; if the password cannot be read `undefined` is passed to the callback.
This module tries to read the `~/.pgpass` file (or the equivalent for windows systems). If the environment variable `PGPASSFILE` is set, this file is used instead. If everything goes right, the password from said file is passed to the callback; if the password cannot be read `undefined` is passed to the callback.

Cases where `undefined` is returned:

Expand All @@ -36,7 +34,12 @@ Cases where `undefined` is returned:
- for non windows systems: the file is write-/readable by the group or by other users
- there is no matching line for the given connection info

The goal of this package is to get included in the `node-postgresql` module to get the same behaviour for the javascript client as for the native client.
There should be no need to use this module directly; it is already included in `node-postgresq`.

## Configuration

The module reads the environment variable `PGPASS_NO_DEESCAPE` to decide if the the read tokens from the password file should be de-escaped or not. Default is to do de-escaping. For further information on this see [this commit](https://github.com/postgres/postgres/commit/8d15e3ec4fcb735875a8a70a09ec0c62153c3329).


## Tests

Expand Down
51 changes: 26 additions & 25 deletions lib/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function isRegFile(mode) {

var fieldNames = [ 'host', 'port', 'database', 'user', 'password' ];
var nrOfFields = fieldNames.length;
var passKey = fieldNames[ fieldNames.length -1 ];
var passKey = fieldNames[ nrOfFields -1 ];


function warn() {
Expand Down Expand Up @@ -113,7 +113,7 @@ module.exports.getPassword = function(connInfo, stream, cb) {
var entry = parseLine(line);
if (entry && isValidEntry(entry) && matcher(connInfo, entry)) {
pass = entry[passKey];
lineStream.end(); // -> calles onEnd(), but pass is set now
lineStream.end(); // -> calls onEnd(), but pass is set now
}
}

Expand Down Expand Up @@ -141,44 +141,45 @@ var parseLine = module.exports.parseLine = function(line) {
return null;
}

function addToObj(idx, i0, i1) {
if (idx >= 0 && idx < nrOfFields) {
obj[ fieldNames[idx] ] = line
.substring(i0, i1)
.replace(/\\([:\\])/g, '$1')
;
return true;
} else {
return false;
}
}

var prevChar = '';
var curChar = '';
var prevChar = '';
var fieldIdx = 0;
var startIdx = 0;
var endIdx = 0;
var obj = {};
var fieldIdx = 0;
var isOk = false;
var isLastField = false;
var addToObj = function(idx, i0, i1) {
var field = line.substring(i0, i1);

if (! process.env.hasOwnProperty('PGPASS_NO_DEESCAPE')) {
field = field.replace(/\\([:\\])/g, '$1');
}

obj[ fieldNames[idx] ] = field;
};

for (var i = 0 ; i < line.length-1 ; i += 1) {
curChar = line.charAt(i+1);
prevChar = line.charAt(i);

isLastField = (fieldIdx == nrOfFields-1);

if (isLastField) {
addToObj(fieldIdx, startIdx);
break;
}

if (i >= 0 && curChar == ':' && prevChar !== '\\') {
if ( ! addToObj(fieldIdx, startIdx, i+1) ) {
return null;
}
addToObj(fieldIdx, startIdx, i+1);

startIdx = i+2;
fieldIdx += 1;
}
}
isOk = addToObj(fieldIdx, startIdx);

return (
isOk &&
Object.keys(obj).length === nrOfFields
) ? obj : null;
obj = ( Object.keys(obj).length === nrOfFields ) ? obj : null;

return obj;
};


Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "pgpass",
"version": "0.0.2",
"version": "0.0.3",
"description": "Module for reading .pgpass",
"main": "lib/index",
"scripts": {
Expand Down
42 changes: 42 additions & 0 deletions test/#1 de-escaping.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
'use strict';

/* global describe: false */
/* global it: false */
/* global after: false */
/* global before: false */

/* jshint -W106 */
var COV = process.env.npm_lifecycle_event === 'coverage';
/* jshint +W106 */

var assert = require('assert')
, path = require('path')
, pgPass = require( path.join('..', COV ? 'lib-cov' : 'lib' , 'index') )
;


var conn = {
'host' : 'host5' ,
'database' : 'database5' ,
'user' : 'dummy\\:user'
};

describe('#1', function(){
before(function(){
process.env.PGPASS_NO_DEESCAPE = true;
process.env.PGPASSFILE = path.join(__dirname, '_pgpass');
});
after(function(){
delete process.env.PGPASS_NO_DEESCAPE;
delete process.env.PGPASSFILE;
});

it('should not de-escape NODE_PG_NO_DESCAPE is set', function(done){
process.env.PGPASSFILE = path.join(__dirname, '_pgpass');

pgPass(conn, function(res){
assert.strictEqual('some:password', res);
done();
});
});
});
2 changes: 2 additions & 0 deletions test/_pgpass
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ host3:3:database3:user3:pass3

host4:*:database4:user4:some\:wired\:password

host5:*:database5:dummy\:user:some:password


5 changes: 3 additions & 2 deletions test/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,12 @@ describe('#parseLine()', function(){
});
});

it('should ignore too short and too long lines', function(){
it('should ignore too short lines', function(){
var tests = [
'::::' ,
'host:port' ,
'host:port:database:user:pass:some:thing:else'
'host:port:database' ,
'host:port:database:'
];

tests.forEach(function(line){
Expand Down

0 comments on commit 149db9f

Please sign in to comment.