import Data.Char import Database.HDBC.ODBC import Database.HDBC import qualified Data.ByteString.Char8 as B -- The ending ';' is required! You can append other options like: -- connectionString' = connectionString ++ "Password=blahblah;" connectionString = "DSN=Default;" outPath = "/tmp/blog/" indexName = outPath ++ "index.html" indexHead = " INDEX\n" main = handleSqlError $ do c <- connectODBC connectionString s <- quickQuery c "SELECT post_title, post_content FROM wp_posts" [] let s' = map (map fromSql) s :: [[B.ByteString]] writeFile indexName indexHead mapM_ process s' disconnect c -- replace / with -, replace " with ', and replace spaces with _ -- turns out this function is unsafe because it works on ASCII without taking into account utf-8 encodings! -- it's therefore possible to garble the file name. clean :: B.ByteString -> String clean fn = let a = B.map f fn f '/' = '-' f '"' = '\'' f x = x -- (b:c) = map B.unpack $ B.words a in -- b ++ (concatMap ('_':) c) B.unpack a htmlHead = " " htmlTitle = " -- Wei Hu " linkHead = "

IO () process [fn,fc] = let fn' = clean fn ufn = B.unpack fn clean_fn = outPath ++ fn' ++ ".html" content = B.concat (map B.pack [htmlHead, ufn, htmlTitle] ++ [fc']) link = B.concat $ map B.pack [linkHead, fn' ++ ".html\">", ufn, "\n"] -- insert a
at the end of each line fc' = let x = B.lines fc y = map ((flip B.append) $ B.pack "
") x in B.concat y in if ufn /= "" then do putStrLn "******************" B.putStrLn fn putStrLn "******************" B.putStrLn fc print "Keep this file?(Y/n)" ans <- getLine if ans == "" || ans == "y" then do B.appendFile indexName link B.writeFile clean_fn content else return () else return ()