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); }