-- -- 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