Example #1
0
        /// <summary>
        /// A method is used to read the HTTP response body and decode to string.
        /// </summary>
        /// <param name="wopiHttpResponse">A parameter represents the HTTP response.</param>
        /// <returns>A return value represents the string which is decode from the HTTP response body. The decode format is UTF-8 by default.</returns>
        public static string ReadHTTPResponseBodyToString(WOPIHttpResponse wopiHttpResponse)
        {
            if (null == wopiHttpResponse)
            {
                throw new ArgumentNullException("wopiHttpResponse");
            }

            string bodyString = string.Empty;
            long   bodyLength = wopiHttpResponse.ContentLength;

            if (bodyLength != 0)
            {
                Stream bodStream = null;
                try
                {
                    bodStream = wopiHttpResponse.GetResponseStream();
                    using (StreamReader strReader = new StreamReader(bodStream))
                    {
                        bodyString = strReader.ReadToEnd();
                    }
                }
                finally
                {
                    if (bodStream != null)
                    {
                        bodStream.Dispose();
                    }
                }
            }

            return(bodyString);
        }
        /// <summary>
        /// This method is used to update a file on the WOPI server.
        /// </summary>
        /// <param name="targetResourceUrl">A parameter represents the target resource URL.</param>
        /// <param name="commonHeaders">A parameter represents the common headers that contain "Authorization" header and etc.</param>
        /// <param name="xwopiSize">A parameter represents the size of the request body.</param>
        /// <param name="bodyContents">A parameter represents the body contents of the request.</param>
        /// <param name="lockIdentifierOfFile">A parameter represents the value which is provided by WOPI client that WOPI server used to identify the lock on the file.</param>
        /// <returns>A return value represents the http response for PutFile operation.</returns>
        public WOPIHttpResponse PutFile(string targetResourceUrl, WebHeaderCollection commonHeaders, int?xwopiSize, byte[] bodyContents, string lockIdentifierOfFile)
        {
            WOPIHttpResponse responseTemp = null;

            if (null == commonHeaders)
            {
                commonHeaders = new WebHeaderCollection();
            }

            // Setting required headers
            commonHeaders.Add("X-WOPI-Lock", lockIdentifierOfFile);
            string wopiOverrideValue = this.GetTheXWOPIOverrideHeaderValue(WOPIOperationName.PutFile);

            commonHeaders.Add("X-WOPI-Override", wopiOverrideValue);

            // Setting optional headers
            if (xwopiSize.HasValue)
            {
                string xwopiSizeValue = xwopiSize.Value.ToString();
                commonHeaders.Add("X-WOPI-Size", xwopiSizeValue);
            }

            responseTemp = this.SendWOPIRequest(targetResourceUrl, commonHeaders, bodyContents, WOPIOperationName.PutFile);
            this.ValidateFileContentCapture();
            this.ValidatePutFileResponse(responseTemp);

            return(responseTemp);
        }
        public void MSWOPI_S18_TC02_CheckFolderInfo_HostAuthenticationId()
        {
            {
                // Get the folder URL.
                string folderFullUrl = Common.GetConfigurationPropertyValue("SubFolderUrl", this.Site);

                // Get the WOPI URL.
                string wopiTargetFolderUrl = WopiSutManageCodeControlAdapter.GetWOPIRootResourceUrl(folderFullUrl, WOPIRootResourceUrlType.FolderLevel, TokenAndRequestUrlHelper.DefaultUserName, TokenAndRequestUrlHelper.DefaultPassword, TokenAndRequestUrlHelper.DefaultDomain);

                // Get the common header.
                WebHeaderCollection commonHeaders = HeadersHelper.GetCommonHeaders(wopiTargetFolderUrl);

                // Return information about the folder and permissions that the current user has relative to that file.
                WOPIHttpResponse httpWebResponseForCheckFolderInfo = WopiAdapter.CheckFolderInfo(wopiTargetFolderUrl, commonHeaders, string.Empty);

                string jsonString = WOPIResponseHelper.ReadHTTPResponseBodyToString(httpWebResponseForCheckFolderInfo);

                // Convert the json string to object.
                CheckFolderInfo checkFolderInfo = WOPISerializerHelper.JsonToObject <CheckFolderInfo>(jsonString);

                // Get the WOPI URL.
                string wopiTargetFolderUrlOther = WopiSutManageCodeControlAdapter.GetWOPIRootResourceUrl(
                    folderFullUrl,
                    WOPIRootResourceUrlType.FileLevel,
                    Common.GetConfigurationPropertyValue("UserName1", this.Site),
                    Common.GetConfigurationPropertyValue("Password1", this.Site),
                    Common.GetConfigurationPropertyValue("Domain", this.Site));

                // Get the common header.
                WebHeaderCollection commonHeadersOther = HeadersHelper.GetCommonHeaders(wopiTargetFolderUrlOther);

                // Return information about the folder and permissions that the current user has relative to that file.
                WOPIHttpResponse httpWebResponseForCheckFolderInfoOther = WopiAdapter.CheckFolderInfo(wopiTargetFolderUrlOther, commonHeadersOther, string.Empty);

                jsonString = WOPIResponseHelper.ReadHTTPResponseBodyToString(httpWebResponseForCheckFolderInfoOther);

                // Convert the json string to object.
                CheckFolderInfo checkFolderInfoOther = WOPISerializerHelper.JsonToObject <CheckFolderInfo>(jsonString);

                // Verify MS-WOPI requirement: MS-WOPI_R742
                this.Site.CaptureRequirementIfAreNotEqual(
                    checkFolderInfo.HostAuthenticationId,
                    checkFolderInfoOther.HostAuthenticationId,
                    742,
                    @"[In Response Body] HostAuthenticationId: A string that is used by the WOPI server to uniquely for a sample of N (default N=2) identify the users.");

                // Verify requirement MS-WOPI_R59
                bool isR59Satisfied = checkFolderInfo.HostAuthenticationId != checkFolderInfoOther.HostAuthenticationId;

                if (Convert.ToBoolean(Common.IsRequirementEnabled("MS-WOPI", 59, this.Site)))
                {
                    // Verify MS-WOPI requirement: MS-WOPI_R59
                    this.Site.CaptureRequirementIfIsTrue(
                        isR59Satisfied,
                        59,
                        @"[In Common URI Parameters] Implementation does support the token is scoped to a specific user and set of resources.(Microsoft SharePoint Foundation 2013 and above follow this behavior)");
                }
            }
        }
        /// <summary>
        /// A method is used to send http request for MS-WOPI operation.
        /// </summary>
        /// <param name="targetResourceUrl">A parameter represents the target resource Uri.</param>
        /// <param name="headers">A parameter represents the headers which is included in the http request.</param>
        /// <param name="body">A parameter represents the body contents which is sent in the http request.</param>
        /// <param name="operationName">A parameter represents the WOPI operation which the http request belongs to.</param>
        /// <returns>A return value represents the http response of the http request which is sent with specified header, URI, body and http method. </returns>
        protected virtual WOPIHttpResponse SendWOPIRequest(string targetResourceUrl, WebHeaderCollection headers, byte[] body, WOPIOperationName operationName)
        {
            HttpWebResponse responseTemp = null;
            HttpWebRequest  request      = null;

            request        = (HttpWebRequest)HttpWebRequest.Create(targetResourceUrl);
            request.Method = this.GetHttpMethodForWOPIOperation(operationName);

            // Setting the required common headers
            if (null == headers)
            {
                headers = new WebHeaderCollection();
            }

            request.Headers = headers;

            if (null == body || 0 == body.Length)
            {
                request.ContentLength = 0;
            }
            else
            {
                request.ContentLength = body.Length;
                request.ContentType   = "application/binary";
                Stream stream = request.GetRequestStream();
                stream.Write(body, 0, body.Length);
            }

            // Get the response by default user credential
            request.Credentials = new NetworkCredential(this.defaultUserName, this.defaultPassword, this.defaultDomain);

            // Log the HTTP request
            this.LogHttpTransportInfo(request, body, null, operationName, false);

            try
            {
                responseTemp = request.GetResponse() as HttpWebResponse;
            }
            catch (WebException webEx)
            {
                this.Site.Log.Add(
                    LogEntryKind.Debug,
                    @"There is a WebException generated when sending WOPI request. Exception message[{0}],\r\nStackTrace:[{1}]",
                    webEx.Message,
                    webEx.StackTrace);

                this.RecordWebExceptionInformation(targetResourceUrl, operationName, webEx);
                throw;
            }

            WOPIHttpResponse wopiHttpResponse = new WOPIHttpResponse(responseTemp);

            // Log the HTTP response
            this.LogHttpTransportInfo(request, null, wopiHttpResponse, operationName);

            this.ValidateCommonMessageCapture();

            return(wopiHttpResponse);
        }
        /// <summary>
        /// This method is used to return the contents of a folder on the WOPI server.
        /// </summary>
        /// <param name="targetResourceUrlOfFloder">A parameter represents the target resource URL.</param>
        /// <param name="commonHeaders">A parameter represents the common headers that contain "Authorization" header and etc.</param>
        /// <returns>A return value represents the http response for EnumerateChildren operation.</returns>
        public WOPIHttpResponse EnumerateChildren(string targetResourceUrlOfFloder, WebHeaderCollection commonHeaders)
        {
            WOPIHttpResponse responseTemp = null;

            responseTemp = this.SendWOPIRequest(targetResourceUrlOfFloder, commonHeaders, null, WOPIOperationName.EnumerateChildren);
            this.ValidateEnumerateChildrenResponse(responseTemp);

            return(responseTemp);
        }
        /// <summary>
        /// This method is used to validate CheckFolderInfo response captures.
        /// </summary>
        /// <param name="response">A parameter represents the response from server.</param>
        private void ValidateCheckFolderInfoResponse(WOPIHttpResponse response)
        {
            string          jsonString      = WOPIResponseHelper.ReadHTTPResponseBodyToString(response);
            CheckFolderInfo checkFolderInfo = WOPISerializerHelper.JsonToObject <CheckFolderInfo>(jsonString);

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-WOPI_R602");

            // Verify MS-WOPI requirement: MS-WOPI_R602
            // The object is not null means JSON string can change to object. JSON to object check all require and optional item.
            this.Site.CaptureRequirementIfIsNotNull(
                checkFolderInfo,
                602,
                @"[In Response Body] The response body is JSON (as specified in [RFC4627]) with the following parameters:
                          JSON:
                          {
                          ""FolderName"":{""type"":""string"",""optional"":false},
                          ""BreadcrumbBrandIconUrl"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""BreadcrumbBrandName"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""BreadcrumbBrandUrl"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""BreadcrumbDocName"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""BreadcrumbDocUrl"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""BreadcrumbFolderName"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""BreadcrumbFolderUrl"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""ClientUrl"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""CloseButtonClosesWindow"":{""type"":""bool"",""default"":false,""optional"":true},
                          ""CloseUrl"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""FileSharingUrl"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""HostAuthenticationId""{""type"":""string"",""default"":"""",""optional"":true},
                          ""HostEditUrl"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""HostEmbeddedEditUrl"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""HostEmbeddedViewUrl"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""HostName"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""HostViewUrl"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""OwnerId"":{""type"":""string"",""optional"":false},
                          ""PresenceProvider""{""type"":""string"",""default"":"""",""optional"":true},
                          ""PresenceUserId""{""type"":""string"",""default"":"""",""optional"":true},
                          ""PrivacyUrl"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""SignoutUrl"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""SupportsSecureStore"":{""type"":""bool"",""default"":false,""optional"":true},
                          ""TenantId""{""type"":""string"",""default"":"""",""optional"":true},
                          ""TermsOfUseUrl"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""UserCanWrite"":{""type"":""bool"",""default"":false,""optional"":true},
                          ""UserFriendlyName"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""UserId"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""WebEditingDisabled"":{""type"":""bool"",""default"":false,""optional"":true},
                          }");

            this.ValidateURL(checkFolderInfo.CloseUrl, "CloseUrl");
            this.ValidateURL(checkFolderInfo.FileSharingUrl, "FileSharingUrl");
            this.ValidateURL(checkFolderInfo.HostEmbeddedEditUrl, "HostEmbeddedEditUrl");
            this.ValidateURL(checkFolderInfo.HostEmbeddedViewUrl, "HostEmbeddedViewUrl");
            this.ValidateURL(checkFolderInfo.PrivacyUrl, "PrivacyUrl");
            this.ValidateURL(checkFolderInfo.SignoutUrl, "SignoutUrl");
        }
Example #7
0
        public void MSWOPI_S18_TC01_CheckFolderInfo()
        {
            if (!Common.IsRequirementEnabled("MS-WOPI", 593, this.Site))
            {
                Site.Assume.Inconclusive(@"The implementation does not support the get the folder access_token and WOPISrc. It is determined using SHOULDMAY PTFConfig property named R593Enabled_MS-WOPI.");
            }
            // Get the folder URL.
            string folderFullUrl = Common.GetConfigurationPropertyValue("SubFolderUrl", this.Site);

            // Get the WOPI URL.
            string wopiTargetFolderUrl = WopiSutManageCodeControlAdapter.GetWOPIRootResourceUrl(folderFullUrl, WOPIRootResourceUrlType.FolderLevel, TokenAndRequestUrlHelper.DefaultUserName, TokenAndRequestUrlHelper.DefaultPassword, TokenAndRequestUrlHelper.DefaultDomain);

            // Get the common header.
            WebHeaderCollection commonHeaders = HeadersHelper.GetCommonHeaders(wopiTargetFolderUrl);

            // Return information about the folder and permissions that the current user has relative to that file.
            WOPIHttpResponse httpWebResponseForCheckFolderInfo = WopiAdapter.CheckFolderInfo(wopiTargetFolderUrl, commonHeaders, string.Empty);

            // Get the json string from the response of CheckFolderInfo.
            string jsonString = WOPIResponseHelper.ReadHTTPResponseBodyToString(httpWebResponseForCheckFolderInfo);

            // Convert the json string to object.
            CheckFolderInfo checkFolderInfo = WOPISerializerHelper.JsonToObject <CheckFolderInfo>(jsonString);

            // Verify MS-WOPI requirement: MS-WOPI_R597
            this.Site.CaptureRequirementIfIsNotNull(
                checkFolderInfo,
                597,
                @"[In HTTP://server/<...>/wopi*/folders/<id>] Operation ""CheckFolderInfo"" is used for ""Returns information about a folder.");

            // Verify MS-WOPI requirement: MS-WOPI_R597
            this.Site.CaptureRequirementIfIsNotNull(
                checkFolderInfo,
                598,
                @"[In CheckFolderInfo] Return information about the folder and permissions that the current user has relative to that file.");

            // The URI in "CheckFolderInfo" WOPI request follow the "HTTP://server/<...>/wopi*/folders/<id>?access_token=<token>" pattern, if the operation execute successfully, capture R599
            // Verify MS-WOPI requirement: MS-WOPI_R599
            this.Site.CaptureRequirement(
                599,
                @"[In CheckFolderInfo] HTTP Verb: GET
                          URI: HTTP://server/<...>/wopi*/folders/<id>?access_token=<token>");

            if (!string.IsNullOrEmpty(checkFolderInfo.UserFriendlyName))
            {
                // Verify MS-WOPI requirement: MS-WOPI_R645
                bool isVerifiedR645 = checkFolderInfo.UserFriendlyName.IndexOf(Common.GetConfigurationPropertyValue("UserName", this.Site), StringComparison.OrdinalIgnoreCase) >= 0 ||
                                      checkFolderInfo.UserFriendlyName.IndexOf(Common.GetConfigurationPropertyValue("UserFriendlyName", this.Site), StringComparison.OrdinalIgnoreCase) >= 0;

                this.Site.CaptureRequirementIfIsTrue(
                    isVerifiedR645,
                    645,
                    @"[In Response Body] UserFriendlyName: A string that is the name of the user.");
            }
        }
        public void MSWOPI_S19_TC05_PutFile_Fail409()
        {
            // Get the file URL.
            string fileUrl = this.AddFileToSUT();

            // Get the WOPI URL.
            string wopiTargetFileUrl = WopiSutManageCodeControlAdapter.GetWOPIRootResourceUrl(fileUrl, WOPIRootResourceUrlType.FileLevel, TokenAndRequestUrlHelper.DefaultUserName, TokenAndRequestUrlHelper.DefaultPassword, TokenAndRequestUrlHelper.DefaultDomain);

            // Get the common header.
            WebHeaderCollection commonHeaders = HeadersHelper.GetCommonHeaders(wopiTargetFileUrl);
            string identifierForLock          = Guid.NewGuid().ToString("N");

            // Lock this file.
            WopiAdapter.Lock(wopiTargetFileUrl, commonHeaders, identifierForLock);

            try
            {
                // Get file content URL.
                string wopiFileContentsLevelUrl = TokenAndRequestUrlHelper.GetSubResourceUrl(wopiTargetFileUrl, WOPISubResourceUrlType.FileContentsLevel);

                // Get the common header.
                commonHeaders = HeadersHelper.GetCommonHeaders(wopiFileContentsLevelUrl);

                string exceptedUpdateContent = "WOPI PUT file test";
                byte[] bodycontents          = Encoding.UTF8.GetBytes(exceptedUpdateContent);
                string identifier            = Guid.NewGuid().ToString("N");

                int statusCode = 0;
                try
                {
                    // Update a file on the WOPI server.
                    WOPIHttpResponse httpWebResponseOfPutFile = WopiAdapter.PutFile(wopiFileContentsLevelUrl, commonHeaders, null, bodycontents, identifier);
                    statusCode = httpWebResponseOfPutFile.StatusCode;
                }
                catch (WebException webEx)
                {
                    HttpWebResponse errorResponse = this.GetErrorResponseFromWebException(webEx);
                    statusCode = this.GetStatusCodeFromHTTPResponse(errorResponse);
                }

                // Verify MS-WOPI requirement: MS-WOPI_R690
                this.Site.CaptureRequirementIfAreEqual(
                    409,
                    statusCode,
                    690,
                    @"[In PutFile] Status code ""409"" means ""Lock mismatch"".");
            }
            finally
            {
                // Release a lock for editing a file.
                commonHeaders = HeadersHelper.GetCommonHeaders(wopiTargetFileUrl);
                WopiAdapter.UnLock(wopiTargetFileUrl, commonHeaders, identifierForLock);
            }
        }
        public void MSWOPI_S19_TC01_GetFile()
        {
            // Get the file URL.
            string fileUrl = this.AddFileToSUT();

            // Get the WOPI URL.
            string wopiTargetFileUrl = WopiSutManageCodeControlAdapter.GetWOPIRootResourceUrl(fileUrl, WOPIRootResourceUrlType.FileLevel, TokenAndRequestUrlHelper.DefaultUserName, TokenAndRequestUrlHelper.DefaultPassword, TokenAndRequestUrlHelper.DefaultDomain);

            // Get file content URL.
            string wopiFileContentsLevelUrl = TokenAndRequestUrlHelper.GetSubResourceUrl(wopiTargetFileUrl, WOPISubResourceUrlType.FileContentsLevel);

            // Get the common header.
            WebHeaderCollection commonHeaders = HeadersHelper.GetCommonHeaders(wopiFileContentsLevelUrl);

            int statusCode = 0;

            // Get a file.
            WOPIHttpResponse responseOfGetFile = WopiAdapter.GetFile(wopiFileContentsLevelUrl, commonHeaders, null);

            statusCode = responseOfGetFile.StatusCode;

            // Verify MS-WOPI requirement: MS-WOPI_R667
            this.Site.CaptureRequirementIfAreEqual(
                200,
                statusCode,
                667,
                @"[In GetFile] Status code ""200"" means ""Success"".");

            // Verify MS-WOPI requirement: MS-WOPI_R657
            this.Site.CaptureRequirementIfIsNotNull(
                responseOfGetFile,
                657,
                @"[In HTTP://server/<...>/wopi*/files/<id>/contents] Operation ""GetFile"" is used for ""Request message to retrieve a file for the HTTP://server/<...>/wopi*/files/<id>/contents operation"".");

            // Verify MS-WOPI requirement: MS-WOPI_R659
            this.Site.CaptureRequirementIfIsNotNull(
                responseOfGetFile,
                659,
                @"[In GetFile] Get a file.");

            // The URI in "GetFile" WOPI request follow the "HTTP://server/<...>/wopi*/files/<id>/contents?access_token=<token>" pattern, if the operation execute successfully, capture R660
            // Verify MS-WOPI requirement: MS-WOPI_R660
            this.Site.CaptureRequirement(
                660,
                @"[In GetFile] HTTP Verb: GET
                          URI: HTTP://server/<...>/wopi*/files/<id>/contents?access_token=<token>");

            // Verify MS-WOPI requirement: MS-WOPI_R672
            this.Site.CaptureRequirementIfIsNotNull(
                responseOfGetFile,
                672,
                @"[In Response Body] The binary contents of the file.");
        }
        public void MSWOPI_S19_TC06_PutFile_Lock()
        {
            // Get the file URL.
            string fileUrl = this.AddFileToSUT();

            // Get the WOPI URL.
            string wopiTargetFileUrl = WopiSutManageCodeControlAdapter.GetWOPIRootResourceUrl(fileUrl, WOPIRootResourceUrlType.FileLevel, TokenAndRequestUrlHelper.DefaultUserName, TokenAndRequestUrlHelper.DefaultPassword, TokenAndRequestUrlHelper.DefaultDomain);

            // Get file content URL.
            string wopiFileContentsLevelUrl = TokenAndRequestUrlHelper.GetSubResourceUrl(wopiTargetFileUrl, WOPISubResourceUrlType.FileContentsLevel);

            // Get the common header.
            WebHeaderCollection commonHeaders = HeadersHelper.GetCommonHeaders(wopiTargetFileUrl);

            string identifierForLock = Guid.NewGuid().ToString("N");

            // Lock this file.
            WopiAdapter.Lock(wopiTargetFileUrl, commonHeaders, identifierForLock);

            try
            {
                // Get the common header.
                commonHeaders = HeadersHelper.GetCommonHeaders(wopiFileContentsLevelUrl);

                string exceptedUpdateContent = "WOPI PUT file test";
                byte[] bodycontents          = Encoding.UTF8.GetBytes(exceptedUpdateContent);

                // Update a file on the WOPI server with the identifier of Lock.
                WopiAdapter.PutFile(wopiFileContentsLevelUrl, commonHeaders, null, bodycontents, identifierForLock);

                // Get the common header.
                commonHeaders = HeadersHelper.GetCommonHeaders(wopiFileContentsLevelUrl);

                // Get a file.
                WOPIHttpResponse responseOfGetFile = WopiAdapter.GetFile(wopiFileContentsLevelUrl, commonHeaders, null);

                // Read message from response of GetFile.
                string actualUpdateContent = WOPIResponseHelper.ReadHTTPResponseBodyToString(responseOfGetFile);

                // Verify MS-WOPI requirement: MS-WOPI_R697
                this.Site.CaptureRequirementIfAreEqual(
                    exceptedUpdateContent,
                    actualUpdateContent,
                    697,
                    @"[In Processing Details] If the file is currently associated with a lock established by the Lock operation (see section 3.3.5.1.3) [or the UnlockAndRelock operation (see section 3.3.5.1.6)] the WOPI server MUST provide the matching lock value in order for this operation to succeed.");
            }
            finally
            {
                // Release a lock for editing a file.
                commonHeaders = HeadersHelper.GetCommonHeaders(wopiTargetFileUrl);
                WopiAdapter.UnLock(wopiTargetFileUrl, commonHeaders, identifierForLock);
            }
        }
        /// <summary>
        /// This method is used to validate Lock response captures.
        /// </summary>
        /// <param name="response">A parameter represents the response from server.</param>
        private void ValidateLockResponse(WOPIHttpResponse response)
        {
            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-WOPI_R402");

            // Verify MS-WOPI requirement: MS-WOPI_R402
            // "X-WOPI-OldLock" is not null in response means this item is required.
            this.Site.CaptureRequirementIfIsNotNull(
                response.Headers["X-WOPI-OldLock"],
                402,
                @"[In Lock] X-WOPI-OldLock is Required.");
        }
Example #12
0
        /// <summary>
        /// A method is used to read the HTTP response body to the bytes array.
        /// </summary>
        /// <param name="wopiHttpResponse">A parameter represents the HTTP response.</param>
        /// <returns>A return value represents the raw body content. If the body length is larger than (int.MaxValue) bytes, the body contents will be chunked by 1024 bytes. The max length of this method is (1024 * int.MaxValue) bytes.</returns>
        public static List <byte[]> ReadRawHTTPResponseToBytes(WOPIHttpResponse wopiHttpResponse)
        {
            if (null == wopiHttpResponse)
            {
                throw new ArgumentNullException("wopiHttpResponse");
            }

            using (Stream bodyStream = wopiHttpResponse.GetResponseStream())
            {
                long contentLengthValue = wopiHttpResponse.ContentLength;
                return(ReadBytesFromHttpBodyStream(bodyStream, contentLengthValue));
            }
        }
Example #13
0
        /// <summary>
        /// A method is used to get raw body contents whose length is in 1 to int.MaxValue bytes scope.
        /// </summary>
        /// <param name="wopiHttpResponse">A parameter represents the HTTP response.</param>
        /// <returns>A return value represents the raw body content.</returns>
        public static byte[] GetContentFromResponse(WOPIHttpResponse wopiHttpResponse)
        {
            List <byte[]> rawBytesOfBody = ReadRawHTTPResponseToBytes(wopiHttpResponse);

            byte[] returnContent = rawBytesOfBody.SelectMany(bytes => bytes).ToArray();

            DiscoveryProcessHelper.AppendLogs(
                typeof(WOPIResponseHelper),
                string.Format(
                    "Read normal size(1 to int.MaxValue bytes) data from response. actual size[{0}] bytes",
                    returnContent.Length));

            return(returnContent);
        }
        public void MSWOPI_S19_TC04_PutFile_Fail404()
        {
            // Get the file URL.
            string fileUrl = this.AddFileToSUT();

            // Get the WOPI URL.
            string wopiTargetFileUrl = WopiSutManageCodeControlAdapter.GetWOPIRootResourceUrl(fileUrl, WOPIRootResourceUrlType.FileLevel, TokenAndRequestUrlHelper.DefaultUserName, TokenAndRequestUrlHelper.DefaultPassword, TokenAndRequestUrlHelper.DefaultDomain);

            // Get file content URL.
            string wopiFileContentsLevelUrl = TokenAndRequestUrlHelper.GetSubResourceUrl(wopiTargetFileUrl, WOPISubResourceUrlType.FileContentsLevel);

            // Get the common header.
            WebHeaderCollection commonHeaders = HeadersHelper.GetCommonHeaders(wopiTargetFileUrl);

            // Delete this file.
            WopiAdapter.DeleteFile(wopiTargetFileUrl, commonHeaders);

            // The file has been deleted, so remove it from the clean up list.
            this.ExcludeFileFromTheCleanUpProcess(fileUrl);

            // Get the common header.
            commonHeaders = HeadersHelper.GetCommonHeaders(wopiFileContentsLevelUrl);

            string exceptedUpdateContent = "WOPI PUT file test";

            byte[] bodycontents = Encoding.UTF8.GetBytes(exceptedUpdateContent);
            string identifier   = Guid.NewGuid().ToString("N");

            int statusCodeOfPutFile = 0;

            try
            {
                // Update a file on the WOPI server.
                WOPIHttpResponse httpWebResponseOfPutFile = WopiAdapter.PutFile(wopiFileContentsLevelUrl, commonHeaders, null, bodycontents, identifier);
                statusCodeOfPutFile = httpWebResponseOfPutFile.StatusCode;
            }
            catch (WebException webEx)
            {
                HttpWebResponse errorResponse = this.GetErrorResponseFromWebException(webEx);
                statusCodeOfPutFile = this.GetStatusCodeFromHTTPResponse(errorResponse);
            }

            // Verify MS-WOPI requirement: MS-WOPI_R689
            this.Site.CaptureRequirementIfAreEqual(
                404,
                statusCodeOfPutFile,
                689,
                @"[In PutFile] Status code ""404"" means ""File unknown/User unauthorized"".");
        }
        /// <summary>
        /// This method is used to release a lock for editing a file.
        /// </summary>
        /// <param name="targetResourceUrl">A parameter represents the target resource URL.</param>
        /// <param name="commonHeaders">A parameter represents the common headers that contain "Authorization" header and etc.</param>
        /// <param name="lockIdentifierOfFile">A parameter represents the value which is provided by WOPI client that WOPI server used to identify the lock on the file.</param>
        /// <returns>A return value represents the http response for UnLock operation.</returns>
        public WOPIHttpResponse UnLock(string targetResourceUrl, WebHeaderCollection commonHeaders, string lockIdentifierOfFile)
        {
            WOPIHttpResponse responseTemp = null;

            if (null == commonHeaders)
            {
                commonHeaders = new WebHeaderCollection();
            }

            commonHeaders.Add("X-WOPI-Lock", lockIdentifierOfFile);
            commonHeaders.Add("X-WOPI-Override", this.GetTheXWOPIOverrideHeaderValue(WOPIOperationName.UnLock));

            responseTemp = this.SendWOPIRequest(targetResourceUrl, commonHeaders, null, WOPIOperationName.UnLock);

            return(responseTemp);
        }
        /// <summary>
        /// This method is used to revoke all links to a file through which a number of users are able to operate on a file in a limited way.
        /// </summary>
        /// <param name="targetResourceUrl">A parameter represents the target resource URL.</param>
        /// <param name="commonHeaders">A parameter represents the common headers that contain "Authorization" header and etc.</param>
        /// <param name="xwopiRestrictedLink">A parameter represents the type of restricted link being revoked by WOPI client.</param>
        /// <returns>A return value represents the http response for RevokeRestrictedLink operation.</returns>
        public WOPIHttpResponse RevokeRestrictedLink(string targetResourceUrl, WebHeaderCollection commonHeaders, string xwopiRestrictedLink)
        {
            WOPIHttpResponse responseTemp = null;

            if (null == commonHeaders)
            {
                commonHeaders = new WebHeaderCollection();
            }

            commonHeaders.Add("X-WOPI-RestrictedLink", xwopiRestrictedLink);
            commonHeaders.Add("X-WOPI-Override", this.GetTheXWOPIOverrideHeaderValue(WOPIOperationName.RevokeRestrictedLink));
            responseTemp = this.SendWOPIRequest(targetResourceUrl, commonHeaders, null, WOPIOperationName.RevokeRestrictedLink);

            this.ValidateFilesCapture();

            return(responseTemp);
        }
        /// <summary>
        /// This method is used to create a file on the WOPI server based on the current file.
        /// </summary>
        /// <param name="targetResourceUrl">A parameter represents the target resource URL.</param>
        /// <param name="commonHeaders">A parameter represents the common headers that contain "Authorization" header and etc.</param>
        /// <param name="xwopiSuggestedTarget">A parameter represents the file name in order to create a file.</param>
        /// <param name="xwopiRelativeTarget">A parameter represents the file name of the current file.</param>
        /// <param name="bodyContents">A parameter represents the body contents of the request.</param>
        /// <param name="xwopiOverwriteRelativeTarget">A parameter represents the value that specifies whether the host overwrite the file name if it exists.</param>
        /// <param name="xwopiSize">A parameter represents the size of the file.</param>
        /// <returns>A return value represents the http response for PutRelativeFile operation.</returns>
        public WOPIHttpResponse PutRelativeFile(string targetResourceUrl, WebHeaderCollection commonHeaders, string xwopiSuggestedTarget, string xwopiRelativeTarget, byte[] bodyContents, bool?xwopiOverwriteRelativeTarget, int?xwopiSize)
        {
            WOPIHttpResponse responseTemp = null;

            if (null == commonHeaders)
            {
                commonHeaders = new WebHeaderCollection();
            }

            // Setting required headers
            string wopiOverrideValue = this.GetTheXWOPIOverrideHeaderValue(WOPIOperationName.PutRelativeFile);

            commonHeaders.Add("X-WOPI-Override", wopiOverrideValue);

            // Setting optional headers
            if (!string.IsNullOrEmpty(xwopiSuggestedTarget))
            {
                commonHeaders.Add("X-WOPI-SuggestedTarget", xwopiSuggestedTarget);
            }

            if (xwopiOverwriteRelativeTarget.HasValue)
            {
                string xwopiOverwriteRelativeTargetValue = xwopiOverwriteRelativeTarget.Value.ToString();
                commonHeaders.Add("X-WOPI-OverwriteRelativeTarget", xwopiOverwriteRelativeTargetValue);
            }

            if (!string.IsNullOrEmpty(xwopiRelativeTarget))
            {
                commonHeaders.Add("X-WOPI-RelativeTarget", xwopiRelativeTarget);
            }

            if (xwopiSize.HasValue)
            {
                string xwopiSizeValue = xwopiSize.Value.ToString();
                commonHeaders.Add("X-WOPI-Size", xwopiSizeValue);
            }

            responseTemp = this.SendWOPIRequest(targetResourceUrl, commonHeaders, bodyContents, WOPIOperationName.PutRelativeFile);

            this.ValidateFilesCapture();
            this.ValidatePutRelativeFileResponse(responseTemp);

            return(responseTemp);
        }
        public void MSWOPI_S19_TC02_GetFile_Fail404()
        {
            // Get the file URL.
            string fileUrl = this.AddFileToSUT();

            // Get the WOPI URL.
            string wopiTargetFileUrl = WopiSutManageCodeControlAdapter.GetWOPIRootResourceUrl(fileUrl, WOPIRootResourceUrlType.FileLevel, TokenAndRequestUrlHelper.DefaultUserName, TokenAndRequestUrlHelper.DefaultPassword, TokenAndRequestUrlHelper.DefaultDomain);

            // Get file content URL.
            string wopiFileContentsLevelUrl = TokenAndRequestUrlHelper.GetSubResourceUrl(wopiTargetFileUrl, WOPISubResourceUrlType.FileContentsLevel);

            // Get the common header.
            WebHeaderCollection commonHeaders = HeadersHelper.GetCommonHeaders(wopiTargetFileUrl);

            // Delete the file.
            WopiAdapter.DeleteFile(wopiTargetFileUrl, commonHeaders);

            // The file has been deleted, so remove it from the clean up list.
            this.ExcludeFileFromTheCleanUpProcess(fileUrl);

            // Get the common header.
            commonHeaders = HeadersHelper.GetCommonHeaders(wopiFileContentsLevelUrl);

            int statusCodeOfGetFile = 0;

            try
            {
                // Get a file.
                WOPIHttpResponse responseOfGetFile = WopiAdapter.GetFile(wopiFileContentsLevelUrl, commonHeaders, null);
                statusCodeOfGetFile = responseOfGetFile.StatusCode;
            }
            catch (WebException webEx)
            {
                HttpWebResponse errorResponse = this.GetErrorResponseFromWebException(webEx);
                statusCodeOfGetFile = this.GetStatusCodeFromHTTPResponse(errorResponse);
            }

            // Verify MS-WOPI requirement: MS-WOPI_R669
            this.Site.CaptureRequirementIfAreEqual(
                404,
                statusCodeOfGetFile,
                669,
                @"[In GetFile] Status code ""404"" means ""File unknown/User unauthorized"".");
        }
        /// <summary>
        /// This method is used to validate ReadSecureStore response captures.
        /// </summary>
        /// <param name="response">A parameter represents the response from server.</param>
        private void ValidateReadSecureStoreResponse(WOPIHttpResponse response)
        {
            string jsonString = WOPIResponseHelper.ReadHTTPResponseBodyToString(response);

            // If the JSON string can be converted to the ReadSecureStore succeed, that means it match the JSON schema definition.
            WOPISerializerHelper.JsonToObject <ReadSecureStore>(jsonString);

            // If the JSON string can converted to object. The process of "JSON to object" check all require and optional item.
            this.Site.CaptureRequirement(
                541,
                @"[In Response Body] The response body is JSON (as specified in [RFC4627]) with the following parameters:
                          JSON:
                          {
                          ""UserName"":{""type"":""string"",""optional"":false},
                          ""Password"":{""type"":""string"",""default"":"""",""optional"":false},
                          ""IsWindowsCredentials"":{""type"":""bool"",""default"":""false"",""optional"":true},
                          ""IsGroup"":{""type"":""bool"",""default"":""false"",""optional"":true},
                          }");
        }
        public void MSWOPI_S20_TC03_EnumerateChildren_Fail404()
        {
            if (!Common.IsRequirementEnabled("MS-WOPI", 593, this.Site))
            {
                Site.Assume.Inconclusive(@"The implementation does not support the get the folder access_token and WOPISrc. It is determined using SHOULDMAY PTFConfig property named R593Enabled_MS-WOPI.");
            }
            // Get the folder URL.
            string folderFullUrl = Common.GetConfigurationPropertyValue("SubFolderUrl", this.Site);

            // Get the WOPI URL.
            string wopiTargetFolderUrl = WopiSutManageCodeControlAdapter.GetWOPIRootResourceUrl(folderFullUrl, WOPIRootResourceUrlType.FolderLevel, TokenAndRequestUrlHelper.DefaultUserName, TokenAndRequestUrlHelper.DefaultPassword, TokenAndRequestUrlHelper.DefaultDomain);

            // Get folder content URL.
            string wopiFolderContentsLevelUrl = TokenAndRequestUrlHelper.GetSubResourceUrl(wopiTargetFolderUrl, WOPISubResourceUrlType.FolderChildrenLevel);

            // Get the common header.
            WebHeaderCollection commonHeaders = HeadersHelper.GetCommonHeaders(wopiFolderContentsLevelUrl);

            // Remove "Authorization" header from common headers.
            commonHeaders.Remove("Authorization");

            // Return the contents of a folder on the WOPI server with invalid token.
            int statusCode = 0;

            try
            {
                WOPIHttpResponse httpWebResponseForEnumerateChildren = WopiAdapter.EnumerateChildren(wopiFolderContentsLevelUrl, commonHeaders);
                statusCode = httpWebResponseForEnumerateChildren.StatusCode;
            }
            catch (WebException webEx)
            {
                HttpWebResponse errorResponse = this.GetErrorResponseFromWebException(webEx);
                statusCode = this.GetStatusCodeFromHTTPResponse(errorResponse);
            }

            // Verify MS-WOPI requirement: MS-WOPI_R709
            this.Site.CaptureRequirementIfAreEqual <int>(
                404,
                statusCode,
                709,
                @"[In EnumerateChildren] Status code ""404"" means ""File unknown/User unauthorized"".");
        }
        /// <summary>
        /// This method is used to take a lock for editing a file.
        /// </summary>
        /// <param name="targetResourceUrl">A parameter represents the target resource URL.</param>
        /// <param name="commonHeaders">A parameter represents the common headers that contain "Authorization" header and etc.</param>
        /// <param name="lockIdentifierValue">A parameter represents the value which is provided by WOPI client that WOPI server used to identify the lock on the file.</param>
        /// <returns>A return value represents the http response for Lock operation.</returns>
        public WOPIHttpResponse Lock(string targetResourceUrl, WebHeaderCollection commonHeaders, string lockIdentifierValue)
        {
            WOPIHttpResponse responseTemp = null;

            if (null == commonHeaders)
            {
                commonHeaders = new WebHeaderCollection();
            }

            // Setting required headers
            commonHeaders.Add("X-WOPI-Lock", lockIdentifierValue);
            string wopiOverrideValue = this.GetTheXWOPIOverrideHeaderValue(WOPIOperationName.Lock);

            commonHeaders.Add("X-WOPI-Override", wopiOverrideValue);

            responseTemp = this.SendWOPIRequest(targetResourceUrl, commonHeaders, null, WOPIOperationName.Lock);
            this.ValidateLockResponse(responseTemp);

            return(responseTemp);
        }
        /// <summary>
        /// This method is used to return the file information including file properties and permissions for the user who is identified by token that is sent in the request.
        /// </summary>
        /// <param name="targetResourceUrl">A parameter represents the target resource URL.</param>
        /// <param name="commonHeaders">A parameter represents the common headers that contain "Authorization" header and etc.</param>
        /// <param name="xwopiSessionContextValue">A parameter represents the value of the session context information.</param>
        /// <returns>A return value represents the http response for CheckFileInfo operation.</returns>
        public WOPIHttpResponse CheckFileInfo(string targetResourceUrl, WebHeaderCollection commonHeaders, string xwopiSessionContextValue)
        {
            WOPIHttpResponse responseTemp = null;

            if (null == commonHeaders)
            {
                commonHeaders = new WebHeaderCollection();
            }

            if (!string.IsNullOrEmpty(xwopiSessionContextValue))
            {
                commonHeaders.Add("X-WOPI-SessionContext", xwopiSessionContextValue);
            }

            responseTemp = this.SendWOPIRequest(targetResourceUrl, commonHeaders, null, WOPIOperationName.CheckFileInfo);
            this.ValidateFilesCapture();
            this.ValidateCheckFileInfoResponse(responseTemp);

            return(responseTemp);
        }
        /// <summary>
        /// This method is used to get a file.
        /// </summary>
        /// <param name="targetResourceUrl">A parameter represents the target resource URL.</param>
        /// <param name="commonHeaders">A parameter represents the common headers that contain "Authorization" header and etc.</param>
        /// <param name="maxExpectedSize">A parameter represents the specifying upper bound size of the file being requested.</param>
        /// <returns>A return value represents the http response for GetFile operation.</returns>
        public WOPIHttpResponse GetFile(string targetResourceUrl, WebHeaderCollection commonHeaders, int?maxExpectedSize)
        {
            WOPIHttpResponse responseTemp = null;

            if (null == commonHeaders)
            {
                commonHeaders = new WebHeaderCollection();
            }

            // Setting the optional headers
            if (maxExpectedSize.HasValue)
            {
                commonHeaders.Add("X-WOPI-MaxExpectedSize", maxExpectedSize.Value.ToString());
            }

            responseTemp = this.SendWOPIRequest(targetResourceUrl, commonHeaders, null, WOPIOperationName.GetFile);

            this.ValidateFileContentCapture();

            return(responseTemp);
        }
        /// <summary>
        /// This method is used to validate PutRelativeFile response captures.
        /// </summary>
        /// <param name="response">A parameter represents the response from server.</param>
        private void ValidatePutRelativeFileResponse(WOPIHttpResponse response)
        {
            string          jsonString      = WOPIResponseHelper.ReadHTTPResponseBodyToString(response);
            PutRelativeFile putRelativeFile = WOPISerializerHelper.JsonToObject <PutRelativeFile>(jsonString);

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-WOPI_R382");

            // Verify MS-WOPI requirement: MS-WOPI_R382
            // The object is not null means JSON string can change to object. JSON to object check all require and optional item.
            this.Site.CaptureRequirementIfIsNotNull(
                putRelativeFile,
                382,
                @"[In Response Body] [Name] The response body is JSON (as specified in [RFC4627]) with the following parameters:
                          JSON:
                          {
                          ""Name"":{""type"":""string"",""optional"":false},
                          ""Url"":{""type"":""string"",""default"":"""",""optional"":false},
                          ""HostViewUrl"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""HostEditUrl"":{""type"":""string"",""default"":"""",""optional"":true},
                          }");
            this.ValidateURL(putRelativeFile.HostViewUrl, "HostViewUrl");
            this.ValidateURL(putRelativeFile.HostEditUrl, "HostEditUrl");
        }
        /// <summary>
        /// This method is used to validate EnumerateChildren response captures.
        /// </summary>
        /// <param name="response">A parameter represents the response from server.</param>
        private void ValidateEnumerateChildrenResponse(WOPIHttpResponse response)
        {
            // All folder children messages are follow this format. If test suite receive a succeed response, capture this requirement.
            this.Site.CaptureRequirement(
                699,
                @"[In HTTP://server/<...>/wopi*/folder/<id>/children] The contents of a folder being accessed by WOPI are identified by the following URI:
                          HTTP://server/<...>/wopi*/folder/<id>/children");

            // All folder children messages are follow this format. If test suite receive a succeed response, capture this requirement.
            this.Site.CaptureRequirement(
                700,
                @"[In HTTP://server/<...>/wopi*/folder/<id>/children] The syntax URI parameters are defined by the following ABNF:
                          id = STRING");

            string            jsonString        = WOPIResponseHelper.ReadHTTPResponseBodyToString(response);
            EnumerateChildren enumerateChildren = WOPISerializerHelper.JsonToObject <EnumerateChildren>(jsonString);

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-WOPI_R712");

            // Verify MS-WOPI requirement: MS-WOPI_R712
            // If the value is not null indicating the JSON string has been converted to EnumerateChildren type object successfully.
            this.Site.CaptureRequirementIfIsNotNull(
                enumerateChildren,
                712,
                @"[In Response Body] The response body is JSON (as specified in [RFC4627]) with the following parameters:
                          JSON:
                          {
                          ""Children"":
                            [{
                              ""Name"":""<name>"",
                              ""Url"":""<url>"",
                              ""Version"":""<version>""
                             },
                          }");
        }
        public void MSWOPI_S19_TC03_PutFile()
        {
            // Get the file URL.
            string fileUrl = this.AddFileToSUT();

            // Get the WOPI URL.
            string wopiTargetFileUrl = WopiSutManageCodeControlAdapter.GetWOPIRootResourceUrl(fileUrl, WOPIRootResourceUrlType.FileLevel, TokenAndRequestUrlHelper.DefaultUserName, TokenAndRequestUrlHelper.DefaultPassword, TokenAndRequestUrlHelper.DefaultDomain);

            // Get file content URL.
            string wopiFileContentsLevelUrl = TokenAndRequestUrlHelper.GetSubResourceUrl(wopiTargetFileUrl, WOPISubResourceUrlType.FileContentsLevel);

            // Get the common header.
            WebHeaderCollection commonHeaders = HeadersHelper.GetCommonHeaders(wopiFileContentsLevelUrl);

            string exceptedUpdateContent = "WOPI PUT file test";

            byte[] bodycontents = Encoding.UTF8.GetBytes(exceptedUpdateContent);
            string identifier   = Guid.NewGuid().ToString("N");

            int statusCode = 0;

            // Update a file on the WOPI server.
            WOPIHttpResponse httpWebResponseOfPutFile = WopiAdapter.PutFile(wopiFileContentsLevelUrl, commonHeaders, null, bodycontents, identifier);

            statusCode = httpWebResponseOfPutFile.StatusCode;

            // Verify MS-WOPI requirement: MS-WOPI_R687
            this.Site.CaptureRequirementIfAreEqual(
                200,
                statusCode,
                687,
                @"[In PutFile] Status code ""200"" means ""Success"".");

            // Get the common header.
            commonHeaders = HeadersHelper.GetCommonHeaders(wopiFileContentsLevelUrl);

            // Get a file.
            WOPIHttpResponse responseOfGetFile = WopiAdapter.GetFile(wopiFileContentsLevelUrl, commonHeaders, null);

            // Read message from response of GetFile.
            string actualUpdateContent = WOPIResponseHelper.ReadHTTPResponseBodyToString(responseOfGetFile);

            // Verify MS-WOPI requirement: MS-WOPI_R674
            this.Site.CaptureRequirementIfAreEqual(
                exceptedUpdateContent,
                actualUpdateContent,
                674,
                @"[In PutFile] Update a file on the WOPI server.");

            // Verify MS-WOPI requirement: MS-WOPI_R675
            this.Site.CaptureRequirement(
                675,
                @"[In PutFile] HTTP Verb: POST
                          URI: HTTP://server/<...>/wopi*/files/<id>/contents?access_token=<token>");

            // Verify MS-WOPI requirement: MS-WOPI_R696
            this.Site.CaptureRequirementIfAreEqual(
                exceptedUpdateContent,
                actualUpdateContent,
                696,
                @"[In Processing Details] The WOPI server MUST update the binary of the file identified by <id> to match the binary contents in the request body, if the response indicates Success.");

            // Verify MS-WOPI requirement: MS-WOPI_R658
            this.Site.CaptureRequirementIfAreEqual(
                exceptedUpdateContent,
                actualUpdateContent,
                658,
                @"[In HTTP://server/<...>/wopi*/files/<id>/contents] Operation ""PutFile"" is used for 
                          ""Request message to update a file for the HTTP://server/<...>/wopi*/files/<id>/contents operation"".");

            // Verify MS-WOPI requirement: MS-WOPI_R673
            this.Site.CaptureRequirementIfAreEqual(
                exceptedUpdateContent,
                actualUpdateContent,
                673,
                @"[In Processing Details] The WOPI server MUST return the complete binary of the file identified by <id> in the response body, if the response indicates Success.");
        }
        /// <summary>
        /// A method used to log the HTTP transport information.
        /// </summary>
        /// <param name="wopiRequest">A parameter represents the request instance of a WOPI operation. It must not be null.</param>
        /// <param name="requestBody">A parameter represents the request body of a WOPI operation.</param>
        /// <param name="wopiResponse">A parameter represents the response of a WOPI operation. It must not be null if the "isResponse" parameter is true.</param>
        /// <param name="operationName">A parameter represents the WOPI operation name.</param>
        /// <param name="isResponse">A parameter represents the HTTP transport information recorded by this method whether belong to the response of a WOPI operation.</param>
        private void LogHttpTransportInfo(HttpWebRequest wopiRequest, byte[] requestBody, WOPIHttpResponse wopiResponse, WOPIOperationName operationName, bool isResponse = true)
        {
            #region validate parameters
            if (isResponse)
            {
                if (null == wopiResponse)
                {
                    throw new ArgumentNullException("wopiResponse");
                }

                // For log response, requires the request URL.
                if (null == wopiRequest)
                {
                    throw new ArgumentNullException("wopiRequest");
                }
            }
            else
            {
                if (null == wopiRequest)
                {
                    throw new ArgumentNullException("wopiRequest");
                }
            }
            #endregion

            #region headers

            // Build headers information
            StringBuilder       headerInfoBuilder = new StringBuilder();
            WebHeaderCollection headers           = isResponse ? wopiResponse.Headers : wopiRequest.Headers;
            if (null != headers && 0 != headers.Count)
            {
                foreach (string oheaderNameItem in headers.AllKeys)
                {
                    string headerValueString = string.Format(
                        "[{0}]:({1})",
                        oheaderNameItem,
                        headers[oheaderNameItem]);

                    headerInfoBuilder.AppendLine(headerValueString);
                }
            }

            #endregion

            #region body information

            // Build body information
            byte[] httpBodyOfResponse = null;
            if (isResponse && 0 != wopiResponse.ContentLength)
            {
                httpBodyOfResponse = WOPIResponseHelper.GetContentFromResponse(wopiResponse);
            }

            byte[]        httpBody        = isResponse ? httpBodyOfResponse : requestBody;
            StringBuilder bodyInfoBuilder = new StringBuilder();
            if (null != httpBody && 0 != httpBody.Length)
            {
                switch (operationName)
                {
                case WOPIOperationName.CheckFileInfo:
                case WOPIOperationName.ReadSecureStore:
                case WOPIOperationName.CheckFolderInfo:
                case WOPIOperationName.EnumerateChildren:
                {
                    if (isResponse)
                    {
                        // log response body by JSON format
                        bodyInfoBuilder.AppendLine(Encoding.UTF8.GetString(httpBody));
                    }

                    break;
                }

                case WOPIOperationName.PutRelativeFile:
                {
                    if (isResponse)
                    {
                        // log the body by JSON format
                        bodyInfoBuilder.AppendLine(Encoding.UTF8.GetString(httpBody));
                    }
                    else
                    {
                        // log the body as bytes string value
                        bodyInfoBuilder.AppendLine(WOPIResponseHelper.GetBytesStringValue(httpBody));
                    }

                    break;
                }

                case WOPIOperationName.GetFile:
                {
                    if (isResponse)
                    {
                        // log the body as bytes string value
                        bodyInfoBuilder.AppendLine(WOPIResponseHelper.GetBytesStringValue(httpBody));
                    }

                    break;
                }

                case WOPIOperationName.PutFile:
                {
                    if (!isResponse)
                    {
                        // log the body as bytes string value
                        bodyInfoBuilder.AppendLine(WOPIResponseHelper.GetBytesStringValue(httpBody));
                    }

                    break;
                }
                }
            }

            #endregion

            string credentialInfo = string.Format(
                "User:[{0}] Domain:[{1}]",
                this.defaultUserName,
                this.defaultDomain);

            string logTitle = string.Format(
                "{0} HTTP {1}{2} for [{3}] operation:",
                isResponse ? "Receive" : "Sending",
                isResponse ? "Response" : "Request",
                isResponse ? string.Empty : " with " + credentialInfo,
                operationName);

            StringBuilder logBuilder = new StringBuilder();
            logBuilder.AppendLine(logTitle);

            string urlInfor = string.Format("Request URL:[{0}]", wopiRequest.RequestUri.AbsoluteUri);
            logBuilder.AppendLine(urlInfor);

            string httpMethodValue = string.Format("HTTP method:[{0}]", this.GetHttpMethodForWOPIOperation(operationName));
            logBuilder.AppendLine(httpMethodValue);

            if (isResponse)
            {
                string httpStatusCodeValue = string.Format("HTTP status code:[{0}]", wopiResponse.StatusCode);
                logBuilder.AppendLine(httpStatusCodeValue);
            }

            string headerInfo = string.Format("Headers:\r\n{0}", 0 == headerInfoBuilder.Length ? "None" : headerInfoBuilder.ToString());
            logBuilder.AppendLine(headerInfo);

            string bodyInfo = string.Format("Body:\r\n{0}", 0 == bodyInfoBuilder.Length ? "None" : bodyInfoBuilder.ToString());
            logBuilder.AppendLine(bodyInfo);

            this.Site.Log.Add(LogEntryKind.Debug, logBuilder.ToString());
        }
Example #28
0
        public void MSWOPI_S20_TC02_EnumerateChildren_Version()
        {
            #region Get the WOPI resource URL for visiting file.

            // Get the file URL.
            string fileUrl = Common.GetConfigurationPropertyValue("UrlOfFileOnSubFolder", this.Site);

            // Get the WOPI URL.
            string wopiTargetFileUrl = WopiSutManageCodeControlAdapter.GetWOPIRootResourceUrl(fileUrl, WOPIRootResourceUrlType.FileLevel, TokenAndRequestUrlHelper.DefaultUserName, TokenAndRequestUrlHelper.DefaultPassword, TokenAndRequestUrlHelper.DefaultDomain);

            // Get file content URL.
            string wopiFileContentsLevelUrl = TokenAndRequestUrlHelper.GetSubResourceUrl(wopiTargetFileUrl, WOPISubResourceUrlType.FileContentsLevel);

            #endregion

            #region  Get the WOPI resource URL for visiting folder.

            // Get the folder URL.
            string folderFullUrl = Common.GetConfigurationPropertyValue("SubFolderUrl", this.Site);

            // Get the WOPI URL.
            string wopiTargetFolderUrl = WopiSutManageCodeControlAdapter.GetWOPIRootResourceUrl(folderFullUrl, WOPIRootResourceUrlType.FolderLevel, TokenAndRequestUrlHelper.DefaultUserName, TokenAndRequestUrlHelper.DefaultPassword, TokenAndRequestUrlHelper.DefaultDomain);

            // Get folder content URL.
            string wopiFolderContentsLevelUrl = TokenAndRequestUrlHelper.GetSubResourceUrl(wopiTargetFolderUrl, WOPISubResourceUrlType.FolderChildrenLevel);

            #endregion

            #region Call EnumerateChildren

            // Get the common header.
            WebHeaderCollection commonHeaders = HeadersHelper.GetCommonHeaders(wopiFolderContentsLevelUrl);

            // Return the contents of a folder on the WOPI server.
            WOPIHttpResponse httpWebResponseForEnumerateChildren = WopiAdapter.EnumerateChildren(wopiFolderContentsLevelUrl, commonHeaders);

            // Get the json string from the response of EnumerateChildren.
            string jsonStringForEnumerateChildren = WOPIResponseHelper.ReadHTTPResponseBodyToString(httpWebResponseForEnumerateChildren);

            // Convert the json string to object.
            EnumerateChildren enchildren = WOPISerializerHelper.JsonToObject <EnumerateChildren>(jsonStringForEnumerateChildren);

            string versionOld = enchildren.Children[0].Version;

            #endregion

            #region Call PutFile

            // Get the common header.
            commonHeaders = HeadersHelper.GetCommonHeaders(wopiFileContentsLevelUrl);

            string exceptedUpdateContent = "WOPI PUT file test";
            byte[] bodycontents          = Encoding.UTF8.GetBytes(exceptedUpdateContent);
            string identifier            = Guid.NewGuid().ToString("N");

            // Update a file on the WOPI server.
            WopiAdapter.PutFile(wopiFileContentsLevelUrl, commonHeaders, null, bodycontents, identifier);

            #endregion

            #region Call EnumerateChildren

            // Get the common header.
            commonHeaders = HeadersHelper.GetCommonHeaders(wopiFolderContentsLevelUrl);

            // Return the contents of a folder on the WOPI server.
            httpWebResponseForEnumerateChildren = WopiAdapter.EnumerateChildren(wopiFolderContentsLevelUrl, commonHeaders);

            // Get the json string from the response of EnumerateChildren.
            jsonStringForEnumerateChildren = WOPIResponseHelper.ReadHTTPResponseBodyToString(httpWebResponseForEnumerateChildren);

            // Convert the json string to object.
            enchildren = WOPISerializerHelper.JsonToObject <EnumerateChildren>(jsonStringForEnumerateChildren);

            string versionNew = enchildren.Children[0].Version;

            #endregion

            #region Call CheckFileInfo

            // Get the common header.
            commonHeaders = HeadersHelper.GetCommonHeaders(wopiTargetFileUrl);

            // Return information about the file
            WOPIHttpResponse responseOfCheckFileInfo = WopiAdapter.CheckFileInfo(wopiTargetFileUrl, commonHeaders, null);

            // Get the json string from the response of CheckFileInfo.
            string jsonStringForCheckFileInfo = WOPIResponseHelper.ReadHTTPResponseBodyToString(responseOfCheckFileInfo);

            // Convert the json string to object.
            CheckFileInfo checkFileInfo = WOPISerializerHelper.JsonToObject <CheckFileInfo>(jsonStringForCheckFileInfo);

            string versionCheckFileInfo = checkFileInfo.Version;

            #endregion

            // Verify MS-WOPI requirement: MS-WOPI_R716
            this.Site.CaptureRequirementIfAreNotEqual <string>(
                versionOld,
                versionNew,
                716,
                @"[In Response Body] [Version] This value MUST change when the file changes.");

            // Verify MS-WOPI requirement: MS-WOPI_R934
            this.Site.CaptureRequirementIfAreEqual <string>(
                versionCheckFileInfo,
                versionNew,
                934,
                @"[In Response Body] [Version] MUST match the value that would be provided by the ""Version"" field in the response to CheckFileInfo (see section 3.3.5.1.1).");
        }
Example #29
0
        public void MSWOPI_S20_TC01_EnumerateChildren()
        {
            // Get the folder URL.
            string folderFullUrl = Common.GetConfigurationPropertyValue("SubFolderUrl", this.Site);

            // Get the WOPI URL.
            string wopiTargetFolderUrl = WopiSutManageCodeControlAdapter.GetWOPIRootResourceUrl(folderFullUrl, WOPIRootResourceUrlType.FolderLevel, TokenAndRequestUrlHelper.DefaultUserName, TokenAndRequestUrlHelper.DefaultPassword, TokenAndRequestUrlHelper.DefaultDomain);

            // Get folder content URL.
            string wopiFolderContentsLevelUrl = TokenAndRequestUrlHelper.GetSubResourceUrl(wopiTargetFolderUrl, WOPISubResourceUrlType.FolderChildrenLevel);

            // Get the common header.
            WebHeaderCollection commonHeaders = HeadersHelper.GetCommonHeaders(wopiFolderContentsLevelUrl);

            // Return the contents of a folder on the WOPI server.
            WOPIHttpResponse httpWebResponseForEnumerateChildren = WopiAdapter.EnumerateChildren(wopiFolderContentsLevelUrl, commonHeaders);

            int statusCode = httpWebResponseForEnumerateChildren.StatusCode;

            // Get the json string from the response of EnumerateChildren.
            string jsonStringForEnumerateChildren = WOPIResponseHelper.ReadHTTPResponseBodyToString(httpWebResponseForEnumerateChildren);

            // Convert the json string to object.
            EnumerateChildren enchildren = WOPISerializerHelper.JsonToObject <EnumerateChildren>(jsonStringForEnumerateChildren);
            string            fileName   = enchildren.Children[0].Name;

            // Verify MS-WOPI requirement: MS-WOPI_R707
            this.Site.CaptureRequirementIfAreEqual <int>(
                200,
                statusCode,
                707,
                @"[In EnumerateChildren] Status code ""200"" means ""Success"".");

            // The status code is 200 mean success.When response is success the URIs are return.
            this.Site.CaptureRequirement(
                703,
                @"[In HTTP://server/<...>/wopi*/folder/<id>/children] Operation ""EnumerateChildren"" is used for ""Returns a set of URIs that provides access to resources in the folder"".");

            // The status code is 200 mean success.When response is success the contexts are return.
            this.Site.CaptureRequirement(
                704,
                @"[In EnumerateChildren] The EnumerateChildren method returns the contents of a folder on the WOPI server.");

            // The status code is 200 mean success.When response is success the URI follows the format.
            this.Site.CaptureRequirement(
                705,
                @"[In EnumerateChildren] HTTP Verb: GET
                          URI: HTTP://server/<...>/wopi*/folder/<id>/children?access_token=<token>");

            string subFileUrl       = Common.GetConfigurationPropertyValue("UrlOfFileOnSubFolder", this.Site);
            string expectedFileName = TestSuiteHelper.GetFileNameFromFullUrl(subFileUrl);

            // Verify MS-WOPI requirement: MS-WOPI_R713
            bool isEqualToExpectedFileName = expectedFileName.CompareStringValueIgnoreCase(fileName, this.Site);

            this.Site.CaptureRequirementIfIsTrue(
                isEqualToExpectedFileName,
                713,
                @"[In Response Body] Name: The name of the child resource.");

            // Verify MS-WOPI requirement: MS-WOPI_R714
            // The EnumerateChildren request message follow this format and use the id and token return by WOPI server.
            // If the WOPI server can return the response of EnumerateChildren, capture R714
            this.Site.CaptureRequirement(
                714,
                @"[In Response Body] Url: The URI of the child resource of the form http://server/<...>/wopi*/files/<id>?access_token=<token> where id is the WOPI server’s unique id of the resource and token is the token that provides access to the resource.");
        }
        /// <summary>
        /// This method is used to validate CheckFileInfo response captures.
        /// </summary>
        /// <param name="response">A parameter represents the response from server.</param>
        private void ValidateCheckFileInfoResponse(WOPIHttpResponse response)
        {
            string        jsonString    = WOPIResponseHelper.ReadHTTPResponseBodyToString(response);
            CheckFileInfo checkFileInfo = WOPISerializerHelper.JsonToObject <CheckFileInfo>(jsonString);

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-WOPI_R273");

            // Verify MS-WOPI requirement: MS-WOPI_R273
            // If the value is not null indicating the JSON string has been converted to CheckFileInfo type object successfully.
            this.Site.CaptureRequirementIfIsNotNull(
                checkFileInfo,
                273,
                @"[In Response Body] The response body is JavaScript Object Notation (JSON) (as specified in [RFC4627]) with the following parameters:
                          JSON:
                          {
                          ""AllowExternalMarketplace"":{""type"":""bool"",""default"":false,""optional"":true},
                          ""BaseFileName"":{""type"":""string"",""optional"":false},
                          ""BreadcrumbBrandName"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""BreadcrumbBrandUrl"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""BreadcrumbDocName"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""BreadcrumbDocUrl"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""BreadcrumbFolderName"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""BreadcrumbFolderUrl"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""ClientUrl"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""CloseButtonClosesWindow"":{""type"":""bool"",""default"":false,""optional"":true},
                          ""CloseUrl"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""DisableBrowserCachingOfUserContent"":{""type"":""bool"",""default"":false,""optional"":true},
                          ""DisablePrint"":{""type"":""bool"",""default"":false,""optional"":true},
                          ""DisableTranslation"":{""type"":""bool"",""default"":false,""optional"":true},
                          ""DownloadUrl"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""FileSharingUrl"":{""type"":""string"",""default"":"""",""optional"":true}, 
                          ""FileUrl"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""HostAuthenticationId""{""type"":""string"",""default"":"""",""optional"":true},
                          ""HostEditUrl"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""HostEmbeddedEditUrl"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""HostEmbeddedViewUrl"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""HostName"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""HostNotes"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""HostRestUrl""{""type"":""string"",""default"":"""",""optional"":true},
                          ""HostViewUrl"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""IrmPolicyDescription"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""IrmPolicyTitle"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""OwnerId"":{""type"":""string"",""optional"":false},
                          ""PresenceProvider""{""type"":""string"",""default"":"""",""optional"":true},
                          ""PresenceUserId""{""type"":""string"",""default"":"""",""optional"":true},
                          ""PrivacyUrl"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""ProtectInClient"":{""type"":""bool"",""default"":false,""optional"":true},
                          ""ReadOnly"":{""type"":""bool"",""default"":false,""optional"":true},
                          ""RestrictedWebViewOnly"":{""type"":""bool"",""default"":false,""optional"":true},
                          ""SHA256"":{""type"":""string"",""optional"":false},
                          ""SignoutUrl"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""Size"":{""type"":""int"",""optional"":false},
                          ""SupportsCoauth"":{""type"":""bool"",""default"":false,""optional"":true},
                          ""SupportsCobalt"":{""type"":""bool"",""default"":false,""optional"":true},
                          ""SupportsFolders"":{""type"":""bool"",""default"":false,""optional"":true},
                          ""SupportsLocks"":{""type"":""bool"",""default"":false,""optional"":true},
                          ""SupportsScenarioLinks"":{""type"":""bool"",""default"":false,""optional"":true},
                          ""SupportsSecureStore"":{""type"":""bool"",""default"":false,""optional"":true},
                          ""SupportsUpdate"":{""type"":""bool"",""default"":false,""optional"":true},
                          ""TenantId""{""type"":""string"",""default"":"""",""optional"":true},
                          ""TermsOfUseUrl"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""TimeZone""{""type"":""string"",""default"":"""",""optional"":true},
                          ""UserCanAttend"":{""type"":""bool"",""default"":false,""optional"":true},
                          ""UserCanNotWriteRelative"":{""type"":""bool"",""default"":false,""optional"":true},
                          ""UserCanPresent"":{""type"":""bool"",""default"":false,""optional"":true},
                          ""UserCanWrite"":{""type"":""bool"",""default"":false,""optional"":true},
                          ""UserFriendlyName"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""UserId"":{""type"":""string"",""default"":"""",""optional"":true},
                          ""Version"":{""type"":""string"",""optional"":false}
                          ""WebEditingDisabled"":{""type"":""bool"",""default"":false,""optional"":true},
                          }");

            if (WOPISerializerHelper.CheckContainItem(jsonString, "ReadOnly"))
            {
                // Check whether "ReadOnly" is in JSON. If JSON string contain this item,it must follow JSON response format.
                this.Site.CaptureRequirement(
                    925,
                    @"[In Response Body] ReadOnly is a Boolean value.");
            }

            if (WOPISerializerHelper.CheckContainItem(jsonString, "SupportsCoauth"))
            {
                // Check whether "SupportsCoauth" is in JSON. If JSON string contain this item,it must follow JSON response format.
                this.Site.CaptureRequirement(
                    950,
                    @"[In Response Body] SupportsCoauth is a Boolean value.");
            }

            if (WOPISerializerHelper.CheckContainItem(jsonString, "SupportsCobalt"))
            {
                // Check whether "SupportsCobalt" is in JSON. If JSON string contain this item,it must follow JSON response format.
                this.Site.CaptureRequirement(
                    775,
                    @"[In Response Body] SupportsCobalt is a Boolean value.");
            }

            if (WOPISerializerHelper.CheckContainItem(jsonString, "SupportsFolders"))
            {
                // Check whether "SupportsFolders" is in JSON. If JSON string contain this item,it must follow JSON response format.
                this.Site.CaptureRequirement(
                    777,
                    @"[In Response Body] SupportsFolders is a Boolean value.");
            }

            if (WOPISerializerHelper.CheckContainItem(jsonString, "SupportsLocks"))
            {
                // Check whether "SupportsLocks" is in JSON. If JSON string contain this item,it must follow JSON response format.
                this.Site.CaptureRequirement(
                    779,
                    @"[In Response Body] SupportsLocks is a Boolean value.");
            }

            if (WOPISerializerHelper.CheckContainItem(jsonString, "SupportsSecureStore"))
            {
                // Check whether "SupportsSecureStore" is in JSON. If JSON string contain this item,it must follow JSON response format.
                this.Site.CaptureRequirement(
                    923,
                    @"[In Response Body] SupportsSecureStore is a Boolean value.");
            }

            if (WOPISerializerHelper.CheckContainItem(jsonString, "SupportsUpdate"))
            {
                // Check whether "SupportsUpdate" is in JSON. If JSON string contain this item,it must follow JSON response format.
                this.Site.CaptureRequirement(
                    783,
                    @"[In Response Body] SupportsUpdate is a Boolean value.");
            }

            if (WOPISerializerHelper.CheckContainItem(jsonString, "UserCanNotWriteRelative"))
            {
                // Check whether "UserCanNotWriteRelative" is in JSON. If JSON string contain this item,it must follow JSON response format.
                this.Site.CaptureRequirement(
                    920,
                    @"[In Response Body] UserCanNotWriteRelative is a Boolean value.");
            }

            if (WOPISerializerHelper.CheckContainItem(jsonString, "UserCanWrite"))
            {
                // Check whether "UserCanWrite" is in JSON. If JSON string contain this item,it must follow JSON response format.
                this.Site.CaptureRequirement(
                    928,
                    @"[In Response Body] UserCanWrite is a Boolean value.");
            }

            this.ValidateURL(checkFileInfo.CloseUrl, "CloseUrl");
            this.ValidateURL(checkFileInfo.DownloadUrl, "DownloadUrl");
            this.ValidateURL(checkFileInfo.FileSharingUrl, "FileSharingUrl");
            this.ValidateURL(checkFileInfo.HostViewUrl, "HostViewUrl");
        }