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
e1543300
Commit
e1543300
authored
Jun 16, 2017
by
Jehonathan Thomas
Committed by
GitHub
Jun 16, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #275 from justcoding121/beta
Stable
parents
acad670d
ac2877be
Show whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
1241 additions
and
262 deletions
+1241
-262
.gitignore
.gitignore
+1
-1
Program.cs
Examples/Titanium.Web.Proxy.Examples.Basic/Program.cs
+0
-33
ProxyTestController.cs
.../Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
+8
-4
README.md
README.md
+2
-1
SystemProxyTest.cs
Tests/Titanium.Web.Proxy.UnitTests/SystemProxyTest.cs
+128
-0
Titanium.Web.Proxy.UnitTests.csproj
...m.Web.Proxy.UnitTests/Titanium.Web.Proxy.UnitTests.csproj
+1
-0
ProxyInfo.cs
Titanium.Web.Proxy/Helpers/ProxyInfo.cs
+200
-0
SystemProxy.cs
Titanium.Web.Proxy/Helpers/SystemProxy.cs
+236
-103
NativeMethods.WinHttp.cs
Titanium.Web.Proxy/Helpers/WinHttp/NativeMethods.WinHttp.cs
+131
-0
WinHttpHandle.cs
Titanium.Web.Proxy/Helpers/WinHttp/WinHttpHandle.cs
+19
-0
WinHttpWebProxyFinder.cs
Titanium.Web.Proxy/Helpers/WinHttp/WinHttpWebProxyFinder.cs
+332
-0
HttpWebClient.cs
Titanium.Web.Proxy/Http/HttpWebClient.cs
+6
-9
Request.cs
Titanium.Web.Proxy/Http/Request.cs
+8
-6
Response.cs
Titanium.Web.Proxy/Http/Response.cs
+13
-13
ProxyServer.cs
Titanium.Web.Proxy/ProxyServer.cs
+124
-63
RequestHandler.cs
Titanium.Web.Proxy/RequestHandler.cs
+22
-18
ResponseHandler.cs
Titanium.Web.Proxy/ResponseHandler.cs
+0
-5
Titanium.Web.Proxy.csproj
Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
+7
-3
Titanium.Web.Proxy.nuspec
Titanium.Web.Proxy/Titanium.Web.Proxy.nuspec
+3
-3
No files found.
.gitignore
View file @
e1543300
Examples/Titanium.Web.Proxy.Examples.Basic/Program.cs
View file @
e1543300
...
...
@@ -14,10 +14,6 @@ namespace Titanium.Web.Proxy.Examples.Basic
//fix console hang due to QuickEdit mode
ConsoleHelper
.
DisableQuickEditMode
();
//On Console exit make sure we also exit the proxy
NativeMethods
.
Handler
=
ConsoleEventCallback
;
NativeMethods
.
SetConsoleCtrlHandler
(
NativeMethods
.
Handler
,
true
);
//Start proxy controller
controller
.
StartProxy
();
...
...
@@ -27,34 +23,5 @@ namespace Titanium.Web.Proxy.Examples.Basic
controller
.
Stop
();
}
private
static
bool
ConsoleEventCallback
(
int
eventType
)
{
if
(
eventType
!=
2
)
return
false
;
try
{
controller
.
Stop
();
}
catch
{
// ignored
}
return
false
;
}
}
internal
static
class
NativeMethods
{
// Keeps it from getting garbage collected
internal
static
ConsoleEventDelegate
Handler
;
[
DllImport
(
"kernel32.dll"
,
SetLastError
=
true
)]
internal
static
extern
bool
SetConsoleCtrlHandler
(
ConsoleEventDelegate
callback
,
bool
add
);
// Pinvoke
internal
delegate
bool
ConsoleEventDelegate
(
int
eventType
);
}
}
Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
View file @
e1543300
using
System
;
using
System.Collections.Concurrent
;
using
System.Collections.Generic
;
using
System.Net
;
using
System.Net.Security
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.EventArguments
;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.Models
;
namespace
Titanium.Web.Proxy.Examples.Basic
...
...
@@ -15,8 +17,8 @@ namespace Titanium.Web.Proxy.Examples.Basic
//share requestBody outside handlers
//Using a dictionary is not a good idea since it can cause memory overflow
//ideally the data should be moved out of memory
//private readonly Dictionary<Guid, string> requestBodyHistory
// = new Dictionary<Guid, string>();
//private readonly
I
Dictionary<Guid, string> requestBodyHistory
// = new
Concurrent
Dictionary<Guid, string>();
public
ProxyTestController
()
{
...
...
@@ -29,6 +31,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
proxyServer
.
ExceptionFunc
=
exception
=>
Console
.
WriteLine
(
exception
.
Message
);
proxyServer
.
TrustRootCertificate
=
true
;
proxyServer
.
ForwardToUpstreamGateway
=
true
;
//optionally set the Certificate Engine
//Under Mono only BouncyCastle will be supported
...
...
@@ -92,8 +95,9 @@ namespace Titanium.Web.Proxy.Examples.Basic
endPoint
.
GetType
().
Name
,
endPoint
.
IpAddress
,
endPoint
.
Port
);
//Only explicit proxies can be set as system proxy!
proxyServer
.
SetAsSystemHttpProxy
(
explicitEndPoint
);
proxyServer
.
SetAsSystemHttpsProxy
(
explicitEndPoint
);
//proxyServer.SetAsSystemHttpProxy(explicitEndPoint);
//proxyServer.SetAsSystemHttpsProxy(explicitEndPoint);
proxyServer
.
SetAsSystemProxy
(
explicitEndPoint
,
ProxyProtocolType
.
AllHttp
);
}
public
void
Stop
()
...
...
README.md
View file @
e1543300
...
...
@@ -112,7 +112,8 @@ Sample request and response event handlers
```
csharp
//To access requestBody from OnResponse handler
private
Dictionary
<
Guid
,
string
>
requestBodyHistory
=
new
Dictionary
<
Guid
,
string
>();
private
IDictionary
<
Guid
,
string
>
requestBodyHistory
=
new
ConcurrentDictionary
<
Guid
,
string
>();
public
async
Task
OnRequest
(
object
sender
,
SessionEventArgs
e
)
{
...
...
Tests/Titanium.Web.Proxy.UnitTests/SystemProxyTest.cs
0 → 100644
View file @
e1543300
using
System
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Net
;
using
System.Text
;
using
System.Threading.Tasks
;
using
Microsoft.VisualStudio.TestTools.UnitTesting
;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.Helpers.WinHttp
;
namespace
Titanium.Web.Proxy.UnitTests
{
[
TestClass
]
public
class
SystemProxyTest
{
[
TestMethod
]
public
void
CompareProxyAdddressReturendByWebProxyAndWinHttpProxyResolver
()
{
var
proxyManager
=
new
SystemProxyManager
();
try
{
CompareUrls
();
proxyManager
.
SetProxy
(
"127.0.0.1"
,
8000
,
ProxyProtocolType
.
Http
);
CompareUrls
();
proxyManager
.
SetProxy
(
"127.0.0.1"
,
8000
,
ProxyProtocolType
.
Https
);
CompareUrls
();
proxyManager
.
SetProxy
(
"127.0.0.1"
,
8000
,
ProxyProtocolType
.
AllHttp
);
CompareUrls
();
// for this test you need to add a proxy.pac file to a local webserver
//function FindProxyForURL(url, host)
//{
// if (shExpMatch(host, "google.com"))
// {
// return "PROXY 127.0.0.1:8888";
// }
// return "DIRECT";
//}
//proxyManager.SetAutoProxyUrl("http://localhost/proxy.pac");
//CompareUrls();
proxyManager
.
SetProxyOverride
(
"<-loopback>"
);
CompareUrls
();
proxyManager
.
SetProxyOverride
(
"<local>"
);
CompareUrls
();
proxyManager
.
SetProxyOverride
(
"yahoo.com"
);
CompareUrls
();
proxyManager
.
SetProxyOverride
(
"*.local"
);
CompareUrls
();
proxyManager
.
SetProxyOverride
(
"http://*.local"
);
CompareUrls
();
proxyManager
.
SetProxyOverride
(
"<-loopback>;*.local"
);
CompareUrls
();
proxyManager
.
SetProxyOverride
(
"<-loopback>;*.local;<local>"
);
CompareUrls
();
}
finally
{
proxyManager
.
RestoreOriginalSettings
();
}
}
private
void
CompareUrls
()
{
var
webProxy
=
WebRequest
.
GetSystemWebProxy
();
var
resolver
=
new
WinHttpWebProxyFinder
();
resolver
.
LoadFromIE
();
CompareProxy
(
webProxy
,
resolver
,
"http://127.0.0.1"
);
CompareProxy
(
webProxy
,
resolver
,
"https://127.0.0.1"
);
CompareProxy
(
webProxy
,
resolver
,
"http://localhost"
);
CompareProxy
(
webProxy
,
resolver
,
"https://localhost"
);
string
hostName
=
null
;
try
{
hostName
=
Dns
.
GetHostName
();
}
catch
{}
if
(
hostName
!=
null
)
{
CompareProxy
(
webProxy
,
resolver
,
"http://"
+
hostName
);
CompareProxy
(
webProxy
,
resolver
,
"https://"
+
hostName
);
}
CompareProxy
(
webProxy
,
resolver
,
"http://google.com"
);
CompareProxy
(
webProxy
,
resolver
,
"https://google.com"
);
CompareProxy
(
webProxy
,
resolver
,
"http://bing.com"
);
CompareProxy
(
webProxy
,
resolver
,
"https://bing.com"
);
CompareProxy
(
webProxy
,
resolver
,
"http://yahoo.com"
);
CompareProxy
(
webProxy
,
resolver
,
"https://yahoo.com"
);
CompareProxy
(
webProxy
,
resolver
,
"http://test.local"
);
CompareProxy
(
webProxy
,
resolver
,
"https://test.local"
);
}
private
void
CompareProxy
(
IWebProxy
webProxy
,
WinHttpWebProxyFinder
resolver
,
string
url
)
{
var
uri
=
new
Uri
(
url
);
var
expectedProxyUri
=
webProxy
.
GetProxy
(
uri
);
var
proxy
=
resolver
.
GetProxy
(
uri
);
if
(
expectedProxyUri
==
uri
)
{
// no proxy
Assert
.
AreEqual
(
proxy
,
null
);
return
;
}
Assert
.
AreEqual
(
expectedProxyUri
.
ToString
(),
$"http://
{
proxy
.
HostName
}
:
{
proxy
.
Port
}
/"
);
}
}
}
Tests/Titanium.Web.Proxy.UnitTests/Titanium.Web.Proxy.UnitTests.csproj
View file @
e1543300
...
...
@@ -60,6 +60,7 @@
<Compile
Include=
"CertificateManagerTests.cs"
/>
<Compile
Include=
"Properties\AssemblyInfo.cs"
/>
<Compile
Include=
"ProxyServerTests.cs"
/>
<Compile
Include=
"SystemProxyTest.cs"
/>
<Compile
Include=
"WinAuthTests.cs"
/>
</ItemGroup>
<ItemGroup>
...
...
Titanium.Web.Proxy/Helpers/ProxyInfo.cs
0 → 100644
View file @
e1543300
using
System
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Text
;
using
System.Text.RegularExpressions
;
using
System.Threading.Tasks
;
namespace
Titanium.Web.Proxy.Helpers
{
internal
class
ProxyInfo
{
public
bool
?
AutoDetect
{
get
;
}
public
string
AutoConfigUrl
{
get
;
}
public
int
?
ProxyEnable
{
get
;
}
public
string
ProxyServer
{
get
;
}
public
string
ProxyOverride
{
get
;
}
public
bool
BypassLoopback
{
get
;
}
public
bool
BypassOnLocal
{
get
;
}
public
Dictionary
<
ProxyProtocolType
,
HttpSystemProxyValue
>
Proxies
{
get
;
}
public
string
[]
BypassList
{
get
;
}
public
ProxyInfo
(
bool
?
autoDetect
,
string
autoConfigUrl
,
int
?
proxyEnable
,
string
proxyServer
,
string
proxyOverride
)
{
AutoDetect
=
autoDetect
;
AutoConfigUrl
=
autoConfigUrl
;
ProxyEnable
=
proxyEnable
;
ProxyServer
=
proxyServer
;
ProxyOverride
=
proxyOverride
;
if
(
proxyServer
!=
null
)
{
Proxies
=
GetSystemProxyValues
(
proxyServer
).
ToDictionary
(
x
=>
x
.
ProtocolType
);
}
if
(
proxyOverride
!=
null
)
{
var
overrides
=
proxyOverride
.
Split
(
';'
);
var
overrides2
=
new
List
<
string
>();
foreach
(
var
overrideHost
in
overrides
)
{
if
(
overrideHost
==
"<-loopback>"
)
{
BypassLoopback
=
true
;
}
else
if
(
overrideHost
==
"<local>"
)
{
BypassOnLocal
=
true
;
}
else
{
overrides2
.
Add
(
BypassStringEscape
(
overrideHost
));
}
}
if
(
overrides2
.
Count
>
0
)
{
BypassList
=
overrides2
.
ToArray
();
}
Proxies
=
GetSystemProxyValues
(
proxyServer
).
ToDictionary
(
x
=>
x
.
ProtocolType
);
}
}
private
static
string
BypassStringEscape
(
string
rawString
)
{
Match
match
=
new
Regex
(
"^(?<scheme>.*://)?(?<host>[^:]*)(?<port>:[0-9]{1,5})?$"
,
RegexOptions
.
IgnoreCase
|
RegexOptions
.
CultureInvariant
).
Match
(
rawString
);
string
empty1
;
string
rawString1
;
string
empty2
;
if
(
match
.
Success
)
{
empty1
=
match
.
Groups
[
"scheme"
].
Value
;
rawString1
=
match
.
Groups
[
"host"
].
Value
;
empty2
=
match
.
Groups
[
"port"
].
Value
;
}
else
{
empty1
=
string
.
Empty
;
rawString1
=
rawString
;
empty2
=
string
.
Empty
;
}
string
str1
=
ConvertRegexReservedChars
(
empty1
);
string
str2
=
ConvertRegexReservedChars
(
rawString1
);
string
str3
=
ConvertRegexReservedChars
(
empty2
);
if
(
str1
==
string
.
Empty
)
str1
=
"(?:.*://)?"
;
if
(
str3
==
string
.
Empty
)
str3
=
"(?::[0-9]{1,5})?"
;
return
"^"
+
str1
+
str2
+
str3
+
"$"
;
}
private
static
string
ConvertRegexReservedChars
(
string
rawString
)
{
if
(
rawString
.
Length
==
0
)
return
rawString
;
var
stringBuilder
=
new
StringBuilder
();
foreach
(
char
ch
in
rawString
)
{
if
(
"#$()+.?[\\^{|"
.
IndexOf
(
ch
)
!=
-
1
)
stringBuilder
.
Append
(
'\\'
);
else
if
(
ch
==
42
)
stringBuilder
.
Append
(
'.'
);
stringBuilder
.
Append
(
ch
);
}
return
stringBuilder
.
ToString
();
}
public
static
ProxyProtocolType
?
ParseProtocolType
(
string
protocolTypeStr
)
{
if
(
protocolTypeStr
==
null
)
{
return
null
;
}
ProxyProtocolType
?
protocolType
=
null
;
if
(
protocolTypeStr
.
Equals
(
"http"
,
StringComparison
.
InvariantCultureIgnoreCase
))
{
protocolType
=
ProxyProtocolType
.
Http
;
}
else
if
(
protocolTypeStr
.
Equals
(
"https"
,
StringComparison
.
InvariantCultureIgnoreCase
))
{
protocolType
=
ProxyProtocolType
.
Https
;
}
return
protocolType
;
}
/// <summary>
/// Parse the system proxy setting values
/// </summary>
/// <param name="proxyServerValues"></param>
/// <returns></returns>
public
static
List
<
HttpSystemProxyValue
>
GetSystemProxyValues
(
string
proxyServerValues
)
{
var
result
=
new
List
<
HttpSystemProxyValue
>();
if
(
string
.
IsNullOrWhiteSpace
(
proxyServerValues
))
return
result
;
var
proxyValues
=
proxyServerValues
.
Split
(
';'
);
if
(
proxyValues
.
Length
>
0
)
{
result
.
AddRange
(
proxyValues
.
Select
(
ParseProxyValue
).
Where
(
parsedValue
=>
parsedValue
!=
null
));
}
else
{
var
parsedValue
=
ParseProxyValue
(
proxyServerValues
);
if
(
parsedValue
!=
null
)
result
.
Add
(
parsedValue
);
}
return
result
;
}
/// <summary>
/// Parses the system proxy setting string
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
private
static
HttpSystemProxyValue
ParseProxyValue
(
string
value
)
{
var
tmp
=
Regex
.
Replace
(
value
,
@"\s+"
,
" "
).
Trim
();
int
equalsIndex
=
tmp
.
IndexOf
(
"="
,
StringComparison
.
InvariantCulture
);
if
(
equalsIndex
>=
0
)
{
string
protocolTypeStr
=
tmp
.
Substring
(
0
,
equalsIndex
);
var
protocolType
=
ParseProtocolType
(
protocolTypeStr
);
if
(
protocolType
.
HasValue
)
{
var
endPointParts
=
tmp
.
Substring
(
equalsIndex
+
1
).
Split
(
':'
);
return
new
HttpSystemProxyValue
{
HostName
=
endPointParts
[
0
],
Port
=
int
.
Parse
(
endPointParts
[
1
]),
ProtocolType
=
protocolType
.
Value
,
};
}
}
return
null
;
}
}
}
Titanium.Web.Proxy/Helpers/SystemProxy.cs
View file @
e1543300
...
...
@@ -2,16 +2,33 @@
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Runtime.InteropServices
;
using
System.Text.RegularExpressions
;
using
Microsoft.Win32
;
// Helper classes for setting system proxy settings
namespace
Titanium.Web.Proxy.Helpers
{
internal
enum
ProxyProtocolType
[
Flags
]
public
enum
ProxyProtocolType
{
Http
,
Https
,
/// <summary>
/// The none
/// </summary>
None
=
0
,
/// <summary>
/// HTTP
/// </summary>
Http
=
1
,
/// <summary>
/// HTTPS
/// </summary>
Https
=
2
,
/// <summary>
/// Both HTTP and HTTPS
/// </summary>
AllHttp
=
Http
|
Https
,
}
internal
partial
class
NativeMethods
...
...
@@ -19,17 +36,44 @@ namespace Titanium.Web.Proxy.Helpers
[
DllImport
(
"wininet.dll"
)]
internal
static
extern
bool
InternetSetOption
(
IntPtr
hInternet
,
int
dwOption
,
IntPtr
lpBuffer
,
int
dwBufferLength
);
[
DllImport
(
"kernel32.dll"
)]
internal
static
extern
IntPtr
GetConsoleWindow
();
// Keeps it from getting garbage collected
internal
static
ConsoleEventDelegate
Handler
;
[
DllImport
(
"kernel32.dll"
,
SetLastError
=
true
)]
internal
static
extern
bool
SetConsoleCtrlHandler
(
ConsoleEventDelegate
callback
,
bool
add
);
// Pinvoke
internal
delegate
bool
ConsoleEventDelegate
(
int
eventType
);
}
internal
class
HttpSystemProxyValue
{
internal
string
HostName
{
get
;
set
;
}
internal
int
Port
{
get
;
set
;
}
internal
bool
IsHttps
{
get
;
set
;
}
internal
ProxyProtocolType
ProtocolType
{
get
;
set
;
}
public
override
string
ToString
()
{
return
$"
{(
IsHttps
?
"https"
:
"http"
)}
=
{
HostName
}
:
{
Port
}
"
;
string
protocol
;
switch
(
ProtocolType
)
{
case
ProxyProtocolType
.
Http
:
protocol
=
"http"
;
break
;
case
ProxyProtocolType
.
Https
:
protocol
=
"https"
;
break
;
default
:
throw
new
Exception
(
"Unsupported protocol type"
);
}
return
$"
{
protocol
}
=
{
HostName
}
:
{
Port
}
"
;
}
}
...
...
@@ -38,174 +82,263 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary>
internal
class
SystemProxyManager
{
private
const
string
regKeyInternetSettings
=
"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
;
private
const
string
regAutoConfigUrl
=
"AutoConfigURL"
;
private
const
string
regProxyEnable
=
"ProxyEnable"
;
private
const
string
regProxyServer
=
"ProxyServer"
;
private
const
string
regProxyOverride
=
"ProxyOverride"
;
internal
const
int
InternetOptionSettingsChanged
=
39
;
internal
const
int
InternetOptionRefresh
=
37
;
internal
void
SetHttpProxy
(
string
hostname
,
int
port
)
private
ProxyInfo
originalValues
;
public
SystemProxyManager
()
{
AppDomain
.
CurrentDomain
.
ProcessExit
+=
(
o
,
args
)
=>
RestoreOriginalSettings
();
if
(
Environment
.
UserInteractive
&&
NativeMethods
.
GetConsoleWindow
()
!=
IntPtr
.
Zero
)
{
NativeMethods
.
Handler
=
eventType
=>
{
if
(
eventType
!=
2
)
{
SetProxy
(
hostname
,
port
,
ProxyProtocolType
.
Http
)
;
return
false
;
}
/// <summary>
/// Remove the http proxy setting from current machine
/// </summary>
internal
void
RemoveHttpProxy
()
{
RemoveProxy
(
ProxyProtocolType
.
Http
);
RestoreOriginalSettings
();
return
false
;
};
//On Console exit make sure we also exit the proxy
NativeMethods
.
SetConsoleCtrlHandler
(
NativeMethods
.
Handler
,
true
);
}
}
/// <summary>
/// Set the HTTPS proxy server for current machine
/// Set the HTTP
and/or HTTP
S proxy server for current machine
/// </summary>
/// <param name="hostname"></param>
/// <param name="port"></param>
internal
void
SetHttpsProxy
(
string
hostname
,
int
port
)
{
SetProxy
(
hostname
,
port
,
ProxyProtocolType
.
Https
);
}
/// <summary>
/// Removes the https proxy setting to nothing
/// </summary>
internal
void
RemoveHttpsProxy
()
{
RemoveProxy
(
ProxyProtocolType
.
Https
);
}
private
void
SetProxy
(
string
hostname
,
int
port
,
ProxyProtocolType
protocolType
)
/// <param name="protocolType"></param>
internal
void
SetProxy
(
string
hostname
,
int
port
,
ProxyProtocolType
protocolType
)
{
var
reg
=
Registry
.
CurrentUser
.
OpenSubKey
(
"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
,
true
);
var
reg
=
Registry
.
CurrentUser
.
OpenSubKey
(
regKeyInternetSettings
,
true
);
if
(
reg
!=
null
)
{
SaveOriginalProxyConfiguration
(
reg
);
PrepareRegistry
(
reg
);
var
exisitingContent
=
reg
.
GetValue
(
"ProxyServer"
)
as
string
;
var
existingSystemProxyValues
=
GetSystemProxyValues
(
exisitingContent
);
existingSystemProxyValues
.
RemoveAll
(
x
=>
protocolType
==
ProxyProtocolType
.
Https
?
x
.
IsHttps
:
!
x
.
IsHttps
);
var
exisitingContent
=
reg
.
GetValue
(
regProxyServer
)
as
string
;
var
existingSystemProxyValues
=
ProxyInfo
.
GetSystemProxyValues
(
exisitingContent
);
existingSystemProxyValues
.
RemoveAll
(
x
=>
(
protocolType
&
x
.
ProtocolType
)
!=
0
);
if
((
protocolType
&
ProxyProtocolType
.
Http
)
!=
0
)
{
existingSystemProxyValues
.
Add
(
new
HttpSystemProxyValue
{
HostName
=
hostname
,
IsHttps
=
protocolType
==
ProxyProtocolType
.
Https
,
ProtocolType
=
ProxyProtocolType
.
Http
,
Port
=
port
});
}
reg
.
SetValue
(
"ProxyEnable"
,
1
);
reg
.
SetValue
(
"ProxyServer"
,
string
.
Join
(
";"
,
existingSystemProxyValues
.
Select
(
x
=>
x
.
ToString
()).
ToArray
()));
if
((
protocolType
&
ProxyProtocolType
.
Https
)
!=
0
)
{
existingSystemProxyValues
.
Add
(
new
HttpSystemProxyValue
{
HostName
=
hostname
,
ProtocolType
=
ProxyProtocolType
.
Https
,
Port
=
port
});
}
reg
.
DeleteValue
(
regAutoConfigUrl
,
false
);
reg
.
SetValue
(
regProxyEnable
,
1
);
reg
.
SetValue
(
regProxyServer
,
string
.
Join
(
";"
,
existingSystemProxyValues
.
Select
(
x
=>
x
.
ToString
()).
ToArray
()));
Refresh
();
}
}
private
void
RemoveProxy
(
ProxyProtocolType
protocolType
)
/// <summary>
/// Remove the HTTP and/or HTTPS proxy setting from current machine
/// </summary>
internal
void
RemoveProxy
(
ProxyProtocolType
protocolType
,
bool
saveOriginalConfig
=
true
)
{
var
reg
=
Registry
.
CurrentUser
.
OpenSubKey
(
regKeyInternetSettings
,
true
);
if
(
reg
!=
null
)
{
var
reg
=
Registry
.
CurrentUser
.
OpenSubKey
(
"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
,
true
);
if
(
reg
?.
GetValue
(
"ProxyServer"
)
!=
null
)
if
(
saveOriginalConfig
)
{
SaveOriginalProxyConfiguration
(
reg
);
}
if
(
reg
.
GetValue
(
regProxyServer
)
!=
null
)
{
var
exisitingContent
=
reg
.
GetValue
(
"ProxyServer"
)
as
string
;
var
exisitingContent
=
reg
.
GetValue
(
regProxyServer
)
as
string
;
var
existingSystemProxyValues
=
GetSystemProxyValues
(
exisitingContent
);
existingSystemProxyValues
.
RemoveAll
(
x
=>
protocolType
==
ProxyProtocolType
.
Https
?
x
.
IsHttps
:
!
x
.
IsHttps
);
var
existingSystemProxyValues
=
ProxyInfo
.
GetSystemProxyValues
(
exisitingContent
);
existingSystemProxyValues
.
RemoveAll
(
x
=>
(
protocolType
&
x
.
ProtocolType
)
!=
0
);
if
(
existingSystemProxyValues
.
Count
!=
0
)
{
reg
.
SetValue
(
"ProxyEnable"
,
1
);
reg
.
SetValue
(
"ProxyServer"
,
string
.
Join
(
";"
,
existingSystemProxyValues
.
Select
(
x
=>
x
.
ToString
()).
ToArray
()));
reg
.
SetValue
(
regProxyEnable
,
1
);
reg
.
SetValue
(
regProxyServer
,
string
.
Join
(
";"
,
existingSystemProxyValues
.
Select
(
x
=>
x
.
ToString
()).
ToArray
()));
}
else
{
reg
.
SetValue
(
"ProxyEnable"
,
0
);
reg
.
SetValue
(
"ProxyServer"
,
string
.
Empty
);
reg
.
SetValue
(
regProxyEnable
,
0
);
reg
.
SetValue
(
regProxyServer
,
string
.
Empty
);
}
}
Refresh
();
}
}
/// <summary>
/// Removes all types of proxy settings (both http and https)
/// </summary>
internal
void
DisableAllProxy
()
{
var
reg
=
Registry
.
CurrentUser
.
OpenSubKey
(
"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
,
true
);
var
reg
=
Registry
.
CurrentUser
.
OpenSubKey
(
regKeyInternetSettings
,
true
);
if
(
reg
!=
null
)
{
reg
.
SetValue
(
"ProxyEnable"
,
0
);
reg
.
SetValue
(
"ProxyServer"
,
string
.
Empty
);
SaveOriginalProxyConfiguration
(
reg
);
reg
.
SetValue
(
regProxyEnable
,
0
);
reg
.
SetValue
(
regProxyServer
,
string
.
Empty
);
Refresh
();
}
}
internal
void
SetAutoProxyUrl
(
string
url
)
{
var
reg
=
Registry
.
CurrentUser
.
OpenSubKey
(
regKeyInternetSettings
,
true
);
if
(
reg
!=
null
)
{
SaveOriginalProxyConfiguration
(
reg
);
reg
.
SetValue
(
regAutoConfigUrl
,
url
);
Refresh
();
}
}
/// <summary>
/// Get the current system proxy setting values
/// </summary>
/// <param name="prevServerValue"></param>
/// <returns></returns>
private
List
<
HttpSystemProxyValue
>
GetSystemProxyValues
(
string
prevServerValue
)
internal
void
SetProxyOverride
(
string
proxyOverride
)
{
var
reg
=
Registry
.
CurrentUser
.
OpenSubKey
(
regKeyInternetSettings
,
true
);
if
(
reg
!=
null
)
{
var
result
=
new
List
<
HttpSystemProxyValue
>();
SaveOriginalProxyConfiguration
(
reg
);
reg
.
SetValue
(
regProxyOverride
,
proxyOverride
);
Refresh
();
}
}
if
(
string
.
IsNullOrWhiteSpace
(
prevServerValue
))
return
result
;
internal
void
RestoreOriginalSettings
()
{
if
(
originalValues
==
null
)
{
return
;
}
var
proxyValues
=
prevServerValue
.
Split
(
';'
);
var
reg
=
Registry
.
CurrentUser
.
OpenSubKey
(
regKeyInternetSettings
,
true
);
if
(
proxyValues
.
Length
>
0
)
if
(
reg
!=
null
)
{
var
ov
=
originalValues
;
if
(
ov
.
AutoConfigUrl
!=
null
)
{
result
.
AddRange
(
proxyValues
.
Select
(
ParseProxyValue
).
Where
(
parsedValue
=>
parsedValue
!=
null
)
);
reg
.
SetValue
(
regAutoConfigUrl
,
ov
.
AutoConfigUrl
);
}
else
{
var
parsedValue
=
ParseProxyValue
(
prevServerValue
);
if
(
parsedValue
!=
null
)
result
.
Add
(
parsedValue
);
reg
.
DeleteValue
(
regAutoConfigUrl
,
false
);
}
return
result
;
if
(
ov
.
ProxyEnable
.
HasValue
)
{
reg
.
SetValue
(
regProxyEnable
,
ov
.
ProxyEnable
.
Value
);
}
else
{
reg
.
DeleteValue
(
regProxyEnable
,
false
);
}
/// <summary>
/// Parses the system proxy setting string
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
private
HttpSystemProxyValue
ParseProxyValue
(
string
value
)
if
(
ov
.
ProxyServer
!=
null
)
{
reg
.
SetValue
(
regProxyServer
,
ov
.
ProxyServer
);
}
else
{
var
tmp
=
Regex
.
Replace
(
value
,
@"\s+"
,
" "
).
Trim
().
ToLower
();
reg
.
DeleteValue
(
regProxyServer
,
false
);
}
if
(
tmp
.
StartsWith
(
"http="
)
||
tmp
.
StartsWith
(
"https="
)
)
if
(
ov
.
ProxyOverride
!=
null
)
{
var
endPoint
=
tmp
.
Substring
(
5
);
return
new
HttpSystemProxyValue
reg
.
SetValue
(
regProxyOverride
,
ov
.
ProxyOverride
);
}
else
{
HostName
=
endPoint
.
Split
(
':'
)[
0
],
Port
=
int
.
Parse
(
endPoint
.
Split
(
':'
)[
1
]),
IsHttps
=
tmp
.
StartsWith
(
"https="
)
};
reg
.
DeleteValue
(
regProxyOverride
,
false
);
}
originalValues
=
null
;
Refresh
();
}
}
internal
ProxyInfo
GetProxyInfoFromRegistry
()
{
var
reg
=
Registry
.
CurrentUser
.
OpenSubKey
(
regKeyInternetSettings
,
true
);
if
(
reg
!=
null
)
{
return
GetProxyInfoFromRegistry
(
reg
);
}
return
null
;
}
private
ProxyInfo
GetProxyInfoFromRegistry
(
RegistryKey
reg
)
{
var
pi
=
new
ProxyInfo
(
null
,
reg
.
GetValue
(
regAutoConfigUrl
)
as
string
,
reg
.
GetValue
(
regProxyEnable
)
as
int
?,
reg
.
GetValue
(
regProxyServer
)
as
string
,
reg
.
GetValue
(
regProxyOverride
)
as
string
);
return
pi
;
}
private
void
SaveOriginalProxyConfiguration
(
RegistryKey
reg
)
{
if
(
originalValues
!=
null
)
{
return
;
}
originalValues
=
GetProxyInfoFromRegistry
(
reg
);
}
/// <summary>
/// Prepares the proxy server registry (create empty values if they don't exist)
/// </summary>
/// <param name="reg"></param>
private
static
void
PrepareRegistry
(
RegistryKey
reg
)
{
if
(
reg
.
GetValue
(
"ProxyEnable"
)
==
null
)
if
(
reg
.
GetValue
(
regProxyEnable
)
==
null
)
{
reg
.
SetValue
(
"ProxyEnable"
,
0
);
reg
.
SetValue
(
regProxyEnable
,
0
);
}
if
(
reg
.
GetValue
(
"ProxyServer"
)
==
null
||
reg
.
GetValue
(
"ProxyEnable"
)
as
string
==
"0"
)
if
(
reg
.
GetValue
(
regProxyServer
)
==
null
||
reg
.
GetValue
(
regProxyEnable
)
as
int
?
==
0
)
{
reg
.
SetValue
(
"ProxyServer"
,
string
.
Empty
);
reg
.
SetValue
(
regProxyServer
,
string
.
Empty
);
}
}
...
...
Titanium.Web.Proxy/Helpers/WinHttp/NativeMethods.WinHttp.cs
0 → 100644
View file @
e1543300
using
System
;
using
System.Runtime.InteropServices
;
// Helper classes for setting system proxy settings
namespace
Titanium.Web.Proxy.Helpers.WinHttp
{
internal
partial
class
NativeMethods
{
internal
static
class
WinHttp
{
[
DllImport
(
"winhttp.dll"
,
SetLastError
=
true
)]
internal
static
extern
bool
WinHttpGetIEProxyConfigForCurrentUser
(
ref
WINHTTP_CURRENT_USER_IE_PROXY_CONFIG
proxyConfig
);
[
DllImport
(
"winhttp.dll"
,
CharSet
=
CharSet
.
Unicode
,
SetLastError
=
true
)]
internal
static
extern
WinHttpHandle
WinHttpOpen
(
string
userAgent
,
AccessType
accessType
,
string
proxyName
,
string
proxyBypass
,
int
dwFlags
);
[
DllImport
(
"winhttp.dll"
,
CharSet
=
CharSet
.
Unicode
,
SetLastError
=
true
)]
internal
static
extern
bool
WinHttpSetTimeouts
(
WinHttpHandle
session
,
int
resolveTimeout
,
int
connectTimeout
,
int
sendTimeout
,
int
receiveTimeout
);
[
DllImport
(
"winhttp.dll"
,
CharSet
=
CharSet
.
Unicode
,
SetLastError
=
true
)]
internal
static
extern
bool
WinHttpGetProxyForUrl
(
WinHttpHandle
session
,
string
url
,
[
In
]
ref
WINHTTP_AUTOPROXY_OPTIONS
autoProxyOptions
,
out
WINHTTP_PROXY_INFO
proxyInfo
);
[
DllImport
(
"winhttp.dll"
,
CharSet
=
CharSet
.
Unicode
,
SetLastError
=
true
)]
internal
static
extern
bool
WinHttpCloseHandle
(
IntPtr
httpSession
);
[
StructLayout
(
LayoutKind
.
Sequential
,
CharSet
=
CharSet
.
Unicode
)]
internal
struct
WINHTTP_CURRENT_USER_IE_PROXY_CONFIG
{
public
bool
AutoDetect
;
public
IntPtr
AutoConfigUrl
;
public
IntPtr
Proxy
;
public
IntPtr
ProxyBypass
;
}
[
Flags
]
internal
enum
AutoProxyFlags
{
AutoDetect
=
1
,
AutoProxyConfigUrl
=
2
,
RunInProcess
=
65536
,
RunOutProcessOnly
=
131072
}
internal
enum
AccessType
{
DefaultProxy
=
0
,
NoProxy
=
1
,
NamedProxy
=
3
}
[
Flags
]
internal
enum
AutoDetectType
{
None
=
0
,
Dhcp
=
1
,
DnsA
=
2
}
[
StructLayout
(
LayoutKind
.
Sequential
,
CharSet
=
CharSet
.
Unicode
)]
internal
struct
WINHTTP_AUTOPROXY_OPTIONS
{
public
AutoProxyFlags
Flags
;
public
AutoDetectType
AutoDetectFlags
;
[
MarshalAs
(
UnmanagedType
.
LPWStr
)]
public
string
AutoConfigUrl
;
private
IntPtr
lpvReserved
;
private
int
dwReserved
;
public
bool
AutoLogonIfChallenged
;
}
[
StructLayout
(
LayoutKind
.
Sequential
,
CharSet
=
CharSet
.
Unicode
)]
internal
struct
WINHTTP_PROXY_INFO
{
public
AccessType
AccessType
;
public
IntPtr
Proxy
;
public
IntPtr
ProxyBypass
;
}
internal
enum
ErrorCodes
{
Success
=
0
,
OutOfHandles
=
12001
,
Timeout
=
12002
,
InternalError
=
12004
,
InvalidUrl
=
12005
,
UnrecognizedScheme
=
12006
,
NameNotResolved
=
12007
,
InvalidOption
=
12009
,
OptionNotSettable
=
12011
,
Shutdown
=
12012
,
LoginFailure
=
12015
,
OperationCancelled
=
12017
,
IncorrectHandleType
=
12018
,
IncorrectHandleState
=
12019
,
CannotConnect
=
12029
,
ConnectionError
=
12030
,
ResendRequest
=
12032
,
SecureCertDateInvalid
=
12037
,
SecureCertCNInvalid
=
12038
,
AuthCertNeeded
=
12044
,
SecureInvalidCA
=
12045
,
SecureCertRevFailed
=
12057
,
CannotCallBeforeOpen
=
12100
,
CannotCallBeforeSend
=
12101
,
CannotCallAfterSend
=
12102
,
CannotCallAfterOpen
=
12103
,
HeaderNotFound
=
12150
,
InvalidServerResponse
=
12152
,
InvalidHeader
=
12153
,
InvalidQueryRequest
=
12154
,
HeaderAlreadyExists
=
12155
,
RedirectFailed
=
12156
,
SecureChannelError
=
12157
,
BadAutoProxyScript
=
12166
,
UnableToDownloadScript
=
12167
,
SecureInvalidCert
=
12169
,
SecureCertRevoked
=
12170
,
NotInitialized
=
12172
,
SecureFailure
=
12175
,
AutoProxyServiceError
=
12178
,
SecureCertWrongUsage
=
12179
,
AudodetectionFailed
=
12180
,
HeaderCountExceeded
=
12181
,
HeaderSizeOverflow
=
12182
,
ChunkedEncodingHeaderSizeOverflow
=
12183
,
ResponseDrainOverflow
=
12184
,
ClientCertNoPrivateKey
=
12185
,
ClientCertNoAccessPrivateKey
=
12186
}
}
}
}
Titanium.Web.Proxy/Helpers/WinHttp/WinHttpHandle.cs
0 → 100644
View file @
e1543300
using
System
;
using
System.Runtime.InteropServices
;
namespace
Titanium.Web.Proxy.Helpers.WinHttp
{
internal
class
WinHttpHandle
:
SafeHandle
{
public
WinHttpHandle
()
:
base
(
IntPtr
.
Zero
,
true
)
{
}
protected
override
bool
ReleaseHandle
()
{
return
NativeMethods
.
WinHttp
.
WinHttpCloseHandle
(
handle
);
}
public
override
bool
IsInvalid
=>
handle
==
IntPtr
.
Zero
;
}
}
\ No newline at end of file
Titanium.Web.Proxy/Helpers/WinHttp/WinHttpWebProxyFinder.cs
0 → 100644
View file @
e1543300
using
System
;
using
System.Collections.Generic
;
using
System.Net
;
using
System.Runtime.CompilerServices
;
using
System.Runtime.InteropServices
;
using
System.Text
;
using
Titanium.Web.Proxy.Models
;
namespace
Titanium.Web.Proxy.Helpers.WinHttp
{
internal
sealed
class
WinHttpWebProxyFinder
:
IDisposable
{
private
readonly
WinHttpHandle
session
;
private
bool
autoDetectFailed
;
private
AutoWebProxyState
state
;
public
ICredentials
Credentials
{
get
;
set
;
}
public
ProxyInfo
ProxyInfo
{
get
;
internal
set
;
}
public
bool
BypassLoopback
{
get
;
internal
set
;
}
public
bool
BypassOnLocal
{
get
;
internal
set
;
}
public
Uri
AutomaticConfigurationScript
{
get
;
internal
set
;
}
public
bool
AutomaticallyDetectSettings
{
get
;
internal
set
;
}
private
WebProxy
Proxy
{
get
;
set
;
}
public
WinHttpWebProxyFinder
()
{
session
=
NativeMethods
.
WinHttp
.
WinHttpOpen
(
null
,
NativeMethods
.
WinHttp
.
AccessType
.
NoProxy
,
null
,
null
,
0
);
if
(
session
==
null
||
session
.
IsInvalid
)
{
int
lastWin32Error
=
GetLastWin32Error
();
}
else
{
int
downloadTimeout
=
60
*
1000
;
if
(
NativeMethods
.
WinHttp
.
WinHttpSetTimeouts
(
session
,
downloadTimeout
,
downloadTimeout
,
downloadTimeout
,
downloadTimeout
))
return
;
int
lastWin32Error
=
GetLastWin32Error
();
}
}
public
bool
GetAutoProxies
(
Uri
destination
,
out
IList
<
string
>
proxyList
)
{
proxyList
=
null
;
if
(
session
==
null
||
session
.
IsInvalid
||
state
==
AutoWebProxyState
.
UnrecognizedScheme
)
return
false
;
string
proxyListString
=
null
;
var
errorCode
=
NativeMethods
.
WinHttp
.
ErrorCodes
.
AudodetectionFailed
;
if
(
AutomaticallyDetectSettings
&&
!
autoDetectFailed
)
{
errorCode
=
(
NativeMethods
.
WinHttp
.
ErrorCodes
)
GetAutoProxies
(
destination
,
null
,
out
proxyListString
);
autoDetectFailed
=
IsErrorFatalForAutoDetect
(
errorCode
);
if
(
errorCode
==
NativeMethods
.
WinHttp
.
ErrorCodes
.
UnrecognizedScheme
)
{
state
=
AutoWebProxyState
.
UnrecognizedScheme
;
return
false
;
}
}
if
(
AutomaticConfigurationScript
!=
null
&&
IsRecoverableAutoProxyError
(
errorCode
))
errorCode
=
(
NativeMethods
.
WinHttp
.
ErrorCodes
)
GetAutoProxies
(
destination
,
AutomaticConfigurationScript
,
out
proxyListString
);
state
=
GetStateFromErrorCode
(
errorCode
);
if
(
state
!=
AutoWebProxyState
.
Completed
)
return
false
;
if
(!
string
.
IsNullOrEmpty
(
proxyListString
))
{
proxyListString
=
RemoveWhitespaces
(
proxyListString
);
proxyList
=
proxyListString
.
Split
(
';'
);
}
return
true
;
}
public
ExternalProxy
GetProxy
(
Uri
destination
)
{
IList
<
string
>
proxies
;
if
(
GetAutoProxies
(
destination
,
out
proxies
))
{
if
(
proxies
==
null
)
{
return
null
;
}
string
proxy
=
proxies
[
0
];
int
port
=
80
;
if
(
proxy
.
Contains
(
":"
))
{
var
parts
=
proxy
.
Split
(
new
[]
{
':'
},
2
);
proxy
=
parts
[
0
];
port
=
int
.
Parse
(
parts
[
1
]);
}
// TODO: Apply authorization
var
systemProxy
=
new
ExternalProxy
{
HostName
=
proxy
,
Port
=
port
,
};
return
systemProxy
;
}
if
(
Proxy
?.
IsBypassed
(
destination
)
==
true
)
return
null
;
var
protocolType
=
ProxyInfo
.
ParseProtocolType
(
destination
.
Scheme
);
if
(
protocolType
.
HasValue
)
{
HttpSystemProxyValue
value
=
null
;
if
(
ProxyInfo
?.
Proxies
?.
TryGetValue
(
protocolType
.
Value
,
out
value
)
==
true
)
{
var
systemProxy
=
new
ExternalProxy
{
HostName
=
value
.
HostName
,
Port
=
value
.
Port
,
};
return
systemProxy
;
}
}
return
null
;
}
public
void
LoadFromIE
()
{
var
pi
=
GetProxyInfo
();
ProxyInfo
=
pi
;
AutomaticallyDetectSettings
=
pi
.
AutoDetect
==
true
;
AutomaticConfigurationScript
=
pi
.
AutoConfigUrl
==
null
?
null
:
new
Uri
(
pi
.
AutoConfigUrl
);
BypassLoopback
=
pi
.
BypassLoopback
;
BypassOnLocal
=
pi
.
BypassOnLocal
;
Proxy
=
new
WebProxy
(
new
Uri
(
"http://localhost"
),
BypassOnLocal
,
pi
.
BypassList
);
}
private
ProxyInfo
GetProxyInfo
()
{
var
proxyConfig
=
new
NativeMethods
.
WinHttp
.
WINHTTP_CURRENT_USER_IE_PROXY_CONFIG
();
RuntimeHelpers
.
PrepareConstrainedRegions
();
try
{
ProxyInfo
result
;
if
(
NativeMethods
.
WinHttp
.
WinHttpGetIEProxyConfigForCurrentUser
(
ref
proxyConfig
))
{
result
=
new
ProxyInfo
(
proxyConfig
.
AutoDetect
,
Marshal
.
PtrToStringUni
(
proxyConfig
.
AutoConfigUrl
),
null
,
Marshal
.
PtrToStringUni
(
proxyConfig
.
Proxy
),
Marshal
.
PtrToStringUni
(
proxyConfig
.
ProxyBypass
));
}
else
{
if
(
Marshal
.
GetLastWin32Error
()
==
8
)
throw
new
OutOfMemoryException
();
result
=
new
ProxyInfo
(
true
,
null
,
null
,
null
,
null
);
}
return
result
;
}
finally
{
Marshal
.
FreeHGlobal
(
proxyConfig
.
Proxy
);
Marshal
.
FreeHGlobal
(
proxyConfig
.
ProxyBypass
);
Marshal
.
FreeHGlobal
(
proxyConfig
.
AutoConfigUrl
);
}
}
public
void
Reset
()
{
state
=
AutoWebProxyState
.
Uninitialized
;
autoDetectFailed
=
false
;
}
public
void
Dispose
()
{
Dispose
(
true
);
}
private
void
Dispose
(
bool
disposing
)
{
if
(!
disposing
||
session
==
null
||
session
.
IsInvalid
)
return
;
session
.
Close
();
}
private
int
GetAutoProxies
(
Uri
destination
,
Uri
scriptLocation
,
out
string
proxyListString
)
{
int
num
=
0
;
var
autoProxyOptions
=
new
NativeMethods
.
WinHttp
.
WINHTTP_AUTOPROXY_OPTIONS
();
autoProxyOptions
.
AutoLogonIfChallenged
=
false
;
if
(
scriptLocation
==
null
)
{
autoProxyOptions
.
Flags
=
NativeMethods
.
WinHttp
.
AutoProxyFlags
.
AutoDetect
;
autoProxyOptions
.
AutoConfigUrl
=
null
;
autoProxyOptions
.
AutoDetectFlags
=
NativeMethods
.
WinHttp
.
AutoDetectType
.
Dhcp
|
NativeMethods
.
WinHttp
.
AutoDetectType
.
DnsA
;
}
else
{
autoProxyOptions
.
Flags
=
NativeMethods
.
WinHttp
.
AutoProxyFlags
.
AutoProxyConfigUrl
;
autoProxyOptions
.
AutoConfigUrl
=
scriptLocation
.
ToString
();
autoProxyOptions
.
AutoDetectFlags
=
NativeMethods
.
WinHttp
.
AutoDetectType
.
None
;
}
if
(!
WinHttpGetProxyForUrl
(
destination
.
ToString
(),
ref
autoProxyOptions
,
out
proxyListString
))
{
num
=
GetLastWin32Error
();
if
(
num
==
(
int
)
NativeMethods
.
WinHttp
.
ErrorCodes
.
LoginFailure
&&
Credentials
!=
null
)
{
autoProxyOptions
.
AutoLogonIfChallenged
=
true
;
if
(!
WinHttpGetProxyForUrl
(
destination
.
ToString
(),
ref
autoProxyOptions
,
out
proxyListString
))
num
=
GetLastWin32Error
();
}
}
return
num
;
}
private
bool
WinHttpGetProxyForUrl
(
string
destination
,
ref
NativeMethods
.
WinHttp
.
WINHTTP_AUTOPROXY_OPTIONS
autoProxyOptions
,
out
string
proxyListString
)
{
proxyListString
=
null
;
bool
flag
;
var
proxyInfo
=
new
NativeMethods
.
WinHttp
.
WINHTTP_PROXY_INFO
();
RuntimeHelpers
.
PrepareConstrainedRegions
();
try
{
flag
=
NativeMethods
.
WinHttp
.
WinHttpGetProxyForUrl
(
session
,
destination
,
ref
autoProxyOptions
,
out
proxyInfo
);
if
(
flag
)
proxyListString
=
Marshal
.
PtrToStringUni
(
proxyInfo
.
Proxy
);
}
finally
{
Marshal
.
FreeHGlobal
(
proxyInfo
.
Proxy
);
Marshal
.
FreeHGlobal
(
proxyInfo
.
ProxyBypass
);
}
return
flag
;
}
private
static
int
GetLastWin32Error
()
{
int
lastWin32Error
=
Marshal
.
GetLastWin32Error
();
if
(
lastWin32Error
==
8
)
throw
new
OutOfMemoryException
();
return
lastWin32Error
;
}
private
static
bool
IsRecoverableAutoProxyError
(
NativeMethods
.
WinHttp
.
ErrorCodes
errorCode
)
{
switch
(
errorCode
)
{
case
NativeMethods
.
WinHttp
.
ErrorCodes
.
AutoProxyServiceError
:
case
NativeMethods
.
WinHttp
.
ErrorCodes
.
AudodetectionFailed
:
case
NativeMethods
.
WinHttp
.
ErrorCodes
.
BadAutoProxyScript
:
case
NativeMethods
.
WinHttp
.
ErrorCodes
.
UnableToDownloadScript
:
case
NativeMethods
.
WinHttp
.
ErrorCodes
.
LoginFailure
:
case
NativeMethods
.
WinHttp
.
ErrorCodes
.
OperationCancelled
:
case
NativeMethods
.
WinHttp
.
ErrorCodes
.
Timeout
:
case
NativeMethods
.
WinHttp
.
ErrorCodes
.
UnrecognizedScheme
:
return
true
;
default
:
return
false
;
}
}
private
static
AutoWebProxyState
GetStateFromErrorCode
(
NativeMethods
.
WinHttp
.
ErrorCodes
errorCode
)
{
if
(
errorCode
==
0L
)
return
AutoWebProxyState
.
Completed
;
switch
(
errorCode
)
{
case
NativeMethods
.
WinHttp
.
ErrorCodes
.
UnableToDownloadScript
:
return
AutoWebProxyState
.
DownloadFailure
;
case
NativeMethods
.
WinHttp
.
ErrorCodes
.
AutoProxyServiceError
:
case
NativeMethods
.
WinHttp
.
ErrorCodes
.
InvalidUrl
:
case
NativeMethods
.
WinHttp
.
ErrorCodes
.
BadAutoProxyScript
:
return
AutoWebProxyState
.
Completed
;
case
NativeMethods
.
WinHttp
.
ErrorCodes
.
AudodetectionFailed
:
return
AutoWebProxyState
.
DiscoveryFailure
;
case
NativeMethods
.
WinHttp
.
ErrorCodes
.
UnrecognizedScheme
:
return
AutoWebProxyState
.
UnrecognizedScheme
;
default
:
return
AutoWebProxyState
.
CompilationFailure
;
}
}
private
static
string
RemoveWhitespaces
(
string
value
)
{
var
stringBuilder
=
new
StringBuilder
();
foreach
(
char
c
in
value
)
{
if
(!
char
.
IsWhiteSpace
(
c
))
stringBuilder
.
Append
(
c
);
}
return
stringBuilder
.
ToString
();
}
private
static
bool
IsErrorFatalForAutoDetect
(
NativeMethods
.
WinHttp
.
ErrorCodes
errorCode
)
{
switch
(
errorCode
)
{
case
NativeMethods
.
WinHttp
.
ErrorCodes
.
BadAutoProxyScript
:
case
NativeMethods
.
WinHttp
.
ErrorCodes
.
AutoProxyServiceError
:
case
NativeMethods
.
WinHttp
.
ErrorCodes
.
Success
:
case
NativeMethods
.
WinHttp
.
ErrorCodes
.
InvalidUrl
:
return
false
;
default
:
return
true
;
}
}
private
enum
AutoWebProxyState
{
Uninitialized
,
DiscoveryFailure
,
DownloadFailure
,
CompilationFailure
,
UnrecognizedScheme
,
Completed
,
}
}
}
\ No newline at end of file
Titanium.Web.Proxy/Http/HttpWebClient.cs
View file @
e1543300
...
...
@@ -80,17 +80,14 @@ namespace Titanium.Web.Proxy.Http
var
requestLines
=
new
StringBuilder
();
//prepare the request & headers
if
(
ServerConnection
.
UpStreamHttpProxy
!=
null
&&
ServerConnection
.
IsHttps
==
false
||
ServerConnection
.
UpStreamHttpsProxy
!=
null
&&
ServerConnection
.
IsHttps
)
{
requestLines
.
AppendLine
(
$"
{
Request
.
Method
}
{
Request
.
RequestUri
.
AbsoluteUri
}
HTTP/
{
Request
.
HttpVersion
.
Major
}
.
{
Request
.
HttpVersion
.
Minor
}
"
);
}
else
{
requestLines
.
AppendLine
(
$"
{
Request
.
Method
}
{
Request
.
RequestUri
.
PathAndQuery
}
HTTP/
{
Request
.
HttpVersion
.
Major
}
.
{
Request
.
HttpVersion
.
Minor
}
"
);
}
//Send Authentication to Upstream proxy if needed
if
(
ServerConnection
.
UpStreamHttpProxy
!=
null
&&
ServerConnection
.
IsHttps
==
false
&&
!
string
.
IsNullOrEmpty
(
ServerConnection
.
UpStreamHttpProxy
.
UserName
)
&&
ServerConnection
.
UpStreamHttpProxy
.
Password
!=
null
)
if
(
ServerConnection
.
UpStreamHttpProxy
!=
null
&&
ServerConnection
.
IsHttps
==
false
&&
!
string
.
IsNullOrEmpty
(
ServerConnection
.
UpStreamHttpProxy
.
UserName
)
&&
ServerConnection
.
UpStreamHttpProxy
.
Password
!=
null
)
{
requestLines
.
AppendLine
(
"Proxy-Connection: keep-alive"
);
requestLines
.
AppendLine
(
"Proxy-Authorization"
+
": Basic "
+
Convert
.
ToBase64String
(
Encoding
.
UTF8
.
GetBytes
(
...
...
Titanium.Web.Proxy/Http/Request.cs
View file @
e1543300
...
...
@@ -33,9 +33,11 @@ namespace Titanium.Web.Proxy.Http
public
bool
HasBody
=>
Method
==
"POST"
||
Method
==
"PUT"
||
Method
==
"PATCH"
;
/// <summary>
/// Request Http hostanem
/// Http hostname header value if exists
/// Note: Changing this does NOT change host in RequestUri
/// Users can set new RequestUri separately
/// </summary>
internal
string
Host
public
string
Host
{
get
{
...
...
@@ -57,9 +59,9 @@ namespace Titanium.Web.Proxy.Http
}
/// <summary>
///
Request content encoding
///
Content encoding header value
/// </summary>
internal
string
ContentEncoding
public
string
ContentEncoding
{
get
{
...
...
@@ -231,7 +233,7 @@ namespace Titanium.Web.Proxy.Http
/// <summary>
/// Encoding for this request
/// </summary>
internal
Encoding
Encoding
=>
this
.
GetEncoding
();
public
Encoding
Encoding
=>
this
.
GetEncoding
();
/// <summary>
/// Terminates the underlying Tcp Connection to client after current request
...
...
@@ -261,7 +263,7 @@ namespace Titanium.Web.Proxy.Http
/// <summary>
/// Does this request has an upgrade to websocket header?
/// </summary>
internal
bool
UpgradeToWebSocket
public
bool
UpgradeToWebSocket
{
get
{
...
...
Titanium.Web.Proxy/Http/Response.cs
View file @
e1543300
...
...
@@ -23,12 +23,15 @@ namespace Titanium.Web.Proxy.Http
/// </summary>
public
string
ResponseStatusDescription
{
get
;
set
;
}
internal
Encoding
Encoding
=>
this
.
GetResponseCharacterEncoding
();
/// <summary>
/// Encoding used in response
/// </summary>
public
Encoding
Encoding
=>
this
.
GetResponseCharacterEncoding
();
/// <summary>
/// Content encoding for this response
/// </summary>
internal
string
ContentEncoding
public
string
ContentEncoding
{
get
{
...
...
@@ -41,12 +44,15 @@ namespace Titanium.Web.Proxy.Http
}
}
internal
Version
HttpVersion
{
get
;
set
;
}
/// <summary>
/// Http version
/// </summary>
public
Version
HttpVersion
{
get
;
set
;
}
/// <summary>
/// Keep the connection alive?
/// </summary>
internal
bool
ResponseKeepAlive
public
bool
ResponseKeepAlive
{
get
{
...
...
@@ -89,7 +95,7 @@ namespace Titanium.Web.Proxy.Http
/// <summary>
/// Length of response body
/// </summary>
internal
long
ContentLength
public
long
ContentLength
{
get
{
...
...
@@ -142,7 +148,7 @@ namespace Titanium.Web.Proxy.Http
/// <summary>
/// Response transfer-encoding is chunked?
/// </summary>
internal
bool
IsChunked
public
bool
IsChunked
{
get
{
...
...
@@ -198,14 +204,8 @@ namespace Titanium.Web.Proxy.Http
/// </summary>
public
Dictionary
<
string
,
List
<
HttpHeader
>>
NonUniqueResponseHeaders
{
get
;
set
;
}
/// <summary>
/// Response network stream
/// </summary>
public
Stream
ResponseStream
{
get
;
set
;
}
/// <summary>
/// response body conten
s
t as byte array
/// response body content as byte array
/// </summary>
internal
byte
[]
ResponseBody
{
get
;
set
;
}
...
...
Titanium.Web.Proxy/ProxyServer.cs
View file @
e1543300
...
...
@@ -9,6 +9,7 @@ using System.Threading;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.EventArguments
;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.Helpers.WinHttp
;
using
Titanium.Web.Proxy.Models
;
using
Titanium.Web.Proxy.Network
;
using
Titanium.Web.Proxy.Network.Tcp
;
...
...
@@ -36,6 +37,8 @@ namespace Titanium.Web.Proxy
/// </summary>
private
Action
<
Exception
>
exceptionFunc
;
private
WinHttpWebProxyFinder
systemProxyResolver
;
/// <summary>
/// Backing field for corresponding public property
/// </summary>
...
...
@@ -61,7 +64,6 @@ namespace Titanium.Web.Proxy
/// </summary>
private
SystemProxyManager
systemProxySettingsManager
{
get
;
}
/// <summary>
/// Set firefox to use default system proxy
/// </summary>
...
...
@@ -287,8 +289,10 @@ namespace Titanium.Web.Proxy
ProxyEndPoints
=
new
List
<
ProxyEndPoint
>();
tcpConnectionFactory
=
new
TcpConnectionFactory
();
if
(!
RunTime
.
IsRunningOnMono
)
{
systemProxySettingsManager
=
new
SystemProxyManager
();
}
CertificateManager
=
new
CertificateManager
(
ExceptionFunc
);
if
(
rootCertificateName
!=
null
)
...
...
@@ -348,32 +352,25 @@ namespace Titanium.Web.Proxy
/// <param name="endPoint"></param>
public
void
SetAsSystemHttpProxy
(
ExplicitProxyEndPoint
endPoint
)
{
if
(
RunTime
.
IsRunningOnMono
)
{
throw
new
Exception
(
"Mono Runtime do not support system proxy settings."
);
SetAsSystemProxy
(
endPoint
,
ProxyProtocolType
.
Http
);
}
ValidateEndPointAsSystemProxy
(
endPoint
);
//clear any settings previously added
ProxyEndPoints
.
OfType
<
ExplicitProxyEndPoint
>().
ToList
().
ForEach
(
x
=>
x
.
IsSystemHttpProxy
=
false
);
systemProxySettingsManager
.
SetHttpProxy
(
Equals
(
endPoint
.
IpAddress
,
IPAddress
.
Any
)
|
Equals
(
endPoint
.
IpAddress
,
IPAddress
.
Loopback
)
?
"127.0.0.1"
:
endPoint
.
IpAddress
.
ToString
(),
endPoint
.
Port
);
endPoint
.
IsSystemHttpProxy
=
true
;
firefoxProxySettingsManager
.
UseSystemProxy
();
Console
.
WriteLine
(
"Set endpoint at Ip {0} and port: {1} as System HTTP Proxy"
,
endPoint
.
IpAddress
,
endPoint
.
Port
);
/// <summary>
/// Set the given explicit end point as the default proxy server for current machine
/// </summary>
/// <param name="endPoint"></param>
public
void
SetAsSystemHttpsProxy
(
ExplicitProxyEndPoint
endPoint
)
{
SetAsSystemProxy
(
endPoint
,
ProxyProtocolType
.
Https
);
}
/// <summary>
/// Set the given explicit end point as the default proxy server for current machine
/// </summary>
/// <param name="endPoint"></param>
public
void
SetAsSystemHttpsProxy
(
ExplicitProxyEndPoint
endPoint
)
/// <param name="protocolType"></param>
public
void
SetAsSystemProxy
(
ExplicitProxyEndPoint
endPoint
,
ProxyProtocolType
protocolType
)
{
if
(
RunTime
.
IsRunningOnMono
)
{
...
...
@@ -382,33 +379,73 @@ namespace Titanium.Web.Proxy
ValidateEndPointAsSystemProxy
(
endPoint
);
bool
isHttp
=
(
protocolType
&
ProxyProtocolType
.
Http
)
>
0
;
bool
isHttps
=
(
protocolType
&
ProxyProtocolType
.
Https
)
>
0
;
if
(
isHttps
)
{
if
(!
endPoint
.
EnableSsl
)
{
throw
new
Exception
(
"Endpoint do not support Https connections"
);
}
//clear any settings previously added
ProxyEndPoints
.
OfType
<
ExplicitProxyEndPoint
>()
.
ToList
()
.
ForEach
(
x
=>
x
.
IsSystemHttpsProxy
=
false
);
EnsureRootCertificate
();
//If certificate was trusted by the machine
if
(
CertificateManager
.
CertValidated
)
if
(!
CertificateManager
.
CertValidated
)
{
systemProxySettingsManager
.
SetHttpsProxy
(
protocolType
=
protocolType
&
~
ProxyProtocolType
.
Https
;
isHttps
=
false
;
}
}
//clear any settings previously added
if
(
isHttp
)
{
ProxyEndPoints
.
OfType
<
ExplicitProxyEndPoint
>().
ToList
().
ForEach
(
x
=>
x
.
IsSystemHttpProxy
=
false
);
}
if
(
isHttps
)
{
ProxyEndPoints
.
OfType
<
ExplicitProxyEndPoint
>().
ToList
().
ForEach
(
x
=>
x
.
IsSystemHttpsProxy
=
false
);
}
systemProxySettingsManager
.
SetProxy
(
Equals
(
endPoint
.
IpAddress
,
IPAddress
.
Any
)
|
Equals
(
endPoint
.
IpAddress
,
IPAddress
.
Loopback
)
?
"127.0.0.1"
:
endPoint
.
IpAddress
.
ToString
(),
endPoint
.
Port
);
}
endPoint
.
Port
,
protocolType
);
if
(
isHttp
)
{
endPoint
.
IsSystemHttpsProxy
=
true
;
}
if
(
isHttps
)
{
endPoint
.
IsSystemHttpsProxy
=
true
;
}
firefoxProxySettingsManager
.
UseSystemProxy
();
Console
.
WriteLine
(
"Set endpoint at Ip {0} and port: {1} as System HTTPS Proxy"
,
endPoint
.
IpAddress
,
endPoint
.
Port
);
string
proxyType
=
null
;
switch
(
protocolType
)
{
case
ProxyProtocolType
.
Http
:
proxyType
=
"HTTP"
;
break
;
case
ProxyProtocolType
.
Https
:
proxyType
=
"HTTPS"
;
break
;
case
ProxyProtocolType
.
AllHttp
:
proxyType
=
"HTTP and HTTPS"
;
break
;
}
if
(
protocolType
!=
ProxyProtocolType
.
None
)
{
Console
.
WriteLine
(
"Set endpoint at Ip {0} and port: {1} as System {2} Proxy"
,
endPoint
.
IpAddress
,
endPoint
.
Port
,
proxyType
);
}
}
/// <summary>
...
...
@@ -416,25 +453,28 @@ namespace Titanium.Web.Proxy
/// </summary>
public
void
DisableSystemHttpProxy
()
{
if
(
RunTime
.
IsRunningOnMono
)
{
throw
new
Exception
(
"Mono Runtime do not support system proxy settings."
);
}
systemProxySettingsManager
.
RemoveHttpProxy
();
DisableSystemProxy
(
ProxyProtocolType
.
Http
);
}
/// <summary>
/// Remove any HTTPS proxy setting for current machine
/// </summary>
public
void
DisableSystemHttpsProxy
()
{
DisableSystemProxy
(
ProxyProtocolType
.
Https
);
}
/// <summary>
/// Remove the specified proxy settings for current machine
/// </summary>
public
void
DisableSystemProxy
(
ProxyProtocolType
protocolType
)
{
if
(
RunTime
.
IsRunningOnMono
)
{
throw
new
Exception
(
"Mono Runtime do not support system proxy settings."
);
}
systemProxySettingsManager
.
Remove
HttpsProxy
(
);
systemProxySettingsManager
.
Remove
Proxy
(
protocolType
);
}
/// <summary>
...
...
@@ -460,9 +500,38 @@ namespace Titanium.Web.Proxy
throw
new
Exception
(
"Proxy is already running."
);
}
if
(
ForwardToUpstreamGateway
&&
GetCustomUpStreamHttpProxyFunc
==
null
&&
GetCustomUpStreamHttpsProxyFunc
==
null
)
//clear any system proxy settings which is pointing to our own endpoint
//due to non gracious proxy shutdown before
if
(
systemProxySettingsManager
!=
null
)
{
var
proxyInfo
=
systemProxySettingsManager
.
GetProxyInfoFromRegistry
();
if
(
proxyInfo
.
Proxies
!=
null
)
{
var
protocolToRemove
=
ProxyProtocolType
.
None
;
foreach
(
var
proxy
in
proxyInfo
.
Proxies
.
Values
)
{
if
(
proxy
.
HostName
==
"127.0.0.1"
&&
ProxyEndPoints
.
Any
(
x
=>
x
.
Port
==
proxy
.
Port
))
{
protocolToRemove
|=
proxy
.
ProtocolType
;
}
}
if
(
protocolToRemove
!=
ProxyProtocolType
.
None
)
{
//do not restore to any of listening address when we quit
systemProxySettingsManager
.
RemoveProxy
(
protocolToRemove
,
false
);
}
}
}
if
(
ForwardToUpstreamGateway
&&
GetCustomUpStreamHttpProxyFunc
==
null
&&
GetCustomUpStreamHttpsProxyFunc
==
null
&&
systemProxySettingsManager
!=
null
)
{
// Use WinHttp to handle PAC/WAPD scripts.
systemProxyResolver
=
new
WinHttpWebProxyFinder
();
systemProxyResolver
.
LoadFromIE
();
GetCustomUpStreamHttpProxyFunc
=
GetSystemUpStreamProxy
;
GetCustomUpStreamHttpsProxyFunc
=
GetSystemUpStreamProxy
;
}
...
...
@@ -494,11 +563,14 @@ namespace Titanium.Web.Proxy
throw
new
Exception
(
"Proxy is not running."
);
}
if
(!
RunTime
.
IsRunningOnMono
)
{
var
setAsSystemProxy
=
ProxyEndPoints
.
OfType
<
ExplicitProxyEndPoint
>().
Any
(
x
=>
x
.
IsSystemHttpProxy
||
x
.
IsSystemHttpsProxy
);
if
(
setAsSystemProxy
)
{
systemProxySettingsManager
.
DisableAllProxy
();
systemProxySettingsManager
.
RestoreOriginalSettings
();
}
}
foreach
(
var
endPoint
in
ProxyEndPoints
)
...
...
@@ -565,19 +637,8 @@ namespace Titanium.Web.Proxy
/// <returns><see cref="ExternalProxy"/> instance containing valid proxy configuration from PAC/WAPD scripts if any exists.</returns>
private
Task
<
ExternalProxy
>
GetSystemUpStreamProxy
(
SessionEventArgs
sessionEventArgs
)
{
// Use built-in WebProxy class to handle PAC/WAPD scripts.
var
systemProxyResolver
=
new
WebProxy
();
var
systemProxyUri
=
systemProxyResolver
.
GetProxy
(
sessionEventArgs
.
WebSession
.
Request
.
RequestUri
);
// TODO: Apply authorization
var
systemProxy
=
new
ExternalProxy
{
HostName
=
systemProxyUri
.
Host
,
Port
=
systemProxyUri
.
Port
};
return
Task
.
FromResult
(
systemProxy
);
var
proxy
=
systemProxyResolver
.
GetProxy
(
sessionEventArgs
.
WebSession
.
Request
.
RequestUri
);
return
Task
.
FromResult
(
proxy
);
}
...
...
Titanium.Web.Proxy/RequestHandler.cs
View file @
e1543300
...
...
@@ -6,6 +6,7 @@ using System.Net;
using
System.Net.Security
;
using
System.Net.Sockets
;
using
System.Security.Authentication
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.EventArguments
;
using
Titanium.Web.Proxy.Exceptions
;
...
...
@@ -236,12 +237,12 @@ namespace Titanium.Web.Proxy
/// <param name="clientStream"></param>
/// <param name="clientStreamReader"></param>
/// <param name="clientStreamWriter"></param>
/// <param name="https
HostN
ame"></param>
/// <param name="https
ConnectHostn
ame"></param>
/// <param name="endPoint"></param>
/// <param name="connectHeaders"></param>
/// <returns></returns>
private
async
Task
<
bool
>
HandleHttpSessionRequest
(
TcpClient
client
,
string
httpCmd
,
Stream
clientStream
,
CustomBinaryReader
clientStreamReader
,
StreamWriter
clientStreamWriter
,
string
https
HostN
ame
,
CustomBinaryReader
clientStreamReader
,
StreamWriter
clientStreamWriter
,
string
https
ConnectHostn
ame
,
ProxyEndPoint
endPoint
,
List
<
HttpHeader
>
connectHeaders
)
{
bool
disposed
=
false
;
...
...
@@ -299,9 +300,9 @@ namespace Titanium.Web.Proxy
//Read the request headers in to unique and non-unique header collections
await
HeaderParser
.
ReadHeaders
(
clientStreamReader
,
args
.
WebSession
.
Request
.
NonUniqueRequestHeaders
,
args
.
WebSession
.
Request
.
RequestHeaders
);
var
httpRemoteUri
=
new
Uri
(
https
HostN
ame
==
null
var
httpRemoteUri
=
new
Uri
(
https
ConnectHostn
ame
==
null
?
httpCmdSplit
[
1
]
:
string
.
Concat
(
"https://"
,
args
.
WebSession
.
Request
.
Host
??
https
HostN
ame
,
httpCmdSplit
[
1
]));
:
string
.
Concat
(
"https://"
,
args
.
WebSession
.
Request
.
Host
??
https
ConnectHostn
ame
,
httpCmdSplit
[
1
]));
args
.
WebSession
.
Request
.
RequestUri
=
httpRemoteUri
;
...
...
@@ -311,7 +312,8 @@ namespace Titanium.Web.Proxy
args
.
ProxyClient
.
ClientStreamReader
=
clientStreamReader
;
args
.
ProxyClient
.
ClientStreamWriter
=
clientStreamWriter
;
if
(
httpsHostName
==
null
&&
//proxy authorization check
if
(
httpsConnectHostname
==
null
&&
await
CheckAuthorization
(
clientStreamWriter
,
args
.
WebSession
.
Request
.
RequestHeaders
.
Values
)
==
false
)
{
...
...
@@ -338,6 +340,12 @@ namespace Titanium.Web.Proxy
await
BeforeRequest
.
InvokeParallelAsync
(
this
,
args
);
}
if
(
args
.
WebSession
.
Request
.
CancelRequest
)
{
args
.
Dispose
();
break
;
}
//if upgrading to websocket then relay the requet without reading the contents
if
(
args
.
WebSession
.
Request
.
UpgradeToWebSocket
)
{
...
...
@@ -354,6 +362,14 @@ namespace Titanium.Web.Proxy
{
connection
=
await
GetServerConnection
(
args
);
}
//create a new connection if hostname changes
else
if
(!
connection
.
HostName
.
Equals
(
args
.
WebSession
.
Request
.
RequestUri
.
Host
,
StringComparison
.
OrdinalIgnoreCase
))
{
connection
.
Dispose
();
Interlocked
.
Decrement
(
ref
serverConnectionCount
);
connection
=
await
GetServerConnection
(
args
);
}
//construct the web request that we are going to issue on behalf of the client.
disposed
=
await
HandleHttpSessionRequestInternal
(
connection
,
args
,
false
);
...
...
@@ -365,12 +381,6 @@ namespace Titanium.Web.Proxy
break
;
}
if
(
args
.
WebSession
.
Request
.
CancelRequest
)
{
args
.
Dispose
();
break
;
}
//if connection is closing exit
if
(
args
.
WebSession
.
Response
.
ResponseKeepAlive
==
false
)
{
...
...
@@ -415,12 +425,6 @@ namespace Titanium.Web.Proxy
{
args
.
WebSession
.
Request
.
RequestLocked
=
true
;
//If request was cancelled by user then dispose the client
if
(
args
.
WebSession
.
Request
.
CancelRequest
)
{
return
true
;
}
//if expect continue is enabled then send the headers first
//and see if server would return 100 conitinue
if
(
args
.
WebSession
.
Request
.
ExpectContinue
)
...
...
Titanium.Web.Proxy/ResponseHandler.cs
View file @
e1543300
...
...
@@ -31,11 +31,6 @@ namespace Titanium.Web.Proxy
//read response & headers from server
await
args
.
WebSession
.
ReceiveResponse
();
if
(!
args
.
WebSession
.
Response
.
ResponseBodyRead
)
{
args
.
WebSession
.
Response
.
ResponseStream
=
args
.
WebSession
.
ServerConnection
.
Stream
;
}
//check for windows authentication
if
(
EnableWinAuth
&&
!
RunTime
.
IsRunningOnMono
...
...
Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
View file @
e1543300
...
...
@@ -52,7 +52,7 @@
</Reference>
<Reference
Include=
"System"
/>
<Reference
Include=
"System.Net"
/>
<Reference
Include=
"System.
c
onfiguration"
/>
<Reference
Include=
"System.
C
onfiguration"
/>
<Reference
Include=
"System.Core"
/>
<Reference
Include=
"System.Xml.Linq"
/>
<Reference
Include=
"System.Data.DataSetExtensions"
/>
...
...
@@ -79,8 +79,12 @@
<Compile
Include=
"Extensions\StringExtensions.cs"
/>
<Compile
Include=
"Helpers\BufferPool.cs"
/>
<Compile
Include=
"Helpers\CustomBufferedStream.cs"
/>
<Compile
Include=
"Helpers\ProxyInfo.cs"
/>
<Compile
Include=
"Helpers\WinHttp\NativeMethods.WinHttp.cs"
/>
<Compile
Include=
"Helpers\Network.cs"
/>
<Compile
Include=
"Helpers\RunTime.cs"
/>
<Compile
Include=
"Helpers\WinHttp\WinHttpHandle.cs"
/>
<Compile
Include=
"Helpers\WinHttp\WinHttpWebProxyFinder.cs"
/>
<Compile
Include=
"Http\HeaderParser.cs"
/>
<Compile
Include=
"Http\Responses\GenericResponse.cs"
/>
<Compile
Include=
"Network\CachedCertificate.cs"
/>
...
...
@@ -129,7 +133,7 @@
<Compile
Include=
"WinAuthHandler.cs"
/>
</ItemGroup>
<ItemGroup>
<COMReference
Include=
"CERTENROLLLib"
>
<COMReference
Include=
"CERTENROLLLib"
Condition=
"'$(OS)' != 'Unix'"
>
<Guid>
{728AB348-217D-11DA-B2A4-000E7BBB2B09}
</Guid>
<VersionMajor>
1
</VersionMajor>
<VersionMinor>
0
</VersionMinor>
...
...
Titanium.Web.Proxy/Titanium.Web.Proxy.nuspec
View file @
e1543300
...
...
@@ -6,8 +6,8 @@
<title>
Titanium web proxy
</title>
<authors>
Titanium
</authors>
<owners>
Titanium
</owners>
<licenseUrl>
https://github.com/
titanium007/Titanium/blob/master
/LICENSE
</licenseUrl>
<projectUrl>
https://github.com/
titanium007/Titanium/
</projectUrl>
<licenseUrl>
https://github.com/
justcoding121/Titanium-Web-Proxy/blob/develop
/LICENSE
</licenseUrl>
<projectUrl>
https://github.com/
justcoding121/Titanium-Web-Proxy
</projectUrl>
<requireLicenseAcceptance>
false
</requireLicenseAcceptance>
<description>
Titanium is a light weight web proxy.
</description>
<releaseNotes></releaseNotes>
...
...
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