diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:51:24 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:51:24 +0000 |
commit | f7548d6d28c313cf80e6f3ef89aed16a19815df1 (patch) | |
tree | a3f6f2a3f247293bee59ecd28e8cd8ceb6ca064a /pigeonhole/tests/extensions/mime | |
parent | Initial commit. (diff) | |
download | dovecot-f7548d6d28c313cf80e6f3ef89aed16a19815df1.tar.xz dovecot-f7548d6d28c313cf80e6f3ef89aed16a19815df1.zip |
Adding upstream version 1:2.3.19.1+dfsg1.upstream/1%2.3.19.1+dfsg1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'pigeonhole/tests/extensions/mime')
26 files changed, 2425 insertions, 0 deletions
diff --git a/pigeonhole/tests/extensions/mime/address.svtest b/pigeonhole/tests/extensions/mime/address.svtest new file mode 100644 index 0000000..1607450 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/address.svtest @@ -0,0 +1,281 @@ +require "vnd.dovecot.testsuite"; +require "mime"; +require "foreverypart"; + +/* + * Basic functionionality + */ + +test_set "message" text: +From: stephan@example.com +To: nico@nl.example.com, harry@de.example.com +cc: Timo <tss(no spam)@fi.iki> +Subject: Frobnitzm + +Test. +. +; + +test "Basic functionality" { + /* Must match */ + if not address :mime :anychild :contains ["to", "from"] "harry" { + test_fail "failed to match address (1)"; + } + + if not address :mime :anychild :contains ["to", "from"] "de.example" { + test_fail "failed to match address (2)"; + } + + if not address :mime :anychild :matches "to" "*@*.example.com" { + test_fail "failed to match address (3)"; + } + + if not address :mime :anychild :is "to" "harry@de.example.com" { + test_fail "failed to match address (4)"; + } + + /* Must not match */ + if address :mime :anychild :is ["to", "from"] "nonsense@example.com" { + test_fail "matches erroneous address"; + } + + /* Match first key */ + if not address :mime :anychild :contains ["to"] ["nico", "fred", "henk"] { + test_fail "failed to match first key"; + } + + /* Match second key */ + if not address :mime :anychild :contains ["to"] ["fred", "nico", "henk"] { + test_fail "failed to match second key"; + } + + /* Match last key */ + if not address :mime :anychild :contains ["to"] ["fred", "henk", "nico"] { + test_fail "failed to match last key"; + } + + /* First header */ + if not address :mime :anychild :contains + ["to", "from"] ["fred", "nico", "henk"] { + test_fail "failed to match first header"; + } + + /* Second header */ + if not address :mime :anychild :contains + ["from", "to"] ["fred", "nico", "henk"] { + test_fail "failed to match second header"; + } + + /* Comment */ + if not address :mime :anychild :is "cc" "tss@fi.iki" { + test_fail "failed to ignore comment in address"; + } +} + +/* + * Basic functionionality - foreverypart + */ + +test "Basic functionality - foreverypart" { + foreverypart { + /* Must match */ + if not address :mime :anychild :contains ["to", "from"] "harry" { + test_fail "failed to match address (1)"; + } + + if not address :mime :anychild :contains ["to", "from"] "de.example" { + test_fail "failed to match address (2)"; + } + + if not address :mime :anychild :matches "to" "*@*.example.com" { + test_fail "failed to match address (3)"; + } + + if not address :mime :anychild :is "to" "harry@de.example.com" { + test_fail "failed to match address (4)"; + } + + /* Must not match */ + if address :mime :anychild :is ["to", "from"] "nonsense@example.com" { + test_fail "matches erroneous address"; + } + + /* Match first key */ + if not address :mime :anychild :contains ["to"] ["nico", "fred", "henk"] { + test_fail "failed to match first key"; + } + + /* Match second key */ + if not address :mime :anychild :contains ["to"] ["fred", "nico", "henk"] { + test_fail "failed to match second key"; + } + + /* Match last key */ + if not address :mime :anychild :contains ["to"] ["fred", "henk", "nico"] { + test_fail "failed to match last key"; + } + + /* First header */ + if not address :mime :anychild :contains + ["to", "from"] ["fred", "nico", "henk"] { + test_fail "failed to match first header"; + } + + /* Second header */ + if not address :mime :anychild :contains + ["from", "to"] ["fred", "nico", "henk"] { + test_fail "failed to match second header"; + } + + /* Comment */ + if not address :mime :anychild :is "cc" "tss@fi.iki" { + test_fail "failed to ignore comment in address"; + } + } +} + +/* + * Address headers + */ + +test_set "message" text: +From: stephan@friep.frop +To: henk@tukkerland.ex +CC: ivo@boer.ex +Bcc: joop@hooibaal.ex +Sender: s.bosch@friep.frop +Resent-From: ivo@boer.ex +Resent-To: idioot@dombo.ex +Subject: Berichtje + +Test. +. +; + +test "Address headers" { + if not address :mime :anychild "from" "stephan@friep.frop" { + test_fail "from header not recognized"; + } + + if not address :mime :anychild "to" "henk@tukkerland.ex" { + test_fail "to header not recognized"; + } + + if not address :mime :anychild "cc" "ivo@boer.ex" { + test_fail "cc header not recognized"; + } + + if not address :mime :anychild "bcc" "joop@hooibaal.ex" { + test_fail "bcc header not recognized"; + } + + if not address :mime :anychild "sender" "s.bosch@friep.frop" { + test_fail "sender header not recognized"; + } + + if not address :mime :anychild "resent-from" "ivo@boer.ex" { + test_fail "resent-from header not recognized"; + } + + if not address :mime :anychild "resent-to" "idioot@dombo.ex" { + test_fail "resent-to header not recognized"; + } +} + +/* + * Address headers - foreverypart + */ + +test "Address headers - foreverypart" { + foreverypart { + if not address :mime :anychild "from" "stephan@friep.frop" { + test_fail "from header not recognized"; + } + + if not address :mime :anychild "to" "henk@tukkerland.ex" { + test_fail "to header not recognized"; + } + + if not address :mime :anychild "cc" "ivo@boer.ex" { + test_fail "cc header not recognized"; + } + + if not address :mime :anychild "bcc" "joop@hooibaal.ex" { + test_fail "bcc header not recognized"; + } + + if not address :mime :anychild "sender" "s.bosch@friep.frop" { + test_fail "sender header not recognized"; + } + + if not address :mime :anychild "resent-from" "ivo@boer.ex" { + test_fail "resent-from header not recognized"; + } + + if not address :mime :anychild "resent-to" "idioot@dombo.ex" { + test_fail "resent-to header not recognized"; + } + } +} + +/* + * Multipart anychild + */ + +test_set "message" text: +From: Hendrik <hendrik@example.com> +To: Harrie <harrie@example.com> +Date: Sat, 11 Oct 2010 00:31:44 +0200 +Subject: Harrie is een prutser +Content-Type: multipart/mixed; boundary=AA +CC: AA@example.com + +This is a multi-part message in MIME format. +--AA +Content-Type: multipart/mixed; boundary=BB +CC: BB@example.com + +This is a multi-part message in MIME format. +--BB +Content-Type: text/plain; charset="us-ascii" +CC: CC@example.com + +Hello + +--BB +Content-Type: text/plain; charset="us-ascii" +CC: DD@example.com + +Hello again + +--BB-- +This is the end of MIME multipart. + +--AA +Content-Type: text/plain; charset="us-ascii" +CC: EE@example.com + +And again + +--AA-- +This is the end of MIME multipart. +. +; + +test "Multipart anychild" { + if not address :mime :anychild :localpart "Cc" "AA" { + test_fail "AA Cc repient does not exist"; + } + if not address :mime :anychild :localpart "Cc" "BB" { + test_fail "BB Cc repient does not exist"; + } + if not address :mime :anychild :localpart "Cc" "CC" { + test_fail "CC Cc repient does not exist"; + } + if not address :mime :anychild :localpart "Cc" "DD" { + test_fail "DD Cc repient does not exist"; + } + if not address :mime :anychild :localpart "Cc" "EE" { + test_fail "EE Cc repient does not exist"; + } +} diff --git a/pigeonhole/tests/extensions/mime/calendar-example.svtest b/pigeonhole/tests/extensions/mime/calendar-example.svtest new file mode 100644 index 0000000..745e6e6 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/calendar-example.svtest @@ -0,0 +1,129 @@ +require "vnd.dovecot.testsuite"; +require "mime"; +require "foreverypart"; +require "editheader"; +require "relational"; +require "variables"; + +# Example from RFC 6047, Section 2.5: +test_set "message" text: +From: user1@example.com +To: user2@example.com +Subject: Phone Conference +Mime-Version: 1.0 +Date: Wed, 07 May 2008 21:30:25 +0400 +Message-ID: <4821E731.5040506@laptop1.example.com> +Content-Type: text/calendar; method=REQUEST; charset=UTF-8 +Content-Transfer-Encoding: quoted-printable + +BEGIN:VCALENDAR +PRODID:-//Example/ExampleCalendarClient//EN +METHOD:REQUEST +VERSION:2.0 +BEGIN:VEVENT +ORGANIZER:mailto:user1@example.com +ATTENDEE;ROLE=CHAIR;PARTSTAT=ACCEPTED:mailto:user1@example.com +ATTENDEE;RSVP=YES;CUTYPE=INDIVIDUAL:mailto:user2@example.com +DTSTAMP:20080507T170000Z +DTSTART:20080701T160000Z +DTEND:20080701T163000Z +SUMMARY:Phone call to discuss your last visit +DESCRIPTION:=D1=82=D1=8B =D0=BA=D0=B0=D0=BA - =D0=B4=D0=BE=D0= + =B2=D0=BE=D0=BB=D0=B5=D0=BD =D0=BF=D0=BE=D0=B5=D0=B7=D0=B4=D0=BA=D0 + =BE=D0=B9? +UID:calsvr.example.com-8739701987387998 +SEQUENCE:0 +STATUS:TENTATIVE +END:VEVENT +END:VCALENDAR +. +; + +test "Calendar only" { + foreverypart { + if allof( + header :mime :count "eq" "Content-Type" "1", + header :mime :contenttype "Content-Type" "text/calendar", + header :mime :param "method" :matches "Content-Type" "*", + header :mime :param "charset" :is "Content-Type" "UTF-8" ) { + addheader "X-ICAL" "${1}"; + break; + } + } + + if not header "x-ical" "request" { + test_fail "Failed to parse message correctly"; + } +} + +# Modified example +test_set "message" text: +From: user1@example.com +To: user2@example.com +Subject: Phone Conference +Mime-Version: 1.0 +Date: Wed, 07 May 2008 21:30:25 +0400 +Message-ID: <4821E731.5040506@laptop1.example.com> +Content-Type: multipart/mixed; boundary=AA + +This is a multi-part message in MIME format. + +--AA +Content-Type: text/plain + +Hello, + +I'd like to discuss your last visit. A tentative meeting schedule is +attached. + +Regards, + +User1 + +--AA +Content-Type: text/calendar; method=REQUEST; charset=UTF-8 +Content-Transfer-Encoding: quoted-printable + +BEGIN:VCALENDAR +PRODID:-//Example/ExampleCalendarClient//EN +METHOD:REQUEST +VERSION:2.0 +BEGIN:VEVENT +ORGANIZER:mailto:user1@example.com +ATTENDEE;ROLE=CHAIR;PARTSTAT=ACCEPTED:mailto:user1@example.com +ATTENDEE;RSVP=YES;CUTYPE=INDIVIDUAL:mailto:user2@example.com +DTSTAMP:20080507T170000Z +DTSTART:20080701T160000Z +DTEND:20080701T163000Z +SUMMARY:Phone call to discuss your last visit +DESCRIPTION:=D1=82=D1=8B =D0=BA=D0=B0=D0=BA - =D0=B4=D0=BE=D0= + =B2=D0=BE=D0=BB=D0=B5=D0=BD =D0=BF=D0=BE=D0=B5=D0=B7=D0=B4=D0=BA=D0 + =BE=D0=B9? +UID:calsvr.example.com-8739701987387998 +SEQUENCE:0 +STATUS:TENTATIVE +END:VEVENT +END:VCALENDAR + +--AA-- +. +; + +test "Multipart message" { + foreverypart { + if allof( + header :mime :count "eq" "Content-Type" "1", + header :mime :contenttype "Content-Type" "text/calendar", + header :mime :param "method" :matches "Content-Type" "*", + header :mime :param "charset" :is "Content-Type" "UTF-8" ) { + addheader "X-ICAL" "${1}"; + break; + } + } + + if not header "x-ical" "request" { + test_fail "Failed to parse message correctly"; + } +} + + diff --git a/pigeonhole/tests/extensions/mime/content-header.svtest b/pigeonhole/tests/extensions/mime/content-header.svtest new file mode 100644 index 0000000..9686e35 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/content-header.svtest @@ -0,0 +1,161 @@ +require "vnd.dovecot.testsuite"; +require "relational"; +require "mime"; + +test_set "message" text: +From: stephan@example.com +To: timo@example.com +Subject: Frop +Content-Type: text/plain + +Frop +. +; + +test "Simple Content-Type :type" { + if not header :mime :type "content-type" "text" { + test_fail "wrong type extracted"; + } +} + +test "Simple Content-Type :subype" { + if not header :mime :subtype "content-type" "plain" { + test_fail "wrong subtype extracted"; + } +} + +test "Simple Content-Type :contenttype" { + if not header :mime :contenttype "content-type" "text/plain" { + test_fail "wrong contenttype extracted"; + } +} + +test_set "message" text: +From: stephan@example.com +To: timo@example.com +Subject: Frop +Content-Type: text/calendar; method=request; charset=UTF-8; + +Frop +. +; + +test "Advanced Content-Type :type" { + if not header :mime :type "content-type" "text" { + test_fail "wrong type extracted"; + } +} + +test "Advanced Content-Type :subype" { + if not header :mime :subtype "content-type" "calendar" { + test_fail "wrong subtype extracted"; + } +} + +test "Advanced Content-Type :contenttype" { + if not header :mime :contenttype "content-type" "text/calendar" { + test_fail "wrong contenttype extracted"; + } +} + +test "Advanced Content-Type :param" { + if not header :mime :param "method" "content-type" "request" { + test_fail "wrong method param extracted"; + } + + if not header :mime :param "charset" "content-type" "UTF-8" { + test_fail "wrong charset param extracted"; + } + + if not header :mime :param ["method", "charset"] + "content-type" "request" { + test_fail "wrong method param extracted"; + } + + if not header :mime :param ["method", "charset"] + "content-type" "UTF-8" { + test_fail "wrong charset param extracted"; + } + + if not header :count "eq" :mime :param ["method", "charset"] + "content-type" "2" { + test_fail "wrong number of parameters"; + } +} + +test_set "message" text: +From: stephan@example.com +To: timo@example.com +Subject: Frop +Content-Type: application/x-stuff; + title*0*=us-ascii'en'This%20is%20even%20more%20; + title*1*=%2A%2A%2Afun%2A%2A%2A%20; + title*2="isn't it!" + +Frop +. +; + +test "Encoded Content-Type :param" { + if not header :mime :param "title" "content-type" + "This is even more ***fun*** isn't it!" { + test_fail "wrong method param extracted"; + } +} + +test_set "message" text: +From: stephan@example.com +To: timo@example.com +Subject: Frop +Content-Type: image/png +Content-Disposition: inline; filename="frop.exe"; title="Frop!" + +Frop +. +; + +test "Content-Disposition :type" { + if not header :mime :type "content-disposition" "inline" { + test_fail "wrong type extracted"; + } +} + +test "Content-Disposition :subype" { + if not header :mime :subtype "content-disposition" "" { + test_fail "wrong subtype extracted"; + } +} + +test "Content-Disposition :contenttype" { + if not header :mime :contenttype "content-disposition" "inline" { + test_fail "wrong contenttype extracted"; + } +} + +test "Content-Disposition :param" { + if not header :mime :param "filename" "content-disposition" "frop.exe" { + test_fail "wrong filename param extracted"; + } + + if not header :mime :param "title" "content-disposition" "Frop!" { + test_fail "wrong title param extracted"; + } + + if not header :mime :param ["filename", "title"] + "content-disposition" "frop.exe" { + test_fail "wrong filename param extracted"; + } + + if not header :mime :param ["filename", "title"] + "content-disposition" "Frop!" { + test_fail "wrong title param extracted"; + } + + if not header :count "eq" :mime :param ["filename", "title"] + "content-disposition" "2" { + test_fail "wrong number of parameters"; + } + +} + + diff --git a/pigeonhole/tests/extensions/mime/errors.svtest b/pigeonhole/tests/extensions/mime/errors.svtest new file mode 100644 index 0000000..b3b858e --- /dev/null +++ b/pigeonhole/tests/extensions/mime/errors.svtest @@ -0,0 +1,162 @@ +require "vnd.dovecot.testsuite"; + +require "relational"; +require "comparator-i;ascii-numeric"; + +test "Foreverypart command" { + if test_script_compile "errors/foreverypart.sieve" { + test_fail "compile should have failed"; + } + + if test_error :count "ne" :comparator "i;ascii-numeric" "12" { + test_fail "incorrect number of compile errors reported"; + } +} + +test "Break command" { + if test_script_compile "errors/break.sieve" { + test_fail "compile should have failed"; + } + + if test_error :count "ne" :comparator "i;ascii-numeric" "21" { + test_fail "incorrect number of compile errors reported"; + } +} + +test "Header test with :mime tag" { + if test_script_compile "errors/header-mime-tag.sieve" { + test_fail "compile should have failed"; + } + + if test_error :count "ne" :comparator "i;ascii-numeric" "10" { + test_fail "incorrect number of compile errors reported"; + } +} + +test "Address test with :mime tag" { + if test_script_compile "errors/address-mime-tag.sieve" { + test_fail "compile should have failed"; + } + + if test_error :count "ne" :comparator "i;ascii-numeric" "6" { + test_fail "incorrect number of compile errors reported"; + } +} + +test "Exists test with :mime tag" { + if test_script_compile "errors/exists-mime-tag.sieve" { + test_fail "compile should have failed"; + } + + if test_error :count "ne" :comparator "i;ascii-numeric" "6" { + test_fail "incorrect number of compile errors reported"; + } +} + +test "Limits" { + if test_script_compile "errors/limits.sieve" { + test_fail "compile should have failed"; + } + + if test_error :count "ne" :comparator "i;ascii-numeric" "2" { + test_fail "incorrect number of compile errors reported"; + } +} + +test_set "message" text: +From: Whomever <whoever@example.com> +To: Someone <someone@example.com> +Date: Sat, 10 Oct 2009 00:30:04 +0200 +Subject: whatever +Content-Type: multipart/mixed; boundary=AA + +This is a multi-part message in MIME format. + +--AA +Content-Type: multipart/alternative; boundary=BB + +This is a multi-part message in MIME format. + +--BB +Content-Type: multipart/alternative; boundary=CC + +This is a multi-part message in MIME format. + +--CC +Content-Type: multipart/alternative; boundary=DD + +This is a multi-part message in MIME format. + +--DD +Content-Type: multipart/alternative; boundary=EE + +This is a nested multi-part message in MIME format. + +--EE +Content-Type: text/plain; charset="us-ascii" + +Hello + +--EE-- + +This is the end of the inner MIME multipart. + +--DD-- + +This is the end of the MIME multipart. + +--CC-- + +This is the end of the MIME multipart. + +--BB-- + +This is the end of the MIME multipart. + +--AA-- + +This is the end of the MIME multipart. +. +; + +test "Limits - include" { + if not test_script_compile "errors/limits-include.sieve" { + test_fail "script compile failed"; + } + + if test_script_run { + test_fail "script run should have failed"; + } +} + +test "Extracttext" { + if test_script_compile "errors/extracttext.sieve" { + test_fail "compile should have failed"; + } + + if test_error :count "ne" :comparator "i;ascii-numeric" "11" { + test_fail "incorrect number of compile errors reported"; + } +} + +test "Extracttext - without variables" { + if test_script_compile "errors/extracttext-novar.sieve" { + test_fail "compile should have failed"; + } + + if test_error :count "ne" :comparator "i;ascii-numeric" "2" { + test_fail "incorrect number of compile errors reported"; + } +} + +test "Extracttext - without foreverypart" { + if test_script_compile "errors/extracttext-nofep.sieve" { + test_fail "compile should have failed"; + } + + if test_error :count "ne" :comparator "i;ascii-numeric" "2" { + test_fail "incorrect number of compile errors reported"; + } +} + + diff --git a/pigeonhole/tests/extensions/mime/errors/address-mime-tag.sieve b/pigeonhole/tests/extensions/mime/errors/address-mime-tag.sieve new file mode 100644 index 0000000..7adb7bc --- /dev/null +++ b/pigeonhole/tests/extensions/mime/errors/address-mime-tag.sieve @@ -0,0 +1,38 @@ +require "mime"; + +## Address + +# No error +if address :contains :mime "To" "frop@example.com" { + discard; +} + +# No error +if address :anychild :contains :mime "To" "frop@example.com" { + discard; +} + +# 1: Bare anychild option +if address :anychild "To" "frop@example.com" { + discard; +} + +# 2: Inappropriate option +if address :mime :anychild :type "To" "frop@example.com" { + discard; +} + +# 3: Inappropriate option +if address :mime :anychild :subtype "To" "frop@example.com" { + discard; +} + +# 4: Inappropriate option +if address :mime :anychild :contenttype "To" "frop@example.com" { + discard; +} + +# 5: Inappropriate option +if address :mime :anychild :param "frop" "To" "frop@example.com" { + discard; +} diff --git a/pigeonhole/tests/extensions/mime/errors/break.sieve b/pigeonhole/tests/extensions/mime/errors/break.sieve new file mode 100644 index 0000000..1858673 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/errors/break.sieve @@ -0,0 +1,157 @@ +require "foreverypart"; + +foreverypart :name "frop" { + # 1: Spurious tag + break :tag; + + # 2: Spurious tests + break true; + + # 3: Spurious tests + break anyof(true, false); + + # 4: Bare string + break "frop"; + + # 5: Bare string-list + break ["frop", "friep"]; + + # 6: Several bad arguments + break 13 ["frop", "friep"]; + + # 7: Spurious additional tag + break :name "frop" :friep; + + # 8: Spurious additional string + break :name "frop" "friep"; + + # 9: Bad name + break :name 13; + + # 10: Bad name + break :name ["frop", "friep"]; + + # No error + break; + + # No error + break :name "frop"; + + # No error + if exists "frop" { + break; + } + + # No error + if exists "frop" { + break :name "frop"; + } + + # No error + foreverypart { + break :name "frop"; + } + + # No error + foreverypart :name "friep" { + break :name "frop"; + } + + # No error + foreverypart :name "friep" { + break :name "friep"; + } + + # No error + foreverypart :name "friep" { + break; + } + + # No error + foreverypart { + if exists "frop" { + break :name "frop"; + } + } + + # No error + foreverypart :name "friep" { + if exists "frop" { + break :name "frop"; + } + } + + # No error + foreverypart :name "friep" { + if exists "frop" { + break :name "friep"; + } + } + + # No error + foreverypart :name "friep" { + if exists "frop" { + break; + } + } +} + +# 11: Outside loop +break; + +# 12: Outside loop +if exists "frop" { + break; +} + +# 13: Outside loop +break :name "frop"; + +# 14: Outside loop +if exists "frop" { + break :name "frop"; +} + +# 15: Bad name +foreverypart { + break :name "frop"; +} + +# 16: Bad name +foreverypart { + if exists "frop" { + break :name "frop"; + } +} + +# 17: Bad name +foreverypart :name "friep" { + break :name "frop"; +} + +# 18: Bad name +foreverypart :name "friep" { + if exists "frop" { + break :name "frop"; + } +} + +# 19: Bad name +foreverypart :name "friep" { + foreverypart :name "frop" { + break :name "frml"; + } +} + +# 20: Bad name +foreverypart :name "friep" { + foreverypart :name "frop" { + if exists "frop" { + break :name "frml"; + } + } +} + + + + diff --git a/pigeonhole/tests/extensions/mime/errors/exists-mime-tag.sieve b/pigeonhole/tests/extensions/mime/errors/exists-mime-tag.sieve new file mode 100644 index 0000000..84c86a7 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/errors/exists-mime-tag.sieve @@ -0,0 +1,43 @@ +require "mime"; + +## Exists + +# No error +if exists :mime "To" { + discard; +} + +# No error +if exists :anychild :mime "To" { + discard; +} + +# 1: Inappropriate option +if exists :anychild "To" { + discard; +} + +# 2: Inappropriate option +if exists :mime :type "To" { + discard; +} + +# 3: Inappropriate option +if exists :mime :subtype "To" { + discard; +} + +# 4: Inappropriate option +if exists :mime :contenttype "To" { + discard; +} + +# 5: Inappropriate option +if exists :mime :param ["frop", "friep"] "To" { + discard; +} + + + + + diff --git a/pigeonhole/tests/extensions/mime/errors/extracttext-nofep.sieve b/pigeonhole/tests/extensions/mime/errors/extracttext-nofep.sieve new file mode 100644 index 0000000..c38b228 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/errors/extracttext-nofep.sieve @@ -0,0 +1,4 @@ +require "extracttext"; +require "variables"; + +keep; diff --git a/pigeonhole/tests/extensions/mime/errors/extracttext-novar.sieve b/pigeonhole/tests/extensions/mime/errors/extracttext-novar.sieve new file mode 100644 index 0000000..8e2a378 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/errors/extracttext-novar.sieve @@ -0,0 +1,6 @@ +require "extracttext"; +require "foreverypart"; + +foreverypart { + extracttext "frop"; +} diff --git a/pigeonhole/tests/extensions/mime/errors/extracttext.sieve b/pigeonhole/tests/extensions/mime/errors/extracttext.sieve new file mode 100644 index 0000000..f8af1c9 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/errors/extracttext.sieve @@ -0,0 +1,42 @@ +require "extracttext"; +require "variables"; +require "foreverypart"; + +# 1: Used outside foreverypart +extracttext :first 10 "data"; + +foreverypart { + # 2: Missing arguments + extracttext; + + # 3: Bad arguments + extracttext 1; + + # 4: Bad arguments + extracttext ["frop", "friep"]; + + # 5: Unknown tag + extracttext :frop "frop"; + + # 6: Invalid variable name + extracttext "${frop}"; + + # Not an error + extracttext "\n\a\m\e"; + + # 7: Trying to assign match variable + extracttext "0"; + + # Not an error + extracttext :lower "frop"; + + # 8: Bad ":first" tag + extracttext :first "frop"; + + # 9: Bad ":first" tag + extracttext :first "frop" "friep"; + + # 10: Bad ":first" tag + extracttext :first ["frop", "friep"] "frml"; +} + diff --git a/pigeonhole/tests/extensions/mime/errors/foreverypart.sieve b/pigeonhole/tests/extensions/mime/errors/foreverypart.sieve new file mode 100644 index 0000000..38a28d4 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/errors/foreverypart.sieve @@ -0,0 +1,45 @@ +require "foreverypart"; + +# 1: No block +foreverypart; + +# 2: Spurious tag +foreverypart :tag { } + +# 3: Spurious tests +foreverypart true { } + +# 4: Spurious tests +foreverypart anyof(true, false) { } + +# 5: Bare string +foreverypart "frop" { } + +# 6: Bare string-list +foreverypart ["frop", "friep"] { } + +# 7: Several bad arguments +foreverypart 13 ["frop", "friep"] { } + +# 8: Spurious additional tag +foreverypart :name "frop" :friep { } + +# 9: Spurious additional string +foreverypart :name "frop" "friep" { } + +# 10: Bad name +foreverypart :name 13 { } + +# 11: Bad name +foreverypart :name ["frop", "friep"] { } + +# No error +foreverypart { keep; } + +# No error +foreverypart :name "frop" { keep; } + +# No error +foreverypart :name "frop" { foreverypart { keep; } } + + diff --git a/pigeonhole/tests/extensions/mime/errors/header-mime-tag.sieve b/pigeonhole/tests/extensions/mime/errors/header-mime-tag.sieve new file mode 100644 index 0000000..85782af --- /dev/null +++ b/pigeonhole/tests/extensions/mime/errors/header-mime-tag.sieve @@ -0,0 +1,100 @@ +require "mime"; + +## Header + +# No error +if header :contains :mime "Content-Type" "text/plain" { + discard; +} + +# No error +if header :mime :type "Content-Type" "text" { + discard; +} + +# No error +if header :mime :subtype "Content-Type" "plain" { + discard; +} + +# No error +if header :mime :contenttype "Content-Type" "text/plain" { + discard; +} + +# No error +if header :mime :param ["frop", "friep"] "Content-Type" "frml" { + discard; +} + +# No error +if header :anychild :contains :mime "Content-Type" "text/plain" { + discard; +} + +# No error +if header :mime :anychild :type "Content-Type" "text" { + discard; +} + +# No error +if header :mime :subtype :anychild "Content-Type" "plain" { + discard; +} + +# No error +if header :anychild :mime :contenttype "Content-Type" "text/plain" { + discard; +} + +# No error +if header :mime :param ["frop", "friep"] :anychild "Content-Type" "frml" { + discard; +} + +# 1: Bare anychild option +if header :anychild "Content-Type" "frml" { + discard; +} + +# 2: Bare mime option +if header :type "Content-Type" "frml" { + discard; +} + +# 3: Bare mime option +if header :subtype "Content-Type" "frml" { + discard; +} + +# 4: Bare mime option +if header :contenttype "Content-Type" "frml" { + discard; +} + +# 5: Bare mime option +if header :param "frop" "Content-Type" "frml" { + discard; +} + +# 6: Multiple option tags +if header :mime :type :subtype "Content-Type" "frml" { + discard; +} + +# 7: Bad param argument +if header :mime :param 13 "Content-Type" "frml" { + discard; +} + +# 8: Missing param argument +if header :mime :param :anychild "Content-Type" "frml" { + discard; +} + +# 9: Missing param argument +if header :mime :param :frop "Content-Type" "frml" { + discard; +} + + diff --git a/pigeonhole/tests/extensions/mime/errors/limits-include.sieve b/pigeonhole/tests/extensions/mime/errors/limits-include.sieve new file mode 100644 index 0000000..ef92456 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/errors/limits-include.sieve @@ -0,0 +1,6 @@ +require "foreverypart"; +require "include"; + +foreverypart :name "frop" { + include "include-loop-2"; +} diff --git a/pigeonhole/tests/extensions/mime/errors/limits.sieve b/pigeonhole/tests/extensions/mime/errors/limits.sieve new file mode 100644 index 0000000..0add1c3 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/errors/limits.sieve @@ -0,0 +1,13 @@ +require "foreverypart"; + +foreverypart :name "frop" { + foreverypart :name "friep" { + foreverypart :name "frml" { + foreverypart { + foreverypart { + break; + } + } + } + } +} diff --git a/pigeonhole/tests/extensions/mime/execute.svtest b/pigeonhole/tests/extensions/mime/execute.svtest new file mode 100644 index 0000000..2ced83b --- /dev/null +++ b/pigeonhole/tests/extensions/mime/execute.svtest @@ -0,0 +1,82 @@ +require "vnd.dovecot.testsuite"; + +/* + * Execution testing (currently just meant to trigger any segfaults) + */ + +test_set "message" text: +From: Whomever <whoever@example.com> +To: Someone <someone@example.com> +Date: Sat, 10 Oct 2009 00:30:04 +0200 +Subject: whatever +Content-Type: multipart/mixed; boundary=outer + +This is a multi-part message in MIME format. + +--outer +Content-Type: multipart/alternative; boundary=inner + +This is a nested multi-part message in MIME format. + +--inner +Content-Type: text/plain; charset="us-ascii" + +Hello + +--inner +Content-Type: text/html; charset="us-ascii" + +<html><body>Hello</body></html> + +--inner-- + +This is the end of the inner MIME multipart. + +--outer +Content-Type: message/rfc822 + +From: Someone Else +Subject: Hello, this is an elaborate request for you to finally say hello + already! + +Please say Hello + +--outer-- + +This is the end of the outer MIME multipart. +. +; + +test "Basic - foreverypart" { + if not test_script_compile "execute/foreverypart.sieve" { + test_fail "script compile failed"; + } + + if not test_script_run { + test_fail "script run failed"; + } + + if not test_result_execute { + test_fail "result execute failed"; + } + + test_binary_save "ihave-basic"; + test_binary_load "ihave-basic"; +} + +test "Basic - mime" { + if not test_script_compile "execute/mime.sieve" { + test_fail "script compile failed"; + } + + if not test_script_run { + test_fail "script run failed"; + } + + if not test_result_execute { + test_fail "result execute failed"; + } + + test_binary_save "ihave-basic"; + test_binary_load "ihave-basic"; +} diff --git a/pigeonhole/tests/extensions/mime/execute/foreverypart.sieve b/pigeonhole/tests/extensions/mime/execute/foreverypart.sieve new file mode 100644 index 0000000..9ae1fba --- /dev/null +++ b/pigeonhole/tests/extensions/mime/execute/foreverypart.sieve @@ -0,0 +1,14 @@ +require "foreverypart"; +require "variables"; + +foreverypart { + foreverypart { + foreverypart { + foreverypart { + set "a" "a${a}"; + } + } + } +} + + diff --git a/pigeonhole/tests/extensions/mime/execute/mime.sieve b/pigeonhole/tests/extensions/mime/execute/mime.sieve new file mode 100644 index 0000000..dd7fedc --- /dev/null +++ b/pigeonhole/tests/extensions/mime/execute/mime.sieve @@ -0,0 +1,69 @@ +require "mime"; +require "foreverypart"; +require "variables"; + +if header :contains :mime "Content-Type" "text/plain" { + discard; +} +if header :mime :type "Content-Type" "text" { + discard; +} +if header :mime :subtype "Content-Type" "plain" { + discard; +} +if header :mime :contenttype "Content-Type" "text/plain" { + discard; +} +if header :mime :param ["frop", "friep"] "Content-Type" "frml" { + discard; +} +if header :anychild :contains :mime "Content-Type" "text/plain" { + discard; +} +if header :mime :anychild :type "Content-Type" "text" { + discard; +} +if header :mime :subtype :anychild "Content-Type" "plain" { + discard; +} +if header :anychild :mime :contenttype "Content-Type" "text/plain" { + discard; +} +if header :mime :param ["frop", "friep"] :anychild "Content-Type" "frml" { + discard; +} + +foreverypart { + foreverypart { + if header :contains :mime "Content-Type" "text/plain" { + discard; + } + if header :mime :type "Content-Type" "text" { + discard; + } + if header :mime :subtype "Content-Type" "plain" { + discard; + } + if header :mime :contenttype "Content-Type" "text/plain" { + discard; + } + if header :mime :param ["frop", "friep"] "Content-Type" "frml" { + discard; + } + if header :anychild :contains :mime "Content-Type" "text/plain" { + discard; + } + if header :mime :anychild :type "Content-Type" "text" { + discard; + } + if header :mime :subtype :anychild "Content-Type" "plain" { + discard; + } + if header :anychild :mime :contenttype "Content-Type" "text/plain" { + discard; + } + if header :mime :param ["frop", "friep"] :anychild "Content-Type" "frml" { + discard; + } + } +} diff --git a/pigeonhole/tests/extensions/mime/exists.svtest b/pigeonhole/tests/extensions/mime/exists.svtest new file mode 100644 index 0000000..517deeb --- /dev/null +++ b/pigeonhole/tests/extensions/mime/exists.svtest @@ -0,0 +1,237 @@ +require "vnd.dovecot.testsuite"; +require "mime"; +require "foreverypart"; + +test_set "message" text: +From: stephan@example.org +To: nico@vestingbar.bl +Subject: Test message +Date: Wed, 29 Jul 2009 18:21:44 +0300 +X-Spam-Status: Not Spam +Resent-To: nico@frop.example.com + +Test! +. +; + +/* + * One header + */ + +test "One header" { + if not exists :mime :anychild "from" { + test_fail "exists test missed from header"; + } + + if exists :mime :anychild "x-nonsense" { + test_fail "exists test found non-existent header"; + } +} + +/* + * One header - foreverypart + */ + +test "One header - foreverypart" { + foreverypart { + if not exists :mime :anychild "from" { + test_fail "exists test missed from header"; + } + + if exists :mime :anychild "x-nonsense" { + test_fail "exists test found non-existent header"; + } + } +} + +/* + * Two headers + */ + +test "Two headers" { + if not exists :mime :anychild ["from","to"] { + test_fail "exists test missed from or to header"; + } + + if exists :mime :anychild ["from","x-nonsense"] { + test_fail "exists test found non-existent header (1)"; + } + + if exists :mime :anychild ["x-nonsense","to"] { + test_fail "exists test found non-existent header (2)"; + } + + if exists :mime :anychild ["x-nonsense","x-nonsense2"] { + test_fail "exists test found non-existent header (3)"; + } +} + +/* + * Two headers - foreverypart + */ + +test "Two headers - foreverypart" { + foreverypart { + if not exists :mime :anychild ["from","to"] { + test_fail "exists test missed from or to header"; + } + + if exists :mime :anychild ["from","x-nonsense"] { + test_fail "exists test found non-existent header (1)"; + } + + if exists :mime :anychild ["x-nonsense","to"] { + test_fail "exists test found non-existent header (2)"; + } + + if exists :mime :anychild ["x-nonsense","x-nonsense2"] { + test_fail "exists test found non-existent header (3)"; + } + } +} + +/* + * Three headers + */ + +test "Three headers" { + if not exists :mime :anychild ["Subject","date","resent-to"] { + test_fail "exists test missed subject, date or resent-to header"; + } + + if exists :mime :anychild ["x-nonsense","date","resent-to"] { + test_fail "exists test found non-existent header (1)"; + } + + if exists :mime :anychild ["subject", "x-nonsense","resent-to"] { + test_fail "exists test found non-existent header (2)"; + } + + if exists :mime :anychild ["subject","date","x-nonsense"] { + test_fail "exists test found non-existent header (3)"; + } + + if exists :mime :anychild ["subject", "x-nonsense","x-nonsense2"] { + test_fail "exists test found non-existent header (4)"; + } + + if exists :mime :anychild ["x-nonsense","date","x-nonsense2"] { + test_fail "exists test found non-existent header (5)"; + } + + if exists :mime :anychild ["x-nonsense","x-nonsense2","resent-to"] { + test_fail "exists test found non-existent header (6)"; + } + + if exists :mime :anychild ["x-nonsense","x-nonsense2","x-nonsense3"] { + test_fail "exists test found non-existent header (7)"; + } +} + +/* + * Three headers - foreverypart + */ + +test "Three headers - foreverypart " { + foreverypart { + if not exists :mime :anychild ["Subject","date","resent-to"] { + test_fail "exists test missed subject, date or resent-to header"; + } + + if exists :mime :anychild ["x-nonsense","date","resent-to"] { + test_fail "exists test found non-existent header (1)"; + } + + if exists :mime :anychild ["subject", "x-nonsense","resent-to"] { + test_fail "exists test found non-existent header (2)"; + } + + if exists :mime :anychild ["subject","date","x-nonsense"] { + test_fail "exists test found non-existent header (3)"; + } + + if exists :mime :anychild ["subject", "x-nonsense","x-nonsense2"] { + test_fail "exists test found non-existent header (4)"; + } + + if exists :mime :anychild ["x-nonsense","date","x-nonsense2"] { + test_fail "exists test found non-existent header (5)"; + } + + if exists :mime :anychild ["x-nonsense","x-nonsense2","resent-to"] { + test_fail "exists test found non-existent header (6)"; + } + + if exists :mime :anychild ["x-nonsense","x-nonsense2","x-nonsense3"] { + test_fail "exists test found non-existent header (7)"; + } + } +} + +/* + * Multipart anychild + */ + +test_set "message" text: +From: Hendrik <hendrik@example.com> +To: Harrie <harrie@example.com> +Date: Sat, 11 Oct 2010 00:31:44 +0200 +Subject: Harrie is een prutser +Content-Type: multipart/mixed; boundary=AA +X-Test1: AA + +This is a multi-part message in MIME format. +--AA +Content-Type: multipart/mixed; boundary=BB +X-Test2: BB + +This is a multi-part message in MIME format. +--BB +Content-Type: text/plain; charset="us-ascii" +X-Test3: CC + +Hello + +--BB +Content-Type: text/plain; charset="us-ascii" +X-Test4: DD + +Hello again + +--BB-- +This is the end of MIME multipart. + +--AA +Content-Type: text/plain; charset="us-ascii" +X-Test5: EE + +And again + +--AA-- +This is the end of MIME multipart. +. +; + +test "Multipart anychild" { + if not exists :mime :anychild "X-Test1" { + test_fail "X-Test1 header does exist"; + } + if not exists :mime :anychild "X-Test2" { + test_fail "X-Test2 header does exist"; + } + if not exists :mime :anychild "X-Test3" { + test_fail "X-Test3 header does exist"; + } + if not exists :mime :anychild "X-Test4" { + test_fail "X-Test4 header does exist"; + } + if not exists :mime :anychild "X-Test5" { + test_fail "X-Test5 header does exist"; + } + if not exists :mime :anychild + ["X-Test1", "X-Test2", "X-Test3", "X-Test4", "X-Test5"] { + test_fail "Not all headers exist"; + } +} + + diff --git a/pigeonhole/tests/extensions/mime/extracttext.svtest b/pigeonhole/tests/extensions/mime/extracttext.svtest new file mode 100644 index 0000000..510a52b --- /dev/null +++ b/pigeonhole/tests/extensions/mime/extracttext.svtest @@ -0,0 +1,143 @@ +require "vnd.dovecot.testsuite"; +require "foreverypart"; +require "variables"; +require "extracttext"; + +test_set "message" text: +From: Hendrik <hendrik@example.com> +To: Harrie <harrie@example.com> +Date: Sat, 11 Oct 2010 00:31:44 +0200 +Subject: Harrie is een prutser +Content-Type: multipart/mixed; boundary=AA + +This is a multi-part message in MIME format. +--AA +Content-Type: multipart/mixed; boundary=BB + +This is a multi-part message in MIME format. +--BB +Content-Type: text/plain; charset="us-ascii" + +This is the first message part containing +plain text. + +--BB +Content-Type: text/plain; charset="us-ascii" + +This is another plain text message part. + +--BB-- +This is the end of MIME multipart. + +--AA +Content-Type: text/html; charset="us-ascii" + +<html> +<body>This is a piece of HTML text.</body> +</html> + +--AA-- +This is the end of MIME multipart. +. +; + +test "Basic" { + set "a" "a"; + foreverypart { + extracttext "b"; + if string "${a}" "aaa" { + if not string :contains "${b}" "first" { + test_fail "bad content extracted: ${b}"; + } + } elsif string "${a}" "aaaa" { + if not string :contains "${b}" "another" { + test_fail "bad content extracted: ${b}"; + } + } elsif string "${a}" "aaaaa" { + if not string :contains "${b}" "HTML text" { + test_fail "bad content extracted: ${b}"; + } + if string :contains "${b}" "<html>" { + test_fail "content extracted html: ${b}"; + } + } + set "a" "a${a}"; + } + if not string "${a}" "aaaaaa" { + set :length "parts" "${a}"; + test_fail "bad number of parts parsed: ${parts}"; + } +} + +test_set "message" text: +From: <stephan@example.com> +To: <frop@example.com> +Subject: Frop! + +FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! +FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! +FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! +FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! +FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! +FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! +FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! +FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! +FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! +FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! +FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! +FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! FROP! +. +; + +test "First - less" { + foreverypart { + extracttext :first 20 "data"; + if not string "${data}" "FROP! FROP! FROP! FR" { + test_fail "Bad data extracted"; + } + + extracttext :length :first 100 "data_len"; + if not string "${data_len}" "100" { + test_fail "Bad number of bytes extracted"; + } + } +} + +test_set "message" text: +From: <stephan@example.com> +To: <frop@example.com> +Subject: Frop! + +FROP! FROP! FROP! FROP! +. +; + +test "First - more" { + foreverypart { + extracttext :first 100 "data"; + if not string :matches "${data}" "FROP! FROP! FROP! FROP!*" { + test_fail "Bad data extracted"; + } + } +} + +test_set "message" text: +From: <stephan@example.com> +To: <frop@example.com> +Subject: Frop! + +FROP! FROP! FROP! FROP! +. +; + +test "Modifier" { + foreverypart { + extracttext :lower :upperfirst "data"; + if not string :matches "${data}" "Frop! frop! frop! frop!*" { + test_fail "Bad data extracted"; + } + } +} + + + diff --git a/pigeonhole/tests/extensions/mime/foreverypart.svtest b/pigeonhole/tests/extensions/mime/foreverypart.svtest new file mode 100644 index 0000000..08907c9 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/foreverypart.svtest @@ -0,0 +1,178 @@ +require "vnd.dovecot.testsuite"; +require "relational"; +require "foreverypart"; +require "mime"; +require "variables"; +require "include"; + +test_set "message" text: +From: Hendrik <hendrik@example.com> +To: Harrie <harrie@example.com> +Date: Sat, 11 Oct 2010 00:31:44 +0200 +Subject: Harrie is een prutser +Content-Type: multipart/mixed; boundary=AA +X-Test: AA + +This is a multi-part message in MIME format. +--AA +Content-Type: multipart/mixed; boundary=BB +X-Test: BB + +This is a multi-part message in MIME format. +--BB +Content-Type: text/plain; charset="us-ascii" +X-Test: CC + +Hello + +--BB +Content-Type: text/plain; charset="us-ascii" +X-Test: DD + +Hello again + +--BB-- +This is the end of MIME multipart. + +--AA +Content-Type: text/plain; charset="us-ascii" +X-Test: EE + +And again + +--AA-- +This is the end of MIME multipart. +. +; + +test "Single loop" { + set "a" "a"; + foreverypart { + set :length "la" "${a}"; + + if string "${a}" "a" { + if not header :mime "X-Test" "AA" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${a}" "aa" { + if not header :mime "X-Test" "BB" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${a}" "aaa" { + if not header :mime "X-Test" "CC" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${a}" "aaaa" { + if not header :mime "X-Test" "DD" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${a}" "aaaaa" { + if not header :mime "X-Test" "EE" { + test_fail "wrong header extracted (${la})"; + } + } + set "a" "a${a}"; + } +} + +test "Double loop" { + set "a" "a"; + foreverypart { + set :length "la" "${a}"; + + if string "${a}" "a" { + if not header :mime "X-Test" "AA" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${a}" "aaaaaa" { + if not header :mime "X-Test" "BB" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${a}" "aaaaaaaaa" { + if not header :mime "X-Test" "CC" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${a}" "aaaaaaaaaa" { + if not header :mime "X-Test" "DD" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${a}" "aaaaaaaaaaa" { + if not header :mime "X-Test" "EE" { + test_fail "wrong header extracted (${la})"; + } + } + + set "a" "a${a}"; + + foreverypart { + set :length "la" "${a}"; + + if string "${a}" "aa" { + if not header :mime "X-Test" "BB" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${a}" "aaa" { + if not header :mime "X-Test" "CC" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${a}" "aaaa" { + if not header :mime "X-Test" "DD" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${a}" "aaaaa" { + if not header :mime "X-Test" "EE" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${a}" "aaaaaaa" { + if not header :mime "X-Test" "CC" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${a}" "aaaaaaaa" { + if not header :mime "X-Test" "DD" { + test_fail "wrong header extracted (${la})"; + } + } + set "a" "a${a}"; + } + } +} + +test "Double loop - include" { + global "in"; + global "error"; + set "in" "a"; + foreverypart { + set :length "la" "${in}"; + + if string "${in}" "in" { + if not header :mime "X-Test" "AA" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${in}" "aaaaaa" { + if not header :mime "X-Test" "BB" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${in}" "aaaaaaaaa" { + if not header :mime "X-Test" "CC" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${in}" "aaaaaaaaaa" { + if not header :mime "X-Test" "DD" { + test_fail "wrong header extracted (${la})"; + } + } elsif string "${in}" "aaaaaaaaaaa" { + if not header :mime "X-Test" "EE" { + test_fail "wrong header extracted (${la})"; + } + } + + set "in" "a${in}"; + + include "include-foreverypart"; + + if not string "${error}" "" { + test_fail "INCLUDED: ${error}"; + } + } +} + diff --git a/pigeonhole/tests/extensions/mime/header.svtest b/pigeonhole/tests/extensions/mime/header.svtest new file mode 100644 index 0000000..48cd9e4 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/header.svtest @@ -0,0 +1,444 @@ +require "vnd.dovecot.testsuite"; +require "variables"; +require "foreverypart"; +require "mime"; + +/* + * Basic functionality + */ + +test_set "message" text: +From: stephan@example.com +To: nico@nl.example.com, harry@de.example.com +Subject: Frobnitzm +Comments: This is nonsense. +Keywords: nonsense, strange, testing +X-Spam: Yes + +Test. +. +; + +test "Basic functionality" { + /* Must match */ + if not header :mime :anychild :contains ["Subject", "Comments"] "Frobnitzm" { + test_fail "failed to match header (1)"; + } + + if not header :mime :anychild :contains ["Subject", "Comments"] "nonsense" { + test_fail "failed to match header(2)"; + } + + if not header :mime :anychild :matches "Keywords" "*, strange, *" { + test_fail "failed to match header (3)"; + } + + if not header :mime :anychild :is "Comments" "This is nonsense." { + test_fail "failed to match header (4)"; + } + + /* Must not match */ + if header :mime :anychild ["subject", "comments", "keywords"] "idiotic" { + test_fail "matched nonsense"; + } + + /* Match first key */ + if not header :mime :anychild :contains ["keywords"] ["strange", "snot", "vreemd"] { + test_fail "failed to match first key"; + } + + /* Match second key */ + if not header :mime :anychild :contains ["keywords"] ["raar", "strange", "vreemd"] { + test_fail "failed to match second key"; + } + + /* Match last key */ + if not header :mime :anychild :contains ["keywords"] ["raar", "snot", "strange"] { + test_fail "failed to match last key"; + } + + /* First header */ + if not header :mime :anychild :contains ["keywords", "subject"] + ["raar", "strange", "vreemd"] { + test_fail "failed to match first header"; + } + + /* Second header */ + if not header :mime :anychild :contains ["subject", "keywords"] + ["raar", "strange", "vreemd"] { + test_fail "failed to match second header"; + } +} + +/* + * Basic functionality - foreverypart + */ + +test "Basic functionality - foreverypart" { + foreverypart { + /* Must match */ + if not header :mime :anychild :contains ["Subject", "Comments"] "Frobnitzm" { + test_fail "failed to match header (1)"; + } + + if not header :mime :anychild :contains ["Subject", "Comments"] "nonsense" { + test_fail "failed to match header(2)"; + } + + if not header :mime :anychild :matches "Keywords" "*, strange, *" { + test_fail "failed to match header (3)"; + } + + if not header :mime :anychild :is "Comments" "This is nonsense." { + test_fail "failed to match header (4)"; + } + + /* Must not match */ + if header :mime :anychild ["subject", "comments", "keywords"] "idiotic" { + test_fail "matched nonsense"; + } + + /* Match first key */ + if not header :mime :anychild :contains ["keywords"] ["strange", "snot", "vreemd"] { + test_fail "failed to match first key"; + } + + /* Match second key */ + if not header :mime :anychild :contains ["keywords"] ["raar", "strange", "vreemd"] { + test_fail "failed to match second key"; + } + + /* Match last key */ + if not header :mime :anychild :contains ["keywords"] ["raar", "snot", "strange"] { + test_fail "failed to match last key"; + } + + /* First header */ + if not header :mime :anychild :contains ["keywords", "subject"] + ["raar", "strange", "vreemd"] { + test_fail "failed to match first header"; + } + + /* Second header */ + if not header :mime :anychild :contains ["subject", "keywords"] + ["raar", "strange", "vreemd"] { + test_fail "failed to match second header"; + } + } +} + +/* + * Matching empty key + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.com +X-Caffeine: C8H10N4O2 +Subject: I need coffee! +Comments: + +Text +. +; + +test "Matching empty key" { + if header :mime :anychild :is "X-Caffeine" "" { + test_fail ":is-matched non-empty header with empty string"; + } + + if not header :mime :anychild :contains "X-Caffeine" "" { + test_fail "failed to match existing header with empty string"; + } + + if not header :mime :anychild :is "comments" "" { + test_fail "failed to match empty header :mime :anychild with empty string"; + } + + if header :mime :anychild :contains "X-Nonsense" "" { + test_fail ":contains-matched non-existent header with empty string"; + } +} + +/* + * Matching empty key - foreverypart + */ + +test "Matching empty key - foreverypart" { + foreverypart { + if header :mime :anychild :is "X-Caffeine" "" { + test_fail ":is-matched non-empty header with empty string"; + } + + if not header :mime :anychild :contains "X-Caffeine" "" { + test_fail "failed to match existing header with empty string"; + } + + if not header :mime :anychild :is "comments" "" { + test_fail "failed to match empty header :mime :anychild with empty string"; + } + + if header :mime :anychild :contains "X-Nonsense" "" { + test_fail ":contains-matched non-existent header with empty string"; + } + } +} + +/* + * Ignoring whitespace + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.com +Subject: Help +X-A: Text +X-B: Text + +Text +. +; + +test "Ignoring whitespace" { + if not header :mime :anychild :is "x-a" "Text" { + if header :mime :anychild :matches "x-a" "*" { + set "header" "${1}"; + } + test_fail "header :mime :anychild test does not strip leading whitespace (header=`${header}`)"; + } + + if not header :mime :anychild :is "x-b" "Text" { + if header :mime :anychild :matches "x-b" "*" { + set "header" "${1}"; + } + test_fail "header :mime :anychild test does not strip trailing whitespace (header=`${header}`)"; + } + + if not header :mime :anychild :is "subject" "Help" { + if header :mime :anychild :matches "subject" "*" { + set "header" "${1}"; + } + test_fail "header :mime :anychild test does not strip both leading and trailing whitespace (header=`${header}`)"; + } +} + +/* + * Ignoring whitespace - foreverypart + */ + +test "Ignoring whitespace - foreverypart" { + foreverypart { + if not header :mime :anychild :is "x-a" "Text" { + if header :mime :anychild :matches "x-a" "*" { + set "header" "${1}"; + } + test_fail "header :mime :anychild test does not strip leading whitespace (header=`${header}`)"; + } + + if not header :mime :anychild :is "x-b" "Text" { + if header :mime :anychild :matches "x-b" "*" { + set "header" "${1}"; + } + test_fail "header :mime :anychild test does not strip trailing whitespace (header=`${header}`)"; + } + + if not header :mime :anychild :is "subject" "Help" { + if header :mime :anychild :matches "subject" "*" { + set "header" "${1}"; + } + test_fail "header :mime :anychild test does not strip both leading and trailing whitespace (header=`${header}`)"; + } + } +} + +/* + * Absent or empty header + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.com +CC: harry@nonsense.ex +Subject: +Comments: + +Text +. +; + +test "Absent or empty header" { + if not header :mime :anychild :matches "Cc" "?*" { + test_fail "CC header is not absent or empty"; + } + + if header :mime :anychild :matches "Subject" "?*" { + test_fail "Subject header is empty, but matched otherwise"; + } + + if header :mime :anychild :matches "Comment" "?*" { + test_fail "Comment header is empty, but matched otherwise"; + } +} + +/* + * Absent or empty header - foreverypart + */ + +test "Absent or empty header - foreverypart" { + foreverypart { + if not header :mime :anychild :matches "Cc" "?*" { + test_fail "CC header is not absent or empty"; + } + + if header :mime :anychild :matches "Subject" "?*" { + test_fail "Subject header is empty, but matched otherwise"; + } + + if header :mime :anychild :matches "Comment" "?*" { + test_fail "Comment header is empty, but matched otherwise"; + } + } +} + + +/* + * Invalid header name + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.com +Subject: Valid message +X-Multiline: This is a multi-line + header body, which should be + unfolded correctly. + +Text +. +; + +test "Invalid header name" { + if header :mime :anychild :contains "subject:" "" { + test_fail "matched invalid header name"; + } + + if header :mime :anychild :contains "to!" "" { + test_fail "matched invalid header name"; + } +} + +/* + * Invalid header name - foreverypart + */ + +test "Invalid header name - foreverypart" { + foreverypart { + if header :mime :anychild :contains "subject:" "" { + test_fail "matched invalid header name"; + } + + if header :mime :anychild :contains "to!" "" { + test_fail "matched invalid header name"; + } + } +} + +/* + * Folded headers + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.com +Subject: Not enough space on a line! +X-Multiline: This is a multi-line + header body, which should be + unfolded correctly. + +Text +. +; + +test "Folded headers" { + if not header :mime :anychild :is "x-multiline" + "This is a multi-line header body, which should be unfolded correctly." { + test_fail "failed to properly unfold folded header."; + } +} + +/* + * Folded headers - foreverypart + */ + +test "Folded headers - foreverypart" { + foreverypart { + if not header :mime :anychild :is "x-multiline" + "This is a multi-line header body, which should be unfolded correctly." { + test_fail "failed to properly unfold folded header."; + } + } +} + +/* + * Multipart anychild + */ + +test_set "message" text: +From: Hendrik <hendrik@example.com> +To: Harrie <harrie@example.com> +Date: Sat, 11 Oct 2010 00:31:44 +0200 +Subject: Harrie is een prutser +Content-Type: multipart/mixed; boundary=AA +X-Test: AA + +This is a multi-part message in MIME format. +--AA +Content-Type: multipart/mixed; boundary=BB +X-Test: BB + +This is a multi-part message in MIME format. +--BB +Content-Type: text/plain; charset="us-ascii" +X-Test: CC + +Hello + +--BB +Content-Type: text/plain; charset="us-ascii" +X-Test: DD + +Hello again + +--BB-- +This is the end of MIME multipart. + +--AA +Content-Type: text/plain; charset="us-ascii" +X-Test: EE + +And again + +--AA-- +This is the end of MIME multipart. +. +; + +test "Multipart anychild" { + if not header :mime :anychild "X-Test" "AA" { + test_fail "No AA"; + } + if not header :mime :anychild "X-Test" "BB" { + test_fail "No BB"; + } + if not header :mime :anychild "X-Test" "CC" { + test_fail "No CC"; + } + if not header :mime :anychild "X-Test" "DD" { + test_fail "No DD"; + } + if not header :mime :anychild "X-Test" "EE" { + test_fail "No EE"; + } +} + + diff --git a/pigeonhole/tests/extensions/mime/included/include-foreverypart.sieve b/pigeonhole/tests/extensions/mime/included/include-foreverypart.sieve new file mode 100644 index 0000000..f1b1b16 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/included/include-foreverypart.sieve @@ -0,0 +1,44 @@ +require "include"; +require "foreverypart"; +require "mime"; +require "variables"; + +global "in"; +global "error"; + +foreverypart { + set :length "la" "${in}"; + + if string "${in}" "aa" { + if not header :mime "X-Test" "BB" { + set "error" "wrong header extracted (${la})"; + return; + } + } elsif string "${in}" "aaa" { + if not header :mime "X-Test" "CC" { + set "error" "wrong header extracted (${la})"; + return; + } + } elsif string "${in}" "aaaa" { + if not header :mime "X-Test" "DD" { + set "error" "wrong header extracted (${la})"; + return; + } + } elsif string "${in}" "aaaaa" { + if not header :mime "X-Test" "EE" { + set "error" "wrong header extracted (${la})"; + return; + } + } elsif string "${in}" "aaaaaaa" { + if not header :mime "X-Test" "CC" { + set "error" "wrong header extracted (${la})"; + return; + } + } elsif string "${in}" "aaaaaaaa" { + if not header :mime "X-Test" "DD" { + set "error" "wrong header extracted (${la})"; + return; + } + } + set "in" "a${in}"; +} diff --git a/pigeonhole/tests/extensions/mime/included/include-loop-2.sieve b/pigeonhole/tests/extensions/mime/included/include-loop-2.sieve new file mode 100644 index 0000000..80c5884 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/included/include-loop-2.sieve @@ -0,0 +1,6 @@ +require "foreverypart"; +require "include"; + +foreverypart :name "friep" { + include "include-loop-3"; +} diff --git a/pigeonhole/tests/extensions/mime/included/include-loop-3.sieve b/pigeonhole/tests/extensions/mime/included/include-loop-3.sieve new file mode 100644 index 0000000..228a8bc --- /dev/null +++ b/pigeonhole/tests/extensions/mime/included/include-loop-3.sieve @@ -0,0 +1,6 @@ +require "foreverypart"; +require "include"; + +foreverypart :name "frml" { + include "include-loop-4"; +} diff --git a/pigeonhole/tests/extensions/mime/included/include-loop-4.sieve b/pigeonhole/tests/extensions/mime/included/include-loop-4.sieve new file mode 100644 index 0000000..00dad84 --- /dev/null +++ b/pigeonhole/tests/extensions/mime/included/include-loop-4.sieve @@ -0,0 +1,6 @@ +require "foreverypart"; +require "include"; + +foreverypart { + include "include-loop-5"; +} diff --git a/pigeonhole/tests/extensions/mime/included/include-loop-5.sieve b/pigeonhole/tests/extensions/mime/included/include-loop-5.sieve new file mode 100644 index 0000000..e22b21c --- /dev/null +++ b/pigeonhole/tests/extensions/mime/included/include-loop-5.sieve @@ -0,0 +1,9 @@ +require "foreverypart"; +require "include"; +require "mime"; + +foreverypart { + if header :mime :subtype "content-type" "plain" { + break; + } +} |