remotestoragefw/webdavaccessplugin/src/rsfwdavaccess.cpp
branchRCL_3
changeset 20 1aa8c82cb4cb
parent 0 3ad9d5175a89
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/remotestoragefw/webdavaccessplugin/src/rsfwdavaccess.cpp	Wed Sep 01 12:15:08 2010 +0100
@@ -0,0 +1,1179 @@
+/*
+* Copyright (c) 2002-2004 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Implements remote access plugin API using WebDAV protocol
+ *
+*/
+
+
+// INCLUDE FILES
+#include "rsfwdavaccess.h"
+#include "rsfwdavfileinfo.h"
+#include "rsfwdavaccesscontext.h"
+#include "rsfwdavtransaction.h"
+#include "mdebug.h"
+
+
+// ============================ MEMBER FUNCTIONS ==============================
+
+void CRsfwDavAccess::ConstructL()
+    {
+    }
+
+CRsfwDavAccess* CRsfwDavAccess::NewL()
+    {
+    CRsfwDavAccess* self = new (ELeave) CRsfwDavAccess;
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+CRsfwDavAccess::~CRsfwDavAccess()
+    {
+    delete iWebDavSession;
+    iDavFileInfos.ResetAndDestroy();
+    iDavAccessContexts.ResetAndDestroy(); 
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::DavFileInfoL
+// Find the file info for the given file name.
+// ----------------------------------------------------------------------------
+//
+CRsfwDavFileInfo* CRsfwDavAccess::DavFileInfoL(const TDesC& aName)
+    {
+    TInt index = DavFileInfoIndexL(aName);
+    if (index != KErrNotFound)
+        {
+        return iDavFileInfos[index];
+        }
+    return NULL;
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::AddDavFileInfo
+// Add a new file info entry.
+// ----------------------------------------------------------------------------
+//
+void CRsfwDavAccess::AddDavFileInfo(CRsfwDavFileInfo* aDavFileInfo)
+    {
+#ifdef _DEBUG
+    TPtrC namePtr;
+    if (aDavFileInfo->Name())
+        {
+        namePtr.Set(*aDavFileInfo->Name());
+        }
+    TPtrC8 lockPtr;
+    if (aDavFileInfo->LockToken())
+        {
+        lockPtr.Set(*aDavFileInfo->LockToken());
+        }
+    DEBUGSTRING16(("Add file info: name='%S'", &namePtr));
+    DEBUGSTRING8(("               lock='%S', time=%d",
+                  &lockPtr,
+                  aDavFileInfo->Timeout()));
+    
+#endif // DEBUG
+    iDavFileInfos.Append(aDavFileInfo);
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::RemoveDavFileInfoL
+// Remove a file info entry.
+// ----------------------------------------------------------------------------
+//
+void CRsfwDavAccess::RemoveDavFileInfoL(const TDesC& aPath)
+    {
+    TInt index = DavFileInfoIndexL(aPath);
+    if (index != KErrNotFound)
+        {
+        CRsfwDavFileInfo* davFileInfo =  iDavFileInfos[index];
+#ifdef _DEBUG
+        TPtrC namePtr;
+        if (davFileInfo->Name())
+            {
+            namePtr.Set(*davFileInfo->Name());
+            }
+        DEBUGSTRING16(("Remove file info: name='%S'", &namePtr));
+#endif // DEBUG
+        iDavFileInfos.Remove(index);
+        delete davFileInfo;
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::SetupL
+// Setup - should be immediately followed by NewL() call.
+// ----------------------------------------------------------------------------
+//
+void CRsfwDavAccess::SetupL(MRsfwRemoteAccessObserver* aRsfwRemoteAccessObserver)
+    {
+    DEBUGSTRING(("DAV: SetupL"));
+    MRsfwConnectionObserver* rsfwConnectionObserver = NULL;
+    if (aRsfwRemoteAccessObserver)
+        {
+        // Cascade remote access observers
+        iRsfwRemoteAccessObserver = aRsfwRemoteAccessObserver;
+        rsfwConnectionObserver = this;
+        }
+    iWebDavSession = CRsfwDavSession::NewL(this, rsfwConnectionObserver);
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::OpenL
+// ----------------------------------------------------------------------------
+//
+TUint CRsfwDavAccess::OpenL(const TUriC& aUri,
+                        const TDesC& /*aFriendlyName*/,
+                        const TDesC& aUserName,
+                        const TDesC& aPassword,
+                        const TDesC& aAuxData,
+                        MRsfwRemoteAccessResponseHandler* aResponseHandler)
+    {
+    if (!aResponseHandler)
+        {
+        User::Leave(KErrArgument);
+        }
+
+    HBufC* url = HBufC::NewLC(KHttpsScheme().Length() +
+                              KMaxServerNameLen +
+                              1 +
+                              KMaxPath);
+    TPtr urlPtr = url->Des();
+
+    TInt portNumber = 0;
+    if (aUri.IsPresent(EUriPort))
+        {
+        TLex portx(aUri.Extract(EUriPort));
+        if (portx.Val(portNumber) != KErrNone)
+            {
+            portNumber = 0;
+            }
+        }
+
+    // Check scheme and map it to port number or vice versa
+    TPtrC scheme;
+    if (aUri.IsPresent(EUriScheme))
+        {
+        scheme.Set(aUri.Extract(EUriScheme));
+        }
+    if (scheme.Length())
+        {
+        if (portNumber == 0)
+            {
+            if (scheme.CompareF(KHttpsScheme) == 0)
+                {
+                portNumber = KHttpsPortNumber;
+                }
+            else
+                {
+                portNumber = KHttpPortNumber;
+                }
+            }
+        }
+    else
+        {
+        if (portNumber == 0)
+            {
+            portNumber = KHttpPortNumber;
+            }
+        if (portNumber == KHttpPortNumber)
+            {
+            scheme.Set(KHttpScheme);
+            }
+        else if (portNumber == KHttpsPortNumber)
+            {
+            scheme.Set(KHttpsScheme);
+            }
+        else
+            {
+            User::Leave(KErrBadName);
+            }
+        }
+        
+    TPtrC rootDirectory;
+    if (aUri.IsPresent(EUriPath))
+        {
+        rootDirectory.Set(aUri.Extract(EUriPath));
+        }
+    iRootDirectory.Copy(rootDirectory);
+    if (!iRootDirectory.Length() ||
+        iRootDirectory[iRootDirectory.Length() - 1] != '/')
+        {
+        // Append trailing '/'
+        iRootDirectory.Append('/');
+        }
+    
+    urlPtr.Copy(scheme);
+    urlPtr.Append(':');
+    urlPtr.Append('/');
+    urlPtr.Append('/');
+    urlPtr.Append(aUri.Extract(EUriHost));
+    // There needs to be a slash between server name and the root dir
+    // (we assume that there cannot be an excess of slash characters)
+    if (urlPtr[urlPtr.Length() - 1] != '/')
+        {
+        if (!iRootDirectory.Length() || (iRootDirectory[0] != '/'))
+            {
+            urlPtr.Append('/');
+            }
+        }
+    urlPtr.Append(iRootDirectory);
+    
+    DEBUGSTRING16(("DAV: OpenL to URL '%S'", &urlPtr));
+    
+    iWebDavSession->OpenL(urlPtr,
+                          portNumber,
+                          aUserName,
+                          aPassword,
+                          aAuxData);
+    CleanupStack::PopAndDestroy(url);
+    return OptionsL(aResponseHandler);
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::GetDirectoryL
+// ----------------------------------------------------------------------------
+//
+TUint CRsfwDavAccess::GetDirectoryL(const TDesC& aPathName,
+                                RPointerArray<CRsfwDirEnt>& aDirEnts,
+                                MRsfwRemoteAccessResponseHandler* aResponseHandler)
+    {
+    // Get the contents of the directory
+    DEBUGSTRING16(("DAV: GetDirectory '%S'", &aPathName));
+
+    // check that arguments are sensible
+    // aPathName might here be null (mounted root directory)
+    if (aPathName.Length() > KMaxPath)
+        {
+        User::Leave(KErrBadName);
+        }
+
+    if (!aResponseHandler)
+        {
+        User::Leave(KErrArgument);
+        }
+
+    CRsfwDavAccessContextPropFindDir* davAccessContextPropFindDir =
+        CRsfwDavAccessContextPropFindDir::NewL(this,
+                                           aResponseHandler,
+                                           aPathName,
+                                           1,
+                                           NULL,
+                                           &aDirEnts);
+    TUint id = AddAccessContext(davAccessContextPropFindDir);
+    davAccessContextPropFindDir->StartL();
+    return id;
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::GetFileL
+// ----------------------------------------------------------------------------
+//
+TUint CRsfwDavAccess::GetFileL(const TDesC& aRemotePathName,
+                           const TDesC& aLocalPathName,
+                           TInt aOffset,
+                           TInt* aLength,
+                           TUint aFlags,
+                           MRsfwRemoteAccessResponseHandler* aResponseHandler)
+    {
+
+#ifdef _DEBUG
+    {
+    TInt length;
+    if (aLength)
+        {
+        length = *aLength;
+        }
+    else
+        {
+        length = 0;
+        }
+    DEBUGSTRING16(("DAV: GetFile rn='%S', ln='%S' (off=%d, len=%d)",
+                   &aRemotePathName,
+                   &aLocalPathName,
+                   aOffset,
+                   length));
+    }
+#endif // DEBUG
+
+    // check that arguments are sensible
+    if (aOffset < 0 ||
+       (aLength && *aLength < 0) ||
+       (!aResponseHandler))
+        {
+        User::Leave(KErrArgument);
+        }
+
+    if ((aLocalPathName.Length() == 0) ||
+        (aLocalPathName.Length() > KMaxPath) ||
+        (aRemotePathName.Length() == 0) ||
+        (aRemotePathName.Length() > KMaxPath))
+        {
+        User::Leave(KErrBadName);
+        }
+
+    CRsfwDavAccessContextGet* davAccessContextGet =
+        CRsfwDavAccessContextGet::NewL(this,
+                                   aResponseHandler,
+                                   aRemotePathName,
+                                   aLocalPathName,
+                                   aOffset,
+                                   aLength,
+                                   aFlags);
+    TUint id = AddAccessContext(davAccessContextGet);
+    davAccessContextGet->StartL();
+    return id;
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::PutFileL
+// ----------------------------------------------------------------------------
+//
+TUint CRsfwDavAccess::PutFileL(const TDesC& aLocalPathName,
+                           const TDesC& aRemotePathName,
+                           const TDesC8& aMimeType,
+                           TInt aOffset,
+                           TInt aLength,
+                           TInt aTotalLength,
+                           MRsfwRemoteAccessResponseHandler* aResponseHandler)
+    {
+    // Copy file to server using PUT,
+    // might require lock token, if the destination file is locked...
+#ifdef _DEBUG
+    {
+    TInt length;
+    if (aLength)
+        {
+        length = aLength;
+        }
+    else
+        {
+        length = 0;
+        }
+    DEBUGSTRING16(("DAV: PutFile ln='%S', rn='%S' (off=%d, len=%d)",
+                   &aLocalPathName,
+                   &aRemotePathName,
+                   aOffset,
+                   length));
+    }
+#endif // DEBUG
+
+    // check that arguments are sensible
+    if (aOffset < 0 ||
+       (aLength < 0) ||
+       (((aOffset + aLength) > aTotalLength) && aTotalLength > 0) ||
+       (!aResponseHandler))
+        {
+        User::Leave(KErrArgument);
+        }
+
+    // note that aLocalPathName can be undefined
+    // (CreateFile calls with null-ptr)
+    if ((aLocalPathName.Length() > KMaxPath) ||
+        (aRemotePathName.Length() == 0) ||
+        (aRemotePathName.Length() > KMaxPath) ||
+        (aMimeType.Length() > KMaxMimeTypeLength))
+        {
+        User::Leave(KErrBadName);
+        }
+
+
+    const HBufC8* lockToken = NULL;
+    CRsfwDavFileInfo *davFileInfo = DavFileInfoL(aRemotePathName);
+    if (davFileInfo)
+        {
+        lockToken = davFileInfo->LockToken();
+        }
+    CRsfwDavAccessContextPut* davAccessContextPut =
+        CRsfwDavAccessContextPut::NewL(this,
+                                   aResponseHandler,
+                                   aLocalPathName,
+                                   aRemotePathName,
+                                   aMimeType,
+                                   aOffset,
+                                   aLength,
+                                   aTotalLength,
+                                   lockToken);
+    TUint id = AddAccessContext(davAccessContextPut);
+    davAccessContextPut->StartL();
+    return id;
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::PutFileL
+// ----------------------------------------------------------------------------
+//
+TUint CRsfwDavAccess::PutFileL(const TDesC& aLocalPathName,
+                           const TDesC& aRemotePathName,
+                           const TDesC8& aMimeType,
+                           MRsfwRemoteAccessResponseHandler* aResponseHandler)
+    {
+    return PutFileL(aLocalPathName,
+                    aRemotePathName,
+                    aMimeType,
+                    0,
+                    NULL,
+                    0,
+                    aResponseHandler);
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::CreateFileL
+// overwriting info not needed in HTTP PUT
+// ----------------------------------------------------------------------------
+//
+TUint CRsfwDavAccess::CreateFileL(const TDesC& aPathName,
+                              TBool /*aOverWriting*/,
+                              MRsfwRemoteAccessResponseHandler* aResponseHandler)
+    {
+    DEBUGSTRING16(("DAV: CreateFile '%S'", &aPathName));
+    // check that arguments are sensible
+    if (!aResponseHandler)
+        {
+        User::Leave(KErrArgument);
+        }
+
+    if ((aPathName.Length() == 0) ||
+       (aPathName.Length() >  KMaxPath))
+        {
+        User::Leave(KErrBadName);
+        }
+        
+    // Could create the file only from LOCK,
+    // but that seems to cause 500 Internal Error with several
+    // Apache servers...
+    TPtrC null;
+    return PutFileL(null, aPathName, KTextPlain, 0, NULL, 0, aResponseHandler);
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::MakeDirectoryL
+// ----------------------------------------------------------------------------
+//
+TUint CRsfwDavAccess::MakeDirectoryL(
+    const TDesC& aPathName,
+    MRsfwRemoteAccessResponseHandler* aResponseHandler)
+    {
+    DEBUGSTRING16(("DAV: MakeDirectory", &aPathName));
+
+    // check that arguments are sensible
+    if (!aResponseHandler)
+        {
+        User::Leave(KErrArgument);
+        }
+
+    if ((aPathName.Length() == 0) ||
+       (aPathName.Length() >  KMaxPath))
+        {
+        User::Leave(KErrBadName);
+        }
+
+    CRsfwDavAccessContextMkDir* davAccessContextMkDir =
+        CRsfwDavAccessContextMkDir::NewL(this,
+                                     aResponseHandler,
+                                     aPathName);
+    TUint id = AddAccessContext(davAccessContextMkDir);
+    davAccessContextMkDir->StartL();
+    return id;
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::DeleteDirectoryL
+// ----------------------------------------------------------------------------
+//
+TUint CRsfwDavAccess::DeleteDirectoryL(
+    const TDesC& aPathName,
+    MRsfwRemoteAccessResponseHandler* aResponseHandler)
+    {
+    DEBUGSTRING16(("DAV: DeleteDirectory '%S'", &aPathName));
+
+    // check that arguments are sensible
+    if (!aResponseHandler)
+        {
+        User::Leave(KErrArgument);
+        }
+
+    if ((aPathName.Length() == 0) ||
+       (aPathName.Length() >  KMaxPath))
+        {
+        User::Leave(KErrBadName);
+        }
+
+    CRsfwDavAccessContextDelete* davAccessContextDelete =
+        CRsfwDavAccessContextDelete::NewL(this,
+                                      aResponseHandler,
+                                      aPathName,
+                                      ETrue,
+                                      NULL);
+    TUint id = AddAccessContext(davAccessContextDelete);
+    davAccessContextDelete->StartL();
+    return id;
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::DeleteFileL
+// ----------------------------------------------------------------------------
+//
+TUint CRsfwDavAccess::DeleteFileL(const TDesC& aPathName,
+                              MRsfwRemoteAccessResponseHandler* aResponseHandler)
+    {
+    DEBUGSTRING16(("DAV: DeleteFile '%S'", &aPathName));
+
+    // check that arguments are sensible
+    if (!aResponseHandler)
+        {
+        User::Leave(KErrArgument);
+        }
+
+    if ((aPathName.Length() == 0) ||
+       (aPathName.Length() >  KMaxPath))
+        {
+        User::Leave(KErrBadName);
+        }
+
+    const HBufC8* lockToken = NULL;
+    CRsfwDavFileInfo *davFileInfo = DavFileInfoL(aPathName);
+    if (davFileInfo)
+        {
+        lockToken = davFileInfo->LockToken();
+        }
+    CRsfwDavAccessContextDelete* davAccessContextDelete =
+        CRsfwDavAccessContextDelete::NewL(this,
+                                      aResponseHandler,
+                                      aPathName,
+                                      EFalse,
+                                      lockToken);
+    TUint id = AddAccessContext(davAccessContextDelete);
+    davAccessContextDelete->StartL();
+    return id;
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::RenameL
+// ----------------------------------------------------------------------------
+//
+TUint CRsfwDavAccess::RenameL(const TDesC& aSrcPathName,
+                          const TDesC& aDstPathName,
+                          TBool aOverwrite,
+                          MRsfwRemoteAccessResponseHandler* aResponseHandler)
+    {
+    DEBUGSTRING16(("DAV: Rename '%S' to '%S'", &aSrcPathName, &aDstPathName));
+
+     // check that arguments are sensible
+    if (!aResponseHandler)
+        {
+        User::Leave(KErrArgument);
+        }
+
+    if ((aSrcPathName.Length() == 0) ||
+        (aSrcPathName.Length() >  KMaxPath) ||
+        (aDstPathName.Length() == 0) ||
+        (aDstPathName.Length() >  KMaxPath))
+        {
+        User::Leave(KErrBadName);
+        }
+
+    // lock token for the source file, if the source is locked...
+    const HBufC8* lockToken = NULL;
+    CRsfwDavFileInfo* davFileInfo = DavFileInfoL(aSrcPathName);
+    if (davFileInfo)
+        {
+        lockToken = davFileInfo->LockToken();
+        }
+        
+    
+    // lock token for the destination file, if the destination is locked
+    const HBufC8* destLockToken = NULL;
+    CRsfwDavFileInfo* destDavFileInfo = DavFileInfoL(aDstPathName);
+    if (destDavFileInfo)
+        {
+        destLockToken = destDavFileInfo->LockToken();
+        }
+    
+        
+    CRsfwDavAccessContextMove* davAccessContextMove =
+        CRsfwDavAccessContextMove::NewL(this,
+                                    aResponseHandler,
+                                    aSrcPathName,
+                                    aDstPathName,
+                                    aOverwrite,
+                                    lockToken,
+                                    destLockToken);
+    TUint id = AddAccessContext(davAccessContextMove);
+    davAccessContextMove->StartL();
+    return id;
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::GetDirectoryAttributesL
+// ----------------------------------------------------------------------------
+//
+TUint CRsfwDavAccess::GetDirectoryAttributesL(
+    const TDesC& aPathName,
+    CRsfwDirEntAttr*& aAttr,
+    MRsfwRemoteAccessResponseHandler* aResponseHandler)
+    {
+    DEBUGSTRING16(("DAV: GetDirectoryAttributes of '%S'",
+                   &aPathName));
+
+    // check that arguments are sensible
+    // aPathName might here be null (mounted root directory)
+    if (!aResponseHandler)
+        {
+        User::Leave(KErrArgument);
+        }
+
+    if (aPathName.Length() > KMaxPath)
+        {
+        User::Leave(KErrBadName);
+        }
+
+    CRsfwDavAccessContextPropFindDir* davAccessContextPropFindDir =
+        CRsfwDavAccessContextPropFindDir::NewL(this,
+                                           aResponseHandler,
+                                           aPathName,
+                                           0,
+                                           &aAttr,
+                                           NULL);
+    TUint id = AddAccessContext(davAccessContextPropFindDir);
+    davAccessContextPropFindDir->StartL();
+    return id;
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::GetFileAttributesL
+// ----------------------------------------------------------------------------
+//
+TUint
+CRsfwDavAccess::GetFileAttributesL(const TDesC& aPathName,
+                               CRsfwDirEntAttr*& aAttr,
+                               MRsfwRemoteAccessResponseHandler* aResponseHandler)
+    {
+    DEBUGSTRING16(("DAV: GetFileAttributes of '%S'",
+                   &aPathName));
+
+    // check that arguments are sensible
+    if (!aResponseHandler)
+        {
+        User::Leave(KErrArgument);
+        }
+
+    if ((aPathName.Length() == 0) ||
+       (aPathName.Length() >  KMaxPath))
+        {
+        User::Leave(KErrBadName);
+        }
+
+    CRsfwDavAccessContextPropFindFile* davAccessContextPropFindFile =
+        CRsfwDavAccessContextPropFindFile::NewL(this,
+                                            aResponseHandler,
+                                            aPathName,
+                                            &aAttr);
+    TUint id = AddAccessContext(davAccessContextPropFindFile);
+    davAccessContextPropFindFile->StartL();
+    return id;
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::SetAttributesL
+// ----------------------------------------------------------------------------
+//
+TUint CRsfwDavAccess::SetAttributesL(
+    const TDesC& /* aPathName */,
+    CRsfwDirEntAttr& /* aAttr */,
+    MRsfwRemoteAccessResponseHandler* /* aResponseHandler */)
+    {
+    DEBUGSTRING(("DAV: SetAttributes"));
+    User::Leave(KErrNotSupported);
+    // Not reached
+    return 0;
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::ObtainLockL
+// ----------------------------------------------------------------------------
+//
+TUint CRsfwDavAccess::ObtainLockL(const TDesC& aPathName,
+                              TUint aLockFlags,
+                              TUint& aTimeout,
+                              TDesC8*& aLockToken,
+                              MRsfwRemoteAccessResponseHandler* aResponseHandler)
+    {
+    // check that arguments are sensible
+    if ((!aResponseHandler) ||
+        (aTimeout == 0))
+        {
+        User::Leave(KErrArgument);
+        }
+
+    // CRsfwDavAccess is the place to know about webdab locks
+    // We only try to obtain a lock if the file was opened for writing
+    if ((!(aLockFlags & EFileWrite)) ||
+        (iWebDavSession->WebDavSupportClass() < KDavVersionTwo))
+        {
+        // WebDAV doesn't have read locks
+        aResponseHandler->HandleRemoteAccessResponse(0, KErrNotSupported); 
+        return 0;
+        }
+    
+    if ((aPathName.Length() == 0) ||
+       (aPathName.Length() >  KMaxPath))
+        {
+        User::Leave(KErrBadName);
+        }
+
+    CRsfwDavAccessContextLock* davAccessContextLock =
+        CRsfwDavAccessContextLock::NewL(this,
+                                    aResponseHandler,
+                                    aPathName,
+                                    aLockFlags,
+                                    aTimeout,
+                                    &aLockToken);
+    TUint id = AddAccessContext(davAccessContextLock);
+    davAccessContextLock->StartL();
+    return id;
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::ReleaseLockL
+// ----------------------------------------------------------------------------
+//
+TUint CRsfwDavAccess::ReleaseLockL(const TDesC& aPathName,
+                               MRsfwRemoteAccessResponseHandler* aResponseHandler)
+    {
+    /*
+      Precondition:
+      - File has been at least locked so there must be fileInfo and
+      locktoken for it
+    */
+    // check that arguments are sensible
+    if (!aResponseHandler)
+        {
+        User::Leave(KErrArgument);
+        }
+
+    if ((aPathName.Length() == 0) ||
+       (aPathName.Length() >  KMaxPath))
+        {
+        User::Leave(KErrBadName);
+        }
+           
+    // Must send the Lock Token
+    CRsfwDavFileInfo* davFileInfo = DavFileInfoL(aPathName);
+    if (!davFileInfo)
+        {
+        User::Leave(KErrNotFound);
+        }
+
+    const HBufC8* lockToken = davFileInfo->LockToken();
+    if (!lockToken)
+        {
+        User::Leave(KErrNotFound);
+        }
+    // Prevent further access to lock token
+    davFileInfo->SetFlag(TRsfwDavFileInfoFlags::EUnlockPending);
+
+    CRsfwDavAccessContextUnlock* davAccessContextUnlock =
+        CRsfwDavAccessContextUnlock::NewL(this,
+                                      aResponseHandler,
+                                      aPathName,
+                                      lockToken);
+    TUint id = AddAccessContext(davAccessContextUnlock);
+    davAccessContextUnlock->StartL();
+    return id;
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::RefreshLockL
+// ----------------------------------------------------------------------------
+//
+TUint CRsfwDavAccess::RefreshLockL(const TDesC& aPathName,
+                               TUint& aTimeout,
+                               MRsfwRemoteAccessResponseHandler* aResponseHandler)
+
+    {
+    /*
+      Precondition:
+      - File has been at least locked
+      so there must be fileInfo and locktoken for it
+    */
+    // check that arguments are sensible
+    if ((!aResponseHandler) ||
+        (aTimeout == 0))
+        {
+        User::Leave(KErrArgument);
+        }
+
+    if ((aPathName.Length() == 0) ||
+       (aPathName.Length() >  KMaxPath))
+        {
+        User::Leave(KErrBadName);
+        }
+
+
+    // Must send the Lock Token
+    CRsfwDavFileInfo* davFileInfo = DavFileInfoL(aPathName);
+    if (!davFileInfo)
+        {
+        User::Leave(KErrNotFound);
+        }
+    const HBufC8* lockToken = davFileInfo->LockToken();
+    if (!lockToken)
+        {
+        User::Leave(KErrNotFound);
+        }
+
+    CRsfwDavAccessContextRefreshLock* davAccessContextRefreshLock =
+        CRsfwDavAccessContextRefreshLock::NewL(this,
+                                           aResponseHandler,
+                                           aPathName,
+                                           lockToken,
+                                           aTimeout);
+    TUint id = AddAccessContext(davAccessContextRefreshLock);
+    davAccessContextRefreshLock->StartL();
+    return id;
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::CancelL by ID
+// ----------------------------------------------------------------------------
+//
+void CRsfwDavAccess::Cancel(TUint aId)
+    {
+    TInt i;
+    if (aId)
+        {
+        i = LookupAccessContextByContextId(aId);
+        if (i != KErrNotFound)
+            {
+            CRsfwDavAccessContext* context = iDavAccessContexts[i];
+            // sometimes it may happen that transaction has not been created for 
+            // some context (e.g. if a leave has occured)
+            if (context->WebDavTransaction())
+                {
+                context->WebDavTransaction()->Cancel();
+                }
+            else
+                {
+                iDavAccessContexts.Remove(i);
+                delete context;                
+                }                        
+            }
+        }
+    else
+        {
+        // Cancel all pending transactions.
+        // Note that cancelling one transaction may result in creating the other
+        // e.g. if you cancel PUT, then RELEASE LOCK is generated.
+        // Anyway the purpose here is to 'kill' all of them, even those generated later
+        DEBUGSTRING(("Cancelling all pending transactions..."));
+        while (iDavAccessContexts.Count() > 0)
+            {
+            CRsfwDavAccessContext* context = iDavAccessContexts[0];
+            TUint id = context->Id();
+            Cancel(id);    
+            }
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::CancelL by path
+// ----------------------------------------------------------------------------
+//
+void CRsfwDavAccess::Cancel(TDesC& aTargetPath)
+    {
+    DEBUGSTRING16(("CRsfwDavAccess::Cancel '%S'", &aTargetPath));
+    TInt i;
+    i = LookupAccessContextByPath(aTargetPath);
+    if (i != KErrNotFound)
+        {
+        DEBUGSTRING16(("found transaction....cancelling webdavop %d", 
+                    iDavAccessContexts[i]->WebDavTransaction()->iWebDavOp));
+        iDavAccessContexts[i]->WebDavTransaction()->Cancel();
+        }
+    }
+
+
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::SetLockToken
+// ----------------------------------------------------------------------------
+//
+TInt CRsfwDavAccess::SetLockToken(const TDesC& aPathName,
+                              const TDesC8& aLockToken)
+    {
+    TRAPD(err, SetLockTokenL(aPathName, aLockToken));
+    return err;
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::SetLockTokenL
+// ----------------------------------------------------------------------------
+//
+void CRsfwDavAccess::SetLockTokenL(const TDesC& aPathName,
+                               const TDesC8& aLockToken)
+    {
+    HBufC* path = HBufC::NewLC(iRootDirectory.Length() + KMaxPath + 1);
+    TPtr pathPtr = path->Des();
+    pathPtr.Copy(iRootDirectory);
+    pathPtr.Append(aPathName);
+
+    DEBUGSTRING16(("DAV: setting lock token: path = '%S'", &pathPtr));
+    DEBUGSTRING8(("                        token = '%S'", &aLockToken));
+    
+    if (aLockToken.Length())
+        {
+        CRsfwDavFileInfo* fileInfo = DavFileInfoL(pathPtr);
+        if (fileInfo)
+            {
+            fileInfo->SetLockTokenL(aLockToken);
+            }
+        else 
+            {
+            // new file
+            fileInfo = CRsfwDavFileInfo::NewL();
+            CleanupStack::PushL(fileInfo);
+            fileInfo->SetNameL(pathPtr);
+            fileInfo->SetLockTokenL(aLockToken);
+            CleanupStack::Pop(fileInfo);
+            // Ownership transferred to file info array
+            AddDavFileInfo(fileInfo);
+            }
+        }
+    else
+        {
+        // Remove lock token
+        RemoveDavFileInfoL(pathPtr);
+        }
+
+    CleanupStack::PopAndDestroy(path);
+    }
+
+// ----------------------------------------------------------------------------
+// From MRsfwDavResponseObserver
+// ----------------------------------------------------------------------------
+
+void CRsfwDavAccess::RequestCompleteL(TUint aWebDavTransactionId)
+    {
+    TInt i = LookupAccessContextByTransactionId(aWebDavTransactionId);
+    if (i != KErrNotFound)
+        {
+        CRsfwDavAccessContext* context = iDavAccessContexts[i];
+        DEBUGSTRING(("DAV: Request %d complete", aWebDavTransactionId));
+        context->TransactionCompleteL();
+        if (context->Done())
+            {
+            MRsfwRemoteAccessResponseHandler* responseHandler =
+                context->ResponseHandler();
+            TUint id = context->Id();
+            TInt status = context->Status();
+            iDavAccessContexts.Remove(i);
+            delete context;
+            responseHandler->HandleRemoteAccessResponse(id, status);
+            }
+        }
+    else
+        {
+        DEBUGSTRING(("DAV: Stray request (id=%d) complete",
+                     aWebDavTransactionId));
+        }
+    }
+
+void CRsfwDavAccess::RequestError(TUint aWebDavTransactionId, TInt aStatus)
+    {
+    TInt i = LookupAccessContextByTransactionId(aWebDavTransactionId);
+    if (i != KErrNotFound)
+        {
+        CRsfwDavAccessContext* context = iDavAccessContexts[i];
+        DEBUGSTRING(("DAV: Request %d error %d",
+                     aWebDavTransactionId,
+                     aStatus));
+        context->TransactionError(aStatus);
+        if (context->Done())
+            {
+            MRsfwRemoteAccessResponseHandler* responseHandler =
+                context->ResponseHandler();
+            TUint id = context->Id();
+            TInt status = context->Status();
+            iDavAccessContexts.Remove(i);
+            delete context;
+            responseHandler->HandleRemoteAccessResponse(id, status);
+            }
+        }
+    else
+        {
+        DEBUGSTRING(("DAV: Stray request (id=%d) error",
+                     aWebDavTransactionId));
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::AddAccessContext
+// Add a context entry in the table of currently active contexts.
+// ----------------------------------------------------------------------------
+//
+TUint CRsfwDavAccess::AddAccessContext(CRsfwDavAccessContext* aDavAccessContext)
+    {
+    TUint id = GetNextAccessContextId();
+    DEBUGSTRING(("DAV: Added transaction %d", id));
+    aDavAccessContext->SetId(id);
+    iDavAccessContexts.Append(aDavAccessContext);
+    return id;
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::LookupAccessContextByTransactionId
+// Find an access context for the given WebDAV transaction id.
+// ----------------------------------------------------------------------------
+//
+TInt CRsfwDavAccess::LookupAccessContextByTransactionId(TUint aWebDavTransactionId)
+    {
+    TInt i;
+    for (i = 0; i < iDavAccessContexts.Count(); i++)
+        {
+        if (iDavAccessContexts[i]->WebDavTransactionId() ==
+            aWebDavTransactionId)
+            {
+            return i;
+            }
+        }
+    DEBUGSTRING(("Access context for id %d is missing !!!",
+                 aWebDavTransactionId));
+    return KErrNotFound;
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::LookupAccessContext
+// Find an access context having the given id.
+// ----------------------------------------------------------------------------
+//
+TInt CRsfwDavAccess::LookupAccessContextByContextId(TUint aId)
+    {
+    TInt i;
+    for (i = 0; i < iDavAccessContexts.Count(); i++)
+        {
+        if (iDavAccessContexts[i]->Id() == aId)
+            {
+            return i;
+            }
+        }
+    DEBUGSTRING(("Access context for id %d is missing !!!", aId));
+    return KErrNotFound;
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::LookupAccessContextByPath
+// Find an access context based on the path of the targer file/directory.
+// ----------------------------------------------------------------------------
+//
+TInt CRsfwDavAccess::LookupAccessContextByPath(TDesC& aTargetPath)
+    { 
+    TInt i;
+    for (i = 0; i < iDavAccessContexts.Count(); i++)
+        {
+        if (iDavAccessContexts[i]->TargetPath() == aTargetPath)
+            {
+            return i;
+            }
+        }
+    return KErrNotFound;
+    }
+
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::DavFileInfoIndexL
+// Find the index to file info array for the given file name.
+// ----------------------------------------------------------------------------
+//
+TInt CRsfwDavAccess::DavFileInfoIndexL(const TDesC& aName)
+    {
+    HBufC* path = HBufC::NewLC(iRootDirectory.Length() + KMaxPath + 1);
+    TPtr pathPtr = path->Des();
+    pathPtr.Copy(iRootDirectory);
+    pathPtr.Append(aName);
+
+    DEBUGSTRING16(("Finding file info for '%S'", &pathPtr));
+    TInt index;
+    for (index = 0; index < iDavFileInfos.Count(); index++)
+        {
+        const HBufC* name = iDavFileInfos[index]->Name();
+        if (name)
+            {
+            if (pathPtr.Compare(*name) == 0)
+                {
+                DEBUGSTRING(("info found"));
+                CleanupStack::PopAndDestroy(path);
+                return index;
+                }
+            }
+        }
+    CleanupStack::PopAndDestroy(path);
+    return KErrNotFound;
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::OptionsL
+// Perform an Options query
+// ----------------------------------------------------------------------------
+//
+TUint CRsfwDavAccess::OptionsL(MRsfwRemoteAccessResponseHandler* aResponseHandler)
+    {
+    CRsfwDavAccessContextOptions* davAccessContextOptions =
+        CRsfwDavAccessContextOptions::NewL(this, aResponseHandler);
+    TUint id = AddAccessContext(davAccessContextOptions);
+    davAccessContextOptions->StartL();
+    return id;
+    }
+
+// ----------------------------------------------------------------------------
+// From MRsfwConnectionObserver
+// ----------------------------------------------------------------------------
+
+// ----------------------------------------------------------------------------
+// CRsfwDavAccess::HandleConnectionEventL
+// Perform an Options query
+// ----------------------------------------------------------------------------
+//
+void CRsfwDavAccess::HandleConnectionEventL(TInt aConnectionEvent,
+                                        TAny* /*aArg*/)
+
+    {
+    switch (aConnectionEvent)
+        {
+    case ERsfwConnectionObserverEventConnectionDisconnected:
+        if (iRsfwRemoteAccessObserver)
+            {
+            iRsfwRemoteAccessObserver->
+                HandleRemoteAccessEventL(
+                    ERsfwRemoteAccessObserverEventConnection,
+                    ERsfwRemoteAccessObserverEventConnectionDisconnected,
+                    NULL);
+            }
+        break;
+        
+    case ERsfwConnectionObserverEventConnectionWeaklyConnected:
+        // If we were reacting to link up events, we would do OptionsL(this);
+        break;
+        
+    case ERsfwConnectionObserverEventConnectionStronglyConnected:
+        // If we were reacting to link up events, we would do OptionsL(this);
+        break;
+        
+    default:
+        break;
+        }
+    }
+
+//  End of File