//
// Internal stuff
//
// Returns false if OriginalString value
// (1) is not correctly escaped as per URI spec excluding intl UNC name case
// (2) or is an absolute Uri that represents implicit file Uri "c:\dir\file"
// (3) or is an absolute Uri that misses a slash before path "file://c:/dir/file"
// (4) or contains unescaped backslashes even if they will be treated
// as forward slashes like http:\\host/path\file or file:\\\c:\path
//
internal unsafe bool InternalIsWellFormedOriginalString()
{
if (UserDrivenParsing)
{
throw new InvalidOperationException(SR.GetString(SR.net_uri_UserDrivenParsing, this.GetType().FullName));
fixed(char *str = m_String)
{
ushort idx = 0;
//
// For a relative Uri we only care about escaping and backslashes
//
if (!IsAbsoluteUri)
{
// my:scheme/path?query is not well formed because the colon is ambiguous
if (!UriParser.ShouldUseLegacyV2Quirks && CheckForColonInFirstPathSegment(m_String))
{
return(false);
}
return((CheckCanonical(str, ref idx, (ushort)m_String.Length, c_EOL)
& (Check.BackslashInPath | Check.EscapedCanonical)) == Check.EscapedCanonical);
}
//
// (2) or is an absolute Uri that represents implicit file Uri "c:\dir\file"
//
if (IsImplicitFile)
{
return(false);
}
//This will get all the offsets, a Host name will be checked separatelly below
EnsureParseRemaining();
Flags nonCanonical = (m_Flags & (Flags.E_CannotDisplayCanonical | Flags.IriCanonical));
// User, Path, Query or Fragment may have some non escaped characters
if (((nonCanonical & Flags.E_CannotDisplayCanonical & (Flags.E_UserNotCanonical | Flags.E_PathNotCanonical |
Flags.E_QueryNotCanonical | Flags.E_FragmentNotCanonical)) != Flags.Zero) &&
(!m_iriParsing || (m_iriParsing &&
(((nonCanonical & Flags.E_UserNotCanonical) == 0) || ((nonCanonical & Flags.UserIriCanonical) == 0)) &&
(((nonCanonical & Flags.E_PathNotCanonical) == 0) || ((nonCanonical & Flags.PathIriCanonical) == 0)) &&
(((nonCanonical & Flags.E_QueryNotCanonical) == 0) || ((nonCanonical & Flags.QueryIriCanonical) == 0)) &&
(((nonCanonical & Flags.E_FragmentNotCanonical) == 0) || ((nonCanonical & Flags.FragmentIriCanonical) == 0)))))
{
return(false);
}
// checking on scheme:\\ or file:////
if (InFact(Flags.AuthorityFound))
{
idx = (ushort)(m_Info.Offset.Scheme + m_Syntax.SchemeName.Length + 2);
if (idx >= m_Info.Offset.User || m_String[idx - 1] == '\\' || m_String[idx] == '\\')
{
return(false);
}
#if !PLATFORM_UNIX
if (InFact(Flags.UncPath | Flags.DosPath))
{
while (++idx < m_Info.Offset.User && (m_String[idx] == '/' || m_String[idx] == '\\'))
{
return(false);
}
}
#endif // !PLATFORM_UNIX
}
// (3) or is an absolute Uri that misses a slash before path "file://c:/dir/file"
// Note that for this check to be more general we assert that if Path is non empty and if it requires a first slash
// (which looks absent) then the method has to fail.
// Today it's only possible for a Dos like path, i.e. file://c:/bla would fail below check.
if (InFact(Flags.FirstSlashAbsent) && m_Info.Offset.Query > m_Info.Offset.Path)
{
return(false);
}
// (4) or contains unescaped backslashes even if they will be treated
// as forward slashes like http:\\host/path\file or file:\\\c:\path
// Note we do not check for Flags.ShouldBeCompressed i.e. allow // /./ and alike as valid
if (InFact(Flags.BackslashInPath))
{
return(false);
}
// Capturing a rare case like file:///c|/dir
if (IsDosPath && m_String[m_Info.Offset.Path + SecuredPathIndex - 1] == '|')
{
return(false);
}
//
// May need some real CPU processing to anwser the request
//
//
// Check escaping for authority
//
// IPv6 hosts cannot be properly validated by CheckCannonical
if ((m_Flags & Flags.CanonicalDnsHost) == 0 && HostType != Flags.IPv6HostType)
{
idx = m_Info.Offset.User;
Check result = CheckCanonical(str, ref idx, (ushort)m_Info.Offset.Path, '/');
if (((result & (Check.ReservedFound | Check.BackslashInPath | Check.EscapedCanonical))
!= Check.EscapedCanonical) &&
(!m_iriParsing || (m_iriParsing &&
((result & (Check.DisplayCanonical | Check.FoundNonAscii | Check.NotIriCanonical))
!= (Check.DisplayCanonical | Check.FoundNonAscii)))))
{
return(false);
}
}
// Want to ensure there are slashes after the scheme
if ((m_Flags & (Flags.SchemeNotCanonical | Flags.AuthorityFound))
== (Flags.SchemeNotCanonical | Flags.AuthorityFound))
{
idx = (ushort)m_Syntax.SchemeName.Length;
while (str[idx++] != ':')
{
;
}
if (idx + 1 >= m_String.Length || str[idx] != '/' || str[idx + 1] != '/')
{
return(false);
}
}
}
//
// May be scheme, host, port or path need some canonicalization but still the uri string is found to be a
// "well formed" one
//
return(true);
}