From a6103eaef256b0cd8c7e841dbf17b49f6e83f359 Mon Sep 17 00:00:00 2001
From: Jean-Paul Calderone <exarkun@twistedmatrix.com>
Date: Thu, 1 Jun 2023 13:28:52 -0400
Subject: [PATCH] Add a demo app that downloads SDMF

---
 README.md             |  4 ++--
 download-sdmf/Main.hs | 34 ++++++++++++++++++++++++++++++++++
 gbs-downloader.cabal  | 20 ++++++++++++++++++++
 3 files changed, 56 insertions(+), 2 deletions(-)
 create mode 100644 download-sdmf/Main.hs

diff --git a/README.md b/README.md
index c34c52b..b125ead 100644
--- a/README.md
+++ b/README.md
@@ -7,8 +7,8 @@ It aims for bit-for-bit compatibility with the original Python implementation.
 
 ### What is the current state?
 
-It's just starting.
-It can't do much.
+* It can download immutable and mutable shares from Great Black Swamp storage servers.
+* It can interpret, decode, and decrypt the data for CHK- and SDMF-encoded shares to recover the plaintext.
 
 ## Why does it exist?
 
diff --git a/download-sdmf/Main.hs b/download-sdmf/Main.hs
new file mode 100644
index 0000000..4e981e1
--- /dev/null
+++ b/download-sdmf/Main.hs
@@ -0,0 +1,34 @@
+module Main where
+
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Char8 as C8
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.Text as T
+import Data.Yaml (decodeEither')
+import System.Environment (getArgs)
+import Tahoe.Announcement (Announcements (..))
+import Tahoe.Download (announcementToMutableStorageServer, download)
+import Tahoe.SDMF (SDMF (..), pCapability, writerReader)
+import Text.Megaparsec (parse)
+
+main :: IO ()
+main = do
+    [announcementPath, readCap] <- getArgs
+    -- Load server announcements
+    announcementsBytes <- B.readFile announcementPath
+    let Right (Announcements announcements) = decodeEither' announcementsBytes
+
+    -- Accept & parse read capability
+    case parse pCapability "<argv>" (T.pack readCap) of
+        Left e -> print $ "Failed to parse cap: " <> show e
+        Right (SDMFVerifier _) -> C8.putStrLn "Nothing currently implemented for verifier caps."
+        Right (SDMFWriter rwcap) -> go announcements (writerReader rwcap)
+        Right (SDMFReader rocap) -> go announcements rocap
+  where
+    go announcements cap = do
+        -- Download & decode the shares
+        result <- download announcements cap announcementToMutableStorageServer
+
+        -- Show the result
+        putStrLn "Your result:"
+        either print (C8.putStrLn . BL.toStrict) result
diff --git a/gbs-downloader.cabal b/gbs-downloader.cabal
index 908ee89..d386c9d 100644
--- a/gbs-downloader.cabal
+++ b/gbs-downloader.cabal
@@ -155,6 +155,26 @@ executable gbs-download-chk
   -- Base language which the package is written in.
   default-language: Haskell2010
 
+executable gbs-download-sdmf
+  import:
+    warnings
+    , language
+
+  main-is:          Main.hs
+  build-depends:
+    , aeson
+    , base
+    , bytestring
+    , containers
+    , gbs-downloader
+    , megaparsec
+    , tahoe-ssk
+    , text
+    , yaml
+
+  hs-source-dirs:   download-sdmf
+  default-language: Haskell2010
+
 test-suite gbs-downloader-test
   -- Import common warning flags.
   import:
-- 
GitLab