diff options
author | Stephen Paul Weber <singpolyma@singpolyma.net> | 2012-12-29 11:14:38 -0500 |
---|---|---|
committer | Stephen Paul Weber <singpolyma@singpolyma.net> | 2012-12-29 11:14:38 -0500 |
commit | 4b5e0e3d27973f8627ed3d83013f55c3b365b306 (patch) | |
tree | b2358f8288bc5d950f372dc369fd48e0c66efd8e | |
parent | 86d6407eccd1ed9f44f4e1a0e495e504d393c1d8 (diff) |
Support partial lengths
-rw-r--r-- | Data/OpenPGP.hs | 38 |
1 files changed, 23 insertions, 15 deletions
diff --git a/Data/OpenPGP.hs b/Data/OpenPGP.hs index dca7838..c6c22e4 100644 --- a/Data/OpenPGP.hs +++ b/Data/OpenPGP.hs | |||
@@ -237,31 +237,39 @@ instance BINARY_CLASS Packet where | |||
237 | blen = fromIntegral $ B.length body | 237 | blen = fromIntegral $ B.length body |
238 | (body, tag) = put_packet p | 238 | (body, tag) = put_packet p |
239 | get = do | 239 | get = do |
240 | tag <- get :: Get Word8 | 240 | (t, packet) <- get_packet_bytes |
241 | let (t, l) = | 241 | return $ unsafeRunGet (parse_packet t) (B.concat packet) |
242 | if (tag .&. 64) /= 0 then | 242 | |
243 | (tag .&. 63, parse_new_length) | 243 | get_packet_bytes :: Get (Word8, [B.ByteString]) |
244 | else | 244 | get_packet_bytes = do |
245 | ((tag `shiftR` 2) .&. 15, parse_old_length tag) | 245 | tag <- get |
246 | len <- l | 246 | let (t, l) = |
247 | -- This forces the whole packet to be consumed | 247 | if (tag .&. 64) /= 0 then |
248 | packet <- getSomeByteString (fromIntegral len) | 248 | (tag .&. 63, parse_new_length) |
249 | return $ unsafeRunGet (parse_packet t) packet | 249 | else |
250 | ((tag `shiftR` 2) .&. 15, (,) <$> parse_old_length tag <*> pure False) | ||
251 | (len, partial) <- l | ||
252 | -- This forces the whole packet to be consumed | ||
253 | packet <- getSomeByteString (fromIntegral len) | ||
254 | if not partial then return (t, [packet]) else | ||
255 | (,) t <$> ((packet:) . snd) <$> get_packet_bytes | ||
250 | 256 | ||
251 | -- http://tools.ietf.org/html/rfc4880#section-4.2.2 | 257 | -- http://tools.ietf.org/html/rfc4880#section-4.2.2 |
252 | parse_new_length :: Get Word32 | 258 | parse_new_length :: Get (Word32, Bool) |
253 | parse_new_length = do | 259 | parse_new_length = do |
254 | len <- fmap fromIntegral (get :: Get Word8) | 260 | len <- fmap fromIntegral (get :: Get Word8) |
255 | case len of | 261 | case len of |
256 | -- One octet length | 262 | -- One octet length |
257 | _ | len < 192 -> return len | 263 | _ | len < 192 -> return (len, False) |
258 | -- Two octet length | 264 | -- Two octet length |
259 | _ | len > 191 && len < 224 -> do | 265 | _ | len > 191 && len < 224 -> do |
260 | second <- fmap fromIntegral (get :: Get Word8) | 266 | second <- fmap fromIntegral (get :: Get Word8) |
261 | return $ ((len - 192) `shiftL` 8) + second + 192 | 267 | return (((len - 192) `shiftL` 8) + second + 192, False) |
262 | -- Five octet length | 268 | -- Five octet length |
263 | 255 -> get :: Get Word32 | 269 | 255 -> (,) <$> (get :: Get Word32) <*> pure False |
264 | -- TODO: Partial body lengths. 1 << (len & 0x1F) | 270 | -- Partial length (streaming) |
271 | _ | len >= 224 && len < 255 -> | ||
272 | return (1 `shiftL` (fromIntegral len .&. 0x1F), True) | ||
265 | _ -> fail "Unsupported new packet length." | 273 | _ -> fail "Unsupported new packet length." |
266 | 274 | ||
267 | -- http://tools.ietf.org/html/rfc4880#section-4.2.1 | 275 | -- http://tools.ietf.org/html/rfc4880#section-4.2.1 |