Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
T
Titanium-Web-Proxy
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Titanium-Web-Proxy
Commits
0f5f8b48
Commit
0f5f8b48
authored
Jul 01, 2017
by
justcoding121
Committed by
justcoding121
Jul 01, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use StreamExtended library
parent
6e6f5567
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
27 changed files
with
30 additions
and
2290 deletions
+30
-2290
DeflateDecompression.cs
Titanium.Web.Proxy/Decompression/DeflateDecompression.cs
+2
-1
GZipDecompression.cs
Titanium.Web.Proxy/Decompression/GZipDecompression.cs
+2
-1
StreamExtensions.cs
Titanium.Web.Proxy/Extensions/StreamExtensions.cs
+2
-1
BufferPool.cs
Titanium.Web.Proxy/Helpers/BufferPool.cs
+0
-28
CustomBinaryReader.cs
Titanium.Web.Proxy/Helpers/CustomBinaryReader.cs
+0
-139
CustomBufferedPeekStream.cs
Titanium.Web.Proxy/Helpers/CustomBufferedPeekStream.cs
+0
-56
CustomBufferedStream.cs
Titanium.Web.Proxy/Helpers/CustomBufferedStream.cs
+0
-527
HttpResponseWriter.cs
Titanium.Web.Proxy/Helpers/HttpResponseWriter.cs
+2
-1
ConnectRequest.cs
Titanium.Web.Proxy/Http/ConnectRequest.cs
+1
-1
ConnectResponse.cs
Titanium.Web.Proxy/Http/ConnectResponse.cs
+2
-2
HeaderParser.cs
Titanium.Web.Proxy/Http/HeaderParser.cs
+2
-1
ProxyClient.cs
Titanium.Web.Proxy/Network/ProxyClient.cs
+2
-1
ClientHelloAlpnAdderStream.cs
Titanium.Web.Proxy/Network/Tcp/ClientHelloAlpnAdderStream.cs
+0
-136
ServerHelloAlpnAdderStream.cs
Titanium.Web.Proxy/Network/Tcp/ServerHelloAlpnAdderStream.cs
+0
-135
TcpConnection.cs
Titanium.Web.Proxy/Network/Tcp/TcpConnection.cs
+2
-3
TcpConnectionFactory.cs
Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs
+2
-1
ProxyServer.cs
Titanium.Web.Proxy/ProxyServer.cs
+2
-1
RequestHandler.cs
Titanium.Web.Proxy/RequestHandler.cs
+3
-2
ClientHelloInfo.cs
Titanium.Web.Proxy/Ssl/ClientHelloInfo.cs
+0
-117
ServerHelloInfo.cs
Titanium.Web.Proxy/Ssl/ServerHelloInfo.cs
+0
-107
SslCiphers.cs
Titanium.Web.Proxy/Ssl/SslCiphers.cs
+0
-337
SslExtension.cs
Titanium.Web.Proxy/Ssl/SslExtension.cs
+0
-18
SslExtensions.cs
Titanium.Web.Proxy/Ssl/SslExtensions.cs
+0
-396
SslTools.cs
Titanium.Web.Proxy/Ssl/SslTools.cs
+0
-266
Titanium.Web.Proxy.csproj
Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
+4
-12
Titanium.Web.Proxy.nuspec
Titanium.Web.Proxy/Titanium.Web.Proxy.nuspec
+1
-0
packages.config
Titanium.Web.Proxy/packages.config
+1
-0
No files found.
Titanium.Web.Proxy/Decompression/DeflateDecompression.cs
View file @
0f5f8b48
using
System.IO
;
using
StreamExtended.Helpers
;
using
System.IO
;
using
System.IO.Compression
;
using
System.IO.Compression
;
using
System.Threading.Tasks
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.Helpers
;
...
...
Titanium.Web.Proxy/Decompression/GZipDecompression.cs
View file @
0f5f8b48
using
System.IO
;
using
StreamExtended.Helpers
;
using
System.IO
;
using
System.IO.Compression
;
using
System.IO.Compression
;
using
System.Threading.Tasks
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.Helpers
;
...
...
Titanium.Web.Proxy/Extensions/StreamExtensions.cs
View file @
0f5f8b48
using
System
;
using
StreamExtended.Network
;
using
System
;
using
System.Globalization
;
using
System.Globalization
;
using
System.IO
;
using
System.IO
;
using
System.Threading.Tasks
;
using
System.Threading.Tasks
;
...
...
Titanium.Web.Proxy/Helpers/BufferPool.cs
deleted
100644 → 0
View file @
6e6f5567
using
System.Collections.Concurrent
;
namespace
Titanium.Web.Proxy.Helpers
{
internal
static
class
BufferPool
{
private
static
readonly
ConcurrentQueue
<
byte
[
]>
buffers
=
new
ConcurrentQueue
<
byte
[
]>
();
internal
static
byte
[]
GetBuffer
(
int
bufferSize
)
{
byte
[]
buffer
;
if
(!
buffers
.
TryDequeue
(
out
buffer
)
||
buffer
.
Length
!=
bufferSize
)
{
buffer
=
new
byte
[
bufferSize
];
}
return
buffer
;
}
internal
static
void
ReturnBuffer
(
byte
[]
buffer
)
{
if
(
buffer
!=
null
)
{
buffers
.
Enqueue
(
buffer
);
}
}
}
}
Titanium.Web.Proxy/Helpers/CustomBinaryReader.cs
deleted
100644 → 0
View file @
6e6f5567
using
System
;
using
System.Collections.Generic
;
using
System.Text
;
using
System.Threading.Tasks
;
namespace
Titanium.Web.Proxy.Helpers
{
/// <summary>
/// A custom binary reader that would allo us to read string line by line
/// using the specified encoding
/// as well as to read bytes as required
/// </summary>
internal
class
CustomBinaryReader
:
IDisposable
{
private
readonly
CustomBufferedStream
stream
;
private
readonly
Encoding
encoding
;
private
bool
disposed
;
internal
byte
[]
Buffer
{
get
;
}
internal
CustomBinaryReader
(
CustomBufferedStream
stream
,
int
bufferSize
)
{
this
.
stream
=
stream
;
Buffer
=
BufferPool
.
GetBuffer
(
bufferSize
);
//default to UTF-8
encoding
=
Encoding
.
UTF8
;
}
/// <summary>
/// Read a line from the byte stream
/// </summary>
/// <returns></returns>
internal
async
Task
<
string
>
ReadLineAsync
()
{
byte
lastChar
=
default
(
byte
);
int
bufferDataLength
=
0
;
// try to use the thread static buffer, usually it is enough
var
buffer
=
Buffer
;
while
(
stream
.
DataAvailable
||
await
stream
.
FillBufferAsync
())
{
byte
newChar
=
stream
.
ReadByteFromBuffer
();
buffer
[
bufferDataLength
]
=
newChar
;
//if new line
if
(
lastChar
==
'\r'
&&
newChar
==
'\n'
)
{
return
encoding
.
GetString
(
buffer
,
0
,
bufferDataLength
-
1
);
}
//end of stream
if
(
newChar
==
'\0'
)
{
return
encoding
.
GetString
(
buffer
,
0
,
bufferDataLength
);
}
bufferDataLength
++;
//store last char for new line comparison
lastChar
=
newChar
;
if
(
bufferDataLength
==
buffer
.
Length
)
{
ResizeBuffer
(
ref
buffer
,
bufferDataLength
*
2
);
}
}
if
(
bufferDataLength
==
0
)
{
return
null
;
}
return
encoding
.
GetString
(
buffer
,
0
,
bufferDataLength
);
}
/// <summary>
/// Read until the last new line
/// </summary>
/// <returns></returns>
internal
async
Task
<
List
<
string
>>
ReadAllLinesAsync
()
{
string
tmpLine
;
var
requestLines
=
new
List
<
string
>();
while
(!
string
.
IsNullOrEmpty
(
tmpLine
=
await
ReadLineAsync
()))
{
requestLines
.
Add
(
tmpLine
);
}
return
requestLines
;
}
/// <summary>
/// Read until the last new line, ignores the result
/// </summary>
/// <returns></returns>
internal
async
Task
ReadAndIgnoreAllLinesAsync
()
{
while
(!
string
.
IsNullOrEmpty
(
await
ReadLineAsync
()))
{
}
}
/// <summary>
/// Read the specified number (or less) of raw bytes from the base stream to the given buffer
/// </summary>
/// <param name="buffer"></param>
/// <param name="bytesToRead"></param>
/// <returns>The number of bytes read</returns>
internal
Task
<
int
>
ReadBytesAsync
(
byte
[]
buffer
,
int
bytesToRead
)
{
return
stream
.
ReadAsync
(
buffer
,
0
,
bytesToRead
);
}
public
void
Dispose
()
{
if
(!
disposed
)
{
disposed
=
true
;
BufferPool
.
ReturnBuffer
(
Buffer
);
}
}
/// <summary>
/// Increase size of buffer and copy existing content to new buffer
/// </summary>
/// <param name="buffer"></param>
/// <param name="size"></param>
private
void
ResizeBuffer
(
ref
byte
[]
buffer
,
long
size
)
{
var
newBuffer
=
new
byte
[
size
];
System
.
Buffer
.
BlockCopy
(
buffer
,
0
,
newBuffer
,
0
,
buffer
.
Length
);
buffer
=
newBuffer
;
}
}
}
Titanium.Web.Proxy/Helpers/CustomBufferedPeekStream.cs
deleted
100644 → 0
View file @
6e6f5567
using
System.Threading.Tasks
;
namespace
Titanium.Web.Proxy.Helpers
{
class
CustomBufferedPeekStream
{
private
readonly
CustomBufferedStream
baseStream
;
public
int
Position
{
get
;
private
set
;
}
public
CustomBufferedPeekStream
(
CustomBufferedStream
baseStream
,
int
startPosition
=
0
)
{
this
.
baseStream
=
baseStream
;
Position
=
startPosition
;
}
public
int
Available
=>
baseStream
.
Available
-
Position
;
public
async
Task
<
bool
>
EnsureBufferLength
(
int
length
)
{
var
val
=
await
baseStream
.
PeekByteAsync
(
Position
+
length
-
1
);
return
val
!=
-
1
;
}
public
byte
ReadByte
()
{
return
baseStream
.
PeekByteFromBuffer
(
Position
++);
}
public
int
ReadInt16
()
{
int
i1
=
ReadByte
();
int
i2
=
ReadByte
();
return
(
i1
<<
8
)
+
i2
;
}
public
int
ReadInt24
()
{
int
i1
=
ReadByte
();
int
i2
=
ReadByte
();
int
i3
=
ReadByte
();
return
(
i1
<<
16
)
+
(
i2
<<
8
)
+
i3
;
}
public
byte
[]
ReadBytes
(
int
length
)
{
var
buffer
=
new
byte
[
length
];
for
(
int
i
=
0
;
i
<
buffer
.
Length
;
i
++)
{
buffer
[
i
]
=
ReadByte
();
}
return
buffer
;
}
}
}
Titanium.Web.Proxy/Helpers/CustomBufferedStream.cs
deleted
100644 → 0
View file @
6e6f5567
This diff is collapsed.
Click to expand it.
Titanium.Web.Proxy/Helpers/HttpResponseWriter.cs
View file @
0f5f8b48
using
System
;
using
StreamExtended.Network
;
using
System
;
using
System.Globalization
;
using
System.Globalization
;
using
System.IO
;
using
System.IO
;
using
System.Text
;
using
System.Text
;
...
...
Titanium.Web.Proxy/Http/ConnectRequest.cs
View file @
0f5f8b48
using
Titanium.Web.Proxy.Ssl
;
using
StreamExtended
;
namespace
Titanium.Web.Proxy.Http
namespace
Titanium.Web.Proxy.Http
{
{
...
...
Titanium.Web.Proxy/Http/ConnectResponse.cs
View file @
0f5f8b48
using
System
;
using
StreamExtended
;
using
System
;
using
System.Net
;
using
System.Net
;
using
Titanium.Web.Proxy.Ssl
;
namespace
Titanium.Web.Proxy.Http
namespace
Titanium.Web.Proxy.Http
{
{
...
...
Titanium.Web.Proxy/Http/HeaderParser.cs
View file @
0f5f8b48
using
System.Collections.Generic
;
using
StreamExtended.Network
;
using
System.Collections.Generic
;
using
System.Threading.Tasks
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.Models
;
using
Titanium.Web.Proxy.Models
;
...
...
Titanium.Web.Proxy/Network/ProxyClient.cs
View file @
0f5f8b48
using
System.Net.Sockets
;
using
StreamExtended.Network
;
using
System.Net.Sockets
;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.Helpers
;
namespace
Titanium.Web.Proxy.Network
namespace
Titanium.Web.Proxy.Network
...
...
Titanium.Web.Proxy/Network/Tcp/ClientHelloAlpnAdderStream.cs
deleted
100644 → 0
View file @
6e6f5567
using
System.Diagnostics
;
using
System.IO
;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.Ssl
;
namespace
Titanium.Web.Proxy.Network.Tcp
{
internal
class
ClientHelloAlpnAdderStream
:
Stream
{
private
readonly
CustomBufferedStream
stream
;
private
bool
called
;
public
ClientHelloAlpnAdderStream
(
CustomBufferedStream
stream
)
{
this
.
stream
=
stream
;
}
public
override
void
Flush
()
{
stream
.
Flush
();
}
public
override
long
Seek
(
long
offset
,
SeekOrigin
origin
)
{
return
stream
.
Seek
(
offset
,
origin
);
}
public
override
void
SetLength
(
long
value
)
{
stream
.
SetLength
(
value
);
}
[
DebuggerStepThrough
]
public
override
int
Read
(
byte
[]
buffer
,
int
offset
,
int
count
)
{
return
stream
.
Read
(
buffer
,
offset
,
count
);
}
public
override
void
Write
(
byte
[]
buffer
,
int
offset
,
int
count
)
{
if
(
called
)
{
stream
.
Write
(
buffer
,
offset
,
count
);
return
;
}
called
=
true
;
var
ms
=
new
MemoryStream
(
buffer
,
offset
,
count
);
//this can be non async, because reads from a memory stream
var
clientHello
=
SslTools
.
GetClientHelloInfo
(
new
CustomBufferedStream
(
ms
,
(
int
)
ms
.
Length
)).
Result
;
if
(
clientHello
!=
null
)
{
// 0x00 0x10: ALPN identifier
// 0x00 0x0e: length of ALPN data
// 0x00 0x0c: length of ALPN data again:)
var
dataToAdd
=
new
byte
[]
{
0x0
,
0x10
,
0x0
,
0xE
,
0x0
,
0xC
,
2
,
(
byte
)
'h'
,
(
byte
)
'2'
,
8
,
(
byte
)
'h'
,
(
byte
)
't'
,
(
byte
)
't'
,
(
byte
)
'p'
,
(
byte
)
'/'
,
(
byte
)
'1'
,
(
byte
)
'.'
,
(
byte
)
'1'
};
int
newByteCount
=
clientHello
.
Extensions
==
null
?
dataToAdd
.
Length
+
2
:
dataToAdd
.
Length
;
var
buffer2
=
new
byte
[
buffer
.
Length
+
newByteCount
];
for
(
int
i
=
0
;
i
<
buffer
.
Length
;
i
++)
{
buffer2
[
i
]
=
buffer
[
i
];
}
//this is a hacky solution, but works
int
length
=
(
buffer
[
offset
+
3
]
<<
8
)
+
buffer
[
offset
+
4
];
length
+=
newByteCount
;
buffer2
[
offset
+
3
]
=
(
byte
)(
length
>>
8
);
buffer2
[
offset
+
4
]
=
(
byte
)
length
;
length
=
(
buffer
[
offset
+
6
]
<<
16
)
+
(
buffer
[
offset
+
7
]
<<
8
)
+
buffer
[
offset
+
8
];
length
+=
newByteCount
;
buffer2
[
offset
+
6
]
=
(
byte
)(
length
>>
16
);
buffer2
[
offset
+
7
]
=
(
byte
)(
length
>>
8
);
buffer2
[
offset
+
8
]
=
(
byte
)
length
;
int
pos
=
offset
+
clientHello
.
EntensionsStartPosition
;
int
endPos
=
offset
+
clientHello
.
ClientHelloLength
;
if
(
clientHello
.
Extensions
!=
null
)
{
// update ALPN length
length
=
(
buffer
[
pos
]
<<
8
)
+
buffer
[
pos
+
1
];
length
+=
newByteCount
;
buffer2
[
pos
]
=
(
byte
)(
length
>>
8
);
buffer2
[
pos
+
1
]
=
(
byte
)
length
;
}
else
{
// add ALPN length
length
=
dataToAdd
.
Length
;
buffer2
[
pos
]
=
(
byte
)(
length
>>
8
);
buffer2
[
pos
+
1
]
=
(
byte
)
length
;
endPos
+=
2
;
}
for
(
int
i
=
0
;
i
<
dataToAdd
.
Length
;
i
++)
{
buffer2
[
endPos
+
i
]
=
dataToAdd
[
i
];
}
// copy the reamining data if any
for
(
int
i
=
clientHello
.
ClientHelloLength
;
i
<
count
;
i
++)
{
buffer2
[
offset
+
newByteCount
+
i
]
=
buffer
[
offset
+
i
];
}
buffer
=
buffer2
;
count
+=
newByteCount
;
}
stream
.
Write
(
buffer
,
offset
,
count
);
}
public
override
bool
CanRead
=>
stream
.
CanRead
;
public
override
bool
CanSeek
=>
stream
.
CanSeek
;
public
override
bool
CanWrite
=>
stream
.
CanWrite
;
public
override
long
Length
=>
stream
.
Length
;
public
override
long
Position
{
get
{
return
stream
.
Position
;
}
set
{
stream
.
Position
=
value
;
}
}
}
}
\ No newline at end of file
Titanium.Web.Proxy/Network/Tcp/ServerHelloAlpnAdderStream.cs
deleted
100644 → 0
View file @
6e6f5567
using
System.Diagnostics
;
using
System.IO
;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.Ssl
;
namespace
Titanium.Web.Proxy.Network.Tcp
{
internal
class
ServerHelloAlpnAdderStream
:
Stream
{
private
readonly
CustomBufferedStream
stream
;
private
bool
called
;
public
ServerHelloAlpnAdderStream
(
CustomBufferedStream
stream
)
{
this
.
stream
=
stream
;
}
public
override
void
Flush
()
{
stream
.
Flush
();
}
public
override
long
Seek
(
long
offset
,
SeekOrigin
origin
)
{
return
stream
.
Seek
(
offset
,
origin
);
}
public
override
void
SetLength
(
long
value
)
{
stream
.
SetLength
(
value
);
}
[
DebuggerStepThrough
]
public
override
int
Read
(
byte
[]
buffer
,
int
offset
,
int
count
)
{
return
stream
.
Read
(
buffer
,
offset
,
count
);
}
public
override
void
Write
(
byte
[]
buffer
,
int
offset
,
int
count
)
{
if
(
called
)
{
stream
.
Write
(
buffer
,
offset
,
count
);
return
;
}
called
=
true
;
var
ms
=
new
MemoryStream
(
buffer
,
offset
,
count
);
//this can be non async, because reads from a memory stream
var
serverHello
=
SslTools
.
GetServerHelloInfo
(
new
CustomBufferedStream
(
ms
,
(
int
)
ms
.
Length
)).
Result
;
if
(
serverHello
!=
null
)
{
// 0x00 0x10: ALPN identifier
// 0x00 0x0e: length of ALPN data
// 0x00 0x0c: length of ALPN data again:)
var
dataToAdd
=
new
byte
[]
{
0x0
,
0x10
,
0x0
,
0x5
,
0x0
,
0x3
,
2
,
(
byte
)
'h'
,
(
byte
)
'2'
};
int
newByteCount
=
serverHello
.
Extensions
==
null
?
dataToAdd
.
Length
+
2
:
dataToAdd
.
Length
;
var
buffer2
=
new
byte
[
buffer
.
Length
+
newByteCount
];
for
(
int
i
=
0
;
i
<
buffer
.
Length
;
i
++)
{
buffer2
[
i
]
=
buffer
[
i
];
}
//this is a hacky solution, but works
int
length
=
(
buffer
[
offset
+
3
]
<<
8
)
+
buffer
[
offset
+
4
];
length
+=
newByteCount
;
buffer2
[
offset
+
3
]
=
(
byte
)(
length
>>
8
);
buffer2
[
offset
+
4
]
=
(
byte
)
length
;
length
=
(
buffer
[
offset
+
6
]
<<
16
)
+
(
buffer
[
offset
+
7
]
<<
8
)
+
buffer
[
offset
+
8
];
length
+=
newByteCount
;
buffer2
[
offset
+
6
]
=
(
byte
)(
length
>>
16
);
buffer2
[
offset
+
7
]
=
(
byte
)(
length
>>
8
);
buffer2
[
offset
+
8
]
=
(
byte
)
length
;
int
pos
=
offset
+
serverHello
.
EntensionsStartPosition
;
int
endPos
=
offset
+
serverHello
.
ServerHelloLength
;
if
(
serverHello
.
Extensions
!=
null
)
{
// update ALPN length
length
=
(
buffer
[
pos
]
<<
8
)
+
buffer
[
pos
+
1
];
length
+=
newByteCount
;
buffer2
[
pos
]
=
(
byte
)(
length
>>
8
);
buffer2
[
pos
+
1
]
=
(
byte
)
length
;
}
else
{
// add ALPN length
length
=
dataToAdd
.
Length
;
buffer2
[
pos
]
=
(
byte
)(
length
>>
8
);
buffer2
[
pos
+
1
]
=
(
byte
)
length
;
endPos
+=
2
;
}
for
(
int
i
=
0
;
i
<
dataToAdd
.
Length
;
i
++)
{
buffer2
[
endPos
+
i
]
=
dataToAdd
[
i
];
}
// copy the reamining data if any
for
(
int
i
=
serverHello
.
ServerHelloLength
;
i
<
count
;
i
++)
{
buffer2
[
offset
+
newByteCount
+
i
]
=
buffer
[
offset
+
i
];
}
buffer
=
buffer2
;
count
+=
newByteCount
;
}
stream
.
Write
(
buffer
,
offset
,
count
);
}
public
override
bool
CanRead
=>
stream
.
CanRead
;
public
override
bool
CanSeek
=>
stream
.
CanSeek
;
public
override
bool
CanWrite
=>
stream
.
CanWrite
;
public
override
long
Length
=>
stream
.
Length
;
public
override
long
Position
{
get
{
return
stream
.
Position
;
}
set
{
stream
.
Position
=
value
;
}
}
}
}
\ No newline at end of file
Titanium.Web.Proxy/Network/Tcp/TcpConnection.cs
View file @
0f5f8b48
using
S
ystem
;
using
S
treamExtended.Network
;
using
System
.IO
;
using
System
;
using
System.Net.Sockets
;
using
System.Net.Sockets
;
using
Titanium.Web.Proxy.Extensions
;
using
Titanium.Web.Proxy.Extensions
;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.Models
;
using
Titanium.Web.Proxy.Models
;
namespace
Titanium.Web.Proxy.Network.Tcp
namespace
Titanium.Web.Proxy.Network.Tcp
...
...
Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs
View file @
0f5f8b48
using
System
;
using
StreamExtended.Network
;
using
System
;
using
System.IO
;
using
System.IO
;
using
System.Linq
;
using
System.Linq
;
using
System.Net.Security
;
using
System.Net.Security
;
...
...
Titanium.Web.Proxy/ProxyServer.cs
View file @
0f5f8b48
using
System
;
using
StreamExtended.Network
;
using
System
;
using
System.Collections.Generic
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Linq
;
using
System.Net
;
using
System.Net
;
...
...
Titanium.Web.Proxy/RequestHandler.cs
View file @
0f5f8b48
using
System
;
using
StreamExtended
;
using
StreamExtended.Network
;
using
System
;
using
System.IO
;
using
System.IO
;
using
System.Linq
;
using
System.Linq
;
using
System.Net
;
using
System.Net
;
...
@@ -13,7 +15,6 @@ using Titanium.Web.Proxy.Helpers;
...
@@ -13,7 +15,6 @@ using Titanium.Web.Proxy.Helpers;
using
Titanium.Web.Proxy.Http
;
using
Titanium.Web.Proxy.Http
;
using
Titanium.Web.Proxy.Models
;
using
Titanium.Web.Proxy.Models
;
using
Titanium.Web.Proxy.Network.Tcp
;
using
Titanium.Web.Proxy.Network.Tcp
;
using
Titanium.Web.Proxy.Ssl
;
namespace
Titanium.Web.Proxy
namespace
Titanium.Web.Proxy
{
{
...
...
Titanium.Web.Proxy/Ssl/ClientHelloInfo.cs
deleted
100644 → 0
View file @
6e6f5567
using
System
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Text
;
namespace
Titanium.Web.Proxy.Ssl
{
public
class
ClientHelloInfo
{
private
static
readonly
string
[]
compressions
=
{
"null"
,
"DEFLATE"
};
public
int
MajorVersion
{
get
;
set
;
}
public
int
MinorVersion
{
get
;
set
;
}
public
byte
[]
Random
{
get
;
set
;
}
public
DateTime
Time
{
get
{
DateTime
time
=
DateTime
.
MinValue
;
if
(
Random
.
Length
>
3
)
{
time
=
new
DateTime
(
1970
,
1
,
1
,
0
,
0
,
0
,
0
,
DateTimeKind
.
Utc
)
.
AddSeconds
(((
uint
)
Random
[
3
]
<<
24
)
+
((
uint
)
Random
[
2
]
<<
16
)
+
((
uint
)
Random
[
1
]
<<
8
)
+
(
uint
)
Random
[
0
]).
ToLocalTime
();
}
return
time
;
}
}
public
byte
[]
SessionId
{
get
;
set
;
}
public
int
[]
Ciphers
{
get
;
set
;
}
public
byte
[]
CompressionData
{
get
;
set
;
}
internal
int
ClientHelloLength
{
get
;
set
;
}
internal
int
EntensionsStartPosition
{
get
;
set
;
}
public
List
<
SslExtension
>
Extensions
{
get
;
set
;
}
private
static
string
SslVersionToString
(
int
major
,
int
minor
)
{
string
str
=
"Unknown"
;
if
(
major
==
3
&&
minor
==
3
)
str
=
"TLS/1.2"
;
else
if
(
major
==
3
&&
minor
==
2
)
str
=
"TLS/1.1"
;
else
if
(
major
==
3
&&
minor
==
1
)
str
=
"TLS/1.0"
;
else
if
(
major
==
3
&&
minor
==
0
)
str
=
"SSL/3.0"
;
else
if
(
major
==
2
&&
minor
==
0
)
str
=
"SSL/2.0"
;
return
$"
{
major
}
.
{
minor
}
(
{
str
}
)"
;
}
/// <summary>
/// Returns a <see cref="System.String" /> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="System.String" /> that represents this instance.
/// </returns>
public
override
string
ToString
()
{
var
sb
=
new
StringBuilder
();
sb
.
AppendLine
(
"A SSLv3-compatible ClientHello handshake was found. Titanium extracted the parameters below."
);
sb
.
AppendLine
();
sb
.
AppendLine
(
$"Version:
{
SslVersionToString
(
MajorVersion
,
MinorVersion
)}
"
);
sb
.
AppendLine
(
$"Random:
{
string
.
Join
(
" "
,
Random
.
Select
(
x
=>
x
.
ToString
(
"X2"
)))}
"
);
sb
.
AppendLine
(
$"\"Time\":
{
Time
}
"
);
sb
.
AppendLine
(
$"SessionID:
{
string
.
Join
(
" "
,
SessionId
.
Select
(
x
=>
x
.
ToString
(
"X2"
)))}
"
);
if
(
Extensions
!=
null
)
{
sb
.
AppendLine
(
"Extensions:"
);
foreach
(
var
extension
in
Extensions
)
{
sb
.
AppendLine
(
$"
{
extension
.
Name
}
:
{
extension
.
Data
}
"
);
}
}
if
(
CompressionData
.
Length
>
0
)
{
int
compressionMethod
=
CompressionData
[
0
];
string
compression
=
compressions
.
Length
>
compressionMethod
?
compressions
[
compressionMethod
]
:
$"unknown [0x
{
compressionMethod
:
X2
}
]"
;
sb
.
AppendLine
(
$"Compression:
{
compression
}
"
);
}
if
(
Ciphers
.
Length
>
0
)
{
sb
.
AppendLine
(
"Ciphers:"
);
foreach
(
int
cipherSuite
in
Ciphers
)
{
string
cipherStr
;
if
(!
SslCiphers
.
Ciphers
.
TryGetValue
(
cipherSuite
,
out
cipherStr
))
{
cipherStr
=
"unknown"
;
}
sb
.
AppendLine
(
$"[0x
{
cipherSuite
:
X4
}
]
{
cipherStr
}
"
);
}
}
return
sb
.
ToString
();
}
}
}
\ No newline at end of file
Titanium.Web.Proxy/Ssl/ServerHelloInfo.cs
deleted
100644 → 0
View file @
6e6f5567
using
System
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Text
;
namespace
Titanium.Web.Proxy.Ssl
{
public
class
ServerHelloInfo
{
private
static
readonly
string
[]
compressions
=
{
"null"
,
"DEFLATE"
};
public
int
MajorVersion
{
get
;
set
;
}
public
int
MinorVersion
{
get
;
set
;
}
public
byte
[]
Random
{
get
;
set
;
}
public
DateTime
Time
{
get
{
DateTime
time
=
DateTime
.
MinValue
;
if
(
Random
.
Length
>
3
)
{
time
=
new
DateTime
(
1970
,
1
,
1
,
0
,
0
,
0
,
0
,
DateTimeKind
.
Utc
)
.
AddSeconds
(((
uint
)
Random
[
3
]
<<
24
)
+
((
uint
)
Random
[
2
]
<<
16
)
+
((
uint
)
Random
[
1
]
<<
8
)
+
(
uint
)
Random
[
0
]).
ToLocalTime
();
}
return
time
;
}
}
public
byte
[]
SessionId
{
get
;
set
;
}
public
int
CipherSuite
{
get
;
set
;
}
public
byte
CompressionMethod
{
get
;
set
;
}
internal
int
ServerHelloLength
{
get
;
set
;
}
internal
int
EntensionsStartPosition
{
get
;
set
;
}
public
List
<
SslExtension
>
Extensions
{
get
;
set
;
}
private
static
string
SslVersionToString
(
int
major
,
int
minor
)
{
string
str
=
"Unknown"
;
if
(
major
==
3
&&
minor
==
3
)
str
=
"TLS/1.2"
;
else
if
(
major
==
3
&&
minor
==
2
)
str
=
"TLS/1.1"
;
else
if
(
major
==
3
&&
minor
==
1
)
str
=
"TLS/1.0"
;
else
if
(
major
==
3
&&
minor
==
0
)
str
=
"SSL/3.0"
;
else
if
(
major
==
2
&&
minor
==
0
)
str
=
"SSL/2.0"
;
return
$"
{
major
}
.
{
minor
}
(
{
str
}
)"
;
}
/// <summary>
/// Returns a <see cref="System.String" /> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="System.String" /> that represents this instance.
/// </returns>
public
override
string
ToString
()
{
var
sb
=
new
StringBuilder
();
sb
.
AppendLine
(
"A SSLv3-compatible ServerHello handshake was found. Titanium extracted the parameters below."
);
sb
.
AppendLine
();
sb
.
AppendLine
(
$"Version:
{
SslVersionToString
(
MajorVersion
,
MinorVersion
)}
"
);
sb
.
AppendLine
(
$"Random:
{
string
.
Join
(
" "
,
Random
.
Select
(
x
=>
x
.
ToString
(
"X2"
)))}
"
);
sb
.
AppendLine
(
$"\"Time\":
{
Time
}
"
);
sb
.
AppendLine
(
$"SessionID:
{
string
.
Join
(
" "
,
SessionId
.
Select
(
x
=>
x
.
ToString
(
"X2"
)))}
"
);
if
(
Extensions
!=
null
)
{
sb
.
AppendLine
(
"Extensions:"
);
foreach
(
var
extension
in
Extensions
)
{
sb
.
AppendLine
(
$"
{
extension
.
Name
}
:
{
extension
.
Data
}
"
);
}
}
string
compression
=
compressions
.
Length
>
CompressionMethod
?
compressions
[
CompressionMethod
]
:
$"unknown [0x
{
CompressionMethod
:
X2
}
]"
;
sb
.
AppendLine
(
$"Compression:
{
compression
}
"
);
sb
.
Append
(
"Cipher:"
);
string
cipherStr
;
if
(!
SslCiphers
.
Ciphers
.
TryGetValue
(
CipherSuite
,
out
cipherStr
))
{
cipherStr
=
"unknown"
;
}
sb
.
AppendLine
(
$"[0x
{
CipherSuite
:
X4
}
]
{
cipherStr
}
"
);
return
sb
.
ToString
();
}
}
}
\ No newline at end of file
Titanium.Web.Proxy/Ssl/SslCiphers.cs
deleted
100644 → 0
View file @
6e6f5567
This diff is collapsed.
Click to expand it.
Titanium.Web.Proxy/Ssl/SslExtension.cs
deleted
100644 → 0
View file @
6e6f5567
namespace
Titanium.Web.Proxy.Ssl
{
public
class
SslExtension
{
public
int
Value
{
get
;
set
;
}
public
string
Name
{
get
;
set
;
}
public
string
Data
{
get
;
set
;
}
public
SslExtension
(
int
value
,
string
name
,
string
data
)
{
Value
=
value
;
Name
=
name
;
Data
=
data
;
}
}
}
\ No newline at end of file
Titanium.Web.Proxy/Ssl/SslExtensions.cs
deleted
100644 → 0
View file @
6e6f5567
This diff is collapsed.
Click to expand it.
Titanium.Web.Proxy/Ssl/SslTools.cs
deleted
100644 → 0
View file @
6e6f5567
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.Helpers
;
namespace
Titanium.Web.Proxy.Ssl
{
class
SslTools
{
public
static
async
Task
<
bool
>
IsClientHello
(
CustomBufferedStream
clientStream
)
{
var
clientHello
=
await
GetClientHelloInfo
(
clientStream
);
return
clientHello
!=
null
;
}
public
static
async
Task
<
ClientHelloInfo
>
GetClientHelloInfo
(
CustomBufferedStream
clientStream
)
{
//detects the HTTPS ClientHello message as it is described in the following url:
//https://stackoverflow.com/questions/3897883/how-to-detect-an-incoming-ssl-https-handshake-ssl-wire-format
int
recordType
=
await
clientStream
.
PeekByteAsync
(
0
);
if
(
recordType
==
0x80
)
{
var
peekStream
=
new
CustomBufferedPeekStream
(
clientStream
,
1
);
//SSL 2
int
length
=
peekStream
.
ReadByte
();
if
(
length
<
9
)
{
// Message body too short.
return
null
;
}
if
(
peekStream
.
ReadByte
()
!=
0x01
)
{
// should be ClientHello
return
null
;
}
int
majorVersion
=
clientStream
.
ReadByte
();
int
minorVersion
=
clientStream
.
ReadByte
();
return
new
ClientHelloInfo
();
}
else
if
(
recordType
==
0x16
)
{
var
peekStream
=
new
CustomBufferedPeekStream
(
clientStream
,
1
);
//should contain at least 43 bytes
// 2 version + 2 length + 1 type + 3 length(?) + 2 version + 32 random + 1 sessionid length
if
(!
await
peekStream
.
EnsureBufferLength
(
43
))
{
return
null
;
}
//SSL 3.0 or TLS 1.0, 1.1 and 1.2
int
majorVersion
=
peekStream
.
ReadByte
();
int
minorVersion
=
peekStream
.
ReadByte
();
int
length
=
peekStream
.
ReadInt16
();
if
(
peekStream
.
ReadByte
()
!=
0x01
)
{
// should be ClientHello
return
null
;
}
length
=
peekStream
.
ReadInt24
();
majorVersion
=
peekStream
.
ReadByte
();
minorVersion
=
peekStream
.
ReadByte
();
byte
[]
random
=
peekStream
.
ReadBytes
(
32
);
length
=
peekStream
.
ReadByte
();
// sessionid + 2 ciphersData length
if
(!
await
peekStream
.
EnsureBufferLength
(
length
+
2
))
{
return
null
;
}
byte
[]
sessionId
=
peekStream
.
ReadBytes
(
length
);
length
=
peekStream
.
ReadInt16
();
// ciphersData + compressionData length
if
(!
await
peekStream
.
EnsureBufferLength
(
length
+
1
))
{
return
null
;
}
byte
[]
ciphersData
=
peekStream
.
ReadBytes
(
length
);
int
[]
ciphers
=
new
int
[
ciphersData
.
Length
/
2
];
for
(
int
i
=
0
;
i
<
ciphers
.
Length
;
i
++)
{
ciphers
[
i
]
=
(
ciphersData
[
2
*
i
]
<<
8
)
+
ciphersData
[
2
*
i
+
1
];
}
length
=
peekStream
.
ReadByte
();
if
(
length
<
1
)
{
return
null
;
}
// compressionData
if
(!
await
peekStream
.
EnsureBufferLength
(
length
))
{
return
null
;
}
byte
[]
compressionData
=
peekStream
.
ReadBytes
(
length
);
int
extenstionsStartPosition
=
peekStream
.
Position
;
var
extensions
=
await
ReadExtensions
(
majorVersion
,
minorVersion
,
peekStream
);
//var rawBytes = new CustomBufferedPeekStream(clientStream).ReadBytes(peekStream.Position);
var
clientHelloInfo
=
new
ClientHelloInfo
{
MajorVersion
=
majorVersion
,
MinorVersion
=
minorVersion
,
Random
=
random
,
SessionId
=
sessionId
,
Ciphers
=
ciphers
,
CompressionData
=
compressionData
,
ClientHelloLength
=
peekStream
.
Position
,
EntensionsStartPosition
=
extenstionsStartPosition
,
Extensions
=
extensions
,
};
return
clientHelloInfo
;
}
return
null
;
}
private
static
async
Task
<
List
<
SslExtension
>>
ReadExtensions
(
int
majorVersion
,
int
minorVersion
,
CustomBufferedPeekStream
peekStream
)
{
List
<
SslExtension
>
extensions
=
null
;
if
(
majorVersion
>
3
||
majorVersion
==
3
&&
minorVersion
>=
1
)
{
if
(
await
peekStream
.
EnsureBufferLength
(
2
))
{
int
extensionsLength
=
peekStream
.
ReadInt16
();
if
(
await
peekStream
.
EnsureBufferLength
(
extensionsLength
))
{
extensions
=
new
List
<
SslExtension
>();
while
(
extensionsLength
>
3
)
{
int
id
=
peekStream
.
ReadInt16
();
int
length
=
peekStream
.
ReadInt16
();
byte
[]
data
=
peekStream
.
ReadBytes
(
length
);
extensions
.
Add
(
SslExtensions
.
GetExtension
(
id
,
data
));
extensionsLength
-=
4
+
length
;
}
}
}
}
return
extensions
;
}
public
static
async
Task
<
bool
>
IsServerHello
(
CustomBufferedStream
serverStream
)
{
var
serverHello
=
await
GetServerHelloInfo
(
serverStream
);
return
serverHello
!=
null
;
}
public
static
async
Task
<
ServerHelloInfo
>
GetServerHelloInfo
(
CustomBufferedStream
serverStream
)
{
//detects the HTTPS ClientHello message as it is described in the following url:
//https://stackoverflow.com/questions/3897883/how-to-detect-an-incoming-ssl-https-handshake-ssl-wire-format
int
recordType
=
await
serverStream
.
PeekByteAsync
(
0
);
if
(
recordType
==
0x80
)
{
// copied from client hello, not tested. SSL2 is deprecated
var
peekStream
=
new
CustomBufferedPeekStream
(
serverStream
,
1
);
//SSL 2
int
length
=
peekStream
.
ReadByte
();
if
(
length
<
9
)
{
// Message body too short.
return
null
;
}
if
(
peekStream
.
ReadByte
()
!=
0x02
)
{
// should be ServerHello
return
null
;
}
int
majorVersion
=
serverStream
.
ReadByte
();
int
minorVersion
=
serverStream
.
ReadByte
();
return
new
ServerHelloInfo
();
}
else
if
(
recordType
==
0x16
)
{
var
peekStream
=
new
CustomBufferedPeekStream
(
serverStream
,
1
);
//should contain at least 43 bytes
// 2 version + 2 length + 1 type + 3 length(?) + 2 version + 32 random + 1 sessionid length
if
(!
await
peekStream
.
EnsureBufferLength
(
43
))
{
return
null
;
}
//SSL 3.0 or TLS 1.0, 1.1 and 1.2
int
majorVersion
=
peekStream
.
ReadByte
();
int
minorVersion
=
peekStream
.
ReadByte
();
int
length
=
peekStream
.
ReadInt16
();
if
(
peekStream
.
ReadByte
()
!=
0x02
)
{
// should be ServerHello
return
null
;
}
length
=
peekStream
.
ReadInt24
();
majorVersion
=
peekStream
.
ReadByte
();
minorVersion
=
peekStream
.
ReadByte
();
byte
[]
random
=
peekStream
.
ReadBytes
(
32
);
length
=
peekStream
.
ReadByte
();
// sessionid + cipherSuite + compressionMethod
if
(!
await
peekStream
.
EnsureBufferLength
(
length
+
2
+
1
))
{
return
null
;
}
byte
[]
sessionId
=
peekStream
.
ReadBytes
(
length
);
int
cipherSuite
=
peekStream
.
ReadInt16
();
byte
compressionMethod
=
peekStream
.
ReadByte
();
int
extenstionsStartPosition
=
peekStream
.
Position
;
var
extensions
=
await
ReadExtensions
(
majorVersion
,
minorVersion
,
peekStream
);
//var rawBytes = new CustomBufferedPeekStream(serverStream).ReadBytes(peekStream.Position);
var
serverHelloInfo
=
new
ServerHelloInfo
{
MajorVersion
=
majorVersion
,
MinorVersion
=
minorVersion
,
Random
=
random
,
SessionId
=
sessionId
,
CipherSuite
=
cipherSuite
,
CompressionMethod
=
compressionMethod
,
ServerHelloLength
=
peekStream
.
Position
,
EntensionsStartPosition
=
extenstionsStartPosition
,
Extensions
=
extensions
,
};
return
serverHelloInfo
;
}
return
null
;
}
}
}
Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
View file @
0f5f8b48
...
@@ -50,6 +50,10 @@
...
@@ -50,6 +50,10 @@
<HintPath>
..\packages\BouncyCastle.1.8.1\lib\BouncyCastle.Crypto.dll
</HintPath>
<HintPath>
..\packages\BouncyCastle.1.8.1\lib\BouncyCastle.Crypto.dll
</HintPath>
<Private>
True
</Private>
<Private>
True
</Private>
</Reference>
</Reference>
<Reference
Include=
"StreamExtended, Version=1.0.13.0, Culture=neutral, PublicKeyToken=bbfa0f1d54f50043, processorArchitecture=MSIL"
>
<HintPath>
..\packages\StreamExtended.1.0.13\lib\net45\StreamExtended.dll
</HintPath>
<Private>
True
</Private>
</Reference>
<Reference
Include=
"System"
/>
<Reference
Include=
"System"
/>
<Reference
Include=
"System.Configuration"
/>
<Reference
Include=
"System.Configuration"
/>
<Reference
Include=
"System.Core"
/>
<Reference
Include=
"System.Core"
/>
...
@@ -87,10 +91,6 @@
...
@@ -87,10 +91,6 @@
<Compile
Include=
"Extensions\StreamExtensions.cs"
/>
<Compile
Include=
"Extensions\StreamExtensions.cs"
/>
<Compile
Include=
"Extensions\StringExtensions.cs"
/>
<Compile
Include=
"Extensions\StringExtensions.cs"
/>
<Compile
Include=
"Extensions\TcpExtensions.cs"
/>
<Compile
Include=
"Extensions\TcpExtensions.cs"
/>
<Compile
Include=
"Helpers\BufferPool.cs"
/>
<Compile
Include=
"Helpers\CustomBinaryReader.cs"
/>
<Compile
Include=
"Helpers\CustomBufferedPeekStream.cs"
/>
<Compile
Include=
"Helpers\CustomBufferedStream.cs"
/>
<Compile
Include=
"Helpers\Firefox.cs"
/>
<Compile
Include=
"Helpers\Firefox.cs"
/>
<Compile
Include=
"Helpers\HttpRequestWriter.cs"
/>
<Compile
Include=
"Helpers\HttpRequestWriter.cs"
/>
<Compile
Include=
"Helpers\HttpResponseWriter.cs"
/>
<Compile
Include=
"Helpers\HttpResponseWriter.cs"
/>
...
@@ -98,18 +98,10 @@
...
@@ -98,18 +98,10 @@
<Compile
Include=
"Helpers\HttpHelper.cs"
/>
<Compile
Include=
"Helpers\HttpHelper.cs"
/>
<Compile
Include=
"Helpers\Network.cs"
/>
<Compile
Include=
"Helpers\Network.cs"
/>
<Compile
Include=
"Helpers\Tcp.cs"
/>
<Compile
Include=
"Helpers\Tcp.cs"
/>
<Compile
Include=
"Network\Tcp\ServerHelloAlpnAdderStream.cs"
/>
<Compile
Include=
"Network\Tcp\ClientHelloAlpnAdderStream.cs"
/>
<Compile
Include=
"Ssl\ServerHelloInfo.cs"
/>
<Compile
Include=
"Ssl\ClientHelloInfo.cs"
/>
<Compile
Include=
"Http\ConnectRequest.cs"
/>
<Compile
Include=
"Http\ConnectRequest.cs"
/>
<Compile
Include=
"Http\ConnectResponse.cs"
/>
<Compile
Include=
"Http\ConnectResponse.cs"
/>
<Compile
Include=
"Http\HeaderCollection.cs"
/>
<Compile
Include=
"Http\HeaderCollection.cs"
/>
<Compile
Include=
"Http\HeaderParser.cs"
/>
<Compile
Include=
"Http\HeaderParser.cs"
/>
<Compile
Include=
"Ssl\SslCiphers.cs"
/>
<Compile
Include=
"Ssl\SslExtension.cs"
/>
<Compile
Include=
"Ssl\SslExtensions.cs"
/>
<Compile
Include=
"Ssl\SslTools.cs"
/>
<Compile
Include=
"Http\HttpWebClient.cs"
/>
<Compile
Include=
"Http\HttpWebClient.cs"
/>
<Compile
Include=
"Http\Request.cs"
/>
<Compile
Include=
"Http\Request.cs"
/>
<Compile
Include=
"Http\Response.cs"
/>
<Compile
Include=
"Http\Response.cs"
/>
...
...
Titanium.Web.Proxy/Titanium.Web.Proxy.nuspec
View file @
0f5f8b48
...
@@ -15,6 +15,7 @@
...
@@ -15,6 +15,7 @@
<tags></tags>
<tags></tags>
<dependencies>
<dependencies>
<dependency
id=
"BouncyCastle"
version=
"1.8.1"
/>
<dependency
id=
"BouncyCastle"
version=
"1.8.1"
/>
<dependency
id=
"StreamExtended"
version=
"1.0.13"
/>
</dependencies>
</dependencies>
</metadata>
</metadata>
<files>
<files>
...
...
Titanium.Web.Proxy/packages.config
View file @
0f5f8b48
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
packages
>
<
packages
>
<
package
id
=
"BouncyCastle"
version
=
"1.8.1"
targetFramework
=
"net45"
/>
<
package
id
=
"BouncyCastle"
version
=
"1.8.1"
targetFramework
=
"net45"
/>
<
package
id
=
"StreamExtended"
version
=
"1.0.13"
targetFramework
=
"net45"
/>
</
packages
>
</
packages
>
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment