| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 | 'use strict';var path = require('path')  , Stream = require('stream').Stream  , split = require('split2')  , util = require('util')  , defaultPort = 5432  , isWin = (process.platform === 'win32')  , warnStream = process.stderr;var S_IRWXG = 56     //    00070(8)  , S_IRWXO = 7      //    00007(8)  , S_IFMT  = 61440  // 00170000(8)  , S_IFREG = 32768  //  0100000(8);function isRegFile(mode) {    return ((mode & S_IFMT) == S_IFREG);}var fieldNames = [ 'host', 'port', 'database', 'user', 'password' ];var nrOfFields = fieldNames.length;var passKey = fieldNames[ nrOfFields -1 ];function warn() {    var isWritable = (        warnStream instanceof Stream &&          true === warnStream.writable    );    if (isWritable) {        var args = Array.prototype.slice.call(arguments).concat("\n");        warnStream.write( util.format.apply(util, args) );    }}Object.defineProperty(module.exports, 'isWin', {    get : function() {        return isWin;    } ,    set : function(val) {        isWin = val;    }});module.exports.warnTo = function(stream) {    var old = warnStream;    warnStream = stream;    return old;};module.exports.getFileName = function(rawEnv){    var env = rawEnv || process.env;    var file = env.PGPASSFILE || (        isWin ?          path.join( env.APPDATA || './' , 'postgresql', 'pgpass.conf' ) :          path.join( env.HOME || './', '.pgpass' )    );    return file;};module.exports.usePgPass = function(stats, fname) {    if (Object.prototype.hasOwnProperty.call(process.env, 'PGPASSWORD')) {        return false;    }    if (isWin) {        return true;    }    fname = fname || '<unkn>';    if (! isRegFile(stats.mode)) {        warn('WARNING: password file "%s" is not a plain file', fname);        return false;    }    if (stats.mode & (S_IRWXG | S_IRWXO)) {        /* If password file is insecure, alert the user and ignore it. */        warn('WARNING: password file "%s" has group or world access; permissions should be u=rw (0600) or less', fname);        return false;    }    return true;};var matcher = module.exports.match = function(connInfo, entry) {    return fieldNames.slice(0, -1).reduce(function(prev, field, idx){        if (idx == 1) {            // the port            if ( Number( connInfo[field] || defaultPort ) === Number( entry[field] ) ) {                return prev && true;            }        }        return prev && (            entry[field] === '*' ||              entry[field] === connInfo[field]        );    }, true);};module.exports.getPassword = function(connInfo, stream, cb) {    var pass;    var lineStream = stream.pipe(split());    function onLine(line) {        var entry = parseLine(line);        if (entry && isValidEntry(entry) && matcher(connInfo, entry)) {            pass = entry[passKey];            lineStream.end(); // -> calls onEnd(), but pass is set now        }    }    var onEnd = function() {        stream.destroy();        cb(pass);    };    var onErr = function(err) {        stream.destroy();        warn('WARNING: error on reading file: %s', err);        cb(undefined);    };    stream.on('error', onErr);    lineStream        .on('data', onLine)        .on('end', onEnd)        .on('error', onErr)    ;};var parseLine = module.exports.parseLine = function(line) {    if (line.length < 11 || line.match(/^\s+#/)) {        return null;    }    var curChar = '';    var prevChar = '';    var fieldIdx = 0;    var startIdx = 0;    var endIdx = 0;    var obj = {};    var isLastField = false;    var addToObj = function(idx, i0, i1) {        var field = line.substring(i0, i1);        if (! Object.hasOwnProperty.call(process.env, '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 !== '\\') {            addToObj(fieldIdx, startIdx, i+1);            startIdx = i+2;            fieldIdx += 1;        }    }    obj = ( Object.keys(obj).length === nrOfFields ) ? obj : null;    return obj;};var isValidEntry = module.exports.isValidEntry = function(entry){    var rules = {        // host        0 : function(x){            return x.length > 0;        } ,        // port        1 : function(x){            if (x === '*') {                return true;            }            x = Number(x);            return (                isFinite(x) &&                  x > 0 &&                  x < 9007199254740992 &&                  Math.floor(x) === x            );        } ,        // database        2 : function(x){            return x.length > 0;        } ,        // username        3 : function(x){            return x.length > 0;        } ,        // password        4 : function(x){            return x.length > 0;        }    };    for (var idx = 0 ; idx < fieldNames.length ; idx += 1) {        var rule = rules[idx];        var value = entry[ fieldNames[idx] ] || '';        var res = rule(value);        if (!res) {            return false;        }    }    return true;};
 |