private Parse ( Stream stream, String toBoundary ) : bool | ||
stream | Stream | Data stream from where to read data. |
toBoundary | String | Entity data is readed to specified boundary. |
Результат | bool |
/// <summary> /// Parses mime entity from stream. /// </summary> /// <param name="stream">Data stream from where to read data.</param> /// <param name="toBoundary">Entity data is readed to specified boundary.</param> /// <returns>Returns false if last entity. Returns true for mulipart entity, if there are more entities.</returns> internal bool Parse(SmartStream stream,string toBoundary) { // Clear header fields m_pHeader.Clear(); m_pHeaderFieldCache.Clear(); // Parse header m_pHeader.Parse(stream); // Parse entity and child entities if any (Conent-Type: multipart/xxx...) // Multipart entity if((this.ContentType & MediaType_enum.Multipart) != 0){ // There must be be boundary ID (rfc 1341 7.2.1 The Content-Type field for multipart entities requires one parameter, // "boundary", which is used to specify the encapsulation boundary.) string boundaryID = this.ContentType_Boundary; if(boundaryID == null){ // This is invalid message, just skip this mime entity } else{ // There is one or more mime entities // Find first boundary start position SmartStream.ReadLineAsyncOP args = new SmartStream.ReadLineAsyncOP(new byte[8000],SizeExceededAction.JunkAndThrowException); stream.ReadLine(args,false); if(args.Error != null){ throw args.Error; } string lineString = args.LineUtf8; while(lineString != null){ if(lineString.StartsWith("--" + boundaryID)){ break; } stream.ReadLine(args,false); if(args.Error != null){ throw args.Error; } lineString = args.LineUtf8; } // This is invalid entity, boundary start not found. Skip that entity. if(string.IsNullOrEmpty(lineString)){ return false; } // Start parsing child entities of this entity while(true){ // Parse and add child entity MimeEntity childEntity = new MimeEntity(); this.ChildEntities.Add(childEntity); // This is last entity, stop parsing if(childEntity.Parse(stream,boundaryID) == false){ break; } // else{ // There are more entities, parse them } // This entity is child of mulipart entity. // All this entity child entities are parsed, // we need to move stream position to next entity start. if(!string.IsNullOrEmpty(toBoundary)){ stream.ReadLine(args,false); if(args.Error != null){ throw args.Error; } lineString = args.LineUtf8; while(lineString != null){ if(lineString.StartsWith("--" + toBoundary)){ break; } stream.ReadLine(args,false); if(args.Error != null){ throw args.Error; } lineString = args.LineUtf8; } // Invalid boundary end, there can't be more entities if(string.IsNullOrEmpty(lineString)){ return false; } // See if last boundary or there is more. Last boundary ends with -- if(lineString.EndsWith(toBoundary + "--")){ return false; } // else{ // There are more entities return true; } } } // Singlepart entity. else{ // Boundary is specified, read data to specified boundary. if(!string.IsNullOrEmpty(toBoundary)){ MemoryStream entityData = new MemoryStream(); SmartStream.ReadLineAsyncOP readLineOP = new SmartStream.ReadLineAsyncOP(new byte[32000],SizeExceededAction.JunkAndThrowException); // Read entity data while get boundary end tag --boundaryID-- or EOS. while(true){ stream.ReadLine(readLineOP,false); if(readLineOP.Error != null){ throw readLineOP.Error; } // End of stream reached. Normally we should get boundary end tag --boundaryID--, but some x mailers won't add it, so // if we reach EOS, consider boundary closed. if(readLineOP.BytesInBuffer == 0){ // Just return data what was readed. m_EncodedData = entityData.ToArray(); return false; } // We readed a line. else{ // We have boundary start/end tag or just "--" at the beginning of line. if(readLineOP.LineBytesInBuffer >= 2 && readLineOP.Buffer[0] == '-' && readLineOP.Buffer[1] == '-'){ string lineString = readLineOP.LineUtf8; // We have boundary end tag, no more boundaries. if(lineString == "--" + toBoundary + "--"){ m_EncodedData = entityData.ToArray(); return false; } // We have new boundary start. else if(lineString == "--" + toBoundary){ m_EncodedData = entityData.ToArray(); return true; } else{ // Just skip } } // Write readed line. entityData.Write(readLineOP.Buffer,0,readLineOP.BytesInBuffer); } } } // Boundary isn't specified, read data to the stream end. else{ MemoryStream ms = new MemoryStream(); stream.ReadAll(ms); m_EncodedData = ms.ToArray(); } } return false; }
/// <summary> /// Parses mime entity from stream. /// </summary> /// <param name="stream">Data stream from where to read data.</param> /// <param name="toBoundary">Entity data is readed to specified boundary.</param> /// <returns>Returns false if last entity. Returns true for mulipart entity, if there are more entities.</returns> internal bool Parse(Stream stream,String toBoundary) { // Clear header fields m_pHeader.Clear(); m_pHeaderFieldCache.Clear(); // Parse header m_pHeader.Parse(stream); // Parse entity and child entities if any (Conent-Type: multipart/xxx...) // Multipart entity if((this.ContentType & MediaType_enum.Multipart) != 0){ // There must be be boundary ID (rfc 1341 7.2.1 The Content-Type field for multipart entities requires one parameter, "boundary", which is used to specify the encapsulation boundary.) String boundaryID = this.ContentType_Boundary; if(boundaryID == null){ // This is invalid message, just skip this mime entity } else{ // There is one or more mime entities // Find first boundary start position StreamLineReader reader = new StreamLineReader(stream); byte[] lineData = reader.ReadLine(); while(lineData != null){ string line = System.Text.Encoding.Default.GetString(lineData); if(line.StartsWith("--" + boundaryID)){ break; } lineData = reader.ReadLine(); } // This is invalid entity, boundary start not found. Skip that entity. if(lineData == null){ return false; } // Start parsing child entities ot this entity while(true){ // Parse and add child entity MimeEntity childEntity = new MimeEntity(); this.ChildEntities.Add(childEntity); // This is last entity, stop parsing if(childEntity.Parse(stream,boundaryID) == false){ break; } // else{ // There are more entities, parse them } // This entity is child of mulipart entity. // All this entity child entities are parsed, // we need to move stream position to next entity start. if(toBoundary != null && toBoundary.Length > 0){ lineData = reader.ReadLine(); while(lineData != null){ String line = System.Text.Encoding.Default.GetString(lineData); if(line.StartsWith("--" + toBoundary)){ break; } lineData = reader.ReadLine(); } // Invalid boundary end, there can't be more entities if(lineData == null){ return false; } // This was last entity if(System.Text.Encoding.Default.GetString(lineData).EndsWith("--")){ return false; } // else{ // There are more entities return true; } } } // Singlepart entity else{ // Boundary is specified, read data to specified boundary. if(toBoundary != null && toBoundary.Length > 0){ MemoryStream entityData = new MemoryStream(); StreamLineReader reader = new StreamLineReader(stream); byte[] lineData = reader.ReadLine(); while(lineData != null){ String line = System.Text.Encoding.Default.GetString(lineData); if(line.StartsWith("--" + toBoundary)){ break; } // Write line to buffer entityData.Write(lineData,0,lineData.Length); entityData.Write(new byte[]{(byte)'\r',(byte)'\n'},0,2); lineData = reader.ReadLine(); } // This is invalid entity, unexpected end of entity. Skip that entity. if(lineData == null){ if(this.ParentEntity != null){ this.ParentEntity.ChildEntities.Remove(this); } return false; } m_EncodedData = entityData.ToArray(); // See if last boundary or there is more. Last boundary ends with -- if(System.Text.Encoding.Default.GetString(lineData).EndsWith("--")){ return false; } return true; } // Boundary isn't specified, read data to the stream end. else{ m_EncodedData = new byte[stream.Length]; stream.Read(m_EncodedData,0,m_EncodedData.Length); } } return false; }