/// <summary> /// This method is used to build intermediate node object from a byte array with a signature. /// </summary> /// <param name="array">Specify the byte array.</param> /// <param name="signature">Specify the signature.</param> /// <returns>Return the intermediate node object.</returns> public LeafNodeObject Build(byte[] array, SignatureObject signature) { LeafNodeObject nodeObject = new LeafNodeObject(); nodeObject.DataSize = new DataSizeObject(); nodeObject.DataSize.DataSize = (ulong)array.Length; nodeObject.Signature = signature; nodeObject.ExGuid = new ExGuid(SequenceNumberGenerator.GetCurrentSerialNumber(), Guid.NewGuid()); nodeObject.DataNodeObjectData = new DataNodeObjectData(array, 0, array.Length); nodeObject.IntermediateNodeObjectList = null; // Now in the current implementation, one intermediate node only contain one single data object node. return(nodeObject); }
/// <summary> /// This method is used to travel the node tree and build the ObjectGroupDataElementData and the extra data element list. /// </summary> /// <param name="node">Specify the object node.</param> /// <param name="dataElements">Specify the list of data elements.</param> private void TravelNodeObject(NodeObject node, ref List <DataElement> dataElements) { if (node is IntermediateNodeObject) { ObjectGroupDataElementData data = new ObjectGroupDataElementData(); data.ObjectGroupDeclarations.ObjectDeclarationList.Add(this.CreateObjectDeclare(node)); data.ObjectGroupData.ObjectGroupObjectDataList.Add(this.CreateObjectData(node as IntermediateNodeObject)); dataElements.Add(new DataElement(DataElementType.ObjectGroupDataElementData, data)); foreach (LeafNodeObject child in (node as IntermediateNodeObject).IntermediateNodeObjectList) { this.TravelNodeObject(child, ref dataElements); } } else if (node is LeafNodeObject) { LeafNodeObject intermediateNode = node as LeafNodeObject; ObjectGroupDataElementData data = new ObjectGroupDataElementData(); data.ObjectGroupDeclarations.ObjectDeclarationList.Add(this.CreateObjectDeclare(node)); data.ObjectGroupData.ObjectGroupObjectDataList.Add(this.CreateObjectData(intermediateNode)); if (intermediateNode.DataNodeObjectData != null) { data.ObjectGroupDeclarations.ObjectDeclarationList.Add(this.CreateObjectDeclare(intermediateNode.DataNodeObjectData)); data.ObjectGroupData.ObjectGroupObjectDataList.Add(this.CreateObjectData(intermediateNode.DataNodeObjectData)); dataElements.Add(new DataElement(DataElementType.ObjectGroupDataElementData, data)); return; } if (intermediateNode.DataNodeObjectData == null && intermediateNode.IntermediateNodeObjectList != null) { dataElements.Add(new DataElement(DataElementType.ObjectGroupDataElementData, data)); foreach (LeafNodeObject child in intermediateNode.IntermediateNodeObjectList) { this.TravelNodeObject(child, ref dataElements); } return; } throw new System.InvalidOperationException("The DataNodeObjectData and IntermediateNodeObjectList properties in LeafNodeObjectData type cannot be null in the same time."); } }
/// <summary> /// This method is used to analyze the chunk for the RDC analysis chunk method. /// </summary> /// <param name="rootNode">Specify the root node object which is needed to be analyzed.</param> /// <param name="site">Specify the ITestSite instance.</param> public override void AnalyzeChunking(IntermediateNodeObject rootNode, TestTools.ITestSite site) { List <LeafNodeObject> expectList = this.Chunking(); foreach (LeafNodeObject nodeObject in rootNode.IntermediateNodeObjectList) { LeafNodeObject expect = expectList.First(); if (!expect.Signature.Equals(nodeObject.Signature)) { site.Assert.Fail("For the RDC chunk method expect the signature {0}, actual signature {1}", expect.ToString(), nodeObject.Signature.ToString()); } if (expect.DataSize.DataSize != nodeObject.DataSize.DataSize) { site.Assert.Fail("For the RDC chunk method expect the chunk size, actual chunk size {1}", expect.DataSize.DataSize, nodeObject.DataSize.DataSize); } expectList.RemoveAt(0); } // If runs here, then all the requirements related for RDC analysis can be captured. MsfsshttpdCapture.VerifyRdcAnalysisChunk(SharedContext.Current.Site); }
/// <summary> /// This method is used to create ObjectGroupObjectData instance from a intermediate node object. /// </summary> /// <param name="node">Specify the node object.</param> /// <returns>Return the ObjectGroupObjectData instance.</returns> private ObjectGroupObjectData CreateObjectData(LeafNodeObject node) { ObjectGroupObjectData objectData = new ObjectGroupObjectData(); objectData.CellIDArray = new CellIDArray(0u, null); List <ExGuid> extendedGuidList = new List <ExGuid>(); if (node.DataNodeObjectData != null) { extendedGuidList.Add(node.DataNodeObjectData.ExGuid); } else if (node.IntermediateNodeObjectList != null) { foreach (LeafNodeObject child in node.IntermediateNodeObjectList) { extendedGuidList.Add(child.ExGuid); } } objectData.ObjectExGUIDArray = new ExGUIDArray(extendedGuidList); objectData.Data = new BinaryItem(node.SerializeToByteList()); return(objectData); }
/// <summary> /// This method is used to build intermediate node object from an list of object group data element. /// </summary> /// <param name="objectGroupList">Specify the list of object group data elements.</param> /// <param name="dataObj">Specify the object group object.</param> /// <param name="intermediateGuid">Specify the intermediate extended GUID.</param> /// <returns>Return the intermediate node object.</returns> public LeafNodeObject Build(List <ObjectGroupDataElementData> objectGroupList, ObjectGroupObjectData dataObj, ExGuid intermediateGuid) { LeafNodeObject node = null; IntermediateNodeObject rootNode = null; int index = 0; if (StreamObject.TryGetCurrent <LeafNodeObject>(dataObj.Data.Content.ToArray(), ref index, out node)) { if (dataObj.ObjectExGUIDArray == null) { throw new InvalidOperationException("Failed to build intermediate node because the object extend GUID array does not exist."); } node.ExGuid = intermediateGuid; // Contain a single Data Node Object. if (dataObj.ObjectExGUIDArray.Count.DecodedValue == 1u) { ObjectGroupObjectDeclare dataNodeDeclare; ObjectGroupObjectData dataNodeData = this.FindByExGuid(objectGroupList, dataObj.ObjectExGUIDArray.Content[0], out dataNodeDeclare); BinaryItem data = dataNodeData.Data; node.DataNodeObjectData = new DataNodeObjectData(data.Content.ToArray(), 0, (int)data.Length.DecodedValue); node.DataNodeObjectData.ExGuid = dataObj.ObjectExGUIDArray.Content[0]; node.IntermediateNodeObjectList = null; if (SharedContext.Current.IsMsFsshttpRequirementsCaptured) { MsfsshttpdCapture.VerifyObjectGroupObjectDataForDataNodeObject(dataNodeData, dataNodeDeclare, objectGroupList, SharedContext.Current.Site); } } else { // Contain a list of LeafNodeObjectData node.IntermediateNodeObjectList = new List <LeafNodeObject>(); node.DataNodeObjectData = null; foreach (ExGuid extGuid in dataObj.ObjectExGUIDArray.Content) { ObjectGroupObjectDeclare intermediateDeclare; ObjectGroupObjectData intermediateData = this.FindByExGuid(objectGroupList, extGuid, out intermediateDeclare); node.IntermediateNodeObjectList.Add(new IntermediateNodeObjectBuilder().Build(objectGroupList, intermediateData, extGuid)); if (SharedContext.Current.IsMsFsshttpRequirementsCaptured) { MsfsshttpdCapture.VerifyObjectGroupObjectDataForIntermediateNode(intermediateData, intermediateDeclare, objectGroupList, SharedContext.Current.Site); } } } } else if (StreamObject.TryGetCurrent <IntermediateNodeObject>(dataObj.Data.Content.ToArray(), ref index, out rootNode)) { // In Sub chunking for larger than 1MB zip file, MOSS2010 could return IntermediateNodeObject. // For easy further process, the rootNode will be replaced by intermediate node instead. node = new LeafNodeObject(); node.IntermediateNodeObjectList = new List <LeafNodeObject>(); node.DataSize = rootNode.DataSize; node.ExGuid = rootNode.ExGuid; node.Signature = rootNode.Signature; node.DataNodeObjectData = null; foreach (ExGuid extGuid in dataObj.ObjectExGUIDArray.Content) { ObjectGroupObjectDeclare intermediateDeclare; ObjectGroupObjectData intermediateData = this.FindByExGuid(objectGroupList, extGuid, out intermediateDeclare); node.IntermediateNodeObjectList.Add(new IntermediateNodeObjectBuilder().Build(objectGroupList, intermediateData, extGuid)); if (SharedContext.Current.IsMsFsshttpRequirementsCaptured) { MsfsshttpdCapture.VerifyObjectGroupObjectDataForIntermediateNode(intermediateData, intermediateDeclare, objectGroupList, SharedContext.Current.Site); } } } else { throw new InvalidOperationException("In the ObjectGroupDataElement cannot only contain the IntermediateNodeObject or IntermediateNodeOBject."); } return(node); }
/// <summary> /// This method is used to analyze the chunk. /// </summary> /// <param name="rootNode">Specify the root node object which will be analyzed.</param> /// <param name="site">Specify the ITestSite instance.</param> public override void AnalyzeChunking(IntermediateNodeObject rootNode, ITestSite site) { List <LeafNodeObject> cloneList = new List <LeafNodeObject>(rootNode.IntermediateNodeObjectList); while (cloneList.Count != 0) { LeafNodeObject nodeObject = cloneList.First(); byte[] content = nodeObject.DataNodeObjectData.ObjectData; if (cloneList.Count == 1) { if (content.Length > 1048576) { throw new NotImplementedException("If the final chunk is larger than 1MB, the signature method is not implemented."); } // Only final chunk left SignatureObject expect = this.GetSHA1Signature(content); if (!expect.Equals(nodeObject.Signature)) { site.Assert.Fail("For the Zip file, final part chunk expect the signature {0}, actual signature {1}", expect.ToString(), nodeObject.Signature.ToString()); } // Verify the less than 1MB final part related requirements if (SharedContext.Current.IsMsFsshttpRequirementsCaptured) { MsfsshttpdCapture.VerifySmallFinalChunk(SharedContext.Current.Site); } } else { if (ZipHeader.IsFileHeader(content, 0)) { byte[] dataFileSignatureBytes; byte[] header = this.AnalyzeFileHeader(content, 0, out dataFileSignatureBytes); int headerLength = header.Length; int compressedSize = (int)this.GetCompressedSize(dataFileSignatureBytes); if (headerLength + compressedSize <= 4096) { if (Common.GetConfigurationPropertyValue("SutVersion", SharedContext.Current.Site) != "SharePointFoundation2010" && Common.GetConfigurationPropertyValue("SutVersion", SharedContext.Current.Site) != "SharePointServer2010") { LeafNodeObject expectNode = new LeafNodeObject.IntermediateNodeObjectBuilder().Build(content, this.GetSingleChunkSignature(header, dataFileSignatureBytes)); if (!expectNode.Signature.Equals(nodeObject.Signature)) { site.Assert.Fail("For the Zip file, when zip file is less than 4096, expect the signature {0}, actual signature {1}", expectNode.Signature.ToString(), nodeObject.Signature.ToString()); } } // Verify the zip file less than 4096 bytes MsfsshttpdCapture.VerifyZipFileLessThan4096Bytes(SharedContext.Current.Site); } else { SignatureObject expectHeader = this.GetSHA1Signature(header); if (!expectHeader.Equals(nodeObject.Signature)) { site.Assert.Fail("For the Zip file header, expect the signature {0}, actual signature {1}", expectHeader.ToString(), nodeObject.Signature.ToString()); } // Remove the header node cloneList.RemoveAt(0); // Then expect the next is file content node nodeObject = cloneList.First(); // Here having something need to be distinguished between the MOSS2010 and MOSS2013 if (nodeObject.DataNodeObjectData == null && nodeObject.IntermediateNodeObjectList != null) { if (Common.IsRequirementEnabled("MS-FSSHTTP-FSSHTTPB", 8213, SharedContext.Current.Site)) { bool isR8213Verified = false; if (compressedSize > 1024 * 1024 && nodeObject.IntermediateNodeObjectList.Count > 1) { isR8213Verified = true; } site.CaptureRequirementIfIsTrue( isR8213Verified, "MS-FSSHTTPD", 8213, @"[In Appendix A: Product Behavior] For implementation, if the number of .ZIP file bytes represented by a chunk is greater than 1 megabyte, a list of subchunks is generated. <4> Section 2.4.1: For SharePoint Server 2010, if the number of .ZIP file bytes represented by a chunk is greater than 1 megabyte, a list of subchunks is generated."); } if (Common.IsRequirementEnabled("MS-FSSHTTP-FSSHTTPB", 8207, SharedContext.Current.Site)) { bool isR8207Verified = false; if (compressedSize > 3 * 1024 * 1024 && nodeObject.IntermediateNodeObjectList.Count > 1) { isR8207Verified = true; } site.CaptureRequirementIfIsTrue( isR8207Verified, "MS-FSSHTTPD", 8207, @"[In Appendix A: Product Behavior] For implementation, if the number of .ZIP file bytes represented by a chunk is greater than 3 megabytes, a list of subchunks is generated. (Microsoft Office 2013/Microsoft SharePoint Foundation 2013/Microsoft SharePoint Server 2013/Microsoft SharePoint Workspace 2010/Microsft Office 2016/Microsft SharePoint Server 2016 follow this behavior.)"); } if (Common.IsRequirementEnabled("MS-FSSHTTP-FSSHTTPB", 8208, SharedContext.Current.Site) && Common.IsRequirementEnabled("MS-FSSHTTP-FSSHTTPB", 8210, SharedContext.Current.Site)) { bool isR8208Verified = true; bool isR8210Verified = true; if (nodeObject.IntermediateNodeObjectList[nodeObject.IntermediateNodeObjectList.Count - 1].DataSize.DataSize > 1024 * 1024) { isR8208Verified = false; } for (int i = 0; i < nodeObject.IntermediateNodeObjectList.Count - 1; i++) { if (nodeObject.IntermediateNodeObjectList[i].DataSize.DataSize != 1024 * 1024) { isR8210Verified = false; } } site.CaptureRequirementIfIsTrue( isR8208Verified, "MS-FSSHTTPD", 8208, @"[In Appendix A: Product Behavior] The size of each subchunk is at most 1 megabyte. (Microsoft SharePoint Server 2010 follows this behavior.)"); site.CaptureRequirementIfIsTrue( isR8210Verified, "MS-FSSHTTPD", 8210, @"[In Appendix A: Product Behavior] All but the last subchunk MUST be 1 megabyte in size. (Microsfot SharePoint Server 2010 follows this behavior.)"); } if (Common.IsRequirementEnabled("MS-FSSHTTP-FSSHTTPB", 8209, SharedContext.Current.Site) && Common.IsRequirementEnabled("MS-FSSHTTP-FSSHTTPB", 8211, SharedContext.Current.Site)) { bool isR8209Verified = true; bool isR8211Verified = true; if (nodeObject.IntermediateNodeObjectList[nodeObject.IntermediateNodeObjectList.Count - 1].DataSize.DataSize > 3 * 1024 * 1024) { isR8209Verified = false; } for (int i = 0; i < nodeObject.IntermediateNodeObjectList.Count - 1; i++) { if (nodeObject.IntermediateNodeObjectList[i].DataSize.DataSize != 3 * 1024 * 1024) { isR8211Verified = false; } } site.CaptureRequirementIfIsTrue( isR8209Verified, "MS-FSSHTTPD", 8209, @"[In Appendix A: Product Behavior] The size of each subchunk is at most 3 megabytes. (Microsoft Office 2013/Microsoft SharePoint Foundation 2013/Microsoft SharePoint Server 2013/Microsoft SharePoint Workspace 2010/Microsft Office 2016/Microsft SharePoint Server 2016 follow this behavior.)"); site.CaptureRequirementIfIsTrue( isR8211Verified, "MS-FSSHTTPD", 8211, @"[In Appendix A: Product Behavior] All but the last subchunk MUST be 3 megabyte in size. (Microsoft Office 2013/Microsoft SharePoint Foundation 2013/Microsoft SharePoint Server 2013/Microsoft SharePoint Workspace 2010/Microsft Office 2016/Microsft SharePoint Server 2016 follow this behavior.)"); } } else if (nodeObject.DataNodeObjectData != null) { site.Assert.AreEqual <ulong>( (ulong)compressedSize, nodeObject.DataSize.DataSize, "The Data Size of the Intermediate Node Object MUST be the total number of bytes represented by the chunk."); if (Common.GetConfigurationPropertyValue("SutVersion", SharedContext.Current.Site) != "SharePointFoundation2010" && Common.GetConfigurationPropertyValue("SutVersion", SharedContext.Current.Site) != "SharePointServer2010") { SignatureObject contentSignature = new SignatureObject(); contentSignature.SignatureData = new BinaryItem(dataFileSignatureBytes); if (!contentSignature.Equals(nodeObject.Signature)) { site.Assert.Fail("For the Zip file content, expect the signature {0}, actual signature {1}", contentSignature.ToString(), nodeObject.Signature.ToString()); } } // Verify the zip file larger than 4096 bytes and less than 1MB. if (SharedContext.Current.IsMsFsshttpRequirementsCaptured) { MsfsshttpdCapture.VerifyZipFileHeaderAndContentSignature(SharedContext.Current.Site); MsfsshttpdCapture.VerifyIntermediateNodeForZipFileChunk(SharedContext.Current.Site); } } else { throw new InvalidOperationException("The DataNodeObjectData and IntermediateNodeObjectList cannot be null at the same time."); } } } } cloneList.RemoveAt(0); } }
/// <summary> /// This method is used to verify the leaf node related requirements. /// </summary> /// <param name="instance">Specify the leaf node instance.</param> /// <param name="site">Specify the ITestSite instance.</param> public void VerifyLeafNodeObject(LeafNodeObject instance, ITestSite site) { // If the instance is not null and there are no parsing errors, then the LeafNodeObjectData related adapter requirements can be directly captured. if (null == instance) { site.Assert.Fail("The instance of type LeafNodeObjectData is null due to parsing error or type casting error."); } // Verify the stream object header related requirements. this.ExpectStreamObjectHeaderStart(instance.StreamObjectHeaderStart, instance.GetType(), site); // Verify MS-FSSHTTPD requirement: MS-FSSHTTPD_R55 site.CaptureRequirementIfAreEqual <Type>( typeof(StreamObjectHeaderStart16bit), instance.StreamObjectHeaderStart.GetType(), "MS-FSSHTTPD", 55, @"[In Leaf Node Object Data] Leaf Node Start (2 bytes): A 16-bit stream object header, as specified in [MS-FSSHTTPB] section 2.2.1.5.1, with a Header Type of 0x00, Compound of 0x1, Type of 0x1F, and Length of 0x00."); // Verify MS-FSSHTTPD requirement: MS-FSSHTTPD_R56 site.CaptureRequirementIfAreEqual <ushort>( 0xFC, LittleEndianBitConverter.ToUInt16(instance.StreamObjectHeaderStart.SerializeToByteList().ToArray(), 0), "MS-FSSHTTPD", 56, @"[In Leaf Node Object Data] Leaf Node Start (2 bytes): The value of this field[Leaf Node Start] MUST be 0x00FC."); // Verify MS-FSSHTTPD requirement: MS-FSSHTTPD_R57 site.CaptureRequirementIfAreEqual <Type>( typeof(StreamObjectHeaderStart16bit), instance.Signature.StreamObjectHeaderStart.GetType(), "MS-FSSHTTPD", 57, @"[In Leaf Node Object Data] Signature Header (2 bytes): A 16-bit stream object header, as specified in [MS-FSSHTTPB] section 2.2.1.5.1, with a Header Type of 0x00, Compound of 0x0, Type of 0x21, and Length equal to the size of Signature Data."); // Verify MS-FSSHTTPD requirement: MS-FSSHTTPD_R61 site.CaptureRequirementIfAreEqual <Type>( typeof(StreamObjectHeaderStart16bit), instance.DataSize.StreamObjectHeaderStart.GetType(), "MS-FSSHTTPD", 61, @"[In Leaf Node Object Data] Data Size Header (2 bytes): A 16-bit stream object header, as specified in [MS-FSSHTTPB] section 2.2.1.5.1, with a Header Type of 0x00, Compound of 0x0, Type of 0x22, and Length of 0x08 (the size, in bytes, of Data Size)."); // Verify MS-FSSHTTPD requirement: MS-FSSHTTPD_R8013 site.CaptureRequirementIfAreEqual <uint>( 0x1110, LittleEndianBitConverter.ToUInt16(instance.DataSize.StreamObjectHeaderStart.SerializeToByteList().ToArray(), 0), "MS-FSSHTTPD", 8013, @"[In Leaf Node Object Data] Data Size Header (2 bytes): The value of this field[Data Size Header] MUST be 0x1110."); // Verify MS-FSSHTTPD requirement: MS-FSSHTTPD_R1360 if (Common.IsRequirementEnabled("MS-FSSHTTP-FSSHTTPB", 1360, site)) { if (instance.DataHash != null) { site.CaptureRequirementIfAreEqual <Type>( typeof(StreamObjectHeaderStart16bit), instance.DataHash.StreamObjectHeaderStart.GetType(), "MS-FSSHTTPD", 1360, @"[In Appendix A: Product Behavior]Implementation does support the Data Hash Header(SharePoint Server 2016 and above follow this behavior.)"); site.CaptureRequirementIfAreEqual <Type>( typeof(BinaryItem), instance.DataHash.Data.GetType(), "MS-FSSHTTPD", 202, @"[In Leaf Node Object Data]Data Hash (variable): A binary item, as specified in [MS-FSSHTTPB] section 2.2.1.3, that specifies the data hash."); } } // Verify the stream object header end related requirements. this.ExpectStreamObjectHeaderEnd(instance.StreamObjectHeaderEnd, instance.GetType(), site); this.ExpectCompoundObject(instance.StreamObjectHeaderStart, site); if (instance.StreamObjectHeaderEnd != null) { // Verify MS-FSSHTTPD requirement: MS-FSSHTTPD_R63 site.CaptureRequirementIfAreEqual <Type>( typeof(StreamObjectHeaderEnd8bit), instance.StreamObjectHeaderEnd.GetType(), "MS-FSSHTTPD", 63, @"[In Leaf Node Object Data] Leaf Node End (1 byte): An 8-bit stream object header end, as specified in [MS-FSSHTTPB] section 2.2.1.5.3, that specifies a stream object of type 0x1F."); // Verify MS-FSSHTTPD requirement: MS-FSSHTTPD_R8014 site.CaptureRequirementIfAreEqual <byte>( 0x7D, instance.StreamObjectHeaderEnd.SerializeToByteList()[0], "MS-FSSHTTPD", 8014, @"[In Leaf Node Object Data] Leaf Node End (1 byte):The value of this field[Leaf Node End] MUST be 0x7D."); } }