source: node_modules/pgpass/lib/helper.js

main
Last change on this file was 62b2964, checked in by Klimentina Efremova <klimentina08642@…>, 2 weeks ago

Project Handcraft Marketplace

  • Property mode set to 100644
File size: 5.4 KB
Line 
1'use strict';
2
3var path = require('path')
4 , Stream = require('stream').Stream
5 , split = require('split2')
6 , util = require('util')
7 , defaultPort = 5432
8 , isWin = (process.platform === 'win32')
9 , warnStream = process.stderr
10;
11
12
13var S_IRWXG = 56 // 00070(8)
14 , S_IRWXO = 7 // 00007(8)
15 , S_IFMT = 61440 // 00170000(8)
16 , S_IFREG = 32768 // 0100000(8)
17;
18function isRegFile(mode) {
19 return ((mode & S_IFMT) == S_IFREG);
20}
21
22var fieldNames = [ 'host', 'port', 'database', 'user', 'password' ];
23var nrOfFields = fieldNames.length;
24var passKey = fieldNames[ nrOfFields -1 ];
25
26
27function warn() {
28 var isWritable = (
29 warnStream instanceof Stream &&
30 true === warnStream.writable
31 );
32
33 if (isWritable) {
34 var args = Array.prototype.slice.call(arguments).concat("\n");
35 warnStream.write( util.format.apply(util, args) );
36 }
37}
38
39
40Object.defineProperty(module.exports, 'isWin', {
41 get : function() {
42 return isWin;
43 } ,
44 set : function(val) {
45 isWin = val;
46 }
47});
48
49
50module.exports.warnTo = function(stream) {
51 var old = warnStream;
52 warnStream = stream;
53 return old;
54};
55
56module.exports.getFileName = function(rawEnv){
57 var env = rawEnv || process.env;
58 var file = env.PGPASSFILE || (
59 isWin ?
60 path.join( env.APPDATA || './' , 'postgresql', 'pgpass.conf' ) :
61 path.join( env.HOME || './', '.pgpass' )
62 );
63 return file;
64};
65
66module.exports.usePgPass = function(stats, fname) {
67 if (Object.prototype.hasOwnProperty.call(process.env, 'PGPASSWORD')) {
68 return false;
69 }
70
71 if (isWin) {
72 return true;
73 }
74
75 fname = fname || '<unkn>';
76
77 if (! isRegFile(stats.mode)) {
78 warn('WARNING: password file "%s" is not a plain file', fname);
79 return false;
80 }
81
82 if (stats.mode & (S_IRWXG | S_IRWXO)) {
83 /* If password file is insecure, alert the user and ignore it. */
84 warn('WARNING: password file "%s" has group or world access; permissions should be u=rw (0600) or less', fname);
85 return false;
86 }
87
88 return true;
89};
90
91
92var matcher = module.exports.match = function(connInfo, entry) {
93 return fieldNames.slice(0, -1).reduce(function(prev, field, idx){
94 if (idx == 1) {
95 // the port
96 if ( Number( connInfo[field] || defaultPort ) === Number( entry[field] ) ) {
97 return prev && true;
98 }
99 }
100 return prev && (
101 entry[field] === '*' ||
102 entry[field] === connInfo[field]
103 );
104 }, true);
105};
106
107
108module.exports.getPassword = function(connInfo, stream, cb) {
109 var pass;
110 var lineStream = stream.pipe(split());
111
112 function onLine(line) {
113 var entry = parseLine(line);
114 if (entry && isValidEntry(entry) && matcher(connInfo, entry)) {
115 pass = entry[passKey];
116 lineStream.end(); // -> calls onEnd(), but pass is set now
117 }
118 }
119
120 var onEnd = function() {
121 stream.destroy();
122 cb(pass);
123 };
124
125 var onErr = function(err) {
126 stream.destroy();
127 warn('WARNING: error on reading file: %s', err);
128 cb(undefined);
129 };
130
131 stream.on('error', onErr);
132 lineStream
133 .on('data', onLine)
134 .on('end', onEnd)
135 .on('error', onErr)
136 ;
137
138};
139
140
141var parseLine = module.exports.parseLine = function(line) {
142 if (line.length < 11 || line.match(/^\s+#/)) {
143 return null;
144 }
145
146 var curChar = '';
147 var prevChar = '';
148 var fieldIdx = 0;
149 var startIdx = 0;
150 var endIdx = 0;
151 var obj = {};
152 var isLastField = false;
153 var addToObj = function(idx, i0, i1) {
154 var field = line.substring(i0, i1);
155
156 if (! Object.hasOwnProperty.call(process.env, 'PGPASS_NO_DEESCAPE')) {
157 field = field.replace(/\\([:\\])/g, '$1');
158 }
159
160 obj[ fieldNames[idx] ] = field;
161 };
162
163 for (var i = 0 ; i < line.length-1 ; i += 1) {
164 curChar = line.charAt(i+1);
165 prevChar = line.charAt(i);
166
167 isLastField = (fieldIdx == nrOfFields-1);
168
169 if (isLastField) {
170 addToObj(fieldIdx, startIdx);
171 break;
172 }
173
174 if (i >= 0 && curChar == ':' && prevChar !== '\\') {
175 addToObj(fieldIdx, startIdx, i+1);
176
177 startIdx = i+2;
178 fieldIdx += 1;
179 }
180 }
181
182 obj = ( Object.keys(obj).length === nrOfFields ) ? obj : null;
183
184 return obj;
185};
186
187
188var isValidEntry = module.exports.isValidEntry = function(entry){
189 var rules = {
190 // host
191 0 : function(x){
192 return x.length > 0;
193 } ,
194 // port
195 1 : function(x){
196 if (x === '*') {
197 return true;
198 }
199 x = Number(x);
200 return (
201 isFinite(x) &&
202 x > 0 &&
203 x < 9007199254740992 &&
204 Math.floor(x) === x
205 );
206 } ,
207 // database
208 2 : function(x){
209 return x.length > 0;
210 } ,
211 // username
212 3 : function(x){
213 return x.length > 0;
214 } ,
215 // password
216 4 : function(x){
217 return x.length > 0;
218 }
219 };
220
221 for (var idx = 0 ; idx < fieldNames.length ; idx += 1) {
222 var rule = rules[idx];
223 var value = entry[ fieldNames[idx] ] || '';
224
225 var res = rule(value);
226 if (!res) {
227 return false;
228 }
229 }
230
231 return true;
232};
233
Note: See TracBrowser for help on using the repository browser.