From d12214d338bba78ccfe3b852e8de1cb13c3e50da Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Tue, 18 Aug 2009 16:00:06 -0400 Subject: [PATCH] Initial commit. --- makefile | 15 +++ src/htnef.hs | 44 +++++++++ src/tnef/attachment.hs | 65 +++++++++++++ src/tnef/file.hs | 85 +++++++++++++++++ src/tnef/object.hs | 119 ++++++++++++++++++++++++ src/tnef/object_lvl.hs | 37 ++++++++ src/tnef/object_name.hs | 68 ++++++++++++++ test/body.tnef | Bin 0 -> 7769 bytes test/data-before-name.tnef | Bin 0 -> 13468 bytes test/multi-name-property.tnef | Bin 0 -> 3039 bytes test/two-files.tnef | Bin 0 -> 3481 bytes test/ytnef_outlook_2k3_appointment.tnef | Bin 0 -> 3057 bytes test/ytnef_random_sample.tnef | Bin 0 -> 98184 bytes 13 files changed, 433 insertions(+) create mode 100644 makefile create mode 100644 src/htnef.hs create mode 100644 src/tnef/attachment.hs create mode 100644 src/tnef/file.hs create mode 100644 src/tnef/object.hs create mode 100644 src/tnef/object_lvl.hs create mode 100644 src/tnef/object_name.hs create mode 100644 test/body.tnef create mode 100644 test/data-before-name.tnef create mode 100644 test/multi-name-property.tnef create mode 100644 test/two-files.tnef create mode 100644 test/ytnef_outlook_2k3_appointment.tnef create mode 100644 test/ytnef_random_sample.tnef diff --git a/makefile b/makefile new file mode 100644 index 0000000..94bbbdc --- /dev/null +++ b/makefile @@ -0,0 +1,15 @@ +all: htnef + +htnef: src/*.hs src/tnef/*.hs + ghc -O2 -Wall --make -fglasgow-exts -o bin/htnef src/*.hs src/tnef/*.hs + +profile: src/*.hs src/tnef/*.hs + ghc -O2 -Wall -prof -auto-all --make -fglasgow-exts -o bin/htnef src/*.hs src/tnef/*.hs + +clean: + rm -f bin/htnef + rm -f src/*.hi + rm -f src/*.o + rm -f src/tnef/*.hi + rm -f src/tnef/*.o + rm -f htnef.prof diff --git a/src/htnef.hs b/src/htnef.hs new file mode 100644 index 0000000..8163644 --- /dev/null +++ b/src/htnef.hs @@ -0,0 +1,44 @@ +-- +-- htnef, a program to do things to TNEF files. +-- +-- Copyright Michael Orlitzky +-- +-- http://michael.orlitzky.com/ +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- http://www.fsf.org/licensing/licenses/gpl.html + +import Data.Binary +import System.Environment (getArgs) +import Tnef.File + + +-- Sequential IO +-- Perform x, ignoring the result. +-- Then return the result of doing the rest of the operations, +-- which will be a single IO (). This forces evaluation +-- of a list of IOs, i.e. [IO ()] +sequential_io :: [IO ()] -> IO () +sequential_io [] = return () +sequential_io (x:xs) = do + x + sequential_io xs + + +-- Decode whatever file is passed on the command line. +main :: IO () +main = do + args <- getArgs + tf :: TnefFile <- decodeFile (args !! 0) + putStrLn (show tf) -- Dump the data... + sequential_io (write_tnef_file tf) -- And write the attachments + \ No newline at end of file diff --git a/src/tnef/attachment.hs b/src/tnef/attachment.hs new file mode 100644 index 0000000..7526d0e --- /dev/null +++ b/src/tnef/attachment.hs @@ -0,0 +1,65 @@ +-- +-- Copyright Michael Orlitzky +-- +-- http://michael.orlitzky.com/ +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- http://www.fsf.org/licensing/licenses/gpl.html +-- + +module Tnef.Attachment where + +import Tnef.Object + +data TnefAttachment = TnefAttachment { att_mod_date :: TnefObject, + att_data :: TnefObject, + att_file_name :: TnefObject, + att_meta_file :: TnefObject, + att_attachment :: TnefObject } + | NilAttachment + deriving (Show) + + +get_attachment_list :: [TnefObject] -> [TnefAttachment] +get_attachment_list [] = [] +get_attachment_list [Nil] = [] +get_attachment_list (x:xs) + | (show (obj_name x) == "Attachment Rendering Data") = (make_attachment xs) : get_attachment_list xs + | otherwise = get_attachment_list xs + + +make_attachment :: [TnefObject] -> TnefAttachment +make_attachment xs + | length xs < 5 = NilAttachment + | otherwise = TnefAttachment m d f mf a + where + m = get_first_with_name xs "Attachment Modification Date" + d = get_first_with_name xs "Attachment Data" + f = get_first_with_name xs "Attachment File Name" + mf = get_first_with_name xs "Attachment Meta File" + a = get_first_with_name xs "Attachment" + +safe_head :: [TnefObject] -> TnefObject +safe_head xs + | ((length xs) == 0) = Nil + | otherwise = head xs + + +get_first_with_name :: [TnefObject] -> String -> TnefObject +get_first_with_name xs name = + safe_head (dropWhile ((/= name) . show . obj_name) xs) + + +write_attachment :: TnefAttachment -> IO () +write_attachment NilAttachment = putStrLn "NilAttachment" +write_attachment x = do + write_tnef_object (show_data (att_file_name x)) (att_data x) diff --git a/src/tnef/file.hs b/src/tnef/file.hs new file mode 100644 index 0000000..d0288b0 --- /dev/null +++ b/src/tnef/file.hs @@ -0,0 +1,85 @@ +-- +-- Copyright Michael Orlitzky +-- +-- http://michael.orlitzky.com/ +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- http://www.fsf.org/licensing/licenses/gpl.html +-- + +module Tnef.File where + +import Data.Binary +import qualified Data.Binary.Get as BinaryGet +import qualified Data.Binary.Put as BinaryPut +import Data.Int (Int64) +import Tnef.Attachment +import Tnef.Object + + +-- A TNEF "file" has a signature at the top which should be the same +-- for all TNEF files. There's also a "key," which probably does +-- something, and looks to be unique. After that, there's a variable +-- number of objects (whose structure can be seen in TnefObject). The +-- "total bytes" thing is not part of the file. I'm just using it to +-- keep track of the bytes read for now (to make sure it equals the +-- size of the file when we're done). +data TnefFile = TnefFile { signature :: Word32, + key :: Word16, + first_object :: TnefObject, + total_bytes :: Int64 } + + +-- Magicest of numbers +-- Important: Int doesn't guarantee 32 bits, so we +-- need to use the Integer type here. +tnef_signature :: Integer +tnef_signature = 0x223e9f78 + + + +instance Show TnefFile where + show x = "Signature: " ++ (show (signature x)) ++ " (Correct: " ++ (show tnef_signature) ++ ")\n" ++ + "Key: " ++ (show (key x)) ++ "\n" ++ + concat (map show (get_object_list x)) -- Show the objects, one at a time + + +-- Recursively collect an array of objects. It dies +-- on the last one, which has no next_object property. +-- Help? +get_object_list :: TnefFile -> [TnefObject] +get_object_list x = get_successive_objects (first_object x) + + +get_successive_objects :: TnefObject -> [TnefObject] +get_successive_objects Nil = [Nil] +get_successive_objects x = (x : (get_successive_objects (next_object x))) + + +instance Binary TnefFile where + put _ = do BinaryPut.putWord8 0 + get = do + signature_word <- BinaryGet.getWord32host + key_word <- BinaryGet.getWord16host + first_object_word <- get :: Get TnefObject + total_bytes_word <- BinaryGet.bytesRead + return (TnefFile { signature = signature_word, + key = key_word, + first_object = first_object_word, + total_bytes = total_bytes_word }) + + +write_tnef_file :: TnefFile -> [IO ()] +write_tnef_file x = do + let objects = get_object_list x + let attachments = get_attachment_list objects + map write_attachment attachments diff --git a/src/tnef/object.hs b/src/tnef/object.hs new file mode 100644 index 0000000..0011ee5 --- /dev/null +++ b/src/tnef/object.hs @@ -0,0 +1,119 @@ +-- +-- Copyright Michael Orlitzky +-- +-- http://michael.orlitzky.com/ +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- http://www.fsf.org/licensing/licenses/gpl.html +-- + +module Tnef.Object where + +import Control.Monad (replicateM) +import Data.Binary +import qualified Data.Binary.Get as BinaryGet +import qualified Data.Binary.Put as BinaryPut +import qualified Data.ByteString.Lazy as BS +import Data.Char +import Data.Word +import Tnef.ObjectName +import Tnef.ObjectLvl + + +-- The only tricky part here is the "chained" TnefObjects. +-- Each object contains the next one. It's like that because +-- I couldn't figure out how to parse an unknown number of +-- objects using Binary.Get. +data TnefObject = TnefObject { obj_lvl :: TnefObjectLvl, + obj_name :: TnefObjectName, + obj_type :: Word16, + obj_length :: Word32, + obj_data :: [Word8], + obj_checksum :: Word16, + next_object :: TnefObject } + | Nil + + +instance Show TnefObject where + show Nil = "Nil" + show x = "" ++ "\n" ++ + " Level: " ++ (show (obj_lvl x)) ++ "\n" ++ + " Name: " ++ (show (obj_name x)) ++ "\n" ++ + " Type: " ++ (show (obj_type x)) ++ "\n" ++ + " Data: " ++ (show_data x) ++ "\n" ++ + " Checksum: " ++ (show (obj_checksum x)) ++ " (Actual: " ++ (show (checksum (obj_data x))) ++ ")\n" ++ + "\n" + +drop_null_byte :: [Word8] -> [Word8] +drop_null_byte = takeWhile (/= 0) + +show_data :: TnefObject -> String +show_data Nil = "" +show_data x + | ((show n) == "Attachment Data") = "(Binary)" + | ((show n) == "Date Sent") = show (obj_data x) + | ((show n) == "Date Received") = show (obj_data x) + | ((show n) == "Date Modified") = show (obj_data x) + | ((show n) == "Attachment Modification Date") = show (obj_data x) + | otherwise = t + where + n = (obj_name x) + t = (map (chr . word8_to_int) (drop_null_byte (obj_data x))) + + +-- Just sum up the values of the bytes, and take that +-- value mod 65536 at the end. (checksum obj_data) should +-- equal the value of obj_checksum for each TnefObject. +checksum :: [Word8] -> Int +checksum x = (foldr (+) 0 (map word8_to_int x)) `mod` 0x10000 + + +-- Just for convenience +word8_to_int :: Word8 -> Int +word8_to_int x = (fromIntegral x) + + +instance Binary TnefObject where + put _ = do BinaryPut.putWord8 0 + get = do + obj_lvl_word <- BinaryGet.getWord8 + obj_name_word <- BinaryGet.getWord16host + obj_type_word <- BinaryGet.getWord16host + obj_length_word <- BinaryGet.getWord32host + -- This pulls in obj_length bytes of data as a [Word8] + obj_data_word <- replicateM (fromIntegral obj_length_word) BinaryGet.getWord8 + obj_checksum_word <- BinaryGet.getWord16host + next_object_word <- get_next_tnef_object + return (TnefObject { obj_lvl = (word_to_lvl obj_lvl_word), + obj_name = (word_to_name obj_name_word), + obj_type = obj_type_word, + obj_length = obj_length_word, + obj_data = obj_data_word, + obj_checksum = obj_checksum_word, + next_object = next_object_word }) + + +-- If there's no more data, return Nil as the "next" object. +get_next_tnef_object :: Get TnefObject +get_next_tnef_object = do + is_empty <- BinaryGet.isEmpty + if is_empty + then return Nil + else (get :: Get TnefObject) + + +write_tnef_object :: String -> TnefObject -> IO () +write_tnef_object _ Nil = return () +write_tnef_object path x + | ((show n) == "Attachment Data") = BS.writeFile path (BS.pack (obj_data x)) + | otherwise = return () + where n = (obj_name x) diff --git a/src/tnef/object_lvl.hs b/src/tnef/object_lvl.hs new file mode 100644 index 0000000..6690c1c --- /dev/null +++ b/src/tnef/object_lvl.hs @@ -0,0 +1,37 @@ +-- +-- Copyright Michael Orlitzky +-- +-- http://michael.orlitzky.com/ +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- http://www.fsf.org/licensing/licenses/gpl.html +-- + +module Tnef.ObjectLvl where + +import Data.Word + +-- TNEF "Levels". Not sure why they're special, but +-- one is attached to every TnefObject. +data TnefObjectLvl = TnefObjectLvl { code :: Integer, + desc :: String } +instance Show TnefObjectLvl where + show = desc + + +tnef_object_lvls :: [TnefObjectLvl] +tnef_object_lvls = [ TnefObjectLvl 0x01 "Message", + TnefObjectLvl 0x02 "Attachment" ] + +-- I want to marry list comprehensions +word_to_lvl :: Word8 -> TnefObjectLvl +word_to_lvl c = head [ x | x <- tnef_object_lvls, (code x) == read (show c)] diff --git a/src/tnef/object_name.hs b/src/tnef/object_name.hs new file mode 100644 index 0000000..4042aa8 --- /dev/null +++ b/src/tnef/object_name.hs @@ -0,0 +1,68 @@ +-- +-- Copyright Michael Orlitzky +-- +-- http://michael.orlitzky.com/ +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- http://www.fsf.org/licensing/licenses/gpl.html +-- + +module Tnef.ObjectName where + +import Data.Word + +-- These are the "names" for TNEF objects. They more or less specify +-- what type of object you've got, so I'm not sure what the "type" +-- field is for as a result. +data TnefObjectName = TnefObjectName { code :: Integer, + desc :: String } +instance Show TnefObjectName where + show = desc + + +tnef_object_names :: [TnefObjectName] +tnef_object_names = [ TnefObjectName 0x0000 "Owner", + TnefObjectName 0x0001 "Sent For", + TnefObjectName 0x0002 "Delegate", + TnefObjectName 0x0006 "Date Start", + TnefObjectName 0x0007 "Date End", + TnefObjectName 0x0008 "Owner Appointment ID", + TnefObjectName 0x0009 "Response Requested", + TnefObjectName 0x8000 "From", + TnefObjectName 0x8004 "Subject", + TnefObjectName 0x8005 "Date Sent", + TnefObjectName 0x8006 "Date Received", + TnefObjectName 0x8007 "Message Status", + TnefObjectName 0x8008 "Message Class", + TnefObjectName 0x8009 "Message ID", + TnefObjectName 0x800a "Parent ID", + TnefObjectName 0x800b "Conversation ID", + TnefObjectName 0x800c "Body", + TnefObjectName 0x800d "Priority", + TnefObjectName 0x800f "Attachment Data", + TnefObjectName 0x8010 "Attachment File Name", + TnefObjectName 0x8011 "Attachment Meta File", + TnefObjectName 0x8012 "Attachment Creation Date", + TnefObjectName 0x8013 "Attachment Modification Date", + TnefObjectName 0x8020 "Date Modified", + TnefObjectName 0x9001 "Attachment Transport Filename", + TnefObjectName 0x9002 "Attachment Rendering Data", + TnefObjectName 0x9003 "MAPI Properties", + TnefObjectName 0x9004 "Recipients", + TnefObjectName 0x9005 "Attachment", + TnefObjectName 0x9006 "TNEF Version", + TnefObjectName 0x9007 "OEM Codepage", + TnefObjectName 0x9008 "Original Message Class" ] + + +word_to_name :: Word16 -> TnefObjectName +word_to_name c = head [ x | x <- tnef_object_names, (code x) == read (show c)] diff --git a/test/body.tnef b/test/body.tnef new file mode 100644 index 0000000000000000000000000000000000000000..06ac6e11ff73e21859809af758052050a2c66329 GIT binary patch literal 7769 zcmcgx&2J<}6|eCuyBixP%U47efh$Xh1b93%{@%66>#;qyhxlVNo;AB%LQi+iOnG~{ zd#k(0>l|PS$`u76AtVHmxFF@kfeSfBLXqGP-~>WKaDYn$0zy6%!tcHA8Qa0Tim*jn zp6=?ZdiCm8@BQAZ>U%FQT=~MsGUs2qD9#DGGW2)hrSsw<3V%x8i9d_X@cnaQ0Ivq{ zm-)#3taucK-&{B+o)ClLG4XkHo6cn9e^oq%ikVF2k^33(BzhE9R?3Cd<)!82!pw4U zvUqj8Qkk7zU7j3YDNZe2of6FpnR6K3!B`oze+>U4B2%E}OZcA&%5X&#Tv@g=LY&NqfH6r3ZANXQ^nI3+V1r0KB%n_SwKKKX2tu@CHGH#l;$>& z8DgEkg6GPuYx(WcQY}}xwY;9IS9a?8?VF|5YHg=3%PX7Jt?Ev_R<2ifD{`&2ee*_s zd8<^bELU$-D_iv)Dos3dbEi^E@R8RZgk4s=_Z-y?iN$L|ynTHj^Di#jq!_N>{dDnH zuPt4={PSO26kpE&;RR|-SKdFaoFA7~wFx6xb~@VAVPvdGca>Z-ejMa&uT)dE4z%*3 zkV+GG;!qhV2Q03VybP5jnSZb7vOiqf@+S$}=$UFX&6>zNT45RFHkMb|)P zjmxumwo7q1XO-k!a18D_w_jYT>=tu{slw#=RB@&_H8K6QTyYZ94L-Ck1DU(r_Hm4t zdA<6o^X{)-`QzSm-`F~M)w|d?-6{L*+hHr(So=D`~ZDM#AhER{XfjS2Qr_y zL~Y;rq!9B@u52&YZ{MiM_4?+9ym51Bqq;1w&Egz9ckaQ z+NV&-aLtT;PSxFS8Pqe^R)tqMGFyS6Z& z@9D6#y>gp$S*h;!Zu6_#TXosAY*i{7ZMibk&#Th-LVdj=m#P~Za(h+Qs%z`@o%yBO zLb;7EG{vCo1TsUYPvGe8K#11TZ}H2phc)l3&?jG zE)5dx`?;vCO`=o7kJ^$)A>A-dJ2r+Fm*J%`n!fA$`vi_i+`!P>(% z+cYpX%GE76;3y%F>(Q4{)ITz$Jix+`{HxW&cfYzZ?HiJ{*pn;R>C0iOOWFG>PeI4N`2~;3BBGH}``}>|Uqwokry?QeD zExc=>2i{rm84ryh5*RY?sn9mMkTEW>0H$e50Rkxy8I=qb z?tw+G66aFQCisC0EsKJdj6I_)w1+P$8N!O}Ht`}y+feD}iTZmsm0DC+`)t&SL@*Dq zMaqUin3$dp!x&3MV8;QR7&Oyh@rXqfvLP-G0v{{OtnOQgR^-^trZyeWJ+TwBG>0ZQ zkO55~y`UB95m4ZQKlYc`Z@|P3@l8d z2I?XUMpA@OO{8aAfsQPfd3JaZ0bZGXVrjUy)qzh)pwj`gv4>cW;7C@UW)}(flQ%d> zoqCbLk}WKnBllu+Kw(bZvsJ+EVOty;jSdOzG&ORmEi~~gL{-uW1jfpw^?iclsEwC! zS38O+2UezwoQVacDJ2YsWTlyyV}YK`9D8hHL6i`rsL-0ljXfAGBoY*~x*T1*@fIlOsBR>U zvPH_Dlb&R|5dyu(=8yt+j0yK*cr(w(3)zXzki&LQOZQcnBjRBnT}+FJi}xf+fU|5H z({cLIOL=>Kk~t>{1o;E!8dy~(ha`)~Zh)Ku$szI`-JxWT_FZJuy?DS;6i`wxhYl;? z1e9AEL}Iok_MCKJ?1B`q2F`%8qa$z>C8Cs=_WSk%>|tBlN* zNZlO8-gu@)cLr7$#Ri_iFh%ixI2R)9A$lxl_tsVxvA0_G_?5z840hAJ+e!Hd`@8&-@bq8eOx2r@2oeS zc0cS~dkp$)iVf~NB>q81#W+j;o0whSJAomqPW<9&Whh(e|d|>{M+?M z@WE+Bymg(~1SbvBRmkWUn+{eDubY?N=4F7G@Jm>eQ*JLjlwajaqJnf7U8$b$mxsFN-C M7!nI6kfC?}1I+S#FaQ7m literal 0 HcmV?d00001 diff --git a/test/data-before-name.tnef b/test/data-before-name.tnef new file mode 100644 index 0000000000000000000000000000000000000000..81ca5d6479a57b0dfa862fb4a0010ac8e8fcce02 GIT binary patch literal 13468 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 literal 0 HcmV?d00001 diff --git a/test/ytnef_outlook_2k3_appointment.tnef b/test/ytnef_outlook_2k3_appointment.tnef new file mode 100644 index 0000000000000000000000000000000000000000..91496f74c39a59136ef39203632f536305c7a92d GIT binary patch literal 3057 zcmb7`Urbw79LK-sUiya>N*xn$%PtpZ97wFCl)vg|DRhufN=7$>vTO}hAuGKdEm2-f zH5z@;1breV#w;^F_~N6QCCVmm{#VouHy?~kOnfnman42Y_dC671P)7fZhFr>=kxvj z&iVa*_x9dr-a2%zuSGbQ+^7II!G~+f2{#RXDb3+m2zSv1A59I9#r=_7&YH~@=F-^$ z&N@VOu>u+)jSf*!6gWtO=zKa=NKczj&lYCP#6lrsS*OfkAkc0$XDxF&T}aJl@-0}e z5{{w{FIlX)T&SdF526VUgoUW2EwNv@B@}^98dT8Piv~nz=4bQfkhN%zS&JBtC&zlH zW~{}WwHThuW&BgtoIkZd`ciwLS~z!F##MCE5}uC?*) zkIwq;c{7VEq9!Q=+MX>avt^)P`r>+QwgC)GOXjfm!pj**%eh**Ryj0~ll%_u2#V*l zw5cPXVl^EP1z*aXe`n!pbmi4I)~2rg=AY+W)>m;Z4eXV@YQLJ;FWK#KXTXq}%`r8~ zxt(J2K=5)@C#UyTopiXpbvoCy=%ZVdm@81cF!~_ZFbsG3TE|a)?^(QmQFNP5c7qjp zMvOcC#nOQ8m7=EL2c9o+9S)`a5wc(YL{MIwN}eRndE{4n@vgX-qb?-}!N2#gXwEUpr5JJh)4#@k$NX zXt$F4h@Yn9=%`cj2HQT25oK+vxi;l^<4TQJ)~~cr9ivK3EomMhR|XPF?k3JPfFO>XP+5Srq;IY&T$y{QOSpGe(QPj;IdK&Tc_iSk_&qu^bRO4 ztzXP~2KV`v*YPg;Y8@O!6Q8IVcyvo%HSgv;>s!VZo5q@`lw*GHaT~0hJbHQK_kq`2 ze?D>i`bs_jFMF_0zQYXcm)bjdKYP$9ZFKxm<0Ah$uGjGXH1U`0`73eTn&O6J{5`ok zZj$!z+h}h}_9tn%b)Pxsb6oZ9J#)^D)(4JV0Os#8zqYZ@-UI2t7+=TX|6!WERCNcGD*rA(l65Y3ZEx2BCS)%DAf_t z<%rFaT}t|~$dgHH@+d|2amnV%OP+pD((EJ>w3`B1S#+G*HujUpJaKM1{;lDgLK7P@ g7dzFGbE%^`^iQ9I`Wo45VoykrE!SadZep+e2PTcjzyJUM literal 0 HcmV?d00001 diff --git a/test/ytnef_random_sample.tnef b/test/ytnef_random_sample.tnef new file mode 100644 index 0000000000000000000000000000000000000000..b9f629502cced917e4eae9dbe4d1334d18ac69b9 GIT binary patch literal 98184 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 IaYyX`0qK|RB>(^b literal 0 HcmV?d00001 -- 2.44.2