@@ -186,6 +186,29 @@ public static extern uint GetLongPathName(
186186 uint cchBuffer
187187 ) ;
188188
189+ public const uint INTERNET_MAX_PATH_LENGTH = 2048 ;
190+ public const uint INTERNET_MAX_SCHEME_LENGTH = 32 ;
191+ static readonly uint INTERNET_MAX_URL_LENGTH = INTERNET_MAX_SCHEME_LENGTH + ( uint ) "://" . Length + INTERNET_MAX_PATH_LENGTH ;
192+
193+ [ Flags ]
194+ public enum URL_APPLYFlags : uint {
195+ URL_APPLY_DEFAULT = 0x00000001 ,
196+ URL_APPLY_GUESSSCHEME = 0x00000002 ,
197+ URL_APPLY_GUESSFILE = 0x00000004 ,
198+ URL_APPLY_FORCEAPPLY = 0x00000008
199+ }
200+
201+ [ DllImport ( "SHLWAPI.DLL" , CharSet = CharSet . Auto , CallingConvention = CallingConvention . Winapi ) ]
202+ public static extern int UrlApplyScheme (
203+ [ MarshalAs ( UnmanagedType . LPTStr ) ]
204+ string pszIn ,
205+
206+ [ MarshalAs ( UnmanagedType . LPTStr ) ]
207+ StringBuilder pszOut ,
208+
209+ ref uint pcchOut ,
210+ URL_APPLYFlags dwFlags ) ;
211+
189212 public enum OS : uint {
190213 OS_WINDOWS = 0 ,
191214 OS_NT = 1 ,
@@ -1958,6 +1981,55 @@ public string this[string shortPath] {
19581981 public static PathNamesLong Long { get ; } = new PathNamesLong ( ) ;
19591982 }
19601983
1984+ private const string URI_SCHEME_HTTP = "http" ;
1985+ private const string URI_SCHEME_HTTPS = "https" ;
1986+ private const string URI_SCHEME_FTP = "ftp" ;
1987+
1988+ public static string ValidateURL ( string url ) {
1989+ // first try a guessed scheme
1990+ // (for example, guess HTTP for www subdomain, FTP for ftp subdomain...)
1991+ StringBuilder validatedURL = new StringBuilder ( ( int ) INTERNET_MAX_URL_LENGTH ) ;
1992+ uint validatedURLCapacity = ( uint ) validatedURL . Capacity ;
1993+
1994+ int err = UrlApplyScheme ( url , validatedURL , ref validatedURLCapacity , URL_APPLYFlags . URL_APPLY_GUESSSCHEME ) ;
1995+
1996+ if ( err == S_OK
1997+ && validatedURLCapacity < validatedURL . Capacity ) {
1998+ url = validatedURL . ToString ( ) ;
1999+ } else {
2000+ // second try the default scheme
2001+ // we only do this to see if it returns S_FALSE
2002+ // if so, we know there is already a scheme and don't add our own
2003+ // we do not use the validated URL given by UrlApplyScheme here
2004+ validatedURL . Clear ( ) ;
2005+ validatedURLCapacity = ( uint ) validatedURL . Capacity ;
2006+
2007+ err = UrlApplyScheme ( url , validatedURL , ref validatedURLCapacity , URL_APPLYFlags . URL_APPLY_DEFAULT ) ;
2008+
2009+ // workaround: we always want to use HTTP, regardless of the default
2010+ // (in case the default is HTTPS)
2011+ if ( err != S_FALSE ) {
2012+ // skip leading slashes for protocol-less URLs
2013+ if ( url . StartsWith ( "//" , StringComparison . Ordinal ) ) {
2014+ url = url . Substring ( 2 ) ;
2015+ }
2016+
2017+ url = URI_SCHEME_HTTP + "://" + url ;
2018+ }
2019+ }
2020+ return url ;
2021+ }
2022+
2023+ public static bool TestInternetURI ( Uri uri ) {
2024+ if ( uri . IsFile ) {
2025+ return false ;
2026+ }
2027+
2028+ // the URI Scheme is always lowercase
2029+ string scheme = uri . Scheme ;
2030+ return scheme == URI_SCHEME_HTTP || scheme == URI_SCHEME_HTTPS || scheme == URI_SCHEME_FTP ;
2031+ }
2032+
19612033 public static string GetWindowsVersionName ( bool edition , bool servicePack , bool architecture ) {
19622034 OperatingSystem operatingSystem = Environment . OSVersion ;
19632035 string versionName = "Windows " ;
@@ -2573,50 +2645,6 @@ public static Process StartProcessCreateBreakawayFromJob(ProcessStartInfo proces
25732645 }
25742646 }
25752647
2576- private static int GetURLProtocolLength ( string url ) {
2577- Uri uri ;
2578-
2579- try {
2580- uri = new Uri ( url ) ;
2581- } catch {
2582- return 0 ;
2583- }
2584-
2585- if ( String . IsNullOrEmpty ( uri . Scheme ) ) {
2586- return 0 ;
2587- }
2588- return ( uri . Scheme + "://" ) . Length ;
2589- }
2590-
2591- public static bool HasURLProtocol ( string url ) {
2592- return GetURLProtocolLength ( url ) > 0 ;
2593- }
2594-
2595- public static string AddURLProtocol ( string url ) {
2596- if ( GetURLProtocolLength ( url ) == 0 ) {
2597- return "http://" + url ;
2598- }
2599- return url ;
2600- }
2601-
2602- public static string RemoveURLProtocol ( string url ) {
2603- return url . Substring ( GetURLProtocolLength ( url ) ) ;
2604- }
2605-
2606- public static bool TestInternetURI ( Uri uri ) {
2607- if ( uri . IsFile ) {
2608- return false ;
2609- }
2610-
2611- const string SCHEME_HTTP = "http" ;
2612- const string SCHEME_HTTPS = "https" ;
2613- const string SCHEME_FTP = "ftp" ;
2614-
2615- // the URI Scheme is always lowercase
2616- string scheme = uri . Scheme ;
2617- return scheme == SCHEME_HTTP || scheme == SCHEME_HTTPS || scheme == SCHEME_FTP ;
2618- }
2619-
26202648 public static BINARY_TYPE GetLibraryBinaryType ( string libFileName ) {
26212649 IntPtr moduleHandle = IntPtr . Zero ;
26222650
0 commit comments