diff --git a/dev/Sieve/Commands.js b/dev/Sieve/Commands.js index 234a35a98..49a2dabfa 100644 --- a/dev/Sieve/Commands.js +++ b/dev/Sieve/Commands.js @@ -102,6 +102,10 @@ export class FileIntoCommand extends GrammarCommand toString() { + // https://datatracker.ietf.org/doc/html/rfc3894 + // :copy + // https://datatracker.ietf.org/doc/html/rfc5490#section-3.2 + // :create return 'fileinto ' + this._mailbox + ';'; } @@ -137,6 +141,8 @@ export class RedirectCommand extends GrammarCommand toString() { + // https://datatracker.ietf.org/doc/html/rfc3894 + // :copy return 'redirect ' + this._address + ';'; } diff --git a/dev/Sieve/Extensions/rfc5173.js b/dev/Sieve/Extensions/rfc5173.js index 2cbefab87..31b299053 100644 --- a/dev/Sieve/Extensions/rfc5173.js +++ b/dev/Sieve/Extensions/rfc5173.js @@ -8,7 +8,7 @@ import { GrammarTest } from 'Sieve/Grammar'; -export class BodyCommand extends GrammarTest +export class BodyTest extends GrammarTest { constructor() { diff --git a/dev/Sieve/Extensions/rfc5183.js b/dev/Sieve/Extensions/rfc5183.js index eeb57d2e1..943f17f01 100644 --- a/dev/Sieve/Extensions/rfc5183.js +++ b/dev/Sieve/Extensions/rfc5183.js @@ -8,7 +8,7 @@ import { GrammarTest } from 'Sieve/Grammar'; -export class EnvironmentCommand extends GrammarTest +export class EnvironmentTest extends GrammarTest { constructor() { diff --git a/dev/Sieve/Extensions/rfc5229.js b/dev/Sieve/Extensions/rfc5229.js index d29bd1707..9076125d6 100644 --- a/dev/Sieve/Extensions/rfc5229.js +++ b/dev/Sieve/Extensions/rfc5229.js @@ -45,7 +45,7 @@ export class SetCommand extends GrammarCommand } } -export class StringCommand extends GrammarTest +export class StringTest extends GrammarTest { constructor() { diff --git a/dev/Sieve/Extensions/rfc5232.js b/dev/Sieve/Extensions/rfc5232.js index 2f9c319bf..3e5f378e3 100644 --- a/dev/Sieve/Extensions/rfc5232.js +++ b/dev/Sieve/Extensions/rfc5232.js @@ -63,7 +63,7 @@ export class RemoveFlagCommand extends FlagCommand { } -export class HasFlagCommand extends GrammarTest +export class HasFlagTest extends GrammarTest { constructor() { diff --git a/dev/Sieve/Extensions/rfc5235.js b/dev/Sieve/Extensions/rfc5235.js index 982da394c..0147159f7 100644 --- a/dev/Sieve/Extensions/rfc5235.js +++ b/dev/Sieve/Extensions/rfc5235.js @@ -8,7 +8,7 @@ import { GrammarTest } from 'Sieve/Grammar'; -export class SpamTestCommand extends GrammarTest +export class SpamTestTest extends GrammarTest { constructor() { @@ -41,7 +41,7 @@ export class SpamTestCommand extends GrammarTest } } -export class VirusTestCommand extends GrammarTest +export class VirusTestTest extends GrammarTest { constructor() { diff --git a/dev/Sieve/Extensions/rfc5260.js b/dev/Sieve/Extensions/rfc5260.js index 9911cb1c4..03d6b6d2b 100644 --- a/dev/Sieve/Extensions/rfc5260.js +++ b/dev/Sieve/Extensions/rfc5260.js @@ -9,7 +9,7 @@ import { GrammarTest } from 'Sieve/Grammar'; -export class DateCommand extends GrammarTest +export class DateTest extends GrammarTest { constructor() { @@ -62,7 +62,7 @@ export class DateCommand extends GrammarTest } } -export class CurrentDateCommand extends GrammarTest +export class CurrentDateTest extends GrammarTest { constructor() { diff --git a/dev/Sieve/Extensions/rfc5490.js b/dev/Sieve/Extensions/rfc5490.js new file mode 100644 index 000000000..aa9409de3 --- /dev/null +++ b/dev/Sieve/Extensions/rfc5490.js @@ -0,0 +1,151 @@ +/** + * https://tools.ietf.org/html/rfc5490 + */ + +import { + GrammarTest, + GrammarString, + GrammarStringList +} from 'Sieve/Grammar'; + +/** + * https://datatracker.ietf.org/doc/html/rfc5490#section-3.1 + */ +export class MailboxExistsTest extends GrammarTest +{ + constructor() + { + super(); + this.mailbox_names = new GrammarStringList; + } + + get require() { return 'mailbox'; } + + toString() + { + return 'mailboxexists ' + this.mailbox_names + ';'; + } + + pushArguments(args) + { + if (args[0] instanceof GrammarStringList) { + this.mailbox_names = args[0]; + } + } +} + +/** + * https://datatracker.ietf.org/doc/html/rfc5490#section-3.3 + */ +export class MetadataTest extends GrammarTest +{ + constructor() + { + super(); + this.mailbox = new GrammarString; + this.annotation_name = new GrammarString; + this.key_list = new GrammarStringList; + } + + get require() { return 'mboxmetadata'; } + + toString() + { + return 'metadata ' + + ' ' + this.match_type + + (this.comparator ? ' :comparator ' + this.comparator : '') + + ' ' + this.mailbox + + ' ' + this.annotation_name + + ' ' + this.key_list.toString(); + } + + pushArguments(args) + { + this.mailbox = args[args.length-3]; + this.annotation_name = args[args.length-2]; + this.key_list = args[args.length-1]; + } +} + +/** + * https://datatracker.ietf.org/doc/html/rfc5490#section-3.4 + */ +export class MetadataExistsTest extends GrammarTest +{ + constructor() + { + super(); + this.mailbox = new GrammarString; + this.annotation_names = new GrammarStringList; + } + + get require() { return 'mboxmetadata'; } + + toString() + { + return 'metadataexists ' + + ' ' + this.mailbox + + ' ' + this.annotation_names; + } + + pushArguments(args) + { + this.mailbox = args[args.length-2]; + this.annotation_names = args[args.length-1]; + } +} + +/** + * https://datatracker.ietf.org/doc/html/rfc5490#section-3.3 + */ +export class ServerMetadataTest extends GrammarTest +{ + constructor() + { + super(); + this.annotation_name = new GrammarString; + this.key_list = new GrammarStringList; + } + + get require() { return 'servermetadata'; } + + toString() + { + return 'servermetadata ' + + ' ' + this.match_type + + (this.comparator ? ' :comparator ' + this.comparator : '') + + ' ' + this.annotation_name + + ' ' + this.key_list.toString(); + } + + pushArguments(args) + { + this.annotation_name = args[args.length-2]; + this.key_list = args[args.length-1]; + } +} + +/** + * https://datatracker.ietf.org/doc/html/rfc5490#section-3.4 + */ +export class ServerMetadataExistsTest extends GrammarTest +{ + constructor() + { + super(); + this.annotation_names = new GrammarStringList; + } + + get require() { return 'servermetadata'; } + + toString() + { + return 'servermetadataexists ' + + ' ' + this.annotation_names; + } + + pushArguments(args) + { + this.annotation_names = args[args.length-1]; + } +} diff --git a/dev/Sieve/Grammar.js b/dev/Sieve/Grammar.js index 93381926c..b656b3ca8 100644 --- a/dev/Sieve/Grammar.js +++ b/dev/Sieve/Grammar.js @@ -231,7 +231,7 @@ export class GrammarTest { constructor(identifier) { - this.identifier = identifier || this.constructor.name.toLowerCase().replace('command', ''); + this.identifier = identifier || this.constructor.name.toLowerCase().replace(/test$/, ''); // Almost every test has a comparator and match_type, so define them here this.comparator = '', this.match_type = ':is', diff --git a/dev/Sieve/Parser.js b/dev/Sieve/Parser.js index 729d00a01..92e705d25 100644 --- a/dev/Sieve/Parser.js +++ b/dev/Sieve/Parser.js @@ -39,32 +39,32 @@ import { } from 'Sieve/Commands'; import { - AddressCommand, - AllOfCommand, - AnyOfCommand, - EnvelopeCommand, - ExistsCommand, - FalseCommand, - HeaderCommand, - NotCommand, - SizeCommand, - TrueCommand + AddressTest, + AllOfTest, + AnyOfTest, + EnvelopeTest, + ExistsTest, + FalseTest, + HeaderTest, + NotTest, + SizeTest, + TrueTest } from 'Sieve/Tests'; -import { BodyCommand } from 'Sieve/Extensions/rfc5173'; -import { EnvironmentCommand } from 'Sieve/Extensions/rfc5183'; -import { SetCommand, StringCommand } from 'Sieve/Extensions/rfc5229'; +import { BodyTest } from 'Sieve/Extensions/rfc5173'; +import { EnvironmentTest } from 'Sieve/Extensions/rfc5183'; +import { SetCommand, StringTest } from 'Sieve/Extensions/rfc5229'; import { VacationCommand } from 'Sieve/Extensions/rfc5230'; import { SetFlagCommand, AddFlagCommand, RemoveFlagCommand, - HasFlagCommand + HasFlagTest } from 'Sieve/Extensions/rfc5232'; -import { SpamTestCommand, VirusTestCommand } from 'Sieve/Extensions/rfc5235'; -import { DateCommand, CurrentDateCommand } from 'Sieve/Extensions/rfc5260'; +import { SpamTestTest, VirusTestTest } from 'Sieve/Extensions/rfc5235'; +import { DateTest, CurrentDateTest } from 'Sieve/Extensions/rfc5260'; import { AddHeaderCommand, DeleteHeaderCommand } from 'Sieve/Extensions/rfc5293'; import { @@ -72,6 +72,12 @@ import { RejectCommand } from 'Sieve/Extensions/rfc5429'; +import { + MailboxExistsTest, + MetadataTest, + MetadataExistsTest +} from 'Sieve/Extensions/rfc5490'; + import { IncludeCommand, ReturnCommand @@ -92,42 +98,46 @@ const keep: KeepCommand, redirect: RedirectCommand, // Test commands - address: AddressCommand, - allof: AllOfCommand, - anyof: AnyOfCommand, - envelope: EnvelopeCommand, - exists: ExistsCommand, - false: FalseCommand, - header: HeaderCommand, - not: NotCommand, - size: SizeCommand, - true: TrueCommand, + address: AddressTest, + allof: AllOfTest, + anyof: AnyOfTest, + envelope: EnvelopeTest, + exists: ExistsTest, + false: FalseTest, + header: HeaderTest, + not: NotTest, + size: SizeTest, + true: TrueTest, // rfc5173 - body: BodyCommand, + body: BodyTest, // rfc5183 - environment: EnvironmentCommand, + environment: EnvironmentTest, // rfc5229 set: SetCommand, - string: StringCommand, + string: StringTest, // rfc5230 vacation: VacationCommand, // rfc5232 setflag: SetFlagCommand, addflag: AddFlagCommand, removeflag: RemoveFlagCommand, - hasflag: HasFlagCommand, + hasflag: HasFlagTest, // rfc5235 - spamtest: SpamTestCommand, - virustest: VirusTestCommand, + spamtest: SpamTestTest, + virustest: VirusTestTest, // rfc5260 - date: DateCommand, - currentdate: CurrentDateCommand, + date: DateTest, + currentdate: CurrentDateTest, // rfc5293 AddHeaderCommand, DeleteHeaderCommand, // rfc5429 ereject: ErejectCommand, reject: RejectCommand, + // rfc5490 + mailboxexists: MailboxExistsTest, + metadata: MetadataTest, + metadataexists: MetadataExistsTest, // rfc6609 include: IncludeCommand, return: ReturnCommand @@ -237,14 +247,14 @@ export const parseScript = (script, name = 'script.sieve') => { new_command = new ConditionalCommand(value); } else if (Commands[value]) { if ('allof' === value || 'anyof' === value) { -// (command instanceof ConditionalCommand || command instanceof NotCommand) || error('Test-list not in conditional'); +// (command instanceof ConditionalCommand || command instanceof NotTest) || error('Test-list not in conditional'); } new_command = new Commands[value](); } else { console.error('Unknown command: ' + value); if (command && ( command instanceof ConditionalCommand - || command instanceof NotCommand + || command instanceof NotTest || command.tests instanceof GrammarTestList)) { new_command = new GrammarTest(value); } else { @@ -253,7 +263,7 @@ export const parseScript = (script, name = 'script.sieve') => { } if (new_command instanceof GrammarTest) { - if (command instanceof ConditionalCommand || command instanceof NotCommand) { + if (command instanceof ConditionalCommand || command instanceof NotTest) { // if/elsif/else new_command // not new_command command.test = new_command; diff --git a/dev/Sieve/README.md b/dev/Sieve/README.md index ec8173089..2e7e4946c 100644 --- a/dev/Sieve/README.md +++ b/dev/Sieve/README.md @@ -18,7 +18,7 @@ https://www.iana.org/assignments/sieve-extensions/sieve-extensions.xhtml - [x] RFC5429 ereject / reject - [ ] RFC5435 enotify - [ ] RFC5463 ihave -- [ ] RFC5490 mailbox / mboxmetadata / servermetadata +- [x] RFC5490 mailbox / mboxmetadata / servermetadata - [ ] RFC5703 enclose / extracttext / foreverypart / mime / replace - [ ] RFC6131 vacation-seconds - [ ] RFC6134 extlists diff --git a/dev/Sieve/Tests.js b/dev/Sieve/Tests.js index 70c2e2487..30949f0ed 100644 --- a/dev/Sieve/Tests.js +++ b/dev/Sieve/Tests.js @@ -18,7 +18,7 @@ const /** * https://tools.ietf.org/html/rfc5228#section-5.1 */ -export class AddressCommand extends GrammarTest +export class AddressTest extends GrammarTest { constructor() { @@ -69,7 +69,7 @@ export class AddressCommand extends GrammarTest /** * https://tools.ietf.org/html/rfc5228#section-5.2 */ -export class AllOfCommand extends GrammarTest +export class AllOfTest extends GrammarTest { constructor() { @@ -86,7 +86,7 @@ export class AllOfCommand extends GrammarTest /** * https://tools.ietf.org/html/rfc5228#section-5.3 */ -export class AnyOfCommand extends GrammarTest +export class AnyOfTest extends GrammarTest { constructor() { @@ -103,7 +103,7 @@ export class AnyOfCommand extends GrammarTest /** * https://tools.ietf.org/html/rfc5228#section-5.4 */ -export class EnvelopeCommand extends GrammarTest +export class EnvelopeTest extends GrammarTest { constructor() { @@ -141,7 +141,7 @@ export class EnvelopeCommand extends GrammarTest /** * https://tools.ietf.org/html/rfc5228#section-5.5 */ -export class ExistsCommand extends GrammarTest +export class ExistsTest extends GrammarTest { constructor() { @@ -167,7 +167,7 @@ export class ExistsCommand extends GrammarTest /** * https://tools.ietf.org/html/rfc5228#section-5.6 */ -export class FalseCommand extends GrammarTest +export class FalseTest extends GrammarTest { toString() { @@ -178,7 +178,7 @@ export class FalseCommand extends GrammarTest /** * https://tools.ietf.org/html/rfc5228#section-5.7 */ -export class HeaderCommand extends GrammarTest +export class HeaderTest extends GrammarTest { constructor() { @@ -228,7 +228,7 @@ export class HeaderCommand extends GrammarTest /** * https://tools.ietf.org/html/rfc5228#section-5.8 */ -export class NotCommand extends GrammarTest +export class NotTest extends GrammarTest { constructor() { @@ -250,7 +250,7 @@ export class NotCommand extends GrammarTest /** * https://tools.ietf.org/html/rfc5228#section-5.9 */ -export class SizeCommand extends GrammarTest +export class SizeTest extends GrammarTest { constructor() { @@ -279,7 +279,7 @@ export class SizeCommand extends GrammarTest /** * https://tools.ietf.org/html/rfc5228#section-5.10 */ -export class TrueCommand extends GrammarTest +export class TrueTest extends GrammarTest { toString() {