{-# LANGUAGE CPP #-} -- GIMP Toolkit (GTK) Binding for Haskell: binding to libgnomevfs -*-haskell-*- -- -- Author : Peter Gavin -- Created: 1-Apr-2007 -- -- Copyright (c) 2007 Peter Gavin -- -- This library is free software: you can redistribute it and/or -- modify it under the terms of the GNU Lesser General Public License -- as published by the Free Software Foundation, either version 3 of -- the License, or (at your option) any later version. -- -- This library is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public -- License along with this program. If not, see -- . -- -- GnomeVFS, the C library which this Haskell library depends on, is -- available under LGPL Version 2. The documentation included with -- this library is based on the original GnomeVFS documentation, -- Copyright (c) 2001 Seth Nickell . The -- documentation is covered by the GNU Free Documentation License, -- version 1.2. -- -- | Maintainer : gtk2hs-devel@lists.sourceforge.net -- Stability : alpha -- Portability : portable (depends on GHC) module System.Gnome.VFS.URI ( -- * Types URI, ToplevelURI, TextURI, URIHideOptions(..), -- * Operations uriFromString, uriResolveRelative, #if GNOME_VFS_CHECK_VERSION(2,16,0) uriResolveSymbolicLink, #endif uriAppendString, uriAppendPath, uriAppendFileName, uriToString, uriIsLocal, uriHasParent, uriGetParent, uriGetToplevel, uriGetHostName, uriGetScheme, uriGetHostPort, uriGetUserName, uriGetPassword, uriSetHostName, uriSetHostPort, uriSetUserName, uriSetPassword, uriEqual, uriIsParent, uriGetPath, uriGetFragmentIdentifier, uriExtractDirname, uriExtractShortName, uriExtractShortPathName, uriListParse, uriMakeFullFromRelative ) where import Control.Monad (liftM) {#import System.Gnome.VFS.Marshal#} -- {#import System.Gnome.VFS.Types#} {#import System.Gnome.VFS.BasicTypes#} import System.Glib.FFI import System.Glib.UTFString {#import System.Glib.GList#} import System.IO (FilePath) {# context lib = "gnomevfs" prefix = "gnome_vfs" #} -- | Create a new 'URI' from @textURI@. Unsupported and unsafe -- methods are not allowed and will result in 'Nothing' being -- returned. URL transforms are allowed. uriFromString :: TextURI -> Maybe URI uriFromString textURI = unsafePerformIO $ withUTFString textURI {# call uri_new #} >>= maybePeek newURI -- | Create a new uri from @relativeReference@, relative to -- @base@. The resolution algorithm in some aspects follows RFC -- 2396, section 5.2, but is not identical due to some extra -- assumptions GnomeVFS makes about URIs. -- -- If relative_reference begins with a valid scheme identifier -- followed by @\':\'@, it is assumed to refer to an absolute URI, and a -- 'URI' is created from it using 'uriFromString'. -- -- Otherwise, depending on its precise syntax, it inherits some -- aspects of the parent URI, but the parents' fragment and query -- components are ignored. -- -- If relative_reference begins with @\"\/\/\"@, it only inherits the -- base scheme; if it begins with @\'\/\'@ (i.e., it is an absolute -- path reference), it inherits everything except the base -- path. Otherwise, it replaces the part of base after the last -- @\'\/\'@. -- -- Note: This function should not be used by application authors -- unless they expect very distinct semantics. Instead, authors -- should use 'uriAppendFileName', 'uriAppendPath', -- 'uriAppendString' or 'uriResolveSymbolicLink'. uriResolveRelative :: URI -- ^ @base@ - the base URI -> String -- ^ @relativeReference@ - a string -- representing a possibly relative -- URI reference -> Maybe URI -- ^ a new URI referring to -- @relativeReference@, or 'Nothing' -- if @relativeReference@ is -- malformed. uriResolveRelative base relativeReference = unsafePerformIO $ (withUTFString relativeReference $ {# call uri_resolve_relative #} base) >>= maybePeek newURI #if GNOME_VFS_CHECK_VERSION(2,16,0) -- | Create a new uri from @symbolicLink@, relative to @base@. -- -- If symbolic_link begins with a @\'\/\'@, it replaces the path of base, -- otherwise it is appended after the last @\'\/\'@ character of base. uriResolveSymbolicLink :: URI -> String -> Maybe URI uriResolveSymbolicLink base symbolicLink = unsafePerformIO $ (withUTFString symbolicLink $ {# call uri_resolve_symbolic_link #} base) >>= maybePeek newURI #endif -- | Create a new URI obtained by appending @uriFragment@ to @uri@. This -- will take care of adding an appropriate directory separator -- between the end of @uri@ and the start of @uriFragment@ if -- necessary. -- -- This function will return 'Nothing' if the resulting URI is not -- valid. uriAppendString :: URI -- ^ @uri@ - the base URI -> String -- ^ @uriFragment@ - an escaped URI fragment -> Maybe URI -- ^ the new URI uriAppendString uri uriFragment = unsafePerformIO $ (withUTFString uriFragment $ {# call uri_append_string #} uri) >>= maybePeek newURI -- | Create a new uri obtained by appending @path@ to @uri@. This will -- take care of adding an appropriate directory separator between -- the end of @uri@ and the start of @path@ if necessary, as well as -- escaping @path@ as necessary. -- -- This function will return 'Nothing' if the resulting URI is not -- valid. uriAppendPath :: URI -- ^ @uri@ - the base URI -> FilePath -- ^ @path@ - a non-escaped file path -> Maybe URI -- ^ the new URI uriAppendPath uri path = unsafePerformIO $ (withUTFString path $ {# call uri_append_path #} uri) >>= maybePeek newURI -- | Create a new URI obtained by appending @fileName@ to @uri@. This -- will take care of adding an appropriate directory separator -- between the end of @uri@ and the start of @fileName@ if -- necessary. @fileName@ might, for instance, be the result of a call -- to 'System.Posix.Directory.readDirStream'. -- -- This function will return 'Nothing' if the resulting URI is not -- valid. uriAppendFileName :: URI -> FilePath -> Maybe URI uriAppendFileName uri fileName = unsafePerformIO $ (withUTFString fileName $ {# call uri_append_file_name #} uri) >>= maybePeek newURI -- | Translate @uri@ into a printable string. The string will not -- contain the URI elements specified by @hideOptions@. -- -- A @file:@ URI on Win32 might look like -- @file:\/\/\/x:\/foo\/bar.txt@. Note that the part after -- @file:\/\/@ is not a legal file name, you need to remove the @\/@ -- in front of the drive letter. This function does that -- automatically if @hideOptions@ specifies that the toplevel -- method, user name, password, host name and host port should be -- hidden. -- -- On the other hand, a @file:@ URI for a UNC path looks like -- @file:\/\/\/\/server\/share\/foo\/bar.txt@, and in that case the part -- after @file:\/\/@ is the correct file name. uriToString :: URI -- ^ @uri@ - a URI -> URIHideOptions -- ^ @hideOptions@ - the URI elements that should not be included in the resulting string -> TextURI -- ^ the resulting string uriToString uri hideOptions = unsafePerformIO $ ({# call uri_to_string #} uri $ cFromEnum hideOptions) >>= readUTFString -- | Check if @uri@ is a local URI. Note that the return value of this -- function entirely depends on the method associated with -- the URI. It is up to the method author to distinguish between -- remote URIs and URIs referring to entities on the local computer. -- -- Warning, this can be slow, as it does I\/O to detect things like -- NFS mounts. uriIsLocal :: URI -- ^ @uri@ - -> IO Bool -- ^ 'True' if @uri@ is local, 'False' otherwise uriIsLocal uri = liftM toBool $ {# call uri_is_local #} uri -- | Check whether @uri@ has a parent or not. uriHasParent :: URI -- ^ @uri@ - -> Bool -- ^ 'True' if @uri@ has a parent, 'False' otherwise uriHasParent uri = unsafePerformIO $ liftM toBool $ {# call uri_has_parent #} uri -- | Retrieve @uri@'s parent URI. uriGetParent :: URI -- ^ @uri@ - -> Maybe URI -- ^ the parent URI, or 'Nothing' if @uri@ has no parent uriGetParent uri = unsafePerformIO $ {# call uri_get_parent #} uri >>= maybePeek newURI -- | Retrieve @uri@'s toplevel URI. uriGetToplevel :: URI -- ^ @uri@ - -> ToplevelURI -- ^ the toplevel URI uriGetToplevel uri = unsafePerformIO $ {# call uri_get_toplevel #} uri >>= newToplevelURI -- | Retrieve the hostname for @uri@. uriGetHostName :: URI -- ^ @uri@ - -> Maybe String -- ^ the hostname, or 'Nothing' if @uri@ has no hostname uriGetHostName uri = unsafePerformIO $ {# call uri_get_host_name #} uri >>= (maybePeek peekUTFString) -- | Retrieve the scheme for @uri@. uriGetScheme :: URI -- ^ @uri@ - -> Maybe String -- ^ the scheme, or 'Nothing' if @uri@ has no scheme uriGetScheme uri = unsafePerformIO $ {# call uri_get_scheme #} uri >>= (maybePeek peekUTFString) -- | Retrieve the host port for @uri@. uriGetHostPort :: URI -- ^ @uri@ - -> Word -- ^ the host port, or @0@ if the default port -- value for the specified toplevel access -- method is used uriGetHostPort uri = unsafePerformIO $ liftM cToEnum $ {# call uri_get_host_port #} uri -- | Retrieve the user name for @uri@. uriGetUserName :: URI -- ^ @uri@ - -> Maybe String -- ^ the user name, or 'Nothing' if @uri@ has no user name uriGetUserName uri = unsafePerformIO $ {# call uri_get_user_name #} uri >>= (maybePeek peekUTFString) -- | Retrieve the password for @uri@. uriGetPassword :: URI -- ^ @uri@ - -> Maybe String -- ^ the password, or 'Nothing' if @uri@ has no password uriGetPassword uri = unsafePerformIO $ {# call uri_get_password #} uri >>= (maybePeek peekUTFString) marshalSet :: (URI -> a -> IO ()) -> URI -> a -> URI marshalSet setAction uri newVal = unsafePerformIO $ do uri <- {# call uri_dup #} uri >>= newURI setAction uri newVal return uri -- | Create a new 'URI' using @uri@, replacing the host name by @hostName@. uriSetHostName :: URI -- ^ @uri@ - -> Maybe String -- ^ @hostName@ - the new hostname -> URI -- ^ the resulting URI uriSetHostName = marshalSet $ \uri hostName -> maybeWith withUTFString hostName $ {# call uri_set_host_name #} uri -- | Create a new 'URI' using @uri@, replacing the host port by @hostPort@. -- -- If @hostPort@ is @0@, use the default port for @uri@'s toplevel -- access method. uriSetHostPort :: URI -- ^ @uri@ - -> Word -- ^ @hostPort@ - the new host port -> URI -- ^ the resulting URI uriSetHostPort = marshalSet $ \uri hostPort -> {# call uri_set_host_port #} uri $ cFromEnum hostPort -- | Create a new 'URI' using @uri@, replacing the user name by @userName@. uriSetUserName :: URI -- ^ @uri@ - -> Maybe String -- ^ @userName@ - the new user name -> URI -- ^ the resulting URI uriSetUserName = marshalSet $ \uri userName -> maybeWith withUTFString userName $ {# call uri_set_user_name #} uri -- | Create a new 'URI' using @uri@, replacing the password by @password@. uriSetPassword :: URI -- ^ @uri@ - -> Maybe String -- ^ @password@ - the new password -> URI -- ^ the resulting URI uriSetPassword = marshalSet $ \uri password -> maybeWith withUTFString password $ {# call uri_set_password #} uri -- | Compare two 'URI's for equality. uriEqual :: URI -- ^ @a@ - -> URI -- ^ @b@ - -> Bool -- ^ 'True' if the URIs are the same, 'False' otherwise. uriEqual a b = unsafePerformIO $ liftM toBool $ {# call uri_equal #} a b -- | Check if @possibleChild@ is contained in @possibleParent@. If -- @recursive@ is 'False', just try the immediate parent; otherwise -- search up through the heirarchy. uriIsParent :: URI -- ^ @possibleParent@ - -> URI -- ^ @possibleChild@ - -> Bool -- ^ @recursive@ - 'True' if parents should be -- checked recursively, 'False' otherwise -> Bool -- ^ 'True' if @possibleChild@ is contained in -- @possibleParent@, otherwise 'False' uriIsParent possibleParent possibleChild recursive = unsafePerformIO $ liftM toBool $ {# call uri_is_parent #} possibleParent possibleChild $ fromBool recursive -- | Retrieve the path name for @uri@. uriGetPath :: URI -- ^ @uri@ - -> Maybe FilePath -- ^ the path name, or 'Nothing' if @uri@ -- has no path name uriGetPath uri = unsafePerformIO $ {# call uri_get_path #} uri >>= (maybePeek peekUTFString) -- | Retrieve the fragment identifier for @uri@. uriGetFragmentIdentifier :: URI -- ^ @uri@ - -> Maybe String -- ^ the fragment identifier, -- or 'Nothing' if @uri@ -- has no fragment -- identifier uriGetFragmentIdentifier uri = unsafePerformIO $ {# call uri_get_fragment_identifier #} uri >>= (maybePeek peekUTFString) -- | Extract the name of the directory in which the file pointed to by -- @uri@ is stored as a string. The string will end with a directory -- separator. uriExtractDirname :: URI -- ^ @uri@ - -> Maybe FilePath -- ^ the directory name, or -- 'Nothing' if @uri@ has no -- directory name uriExtractDirname uri = unsafePerformIO $ {# call uri_extract_dirname #} uri >>= (maybePeek readUTFString) -- | Retrieve base file name for @uri@, ignoring any trailing path -- separators. This matches the XPG definition of basename, but not -- 'System.FilePath.basename'. This is often useful when you want -- the name of something that's pointed to by a URI, and don't care -- whether the uri has a directory or file form. If @uri@ points to -- the root of a domain, returns the host name. If there's no host -- name, returns the path separator. -- -- See also: 'uriExtractShortPathName'. uriExtractShortName :: URI -- ^ @uri@ - -> String -- the unescaped short form of the name uriExtractShortName uri = unsafePerformIO $ {# call uri_extract_short_name #} uri >>= readUTFString -- | Retrieve base file name for @uri@, ignoring any trailing path -- separators. This matches the XPG definition of basename, but not -- 'System.FilePath.basename'. This is often useful when you want -- the name of something that's pointed to by a URI, and don't care -- whether the uri has a directory or file form. If @uri@ points to -- the root of any domain, returns the path separator. -- -- See also: 'uriExtractShortName'. uriExtractShortPathName :: URI -- ^ @uri@ - -> String -- the uriExtractShortPathName uri = unsafePerformIO $ {# call uri_extract_short_path_name #} uri >>= readUTFString -- | Extracts a list of URIs from a standard @text\/uri-list@, such as -- one would get on a drop operation. uriListParse :: String -- ^ @uriList@ - a list of URIs, separated by newlines -> [URI] -- ^ the list of URIs uriListParse uriList = unsafePerformIO $ do uriList <- withUTFString uriList $ \cURIList -> {# call uri_list_parse #} cURIList >>= fromGList sequence $ map newURI uriList -- | Returns a full URI given a full base URI, and a secondary URI -- which may be relative. uriMakeFullFromRelative :: String -- ^ @baseURI@ - -> String -- ^ @relativeURI@ - -> Maybe String -- ^ the resulting URI uriMakeFullFromRelative baseURI relativeURI = unsafePerformIO $ (withUTFString baseURI $ \cBaseURI -> withUTFString relativeURI $ \cRelativeURI -> {# call uri_make_full_from_relative #} cBaseURI cRelativeURI) >>= maybePeek readUTFString