Merge pull request #1304 from slluis/mac-proxy-autoconfig
[mono.git] / mcs / class / WindowsBase / System.IO.Packaging / PackUriHelper.cs
1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 // 
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 // 
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 //
20 // Copyright (c) 2007 Novell, Inc. (http://www.novell.com)
21 //
22 // Authors:
23 //      Chris Toshok (toshok@ximian.com)
24 //
25
26 using System;
27
28 namespace System.IO.Packaging {
29
30         public static class PackUriHelper
31         {
32                 public static readonly string UriSchemePack = "pack";
33                 static readonly Uri PackSchemeUri = new Uri("pack://", UriKind.Absolute);
34                 static readonly char[] _escapedChars = new char[] { '%', ',', '?', '@' };
35
36                 
37                 static PackUriHelper ()
38                 {
39                         if (!UriParser.IsKnownScheme (UriSchemePack))
40                                 UriParser.Register (new PackUriParser (), UriSchemePack, -1);
41                 }
42                 
43                 public static int ComparePackUri (Uri firstPackUri, Uri secondPackUri)
44                 {
45                         if (firstPackUri == null)
46                                 return secondPackUri == null ? 0 : -1;
47                         if (secondPackUri == null)
48                                 return 1;
49
50                         Check.PackUriIsValid (firstPackUri);
51                         Check.PackUriIsValid (secondPackUri);
52
53                         // FIXME: What exactly is compared. Lets assume originalstring
54                         return firstPackUri.OriginalString.CompareTo (secondPackUri.OriginalString);
55                 }
56
57                 public static int ComparePartUri (Uri firstPartUri, Uri secondPartUri)
58                 {
59                         if (firstPartUri == null)
60                                 return secondPartUri == null ? 0 : -1;
61                         if (secondPartUri == null)
62                                 return 1;
63
64                         Check.PartUriIsValid (firstPartUri);
65                         Check.PartUriIsValid (secondPartUri);
66
67                         return firstPartUri.OriginalString.CompareTo (secondPartUri.OriginalString);
68                 }
69
70                 public static Uri Create (Uri packageUri)
71                 {
72                         return Create (packageUri, null, null);
73                 }
74
75                 public static Uri Create (Uri packageUri, Uri partUri)
76                 {
77                         return Create (packageUri, partUri, null);
78                 }
79
80                 public static Uri Create (Uri packageUri, Uri partUri, string fragment)
81                 {
82                         Check.PackageUri (packageUri);
83                         Check.PackageUriIsValid (packageUri);
84                         
85                         if (partUri != null)
86                                 Check.PartUriIsValid (partUri);
87                         
88                         if (fragment != null && (fragment.Length == 0 || fragment[0] != '#'))
89                                 throw new ArgumentException ("Fragment", "Fragment must not be empty and must start with '#'");
90
91                         // FIXME: Validate that partUri is a valid one? Must be relative, must start with '/'
92
93                         // First replace the slashes, then escape the special characters
94                         //string orig = packageUri.GetComponents(UriComponents.AbsoluteUri, UriFormat.UriEscaped);
95                         string orig = packageUri.OriginalString;
96
97                         foreach (var ch in _escapedChars)
98                         {
99                                 orig = !orig.Contains(ch.ToString()) ? orig : orig.Replace(ch.ToString(), Uri.HexEscape(ch));
100                         }
101
102                         orig = orig.Replace('/', ',');
103
104                         if (partUri != null)
105                                 orig += partUri.OriginalString;
106
107                         if ((fragment == null && partUri == null)&& orig[orig.Length - 1] != '/')
108                                 orig += '/';
109
110                         if (fragment != null)
111                                 orig += fragment;
112                         
113                         return new Uri ("pack://" + orig);
114                 }
115
116                 public static Uri CreatePartUri (Uri partUri)
117                 {
118                         Check.PartUri (partUri);
119                         
120                         if (partUri.OriginalString[0] != '/')
121                                 partUri = new Uri("/" + partUri.ToString (), UriKind.Relative);
122                         return partUri;
123                 }
124
125                 public static Uri GetNormalizedPartUri (Uri partUri)
126                 {
127                         Check.PartUri (partUri);
128                         return new Uri (partUri.ToString ().ToUpperInvariant (), UriKind.Relative);
129                 }
130
131                 public static Uri GetPackageUri (Uri packUri)
132                 {
133                         Check.PackUri (packUri);
134                         Check.PackUriIsValid (packUri);
135
136                         string s = packUri.Host.Replace(',', '/');
137                         return new Uri (Uri.UnescapeDataString(s), UriKind.RelativeOrAbsolute);
138                 }
139
140                 public static Uri GetPartUri (Uri packUri)
141                 {
142                         Check.PackUri(packUri);
143                         Check.PackUriIsValid(packUri);
144
145                         if (string.IsNullOrEmpty(packUri.AbsolutePath) || packUri.AbsolutePath == "/")
146                                 return null;
147
148                         return new Uri(packUri.AbsolutePath, UriKind.Relative);
149                 }
150
151                 public static Uri GetRelationshipPartUri (Uri partUri)
152                 {
153                         Check.PartUri (partUri);
154                         Check.PartUriIsValid (partUri);
155                         
156                         int index = partUri.OriginalString.LastIndexOf ("/");
157                         string s = partUri.OriginalString.Substring (0, index);
158                         s += "/_rels" + partUri.OriginalString.Substring (index) + ".rels";
159                         return new Uri (s, UriKind.Relative);
160                 }
161
162                 public static Uri GetRelativeUri (Uri sourcePartUri, Uri targetPartUri)
163                 {
164                         Check.SourcePartUri (sourcePartUri);
165                         Check.TargetPartUri (targetPartUri);
166
167                         Uri uri = new Uri ("http://fake.com");
168                         Uri a = new Uri (uri, sourcePartUri.OriginalString);
169                         Uri b = new Uri (uri, targetPartUri.OriginalString);
170
171                         return a.MakeRelativeUri(b);
172                 }
173
174                 public static Uri GetSourcePartUriFromRelationshipPartUri (Uri relationshipPartUri)
175                 {
176                         //Check.RelationshipPartUri (relationshipPartUri);
177                         if (!IsRelationshipPartUri (relationshipPartUri))
178                                 throw new Exception  ("is not a relationship part!?");
179                         return null;
180                 }
181
182                 public static bool IsRelationshipPartUri (Uri partUri)
183                 {
184                         Check.PartUri (partUri);
185                         return partUri.OriginalString.StartsWith ("/_rels") && partUri.OriginalString.EndsWith (".rels");
186                 }
187
188                 public static Uri ResolvePartUri (Uri sourcePartUri, Uri targetUri)
189                 {
190                         Check.SourcePartUri (sourcePartUri);
191                         Check.TargetUri (targetUri);
192                         
193                         Check.PartUriIsValid (sourcePartUri);
194                         if (targetUri.IsAbsoluteUri)
195                                 throw new ArgumentException ("targetUri", "Absolute URIs are not supported");
196
197                         Uri uri = new Uri ("http://fake.com");
198                         uri = new Uri (uri, sourcePartUri);
199                         uri = new Uri (uri, targetUri);
200
201                         // Trim out 'http://fake.com'
202                         return new Uri (uri.OriginalString.Substring (15), UriKind.Relative); 
203                 }
204         }
205
206 }