Commit b39e7b78 authored by Brickner_cp's avatar Brickner_cp

HTTP

parent 65032c0f
...@@ -2,6 +2,7 @@ using System; ...@@ -2,6 +2,7 @@ using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text;
using PcapDotNet.Base; using PcapDotNet.Base;
using PcapDotNet.Packets.Ethernet; using PcapDotNet.Packets.Ethernet;
using PcapDotNet.Packets.IpV4; using PcapDotNet.Packets.IpV4;
...@@ -150,7 +151,12 @@ namespace PcapDotNet.Packets ...@@ -150,7 +151,12 @@ namespace PcapDotNet.Packets
public override string ToString() public override string ToString()
{ {
return _buffer.Range(StartOffset, Length).BytesSequenceToHexadecimalString(); return Buffer.Range(StartOffset, Length).BytesSequenceToHexadecimalString();
}
public string ToString(Encoding encoding)
{
return encoding.GetString(Buffer, StartOffset, Length);
} }
internal void Write(byte[] buffer, int offset) internal void Write(byte[] buffer, int offset)
......
...@@ -218,6 +218,23 @@ namespace PcapDotNet.Packets.Http ...@@ -218,6 +218,23 @@ namespace PcapDotNet.Packets.Http
} }
} }
public Datagram Body
{
get
{
if (_body == null)
{
ParseHeader();
if (_bodyOffset != null)
{
int bodyOffsetValue = _bodyOffset.Value;
_body = new Datagram(Buffer, StartOffset + bodyOffsetValue, Length - bodyOffsetValue);
}
}
return _body;
}
}
internal static HttpDatagram CreateDatagram(byte[] buffer, int offset, int length) internal static HttpDatagram CreateDatagram(byte[] buffer, int offset, int length)
{ {
if (length >= _httpSlash.Length && buffer.SequenceEqual(offset, _httpSlash, 0, _httpSlash.Length)) if (length >= _httpSlash.Length && buffer.SequenceEqual(offset, _httpSlash, 0, _httpSlash.Length))
...@@ -260,6 +277,11 @@ namespace PcapDotNet.Packets.Http ...@@ -260,6 +277,11 @@ namespace PcapDotNet.Packets.Http
HttpParser parser = new HttpParser(Buffer, StartOffset + headerOffsetValue, Length - headerOffsetValue); HttpParser parser = new HttpParser(Buffer, StartOffset + headerOffsetValue, Length - headerOffsetValue);
while (parser.Success) while (parser.Success)
{ {
if (parser.CarraigeReturnLineFeed().Success)
{
_bodyOffset = parser.Offset - StartOffset;
break;
}
string fieldName; string fieldName;
IEnumerable<byte> fieldValue; IEnumerable<byte> fieldValue;
parser.Token(out fieldName).Colon().FieldValue(out fieldValue).CarraigeReturnLineFeed(); parser.Token(out fieldName).Colon().FieldValue(out fieldValue).CarraigeReturnLineFeed();
...@@ -273,8 +295,11 @@ namespace PcapDotNet.Packets.Http ...@@ -273,8 +295,11 @@ namespace PcapDotNet.Packets.Http
private bool _isParsedFirstLine; private bool _isParsedFirstLine;
private bool _isParsedHeader; private bool _isParsedHeader;
private int? _headerOffset; private int? _headerOffset;
private int? _bodyOffset;
private HttpVersion _version; private HttpVersion _version;
private HttpHeader _header; private HttpHeader _header;
private Datagram _body;
} }
......
...@@ -9,6 +9,18 @@ namespace PcapDotNet.Packets.Http ...@@ -9,6 +9,18 @@ namespace PcapDotNet.Packets.Http
{ {
public class HttpField : IEquatable<HttpField> public class HttpField : IEquatable<HttpField>
{ {
public static HttpField CreateField(string fieldName, byte[] fieldValue)
{
switch (fieldName)
{
case HttpTransferEncodingField.Name:
return new HttpTransferEncodingField(fieldValue);
default:
return new HttpField(fieldName, fieldValue.ToArray());
}
}
public HttpField(string name, string value) public HttpField(string name, string value)
: this(name, value, _defaultEncoding) : this(name, value, _defaultEncoding)
{ {
......
...@@ -50,7 +50,7 @@ namespace PcapDotNet.Packets.Http ...@@ -50,7 +50,7 @@ namespace PcapDotNet.Packets.Http
mergedFields[fieldName] = fieldValue.Concat(AsciiBytes.Comma).Concat(field.Value); mergedFields[fieldName] = fieldValue.Concat(AsciiBytes.Comma).Concat(field.Value);
} }
_fields = mergedFields.ToDictionary(field => field.Key, field => new HttpField(field.Key, field.Value)); _fields = mergedFields.ToDictionary(field => field.Key, field => HttpField.CreateField(field.Key, field.Value.ToArray()));
} }
public IEnumerator<HttpField> GetEnumerator() public IEnumerator<HttpField> GetEnumerator()
......
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using PcapDotNet.Base; using PcapDotNet.Base;
namespace PcapDotNet.Packets.Http namespace PcapDotNet.Packets.Http
{ {
public class HttpTransferCoding
{
public HttpTransferCoding(string codingName, ReadOnlyCollection<HttpParameter> parameters)
{
CodingName = codingName;
Parameters = parameters;
}
public string CodingName { get; private set; }
public ReadOnlyCollection<HttpParameter> Parameters { get; private set; }
}
public class HttpParameter
{
public HttpParameter(string attribute, Datagram value)
{
Attribute = attribute;
Value = value;
}
public string Attribute { get; private set; }
public Datagram Value { get; private set; }
}
internal class HttpParser internal class HttpParser
{ {
public HttpParser(byte[] buffer) public HttpParser(byte[] buffer)
...@@ -28,7 +53,7 @@ namespace PcapDotNet.Packets.Http ...@@ -28,7 +53,7 @@ namespace PcapDotNet.Packets.Http
get { return _offset; } get { return _offset; }
} }
public HttpParser Token(out string token) public HttpParser Token(out Datagram token)
{ {
if (!Success) if (!Success)
{ {
...@@ -43,11 +68,19 @@ namespace PcapDotNet.Packets.Http ...@@ -43,11 +68,19 @@ namespace PcapDotNet.Packets.Http
return Fail(); return Fail();
} }
token = Encoding.ASCII.GetString(_buffer, _offset, tokenLength); token = new Datagram(_buffer, _offset, tokenLength);
_offset += token.Length; _offset += token.Length;
return this; return this;
} }
public HttpParser Token(out string token)
{
Datagram bytesToken;
Token(out bytesToken);
token = Success ? bytesToken.ToString(Encoding.ASCII) : null;
return this;
}
public HttpParser Colon() public HttpParser Colon()
{ {
return Bytes(AsciiBytes.Colon); return Bytes(AsciiBytes.Colon);
...@@ -230,6 +263,127 @@ namespace PcapDotNet.Packets.Http ...@@ -230,6 +263,127 @@ namespace PcapDotNet.Packets.Http
return this; return this;
} }
public HttpParser CommaSeparated<T>(Func<T> commaSeparatedParsing, out List<T> commaSeparated)
{
commaSeparated = new List<T>();
bool more = true;
while (Success && more)
{
commaSeparated.Add(commaSeparatedParsing());
SkipLws();
more = false;
while (IsNext(AsciiBytes.Comma))
{
++_offset;
more = true;
SkipLws();
}
}
if (!Success)
commaSeparated = null;
return this;
}
public HttpTransferCoding TransferCoding()
{
string codingName;
Token(out codingName);
List<HttpParameter> parameters = new List<HttpParameter>();
while (Success && IsNext(AsciiBytes.Semicolon))
{
++_offset;
HttpParameter parameter;
Parameter(out parameter);
}
return Success ? new HttpTransferCoding(codingName, parameters.AsReadOnly()) : null;
}
public HttpParser Parameter(out HttpParameter parameter)
{
string attribute;
Token(out attribute).Bytes(AsciiBytes.EqualsSign);
Datagram value;
if (IsNext(AsciiBytes.DoubleQuotationMark))
QuotedString(out value);
else
Token(out value);
parameter = Success ? new HttpParameter(attribute, value) : null;
return this;
}
public HttpParser QuotedString(out Datagram quotedString)
{
quotedString = null;
int startOffset = _offset;
// Parse first "
if (!Bytes(AsciiBytes.DoubleQuotationMark).Success)
return this;
while (IsNext())
{
byte next = Next();
// Parse last "
if (next == AsciiBytes.DoubleQuotationMark)
{
++_offset;
quotedString = new Datagram(_buffer, startOffset, _offset - startOffset);
return this;
}
// Parse \char
if (next == AsciiBytes.BackSlash && IsNextNext() && NextNext().IsChar())
_offset += 2;
else
{
// parse text
int original = _offset;
SkipLws();
if (original == _offset)
{
// text isn't LWS - parse a byte that isn't control
if (!next.IsControl())
++_offset;
else
return Fail(); // illegal byte
}
}
}
// no " found
return Fail();
}
private bool IsNextNext()
{
return _offset + 1 < _totalLength;
}
private bool IsNext()
{
return _offset < _totalLength;
}
private byte Next()
{
return _buffer[_offset];
}
private byte NextNext()
{
return _buffer[_offset + 1];
}
private bool IsNext(byte next)
{
return (IsNext() && Next() == next);
}
private HttpParser Fail() private HttpParser Fail()
{ {
Success = false; Success = false;
......
using System;
using System.Collections.Generic;
namespace PcapDotNet.Packets.Http
{
public class HttpTransferEncodingField : HttpField
{
public const string Name = "Transfer-Encoding";
public HttpTransferEncodingField(byte[] fieldValue)
: base(Name, fieldValue)
{
HttpParser parser = new HttpParser(fieldValue);
List<HttpTransferCoding> transferCodings;
parser.CommaSeparated(parser.TransferCoding, out transferCodings);
}
}
}
\ No newline at end of file
...@@ -117,6 +117,7 @@ ...@@ -117,6 +117,7 @@
<Compile Include="Http\HttpParser.cs" /> <Compile Include="Http\HttpParser.cs" />
<Compile Include="Http\HttpRequestDatagram.cs" /> <Compile Include="Http\HttpRequestDatagram.cs" />
<Compile Include="Http\HttpResponseDatagram.cs" /> <Compile Include="Http\HttpResponseDatagram.cs" />
<Compile Include="Http\HttpTransferEncodingField.cs" />
<Compile Include="Http\HttpVersion.cs" /> <Compile Include="Http\HttpVersion.cs" />
<Compile Include="Icmp\IcmpAddressMaskReplyDatagram.cs" /> <Compile Include="Icmp\IcmpAddressMaskReplyDatagram.cs" />
<Compile Include="Icmp\IcmpAddressMaskReplyLayer.cs" /> <Compile Include="Icmp\IcmpAddressMaskReplyLayer.cs" />
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment