private void HandleResponse(WopiResponse response)
        {
            switch (response.ResponseType)
            {
            case WopiResponseType.ServerError:
                ReturnStatus(500, response.Message);
                break;

            case WopiResponseType.FileUnknown:
                ReturnStatus(404, "File Unknown/User Unauthorized");
                break;

            case WopiResponseType.InvalidToken:
                ReturnStatus(401, response.Message);
                break;

            case WopiResponseType.LockMismatch:
                Response.Headers[WopiHeaders.Lock] = response.Message ?? String.Empty;
                //if (!String.IsNullOrEmpty(reason))
                //{
                //    Response.Headers[WopiHeaders.LockFailureReason] = reason;
                //}
                ReturnStatus(409, "Lock mismatch/Locked by another interface");
                break;

            case WopiResponseType.Success:

                break;
            }
        }
        public async Task <HttpResponseMessage> GetFile(string file_id)
        {
            var          getFileRequest = new GetFileRequest(this.Request, file_id);
            WopiResponse wopiResponse   = null;

            try
            {
                if (await Authorize(getFileRequest))
                {
                    if (await WopiProof.Validate(getFileRequest))
                    {
                        wopiResponse = await GetFile(getFileRequest);
                    }
                    else
                    {
                        getFileRequest.ResponseServerError("Proof validation failed");
                    }
                }
                else
                {
                    wopiResponse = getFileRequest.ResponseUnauthorized();
                }
            }
            catch (Exception ex)
            {
                wopiResponse = getFileRequest.ResponseServerError(ex.Message);
            }

            return(wopiResponse.ToHttpResponse());
        }
        public override async Task <WopiResponse> RenameFile(RenameFileRequest renameFileRequest)
        {
            WopiResponse wopiResponse = null;
            var          file         = DocumentDBRepository <DetailedFileModel> .GetItem("Files", i => i.id.ToString() == renameFileRequest.ResourceId);

            // Check for null file
            if (file != null)
            {
                // Make sure the X-WOPI-RequestedName header is included
                if (renameFileRequest.RequestedName != null)
                {
                    // Ensure the file isn't locked
                    if (String.IsNullOrEmpty(file.LockValue) ||
                        (file.LockExpires != null &&
                         file.LockExpires < DateTime.Now))
                    {
                        // Update the file with a LockValue and LockExpiration
                        file.LockValue    = renameFileRequest.Lock;
                        file.LockExpires  = DateTime.Now.AddMinutes(30);
                        file.BaseFileName = renameFileRequest.RequestedName;
                        await DocumentDBRepository <FileModel> .UpdateItemAsync("Files", file.id.ToString(), (FileModel)file);

                        // Return success 200
                        wopiResponse = renameFileRequest.ResponseOK(renameFileRequest.RequestedName);
                    }
                    else if (file.LockValue == renameFileRequest.Lock)
                    {
                        // File lock matches existing lock, so we can change the name
                        file.LockExpires  = DateTime.Now.AddMinutes(30);
                        file.BaseFileName = renameFileRequest.RequestedName;
                        await DocumentDBRepository <FileModel> .UpdateItemAsync("Files", file.id.ToString(), (FileModel)file);

                        // Return success 200
                        wopiResponse = renameFileRequest.ResponseOK(renameFileRequest.RequestedName);
                    }
                    else
                    {
                        // The file is locked by someone else...return mismatch
                        wopiResponse = renameFileRequest.ResponseLockConflict(file.LockValue, String.Format("File locked by {0}", file.LockValue));
                    }
                }
                else
                {
                    // X-WOPI-RequestedName header wasn't included
                    wopiResponse = renameFileRequest.ResponseBadRequest("X-WOPI-RequestedName header wasn't included in request");
                }
            }
            else
            {
                wopiResponse = renameFileRequest.ResponseNotFound();
            }
            return(wopiResponse);
        }
        public override async Task <WopiResponse> UnlockAndRelock(UnlockAndRelockRequest unlockAndRelockRequest)
        {
            WopiResponse wopiResponse = null;
            var          file         = DocumentDBRepository <DetailedFileModel> .GetItem("Files", i => i.id.ToString() == unlockAndRelockRequest.ResourceId);

            // Check for null file
            if (file != null)
            {
                // Ensure the file has a valid lock
                if (String.IsNullOrEmpty(file.LockValue))
                {
                    // File isn't locked...pass empty Lock in mismatch response
                    wopiResponse = unlockAndRelockRequest.ResponseLockConflict(String.Empty, "File isn't locked");
                }
                else if (file.LockExpires != null && file.LockExpires < DateTime.Now)
                {
                    // File lock expired, so clear it out
                    file.LockValue   = null;
                    file.LockExpires = null;
                    await DocumentDBRepository <FileModel> .UpdateItemAsync("Files", file.id.ToString(), (FileModel)file);

                    // File isn't locked...pass empty Lock in mismatch response
                    wopiResponse = unlockAndRelockRequest.ResponseLockConflict(String.Empty, "File isn't locked");
                }
                else if (unlockAndRelockRequest.OldLock != file.LockValue)
                {
                    // File lock mismatch...pass Lock in mismatch response
                    wopiResponse = unlockAndRelockRequest.ResponseLockConflict(file.LockValue, "Lock mismatch");
                }
                else
                {
                    // Update the file with a LockValue and LockExpiration
                    file.LockValue   = unlockAndRelockRequest.Lock;
                    file.LockExpires = DateTime.Now.AddMinutes(30);
                    await DocumentDBRepository <FileModel> .UpdateItemAsync("Files", file.id.ToString(), (FileModel)file);

                    // Return success 200
                    wopiResponse = unlockAndRelockRequest.ResponseOK();
                }
            }
            else
            {
                wopiResponse = wopiResponse = unlockAndRelockRequest.ResponseNotFound();
            }
            return(wopiResponse);
        }
        public override async Task <WopiResponse> Lock(LockRequest lockRequest)
        {
            WopiResponse wopiResponse = null;
            var          file         = DocumentDBRepository <DetailedFileModel> .GetItem("Files", i => i.id.ToString() == lockRequest.ResourceId);

            // Check for null file
            if (file != null)
            {
                // Ensure the file isn't already locked or expired
                if (String.IsNullOrEmpty(file.LockValue) ||
                    (file.LockExpires != null &&
                     file.LockExpires < DateTime.Now))
                {
                    // Update the file with a LockValue and LockExpiration
                    file.LockValue   = lockRequest.Lock;
                    file.LockExpires = DateTime.Now.AddMinutes(30);
                    await DocumentDBRepository <FileModel> .UpdateItemAsync("Files", file.id.ToString(), (FileModel)file);

                    // Return success 200
                    wopiResponse = lockRequest.ResponseOK(file.Version.ToString());
                }
                else if (file.LockValue == lockRequest.Lock)
                {
                    // File lock matches existing lock, so refresh lock by extending expiration
                    file.LockExpires = DateTime.Now.AddMinutes(30);
                    await DocumentDBRepository <FileModel> .UpdateItemAsync("Files", file.id.ToString(), (FileModel)file);

                    // Return success 200
                    wopiResponse = lockRequest.ResponseOK(file.Version.ToString());
                }
                else
                {
                    // The file is locked by someone else...return mismatch
                    wopiResponse = lockRequest.ResponseLockConflict(file.LockValue, String.Format("File already locked by {0}", file.LockValue));
                }
            }
            else
            {
                wopiResponse = lockRequest.ResponseNotFound();
            }
            return(wopiResponse);
        }
        public override async Task <WopiResponse> PutUserInfo(PutUserInfoRequest putUserInfoRequest)
        {
            WopiResponse wopiResponse = null;
            var          file         = DocumentDBRepository <DetailedFileModel> .GetItem("Files", i => i.id.ToString() == putUserInfoRequest.ResourceId);

            // Check for null file
            if (file != null)
            {
                file.UserInfo = putUserInfoRequest.UserInfo;

                // Update the file in DocumentDB
                await DocumentDBRepository <FileModel> .UpdateItemAsync("Files", file.id.ToString(), (FileModel)file);

                // Return success
                return(putUserInfoRequest.ResponseOK());
            }
            else
            {
                wopiResponse = putUserInfoRequest.ResponseNotFound();
            }
            return(wopiResponse);
        }
        public override async Task <WopiResponse> GetLock(GetLockRequest getLockRequest)
        {
            WopiResponse wopiResponse = null;
            var          file         = DocumentDBRepository <DetailedFileModel> .GetItem("Files", i => i.id.ToString() == getLockRequest.ResourceId);

            // Check for null file
            if (file != null)
            {
                // Check for valid lock on file
                if (String.IsNullOrEmpty(file.LockValue))
                {
                    // File is not locked...return empty X-WOPI-Lock header
                    // Return success 200
                    wopiResponse = getLockRequest.ResponseFileNotLocked();
                }
                else if (file.LockExpires != null && file.LockExpires < DateTime.Now)
                {
                    // File lock expired, so clear it out
                    file.LockValue   = null;
                    file.LockExpires = null;
                    await DocumentDBRepository <FileModel> .UpdateItemAsync("Files", file.id.ToString(), (FileModel)file);

                    // File is not locked...return empty X-WOPI-Lock header
                    // Return success 200
                    wopiResponse = getLockRequest.ResponseFileNotLocked();
                }
                else
                {
                    // Return success 200
                    wopiResponse = getLockRequest.ResponseFileLocked(file.LockValue);
                }
            }
            else
            {
                wopiResponse = getLockRequest.ResponseNotFound();
            }

            return(wopiResponse);
        }
        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());
        }
        public override async Task <WopiResponse> PutFile(PutFileRequest putFileRequest)
        {
            WopiResponse wopiResponse = null;
            var          file         = DocumentDBRepository <DetailedFileModel> .GetItem("Files", i => i.id.ToString() == putFileRequest.ResourceId);

            // Check for null file
            if (file != null)
            {
                var inputStream = await putFileRequest.Content.ReadAsStreamAsync();

                // Ensure the file has a valid lock
                if (String.IsNullOrEmpty(file.LockValue))
                {
                    // If the file is 0 bytes, this is document creation
                    if (inputStream.Length == 0)
                    {
                        // Update the file in blob storage
                        var bytes = new byte[inputStream.Length];
                        inputStream.Read(bytes, 0, bytes.Length);
                        file.Size = bytes.Length;
                        await AzureStorageUtil.UploadFile(file.id.ToString(), file.Container, bytes);

                        // Update version
                        file.Version++;
                        await DocumentDBRepository <FileModel> .UpdateItemAsync("Files", file.id.ToString(), file);

                        // Return success 200
                        wopiResponse = putFileRequest.ResponseOK();
                    }
                    else
                    {
                        // File isn't locked...pass empty Lock in mismatch response
                        wopiResponse = putFileRequest.ResponseLockConflict(String.Empty, "File isn't locked");
                    }
                }
                else if (file.LockExpires != null && file.LockExpires < DateTime.Now)
                {
                    // File lock expired, so clear it out
                    file.LockValue   = null;
                    file.LockExpires = null;
                    await DocumentDBRepository <FileModel> .UpdateItemAsync("Files", file.id.ToString(), file);

                    // File isn't locked...pass empty Lock in mismatch response
                    wopiResponse = putFileRequest.ResponseLockConflict(String.Empty, "File isn't locked");
                }
                else if (putFileRequest.Lock != file.LockValue)
                {
                    // File lock mismatch...pass Lock in mismatch response
                    wopiResponse = putFileRequest.ResponseLockConflict(file.LockValue, "Lock mismatch");
                }
                else
                {
                    // Update the file in blob storage
                    var bytes = new byte[inputStream.Length];
                    inputStream.Read(bytes, 0, bytes.Length);
                    file.Size = bytes.Length;
                    await AzureStorageUtil.UploadFile(file.id.ToString(), file.Container, bytes);

                    // Update version
                    file.Version++;
                    await DocumentDBRepository <FileModel> .UpdateItemAsync("Files", file.id.ToString(), (FileModel)file);

                    // Return success 200
                    wopiResponse = putFileRequest.ResponseOK();
                }
            }
            else
            {
                wopiResponse = putFileRequest.ResponseNotFound();
            }
            return(wopiResponse);
        }
        public override async Task <WopiResponse> PutRelativeFileSuggested(PutRelativeFileSuggestedRequest putRelativeFileSuggestedRequest)
        {
            WopiResponse wopiResponse = null;
            var          file         = DocumentDBRepository <DetailedFileModel> .GetItem("Files", i => i.id.ToString() == putRelativeFileSuggestedRequest.ResourceId);

            // Check for null file
            if (file != null)
            {
                var inputStream = await putRelativeFileSuggestedRequest.Content.ReadAsStreamAsync();

                // Suggested mode...might just be an extension
                var fileName = putRelativeFileSuggestedRequest.SuggestedTarget;
                if (fileName.IndexOf('.') == 0)
                {
                    fileName = file.BaseFileName.Substring(0, file.BaseFileName.LastIndexOf('.')) + fileName;
                }

                // Create the file entity
                FileModel newFile = new FileModel()
                {
                    id           = Guid.NewGuid(),
                    OwnerId      = file.OwnerId,
                    BaseFileName = fileName,
                    Size         = inputStream.Length,
                    Container    = file.Container,
                    Version      = 1
                };

                // First stream the file into blob storage
                var bytes = new byte[inputStream.Length];
                await inputStream.ReadAsync(bytes, 0, (int)inputStream.Length);

                var id = await Utils.AzureStorageUtil.UploadFile(newFile.id.ToString(), newFile.Container, bytes);

                // Write the details into documentDB
                await DocumentDBRepository <FileModel> .CreateItemAsync("Files", (FileModel)newFile);

                // Get access token for the new file
                WopiSecurity security = new WopiSecurity();
                var          token    = security.GenerateToken(newFile.OwnerId, newFile.Container, newFile.id.ToString());
                var          tokenStr = security.WriteToken(token);

                // Prepare the Json response
                var name = newFile.BaseFileName;

                var url = string.Format("https://{0}/wopi/files/{1}?access_token={2}",
                                        putRelativeFileSuggestedRequest.RequestUri.Authority, newFile.id.ToString(), tokenStr);

                // Add the optional properties to response if applicable (HostViewUrl, HostEditUrl)
                string hostViewUrl = null;
                string hostEditUrl = null;
                var    actions     = await WopiDiscovery.GetActions();

                var fileExt = newFile.BaseFileName.Substring(newFile.BaseFileName.LastIndexOf('.') + 1).ToLower();
                var view    = actions.FirstOrDefault(i => i.ext == fileExt && i.name == "view");
                if (view != null)
                {
                    hostViewUrl = WopiDiscovery.GetActionUrl(view, newFile.id.ToString(), putRelativeFileSuggestedRequest.RequestUri.Authority);
                }
                var edit = actions.FirstOrDefault(i => i.ext == fileExt && i.name == "edit");
                if (edit != null)
                {
                    hostEditUrl = WopiDiscovery.GetActionUrl(edit, newFile.id.ToString(), putRelativeFileSuggestedRequest.RequestUri.Authority);
                }

                // Write the response and return a success 200
                wopiResponse = putRelativeFileSuggestedRequest.ResponseOK(fileName, new Uri(url), new Uri(hostViewUrl), new Uri(hostEditUrl));
            }
            else
            {
                wopiResponse = putRelativeFileSuggestedRequest.ResponseNotFound();
            }
            return(wopiResponse);
        }