diff --git a/TODO.org b/TODO.org
--- a/TODO.org
+++ b/TODO.org
@@ -7,8 +7,8 @@
 ** update serializers back to LDIF for base64 & all DN notations
 ** add module tests for versioned LDIFs
 ** add module tests for base64 parsing
-** Use getopt for input parameters on diffLDIF cmd
-** TODO Implement ldifmodify (like ldapmodify)
+** DONE Use getopt for input parameters on diffLDIF cmd
+** DONE Implement ldifmodify (like ldapmodify)
     offline applying of Change LDIF on Content LDIF
     ldifmodify -f <contentLDIF> -o <outputLDIF> [<modifyLDIF> ... ] 
 * Archive
diff --git a/ldif.cabal b/ldif.cabal
--- a/ldif.cabal
+++ b/ldif.cabal
@@ -1,5 +1,5 @@
 Name:            ldif
-Version:         0.0.6
+Version:         0.0.7
 License:         BSD3
 License-File:    LICENSE
 Synopsis:        The LDAP Data Interchange Format (LDIF) parser 
@@ -82,9 +82,13 @@
   Hs-Source-Dirs:  src
   Main-Is:         ldifmodify.hs
 
+Executable ldifparse
+  Hs-Source-Dirs:  src
+  Main-Is:         ldifparse.hs
+
 Executable test
   Hs-Source-Dirs:  src, tests
   Main-Is:         TestMain.hs
-  Build-Depends:   base, HUnit
+  Build-Depends:   base, HUnit == 1.2.*
   if !flag(test)
     Buildable:     False
diff --git a/src/Text/LDIF/Apply.hs b/src/Text/LDIF/Apply.hs
--- a/src/Text/LDIF/Apply.hs
+++ b/src/Text/LDIF/Apply.hs
@@ -3,52 +3,50 @@
 )
 where
 import Text.LDIF.Types
-import Text.LDIF.Printer
 import Text.LDIF.Utils
-import Data.Maybe
-import Data.Either
+import Text.LDIF.Printer
 import Data.List (nub)
 
 -- | Apply one LDIF to another LDIF. The destination LDIF has
 -- | to be Content LDIF
 applyLDIF :: LDIF -> LDIF -> LDIF
-applyLDIF dst@(LDIFContent _ _) (LDIFChanges _ xs) = foldr (applyRecord2LDIF) dst xs
-applyLDIF dst@(LDIFContent _ _) (LDIFContent _ xs) = foldr (applyRecord2LDIF) dst xs
-applyLDIF _ _ = error "Destination LDIF has to be Content LDIF and not Change LDIF"
+applyLDIF dst (LDIF _ xs) = foldr (applyRecord2LDIF) dst xs
 
 -- | Apply one LDIF Content/Change Record into LDIF and produce Changed LDIF
 applyRecord2LDIF :: LDIFRecord -> LDIF -> LDIF
-applyRecord2LDIF rec@(ContentRecord dn vals) dst = applyRecord2LDIF (ChangeRecord dn (ChangeAdd vals)) dst
-applyRecord2LDIF rec@(ChangeRecord  dn op)   dst = applyChange2Record op dn dst (findRecordByDN dst dn)
+applyRecord2LDIF (ContentRecord dn vals) dst = applyRecord2LDIF (ChangeRecord dn (ChangeAdd vals)) dst
+applyRecord2LDIF (ChangeRecord  dn op)   dst = applyChange2Record op dn dst (findRecordByDN dst dn)
 
 -- | Apply one LDIF Change (add/del/modf) for given DN within LDIF Content 
 applyChange2Record :: Change -> DN -> LDIF -> Maybe LDIFRecord -> LDIF
-applyChange2Record (ChangeAdd vals)   dn (LDIFContent v xs) Nothing  = LDIFContent v (xs++[ContentRecord dn vals]) 
-applyChange2Record (ChangeAdd vals)   dn (LDIFContent v xs) (Just _) = error ("ADD: Already exists: "++(show dn))
-applyChange2Record ChangeDelete       dn (LDIFContent v xs) (Just _) = let rn = filter (\x -> dn /= (reDN x)) xs
-                                                                       in LDIFContent v rn
-applyChange2Record ChangeDelete       dn (LDIFContent v xs) Nothing  = error ("DELETE: Entry not found: "++(show dn))
-applyChange2Record (ChangeModify ops) dn (LDIFContent v xs) (Just r) = let pre  = takeWhile (\x -> dn /= (reDN x)) xs
-                                                                           post = filter (\x -> dn /= (reDN x)) $ dropWhile (\x -> dn /= (reDN x)) xs
-                                                                           rn   = foldr applyMod2Record r ops
-                                                                       in LDIFContent v (pre++[rn]++post)
-applyChange2Record ChangeModDN      _ _ _  = error "Operation ModDN is not supported"
+applyChange2Record (ChangeAdd vals)   dn ld Nothing  = LDIF (lcVersion ld) ((lcEntries ld)++[ContentRecord dn vals]) 
+applyChange2Record (ChangeAdd _)      dn _  (Just _) = error ("ADD: Already exists: "++(dn2str dn))
+applyChange2Record ChangeDelete       dn ld (Just _) = LDIF (lcVersion ld) (filter (\x -> dn /= (reDN x)) (lcEntries ld))
+applyChange2Record ChangeDelete       dn _  Nothing  = error ("DELETE: Entry not found: "++(dn2str dn))
+applyChange2Record (ChangeModify _)   dn _  Nothing  = error ("MODIFY: Entry not found: "++(dn2str dn))
+applyChange2Record (ChangeModify ops) dn ld (Just r) = let pre  = takeWhile (\x -> dn /= (reDN x)) (lcEntries ld)
+                                                           post = filter (\x -> dn /= (reDN x)) $ dropWhile (\x -> dn /= (reDN x)) (lcEntries ld)
+                                                           rn   = foldr applyMod2Record r ops
+                                                       in LDIF (lcVersion ld) (pre++[rn]++post)
+applyChange2Record ChangeModDN      _ _ _  = error "ModDN: Operation is not supported yet."
+--applyChange2Record x _ y _                 = error $ "Unexpected LDIF Content: " ++ (show x) ++ (show y)
 
 -- | Apply Attribute Modification (Add/Del/Replace) to ContentRecord and produce changed ContentRecord
 applyMod2Record :: Modify -> LDIFRecord -> LDIFRecord
 applyMod2Record (ModAdd      name vals) (ContentRecord dn av) = let nav = map (\v -> (name,v)) vals  -- new attr/values
                                                                     mav = av ++ nav                  -- merged attr/values
                                                                     verified = if (length $ nub mav) == (length mav) then mav
-                                                                               else error ("ModAdd: Values already exists: "++(show av)++" vs "++(show vals)++" DN:"++(show dn))
+                                                                               else error ("ModAdd: Values already exists: "++(show av)++" vs "++(show vals)++" DN:"++(dn2str dn))
                                                                     in ContentRecord dn verified
-applyMod2Record (ModDelete   name [])   (ContentRecord dn av) = let nav = filter (\(n,v) -> n /= name) av -- new attr/values
+applyMod2Record (ModDelete   name [])   (ContentRecord dn av) = let nav = filter (\(n,_) -> n /= name) av -- new attr/values
                                                                     verified = if (length $ nub nav) /= (length av) then nav
-                                                                               else error ("ModDel: Attribute not found: "++(show name)++" DN:"++(show dn))
+                                                                               else error ("ModDel: Attribute not found: "++(show name)++" DN:"++(dn2str dn))
                                                                 in ContentRecord dn verified
 applyMod2Record (ModDelete   name vals) (ContentRecord dn av) = let mav = filter (\(n,v) -> n /= name || v `notElem` vals) av
                                                                     verified = if (length av) - (length mav) == (length vals) then mav
-                                                                               else error ("ModDel: Attribute/Value not found: "++(show name)++"vals"++(show vals)++" DN:"++(show dn))
+                                                                               else error ("ModDel: Attribute/Value not found: "++(show name)++"vals"++(show vals)++" DN:"++(dn2str dn))
                                                                 in ContentRecord dn verified
 applyMod2Record (ModReplace  name vals) (ContentRecord dn av) = let nav = map (\v -> (name,v)) vals -- new attr/values
-                                                                    mav = (filter (\(n,v) -> n /= name) av) ++ nav -- merged
+                                                                    mav = (filter (\(n,_) -> n /= name) av) ++ nav -- merged
                                                                 in ContentRecord dn mav
+applyMod2Record _ x = error $ "Unexpected LDIF Record:" ++ (show x)
diff --git a/src/Text/LDIF/Diff.hs b/src/Text/LDIF/Diff.hs
--- a/src/Text/LDIF/Diff.hs
+++ b/src/Text/LDIF/Diff.hs
@@ -5,10 +5,7 @@
 where
 import Text.LDIF.Types
 import Text.LDIF.Utils
-import Text.LDIF.Printer
 import Data.Maybe
-import Data.Either
-import Data.List (nub)
 
 -- | Create Change LDIF between to LDIF contents. If any
 -- | of input argument is not LDIFContent it returns Nothing. 
@@ -18,8 +15,14 @@
 -- | Unsing following strategy: 
 -- | 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 _ c1) l2@(LDIFContent v2 c2) = Just (LDIFChanges v2 (changes ++ adds))
+diffLDIF :: LDIF -> LDIF -> Either String LDIF
+diffLDIF l1 l2 | getLDIFType l1 == LDIFContentType && getLDIFType l2 == LDIFContentType = Right (diffLDIF' l1 l2)
+               | otherwise = Left ("Diff supported only on Content LDIFs but SRC="
+                                         ++(show $ getLDIFType l1)++" and DST="
+                                         ++(show $ getLDIFType l2))
+
+diffLDIF' :: LDIF -> LDIF -> LDIF
+diffLDIF' l1@(LDIF _ c1) l2@(LDIF v2 c2) = LDIF v2 (changes ++ adds)
    where 
       adds = map (content2add) $ filter (not . isEntryIn l1) c2
       changes = filter (not . isDummyRecord) $ foldl (processEntry) [] c1
@@ -33,7 +36,7 @@
                           Nothing -> False
                           Just _  -> True
       content2add (ContentRecord dn vals) = ChangeRecord dn (ChangeAdd vals)
-diffLDIF _ _ = Nothing
+      content2add (ChangeRecord _ _)      = error "Unexpected record type"
 
 -- | Diff two AttrVal Records if any of provided. 
 -- | Implementation uses inefficient algorithm for large count of attributes within ContentRecord.
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
@@ -7,9 +7,8 @@
 where
 import Text.LDIF.Types
 import Text.ParserCombinators.Parsec
-import Data.Either
 import Data.Char
-import Data.List (isPrefixOf, foldl')
+import Data.List (isPrefixOf)
 
 -- | Parse string as LDIF content and return LDIF or ParseError
 parseLDIFStr :: String -> Either ParseError LDIF
@@ -26,6 +25,7 @@
 -- | and mismatch generates ParseError
 parseLDIFStrAs' :: String -> Maybe LDIFType -> String -> Either ParseError LDIF
 parseLDIFStrAs' nm Nothing                = parse pLdif        nm . preproc
+parseLDIFStrAs' nm (Just LDIFMixedType)   = parse pLdif        nm . preproc
 parseLDIFStrAs' nm (Just LDIFContentType) = parse pLdifContent nm . preproc
 parseLDIFStrAs' nm (Just LDIFChangesType) = parse pLdifChanges nm . preproc
 
@@ -56,12 +56,12 @@
 takeLine :: [String] -> (String, [String])
 takeLine []     = ([],[])
 takeLine (x:[]) = (x,[])
-takeLine (x:xs) = let isCont x = " " `isPrefixOf` x  
+takeLine (x:xs) = let isCont z = " " `isPrefixOf` z
                   in (x ++ (concat $ map (tail) $ takeWhile (isCont) xs), dropWhile (isCont) xs) 
 
 -- | Parsec ldif parser
 pLdif :: CharParser st LDIF
-pLdif = try pLdifChanges <|> pLdifContent
+pLdif = try pLdifChanges <|> try pLdifMixed
 
 pLdifChanges :: CharParser st LDIF
 pLdifChanges = do
@@ -69,15 +69,26 @@
     ver <- optionMaybe pVersionSpec
     pSEPs
     recs <- sepEndBy1 pChangeRec pSEPs
-    return $ LDIFChanges ver recs
+    eof
+    return $ LDIF ver recs
 
+pLdifMixed:: CharParser st LDIF
+pLdifMixed = do
+    pSEPs
+    ver <- optionMaybe pVersionSpec
+    pSEPs
+    recs <- sepEndBy1 pRec pSEPs
+    eof
+    return $ LDIF ver recs
+
 pLdifContent :: CharParser st LDIF
 pLdifContent = do
     pSEPs
     ver <- optionMaybe pVersionSpec
     pSEPs
     recs <- sepEndBy1 pAttrValRec pSEPs
-    return $ LDIFContent ver recs
+    eof
+    return $ LDIF ver recs
 
 pAttrValRec ::  CharParser st LDIFRecord
 pAttrValRec = do
@@ -86,6 +97,9 @@
     attrVals <- sepEndBy1 pAttrValSpec pSEP
     return $ ContentRecord dn attrVals
 
+pRec :: CharParser st LDIFRecord
+pRec = try pChangeRec <|> pAttrValRec
+
 pChangeRec :: CharParser st LDIFRecord
 pChangeRec = try pChangeAdd
          <|> try pChangeDel
@@ -96,9 +110,9 @@
 pChangeAdd = do
     dn <- pDNSpec
     pSEP
-    string "changetype:"
+    _ <- string "changetype:"
     pFILL
-    string "add"
+    _ <- string "add"
     pSEP
     vals <- sepEndBy1 pAttrValSpec pSEP
     return $ ChangeRecord dn (ChangeAdd vals)
@@ -107,9 +121,9 @@
 pChangeDel = do
     dn <- pDNSpec
     pSEP
-    string "changetype:"
+    _ <- string "changetype:"
     pFILL
-    string "delete"
+    _ <- string "delete"
     pSEP
     return $ ChangeRecord dn ChangeDelete
 
@@ -117,9 +131,9 @@
 pChangeMod = do
     dn <- pDNSpec
     pSEP
-    string "changetype:"
+    _ <- string "changetype:"
     pFILL
-    string "modify"
+    _ <- string "modify"
     pSEP
     mods <- sepEndBy1 pModSpec (char '-' >> pSEP)
     return $ ChangeRecord dn (ChangeModify mods)
@@ -128,17 +142,17 @@
 pChangeModDN = do
     dn <- pDNSpec
     pSEP
-    string "changetype:"
+    _ <- string "changetype:"
     pFILL
-    string "modrdn" 
+    _ <- string "modrdn" 
     pSEP
-    string "newrdn:"
+    _ <- string "newrdn:"
     pFILL 
-    pRDN
+    _ <- pRDN
     pSEP
-    string "deleteoldrdn:"
+    _ <- string "deleteoldrdn:"
     pFILL
-    oneOf "01"
+    _ <- oneOf "01"
     pSEP
     return $ ChangeRecord dn ChangeModDN
 
@@ -147,7 +161,7 @@
 
 pDNSpec :: CharParser st DN
 pDNSpec = do
-    string "dn:"
+    _ <- string "dn:"
     pDN
 
 pDN :: CharParser st DN
@@ -160,7 +174,7 @@
 pAttrEqValue = do
    pFILL
    att <- pAttributeType
-   char '='
+   _ <- char '='
    val <- pAttrValueDN
    return (att,val)
 
@@ -168,12 +182,13 @@
 pAttrValueDN = do
    many (noneOf stringChars)
    where 
-     specialChars = [',','=','+','<','>','#',';','\n','\r']
+     specialChars = [',','=','+','#',';','\n','\r']
+     -- specialChars = [',','=','+','<','>','#',';','\n','\r']
      stringChars  = '\\':'"':specialChars 
 
 pVersionSpec :: CharParser st String
 pVersionSpec = do
-   string "version:"
+   _ <- string "version:"
    pFILL
    many1 digit
 
@@ -213,7 +228,7 @@
 
 pValueSpec :: CharParser st Value
 pValueSpec = try (char ':' >> char ':' >> pFILL >> pBase64String)
-         <|> try (char ':' >> pFILL >> pSafeString) 
+         <|> try (char ':' >> pFILL >> pSafeString') 
          <|> (char ':' >> char '<' >> pFILL >> pURL)
 
 pURL :: CharParser st String
@@ -224,6 +239,11 @@
    c <- noneOf "\n\r :<"
    r <- many (noneOf "\n\r")
    return $ c:r
+
+pSafeString' :: CharParser st String
+pSafeString' = do
+   r <- many (noneOf "\n\r")
+   return r
  
 pBase64String :: CharParser st String
 pBase64String = pSafeString
@@ -234,11 +254,11 @@
 pLdapOid :: CharParser st Attribute
 pLdapOid = do
    num <- many1 digit
-   rest <- many (do { string "."; n <- many1 digit; return $ '.':n})
+   rest <- many (do { _ <- string "."; n <- many1 digit; return $ '.':n})
    return (Attribute $ num ++ concat rest)
 
 pFILL :: CharParser st ()
-pFILL = spaces
+pFILL = skipMany (oneOf [' ', '\t'])
 
 pSEP :: CharParser st ()
 pSEP = try (char '\r' >> char '\n' >> return () )
diff --git a/src/Text/LDIF/Printer.hs b/src/Text/LDIF/Printer.hs
--- a/src/Text/LDIF/Printer.hs
+++ b/src/Text/LDIF/Printer.hs
@@ -10,8 +10,7 @@
 
 -- | Serialize LDIF in LDIF Format
 ldif2str :: LDIF -> String
-ldif2str (LDIFContent v xs) = unlines $ (ver2str v) ++ (map (record2str) xs)
-ldif2str (LDIFChanges v xs) = unlines $ (ver2str v) ++ (map (record2str) xs)
+ldif2str (LDIF v xs) = unlines $ (ver2str v) ++ (map (record2str) xs)
 
 -- | Serialize version to LDIF Format Lines
 ver2str :: Maybe String -> [String]
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
@@ -23,12 +23,18 @@
 type AttrValue = (Attribute, Value)
 
 -- | Type of LDIF Files (Content, Changes)
-data LDIFType = LDIFContentType | LDIFChangesType deriving (Show, Eq) -- Maybe LDIFMixedType 
+data LDIFType = LDIFContentType 
+              | LDIFChangesType 
+              | LDIFMixedType deriving Eq
 
+instance Show LDIFType where
+    show LDIFChangesType = "Delta"
+    show LDIFContentType = "Content"
+    show LDIFMixedType   = "Mixed"
+
 -- | Represents LDIF structure, it can be either simply LDIF data dump or
 -- | changes LDIF with LDAP operations 
-data LDIF = LDIFContent { lcVersion :: Maybe String, lcEntries :: [LDIFRecord] }
-          | LDIFChanges { lcVersion :: Maybe String, lcChanges :: [LDIFRecord] } deriving (Show, Eq)
+data LDIF = LDIF { lcVersion :: Maybe String, lcEntries :: [LDIFRecord] } deriving (Show, Eq)
 
 -- | Represents one data record within LDIF file with DN and content
 -- | Represents one change record within LDIF file with DN and content
diff --git a/src/Text/LDIF/Utils.hs b/src/Text/LDIF/Utils.hs
--- a/src/Text/LDIF/Utils.hs
+++ b/src/Text/LDIF/Utils.hs
@@ -7,19 +7,21 @@
         takeDNPrefix,
         leafOfDN,
         rootOfDN,
-        isDummyRecord
+        lookupAttr,
+        filterAttr,
+        isDummyRecord,
+        ldif2tree,
+        getLDIFType,
+        isContentRecord,
+        isChangeRecord
 )
 where
 import Text.LDIF.Types
-import Text.LDIF.Printer
-import Data.Maybe
-import Data.Either
-import Data.List (nub)
+import Data.Tree
 
 -- | Find all Contents with given DN
 findRecordsByDN :: LDIF -> DN -> [LDIFRecord]
-findRecordsByDN (LDIFContent _ entries) dn = filter (\x -> (reDN x) == dn) entries
-findRecordsByDN (LDIFChanges _ entries) dn = filter (\x -> (reDN x) == dn) entries
+findRecordsByDN (LDIF _ entries) dn = filter (\x -> (reDN x) == dn) entries
 
 -- | Find first Content with given DN
 findRecordByDN :: LDIF -> DN -> Maybe LDIFRecord
@@ -28,6 +30,14 @@
                                  xs   -> Just (head xs)
 
 
+-- | Find fist Attribute within attributes pairs list
+lookupAttr :: String -> [AttrValue] -> Maybe Value
+lookupAttr attr xs = lookup (Attribute attr) xs
+
+-- | Filter Attribute Value list according Attribute name
+filterAttr :: String -> [AttrValue] -> [AttrValue]
+filterAttr attr xs  = filter (\x -> (Attribute attr) == fst x) xs
+
 -- | Change record without any impact
 isDummyRecord :: LDIFRecord -> Bool
 isDummyRecord (ChangeRecord _ (ChangeModify [])) = True 
@@ -46,11 +56,47 @@
 getDNValue (DN vals) idx = vals !! idx
 
 takeDNPrefix :: DN -> Int -> DN
-takeDNPrefix (DN vals) n = (DN (take n vals))
+takeDNPrefix (DN vals) n = (DN (reverse $ take n (reverse vals)))
 
 -- | Check if the dn1 is prefix of dn2
 isDNPrefixOf :: DN -> DN -> Bool
 isDNPrefixOf dn1 dn2 | (sizeOfDN dn1) >= (sizeOfDN dn2) = False
-                     | otherwise = let n = (sizeOfDN dn2)
-                                   in (takeDNPrefix dn1 n) == dn2
+                     | otherwise = let n = (sizeOfDN dn1)
+                                   in (takeDNPrefix dn2 n) == dn1
 
+dummyRootDN :: DN
+dummyRootDN = DN [(Attribute "dc", "root")]
+
+ldif2tree :: LDIF -> Tree LDIFRecord
+ldif2tree (LDIF _ entries) = Node (ChangeRecord dummyRootDN (ChangeAdd [])) (ldifRecs2tree entries)
+
+isParentRecordOf :: LDIFRecord -> LDIFRecord -> Bool
+isParentRecordOf a b = isDNPrefixOf (reDN a) (reDN b)
+
+ldifRoots :: [LDIFRecord] -> [LDIFRecord]
+ldifRoots xs = let isRoot x = all (\y -> not $ isParentRecordOf y x) xs
+               in filter (isRoot) xs
+
+ldifRecs2tree :: [LDIFRecord] -> [Tree LDIFRecord]
+ldifRecs2tree xs = let roots = (ldifRoots xs)
+                       subtr x = ldifRecs2tree $ filter (isParentRecordOf x) xs
+                   in map (\x -> Node x (subtr x)) roots
+
+isContentRecord :: LDIFRecord -> Bool
+isContentRecord (ContentRecord _ _) = True
+isContentRecord _ = False
+
+isChangeRecord :: LDIFRecord -> Bool
+isChangeRecord (ChangeRecord _ _) = True
+isChangeRecord _ = False
+
+getLDIFType :: LDIF -> LDIFType
+getLDIFType (LDIF _ []) = LDIFContentType
+getLDIFType (LDIF _ xs) = getLDIFType' con chg
+    where
+      con = filter (isContentRecord) xs
+      chg = filter (not . isContentRecord) xs
+      getLDIFType' [] [] = error "Unexpected"
+      getLDIFType' [] _  = LDIFChangesType
+      getLDIFType' _  [] = LDIFContentType
+      getLDIFType' _  _  = LDIFMixedType
diff --git a/src/diffLDIF.hs b/src/diffLDIF.hs
--- a/src/diffLDIF.hs
+++ b/src/diffLDIF.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE DeriveDataTypeable #-}
 -- | Make Change LDIF based on two Content LDIFs
 import Data.List
 import Data.Either
@@ -6,11 +7,31 @@
 import System.FilePath 
 import System.Environment
 import Text.LDIF
+import System.Console.CmdArgs
 
+progDesc = "Create delta LDIF between Source LDIF and Target LDIF"
+
+data DiffLdif = DiffLdif { srcFile :: FilePath
+                         , dstFile :: FilePath } deriving (Show, Data, Typeable)
+
+defaultCfg = mode $ DiffLdif { srcFile = def &= typFile & flag "s" & text "Source LDIF File"
+                             , dstFile = def &= typFile & flag "t" & text "Target LDIF File" }
+
+verifyCfg :: DiffLdif -> IO ()
+verifyCfg (DiffLdif [] []) = do 
+  msg <- cmdArgsHelp progDesc [defaultCfg] Text
+  error msg
+verifyCfg (DiffLdif [] _)  = error "Missing Source LDIF File parameter (-s)"
+verifyCfg (DiffLdif _ [])  = error "Missing Target LDIF File parameter (-t)"
+verifyCfg (DiffLdif _ _ )  = return ()
+
 main = do
-  args <- getArgs
-  ml1 <- parseLDIFFile (args !! 0)
-  ml2 <- parseLDIFFile (args !! 1)
+  cfg <- cmdArgs progDesc [defaultCfg]
+  verifyCfg cfg
+  ml1 <- parseLDIFFile (srcFile cfg)
+  ml2 <- parseLDIFFile (dstFile cfg)
   case rights [ml1,ml2] of 
-       [l1,l2] -> putStrLn $ ldif2str $ fromJust $ diffLDIF l1 l2  
+       [l1,l2] -> case diffLDIF l1 l2 of
+                    Left err -> putStrLn err
+                    Right delta -> putStrLn $ ldif2str delta
        _       -> print $ lefts [ml1,ml2] 
diff --git a/src/ldif2html.hs b/src/ldif2html.hs
--- a/src/ldif2html.hs
+++ b/src/ldif2html.hs
@@ -9,8 +9,7 @@
 import qualified Data.Set as Set
 
 ldif2html :: Set.Set String -> LDIF -> String
-ldif2html idx (LDIFContent v xs) = unlines $ (ver2str v) ++ (map (record2html idx) xs)
-ldif2html idx (LDIFChanges v xs) = unlines $ (ver2str v) ++ (map (record2html idx) xs)
+ldif2html idx (LDIF v xs) = unlines $ (ver2str v) ++ (map (record2html idx) xs)
 
 -- | Serialize version to LDIF Format Lines
 ver2str :: Maybe String -> [String]
@@ -73,5 +72,4 @@
        xs  -> mapM_ print xs
 
 dns :: LDIF -> Set.Set String
-dns (LDIFContent _ xs) = Set.fromList $ nub $ map (dn2last . reDN) xs
-dns (LDIFChanges _ xs) = Set.fromList $ nub $ map (dn2last . reDN) xs
+dns (LDIF _ xs) = Set.fromList $ nub $ map (dn2last . reDN) xs
diff --git a/src/ldifmodify.hs b/src/ldifmodify.hs
--- a/src/ldifmodify.hs
+++ b/src/ldifmodify.hs
@@ -10,6 +10,8 @@
 import Text.LDIF
 import System.Console.CmdArgs
 
+progDesc = "Apply LDAP operations from LDIF to LDIF (like ldapmodify)"
+
 data LdifModify = LdifModify { baseFile :: FilePath
                              , modFiles  :: [FilePath]
                              , outFile  :: FilePath } deriving (Show, Data, Typeable)
@@ -19,12 +21,15 @@
                                , outFile = def &= typFile & flag "o" & text "Output LDIF File" }
 
 verifyCfg :: LdifModify -> IO ()
+verifyCfg (LdifModify [] [] [])                       = do
+               msg <- cmdArgsHelp progDesc [defaultCfg] Text
+               error msg
 verifyCfg (LdifModify bf mfx ouf) | length bf  == 0   = error "Missing Base LDIF File parameter (-f)"
                                   | length mfx == 0   = error "Missing LDIF Files for applying as arguments"
                                   | otherwise         = return ()                                                              
 
 main = do
-  cfg <- cmdArgs "LDIF Modify. Apply LDAP operations from LDIF to LDIF" [defaultCfg]
+  cfg <- cmdArgs progDesc [defaultCfg]
   verifyCfg cfg
   baseLDIF <- safeParseLDIFFile (baseFile cfg)
   modLDIFs <- mapM (safeParseLDIFFile) (modFiles cfg)
diff --git a/src/ldifparse.hs b/src/ldifparse.hs
new file mode 100644
--- /dev/null
+++ b/src/ldifparse.hs
@@ -0,0 +1,18 @@
+-- | 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
+
+main = do
+  args <- getArgs
+  ml1 <- parseLDIFFile (args !! 0)
+  case ml1 of 
+       Right l1 -> do
+             print l1
+             putStrLn "========================================================"
+             putStrLn $ ldif2str l1
+       Left err -> print err
diff --git a/tests/TestMain.hs b/tests/TestMain.hs
--- a/tests/TestMain.hs
+++ b/tests/TestMain.hs
@@ -12,14 +12,21 @@
     ls <- getLDIFs ldifDir
     runTestTT (tests ls)
 
-tests ls = TestList $ (testCasesParseOK ls) ++ (testCasesDIFF)
+tests ls = TestList $ (testCasesParseOK ls) ++ testCasesDIFF ++ testCasesUtils
 
 --
 -- Test Cases
 --
 testCasesDIFF = [TestCase (assertEqual "dummy" True True)]
 testCasesParseOK ls = map (\x -> TestCase (assertParsedOK x)) $ filter (isOK) ls
-
+testCasesUtils = [ TestCase (assertBool "DN1Root is Prefix of DN2Root" (not $ isDNPrefixOf dn1root dn2root))
+                 , TestCase (assertBool "DN1Root is Prefix of DN1Child" (isDNPrefixOf dn1root dn1child))
+                 , TestCase (assertBool "DN Size 1" (1 == sizeOfDN dn1root))
+                 , TestCase (assertBool "DN Size 2" (2 == sizeOfDN dn1child))]
+    where
+      dn1root = head $ rights [ parseDNStr "dc=sk" ]
+      dn2root = head $ rights [ parseDNStr "dc=de" ]
+      dn1child = head $ rights [ parseDNStr "o=green,dc=sk" ]
 --
 -- Support Methods
 --
@@ -38,9 +45,9 @@
                            | (isSuffixOf ".content.ldif" name) = assertTypeContent name ldif
                            | otherwise = assertFailure $ "Unexpected filename: (not .modify.ldif or .content.ldif " ++ name
 
-assertTypeContent n l@(LDIFContent _ _) = assertBool "Valid Content Type" True -- >> (putStrLn $ "\n\n" ++ n ++ "\n\n" ++ (show l))
-assertTypeContent n x = assertFailure $ n ++ " is not type of LDIFContent"
+assertTypeContent n l  | (getLDIFType l == LDIFContentType) = assertBool "Valid Content Type" True -- >> (putStrLn $ "\n\n" ++ n ++ "\n\n" ++ (show l))
+                       | otherwise          = assertFailure $ n ++ " is not type of LDIFContent"
 
-assertTypeChanges n l@(LDIFChanges _ _) = assertBool "Valid Changes Type" True -- >> (putStrLn $ "\n\n" ++ n ++ "\n\n" ++ (show l))
-assertTypeChanges n x = assertFailure $ n ++ " is not type of LDIFChanges"
+assertTypeChanges n l | (getLDIFType l /= LDIFContentType) = assertBool "Valid Changes Type" True -- >> (putStrLn $ "\n\n" ++ n ++ "\n\n" ++ (show l))
+                      | otherwise          = assertFailure $ n ++ " is not type of LDIFChanges"
   
