/// <summary> /// Reads data from the file. /// </summary> /// <param name="volumeIndex">The volume index of the file.</param> /// <param name="item">The item containing information about the file to read.</param> /// <param name="buffer">The buffer to read the data</param> /// <returns>Returns true if the data was read successfully.</returns> private bool ReadFromFile(int volumeIndex, ref UdfRecord item, ref byte[] buffer) { if (item.Size >= MaxExtents) { return(false); } if (item.IsInline) { buffer = item.InlineData; return(true); } buffer = new byte[item.Size]; int position = 0; for (int i = 0; i < item.Extents.Count; i++) { FileExtent e = item.Extents[i]; int length = e.Length; byte[] b = UdfHelper.Readbytes(position, buffer, buffer.Length); if (!this.ReadData(volumeIndex, e.PartitionReference, e.Position, length, b)) { return(false); } position += length; } return(true); }
/// <summary> /// Reads the data from the image for a record. /// </summary> /// <param name="item">The item to read the data into.</param> /// <param name="volumeIndex">The index of the volume the file resides on.</param> /// <param name="lad">The long allocation descriptor of the file.</param> /// <param name="numRecurseAllowed">The number of recursions allowed before the method fails.</param> /// <returns>Returns true if the record was read successfully.</returns> private bool ReadRecordData(UdfRecord item, int volumeIndex, LongAllocationDescriptor lad, int numRecurseAllowed) { if (this.itemCount > MaxItems) { return(false); } LogicalVolume volume = this.LogicalVolumes[volumeIndex]; if (lad.Length != volume.BlockSize) { return(false); } // Read the record. int size = lad.Length; byte[] buffer = new byte[size]; if (!this.ReadData(volumeIndex, lad, buffer)) { return(false); } // Validate the tag is a file. VolumeTag tag = new VolumeTag(); tag.Parse(0, buffer, size); if (tag.Identifier != (short)VolumeDescriptorType.File) { return(false); } // Validate the IcbTage indicates file or directory. item.IcbTag.Parse(16, buffer); if (item.IcbTag.FileType != IcbFileType.Directory && item.IcbTag.FileType != IcbFileType.File) { return(false); } item.Parse(buffer); int extendedAttrLen = UdfHelper.Get32(168, buffer); int allocDescriptorsLen = UdfHelper.Get32(172, buffer); if ((extendedAttrLen & 3) != 0) { return(false); } int position = 176; if (extendedAttrLen > size - position) { return(false); } position += extendedAttrLen; IcbDescriptorType desctType = item.IcbTag.DescriptorType; if (allocDescriptorsLen > size - position) { return(false); } if (desctType == IcbDescriptorType.Inline) { // If the file data is inline, read it in now since we have it. item.IsInline = true; item.InlineData = UdfHelper.Readbytes(position, buffer, allocDescriptorsLen); } else { // Otherwise read the information about where the file is located for later. item.IsInline = false; item.InlineData = new byte[0]; if ((desctType != IcbDescriptorType.Short) && (desctType != IcbDescriptorType.Long)) { return(false); } for (int index = 0; index < allocDescriptorsLen;) { FileExtent extent = new FileExtent(); if (desctType == IcbDescriptorType.Short) { if (index + 8 > allocDescriptorsLen) { return(false); } ShortAllocationDescriptor sad = new ShortAllocationDescriptor(); sad.Parse(position + index, buffer); extent.Position = sad.Position; extent.Length = sad.Length; extent.PartitionReference = lad.Location.PartitionReference; index += 8; } else { if (index + 16 > allocDescriptorsLen) { return(false); } LongAllocationDescriptor ladNew = new LongAllocationDescriptor(); ladNew.Parse(position + index, buffer); extent.Position = ladNew.Location.Position; extent.PartitionReference = ladNew.Location.PartitionReference; extent.Length = ladNew.Length; index += 16; } item.Extents.Add(extent); } } if (item.IcbTag.IsDirectory) { if (!item.CheckChunkSizes() || !this.CheckItemExtents(volumeIndex, item)) { return(false); } buffer = new byte[0]; if (!this.ReadFromFile(volumeIndex, ref item, ref buffer)) { return(false); } item._size = 0; item.Extents.Clear(); size = buffer.Length; int processedTotal = 0; int processedCur = -1; while (processedTotal < size || processedCur == 0) { UdfFileInformation fileId = new UdfFileInformation(); fileId.Parse(processedTotal, buffer, (size - processedTotal), ref processedCur); if (!fileId.IsItLinkParent) { // Recursively read the contentst of the drirectory UdfRecord fileItem = new UdfRecord(); fileItem.Id = fileId.Identifier; if (fileItem.Id.Data != null) { this.fileNameLengthTotal += fileItem.Id.Data.Length; } if (this.fileNameLengthTotal > MaxFileNameLength) { return(false); } fileItem._Parent = item; item.Subitems.Add(fileItem); if (item.Subitems.Count > MaxFiles) { return(false); } this.ReadRecord(fileItem, volumeIndex, fileId.Icb, numRecurseAllowed); } processedTotal += processedCur; } } else { if (item.Extents.Count > MaxExtents - this.numExtents) { return(false); } this.numExtents += item.Extents.Count; if (item.InlineData.Length > MaxInlineExtentsSize - this.inlineExtentsSize) { return(false); } this.inlineExtentsSize += item.InlineData.Length; } this.itemCount++; return(true); }
/// <summary> /// Reads the data from the image for a record. /// </summary> /// <param name="item">The item to read the data into.</param> /// <param name="volumeIndex">The index of the volume the file resides on.</param> /// <param name="lad">The long allocation descriptor of the file.</param> /// <param name="numRecurseAllowed">The number of recursions allowed before the method fails.</param> /// <returns>Returns true if the record was read successfully.</returns> private bool ReadRecordData(UdfRecord item, int volumeIndex, LongAllocationDescriptor lad, int numRecurseAllowed) { if (this.itemCount > MaxItems) { return false; } LogicalVolume volume = this.LogicalVolumes[volumeIndex]; if (lad.Length != volume.BlockSize) { return false; } // Read the record. int size = lad.Length; byte[] buffer = new byte[size]; if (!this.ReadData(volumeIndex, lad, buffer)) { return false; } // Validate the tag is a file. VolumeTag tag = new VolumeTag(); tag.Parse(0, buffer, size); if (tag.Identifier != (short)VolumeDescriptorType.File) { return false; } // Validate the IcbTage indicates file or directory. item.IcbTag.Parse(16, buffer); if (item.IcbTag.FileType != IcbFileType.Directory && item.IcbTag.FileType != IcbFileType.File) { return false; } item.Parse(buffer); int extendedAttrLen = UdfHelper.Get32(168, buffer); int allocDescriptorsLen = UdfHelper.Get32(172, buffer); if ((extendedAttrLen & 3) != 0) { return false; } int position = 176; if (extendedAttrLen > size - position) { return false; } position += extendedAttrLen; IcbDescriptorType desctType = item.IcbTag.DescriptorType; if (allocDescriptorsLen > size - position) { return false; } if (desctType == IcbDescriptorType.Inline) { // If the file data is inline, read it in now since we have it. item.IsInline = true; item.InlineData = UdfHelper.Readbytes(position, buffer, allocDescriptorsLen); } else { // Otherwise read the information about where the file is located for later. item.IsInline = false; item.InlineData = new byte[0]; if ((desctType != IcbDescriptorType.Short) && (desctType != IcbDescriptorType.Long)) { return false; } for (int index = 0; index < allocDescriptorsLen;) { FileExtent extent = new FileExtent(); if (desctType == IcbDescriptorType.Short) { if (index + 8 > allocDescriptorsLen) { return false; } ShortAllocationDescriptor sad = new ShortAllocationDescriptor(); sad.Parse(position + index, buffer); extent.Position = sad.Position; extent.Length = sad.Length; extent.PartitionReference = lad.Location.PartitionReference; index += 8; } else { if (index + 16 > allocDescriptorsLen) { return false; } LongAllocationDescriptor ladNew = new LongAllocationDescriptor(); ladNew.Parse(position + index, buffer); extent.Position = ladNew.Location.Position; extent.PartitionReference = ladNew.Location.PartitionReference; extent.Length = ladNew.Length; index += 16; } item.Extents.Add(extent); } } if (item.IcbTag.IsDirectory) { if (!item.CheckChunkSizes() || !this.CheckItemExtents(volumeIndex, item)) { return false; } buffer = new byte[0]; if (!this.ReadFromFile(volumeIndex, ref item, ref buffer)) { return false; } item._size = 0; item.Extents.Clear(); size = buffer.Length; int processedTotal = 0; int processedCur = -1; while (processedTotal < size || processedCur == 0) { UdfFileInformation fileId = new UdfFileInformation(); fileId.Parse(processedTotal, buffer, (size - processedTotal), ref processedCur); if (!fileId.IsItLinkParent) { // Recursively read the contentst of the drirectory UdfRecord fileItem = new UdfRecord(); fileItem.Id = fileId.Identifier; if (fileItem.Id.Data != null) { this.fileNameLengthTotal += fileItem.Id.Data.Length; } if (this.fileNameLengthTotal > MaxFileNameLength) { return false; } fileItem._Parent = item; item.Subitems.Add(fileItem); if (item.Subitems.Count > MaxFiles) { return false; } this.ReadRecord(fileItem, volumeIndex, fileId.Icb, numRecurseAllowed); } processedTotal += processedCur; } } else { if (item.Extents.Count > MaxExtents - this.numExtents) { return false; } this.numExtents += item.Extents.Count; if (item.InlineData.Length > MaxInlineExtentsSize - this.inlineExtentsSize) { return false; } this.inlineExtentsSize += item.InlineData.Length; } this.itemCount++; return true; }