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
18ff30f2
Commit
18ff30f2
authored
Jun 16, 2017
by
Honfika
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
#264 GetSystemUpStreamProxy
parent
0a2199b9
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
626 additions
and
89 deletions
+626
-89
ProxyTestController.cs
.../Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
+1
-0
ProxyInfo.cs
Titanium.Web.Proxy/Helpers/ProxyInfo.cs
+116
-0
SystemProxy.cs
Titanium.Web.Proxy/Helpers/SystemProxy.cs
+42
-77
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
+267
-0
ProxyServer.cs
Titanium.Web.Proxy/ProxyServer.cs
+46
-12
Titanium.Web.Proxy.csproj
Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
+4
-0
No files found.
Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
View file @
18ff30f2
...
@@ -31,6 +31,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
...
@@ -31,6 +31,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
proxyServer
.
ExceptionFunc
=
exception
=>
Console
.
WriteLine
(
exception
.
Message
);
proxyServer
.
ExceptionFunc
=
exception
=>
Console
.
WriteLine
(
exception
.
Message
);
proxyServer
.
TrustRootCertificate
=
true
;
proxyServer
.
TrustRootCertificate
=
true
;
proxyServer
.
ForwardToUpstreamGateway
=
true
;
//optionally set the Certificate Engine
//optionally set the Certificate Engine
//Under Mono only BouncyCastle will be supported
//Under Mono only BouncyCastle will be supported
...
...
Titanium.Web.Proxy/Helpers/ProxyInfo.cs
0 → 100644
View file @
18ff30f2
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
Dictionary
<
ProxyProtocolType
,
HttpSystemProxyValue
>
Proxies
{
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
);
}
}
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 @
18ff30f2
...
@@ -54,7 +54,9 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -54,7 +54,9 @@ namespace Titanium.Web.Proxy.Helpers
internal
class
HttpSystemProxyValue
internal
class
HttpSystemProxyValue
{
{
internal
string
HostName
{
get
;
set
;
}
internal
string
HostName
{
get
;
set
;
}
internal
int
Port
{
get
;
set
;
}
internal
int
Port
{
get
;
set
;
}
internal
ProxyProtocolType
ProtocolType
{
get
;
set
;
}
internal
ProxyProtocolType
ProtocolType
{
get
;
set
;
}
public
override
string
ToString
()
public
override
string
ToString
()
...
@@ -85,14 +87,12 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -85,14 +87,12 @@ namespace Titanium.Web.Proxy.Helpers
private
const
string
regAutoConfigUrl
=
"AutoConfigURL"
;
private
const
string
regAutoConfigUrl
=
"AutoConfigURL"
;
private
const
string
regProxyEnable
=
"ProxyEnable"
;
private
const
string
regProxyEnable
=
"ProxyEnable"
;
private
const
string
regProxyServer
=
"ProxyServer"
;
private
const
string
regProxyServer
=
"ProxyServer"
;
private
const
string
regProxyOverride
=
"ProxyOverride"
;
internal
const
int
InternetOptionSettingsChanged
=
39
;
internal
const
int
InternetOptionSettingsChanged
=
39
;
internal
const
int
InternetOptionRefresh
=
37
;
internal
const
int
InternetOptionRefresh
=
37
;
private
bool
originalValuesLoaded
;
private
ProxyInfo
originalValues
;
private
string
originalAutoConfigUrl
;
private
int
?
originalProxyEnable
;
private
string
originalProxyServer
;
public
SystemProxyManager
()
public
SystemProxyManager
()
{
{
...
@@ -131,7 +131,7 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -131,7 +131,7 @@ namespace Titanium.Web.Proxy.Helpers
PrepareRegistry
(
reg
);
PrepareRegistry
(
reg
);
var
exisitingContent
=
reg
.
GetValue
(
regProxyServer
)
as
string
;
var
exisitingContent
=
reg
.
GetValue
(
regProxyServer
)
as
string
;
var
existingSystemProxyValues
=
GetSystemProxyValues
(
exisitingContent
);
var
existingSystemProxyValues
=
ProxyInfo
.
GetSystemProxyValues
(
exisitingContent
);
existingSystemProxyValues
.
RemoveAll
(
x
=>
(
protocolType
&
x
.
ProtocolType
)
!=
0
);
existingSystemProxyValues
.
RemoveAll
(
x
=>
(
protocolType
&
x
.
ProtocolType
)
!=
0
);
if
((
protocolType
&
ProxyProtocolType
.
Http
)
!=
0
)
if
((
protocolType
&
ProxyProtocolType
.
Http
)
!=
0
)
{
{
...
@@ -175,7 +175,7 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -175,7 +175,7 @@ namespace Titanium.Web.Proxy.Helpers
{
{
var
exisitingContent
=
reg
.
GetValue
(
regProxyServer
)
as
string
;
var
exisitingContent
=
reg
.
GetValue
(
regProxyServer
)
as
string
;
var
existingSystemProxyValues
=
GetSystemProxyValues
(
exisitingContent
);
var
existingSystemProxyValues
=
ProxyInfo
.
GetSystemProxyValues
(
exisitingContent
);
existingSystemProxyValues
.
RemoveAll
(
x
=>
(
protocolType
&
x
.
ProtocolType
)
!=
0
);
existingSystemProxyValues
.
RemoveAll
(
x
=>
(
protocolType
&
x
.
ProtocolType
)
!=
0
);
if
(
existingSystemProxyValues
.
Count
!=
0
)
if
(
existingSystemProxyValues
.
Count
!=
0
)
...
@@ -214,7 +214,7 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -214,7 +214,7 @@ namespace Titanium.Web.Proxy.Helpers
internal
void
RestoreOriginalSettings
()
internal
void
RestoreOriginalSettings
()
{
{
if
(
!
originalValuesLoaded
)
if
(
originalValues
==
null
)
{
{
return
;
return
;
}
}
...
@@ -223,110 +223,75 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -223,110 +223,75 @@ namespace Titanium.Web.Proxy.Helpers
if
(
reg
!=
null
)
if
(
reg
!=
null
)
{
{
if
(
originalAutoConfigUrl
!=
null
)
var
ov
=
originalValues
;
if
(
ov
.
AutoConfigUrl
!=
null
)
{
{
reg
.
SetValue
(
regAutoConfigUrl
,
o
riginal
AutoConfigUrl
);
reg
.
SetValue
(
regAutoConfigUrl
,
o
v
.
AutoConfigUrl
);
}
}
else
else
{
{
reg
.
DeleteValue
(
regAutoConfigUrl
,
false
);
reg
.
DeleteValue
(
regAutoConfigUrl
,
false
);
}
}
if
(
o
riginal
ProxyEnable
.
HasValue
)
if
(
o
v
.
ProxyEnable
.
HasValue
)
{
{
reg
.
SetValue
(
regProxyEnable
,
o
riginal
ProxyEnable
.
Value
);
reg
.
SetValue
(
regProxyEnable
,
o
v
.
ProxyEnable
.
Value
);
}
}
else
else
{
{
reg
.
DeleteValue
(
regProxyEnable
,
false
);
reg
.
DeleteValue
(
regProxyEnable
,
false
);
}
}
if
(
o
riginal
ProxyServer
!=
null
)
if
(
o
v
.
ProxyServer
!=
null
)
{
{
reg
.
SetValue
(
regProxyServer
,
o
riginal
ProxyServer
);
reg
.
SetValue
(
regProxyServer
,
o
v
.
ProxyServer
);
}
}
else
else
{
{
reg
.
DeleteValue
(
regProxyServer
,
false
);
reg
.
DeleteValue
(
regProxyServer
,
false
);
}
}
originalValuesLoaded
=
false
;
if
(
ov
.
ProxyOverride
!=
null
)
{
reg
.
SetValue
(
regProxyOverride
,
ov
.
ProxyOverride
);
}
else
{
reg
.
DeleteValue
(
regProxyOverride
,
false
);
}
originalValues
=
null
;
Refresh
();
Refresh
();
}
}
}
}
private
void
SaveOriginalProxyConfiguration
(
RegistryKey
reg
)
internal
ProxyInfo
GetProxyInfoFromRegistry
(
)
{
{
originalAutoConfigUrl
=
reg
.
GetValue
(
regAutoConfigUrl
)
as
string
;
var
reg
=
Registry
.
CurrentUser
.
OpenSubKey
(
regKeyInternetSettings
,
true
);
originalProxyServer
=
reg
.
GetValue
(
regProxyServer
)
as
string
;
originalProxyEnable
=
reg
.
GetValue
(
regProxyEnable
)
as
int
?;
originalValuesLoaded
=
true
;
}
/// <summary>
/// Get the current system proxy setting values
/// </summary>
/// <param name="prevServerValue"></param>
/// <returns></returns>
private
List
<
HttpSystemProxyValue
>
GetSystemProxyValues
(
string
prevServerValue
)
{
var
result
=
new
List
<
HttpSystemProxyValue
>();
if
(
string
.
IsNullOrWhiteSpace
(
prevServerValue
))
return
result
;
var
proxyValues
=
prevServerValue
.
Split
(
';'
);
if
(
proxyValues
.
Length
>
0
)
if
(
reg
!=
null
)
{
result
.
AddRange
(
proxyValues
.
Select
(
ParseProxyValue
).
Where
(
parsedValue
=>
parsedValue
!=
null
));
}
else
{
{
var
parsedValue
=
ParseProxyValue
(
prevServerValue
);
return
GetProxyInfoFromRegistry
(
reg
);
if
(
parsedValue
!=
null
)
result
.
Add
(
parsedValue
);
}
}
return
result
;
return
null
;
}
}
/// <summary>
private
ProxyInfo
GetProxyInfoFromRegistry
(
RegistryKey
reg
)
/// Parses the system proxy setting string
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
private
HttpSystemProxyValue
ParseProxyValue
(
string
value
)
{
{
var
tmp
=
Regex
.
Replace
(
value
,
@"\s+"
,
" "
).
Trim
();
var
pi
=
new
ProxyInfo
(
null
,
int
equalsIndex
=
tmp
.
IndexOf
(
"="
,
StringComparison
.
InvariantCulture
);
reg
.
GetValue
(
regAutoConfigUrl
)
as
string
,
if
(
equalsIndex
>=
0
)
reg
.
GetValue
(
regProxyEnable
)
as
int
?,
{
reg
.
GetValue
(
regProxyServer
)
as
string
,
string
protocolTypeStr
=
tmp
.
Substring
(
0
,
equalsIndex
);
reg
.
GetValue
(
regProxyOverride
)
as
string
);
ProxyProtocolType
?
protocolType
=
null
;
if
(
protocolTypeStr
.
Equals
(
"http"
,
StringComparison
.
InvariantCultureIgnoreCase
))
return
pi
;
{
}
protocolType
=
ProxyProtocolType
.
Http
;
}
else
if
(
protocolTypeStr
.
Equals
(
"https"
,
StringComparison
.
InvariantCultureIgnoreCase
))
{
protocolType
=
ProxyProtocolType
.
Https
;
}
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
;
private
void
SaveOriginalProxyConfiguration
(
RegistryKey
reg
)
{
originalValues
=
GetProxyInfoFromRegistry
(
reg
);
}
}
/// <summary>
/// <summary>
...
...
Titanium.Web.Proxy/Helpers/WinHttp/NativeMethods.WinHttp.cs
0 → 100644
View file @
18ff30f2
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 @
18ff30f2
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 @
18ff30f2
using
System
;
using
System.Collections.Generic
;
using
System.Net
;
using
System.Runtime.CompilerServices
;
using
System.Runtime.InteropServices
;
using
System.Security.Policy
;
using
System.Text
;
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
Uri
AutomaticConfigurationScript
{
get
;
internal
set
;
}
public
bool
AutomaticallyDetectSettings
{
get
;
internal
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
GetProxies
(
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
)
GetProxies
(
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
)
GetProxies
(
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
void
LoadFromIE
()
{
var
pi
=
GetProxyInfo
();
ProxyInfo
=
pi
;
AutomaticallyDetectSettings
=
pi
.
AutoDetect
==
true
;
AutomaticConfigurationScript
=
pi
.
AutoConfigUrl
==
null
?
null
:
new
Uri
(
pi
.
AutoConfigUrl
);
}
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
GetProxies
(
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/ProxyServer.cs
View file @
18ff30f2
...
@@ -9,6 +9,7 @@ using System.Threading;
...
@@ -9,6 +9,7 @@ using System.Threading;
using
System.Threading.Tasks
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.EventArguments
;
using
Titanium.Web.Proxy.EventArguments
;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.Helpers.WinHttp
;
using
Titanium.Web.Proxy.Models
;
using
Titanium.Web.Proxy.Models
;
using
Titanium.Web.Proxy.Network
;
using
Titanium.Web.Proxy.Network
;
using
Titanium.Web.Proxy.Network.Tcp
;
using
Titanium.Web.Proxy.Network.Tcp
;
...
@@ -36,6 +37,8 @@ namespace Titanium.Web.Proxy
...
@@ -36,6 +37,8 @@ namespace Titanium.Web.Proxy
/// </summary>
/// </summary>
private
Action
<
Exception
>
exceptionFunc
;
private
Action
<
Exception
>
exceptionFunc
;
private
WinHttpWebProxyFinder
systemProxyResolver
;
/// <summary>
/// <summary>
/// Backing field for corresponding public property
/// Backing field for corresponding public property
/// </summary>
/// </summary>
...
@@ -61,7 +64,6 @@ namespace Titanium.Web.Proxy
...
@@ -61,7 +64,6 @@ namespace Titanium.Web.Proxy
/// </summary>
/// </summary>
private
SystemProxyManager
systemProxySettingsManager
{
get
;
}
private
SystemProxyManager
systemProxySettingsManager
{
get
;
}
/// <summary>
/// <summary>
/// Set firefox to use default system proxy
/// Set firefox to use default system proxy
/// </summary>
/// </summary>
...
@@ -498,9 +500,14 @@ namespace Titanium.Web.Proxy
...
@@ -498,9 +500,14 @@ namespace Titanium.Web.Proxy
throw
new
Exception
(
"Proxy is already running."
);
throw
new
Exception
(
"Proxy is already running."
);
}
}
if
(
ForwardToUpstreamGateway
&&
GetCustomUpStreamHttpProxyFunc
==
null
if
(
ForwardToUpstreamGateway
&&
GetCustomUpStreamHttpsProxyFunc
==
null
)
&&
GetCustomUpStreamHttpProxyFunc
==
null
&&
GetCustomUpStreamHttpsProxyFunc
==
null
&&
systemProxySettingsManager
!=
null
)
{
{
// Use WinHttp to handle PAC/WAPD scripts.
systemProxyResolver
=
new
WinHttpWebProxyFinder
();
systemProxyResolver
.
LoadFromIE
();
GetCustomUpStreamHttpProxyFunc
=
GetSystemUpStreamProxy
;
GetCustomUpStreamHttpProxyFunc
=
GetSystemUpStreamProxy
;
GetCustomUpStreamHttpsProxyFunc
=
GetSystemUpStreamProxy
;
GetCustomUpStreamHttpsProxyFunc
=
GetSystemUpStreamProxy
;
}
}
...
@@ -606,19 +613,46 @@ namespace Titanium.Web.Proxy
...
@@ -606,19 +613,46 @@ namespace Titanium.Web.Proxy
/// <returns><see cref="ExternalProxy"/> instance containing valid proxy configuration from PAC/WAPD scripts if any exists.</returns>
/// <returns><see cref="ExternalProxy"/> instance containing valid proxy configuration from PAC/WAPD scripts if any exists.</returns>
private
Task
<
ExternalProxy
>
GetSystemUpStreamProxy
(
SessionEventArgs
sessionEventArgs
)
private
Task
<
ExternalProxy
>
GetSystemUpStreamProxy
(
SessionEventArgs
sessionEventArgs
)
{
{
// Use built-in WebProxy class to handle PAC/WAPD scripts.
var
uri
=
sessionEventArgs
.
WebSession
.
Request
.
RequestUri
;
var
systemProxyResolver
=
WebRequest
.
GetSystemWebProxy
();
IList
<
string
>
proxies
;
if
(
systemProxyResolver
.
GetProxies
(
uri
,
out
proxies
)
&&
proxies
!=
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
,
};
var
systemProxyUri
=
systemProxyResolver
.
GetProxy
(
sessionEventArgs
.
WebSession
.
Request
.
RequestUri
);
return
Task
.
FromResult
(
systemProxy
);
}
// TODO: Apply authorization
var
protocolType
=
ProxyInfo
.
ParseProtocolType
(
uri
.
Scheme
);
var
systemProxy
=
new
ExternalProxy
if
(
protocolType
.
HasValue
)
{
{
HostName
=
systemProxyUri
.
Host
,
HttpSystemProxyValue
value
=
null
;
Port
=
systemProxyUri
.
Port
if
(
systemProxyResolver
.
ProxyInfo
?.
Proxies
?.
TryGetValue
(
protocolType
.
Value
,
out
value
)
==
true
)
};
{
var
systemProxy
=
new
ExternalProxy
{
HostName
=
value
.
HostName
,
Port
=
value
.
Port
,
};
return
Task
.
FromResult
(
systemProxy
);
}
}
return
Task
.
FromResult
(
systemProxy
);
return
Task
.
FromResult
(
(
ExternalProxy
)
null
);
}
}
...
...
Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
View file @
18ff30f2
...
@@ -79,8 +79,12 @@
...
@@ -79,8 +79,12 @@
<Compile
Include=
"Extensions\StringExtensions.cs"
/>
<Compile
Include=
"Extensions\StringExtensions.cs"
/>
<Compile
Include=
"Helpers\BufferPool.cs"
/>
<Compile
Include=
"Helpers\BufferPool.cs"
/>
<Compile
Include=
"Helpers\CustomBufferedStream.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\Network.cs"
/>
<Compile
Include=
"Helpers\RunTime.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\HeaderParser.cs"
/>
<Compile
Include=
"Http\Responses\GenericResponse.cs"
/>
<Compile
Include=
"Http\Responses\GenericResponse.cs"
/>
<Compile
Include=
"Network\CachedCertificate.cs"
/>
<Compile
Include=
"Network\CachedCertificate.cs"
/>
...
...
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