packages feed

magic-wormhole 0.1.0 → 0.2.0

raw patch · 11 files changed

+316/−182 lines, 11 filesdep ~basedep ~spake2dep ~websocketssetup-changednew-uploaderPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base, spake2, websockets

API changes (from Hackage documentation)

- MagicWormhole: newtype Offer
- MagicWormhole.Internal.FileTransfer: newtype Offer
+ MagicWormhole: Directory :: DirectoryMode -> Text -> Natural -> Natural -> Natural -> Offer
+ MagicWormhole: File :: FilePath -> FileOffset -> Offer
+ MagicWormhole: ZipFileDeflated :: DirectoryMode
+ MagicWormhole: [dirName] :: Offer -> Text
+ MagicWormhole: [directoryMode] :: Offer -> DirectoryMode
+ MagicWormhole: [numBytes] :: Offer -> Natural
+ MagicWormhole: [numFiles] :: Offer -> Natural
+ MagicWormhole: [zipSize] :: Offer -> Natural
+ MagicWormhole: data DirectoryMode
+ MagicWormhole: data Offer
+ MagicWormhole: deriveKey :: EncryptedConnection -> Purpose -> Key
+ MagicWormhole.Internal.FileTransfer: Directory :: DirectoryMode -> Text -> Natural -> Natural -> Natural -> Offer
+ MagicWormhole.Internal.FileTransfer: File :: FilePath -> FileOffset -> Offer
+ MagicWormhole.Internal.FileTransfer: ZipFileDeflated :: DirectoryMode
+ MagicWormhole.Internal.FileTransfer: [dirName] :: Offer -> Text
+ MagicWormhole.Internal.FileTransfer: [directoryMode] :: Offer -> DirectoryMode
+ MagicWormhole.Internal.FileTransfer: [numBytes] :: Offer -> Natural
+ MagicWormhole.Internal.FileTransfer: [numFiles] :: Offer -> Natural
+ MagicWormhole.Internal.FileTransfer: [zipSize] :: Offer -> Natural
+ MagicWormhole.Internal.FileTransfer: data DirectoryMode
+ MagicWormhole.Internal.FileTransfer: data Offer
+ MagicWormhole.Internal.FileTransfer: instance Data.Aeson.Types.FromJSON.FromJSON MagicWormhole.Internal.FileTransfer.DirectoryMode
+ MagicWormhole.Internal.FileTransfer: instance Data.Aeson.Types.ToJSON.ToJSON MagicWormhole.Internal.FileTransfer.DirectoryMode
+ MagicWormhole.Internal.FileTransfer: instance GHC.Classes.Eq MagicWormhole.Internal.FileTransfer.DirectoryMode
+ MagicWormhole.Internal.FileTransfer: instance GHC.Show.Show MagicWormhole.Internal.FileTransfer.DirectoryMode
+ MagicWormhole.Internal.Peer: deriveKey :: EncryptedConnection -> Purpose -> Key

Files

− CHANGELOG.md
@@ -1,7 +0,0 @@-# Changelog--## 0.1.0 (2018-01-17)--Initial release--* Exchange text messages with Magic Wormhole peers
LICENSE view
@@ -1,163 +1,202 @@-Apache License -Version 2.0, January 2004+                                 Apache License+                           Version 2.0, January 2004+                        http://www.apache.org/licenses/ -http://www.apache.org/licenses/+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION+   1. Definitions. -1. Definitions.+      "License" shall mean the terms and conditions for use, reproduction,+      and distribution as defined by Sections 1 through 9 of this document. -"License" shall mean the terms and conditions for use, reproduction, and-distribution as defined by Sections 1 through 9 of this document.+      "Licensor" shall mean the copyright owner or entity authorized by+      the copyright owner that is granting the License. -"Licensor" shall mean the copyright owner or entity authorized by the-copyright owner that is granting the License.+      "Legal Entity" shall mean the union of the acting entity and all+      other entities that control, are controlled by, or are under common+      control with that entity. For the purposes of this definition,+      "control" means (i) the power, direct or indirect, to cause the+      direction or management of such entity, whether by contract or+      otherwise, or (ii) ownership of fifty percent (50%) or more of the+      outstanding shares, or (iii) beneficial ownership of such entity. -"Legal Entity" shall mean the union of the acting entity and all other-entities that control, are controlled by, or are under common control with-that entity. For the purposes of this definition, "control" means (i) the-power, direct or indirect, to cause the direction or management of such-entity, whether by contract or otherwise, or (ii) ownership of fifty percent-(50%) or more of the outstanding shares, or (iii) beneficial ownership of such-entity.+      "You" (or "Your") shall mean an individual or Legal Entity+      exercising permissions granted by this License. -"You" (or "Your") shall mean an individual or Legal Entity exercising-permissions granted by this License.+      "Source" form shall mean the preferred form for making modifications,+      including but not limited to software source code, documentation+      source, and configuration files. -"Source" form shall mean the preferred form for making modifications,-including but not limited to software source code, documentation source, and-configuration files.+      "Object" form shall mean any form resulting from mechanical+      transformation or translation of a Source form, including but+      not limited to compiled object code, generated documentation,+      and conversions to other media types. -"Object" form shall mean any form resulting from mechanical transformation or-translation of a Source form, including but not limited to compiled object-code, generated documentation, and conversions to other media types.+      "Work" shall mean the work of authorship, whether in Source or+      Object form, made available under the License, as indicated by a+      copyright notice that is included in or attached to the work+      (an example is provided in the Appendix below). -"Work" shall mean the work of authorship, whether in Source or Object form,-made available under the License, as indicated by a copyright notice that is-included in or attached to the work (an example is provided in the Appendix-below).+      "Derivative Works" shall mean any work, whether in Source or Object+      form, that is based on (or derived from) the Work and for which the+      editorial revisions, annotations, elaborations, or other modifications+      represent, as a whole, an original work of authorship. For the purposes+      of this License, Derivative Works shall not include works that remain+      separable from, or merely link (or bind by name) to the interfaces of,+      the Work and Derivative Works thereof. -"Derivative Works" shall mean any work, whether in Source or Object form, that-is based on (or derived from) the Work and for which the editorial revisions,-annotations, elaborations, or other modifications represent, as a whole, an-original work of authorship. For the purposes of this License, Derivative-Works shall not include works that remain separable from, or merely link (or-bind by name) to the interfaces of, the Work and Derivative Works thereof.+      "Contribution" shall mean any work of authorship, including+      the original version of the Work and any modifications or additions+      to that Work or Derivative Works thereof, that is intentionally+      submitted to Licensor for inclusion in the Work by the copyright owner+      or by an individual or Legal Entity authorized to submit on behalf of+      the copyright owner. For the purposes of this definition, "submitted"+      means any form of electronic, verbal, or written communication sent+      to the Licensor or its representatives, including but not limited to+      communication on electronic mailing lists, source code control systems,+      and issue tracking systems that are managed by, or on behalf of, the+      Licensor for the purpose of discussing and improving the Work, but+      excluding communication that is conspicuously marked or otherwise+      designated in writing by the copyright owner as "Not a Contribution." -"Contribution" shall mean any work of authorship, including the original-version of the Work and any modifications or additions to that Work or-Derivative Works thereof, that is intentionally submitted to Licensor for-inclusion in the Work by the copyright owner or by an individual or Legal-Entity authorized to submit on behalf of the copyright owner. For the purposes-of this definition, "submitted" means any form of electronic, verbal, or-written communication sent to the Licensor or its representatives, including-but not limited to communication on electronic mailing lists, source code-control systems, and issue tracking systems that are managed by, or on behalf-of, the Licensor for the purpose of discussing and improving the Work, but-excluding communication that is conspicuously marked or otherwise designated-in writing by the copyright owner as "Not a Contribution."+      "Contributor" shall mean Licensor and any individual or Legal Entity+      on behalf of whom a Contribution has been received by Licensor and+      subsequently incorporated within the Work. -"Contributor" shall mean Licensor and any individual or Legal Entity on behalf-of whom a Contribution has been received by Licensor and subsequently-incorporated within the Work.+   2. Grant of Copyright License. Subject to the terms and conditions of+      this License, each Contributor hereby grants to You a perpetual,+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable+      copyright license to reproduce, prepare Derivative Works of,+      publicly display, publicly perform, sublicense, and distribute the+      Work and such Derivative Works in Source or Object form. -2. Grant of Copyright License. Subject to the terms and conditions of this-License, each Contributor hereby grants to You a perpetual, worldwide,-non-exclusive, no-charge, royalty-free, irrevocable copyright license to-reproduce, prepare Derivative Works of, publicly display, publicly perform,-sublicense, and distribute the Work and such Derivative Works in Source or-Object form.+   3. Grant of Patent License. Subject to the terms and conditions of+      this License, each Contributor hereby grants to You a perpetual,+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable+      (except as stated in this section) patent license to make, have made,+      use, offer to sell, sell, import, and otherwise transfer the Work,+      where such license applies only to those patent claims licensable+      by such Contributor that are necessarily infringed by their+      Contribution(s) alone or by combination of their Contribution(s)+      with the Work to which such Contribution(s) was submitted. If You+      institute patent litigation against any entity (including a+      cross-claim or counterclaim in a lawsuit) alleging that the Work+      or a Contribution incorporated within the Work constitutes direct+      or contributory patent infringement, then any patent licenses+      granted to You under this License for that Work shall terminate+      as of the date such litigation is filed. -3. Grant of Patent License. Subject to the terms and conditions of this-License, each Contributor hereby grants to You a perpetual, worldwide,-non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this-section) patent license to make, have made, use, offer to sell, sell, import,-and otherwise transfer the Work, where such license applies only to those-patent claims licensable by such Contributor that are necessarily infringed by-their Contribution(s) alone or by combination of their Contribution(s) with-the Work to which such Contribution(s) was submitted. If You institute patent-litigation against any entity (including a cross-claim or counterclaim in a-lawsuit) alleging that the Work or a Contribution incorporated within the Work-constitutes direct or contributory patent infringement, then any patent-licenses granted to You under this License for that Work shall terminate as of-the date such litigation is filed.+   4. Redistribution. You may reproduce and distribute copies of the+      Work or Derivative Works thereof in any medium, with or without+      modifications, and in Source or Object form, provided that You+      meet the following conditions: -4. Redistribution. You may reproduce and distribute copies of the Work or-Derivative Works thereof in any medium, with or without modifications, and in-Source or Object form, provided that You meet the following conditions:+      (a) You must give any other recipients of the Work or+          Derivative Works a copy of this License; and -You must give any other recipients of the Work or Derivative Works a copy of-this License; and+      (b) You must cause any modified files to carry prominent notices+          stating that You changed the files; and -You must cause any modified files to carry prominent notices stating that You-changed the files; and+      (c) You must retain, in the Source form of any Derivative Works+          that You distribute, all copyright, patent, trademark, and+          attribution notices from the Source form of the Work,+          excluding those notices that do not pertain to any part of+          the Derivative Works; and -You must retain, in the Source form of any Derivative Works that You-distribute, all copyright, patent, trademark, and attribution notices from the-Source form of the Work, excluding those notices that do not pertain to any-part of the Derivative Works; and+      (d) If the Work includes a "NOTICE" text file as part of its+          distribution, then any Derivative Works that You distribute must+          include a readable copy of the attribution notices contained+          within such NOTICE file, excluding those notices that do not+          pertain to any part of the Derivative Works, in at least one+          of the following places: within a NOTICE text file distributed+          as part of the Derivative Works; within the Source form or+          documentation, if provided along with the Derivative Works; or,+          within a display generated by the Derivative Works, if and+          wherever such third-party notices normally appear. The contents+          of the NOTICE file are for informational purposes only and+          do not modify the License. You may add Your own attribution+          notices within Derivative Works that You distribute, alongside+          or as an addendum to the NOTICE text from the Work, provided+          that such additional attribution notices cannot be construed+          as modifying the License. -If the Work includes a "NOTICE" text file as part of its distribution, then-any Derivative Works that You distribute must include a readable copy of the-attribution notices contained within such NOTICE file, excluding those notices-that do not pertain to any part of the Derivative Works, in at least one of-the following places: within a NOTICE text file distributed as part of the-Derivative Works; within the Source form or documentation, if provided along-with the Derivative Works; or, within a display generated by the Derivative-Works, if and wherever such third-party notices normally appear. The contents-of the NOTICE file are for informational purposes only and do not modify the-License. You may add Your own attribution notices within Derivative Works that-You distribute, alongside or as an addendum to the NOTICE text from the Work,-provided that such additional attribution notices cannot be construed as-modifying the License.+      You may add Your own copyright statement to Your modifications and+      may provide additional or different license terms and conditions+      for use, reproduction, or distribution of Your modifications, or+      for any such Derivative Works as a whole, provided Your use,+      reproduction, and distribution of the Work otherwise complies with+      the conditions stated in this License. -You may add Your own copyright statement to Your modifications and may provide-additional or different license terms and conditions for use, reproduction, or-distribution of Your modifications, or for any such Derivative Works as a-whole, provided Your use, reproduction, and distribution of the Work otherwise-complies with the conditions stated in this License.+   5. Submission of Contributions. Unless You explicitly state otherwise,+      any Contribution intentionally submitted for inclusion in the Work+      by You to the Licensor shall be under the terms and conditions of+      this License, without any additional terms or conditions.+      Notwithstanding the above, nothing herein shall supersede or modify+      the terms of any separate license agreement you may have executed+      with Licensor regarding such Contributions. -5. Submission of Contributions. Unless You explicitly state otherwise, any-Contribution intentionally submitted for inclusion in the Work by You to the-Licensor shall be under the terms and conditions of this License, without any-additional terms or conditions. Notwithstanding the above, nothing herein-shall supersede or modify the terms of any separate license agreement you may-have executed with Licensor regarding such Contributions.+   6. Trademarks. This License does not grant permission to use the trade+      names, trademarks, service marks, or product names of the Licensor,+      except as required for reasonable and customary use in describing the+      origin of the Work and reproducing the content of the NOTICE file. -6. Trademarks. This License does not grant permission to use the trade names,-trademarks, service marks, or product names of the Licensor, except as-required for reasonable and customary use in describing the origin of the Work-and reproducing the content of the NOTICE file.+   7. Disclaimer of Warranty. Unless required by applicable law or+      agreed to in writing, Licensor provides the Work (and each+      Contributor provides its Contributions) on an "AS IS" BASIS,+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or+      implied, including, without limitation, any warranties or conditions+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A+      PARTICULAR PURPOSE. You are solely responsible for determining the+      appropriateness of using or redistributing the Work and assume any+      risks associated with Your exercise of permissions under this License. -7. Disclaimer of Warranty. Unless required by applicable law or agreed to in-writing, Licensor provides the Work (and each Contributor provides its-Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY-KIND, either express or implied, including, without limitation, any warranties-or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A-PARTICULAR PURPOSE. You are solely responsible for determining the-appropriateness of using or redistributing the Work and assume any risks-associated with Your exercise of permissions under this License.+   8. Limitation of Liability. In no event and under no legal theory,+      whether in tort (including negligence), contract, or otherwise,+      unless required by applicable law (such as deliberate and grossly+      negligent acts) or agreed to in writing, shall any Contributor be+      liable to You for damages, including any direct, indirect, special,+      incidental, or consequential damages of any character arising as a+      result of this License or out of the use or inability to use the+      Work (including but not limited to damages for loss of goodwill,+      work stoppage, computer failure or malfunction, or any and all+      other commercial damages or losses), even if such Contributor+      has been advised of the possibility of such damages. -8. Limitation of Liability. In no event and under no legal theory, whether in-tort (including negligence), contract, or otherwise, unless required by-applicable law (such as deliberate and grossly negligent acts) or agreed to in-writing, shall any Contributor be liable to You for damages, including any-direct, indirect, special, incidental, or consequential damages of any-character arising as a result of this License or out of the use or inability-to use the Work (including but not limited to damages for loss of goodwill,-work stoppage, computer failure or malfunction, or any and all other-commercial damages or losses), even if such Contributor has been advised of-the possibility of such damages.+   9. Accepting Warranty or Additional Liability. While redistributing+      the Work or Derivative Works thereof, You may choose to offer,+      and charge a fee for, acceptance of support, warranty, indemnity,+      or other liability obligations and/or rights consistent with this+      License. However, in accepting such obligations, You may act only+      on Your own behalf and on Your sole responsibility, not on behalf+      of any other Contributor, and only if You agree to indemnify,+      defend, and hold each Contributor harmless for any liability+      incurred by, or claims asserted against, such Contributor by reason+      of your accepting any such warranty or additional liability. -9. Accepting Warranty or Additional Liability. While redistributing the Work-or Derivative Works thereof, You may choose to offer, and charge a fee for,-acceptance of support, warranty, indemnity, or other liability obligations-and/or rights consistent with this License. However, in accepting such-obligations, You may act only on Your own behalf and on Your sole-responsibility, not on behalf of any other Contributor, and only if You agree-to indemnify, defend, and hold each Contributor harmless for any liability-incurred by, or claims asserted against, such Contributor by reason of your-accepting any such warranty or additional liability.+   END OF TERMS AND CONDITIONS -END OF TERMS AND CONDITIONS+   APPENDIX: How to apply the Apache License to your work.++      To apply the Apache License to your work, attach the following+      boilerplate notice, with the fields enclosed by brackets "[]"+      replaced with your own identifying information. (Don't include+      the brackets!)  The text should be enclosed in the appropriate+      comment syntax for the file format. We also recommend that a+      file or class name and description of purpose be included on the+      same "printed page" as the copyright notice for easier+      identification within third-party archives.++   Copyright [yyyy] [name of copyright owner]++   Licensed under the Apache License, Version 2.0 (the "License");+   you may not use this file except in compliance with the License.+   You may obtain a copy of the License at++       http://www.apache.org/licenses/LICENSE-2.0++   Unless required by applicable law or agreed to in writing, software+   distributed under the License is distributed on an "AS IS" BASIS,+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+   See the License for the specific language governing permissions and+   limitations under the License.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
cmd/HocusPocus.hs view
@@ -87,7 +87,9 @@         MagicWormhole.PlainText received <- atomically $ MagicWormhole.receiveMessage conn         case Aeson.eitherDecode (toS received) of           Left err -> panic $ "Could not decode message: " <> show err-          Right (MagicWormhole.Message message) -> pure message)+          Right (MagicWormhole.Message message) -> pure message+          Right (MagicWormhole.File _ _) -> pure $ "File transfer is not supported"+          Right (MagicWormhole.Directory _ _ _ _ _) -> pure $ "Directory transfer is not supported")  -- | Bounce a trivial message to and from a Rendezvous server. bounce :: MagicWormhole.WebSocketEndpoint -> MagicWormhole.AppID -> IO ()@@ -114,6 +116,8 @@       case Aeson.eitherDecode (toS received) of         Left err -> panic $ "Could not decode message: " <> show err         Right (MagicWormhole.Message message) -> pure message+        Right (MagicWormhole.File _ _) -> pure $ "File transfer is not supported"+        Right (MagicWormhole.Directory _ _ _ _ _) -> pure $ "Directory transfer is not supported"      password = Spake2.makePassword "potato" 
magic-wormhole.cabal view
@@ -1,32 +1,27 @@--- This file has been generated from package.yaml by hpack version 0.17.1.+-- This file has been generated from package.yaml by hpack version 0.28.2. -- -- see: https://github.com/sol/hpack+--+-- hash: 70e0d0470150c88f241234f7c12f2f2e92a2dcc939f84e6da5db4c8ba17a06a5  name:           magic-wormhole-version:        0.1.0+version:        0.2.0 synopsis:       Interact with Magic Wormhole-description:    Client library for interacting with a Magic Wormhole server.-                .-                Magic Wormhole is a technology for getting things from one computer to another, safely.-                It does this by using a server to locate peers, and then using SPAKE2 encryption to-                negotiate a secure connection to a peer. It is especially useful for sending files-                and short messages to other humans.+description:    Magic Wormhole is a scheme to get things from one computer to another,+                safely.                 .-                You can learn more about Magic Wormhole by exploring the documentation on-                the [canonical, Python-                implementation](https://github.com/warner/magic-wormhole).+                This is a library for client-side interactions with a Magic Wormhole server. category:       Crypto-homepage:       https://github.com/LeastAuthority/haskell-magic-wormhole#readme-bug-reports:    https://github.com/LeastAuthority/haskell-magic-wormhole/issues-maintainer:     Jonathan M. Lange <jml@mumak.net>+homepage:       https://github.com/leastauthority/haskell-magic-wormhole#readme+bug-reports:    https://github.com/leastauthority/haskell-magic-wormhole/issues+author:         Jonathan M. Lange <jml@mumak.net>,+                Ramakrishnan Muthukrishnan <ram@leastauthority.com>,+                Jean-Paul Calderone <jean-paul@leastauthority.com>+maintainer:     Least Authority TFA GmbH license:        Apache license-file:   LICENSE build-type:     Simple cabal-version:  >= 1.10--extra-source-files:-    CHANGELOG.md- data-files:     tests/python/derive_phase_key.py     tests/python/nacl_exchange.py@@ -35,18 +30,16 @@  source-repository head   type: git-  location: https://github.com/LeastAuthority/haskell-magic-wormhole+  location: https://github.com/leastauthority/haskell-magic-wormhole  library   hs-source-dirs:       src   default-extensions: NoImplicitPrelude OverloadedStrings TypeApplications-  ghc-options: -Wall+  ghc-options: -Wall -Werror=incomplete-patterns   build-depends:-      base >= 4.9 && < 5-    , protolude >= 0.2-    , spake2 >= 0.4.1-    , aeson+      aeson+    , base ==4.9.*     , bytestring     , containers     , cryptonite@@ -55,10 +48,12 @@     , network     , network-uri     , pqueue+    , protolude >=0.2     , saltine+    , spake2 >=0.4     , stm     , unordered-containers-    , websockets+    , websockets >=0.8.0.0   exposed-modules:       MagicWormhole       MagicWormhole.Internal.ClientProtocol@@ -70,21 +65,25 @@       MagicWormhole.Internal.Sequential       MagicWormhole.Internal.Versions       MagicWormhole.Internal.WebSockets+  other-modules:+      Paths_magic_wormhole   default-language: Haskell2010  executable hocus-pocus   main-is: HocusPocus.hs+  other-modules:+      Paths_magic_wormhole   hs-source-dirs:       cmd   default-extensions: NoImplicitPrelude OverloadedStrings TypeApplications-  ghc-options: -Wall+  ghc-options: -Wall -Werror=incomplete-patterns   build-depends:-      base >= 4.9 && < 5-    , protolude >= 0.2-    , spake2 >= 0.4.1-    , aeson+      aeson+    , base ==4.9.*     , magic-wormhole     , optparse-applicative+    , protolude >=0.2+    , spake2 >=0.4     , text   default-language: Haskell2010 @@ -94,28 +93,30 @@   hs-source-dirs:       tests   default-extensions: NoImplicitPrelude OverloadedStrings TypeApplications-  ghc-options: -Wall+  ghc-options: -Wall -Werror=incomplete-patterns   build-depends:-      base >= 4.9 && < 5-    , protolude >= 0.2-    , spake2 >= 0.4.1-    , aeson+      aeson+    , base ==4.9.*     , bytestring     , hedgehog     , magic-wormhole     , memory     , process+    , protolude >=0.2     , saltine+    , spake2 >=0.3     , stm     , tasty     , tasty-hedgehog     , tasty-hspec   other-modules:       ClientProtocol+      FileTransfer       Generator       Integration       Messages       Pake       Sequential       WebSockets+      Paths_magic_wormhole   default-language: Haskell2010
src/MagicWormhole.hs view
@@ -59,6 +59,7 @@   , Peer.withEncryptedConnection   , ClientProtocol.Connection   , Peer.EncryptedConnection+  , Peer.deriveKey     -- *** Errors   , ClientProtocol.PeerError   , Versions.VersionsError@@ -75,6 +76,7 @@     -- However, Magic Wormhole comes with at least one built-in "application": message and file transfer.     -- This Haskell implementation only supports sending and receiving a simple message.   , FileTransfer.Offer(..)+  , FileTransfer.DirectoryMode(..)   ) where  import qualified MagicWormhole.Internal.ClientProtocol as ClientProtocol
src/MagicWormhole/Internal/FileTransfer.hs view
@@ -8,6 +8,8 @@ -- you can send an 'Offer' to share a simple text message. module MagicWormhole.Internal.FileTransfer   ( Offer(..)+  -- * for tests+  , DirectoryMode(..)   ) where  import Protolude@@ -19,20 +21,61 @@   , (.=)   , object   , withObject+  , Value( String )   )+import Data.Aeson.Types (typeMismatch)+import System.Posix.Types (FileOffset)+import Numeric.Natural (Natural)  -- | An offer made by a sender as part of the Magic Wormhole file transfer protocol. -- -- Currently only supports sending simple text messages. A full version would -- also support sending files and directories.-newtype Offer+data Offer   -- | A simple text message.-  = Message Text deriving (Eq, Show)+  = Message Text+  -- | Offer a File with filename and size.+  | File FilePath FileOffset+  -- | Offer a Directory+  | Directory+    { directoryMode :: DirectoryMode+      -- ^ Mode. Currently always "zipfile/deflated".+    , dirName :: Text+      -- ^ Directory Name.+    , zipSize :: Natural+      -- ^ size of the transmitted compressed data in bytes+    , numBytes :: Natural+      -- ^ estimated total size of the uncompressed directory+    , numFiles :: Natural+      -- ^ number of files and directories being sent+    } deriving (Eq, Show)  instance ToJSON Offer where   toJSON (Message text) = object [ "offer" .= object [ "message" .= text ] ]+  toJSON (File name size) = object [ "offer" .= object [ "file" .= object [ "filename" .= name, "filesize" .= fromEnum size ] ] ]+  toJSON (Directory mode dirname zipsize numbytes numfiles) = object [ "offer" .= object [ "directory" .= object [ "mode" .= mode, "dirname" .= dirname, "zipsize" .= zipsize, "numbytes" .= numbytes, "numfiles" .= numfiles ] ] ]  instance FromJSON Offer where   parseJSON = withObject "Offer" $ \obj -> do     offer <- obj .: "offer"-    Message <$> offer .: "message"+    asum [ Message <$> offer .: "message"+         , File+           <$> ((offer .: "file") >>= (.: "filename"))+           <*> (toEnum <$> ((offer .: "file") >>= (.: "filesize")))+         , Directory+           <$> ((offer .: "directory") >>= (.: "mode"))+           <*> ((offer .: "directory") >>= (.: "dirname"))+           <*> (toEnum <$> ((offer .: "directory") >>= (.: "zipsize")))+           <*> (toEnum <$> ((offer .: "directory") >>= (.: "numbytes")))+           <*> (toEnum <$> ((offer .: "directory") >>= (.: "numfiles")))+         ]++data DirectoryMode = ZipFileDeflated+  deriving (Eq, Show)++instance FromJSON DirectoryMode where+  parseJSON (String s) | s == "zipfile/deflated" = return ZipFileDeflated+  parseJSON o = typeMismatch "failed to parse Directory Mode" o++instance ToJSON DirectoryMode where+  toJSON ZipFileDeflated = String "zipfile/deflated"
src/MagicWormhole/Internal/Peer.hs view
@@ -7,6 +7,7 @@   , withEncryptedConnection   , sendMessage   , receiveMessage+  , deriveKey   ) where  import Protolude hiding (phase)@@ -17,6 +18,7 @@   , newTVar   , readTVar   )+import qualified Crypto.Saltine.Core.SecretBox as SecretBox import qualified Crypto.Spake2 as Spake2  import qualified MagicWormhole.Internal.ClientProtocol as ClientProtocol@@ -64,7 +66,6 @@   conn <- establishEncryption peer password   runEncryptedConnection conn (action conn) - -- | A Magic Wormhole peer-to-peer application session. -- -- Construct one of these using 'withEncryptedConnection'.@@ -146,3 +147,10 @@ -- Obtain an 'EncryptedConnection' with 'withEncryptedConnection'. receiveMessage :: EncryptedConnection -> STM ClientProtocol.PlainText receiveMessage conn = snd <$> Sequential.next (inbound conn)+++-- | Derive a new key for the given purpose+--+-- Construct a new key from the encrypted connection's session key for the given purpose+deriveKey :: EncryptedConnection -> ClientProtocol.Purpose -> SecretBox.Key+deriveKey conn = ClientProtocol.deriveKey (sharedKey conn)
+ tests/FileTransfer.hs view
@@ -0,0 +1,18 @@+-- | Tests for serializing and deserializing FileTransfer messages+module FileTransfer (tests) where++import Protolude++import Data.Aeson (encode, eitherDecode)+import Hedgehog (forAll, property, tripping)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.Hedgehog (testProperty)++import qualified Generator++tests :: IO TestTree+tests = pure $ testGroup "FileTransfer"+  [ testProperty "offer messages roundtrip" $ property $ do+      x <- forAll Generator.offerMessages+      tripping x encode eitherDecode+  ]
tests/Generator.hs view
@@ -7,6 +7,7 @@   , appIDs   , phases   , sides+  , offerMessages   ) where  import Protolude@@ -29,6 +30,10 @@   , Mailbox(..)   , Mood(..)   )+import qualified MagicWormhole.Internal.FileTransfer as F+  ( Offer(..)+  , DirectoryMode(..)+  )  clientMessages :: MonadGen m => m ClientMessage clientMessages = Gen.choice@@ -97,3 +102,20 @@  welcomeMessages :: MonadGen m => m WelcomeMessage welcomeMessages = WelcomeMessage <$> Gen.maybe (Gen.text (Range.linear 0 1024) Gen.unicode) <*> Gen.maybe (Gen.text (Range.linear 0 1024) Gen.unicode)++directoryModes :: MonadGen m => m F.DirectoryMode+directoryModes = Gen.choice+  [ return F.ZipFileDeflated+  ]++offerMessages :: MonadGen m => m F.Offer+offerMessages = Gen.choice+  [ F.Message <$> (Gen.text (Range.linear 0 1024) Gen.unicode)+  , F.File <$> toS <$> (Gen.text (Range.linear 0 100) Gen.unicode)  <*> (fromIntegral <$> (Gen.int (Range.linear 0 maxBound)))+  , F.Directory+    <$> directoryModes -- (toS <$> (Gen.text (Range.linear 0 100) Gen.unicode))+    <*> (toS <$> (Gen.text (Range.linear 0 100) Gen.unicode))+    <*> (fromIntegral <$> (Gen.int (Range.linear 0 maxBound)))+    <*> (fromIntegral <$> (Gen.int (Range.linear 0 maxBound)))+    <*> (fromIntegral <$> (Gen.int (Range.linear 0 maxBound)))+  ]
tests/Tasty.hs view
@@ -9,6 +9,7 @@ import qualified Messages import qualified Sequential import qualified WebSockets+import qualified FileTransfer  main :: IO () main = sequence tests >>= defaultMain . testGroup "MagicWormhole"@@ -16,6 +17,7 @@     tests =       [ ClientProtocol.tests       , Messages.tests+      , FileTransfer.tests       , Sequential.tests       , WebSockets.tests         -- Put these at the end because they are slowest.