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:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
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.
20 // Copyright (c) 2007 Novell, Inc. (http://www.novell.com)
23 // Chris Toshok (toshok@ximian.com)
28 namespace System.IO.Packaging {
30 public static class PackUriHelper
32 public static readonly string UriSchemePack = "pack";
33 static readonly Uri PackSchemeUri = new Uri("pack://", UriKind.Absolute);
34 static readonly char[] _escapedChars = new char[] { '%', ',', '?', '@' };
37 static PackUriHelper ()
39 if (!UriParser.IsKnownScheme (UriSchemePack))
40 UriParser.Register (new PackUriParser (), UriSchemePack, -1);
43 public static int ComparePackUri (Uri firstPackUri, Uri secondPackUri)
45 if (firstPackUri == null)
46 return secondPackUri == null ? 0 : -1;
47 if (secondPackUri == null)
50 Check.PackUriIsValid (firstPackUri);
51 Check.PackUriIsValid (secondPackUri);
53 // FIXME: What exactly is compared. Lets assume originalstring
54 return firstPackUri.OriginalString.CompareTo (secondPackUri.OriginalString);
57 public static int ComparePartUri (Uri firstPartUri, Uri secondPartUri)
59 if (firstPartUri == null)
60 return secondPartUri == null ? 0 : -1;
61 if (secondPartUri == null)
64 Check.PartUriIsValid (firstPartUri);
65 Check.PartUriIsValid (secondPartUri);
67 return firstPartUri.OriginalString.CompareTo (secondPartUri.OriginalString);
70 public static Uri Create (Uri packageUri)
72 return Create (packageUri, null, null);
75 public static Uri Create (Uri packageUri, Uri partUri)
77 return Create (packageUri, partUri, null);
80 public static Uri Create (Uri packageUri, Uri partUri, string fragment)
82 Check.PackageUri (packageUri);
83 Check.PackageUriIsValid (packageUri);
86 Check.PartUriIsValid (partUri);
88 if (fragment != null && (fragment.Length == 0 || fragment[0] != '#'))
89 throw new ArgumentException ("Fragment", "Fragment must not be empty and must start with '#'");
91 // FIXME: Validate that partUri is a valid one? Must be relative, must start with '/'
93 // First replace the slashes, then escape the special characters
94 //string orig = packageUri.GetComponents(UriComponents.AbsoluteUri, UriFormat.UriEscaped);
95 string orig = packageUri.OriginalString;
97 foreach (var ch in _escapedChars)
99 orig = !orig.Contains(ch.ToString()) ? orig : orig.Replace(ch.ToString(), Uri.HexEscape(ch));
102 orig = orig.Replace('/', ',');
105 orig += partUri.OriginalString;
107 if ((fragment == null && partUri == null)&& orig[orig.Length - 1] != '/')
110 if (fragment != null)
113 return new Uri ("pack://" + orig);
116 public static Uri CreatePartUri (Uri partUri)
118 Check.PartUri (partUri);
120 if (partUri.OriginalString[0] != '/')
121 partUri = new Uri("/" + partUri.ToString (), UriKind.Relative);
125 public static Uri GetNormalizedPartUri (Uri partUri)
127 Check.PartUri (partUri);
128 return new Uri (partUri.ToString ().ToUpperInvariant (), UriKind.Relative);
131 public static Uri GetPackageUri (Uri packUri)
133 Check.PackUri (packUri);
134 Check.PackUriIsValid (packUri);
136 string s = packUri.Host.Replace(',', '/');
137 return new Uri (Uri.UnescapeDataString(s), UriKind.RelativeOrAbsolute);
140 public static Uri GetPartUri (Uri packUri)
142 Check.PackUri(packUri);
143 Check.PackUriIsValid(packUri);
145 if (string.IsNullOrEmpty(packUri.AbsolutePath) || packUri.AbsolutePath == "/")
148 return new Uri(packUri.AbsolutePath, UriKind.Relative);
151 public static Uri GetRelationshipPartUri (Uri partUri)
153 Check.PartUri (partUri);
154 Check.PartUriIsValid (partUri);
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);
162 public static Uri GetRelativeUri (Uri sourcePartUri, Uri targetPartUri)
164 Check.SourcePartUri (sourcePartUri);
165 Check.TargetPartUri (targetPartUri);
167 Uri uri = new Uri ("http://fake.com");
168 Uri a = new Uri (uri, sourcePartUri.OriginalString);
169 Uri b = new Uri (uri, targetPartUri.OriginalString);
171 return a.MakeRelativeUri(b);
174 public static Uri GetSourcePartUriFromRelationshipPartUri (Uri relationshipPartUri)
176 //Check.RelationshipPartUri (relationshipPartUri);
177 if (!IsRelationshipPartUri (relationshipPartUri))
178 throw new Exception ("is not a relationship part!?");
182 public static bool IsRelationshipPartUri (Uri partUri)
184 Check.PartUri (partUri);
185 return partUri.OriginalString.StartsWith ("/_rels") && partUri.OriginalString.EndsWith (".rels");
188 public static Uri ResolvePartUri (Uri sourcePartUri, Uri targetUri)
190 Check.SourcePartUri (sourcePartUri);
191 Check.TargetUri (targetUri);
193 Check.PartUriIsValid (sourcePartUri);
194 if (targetUri.IsAbsoluteUri)
195 throw new ArgumentException ("targetUri", "Absolute URIs are not supported");
197 Uri uri = new Uri ("http://fake.com");
198 uri = new Uri (uri, sourcePartUri);
199 uri = new Uri (uri, targetUri);
201 // Trim out 'http://fake.com'
202 return new Uri (uri.OriginalString.Substring (15), UriKind.Relative);