5 // Lawrence Pit (loz@cable.a2000.nl)
7 // Copyright (C) 2005, 2010 Novell, Inc (http://www.novell.com)
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System.Collections;
31 using System.Runtime.Serialization;
34 // See RFC 2396 for more info on URI's.
38 public class UriBuilder
40 private string scheme;
45 private string fragment;
46 private string username;
47 private string password;
50 private bool modified;
57 Initialize (Uri.UriSchemeHttp, "localhost", -1, String.Empty, String.Empty);
60 public UriBuilder (string uri)
63 throw new ArgumentNullException ("uriString");
66 if (Uri.TryCreate (uri, UriKind.Absolute, out u)) {
68 } else if (!uri.Contains (Uri.SchemeDelimiter)) {
69 // second chance, UriBuilder parsing is more forgiving than Uri
70 Initialize (new Uri (Uri.UriSchemeHttp + Uri.SchemeDelimiter + uri));
72 throw new UriFormatException ();
75 public UriBuilder (Uri uri)
79 throw new ArgumentNullException ("uri");
84 public UriBuilder (string schemeName, string hostName)
86 Initialize (schemeName, hostName, -1, String.Empty, String.Empty);
89 public UriBuilder (string scheme, string host, int portNumber)
91 Initialize (scheme, host, portNumber, String.Empty, String.Empty);
94 public UriBuilder (string scheme, string host, int port, string pathValue)
96 Initialize (scheme, host, port, pathValue, String.Empty);
99 public UriBuilder (string scheme, string host, int port, string path, string extraValue)
101 Initialize (scheme, host, port, path, extraValue);
104 private void Initialize (Uri uri)
106 Initialize (uri.Scheme, uri.Host, uri.Port, uri.AbsolutePath, String.Empty);
107 fragment = uri.Fragment;
109 username = uri.UserInfo;
110 int pos = username.IndexOf (':');
112 password = username.Substring (pos + 1);
113 username = username.Substring (0, pos);
115 password = String.Empty;
119 private void Initialize (string scheme, string host, int port, string pathValue, string extraValue)
127 query = String.Empty;
128 fragment = String.Empty;
130 username = String.Empty;
131 password = String.Empty;
133 if (String.IsNullOrEmpty (extraValue))
136 if (extraValue [0] == '#')
137 Fragment = extraValue.Remove (0, 1);
138 else if (extraValue [0] == '?')
139 Query = extraValue.Remove (0, 1);
141 throw new ArgumentException ("extraValue");
146 public string Fragment {
147 get { return fragment; }
150 if (fragment == null)
151 fragment = String.Empty;
152 else if (fragment.Length > 0)
153 fragment = "#" + value.Replace ("%23", "#");
161 if (String.IsNullOrEmpty (value))
163 else if ((value.IndexOf (':') != -1) && (value [0] != '[')) {
164 host = "[" + value + "]";
172 public string Password {
173 get { return password; }
175 password = (value == null) ? String.Empty : value;
182 if (value == null || value.Length == 0) {
185 path = Uri.EscapeString (value.Replace ('\\', '/'), Uri.EscapeCommonHexBracketsQuery);
195 throw new ArgumentOutOfRangeException ("value");
202 public string Query {
203 get { return query; }
205 // LAMESPEC: it doesn't say to always prepend a
206 // question mark to the value.. it does say this
208 if (value == null || value.Length == 0)
209 query = String.Empty;
216 public string Scheme {
217 get { return scheme; }
220 value = String.Empty;
221 int colonPos = value.IndexOf (':');
223 value = value.Substring (0, colonPos);
224 scheme = value.ToLower ();
233 uri = new Uri (ToString ());
234 // some properties are updated once the Uri is created - see unit tests
236 path = uri.AbsolutePath;
242 public string UserName {
243 get { return username; }
245 username = (value == null) ? String.Empty : value;
252 public override bool Equals (object rparam)
254 return (rparam == null) ? false : this.Uri.Equals (rparam.ToString ());
257 public override int GetHashCode ()
259 return this.Uri.GetHashCode ();
262 public override string ToString ()
264 StringBuilder builder = new StringBuilder ();
266 builder.Append (scheme);
267 // note: mailto and news use ':', not "://", as their delimiter
268 builder.Append (Uri.GetSchemeDelimiter (scheme));
270 if (username != String.Empty) {
271 builder.Append (username);
272 if (password != String.Empty)
273 builder.Append (":" + password);
274 builder.Append ('@');
277 if (host.Length > 0) {
278 builder.Append (host);
280 builder.Append (":" + port);
283 if (path != String.Empty &&
284 builder [builder.Length - 1] != '/' &&
285 path.Length > 0 && path [0] != '/')
286 builder.Append ('/');
287 builder.Append (path);
288 builder.Append (query);
289 builder.Append (fragment);
291 return builder.ToString ();