diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) Radoslav Dorcik 2009
+
+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 the author nor the names of his contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 AUTHORS 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/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/epub.cabal b/epub.cabal
new file mode 100644
--- /dev/null
+++ b/epub.cabal
@@ -0,0 +1,45 @@
+Name:            epub
+Version:         0.0.1
+License:         BSD3
+License-File:    LICENSE
+Synopsis:        EPUB E-Book construction support library
+Author:          Radoslav Dorcik <radoslav.dorcik@gmail.com>
+Maintainer:      radoslav.dorcik@gmail.com
+Description:     
+  .
+  EPUB E-Book Construction support library, for the details look
+  at http://en.wikipedia.org/wiki/EPUB.
+  .
+Category:        Text
+Stability:       experimental
+Build-Type:      Simple
+Cabal-Version:   >= 1.6
+
+Source-Repository head
+  type:     darcs
+  location: http://patch-tag.com/r/dixiecko/epub
+    
+Library
+  Build-Depends:   ghc,
+                   base         < 5,
+                   filepath,
+                   haskell98,
+                   old-time,
+                   utf8-string,
+                   bytestring,      
+                   zip-archive,
+                   xml,
+                   Cabal        >= 1.5 && < 1.9
+  Hs-Source-Dirs:  src
+  Extensions:      CPP, PatternGuards
+  Ghc-Options:      -Wall -fno-warn-orphans
+
+  Exposed-modules:
+        Codec.EBook
+        Codec.EBook.Types
+        Codec.EBook.OCF
+        Codec.EBook.OPF
+
+Executable xhtml2epub
+  Hs-Source-Dirs:  src
+  Main-Is:         xhtml2epub.hs
diff --git a/src/Codec/EBook.hs b/src/Codec/EBook.hs
new file mode 100644
--- /dev/null
+++ b/src/Codec/EBook.hs
@@ -0,0 +1,50 @@
+-- EBook Types definition
+
+module Codec.EBook (
+    module Codec.EBook.Types,
+    module Codec.EBook.OPF,
+    module Codec.EBook.OCF,
+    book2Bin,
+    book2Bin',
+    book2Arch',
+    book2Arch,
+    opsMediatype
+) 
+where
+
+import System.Time 
+import Codec.Archive.Zip
+import Codec.EBook.Types
+import Codec.EBook.OPF
+import Codec.EBook.OCF
+import qualified Data.ByteString.Lazy as B
+
+-- EPUB media type
+opsMediatype = "application/xhtml+xml"
+
+-- Serialize Book to binary EPUB Format
+book2Bin :: Book -> Integer -> B.ByteString
+book2Bin book = fromArchive . book2Arch book
+
+-- Serialize Book to binary EPUB Format with current time
+book2Bin' :: Book -> IO B.ByteString
+book2Bin' book = do 
+          (TOD t _) <- getClockTime 
+          return $ fromArchive (book2Arch book t)
+
+-- Serialize Book to ZIP Archive with current time
+book2Arch' :: Book -> IO Archive
+book2Arch' book = do
+          (TOD t _) <- getClockTime 
+          return $ book2Arch book t
+
+-- Serialize Book to ZIP Archive
+book2Arch :: Book -> Integer -> Archive
+book2Arch book t = let conXMLFile = containerXMLFile' opfFileName
+                       opfFileName = "book.opf"
+                       mimeFile   = mimetypeFile
+                       contFiles  = bookFiles book
+                       allFiles   = mimeFile:conXMLFile:contFiles ++ opfFiles book opfFileName
+                       entries    = map (\(n,c) -> toEntry n t c) allFiles
+                       arch       = foldl (\a e -> addEntryToArchive e a) emptyArchive entries
+                   in  arch 
diff --git a/src/Codec/EBook/OCF.hs b/src/Codec/EBook/OCF.hs
new file mode 100644
--- /dev/null
+++ b/src/Codec/EBook/OCF.hs
@@ -0,0 +1,35 @@
+-- | Open Container Format 1.0
+
+module Codec.EBook.OCF(
+	defaultMediatype,
+	defaultMimetype,
+	containerXMLFile,
+        containerXMLFile',
+        mimetypeFile,
+       )
+where
+
+import Codec.EBook.Types
+import Text.XML.Light
+import Codec.Archive.Zip
+import qualified Data.ByteString.Lazy as B
+
+defaultMediatype = "application/oebps-package+xml"
+defaultMimetype = "application/epub+zip"
+
+containerXMLFile' :: FilePath -> (FilePath, B.ByteString)
+containerXMLFile' p = containerXMLFile p defaultMediatype
+
+mimetypeFile :: (FilePath, B.ByteString)
+mimetypeFile = ("mimetype", str2bstr defaultMimetype)
+
+containerXMLFile :: FilePath -> String -> (FilePath, B.ByteString)
+containerXMLFile p m = ("META-INF/container.xml", str2bstr $ ppTopElement contTag)
+	where
+	   contTag = add_attrs contAttrs $ unode "container" rootfilesTag
+           contAttrs = [ Attr (unqual "version") "1.0"
+			,Attr (unqual "xmlns")   "urn:oasis:names:tc:opendocument:xmlns:container" ] 
+           rootfilesTag = unode "rootfiles" (rootfileTag p m)
+           rootfileTag p m = add_attrs (rfAttrs p m) $ unode "rootfile" ()
+           rfAttrs p m = [ Attr (unqual "full-path") p
+			  ,Attr (unqual "media-type")  m ] 
diff --git a/src/Codec/EBook/OPF.hs b/src/Codec/EBook/OPF.hs
new file mode 100644
--- /dev/null
+++ b/src/Codec/EBook/OPF.hs
@@ -0,0 +1,76 @@
+-- Open Packaging Format 2.0
+
+module Codec.EBook.OPF (
+	ncxXML,
+        opfXML,
+        opfFiles
+) 
+where
+import Data.Maybe (fromJust)
+import Text.XML.Light
+import Codec.EBook.Types
+import qualified Data.ByteString.Lazy as B
+
+opfDefaultLang = "en"
+opfDefaultCreator = "Unknown"
+
+opfFiles :: Book -> FilePath -> [(FilePath, B.ByteString)] 
+opfFiles book name = let ncxXMLFile = (ncxFileName,ncxXML book)
+                         opfXMLFile = (name,opfXML book ncxFileName)
+                         ncxFileName = "book.ncx"
+                     in [opfXMLFile, ncxXMLFile]
+
+ncxXML :: Book -> B.ByteString
+ncxXML o = str2bstr $ ppTopElement packageT
+	where
+	   packageT= add_attrs packageA $ unode "ncx" nestedT
+           packageA = [ Attr (unqual "version") "2005-1"
+                       ,Attr (unqual "xml:lang") "en"
+	               ,Attr (unqual "xmlns")   "http://www.daisy.org/z3986/2005/ncx/" ]
+           nestedT = [ headT, docTitleT, docAuthorT, navMapT ]
+           headT = unode "head" $ map (\(n,v) -> add_attrs [ Attr (unqual "name") n,Attr (unqual "content") v] $ unode "meta" ()) metaVals
+           metaVals = [ ("dtb:uid",(bookID o))
+                       ,("dtb:depth","1")
+                       ,("dtb:totalPageCount","0") 
+                       ,("dtb:maxPageNumber","0") ]
+           docTitleT = unode "docTitle" $ unode "text" (bookTitle o)
+           docAuthorT = unode "docAuthor" $ unode "text" (bookAuthor o)
+           numChapterEnt = zip (chapterItems $ bookItems o) [1..]
+           navMapT = unode "navMap" (map navPointT numChapterEnt)
+           navPointT (e,i) = add_attrs [ Attr (unqual "class") "chapter" 
+                                        ,Attr (unqual "id") (itemID e)
+                                        ,Attr (unqual "playOrder") (show i) 
+                                      ] $ unode "navPoint" [ unode "navLabel" $ unode "text" (chapterTitle (fromJust $ itemMetadata e))
+                                                            ,add_attr (Attr (unqual "src") (itemFileName e) ) $ unode "content" ()
+					  	           ]
+
+opfXML :: Book -> FilePath -> B.ByteString
+opfXML o xn = str2bstr $ ppTopElement packageT
+	where
+	   packageT= add_attrs packageA $ unode "package" nestedT
+           packageA = [ Attr (unqual "version") "2.0"
+                       ,Attr (unqual "unique-identifier") "BookId"
+	               ,Attr (unqual "xmlns")   "http://www.idpf.org/2007/opf" ]
+           nestedT = [ metadataT, manifestT, spineT ]
+           metadataT = add_attrs metadataA $ unode "metadata" [
+                            unode "dc:title" (bookTitle o),
+                            unode "dc:language" (bookLang o),
+                            add_attrs [ Attr (unqual "id") "BookId" 
+                                       ,Attr (unqual "opf:scheme") "URI" 
+                                      ] $ unode "dc:identifier" (bookID o)
+                       ]
+           metadataA = [ Attr (unqual "xmlns:dc")  "http://purl.org/dc/elements/1.1/" 
+                        ,Attr (unqual "xmlns:opf") "http://www.idpf.org/2007/opf"
+            	       ]
+ 	   manifestT = unode "manifest" $ map manifestItemT (bookItems o) ++ [ncxItem]
+           manifestItemT i = add_attrs [ Attr (unqual "id") (itemID i) 
+                                        ,Attr (unqual "href") (itemFileName i)
+                                        ,Attr (unqual "media-type") (itemMediaType i) 
+                                       ] $ unode "item" ()
+           ncxItem = add_attrs [ Attr (unqual "id") "ncx" 
+                                ,Attr (unqual "href") xn
+                                ,Attr (unqual "media-type") "application/x-dtbncx+xml" 
+                                       ] $ unode "item" ()
+           spineT = add_attrs [ Attr (unqual "toc") "ncx" ] $ unode "spine" (map spineItemT (bookItems o))
+           spineItemT i = add_attrs [ Attr (unqual "idref") (itemID i) ] $ unode "itemref" ()
+
diff --git a/src/Codec/EBook/Types.hs b/src/Codec/EBook/Types.hs
new file mode 100644
--- /dev/null
+++ b/src/Codec/EBook/Types.hs
@@ -0,0 +1,56 @@
+-- Book Types definition
+
+module Codec.EBook.Types (
+   Book(..),
+   BookItem(..),
+   Metadata(..),
+   emptyBook,
+   addItem2Book,
+   bookFiles,
+   chapterItems,
+   str2bstr
+) 
+where
+import qualified Data.ByteString.Lazy as B
+import qualified Data.ByteString.Lazy.Char8 as U
+import Control.Arrow ((&&&))
+
+data Book = Book { 
+               bookID     :: String,
+               bookTitle  :: String,
+               bookAuthor :: String, 
+               bookLang   :: String,
+               bookItems  :: [BookItem]
+            } deriving (Show, Eq, Ord)
+
+data BookItem = BookItem {
+               itemID        :: String,
+               itemFileName  :: FilePath,
+               itemContent   :: B.ByteString,
+               itemMediaType :: String,
+               itemMetadata  :: Maybe Metadata
+            } deriving (Show, Eq, Ord)
+
+data Metadata = ChapterMetadata {
+                chapterTitle :: String
+            } deriving (Show, Eq, Ord)
+
+str2bstr :: String -> B.ByteString
+str2bstr = U.pack
+
+emptyBook :: Book
+emptyBook = Book "NO ID" "NO TITLE" "NO AUTHOR" "en" []
+
+bookFiles :: Book -> [(FilePath, B.ByteString)]
+bookFiles = map (itemFileName &&& itemContent) . bookItems
+
+chapterItems :: [BookItem] -> [BookItem]
+chapterItems = filter isChapter
+   where
+      isChapter (BookItem _ _ _ _ Nothing ) = False
+      isChapter _ = True
+
+addItem2Book :: Book -> BookItem -> Book
+addItem2Book book item = book { bookItems = newItems }
+       where
+          newItems = bookItems book ++ [item]
diff --git a/src/xhtml2epub.hs b/src/xhtml2epub.hs
new file mode 100644
--- /dev/null
+++ b/src/xhtml2epub.hs
@@ -0,0 +1,29 @@
+import qualified Data.ByteString.Lazy as B
+import Codec.EBook
+import System.Environment (getArgs)
+import System.FilePath
+import Data.List (foldl')
+
+main = do
+  args <- getArgs
+  case args of 
+     (nameOfBook:fileNames) -> do 
+          let book = emptyBook { 
+                bookID = "http://localhost/"++nameOfBook,
+                bookAuthor = "xhtml2epub",
+                bookTitle = nameOfBook
+          }
+          items <- mapM loadItems fileNames
+          let bookFull = foldl' addItem2Book book items
+          let epubFName = nameOfBook++".epub"
+          outdata <- book2Bin' bookFull
+          B.writeFile epubFName  outdata
+          putStrLn $ epubFName ++ " constructed."
+     _ -> error "Usage: xhtml2epub <name of book> <xhtml file1> [<xhtml file2>,...]"
+
+loadItems :: FilePath -> IO BookItem
+loadItems p = do
+   c <- B.readFile p
+   return (BookItem ("http://localhost/"++np) np c opsMediatype (Just (ChapterMetadata np))) 
+   where
+      np = normalise p
