]> gitweb @ CieloNegro.org - Rakka.git/commitdiff
wrote much code...
authorpho <pho@cielonegro.org>
Tue, 9 Oct 2007 15:26:09 +0000 (00:26 +0900)
committerpho <pho@cielonegro.org>
Tue, 9 Oct 2007 15:26:09 +0000 (00:26 +0900)
darcs-hash:20071009152609-62b54-4ad6a3ed116793bf48b02b07f16cc282636568fe.gz

13 files changed:
Rakka.cabal
Rakka/Environment.hs
Rakka/Page.hs
Rakka/Resource.hs
Rakka/Resource/Object.hs
Rakka/Resource/Page.hs
Rakka/Resource/Page/Get.hs
Rakka/Storage.hs
Rakka/Storage/DefaultPage.hs
Rakka/SystemConfig.hs [new file with mode: 0644]
Rakka/Utils.hs
defaultPages/MainPage [moved from defaultPages/Main_Page with 65% similarity]
defaultPages/StyleSheet/Default [new file with mode: 0644]

index 9c173bfad43be9dd1e69f673af1caa8cb9ccd71f..07f3e41b73dce89d7f6435ab0cf3c0b07c310a58 100644 (file)
@@ -25,10 +25,11 @@ Extensions:
 GHC-Options:
     -fwarn-unused-imports
 Build-Depends:
-    base, mtl, network, unix, encoding, base64-string, hxt, HsSVN, Lucu
+    base, mtl, network, unix, encoding, Crypto, hxt, filepath, HsSVN, Lucu
 Exposed-Modules:
     Rakka.Page
     Rakka.Storage
+    Rakka.SystemConfig
 Other-Modules:
     Rakka.Environment
     Rakka.Storage.DefaultPage
index 881a9e69ef40fe3f8023fb81aafc80bb90f08b2f..015d37d43fda667574f42886fd7b9c2b8a3a4180 100644 (file)
@@ -1,28 +1,20 @@
 module Rakka.Environment
     ( Environment(..)
     , setupEnv
-
-    , getSiteName
-    , getSiteNameA
-
-    , getBaseURI
-    , getBaseURIA
     )
     where
 
-import           Control.Arrow.ArrowIO
-import qualified Data.ByteString.Char8 as C8
-import           Data.Maybe
 import           Network
 import qualified Network.HTTP.Lucu.Config as LC
-import           Network.URI
 import           Rakka.Storage
+import           Rakka.SystemConfig
 
 
 data Environment = Environment {
-      envLocalStateDir :: FilePath
-    , envLucuConf      :: LC.Config
-    , envStorage       :: Storage
+      envLocalStateDir :: !FilePath
+    , envLucuConf      :: !LC.Config
+    , envStorage       :: !Storage
+    , envSysConf       :: !SystemConfig
     }
 
 
@@ -31,38 +23,9 @@ setupEnv lsdir portNum
     = do let lucuConf = LC.defaultConfig {
                           LC.cnfServerPort = PortNumber portNum
                         }
-         storage <- mkStorage -- FIXME
          return $ Environment {
                       envLocalStateDir = lsdir
                     , envLucuConf      = lucuConf
-                    , envStorage       = storage
+                    , envStorage       = mkStorage
+                    , envSysConf       = mkSystemConfig lucuConf
                     }
-
-
-getSiteName :: Environment -> IO String
-getSiteName env
-    = return "Rakka" -- FIXME
-
-
-getSiteNameA :: ArrowIO a => Environment -> a b String
-getSiteNameA = arrIO0 . getSiteName
-
-
-getBaseURI :: Environment -> IO URI
-getBaseURI env
-    = do let conf = envLucuConf env
-             host = C8.unpack $ LC.cnfServerHost conf
-             port = case LC.cnfServerPort conf of
-                      PortNumber num -> fromIntegral num
-             
-             defaultURI
-                  = "http://" ++ host ++
-                    (if port == 80
-                     then ""
-                     else ':' : show port) ++ "/"
-
-         return $ fromJust $ parseURI defaultURI -- FIXME
-
-
-getBaseURIA :: ArrowIO a => Environment -> a b URI
-getBaseURIA = arrIO0 . getBaseURI
\ No newline at end of file
index 2e3ea45cae6250310d6d88191e2c4e4208b957d8..c22e5206583c819facd8baab5ec437a4038d60a7 100644 (file)
@@ -4,6 +4,7 @@ module Rakka.Page
     , encodePageName
     , decodePageName
     , mkPageURI
+    , mkObjectURI
     )
     where
 
@@ -14,6 +15,7 @@ import           Data.Encoding.UTF8
 import           Network.HTTP.Lucu
 import           Network.URI
 import           Subversion.Types
+import           System.FilePath
 import           System.Time
 
 
@@ -22,34 +24,35 @@ type PageName = String
 
 data Page
     = Redirection {
-        redirName     :: PageName
-      , redirDest     :: PageName
-      , redirRevision :: Maybe RevNum
-      , redirLastMod  :: CalendarTime
+        redirName     :: !PageName
+      , redirDest     :: !PageName
+      , redirRevision :: !(Maybe RevNum)
+      , redirLastMod  :: !CalendarTime
       }
     | Entity {
-        pageName      :: PageName
-      , pageType      :: MIMEType
-      , pageIsTheme   :: Bool     -- text/css 以外では無意味
-      , pageIsFeed    :: Bool     -- text/x-rakka 以外では無意味
-      , pageIsLocked  :: Bool
-      , pageIsBoring  :: Bool
-      , pageRevision  :: Maybe RevNum
-      , pageLastMod   :: CalendarTime
-      , pageSummary   :: Maybe String
-      , pageOtherLang :: [(String, PageName)]
-      , pageContent   :: LazyByteString
+        pageName      :: !PageName
+      , pageType      :: !MIMEType
+      , pageIsTheme   :: !Bool     -- text/css 以外では無意味
+      , pageIsFeed    :: !Bool     -- text/x-rakka 以外では無意味
+      , pageIsLocked  :: !Bool
+      , pageIsBoring  :: !Bool
+      , pageIsBinary  :: !Bool
+      , pageRevision  :: !(Maybe RevNum)
+      , pageLastMod   :: !CalendarTime
+      , pageSummary   :: !(Maybe String)
+      , pageOtherLang :: ![(String, PageName)]
+      , pageContent   :: !LazyByteString
       }
 
 
 -- UTF-8 に encode してから 0x20 - 0x7E の範圍を除いて URI escape する。
 encodePageName :: PageName -> FilePath
-encodePageName = escapeURIString shouldEscape . C8.unpack . encode UTF8 
+encodePageName = escapeURIString isSafe . C8.unpack . encode UTF8 
     where
-      shouldEscape :: Char -> Bool
-      shouldEscape c
-          | c >= ' ' && c <= '~' = False
-          | otherwise            = True
+      isSafe :: Char -> Bool
+      isSafe c
+          | c >= ' ' && c <= '~' = True
+          | otherwise            = False
 
 
 -- URI unescape して UTF-8 から decode する。
@@ -59,9 +62,13 @@ decodePageName = decode UTF8 . C8.pack . unEscapeString
 
 mkPageURI :: URI -> PageName -> URI
 mkPageURI baseURI name
-    | uriPath baseURI == ""         = baseURI { uriPath = "/" ++ encoded }
-    | uriPath baseURI == "/"        = baseURI { uriPath = "/" ++ encoded }
-    | last (uriPath baseURI) == '/' = baseURI { uriPath = uriPath baseURI ++ encoded }
-    | otherwise                     = baseURI { uriPath = uriPath baseURI ++ "/" ++ encoded }
-    where
-      encoded = encodePageName name
+    = baseURI {
+        uriPath = foldl combine "/" [uriPath baseURI, encodePageName name]
+      }
+
+
+mkObjectURI :: URI -> PageName -> URI
+mkObjectURI baseURI name
+    = baseURI {
+        uriPath = foldl combine "/" [uriPath baseURI, "object", encodePageName name]
+      }
index c79b215cfe5fb5e1bce74101982c18ee3cc7922c..e1166b4d33079b0096d81a63f2d8c00af1d8b396 100644 (file)
@@ -70,10 +70,9 @@ outputXmlPage :: XmlTree -> IOSArrow XmlTree XmlTree -> Resource ()
 outputXmlPage tree toXHTML
     = do mType <- getEntityType
          setContentType mType
-         let formatter = if mType == read "text/xml" then
-                             this
-                         else
-                             toXHTML
+         let formatter = case mType of
+                           MIMEType "application" "xhtml+xml" _ -> toXHTML
+                           MIMEType "text"        "xml"       _ -> this
          [resultStr] <- liftIO $ runX ( setErrorMsgHandler False fail
                                         >>>
                                         constA tree
index 9e30d1eee78d919f8094c10ab02adb886c78b0c4..af0d9b7604da54602e89e7d6ef4e25a749947c48 100644 (file)
@@ -4,19 +4,68 @@ module Rakka.Resource.Object
     where
 
 import           Network.HTTP.Lucu
+import           Network.HTTP.Lucu.Utils
 import           Rakka.Environment
+import           Rakka.Page
+import           Rakka.Storage
+import           Rakka.SystemConfig
+import           System.FilePath
+import           System.Time
 
 
 resObject :: Environment -> ResourceDef
 resObject env
     = ResourceDef {
         resUsesNativeThread = False
-      , resIsGreedy         = False
-      , resGet              = Just $ do setContentType $ read "text/plain"
-                                        output "FIXME: not implemented"
+      , resIsGreedy         = True
+      , resGet              = Just $ getPathInfo >>= handleGet env . toPageName
       , resHead             = Nothing
       , resPost             = Nothing
       , resPut              = Nothing
       , resDelete           = Nothing
       }
+    where
+      toPageName :: [String] -> PageName
+      toPageName = decodePageName . dropExtension . joinWith "/" 
+
+
+handleGet :: Environment -> PageName -> Resource ()
+handleGet env name
+    = do pageM <- getPage (envStorage env) name
+         case pageM of
+           Nothing
+               -> foundNoEntity Nothing
+
+           Just redir@(Redirection _ _ _ _)
+               -> handleRedirect env redir
+
+           Just entity@(Entity _ _ _ _ _ _ _ _ _ _ _ _)
+               -> handleGetEntity env entity
+
+
+{-
+  HTTP/1.1 302 Found
+  Location: http://example.org/object/Destination
+-}
+handleRedirect :: Environment -> Page -> Resource ()
+handleRedirect env redir
+    = do BaseURI baseURI <- getSysConf (envSysConf env) (BaseURI undefined)
+         redirect Found (mkObjectURI baseURI $ redirName redir)
+
+
+{-
+  HTTP/1.1 200 OK
+  Content-Type: image/png
+  
+  ...
+-}
+handleGetEntity :: Environment -> Page -> Resource ()
+handleGetEntity env page
+    = do let lastMod = toClockTime $ pageLastMod page
+
+         case pageRevision page of
+           Nothing  -> foundTimeStamp lastMod
+           Just rev -> foundEntity (strongETag $ show rev) lastMod
 
+         setContentType (pageType    page)
+         outputLBS      (pageContent page)
index c72cf88b91ccc52088b03f4530729ed67671ce67..6d8c7d52312facf1ee629c0d00d21c3f3fc8a48c 100644 (file)
@@ -9,6 +9,7 @@ import           Network.HTTP.Lucu.Utils
 import           Rakka.Environment
 import           Rakka.Page
 import           Rakka.Resource.Page.Get
+import           System.FilePath
 
 
 fallbackPage :: Environment -> [String] -> IO (Maybe ResourceDef)
@@ -26,10 +27,9 @@ fallbackPage env path
           , resPut              = Just $ handlePut env (toPageName path)
           , resDelete           = Just $ handleDelete env (toPageName path)
           }
-
-
-toPageName :: [String] -> PageName
-toPageName = decodePageName . joinWith "/" 
+    where
+      toPageName :: [String] -> PageName
+      toPageName = decodePageName . dropExtension . joinWith "/"
 
 
 handlePut :: Environment -> PageName -> Resource ()
index 322e9db9f06abaf287685b44a9a2b45c24604cb0..30da9b97f9b9dbf626f049d4f595ff9d28e1cfd1 100644 (file)
@@ -4,35 +4,56 @@ module Rakka.Resource.Page.Get
     where
 
 import           Control.Arrow
+import           Control.Arrow.ArrowIf
+import           Control.Arrow.ArrowIO
 import           Control.Arrow.ArrowList
+import           Data.Encoding
+import           Data.Encoding.UTF8
 import           Network.HTTP.Lucu
 import           Network.URI
 import           Rakka.Environment
 import           Rakka.Page
 import           Rakka.Resource
 import           Rakka.Storage
+import           Rakka.SystemConfig
 import           Rakka.Utils
+import           System.Time
 import           Text.XML.HXT.Arrow.XmlArrow
+import           Text.XML.HXT.Arrow.XmlNodeSet
 import           Text.XML.HXT.DOM.TypeDefs
 
 
+handleGet :: Environment -> PageName -> Resource ()
+handleGet env name
+    = runIdempotentA $ proc ()
+    -> do pageM <- getPageA (envStorage env) -< name
+          case pageM of
+            Nothing
+                -> returnA -< foundNoEntity Nothing
+
+            Just redir@(Redirection _ _ _ _)
+                -> handleRedirect env -< redir
+
+            Just entity@(Entity _ _ _ _ _ _ _ _ _ _ _ _)
+                -> handleGetEntity env -< entity
+
 {-
-  [リダイレクトの場合]
   HTTP/1.1 302 Found
   Location: http://example.org/Destination?from=Source&revision=112
-
-  <page site="CieloNegro"
-        baseURI="http://example.org/"
-        name="Source"
-        redirect="Destination"
-        revision="112"         -- デフォルトでない場合のみ存在
-        lastModified="2000-01-01T00:00:00" />
+-}
+handleRedirect :: (ArrowXml a, ArrowIO a) => Environment -> a Page (Resource ())
+handleRedirect env
+    = proc redir
+    -> do BaseURI baseURI <- getSysConfA (envSysConf env) (BaseURI undefined) -< ()
+          returnA -< redirect Found (mkPageURI baseURI $ redirName redir) -- FIXME
 
 
-  [text/* の場合]
+{-
+  [pageIsBinary が False の場合]
 
   <page site="CieloNegro"
         baseURI="http://example.org/"
+        styleSheet="StyleSheet/Default"
         name="Foo/Bar"
         type="text/x-rakka"
         isTheme="no"        -- text/css の場合のみ存在
@@ -45,7 +66,7 @@ import           Text.XML.HXT.DOM.TypeDefs
         blah blah...
     </summary> -- 存在しない場合もある
 
-    <otherLang>
+    <otherLang> -- 存在しない場合もある
       <link lang="ja" page="Bar/Baz" />
     </otherLang>
 
@@ -55,40 +76,144 @@ import           Text.XML.HXT.DOM.TypeDefs
   </page>
 
   
-  [text/* 以外の場合: content 要素の代はりに object 要素]
+  [pageIsBinary が True の場合: content 要素の代はりに object 要素]
   
   <object data="/object/Foo/Bar" /> -- data 屬性に URI
 -}
-handleGet :: Environment -> PageName -> Resource ()
-handleGet env name
-    = let sto = envStorage env
-      in 
-        runIdempotentA $ proc ()
-          -> do siteName <- getSiteNameA env -< ()
-                baseURI  <- getBaseURIA  env -< ()
-
-                pageM <- getPageA sto -< name
-                case pageM of
-                  Nothing
-                      -> returnA -< foundNoEntity Nothing
-
-                  Just redir@(Redirection _ _ _ _)
-                      -> do tree <- ( eelem "/"
-                                      += ( eelem "page"
-                                           += sattr "site"     siteName
-                                           += sattr "baseURI"  (uriToString id baseURI "")
-                                           += sattr "name"     name
-                                           += sattr "redirect" (redirDest redir)
-                                           += ( case redirRevision redir of
-                                                  Nothing  -> none
-                                                  Just rev -> sattr "revision" (show rev)
-                                              )
-                                           += sattr "lastModified" (formatW3CDateTime $ redirLastMod redir)
-                                         )
-                                    ) -<< ()
-                            returnA -< do redirect SeeOther (mkPageURI baseURI name)
-                                          outputXmlPage tree redirToXHTML
-
-
-redirToXHTML :: ArrowXml a => a XmlTree XmlTree
-redirToXHTML = error "not implemented"
\ No newline at end of file
+handleGetEntity :: (ArrowXml a, ArrowIO a) => Environment -> a Page (Resource ())
+handleGetEntity env
+    = let sysConf = envSysConf env
+      in
+        proc page
+          -> do SiteName   siteName <- getSysConfA sysConf (SiteName   undefined) -< ()
+                BaseURI    baseURI  <- getSysConfA sysConf (BaseURI    undefined) -< ()
+                StyleSheet cssName  <- getSysConfA sysConf (StyleSheet undefined) -< ()
+
+                tree <- ( eelem "/"
+                          += ( eelem "page"
+                               += sattr "site"       siteName
+                               += sattr "baseURI"    (uriToString id baseURI "")
+                               += sattr "styleSheet" cssName
+                               += sattr "name"       (pageName page)
+                               += sattr "type"       (show $ pageType page)
+                               += ( case pageType page of
+                                      MIMEType "text" "css" _
+                                          -> sattr "isTheme" (yesOrNo $ pageIsTheme page)
+                                      _   -> none
+                                  )
+                               += ( case pageType page of
+                                      MIMEType "text" "x-rakka" _
+                                          -> sattr "isFeed" (yesOrNo $ pageIsFeed page)
+                                      _   -> none
+                                  )
+                               += sattr "isLocked" (yesOrNo $ pageIsLocked page)
+                               += ( case pageRevision page of
+                                      Nothing  -> none
+                                      Just rev -> sattr "revision" (show rev)
+                                  )
+                               += sattr "lastModified" (formatW3CDateTime $ pageLastMod page)
+
+                               += ( case pageSummary page of
+                                      Nothing -> none
+                                      Just s  -> eelem "summary" += txt s
+                                  )
+
+                               += ( case pageOtherLang page of
+                                      [] -> none
+                                      xs -> selem "otherLang"
+                                            [ eelem "link"
+                                              += sattr "lang" lang
+                                              += sattr "page" page
+                                                  | (lang, page) <- xs ]
+                                  )
+                                                  
+                               += ( case pageIsBinary page of
+                                      False -> eelem "content"
+                                               += txt (decodeLazy UTF8 $ pageContent page)
+
+                                      True  -> eelem "object"
+                                               += sattr "data" (uriToString id (mkObjectURI baseURI $ pageName page) "")
+                                  )
+                             )
+                        ) -<< ()
+
+                returnA -< do let lastMod = toClockTime $ pageLastMod page
+
+                              case pageRevision page of
+                                Nothing  -> foundTimeStamp lastMod
+                                Just rev -> foundEntity (strongETag $ show rev) lastMod
+
+                              outputXmlPage tree entityToXHTML
+
+
+entityToXHTML :: ArrowXml a => a XmlTree XmlTree
+entityToXHTML
+    = eelem "/"
+      += ( eelem "html"
+           += sattr "xmlns" "http://www.w3.org/1999/xhtml"
+           += ( eelem "head"
+                += ( eelem "title"
+                     += getXPathTreesInDoc "/page/@site/text()"
+                     += txt " - "
+                     += getXPathTreesInDoc "/page/@name/text()"
+                   )
+                += ( eelem "base"
+                     += attr "href"
+                            ( getXPathTreesInDoc "/page/@baseURI/text()" )
+                   )
+                += ( eelem "link"
+                     += sattr "rel"  "stylesheet"
+                     += sattr "type" "text/css"
+                     += attr "href"
+                            ( txt "./object/"
+                              <+>
+                              getXPathTreesInDoc "/page/@styleSheet/text()"
+                              >>>
+                              getText
+                              >>>
+                              arr encodePageName
+                              >>>
+                              mkText
+                            )
+                   )
+              )
+           += ( eelem "body"
+                += ( eelem "div"
+                     += sattr "class" "header"
+                   )
+                += ( eelem "div"
+                     += sattr "class" "center"
+                     += ( eelem "div"
+                          += sattr "class" "title"
+                        )
+                     += ( eelem "div"
+                          += sattr "class" "body"
+                          += ( getXPathTreesInDoc "/page/content"
+                               `guards`
+                               getXPathTreesInDoc "/page/content/text()" -- FIXME
+                             )
+                          += ( getXPathTreesInDoc "/page/object"
+                               `guards`
+                               eelem "object"
+                               += attr "data"
+                                      ( getXPathTreesInDoc "/page/object/@data/text()" )
+                             )
+                        )
+                   )
+                += ( eelem "div"
+                     += sattr "class" "footer"
+                   )
+                += ( eelem "div"
+                     += sattr "class" "left side-bar"
+                     += ( eelem "div"
+                          += sattr "class" "content"
+                        )
+                   )
+                += ( eelem "div"
+                     += sattr "class" "right side-bar"
+                     += ( eelem "div"
+                          += sattr "class" "content"
+                        )
+                   )
+              )
+         )
index 7a0d0c212997aef4a51f619678ee803c1823d501..1abace0ac17453e210c87b284cb56eda4be73282 100644 (file)
@@ -12,6 +12,7 @@ module Rakka.Storage
     where
 
 import           Control.Arrow.ArrowIO
+import           Control.Monad.Trans
 import           Rakka.Page
 import           Rakka.Storage.DefaultPage
 import           Subversion.Types
@@ -20,16 +21,16 @@ import           Subversion.Types
 data Storage = Storage -- FIXME
 
 
-mkStorage :: IO Storage -- FIXME
-mkStorage = return Storage
+mkStorage :: Storage -- FIXME
+mkStorage = Storage
 
 
-getPage :: Storage -> PageName -> IO (Maybe Page)
+getPage :: MonadIO m => Storage -> PageName -> m (Maybe Page)
 getPage sto name
-    = loadDefaultPage name -- FIXME
+    = liftIO $ loadDefaultPage name -- FIXME
 
 
-putPage :: Storage -> Maybe RevNum -> Page -> IO ()
+putPage :: MonadIO m => Storage -> Maybe RevNum -> Page -> m ()
 putPage sto oldRev page
     = error "FIXME: not implemented"
 
index 9cdaf45afed2152cc8b37b7753e985dab48a1461..5362cc7d33771cd3a8c5ec89c6760a7c6ebe61cf 100644 (file)
@@ -3,11 +3,13 @@ module Rakka.Storage.DefaultPage
     )
     where
 
-import qualified Codec.Binary.Base64.String as B64
+import qualified Codec.Binary.Base64 as B64
 import           Control.Arrow
 import           Control.Arrow.ArrowIO
 import           Control.Arrow.ArrowList
-import qualified Data.ByteString.Lazy.Char8 as L8
+import qualified Data.ByteString.Lazy as L
+import           Data.Encoding
+import           Data.Encoding.UTF8
 import           Paths_Rakka -- Cabal が用意する。
 import           Rakka.Page
 import           Rakka.Utils
@@ -23,13 +25,13 @@ import           Text.XML.HXT.DOM.XmlKeywords
 
 loadDefaultPage :: PageName -> IO (Maybe Page)
 loadDefaultPage pageName
-    -- ./data/Foo を探した後、Cabal で defaultPages/Foo を探す。
-    = do let pagePath = encodePageName pageName
-         isInDataDir <- doesFileExist ("./data/" ++ pagePath)
+    -- ./defaultPages/Foo を探した後、Cabal で defaultPages/Foo を探す。
+    = do let pagePath = "defaultPages/" ++ encodePageName pageName
+         isInDataDir <- doesFileExist pagePath
          if isInDataDir then
-             return . Just =<< loadPageFile pageName ("./data/" ++ pagePath)
+             return . Just =<< loadPageFile pageName pagePath
            else
-             do fpath       <- getDataFileName ("defaultPages/" ++ pagePath)
+             do fpath       <- getDataFileName pagePath
                 isInstalled <- doesFileExist fpath
                 if isInstalled then
                     return . Just =<< loadPageFile pageName fpath
@@ -79,7 +81,7 @@ parseEntity
     -> do mimeType <- (getXPathTreesInDoc "/page/@type/text()" >>> getText
                        >>> arr read) -< tree
 
-          isTheme  <- (maybeA (getXPathTreesInDoc "/page/@type/text()" >>> getText)
+          isTheme  <- (maybeA (getXPathTreesInDoc "/page/@isTheme/text()" >>> getText)
                        >>> defaultTo "no"
                        >>> parseYesOrNo) -< tree
           isFeed   <- (maybeA (getXPathTreesInDoc "/page/@isFeed/text()" >>> getText)
@@ -102,12 +104,13 @@ parseEntity
                                &&&
                                getAttrValue0 "page")) -< tree
 
-          textData   <- maybeA (getXPathTreesInDoc "/page/textData"   >>> getText) -< tree
-          binaryData <- maybeA (getXPathTreesInDoc "/page/binaryData" >>> getText) -< tree
+          textData   <- maybeA (getXPathTreesInDoc "/page/textData/text()"   >>> getText) -< tree
+          binaryData <- maybeA (getXPathTreesInDoc "/page/binaryData/text()" >>> getText) -< tree
 
-          let content = case (textData, binaryData) of
-                          (Just text, _          ) -> L8.pack text
-                          (_        , Just binary) -> L8.pack $ B64.decode binary
+          let (isBinary, content)
+                  = case (textData, binaryData) of
+                      (Just text, _          ) -> (False, encodeLazy UTF8 text      )
+                      (_        , Just binary) -> (True , L.pack $ B64.decode binary)
 
           returnA -< Entity {
                         pageName      = name
@@ -116,6 +119,7 @@ parseEntity
                       , pageIsFeed    = isFeed
                       , pageIsLocked  = isLocked
                       , pageIsBoring  = isBoring
+                      , pageIsBinary  = isBinary
                       , pageRevision  = Nothing
                       , pageLastMod   = lastMod
                       , pageSummary   = summary
diff --git a/Rakka/SystemConfig.hs b/Rakka/SystemConfig.hs
new file mode 100644 (file)
index 0000000..ea7e370
--- /dev/null
@@ -0,0 +1,87 @@
+module Rakka.SystemConfig
+    ( SystemConfig
+    , SysConfValue(..)
+
+    , mkSystemConfig -- private
+
+    , getSysConf
+    , getSysConfA
+    )
+    where
+
+import           Control.Arrow.ArrowIO
+import           Control.Monad.Trans
+import qualified Data.ByteString.Char8 as C8
+import           Data.Maybe
+import           Network
+import qualified Network.HTTP.Lucu.Config as LC
+import           Network.URI
+
+
+data SystemConfig = SystemConfig {
+      scLucuConf :: !LC.Config
+    }
+
+
+data SysConfValue
+    = SiteName String
+    | BaseURI URI
+    | StyleSheet String
+
+
+mkSystemConfig :: LC.Config -> SystemConfig
+mkSystemConfig = SystemConfig
+
+
+getSysConf :: MonadIO m => SystemConfig -> SysConfValue -> m SysConfValue
+getSysConf sc key
+    = liftIO $ sysConfDefault sc key -- FIXME
+
+
+getSysConfA :: ArrowIO a => SystemConfig -> SysConfValue -> a b SysConfValue
+getSysConfA = (arrIO0 .) . getSysConf
+
+
+{- paths -}
+sysConfPath :: SysConfValue -> FilePath
+sysConfPath (SiteName   _) = "/siteName"
+sysConfPath (BaseURI    _) = "/baseURI"
+sysConfPath (StyleSheet _) = "/styleSheet"
+
+
+{- marshalling -}
+marshalSysConf :: SysConfValue -> String
+marshalSysConf (SiteName   name) = name
+marshalSysConf (BaseURI    uri ) = uriToString id uri ""
+marshalSysConf (StyleSheet name) = name
+
+
+{- unmarshalling -}
+unmarshalSysConf :: SysConfValue -> String -> SysConfValue
+unmarshalSysConf (SiteName   _) name = SiteName name
+unmarshalSysConf (BaseURI    _) uri  = BaseURI $ fromJust $ parseURI uri
+unmarshalSysConf (StyleSheet _) name = StyleSheet name
+
+
+{- getting default value -}
+sysConfDefault :: SystemConfig -> SysConfValue -> IO SysConfValue
+
+sysConfDefault _ (SiteName _)
+    = return $ SiteName "Rakka"
+
+sysConfDefault sc (BaseURI _)
+    = do let conf = scLucuConf sc
+             host = C8.unpack $ LC.cnfServerHost conf
+             port = case LC.cnfServerPort conf of
+                      PortNumber num -> fromIntegral num
+             
+             defaultURI
+                  = "http://" ++ host ++
+                    (if port == 80
+                     then ""
+                     else ':' : show port) ++ "/"
+
+         return $ BaseURI $ fromJust $ parseURI defaultURI
+
+sysConfDefault _ (StyleSheet _)
+    = return $ StyleSheet "StyleSheet/Default"
index 4da609cd48b0baf42d015c3975f2644a2190f2da..92f3b1232f51eacb51cdddefeaa15c6db36258db 100644 (file)
@@ -1,5 +1,6 @@
 module Rakka.Utils
-    ( parseYesOrNo
+    ( yesOrNo
+    , parseYesOrNo
     , maybeA
     , defaultTo
     , deleteIfEmpty
@@ -13,6 +14,11 @@ import           System.Time
 import           Text.Printf
 
 
+yesOrNo :: Bool -> String
+yesOrNo True  = "yes"
+yesOrNo False = "no"
+
+
 parseYesOrNo :: ArrowChoice a => a String Bool
 parseYesOrNo 
     = proc str -> do case str of
similarity index 65%
rename from defaultPages/Main_Page
rename to defaultPages/MainPage
index 1acd8ae5f8351b13fc99ba64db8a49ea1bed0771..3da51be5986828205af85158de83d200c32881f2 100644 (file)
@@ -2,8 +2,5 @@
 <page xmlns="http://cielonegro.org/schema/Rakka/Page/1.0"
       type="text/x-rakka"
       isBoring="yes">
-
-  <textData>
-    This is the main page. Hello, world!
-  </textData>
-</page>
\ No newline at end of file
+  <textData>This is the main page. Hello, world!</textData>
+</page>
diff --git a/defaultPages/StyleSheet/Default b/defaultPages/StyleSheet/Default
new file mode 100644 (file)
index 0000000..b01806f
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<page xmlns="http://cielonegro.org/schema/Rakka/Page/1.0"
+      type="text/css"
+      isBoring="yes"
+      isTheme="yes">
+  <textData>
+* {
+    padding: 0;
+    margin: 0;
+
+    list-style-type: none;
+}
+
+body {
+    background-color: white;
+}
+
+.side-bar ul, .side-bar ol {
+    margin-top: 0.4em;
+}
+
+.side-bar li + li {
+    margin-top: 0.2em;
+}
+
+.side-bar ul + h1 {
+    margin-top: 1.2em;
+}
+</textData>
+</page>