diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,32 @@
+netlines license
+Copyright (c) 2010, Ertugrul Soeylemez
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * 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.
+
+    * Neither the name of the author nor the names of any 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/Network/NetLines.hs b/Network/NetLines.hs
new file mode 100644
--- /dev/null
+++ b/Network/NetLines.hs
@@ -0,0 +1,100 @@
+-- |
+-- Module:     Network.NetLines
+-- Copyright:  (c) 2010 Ertugrul Soeylemez
+-- License:    BSD3
+-- Maintainer: Ertugrul Soeylemez <es@ertes.de>
+-- Stability:  experimental
+--
+-- Enumerator tools for working with text-based network protocols.
+
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module Network.NetLines
+    ( -- * Conversion to lines
+      netLine,
+      netLines,
+
+      -- * Enumerators
+      enumHandleTimeout
+    )
+    where
+
+import qualified Data.ByteString as B
+import Control.ContStuff
+import Data.ByteString (ByteString)
+import Data.Enumerator as E
+import Data.Enumerator.Binary as EB
+import Data.Word
+import System.IO
+import System.IO.Error as IOErr
+
+
+-- | Enumerate from a handle with the given buffer size (first argument)
+-- and timeout in milliseconds (second argument).  If the timeout is
+-- exceeded an exception is thrown via 'throwError'.
+
+enumHandleTimeout :: forall b m. MonadIO m =>
+                     Int -> Int -> Handle -> Enumerator ByteString m b
+enumHandleTimeout bufSize timeout h = loop
+    where
+    loop :: Enumerator ByteString m b
+    loop (Continue k) = do
+          mHaveInput <- liftIO $ IOErr.try (hWaitForInput h timeout)
+          case mHaveInput of
+            Left err
+                | isEOFError err -> continue k
+                | otherwise      -> throwError err
+            Right False -> throwError $ userError "Handle timed out"
+            Right True  -> do
+                mStr <- liftIO $ IOErr.try (B.hGetNonBlocking h bufSize)
+                str <- either throwError return mStr
+                if B.null str
+                  then continue k
+                  else k (Chunks [str]) >>== loop
+    loop step = returnI step
+
+
+-- | Savely read a line with the given maximum length.  If a longer line
+-- is enumerated, the excess data is dropped in constant space.  Returns
+-- 'Nothing' on EOF.
+--
+-- Please note that this function is very error-tolerant in the way it
+-- handles line endings.  Both CR and LF are proper line terminators.
+-- This function ignores empty lines.
+
+netLine :: forall m r. Monad m => Int -> MaybeT r (Iteratee ByteString m) ByteString
+netLine n =
+    lift (EB.dropWhile isEol) >> netLine' n
+
+    where
+    isEol :: Word8 -> Bool
+    isEol 10 = True
+    isEol 13 = True
+    isEol _  = False
+
+    isNotEol :: Word8 -> Bool
+    isNotEol = not . isEol
+
+    netLine' :: Int -> MaybeT r (Iteratee ByteString m) ByteString
+    netLine' 0 = B.empty <$ lift (EB.dropWhile isNotEol)
+    netLine' n = do
+        c <- liftF EB.head
+        if isNotEol c
+          then B.cons c <$> netLine' (n-1)
+          else return B.empty
+
+
+-- | Convert a stream of bytes to a stream of lines with the given
+-- maximum length.  Longer lines are silently truncated in constant
+-- space.
+
+netLines :: forall b m. Monad m => Int -> Enumeratee ByteString ByteString m b
+netLines maxLen = loop
+    where
+    loop :: Enumeratee ByteString ByteString m b
+    loop (Continue k) = do
+        mLine <- evalMaybeT $ netLine maxLen
+        case mLine of
+          Just line -> k (Chunks [line]) >>== loop
+          Nothing   -> k EOF >>== loop
+    loop step = return step
diff --git a/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,12 @@
+netlines setup script
+Copyright (C) 2010, Ertugrul Soeylemez
+
+Please see the LICENSE file for terms and conditions of use,
+modification and distribution of this package, including this file.
+
+> module Main where
+>
+> import Distribution.Simple
+>
+> main :: IO ()
+> main = defaultMain
diff --git a/netlines.cabal b/netlines.cabal
new file mode 100644
--- /dev/null
+++ b/netlines.cabal
@@ -0,0 +1,28 @@
+Name:          netlines
+Version:       0.1.0
+Category:      Network
+Synopsis:      Enumerator tools for text-based network protocols
+Maintainer:    Ertugrul Söylemez <es@ertes.de>
+Author:        Ertugrul Söylemez <es@ertes.de>
+Copyright:     (c) 2010 Ertugrul Söylemez
+License:       BSD3
+License-file:  LICENSE
+Build-type:    Simple
+Stability:     experimental
+Cabal-version: >= 1.6
+Description:
+
+    Enumerator tools for text-based network protocols.  This includes,
+    among other things, an enumeratee to split an incoming ByteString
+    stream to a length-limited line stream in a safe manner
+    (i.e. constant space).
+
+Library
+  Build-depends:
+    base >= 4 && <= 5,
+    bytestring >= 0.9.1.7,
+    contstuff >= 1.2.4,
+    enumerator >= 0.4.7
+  GHC-Options:   -W
+  Exposed-modules:
+    Network.NetLines
