internal void AddFile(ReconstructedFile file, ContentRange range) { if (this.closed) { throw new Exception("The assembler is closed."); } else { this.timestamp = file.Timestamp; if (this.filePartList.ContainsKey(range.Start)) { if (this.filePartList[range.Start].FileSize < file.FileSize) { this.filePartList[range.Start] = file; } } else { this.filePartList.Add(range.Start, file); } } }
internal ReconstructedFile Reassemble() { string destinationPath = FileStreamAssembler.GetFilePath(this.fileAssmeblyRootLocation, this.fiveTuple, this.transferIsClientToServer, this.fileStreamType, this.fileLocation, this.filename, this.parentAssemblerList, this.extendedFileId); ReconstructedFile reconstructedFile = null; using (System.IO.FileStream fullFileStream = new System.IO.FileStream(destinationPath, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.None, 256 * 1024)) {//256 kB buffer is probably a suitable value for good performance on large files foreach (KeyValuePair <long, ReconstructedFile> part in this.filePartList) { //if (fullFileStream.Position != part.Key) // fullFileStream.Seek(part.Key, System.IO.SeekOrigin.Begin); long partOffset = fullFileStream.Position - part.Key; if (partOffset < part.Key + part.Value.FileSize) { using (System.IO.FileStream partStream = new System.IO.FileStream(part.Value.FilePath, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read, 256 * 1024)) { if (partOffset > 0) { partStream.Seek(partOffset, System.IO.SeekOrigin.Begin); } //Stream.CopyTo isn't available in .NET 2.0 so I'll have to copy the data manually byte[] buffer = new byte[4096]; int bytesRead = partStream.Read(buffer, 0, buffer.Length); while (bytesRead > 0) { fullFileStream.Write(buffer, 0, bytesRead); bytesRead = partStream.Read(buffer, 0, buffer.Length); } } } } fullFileStream.Close();//so that I can read the full size of the file when creating the ReconstructedFile reconstructedFile = new ReconstructedFile(destinationPath, this.fiveTuple, this.transferIsClientToServer, this.fileStreamType, this.extendedFileId, this.initialFrameNumber, this.timestamp, this.serverHostname); } this.closed = true; this.filePartList.Clear(); return(reconstructedFile); }
internal Add(ReconstructedFile reconstructedFile, ContentRange contentRange) { //reconstructedFile.se bool fileTransferIsServerToClient = true; new FileSegmentAssembler(this.fileOutputDirectory, fileTransferIsServerToClient, reconstructedFile.Filename, reconstructedFile. }
internal void Close() { //TODO release all file handles and flush data to disk and move file from cache to server/port directory if (this.fileStream != null) { this.fileStream.Close(); } if (this.parentAssemblerList != null) { this.parentAssemblerList.Remove(this.uniqueFileId); } string fixedFilename = this.filePath;//no directory info string fixedFileLocation = ""; FileStreamAssembler.FixFilenameAndLocation(ref fixedFilename, ref fixedFileLocation); string destinationPath; //reassemble the files at the server, regardless if they were downloaded from there or uploaded to the server if (this.transferIsClientToServer) { destinationPath = FileStreamAssembler.GetFilePath(FileStreamAssembler.FileAssmeblyRootLocation.destination, this.fiveTuple, this.transferIsClientToServer, this.fileStreamType, fixedFileLocation, fixedFilename, this.fileStreamAssemblerList, ""); } else { destinationPath = FileStreamAssembler.GetFilePath(FileStreamAssembler.FileAssmeblyRootLocation.source, this.fiveTuple, this.transferIsClientToServer, this.fileStreamType, fixedFileLocation, fixedFilename, this.fileStreamAssemblerList, ""); } //I need to create the directory here since the file might either be moved to this located or a new file will be created there from a stream //string directoryName = destinationPath.Substring(0, destinationPath.Length - fixedFilename.Length); string directoryName = System.IO.Path.GetDirectoryName(destinationPath); if (!System.IO.Directory.Exists(directoryName)) { try { System.IO.Directory.CreateDirectory(directoryName); } catch (Exception e) { this.fileStreamAssemblerList.PacketHandler.OnAnomalyDetected("Error creating directory \"" + directoryName + "\" for path \"" + destinationPath + "\".\n" + e.Message); } } //files which are already completed can simply be moved to their final destination if (this.fileStream != null) { this.fileStream.Close(); } try { //string tmpPath = this.tempFilePath; if (System.IO.File.Exists(this.tempFilePath)) { System.IO.File.Move(this.tempFilePath, destinationPath); } } catch (Exception e) { this.fileStreamAssemblerList.PacketHandler.OnAnomalyDetected("Error moving file \"" + this.tempFilePath + "\" to \"" + destinationPath + "\". " + e.Message); } if (System.IO.File.Exists(destinationPath)) { try { ReconstructedFile completedFile = new ReconstructedFile(destinationPath, this.fiveTuple, this.transferIsClientToServer, this.fileStreamType, this.details, this.initialFrameNumber, this.initialTimeStamp, this.serverHostname); this.fileStreamAssemblerList.PacketHandler.AddReconstructedFile(completedFile); //parentAssemblerList.PacketHandler.ParentForm.ShowReconstructedFile(completedFile); } catch (Exception e) { this.fileStreamAssemblerList.PacketHandler.OnAnomalyDetected("Error creating reconstructed file: " + e.Message); } } }
/// <summary> /// Closes the fileStream and removes the FileStreamAssembler from the parentAssemblerList /// </summary> internal void FinishAssembling() { this.isActive = false; try { foreach (byte[] data in tcpPacketBufferWindow.Values) { this.fileStream.Write(data, 0, data.Length); } this.fileStream.Flush(); } catch (Exception ex) { if (fileStream != null) { parentAssemblerList.PacketHandler.OnAnomalyDetected("Error writing final data to file \"" + fileStream.Name + "\".\n" + ex.Message); } else { parentAssemblerList.PacketHandler.OnAnomalyDetected("Error writing final data to file \"" + this.filename + "\".\n" + ex.Message); } } tcpPacketBufferWindow.Clear(); parentAssemblerList.Remove(this, false); string destinationPath = GetFilePath(false); //I need to create the directory here since the file might either be moved to this located or a new file will be created there from a stream string directoryName = destinationPath.Substring(0, destinationPath.Length - this.filename.Length); if (this.fileStreamType != FileStreamTypes.HttpPostMimeMultipartFormData && !System.IO.Directory.Exists(directoryName)) { try { System.IO.Directory.CreateDirectory(directoryName); } catch (Exception e) { parentAssemblerList.PacketHandler.OnAnomalyDetected("Error creating directory \"" + directoryName + "\".\n" + e.Message); //parentAssemblerList.PacketHandler.ParentForm.ShowError("Error creating directory \""+directoryName+"\".\n"+e.Message); } } if (System.IO.File.Exists(destinationPath)) { try { System.IO.File.Delete(destinationPath); } catch (Exception e) { parentAssemblerList.PacketHandler.OnAnomalyDetected("Error deleting file \"" + destinationPath + "\" (tried to replace it)"); //parentAssemblerList.PacketHandler.ParentForm.ShowError("Error deleting file \""+destinationPath+"\" (tried to replace it)"); } } //do some special fixes such as un-chunk data or decompress compressed data if (this.fileStreamType == FileStreamTypes.HttpGetChunked || (parentAssemblerList.DecompressGzipStreams && this.contentEncoding == Packets.HttpPacket.ContentEncodings.Gzip) || this.contentEncoding == Packets.HttpPacket.ContentEncodings.Deflate) { this.fileStream.Position = 0;//move to fileStream start since it needs to be read if (this.fileStreamType == FileStreamTypes.HttpGetChunked && (parentAssemblerList.DecompressGzipStreams && this.contentEncoding == Packets.HttpPacket.ContentEncodings.Gzip)) { using (DeChunkedDataStream deChunkedStream = new DeChunkedDataStream(this.fileStream)) { using (System.IO.Compression.GZipStream decompressedStream = new System.IO.Compression.GZipStream(deChunkedStream, System.IO.Compression.CompressionMode.Decompress)) { try { this.WriteStreamToFile(decompressedStream, destinationPath); } catch (Exception e) { this.parentAssemblerList.PacketHandler.OnAnomalyDetected("Error: Cannot write to file " + destinationPath + " (" + e.Message + ")"); //this.parentAssemblerList.PacketHandler.ParentForm.ShowError("Error: Cannot write to file "+destinationPath+" ("+e.Message+")"); } decompressedStream.Close(); } deChunkedStream.Close(); } } else if (this.fileStreamType == FileStreamTypes.HttpGetChunked && this.contentEncoding == Packets.HttpPacket.ContentEncodings.Deflate) { using (DeChunkedDataStream deChunkedStream = new DeChunkedDataStream(this.fileStream)) { using (System.IO.Compression.DeflateStream decompressedStream = new System.IO.Compression.DeflateStream(deChunkedStream, System.IO.Compression.CompressionMode.Decompress)) { try { this.WriteStreamToFile(decompressedStream, destinationPath); } catch (Exception e) { this.parentAssemblerList.PacketHandler.OnAnomalyDetected("Error: Cannot write to file " + destinationPath + " (" + e.Message + ")"); //this.parentAssemblerList.PacketHandler.ParentForm.ShowError("Error: Cannot write to file "+destinationPath+" ("+e.Message+")"); } decompressedStream.Close(); } deChunkedStream.Close(); } } else if (this.fileStreamType == FileStreamTypes.HttpGetChunked) { using (DeChunkedDataStream deChunkedStream = new DeChunkedDataStream(this.fileStream)) { try { this.WriteStreamToFile(deChunkedStream, destinationPath); } catch (Exception e) { this.parentAssemblerList.PacketHandler.OnAnomalyDetected("Error: Cannot write to file " + destinationPath + " (" + e.Message + ")"); //this.parentAssemblerList.PacketHandler.ParentForm.ShowError("Error: Cannot write to file "+destinationPath+" ("+e.Message+")"); } deChunkedStream.Close(); } } else { using (System.IO.Compression.GZipStream decompressedStream = new System.IO.Compression.GZipStream(this.fileStream, System.IO.Compression.CompressionMode.Decompress)) { try { this.WriteStreamToFile(decompressedStream, destinationPath); } catch (Exception e) { this.parentAssemblerList.PacketHandler.OnAnomalyDetected("Error: Cannot write to file " + destinationPath + " (" + e.Message + ")"); //this.parentAssemblerList.PacketHandler.ParentForm.ShowError("Error: Cannot write to file "+destinationPath+" ("+e.Message+")"); } decompressedStream.Close(); } } this.fileStream.Close(); System.IO.File.Delete(GetFilePath(true));//delete the temp file } else if (this.fileStreamType == FileStreamTypes.HttpPostMimeMultipartFormData) { Mime.UnbufferedReader mimeReader = new PacketParser.Mime.UnbufferedReader(this.fileStream); List <Mime.MultipartPart> parts = new List <PacketParser.Mime.MultipartPart>(); foreach (Mime.MultipartPart part in Mime.PartBuilder.GetParts(mimeReader, this.Details)) { parts.Add(part); } this.parentAssemblerList.PacketHandler.ExtractMultipartFormData(parts, sourceHost, destinationHost, timestamp, this.initialFrameNumber, "TCP " + sourcePort, "TCP " + destinationPort, ApplicationLayerProtocol.Unknown); foreach (Mime.MultipartPart part in parts) { if (part.Attributes["filename"] != null && part.Attributes["filename"].Length > 0 && part.Data != null && part.Data.Length > 0) { //we have a file! string mimeFileLocation = part.Attributes["filename"]; if (mimeFileLocation.Contains("/")) { mimeFileLocation = mimeFileLocation.Substring(0, mimeFileLocation.LastIndexOf('/')); } if (mimeFileLocation.Contains("\\")) { mimeFileLocation = mimeFileLocation.Substring(0, mimeFileLocation.LastIndexOf('\\')); } string mimeFileName = part.Attributes["filename"]; if (mimeFileName.Contains("/") && mimeFileName.Length > mimeFileName.LastIndexOf('/') + 1) { mimeFileName = mimeFileName.Substring(mimeFileName.LastIndexOf('/') + 1); } if (mimeFileName.Contains("\\") && mimeFileName.Length > mimeFileName.LastIndexOf('\\') + 1) { mimeFileName = mimeFileName.Substring(mimeFileName.LastIndexOf('\\') + 1); } using (FileStreamAssembler partAssembler = new FileStreamAssembler(this.parentAssemblerList, this.sourceHost, this.sourcePort, this.destinationHost, this.destinationPort, this.tcpTransfer, FileStreamTypes.HttpPostMimeFileData, mimeFileName, mimeFileLocation, part.Attributes["filename"], this.initialFrameNumber, this.timestamp)) { this.parentAssemblerList.Add(partAssembler); partAssembler.FileContentLength = part.Data.Length; partAssembler.FileSegmentRemainingBytes = part.Data.Length; if (partAssembler.TryActivate()) { partAssembler.AddData(part.Data, 0); } } /* * FixFilenameAndLocation(ref mimeFileName, ref mimeFileLocation); * string mimeFilePath=GetFilePath(false, this.tcpTransfer, this.sourceHost.IPAddress, this.destinationHost.IPAddress, this.sourcePort, this.destinationPort, this.fileStreamType, mimeFileLocation, mimeFileName, this.parentAssemblerList); * Mime.ByteArrayStream partDataStream=new PacketParser.Mime.ByteArrayStream(part.Data, 0); * pare * this.WriteStreamToFile(partDataStream, mimeFilePath); * try { * ReconstructedFile completedFile=new ReconstructedFile(mimeFilePath, sourceHost, destinationHost, sourcePort, destinationPort, tcpTransfer, fileStreamType, "boundary="+details, this.initialFrameNumber, this.timestamp); * parentAssemblerList.PacketHandler.AddReconstructedFile(completedFile); * //parentAssemblerList.PacketHandler.ParentForm.ShowReconstructedFile(completedFile); * } * catch(Exception e) { * this.parentAssemblerList.PacketHandler.OnAnomalyDetected("Error creating reconstructed file: "+e.Message); * }*/ } } this.fileStream.Close(); System.IO.File.Delete(GetFilePath(true)); } else //files which are already completed can simply be moved to their final destination { if (this.fileStream != null) { this.fileStream.Close(); } try { string tmpPath = GetFilePath(true); if (System.IO.File.Exists(tmpPath)) { System.IO.File.Move(tmpPath, destinationPath); } } catch (Exception e) { this.parentAssemblerList.PacketHandler.OnAnomalyDetected("Error moving file \"" + GetFilePath(true) + "\" to \"" + destinationPath + "\". " + e.Message); } } if (System.IO.File.Exists(destinationPath)) { try { ReconstructedFile completedFile = new ReconstructedFile(destinationPath, sourceHost, destinationHost, sourcePort, destinationPort, tcpTransfer, fileStreamType, details, this.initialFrameNumber, this.timestamp); parentAssemblerList.PacketHandler.AddReconstructedFile(completedFile); //parentAssemblerList.PacketHandler.ParentForm.ShowReconstructedFile(completedFile); } catch (Exception e) { this.parentAssemblerList.PacketHandler.OnAnomalyDetected("Error creating reconstructed file: " + e.Message); } } }