コード例 #1
0
        public override Task <bool> Authorize(WopiRequest wopiRequest)
        {
            try
            {
                if (string.IsNullOrEmpty(wopiRequest.AccessToken))
                {
                    return(Task.FromResult <bool>(false));
                }

                // Get the requested file from Document DB
                var itemId   = new Guid(wopiRequest.ResourceId);
                var wopiFile = DocumentDBRepository <DetailedFileModel> .GetItem("Files", file => file.id == itemId);

                // Check for missing file
                if (wopiFile == null)
                {
                    return(Task.FromResult <bool>(false));
                }

                // Validate the access token
                return(Task.FromResult <bool>(WopiSecurity.ValidateToken(wopiRequest.AccessToken, wopiFile.Container, wopiFile.id.ToString())));
            }
            catch (Exception)
            {
                // Any exception will return false, but should probably return an alternate status codes
                return(Task.FromResult <bool>(false));
            }
        }
コード例 #2
0
        public void ProcessRequestPrivate(IAsyncResult result)
        {
            HttpListener        listener = (HttpListener)result.AsyncState;
            HttpListenerContext context  = listener.EndGetContext(result);

            if (!_authorization.ValidateWopiProofKey(context.Request))
            {
                _errHandler.ReturnServerError(context.Response);
            }
            _processor = new WopiProcessor(_authorization, _errHandler, context.Response);

            WopiRequest requestData = ParseRequest(context.Request);


            switch (requestData.Type)
            {
            case RequestType.CheckFileInfo:
                _processor.HandleCheckFileInfoRequest(requestData);
                break;

            case RequestType.Lock:
                _processor.HandleLockRequest(requestData);
                break;

            case RequestType.Unlock:
                _processor.HandleUnlockRequest(requestData);
                break;

            case RequestType.RefreshLock:
                _processor.HandleRefreshLockRequest(requestData);
                break;

            case RequestType.UnlockAndRelock:
                _processor.HandleUnlockAndRelockRequest(requestData);
                break;

            case RequestType.GetFile:
                _processor.HandleGetFileRequest(requestData);
                break;

            case RequestType.PutFile:
                _processor.HandlePutFileRequest(requestData);
                break;

            case RequestType.PutRelativeFile:
            case RequestType.EnumerateChildren:
            case RequestType.CheckFolderInfo:
            case RequestType.DeleteFile:
            case RequestType.ExecuteCobaltRequest:
            case RequestType.GetRestrictedLink:
            case RequestType.ReadSecureStore:
            case RequestType.RevokeRestrictedLink:
                _errHandler.ReturnUnsupported(context.Response);
                break;

            default:
                _errHandler.ReturnServerError(context.Response);
                break;
            }
        }
コード例 #3
0
        public void HandleUnlockAndRelockRequest(WopiRequest requestData)
        {
            lock (this)
            {
                // userId(user@polihub) will be passed from the policyHub application
                if (!_authorization.ValidateToken(requestData.AccessToken, "user@policyhub", requestData.Id))
                {
                    _errorHandler.ReturnInvalidToken(_response);
                    _response.Close();
                    return;
                }

                if (!File.Exists(requestData.FullPath))
                {
                    _errorHandler.ReturnFileUnknown(_response);
                    _response.Close();
                    return;
                }

                string newLock = requestData.LockId;
                string oldLock = requestData.OldLockId;

                lock (LockInfo.Locks)
                {
                    LockInfo existingLock;
                    if (LockInfo.TryGetLock(requestData.Id, out existingLock))
                    {
                        if (existingLock.Lock == oldLock)
                        {
                            LockInfo.Locks[requestData.Id] = new LockInfo()
                            {
                                DateCreated = DateTime.UtcNow, Lock = newLock
                            };
                            _response.AddHeader(WopiHeaders.Lock, newLock);
                            _response.StatusCode = (int)HttpStatusCode.OK;
                            _errorHandler.ReturnSuccess(_response);
                        }
                        else
                        {
                            _response.AddHeader(WopiHeaders.Lock, existingLock.Lock);
                            _response.AddHeader(WopiHeaders.LockFailureReason, "Lock mismatch/Locked by another interface");
                            _response.StatusCode = (int)HttpStatusCode.Conflict;
                            _errorHandler.ReturnLockMismatch(_response, existingLock.Lock);
                        }
                    }
                    else
                    {
                        _response.AddHeader(WopiHeaders.Lock, newLock);
                        _response.AddHeader(WopiHeaders.LockFailureReason, "File not locked");
                        _response.StatusCode = (int)HttpStatusCode.Conflict;
                        _errorHandler.ReturnLockMismatch(_response, reason: "File not locked");
                    }
                }
                _response.Close();
            }
        }
コード例 #4
0
        public void HandleRefreshLockRequest(WopiRequest requestData)
        {
            lock (this)
            {
                if (!_authorization.ValidateAccess(requestData, writeAccessRequired: true))
                {
                    _errorHandler.ReturnInvalidToken(_response);
                    _response.Close();
                    return;
                }

                if (!File.Exists(requestData.FullPath))
                {
                    _errorHandler.ReturnFileUnknown(_response);
                    _response.Close();
                    return;
                }

                string newLock = requestData.LockId;

                lock (LockInfo.Locks)
                {
                    LockInfo existingLock;
                    if (LockInfo.TryGetLock(requestData.Id, out existingLock))
                    {
                        if (existingLock.Lock == newLock)
                        {

                            existingLock.DateCreated = DateTime.UtcNow;
                            _response.AddHeader(WopiHeaders.Lock, existingLock.Lock);
                            _response.StatusCode = (int)HttpStatusCode.OK;
                            _errorHandler.ReturnSuccess(_response);

                        }
                        else
                        {
                            _errorHandler.ReturnLockMismatch(_response, existingLock.Lock);
                            _response.AddHeader(WopiHeaders.Lock, existingLock.Lock);
                            _response.AddHeader(WopiHeaders.LockFailureReason, "Lock mismatch/Locked by another interface");
                            _response.StatusCode = (int)HttpStatusCode.Conflict;
                        }
                    }
                    else
                    {
                        _errorHandler.ReturnLockMismatch(_response, reason: "File not locked");
                        _response.AddHeader(WopiHeaders.Lock, newLock);
                        _response.AddHeader(WopiHeaders.LockFailureReason, "File not locked");
                        _response.StatusCode = (int)HttpStatusCode.Conflict;

                    }
                }
                _response.Close();
            }
        }
コード例 #5
0
        public void HandleCheckFileInfoRequest(WopiRequest requestData)
        {
            lock (this)
            {
                // userId(user@polihub) will be passed from the policyHub application
                if (!_authorization.ValidateToken(requestData.AccessToken, ConfigurationManager.AppSettings["userId"], requestData.Id))
                {
                    _errorHandler.ReturnInvalidToken(_response);
                    _response.Close();
                    return;
                }

                if (!File.Exists(requestData.FullPath))
                {
                    _errorHandler.ReturnFileUnknown(_response);
                    _response.Close();
                    return;
                }

                try
                {
                    FileInfo          fileInfo  = new FileInfo(requestData.FullPath);
                    ResponseGenerator generator = new ResponseGenerator(fileInfo);

                    if (!fileInfo.Exists)
                    {
                        _errorHandler.ReturnFileUnknown(_response);
                        return;
                    }

                    var memoryStream = new MemoryStream();
                    var json         = new DataContractJsonSerializer(typeof(WopiCheckFileInfo));

                    json.WriteObject(memoryStream, generator.GetFileInfoResponse());
                    memoryStream.Flush();
                    memoryStream.Position = 0;

                    StreamReader streamReader = new StreamReader(memoryStream);
                    var          jsonResponse = Encoding.UTF8.GetBytes(streamReader.ReadToEnd());

                    _response.ContentType     = ConfigurationManager.AppSettings["appJson"];
                    _response.ContentLength64 = jsonResponse.Length;
                    _response.OutputStream.Write(jsonResponse, 0, jsonResponse.Length);
                    _errorHandler.ReturnSuccess(_response);
                }
                catch (UnauthorizedAccessException)
                {
                    _errorHandler.ReturnFileUnknown(_response);
                }
                _response.Close();
            }
        }
コード例 #6
0
        public WopiResponse HandleRefresh()
        {
            var requestData = WopiRequest.ParseRequest(_request);
            var documentId  = Convert.ToInt64(requestData.Id);
            var document    = FB.GetDocument(documentId);

            if (document == null)
            {
                return(new WopiResponse()
                {
                    ResponseType = WopiResponseType.FileUnknown, Message = "File not found"
                });
            }

            var newLock = new LockInfo()
            {
                DateCreated = DateTime.UtcNow, Lock = _request.Headers[WopiHeaders.Lock]
            };

            var currentLockInfo = FB.GetLockInfo(document);
            var currentLock     = !string.IsNullOrEmpty(currentLockInfo)
                ? Newtonsoft.Json.JsonConvert.DeserializeObject <LockInfo>(currentLockInfo)
                : null;

            if (currentLock == null)
            {
                // on refresh, there should already be a lock
                return(new WopiResponse()
                {
                    ResponseType = WopiResponseType.LockMismatch, Message = ""
                });
            }

            lock (currentLock)
            {
                if (currentLock.Lock != newLock.Lock)
                {
                    // trying to lock again with a different lock? YEAH RIGHT
                    return(new WopiResponse()
                    {
                        ResponseType = WopiResponseType.LockMismatch, Message = currentLock.Lock
                    });
                }

                // update the lock (refresh) and return success:
                FB.UpdateLockInfo(document, Newtonsoft.Json.JsonConvert.SerializeObject(newLock));
                return(new WopiResponse()
                {
                    ResponseType = WopiResponseType.Success
                });
            }
        }
コード例 #7
0
        public void HandleUnlockRequest(WopiRequest requestData)
        {
            lock (this)
            {
                // userId(user@polihub) will be passed from the policyHub application
                if (!_authorization.ValidateToken(requestData.AccessToken, ConfigurationManager.AppSettings["userId"], requestData.Id))
                {
                    _errorHandler.ReturnInvalidToken(_response);
                    _response.Close();
                    return;
                }
                if (!File.Exists(requestData.FullPath))
                {
                    _errorHandler.ReturnFileUnknown(_response);
                    _response.Close();
                    return;
                }

                string newLock = requestData.LockId;

                lock (LockInfo.Locks)
                {
                    LockInfo existingLock;
                    if (LockInfo.TryGetLock(requestData.Id, out existingLock))
                    {
                        if (existingLock.Lock == newLock)
                        {
                            LockInfo.Locks.Remove(requestData.Id);
                            _errorHandler.ReturnSuccess(_response);
                            _response.AddHeader(WopiHeaders.Lock, existingLock.Lock);
                            _response.StatusCode = (int)HttpStatusCode.OK;
                        }
                        else
                        {
                            _errorHandler.ReturnLockMismatch(_response, existingLock.Lock);
                            _response.AddHeader(WopiHeaders.Lock, existingLock.Lock);
                            _response.AddHeader(WopiHeaders.LockFailureReason, ConfigurationManager.AppSettings["lockMismatch"]);
                            _response.StatusCode = (int)HttpStatusCode.Conflict;
                        }
                    }
                    else
                    {
                        _errorHandler.ReturnLockMismatch(_response, reason: ConfigurationManager.AppSettings["notLocked"]);
                        _response.AddHeader(WopiHeaders.Lock, newLock);
                        _response.AddHeader(WopiHeaders.LockFailureReason, ConfigurationManager.AppSettings["notLocked"]);
                        _response.StatusCode = (int)HttpStatusCode.Conflict;
                    }
                }
                _response.Close();
            }
        }
コード例 #8
0
        public void HandleCheckFileInfoRequest(WopiRequest requestData)
        {
            lock (this)
            {
                if (!_authorization.ValidateAccess(requestData, writeAccessRequired: false))
                {
                    _errorHandler.ReturnInvalidToken(_response);
                    _response.Close();
                    return;
                }

                if (!File.Exists(requestData.FullPath))
                {
                    _errorHandler.ReturnFileUnknown(_response);
                    _response.Close();
                    return;
                }

                try
                {
                    FileInfo fileInfo = new FileInfo(requestData.FullPath);
                    ResponseGenerator generator = new ResponseGenerator(fileInfo);
                    if (!fileInfo.Exists)
                    {
                        _errorHandler.ReturnFileUnknown(_response);
                        return;
                    }

                    var memoryStream = new MemoryStream();
                    var json = new DataContractJsonSerializer(typeof(WopiCheckFileInfo));
                    json.WriteObject(memoryStream, generator.GetFileInfoResponse());
                    memoryStream.Flush();
                    memoryStream.Position = 0;
                    StreamReader streamReader = new StreamReader(memoryStream);
                    var jsonResponse = Encoding.UTF8.GetBytes(streamReader.ReadToEnd());

                    _response.ContentType = @"application/json";
                    _response.ContentLength64 = jsonResponse.Length;
                    _response.OutputStream.Write(jsonResponse, 0, jsonResponse.Length);
                    _errorHandler.ReturnSuccess(_response);

                }
                catch (UnauthorizedAccessException)
                {
                    _errorHandler.ReturnFileUnknown(_response);

                }
                _response.Close();
            }
        }
コード例 #9
0
        /// <summary>
        /// Determines if the user is authorized to access the WebAPI endpoint based on the bearer token
        /// </summary>
        protected override bool IsAuthorized(HttpActionContext actionContext)
        {
            try
            {
                // Parse the query string and ensure there is an access_token
                var queryParams = parseRequestParams(actionContext.Request.RequestUri.Query);
                if (!queryParams.ContainsKey("access_token"))
                {
                    return(false);
                }

                // Get the details of the WOPI request
                Token token;
                try
                {
                    token = Token.Get(queryParams["access_token"]);
                }
                catch
                {
                    return(false);
                }

                WopiRequest requestData = new WopiRequest()
                {
                    RequestType = WopiRequestType.None,
                    AccessToken = token,
                    Id          = actionContext.RequestContext.RouteData.Values["id"].ToString()
                };

                // Get the requested file from Document DB
                var itemId = new Guid(requestData.Id);
                //var file = DocumentDBRepository<DetailedFileModel>.GetItem("Files", i => i.id == itemId);
                var file = Models.Api.File.Get(itemId);


                // Check for missing file
                if (file == null)
                {
                    return(false);
                }

                // Validate the access token
                return(WopiSecurity.ValidateToken(requestData.AccessToken, file.id.ToString()));
            }
            catch (Exception)
            {
                // Any exception will return false, but should probably return an alternate status codes
                return(false);
            }
        }
コード例 #10
0
        // required endpoints:
        // https://wopi.readthedocs.io/en/latest/wopi_requirements.html#requirements

        protected override void OnActionExecuting(ActionExecutingContext context)
        {
            var requestData = WopiRequest.ParseRequest(Request);

            if (!FB.ValidateAccessToken(Request.QueryString["access_token"], Convert.ToInt64(requestData.Id)))
            {
                HandleResponse(new WopiResponse()
                {
                    ResponseType = WopiResponseType.InvalidToken, Message = "Invalid Token"
                });
                context.Result = new HttpStatusCodeResult(Response.StatusCode, Response.StatusDescription);
            }

            base.OnActionExecuting(context);
        }
コード例 #11
0
        bool IWopiRequestFactory.TryCreateRequest(HttpRequest httpRequest, out WopiRequest wopiRequest)
        {
            if (httpRequest is null)
            {
                throw new ArgumentNullException(nameof(httpRequest));
            }

            wopiRequest = WopiRequest.EMPTY;

            var path = httpRequest.Path;

            if (path.HasValue && path.StartsWithSegments("/wopi", StringComparison.OrdinalIgnoreCase))
            {
                var accessToken = httpRequest.Query["access_token"].FirstOrDefault();

                if (string.IsNullOrWhiteSpace(accessToken))
                {
                    return(EmptyResponse("The access token query parameter is either missing, or it has an empty value"));                                        // TODO - Might be better to be more specific with a WopiRequest.MissingAccessToken response?
                }
                if (path.StartsWithSegments("/wopi/files", StringComparison.OrdinalIgnoreCase))
                {
                    wopiRequest = IdentifyFileRequest(httpRequest, path, accessToken, _features);
                }
                else if (path.StartsWithSegments("/wopi/folders", StringComparison.OrdinalIgnoreCase))
                {
                    wopiRequest = IdentifyFolderRequest();
                }
                else
                {
                    return(EmptyResponse($"Failed to identify WOPI request.  Endpoint '{path}' not supported"));
                }

                if (wopiRequest.IsUnableToValidateAccessToken())
                {
                    wopiRequest = WopiRequest.EMPTY;

                    return(EmptyResponse($"The access token provided '{accessToken}' could not be identified as valid")); // TODO - Might be better to be more specific with a WopiRequest.InvalidAccessToken response?
                }
                else
                {
                    return(true);  // Valid WOPI request that can be actioned
                }
            }

            _logger?.LogTrace($"Determined the request does not related to WOPI: '{path.Value}'");

            return(false);  // Not a WOPI request so nothing for us to do
        }
コード例 #12
0
        /// <summary>
        /// Validates the WOPI Proof on an incoming WOPI request
        /// </summary>
        public async Task <bool> ValidateAsync(WopiRequest wopiRequest)
        {
            var hostUrl = wopiRequest.RequestUri.OriginalString.Replace(":44300", "").Replace(":443", "");

            // Make sure the request has the correct headers
            if (wopiRequest.Proof == null ||
                wopiRequest.Timestamp == null)
            {
                return(false);
            }

            // Set the requested proof values
            var requestProof    = wopiRequest.Proof;
            var requestProofOld = string.Empty;

            if (wopiRequest.ProofOld != null)
            {
                requestProofOld = wopiRequest.ProofOld;
            }

            // Get the WOPI proof info from discovery
            var discoProof = await GetWopiProofAsync();

            // Encode the values into bytes
            var accessTokenBytes = Encoding.UTF8.GetBytes(wopiRequest.AccessToken);
            var hostUrlBytes     = Encoding.UTF8.GetBytes(hostUrl.ToUpperInvariant());
            var timeStampBytes   = BitConverter.GetBytes(Convert.ToInt64(wopiRequest.Timestamp)).Reverse().ToArray();

            // Build expected proof
            List <byte> expected = new List <byte>(
                4 + accessTokenBytes.Length +
                4 + hostUrlBytes.Length +
                4 + timeStampBytes.Length);

            // Add the values to the expected variable
            expected.AddRange(BitConverter.GetBytes(accessTokenBytes.Length).Reverse().ToArray());
            expected.AddRange(accessTokenBytes);
            expected.AddRange(BitConverter.GetBytes(hostUrlBytes.Length).Reverse().ToArray());
            expected.AddRange(hostUrlBytes);
            expected.AddRange(BitConverter.GetBytes(timeStampBytes.Length).Reverse().ToArray());
            expected.AddRange(timeStampBytes);
            byte[] expectedBytes = expected.ToArray();

            return(VerifyProof(expectedBytes, requestProof, discoProof.value) ||
                   VerifyProof(expectedBytes, requestProof, discoProof.oldvalue) ||
                   VerifyProof(expectedBytes, requestProofOld, discoProof.value));
        }
コード例 #13
0
        public override Task <bool> Authorize(WopiRequest wopiRequest)
        {
            try
            {
                if (string.IsNullOrEmpty(wopiRequest.AccessToken))
                {
                    return(Task.FromResult <bool>(false));
                }

                // Validate the access token contains authenticated user
                // We're only doing authentication here and deferring authorization to the other WOPI operations
                // to avoid multiple DB queries
                var userId = WopiSecurity.GetIdentityNameFromToken(wopiRequest.AccessToken);
                return(Task.FromResult <bool>(userId != null));
            }
            catch (Exception)
            {
                // Any exception will return false, but should probably return an alternate status codes
                return(Task.FromResult <bool>(false));
            }
        }
コード例 #14
0
        public void GetFileLockId(WopiRequest requestData)
        {
            lock (this)
            {
                if (!_authorization.ValidateAccess(requestData, writeAccessRequired: true))
                {
                    _errorHandler.ReturnInvalidToken(_response);
                    _response.Close();
                    return;
                }

                if (!File.Exists(requestData.FullPath))
                {
                    _errorHandler.ReturnFileUnknown(_response);
                    _response.Close();
                    return;
                }

                lock (LockInfo.Locks)
                {
                    LockInfo existingLock;
                    bool     fLocked = LockInfo.TryGetLock(requestData.Id, out existingLock);
                    if (fLocked)
                    {
                        _errorHandler.ReturnSuccess(_response);
                        _response.AddHeader(WopiHeaders.Lock, existingLock.Lock);
                        _response.StatusCode = (int)HttpStatusCode.OK;
                    }
                    else
                    {
                        _errorHandler.ReturnSuccess(_response);
                        _response.AddHeader(WopiHeaders.Lock, "");
                        _response.AddHeader(WopiHeaders.LockFailureReason, ConfigurationManager.AppSettings["notLocked"]);
                        _response.StatusCode = (int)HttpStatusCode.OK;
                    }
                }
                _response.Close();
            }
        }
コード例 #15
0
        public void HandleGetFileRequest(WopiRequest requestData)
        {
            lock (this)
            {
                // userId(user@polihub) will be passed from the policyHub application
                if (!_authorization.ValidateToken(requestData.AccessToken, ConfigurationManager.AppSettings["userId"], requestData.Id))
                {
                    _errorHandler.ReturnInvalidToken(_response);
                    _response.Close();
                    return;
                }

                if (!File.Exists(requestData.FullPath))
                {
                    _errorHandler.ReturnFileUnknown(_response);
                    _response.Close();
                    return;
                }
                try
                {
                    FileInfo          fileInfo  = new FileInfo(requestData.FullPath);
                    ResponseGenerator generator = new ResponseGenerator(fileInfo);

                    var content = generator.GetFileContent();
                    _response.ContentType     = ConfigurationManager.AppSettings["appXbinary"];
                    _response.ContentLength64 = content.Length;
                    _response.OutputStream.Write(content, 0, content.Length);
                    _errorHandler.ReturnSuccess(_response);
                }
                catch (UnauthorizedAccessException)
                {
                    _errorHandler.ReturnFileUnknown(_response);
                }
                catch (FileNotFoundException)
                {
                    _errorHandler.ReturnFileUnknown(_response);
                }
            }
        }
コード例 #16
0
        public WopiResponse Handle()
        {
            var requestData = WopiRequest.ParseRequest(_request);

            try
            {
                var documentId = Convert.ToInt64(requestData.Id);
                FB.DeleteDocument(documentId);
            }
            catch (Exception ex)
            {
                return(new WopiResponse()
                {
                    ResponseType = WopiResponseType.ServerError, Message = ex.Message
                });
            }

            return(new WopiResponse()
            {
                ResponseType = WopiResponseType.Success
            });
        }
コード例 #17
0
        public void HandleGetFileRequest(WopiRequest requestData)
        {
            lock (this)
            {
                if (!_authorization.ValidateAccess(requestData, writeAccessRequired: false))
                {
                    _errorHandler.ReturnInvalidToken(_response);
                    _response.Close();
                    return;
                }

                if (!File.Exists(requestData.FullPath))
                {
                    _errorHandler.ReturnFileUnknown(_response);
                    _response.Close();
                    return;
                }
            try
            {
                FileInfo fileInfo = new FileInfo(requestData.FullPath);
                ResponseGenerator generator = new ResponseGenerator(fileInfo);
                var content = generator.GetFileContent();
                _response.ContentType = @"application/x-binary";
                _response.ContentLength64 = content.Length;
                _response.OutputStream.Write(content, 0, content.Length);
                _errorHandler.ReturnSuccess(_response);
                
            }
            catch (UnauthorizedAccessException)
            {
                _errorHandler.ReturnFileUnknown(_response);
                
            }
            catch (FileNotFoundException)
            {
                _errorHandler.ReturnFileUnknown(_response);
            }
        }
コード例 #18
0
 public abstract Task <bool> Authorize(WopiRequest wopiRequest);
コード例 #19
0
        public WopiResponse Handle()
        {
            var requestData = WopiRequest.ParseRequest(_request);
            var documentId  = Convert.ToInt64(requestData.Id);
            var document    = FB.GetDocument(documentId);

            if (document == null)
            {
                return(new WopiResponse()
                {
                    ResponseType = WopiResponseType.FileUnknown, Message = "File not found"
                });
            }

            var newLock = new LockInfo()
            {
                DateCreated = DateTime.UtcNow, Lock = _request.Headers[WopiHeaders.Lock]
            };
            var oldLock = _request.Headers[WopiHeaders.OldLock];

            var currentLockInfo = FB.GetLockInfo(document);
            var currentLock     = !string.IsNullOrEmpty(currentLockInfo)
                ? Newtonsoft.Json.JsonConvert.DeserializeObject <LockInfo>(currentLockInfo)
                : null;

            if (currentLock == null)
            {
                // The file is not currently locked or the lock has already expired
                FB.UpdateLockInfo(document, Newtonsoft.Json.JsonConvert.SerializeObject(newLock));
                return(new WopiResponse()
                {
                    ResponseType = WopiResponseType.Success
                });
            }

            lock (currentLock)
            {
                // unlock & relock:
                if (!string.IsNullOrEmpty(oldLock))
                {
                    if (oldLock == currentLock.Lock && oldLock != newLock.Lock)
                    {
                        FB.UpdateLockInfo(document, Newtonsoft.Json.JsonConvert.SerializeObject(newLock));
                        return(new WopiResponse()
                        {
                            ResponseType = WopiResponseType.Success
                        });
                    }

                    if (oldLock != currentLock.Lock)
                    {
                        return(new WopiResponse()
                        {
                            ResponseType = WopiResponseType.LockMismatch, Message = currentLock.Lock
                        });
                    }
                }

                if (currentLock.Lock != newLock.Lock)
                {
                    // trying to lock again with a different lock? YEAH RIGHT
                    return(new WopiResponse()
                    {
                        ResponseType = WopiResponseType.LockMismatch, Message = currentLock.Lock
                    });
                }

                // locking with the same lock? validator says this should be ok:
                return(new WopiResponse()
                {
                    ResponseType = WopiResponseType.Success
                });
            }
        }
コード例 #20
0
 public bool ValidateAccess(WopiRequest requestData, bool writeAccessRequired)
 {
     return(!String.IsNullOrWhiteSpace(requestData.AccessToken) && (requestData.AccessToken != "INVALID"));
 }
コード例 #21
0
        private static WopiRequest ParseRequest(HttpListenerRequest request)
        {
            WopiRequest requestData = new WopiRequest()
            {
                Type        = RequestType.None,
                AccessToken = request.QueryString["access_token"],
                Id          = "",
                LockId      = request.Headers[WopiHeaders.Lock],
                OldLockId   = request.Headers[WopiHeaders.OldLock]
            };

            string requestPath = request.Url.AbsolutePath;
            string wopiPath    = requestPath.Substring(WopiPath.Length);

            if (wopiPath.StartsWith(FilesRequestPath))
            {
                string rawId = wopiPath.Substring(FilesRequestPath.Length);

                if (rawId.EndsWith(ContentsRequestPath))
                {
                    requestData.Id = rawId.Substring(0, rawId.Length - ContentsRequestPath.Length);

                    if (request.HttpMethod == "GET")
                    {
                        requestData.Type = RequestType.GetFile;
                    }
                    if (request.HttpMethod == "POST")
                    {
                        requestData.Type = RequestType.PutFile;
                        using (var memstream = new MemoryStream())
                        {
                            memstream.Flush();
                            memstream.Position = 0;
                            request.InputStream.CopyTo(memstream);
                            requestData.FileData = memstream.ToArray();
                        }
                    }
                }
                else
                {
                    requestData.Id = rawId;

                    if (request.HttpMethod == "GET")
                    {
                        requestData.Type = RequestType.CheckFileInfo;
                    }
                    else if (request.HttpMethod == "POST")
                    {
                        string wopiOverride = request.Headers[WopiHeaders.RequestType];

                        switch (wopiOverride)
                        {
                        case "PUT_RELATIVE":
                            requestData.Type = RequestType.PutRelativeFile;
                            if (request.Headers[WopiHeaders.RelativeTarget] != null)
                            {
                                requestData.RelativeTarget = request.Headers[WopiHeaders.RelativeTarget];
                            }
                            if (request.Headers[WopiHeaders.SuggestedTarget] != null)
                            {
                                requestData.SuggestedTarget = request.Headers[WopiHeaders.SuggestedTarget];
                            }
                            if (request.Headers[WopiHeaders.OverwriteRelativeTarget] != null)
                            {
                                requestData.OverwriteTarget = bool.Parse(request.Headers[WopiHeaders.OverwriteRelativeTarget]);
                            }

                            using (var memstream = new MemoryStream())
                            {
                                memstream.Flush();
                                memstream.Position = 0;
                                request.InputStream.CopyTo(memstream);
                                requestData.FileData = memstream.ToArray();
                            }

                            break;

                        case "LOCK":
                            if (request.Headers[WopiHeaders.OldLock] != null)
                            {
                                requestData.Type = RequestType.UnlockAndRelock;
                            }
                            else
                            {
                                requestData.Type = RequestType.Lock;
                            }
                            break;

                        case "UNLOCK":
                            requestData.Type = RequestType.Unlock;
                            break;

                        case "REFRESH_LOCK":
                            requestData.Type = RequestType.RefreshLock;
                            break;

                        case "COBALT":
                            requestData.Type = RequestType.ExecuteCobaltRequest;
                            break;

                        case "DELETE":
                            requestData.Type = RequestType.DeleteFile;
                            break;

                        case "READ_SECURE_STORE":
                            requestData.Type = RequestType.ReadSecureStore;
                            break;

                        case "GET_RESTRICTED_LINK":
                            requestData.Type = RequestType.GetRestrictedLink;
                            break;

                        case "REVOKE_RESTRICTED_LINK":
                            requestData.Type = RequestType.RevokeRestrictedLink;
                            break;

                        case "GET_LOCK":
                            requestData.Type = RequestType.GetLock;
                            break;
                        }
                    }
                }
            }
            else if (wopiPath.StartsWith(FoldersRequestPath))
            {
                string rawId = wopiPath.Substring(FoldersRequestPath.Length);

                if (rawId.EndsWith(ChildrenRequestPath))
                {
                    requestData.Id   = rawId.Substring(0, rawId.Length - ChildrenRequestPath.Length);
                    requestData.Type = RequestType.EnumerateChildren;
                }
                else
                {
                    requestData.Id   = rawId;
                    requestData.Type = RequestType.CheckFolderInfo;
                }
            }
            else
            {
                requestData.Type = RequestType.None;
            }

            return(requestData);
        }
コード例 #22
0
        public WopiResponse Handle()
        {
            var requestData = WopiRequest.ParseRequest(_request);

            try
            {
                var documentId = Convert.ToInt64(requestData.Id);
                var document   = FB.GetDocument(documentId);

                if (document == null)
                {
                    return(new WopiResponse()
                    {
                        ResponseType = WopiResponseType.FileUnknown, Message = "File not found"
                    });
                }

                var currentLock = "";
                if (LockHelper.IsLockMismatch(_request, document, out currentLock))
                {
                    return(new WopiResponse()
                    {
                        ResponseType = WopiResponseType.LockMismatch, Message = currentLock
                    });
                }

                // FileInfo putTargetFileInfo = new FileInfo(requestData.FullPath);

                // The WOPI spec allows for a PutFile to succeed on a non-locked file if the file is currently zero bytes in length.
                // This allows for a more efficient Create New File flow that saves the Lock roundtrips.
                //if (!hasExistingLock && putTargetFileInfo.Length != 0)
                //{
                //    // With no lock and a non-zero file, a PutFile could potentially result in data loss by clobbering
                //    // existing content.  Therefore, return a lock mismatch error.
                //    ReturnLockMismatch(context.Response, reason: "PutFile on unlocked file with current size != 0");
                //}

                // Either the file has a valid lock that matches the lock in the request, or the file is unlocked
                // and is zero bytes.  Either way, proceed with the PutFile.

                var binary = IOHelper.StreamToBytes(_request.InputStream);
                FB.SaveDocument(document, binary);
            }
            catch (UnauthorizedAccessException uex)
            {
                return(new WopiResponse()
                {
                    ResponseType = WopiResponseType.FileUnknown, Message = uex.Message
                });
            }
            catch (Exception ex)
            {
                return(new WopiResponse()
                {
                    ResponseType = WopiResponseType.ServerError, Message = ex.Message
                });
            }

            return(new WopiResponse()
            {
                ResponseType = WopiResponseType.Success
            });
        }
コード例 #23
0
        /// <summary>
        /// Called at the beginning of a WOPI request to parse the request and determine the request type
        /// </summary>
        public static WopiRequest ParseRequest(HttpRequest request)
        {
            // Initilize wopi request data object with default values
            WopiRequest requestData = new WopiRequest()
            {
                RequestType = WopiRequestType.None,
                AccessToken = request.QueryString["access_token"],
                Id          = ""
            };

            // Get request path, e.g. /<...>/wopi/files/<id>
            string requestPath = request.Url.AbsolutePath.ToLower();

            // Remove /<...>/wopi/
            string wopiPath = requestPath.Substring(requestPath.IndexOf(WopiUtil.WOPI_BASE_PATH) + WopiUtil.WOPI_BASE_PATH.Length);

            // Check the type of request being made
            if (wopiPath.StartsWith(WopiUtil.WOPI_FILES_PATH))
            {
                // This is a file-related request

                // Remove /files/ from the beginning of wopiPath
                string rawId = wopiPath.Substring(WopiUtil.WOPI_FILES_PATH.Length);

                if (rawId.EndsWith(WopiUtil.WOPI_CONTENTS_PATH))
                {
                    // The rawId ends with /contents so this is a request to read/write the file contents

                    // Remove /contents from the end of rawId to get the actual file id
                    requestData.Id = rawId.Substring(0, rawId.Length - WopiUtil.WOPI_CONTENTS_PATH.Length);

                    // Check request verb to determine file operation
                    if (request.HttpMethod == "GET")
                    {
                        requestData.RequestType = WopiRequestType.GetFile;
                    }
                    if (request.HttpMethod == "POST")
                    {
                        requestData.RequestType = WopiRequestType.PutFile;
                    }
                }
                else
                {
                    requestData.Id = rawId;

                    if (request.HttpMethod == "GET")
                    {
                        // GET requests to the file are always CheckFileInfo
                        requestData.RequestType = WopiRequestType.CheckFileInfo;
                    }
                    else if (request.HttpMethod == "POST")
                    {
                        // Use the X-WOPI-Override header to determine the request type for POSTs
                        string wopiOverride = request.Headers[WopiRequestHeaders.OVERRIDE];
                        switch (wopiOverride)
                        {
                        case "LOCK":
                            // Check lock type based on presence of OldLock header
                            if (request.Headers[WopiRequestHeaders.OLD_LOCK] != null)
                            {
                                requestData.RequestType = WopiRequestType.UnlockAndRelock;
                            }
                            else
                            {
                                requestData.RequestType = WopiRequestType.Lock;
                            }
                            break;

                        case "GET_LOCK":
                            requestData.RequestType = WopiRequestType.GetLock;
                            break;

                        case "REFRESH_LOCK":
                            requestData.RequestType = WopiRequestType.RefreshLock;
                            break;

                        case "UNLOCK":
                            requestData.RequestType = WopiRequestType.Unlock;
                            break;

                        case "PUT_RELATIVE":
                            requestData.RequestType = WopiRequestType.PutRelativeFile;
                            break;

                        case "RENAME_FILE":
                            requestData.RequestType = WopiRequestType.RenameFile;
                            break;

                        case "PUT_USER_INFO":
                            requestData.RequestType = WopiRequestType.PutUserInfo;
                            break;

                            /*
                             * // The following WOPI_Override values were referenced in the product group sample, but not in the documentation
                             * case "COBALT":
                             *  requestData.RequestType = WopiRequestType.ExecuteCobaltRequest;
                             *  break;
                             * case "DELETE":
                             *  requestData.RequestType = WopiRequestType.DeleteFile;
                             *  break;
                             * case "READ_SECURE_STORE":
                             *  requestData.RequestType = WopiRequestType.ReadSecureStore;
                             *  break;
                             * case "GET_RESTRICTED_LINK":
                             *  requestData.RequestType = WopiRequestType.GetRestrictedLink;
                             *  break;
                             * case "REVOKE_RESTRICTED_LINK":
                             *  requestData.RequestType = WopiRequestType.RevokeRestrictedLink;
                             *  break;
                             */
                        }
                    }
                }
            }
            else if (wopiPath.StartsWith(WopiUtil.WOPI_FOLDERS_PATH))
            {
                // This is a folder-related request

                // Remove /folders/ from the beginning of wopiPath
                string rawId = wopiPath.Substring(WopiUtil.WOPI_FOLDERS_PATH.Length);

                if (rawId.EndsWith(WopiUtil.WOPI_CHILDREN_PATH))
                {
                    // rawId ends with /children, so it's an EnumerateChildren request.

                    // Remove /children from the end of rawId
                    requestData.Id = rawId.Substring(0, WopiUtil.WOPI_CHILDREN_PATH.Length);
                    //requestData.RequestType = WopiRequestType.EnumerateChildren;
                }
                else
                {
                    // rawId doesn't end with /children, so it's a CheckFolderInfo.

                    requestData.Id = rawId;
                    //requestData.RequestType = WopiRequestType.CheckFolderInfo;
                }
            }
            else
            {
                // This is an unknown request
                requestData.RequestType = WopiRequestType.None;
            }

            return(requestData);
        }
コード例 #24
0
        public void HandlePutRelativeFileRequest(WopiRequest requestData)
        {
            lock (this)
            {
                // userId(user@polihub) will be passed from the policyHub application
                if (!_authorization.ValidateToken(requestData.AccessToken, "user@policyhub", requestData.Id))
                {
                    _errorHandler.ReturnInvalidToken(_response);
                    _response.Close();
                    return;
                }

                if (!File.Exists(requestData.FullPath))
                {
                    _errorHandler.ReturnFileUnknown(_response);
                    _response.Close();
                    return;
                }

                if (requestData.RelativeTarget != null && requestData.SuggestedTarget != null)
                {
                    // Theses headers are mutually exclusive, so we should return a 501 Not Implemented
                    _errorHandler.ReturnBadRequest(_response);
                    _response.Close();
                    return;
                }

                else if (requestData.RelativeTarget == null && requestData.SuggestedTarget == null)
                {
                    _errorHandler.ReturnBadRequest(_response);
                    _response.Close();
                    return;
                }

                else if (requestData.RelativeTarget != null || requestData.SuggestedTarget != null)
                {
                    string fileName = "";
                    string filePath = "";
                    if (requestData.RelativeTarget != null)
                    {
                        // Specific mode...use the exact filename
                        fileName = requestData.RelativeTarget;
                        bool IsinvalidName = (string.IsNullOrEmpty(fileName) || fileName.IndexOfAny(System.IO.Path.GetInvalidFileNameChars()) >= 0);
                        if (IsinvalidName || fileName.IndexOf('.') == 0)
                        {
                            _errorHandler.ReturnBadRequest(_response);
                            _response.Close();
                            return;
                        }

                        filePath = Path.Combine(WopiHandler.LocalStoragePath, fileName);

                        //if file already exist
                        if (File.Exists(filePath))
                        {
                            if (!requestData.OverwriteTarget)
                            {
                                while (File.Exists(filePath))
                                {
                                    int i = 1;
                                    var filenamewithoutext = Path.GetFileNameWithoutExtension(fileName);
                                    fileName = filenamewithoutext + "_" + i.ToString() + Path.GetExtension(filePath);
                                    filePath = Path.Combine(WopiHandler.LocalStoragePath, fileName);
                                    i        = i + 1;
                                }
                                _response.AddHeader(WopiHeaders.ValidRelativeTarget, fileName);
                                _errorHandler.ReturnConflict(_response);
                                _response.Close();
                                return;
                            }
                            else
                            {
                                LockInfo existingLock;
                                bool     hasExistingLock;

                                lock (LockInfo.Locks)
                                {
                                    hasExistingLock = LockInfo.TryGetLock(requestData.Id, out existingLock);
                                }
                                if (hasExistingLock)
                                {
                                    _response.AddHeader(WopiHeaders.Lock, existingLock.Lock);
                                    _errorHandler.ReturnConflict(_response);
                                    _response.Close();
                                    return;
                                }
                            }
                        }
                    }
                    else
                    {
                        // Suggested mode...might just be an extension

                        fileName = requestData.SuggestedTarget;

                        if (fileName.IndexOf('.') == 0)
                        {
                            fileName = Path.GetFileNameWithoutExtension(requestData.Id) + fileName;
                        }

                        fileName = MakeValidFileName(fileName);
                        filePath = Path.Combine(WopiHandler.LocalStoragePath, fileName);

                        //if file already exist
                        if (File.Exists(filePath))
                        {
                            int i = 0;
                            while (File.Exists(filePath))
                            {
                                i = i + 1;
                                var filenamewithoutext = Path.GetFileNameWithoutExtension(fileName);
                                if (!filenamewithoutext.EndsWith(i.ToString()))
                                {
                                    if (filenamewithoutext.Substring(filenamewithoutext.Length - 1) == (i - 1).ToString())
                                    {
                                        filenamewithoutext = filenamewithoutext.Substring(0, filenamewithoutext.Length - 1);
                                    }

                                    fileName = filenamewithoutext + i.ToString() + Path.GetExtension(filePath);
                                }


                                filePath = WopiHandler.LocalStoragePath + fileName;
                            }
                        }
                    }

                    try
                    {
                        File.WriteAllBytes(filePath, requestData.FileData);
                        _response.ContentType = @"application / json";
                        string fileurl = String.Format(@"http://localhost:8080/wopi/files/{0}?access_token={1}", fileName, requestData.AccessToken);
                        PutRelativeFileResponse putRelative = new PutRelativeFileResponse
                        {
                            Name = fileName,
                            Url  = fileurl
                        };
                        DataContractJsonSerializer js = new DataContractJsonSerializer(typeof(PutRelativeFileResponse));
                        MemoryStream msObj            = new MemoryStream();
                        js.WriteObject(msObj, putRelative);
                        msObj.Position = 0;
                        StreamReader sr           = new StreamReader(msObj);
                        string       json         = sr.ReadToEnd();
                        var          jsonResponse = Encoding.ASCII.GetBytes(json);
                        _response.ContentLength64 = jsonResponse.Length;
                        _response.OutputStream.Write(jsonResponse, 0, jsonResponse.Length);
                        _response.StatusCode = (int)HttpStatusCode.OK;
                    }
                    catch (IOException)
                    {
                        _errorHandler.ReturnServerError(_response);
                    }
                    _response.Close();
                }
            }
        }
コード例 #25
0
        public void HandlePutFileRequest(WopiRequest requestData)
        {
            lock (this)
            {
                // userId(user@polihub) will be passed from the policyHub application
                if (!_authorization.ValidateToken(requestData.AccessToken, "user@policyhub", requestData.Id))
                {
                    _errorHandler.ReturnInvalidToken(_response);
                    _response.Close();
                    return;
                }

                if (!File.Exists(requestData.FullPath))
                {
                    _errorHandler.ReturnFileUnknown(_response);
                    _response.Close();
                    return;
                }
                string   newLock = requestData.LockId;
                LockInfo existingLock;
                bool     hasExistingLock;

                lock (LockInfo.Locks)
                {
                    hasExistingLock = LockInfo.TryGetLock(requestData.Id, out existingLock);
                }

                if (hasExistingLock && existingLock.Lock != newLock)
                {
                    // lock mismatch/locked by another interface
                    _errorHandler.ReturnLockMismatch(_response, existingLock.Lock);
                    _response.AddHeader(WopiHeaders.Lock, existingLock.Lock);
                    _response.AddHeader(WopiHeaders.LockFailureReason, "Lock mismatch/Locked by another interface");
                    _response.StatusCode = (int)HttpStatusCode.Conflict;
                    _response.Close();
                    return;
                }

                FileInfo putTargetFileInfo = new FileInfo(requestData.FullPath);

                if (!hasExistingLock && putTargetFileInfo.Length != 0)
                {
                    _response.AddHeader(WopiHeaders.Lock, newLock);
                    _response.AddHeader(WopiHeaders.LockFailureReason, "PutFile on unlocked file with current size != 0");
                    _response.StatusCode = (int)HttpStatusCode.Conflict;
                    _errorHandler.ReturnLockMismatch(_response, reason: "PutFile on unlocked file with current size != 0");
                    _response.Close();
                    return;
                }


                try
                {
                    ResponseGenerator generator = new ResponseGenerator(putTargetFileInfo);

                    generator.Save(requestData.FileData);
                    _response.ContentLength64 = 0;
                    _response.ContentType     = @"text/html";
                    _response.StatusCode      = (int)HttpStatusCode.OK;
                }
                catch (UnauthorizedAccessException)
                {
                    _errorHandler.ReturnFileUnknown(_response);
                }
                catch (IOException)
                {
                    _errorHandler.ReturnServerError(_response);
                }
                _response.Close();
            }
        }
コード例 #26
0
        public async Task <HttpResponseMessage> ProcessPostActions(string file_id)
        {
            WopiRequest  wopiRequest  = new WopiRequest(this.Request, file_id);
            WopiResponse wopiResponse = null;

            try
            {
                if (await Authorize(wopiRequest))
                {
                    if (await WopiProof.Validate(wopiRequest))
                    {
                        var filesPostOverride = WopiRequest.GetHttpRequestHeader(this.Request, WopiRequestHeaders.OVERRIDE);

                        switch (filesPostOverride)
                        {
                        case "LOCK":
                            var oldLock = WopiRequest.GetHttpRequestHeader(this.Request, WopiRequestHeaders.OLD_LOCK);
                            if (oldLock != null)
                            {
                                wopiResponse = await UnlockAndRelock(new UnlockAndRelockRequest(this.Request, file_id));
                            }
                            else
                            {
                                wopiResponse = await Lock(new LockRequest(this.Request, file_id));
                            }
                            break;

                        case "GET_LOCK":
                            wopiResponse = await GetLock(new GetLockRequest(this.Request, file_id));

                            break;

                        case "REFRESH_LOCK":
                            wopiResponse = await RefreshLock(new RefreshLockRequest(this.Request, file_id));

                            break;

                        case "UNLOCK":
                            wopiResponse = await Unlock(new UnlockRequest(this.Request, file_id));

                            break;

                        case "PUT_RELATIVE":
                            var suggestedTarget = WopiRequest.GetHttpRequestHeader(this.Request, WopiRequestHeaders.SUGGESTED_TARGET);
                            var relativeTarget  = WopiRequest.GetHttpRequestHeader(this.Request, WopiRequestHeaders.RELATIVE_TARGET);
                            if (suggestedTarget != null && relativeTarget != null)
                            {
                                // This really should be BadRequest, but the spec requires NotImplmented
                                wopiResponse = new WopiResponse()
                                {
                                    StatusCode = HttpStatusCode.NotImplemented
                                };
                            }
                            else
                            {
                                if (suggestedTarget != null)
                                {
                                    wopiResponse = await PutRelativeFileSuggested(new PutRelativeFileSuggestedRequest(this.Request, file_id));
                                }
                                else if (relativeTarget != null)
                                {
                                    wopiResponse = await PutRelativeFileSpecific(new PutRelativeFileSpecificRequest(this.Request, file_id));
                                }
                                else     // Both are null
                                {
                                    wopiResponse = new WopiResponse()
                                    {
                                        StatusCode = HttpStatusCode.BadRequest
                                    }
                                };
                            }
                            break;

                        case "RENAME_FILE":
                            wopiResponse = await RenameFile(new RenameFileRequest(this.Request, file_id));

                            break;

                        case "PUT_USER_INFO":
                            wopiResponse = await PutUserInfo(new PutUserInfoRequest(this.Request, file_id));

                            break;

                        case "DELETE":
                            wopiResponse = await DeleteFile(new DeleteFileRequest(this.Request, file_id));

                            break;

                        default:
                            wopiResponse = wopiRequest.ResponseServerError(string.Format("Invalid {0} header value: {1}", WopiRequestHeaders.OVERRIDE, filesPostOverride));
                            break;
                        }
                    }
                    else
                    {
                        wopiResponse = wopiRequest.ResponseServerError("Proof validation failed");
                    }
                }
                else
                {
                    wopiResponse = wopiRequest.ResponseUnauthorized();
                }
            }
            catch (Exception ex)
            {
                wopiResponse = wopiRequest.ResponseServerError(ex.Message);
            }
            return(wopiResponse.ToHttpResponse());
        }
コード例 #27
0
        public WopiJsonResponse Handle()
        {
            var requestData = WopiRequest.ParseRequest(_request);
            var newName     = _request.Headers[WopiHeaders.RequestedName];

            try
            {
                // if the file name is illegal then
                // return 400
                // add response header WopiHeaders.InvalidFileNameError - describing the reason the rename operation could not be completed
                if (string.IsNullOrEmpty(newName))
                {
                    return(new WopiJsonResponse()
                    {
                        StatusCode = 400,
                        Headers = new NameValueCollection {
                            { WopiHeaders.InvalidFileNameError, "Invalid filename for rename" }
                        },
                    });
                }

                newName = IOHelper.Utf7Encode(newName);

                var documentId = Convert.ToInt64(requestData.Id);
                var document   = FB.GetDocument(documentId);

                if (document == null)
                {
                    return(new WopiJsonResponse()
                    {
                        StatusCode = 404, Json = new RenameResponse()
                    });
                }

                var currentLock = "";
                if (LockHelper.IsLockMismatch(_request, document, out currentLock))
                {
                    return(new WopiJsonResponse()
                    {
                        StatusCode = 409, Json = new RenameResponse()
                    });
                }

                // rename the document:
                FB.RenameDocument(document, newName);
            }
            catch (Exception ex)
            {
                //return new WopiResponse() { ResponseType = WopiResponseType.ServerError, Message = ex.Message };
                return(new WopiJsonResponse()
                {
                    StatusCode = 500, Json = new { Message = ex.Message }
                });
            }

            //return new WopiResponse() { ResponseType = WopiResponseType.Success };
            return(new WopiJsonResponse()
            {
                StatusCode = 200, Json = new RenameResponse()
                {
                    Name = newName
                }
            });
        }
コード例 #28
0
        public WopiJsonResponse Handle()
        {
            var requestData = WopiRequest.ParseRequest(_request);

            var responseData = new PutRelativeResponse();

            var documentId      = Convert.ToInt64(requestData.Id);
            var relativeTarget  = _request.Headers[WopiHeaders.RelativeTarget];
            var suggestedTarget = _request.Headers[WopiHeaders.SuggestedTarget];

            // make sure we don't have both headers present:
            if (!string.IsNullOrEmpty(relativeTarget) && !string.IsNullOrEmpty(suggestedTarget))
            {
                return(new WopiJsonResponse()
                {
                    StatusCode = 501,
                    Json = new PutRelativeResponse()
                });
            }

            var    overwriteRelative = _request.Headers[WopiHeaders.OverwriteRelativeTarget];
            string extension;

            if (!string.IsNullOrEmpty(relativeTarget))
            {
                // check if we have a file matching the target name
                // and if so, return 409 conflict w/ lock response
                extension         = relativeTarget.Substring(relativeTarget.LastIndexOf(".") + 1);
                responseData.Name = IOHelper.Utf7Encode(relativeTarget); // extension should already be here, we just need to get it for below

                var overwriteExisting = !string.IsNullOrEmpty(overwriteRelative) && overwriteRelative.ToLower().Equals("true");
                var relativeDocument  = FB.GetDocumentByNameAndExtension(responseData.Name, extension, documentId);

                // does this document already exist?
                if (relativeDocument != null)
                {
                    // lock check - make sure the existing document isn't locked:
                    var currentLock = "";
                    if (LockHelper.IsLockMismatch(_request, relativeDocument, out currentLock))
                    {
                        return(new WopiJsonResponse()
                        {
                            StatusCode = 409, Json = responseData
                        });
                    }

                    // not locked - but the document exists, so make sure the overwrite existing header is set:
                    if (!overwriteExisting)
                    {
                        return(new WopiJsonResponse()
                        {
                            StatusCode = 409,
                            Json = responseData
                        });
                    }
                }
            }
            else
            {
                // suggested mode:
                // save the file with whatever name we want, and return that name:
                extension         = suggestedTarget.Substring(suggestedTarget.LastIndexOf(".") + 1);
                responseData.Name = "wopitest_putrelative." + extension;
            }

            var binary        = IOHelper.StreamToBytes(_request.InputStream);
            var newDocumentId = FB.SaveNewDocument(binary, extension, responseData.Name, documentId);
            var newToken      = FB.GetAccessToken(newDocumentId);

            responseData.Url = $"{Constants.WopiApiUrl}wopi/files/{newDocumentId}?access_token={newToken}";

            return(new WopiJsonResponse()
            {
                StatusCode = 200,
                Json = responseData
            });
        }
コード例 #29
0
        public WopiResponse Handle()
        {
            var requestData = WopiRequest.ParseRequest(_request);
            var documentId  = Convert.ToInt64(requestData.Id);
            var document    = FB.GetDocument(documentId);

            try
            {
                if (document == null)
                {
                    return(new WopiResponse()
                    {
                        ResponseType = WopiResponseType.FileUnknown, Message = "File not found"
                    });
                }

                var newLock = _request.Headers[WopiHeaders.Lock];

                var currentLockInfo = FB.GetLockInfo(document);
                var currentLock     = !string.IsNullOrEmpty(currentLockInfo)
                    ? Newtonsoft.Json.JsonConvert.DeserializeObject <LockInfo>(currentLockInfo)
                    : null;

                if (currentLock == null)
                {
                    return(new WopiResponse()
                    {
                        ResponseType = WopiResponseType.LockMismatch
                    });
                }

                lock (currentLock)
                {
                    if (currentLock.Lock == newLock)
                    {
                        // There is a valid lock on the file and the existing lock matches the provided one
                        FB.UpdateLockInfo(document, string.Empty);
                        return(new WopiResponse()
                        {
                            ResponseType = WopiResponseType.Success
                        });
                    }
                    else
                    {
                        // The existing lock doesn't match the requested one.  Return a lock mismatch error
                        return(new WopiResponse()
                        {
                            ResponseType = WopiResponseType.LockMismatch, Message = currentLock.Lock
                        });
                    }
                }
            }
            catch (Exception ex)
            {
                FB.UpdateLockInfo(document, ex.Message);
                return(new WopiResponse()
                {
                    ResponseType = WopiResponseType.ServerError, Message = ex.Message
                });
            }
        }