public bool TryOpenFile(string filename, out StreamView stream) { if (!EntryMap.TryGetValue(filename, out var entry)) { stream = null; return(false); } stream = new StreamView(Stream, entry.DataPosition, entry.Length); return(true); }
private VirtualDirectory ConvertCvmToVirtualDirectory(VirtualFile cvmFile) { using (var stream = cvmFile.Open()) { var streamView = new StreamView(stream, 0x1800, stream.Length - 0x1800); var cvmIsoFilesystem = new CDReader(streamView, false); var directory = cvmIsoFilesystem.ToVirtualDirectory(); directory.Name = Path.GetFileNameWithoutExtension(cvmFile.Name); return(directory); } }
void BuildViews() { if (streamView == null) { // We initialize the streamview and keep a reference to it here because // both the ActivityStreamView and the SingleLineStreamView use this instace // and only effect the visual templates shown. This would not be the // best reference implementation for implementing stream views but in this // case it gets the job done. streamView = new StreamView(); view1 = new ActivityStreamViewHelper(state, streamView); view2 = new SingleLineViewHelper(state, streamView); } }
public void Test_STREAM_VIEW_2() { Stream b = null; List <Sector> temp = new List <Sector>(); StreamView sv = new StreamView(temp, 512, b); sv.Write(BitConverter.GetBytes(1), 0, 4); sv.Seek(0, SeekOrigin.Begin); BinaryReader br = new BinaryReader(sv); Int32 t = br.ReadInt32(); Assert.IsTrue(t == 1); }
private string GetTitle(StreamView view) { switch (view) { case StreamView.ExpandedView: return(Strings.Resources.StreamViewExpanded); case StreamView.ListView: return(Strings.Resources.StreamViewList); default: return(view.ToString("G")); } }
public static CryptoStream CreateDecryptorStream(Stream source, bool readHeader = true, bool skipSignature = false) { var decryptor = sAesManaged.CreateDecryptor(); if (!readHeader) { return(new CryptoStream(source, decryptor, CryptoStreamMode.Read)); } ReadHeader(source, skipSignature, out uint encryptedSize, out _); var streamView = new StreamView(source, source.Position, encryptedSize, true); return(new CryptoStream(streamView, decryptor, CryptoStreamMode.Read)); }
public void TEST_STREAM_VIEW() { Stream a = null; List <Sector> temp = new List <Sector>(); Sector s = new Sector(512); Buffer.BlockCopy(BitConverter.GetBytes((int)1), 0, s.GetData(), 0, 4); temp.Add(s); StreamView sv = new StreamView(temp, 512, 0, null, a); BinaryReader br = new BinaryReader(sv); Int32 t = br.ReadInt32(); Assert.IsTrue(t == 1); }
public void Test_STREAM_VIEW_LARGE_DATA() { Stream b = null; List <Sector> temp = new List <Sector>(); StreamView sv = new StreamView(temp, 512, b); for (int i = 0; i < 200; i++) { sv.Write(BitConverter.GetBytes(i), 0, 4); } sv.Seek(0, SeekOrigin.Begin); BinaryReader br = new BinaryReader(sv); for (int i = 0; i < 200; i++) { Assert.IsTrue(i == br.ReadInt32(), "Failed with " + i.ToString()); } }
/// <summary> /// Tries to open a file for reading. /// </summary> /// <param name="hash">Hash of the file.</param> /// <param name="stream">Readable stream of the file's data.</param> /// <returns>Whether the operation succeeded or not.</returns> public bool TryOpenFile(uint hash, out Stream stream) { if (!TryGetFileEntry(hash, out var entry)) { stream = null; return(false); } stream = new StreamView(mStream, entry.Offset, entry.CompressedSize); var headerBytes = new byte[2]; stream.Read(headerBytes, 0, 2); if (headerBytes[0] == 0x78) { stream = new DeflateStream(stream, CompressionMode.Decompress); } else { stream.Seek(-2, SeekOrigin.Current); } return(true); }
/// <summary> /// Sets the data for the current stream /// </summary> /// <param name="cfItem"></param> /// <param name="buffer"></param> /// <exception cref="CFException">Raised when <see cref="buffer" /> is null</exception> private void SetStreamData(CFItem cfItem, Byte[] buffer) { if (buffer == null) throw new CFException("Parameter [buffer] cannot be null"); // Quick and dirty :-) if (buffer.Length == 0) return; var directoryEntry = cfItem.DirEntry; var sectorType = SectorType.Normal; var sectorSize = GetSectorSize(); if (buffer.Length < _header.MinSizeStandardStream) { sectorType = SectorType.Mini; sectorSize = Sector.MinisectorSize; } // Check for transition ministream -> stream: // Only in this case we need to free old sectors, // otherwise they will be overwritten. if (directoryEntry.StartSector != Sector.Endofchain) { if ( (buffer.Length < _header.MinSizeStandardStream && directoryEntry.Size > _header.MinSizeStandardStream) || (buffer.Length > _header.MinSizeStandardStream && directoryEntry.Size < _header.MinSizeStandardStream) ) { if (directoryEntry.Size < _header.MinSizeStandardStream) { FreeMiniChain(GetMiniSectorChain(directoryEntry.StartSector), _eraseFreeSectors); } else { FreeChain(GetNormalSectorChain(directoryEntry.StartSector), _eraseFreeSectors); } directoryEntry.Size = 0; directoryEntry.StartSector = Sector.Endofchain; } } var sectorChain = GetSectorChain(directoryEntry.StartSector, sectorType); Queue<Sector> freeList = null; if (_sectorRecycle) freeList = FindFreeSectors(sectorType); // Collect available free sectors var streamView = new StreamView(sectorChain, sectorSize, buffer.Length, freeList, SourceStream); streamView.Write(buffer, 0, buffer.Length); switch (sectorType) { case SectorType.Normal: SetNormalSectorChain(streamView.BaseSectorChain); break; case SectorType.Mini: SetMiniSectorChain(streamView.BaseSectorChain); break; } if (streamView.BaseSectorChain.Count > 0) { directoryEntry.StartSector = streamView.BaseSectorChain[0].Id; directoryEntry.Size = buffer.Length; } else { directoryEntry.StartSector = Sector.Endofchain; directoryEntry.Size = 0; } }
/// <summary> /// Allocate space, setup sectors id and refresh header /// for the new or updated mini sector chain. /// </summary> /// <param name="sectorChain">The new MINI sector chain</param> private void SetMiniSectorChain(IList<Sector> sectorChain) { var miniFAT = GetSectorChain(_header.FirstMiniFATSectorId, SectorType.Normal); var miniStream = GetSectorChain(RootEntry.StartSector, SectorType.Normal); var miniFATView = new StreamView( miniFAT, GetSectorSize(), _header.MiniFATSectorsNumber*Sector.MinisectorSize, SourceStream ); var miniStreamView = new StreamView( miniStream, GetSectorSize(), RootStorage.Size, SourceStream); // Set updated/new sectors within the ministream foreach (var sector in sectorChain) { if (sector.Id != -1) { // Overwrite miniStreamView.Seek(Sector.MinisectorSize*sector.Id, SeekOrigin.Begin); miniStreamView.Write(sector.GetData(), 0, Sector.MinisectorSize); } else { // Allocate, position ministream at the end of already allocated // ministream's sectors miniStreamView.Seek(RootStorage.Size, SeekOrigin.Begin); miniStreamView.Write(sector.GetData(), 0, Sector.MinisectorSize); sector.Id = (int) (miniStreamView.Position - Sector.MinisectorSize)/Sector.MinisectorSize; RootStorage.DirEntry.Size = miniStreamView.Length; } } // Update miniFAT for (var i = 0; i < sectorChain.Count - 1; i++) { var currentId = sectorChain[i].Id; var nextId = sectorChain[i + 1].Id; //AssureLength(miniFATView, Math.Max(currentId * SIZE_OF_SID, nextId * SIZE_OF_SID)); miniFATView.Seek(currentId*4, SeekOrigin.Begin); miniFATView.Write(BitConverter.GetBytes(nextId), 0, 4); } // Write End of Chain in MiniFAT miniFATView.Seek(sectorChain[sectorChain.Count - 1].Id*SizeOfSID, SeekOrigin.Begin); miniFATView.Write(BitConverter.GetBytes(Sector.Endofchain), 0, 4); // Update sector chains SetNormalSectorChain(miniStreamView.BaseSectorChain); SetNormalSectorChain(miniFATView.BaseSectorChain); //Update HEADER and root storage when ministream changes if (miniFAT.Count > 0) { RootStorage.DirEntry.StartSector = miniStream[0].Id; _header.MiniFATSectorsNumber = (uint) miniFAT.Count; _header.FirstMiniFATSectorId = miniFAT[0].Id; } }
/// <summary> /// Allocate space, setup sectors id and refresh header /// for the new or updated FAT sector chain. /// </summary> /// <param name="sectorChain">The new or updated generic sector chain</param> private void SetFATSectorChain(IList<Sector> sectorChain) { var fatSectors = GetSectorChain(-1, SectorType.FAT); var fatStream = new StreamView( fatSectors, GetSectorSize(), _header.FATSectorsNumber*GetSectorSize(), SourceStream ); // Write FAT chain values -- for (var i = 0; i < sectorChain.Count - 1; i++) { var sN = sectorChain[i + 1]; var sC = sectorChain[i]; fatStream.Seek(sC.Id*4, SeekOrigin.Begin); fatStream.Write(BitConverter.GetBytes(sN.Id), 0, 4); } fatStream.Seek(sectorChain[sectorChain.Count - 1].Id*4, SeekOrigin.Begin); fatStream.Write(BitConverter.GetBytes(Sector.Endofchain), 0, 4); // Merge chain to CFS SetDIFATSectorChain(fatStream.BaseSectorChain); }
public override async Task ExecuteResultAsync(IWebDavResponse response, CancellationToken ct) { await base.ExecuteResultAsync(response, ct).ConfigureAwait(false); response.Headers["Accept-Ranges"] = new[] { "bytes" }; var properties = await _document.GetProperties(response.Dispatcher).ToList(ct).ConfigureAwait(false); var etagProperty = properties.OfType <GetETagProperty>().FirstOrDefault(); if (etagProperty != null) { var propValue = await etagProperty.GetValueAsync(ct).ConfigureAwait(false); response.Headers["ETag"] = new[] { propValue.ToString() }; } if (!_returnFile) { var lastModifiedProp = properties.OfType <LastModifiedProperty>().FirstOrDefault(); if (lastModifiedProp != null) { var propValue = await lastModifiedProp.GetValueAsync(ct).ConfigureAwait(false); response.Headers["Last-Modified"] = new[] { propValue.ToString("R") }; } return; } var views = new List <StreamView>(); try { foreach (var rangeItem in _rangeItems) { var baseStream = await _document.OpenReadAsync(ct).ConfigureAwait(false); var streamView = await StreamView .CreateAsync(baseStream, rangeItem.From, rangeItem.Length, ct) .ConfigureAwait(false); views.Add(streamView); } string contentType; var contentTypeProp = properties.OfType <GetContentTypeProperty>().FirstOrDefault(); if (contentTypeProp != null) { contentType = await contentTypeProp.GetValueAsync(ct).ConfigureAwait(false); } else { contentType = MimeTypesMap.DefaultMimeType; } HttpContent content; if (_rangeItems.Count == 1) { // No multipart content var rangeItem = _rangeItems.Single(); var streamView = views.Single(); content = new StreamContent(streamView); try { content.Headers.ContentRange = new ContentRangeHeaderValue(rangeItem.From, rangeItem.To, _document.Length); content.Headers.ContentLength = rangeItem.Length; } catch { content.Dispose(); throw; } content.Headers.ContentType = MediaTypeHeaderValue.Parse(contentType); } else { // Multipart content var multipart = new MultipartContent("byteranges"); try { var index = 0; foreach (var rangeItem in _rangeItems) { var streamView = views[index++]; var partContent = new StreamContent(streamView); partContent.Headers.ContentRange = new ContentRangeHeaderValue(rangeItem.From, rangeItem.To, _document.Length); partContent.Headers.ContentType = MediaTypeHeaderValue.Parse(contentType); partContent.Headers.ContentLength = rangeItem.Length; multipart.Add(partContent); } } catch { multipart.Dispose(); throw; } content = multipart; } using (content) { await SetPropertiesToContentHeaderAsync(content, properties, ct) .ConfigureAwait(false); foreach (var header in content.Headers) { response.Headers.Add(header.Key, header.Value.ToArray()); } await content.CopyToAsync(response.Body).ConfigureAwait(false); } } finally { foreach (var streamView in views) { streamView.Dispose(); } } }
/// <summary> /// Gets data from the <see cref="cFStream" /> /// </summary> /// <param name="cFStream"></param> /// <returns></returns> /// <exception cref="CFDisposedException">Raised when the file is closed</exception> internal byte[] GetData(CFStream cFStream) { if (IsClosed) throw new CFDisposedException("Compound File closed: cannot access data"); byte[] result; var directoryEntry = cFStream.DirEntry; if (directoryEntry.Size < _header.MinSizeStandardStream) { var miniView = new StreamView(GetSectorChain(directoryEntry.StartSector, SectorType.Mini), Sector.MinisectorSize, directoryEntry.Size, SourceStream); var br = new BinaryReader(miniView); result = br.ReadBytes((int) directoryEntry.Size); br.Close(); } else { var sView = new StreamView(GetSectorChain(directoryEntry.StartSector, SectorType.Normal), GetSectorSize(), directoryEntry.Size, SourceStream); result = new byte[(int) directoryEntry.Size]; sView.Read(result, 0, result.Length); } return result; }
/// <summary> /// Get the FAT sector chain /// </summary> /// <returns>List of FAT sectors</returns> private List<Sector> GetFatSectorChain() { const int numberOfHeaderFATEntry = 109; //Number of FAT sectors id in the header var result = new List<Sector>(); int nextSecId; var difatSectors = GetDifatSectorChain(); var idx = 0; // Read FAT entries from the header Fat entry array (max 109 entries) while (idx < _header.FATSectorsNumber && idx < numberOfHeaderFATEntry) { nextSecId = _header.DIFAT[idx]; var sector = _sectors[nextSecId]; if (sector == null) { sector = new Sector(GetSectorSize(), SourceStream) {Id = nextSecId, Type = SectorType.FAT}; _sectors[nextSecId] = sector; } result.Add(sector); idx++; } //Is there any DIFAT sector containing other FAT entries ? if (difatSectors.Count <= 0) return result; var difatStream = new StreamView ( difatSectors, GetSectorSize(), _header.FATSectorsNumber > numberOfHeaderFATEntry ? (_header.FATSectorsNumber - numberOfHeaderFATEntry)*4 : 0, SourceStream ); var nextDIFATSectorBuffer = new byte[4]; difatStream.Read(nextDIFATSectorBuffer, 0, 4); nextSecId = BitConverter.ToInt32(nextDIFATSectorBuffer, 0); var i = 0; var numberOfFatHeaderEntries = numberOfHeaderFATEntry; while (numberOfFatHeaderEntries < _header.FATSectorsNumber) { if (difatStream.Position == ((GetSectorSize() - 4) + i*GetSectorSize())) { difatStream.Seek(4, SeekOrigin.Current); i++; continue; } var sector = _sectors[nextSecId]; if (sector == null) { sector = new Sector(GetSectorSize(), SourceStream) {Type = SectorType.FAT, Id = nextSecId}; _sectors[nextSecId] = sector; //UUU } result.Add(sector); difatStream.Read(nextDIFATSectorBuffer, 0, 4); nextSecId = BitConverter.ToInt32(nextDIFATSectorBuffer, 0); numberOfFatHeaderEntries++; } return result; }
private void FreeMiniChain(IList<Sector> sectorChain, bool zeroSector) { var zeroedMiniSector = new byte[Sector.MinisectorSize]; var miniFAT = GetSectorChain(_header.FirstMiniFATSectorId, SectorType.Normal); var miniStream = GetSectorChain(RootEntry.StartSector, SectorType.Normal); var miniFATView = new StreamView(miniFAT, GetSectorSize(), _header.MiniFATSectorsNumber*Sector.MinisectorSize, SourceStream); var miniStreamView = new StreamView(miniStream, GetSectorSize(), RootStorage.Size, SourceStream); // Set updated/new sectors within the ministream if (zeroSector) { foreach (var sector in sectorChain) { if (sector.Id == -1) continue; // Overwrite miniStreamView.Seek(Sector.MinisectorSize*sector.Id, SeekOrigin.Begin); miniStreamView.Write(zeroedMiniSector, 0, Sector.MinisectorSize); } } // Update miniFAT for (var i = 0; i < sectorChain.Count - 1; i++) { var currentId = sectorChain[i].Id; miniFATView.Seek(currentId*4, SeekOrigin.Begin); miniFATView.Write(BitConverter.GetBytes(Sector.FreeSector), 0, 4); } //AssureLength(miniFATView, sectorChain[sectorChain.Count - 1].Id * SIZE_OF_SID); // Write End of Chain in MiniFAT miniFATView.Seek(sectorChain[sectorChain.Count - 1].Id*SizeOfSID, SeekOrigin.Begin); miniFATView.Write(BitConverter.GetBytes(Sector.FreeSector), 0, 4); // Update sector chains SetNormalSectorChain(miniStreamView.BaseSectorChain); SetNormalSectorChain(miniFATView.BaseSectorChain); //Update HEADER and root storage when ministream changes if (miniFAT.Count > 0) { RootStorage.DirEntry.StartSector = miniStream[0].Id; _header.MiniFATSectorsNumber = (uint) miniFAT.Count; _header.FirstMiniFATSectorId = miniFAT[0].Id; } }
private void FreeChain(IList<Sector> sectorChain, bool zeroSector) { var fat = GetSectorChain(-1, SectorType.FAT); var fatView = new StreamView(fat, GetSectorSize(), fat.Count*GetSectorSize(), SourceStream); // Zeroes out sector data (if requested) if (zeroSector) { foreach (var sector in sectorChain) sector.ZeroData(); } // Update FAT marking unallocated sectors for (var i = 0; i < sectorChain.Count - 1; i++) { var currentId = sectorChain[i].Id; //AssureLength(FATView, Math.Max(currentId * SIZE_OF_SID, nextId * SIZE_OF_SID)); fatView.Seek(currentId*4, SeekOrigin.Begin); fatView.Write(BitConverter.GetBytes(Sector.FreeSector), 0, 4); } }
/// <summary> /// Commit directory entries change on the Current Source stream /// </summary> private void CommitDirectory() { const int directorySize = 128; var directorySectors = GetSectorChain(_header.FirstDirectorySectorId, SectorType.Normal); var sv = new StreamView(directorySectors, GetSectorSize(), 0, SourceStream); foreach (var directoryEntry in _directoryEntries) directoryEntry.Write(sv); var delta = _directoryEntries.Count; while (delta%(GetSectorSize()/directorySize) != 0) { var dummy = new DirectoryEntry(StgType.StgInvalid); dummy.Write(sv); delta++; } foreach (var s in directorySectors) { s.Type = SectorType.Directory; } SetNormalSectorChain(directorySectors); _header.FirstDirectorySectorId = directorySectors[0].Id; // Version 4 supports directory sectors count _header.DirectorySectorsNumber = _header.MajorVersion == 3 ? 0 : directorySectors.Count; }
/// <summary> /// Check for transaction lock sector addition and mark it in the FAT. /// </summary> private void CheckForLockSector() { //If transaction lock has been added and not yet allocated in the FAT... if (TransactionLockAdded && !TransactionLockAllocated) { var fatStream = new StreamView(GetFatSectorChain(), GetSectorSize(), SourceStream); fatStream.Seek(LockSectorId*4, SeekOrigin.Begin); fatStream.Write(BitConverter.GetBytes(Sector.Endofchain), 0, 4); TransactionLockAllocated = true; } }
public ActivityStreamViewHelper(ConversationsState state, StreamView view) { this.state = state; this.view = view; }
/// <summary> /// Scan FAT o miniFAT for free sectors to reuse. /// </summary> /// <param name="sType">Type of sector to look for</param> /// <returns>A stack of available sectors or minisectors already allocated</returns> internal Queue<Sector> FindFreeSectors(SectorType sType) { var freeList = new Queue<Sector>(); if (sType == SectorType.Normal) { var fatChain = GetSectorChain(-1, SectorType.FAT); var fatStream = new StreamView(fatChain, GetSectorSize(), _header.FATSectorsNumber*GetSectorSize(), SourceStream); var idx = 0; while (idx < _sectors.Count) { var id = fatStream.ReadInt32(); if (id == Sector.FreeSector) { if (_sectors[idx] == null) { var sector = new Sector(GetSectorSize(), SourceStream) {Id = idx}; _sectors[idx] = sector; } freeList.Enqueue(_sectors[idx]); } idx++; } } else { var miniFAT = GetSectorChain(_header.FirstMiniFATSectorId, SectorType.Normal); var miniFATView = new StreamView(miniFAT, GetSectorSize(), _header.MiniFATSectorsNumber*Sector.MinisectorSize, SourceStream); var miniStream = GetSectorChain(RootEntry.StartSector, SectorType.Normal); var miniStreamView = new StreamView(miniStream, GetSectorSize(), RootStorage.Size, SourceStream); long ptr = 0; var nMinisectors = (int) (miniStreamView.Length/Sector.MinisectorSize); while (ptr < nMinisectors) { //AssureLength(miniStreamView, (int)miniFATView.Length); var id = miniFATView.ReadInt32(); ptr += 4; if (id != Sector.FreeSector) continue; var miniSector = new Sector(Sector.MinisectorSize, SourceStream) { Id = (int) ((ptr - 4)/4), Type = SectorType.Mini }; miniStreamView.Seek(miniSector.Id*Sector.MinisectorSize, SeekOrigin.Begin); miniStreamView.Read(miniSector.GetData(), 0, Sector.MinisectorSize); freeList.Enqueue(miniSector); } } return freeList; }
/// <summary> /// Gets data from the <see cref="cFStream" /> /// </summary> /// <param name="cFStream"></param> /// <param name="offset"></param> /// <param name="count"></param> /// <returns></returns> /// <exception cref="CFDisposedException">Raised when the file is closed</exception> internal byte[] GetData(CFStream cFStream, long offset, ref int count) { var directoryEntry = cFStream.DirEntry; count = (int) Math.Min(directoryEntry.Size - offset, count); StreamView streamView; if (directoryEntry.Size < _header.MinSizeStandardStream) { streamView = new StreamView(GetSectorChain(directoryEntry.StartSector, SectorType.Mini), Sector.MinisectorSize, directoryEntry.Size, SourceStream); } else { streamView = new StreamView(GetSectorChain(directoryEntry.StartSector, SectorType.Normal), GetSectorSize(), directoryEntry.Size, SourceStream); } var result = new byte[count]; streamView.Seek(offset, SeekOrigin.Begin); streamView.Read(result, 0, result.Length); return result; }
public StreamViewItem(StreamView view) { View = view; Title = GetTitle(view); }
public SingleLineViewHelper(ConversationsState state, StreamView view) { this.state = state; this.view = view; }
private string GetTitle(StreamView view) { switch (view) { case StreamView.ExpandedView: return Strings.Resources.StreamViewExpanded; case StreamView.ListView: return Strings.Resources.StreamViewList; default: return view.ToString("G"); } }
/// <summary> /// Load directory entries from compound file. Header and FAT MUST be already loaded. /// </summary> private void LoadDirectories() { var directoryChain = GetSectorChain(_header.FirstDirectorySectorId, SectorType.Normal); if (_header.FirstDirectorySectorId == Sector.Endofchain) _header.FirstDirectorySectorId = directoryChain[0].Id; var dirReader = new StreamView(directoryChain, GetSectorSize(), directoryChain.Count*GetSectorSize(), SourceStream); while (dirReader.Position < directoryChain.Count*GetSectorSize()) { var de = new DirectoryEntry(StgType.StgInvalid); //We are not inserting dirs. Do not use 'InsertNewDirectoryEntry' de.Read(dirReader); _directoryEntries.Add(de); de.SID = _directoryEntries.Count - 1; } }
/// <summary> /// Setup the DIFAT sector chain /// </summary> /// <param name="faTsectorChain">A FAT sector chain</param> private void SetDIFATSectorChain(List<Sector> faTsectorChain) { // Get initial sector's count _header.FATSectorsNumber = faTsectorChain.Count; // Allocate Sectors foreach (var s in faTsectorChain) { if (s.Id != -1) continue; _sectors.Add(s); s.Id = _sectors.Count - 1; s.Type = SectorType.FAT; } // Sector count... var nCurrentSectors = _sectors.Count; // Temp DIFAT count var nDIFATSectors = (int) _header.DIFATSectorsNumber; if (faTsectorChain.Count > HeaderDIFATEntriesCount) { nDIFATSectors = Ceiling((double) (faTsectorChain.Count - HeaderDIFATEntriesCount)/_difatSectorFATEntriesCount); nDIFATSectors = LowSaturation(nDIFATSectors - (int) _header.DIFATSectorsNumber); //required DIFAT } // ...sum with new required DIFAT sectors count nCurrentSectors += nDIFATSectors; // ReCheck FAT bias while (_header.FATSectorsNumber*_fatSectorEntriesCount < nCurrentSectors) { var extraFATSector = new Sector(GetSectorSize(), SourceStream); _sectors.Add(extraFATSector); extraFATSector.Id = _sectors.Count - 1; extraFATSector.Type = SectorType.FAT; faTsectorChain.Add(extraFATSector); _header.FATSectorsNumber++; nCurrentSectors++; //... so, adding a FAT sector may induce DIFAT sectors to increase by one // and consequently this may induce ANOTHER FAT sector (TO-THINK: May this condition occure ?) if (nDIFATSectors*_difatSectorFATEntriesCount >= (_header.FATSectorsNumber > HeaderDIFATEntriesCount ? _header.FATSectorsNumber - HeaderDIFATEntriesCount : 0)) continue; nDIFATSectors++; nCurrentSectors++; } var difatSectors = GetSectorChain(-1, SectorType.DIFAT); var difatStream = new StreamView(difatSectors, GetSectorSize(), SourceStream); // Write DIFAT Sectors (if required) // Save room for the following chaining for (var i = 0; i < faTsectorChain.Count; i++) { if (i < HeaderDIFATEntriesCount) _header.DIFAT[i] = faTsectorChain[i].Id; else { // room for DIFAT chaining at the end of any DIFAT sector (4 bytes) if (i != HeaderDIFATEntriesCount && (i - HeaderDIFATEntriesCount)%_difatSectorFATEntriesCount == 0) { var temp = new byte[sizeof (int)]; difatStream.Write(temp, 0, sizeof (int)); } difatStream.Write(BitConverter.GetBytes(faTsectorChain[i].Id), 0, sizeof (int)); } } // Allocate room for DIFAT sectors foreach (var sector in difatStream.BaseSectorChain) { if (sector.Id != -1) continue; _sectors.Add(sector); sector.Id = _sectors.Count - 1; sector.Type = SectorType.DIFAT; } _header.DIFATSectorsNumber = (uint) nDIFATSectors; // Chain first sector if (difatStream.BaseSectorChain != null && difatStream.BaseSectorChain.Count > 0) { _header.FirstDIFATSectorId = difatStream.BaseSectorChain[0].Id; // Update header information _header.DIFATSectorsNumber = (uint) difatStream.BaseSectorChain.Count; // Write chaining information at the end of DIFAT Sectors for (var i = 0; i < difatStream.BaseSectorChain.Count - 1; i++) { Buffer.BlockCopy( BitConverter.GetBytes(difatStream.BaseSectorChain[i + 1].Id), 0, difatStream.BaseSectorChain[i].GetData(), GetSectorSize() - sizeof (int), 4); } Buffer.BlockCopy( BitConverter.GetBytes(Sector.Endofchain), 0, difatStream.BaseSectorChain[difatStream.BaseSectorChain.Count - 1].GetData(), GetSectorSize() - sizeof (int), sizeof (int) ); } else _header.FirstDIFATSectorId = Sector.Endofchain; // Mark DIFAT Sectors in FAT var fatSv = new StreamView(faTsectorChain, GetSectorSize(), _header.FATSectorsNumber*GetSectorSize(), SourceStream); for (var i = 0; i < _header.DIFATSectorsNumber; i++) { fatSv.Seek(difatStream.BaseSectorChain[i].Id*4, SeekOrigin.Begin); fatSv.Write(BitConverter.GetBytes(Sector.DifSector), 0, 4); } for (var i = 0; i < _header.FATSectorsNumber; i++) { fatSv.Seek(fatSv.BaseSectorChain[i].Id*4, SeekOrigin.Begin); fatSv.Write(BitConverter.GetBytes(Sector.FATSector), 0, 4); } _header.FATSectorsNumber = fatSv.BaseSectorChain.Count; }
/// <summary> /// Get a mini sector chain /// </summary> /// <param name="sectorId">First sector id of the required chain</param> /// <returns>A list of mini sectors (64 bytes)</returns> private List<Sector> GetMiniSectorChain(int sectorId) { var result = new List<Sector>(); if (sectorId == Sector.Endofchain) return result; var miniFAT = GetNormalSectorChain(_header.FirstMiniFATSectorId); var miniStream = GetNormalSectorChain(RootEntry.StartSector); var miniFATView = new StreamView(miniFAT, GetSectorSize(), _header.MiniFATSectorsNumber*Sector.MinisectorSize, SourceStream); var miniStreamView = new StreamView(miniStream, GetSectorSize(), RootStorage.Size, SourceStream); var miniFATReader = new BinaryReader(miniFATView); var nextSectorId = sectorId; while (true) { if (nextSectorId == Sector.Endofchain) break; var miniSector = new Sector(Sector.MinisectorSize, SourceStream) { Id = nextSectorId, Type = SectorType.Mini }; miniStreamView.Seek(nextSectorId*Sector.MinisectorSize, SeekOrigin.Begin); miniStreamView.Read(miniSector.GetData(), 0, Sector.MinisectorSize); result.Add(miniSector); miniFATView.Seek(nextSectorId*4, SeekOrigin.Begin); nextSectorId = miniFATReader.ReadInt32(); } return result; }
public override async Task ExecuteResultAsync(IWebDavResponse response, CancellationToken ct) { await base.ExecuteResultAsync(response, ct); response.Headers["Accept-Ranges"] = new[] { "bytes" }; var properties = await _document.GetProperties(response.Dispatcher).ToList(ct); var etagProperty = properties.OfType <GetETagProperty>().FirstOrDefault(); if (etagProperty != null) { var propValue = await etagProperty.GetValueAsync(ct); response.Headers["ETag"] = new[] { propValue.ToString() }; } if (!_returnFile) { var lastModifiedProp = properties.OfType <LastModifiedProperty>().FirstOrDefault(); if (lastModifiedProp != null) { var propValue = await lastModifiedProp.GetValueAsync(ct); response.Headers["Last-Modified"] = new[] { propValue.ToString("R") }; } return; } var views = new List <StreamView>(); try { foreach (var rangeItem in _rangeItems) { var baseStream = await _document.OpenReadAsync(ct); var streamView = await StreamView .CreateAsync(baseStream, rangeItem.From, rangeItem.Length, ct) ; views.Add(streamView); } string contentType; var contentTypeProp = properties.OfType <GetContentTypeProperty>().FirstOrDefault(); if (contentTypeProp != null) { contentType = await contentTypeProp.GetValueAsync(ct); } else { contentType = MimeTypesMap.DefaultMimeType; } if (_rangeItems.Count == 1) { // No multipart content var rangeItem = _rangeItems.Single(); var streamView = views.Single(); using (var streamContent = new StreamContent(streamView)) { streamContent.Headers.ContentRange = new ContentRangeHeaderValue( rangeItem.From, rangeItem.To, _document.Length); streamContent.Headers.ContentLength = rangeItem.Length; streamContent.Headers.ContentType = MediaTypeHeaderValue.Parse(contentType); await SetPropertiesToContentHeaderAsync(streamContent, properties, ct) ; foreach (var header in streamContent.Headers) { response.Headers.Add(header.Key, header.Value.ToArray()); } // Use the CopyToAsync function of the stream itself, because // we're able to pass the cancellation token. This is a workaround // for issue dotnet/corefx#9071 and fixes FubarDevelopment/WebDavServer#47. await streamView.CopyToAsync(response.Body, 81920, ct) ; } } else { // Multipart content using (var multipart = new MultipartContent("byteranges")) { var index = 0; foreach (var rangeItem in _rangeItems) { var streamView = views[index++]; var partContent = new StreamContent(streamView); partContent.Headers.ContentRange = new ContentRangeHeaderValue( rangeItem.From, rangeItem.To, _document.Length); partContent.Headers.ContentType = MediaTypeHeaderValue.Parse(contentType); partContent.Headers.ContentLength = rangeItem.Length; multipart.Add(partContent); } await SetPropertiesToContentHeaderAsync(multipart, properties, ct) ; foreach (var header in multipart.Headers) { response.Headers.Add(header.Key, header.Value.ToArray()); } // TODO: Workaround for issue dotnet/corefx#9071 await multipart.CopyToAsync(response.Body); } } } finally { foreach (var streamView in views) { streamView.Dispose(); } } }
/// <summary> /// Get a standard sector chain /// </summary> /// <param name="secId">First SecID of the required chain</param> /// <returns>A list of sectors</returns> /// <exception cref="CFCorruptedFileException">Raised when the file is corrupt</exception> private List<Sector> GetNormalSectorChain(int secId) { var result = new List<Sector>(); var nextSecId = secId; var fatSectors = GetFatSectorChain(); var fatStream = new StreamView(fatSectors, GetSectorSize(), fatSectors.Count*GetSectorSize(), SourceStream); while (true) { if (nextSecId == Sector.Endofchain) break; if (nextSecId >= _sectors.Count) throw new CFCorruptedFileException( string.Format( "Next Sector ID reference an out of range sector. NextID : {0} while sector count {1}", nextSecId, _sectors.Count)); var sector = _sectors[nextSecId]; if (sector == null) { sector = new Sector(GetSectorSize(), SourceStream) {Id = nextSecId, Type = SectorType.Normal}; _sectors[nextSecId] = sector; } result.Add(sector); fatStream.Seek(nextSecId*4, SeekOrigin.Begin); var next = fatStream.ReadInt32(); if (next != nextSecId) nextSecId = next; else throw new CFCorruptedFileException("Cyclic sector chain found. File is corrupted"); } return result; }