You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 7-8.RSVP
Socket
Socket
Sign inDemoInstall

mongodb-core

Package Overview
Dependencies
Maintainers
3
Versions
177
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 3.1.5 to 3.1.6

11

HISTORY.md

@@ -5,2 +5,13 @@ # Change Log

<a name="3.1.6"></a>
## [3.1.6](https://github.com/mongodb-js/mongodb-core/compare/v3.1.4...v3.1.6) (2018-10-09)
### Bug Fixes
* **srv-parsing:** ensure parse options are propogated to txt lookup ([923ceb0](https://github.com/mongodb-js/mongodb-core/commit/923ceb0))
* **uri-parser:** add exemption list for number coercion in options ([82896ea](https://github.com/mongodb-js/mongodb-core/commit/82896ea))
<a name="3.1.5"></a>

@@ -7,0 +18,0 @@ ## [3.1.5](https://github.com/mongodb-js/mongodb-core/compare/v3.1.4...v3.1.5) (2018-09-15)

2

lib/connection/connection.js

@@ -283,3 +283,3 @@ 'use strict';

// Handle a message once it is recieved
// Handle a message once it is received
var emitMessageHandler = function(self, message) {

@@ -286,0 +286,0 @@ var msgHeader = parseHeader(message);

@@ -127,3 +127,3 @@ 'use strict';

*
* @param {(MongoError|Error})} error
* @param {MongoError|Error} error
*/

@@ -130,0 +130,0 @@ function isRetryableError(error) {

@@ -89,3 +89,3 @@ 'use strict';

serverDescriptions,
options.replicaset,
options.replicaSet,
null,

@@ -388,4 +388,4 @@ null,

function topologyTypeFromSeedlist(seedlist, options) {
if (seedlist.length === 1 && !options.replicaset) return TopologyType.Single;
if (options.replicaset) return TopologyType.ReplicaSetNoPrimary;
if (seedlist.length === 1 && !options.replicaSet) return TopologyType.Single;
if (options.replicaSet) return TopologyType.ReplicaSetNoPrimary;
return TopologyType.Unknown;

@@ -392,0 +392,0 @@ }

@@ -6,2 +6,3 @@ 'use strict';

const MongoParseError = require('./error').MongoParseError;
const ReadPreference = require('./topologies/read_preference');

@@ -127,3 +128,3 @@ /**

parseConnectionString(connectionString, callback);
parseConnectionString(connectionString, options, callback);
});

@@ -136,6 +137,7 @@ });

*
* @param {string} key The key for the parsed value
* @param {Array|String} value The value to parse
* @return {Array|Object|String} The parsed value
*/
function parseQueryStringItemValue(value) {
function parseQueryStringItemValue(key, value) {
if (Array.isArray(value)) {

@@ -148,3 +150,3 @@ // deduplicate and simplify arrays

const parts = pair.split(':');
result[parts[0]] = parseQueryStringItemValue(parts[1]);
result[parts[0]] = parseQueryStringItemValue(key, parts[1]);
return result;

@@ -154,7 +156,7 @@ }, {});

value = value.split(',').map(v => {
return parseQueryStringItemValue(v);
return parseQueryStringItemValue(key, v);
});
} else if (value.toLowerCase() === 'true' || value.toLowerCase() === 'false') {
value = value.toLowerCase() === 'true';
} else if (!Number.isNaN(value)) {
} else if (!Number.isNaN(value) && !STRING_OPTIONS.has(key)) {
const numericValue = parseFloat(value);

@@ -169,9 +171,217 @@ if (!Number.isNaN(numericValue)) {

// Options that are known boolean types
const BOOLEAN_OPTIONS = new Set([
'slaveok',
'slave_ok',
'sslvalidate',
'fsync',
'safe',
'retrywrites',
'j'
]);
// Known string options, only used to bypass Number coercion in `parseQueryStringItemValue`
const STRING_OPTIONS = new Set(['authsource']);
// Supported text representations of auth mechanisms
// NOTE: this list exists in native already, if it is merged here we should deduplicate
const AUTH_MECHANISMS = new Set([
'GSSAPI',
'MONGODB-X509',
'MONGODB-CR',
'DEFAULT',
'SCRAM-SHA-1',
'SCRAM-SHA-256',
'PLAIN'
]);
// Lookup table used to translate normalized (lower-cased) forms of connection string
// options to their expected camelCase version
const CASE_TRANSLATION = {
replicaset: 'replicaSet',
connecttimeoutms: 'connectTimeoutMS',
sockettimeoutms: 'socketTimeoutMS',
maxpoolsize: 'maxPoolSize',
minpoolsize: 'minPoolSize',
maxidletimems: 'maxIdleTimeMS',
waitqueuemultiple: 'waitQueueMultiple',
waitqueuetimeoutms: 'waitQueueTimeoutMS',
wtimeoutms: 'wtimeoutMS',
readconcern: 'readConcern',
readconcernlevel: 'readConcernLevel',
readpreference: 'readPreference',
maxstalenessseconds: 'maxStalenessSeconds',
readpreferencetags: 'readPreferenceTags',
authsource: 'authSource',
authmechanism: 'authMechanism',
authmechanismproperties: 'authMechanismProperties',
gssapiservicename: 'gssapiServiceName',
localthresholdms: 'localThresholdMS',
serverselectiontimeoutms: 'serverSelectionTimeoutMS',
serverselectiontryonce: 'serverSelectionTryOnce',
heartbeatfrequencyms: 'heartbeatFrequencyMS',
appname: 'appName',
retrywrites: 'retryWrites',
uuidrepresentation: 'uuidRepresentation',
zlibcompressionlevel: 'zlibCompressionLevel'
};
/**
* Sets the value for `key`, allowing for any required translation
*
* @param {object} obj The object to set the key on
* @param {string} key The key to set the value for
* @param {*} value The value to set
* @param {object} options The options used for option parsing
*/
function applyConnectionStringOption(obj, key, value, options) {
// simple key translation
if (key === 'journal') {
key = 'j';
} else if (key === 'wtimeoutms') {
key = 'wtimeout';
}
// more complicated translation
if (BOOLEAN_OPTIONS.has(key)) {
value = value === 'true' || value === true;
} else if (key === 'appname') {
value = decodeURIComponent(value);
} else if (key === 'readconcernlevel') {
key = 'readconcern';
value = { level: value };
}
// simple validation
if (key === 'compressors') {
value = Array.isArray(value) ? value : [value];
if (!value.every(c => c === 'snappy' || c === 'zlib')) {
throw new MongoParseError(
'Value for `compressors` must be at least one of: `snappy`, `zlib`'
);
}
}
if (key === 'authmechanism' && !AUTH_MECHANISMS.has(value)) {
throw new MongoParseError(
'Value for `authMechanism` must be one of: `DEFAULT`, `GSSAPI`, `PLAIN`, `MONGODB-X509`, `SCRAM-SHA-1`, `SCRAM-SHA-256`'
);
}
if (key === 'readpreference' && !ReadPreference.isValid(value)) {
throw new MongoParseError(
'Value for `readPreference` must be one of: `primary`, `primaryPreferred`, `secondary`, `secondaryPreferred`, `nearest`'
);
}
if (key === 'zlibcompressionlevel' && (value < -1 || value > 9)) {
throw new MongoParseError('zlibCompressionLevel must be an integer between -1 and 9');
}
// special cases
if (key === 'compressors' || key === 'zlibcompressionlevel') {
obj.compression = obj.compression || {};
obj = obj.compression;
}
if (key === 'authmechanismproperties') {
if (typeof value.SERVICE_NAME === 'string') obj.gssapiServiceName = value.SERVICE_NAME;
if (typeof value.SERVICE_REALM === 'string') obj.gssapiServiceRealm = value.SERVICE_REALM;
if (typeof value.CANONICALIZE_HOST_NAME !== 'undefined') {
obj.gssapiCanonicalizeHostName = value.CANONICALIZE_HOST_NAME;
}
}
// set the actual value
if (options.caseTranslate && CASE_TRANSLATION[key]) {
obj[CASE_TRANSLATION[key]] = value;
return;
}
obj[key] = value;
}
const USERNAME_REQUIRED_MECHANISMS = new Set([
'GSSAPI',
'MONGODB-CR',
'PLAIN',
'SCRAM-SHA-1',
'SCRAM-SHA-256'
]);
/**
* Modifies the parsed connection string object taking into account expectations we
* have for authentication-related options.
*
* @param {object} parsed The parsed connection string result
* @return The parsed connection string result possibly modified for auth expectations
*/
function applyAuthExpectations(parsed) {
if (parsed.options == null) {
return;
}
const options = parsed.options;
const authSource = options.authsource || options.authSource;
if (authSource != null) {
parsed.auth = Object.assign({}, parsed.auth, { db: authSource });
}
const authMechanism = options.authmechanism || options.authMechanism;
if (authMechanism != null) {
if (
USERNAME_REQUIRED_MECHANISMS.has(authMechanism) &&
(!parsed.auth || parsed.auth.username == null)
) {
throw new MongoParseError(`Username required for mechanism \`${authMechanism}\``);
}
if (authMechanism === 'GSSAPI') {
if (authSource != null && authSource !== '$external') {
throw new MongoParseError(
`Invalid source \`${authSource}\` for mechanism \`${authMechanism}\` specified.`
);
}
parsed.auth = Object.assign({}, parsed.auth, { db: '$external' });
}
if (authMechanism === 'MONGODB-X509') {
if (parsed.auth && parsed.auth.password != null) {
throw new MongoParseError(`Password not allowed for mechanism \`${authMechanism}\``);
}
if (authSource != null && authSource !== '$external') {
throw new MongoParseError(
`Invalid source \`${authSource}\` for mechanism \`${authMechanism}\` specified.`
);
}
parsed.auth = Object.assign({}, parsed.auth, { db: '$external' });
}
if (authMechanism === 'PLAIN') {
if (parsed.auth && parsed.auth.db == null) {
parsed.auth = Object.assign({}, parsed.auth, { db: '$external' });
}
}
}
// default to `admin` if nothing else was resolved
if (parsed.auth && parsed.auth.db == null) {
parsed.auth = Object.assign({}, parsed.auth, { db: 'admin' });
}
return parsed;
}
/**
* Parses a query string according the connection string spec.
*
* @param {String} query The query string to parse
* @param {object} [options] The options used for options parsing
* @return {Object|Error} The parsed query string as an object, or an error if one was encountered
*/
function parseQueryString(query) {
function parseQueryString(query, options) {
const result = {};

@@ -183,6 +393,8 @@ let parsedQueryString = qs.parse(query);

if (value === '' || value == null) {
return new MongoParseError('Incomplete key value pair for option');
throw new MongoParseError('Incomplete key value pair for option');
}
result[key.toLowerCase()] = parseQueryStringItemValue(value);
const normalizedKey = key.toLowerCase();
const parsedValue = parseQueryStringItemValue(normalizedKey, value);
applyConnectionStringOption(result, normalizedKey, parsedValue, options);
}

@@ -208,2 +420,3 @@

* @param {object} [options] Optional settings.
* @param {boolean} [options.caseTranslate] Whether the parser should translate options back into camelCase after normalization
* @param {parseCallback} callback

@@ -213,3 +426,3 @@ */

if (typeof options === 'function') (callback = options), (options = {});
options = options || {};
options = Object.assign({}, { caseTranslate: true }, options);

@@ -240,9 +453,12 @@ // Check for bad uris before we parse

const query = dbAndQuery.length > 1 ? dbAndQuery[1] : null;
let parsedOptions = parseQueryString(query);
if (parsedOptions instanceof MongoParseError) {
return callback(parsedOptions);
let parsedOptions;
try {
parsedOptions = parseQueryString(query, options);
} catch (parseError) {
return callback(parseError);
}
parsedOptions = Object.assign({}, parsedOptions, options);
const auth = { username: null, password: null, db: db && db !== '' ? qs.unescape(db) : 'admin' };
const auth = { username: null, password: null, db: db && db !== '' ? qs.unescape(db) : null };
if (cap[4].split('?')[0].indexOf('@') !== -1) {

@@ -321,9 +537,17 @@ return callback(new MongoParseError('Unescaped slash in userinfo section'));

callback(null, {
const result = {
hosts: hosts,
auth: auth.db || auth.username ? auth : null,
options: Object.keys(parsedOptions).length ? parsedOptions : null
});
};
try {
applyAuthExpectations(result);
} catch (authError) {
return callback(authError);
}
callback(null, result);
}
module.exports = parseConnectionString;
{
"name": "mongodb-core",
"version": "3.1.5",
"version": "3.1.6",
"description": "Core MongoDB driver functionality, no bells and whistles and meant for integration not end applications",

@@ -44,3 +44,3 @@ "main": "index.js",

"sinon": "^6.0.0",
"snappy": "^6.0.1",
"snappy": "^6.1.1",
"standard-version": "^4.4.0"

@@ -51,3 +51,3 @@ },

"mongodb-extjson": "^2.1.2",
"snappy": "^6.0.1",
"snappy": "^6.1.1",
"bson-ext": "^2.0.0"

@@ -54,0 +54,0 @@ },

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc