154 lines
4.6 KiB
C#
154 lines
4.6 KiB
C#
// /**
|
|
// * File: Message.cs
|
|
// * Author: haraldwolff
|
|
// *
|
|
// * This file and it's content is copyrighted by the Author and / or copyright holder.
|
|
// * Any use wihtout proper permission is illegal and may lead to legal actions.
|
|
// *
|
|
// *
|
|
// **/
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Text;
|
|
using System.Globalization;
|
|
using ln.http.io;
|
|
using ln.types;
|
|
using ln.http.message.parser;
|
|
namespace ln.http.message
|
|
{
|
|
public class Message
|
|
{
|
|
public HeaderContainer Headers { get; private set; }
|
|
|
|
byte[] bodyData;
|
|
int bodyOffset;
|
|
int bodyLength;
|
|
|
|
List<Message> parts;
|
|
|
|
bool isMultipart;
|
|
public bool IsMultipart => isMultipart;
|
|
|
|
public Message()
|
|
{
|
|
Setup(new HeaderContainer(), new byte[0], 0, 0);
|
|
}
|
|
|
|
public Message(HeaderContainer headers, byte[] body)
|
|
: this(headers, body, 0, body.Length) { }
|
|
|
|
public Message(HeaderContainer headers, byte[] body, int offset, int length)
|
|
{
|
|
Setup(headers, body, offset, length);
|
|
}
|
|
|
|
public Message(byte[] body, int offset, int length)
|
|
{
|
|
MemoryStream memoryStream = new MemoryStream(body, offset, length);
|
|
HeaderContainer headers = MIME.ReadHeader(new UnbufferedStreamReader(memoryStream));
|
|
|
|
if (memoryStream.Position >= length)
|
|
throw new FormatException("MIME header section too long");
|
|
|
|
Setup(headers, body, offset + (int)memoryStream.Position, length - (int)memoryStream.Position);
|
|
}
|
|
|
|
public Message(Stream stream)
|
|
{
|
|
HeaderContainer headers = MIME.ReadHeader(new UnbufferedStreamReader(stream));
|
|
|
|
byte[] data = stream.ReadToEnd();
|
|
|
|
Setup(headers, data, 0, data.Length);
|
|
}
|
|
|
|
private void Setup(HeaderContainer headers, byte[] body, int offset, int length)
|
|
{
|
|
Headers = headers;
|
|
|
|
bodyData = body;
|
|
bodyOffset = offset;
|
|
bodyLength = length;
|
|
|
|
string ct = Headers["Content-Type"].Value;
|
|
isMultipart = ct.StartsWith("multipart/", StringComparison.InvariantCulture) || ct.StartsWith("message/", StringComparison.InvariantCulture);
|
|
}
|
|
|
|
public void ReadParts()
|
|
{
|
|
parts = new List<Message>();
|
|
|
|
if (isMultipart)
|
|
{
|
|
string boundary = Headers["Content-Type"].GetParameter("boundary");
|
|
string delimiter = "--" + boundary;
|
|
int[] indeces = FindIndeces(bodyData, bodyOffset, bodyLength, Encoding.ASCII.GetBytes(delimiter));
|
|
|
|
for (int n = 1; n < indeces.Length; n++)
|
|
{
|
|
Message part = new Message(bodyData, indeces[n - 1], indeces[n] - indeces[n - 1]);
|
|
parts.Add(part);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
int[] FindIndeces(byte[] data,int offset,int length,byte[] pattern)
|
|
{
|
|
List<int> offsets = new List<int>();
|
|
List<int> validated = new List<int>();
|
|
|
|
for (int n = offset; n < (length - pattern.Length); n++)
|
|
{
|
|
int p = 0;
|
|
while ((p < pattern.Length) && (data[n + p] == pattern[p]))
|
|
p++;
|
|
|
|
if (p == pattern.Length)
|
|
{
|
|
if ((n == offset) || ((n >= (offset + 2)) && (data[offset + n - 2] == '\r') && (data[offset + n - 1] == '\n')))
|
|
{
|
|
n += pattern.Length;
|
|
|
|
while ((n < (offset + length)) && (data[n - 2] != '\r') && (data[n - 1] != '\n'))
|
|
n++;
|
|
|
|
validated.Add(n);
|
|
|
|
|
|
if (((offset + length) > (n + 1)) && (data[n] == '-') && (data[n + 1] == '-'))
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return validated.ToArray();
|
|
}
|
|
|
|
|
|
public Stream OpenBodyStream() => new MemoryStream(bodyData, bodyOffset, bodyLength);
|
|
|
|
public IEnumerable<Message> Parts
|
|
{
|
|
get
|
|
{
|
|
if (parts == null)
|
|
ReadParts();
|
|
return parts;
|
|
}
|
|
}
|
|
|
|
public bool HasHeader(string name) => Headers.Contains(name);
|
|
public Header GetHeader(string name) => Headers[name];
|
|
public void SetHeader(string name, string value) => Headers.Set(name, value);
|
|
public void RemoveHeader(String name) => Headers.Remove(name);
|
|
|
|
public override string ToString()
|
|
{
|
|
return base.ToString();
|
|
}
|
|
|
|
}
|
|
}
|