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)
78 throw new ArgumentNullException ("uri");
82 public UriBuilder (string schemeName, string hostName)
84 Initialize (schemeName, hostName, -1, String.Empty, String.Empty);
87 public UriBuilder (string scheme, string host, int portNumber)
89 Initialize (scheme, host, portNumber, String.Empty, String.Empty);
92 public UriBuilder (string scheme, string host, int port, string pathValue)
94 Initialize (scheme, host, port, pathValue, String.Empty);
97 public UriBuilder (string scheme, string host, int port, string path, string extraValue)
99 Initialize (scheme, host, port, path, extraValue);
102 private void Initialize (Uri uri)
104 Initialize (uri.Scheme, uri.Host, uri.Port, uri.AbsolutePath, String.Empty);
105 fragment = uri.Fragment;
107 username = uri.UserInfo;
108 int pos = username.IndexOf (':');
110 password = username.Substring (pos + 1);
111 username = username.Substring (0, pos);
113 password = String.Empty;
117 private void Initialize (string scheme, string host, int port, string pathValue, string extraValue)
125 query = String.Empty;
126 fragment = String.Empty;
128 username = String.Empty;
129 password = String.Empty;
131 if (String.IsNullOrEmpty (extraValue))
134 if (extraValue [0] == '#')
135 Fragment = extraValue.Remove (0, 1);
136 else if (extraValue [0] == '?')
137 Query = extraValue.Remove (0, 1);
139 throw new ArgumentException ("extraValue");
144 public string Fragment {
145 get { return fragment; }
148 if (fragment == null)
149 fragment = String.Empty;
150 else if (fragment.Length > 0)
151 fragment = "#" + value.Replace ("%23", "#");
159 if (String.IsNullOrEmpty (value))
161 else if ((value.IndexOf (':') != -1) && (value [0] != '[')) {
162 host = "[" + value + "]";
170 public string Password {
171 get { return password; }
173 password = (value == null) ? String.Empty : value;
180 if (value == null || value.Length == 0) {
183 path = Uri.EscapeString (value.Replace ('\\', '/'), Uri.EscapeCommonHexBracketsQuery);
193 throw new ArgumentOutOfRangeException ("value");
200 public string Query {
201 get { return query; }
203 // LAMESPEC: it doesn't say to always prepend a
204 // question mark to the value.. it does say this
206 if (value == null || value.Length == 0)
207 query = String.Empty;
214 public string Scheme {
215 get { return scheme; }
218 value = String.Empty;
219 int colonPos = value.IndexOf (':');
221 value = value.Substring (0, colonPos);
222 scheme = value.ToLower ();
231 uri = new Uri (ToString ());
232 // some properties are updated once the Uri is created - see unit tests
234 path = uri.AbsolutePath;
240 public string UserName {
241 get { return username; }
243 username = (value == null) ? String.Empty : value;
250 public override bool Equals (object rparam)
252 return (rparam == null) ? false : this.Uri.Equals (rparam.ToString ());
255 public override int GetHashCode ()
257 return this.Uri.GetHashCode ();
260 public override string ToString ()
262 StringBuilder builder = new StringBuilder ();
264 builder.Append (scheme);
265 // note: mailto and news use ':', not "://", as their delimiter
266 builder.Append (Uri.GetSchemeDelimiter (scheme));
268 if (username != String.Empty) {
269 builder.Append (username);
270 if (password != String.Empty)
271 builder.Append (":" + password);
272 builder.Append ('@');
275 if (host.Length > 0) {
276 builder.Append (host);
278 builder.Append (":" + port);
281 if (path != String.Empty &&
282 builder [builder.Length - 1] != '/' &&
283 path.Length > 0 && path [0] != '/')
284 builder.Append ('/');
285 builder.Append (path);
286 builder.Append (query);
287 builder.Append (fragment);
289 return builder.ToString ();