summaryrefslogtreecommitdiffstats
path: root/libkmime/tests
diff options
context:
space:
mode:
Diffstat (limited to 'libkmime/tests')
-rw-r--r--libkmime/tests/Makefile.am16
-rw-r--r--libkmime/tests/data/codec_b/basic-decode.b1
-rw-r--r--libkmime/tests/data/codec_b/basic-decode.b.expectedbin0 -> 256 bytes
-rw-r--r--libkmime/tests/data/codec_b/basic-encodebin0 -> 256 bytes
-rw-r--r--libkmime/tests/data/codec_b/basic-encode.expected1
-rw-r--r--libkmime/tests/data/codec_b/null-decode.b0
-rw-r--r--libkmime/tests/data/codec_b/null-decode.b.expected0
-rw-r--r--libkmime/tests/data/codec_b/null-encode0
-rw-r--r--libkmime/tests/data/codec_b/null-encode.expected0
-rw-r--r--libkmime/tests/data/codec_b/padding01
-rw-r--r--libkmime/tests/data/codec_b/padding0.expected1
-rw-r--r--libkmime/tests/data/codec_b/padding11
-rw-r--r--libkmime/tests/data/codec_b/padding1.expected1
-rw-r--r--libkmime/tests/data/codec_b/padding21
-rw-r--r--libkmime/tests/data/codec_b/padding2.expected1
-rw-r--r--libkmime/tests/data/codec_base64/basic-decode.base645
-rw-r--r--libkmime/tests/data/codec_base64/basic-decode.base64.expectedbin0 -> 256 bytes
-rw-r--r--libkmime/tests/data/codec_base64/basic-encodebin0 -> 256 bytes
-rw-r--r--libkmime/tests/data/codec_base64/basic-encode.expected5
-rw-r--r--libkmime/tests/data/codec_base64/corrupt.base645
-rw-r--r--libkmime/tests/data/codec_base64/corrupt.base64.expectedbin0 -> 256 bytes
-rw-r--r--libkmime/tests/data/codec_base64/very_small1
-rw-r--r--libkmime/tests/data/codec_base64/very_small.expected1
-rw-r--r--libkmime/tests/data/codec_q/all-encoded.q1
-rw-r--r--libkmime/tests/data/codec_q/all-encoded.q.expectedbin0 -> 256 bytes
-rw-r--r--libkmime/tests/data/codec_q/basic-encodebin0 -> 256 bytes
-rw-r--r--libkmime/tests/data/codec_q/basic-encode.expected1
-rw-r--r--libkmime/tests/data/codec_q/nothing-encoded.qbin0 -> 256 bytes
-rw-r--r--libkmime/tests/data/codec_q/nothing-encoded.q.expected2
-rw-r--r--libkmime/tests/data/codec_q/null-decode.q0
-rw-r--r--libkmime/tests/data/codec_q/null-decode.q.expected0
-rw-r--r--libkmime/tests/data/codec_q/null-encode0
-rw-r--r--libkmime/tests/data/codec_q/null-encode.expected0
-rw-r--r--libkmime/tests/data/codec_quoted-printable/basic-decode.quoted-printable9
-rw-r--r--libkmime/tests/data/codec_quoted-printable/basic-decode.quoted-printable.expectedbin0 -> 256 bytes
-rw-r--r--libkmime/tests/data/codec_quoted-printable/basic-encodebin0 -> 256 bytes
-rw-r--r--libkmime/tests/data/codec_quoted-printable/basic-encode.expected9
-rw-r--r--libkmime/tests/data/codec_quoted-printable/corrupt.quoted-printable28
-rw-r--r--libkmime/tests/data/codec_quoted-printable/corrupt.quoted-printable.expected20
-rw-r--r--libkmime/tests/data/codec_quoted-printable/wrap44
-rw-r--r--libkmime/tests/data/codec_quoted-printable/wrap.expected64
-rw-r--r--libkmime/tests/data/codec_x-kmime-rfc2231/all-encoded.x-kmime-rfc22311
-rw-r--r--libkmime/tests/data/codec_x-kmime-rfc2231/all-encoded.x-kmime-rfc2231.expectedbin0 -> 256 bytes
-rw-r--r--libkmime/tests/data/codec_x-kmime-rfc2231/basic-encodebin0 -> 256 bytes
-rw-r--r--libkmime/tests/data/codec_x-kmime-rfc2231/basic-encode.expected1
-rw-r--r--libkmime/tests/data/codec_x-kmime-rfc2231/nothing-encoded.x-kmime-rfc2231bin0 -> 256 bytes
-rw-r--r--libkmime/tests/data/codec_x-kmime-rfc2231/nothing-encoded.x-kmime-rfc2231.expected2
-rw-r--r--libkmime/tests/data/codec_x-kmime-rfc2231/null-decode.x-kmime-rfc22310
-rw-r--r--libkmime/tests/data/codec_x-kmime-rfc2231/null-decode.x-kmime-rfc2231.expected0
-rw-r--r--libkmime/tests/data/codec_x-kmime-rfc2231/null-encode0
-rw-r--r--libkmime/tests/data/codec_x-kmime-rfc2231/null-encode.expected0
-rw-r--r--libkmime/tests/data/codec_x-uuencode/basic-decode.x-uuencode9
-rw-r--r--libkmime/tests/data/codec_x-uuencode/basic-decode.x-uuencode.expectedbin0 -> 256 bytes
-rwxr-xr-xlibkmime/tests/gen_decode_map.pl17
-rwxr-xr-xlibkmime/tests/run_codec_tests93
-rw-r--r--libkmime/tests/test_charfreq.cpp41
-rw-r--r--libkmime/tests/test_dates.cpp93
-rw-r--r--libkmime/tests/test_kmime_codec.cpp449
-rw-r--r--libkmime/tests/test_kmime_header_parsing.cpp431
-rw-r--r--libkmime/tests/test_mdn.cpp151
60 files changed, 1507 insertions, 0 deletions
diff --git a/libkmime/tests/Makefile.am b/libkmime/tests/Makefile.am
new file mode 100644
index 000000000..643d99889
--- /dev/null
+++ b/libkmime/tests/Makefile.am
@@ -0,0 +1,16 @@
+AM_CPPFLAGS = -I$(top_srcdir)/libkmime $(all_includes)
+LDADD = ../libkmime.la
+
+# test programs:
+check_PROGRAMS = test_kmime_header_parsing \
+ test_charfreq \
+ test_mdn \
+ test_dates \
+ test_kmime_codec
+
+test_kmime_codec_SOURCES = test_kmime_codec.cpp
+test_charfreq_SOURCES = test_charfreq.cpp
+test_mdn_SOURCES = test_mdn.cpp
+test_dates_SOURCES = test_dates.cpp
+test_kmime_header_parsing_SOURCES = test_kmime_header_parsing.cpp
+
diff --git a/libkmime/tests/data/codec_b/basic-decode.b b/libkmime/tests/data/codec_b/basic-decode.b
new file mode 100644
index 000000000..742532dca
--- /dev/null
+++ b/libkmime/tests/data/codec_b/basic-decode.b
@@ -0,0 +1 @@
+AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w== \ No newline at end of file
diff --git a/libkmime/tests/data/codec_b/basic-decode.b.expected b/libkmime/tests/data/codec_b/basic-decode.b.expected
new file mode 100644
index 000000000..c86626638
--- /dev/null
+++ b/libkmime/tests/data/codec_b/basic-decode.b.expected
Binary files differ
diff --git a/libkmime/tests/data/codec_b/basic-encode b/libkmime/tests/data/codec_b/basic-encode
new file mode 100644
index 000000000..c86626638
--- /dev/null
+++ b/libkmime/tests/data/codec_b/basic-encode
Binary files differ
diff --git a/libkmime/tests/data/codec_b/basic-encode.expected b/libkmime/tests/data/codec_b/basic-encode.expected
new file mode 100644
index 000000000..742532dca
--- /dev/null
+++ b/libkmime/tests/data/codec_b/basic-encode.expected
@@ -0,0 +1 @@
+AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w== \ No newline at end of file
diff --git a/libkmime/tests/data/codec_b/null-decode.b b/libkmime/tests/data/codec_b/null-decode.b
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/libkmime/tests/data/codec_b/null-decode.b
diff --git a/libkmime/tests/data/codec_b/null-decode.b.expected b/libkmime/tests/data/codec_b/null-decode.b.expected
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/libkmime/tests/data/codec_b/null-decode.b.expected
diff --git a/libkmime/tests/data/codec_b/null-encode b/libkmime/tests/data/codec_b/null-encode
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/libkmime/tests/data/codec_b/null-encode
diff --git a/libkmime/tests/data/codec_b/null-encode.expected b/libkmime/tests/data/codec_b/null-encode.expected
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/libkmime/tests/data/codec_b/null-encode.expected
diff --git a/libkmime/tests/data/codec_b/padding0 b/libkmime/tests/data/codec_b/padding0
new file mode 100644
index 000000000..f2ba8f84a
--- /dev/null
+++ b/libkmime/tests/data/codec_b/padding0
@@ -0,0 +1 @@
+abc \ No newline at end of file
diff --git a/libkmime/tests/data/codec_b/padding0.expected b/libkmime/tests/data/codec_b/padding0.expected
new file mode 100644
index 000000000..83ee822d5
--- /dev/null
+++ b/libkmime/tests/data/codec_b/padding0.expected
@@ -0,0 +1 @@
+YWJj \ No newline at end of file
diff --git a/libkmime/tests/data/codec_b/padding1 b/libkmime/tests/data/codec_b/padding1
new file mode 100644
index 000000000..9ae9e86b7
--- /dev/null
+++ b/libkmime/tests/data/codec_b/padding1
@@ -0,0 +1 @@
+ab \ No newline at end of file
diff --git a/libkmime/tests/data/codec_b/padding1.expected b/libkmime/tests/data/codec_b/padding1.expected
new file mode 100644
index 000000000..ea0a9ede2
--- /dev/null
+++ b/libkmime/tests/data/codec_b/padding1.expected
@@ -0,0 +1 @@
+YWI= \ No newline at end of file
diff --git a/libkmime/tests/data/codec_b/padding2 b/libkmime/tests/data/codec_b/padding2
new file mode 100644
index 000000000..2e65efe2a
--- /dev/null
+++ b/libkmime/tests/data/codec_b/padding2
@@ -0,0 +1 @@
+a \ No newline at end of file
diff --git a/libkmime/tests/data/codec_b/padding2.expected b/libkmime/tests/data/codec_b/padding2.expected
new file mode 100644
index 000000000..3b15ffb5e
--- /dev/null
+++ b/libkmime/tests/data/codec_b/padding2.expected
@@ -0,0 +1 @@
+YQ== \ No newline at end of file
diff --git a/libkmime/tests/data/codec_base64/basic-decode.base64 b/libkmime/tests/data/codec_base64/basic-decode.base64
new file mode 100644
index 000000000..da6724734
--- /dev/null
+++ b/libkmime/tests/data/codec_base64/basic-decode.base64
@@ -0,0 +1,5 @@
+AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4
+OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3Bx
+cnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmq
+q6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj
+5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==
diff --git a/libkmime/tests/data/codec_base64/basic-decode.base64.expected b/libkmime/tests/data/codec_base64/basic-decode.base64.expected
new file mode 100644
index 000000000..c86626638
--- /dev/null
+++ b/libkmime/tests/data/codec_base64/basic-decode.base64.expected
Binary files differ
diff --git a/libkmime/tests/data/codec_base64/basic-encode b/libkmime/tests/data/codec_base64/basic-encode
new file mode 100644
index 000000000..c86626638
--- /dev/null
+++ b/libkmime/tests/data/codec_base64/basic-encode
Binary files differ
diff --git a/libkmime/tests/data/codec_base64/basic-encode.expected b/libkmime/tests/data/codec_base64/basic-encode.expected
new file mode 100644
index 000000000..da6724734
--- /dev/null
+++ b/libkmime/tests/data/codec_base64/basic-encode.expected
@@ -0,0 +1,5 @@
+AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4
+OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3Bx
+cnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmq
+q6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj
+5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==
diff --git a/libkmime/tests/data/codec_base64/corrupt.base64 b/libkmime/tests/data/codec_base64/corrupt.base64
new file mode 100644
index 000000000..1d13f2431
--- /dev/null
+++ b/libkmime/tests/data/codec_base64/corrupt.base64
@@ -0,0 +1,5 @@
+A AECAwQ-FBgcICQoLDA0OD&xAREhM
+UFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4
+OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmq
+q6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIüycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj
+5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==ghfh \ No newline at end of file
diff --git a/libkmime/tests/data/codec_base64/corrupt.base64.expected b/libkmime/tests/data/codec_base64/corrupt.base64.expected
new file mode 100644
index 000000000..c86626638
--- /dev/null
+++ b/libkmime/tests/data/codec_base64/corrupt.base64.expected
Binary files differ
diff --git a/libkmime/tests/data/codec_base64/very_small b/libkmime/tests/data/codec_base64/very_small
new file mode 100644
index 000000000..3cacc0b93
--- /dev/null
+++ b/libkmime/tests/data/codec_base64/very_small
@@ -0,0 +1 @@
+12 \ No newline at end of file
diff --git a/libkmime/tests/data/codec_base64/very_small.expected b/libkmime/tests/data/codec_base64/very_small.expected
new file mode 100644
index 000000000..7f9ade1ac
--- /dev/null
+++ b/libkmime/tests/data/codec_base64/very_small.expected
@@ -0,0 +1 @@
+MTI=
diff --git a/libkmime/tests/data/codec_q/all-encoded.q b/libkmime/tests/data/codec_q/all-encoded.q
new file mode 100644
index 000000000..a421bb40d
--- /dev/null
+++ b/libkmime/tests/data/codec_q/all-encoded.q
@@ -0,0 +1 @@
+=00=01=02=03=04=05=06=07=08=09=0A=0B=0C=0D=0E=0F=10=11=12=13=14=15=16=17=18=19=1A=1B=1C=1D=1E=1F=20=21=22=23=24=25=26=27=28=29=2A=2B=2C=2D=2E=2F=30=31=32=33=34=35=36=37=38=39=3A=3B=3C=3D=3E=3F=40=41=42=43=44=45=46=47=48=49=4A=4B=4C=4D=4E=4F=50=51=52=53=54=55=56=57=58=59=5A=5B=5C=5D=5E=5F=60=61=62=63=64=65=66=67=68=69=6A=6B=6C=6D=6E=6F=70=71=72=73=74=75=76=77=78=79=7A=7B=7C=7D=7E=7F=80=81=82=83=84=85=86=87=88=89=8A=8B=8C=8D=8E=8F=90=91=92=93=94=95=96=97=98=99=9A=9B=9C=9D=9E=9F=A0=A1=A2=A3=A4=A5=A6=A7=A8=A9=AA=AB=AC=AD=AE=AF=B0=B1=B2=B3=B4=B5=B6=B7=B8=B9=BA=BB=BC=BD=BE=BF=C0=C1=C2=C3=C4=C5=C6=C7=C8=C9=CA=CB=CC=CD=CE=CF=D0=D1=D2=D3=D4=D5=D6=D7=D8=D9=DA=DB=DC=DD=DE=DF=E0=E1=E2=E3=E4=E5=E6=E7=E8=E9=EA=EB=EC=ED=EE=EF=F0=F1=F2=F3=F4=F5=F6=F7=F8=F9=FA=FB=FC=FD=FE=FF \ No newline at end of file
diff --git a/libkmime/tests/data/codec_q/all-encoded.q.expected b/libkmime/tests/data/codec_q/all-encoded.q.expected
new file mode 100644
index 000000000..c86626638
--- /dev/null
+++ b/libkmime/tests/data/codec_q/all-encoded.q.expected
Binary files differ
diff --git a/libkmime/tests/data/codec_q/basic-encode b/libkmime/tests/data/codec_q/basic-encode
new file mode 100644
index 000000000..c86626638
--- /dev/null
+++ b/libkmime/tests/data/codec_q/basic-encode
Binary files differ
diff --git a/libkmime/tests/data/codec_q/basic-encode.expected b/libkmime/tests/data/codec_q/basic-encode.expected
new file mode 100644
index 000000000..8f051a201
--- /dev/null
+++ b/libkmime/tests/data/codec_q/basic-encode.expected
@@ -0,0 +1 @@
+=00=01=02=03=04=05=06=07=08=09=0A=0B=0C=0D=0E=0F=10=11=12=13=14=15=16=17=18=19=1A=1B=1C=1D=1E=1F_!=22=23=24=25=26=27=28=29*+=2C-=2E/0123456789=3A=3B=3C=3D=3E=3F=40ABCDEFGHIJKLMNOPQRSTUVWXYZ=5B=5C=5D=5E=5F=60abcdefghijklmnopqrstuvwxyz=7B=7C=7D=7E=7F=80=81=82=83=84=85=86=87=88=89=8A=8B=8C=8D=8E=8F=90=91=92=93=94=95=96=97=98=99=9A=9B=9C=9D=9E=9F=A0=A1=A2=A3=A4=A5=A6=A7=A8=A9=AA=AB=AC=AD=AE=AF=B0=B1=B2=B3=B4=B5=B6=B7=B8=B9=BA=BB=BC=BD=BE=BF=C0=C1=C2=C3=C4=C5=C6=C7=C8=C9=CA=CB=CC=CD=CE=CF=D0=D1=D2=D3=D4=D5=D6=D7=D8=D9=DA=DB=DC=DD=DE=DF=E0=E1=E2=E3=E4=E5=E6=E7=E8=E9=EA=EB=EC=ED=EE=EF=F0=F1=F2=F3=F4=F5=F6=F7=F8=F9=FA=FB=FC=FD=FE=FF \ No newline at end of file
diff --git a/libkmime/tests/data/codec_q/nothing-encoded.q b/libkmime/tests/data/codec_q/nothing-encoded.q
new file mode 100644
index 000000000..c86626638
--- /dev/null
+++ b/libkmime/tests/data/codec_q/nothing-encoded.q
Binary files differ
diff --git a/libkmime/tests/data/codec_q/nothing-encoded.q.expected b/libkmime/tests/data/codec_q/nothing-encoded.q.expected
new file mode 100644
index 000000000..8323fc635
--- /dev/null
+++ b/libkmime/tests/data/codec_q/nothing-encoded.q.expected
@@ -0,0 +1,2 @@
+
+ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^ `abcdefghijklmnopqrstuvwxyz{|}~ \ No newline at end of file
diff --git a/libkmime/tests/data/codec_q/null-decode.q b/libkmime/tests/data/codec_q/null-decode.q
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/libkmime/tests/data/codec_q/null-decode.q
diff --git a/libkmime/tests/data/codec_q/null-decode.q.expected b/libkmime/tests/data/codec_q/null-decode.q.expected
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/libkmime/tests/data/codec_q/null-decode.q.expected
diff --git a/libkmime/tests/data/codec_q/null-encode b/libkmime/tests/data/codec_q/null-encode
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/libkmime/tests/data/codec_q/null-encode
diff --git a/libkmime/tests/data/codec_q/null-encode.expected b/libkmime/tests/data/codec_q/null-encode.expected
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/libkmime/tests/data/codec_q/null-encode.expected
diff --git a/libkmime/tests/data/codec_quoted-printable/basic-decode.quoted-printable b/libkmime/tests/data/codec_quoted-printable/basic-decode.quoted-printable
new file mode 100644
index 000000000..47b7e654e
--- /dev/null
+++ b/libkmime/tests/data/codec_quoted-printable/basic-decode.quoted-printable
@@ -0,0 +1,9 @@
+=00=01=02=03=04=05=06=07=08=09
+=0B=0C=0D=0E=0F=10=11=12=13=14=15=16=17=18=19=1A=1B=1C=1D=1E=1F !"#$%&'()*+=
+,-./0123456789:;<=3D>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrst=
+uvwxyz{|}~=7F=80=81=82=83=84=85=86=87=88=89=8A=8B=8C=8D=8E=8F=90=91=92=93=
+=94=95=96=97=98=99=9A=9B=9C=9D=9E=9F=A0=A1=A2=A3=A4=A5=A6=A7=A8=A9=AA=AB=AC=
+=AD=AE=AF=B0=B1=B2=B3=B4=B5=B6=B7=B8=B9=BA=BB=BC=BD=BE=BF=C0=C1=C2=C3=C4=C5=
+=C6=C7=C8=C9=CA=CB=CC=CD=CE=CF=D0=D1=D2=D3=D4=D5=D6=D7=D8=D9=DA=DB=DC=DD=DE=
+=DF=E0=E1=E2=E3=E4=E5=E6=E7=E8=E9=EA=EB=EC=ED=EE=EF=F0=F1=F2=F3=F4=F5=F6=F7=
+=F8=F9=FA=FB=FC=FD=FE=FF \ No newline at end of file
diff --git a/libkmime/tests/data/codec_quoted-printable/basic-decode.quoted-printable.expected b/libkmime/tests/data/codec_quoted-printable/basic-decode.quoted-printable.expected
new file mode 100644
index 000000000..c86626638
--- /dev/null
+++ b/libkmime/tests/data/codec_quoted-printable/basic-decode.quoted-printable.expected
Binary files differ
diff --git a/libkmime/tests/data/codec_quoted-printable/basic-encode b/libkmime/tests/data/codec_quoted-printable/basic-encode
new file mode 100644
index 000000000..c86626638
--- /dev/null
+++ b/libkmime/tests/data/codec_quoted-printable/basic-encode
Binary files differ
diff --git a/libkmime/tests/data/codec_quoted-printable/basic-encode.expected b/libkmime/tests/data/codec_quoted-printable/basic-encode.expected
new file mode 100644
index 000000000..47b7e654e
--- /dev/null
+++ b/libkmime/tests/data/codec_quoted-printable/basic-encode.expected
@@ -0,0 +1,9 @@
+=00=01=02=03=04=05=06=07=08=09
+=0B=0C=0D=0E=0F=10=11=12=13=14=15=16=17=18=19=1A=1B=1C=1D=1E=1F !"#$%&'()*+=
+,-./0123456789:;<=3D>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrst=
+uvwxyz{|}~=7F=80=81=82=83=84=85=86=87=88=89=8A=8B=8C=8D=8E=8F=90=91=92=93=
+=94=95=96=97=98=99=9A=9B=9C=9D=9E=9F=A0=A1=A2=A3=A4=A5=A6=A7=A8=A9=AA=AB=AC=
+=AD=AE=AF=B0=B1=B2=B3=B4=B5=B6=B7=B8=B9=BA=BB=BC=BD=BE=BF=C0=C1=C2=C3=C4=C5=
+=C6=C7=C8=C9=CA=CB=CC=CD=CE=CF=D0=D1=D2=D3=D4=D5=D6=D7=D8=D9=DA=DB=DC=DD=DE=
+=DF=E0=E1=E2=E3=E4=E5=E6=E7=E8=E9=EA=EB=EC=ED=EE=EF=F0=F1=F2=F3=F4=F5=F6=F7=
+=F8=F9=FA=FB=FC=FD=FE=FF \ No newline at end of file
diff --git a/libkmime/tests/data/codec_quoted-printable/corrupt.quoted-printable b/libkmime/tests/data/codec_quoted-printable/corrupt.quoted-printable
new file mode 100644
index 000000000..ca67337f8
--- /dev/null
+++ b/libkmime/tests/data/codec_quoted-printable/corrupt.quoted-printable
@@ -0,0 +1,28 @@
+Trailing spaces should be stripped:
+Here, only five trailing spaces should appear: =20
+Trailing tabs should be stripped:
+Here, only five trailing spaces should appear: =20
+Trailing mixture of tabs and spaces should be stripped:
+Trailing mixture of tabs and spaces should be stripped:
+Tab, space, space, tab: =09
+Space, tab, tab, space: =20
+
+Trailing spaces should=
+ be stripped:
+Trailing tabs should=
+ be stripped:
+Trailing mixture of tabs=
+ and spaces=
+ should be stripped:
+Tab, space, space, tab: =
+Space, tab, tab, space: =
+The end.
+
+A =3D wasn't properly encoded (should be kept): APE=MAN MAN=APE
+A =3D wasn't properly encoded (lowercase): ape=man man=ape
+Lowercase hexchars: =bb=a1=4b=44=45 =72=75=6c=65=7a=21=ab
+Mixed-case hexchars: =Bb=A1=4B=44=45 =72=75=6C=65=7A=21=aB
+A misplaced (unencoded =3D), followed by whitespace: = not at end!
+Two consecutive =3D at the end of the line: ==
+Same, followed by trailing whitespace: ==
+A misplaced (unencoded =3D), as the ultimate character: = \ No newline at end of file
diff --git a/libkmime/tests/data/codec_quoted-printable/corrupt.quoted-printable.expected b/libkmime/tests/data/codec_quoted-printable/corrupt.quoted-printable.expected
new file mode 100644
index 000000000..18993c21f
--- /dev/null
+++ b/libkmime/tests/data/codec_quoted-printable/corrupt.quoted-printable.expected
@@ -0,0 +1,20 @@
+Trailing spaces should be stripped:
+Here, only five trailing spaces should appear:
+Trailing tabs should be stripped:
+Here, only five trailing spaces should appear:
+Trailing mixture of tabs and spaces should be stripped:
+Trailing mixture of tabs and spaces should be stripped:
+Tab, space, space, tab:
+Space, tab, tab, space:
+
+Trailing spaces should be stripped:
+Trailing tabs should be stripped:
+Trailing mixture of tabs and spaces should be stripped:
+Tab, space, space, tab: Space, tab, tab, space: The end.
+
+A = wasn't properly encoded (should be kept): APE=MAN MAN=APE
+A = wasn't properly encoded (lowercase): ape=man man=ape
+Lowercase hexchars: »¡KDE rulez!«
+Mixed-case hexchars: »¡KDE rulez!«
+A misplaced (unencoded =), followed by whitespace: = not at end!
+Two consecutive = at the end of the line: =Same, followed by trailing whitespace: =A misplaced (unencoded =), as the ultimate character: = \ No newline at end of file
diff --git a/libkmime/tests/data/codec_quoted-printable/wrap b/libkmime/tests/data/codec_quoted-printable/wrap
new file mode 100644
index 000000000..49e8a9ccd
--- /dev/null
+++ b/libkmime/tests/data/codec_quoted-printable/wrap
@@ -0,0 +1,44 @@
+This is a line without a special char at the end.
+This is a line with a space at the end.
+This is a line with multiple spaces at the end.
+This is a line with a tab at the end.
+This is a line with an umlaut at the end.ä
+This is a line with an umlaut and a space at the end.ä
+This is a line with an umlaut and a tab at the end.ä
+From This is a line with From at the beginning.
+.This is a line with a dot at the beginning.
+-This is a line with a dash at the beginning.
+
+This is a very long line (ä ) which just happens to be wrapped so that a From appears at the beginning of the second line. Furthermore, this break. makes a dot appear as the first character on the third line.
+
+Just long enough: xxxxxxxx This is a line without a special char at the end.
+Just too long: xxxxxxxxxxxx This is a line without a special char at the end.
+xxxxxxxxxxxxxxxxxxxxxxxxxxxx This is a line without a special char at the end.
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxx This is a line without a special char at the end.
+
+Just long enough: xxxxxxxxxxxxxxx This is a line with a space at the end.
+Just too long: xxxxxxxxxxxxxxxxxxx This is a line with a space at the end.
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx This is a line with a space at the end.
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx This is a line with a space at the end.
+
+Just long enough: xxxxxxxxxxxxxxxxx This is a line with a tab at the end.
+Just too long: xxxxxxxxxxxxxxxxxxxxx This is a line with a tab at the end.
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx This is a line with a tab at the end.
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx This is a line with a tab at the end.
+
+Just long enough: xxxxxxxxxxxxx This is a line with an umlaut at the end.ä
+Just too long: xxxxxxxxxxxxxxxxx This is a line with an umlaut at the end.ä
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx This is a line with an umlaut at the end.ä
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx This is a line with an umlaut at the end.ä
+
+Just long enough This is a line with an umlaut and a space at the end.ä
+Just too long: xx This is a line with an umlaut and a space at the end.ä
+xxxxxxxxxxxxxxxxxx This is a line with an umlaut and a space at the end.ä
+xxxxxxxxxxxxxxxxxxx This is a line with an umlaut and a space at the end.ä
+
+Just long enough: This is a line with an umlaut and a tab at the end.ä
+Just too long: xxxx This is a line with an umlaut and a tab at the end.ä
+xxxxxxxxxxxxxxxxxxxx This is a line with an umlaut and a tab at the end.ä
+xxxxxxxxxxxxxxxxxxxxx This is a line with an umlaut and a tab at the end.ä
+
+This line has a space at the end and ends the buffer \ No newline at end of file
diff --git a/libkmime/tests/data/codec_quoted-printable/wrap.expected b/libkmime/tests/data/codec_quoted-printable/wrap.expected
new file mode 100644
index 000000000..b95c65523
--- /dev/null
+++ b/libkmime/tests/data/codec_quoted-printable/wrap.expected
@@ -0,0 +1,64 @@
+This is a line without a special char at the end.
+This is a line with a space at the end.=20
+This is a line with multiple spaces at the end. =20
+This is a line with a tab at the end.=09
+This is a line with an umlaut at the end.=E4
+This is a line with an umlaut and a space at the end.=E4=20
+This is a line with an umlaut and a tab at the end.=E4=09
+=46rom This is a line with From at the beginning.
+=2EThis is a line with a dot at the beginning.
+=2DThis is a line with a dash at the beginning.
+
+This is a very long line (=E4 ) which just happens to be wrapped so that a =
+=46rom appears at the beginning of the second line. Furthermore, this break=
+=2E makes a dot appear as the first character on the third line.
+
+Just long enough: xxxxxxxx This is a line without a special char at the end.
+Just too long: xxxxxxxxxxxx This is a line without a special char at the en=
+d.
+xxxxxxxxxxxxxxxxxxxxxxxxxxxx This is a line without a special char at the e=
+nd.
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxx This is a line without a special char at the =
+end.
+
+Just long enough: xxxxxxxxxxxxxxx This is a line with a space at the end.=20
+Just too long: xxxxxxxxxxxxxxxxxxx This is a line with a space at the end.=
+=20
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx This is a line with a space at the end.=
+=20
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx This is a line with a space at the end=
+=2E=20
+
+Just long enough: xxxxxxxxxxxxxxxxx This is a line with a tab at the end.=09
+Just too long: xxxxxxxxxxxxxxxxxxxxx This is a line with a tab at the end.=
+=09
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx This is a line with a tab at the end.=
+=09
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx This is a line with a tab at the end=
+=2E=09
+
+Just long enough: xxxxxxxxxxxxx This is a line with an umlaut at the end.=E4
+Just too long: xxxxxxxxxxxxxxxxx This is a line with an umlaut at the end.=
+=E4
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx This is a line with an umlaut at the end.=
+=E4
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx This is a line with an umlaut at the end=
+=2E=E4
+
+Just long enough This is a line with an umlaut and a space at the end.=E4=20
+Just too long: xx This is a line with an umlaut and a space at the end.=E4=
+=20
+xxxxxxxxxxxxxxxxxx This is a line with an umlaut and a space at the end.=E4=
+=20
+xxxxxxxxxxxxxxxxxxx This is a line with an umlaut and a space at the end.=
+=E4=20
+
+Just long enough: This is a line with an umlaut and a tab at the end.=E4=09
+Just too long: xxxx This is a line with an umlaut and a tab at the end.=E4=
+=09
+xxxxxxxxxxxxxxxxxxxx This is a line with an umlaut and a tab at the end.=E4=
+=09
+xxxxxxxxxxxxxxxxxxxxx This is a line with an umlaut and a tab at the end.=
+=E4=09
+
+This line has a space at the end and ends the buffer=20 \ No newline at end of file
diff --git a/libkmime/tests/data/codec_x-kmime-rfc2231/all-encoded.x-kmime-rfc2231 b/libkmime/tests/data/codec_x-kmime-rfc2231/all-encoded.x-kmime-rfc2231
new file mode 100644
index 000000000..03bc48165
--- /dev/null
+++ b/libkmime/tests/data/codec_x-kmime-rfc2231/all-encoded.x-kmime-rfc2231
@@ -0,0 +1 @@
+%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20%21%22%23%24%25%26%27%28%29%2A%2B%2C%2D%2E%2F%30%31%32%33%34%35%36%37%38%39%3A%3B%3C%3D%3E%3F%40%41%42%43%44%45%46%47%48%49%4A%4B%4C%4D%4E%4F%50%51%52%53%54%55%56%57%58%59%5A%5B%5C%5D%5E%5F%60%61%62%63%64%65%66%67%68%69%6A%6B%6C%6D%6E%6F%70%71%72%73%74%75%76%77%78%79%7A%7B%7C%7D%7E%7F%80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF \ No newline at end of file
diff --git a/libkmime/tests/data/codec_x-kmime-rfc2231/all-encoded.x-kmime-rfc2231.expected b/libkmime/tests/data/codec_x-kmime-rfc2231/all-encoded.x-kmime-rfc2231.expected
new file mode 100644
index 000000000..c86626638
--- /dev/null
+++ b/libkmime/tests/data/codec_x-kmime-rfc2231/all-encoded.x-kmime-rfc2231.expected
Binary files differ
diff --git a/libkmime/tests/data/codec_x-kmime-rfc2231/basic-encode b/libkmime/tests/data/codec_x-kmime-rfc2231/basic-encode
new file mode 100644
index 000000000..c86626638
--- /dev/null
+++ b/libkmime/tests/data/codec_x-kmime-rfc2231/basic-encode
Binary files differ
diff --git a/libkmime/tests/data/codec_x-kmime-rfc2231/basic-encode.expected b/libkmime/tests/data/codec_x-kmime-rfc2231/basic-encode.expected
new file mode 100644
index 000000000..61c504b7b
--- /dev/null
+++ b/libkmime/tests/data/codec_x-kmime-rfc2231/basic-encode.expected
@@ -0,0 +1 @@
+%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20!%22%23%24%25%26%27%28%29%2A+%2C-%2E%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E%5F%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D%7E%7F%80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF \ No newline at end of file
diff --git a/libkmime/tests/data/codec_x-kmime-rfc2231/nothing-encoded.x-kmime-rfc2231 b/libkmime/tests/data/codec_x-kmime-rfc2231/nothing-encoded.x-kmime-rfc2231
new file mode 100644
index 000000000..c86626638
--- /dev/null
+++ b/libkmime/tests/data/codec_x-kmime-rfc2231/nothing-encoded.x-kmime-rfc2231
Binary files differ
diff --git a/libkmime/tests/data/codec_x-kmime-rfc2231/nothing-encoded.x-kmime-rfc2231.expected b/libkmime/tests/data/codec_x-kmime-rfc2231/nothing-encoded.x-kmime-rfc2231.expected
new file mode 100644
index 000000000..8323fc635
--- /dev/null
+++ b/libkmime/tests/data/codec_x-kmime-rfc2231/nothing-encoded.x-kmime-rfc2231.expected
@@ -0,0 +1,2 @@
+
+ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^ `abcdefghijklmnopqrstuvwxyz{|}~ \ No newline at end of file
diff --git a/libkmime/tests/data/codec_x-kmime-rfc2231/null-decode.x-kmime-rfc2231 b/libkmime/tests/data/codec_x-kmime-rfc2231/null-decode.x-kmime-rfc2231
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/libkmime/tests/data/codec_x-kmime-rfc2231/null-decode.x-kmime-rfc2231
diff --git a/libkmime/tests/data/codec_x-kmime-rfc2231/null-decode.x-kmime-rfc2231.expected b/libkmime/tests/data/codec_x-kmime-rfc2231/null-decode.x-kmime-rfc2231.expected
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/libkmime/tests/data/codec_x-kmime-rfc2231/null-decode.x-kmime-rfc2231.expected
diff --git a/libkmime/tests/data/codec_x-kmime-rfc2231/null-encode b/libkmime/tests/data/codec_x-kmime-rfc2231/null-encode
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/libkmime/tests/data/codec_x-kmime-rfc2231/null-encode
diff --git a/libkmime/tests/data/codec_x-kmime-rfc2231/null-encode.expected b/libkmime/tests/data/codec_x-kmime-rfc2231/null-encode.expected
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/libkmime/tests/data/codec_x-kmime-rfc2231/null-encode.expected
diff --git a/libkmime/tests/data/codec_x-uuencode/basic-decode.x-uuencode b/libkmime/tests/data/codec_x-uuencode/basic-decode.x-uuencode
new file mode 100644
index 000000000..365e61ddf
--- /dev/null
+++ b/libkmime/tests/data/codec_x-uuencode/basic-decode.x-uuencode
@@ -0,0 +1,9 @@
+begin 664 foo
+M``$"`P0%!@<("0H+#`T.#Q`1$A,4%187&!D:&QP='A\@(2(C)"4F)R@I*BLL
+M+2XO,#$R,S0U-C<X.3H[/#T^/T!!0D-$149'2$E*2TQ-3D]045)35%565UA9
+M6EM<75Y?8&%B8V1E9F=H:6IK;&UN;W!Q<G-T=79W>'EZ>WQ]?G^`@8*#A(6&
+MAXB)BHN,C8Z/D)&2DY25EI>8F9J;G)V>GZ"AHJ.DI::GJ*FJJZRMKJ^PL;*S
+MM+6VM[BYNKN\O;Z_P,'"P\3%QL?(R<K+S,W.S]#1TM/4U=;7V-G:V]S=WM_@
+?X>+CY.7FY^CIZNOL[>[O\/'R\_3U]O?X^?K[_/W^_P``
+`
+end
diff --git a/libkmime/tests/data/codec_x-uuencode/basic-decode.x-uuencode.expected b/libkmime/tests/data/codec_x-uuencode/basic-decode.x-uuencode.expected
new file mode 100644
index 000000000..c86626638
--- /dev/null
+++ b/libkmime/tests/data/codec_x-uuencode/basic-decode.x-uuencode.expected
Binary files differ
diff --git a/libkmime/tests/gen_decode_map.pl b/libkmime/tests/gen_decode_map.pl
new file mode 100755
index 000000000..131aef1e7
--- /dev/null
+++ b/libkmime/tests/gen_decode_map.pl
@@ -0,0 +1,17 @@
+#!/usr/bin/perl -w
+
+use strict;
+
+my @encodingMap = ( 'A' .. 'Z', 'a' .. 'z', '0' .. '9', '+', '/' );
+my @decodingMap = (64) x 128;
+
+my $len = scalar @encodingMap;
+for ( my $i = 0 ; $i < $len ; $i++ ) {
+ my $value = ord $encodingMap[$i];
+ $decodingMap[$value] = $i;
+}
+
+for ( my $i = 0 ; $i < 128 ; $i += 16 ) {
+ print " ", join( ", ", @decodingMap[$i..($i+7)] ), ", ",
+ join( ", ", @decodingMap[($i+8)..($i+15)] ), ",\n";
+}
diff --git a/libkmime/tests/run_codec_tests b/libkmime/tests/run_codec_tests
new file mode 100755
index 000000000..62908eeec
--- /dev/null
+++ b/libkmime/tests/run_codec_tests
@@ -0,0 +1,93 @@
+#!/bin/bash
+
+TEST="./test_kmime_codec"
+#BUFFER_SIZES="$(seq 7)"
+#BUFFER_SIZES="$(seq 5) 15 16 17 23 24 25 31 32 33 4096"
+BUFFER_SIZES="$(seq 17) 23 24 25 31 32 33 4096"
+USAGE_PATTERNS="chunkwise kio"
+
+oldDirName=""
+encoding=""
+action=""
+inFile=""
+resultFile=""
+
+totalTests=0
+passedTests=0
+failedTests=0
+
+# loop over all .expected files in the directory
+# specified by the single argument:
+
+for i in $(find "$@" -type f -name '*.expected'); do
+ dirName="$(dirname "$i")"
+ if [ "$dirName" != "$oldDirName" ]; then
+ oldDirName="$dirName"
+ # new directory: extract encoding
+ encoding="$(basename "$dirName")"
+ encoding="${encoding#codec_}"
+ echo Entering directory \"$dirName\".
+ echo Using encoding \"$encoding\".
+ fi
+
+ testName="$(basename "$i")"
+ testName="${testName%.expected}"
+ echo "testName=$testName"
+ inFile="$dirName/$testName"
+ echo "inFile=$inFile"
+ if [ "${testName%.$encoding}" != "$testName" ]; then
+ testName="${testName%.$encoding}"
+ action="--decode"
+ else
+ #testName stays the same
+ action="--encode"
+ fi
+ resultFile="$dirName/$testName.result"
+ echo "resultFile=$resultFile"
+ echo performing ${action#--} test \"$testName\"
+ for usagePattern in $(echo $USAGE_PATTERNS); do
+ for insize in -1 $(echo $BUFFER_SIZES); do
+ for outsize in $(echo $BUFFER_SIZES); do
+ let "totalTests++"
+ if [ "$insize" == "-1" ]; then
+ #omit --input-buffer-size
+ $TEST $action $encoding \
+ --usage-pattern $usagePattern \
+ --output-buffer-size $outsize \
+ --outfile "$resultFile" \
+ "$inFile" \
+ > /dev/null 2> /dev/null
+ else
+ $TEST $action $encoding \
+ --usage-pattern $usagePattern \
+ --input-buffer-size $insize \
+ --output-buffer-size $outsize \
+ --outfile "$resultFile" \
+ "$inFile" \
+ > /dev/null 2> /dev/null
+ fi
+ result=$?
+ case $result in
+ 0)
+ if cmp "$i" "$resultFile" >/dev/null 2>/dev/null ; then
+ let "passedTests++"
+ else
+ let "failedTests++"
+ mv "$resultFile" "$resultfile.failed.$usagePattern.$insize-$outsize"
+ fi
+ ;;
+ *)
+ let "failedTests++"
+ mv "$resultFile" "$resultFile.failed.$usagePattern.$insize-$outsize-$result" || touch "$resultFile.failed.$insize-$outsize-$result"
+ ;;
+ esac
+ rm -rf "$resultFile"
+ done
+ done
+ done
+ if [ $totalTests != $passedTests ]; then
+ echo "some tests failed."
+ fi
+done
+
+echo "TOTAL: $totalTests; PASSED: $passedTests; FAILED: $failedTests;"
diff --git a/libkmime/tests/test_charfreq.cpp b/libkmime/tests/test_charfreq.cpp
new file mode 100644
index 000000000..c5b708819
--- /dev/null
+++ b/libkmime/tests/test_charfreq.cpp
@@ -0,0 +1,41 @@
+// test program for KMime::CharFreq.
+// compile with g++ -I$QTDIR/include -L$QTDIR/lib -lqt(-mt) \
+// -o test_charfreq test_charfreq.cpp
+
+#include "../kmime_charfreq.cpp"
+
+#include <iostream>
+
+#include <qfile.h>
+
+using namespace std;
+using namespace KMime;
+
+static const char * typeToString( int type ) {
+ switch ( type ) {
+ case CharFreq::EightBitData:
+ return "eight bit data (binary)";
+ case CharFreq::EightBitText:
+ return "eight bit text";
+ case CharFreq::SevenBitData:
+ return "seven bit data";
+ case CharFreq::SevenBitText:
+ return "seven bit text";
+ default:
+ return "unknown type";
+ }
+}
+
+int main( int argc, char **argv ) {
+ for ( int i = 1 /*not program*/ ; i < argc ; i++ ) {
+ QFile in( argv[i] );
+ if ( !in.open( IO_ReadOnly ) ) {
+ cerr << argv[i] << ": does not exist!" << endl;
+ continue;
+ }
+ QByteArray ba = in.readAll();
+ CharFreq cf( ba );
+ cout << argv[i] << ": " << typeToString(cf.type()) << endl;
+ }
+ return 0;
+}
diff --git a/libkmime/tests/test_dates.cpp b/libkmime/tests/test_dates.cpp
new file mode 100644
index 000000000..f70269282
--- /dev/null
+++ b/libkmime/tests/test_dates.cpp
@@ -0,0 +1,93 @@
+#include <kmime_util.h>
+#include <kmime_header_parsing.h>
+#include <kdebug.h>
+#include <kinstance.h>
+using namespace KMime;
+
+
+int
+main()
+{
+ KInstance app("# ");
+ DateFormatter t;
+
+ time_t ntime = time(0);
+ kdDebug()<<"Time now:"<<endl;
+ kdDebug()<<"\tFancy : \t"<<t.dateString(ntime)<<endl;
+ t.setFormat(DateFormatter::Localized);
+ kdDebug()<<"\tLocalized : \t"<<t.dateString(ntime)<<endl;
+ t.setFormat(DateFormatter::CTime);
+ kdDebug()<<"\tCTime : \t"<<t.dateString(ntime)<<endl;
+ t.setFormat(DateFormatter::Iso);
+ kdDebug()<<"\tIso : \t"<<t.dateString(ntime)<<endl;
+ kdDebug()<<"\trfc2822 : \t"<<t.rfc2822(ntime)<<endl;
+ QString rfcd = t.rfc2822(ntime);
+ Types::DateTime dt;
+ QDateTime qdt;
+ const char *str = rfcd.latin1();
+ if ( HeaderParsing::parseDateTime( str, str + rfcd.length(), dt ) ) {
+ kdDebug()<<"@@@ ntime = "<<(ntime)<<", dt = "<<(dt.time)<<endl;
+ qdt.setTime_t( dt.time );
+ kdDebug()<<"@@@ qq = "<< qdt.toString("ddd, dd MMM yyyy hh:mm:ss") <<endl;
+ kdDebug()<<"@@@ rfc2822 : "<<t.rfc2822(dt.time)<<endl;
+ }
+ QString ddd = "Mon, 05 Aug 2002 01:57:51 -0700";
+ str = ddd.latin1();
+ if ( HeaderParsing::parseDateTime( str, str + ddd.length(), dt ) ) {
+ kdDebug()<<"dt = "<<(dt.time)<<endl;
+ kdDebug()<<"@@@ rfc2822 : "<<t.rfc2822(dt.time)<<endl;
+ }
+
+ t.setCustomFormat("MMMM dddd yyyy Z");
+ kdDebug()<<"\tCustom : \t"<<t.dateString(ntime)<<endl;
+
+ ntime -= (24 * 3600 + 1);
+ kdDebug()<<"Time 24 hours and 1 second ago:"<<endl;
+ t.setFormat( DateFormatter::Fancy );
+ kdDebug()<<"\tFancy : \t"<<t.dateString(ntime)<<endl;
+ t.setFormat(DateFormatter::Localized);
+ kdDebug()<<"\tLocalized : \t"<<t.dateString(ntime)<<endl;
+ t.setFormat(DateFormatter::CTime);
+ kdDebug()<<"\tCTime : \t"<<t.dateString(ntime)<<endl;
+ t.setFormat(DateFormatter::Iso);
+ kdDebug()<<"\tIso : \t"<<t.dateString(ntime)<<endl;
+ kdDebug()<<"\trfc2822 : \t"<<t.rfc2822(ntime)<<endl;
+ t.setCustomFormat("MMMM dddd Z yyyy");
+ kdDebug()<<"\tCustom : \t"<<t.dateString(ntime)<<endl;
+
+ t.setFormat(DateFormatter::Fancy);
+ ntime -= (24*3600 *30 + 59);
+ kdDebug()<<"Time 31 days and 1 minute ago:"<<endl;
+ kdDebug()<<"\tFancy : \t"<<t.dateString(ntime)<<endl;
+ t.setFormat(DateFormatter::Localized);
+ kdDebug()<<"\tLocalized : \t"<<t.dateString(ntime)<<endl;
+ t.setFormat(DateFormatter::CTime);
+ kdDebug()<<"\tCTime : \t"<<t.dateString(ntime)<<endl;
+ t.setFormat(DateFormatter::Iso);
+ kdDebug()<<"\tIso : \t"<<t.dateString(ntime)<<endl;
+ kdDebug()<<"\trfc2822 : \t"<<t.rfc2822(ntime)<<endl;
+ t.setCustomFormat("MMMM Z dddd yyyy");
+ kdDebug()<<"\tCustom : \t"<<t.dateString(ntime)<<endl;
+
+
+ kdDebug()<<"Static functions (dates like in the last test):"<<endl;
+ kdDebug()<<"\tFancy : \t"<< DateFormatter::formatDate( DateFormatter::Fancy, ntime) <<endl;
+ kdDebug()<<"\tLocalized : \t"<< DateFormatter::formatDate( DateFormatter::Localized, ntime) <<endl;
+ kdDebug()<<"\tCTime : \t"<< DateFormatter::formatDate( DateFormatter::CTime, ntime ) <<endl;
+ kdDebug()<<"\tIso : \t"<< DateFormatter::formatDate( DateFormatter::Iso, ntime ) <<endl;
+ kdDebug()<<"\trfc2822 : \t"<< DateFormatter::rfc2822FormatDate( ntime ) <<endl;
+ kdDebug()<<"\tCustom : \t"<< DateFormatter::formatDate( DateFormatter::Custom, ntime,
+ "Z MMMM dddd yyyy") <<endl;
+ t.setFormat(DateFormatter::Fancy);
+ kdDebug()<<"QDateTime taking: (dates as in first test)"<<endl;
+ kdDebug()<<"\tFancy : \t"<<t.dateString((QDateTime::currentDateTime()))<<endl;
+ t.setFormat(DateFormatter::Localized);
+ kdDebug()<<"\tLocalized : \t"<<t.dateString(QDateTime::currentDateTime())<<endl;
+ t.setFormat(DateFormatter::CTime);
+ kdDebug()<<"\tCTime : \t"<<t.dateString(QDateTime::currentDateTime())<<endl;
+ t.setFormat(DateFormatter::Iso);
+ kdDebug()<<"\tIso : \t"<<t.dateString(QDateTime::currentDateTime())<<endl;
+ t.setCustomFormat("MMMM d dddd yyyy Z");
+ kdDebug()<<"\tCustom : \t"<<t.dateString(QDateTime::currentDateTime())<<endl;
+
+}
diff --git a/libkmime/tests/test_kmime_codec.cpp b/libkmime/tests/test_kmime_codec.cpp
new file mode 100644
index 000000000..f13b2b434
--- /dev/null
+++ b/libkmime/tests/test_kmime_codec.cpp
@@ -0,0 +1,449 @@
+/* test program for KMime::Codec's:
+ compile with:
+ g++ -I$QTDIR/include -I$KDEDIR/include -L$QTDIR/lib -L$KDEDIR/lib \
+ -lqt-mt -lkdecore -lkdenetwork -O2 -pthread -DQT_THREAD_SUPPORT \
+ -o test_kmime_codec{,.cpp}
+*/
+
+// return codes:
+#define USAGE_DISPLAYED 1
+#define UNKNOWN_CODEC 2
+#define INFILE_READ_ERR 3
+#define OUTFILE_WRITE_ERR 4
+
+#include <../kmime_codecs.h>
+
+#include <kdebug.h>
+
+#include <cstdlib>
+#include <iostream>
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <getopt.h>
+#include <cassert>
+
+#include <qfile.h>
+#include <qcstring.h> // QByteArray
+
+using namespace KMime;
+using namespace std;
+
+static struct option long_options[] = {
+ { "encode", 1, 0, 0 },
+ { "decode", 1, 0, 0 },
+ { "output-buffer-size", 1, 0, 0 },
+ { "input-buffer-size", 1, 0, 0 },
+ { "outfile", 1, 0, 0 },
+ { "with-crlf", 0, 0, 0 },
+ { "iterations", 1, 0, 0 },
+ { "without-finish", 0, 0, 0 },
+ { "verbose", 0, 0, 0 },
+ { "usage-pattern", 1, 0, 0 },
+ { 0, 0, 0, 0 }
+};
+
+void usage( const char * msg=0 ) {
+ if ( msg && *msg )
+ cerr << msg << endl;
+ cerr << "usage: test_kmime_codec (--encode|--decode) "
+ "<encoding-name> [options] infile\n"
+ "where options include:\n\n"
+ " --outfile <outfile> write output into file <outfile>\n"
+ " --output-buffer-size <size> en/decode into chunks of <size> bytes\n"
+ " default: 4096\n"
+ " --input-buffer-size <size> en/decode from chunks of <size> bytes\n"
+ " default: slurp in whole file\n"
+ " --with-crlf use CRLF instead of LF in output\n"
+ " --iterations <number> do more than one iteration\n"
+ " default: 1\n"
+ " --usage-pattern { kio | chunkwise | convenience-qba }\n"
+ " use a certain usage pattern to be tested\n"
+ " (default: chunkwise)\n"
+ " --without-finish don't call the finish() method\n"
+ " --verbose output detailed progress information\n"
+ << endl;
+ exit(USAGE_DISPLAYED);
+}
+
+void missingParameterTo( const char * option ) {
+ cerr << "Missing or malformed parameter to " << option << endl;
+ usage();
+}
+
+static enum { Kio = 0, ChunkWise = 1, ConvenienceQBA = 3 }
+pattern = ChunkWise;
+static int outbufsize = 4096;
+static int inbufsize = -1; // whole file
+static bool writing = false;
+static bool withCRLF = false;
+static bool withFinish = true;
+static bool verbose = false;
+
+void encode_decode_kio( bool, const Codec *, const QByteArray &, QFile & );
+void encode_decode_chunkwise( bool, const Codec *,
+ const QByteArray &, QFile & );
+void encode_decode_convenience_qba( bool, const Codec *, const QByteArray &,
+ QFile & );
+
+int main( int argc, char * argv[] ) {
+
+ int iterations = 1;
+ bool encode = false;
+ bool decode = false;
+ QCString outfilename, infilename;
+ QCString encodingName;
+
+ // options parsing:
+ while( 1 ) {
+ int option_index = 0;
+ if ( getopt_long( argc, argv, "", long_options, &option_index ) )
+ break;
+ switch ( option_index ) {
+ case 0: // encode
+ if ( !optarg || !*optarg ) missingParameterTo( "--encode." );
+ encode = true;
+ encodingName = QCString(optarg);
+ break;
+ case 1: // decode
+ if ( !optarg || !*optarg ) missingParameterTo( "--decode" );
+ decode = true;
+ encodingName = QCString(optarg);
+ break;
+ case 2: // output-buffer-size
+ if ( !optarg || (outbufsize = atoi( optarg )) < 1 )
+ missingParameterTo( "--output-buffer-size" );
+ break;
+ case 3: // input-buffer-size
+ if ( !optarg || (inbufsize = atoi( optarg )) < 1 )
+ missingParameterTo( "--input-buffer-size" );
+ break;
+ case 4: // outfile
+ if ( !optarg || !*optarg ) missingParameterTo( "--outfile" );
+ outfilename = QCString(optarg);
+ writing = true;
+ break;
+ case 5: // with-crlf
+ withCRLF = true;
+ break;
+ case 6: // iterations
+ if ( !optarg || (iterations = atoi( optarg )) < 1 )
+ missingParameterTo( "--iterations" );
+ break;
+ case 7: // without-finish
+ withFinish = false;
+ break;
+ case 8: // verbose
+ verbose = true;
+ break;
+ case 9: // usage-pattern
+ if ( !qstricmp( "kio", optarg ) )
+ pattern = Kio;
+ else if ( !qstricmp( "chunkwise", optarg ) )
+ pattern = ChunkWise;
+ else if ( !qstricmp( "convenience-qba", optarg ) )
+ pattern = ConvenienceQBA;
+ else {
+ cerr << "Unknown usage pattern \"" << optarg << "\"" << endl;
+ usage();
+ }
+ break;
+ default: usage( "Unknown option" );
+ }
+ }
+
+ if ( !decode && !encode )
+ usage( "You must specify exactly one of --encode, --decode." );
+ if ( decode && encode )
+ usage( "You must specify exactly one of --encode, --decode.");
+
+ if ( verbose ) {
+ if ( encode )
+ kdDebug() << "encoding as " << encodingName << endl;
+ else if ( decode )
+ kdDebug() << "decoding " << encodingName << endl;
+ }
+
+ if ( optind != argc - 1 ) usage();
+
+ QFile infile( argv[ optind ] );
+ if (!infile.exists()) {
+ kdDebug() << "infile \"" << infile.name() << "\" does not exist!" << endl;
+ return INFILE_READ_ERR;
+ }
+ if (!infile.open( IO_ReadOnly )) {
+ kdDebug() << "cannot open " << infile.name() << " for reading!"
+ << endl;
+ return INFILE_READ_ERR;
+ }
+
+ QFile outfile( outfilename );
+ if ( !outfilename.isEmpty() ) {
+ if (!outfile.open( IO_WriteOnly|IO_Truncate )) {
+ kdDebug() << "cannot open " << outfile.name() << " for writing!"
+ << endl;
+ return OUTFILE_WRITE_ERR;
+ }
+ }
+
+ if ( verbose ) {
+ kdDebug() << "using output buffer size of " << outbufsize << endl;
+ kdDebug() << "using input buffer size of " << inbufsize << endl;
+ }
+ if ( !withFinish )
+ kdWarning() << "omitting finish calls. Results may be truncated!" << endl;
+
+ if ( inbufsize <= 0 )
+ inbufsize = infile.size();
+
+ // get a codec. Don't delete it later!!
+ kdDebug( verbose ) << "obtaining codec for \""
+ << encodingName << "\"" << endl;
+ Codec * codec = Codec::codecForName( encodingName );
+ if ( !codec ) {
+ kdDebug() << "unknown codec \"" << encodingName << "\"" << endl;
+ return UNKNOWN_CODEC;
+ }
+
+ QByteArray infile_buffer = infile.readAll();
+
+ for ( int i = 0 ; i < iterations ; ++i ) {
+ kdDebug( verbose ) << "starting iteration " << i+1
+ << " of " << iterations << endl;
+ switch ( pattern ) {
+ case ChunkWise:
+ encode_decode_chunkwise( encode, codec, infile_buffer, outfile );
+ break;
+ case Kio:
+ encode_decode_kio( encode, codec, infile_buffer, outfile );
+ break;
+ case ConvenienceQBA:
+ encode_decode_convenience_qba( encode, codec, infile_buffer, outfile );
+ break;
+ default:
+ usage();
+ }
+ }
+
+ return 0;
+}
+
+void encode_decode_convenience_qba( bool encode, const Codec * codec,
+ const QByteArray & infile_buffer,
+ QFile & outfile )
+{
+ QByteArray out;
+ if ( encode )
+ out = codec->encode( infile_buffer, withCRLF );
+ else
+ out = codec->decode( infile_buffer, withCRLF );
+ if ( writing ) {
+ Q_LONG written = outfile.writeBlock( out );
+ assert( written == (Q_LONG)out.size() );
+ }
+}
+
+void encode_kio_internal( Encoder * enc, QByteArray::ConstIterator & iit,
+ QByteArray::ConstIterator & iend,
+ QByteArray & out )
+{
+ out.resize( outbufsize );
+ QByteArray::Iterator oit = out.begin();
+ QByteArray::ConstIterator oend = out.end();
+
+ while ( !enc->encode( iit, iend, oit, oend ) )
+ if ( oit == oend ) return;
+
+ while ( !enc->finish( oit, oend ) )
+ if ( oit == oend ) return;
+
+ out.truncate( oit - out.begin() );
+}
+
+void decode_kio_internal( Decoder * dec, QByteArray::ConstIterator & iit,
+ QByteArray::ConstIterator & iend,
+ QByteArray & out ) {
+ out.resize( outbufsize );
+ QByteArray::Iterator oit = out.begin();
+ QByteArray::ConstIterator oend = out.end();
+
+ while ( !dec->decode( iit, iend, oit, oend ) )
+ if ( oit == oend ) return;
+
+ while ( !dec->finish( oit, oend ) )
+ if ( oit == oend ) return;
+
+ out.truncate( oit - out.begin() );
+}
+
+void encode_decode_kio( bool encode, const Codec * codec,
+ const QByteArray & infile_buffer, QFile & outfile )
+{
+
+ Encoder * enc = 0;
+ Decoder * dec = 0;
+
+ // Get an encoder. This one you have to delete!
+ if ( encode ) {
+ enc = codec->makeEncoder( withCRLF );
+ assert( enc );
+ } else {
+ dec = codec->makeDecoder( withCRLF );
+ assert( dec );
+ }
+
+ QByteArray::ConstIterator iit = infile_buffer.begin();
+ QByteArray::ConstIterator iend = infile_buffer.end();
+
+ QByteArray out;
+ do {
+ out = QByteArray();
+ if ( encode )
+ encode_kio_internal( enc, iit, iend, out );
+ else
+ decode_kio_internal( dec, iit, iend, out );
+ if ( writing && out.size() ) {
+ Q_LONG written = outfile.writeBlock( out );
+ assert( written == (Q_LONG)out.size() );
+ }
+ } while ( out.size() );
+
+ if ( encode )
+ delete enc;
+ else
+ delete dec;
+}
+
+void encode_decode_chunkwise( bool encode, const Codec * codec,
+ const QByteArray & infile_buffer, QFile & outfile )
+{
+ Encoder * enc = 0;
+ Decoder * dec = 0;
+
+
+ QByteArray indata( inbufsize );
+ QByteArray outdata( outbufsize );
+
+ // we're going to need this below:
+#define write_full_outdata_then_reset do { \
+ kdDebug( verbose ) << " flushing output buffer." << endl; \
+ if ( writing ) { \
+ Q_LONG outlen = outfile.writeBlock( outdata.data(), \
+ outdata.size() ); \
+ if ( outlen != (int)outdata.size() ) \
+ exit(OUTFILE_WRITE_ERR); \
+ } \
+ oit = outdata.begin(); \
+ } while ( false )
+
+#define report_status(x,y) do { \
+ kdDebug( verbose ) << " " #x "() returned " #y " after processing " \
+ << iit - indata.begin() << " bytes of input.\n" \
+ << " output iterator now at position " \
+ << oit - outdata.begin() << " of " \
+ << outdata.size() << endl; \
+ } while ( false )
+
+#define report_finish_status(y) do { \
+ kdDebug( verbose ) << " finish() returned " #y "\n" \
+ << " output iterator now at position " \
+ << oit - outdata.begin() << " of " \
+ << outdata.size() << endl; \
+ } while ( false )
+
+
+ // Initialize the output iterators:
+ QByteArray::Iterator oit = outdata.begin();
+ QByteArray::Iterator oend = outdata.end();
+
+ // Get an encoder. This one you have to delete!
+ if ( encode ) {
+ enc = codec->makeEncoder( withCRLF );
+ assert( enc );
+ } else {
+ dec = codec->makeDecoder( withCRLF );
+ assert( dec );
+ }
+
+ //
+ // Loop over input chunks:
+ //
+ uint offset = 0;
+ while ( offset < infile_buffer.size() ) {
+ uint reallyRead = QMIN( indata.size(), infile_buffer.size() - offset );
+ indata.duplicate( infile_buffer.begin() + offset, reallyRead );
+ offset += reallyRead;
+
+ kdDebug( verbose ) << " read " << reallyRead << " bytes (max: "
+ << indata.size() << ") from input." << endl;
+
+ // setup input iterators:
+ QByteArray::ConstIterator iit = indata.begin();
+ QByteArray::ConstIterator iend = indata.begin() + reallyRead;
+
+ if ( encode ) {
+ //
+ // Loop over encode() calls:
+ //
+ while ( !enc->encode( iit, iend, oit, oend ) ) {
+ report_status( encode, false );
+ if ( oit == oend )
+ // output buffer full:
+ write_full_outdata_then_reset;
+ }
+ report_status( encode, true );
+ } else {
+ //
+ // Loop over decode() calls:
+ //
+ while ( !dec->decode( iit, iend, oit, oend ) ) {
+ report_status( decode, false );
+ if ( oit == oend )
+ // output buffer full:
+ write_full_outdata_then_reset;
+ }
+ report_status( decode, true );
+ }
+ } // end loop over input chunks
+
+ //
+ // Now finish the encoding/decoding:
+ // (same loops as above, just s/encode|decode/finish())
+ //
+ if ( withFinish )
+ if ( encode ) {
+ while ( !enc->finish( oit, oend ) ) {
+ report_finish_status( false );
+ if ( oit == oend )
+ write_full_outdata_then_reset;
+ }
+ report_finish_status( true );
+ } else {
+ while ( !dec->finish( oit, oend ) ) {
+ report_finish_status( false );
+ if ( oit == oend )
+ write_full_outdata_then_reset;
+ }
+ report_finish_status( true );
+ }
+
+ //
+ // Write out last (partial) output chunk:
+ //
+ if ( writing ) {
+ Q_LONG outlen = outfile.writeBlock( outdata.data(),
+ oit - outdata.begin() );
+ if ( outlen != oit - outdata.begin() )
+ exit(OUTFILE_WRITE_ERR);
+ }
+
+ //
+ // Delete en/decoder:
+ //
+ if ( encode )
+ delete enc;
+ else
+ delete dec;
+}
+
diff --git a/libkmime/tests/test_kmime_header_parsing.cpp b/libkmime/tests/test_kmime_header_parsing.cpp
new file mode 100644
index 000000000..3839bff7e
--- /dev/null
+++ b/libkmime/tests/test_kmime_header_parsing.cpp
@@ -0,0 +1,431 @@
+
+#include <../kmime_headers.h>
+#include <../kmime_header_parsing.h>
+
+#include <kinstance.h>
+
+#include <qfile.h>
+#include <qcstring.h>
+//#include <qstring.h>
+
+//#include <stdio.h>
+#include <iostream>
+#include <cstdlib>
+#include <cassert>
+
+#define _GNU_SOURCE
+#include <getopt.h>
+
+using namespace KMime::HeaderParsing;
+using namespace std;
+
+static const char * tokenTypes[] = {
+ "encoded-word",
+ "atom",
+ "token",
+ "quoted-string",
+ "domain-literal",
+ "comment",
+ "phrase",
+ "dot-atom",
+ "domain",
+ "obs-route",
+ "addr-spec",
+ "angle-addr",
+ "mailbox",
+ "group",
+ "address",
+ "address-list",
+ "parameter",
+ "raw-parameter-list",
+ "parameter-list",
+ "time",
+ "date-time"
+};
+static const int tokenTypesLen = sizeof tokenTypes / sizeof *tokenTypes;
+
+void usage( const char * msg=0 ) {
+ if ( msg && *msg )
+ cerr << msg << endl;
+ cerr <<
+ "usage: test_kmime_header_parsing "
+ "(--token <tokentype>|--headerfield <fieldtype>|--header)\n"
+ "\n"
+ " --token <tokentype> interpret input as <tokentype> and output\n"
+ " (-t) in parsed form. Currently defined values of\n"
+ " <tokentype> are:" << endl;
+ for ( int i = 0 ; i < tokenTypesLen ; ++i )
+ cerr << " " << tokenTypes[i] << endl;
+ cerr << "\n"
+ " --headerfield <fieldtype> interpret input as header field <fieldtype>\n"
+ " (-f) and output in parsed form.\n"
+ "\n"
+ " --header parse an RFC2822 header. Iterates over all\n"
+ " (-h) header fields and outputs them in parsed form." << endl;
+ exit(1);
+}
+
+ostream & operator<<( ostream & stream, const QString & str ) {
+ return stream << str.utf8().data();
+}
+
+int main( int argc, char * argv[] ) {
+ if ( argc == 1 || argc > 3 ) usage();
+ //
+ // process options:
+ //
+ enum { None, Token, HeaderField, Header } action = None;
+ const char * argument = 0;
+ bool withCRLF = false;
+ while( true ) {
+ int option_index = 0;
+ static const struct option long_options[] = {
+ // actions:
+ { "token", 1, 0, 't' },
+ { "headerfield", 1, 0, 'f' },
+ { "header", 0, 0, 'h' },
+ { "crlf", 0, 0, 'c' },
+ { 0, 0, 0, 0 }
+ };
+
+ int c = getopt_long( argc, argv, "cf:ht:", long_options, &option_index );
+ if ( c == -1 ) break;
+
+ switch ( c ) {
+ case 'c': // --crlf
+ withCRLF = true;
+ break;
+ case 't': // --token <tokentype>
+ action = Token;
+ argument = optarg;
+ break;
+ case 'f': // --headerfield <headertype>
+ usage( "--headerfield is not yet implemented!" );
+ break;
+ case 'h': // --header
+ usage( "--header is not yet implemented!" );
+ break;
+ default:
+ usage( "unknown option encountered!" );
+ }
+ }
+
+ if ( optind < argc ) usage( "non-option argument encountered!" );
+
+ assert( action == Token );
+
+ int index;
+ for ( index = 0 ; index < tokenTypesLen ; ++index )
+ if ( !qstricmp( tokenTypes[index], argument ) ) break;
+
+ if ( index >= tokenTypesLen ) usage( "unknown token type" );
+
+ KInstance instance( "test_kmime_header_parsing" );
+
+ QFile stdIn;
+ stdIn.open( IO_ReadOnly, stdin );
+ const QByteArray indata = stdIn.readAll();
+ stdIn.close();
+ QByteArray::ConstIterator iit = indata.begin();
+ const QByteArray::ConstIterator iend = indata.end();
+
+ switch ( index ) {
+ case 0:
+ { // encoded-word
+ QString result;
+ QCString language;
+ // must have checked for initial '=' already:
+ bool ok = indata.size() >= 1 && *iit++ == '=' &&
+ parseEncodedWord( iit, iend, result, language );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result:\n" << result << endl
+ << "language:\n" << language.data() << endl;
+ }
+ break;
+ case 1:
+ { // atom
+ QString result = "with 8bit: ";
+ bool ok = parseAtom( iit, iend, result, true );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result:\n" << result << endl;
+
+ result = "without 8bit: ";
+#ifdef COMPILE_FAIL
+ ok = parseAtom( indata.begin(), iend, result, false );
+#else
+ iit = indata.begin();
+ ok = parseAtom( iit, iend, result, false );
+#endif
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result:\n" << result << endl;
+ }
+ break;
+ case 2:
+ { // token
+ QString result = "with 8bit: ";
+ bool ok = parseToken( iit, iend, result, true );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result:\n" << result << endl;
+
+ result = "without 8bit: ";
+#ifdef COMPILE_FAIL
+ ok = parseToken( indata.begin(), iend, result, false );
+#else
+ iit = indata.begin();
+ ok = parseToken( iit, iend, result, false );
+#endif
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result:\n" << result << endl;
+ }
+ break;
+ case 3:
+ { // quoted-string
+ QString result;
+ // must have checked for initial '"' already:
+ bool ok = *iit++ == '"' &&
+ parseGenericQuotedString( iit, iend, result, withCRLF, '"', '"' );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result:\n" << result << endl;
+ }
+ break;
+ case 4:
+ { // domain-literal
+ QString result;
+ // must have checked for initial '[' already:
+ bool ok = *iit++ == '[' &&
+ parseGenericQuotedString( iit, iend, result, withCRLF, '[', ']' );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result:\n" << result << endl;
+ }
+ break;
+ case 5:
+ { // comment
+ QString result;
+ // must have checked for initial '(' already:
+ bool ok = *iit++ == '(' &&
+ parseComment( iit, iend, result, withCRLF, true );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result:\n" << result << endl;
+ }
+ break;
+ case 6:
+ { // phrase
+ QString result;
+ bool ok = parsePhrase( iit, iend, result, withCRLF );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result:\n" << result << endl;
+ }
+ break;
+ case 7:
+ { // dot-atom
+ QString result;
+ bool ok = parseDotAtom( iit, iend, result, withCRLF );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result:\n" << result << endl;
+ }
+ break;
+ case 8:
+ { // domain
+ QString result;
+ bool ok = parseDomain( iit, iend, result, withCRLF );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result:\n" << result << endl;
+ }
+ break;
+ case 9:
+ { // obs-route
+ QStringList result;
+ bool ok = parseObsRoute( iit, iend, result, withCRLF, true /*save*/ );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result: " << result.count() << " domains:" << endl;
+ for ( QStringList::ConstIterator it = result.begin() ;
+ it != result.end() ; ++it )
+ cout << (*it) << endl;
+ }
+ break;
+ case 10:
+ { // addr-spec
+ KMime::Types::AddrSpec result;
+ bool ok = parseAddrSpec( iit, iend, result, withCRLF );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result.localPart:\n" << result.localPart << endl
+ << "result.domain:\n" << result.domain << endl;
+ }
+ break;
+ case 11:
+ { // angle-addr
+ KMime::Types::AddrSpec result;
+ bool ok = parseAngleAddr( iit, iend, result, withCRLF );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result.localPart:\n" << result.localPart << endl
+ << "result.domain:\n" << result.domain << endl;
+ }
+ break;
+ case 12:
+ { // mailbox
+ KMime::Types::Mailbox result;
+ bool ok = parseMailbox( iit, iend, result, withCRLF );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result.displayName:\n" << result.displayName << endl
+ << "result.addrSpec.localPart:\n" << result.addrSpec.localPart << endl
+ << "result.addrSpec.domain:\n" << result.addrSpec.domain << endl;
+ }
+ break;
+ case 13:
+ { // group
+ KMime::Types::Address result;
+ bool ok = parseGroup( iit, iend, result, withCRLF );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result.displayName:\n" << result.displayName << endl;
+ int i = 0;
+ for ( QValueList<KMime::Types::Mailbox>::ConstIterator
+ it = result.mailboxList.begin();
+ it != result.mailboxList.end() ; ++it, ++i )
+ cout << "result.mailboxList[" << i << "].displayName:\n"
+ << (*it).displayName << endl
+ << "result.mailboxList[" << i << "].addrSpec.localPart:\n"
+ << (*it).addrSpec.localPart << endl
+ << "result.mailboxList[" << i << "].addrSpec.domain:\n"
+ << (*it).addrSpec.domain << endl;
+ }
+ break;
+ case 14:
+ { // address
+ KMime::Types::Address result;
+ bool ok = parseAddress( iit, iend, result, withCRLF );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result.displayName:\n" << endl;
+ int i = 0;
+ for ( QValueList<KMime::Types::Mailbox>::ConstIterator
+ it = result.mailboxList.begin();
+ it != result.mailboxList.end() ; ++it, ++i )
+ cout << "result.mailboxList[" << i << "].displayName:\n"
+ << (*it).displayName << endl
+ << "result.mailboxList[" << i << "].addrSpec.localPart:\n"
+ << (*it).addrSpec.localPart << endl
+ << "result.mailboxList[" << i << "].addrSpec.domain:\n"
+ << (*it).addrSpec.domain << endl;
+ }
+ break;
+ case 15:
+ { // address-list
+ QValueList<KMime::Types::Address> result;
+ bool ok = parseAddressList( iit, iend, result, withCRLF );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl;
+ int j = 0;
+ for ( QValueList<KMime::Types::Address>::ConstIterator
+ jt = result.begin() ; jt != result.end() ; ++jt, ++j ) {
+ cout << "result[" << j << "].displayName:\n"
+ << (*jt).displayName << endl;
+ int i = 0;
+ for ( QValueList<KMime::Types::Mailbox>::ConstIterator
+ it = (*jt).mailboxList.begin();
+ it != (*jt).mailboxList.end() ; ++it, ++i )
+ cout << "result[" << j << "].mailboxList[" << i << "].displayName:\n"
+ << (*it).displayName << endl
+ << "result[" << j << "].mailboxList[" << i << "].addrSpec.localPart:\n"
+ << (*it).addrSpec.localPart << endl
+ << "result[" << j << "].mailboxList[" << i << "].addrSpec.domain:\n"
+ << (*it).addrSpec.domain << endl;
+ }
+ }
+ break;
+ case 16:
+ { // parameter
+ QPair<QString,KMime::Types::QStringOrQPair> result;
+ bool ok = parseParameter( iit, iend, result, withCRLF );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result.first (attribute):\n" << result.first << endl
+ << "result.second.qstring (value):\n" << result.second.qstring << endl
+ << "result.second.qpair (value):\n"
+ << QCString( result.second.qpair.first,
+ result.second.qpair.second+1 ).data() << endl;
+ }
+ break;
+ case 17:
+ { // raw-parameter-list
+ QMap<QString,KMime::Types::QStringOrQPair> result;
+ bool ok = parseRawParameterList( iit, iend, result, withCRLF );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result: " << result.count() << " raw parameters:" << endl;
+ int i = 0;
+ for ( QMap<QString,KMime::Types::QStringOrQPair>::ConstIterator
+ it = result.begin() ; it != result.end() ; ++it, ++i )
+ cout << "result[" << i << "].key() (attribute):\n"
+ << it.key() << endl
+ << "result[" << i << "].data().qstring (value):\n"
+ << it.data().qstring << endl
+ << "result[" << i << "].data().qpair (value):\n"
+ << QCString( it.data().qpair.first,
+ it.data().qpair.second+1 ).data() << endl;
+ }
+ break;
+ case 18:
+ { // parameter-list
+ QMap<QString,QString> result;
+ bool ok = parseParameterList( iit, iend, result, withCRLF );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result: " << result.count() << " parameters:" << endl;
+ int i = 0;
+ for ( QMap<QString,QString>::Iterator it = result.begin() ;
+ it != result.end() ; ++it, ++i )
+ cout << "result[" << i << "].key() (attribute):\n"
+ << it.key() << endl
+ << "result[" << i << "].data() (value):\n"
+ << it.data() << endl;
+ }
+ break;
+ case 19:
+ { // time
+ int hour, mins, secs;
+ long int secsEastOfGMT;
+ bool timeZoneKnown = true;
+
+ bool ok = parseTime( iit, iend, hour, mins, secs,
+ secsEastOfGMT, timeZoneKnown, withCRLF );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result.hour: " << hour << endl
+ << "result.mins: " << mins << endl
+ << "result.secs: " << secs << endl
+ << "result.secsEastOfGMT: " << secsEastOfGMT << endl
+ << "result.timeZoneKnown: " << timeZoneKnown << endl;
+ }
+ break;
+ case 20:
+ { // date-time
+ KMime::Types::DateTime result;
+ bool ok = parseDateTime( iit, iend, result, withCRLF );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result.time (in local timezone): " << ctime( &(result.time) )
+ << "result.secsEastOfGMT: " << result.secsEastOfGMT
+ << " (" << result.secsEastOfGMT/60 << "mins)" << endl
+ << "result.timeZoneKnown: " << result.timeZoneKnown << endl;
+ }
+ break;
+ default:
+ assert( 0 );
+ }
+}
diff --git a/libkmime/tests/test_mdn.cpp b/libkmime/tests/test_mdn.cpp
new file mode 100644
index 000000000..1bb387f1d
--- /dev/null
+++ b/libkmime/tests/test_mdn.cpp
@@ -0,0 +1,151 @@
+#include <kmime_mdn.h>
+using namespace KMime::MDN;
+
+#include <qcstring.h>
+#include <qstring.h>
+#include <qvaluelist.h>
+
+#include <iostream>
+using std::cout;
+using std::cerr;
+#include <cstdlib>
+using std::exit;
+using std::endl;
+
+#define _GNU_SOURCE 1
+#include <getopt.h>
+
+void usage( const char * msg=0 ) {
+ if ( msg )
+ cerr << msg << endl;
+ cerr << "usage: test_mdn <options>\n"
+ "where options include the following:" << endl
+ << "FIXME" << endl;
+ exit( 1 );
+}
+
+int main( int argc, char * argv[] ) {
+
+ QString finalRecipient;
+ QString originalRecipient;
+ QCString originalMessageId;
+ ActionMode actionMode = ManualAction;
+ SendingMode sendingMode = SentManually;
+ DispositionType dispositionType = Displayed;
+ QValueList<DispositionModifier> dispositionModifiers;
+ QString special;
+
+ while ( true ) {
+ int option_index = 0;
+ static const struct option long_options[] = {
+ { "action-mode", 1, 0, 'a' },
+ { "disposition-type", 1, 0, 'd' },
+ { "final-recipient", 1, 0, 'f' },
+ { "original-message-id", 1, 0, 'i' },
+ { "disposition-modifiers", 1, 0, 'm' },
+ { "original-recipient", 1, 0, 'o' },
+ { "sending-mode", 1, 0, 's' },
+ { 0, 0, 0, 0 }
+ };
+
+ int c = getopt_long( argc, argv, "a:d:f:i:m:o:s:",
+ long_options, &option_index );
+ if ( c == -1 ) break;
+
+#define EQUALS(x) !qstricmp( optarg, x )
+
+ switch ( c ) {
+
+ case 'a': // --action-mode
+ if ( EQUALS( "manual-action" ) )
+ actionMode = ManualAction;
+ else if ( EQUALS( "automatic-action" ) )
+ actionMode = AutomaticAction;
+ else
+ usage( "unknown action mode!" );
+ break;
+
+ case 'd': // --disposition-type
+ if ( EQUALS( "displayed" ) )
+ dispositionType = Displayed;
+ else if ( EQUALS( "deleted" ) )
+ dispositionType = Deleted;
+ else if ( EQUALS( "dispatched" ) )
+ dispositionType = Dispatched;
+ else if ( EQUALS( "processed" ) )
+ dispositionType = Processed;
+ else if ( EQUALS( "denied" ) )
+ dispositionType = Denied;
+ else if ( EQUALS( "failed" ) )
+ dispositionType = Failed;
+ else
+ usage( "unknown disposition type!" );
+ break;
+
+ case 'f': // --final-recipient
+ if ( optarg && *optarg )
+ finalRecipient = QString::fromUtf8( optarg );
+ else
+ usage( "--final-recipient is missing a value" );
+ break;
+
+ case 'i': // --original-message-id
+ if ( optarg && *optarg )
+ originalMessageId = optarg;
+ else
+ usage( "--original-message-id is missing a value" );
+ break;
+
+ case 'm': // --disposition-modifier
+ if ( EQUALS( "error" ) )
+ dispositionModifiers << Error;
+ else if ( EQUALS( "warning" ) )
+ dispositionModifiers << Warning;
+ else if ( EQUALS( "superseded" ) )
+ dispositionModifiers << Superseded;
+ else if ( EQUALS( "expired" ) )
+ dispositionModifiers << Expired;
+ else if ( EQUALS( "mailbox-terminated" ) )
+ dispositionModifiers << MailboxTerminated;
+ else
+ usage( "unknwon disposition modifier!" );
+ break;
+
+ case 'o': // --original-recipient
+ if ( optarg && *optarg )
+ originalRecipient = QString::fromUtf8( optarg );
+ else
+ usage( "--original-recipient is missing a value" );
+ break;
+
+ case 's': // --sending-mode
+ if ( EQUALS( "MDN-sent-manually" ) )
+ sendingMode = SentManually;
+ else if ( EQUALS( "MDN-sent-automatically" ) )
+ sendingMode = SentAutomatically;
+ else
+ usage( "unknown sending mode" );
+ break;
+
+ default:
+ usage( "unknown option encountered!" );
+ }
+ }
+
+ if ( optind < argc )
+ special = QString::fromUtf8( argv[optind++] );
+ if ( optind < argc )
+ usage( "too many arguments!" );
+
+ QCString result = dispositionNotificationBodyContent( finalRecipient,
+ originalRecipient.latin1(),
+ originalMessageId,
+ dispositionType,
+ actionMode,
+ sendingMode,
+ dispositionModifiers,
+ special );
+ cout << "Result:\n" << result.data();
+
+ return 0;
+}