Beispiel #1
0
        public static Task<FormData> ParseMultipart(Stream stream, string boundary) {
            if (stream == null) {
                throw new ArgumentNullException("stream");
            }
            if (boundary == null) {
                throw new ArgumentNullException("boundary");
            }
            if (boundary.Length == 0) {
                throw new ArgumentException("Boundary cannot be empty", "boundary");
            }
            var form = new FormData();

            boundary = "--" + boundary;
            var boundaryBytes = Encoding.UTF8.GetBytes("\r\n" + boundary);

            string currentLine = stream.ReadLine(Encoding.UTF8);
            if (currentLine != boundary) {
                form.IsValid = false;
                return TaskHelper.Completed(form);
            }
            while (true) {
                currentLine = stream.ReadLine(Encoding.UTF8);
                // parse ContentDisposition line
                var match = ContentDispositionFormDataRegex.Match(currentLine);
                if (!match.Success) {
                    form.IsValid = false;
                    return TaskHelper.Completed(form);
                }
                string fieldName = match.Groups[1].Value;
                string fileName = match.Groups[2].Success ? match.Groups[3].Value : null;

                if (fileName != null) {
                    if (!ParseMultipartFile(stream, form, fieldName, fileName, boundaryBytes)) {
                        form.IsValid = false;
                        return TaskHelper.Completed(form);
                    }
                }
                else {
                    if (!ParseMultipartField(stream, form, fieldName, boundaryBytes)) {
                        form.IsValid = false;
                        return TaskHelper.Completed(form);
                    }
                }

                // check end or next
                currentLine = stream.ReadLine(Encoding.UTF8);
                // --boundary-- end
                if (currentLine == "--") {
                    break;
                }
                // --boundary between
                if (currentLine != string.Empty) {
                    form.IsValid = false;
                    return TaskHelper.Completed(form);
                }
            }
            return TaskHelper.Completed(form);
        }
Beispiel #2
0
        protected static IList<KeyValuePair<string, string>> ReadHeaders(Stream stream)
        {
            var headers = new List<KeyValuePair<string, string>>();
            var line = stream.ReadLine();
            while (line.Trim() != "")
            {
                var parts = line.Split(new[] { ':' }, 2);
                if (parts.Length != 2)
                    throw new Exception("Invalid HttpHeader");
                var name = parts[0].Trim();
                var value = parts[1].Trim();
                headers.Add(new KeyValuePair<string, string>(name, value));
                line = stream.ReadLine();
            }

            return headers;
        }
Beispiel #3
0
 private static void Parse3Tokens(Stream stream, out string token1, out string token2, out string token3)
 {
     var reader = new StringReader(stream.ReadLine());
     token1 = reader.ReadUntilWhitespace();
     reader.SkipWhitespace();
     token2 = reader.ReadUntilWhitespace();
     reader.SkipWhitespace();
     token3 = reader.ReadLine();
 }
 protected override void ReadFirstLine(Stream stream)
 {
     var line = stream.ReadLine();
     var parts = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
     if (parts.Length != 3)
         throw new Exception("Invalid HttpRequest");
     Method = parts[0];
     Destination = parts[1];
     Version = parts[2];
 }
 protected override void ReadFirstLine(Stream stream)
 {
     var line = stream.ReadLine();
     var parts = line.Split(new[] { ' ' }, 3, StringSplitOptions.RemoveEmptyEntries);
     if (parts.Length < 2)
         throw new Exception("Invalid HttpRequest");
     Version = parts[0];
     var statusCode = 0;
     if (!int.TryParse(parts[1], out statusCode))
         Errors.Add("Invalid StatusCode");
     StatusCode = (HttpStatusCode) statusCode;
     if (parts.Length == 3)
         StatusDescription = parts[2];
 }
        public override object Deserialize(Stream stream)
        {
            string typeName = stream.ReadLine(MessageEncoding);

            int length = stream.ReadInt();
            byte[] messageBuffer = stream.Read(length);
            Type type = ReflectionHelper.FindType(typeName);

            if (type != null)
            {
                MemoryStream messageStream = new MemoryStream(messageBuffer);
                return Serializer.NonGeneric.Deserialize(type, messageStream);
            }
            else
            {
                throw new Exception("Invalid message type");
            }
        }
        public override IMessage Deserialize(Stream stream)
        {
            // The command should be on its own line
            string messageName = stream.ReadLine(MessageEncoding);
            //while (commandLine.Length == 0)
            //    commandLine = stream.ReadLine(MessageEncoding);

            //string[] commandTokens = commandLine.Split(" ".ToCharArray());

            IMessage message = MessageFactory.Create(messageName);
            if (message != null)
            {
                message.Deserialize(stream, MessageEncoding);
            }
            else
            {
                throw new Exception("Unknown message: " + messageName);
            }

            return message;
        }
Beispiel #8
0
        private static void ParseHeaders(Stream stream, Action<string, string> onHeader)
        {
            string headerLine = null;

            while (true)
            {
                headerLine = stream.ReadLine();

                if (headerLine == String.Empty)
                {
                    break;
                }

                var headerReader = new StringReader(headerLine);
                string key = headerReader.ReadUntil(c => c == ':');
                headerReader.Read();
                headerReader.SkipWhitespace();
                string value = headerReader.ReadToEnd();

                onHeader(key, value);
            }
        }
Beispiel #9
0
        public virtual void Load(Stream reader,  Scope scope, int maxLength, char? termChar = null)
        {
            Scope = scope;
            Headers = null;
            Body = null;

            var headers = new StringBuilder();
            string line;
            while ((line = reader.ReadLine(ref maxLength, _DefaultEncoding, termChar)) != null)
            {
                if (line.Trim().Length == 0)
                    if (headers.Length == 0)
                        continue;
                    else
                        break;
                headers.AppendLine(line);
            }
            RawHeaders = headers.ToString();

            if (Scope > Scope.Headers)
            {
                string boundary = Headers.GetBoundary();
                if (!string.IsNullOrEmpty(boundary))
                {
                    var atts = new List<Attachment>();
                    // Read the mime structure anyways, but the body might be empty.
                    var body = ParseMime(reader, boundary, ref maxLength, atts, Encoding, termChar, scope);
                    if (Scope > Scope.HeadersAndMime && !string.IsNullOrEmpty(body))
                    {
                        SetBody(body);
                    }

                    foreach (var att in atts)
                    {
                        Add(att);
                    }

                    if (maxLength > 0)
                        reader.ReadToEnd(maxLength, Encoding);
                }
                else if (Scope > Scope.HeadersAndMime)
                {
                    //	sometimes when email doesn't have a body, we get here with maxLength == 0 and we shouldn't read any further
                    string body = String.Empty;
                    if (maxLength > 0)
                        body = reader.ReadToEnd(maxLength, Encoding);

                    SetBody(body);
                }
            }

            Date = Headers.GetDate();
            To = Headers.GetMailAddresses("To").ToList();
            Cc = Headers.GetMailAddresses("Cc").ToList();
            Bcc = Headers.GetMailAddresses("Bcc").ToList();
            Sender = Headers.GetMailAddresses("Sender").FirstOrDefault();
            ReplyTo = Headers.GetMailAddresses("Reply-To").ToList();
            From = Headers.GetMailAddresses("From").FirstOrDefault();
            MessageID = Headers["Message-ID"].RawValue;

            Importance = Headers.GetEnum<MailPriority>("Importance");
            Subject = Headers["Subject"].RawValue;
        }
Beispiel #10
0
        private static void ParseMime(Stream reader, string boundary, ref int maxLength, ICollection<Attachment> attachments, Encoding encoding, char? termChar)
        {
            var maxLengthSpecified = maxLength > 0;
            string data,
                bounderInner = "--" + boundary,
                bounderOuter = bounderInner + "--";

            do {
                data = reader.ReadLine(ref maxLength, encoding, termChar);
            } while (data != null && !data.StartsWith(bounderInner));

            while (data != null && !data.StartsWith(bounderOuter) && !(maxLengthSpecified && maxLength == 0)) {
                data = reader.ReadLine(ref maxLength, encoding, termChar);
                var a = new Attachment { Encoding = encoding };

                var part = new StringBuilder();
                // read part header
                while (!data.StartsWith(bounderInner) && data != string.Empty && !(maxLengthSpecified && maxLength == 0)) {
                    part.AppendLine(data);
                    data = reader.ReadLine(ref maxLength, encoding, termChar);
                }
                a.RawHeaders = part.ToString();
                // header body

                // check for nested part
                var nestedboundary = a.Headers.GetBoundary();
                if (!string.IsNullOrEmpty(nestedboundary)) {
                    ParseMime(reader, nestedboundary, ref maxLength, attachments, encoding, termChar);
                } else {
                    data = reader.ReadLine(ref maxLength, a.Encoding, termChar);
                    var body = new StringBuilder();
                    while (!data.StartsWith(bounderInner) && !(maxLengthSpecified && maxLength == 0)) {
                        body.AppendLine(data);
                        data = reader.ReadLine(ref maxLength, a.Encoding, termChar);
                    }
                    a.SetBody(body.ToString());
                    attachments.Add(a);
                }
            }
        }
Beispiel #11
0
        public virtual void Load(Stream reader, bool headersOnly = false, int maxLength = 0, char? termChar = null)
        {
            _HeadersOnly = headersOnly;
            Headers = null;
            Body = null;

            if (headersOnly) {
                RawHeaders = reader.ReadToEnd(maxLength, _DefaultEncoding);
            } else {
                var headers = new StringBuilder();
                string line;
                while ((line = reader.ReadLine(ref maxLength, _DefaultEncoding, termChar)) != null) {
                    if (line.Trim().Length == 0)
                        if (headers.Length == 0)
                            continue;
                        else
                            break;
                    headers.AppendLine(line);
                }
                RawHeaders = headers.ToString();

                string boundary = Headers.GetBoundary();
                if (!string.IsNullOrEmpty(boundary)) {
                    //else this is a multipart Mime Message
                    //using (var subreader = new StringReader(line + Environment.NewLine + reader.ReadToEnd()))
                    var atts = new List<Attachment>();
                    ParseMime(reader, boundary, ref maxLength, atts, Encoding, termChar);
                    foreach (var att in atts)
                        (att.IsAttachment ? Attachments : AlternateViews).Add(att);

                    if (maxLength > 0)
                        reader.ReadToEnd(maxLength, Encoding);
                } else {
                    SetBody(reader.ReadToEnd(maxLength, Encoding).Trim());
                }
            }

            if (string.IsNullOrWhiteSpace(Body) && AlternateViews.Count > 0) {
                var att = AlternateViews.FirstOrDefault(x => x.ContentType.Is("text/plain"));
                if (att == null) {
                    att = AlternateViews.FirstOrDefault(x => x.ContentType.Contains("html"));
                }

                if (att != null) {
                    Body = att.Body;
                    ContentTransferEncoding = att.Headers["Content-Transfer-Encoding"].RawValue;
                    ContentType = att.Headers["Content-Type"].RawValue;
                }
            }

            Date = Headers.GetDate();
            To = Headers.GetAddresses("To").ToList();
            Cc = Headers.GetAddresses("Cc").ToList();
            Bcc = Headers.GetAddresses("Bcc").ToList();
            Sender = Headers.GetAddresses("Sender").FirstOrDefault();
            ReplyTo = Headers.GetAddresses("Reply-To").ToList();
            From = Headers.GetAddresses("From").FirstOrDefault();
            MessageID = Headers["Message-ID"].RawValue;

            Importance = Headers.GetEnum<MailPriority>("Importance");
            Subject = Headers["Subject"].RawValue;
        }
Beispiel #12
0
        private void ParseMime(Stream reader, string boundary, int maxLength)
        {
            var maxLengthSpecified = maxLength > 0;
              string data,
            bounderInner = "--" + boundary,
            bounderOuter = bounderInner + "--";

              do {
            data = reader.ReadLine(ref maxLength, Encoding);
              } while (data != null && !data.StartsWith(bounderInner));

              while (data != null && !data.StartsWith(bounderOuter) && (maxLength > 0 || !maxLengthSpecified)) {
            data = reader.ReadLine(ref maxLength, Encoding);
            var a = new Attachment { Encoding = Encoding };

            var part = new StringBuilder();
            // read part header
            while (!data.StartsWith(bounderInner) && data != string.Empty) {
              part.AppendLine(data);
              data = reader.ReadLine(ref maxLength, Encoding);
            }
            a.RawHeaders = part.ToString();
            // header body

            data = reader.ReadLine(ref maxLength, Encoding);
            var body = new StringBuilder();
            while (data != string.Empty && !data.StartsWith(bounderInner)) {
              body.AppendLine(data);
              data = reader.ReadLine(ref maxLength, Encoding);
            }
            // check for nested part
            string nestedboundary = a.Headers.GetBoundary();
            if (!string.IsNullOrEmpty(nestedboundary)) {
              ParseMime(body.ToString(), nestedboundary);

            } else { // nested
              a.SetBody(body.ToString());
              (a.IsAttachment ? Attachments : AlternateViews).Add(a);
            }
              }

              if (maxLength > 0)
            data = reader.ReadToEnd(maxLength, Encoding);
        }
Beispiel #13
0
		public virtual void Load(Stream reader, bool headersOnly = false, int maxLength = 0, char? termChar = null)
		{
			_HeadersOnly = headersOnly;
			Headers = null;
			Body = null;
			if (maxLength == 0)
				return;


			var headers = new StringBuilder();
			string line;
			while ((line = reader.ReadLine(ref maxLength, _DefaultEncoding, termChar)) != null) {
				if (line.Length == 0)
					if (headers.Length == 0)
						continue;
					else
						break;
				headers.AppendLine(line);
			}
			RawHeaders = headers.ToString();

			if (!headersOnly) {
				string boundary = Headers.GetBoundary();
				if (!string.IsNullOrEmpty(boundary)) {
					var atts = new List<Attachment>();
					var body = ParseMime(reader, boundary, ref maxLength, atts, Encoding, termChar);
					if (!string.IsNullOrEmpty(body))
						SetBody(body);

					foreach (var att in atts)
						(att.IsAttachment ? Attachments : AlternateViews).Add(att);

					if (maxLength > 0)
						reader.ReadToEnd(maxLength, Encoding);
				} else {
					//	sometimes when email doesn't have a body, we get here with maxLength == 0 and we shouldn't read any further
					string body = String.Empty;
					if (maxLength > 0)
						body = reader.ReadToEnd(maxLength, Encoding);

					SetBody(body);
				}
			}
			else if (maxLength > 0)
				reader.ReadToEnd(maxLength, Encoding);

			if ((string.IsNullOrWhiteSpace(Body) || ContentType.StartsWith("multipart/")) && AlternateViews.Count > 0) {
				var att = AlternateViews.GetTextView() ?? AlternateViews.GetHtmlView();
				if (att != null) {
					Body = att.Body;
					ContentTransferEncoding = att.Headers["Content-Transfer-Encoding"].RawValue;
					ContentType = att.Headers["Content-Type"].RawValue;
				}
			}

			Date = Headers.GetDate();
			To = Headers.GetMailAddresses("To").ToList();
			Cc = Headers.GetMailAddresses("Cc").ToList();
			Bcc = Headers.GetMailAddresses("Bcc").ToList();
			Sender = Headers.GetMailAddresses("Sender").FirstOrDefault();
			ReplyTo = Headers.GetMailAddresses("Reply-To").ToList();
			From = Headers.GetMailAddresses("From").FirstOrDefault();
			MessageID = Headers["Message-ID"].RawValue;

			Importance = Headers.GetEnum<MailPriority>("Importance");
			Subject = Headers["Subject"].RawValue;
		}
Beispiel #14
0
        private static bool ParseMultipartField(Stream stream, FormData form, string fieldName, byte[] boundaryBytes) {
            string contentType = null;
            string headerLine;
            Match match;
            while ((headerLine = stream.ReadLine(Encoding.UTF8)) != string.Empty) {
                // parse 'Content-" headers
                match = ContentTypeFormDataRegex.Match(headerLine);
                if (match.Success) {
                    // nested: Content-Type: multipart/mixed; boundary=BbC04y
                    contentType = match.Groups[1].Value.Trim();
                    if (match.Groups[2].Success) {
                        string fileBoundary = match.Groups[4].Value;
                        byte[] fileBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + fileBoundary);
                        byte[] temp;
                        if (!stream.ReadTo(fileBoundaryBytes, out temp)) {
                            return false;
                        }
                        if (stream.ReadLine(Encoding.UTF8) != string.Empty) {
                            return false;
                        }
                        bool moreFiles = true;
                        while (moreFiles) {
                            string line = stream.ReadLine(Encoding.UTF8);
                            match = ContentDispositionFileRegex.Match(line);
                            if (!match.Success) {
                                return false;
                            }
                            string filename = match.Groups[1].Value;
                            if (!ParseMultipartFile(stream, form, fieldName, filename, fileBoundaryBytes)) {
                                return false;
                            }
                            line = stream.ReadLine(Encoding.UTF8);
                            if (line == "--") {
                                moreFiles = false;
                            }
                            else if (line != string.Empty) {
                                return false;
                            }
                        }
                        // NB: CrLf already ripped here
                        var boundaryNoCrLf = new byte[boundaryBytes.Length - 2];
                        Array.Copy(boundaryBytes, 2, boundaryNoCrLf, 0, boundaryBytes.Length - 2);
                        if (!stream.ReadTo(boundaryNoCrLf, out temp)) {
                            return false;
                        }
                        if (temp.Length != 0) {
                            return false;
                        }
                        return true;
                    }
                }
            }
            if (contentType == null) {
                contentType = "text/plain";
            }

            byte[] value;
            if (!stream.ReadTo(boundaryBytes, out value)) {
                return false;
            }
            // handle charset: content-type: text/plain;charset=windows-1250
            match = CharsetRegex.Match(contentType);
            Encoding encoding = match.Success ? Encoding.GetEncoding(match.Groups[2].Value) : Encoding.UTF8;
            form[fieldName] = encoding.GetString(value);

            return true;
        }
Beispiel #15
0
        private static string ParseMime(Stream reader, string boundary, ref int maxLength, ICollection<Attachment> attachments, Encoding encoding, char? termChar, Scope scope)
        {
            var maxLengthSpecified = maxLength > 0;
            string data = null,
                bounderInner = "--" + boundary,
                bounderOuter = bounderInner + "--";
            var n = 0;
            var body = new System.Text.StringBuilder();
            do
            {
                if (maxLengthSpecified && maxLength <= 0)
                    return body.ToString();
                if (data != null)
                {
                    body.Append(data);
                }
                data = reader.ReadLine(ref maxLength, encoding, termChar);
                n++;
            } while (data != null && !data.StartsWith(bounderInner));

            while (data != null && !data.StartsWith(bounderOuter) && !(maxLengthSpecified && maxLength == 0))
            {
                data = reader.ReadLine(ref maxLength, encoding, termChar);
                if (data == null) break;
                var a = new Attachment { Encoding = encoding };

                var part = new StringBuilder();
                // read part header
                while (!data.StartsWith(bounderInner) && data != string.Empty && !(maxLengthSpecified && maxLength == 0))
                {
                    part.AppendLine(data);
                    data = reader.ReadLine(ref maxLength, encoding, termChar);
                    if (data == null) break;
                }
                a.RawHeaders = part.ToString();
                // header body

                // check for nested part
                var nestedboundary = a.Headers.GetBoundary();
                if (!string.IsNullOrEmpty(nestedboundary))
                {
                    ParseMime(reader, nestedboundary, ref maxLength, attachments, encoding, termChar, scope);
                    while (!data.StartsWith(bounderInner))
                        data = reader.ReadLine(ref maxLength, encoding, termChar);
                }
                else
                {
                    data = reader.ReadLine(ref maxLength, a.Encoding, termChar);
                    if (data == null) break;
                    var nestedBody = new StringBuilder();
                    while (!data.StartsWith(bounderInner) && !(maxLengthSpecified && maxLength == 0))
                    {
                        nestedBody.AppendLine(data);
                        data = reader.ReadLine(ref maxLength, a.Encoding, termChar);
                        if (data == null)
                        {
                            throw new EndOfStreamException("Unexpected end of file");
                        }
                    }
                    if (scope > Scope.HeadersAndMime)
                    {
                        a.SetBody(nestedBody.ToString());
                    }
                    attachments.Add(a);
                }
            }
            return body.ToString();
        }
Beispiel #16
0
        private static bool CopyHttpStream(Stream fromStream, Stream toStream, string firstLine = "", string sslTunnelDomain="")
        {
            bool keepAlive = false; 
            var encoding = Encoding.UTF8;
            string method;
            string version;
            string url;

            using (var fromStreamReader = new BinaryReader(fromStream, encoding, true))
            using (var toStreamWriter = new BinaryWriter(toStream, encoding, true))
            {
                if (String.IsNullOrEmpty(firstLine))
                    firstLine = fromStream.ReadLine();

                if (!String.IsNullOrEmpty(sslTunnelDomain))
                {
                    //modify the path in the http request to include the domain
                    ParseHttpCommand(firstLine, out method, out url, out version);
                    //modify the forward address so it has complete URL 
                    firstLine = method + ' ' + "https://" + sslTunnelDomain + url + ' ' + version;
                    firstLine += "\r\n";
                    firstLine += "X-Forward-Secure: true";
                }
                LogMessage(string.Format(firstLine));
                toStream.WriteLine(firstLine);
                toStream.Flush();

                string line;
                int contentLength = 0;
                bool chunked = false;

                //copy the headers
                while (!String.IsNullOrEmpty(line = fromStreamReader.ReadLine()))
                {
                    if (line.StartsWith("Content-Length:", true, CultureInfo.CurrentCulture))
                        contentLength = int.Parse(line.Replace("Content-Length:", ""));
                    if (line.StartsWith("Transfer-Encoding: chunked", true, CultureInfo.CurrentCulture))
                        chunked = true;
                    if (line.StartsWith("Proxy-Connection: Keep-Alive", true, CultureInfo.CurrentCulture))
                        keepAlive = true;
                    toStreamWriter.WriteLine(line);
                }
                toStreamWriter.WriteLine();
                if (contentLength > 0)
                    toStreamWriter.Write(fromStreamReader.ReadBytes(contentLength));

                if(chunked)
                {
                    while (!String.IsNullOrEmpty(line = fromStreamReader.ReadLine()))
                    {
                        contentLength = int.Parse(line, System.Globalization.NumberStyles.HexNumber);
                        toStreamWriter.Write(fromStreamReader.ReadBytes(contentLength));
                        fromStreamReader.ReadLine();
                    }
                }
                toStreamWriter.Flush();
            }
            return keepAlive;
        }
Beispiel #17
0
        private static Stream GetSslTunnelStream(Stream stream, string version = "HTTP/1.1")
        {
            SslStream sslStream = null;
            //Browser wants to create a secure tunnel
            //read and ignore headers
            while (!String.IsNullOrEmpty(stream.ReadLine())) ;
            //tell the client that a tunnel has been established              
            LogMessage(string.Format("Doing CONNECT"));
            var connectStreamWriter = new BinaryWriter(stream);
            connectStreamWriter.WriteLine(version + " 200 Connection established");
            connectStreamWriter.WriteLine(String.Format("Timestamp: {0}", DateTime.Now.ToString()));
            connectStreamWriter.WriteLine("Proxy-agent: buskerproxy");
            connectStreamWriter.WriteLine();
            connectStreamWriter.Flush();

            //open a decrypting stream    
            sslStream = new SslStream(stream, false);
            try
            {
                sslStream.AuthenticateAsServer(_certificate, false, SslProtocols.Tls | SslProtocols.Ssl3 | SslProtocols.Ssl2, true);
            }
            catch (Exception ex)
            {
                stream.Close();
                sslStream.Close();
                return null;
            }
            return sslStream;
        }
Beispiel #18
0
        private static bool ParseMultipartFile(Stream stream, FormData form, string fieldName, string fileName, byte[] boundaryBytes) {
            string contentType = null;
            string headerLine;
            while ((headerLine = stream.ReadLine(Encoding.UTF8)) != string.Empty) {
                // parse 'Content-" headers
                var match = ContentTypeFileRegex.Match(headerLine);
                if (match.Success) {
                    contentType = match.Groups[1].Value.Trim();
                }
            }
            if (contentType == null) {
                //todo: infer from file type (extension)
                contentType = "application/octet-stream";
            }

            byte[] data;
            if (!stream.ReadTo(boundaryBytes, out data)) {
                return false;
            }
            form.Files.Add(new PostedFile(fieldName, fileName, data, contentType));
            return true;
        }