improve backup file output for rules: array instead of one huge string

pull/2/head
Raymond Hill 8 years ago
parent 1a5d7e400d
commit 749e8d5cc4
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2

@ -1,7 +1,7 @@
/******************************************************************************* /*******************************************************************************
uMatrix - a Chromium browser extension to black/white list requests. uMatrix - a Chromium browser extension to black/white list requests.
Copyright (C) 2014-2017 Raymond Hill Copyright (C) 2014-2018 Raymond Hill
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -20,7 +20,6 @@
*/ */
/* global punycode */ /* global punycode */
/* jshint bitwise: false */
'use strict'; 'use strict';
@ -31,13 +30,11 @@
/******************************************************************************/ /******************************************************************************/
var µm = µMatrix; var µm = µMatrix;
var magicId = 'axyorpwxtmnf'; var selfieVersion = 1;
var uniqueIdGenerator = 1;
/******************************************************************************/ /******************************************************************************/
var Matrix = function() { var Matrix = function() {
this.id = uniqueIdGenerator++;
this.reset(); this.reset();
this.sourceRegister = ''; this.sourceRegister = '';
this.decomposedSourceRegister = ['']; this.decomposedSourceRegister = [''];
@ -103,10 +100,10 @@ var switchStateToNameMap = new Map([
[ 2, 'false' ] [ 2, 'false' ]
]); ]);
var nameToSwitchStateMap = { var nameToSwitchStateMap = new Map([
'true': 1, [ 'true', 1 ],
'false': 2 [ 'false', 2 ]
}; ]);
/******************************************************************************/ /******************************************************************************/
@ -594,15 +591,13 @@ Matrix.prototype.extractAllSourceHostnames = (function() {
/******************************************************************************/ /******************************************************************************/
Matrix.prototype.toString = function() { Matrix.prototype.toArray = function() {
var out = []; let out = [];
var rule, type, switchName, val; for ( let rule of this.rules.keys() ) {
var srcHostname, desHostname; let srcHostname = this.srcHostnameFromRule(rule);
for ( rule of this.rules.keys() ) { let desHostname = this.desHostnameFromRule(rule);
srcHostname = this.srcHostnameFromRule(rule); for ( let type of typeBitOffsets.keys() ) {
desHostname = this.desHostnameFromRule(rule); let val = this.evaluateCell(srcHostname, desHostname, type);
for ( type of typeBitOffsets.keys() ) {
val = this.evaluateCell(srcHostname, desHostname, type);
if ( val === 0 ) { continue; } if ( val === 0 ) { continue; }
out.push( out.push(
punycode.toUnicode(srcHostname) + ' ' + punycode.toUnicode(srcHostname) + ' ' +
@ -612,176 +607,140 @@ Matrix.prototype.toString = function() {
); );
} }
} }
for ( srcHostname of this.switches.keys() ) { for ( let srcHostname of this.switches.keys() ) {
for ( switchName of switchBitOffsets.keys() ) { for ( let switchName of switchBitOffsets.keys() ) {
val = this.evaluateSwitch(switchName, srcHostname); let val = this.evaluateSwitch(switchName, srcHostname);
if ( val === 0 ) { continue; } if ( val === 0 ) { continue; }
out.push(switchName + ': ' + srcHostname + ' ' + switchStateToNameMap.get(val)); out.push(
switchName + ': ' +
srcHostname + ' ' +
switchStateToNameMap.get(val)
);
}
} }
return out;
};
/******************************************************************************/
Matrix.prototype.fromArray = function(lines, append) {
let matrix = append === true ? this : new Matrix();
for ( let line of lines ) {
matrix.fromLine(line);
} }
return out.sort().join('\n'); if ( append !== true ) {
this.assign(matrix);
}
this.modifiedTime = Date.now();
};
/******************************************************************************/
Matrix.prototype.toString = function() {
return this.toArray().join('\n');
}; };
/******************************************************************************/ /******************************************************************************/
Matrix.prototype.fromString = function(text, append) { Matrix.prototype.fromString = function(text, append) {
var matrix = append ? this : new Matrix(); let matrix = append === true ? this : new Matrix();
var textEnd = text.length; let textEnd = text.length;
var lineBeg = 0, lineEnd; let lineBeg = 0;
var line, pos;
var fields, fieldVal;
var switchName;
var srcHostname = '';
var desHostname = '';
var type, state;
while ( lineBeg < textEnd ) { while ( lineBeg < textEnd ) {
lineEnd = text.indexOf('\n', lineBeg); let lineEnd = text.indexOf('\n', lineBeg);
if ( lineEnd < 0 ) { if ( lineEnd === -1 ) {
lineEnd = text.indexOf('\r', lineBeg); lineEnd = text.indexOf('\r', lineBeg);
if ( lineEnd < 0 ) { if ( lineEnd === -1 ) {
lineEnd = textEnd; lineEnd = textEnd;
} }
} }
line = text.slice(lineBeg, lineEnd).trim(); let line = text.slice(lineBeg, lineEnd).trim();
lineBeg = lineEnd + 1; lineBeg = lineEnd + 1;
pos = line.indexOf('# '); let pos = line.indexOf('# ');
if ( pos !== -1 ) { if ( pos !== -1 ) {
line = line.slice(0, pos).trim(); line = line.slice(0, pos).trim();
} }
if ( line === '' ) { if ( line === '' ) { continue; }
continue;
}
fields = line.split(/\s+/);
// Less than 2 fields makes no sense matrix.fromLine(line);
if ( fields.length < 2 ) {
continue;
} }
fieldVal = fields[0]; if ( append !== true ) {
this.assign(matrix);
// Special directives:
// title
pos = fieldVal.indexOf('title:');
if ( pos !== -1 ) {
// TODO
continue;
}
// Name
pos = fieldVal.indexOf('name:');
if ( pos !== -1 ) {
// TODO
continue;
} }
// Switch on/off this.modifiedTime = Date.now();
};
// `switch:` srcHostname state /******************************************************************************/
// state = [`true`, `false`]
switchName = '';
if ( fieldVal === 'switch:' || fieldVal === 'matrix:' ) {
fieldVal = 'matrix-off:';
}
pos = fieldVal.indexOf(':');
if ( pos !== -1 ) {
switchName = fieldVal.slice(0, pos);
}
if ( switchBitOffsets.has(switchName) ) {
srcHostname = punycode.toASCII(fields[1]);
// No state field: reject // https://github.com/gorhill/uMatrix/issues/759
fieldVal = fields[2]; // Backward compatibility: 'plugin' => 'media'
if ( fieldVal === null ) {
continue;
}
// Unknown state: reject
if ( nameToSwitchStateMap.hasOwnProperty(fieldVal) === false ) {
continue;
}
// Backward compatibility: Matrix.prototype.fromLine = function(line) {
// `chromium-behind-the-scene` is now `behind-the-scene` let fields = line.split(/\s+/);
if ( srcHostname === 'chromium-behind-the-scene' ) { if ( fields.length < 3 ) { return false; }
srcHostname = 'behind-the-scene'; let field0 = fields[0];
}
matrix.setSwitch(switchName, srcHostname, nameToSwitchStateMap[fieldVal]); // Switches
continue; let pos = field0.indexOf(':');
if ( pos !== -1 ) {
let switchName = field0.slice(0, pos);
let srcHostname = punycode.toASCII(fields[1]);
let state = fields[2];
if (
switchBitOffsets.has(switchName) === false ||
nameToSwitchStateMap.has(state) === false
) {
return false;
} }
this.setSwitch(
// Unknown directive switchName,
if ( fieldVal.endsWith(':') ) { srcHostname,
continue; nameToSwitchStateMap.get(state)
);
return true;
} }
// Valid rule syntax: // Rules
if ( fields.length < 4 ) { return false; }
// srcHostname desHostname [type [state]] let srcHostname = punycode.toASCII(fields[0]);
// type = a valid request type let desHostname = punycode.toASCII(fields[1]);
// state = [`block`, `allow`, `inherit`] let type = fields[2];
// srcHostname desHostname type if ( type !== undefined ) {
// type = a valid request type
// state = `allow`
// srcHostname desHostname
// type = `*`
// state = `allow`
// Lines with invalid syntax silently ignored
srcHostname = punycode.toASCII(fields[0]);
desHostname = punycode.toASCII(fields[1]);
fieldVal = fields[2];
if ( fieldVal !== undefined ) {
type = fieldVal;
// https://github.com/gorhill/uMatrix/issues/759
// Backward compatibility.
if ( type === 'plugin' ) { if ( type === 'plugin' ) {
type = 'media'; type = 'media';
} } else if ( typeBitOffsets.has(type) === false ) {
// Unknown type: reject return false;
if ( typeBitOffsets.has(type) === false ) {
continue;
} }
} else { } else {
type = '*'; type = '*';
} }
fieldVal = fields[3]; let state = fields[3];
if ( fieldVal !== undefined ) { if ( state !== undefined ) {
// Unknown state: reject if ( nameToStateMap.hasOwnProperty(state) === false ) {
if ( nameToStateMap.hasOwnProperty(fieldVal) === false ) { return false;
continue;
} }
state = nameToStateMap[fieldVal]; state = nameToStateMap[state];
} else { } else {
state = 2; state = 2;
} }
matrix.setCell(srcHostname, desHostname, type, state); this.setCell(srcHostname, desHostname, type, state);
} return true;
if ( !append ) {
this.assign(matrix);
}
this.modifiedTime = Date.now();
}; };
/******************************************************************************/ /******************************************************************************/
Matrix.prototype.toSelfie = function() { Matrix.prototype.toSelfie = function() {
return { return {
magicId: magicId, version: selfieVersion,
switches: Array.from(this.switches), switches: Array.from(this.switches),
rules: Array.from(this.rules) rules: Array.from(this.rules)
}; };
@ -790,7 +749,7 @@ Matrix.prototype.toSelfie = function() {
/******************************************************************************/ /******************************************************************************/
Matrix.prototype.fromSelfie = function(selfie) { Matrix.prototype.fromSelfie = function(selfie) {
if ( selfie.magicId !== magicId ) { return false; } if ( selfie.version !== selfieVersion ) { return false; }
this.switches = new Map(selfie.switches); this.switches = new Map(selfie.switches);
this.rules = new Map(selfie.rules); this.rules = new Map(selfie.rules);
this.modifiedTime = Date.now(); this.modifiedTime = Date.now();

@ -864,7 +864,7 @@ var onMessage = function(request, sender, callback) {
version: vAPI.app.version, version: vAPI.app.version,
when: Date.now(), when: Date.now(),
settings: µm.userSettings, settings: µm.userSettings,
rules: µm.pMatrix.toString(), rules: µm.pMatrix.toArray().sort(),
rawSettings: µm.rawSettings rawSettings: µm.rawSettings
}; };
break; break;

@ -242,22 +242,27 @@
/******************************************************************************/ /******************************************************************************/
µMatrix.saveMatrix = function() { µMatrix.saveMatrix = function() {
µMatrix.XAL.keyvalSetOne('userMatrix', this.pMatrix.toString()); vAPI.storage.set({ userMatrix: this.pMatrix.toArray() });
}; };
µMatrix.loadMatrix = function(callback) { µMatrix.loadMatrix = function(callback) {
if ( typeof callback !== 'function' ) { if ( typeof callback !== 'function' ) {
callback = this.noopFunc; callback = this.noopFunc;
} }
var µm = this; let µm = this;
var onLoaded = function(bin) { let onLoaded = function(bin) {
if ( bin.hasOwnProperty('userMatrix') ) { if ( bin instanceof Object === false ) {
return callback();
}
if ( typeof bin.userMatrix === 'string' ) {
µm.pMatrix.fromString(bin.userMatrix); µm.pMatrix.fromString(bin.userMatrix);
} else if ( Array.isArray(bin.userMatrix) ) {
µm.pMatrix.fromArray(bin.userMatrix);
}
µm.tMatrix.assign(µm.pMatrix); µm.tMatrix.assign(µm.pMatrix);
callback(); callback();
}
}; };
this.XAL.keyvalGetOne('userMatrix', onLoaded); vAPI.storage.get('userMatrix', onLoaded);
}; };
/******************************************************************************/ /******************************************************************************/

Loading…
Cancel
Save