ln.type/URI.cs

247 lines
7.2 KiB
C#

// /**
// * File: URI.cs
// * Author: haraldwolff
// *
// * This file and it's content is copyrighted by the Author and / or copyright holder.
// * Any use wihtout proper permission is illegal and may lead to legal actions.
// *
// *
// **/
using System;
using System.Text;
namespace ln.type
{
/**
* Quick and Dirty RFC3986 URI
*
**/
public class URI
{
public String Scheme { get; private set; } = String.Empty;
public String Authority { get; private set; } = String.Empty;
public String[] UserInfo { get; private set; } = new String[0];
public String Host { get; private set; } = String.Empty;
public String Port { get; private set; } = String.Empty;
public String Path { get; private set; } = String.Empty;
public String Query { get; private set; } = String.Empty;
public String Fragment { get; private set; } = String.Empty;
private URI()
{
}
public URI(String uri)
{
Parse(uri);
ParseAuthority();
}
public URI(String scheme, String authority, string path)
{
Parse(String.Format("{0}://{1}{2}", scheme, authority, path));
ParseAuthority();
}
public URI(String scheme,String authority,string path,string query,string fragment)
{
Scheme = scheme;
Authority = authority;
Path = path;
Query = query;
Fragment = fragment;
ParseAuthority();
}
public URI(URI uri, string path)
{
Parse(String.Format("{0}://{1}{2}", uri.Scheme, uri.Authority, path));
ParseAuthority();
}
public URI Follow(String path)
{
if (path.StartsWith("/",StringComparison.InvariantCulture))
{
return new URI(Scheme, Authority, path);
} else if (Path.EndsWith("/",StringComparison.InvariantCulture) || path.StartsWith("?",StringComparison.InvariantCulture) || path.StartsWith("#", StringComparison.InvariantCulture))
{
return new URI(Scheme, Authority, String.Format("{0}{1}", Path, path));
}
else
{
int indSlash = Path.LastIndexOf('/');
return new URI(Scheme, Authority, String.Format("{0}/{1}",Path.Substring(0,indSlash),path));
}
}
private void Parse(String uri)
{
char[] chUri = uri.ToCharArray();
int n = 0;
int m = 0;
// Scheme
while ((chUri[n] != ':') && ((++n) < chUri.Length)) { };
if (n < 2)
throw new FormatException(String.Format("URL malformed: {0}",uri));
Scheme = new string(chUri, 0, n);
n++;
if (n < chUri.Length)
{
if ((chUri.Length - n > 1) && (chUri[n] == '/') && (chUri[n+1] == '/'))
{
// Authority
n += 2;
m = n;
while (
(m < chUri.Length) &&
(chUri[m] != '/') &&
(chUri[m] != '?') &&
(chUri[m] != '#')
) { m++; }
Authority = new string(chUri, n, (m - n));
n = m;
}
// Path
m = n;
while (
(m < chUri.Length) &&
(chUri[m] != '?') &&
(chUri[m] != '#')
)
{ m++; }
Path = new string(chUri, n, (m - n));
n = m;
if (n < chUri.Length)
{
if (chUri[n] == '?')
{
n++;
m = n;
while (
(m < chUri.Length) &&
(chUri[m] != '#')
)
{ m++; }
Query = new string(chUri, n, (m - n));
n = m;
}
if ((n<chUri.Length) && (chUri[n] == '#'))
{
n++;
m = n;
while (
(m < chUri.Length) &&
(chUri[m] != '#')
)
{ m++; }
Fragment = new string(chUri, n, (m - n));
n = m;
}
if (n < chUri.Length)
throw new FormatException(String.Format("Malformed URI: {0}", uri));
}
}
}
private void ParseAuthority()
{
int indAt = Authority.IndexOf('@');
if (indAt != -1)
{
UserInfo = Authority.Substring(0, indAt).Split(':');
}
indAt++;
int indPort = Authority.IndexOf(':', indAt);
if (indPort != -1)
{
Host = Authority.Substring(indAt, indPort - indAt);
Port = Authority.Substring(indPort + 1);
}
else
{
Host = Authority.Substring(indAt);
}
}
public override string ToString()
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(Scheme);
stringBuilder.Append(':');
if (!String.Empty.Equals(Authority))
{
stringBuilder.Append("//");
if (UserInfo.Length > 0)
{
stringBuilder.Append(UserInfo[0]);
stringBuilder.Append('@');
}
stringBuilder.Append(Host);
if (!String.Empty.Equals(Port))
{
stringBuilder.Append(':');
stringBuilder.Append(Port);
}
}
stringBuilder.Append(Path);
if (!string.Empty.Equals(Query))
{
stringBuilder.Append("?");
stringBuilder.Append(Query);
}
if (!string.Empty.Equals(Fragment))
{
stringBuilder.Append('#');
stringBuilder.Append(Fragment);
}
return stringBuilder.ToString();
}
private int GetHashCode(String s)
{
return (s == null) ? -1 : s.GetHashCode();
}
public override int GetHashCode()
{
return GetHashCode(Scheme) ^ GetHashCode(Authority) ^ GetHashCode(Path) ^ GetHashCode(Query) ^ GetHashCode(Fragment);
}
public override bool Equals(object obj)
{
if (obj is URI)
{
URI other = obj as URI;
return Scheme.Equals(other.Scheme) && Authority.Equals(other.Authority) && Path.Equals(other.Path) && Query.Equals(other.Query) && Fragment.Equals(other.Fragment);
}
return false;
}
}
}