コード例 #1
0
 /// <summary>
 /// Constructor used to rebuild the object without passing extra ref info.
 /// </summary>
 /// <param name="path"></param>
 /// <param name="logicalLockKey"></param>
 /// <param name="userAgent"></param>
 /// <param name="lockscope"></param>
 /// <param name="locktype"></param>
 /// <param name="owner"></param>
 /// <param name="requestedlocktimeout"></param>
 /// <param name="token"></param>
 /// <param name="requestdocument"></param>
 /// <param name="depth"></param>
 /// <param name="expirationDate"></param>
 public WebDaveStoreItemLockInstance(
     Uri path,
     String logicalLockKey,
     String userAgent,
     WebDavLockScope lockscope,
     WebDavLockType locktype,
     string owner,
     string requestedlocktimeout,
     string token,
     XmlDocument requestdocument,
     int depth,
     DateTime?expirationDate)
 {
     Path                = path;
     LogicalLockKey      = logicalLockKey;
     UserAgent           = userAgent;
     LockScope           = lockscope;
     LockType            = locktype;
     Owner               = owner;
     Token               = token;
     RequestDocument     = requestdocument;
     Depth               = depth;
     RequestedTimeout    = requestedlocktimeout;
     this.ExpirationDate = ExpirationDate;
 }
コード例 #2
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="path"></param>
 /// <param name="lockscope"></param>
 /// <param name="locktype"></param>
 /// <param name="owner"></param>
 /// <param name="requestedlocktimeout"></param>
 /// <param name="token"></param>
 /// <param name="requestdocument"></param>
 /// <param name="depth"></param>
 public WebDaveStoreItemLockInstance(Uri path, WebDavLockScope lockscope, WebDavLockType locktype, string owner, ref string requestedlocktimeout, ref string token, XmlDocument requestdocument, int depth)
 {
     Path            = path;
     LockScope       = lockscope;
     LockType        = locktype;
     Owner           = owner;
     Token           = token;
     RequestDocument = requestdocument;
     Token           = token = "urn:uuid:" + Guid.NewGuid();
     Depth           = depth;
     RefreshLock(ref requestedlocktimeout);
 }
コード例 #3
0
        /// <summary>
        /// </summary>
        /// <param name="path"></param>
        /// <param name="lockscope"></param>
        /// <param name="locktype"></param>
        /// <param name="owner"></param>
        /// <param name="requestedlocktimeout"></param>
        /// <param name="token"></param>
        /// <param name="requestdocument"></param>
        /// <param name="depth"></param>
        /// <param name="lockSystem"></param>
        /// <param name="createdate"></param>
        protected WebDavStoreItemLockInstanceBase(string path, WebDavLockScope lockscope, WebDavLockType locktype, string owner, double? requestedlocktimeout, Guid? token, XmlDocument requestdocument, int depth, IWebDavStoreItemLock lockSystem, DateTime? createdate = null)
        {
            Path = path;
            LockScope = lockscope;
            LockType = locktype;
            Owner = owner;
            Token = token;
            RequestDocument = requestdocument;
            Token = token; // token = "urn:uuid:" + Guid.NewGuid();     
            Depth = depth;
            LockSystem = lockSystem;

            if (createdate == null)
                CreateDate = DateTime.Now;
            else
                CreateDate = (DateTime) createdate;

            RequestedLockTimeout = requestedlocktimeout;

            RefreshLock(requestedlocktimeout);
        }
        /// <summary>
        ///     Locks the object passed.
        /// </summary>
        /// <param name="storeItem"></param>
        /// <param name="lockscope"></param>
        /// <param name="locktype"></param>
        /// <param name="lockowner"></param>
        /// <param name="requestedlocktimeout"></param>
        /// <param name="locktoken"></param>
        /// <param name="requestDocument"></param>
        /// <param name="depth"></param>
        /// <returns></returns>
        public override int Lock(IWebDavStoreItem storeItem, WebDavLockScope lockscope, WebDavLockType locktype,
            string lockowner, double? requestedlocktimeout, out Guid? locktoken, XmlDocument requestDocument, int depth)
        {
            locktoken = null;
            try
            {
                var sqlStoreItem = (WebDavSqlStoreItem) storeItem;


                CleanLocks();


                using (OnlineFilesEntities context = new OnlineFilesEntities())
                {
                    WebDavSqlStoreItemLockInstance inst;
                    if (!context.ObjectLockInfoes.Any(d => d.ObjectGuid == sqlStoreItem.ObjectGuid && d.isFolder == sqlStoreItem.IsCollection))
                    {
                        inst = new WebDavSqlStoreItemLockInstance(
                            PrincipleFactory.Instance.GetPrinciple(FromType.WebDav).UserProfile,
                            storeItem.ItemPath,
                            lockscope, locktype, lockowner,
                            requestedlocktimeout,
                            null, requestDocument, depth, this);

                        locktoken = CreateSqlLock(ref inst, sqlStoreItem);

                        return (int) HttpStatusCode.OK;
                    }
                    switch (lockscope)
                    {
                        case WebDavLockScope.Exclusive:
//#if DEBUG
//                            WebDavServer.Log.Debug("Lock Creation Failed (Exclusive), URI already has a lock.");
//#endif

                            return 423;
                        case WebDavLockScope.Shared:
                            if (context.ObjectLockInfoes.Any(d =>
                                d.ObjectGuid == sqlStoreItem.ObjectGuid &&
                                d.isFolder == sqlStoreItem.IsCollection &&
                                d.LockScope == (int) WebDavLockScope.Exclusive))
                            {
//#if DEBUG
//                                WebDavServer.Log.Debug("Lock Creation Failed (Shared), URI has exclusive lock.");
//#endif
                                return 423;
                            }
                            break;
                    }

                    //If the scope is shared and all other locks on this uri are shared we are ok, otherwise we fail.
                    //423 (Locked), potentially with 'no-conflicting-lock' precondition code - 
                    //There is already a lock on the resource that is not compatible with the 
                    //requested lock (see lock compatibility table above).

                    //If it gets to here, then we are most likely creating another shared lock on the file.
                    inst = new WebDavSqlStoreItemLockInstance(
                        PrincipleFactory.Instance.GetPrinciple(FromType.WebDav).UserProfile,
                        storeItem.ItemPath, lockscope, locktype, lockowner,
                        requestedlocktimeout, null, requestDocument, depth, this);

                    locktoken = CreateSqlLock(ref inst, sqlStoreItem);
                    return (int) HttpStatusCode.OK;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message + ex.StackTrace);
                throw;
            }
        }
コード例 #5
0
        /// <summary>
        /// Locks the request Path.
        /// </summary>
        /// <param name="path">URI to the item to be locked</param>
        /// <param name="lockscope">The lock Scope used for locking</param>
        /// <param name="locktype">The lock Type used for locking</param>
        /// <param name="lockowner">The owner of the lock</param>
        /// <param name="requestedlocktimeout">The requested timeout</param>
        /// <param name="locktoken">Out parameter, returns the issued token</param>
        /// <param name="requestDocument">the Request Document</param>
        /// <param name="depth">How deep to lock, 0,1, or infinity</param>
        /// <returns></returns>
        public static int Lock(Uri path, WebDavLockScope lockscope, WebDavLockType locktype, string lockowner,
                               ref string requestedlocktimeout, out string locktoken, XmlDocument requestDocument, int depth)
        {
            CleanLocks(path);
            WebDavServer.Log.Info("Lock Requested Timeout:" + requestedlocktimeout);
            locktoken = string.Empty;
            lock (ObjectLocks)
            {
                /*
                 * The table below describes the behavior that occurs when a lock request is made on a resource.
                 * Current State   Shared Lock OK      Exclusive Lock OK
                 * None	            True	            True
                 * Shared Lock      True                False
                 * Exclusive Lock	    False	            False*
                 *
                 * Legend: True = lock may be granted. False = lock MUST NOT be granted. *=It is illegal for a principal to request the same lock twice.
                 *
                 * The current lock state of a resource is given in the leftmost column, and lock requests are listed in the first row. The intersection of a row and column gives the result of a lock request. For example, if a shared lock is held on a resource, and an exclusive lock is requested, the table entry is "false", indicating that the lock must not be granted.
                 */


                //if ObjectLocks doesn't contain the path, then this is a new lock and regardless
                //of whether it is Exclusive or Shared it is successful.
                if (!ObjectLocks.ContainsKey(path))
                {
                    ObjectLocks.Add(path, new List <WebDaveStoreItemLockInstance>());

                    ObjectLocks[path].Add(new WebDaveStoreItemLockInstance(path, lockscope, locktype, lockowner,
                                                                           ref requestedlocktimeout, ref locktoken,
                                                                           requestDocument, depth));

                    WebDavServer.Log.Debug("Created New Lock (" + lockscope + "), URI had no locks.  Timeout:" +
                                           requestedlocktimeout);

                    return((int)HttpStatusCode.OK);
                }

                //The fact that ObjectLocks contains this URI means that there is already a lock on this object,
                //This means the lock fails because you can only have 1 exclusive lock.
                if (lockscope == WebDavLockScope.Exclusive)
                {
                    WebDavServer.Log.Debug("Lock Creation Failed (Exclusive), URI already has a lock.");
                    return(423);
                }

                //If the scope is shared and all other locks on this uri are shared we are ok, otherwise we fail.
                if (lockscope == WebDavLockScope.Shared)
                {
                    if (ObjectLocks[path].Any(itemLock => itemLock.LockScope == WebDavLockScope.Exclusive))
                    {
                        WebDavServer.Log.Debug("Lock Creation Failed (Shared), URI has exclusive lock.");
                        return(423);
                    }
                }
                //423 (Locked), potentially with 'no-conflicting-lock' precondition code -
                //There is already a lock on the resource that is not compatible with the
                //requested lock (see lock compatibility table above).

                //If it gets to here, then we are most likely creating another shared lock on the file.

                #region Create New Lock

                ObjectLocks[path].Add(new WebDaveStoreItemLockInstance(path, lockscope, locktype, lockowner,
                                                                       ref requestedlocktimeout, ref locktoken,
                                                                       requestDocument, depth));

                WebDavServer.Log.Debug("Created New Lock (" + lockscope + "), URI had no locks.  Timeout:" +
                                       requestedlocktimeout);

                #endregion

                return((int)HttpStatusCode.OK);
            }
        }
コード例 #6
0
        /// <summary>
        /// Locks the request Path.
        /// </summary>
        /// <param name="path">URI to the item to be locked</param>
        /// <param name="logicalLockKey">Logical lock key taken from document.</param>
        /// <param name="lockscope">The lock Scope used for locking</param>
        /// <param name="locktype">The lock Type used for locking</param>
        /// <param name="lockowner">The owner of the lock</param>
        /// <param name="userAgent">User agent of the request</param>
        /// <param name="requestedlocktimeout">The requested timeout</param>
        /// <param name="locktoken">Out parameter, returns the issued token</param>
        /// <param name="requestDocument">the Request Document</param>
        /// <param name="depth">How deep to lock, 0,1, or infinity</param>
        /// <returns></returns>
        public static int Lock(
            Uri path,
            String logicalLockKey,
            WebDavLockScope lockscope,
            WebDavLockType locktype,
            string lockowner,
            String userAgent,
            ref string requestedlocktimeout,
            out string locktoken,
            XmlDocument requestDocument,
            int depth)
        {
            LoadAndCleanLocks(path);
            WebDavServer.Log.Debug("Lock Requested Timeout:" + requestedlocktimeout);
            locktoken = string.Empty;
            lock (ObjectLocks)
            {
                /*
                 * The table below describes the behavior that occurs when a lock request is made on a resource.
                 * Current State   Shared Lock OK      Exclusive Lock OK
                 * None	            True	            True
                 * Shared Lock      True                False
                 * Exclusive Lock	    False	            False*
                 *
                 * Legend: True = lock may be granted. False = lock MUST NOT be granted. *=It is illegal for a principal to request the same lock twice.
                 *
                 * The current lock state of a resource is given in the leftmost column, and lock requests are listed in the first row. The intersection of a row and column gives the result of a lock request. For example, if a shared lock is held on a resource, and an exclusive lock is requested, the table entry is "false", indicating that the lock must not be granted.
                 */


                //if ObjectLocks doesn't contain the path, then this is a new lock and regardless
                if (ObjectLocks[path].Count == 0)
                {
                    //Pay attention, we could have a lock in other path with the very same logical key.
                    var logicalKeyLocks = ObjectLocks.Values
                                          .SelectMany(l => l)
                                          .Where(l =>
                                                 l.LogicalLockKey == logicalLockKey &&
                                                 l.Owner != lockowner &&
                                                 l.UserAgent != userAgent)
                                          .ToList();
                    if (logicalKeyLocks.Count > 0)
                    {
                        //we have some logical lock from different user, if we request exclusive, fail
                        if (lockscope == WebDavLockScope.Exclusive)
                        {
                            return(423);
                        }

                        //if lock requested is shared, but anyone of the other has an Exclusive lock fail
                        if (lockscope == WebDavLockScope.Shared &&
                            logicalKeyLocks.Any(l => l.LockScope == WebDavLockScope.Exclusive))
                        {
                            return(423);
                        }
                    }

                    ObjectLocks[path].Add(new WebDaveStoreItemLockInstance(path, logicalLockKey, userAgent, lockscope, locktype, lockowner,
                                                                           ref requestedlocktimeout, ref locktoken,
                                                                           requestDocument, depth));

                    WebDavServer.Log.Debug("Created New Lock ({0}), URI {1} had no locks. Timeout: {2}", lockscope, path, requestedlocktimeout);

                    LockPersister.Persist(path, ObjectLocks[path]);
                    return((int)HttpStatusCode.OK);
                }

                //The fact that ObjectLocks contains this URI means that there is already a lock on this object,
                //This means the lock fails because you can only have 1 exclusive lock.
                if (lockscope == WebDavLockScope.Exclusive)
                {
                    //TODO: Verify, it seems that the windows client issues multiple lock, if the
                    //lock was already issued to the same identity, we can consider the lock to
                    //be a refresh.
                    //Check on useragent is needed to verify that the tool is the very same
                    //TODO: we should also check from IP address of caller to be 100% sure.
                    if (ObjectLocks[path].All(l => l.Owner == lockowner && l.UserAgent == userAgent))
                    {
                        //the same owner requested a lock it it should not happen but windows client
                        //issues multiple lock without issuing a UNLOCK (this happens when it issued a DELETE
                        //probably it assumes that a DELETE also release the LOCK).
                        ObjectLocks[path].Clear(); //clear all old lock,
                    }
                    else
                    {
                        WebDavServer.Log.Debug("Lock Creation Failed (Exclusive), URI {0} already has a lock.", path);
                        return(423);
                    }
                }

                //If the scope is shared and all other locks on this uri are shared we are ok, otherwise we fail.
                if (lockscope == WebDavLockScope.Shared)
                {
                    if (ObjectLocks[path].Any(itemLock => itemLock.LockScope == WebDavLockScope.Exclusive))
                    {
                        WebDavServer.Log.Debug("Lock Creation Failed (Shared), URI has exclusive lock.");
                        return(423);
                    }
                }
                //423 (Locked), potentially with 'no-conflicting-lock' precondition code -
                //There is already a lock on the resource that is not compatible with the
                //requested lock (see lock compatibility table above).

                //If it gets to here, then we are most likely creating another shared lock on the file.

                #region Create New Lock

                ObjectLocks[path].Add(new WebDaveStoreItemLockInstance(path, logicalLockKey, userAgent, lockscope, locktype, lockowner,
                                                                       ref requestedlocktimeout, ref locktoken,
                                                                       requestDocument, depth));

                WebDavServer.Log.Debug("Created New Lock (" + lockscope + "), URI had no locks.  Timeout:" +
                                       requestedlocktimeout);

                #endregion
                LockPersister.Persist(path, ObjectLocks[path]);
                return((int)HttpStatusCode.OK);
            }
        }
コード例 #7
0
        /// <summary>
        ///     Locks the object passed.
        /// </summary>
        /// <param name="storeItem"></param>
        /// <param name="lockscope"></param>
        /// <param name="locktype"></param>
        /// <param name="lockowner"></param>
        /// <param name="requestedlocktimeout"></param>
        /// <param name="locktoken"></param>
        /// <param name="requestDocument"></param>
        /// <param name="depth"></param>
        /// <returns></returns>
        public override int Lock(IWebDavStoreItem storeItem, WebDavLockScope lockscope, WebDavLockType locktype,
                                 string lockowner, double?requestedlocktimeout, out Guid?locktoken, XmlDocument requestDocument, int depth)
        {
            locktoken = null;
            try
            {
                var sqlStoreItem = (WebDavSqlStoreItem)storeItem;


                CleanLocks();


                using (OnlineFilesEntities context = new OnlineFilesEntities())
                {
                    WebDavSqlStoreItemLockInstance inst;
                    if (!context.ObjectLockInfoes.Any(d => d.ObjectGuid == sqlStoreItem.ObjectGuid && d.isFolder == sqlStoreItem.IsCollection))
                    {
                        inst = new WebDavSqlStoreItemLockInstance(
                            PrincipleFactory.Instance.GetPrinciple(FromType.WebDav).UserProfile,
                            storeItem.ItemPath,
                            lockscope, locktype, lockowner,
                            requestedlocktimeout,
                            null, requestDocument, depth, this);

                        locktoken = CreateSqlLock(ref inst, sqlStoreItem);

                        return((int)HttpStatusCode.OK);
                    }
                    switch (lockscope)
                    {
                    case WebDavLockScope.Exclusive:
//#if DEBUG
//                            WebDavServer.Log.Debug("Lock Creation Failed (Exclusive), URI already has a lock.");
//#endif

                        return(423);

                    case WebDavLockScope.Shared:
                        if (context.ObjectLockInfoes.Any(d =>
                                                         d.ObjectGuid == sqlStoreItem.ObjectGuid &&
                                                         d.isFolder == sqlStoreItem.IsCollection &&
                                                         d.LockScope == (int)WebDavLockScope.Exclusive))
                        {
//#if DEBUG
//                                WebDavServer.Log.Debug("Lock Creation Failed (Shared), URI has exclusive lock.");
//#endif
                            return(423);
                        }
                        break;
                    }

                    //If the scope is shared and all other locks on this uri are shared we are ok, otherwise we fail.
                    //423 (Locked), potentially with 'no-conflicting-lock' precondition code -
                    //There is already a lock on the resource that is not compatible with the
                    //requested lock (see lock compatibility table above).

                    //If it gets to here, then we are most likely creating another shared lock on the file.
                    inst = new WebDavSqlStoreItemLockInstance(
                        PrincipleFactory.Instance.GetPrinciple(FromType.WebDav).UserProfile,
                        storeItem.ItemPath, lockscope, locktype, lockowner,
                        requestedlocktimeout, null, requestDocument, depth, this);

                    locktoken = CreateSqlLock(ref inst, sqlStoreItem);
                    return((int)HttpStatusCode.OK);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message + ex.StackTrace);
                throw;
            }
        }
コード例 #8
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="path"></param>
 /// <param name="lockscope"></param>
 /// <param name="locktype"></param>
 /// <param name="owner"></param>
 /// <param name="requestedlocktimeout"></param>
 /// <param name="token"></param>
 /// <param name="requestdocument"></param>
 /// <param name="depth"></param>
 public WebDaveStoreItemLockInstance(Uri path, WebDavLockScope lockscope, WebDavLockType locktype, string owner, ref string requestedlocktimeout, ref string token, XmlDocument requestdocument, int depth)
 {
     Path = path;
     LockScope = lockscope;
     LockType = locktype;
     Owner = owner;
     Token = token;
     RequestDocument = requestdocument;
     Token = token = "urn:uuid:" + Guid.NewGuid();
     Depth = depth;
     RefreshLock(ref requestedlocktimeout);
 }
 public WebDavSqlStoreItemLockInstance(SecurityObject so, string path, WebDavLockScope lockscope, WebDavLockType locktype, string owner, double? requestedlocktimeout, Guid? token, XmlDocument requestdocument, int depth, IWebDavStoreItemLock lockSystem, DateTime? createdate = null)
     : base(path, lockscope, locktype, owner, requestedlocktimeout, token, requestdocument, depth, lockSystem, createdate)
 {
     SoOwner = so;
 }
 public WebDavSqlStoreItemLockInstance(SecurityObject so, string path, WebDavLockScope lockscope, WebDavLockType locktype, string owner, double?requestedlocktimeout, Guid?token, XmlDocument requestdocument, int depth, IWebDavStoreItemLock lockSystem, DateTime?createdate = null)
     : base(path, lockscope, locktype, owner, requestedlocktimeout, token, requestdocument, depth, lockSystem, createdate)
 {
     SoOwner = so;
 }
コード例 #11
0
        /// <summary>
        /// Processes the request.
        /// </summary>
        /// <param name="server">The <see cref="WebDavServer" /> through which the request came in from the client.</param>
        /// <param name="context">The
        /// <see cref="IHttpListenerContext" /> object containing both the request and response
        /// objects to use.</param>
        /// <param name="store">The <see cref="IWebDavStore" /> that the <see cref="WebDavServer" /> is hosting.</param>
        /// <exception cref="WebDAVSharp.Server.Exceptions.WebDavPreconditionFailedException"></exception>
        /// <param name="response"></param>
        /// <param name="request"></param>
        protected override void OnProcessRequest(
            WebDavServer server,
            IHttpListenerContext context,
            IWebDavStore store,
            XmlDocument request,
            XmlDocument response)
        {
            if (!WebDavStoreItemLock.LockEnabled)
            {
                throw new WebDavNotImplementedException("Lock support disabled");
            }

            /***************************************************************************************************
            * Retreive al the information from the request
            ***************************************************************************************************/

            // read the headers
            int    depth      = GetDepthHeader(context.Request);
            string timeout    = GetTimeoutHeader(context.Request);
            string locktoken  = GetLockTokenIfHeader(context.Request);
            int    lockResult = 0;
            // Initiate the XmlNamespaceManager and the XmlNodes
            XmlNamespaceManager manager;
            XmlNode             lockscopeNode, locktypeNode, ownerNode;

            if (string.IsNullOrEmpty(locktoken))
            {
                #region New Lock

                // try to read the body
                try
                {
                    StreamReader reader      = new StreamReader(context.Request.InputStream, Encoding.UTF8);
                    string       requestBody = reader.ReadToEnd();

                    if (!requestBody.Equals("") && requestBody.Length != 0)
                    {
                        request.LoadXml(requestBody);

                        if (request.DocumentElement != null &&
                            request.DocumentElement.LocalName != "prop" &&
                            request.DocumentElement.LocalName != "lockinfo")
                        {
                            WebDavServer.Log.Debug("LOCK method without prop or lockinfo element in xml document");
                        }

                        manager = new XmlNamespaceManager(request.NameTable);
                        manager.AddNamespace("D", "DAV:");
                        manager.AddNamespace("Office", "schemas-microsoft-com:office:office");
                        manager.AddNamespace("Repl", "http://schemas.microsoft.com/repl/");
                        manager.AddNamespace("Z", "urn:schemas-microsoft-com:");

                        // Get the lockscope, locktype and owner as XmlNodes from the XML document
                        lockscopeNode = request.DocumentElement.SelectSingleNode("D:lockscope", manager);
                        locktypeNode  = request.DocumentElement.SelectSingleNode("D:locktype", manager);
                        ownerNode     = request.DocumentElement.SelectSingleNode("D:owner", manager);
                    }
                    else
                    {
                        throw new WebDavPreconditionFailedException();
                    }
                }
                catch (Exception ex)
                {
                    WebDavServer.Log.Warning(ex.Message);
                    throw;
                }

                /***************************************************************************************************
                * Lock the file or folder
                ***************************************************************************************************/

                // Get the parent collection of the item
                IWebDavStoreCollection collection = GetParentCollection(server, store, context.Request.Url);

                WebDavLockScope lockscope = (lockscopeNode.InnerXml.StartsWith("<D:exclusive"))
                    ? WebDavLockScope.Exclusive
                    : WebDavLockScope.Shared;

                //Only lock available at this time is a Write Lock according to RFC
                WebDavLockType locktype = (locktypeNode.InnerXml.StartsWith("<D:write"))
                    ? WebDavLockType.Write
                    : WebDavLockType.Write;

                string userAgent = context.Request.Headers["User-Agent"];

                WindowsIdentity Identity = (WindowsIdentity)Thread.GetData(Thread.GetNamedDataSlot(WebDavServer.HttpUser));

                // Get the item from the collection
                try
                {
                    var    item           = GetItemFromCollection(collection, context.Request.Url);
                    String lockLogicalKey = context.Request.Url.AbsoluteUri;
                    if (item != null)
                    {
                        lockLogicalKey = item.LockLogicalKey;
                    }
                    if (item != null && !item.Lock())
                    {
                        lockResult = 423; //Resource cannot be locked
                    }
                    else
                    {
                        //try acquiring a standard lock,
                        lockResult = WebDavStoreItemLock.Lock(
                            context.Request.Url,
                            lockLogicalKey,
                            lockscope,
                            locktype,
                            Identity.Name,
                            userAgent,
                            ref timeout,
                            out locktoken,
                            request,
                            depth);
                    }
                }
                catch (Exception ex)
                {
                    WebDavServer.Log.Error(String.Format("Error occourred while acquiring lock {0}", context.Request.Url), ex);
                    lockResult = 423; //Resource cannot be locked some exception occurred
                }
                #endregion
            }
            else
            {
                #region Refreshing a lock
                //Refresh lock will ref us back the original XML document which was used to request this lock, from
                //this we will grab the data we need to build the response to the lock refresh request.
                lockResult = WebDavStoreItemLock.RefreshLock(context.Request.Url, locktoken, ref timeout, out request);
                if (request == null)
                {
                    context.SendSimpleResponse(409);
                    return;
                }

                try
                {
                    if (request.DocumentElement != null &&
                        request.DocumentElement.LocalName != "prop" &&
                        request.DocumentElement.LocalName != "lockinfo")
                    {
                        WebDavServer.Log.Debug("LOCK method without prop or lockinfo element in xml document");
                    }

                    manager = new XmlNamespaceManager(request.NameTable);
                    manager.AddNamespace("D", "DAV:");
                    manager.AddNamespace("Office", "schemas-microsoft-com:office:office");
                    manager.AddNamespace("Repl", "http://schemas.microsoft.com/repl/");
                    manager.AddNamespace("Z", "urn:schemas-microsoft-com:");

                    // Get the lockscope, locktype and owner as XmlNodes from the XML document
                    lockscopeNode = request.DocumentElement.SelectSingleNode("D:lockscope", manager);
                    locktypeNode  = request.DocumentElement.SelectSingleNode("D:locktype", manager);
                    ownerNode     = request.DocumentElement.SelectSingleNode("D:owner", manager);
                }
                catch (Exception ex)
                {
                    WebDavServer.Log.Warning(ex.Message);
                    throw;
                }

                #endregion
            }

            /***************************************************************************************************
            * Create the body for the response
            ***************************************************************************************************/

            // Create the basic response XmlDocument
            const string responseXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><D:prop xmlns:D=\"DAV:\"><D:lockdiscovery><D:activelock/></D:lockdiscovery></D:prop>";
            response.LoadXml(responseXml);

            // Select the activelock XmlNode
            XmlNode activelock = response.DocumentElement.SelectSingleNode("D:lockdiscovery/D:activelock", manager);

            // Import the given nodes
            activelock.AppendChild(response.ImportNode(lockscopeNode, true));
            activelock.AppendChild(response.ImportNode(locktypeNode, true));
            activelock.AppendChild(response.ImportNode(ownerNode, true));

            // Add the additional elements, e.g. the header elements

            // The timeout element
            WebDavProperty timeoutProperty = new WebDavProperty("timeout", timeout);// timeout);
            activelock.AppendChild(timeoutProperty.ToXmlElement(response));

            // The depth element
            WebDavProperty depthProperty = new WebDavProperty("depth", (depth == 0 ? "0" : "Infinity"));
            activelock.AppendChild(depthProperty.ToXmlElement(response));

            // The locktoken element
            WebDavProperty locktokenProperty = new WebDavProperty("locktoken", string.Empty);
            XmlElement     locktokenElement  = locktokenProperty.ToXmlElement(response);
            WebDavProperty hrefProperty      = new WebDavProperty("href", locktoken);//"opaquelocktoken:e71d4fae-5dec-22df-fea5-00a0c93bd5eb1");
            locktokenElement.AppendChild(hrefProperty.ToXmlElement(response));
            activelock.AppendChild(locktokenElement);

            // The lockroot element
            WebDavProperty lockRootProperty = new WebDavProperty("lockroot", string.Empty);
            XmlElement     lockRootElement  = lockRootProperty.ToXmlElement(response);
            WebDavProperty hrefRootProperty = new WebDavProperty("href", context.Request.Url.AbsoluteUri);//"lockroot
            lockRootElement.AppendChild(hrefRootProperty.ToXmlElement(response));
            activelock.AppendChild(lockRootElement);

            /***************************************************************************************************
            * Send the response
            ***************************************************************************************************/

            // convert the StringBuilder
            string resp = response.InnerXml;
            if (WebDavServer.Log.IsEnabled(Serilog.Events.LogEventLevel.Debug))
            {
                WebDavServer.Log.Debug(
                    @"Request {0}:{1}:{2}
Request
{3}
Response:
{4}",
                    context.Request.HttpMethod, context.Request.RemoteEndPoint, context.Request.Url,
                    request.Beautify(),
                    response.Beautify());
            }


            byte[] responseBytes = Encoding.UTF8.GetBytes(resp);


            context.Response.StatusCode        = lockResult;
            context.Response.StatusDescription = HttpWorkerRequest.GetStatusDescription(lockResult);

            // set the headers of the response
            context.Response.ContentLength64             = responseBytes.Length;
            context.Response.AdaptedInstance.ContentType = "text/xml";

            // the body
            context.Response.OutputStream.Write(responseBytes, 0, responseBytes.Length);

            context.Response.Close();
        }
コード例 #12
0
 /// <summary>
 /// </summary>
 /// <param name="lockscope"></param>
 /// <param name="locktype"></param>
 /// <param name="lockowner"></param>
 /// <param name="requestedlocktimeout"></param>
 /// <param name="locktoken"></param>
 /// <param name="requestDocument"></param>
 /// <param name="depth"></param>
 /// <param name="storeItem"></param>
 /// <returns></returns>
 public virtual int Lock(IWebDavStoreItem storeItem, WebDavLockScope lockscope, WebDavLockType locktype, string lockowner, double? requestedlocktimeout, out Guid? locktoken, XmlDocument requestDocument, int depth)
 {
     throw new NotImplementedException();
 }
コード例 #13
0
        /// <summary>
        /// Locks the request Path.
        /// </summary>
        /// <param name="path">URI to the item to be locked</param>
        /// <param name="lockscope">The lock Scope used for locking</param>
        /// <param name="locktype">The lock Type used for locking</param>
        /// <param name="lockowner">The owner of the lock</param>
        /// <param name="requestedlocktimeout">The requested timeout</param>
        /// <param name="locktoken">Out parameter, returns the issued token</param>
        /// <param name="requestDocument">the Request Document</param>
        /// <param name="depth">How deep to lock, 0,1, or infinity</param>
        /// <returns></returns>
        public static int Lock(Uri path, WebDavLockScope lockscope, WebDavLockType locktype, string lockowner,
            ref string requestedlocktimeout, out string locktoken, XmlDocument requestDocument, int depth)
        {
            CleanLocks(path);
            WebDavServer.Log.Info("Lock Requested Timeout:" + requestedlocktimeout);
            locktoken = string.Empty;
            lock (ObjectLocks)
            {
                /*
            The table below describes the behavior that occurs when a lock request is made on a resource.
            Current State   Shared Lock OK      Exclusive Lock OK
            None	            True	            True
            Shared Lock     	True            	False
            Exclusive Lock	    False	            False*

            Legend: True = lock may be granted. False = lock MUST NOT be granted. *=It is illegal for a principal to request the same lock twice.

            The current lock state of a resource is given in the leftmost column, and lock requests are listed in the first row. The intersection of a row and column gives the result of a lock request. For example, if a shared lock is held on a resource, and an exclusive lock is requested, the table entry is "false", indicating that the lock must not be granted.            
             */


                //if ObjectLocks doesn't contain the path, then this is a new lock and regardless
                //of whether it is Exclusive or Shared it is successful.
                if (!ObjectLocks.ContainsKey(path))
                {
                    ObjectLocks.Add(path, new List<WebDaveStoreItemLockInstance>());

                    ObjectLocks[path].Add(new WebDaveStoreItemLockInstance(path, lockscope, locktype, lockowner,
                        ref requestedlocktimeout, ref locktoken,
                        requestDocument, depth));

                    WebDavServer.Log.Debug("Created New Lock (" + lockscope + "), URI had no locks.  Timeout:" +
                                           requestedlocktimeout);

                    return (int)HttpStatusCode.OK;
                }

                //The fact that ObjectLocks contains this URI means that there is already a lock on this object,
                //This means the lock fails because you can only have 1 exclusive lock.
                if (lockscope == WebDavLockScope.Exclusive)
                {
                    WebDavServer.Log.Debug("Lock Creation Failed (Exclusive), URI already has a lock.");
                    return 423;
                }

                //If the scope is shared and all other locks on this uri are shared we are ok, otherwise we fail.
                if (lockscope == WebDavLockScope.Shared)
                    if (ObjectLocks[path].Any(itemLock => itemLock.LockScope == WebDavLockScope.Exclusive))
                    {
                        WebDavServer.Log.Debug("Lock Creation Failed (Shared), URI has exclusive lock.");
                        return 423;
                    }
                //423 (Locked), potentially with 'no-conflicting-lock' precondition code - 
                //There is already a lock on the resource that is not compatible with the 
                //requested lock (see lock compatibility table above).

                //If it gets to here, then we are most likely creating another shared lock on the file.

                #region Create New Lock

                ObjectLocks[path].Add(new WebDaveStoreItemLockInstance(path, lockscope, locktype, lockowner,
                    ref requestedlocktimeout, ref locktoken,
                    requestDocument, depth));

                WebDavServer.Log.Debug("Created New Lock (" + lockscope + "), URI had no locks.  Timeout:" +
                                       requestedlocktimeout);

                #endregion

                return (int)HttpStatusCode.OK;
            }
        }
コード例 #14
0
        /// <summary>
        /// Locks the request Path.
        /// </summary>
        /// <param name="path">URI to the item to be locked</param>
        /// <param name="logicalLockKey">Logical lock key taken from document.</param>
        /// <param name="lockscope">The lock Scope used for locking</param>
        /// <param name="locktype">The lock Type used for locking</param>
        /// <param name="lockowner">The owner of the lock</param>
        /// <param name="userAgent">User agent of the request</param>
        /// <param name="requestedlocktimeout">The requested timeout</param>
        /// <param name="locktoken">Out parameter, returns the issued token</param>
        /// <param name="requestDocument">the Request Document</param>
        /// <param name="depth">How deep to lock, 0,1, or infinity</param>
        /// <returns></returns>
        public static int Lock(
            Uri path, 
            String logicalLockKey, 
            WebDavLockScope lockscope, 
            WebDavLockType locktype, 
            string lockowner,
            String userAgent,
            ref string requestedlocktimeout, 
            out string locktoken, 
            XmlDocument requestDocument, 
            int depth)
        {
            LoadAndCleanLocks(path);
            WebDavServer.Log.Debug("Lock Requested Timeout:" + requestedlocktimeout);
            locktoken = string.Empty;
            lock (ObjectLocks)
            {
                /*
            The table below describes the behavior that occurs when a lock request is made on a resource.
            Current State   Shared Lock OK      Exclusive Lock OK
            None	            True	            True
            Shared Lock     	True            	False
            Exclusive Lock	    False	            False*

            Legend: True = lock may be granted. False = lock MUST NOT be granted. *=It is illegal for a principal to request the same lock twice.

            The current lock state of a resource is given in the leftmost column, and lock requests are listed in the first row. The intersection of a row and column gives the result of a lock request. For example, if a shared lock is held on a resource, and an exclusive lock is requested, the table entry is "false", indicating that the lock must not be granted.            
             */


                //if ObjectLocks doesn't contain the path, then this is a new lock and regardless
                if (ObjectLocks[path].Count == 0)
                {
                    //Pay attention, we could have a lock in other path with the very same logical key.
                    var logicalKeyLocks = ObjectLocks.Values
                        .SelectMany(l => l)
                        .Where(l => 
                            l.LogicalLockKey == logicalLockKey && 
                            l.Owner != lockowner &&
                            l.UserAgent != userAgent)
                        .ToList();
                    if (logicalKeyLocks.Count > 0)
                    {
                        //we have some logical lock from different user, if we request exclusive, fail
                        if (lockscope == WebDavLockScope.Exclusive) 
                            return 423;

                        //if lock requested is shared, but anyone of the other has an Exclusive lock fail
                        if (lockscope == WebDavLockScope.Shared &&
                            logicalKeyLocks.Any(l => l.LockScope == WebDavLockScope.Exclusive))
                            return 423;
                    }

                    ObjectLocks[path].Add(new WebDaveStoreItemLockInstance(path,logicalLockKey, userAgent, lockscope, locktype, lockowner,
                        ref requestedlocktimeout, ref locktoken,
                        requestDocument, depth));

                    WebDavServer.Log.DebugFormat("Created New Lock ({0}), URI {1} had no locks. Timeout: {2}", lockscope, path, requestedlocktimeout);

                     LockPersister.Persist(path, ObjectLocks[path]);
                    return (int)HttpStatusCode.OK;
                }

                //The fact that ObjectLocks contains this URI means that there is already a lock on this object,
                //This means the lock fails because you can only have 1 exclusive lock.
                if (lockscope == WebDavLockScope.Exclusive)
                {
                    //TODO: Verify, it seems that the windows client issues multiple lock, if the
                    //lock was already issued to the same identity, we can consider the lock to 
                    //be a refresh.
                    //Check on useragent is needed to verify that the tool is the very same
                    //TODO: we should also check from IP address of caller to be 100% sure.
                    if (ObjectLocks[path].All(l => l.Owner == lockowner && l.UserAgent == userAgent))
                    {
                        //the same owner requested a lock it it should not happen but windows client
                        //issues multiple lock without issuing a UNLOCK (this happens when it issued a DELETE 
                        //probably it assumes that a DELETE also release the LOCK).
                        ObjectLocks[path].Clear(); //clear all old lock, 
                    }
                    else
                    {
                        WebDavServer.Log.DebugFormat("Lock Creation Failed (Exclusive), URI {0} already has a lock.", path);
                        return 423;
                    }
                }

                //If the scope is shared and all other locks on this uri are shared we are ok, otherwise we fail.
                if (lockscope == WebDavLockScope.Shared)
                    if (ObjectLocks[path].Any(itemLock => itemLock.LockScope == WebDavLockScope.Exclusive))
                    {
                        WebDavServer.Log.Debug("Lock Creation Failed (Shared), URI has exclusive lock.");
                        return 423;
                    }
                //423 (Locked), potentially with 'no-conflicting-lock' precondition code - 
                //There is already a lock on the resource that is not compatible with the 
                //requested lock (see lock compatibility table above).

                //If it gets to here, then we are most likely creating another shared lock on the file.

                #region Create New Lock

                ObjectLocks[path].Add(new WebDaveStoreItemLockInstance(path, logicalLockKey, userAgent, lockscope, locktype, lockowner,
                    ref requestedlocktimeout, ref locktoken,
                    requestDocument, depth));

                WebDavServer.Log.Debug("Created New Lock (" + lockscope + "), URI had no locks.  Timeout:" +
                                       requestedlocktimeout);

                #endregion
                LockPersister.Persist(path, ObjectLocks[path]);
                return (int)HttpStatusCode.OK;
            }
        }
コード例 #15
0
        /// <summary>
        /// Processes the request.
        /// </summary>
        /// <param name="context">The
        /// <see cref="IWebDavContext" /> object containing both the request and response
        /// objects to use.</param>
        /// <param name="store">The <see cref="IWebDavStore" /> that the <see cref="WebDavServer" /> is hosting.</param>
        /// <exception cref="WebDAVSharp.Server.Exceptions.WebDavPreconditionFailedException"></exception>
        public void ProcessRequest(IWebDavContext context, IWebDavStore store)
        {
            /***************************************************************************************************
            * Retreive al the information from the request
            ***************************************************************************************************/

            // read the headers
            int    depth     = GetDepthHeader(context.Request);
            string timeout   = GetTimeoutHeader(context.Request);
            string locktoken = GetLockTokenIfHeader(context.Request);
            int    lockResult;
            // Initiate the XmlNamespaceManager and the XmlNodes
            XmlNamespaceManager manager;
            XmlNode             lockscopeNode, locktypeNode, ownerNode;
            XmlDocument         requestDocument = new XmlDocument();

            if (string.IsNullOrEmpty(locktoken))
            {
                #region New Lock
                // try to read the body
                try
                {
                    StreamReader reader      = new StreamReader(context.Request.InputStream, Encoding.UTF8);
                    string       requestBody = reader.ReadToEnd();

                    if (!requestBody.Equals("") && requestBody.Length != 0)
                    {
                        requestDocument.LoadXml(requestBody);

                        if (requestDocument.DocumentElement != null &&
                            requestDocument.DocumentElement.LocalName != "prop" &&
                            requestDocument.DocumentElement.LocalName != "lockinfo")
                        {
                            WebDavServer.Log.Debug("LOCK method without prop or lockinfo element in xml document");
                        }

                        manager = new XmlNamespaceManager(requestDocument.NameTable);
                        manager.AddNamespace("D", "DAV:");
                        manager.AddNamespace("Office", "schemas-microsoft-com:office:office");
                        manager.AddNamespace("Repl", "http://schemas.microsoft.com/repl/");
                        manager.AddNamespace("Z", "urn:schemas-microsoft-com:");

                        // Get the lockscope, locktype and owner as XmlNodes from the XML document
                        lockscopeNode = requestDocument.DocumentElement.SelectSingleNode("D:lockscope", manager);
                        locktypeNode  = requestDocument.DocumentElement.SelectSingleNode("D:locktype", manager);
                        ownerNode     = requestDocument.DocumentElement.SelectSingleNode("D:owner", manager);
                    }
                    else
                    {
                        throw new WebDavPreconditionFailedException();
                    }
                }
                catch (Exception ex)
                {
                    WebDavServer.Log.Warn(ex.Message);
                    throw;
                }


                /***************************************************************************************************
                * Lock the file or folder
                ***************************************************************************************************/


                // Get the parent collection of the item
                IWebDavStoreCollection collection = GetParentCollection(store, context, context.Request.Url);

                WebDavLockScope lockscope = (lockscopeNode.InnerXml.StartsWith("<D:exclusive"))
                    ? WebDavLockScope.Exclusive
                    : WebDavLockScope.Shared;

                //Only lock available at this time is a Write Lock according to RFC
                WebDavLockType locktype = (locktypeNode.InnerXml.StartsWith("<D:write")) ? WebDavLockType.Write : WebDavLockType.Write;

                string lockuser = ownerNode.InnerText;

                WindowsIdentity Identity = (WindowsIdentity)Thread.GetData(Thread.GetNamedDataSlot(Constants.HttpUser));

                lockResult = WebDavStoreItemLock.Lock(context.Request.Url, lockscope, locktype, Identity.Name, ref timeout,
                                                      out locktoken, requestDocument, depth);

                // Get the item from the collection
                try
                {
                    GetItemFromCollection(collection, context.Request.Url);
                }
                catch (Exception)
                {
                    lockResult = (int)HttpStatusCode.Created;
                }
                #endregion
            }
            else
            {
                #region Refreshing a lock
                //Refresh lock will ref us back the original XML document which was used to request this lock, from
                //this we will grab the data we need to build the response to the lock refresh request.
                lockResult = WebDavStoreItemLock.RefreshLock(context.Request.Url, locktoken, ref timeout, out requestDocument);
                if (requestDocument == null)
                {
                    context.SetStatusCode(409);
                    return;
                }

                try
                {
                    if (requestDocument.DocumentElement != null &&
                        requestDocument.DocumentElement.LocalName != "prop" &&
                        requestDocument.DocumentElement.LocalName != "lockinfo")
                    {
                        WebDavServer.Log.Debug("LOCK method without prop or lockinfo element in xml document");
                    }

                    manager = new XmlNamespaceManager(requestDocument.NameTable);
                    manager.AddNamespace("D", "DAV:");
                    manager.AddNamespace("Office", "schemas-microsoft-com:office:office");
                    manager.AddNamespace("Repl", "http://schemas.microsoft.com/repl/");
                    manager.AddNamespace("Z", "urn:schemas-microsoft-com:");

                    // Get the lockscope, locktype and owner as XmlNodes from the XML document
                    lockscopeNode = requestDocument.DocumentElement.SelectSingleNode("D:lockscope", manager);
                    locktypeNode  = requestDocument.DocumentElement.SelectSingleNode("D:locktype", manager);
                    ownerNode     = requestDocument.DocumentElement.SelectSingleNode("D:owner", manager);
                }
                catch (Exception ex)
                {
                    WebDavServer.Log.Warn(ex.Message);
                    throw;
                }

                #endregion
            }

            /***************************************************************************************************
            * Create the body for the response
            ***************************************************************************************************/

            // Create the basic response XmlDocument
            XmlDocument  responseDoc = new XmlDocument();
            const string responseXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><D:prop xmlns:D=\"DAV:\"><D:lockdiscovery><D:activelock/></D:lockdiscovery></D:prop>";
            responseDoc.LoadXml(responseXml);

            // Select the activelock XmlNode
            XmlNode activelock = responseDoc.DocumentElement.SelectSingleNode("D:lockdiscovery/D:activelock", manager);

            // Import the given nodes
            activelock.AppendChild(responseDoc.ImportNode(lockscopeNode, true));
            activelock.AppendChild(responseDoc.ImportNode(locktypeNode, true));
            activelock.AppendChild(responseDoc.ImportNode(ownerNode, true));

            // Add the additional elements, e.g. the header elements

            // The timeout element
            WebDavProperty timeoutProperty = new WebDavProperty("timeout", timeout);// timeout);
            activelock.AppendChild(timeoutProperty.ToXmlElement(responseDoc));

            // The depth element
            WebDavProperty depthProperty = new WebDavProperty("depth", (depth == 0 ? "0" : "Infinity"));
            activelock.AppendChild(depthProperty.ToXmlElement(responseDoc));

            // The locktoken element
            WebDavProperty locktokenProperty = new WebDavProperty("locktoken", string.Empty);
            XmlElement     locktokenElement  = locktokenProperty.ToXmlElement(responseDoc);
            WebDavProperty hrefProperty      = new WebDavProperty("href", locktoken);//"opaquelocktoken:e71d4fae-5dec-22df-fea5-00a0c93bd5eb1");
            locktokenElement.AppendChild(hrefProperty.ToXmlElement(responseDoc));


            activelock.AppendChild(locktokenElement);

            /***************************************************************************************************
            * Send the response
            ***************************************************************************************************/

            // convert the StringBuilder
            string resp          = responseDoc.InnerXml;
            byte[] responseBytes = Encoding.UTF8.GetBytes(resp);

            context.SetStatusCode(lockResult);
            context.Response.StatusDescription = HttpWorkerRequest.GetStatusDescription(lockResult);

            // set the headers of the response
            context.Response.ContentLength64 = responseBytes.Length;
            context.Response.AppendHeader("ContentType", "text/xml");

            // the body
            context.Response.OutputStream.Write(responseBytes, 0, responseBytes.Length);
        }
コード例 #16
0
 /// <summary>
 /// Constructor used to rebuild the object without passing extra ref info.
 /// </summary>
 /// <param name="path"></param>
 /// <param name="logicalLockKey"></param>
 /// <param name="userAgent"></param>
 /// <param name="lockscope"></param>
 /// <param name="locktype"></param>
 /// <param name="owner"></param>
 /// <param name="requestedlocktimeout"></param>
 /// <param name="token"></param>
 /// <param name="requestdocument"></param>
 /// <param name="depth"></param>
 /// <param name="expirationDate"></param>
 public WebDaveStoreItemLockInstance(
      Uri path,
      String logicalLockKey,
      String userAgent,
      WebDavLockScope lockscope,
      WebDavLockType locktype,
      string owner,
      string requestedlocktimeout,
      string token,
      XmlDocument requestdocument,
      int depth,
      DateTime? expirationDate)
 {
     Path = path;
     LogicalLockKey = logicalLockKey;
     UserAgent = userAgent;
     LockScope = lockscope;
     LockType = locktype;
     Owner = owner;
     Token = token;
     RequestDocument = requestdocument;
     Depth = depth;
     RequestedTimeout = requestedlocktimeout;
     this.ExpirationDate = ExpirationDate;
 }