fetchImage :: String -> String -> IO (Either String Content)
fetchImage href link = do
  mbimg <-
      case (isURI link, readDataURI link) of
       (True, Just (mime,_,True,base64)) ->
           let mime' = map toLower mime
           in if mime' == "image/png" || mime' == "image/jpeg"
              then return (Just (mime',base64))
              else return Nothing
       (True, Just _) -> return Nothing  -- not base64-encoded
       (True, Nothing) -> fetchURL link
       (False, _) -> do
        d <- nothingOnError $ B.readFile (unEscapeString link)
        let t = case map toLower (takeExtension link) of
                  ".png" -> Just "image/png"
                  ".jpg" -> Just "image/jpeg"
                  ".jpeg" -> Just "image/jpeg"
                  ".jpe" -> Just "image/jpeg"
                  _ -> Nothing  -- only PNG and JPEG are supported in FB2
        return $ liftM2 (,) t (liftM (toStr . encode) d)
  case mbimg of
    Just (imgtype, imgdata) -> do
        return . Right $ el "binary"
                   ( [uattr "id" href
                     , uattr "content-type" imgtype]
                   , txt imgdata )
    _ -> return (Left ('#':href))
  where
   nothingOnError :: (IO B.ByteString) -> (IO (Maybe B.ByteString))
   nothingOnError action = liftM Just action `E.catch` omnihandler
   omnihandler :: E.SomeException -> IO (Maybe B.ByteString)
   omnihandler _ = return Nothing

-- | Extract mime type and encoded data from the Data URI.
fetchImage :: String -> String -> IO (Either String Content)
fetchImage href link = do
  mbimg <-
      case (isURI link, readDataURI link) of
       (True, Just (mime,_,True,base64)) ->
           let mime' = map toLower mime
           in if mime' == "image/png" || mime' == "image/jpeg"
              then return (Just (mime',base64))
              else return Nothing
       (True, Just _) -> return Nothing  -- not base64-encoded
       (True, Nothing) -> fetchURL link
       (False, _) -> do
        d <- nothingOnError $ B.readFile (unEscapeString link)
        let t = case map toLower (takeExtension link) of
                  ".png" -> Just "image/png"
                  ".jpg" -> Just "image/jpeg"
                  ".jpeg" -> Just "image/jpeg"
                  ".jpe" -> Just "image/jpeg"
                  _ -> Nothing  -- only PNG and JPEG are supported in FB2
        return $ liftM2 (,) t (liftM (toStr . encode) d)
  case mbimg of
    Just (imgtype, imgdata) -> do
        return . Right $ el "binary"
                   ( [uattr "id" href
                     , uattr "content-type" imgtype]
                   , txt imgdata )
    _ -> return (Left ('#':href))
  where
   nothingOnError :: (IO B.ByteString) -> (IO (Maybe B.ByteString))
   nothingOnError action = liftM Just action `E.catch` omnihandler
   omnihandler :: E.SomeException -> IO (Maybe B.ByteString)
   omnihandler _ = return Nothing

-- | Extract mime type and encoded data from the Data URI.
fetchImage href link = do
  mbimg <-
      case (isURI link, readDataURI link) of
       (True, Just (mime,_,True,base64)) ->
           let mime' = map toLower mime
           in if mime' == "image/png" || mime' == "image/jpeg"
              then return (Just (mime',base64))
              else return Nothing
       (True, Just _) -> return Nothing  -- not base64-encoded
       (True, Nothing) -> fetchURL link
       (False, _) -> do
        d <- nothingOnError $ B.readFile (unEscapeString link)
        let t = case map toLower (takeExtension link) of
                  ".png" -> Just "image/png"
                  ".jpg" -> Just "image/jpeg"
                  ".jpeg" -> Just "image/jpeg"
                  ".jpe" -> Just "image/jpeg"
                  _ -> Nothing  -- only PNG and JPEG are supported in FB2
        return $ liftM2 (,) t (liftM (toStr . encode) d)
  case mbimg of
    Just (imgtype, imgdata) -> do
        return . Right $ el "binary"
                   ( [uattr "id" href
                     , uattr "content-type" imgtype]
                   , txt imgdata )
    _ -> return (Left ('#':href))
  where
   nothingOnError :: (IO B.ByteString) -> (IO (Maybe B.ByteString))
   nothingOnError action = liftM Just action `E.catch` omnihandler
   omnihandler :: E.SomeException -> IO (Maybe B.ByteString)
   omnihandler _ = return Nothing

-- | Extract mime type and encoded data from the Data URI.