diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,28 @@
+Copyright (c) 2011 typLAB
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+3. Neither the name of Universiteit Utrecht nor the names of its contributors
+   may be used to endorse or promote products derived from this software without
+   specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,12 @@
+This package allows you to uri encode and uri decode `String`s,
+`Text`s and `ByteString`s.
+
+The default is to encode everything but ASCII alphabetic characters,
+decimal digits, and `- _ . ~`, according to RFC 3986.
+
+It has support for all of unicode, by first encoding strings to UTF8,
+and then encoding the individual bytes. This works both for `network`
+\> 2.4 (which also does this) and for older version.
+
+Additionally, two command line utilities are provided if the package
+is built with the `tools` flag: `uri-encode` and `uri-decode`.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/src/Network/URI/Encode.hs b/src/Network/URI/Encode.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/URI/Encode.hs
@@ -0,0 +1,130 @@
+{-# LANGUAGE CPP #-}
+{- |
+Unicode aware URI encoding and decoding functions for both String and Text.
+Although standards are pretty vague about Unicode in URIs most browsers are
+pretty straightforward when encoding URIs: Encode a text to a UTF-8 string and
+URI-encode every individual byte (not character).
+-}
+
+module Network.URI.Encode
+  ( encode
+  , encodeWith
+  , encodeText
+  , encodeTextWith
+  , encodeTextToBS
+  , encodeTextToBSWith
+  , encodeByteString
+  , encodeByteStringWith
+
+  , decode
+  , decodeText
+  , decodeBSToText
+  , decodeByteString
+
+  , isAllowed
+  ) where
+
+import Data.Text
+import Network.URI
+import qualified Data.ByteString.Char8 as U
+import qualified Data.ByteString.UTF8  as U
+
+-------------------------------------------------------------------------------
+-- | URI encode a 'String', unicode aware.
+
+encode :: String -> String
+encode = encodeWith isAllowed
+
+-- | URI encode a 'String', unicode aware, using the predicate to
+-- decide which characters are escaped ('False' means escape).
+
+encodeWith :: (Char -> Bool) -> String -> String
+encodeWith predicate = escapeURIString predicate . fixUtf8
+
+-- | URI decode a 'String', unicode aware.
+
+decode :: String -> String
+decode = unfixUtf8 . unEscapeString
+
+-------------------------------------------------------------------------------
+-- | URI encode a 'Text', unicode aware.
+
+encodeText :: Text -> Text
+encodeText = pack . encode . unpack
+
+-- | URI encode a 'Text', unicode aware, using the predicate to
+-- decide which characters are escaped ('False' means escape).
+
+encodeTextWith :: (Char -> Bool) -> Text -> Text
+encodeTextWith predicate = pack . encodeWith predicate . unpack
+
+-- | URI decode a 'Text', unicode aware.
+
+decodeText :: Text -> Text
+decodeText = pack . decode . unpack
+
+-------------------------------------------------------------------------------
+-- | URI encode a 'Text' into a 'ByteString', unicode aware.
+
+encodeTextToBS :: Text -> U.ByteString
+encodeTextToBS = U.pack . encode . unpack
+
+-- | URI encode a 'Text' into a 'ByteString', unicode aware, using the
+-- predicate to decide which characters are escaped ('False' means escape).
+
+encodeTextToBSWith :: (Char -> Bool) -> Text -> U.ByteString
+encodeTextToBSWith predicate = U.pack . encodeWith predicate . unpack
+
+-- | URI decode a 'ByteString' into a 'Text', unicode aware.
+
+decodeBSToText :: U.ByteString -> Text
+decodeBSToText = pack . decode . U.unpack
+
+-------------------------------------------------------------------------------
+-- | URI encode a UTF8-encoded 'ByteString' into a 'ByteString', unicode aware.
+
+encodeByteString :: U.ByteString -> U.ByteString
+encodeByteString = U.pack . encode . U.toString
+
+-- | URI encode a UTF8-encoded 'ByteString into a 'ByteString', unicode aware,
+-- using the predicate to decide which characters are escaped ('False' means
+-- escape).
+
+encodeByteStringWith :: (Char -> Bool) -> U.ByteString -> U.ByteString
+encodeByteStringWith predicate = U.pack . encodeWith predicate . U.unpack
+
+-- | URI decode a 'ByteString' into a UTF8-encoded 'ByteString', unicode aware.
+
+decodeByteString :: U.ByteString -> U.ByteString
+decodeByteString = U.fromString . decode . U.unpack
+
+-------------------------------------------------------------------------------
+-- | Is a character allowed in a URI. Only ASCII alphabetic
+-- characters, decimal digits, and - _ . ~ are allowed. This is
+-- following RFC 3986.
+
+isAllowed :: Char -> Bool
+isAllowed c = c `elem` (['A'..'Z'] ++ ['a'..'z'] ++ ['0'..'9'] ++ "-_.~")
+
+-------------------------------------------------------------------------------
+-- | "Fix" a String before encoding. This actually breaks the string,
+-- by changing unicode characters into their byte pairs. For network
+-- \>= 2.4, this is the identity, since that correctly handles unicode
+-- characters.
+fixUtf8 :: String -> String
+#if MIN_VERSION_network(2,4,0)
+fixUtf8 = id
+#else
+fixUtf8 = U.unpack . U.fromString
+#endif
+
+-- | "Unfix" a String again. For network \>= 2.4.1.1 this is the
+-- identity, since that correctly handles unicode characters. Note
+-- that network 2.4.1.0 (one that is still broken) cannot be excluded
+-- by CPP, so this version is excluded in the cabal dependencies.
+unfixUtf8 :: String -> String
+#if MIN_VERSION_network(2,4,1)
+unfixUtf8 = id
+#else
+unfixUtf8 = U.toString . U.pack
+#endif
diff --git a/src/URIDecode.hs b/src/URIDecode.hs
new file mode 100644
--- /dev/null
+++ b/src/URIDecode.hs
@@ -0,0 +1,13 @@
+module Main where
+
+import Data.List (intercalate)
+import System.Environment (getArgs)
+
+import Network.URI.Encode
+
+main :: IO ()
+main = getArgs >>= \args ->
+  if null args
+    then interact (unlines . map decode . lines)
+    else putStrLn . intercalate " " . map decode $ args
+
diff --git a/src/URIEncode.hs b/src/URIEncode.hs
new file mode 100644
--- /dev/null
+++ b/src/URIEncode.hs
@@ -0,0 +1,14 @@
+module Main where
+
+import Data.List (intercalate)
+import System.Environment (getArgs)
+
+import Network.URI.Encode
+
+main :: IO ()
+main = getArgs >>= \args ->
+  if null args
+    then interact (unlines . map encode . lines)
+    else putStrLn . intercalate " " . map encode $ args
+
+
diff --git a/uri-encode.cabal b/uri-encode.cabal
new file mode 100644
--- /dev/null
+++ b/uri-encode.cabal
@@ -0,0 +1,60 @@
+Name:               uri-encode
+Version:            1.5.0.1
+Description:        Unicode aware uri-encoding.
+Synopsis:           Unicode aware uri-encoding.
+Cabal-version:      >= 1.8
+Category:           Network, Web
+Author:             Silk
+Maintainer:         code@silk.co
+License:            OtherLicense
+License-File:       LICENSE
+Build-Type:         Simple
+Extra-Source-Files: README.md
+
+Flag tools
+  Default: False
+
+Library
+  GHC-Options:      -Wall
+  HS-Source-Dirs:   src
+
+  Build-Depends:    base ==4.*
+                  , bytestring >= 0.9 && < 0.11
+                  , network (>= 2.2 && < 2.4.1.0) || (> 2.4.1.0 && < 2.5)
+                  , text >=0.7 && < 1.2
+                  , utf8-string ==0.3.*
+
+  Exposed-Modules: Network.URI.Encode
+
+
+Executable          uri-encode
+  if flag(tools)
+    Buildable:      True
+    Build-Depends:    base ==4.*
+                    , bytestring >= 0.9 && < 0.11
+                    , network (>= 2.2 && < 2.4.1.0) || (> 2.4.1.0 && < 2.5)
+                    , text >=0.7 && < 1.2
+                    , utf8-string ==0.3.*
+  else
+    Buildable:      False
+  Main-is:          URIEncode.hs
+  GHC-Options:      -Wall
+  HS-Source-Dirs:   src
+
+Executable          uri-decode
+  if flag(tools)
+    Buildable:      True
+    Build-Depends:    base ==4.*
+                    , bytestring >= 0.9 && < 0.11
+                    , network (>= 2.2 && < 2.4.1.0) || (> 2.4.1.0 && < 2.5)
+                    , text >=0.7 && < 1.2
+                    , utf8-string ==0.3.*
+  else
+    Buildable:      False
+  Main-is:          URIDecode.hs
+  GHC-Options:      -Wall
+  HS-Source-Dirs:   src
+
+Source-Repository head
+  Type:             Git
+  Location:         https://github.com/silkapp/uri-encode.git
