mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-08-25 18:19:22 +03:00
Get most valid Sieve scripts parsed properly
This commit is contained in:
parent
c254025d7a
commit
76ade5eac0
25 changed files with 175 additions and 71 deletions
|
|
@ -68,9 +68,10 @@ export class AddressTest extends TestCommand
|
|||
}
|
||||
return result
|
||||
+ (this.last ? ' :last' : (this.index.value ? ' :index ' + this.index : ''))
|
||||
+ (this.comparator ? ' :comparator ' + this.comparator : '')
|
||||
+ (this._comparator ? ' :comparator ' + this._comparator : '')
|
||||
+ ' ' + this.address_part
|
||||
+ ' ' + this.match_type
|
||||
+ (this._match_type ? ' ' + this._match_type : '')
|
||||
+ (this.relational_match ? ' ' + this.relational_match : '')
|
||||
+ ' ' + this.header_list
|
||||
+ ' ' + this.key_list;
|
||||
}
|
||||
|
|
@ -147,9 +148,10 @@ export class EnvelopeTest extends TestCommand
|
|||
toString()
|
||||
{
|
||||
return 'envelope'
|
||||
+ (this.comparator ? ' :comparator ' + this.comparator : '')
|
||||
+ (this._comparator ? ' :comparator ' + this._comparator : '')
|
||||
+ ' ' + this.address_part
|
||||
+ ' ' + this.match_type
|
||||
+ (this._match_type ? ' ' + this._match_type : '')
|
||||
+ (this.relational_match ? ' ' + this.relational_match : '')
|
||||
+ ' ' + this.envelope_part
|
||||
+ ' ' + this.key_list;
|
||||
}
|
||||
|
|
@ -279,8 +281,9 @@ export class HeaderTest extends TestCommand
|
|||
}
|
||||
return result
|
||||
+ (this.last ? ' :last' : (this.index.value ? ' :index ' + this.index : ''))
|
||||
+ (this.comparator ? ' :comparator ' + this.comparator : '')
|
||||
+ ' ' + this.match_type
|
||||
+ (this._comparator ? ' :comparator ' + this._comparator : '')
|
||||
+ (this._match_type ? ' ' + this._match_type : '')
|
||||
+ (this.relational_match ? ' ' + this.relational_match : '')
|
||||
+ ' ' + this.header_names
|
||||
+ ' ' + this.key_list;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,8 +22,9 @@ export class BodyTest extends TestCommand
|
|||
toString()
|
||||
{
|
||||
return 'body'
|
||||
+ (this.comparator ? ' :comparator ' + this.comparator : '')
|
||||
+ ' ' + this.match_type
|
||||
+ (this._comparator ? ' :comparator ' + this._comparator : '')
|
||||
+ (this._match_type ? ' ' + this._match_type : '')
|
||||
+ (this.relational_match ? ' ' + this.relational_match : '')
|
||||
+ ' ' + this.body_transform
|
||||
+ ' ' + this.key_list;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,8 +25,9 @@ export class EnvironmentTest extends TestCommand
|
|||
toString()
|
||||
{
|
||||
return 'environment'
|
||||
+ (this.comparator ? ' :comparator ' + this.comparator : '')
|
||||
+ ' ' + this.match_type
|
||||
+ (this._comparator ? ' :comparator ' + this._comparator : '')
|
||||
+ (this._match_type ? ' ' + this._match_type : '')
|
||||
+ (this.relational_match ? ' ' + this.relational_match : '')
|
||||
+ ' ' + this._name
|
||||
+ ' ' + this.key_list;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,8 +57,9 @@ export class StringTest extends TestCommand
|
|||
toString()
|
||||
{
|
||||
return 'string'
|
||||
+ ' ' + this.match_type
|
||||
+ (this.comparator ? ' :comparator ' + this.comparator : '')
|
||||
+ (this._match_type ? ' ' + this._match_type : '')
|
||||
+ (this.relational_match ? ' ' + this.relational_match : '')
|
||||
+ (this._comparator ? ' :comparator ' + this._comparator : '')
|
||||
+ ' ' + this.source
|
||||
+ ' ' + this.key_list;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,8 +79,9 @@ export class HasFlagTest extends TestCommand
|
|||
toString()
|
||||
{
|
||||
return 'hasflag'
|
||||
+ ' ' + this.match_type
|
||||
+ (this.comparator ? ' :comparator ' + this.comparator : '')
|
||||
+ (this._match_type ? ' ' + this._match_type : '')
|
||||
+ (this.relational_match ? ' ' + this.relational_match : '')
|
||||
+ (this._comparator ? ' :comparator ' + this._comparator : '')
|
||||
+ ' ' + this.variable_list
|
||||
+ ' ' + this.list_of_flags;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export class SpamTestTest extends TestCommand
|
|||
}
|
||||
|
||||
// get require() { return this.percent ? 'spamtestplus' : 'spamtest'; }
|
||||
get require() { return /:value|:count/.test(this.match_type) ? ['spamtestplus','relational'] : 'spamtestplus'; }
|
||||
get require() { return /:value|:count/.test(this._match_type) ? ['spamtestplus','relational'] : 'spamtestplus'; }
|
||||
|
||||
get value() { return this._value.value; }
|
||||
set value(v) { this._value.value = v; }
|
||||
|
|
@ -26,8 +26,9 @@ export class SpamTestTest extends TestCommand
|
|||
{
|
||||
return 'spamtest'
|
||||
+ (this.percent ? ' :percent' : '')
|
||||
+ (this.comparator ? ' :comparator ' + this.comparator : '')
|
||||
+ ' ' + this.match_type
|
||||
+ (this._comparator ? ' :comparator ' + this._comparator : '')
|
||||
+ (this._match_type ? ' ' + this._match_type : '')
|
||||
+ (this.relational_match ? ' ' + this.relational_match : '')
|
||||
+ ' ' + this._value;
|
||||
}
|
||||
|
||||
|
|
@ -51,7 +52,7 @@ export class VirusTestTest extends TestCommand
|
|||
this._value = new GrammarQuotedString; // 1 - 5
|
||||
}
|
||||
|
||||
get require() { return /:value/.test(this.match_type) ? ['virustest','relational'] : 'virustest'; }
|
||||
get require() { return ':value' == this._match_type ? ['virustest','relational'] : 'virustest'; }
|
||||
|
||||
get value() { return this._value.value; }
|
||||
set value(v) { this._value.value = v; }
|
||||
|
|
@ -59,8 +60,9 @@ export class VirusTestTest extends TestCommand
|
|||
toString()
|
||||
{
|
||||
return 'virustest'
|
||||
+ (this.comparator ? ' :comparator ' + this.comparator : '')
|
||||
+ ' ' + this.match_type
|
||||
+ (this._comparator ? ' :comparator ' + this._comparator : '')
|
||||
+ (this._match_type ? ' ' + this._match_type : '')
|
||||
+ (this.relational_match ? ' ' + this.relational_match : '')
|
||||
+ ' ' + this._value;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,8 +41,9 @@ export class DateTest extends TestCommand
|
|||
return 'date'
|
||||
+ (this.last ? ' :last' : (this.index.value ? ' :index ' + this.index : ''))
|
||||
+ (this.originalzone ? ' :originalzone' : (this._zone.length ? ' :zone ' + this._zone : ''))
|
||||
+ (this.comparator ? ' :comparator ' + this.comparator : '')
|
||||
+ ' ' + this.match_type
|
||||
+ (this._comparator ? ' :comparator ' + this._comparator : '')
|
||||
+ (this._match_type ? ' ' + this._match_type : '')
|
||||
+ (this.relational_match ? ' ' + this.relational_match : '')
|
||||
+ ' ' + this._header_name
|
||||
+ ' ' + this._date_part
|
||||
+ ' ' + this.key_list;
|
||||
|
|
@ -89,8 +90,9 @@ export class CurrentDateTest extends TestCommand
|
|||
{
|
||||
return 'currentdate'
|
||||
+ (this._zone.length ? ' :zone ' + this._zone : '')
|
||||
+ (this.comparator ? ' :comparator ' + this.comparator : '')
|
||||
+ ' ' + this.match_type
|
||||
+ (this._comparator ? ' :comparator ' + this._comparator : '')
|
||||
+ (this._match_type ? ' ' + this._match_type : '')
|
||||
+ (this.relational_match ? ' ' + this.relational_match : '')
|
||||
+ ' ' + this._date_part
|
||||
+ ' ' + this.key_list;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,8 +116,9 @@ export class NotifyMethodCapabilityTest extends TestCommand
|
|||
toString()
|
||||
{
|
||||
return 'valid_notify_method '
|
||||
+ (this.comparator ? ' :comparator ' + this.comparator : '')
|
||||
+ (this.match_type ? ' ' + this.match_type : '')
|
||||
+ (this._comparator ? ' :comparator ' + this._comparator : '')
|
||||
+ (this._match_type ? ' ' + this._match_type : '')
|
||||
+ (this.relational_match ? ' ' + this.relational_match : '')
|
||||
+ this._notification_uri
|
||||
+ this._notification_capability
|
||||
+ this.key_list;
|
||||
|
|
|
|||
|
|
@ -58,8 +58,9 @@ export class MetadataTest extends TestCommand
|
|||
toString()
|
||||
{
|
||||
return 'metadata '
|
||||
+ ' ' + this.match_type
|
||||
+ (this.comparator ? ' :comparator ' + this.comparator : '')
|
||||
+ ' ' + this._match_type
|
||||
+ (this.relational_match ? ' ' + this.relational_match : '')
|
||||
+ (this._comparator ? ' :comparator ' + this._comparator : '')
|
||||
+ ' ' + this._mailbox
|
||||
+ ' ' + this._annotation_name
|
||||
+ ' ' + this.key_list;
|
||||
|
|
@ -124,8 +125,9 @@ export class ServerMetadataTest extends TestCommand
|
|||
toString()
|
||||
{
|
||||
return 'servermetadata '
|
||||
+ ' ' + this.match_type
|
||||
+ (this.comparator ? ' :comparator ' + this.comparator : '')
|
||||
+ ' ' + this._match_type
|
||||
+ (this.relational_match ? ' ' + this.relational_match : '')
|
||||
+ (this._comparator ? ' :comparator ' + this._comparator : '')
|
||||
+ ' ' + this._annotation_name
|
||||
+ ' ' + this.key_list;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import {
|
|||
MULTILINE_DOTSTART
|
||||
} from 'Sieve/RegEx';
|
||||
|
||||
import { arrayToString, getMatchTypes } from 'Sieve/Utils';
|
||||
import { arrayToString, getMatchTypes, getComparators, koObserve } from 'Sieve/Utils';
|
||||
|
||||
/**
|
||||
* abstract
|
||||
|
|
@ -151,19 +151,65 @@ export /*abstract*/ class TestCommand extends GrammarCommand
|
|||
*/
|
||||
super(identifier);
|
||||
// Almost every test has a comparator and match_type, so define them here
|
||||
this.comparator = '';
|
||||
this.match_type = ':is';
|
||||
this._comparator = '';
|
||||
this._match_type = '';
|
||||
this.relational_match = ''; // GrammarQuotedString DQUOTE ( "gt" / "ge" / "lt" / "le" / "eq" / "ne" ) DQUOTE
|
||||
koObserve(this, 'match_type');
|
||||
}
|
||||
|
||||
get require() { return /:value|:count/.test(this._match_type) ? 'relational' : ''; }
|
||||
|
||||
get match_type()
|
||||
{
|
||||
return this._match_type;
|
||||
}
|
||||
set match_type(value)
|
||||
{
|
||||
// default?
|
||||
if (':is' == value) {
|
||||
value = '';
|
||||
}
|
||||
if (value.length && !getMatchTypes(0).includes(value)) {
|
||||
throw 'Unsupported match-type ' + value;
|
||||
}
|
||||
if (':list' == value) {
|
||||
this._comparator = '';
|
||||
}
|
||||
if (':count' != value && ':value' != value) {
|
||||
this.relational_match = '';
|
||||
}
|
||||
this._match_type = value;
|
||||
}
|
||||
|
||||
get comparator()
|
||||
{
|
||||
return this._comparator;
|
||||
}
|
||||
set comparator(value)
|
||||
{
|
||||
if (!(value instanceof GrammarQuotedString)) {
|
||||
value = new GrammarQuotedString(value);
|
||||
}
|
||||
// default?
|
||||
if (value.length && 'i;ascii-casemap' != value.value) {
|
||||
if (':list' == this._match_type) {
|
||||
throw 'Comparator not allowed when using :list';
|
||||
}
|
||||
if (!getComparators().includes(value.value)) {
|
||||
throw 'Unsupported comparator ' + value;
|
||||
}
|
||||
this._comparator = value;
|
||||
} else {
|
||||
this._comparator = '';
|
||||
}
|
||||
}
|
||||
|
||||
toString()
|
||||
{
|
||||
// https://datatracker.ietf.org/doc/html/rfc6134#section-2.3
|
||||
if (!getMatchTypes().includes(this.match_type)) {
|
||||
throw 'Unsupported match-type ' + this.match_type;
|
||||
}
|
||||
return (this.identifier
|
||||
+ (this.comparator ? ' :comparator ' + this.comparator : '')
|
||||
+ (this.match_type ? ' ' + this.match_type : '')
|
||||
+ (this._comparator ? ' :comparator ' + this._comparator : '')
|
||||
+ (this._match_type ? ' ' + this._match_type : '')
|
||||
+ (this.relational_match ? ' ' + this.relational_match : '')
|
||||
+ ' ' + arrayToString(this.arguments, ' ')).trim();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,18 +119,20 @@ export const parseScript = (script, name = 'script.sieve') => {
|
|||
let prev_arg = args[args.length-1];
|
||||
if (getMatchTypes(0).includes(arg)) {
|
||||
command.match_type = arg;
|
||||
} else if (':value' === prev_arg || ':count' === prev_arg) {
|
||||
// Sieve relational [RFC5231] match types
|
||||
/^(gt|ge|lt|le|eq|ne)$/.test(arg.value) || error('Invalid relational match-type ' + arg);
|
||||
command.match_type = prev_arg + ' ' + arg;
|
||||
} else if (getMatchTypes(0).includes(prev_arg)) {
|
||||
--args.length;
|
||||
// requires.push('relational');
|
||||
if (':value' === prev_arg || ':count' === prev_arg) {
|
||||
// Sieve relational [RFC5231] match types
|
||||
/^"(gt|ge|lt|le|eq|ne)"$/.test(arg) || error('Invalid relational match-type ' + arg);
|
||||
command.relational_match = arg;
|
||||
// requires.push('relational');
|
||||
return;
|
||||
}
|
||||
} else if (':comparator' === prev_arg) {
|
||||
command.comparator = arg;
|
||||
--args.length;
|
||||
} else {
|
||||
args.push(arg);
|
||||
}
|
||||
args.push(arg);
|
||||
},
|
||||
pushArgs = () => {
|
||||
if (args.length) {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ https://www.iana.org/assignments/sieve-extensions/sieve-extensions.xhtml
|
|||
- [ ] RFC3461 envelope-dsn / redirect-dsn
|
||||
- [x] RFC3894 copy
|
||||
- [ ] RFC4790 comparator-*
|
||||
- [ ] RFC5051 i;unicode-casemap
|
||||
- [x] RFC5173 body
|
||||
- [x] RFC5183 environment
|
||||
- [x] RFC5228 encoded-character / envelope / fileinto
|
||||
|
|
|
|||
|
|
@ -58,13 +58,45 @@ export const
|
|||
serverErrorDesc(text);
|
||||
},
|
||||
|
||||
getComparators = () => ['i;ascii-casemap'],
|
||||
koObserve = (obj, prop) => {
|
||||
// Object.getOwnPropertyNames(obj).forEach(prop => {
|
||||
// prop = prop.replace(/^_/, '');
|
||||
obj['ko_' + prop] = ko.computed({
|
||||
read: () => obj[prop],
|
||||
write: (v) => obj[prop] = v,
|
||||
pure:true
|
||||
});
|
||||
// });
|
||||
// Object.preventExtensions(obj);
|
||||
},
|
||||
|
||||
getComparators = (validOnly = 0) => {
|
||||
let result = [
|
||||
// Default
|
||||
'i;ascii-casemap',
|
||||
];
|
||||
if (capa.includes('relational') || !validOnly) {
|
||||
result.push('i;octet');
|
||||
}
|
||||
if (capa.includes('comparator-i;ascii-numeric') || !validOnly) {
|
||||
result.push('i;ascii-numeric');
|
||||
}
|
||||
if (capa.includes('comparator-i;unicode-casemap') || !validOnly) {
|
||||
result.push('i;unicode-casemap');
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
getMatchTypes = (validOnly = 1) => {
|
||||
let result = [':is',':contains',':matches'];
|
||||
// https://datatracker.ietf.org/doc/html/rfc6134#section-2.3
|
||||
// Only available for tests with a key_list property
|
||||
if (capa.includes('extlists') || !validOnly) {
|
||||
result.push(':list');
|
||||
}
|
||||
if (capa.includes('relational') || !validOnly) {
|
||||
result.push(':value');
|
||||
result.push(':count');
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue