diff --git a/TODO.org b/TODO.org
--- a/TODO.org
+++ b/TODO.org
@@ -11,3 +11,12 @@
 * TODO add module tests for versioned LDIFs
 * TODO add module tests for base64 parsing
 * TODO Implement Attribute Name case-insensitive matching at DN
+* TODO Use getopt for input parameters on diffLDIF cmd
+* TODO Implement ldifmodify (like ldapmodify)
+   offline applying of Change LDIF on Content LDIF
+   ldifmodify -h <contentLDIF> -f <changeLDIF> [-o <contentLDIFAfter>] 
+* DONE Change interface for providing parser method with expected type of LDIF
+it allows parse changeldif as contentldif regardless the content.
+
+* DONE Add ldif2html which generate hypertext LDIF representation
+* DONE Update unwrap method in preprocessor for feasible resource consuption
diff --git a/ldif.cabal b/ldif.cabal
--- a/ldif.cabal
+++ b/ldif.cabal
@@ -1,5 +1,5 @@
 Name:            ldif
-Version:         0.0.3
+Version:         0.0.4
 License:         BSD3
 License-File:    LICENSE
 Synopsis:        The LDAP Data Interchange Format (LDIF) parser 
@@ -15,7 +15,9 @@
  It includes following tool:
  .
  - diffLDIF command generates change LDIF between two 
-   content LDIF files. 
+   content LDIF files.
+ - ldif2html command generates hypertext HTML browsable
+   LDIF file. 
  .
 Category:        Text
 Stability:       experimental
@@ -39,7 +41,7 @@
     
 Source-Repository head
   type:     darcs
-  location: http://rampa.sk/repo/ldif
+  location: http://patch-tag.com/r/dixiecko/ldif
 
 flag test
   description: Build test program.
@@ -50,6 +52,7 @@
                    base         < 5,
                    filepath,
                    haskell98,
+                   containers,
                    parsec       >= 2.1.0,
                    Cabal        >= 1.5 && < 1.9
   Hs-Source-Dirs:  src
@@ -66,6 +69,10 @@
 Executable diffLDIF
   Hs-Source-Dirs:  src
   Main-Is:         diffLDIF.hs
+
+Executable ldif2html
+  Hs-Source-Dirs:  src
+  Main-Is:         ldif2html.hs
 
 Executable test
   Hs-Source-Dirs:  src, tests
diff --git a/src/Text/LDIF/Parser.hs b/src/Text/LDIF/Parser.hs
--- a/src/Text/LDIF/Parser.hs
+++ b/src/Text/LDIF/Parser.hs
@@ -1,5 +1,6 @@
 module Text.LDIF.Parser (
 	parseLDIFStr,
+        parseLDIFStrAs,
 	parseLDIFFile,
         parseDNStr
 )
@@ -8,25 +9,36 @@
 import Text.ParserCombinators.Parsec
 import Data.Either
 import Data.Char
-import Data.List (isPrefixOf)
+import Data.List (isPrefixOf, foldl')
 
 -- | Parse string as LDIF content and return LDIF or ParseError
 parseLDIFStr :: String -> Either ParseError LDIF
-parseLDIFStr = parse pLdif "(param)" . preproc 
+parseLDIFStr = parseLDIFStrAs Nothing 
 
 -- | Read and parse provided file and return LDIF or ParseError
 parseLDIFFile :: String -> IO (Either ParseError LDIF)
 parseLDIFFile name = do
 	input <- readFile name
-	return $ parse pLdif name (preproc input)
+        return $ parseLDIFStrAs' name Nothing input
 
+-- | Read and parse provided string and return LDIF or ParserError
+-- | If LDIF type is specified than given type is expected for parsing 
+-- | and mismatch generates ParseError
+parseLDIFStrAs' :: String -> Maybe LDIFType -> String -> Either ParseError LDIF
+parseLDIFStrAs' nm Nothing                = parse pLdif        nm . preproc
+parseLDIFStrAs' nm (Just LDIFContentType) = parse pLdifContent nm . preproc
+parseLDIFStrAs' nm (Just LDIFChangesType) = parse pLdifChanges nm . preproc
+
+parseLDIFStrAs :: Maybe LDIFType -> String -> Either ParseError LDIF
+parseLDIFStrAs = parseLDIFStrAs' "(param)"
+
 -- | Parse string as DN and return DN type or ParseError
 parseDNStr :: String -> Either ParseError DN
 parseDNStr = parse pDN "(param)" 
 
 -- | Preprocessing for concat wrapped lines and remove comment lines
 preproc :: String -> String
-preproc = unwrap . stripComments
+preproc = stripComments . unwrap
 
 -- | Remove Comment Lines
 stripComments :: String -> String
@@ -34,32 +46,36 @@
 
 -- | Unwrap lines, lines with space at begin is continue of previous line 
 unwrap :: String -> String
-unwrap input = unlines $ preprocLines $ lines input
-   where 
-    preprocLines xs = unbox $ foldl (preprocLine) ([],Nothing) xs
-    preprocLine (ys,r) []                 = (addLineMaybe ys r,Just []) 
-    preprocLine (ys,r) (l:lx) | l == ' '  = (ys,concatLineMaybe r lx)
-                              | otherwise = (addLineMaybe ys r, Just $ l:lx)
-    concatLineMaybe Nothing  x = Just x
-    concatLineMaybe (Just y) x = Just (y++x)
-    addLineMaybe xs Nothing  = xs
-    addLineMaybe xs (Just x) = xs++[x]
-    unbox (ys,Nothing) = ys
-    unbox (ys,Just x)  = ys++[x]
+unwrap xs = unlines $ takeLines $ lines xs
 
+takeLines :: [String] -> [String]
+takeLines [] = []
+takeLines xs = let (ln,ys) = takeLine xs
+               in ln:takeLines ys
+
+takeLine :: [String] -> (String, [String])
+takeLine []     = ([],[])
+takeLine (x:[]) = (x,[])
+takeLine (x:xs) = let isCont x = " " `isPrefixOf` x  
+                  in (x ++ (concat $ map (tail) $ takeWhile (isCont) xs), dropWhile (isCont) xs) 
+
 -- | Parsec ldif parser
 pLdif :: CharParser st LDIF
 pLdif = try pLdifChanges <|> pLdifContent
 
 pLdifChanges :: CharParser st LDIF
 pLdifChanges = do
+    pSEPs
     ver <- optionMaybe pVersionSpec
+    pSEPs
     recs <- sepEndBy1 pChangeRec pSEPs
     return $ LDIFChanges ver recs
 
 pLdifContent :: CharParser st LDIF
 pLdifContent = do
+    pSEPs
     ver <- optionMaybe pVersionSpec
+    pSEPs
     recs <- sepEndBy1 pAttrValRec pSEPs
     return $ LDIFContent ver recs
 
diff --git a/src/Text/LDIF/Proc.hs b/src/Text/LDIF/Proc.hs
--- a/src/Text/LDIF/Proc.hs
+++ b/src/Text/LDIF/Proc.hs
@@ -34,7 +34,7 @@
 -- | 1. Iterate over L1 DN's and Modify / Remove Content 
 -- | 2. Iterate over L2 and Add Content not in L1
 diffLDIF :: LDIF -> LDIF -> Maybe LDIF
-diffLDIF l1@(LDIFContent v1 c1) l2@(LDIFContent v2 c2) = Just (LDIFChanges v2 changes) 
+diffLDIF (LDIFContent _ c1) l2@(LDIFContent v2 _) = Just (LDIFChanges v2 changes) 
    where 
       changes = filter (not . isDummyChangeRecord) $ foldl (processEntry) [] c1
       processEntry xs e1 = let me2 = findContentByDN l2 (coDN e1) 
diff --git a/src/Text/LDIF/Types.hs b/src/Text/LDIF/Types.hs
--- a/src/Text/LDIF/Types.hs
+++ b/src/Text/LDIF/Types.hs
@@ -6,14 +6,17 @@
         Change(..),
         Modify(..), 
         DN(..), 
+        LDIFType(..),
         Attribute, Value, AttrValue
 )
 where
-import Data.Char
 
 type Attribute = String
 type Value = String
 type AttrValue = (Attribute, Value)
+
+-- | Type of LDIF Files (Content, Changes)
+data LDIFType = LDIFContentType | LDIFChangesType deriving (Show, Eq) -- Maybe LDIFMixedType 
 
 -- | Represents LDIF structure, it can be either simply LDIF data dump or
 -- | changes LDIF with LDAP operations 
diff --git a/src/ldif2html.hs b/src/ldif2html.hs
new file mode 100644
--- /dev/null
+++ b/src/ldif2html.hs
@@ -0,0 +1,79 @@
+-- | Make Change LDIF based on two Content LDIFs
+import Data.List
+import Data.Either
+import Data.Maybe
+import Control.Monad 
+import System.FilePath 
+import System.Environment
+import Text.LDIF
+import qualified Data.Set as Set
+
+ldif2html :: Set.Set String -> LDIF -> String
+ldif2html idx (LDIFContent v xs) = unlines $ (ver2Str v) ++ (map (content2html idx) xs)
+ldif2html idx (LDIFChanges v xs) = unlines $ (ver2Str v) ++ (map (change2html idx) xs)
+
+-- | Serialize version to LDIF Format Lines
+ver2Str :: Maybe String -> [String]
+ver2Str Nothing = []
+ver2Str (Just v) = ["version: "++v]
+
+-- | Serialize DN to LDIF Format
+dn2html :: DN -> String
+dn2html ys@(DN xs) = concat [ "<div id=\"abc"++nm++"\"></div><b>dn:</b> <font color=\"green\"><b>", intercalate "," $ map (\(n,v) -> n++"="++v) xs, "</b></font>"]
+      where
+         nm = dn2last ys
+
+dn2last (DN xs) = snd $ head xs
+
+-- | Serialize Content Record in LDIF Format
+content2html :: Set.Set String -> ContentRecord -> String
+content2html idx (ContentRecord dn xs) = unlines $ [ (dn2html dn) ] ++ (attrVals2Ln idx xs)
+
+-- | Serialize Change Record in LDIF Format
+change2html :: Set.Set String -> ChangeRecord -> String
+change2html idx (ChangeRecord dn (ChangeDelete))     = unlines   [ (dn2Str dn), "changetype: delete" ]
+change2html idx (ChangeRecord dn (ChangeAdd xs))    = unlines $ [ (dn2html dn), "changetype: add"    ] ++ (attrVals2Ln idx xs)
+change2html idx (ChangeRecord dn (ChangeModify xs))  = unlines $ [ (dn2Str dn), "changetype: modify" ] ++ (mods2Ln idx xs)
+change2html idx (ChangeRecord dn (ChangeModDN))      = unlines $ [ (dn2Str dn), "changetype: moddn"  ]
+
+attrVals2Ln :: Set.Set String -> [AttrValue] -> [String]
+attrVals2Ln idx xs = map (attrVal2Ln idx) xs
+
+attrVal2Ln :: Set.Set String -> AttrValue -> String
+attrVal2Ln idx (n,v) = if Set.member v idx then "<b>"++n++"</b> : <a href=\"#abc"++v++"\">"++v++"</a>"
+                          else "<b>"++n++"</b> : "++v
+
+mods2Ln :: Set.Set String -> [Modify] -> [String]
+mods2Ln idx xs = intercalate ["-"] $ map (mod2Ln idx) xs
+
+mod2Ln :: Set.Set String -> Modify -> [String]
+mod2Ln idx (ModAdd     nm xs) = [ attrVal2Ln idx ("add",nm)     ] ++ (map (\v -> attrVal2Ln idx (nm,v)) xs) 
+mod2Ln idx (ModDelete  nm xs) = [ attrVal2Ln idx ("delete",nm)  ] ++ (map (\v -> attrVal2Ln idx (nm,v)) xs)
+mod2Ln idx (ModReplace nm xs) = [ attrVal2Ln idx ("replace",nm) ] ++ (map (\v -> attrVal2Ln idx (nm,v)) xs)
+
+-- Dummy ldif2html implementation but it should
+-- display LDIF file as HTML with values as href to
+-- DN which has the value as the leaf RDN value
+main = do
+  args <- getArgs
+  case args of 
+     []         -> putStrLn "Usage: ldif2html <input.ldif> [<input2.ldif> <input3.ldif> ... <inputN.ldif> <output.ldif>]"
+     [inp]      -> do
+                      doLDIF2HTML [inp] (putStrLn)
+                      putStrLn "# Done."
+     xs         -> do
+                      doLDIF2HTML (init xs) (writeFile (last xs)) 
+                      putStrLn $ "## Processed : " ++ (unlines $ init xs)
+                      putStrLn $ "## Written   : " ++ (last xs)
+
+doLDIF2HTML names outF = do
+  mls <- mapM (parseLDIFFile) names
+  case lefts mls of 
+       []   -> do
+                 let idx = Set.unions $ map (dns) (rights mls)
+                 outF $ concat ["<html><body bgcolor=lightyellow><pre>", concat $ map (ldif2html idx) (rights mls), "</pre></body></html>" ]
+       xs  -> mapM_ print xs
+
+dns :: LDIF -> Set.Set String
+dns (LDIFContent _ xs) = Set.fromList $ nub $ map (dn2last . coDN) xs
+dns (LDIFChanges _ xs) = Set.fromList $ nub $ map (dn2last . chDN) xs
