mirror of
https://github.com/avwo/whistle.git
synced 2026-10-28 14:07:30 +08:00
684 lines
18 KiB
JavaScript
684 lines
18 KiB
JavaScript
var fs = require('fs');
|
|
var path = require('path');
|
|
var rules = require('./index');
|
|
var util = require('../util');
|
|
var config = require('../config');
|
|
var Storage = require('./storage');
|
|
var httpMgr = require('../util/http-mgr');
|
|
var Buffer = require('safe-buffer').Buffer;
|
|
|
|
var INTERVAL = 1000 * 60 * 60;
|
|
var MAX_URL_LEN = 10 * 1024;
|
|
var MAX_HEADERS_LEN = 128 * 1024;
|
|
var MAX_BODY_LEN = 256 * 1024;
|
|
var MAX_METHOD_LEN = 64;
|
|
var MAX_HISTORY_LEN = 36;
|
|
var history = [];
|
|
var rulesStorage = new Storage(config.rulesDir, { Default: true });
|
|
var valuesStorage = new Storage(config.valuesDir);
|
|
var propertiesStorage = new Storage(config.propertiesDir);
|
|
var LINE_END_RE = /\n|\r\n|\r/g;
|
|
var MAX_REMOTE_RULES_COUNT = 12;
|
|
var REMOTE_RULES_RE = /^\s*@(`?)(whistle\.[a-z\d_\-]+(?:\/[^\s#]*)?|(?:https?:\/\/|[a-z]:[\\/]|~?\/)[^\s#]+)\s*\1(?:#.*)?$/img;
|
|
var MAX_COUNT_BY_IMPORT = 60;
|
|
var uploadFiles = [];
|
|
var MAX_FILENAME_LEN = 60;
|
|
var ILLEGAL_FILENAME_RE = /[\\/:*?"<>|\s]/;
|
|
var LOCAL_FILES = config.LOCAL_FILES;
|
|
var inlineValues, proxy;
|
|
var CONTROL_RE = /[\u001e\u001f\u200e\u200f\u200d\u200c\u202a\u202d\u202e\u202c\u206e\u206f\u206b\u206a\u206d\u206c]+/g;
|
|
var MULTI_LINE_VALUE_RE = /^[^\n\r\S]*(```+)[^\n\r\S]*(\S+)[^\n\r\S]*[\r\n]([\s\S]+?)[\r\n][^\n\r\S]*\1\s*$/mg;
|
|
|
|
try {
|
|
history = JSON.parse(propertiesStorage.readFile('composerHistory'));
|
|
if (Array.isArray(history)) {
|
|
history = history.filter(checkHistory);
|
|
history = history.slice(0, MAX_HISTORY_LEN);
|
|
} else {
|
|
history = [];
|
|
}
|
|
} catch(e) {}
|
|
|
|
function limitValueLen(name, len) {
|
|
var value = propertiesStorage.getProperty(name);
|
|
if (typeof value !== 'string') {
|
|
propertiesStorage.setProperty(name, name);
|
|
} else if (value.length > len) {
|
|
propertiesStorage.setProperty(name, value.substring(0, len));
|
|
}
|
|
}
|
|
|
|
limitValueLen('Custom1', 16);
|
|
limitValueLen('Custom2', 16);
|
|
|
|
function checkFilename(name) {
|
|
if (!name || typeof name !== 'string' || name.length > MAX_FILENAME_LEN) {
|
|
return false;
|
|
}
|
|
return !ILLEGAL_FILENAME_RE.test(name);
|
|
}
|
|
|
|
try {
|
|
var _files = fs.readdirSync(LOCAL_FILES)
|
|
.filter(checkFilename);
|
|
for (var i = 0, len = _files.length; i < len; i++) {
|
|
var _name = _files[i];
|
|
try {
|
|
var stat = fs.statSync(path.join(LOCAL_FILES, _name));
|
|
if (stat.isFile) {
|
|
uploadFiles.push({
|
|
name: _name,
|
|
date: stat.mtime.getTime()
|
|
});
|
|
}
|
|
} catch (e) {}
|
|
if (uploadFiles.length >= MAX_FILENAME_LEN) {
|
|
break;
|
|
}
|
|
}
|
|
if (uploadFiles.length) {
|
|
uploadFiles.sort(function(prev, next) {
|
|
return util.compare(prev.date, next.date);
|
|
});
|
|
}
|
|
} catch (e) {}
|
|
|
|
function checkHistory(data) {
|
|
return typeof data.url === 'string' && typeof data.method === 'string'
|
|
&& typeof data.headers === 'string' && typeof data.body === 'string';
|
|
}
|
|
|
|
|
|
process.nextTick(function() {
|
|
parseRules();
|
|
});
|
|
/**
|
|
* rules
|
|
*/
|
|
|
|
function resolveInlineValues(str) {
|
|
str = str && str.replace(CONTROL_RE, '').trim();
|
|
if (!str || str.indexOf('```') === -1) {
|
|
return str;
|
|
}
|
|
return str.replace(MULTI_LINE_VALUE_RE, function(_, __, key, value) {
|
|
inlineValues = inlineValues || {};
|
|
if (!inlineValues[key]) {
|
|
inlineValues[key] = value;
|
|
}
|
|
return '';
|
|
});
|
|
}
|
|
|
|
function reverseRules(text, orig) {
|
|
if (!text) {
|
|
return '';
|
|
}
|
|
text = resolveInlineValues(text);
|
|
text = text.split(LINE_END_RE).reverse();
|
|
return orig ? text : text.join('\n');
|
|
}
|
|
|
|
function parseRules() {
|
|
var disableRules = !config.notAllowedDisableRules && propertiesStorage.getProperty('disabledAllRules');
|
|
var shadowRules = disableRules && config.allowDisableShadowRules ? null : config.shadowRules;
|
|
var value = [];
|
|
if (!disableRules && !config.multiEnv) {
|
|
getAllRulesFile().forEach(function(file) {
|
|
if (file.selected) {
|
|
value.push(file.data);
|
|
}
|
|
});
|
|
}
|
|
var backRulesFirst = !config.disabledBackOption && propertiesStorage.getProperty('backRulesFirst') === true;
|
|
var defaultRules = disableRules || defaultRulesIsDisabled() ? null : getDefaultRules();
|
|
if (defaultRules) {
|
|
if (backRulesFirst) {
|
|
value.unshift(defaultRules);
|
|
} else {
|
|
value.push(defaultRules);
|
|
}
|
|
}
|
|
|
|
if (backRulesFirst) {
|
|
value = reverseRules(value.join('\n'), true);
|
|
}
|
|
value = value && value.join('\r\n');
|
|
if (shadowRules) {
|
|
if (backRulesFirst) {
|
|
value = reverseRules(shadowRules) + '\n' + value;
|
|
} else {
|
|
value += '\n' + shadowRules;
|
|
}
|
|
}
|
|
var rulesText = value;
|
|
var index = 0;
|
|
if (rulesText) {
|
|
rulesText = rulesText.replace(REMOTE_RULES_RE, function(_, apo, rulesUrl) {
|
|
if (index >= MAX_REMOTE_RULES_COUNT) {
|
|
return '';
|
|
}
|
|
++index;
|
|
rulesUrl = util.getPluginRulesUrl(rulesUrl);
|
|
if (apo) {
|
|
rulesUrl = util.setConfigVar(rulesUrl);
|
|
}
|
|
var remoteRules = httpMgr.add(rulesUrl, config.runtimeHeaders);
|
|
return backRulesFirst ? reverseRules(remoteRules) : remoteRules;
|
|
});
|
|
}
|
|
if (!index) {
|
|
httpMgr.clean();
|
|
}
|
|
rules.parse(rulesText, null, inlineValues);
|
|
inlineValues = null;
|
|
}
|
|
|
|
httpMgr.addChangeListener(parseRules);
|
|
|
|
exports.parseRules = parseRules;
|
|
|
|
function setDefaultRules(data) {
|
|
data = typeof data != 'string' ? '' : data;
|
|
var oldData = rulesStorage.getProperty('defalutRules') || '';
|
|
rulesStorage.setProperty('defalutRules', data);
|
|
parseRules();
|
|
return data !== oldData;
|
|
}
|
|
|
|
function getDefaultRules() {
|
|
return rulesStorage.getProperty('defalutRules');
|
|
}
|
|
|
|
function disableDefaultRules() {
|
|
rulesStorage.setProperty('disabledDefalutRules', true);
|
|
parseRules();
|
|
}
|
|
|
|
function enableDefaultRules() {
|
|
rulesStorage.setProperty('disabledDefalutRules', false);
|
|
parseRules();
|
|
}
|
|
|
|
function defaultRulesIsDisabled() {
|
|
return rulesStorage.getProperty('disabledDefalutRules');
|
|
}
|
|
|
|
function selectRulesFile(file) {
|
|
if (!rulesStorage.existsFile(file) || config.multiEnv) {
|
|
return;
|
|
}
|
|
|
|
var selectedList = allowMultipleChoice() ? getSelectedRulesList() : [];
|
|
if (selectedList.indexOf(file) == -1) {
|
|
selectedList.push(file);
|
|
rulesStorage.setProperty('selectedList', selectedList);
|
|
}
|
|
parseRules();
|
|
return selectedList;
|
|
}
|
|
|
|
function unselectRulesFile(file, force) {
|
|
if (!force && config.multiEnv) {
|
|
return;
|
|
}
|
|
var selectedList = getSelectedRulesList();
|
|
var index = selectedList.indexOf(file);
|
|
if (index != -1) {
|
|
selectedList.splice(index, 1);
|
|
rulesStorage.setProperty('selectedList', selectedList);
|
|
}
|
|
parseRules();
|
|
|
|
return selectedList;
|
|
}
|
|
|
|
function allowMultipleChoice() {
|
|
return !config.disabledMultipleOption && propertiesStorage.getProperty('allowMultipleChoice');
|
|
}
|
|
|
|
function clearSelection() {
|
|
rulesStorage.setProperty('selectedList', []);
|
|
parseRules();
|
|
}
|
|
|
|
function getSelectedRulesList() {
|
|
if (config.multiEnv) {
|
|
return [];
|
|
}
|
|
var selectedList = rulesStorage.getProperty('selectedList');
|
|
if (!Array.isArray(selectedList)) {
|
|
selectedList = [];
|
|
rulesStorage.setProperty('selectedList', selectedList);
|
|
}
|
|
return selectedList;
|
|
}
|
|
|
|
function removeRulesFile(file) {
|
|
unselectRulesFile(file, true);
|
|
return rulesStorage.removeFile(file);
|
|
}
|
|
|
|
function renameRulesFile(file, newFile) {
|
|
if (!rulesStorage.renameFile(file, newFile)) {
|
|
return;
|
|
}
|
|
|
|
var selectedList = getSelectedRulesList();
|
|
var index = selectedList.indexOf(file);
|
|
if (index != -1) {
|
|
selectedList[index] = newFile;
|
|
rulesStorage.setProperty('selectedList', selectedList);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function addRulesFile(file, data) {
|
|
return rulesStorage.writeFile(file, data);
|
|
}
|
|
|
|
function getAllRulesFile() {
|
|
var list = rulesStorage.getFileList();
|
|
var selectedList = getSelectedRulesList();
|
|
list.forEach(function(file) {
|
|
file.selected = selectedList.indexOf(file.name) != -1;
|
|
});
|
|
return list;
|
|
}
|
|
|
|
function resetRulesIfResort(fromName, toName) {
|
|
var selectedList = getSelectedRulesList();
|
|
if (selectedList.indexOf(fromName) == -1 && selectedList.indexOf(toName) == -1) {
|
|
return;
|
|
}
|
|
parseRules();
|
|
}
|
|
|
|
exports.rules = {
|
|
recycleBin: rulesStorage.recycleBin,
|
|
enableBackRulesFirst: function(backRulesFirst) {
|
|
var curFlag = propertiesStorage.getProperty('backRulesFirst') === true;
|
|
if (curFlag !== backRulesFirst) {
|
|
propertiesStorage.setProperty('backRulesFirst', backRulesFirst);
|
|
parseRules();
|
|
}
|
|
},
|
|
moveTo: function(fromName, toName, clientId) {
|
|
if (rulesStorage.moveTo(fromName, toName)) {
|
|
resetRulesIfResort(fromName, toName);
|
|
config.setModified(clientId, true);
|
|
proxy.emit('rulesDataChange', 'move', fromName, toName);
|
|
return true;
|
|
}
|
|
},
|
|
get: function(file) {
|
|
return rulesStorage.readFile(file);
|
|
},
|
|
remove: function(file, clientId) {
|
|
if (removeRulesFile(file)) {
|
|
config.setModified(clientId, true);
|
|
proxy.emit('rulesDataChange', 'remove', file);
|
|
}
|
|
},
|
|
add: function(file, data, clientId) {
|
|
if (file !== 'Default' && addRulesFile(file, data)) {
|
|
config.setModified(clientId, true);
|
|
proxy.emit('rulesDataChange', 'add', file);
|
|
}
|
|
},
|
|
rename: function(file, newFile, clientId) {
|
|
if (renameRulesFile(file, newFile)) {
|
|
config.setModified(clientId, true);
|
|
proxy.emit('rulesDataChange', 'rename', file, newFile);
|
|
}
|
|
},
|
|
select: selectRulesFile,
|
|
unselect: unselectRulesFile,
|
|
list: getAllRulesFile,
|
|
getDefault: getDefaultRules,
|
|
setDefault: function(value, clientId) {
|
|
if (setDefaultRules(value)) {
|
|
config.setModified(clientId, true);
|
|
proxy.emit('rulesDataChange', 'add', 'Default');
|
|
}
|
|
},
|
|
enableDefault: enableDefaultRules,
|
|
disableDefault: disableDefaultRules,
|
|
defaultRulesIsDisabled: defaultRulesIsDisabled,
|
|
parseRules: parseRules,
|
|
clearSelection:clearSelection,
|
|
getSelectedList: getSelectedRulesList
|
|
};
|
|
|
|
|
|
/**
|
|
* values
|
|
*/
|
|
|
|
function addValuesFile(file, data) {
|
|
return valuesStorage.writeFile(file, data);
|
|
}
|
|
|
|
function indexOfUploadFiles(name) {
|
|
for (var i = 0, len = uploadFiles.length; i < len; i++) {
|
|
var file = uploadFiles[i];
|
|
if (file.name === name) {
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
exports.values = {
|
|
recycleBin: valuesStorage.recycleBin,
|
|
getUploadFiles: function() {
|
|
return uploadFiles;
|
|
},
|
|
download: function(name, res) {
|
|
if (!checkFilename(name)) {
|
|
return res.end();
|
|
}
|
|
res.download(path.join(LOCAL_FILES, name), name);
|
|
},
|
|
existsFile: function(name) {
|
|
return name && indexOfUploadFiles(name) !== -1;
|
|
},
|
|
LIMIMT_FILES_COUNT: MAX_FILENAME_LEN,
|
|
addUploadFile: function(options, callback) {
|
|
var name = options.name;
|
|
if (!checkFilename(name)) {
|
|
return callback();
|
|
}
|
|
if (uploadFiles.length >= MAX_FILENAME_LEN
|
|
&& indexOfUploadFiles(name) === -1) {
|
|
return callback(new Error('The number of uploaded files cannot exceed 60.'));
|
|
}
|
|
var content = '';
|
|
var base64 = options.base64;
|
|
var headers = options.headers;
|
|
|
|
if (headers && typeof headers === 'string') {
|
|
try {
|
|
content = Buffer.from(headers + '\r\n\r\n');
|
|
} catch (e) {
|
|
return callback();
|
|
}
|
|
}
|
|
|
|
if (base64 && typeof base64 === 'string') {
|
|
try {
|
|
base64 = Buffer.from(base64, 'base64');
|
|
content = content ? Buffer.concat([content, base64]) : base64;
|
|
} catch (e) {
|
|
return callback();
|
|
}
|
|
}
|
|
if (!content) {
|
|
return callback();
|
|
}
|
|
fs.writeFile(path.join(LOCAL_FILES, name), content, function(err) {
|
|
if (!err) {
|
|
var index = indexOfUploadFiles(name);
|
|
if (index !== -1) {
|
|
uploadFiles.splice(index, 1);
|
|
}
|
|
uploadFiles.unshift({
|
|
name: name,
|
|
date: Date.now()
|
|
});
|
|
}
|
|
callback(err);
|
|
});
|
|
},
|
|
removeUploadFile: function(name, callback) {
|
|
if (!checkFilename(name) || indexOfUploadFiles(name) === -1) {
|
|
return callback();
|
|
}
|
|
fs.unlink(path.join(LOCAL_FILES, name), function(err) {
|
|
var index = indexOfUploadFiles(name);
|
|
if (index === -1 || !err || err.code === 'ENOENT') {
|
|
if (index !== -1) {
|
|
uploadFiles.splice(index, 1);
|
|
}
|
|
return callback();
|
|
}
|
|
callback(err);
|
|
});
|
|
},
|
|
moveTo: function(fromName, toName, clientId) {
|
|
if (valuesStorage.moveTo(fromName, toName)) {
|
|
config.setModified(clientId);
|
|
proxy.emit('valuesDataChange', 'move', fromName, toName);
|
|
return true;
|
|
}
|
|
},
|
|
add: function(file, data, clientId) {
|
|
if (addValuesFile(file, data)) {
|
|
config.setModified(clientId);
|
|
proxy.emit('valuesDataChange', 'add', file);
|
|
}
|
|
},
|
|
get: function(file) {
|
|
return valuesStorage.readFile(file);
|
|
},
|
|
remove: function remove(file, clientId) {
|
|
if (valuesStorage.removeFile(file)) {
|
|
config.setModified(clientId);
|
|
proxy.emit('valuesDataChange', 'remove', file);
|
|
}
|
|
},
|
|
rename: function(file, newFile, clientId) {
|
|
if (valuesStorage.renameFile(file, newFile)) {
|
|
config.setModified(clientId);
|
|
proxy.emit('valuesDataChange', 'rename', file, newFile);
|
|
}
|
|
},
|
|
list: function list() {
|
|
var selectedFile = valuesStorage.getProperty('selectedFile');
|
|
var list = valuesStorage.getFileList();
|
|
if (selectedFile) {
|
|
list.forEach(function(file) {
|
|
file.selected = file.name == selectedFile;
|
|
});
|
|
}
|
|
return list;
|
|
},
|
|
select: function(file) {
|
|
typeof file == 'string' && valuesStorage.setProperty('selectedFile', file);
|
|
},
|
|
unselect: function() {
|
|
valuesStorage.removeProperty('selectedFile');
|
|
}
|
|
};
|
|
|
|
|
|
|
|
setTimeout(function getWhistleVersion() {
|
|
util.getLatestVersion(config.registry, function(ver) {
|
|
ver && propertiesStorage.writeFile('latestVersion', ver);
|
|
setTimeout(getWhistleVersion, INTERVAL);
|
|
});
|
|
}, 1000); //等待package的信息配置更新完成
|
|
|
|
/**
|
|
* properties
|
|
*/
|
|
var composerTimer;
|
|
function saveComposerHistory() {
|
|
composerTimer = null;
|
|
try {
|
|
propertiesStorage.writeFile('composerHistory', JSON.stringify(history));
|
|
} catch(e) {}
|
|
}
|
|
|
|
exports.properties = {
|
|
getLatestVersion: function() {
|
|
var version = propertiesStorage.readFile('latestVersion');
|
|
return typeof version === 'string' && version.length < 60 ? version : '';
|
|
},
|
|
isEnableCapture: function() {
|
|
if (config.multiEnv) {
|
|
return false;
|
|
}
|
|
if (config.isEnableCapture != null) {
|
|
return config.isEnableCapture;
|
|
}
|
|
return !!propertiesStorage.getProperty('interceptHttpsConnects');
|
|
},
|
|
setEnableCapture: function(enable) {
|
|
config.isEnableCapture = enable;
|
|
propertiesStorage.setProperty('interceptHttpsConnects', enable);
|
|
},
|
|
isEnableHttp2: function() {
|
|
if (config.isEnableHttp2 != null) {
|
|
return config.isEnableHttp2;
|
|
}
|
|
return propertiesStorage.getProperty('enableHttp2') !== false;
|
|
},
|
|
setEnableHttp2: function(enable) {
|
|
config.isEnableHttp2 = enable;
|
|
propertiesStorage.setProperty('enableHttp2', enable);
|
|
},
|
|
set: function(name, value) {
|
|
typeof name == 'string' ? propertiesStorage.setProperty(name, value) : propertiesStorage.setProperties(name);
|
|
},
|
|
remove: function(name) {
|
|
propertiesStorage.removeProperty(name);
|
|
},
|
|
get: function(name) {
|
|
return propertiesStorage.getProperty(name);
|
|
},
|
|
getHistory: function() {
|
|
return history;
|
|
},
|
|
addHistory: function(data) {
|
|
if (!data.needResponse || !checkHistory(data)) {
|
|
return;
|
|
}
|
|
var url = data.url;
|
|
var method = data.method;
|
|
var headers = data.headers;
|
|
var body = data.body;
|
|
var result = {
|
|
date: Date.now(),
|
|
useH2: data.useH2,
|
|
url: url.length > MAX_URL_LEN ? url.substring(0, MAX_URL_LEN) : url,
|
|
method: method.length > MAX_METHOD_LEN ? method.substring(0, MAX_METHOD_LEN) : method,
|
|
headers: headers.length > MAX_HEADERS_LEN ? headers.substring(0, MAX_HEADERS_LEN) : headers,
|
|
body: body.length > MAX_BODY_LEN ? body.substring(0, MAX_BODY_LEN) : body,
|
|
isHexText: !!data.isHexText
|
|
};
|
|
for (var i = 0, len = history.length; i < len; i++) {
|
|
var item = history[i];
|
|
if (item.url === result.url && item.method === result.method
|
|
&& item.headers === result.headers && item.body === result.body && !item.useH2 !== result.useH2) {
|
|
history.splice(i, 1);
|
|
break;
|
|
}
|
|
}
|
|
history.unshift(result);
|
|
var overflow = history.length - MAX_HISTORY_LEN;
|
|
if (overflow > 0) {
|
|
history.splice(MAX_HISTORY_LEN, overflow);
|
|
}
|
|
if (!composerTimer) {
|
|
composerTimer = setTimeout(saveComposerHistory, 2000);
|
|
}
|
|
}
|
|
};
|
|
|
|
function getRules(rules) {
|
|
if (Array.isArray(rules)) {
|
|
return rules.join('\n');
|
|
}
|
|
if (typeof rules === 'string') {
|
|
return rules;
|
|
}
|
|
}
|
|
|
|
exports.addRules = function(rules, replace, clientId) {
|
|
if (rules == null) {
|
|
return;
|
|
}
|
|
replace = replace !== false;
|
|
var hasChanged;
|
|
if (Array.isArray(rules) || typeof rules == 'string') {
|
|
if (replace !== false || !getDefaultRules()) {
|
|
hasChanged = setDefaultRules(getRules(rules));
|
|
}
|
|
} else {
|
|
var keys = Object.keys(rules).slice(keys, MAX_COUNT_BY_IMPORT);
|
|
keys.forEach(function(name) {
|
|
var item = name ? rules[name] : null;
|
|
if (Array.isArray(item) || typeof item === 'string') {
|
|
item = { rules: item };
|
|
}
|
|
if (item) {
|
|
item.rules = getRules(item.rules);
|
|
if (typeof item.replace !== 'boolean') {
|
|
item.replace = replace;
|
|
}
|
|
if (name === 'Default') {
|
|
if (typeof item.rules === 'string'
|
|
&& (item.replace !== false || !getDefaultRules())) {
|
|
if (setDefaultRules(item.rules)) {
|
|
hasChanged = true;
|
|
}
|
|
}
|
|
if (item.enable) {
|
|
enableDefaultRules();
|
|
} else if (item.enable === false) {
|
|
disableDefaultRules();
|
|
}
|
|
} else {
|
|
if (typeof item.rules === 'string'
|
|
&& (item.replace !== false || !rulesStorage.existsFile(name))) {
|
|
if (addRulesFile(name, item.rules)) {
|
|
hasChanged = true;
|
|
}
|
|
}
|
|
if (item.enable) {
|
|
selectRulesFile(name);
|
|
} else if (item.enable === false) {
|
|
unselectRulesFile(name);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
if (hasChanged) {
|
|
config.setModified(clientId, true);
|
|
}
|
|
};
|
|
|
|
exports.addValues = function(values, replace, clientId) {
|
|
if (values == null || Array.isArray(values)) {
|
|
return;
|
|
}
|
|
replace = replace !== false;
|
|
var hasChanged;
|
|
var keys = Object.keys(values).slice(0, MAX_COUNT_BY_IMPORT);
|
|
keys.forEach(function(name) {
|
|
if (/\s/.test(name) || (!replace && valuesStorage.existsFile(name))) {
|
|
return;
|
|
}
|
|
var value = name ? values[name] : null;
|
|
if (value == null) {
|
|
return;
|
|
}
|
|
if (typeof value !== 'string') {
|
|
value = JSON.stringify(value, null, ' ');
|
|
}
|
|
if (addValuesFile(name, value)) {
|
|
hasChanged = true;
|
|
}
|
|
});
|
|
if (hasChanged) {
|
|
config.setModified(clientId);
|
|
}
|
|
};
|
|
|
|
exports.setup = function(p) {
|
|
proxy = p;
|
|
};
|