|
@ -19,7 +19,7 @@ |
|
|
Home: https://github.com/gorhill/uMatrix
|
|
|
Home: https://github.com/gorhill/uMatrix
|
|
|
*/ |
|
|
*/ |
|
|
|
|
|
|
|
|
/* global µMatrix */ |
|
|
|
|
|
|
|
|
/* global punycode, µMatrix */ |
|
|
/* jshint bitwise: false */ |
|
|
/* jshint bitwise: false */ |
|
|
|
|
|
|
|
|
/******************************************************************************/ |
|
|
/******************************************************************************/ |
|
@ -68,6 +68,23 @@ var typeBitOffsets = { |
|
|
'other': 16 |
|
|
'other': 16 |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
var stateToNameMap = { |
|
|
|
|
|
'1': 'block', |
|
|
|
|
|
'2': 'allow', |
|
|
|
|
|
'3': 'inherit' |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
var nameToStateMap = { |
|
|
|
|
|
'block': 1, |
|
|
|
|
|
'allow': 2, |
|
|
|
|
|
'inherit': 3 |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
var nameToSwitchMap = { |
|
|
|
|
|
'on': true, |
|
|
|
|
|
'off': false |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
/******************************************************************************/ |
|
|
/******************************************************************************/ |
|
|
|
|
|
|
|
|
var columnHeaders = (function() { |
|
|
var columnHeaders = (function() { |
|
@ -233,6 +250,7 @@ Matrix.prototype.evaluateCellZ = function(srcHostname, desHostname, type) { |
|
|
return v; |
|
|
return v; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
// TODO: external rules? (for presets)
|
|
|
pos = s.indexOf('.'); |
|
|
pos = s.indexOf('.'); |
|
|
if ( pos !== -1 ) { |
|
|
if ( pos !== -1 ) { |
|
|
s = s.slice(pos + 1); |
|
|
s = s.slice(pos + 1); |
|
@ -406,6 +424,175 @@ Matrix.prototype.extractAllSourceHostnames = function() { |
|
|
|
|
|
|
|
|
/******************************************************************************/ |
|
|
/******************************************************************************/ |
|
|
|
|
|
|
|
|
|
|
|
Matrix.prototype.toString = function() { |
|
|
|
|
|
var out = []; |
|
|
|
|
|
var rule, type, val; |
|
|
|
|
|
var srcHostname, desHostname; |
|
|
|
|
|
for ( rule in this.rules ) { |
|
|
|
|
|
if ( this.rules.hasOwnProperty(rule) === false ) { |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
srcHostname = this.srcHostnameFromRule(rule); |
|
|
|
|
|
desHostname = this.desHostnameFromRule(rule); |
|
|
|
|
|
for ( type in typeBitOffsets ) { |
|
|
|
|
|
if ( typeBitOffsets.hasOwnProperty(type) === false ) { |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
val = this.evaluateCell(srcHostname, desHostname, type); |
|
|
|
|
|
if ( val === 0 ) { |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
out.push(srcHostname + ' ' + desHostname + ' ' + type + ' ' + stateToNameMap[val]); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
for ( srcHostname in this.switchedOn ) { |
|
|
|
|
|
if ( this.switchedOn.hasOwnProperty(srcHostname) === false ) { |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
val = this.switchedOn[srcHostname] ? 'on' : 'off'; |
|
|
|
|
|
out.push(srcHostname + ' switch: ' + val); |
|
|
|
|
|
} |
|
|
|
|
|
return out.sort().join('\n'); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************/ |
|
|
|
|
|
|
|
|
|
|
|
Matrix.prototype.fromString = function(text) { |
|
|
|
|
|
var textEnd = text.length; |
|
|
|
|
|
var lineBeg = 0, lineEnd; |
|
|
|
|
|
var line, pos; |
|
|
|
|
|
var fields, nextField, fieldVal; |
|
|
|
|
|
var srcHostname = ''; |
|
|
|
|
|
var desHostname = ''; |
|
|
|
|
|
var type, state; |
|
|
|
|
|
|
|
|
|
|
|
while ( lineBeg < textEnd ) { |
|
|
|
|
|
lineEnd = text.indexOf('\n', lineBeg); |
|
|
|
|
|
if ( lineEnd < 0 ) { |
|
|
|
|
|
lineEnd = text.indexOf('\r', lineBeg); |
|
|
|
|
|
if ( lineEnd < 0 ) { |
|
|
|
|
|
lineEnd = textEnd; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
line = text.slice(lineBeg, lineEnd).trim(); |
|
|
|
|
|
lineBeg = lineEnd + 1; |
|
|
|
|
|
|
|
|
|
|
|
pos = line.indexOf('# '); |
|
|
|
|
|
if ( pos !== -1 ) { |
|
|
|
|
|
line = line.slice(0, pos).trim(); |
|
|
|
|
|
} |
|
|
|
|
|
if ( line === '' ) { |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fields = line.split(/\s+/); |
|
|
|
|
|
|
|
|
|
|
|
// Special directives:
|
|
|
|
|
|
|
|
|
|
|
|
// title
|
|
|
|
|
|
pos = fields[0].indexOf('title:'); |
|
|
|
|
|
if ( pos !== -1 ) { |
|
|
|
|
|
// TODO
|
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Name
|
|
|
|
|
|
pos = fields[0].indexOf('name:'); |
|
|
|
|
|
if ( pos !== -1 ) { |
|
|
|
|
|
// TODO
|
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Valid rule syntax:
|
|
|
|
|
|
|
|
|
|
|
|
// srcHostname desHostname type state
|
|
|
|
|
|
// type = a valid request type
|
|
|
|
|
|
// state = [`block`, `allow`, `inherit`]
|
|
|
|
|
|
|
|
|
|
|
|
// srcHostname desHostname type
|
|
|
|
|
|
// type = a valid request type
|
|
|
|
|
|
// state = `allow`
|
|
|
|
|
|
|
|
|
|
|
|
// srcHostname desHostname
|
|
|
|
|
|
// type = `*`
|
|
|
|
|
|
// state = `allow`
|
|
|
|
|
|
|
|
|
|
|
|
// desHostname
|
|
|
|
|
|
// srcHostname from a previous line
|
|
|
|
|
|
// type = `*`
|
|
|
|
|
|
// state = `allow`
|
|
|
|
|
|
|
|
|
|
|
|
// srcHostname `switch:` state
|
|
|
|
|
|
// state = [`on`, `off`]
|
|
|
|
|
|
|
|
|
|
|
|
// `switch:` state
|
|
|
|
|
|
// srcHostname from a previous line
|
|
|
|
|
|
// state = [`on`, `off`]
|
|
|
|
|
|
|
|
|
|
|
|
// Lines with invalid syntax silently ignored
|
|
|
|
|
|
|
|
|
|
|
|
if ( fields.length === 1 ) { |
|
|
|
|
|
// Can't infer srcHostname: reject
|
|
|
|
|
|
if ( srcHostname === '' ) { |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
desHostname = punycode.toASCII(fields[0]); |
|
|
|
|
|
nextField = 1; |
|
|
|
|
|
} else { |
|
|
|
|
|
srcHostname = punycode.toASCII(fields[0]); |
|
|
|
|
|
desHostname = punycode.toASCII(fields[1]); |
|
|
|
|
|
nextField = 2; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fieldVal = fields[nextField]; |
|
|
|
|
|
nextField += 1; |
|
|
|
|
|
|
|
|
|
|
|
// Special rule: switch on/off
|
|
|
|
|
|
|
|
|
|
|
|
if ( desHostname === 'switch:' ) { |
|
|
|
|
|
// No state field: reject
|
|
|
|
|
|
if ( fieldVal === null ) { |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
// Unknown state: reject
|
|
|
|
|
|
if ( nameToSwitchMap.hasOwnProperty(fieldVal) === false ) { |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
this.setSwitch(srcHostname, nameToSwitchMap[fieldVal]); |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Standard rule
|
|
|
|
|
|
|
|
|
|
|
|
if ( fieldVal !== null ) { |
|
|
|
|
|
type = fieldVal; |
|
|
|
|
|
// Unknown type: reject
|
|
|
|
|
|
if ( typeBitOffsets.hasOwnProperty(type) === false ) { |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
type = '*'; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fieldVal = fields[nextField]; |
|
|
|
|
|
nextField += 1; |
|
|
|
|
|
|
|
|
|
|
|
if ( fieldVal !== null ) { |
|
|
|
|
|
// Unknown state: reject
|
|
|
|
|
|
if ( nameToStateMap.hasOwnProperty(fieldVal) === false ) { |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
state = nameToStateMap[fieldVal]; |
|
|
|
|
|
} else { |
|
|
|
|
|
state = 2; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
this.setCell(srcHostname, desHostname, type, state); |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************/ |
|
|
|
|
|
|
|
|
Matrix.prototype.toSelfie = function() { |
|
|
Matrix.prototype.toSelfie = function() { |
|
|
return { |
|
|
return { |
|
|
magicId: magicId, |
|
|
magicId: magicId, |
|
|