Skip to content

Commit

Permalink
Fixed loading of PackagePart relationships to avoid (incorrect) conve…
Browse files Browse the repository at this point in the history
…rsion of relative target uris into absolute. (fixes xamarin bug mono#6602)
  • Loading branch information
pruiz committed Oct 20, 2012
1 parent 8298b36 commit 90bb2f1
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 34 deletions.
25 changes: 22 additions & 3 deletions mcs/class/WindowsBase/System.IO.Packaging/Check.cs
Expand Up @@ -70,6 +70,18 @@ private static bool EmptyOrBlank (string s)
{
return (s != null && (s == "" || s.Trim ().Length == 0));
}

private static void PartUriDoesntEndWithSlash(Uri uri)
{
var s = !uri.IsAbsoluteUri ? uri.OriginalString
: uri.GetComponents(UriComponents.Path, UriFormat.UriEscaped);

// We allow '/' at uri's beggining.
if ((s.Length > 1) && s.EndsWith("/"))
{
throw new ArgumentException("Part URI cannot end with a forward slash.");
}
}

public static void Package(object package)
{
Expand All @@ -91,11 +103,11 @@ public static void PackageUriIsValid (Uri packageUri)

public static void PackUriIsValid (Uri packUri)
{
if (!packUri.IsAbsoluteUri)
throw new ArgumentException("packUri", "PackUris must be absolute");

if (packUri.Scheme != PackUriHelper.UriSchemePack)
throw new ArgumentException ("packUri", "Uri scheme is not a valid PackUri scheme");

if (!packUri.IsAbsoluteUri)
throw new ArgumentException ("packUri", "PackUris must be absolute");
}

public static void PartUri (object partUri)
Expand Down Expand Up @@ -131,14 +143,21 @@ public static void PartUri (Uri partUri)
throw new ArgumentException ("partUri", "Part uri cannot be an empty string");
}

public static void PackUri(Uri packUri)
{
NotNull(packUri, "packUri");
}

public static void SourcePartUri (Uri sourcePartUri)
{
NotNull(sourcePartUri, "sourcePartUri");
PartUriDoesntEndWithSlash(sourcePartUri);
}

public static void TargetPartUri (Uri targetPartUri)
{
NotNull(targetPartUri, "targetPartUri");
PartUriDoesntEndWithSlash(targetPartUri);
}

public static void SourceUri (Uri sourceUri)
Expand Down
38 changes: 28 additions & 10 deletions mcs/class/WindowsBase/System.IO.Packaging/PackUriHelper.cs
Expand Up @@ -31,6 +31,8 @@ public static class PackUriHelper
{
public static readonly string UriSchemePack = "pack";
static readonly Uri PackSchemeUri = new Uri("pack://", UriKind.Absolute);
static readonly char[] _escapedChars = new char[] { '%', ',', '?', '@' };


static PackUriHelper ()
{
Expand Down Expand Up @@ -85,13 +87,21 @@ public static Uri Create (Uri packageUri, Uri partUri, string fragment)
// FIXME: Validate that partUri is a valid one? Must be relative, must start with '/'

// First replace the slashes, then escape the special characters
string orig = packageUri.OriginalString.Replace ('/', ',');

//string orig = packageUri.GetComponents(UriComponents.AbsoluteUri, UriFormat.UriEscaped);
string orig = packageUri.OriginalString;

foreach (var ch in _escapedChars)
{
orig = !orig.Contains(ch.ToString()) ? orig : orig.Replace(ch.ToString(), Uri.HexEscape(ch));
}

orig = orig.Replace('/', ',');

if (partUri != null)
orig += partUri.OriginalString;

// if (sb[sb.Length - 1] != '/')
// sb.Append ('/');
if ((fragment == null && partUri == null)&& orig[orig.Length - 1] != '/')
orig += '/';

if (fragment != null)
orig += fragment;
Expand All @@ -116,14 +126,22 @@ public static Uri GetNormalizedPartUri (Uri partUri)

public static Uri GetPackageUri (Uri packUri)
{
//Check.PackUri (packUri);
string s = packUri.Host.Replace (',', '/');
return new Uri (s, UriKind.Relative);
Check.PackUri (packUri);
Check.PackUriIsValid (packUri);

string s = packUri.Host.Replace(',', '/');
return new Uri (Uri.UnescapeDataString(s), UriKind.RelativeOrAbsolute);
}

public static Uri GetPartUri (Uri packUri)
{
throw new NotImplementedException ();
Check.PackUri(packUri);
Check.PackUriIsValid(packUri);

if (string.IsNullOrEmpty(packUri.AbsolutePath) || packUri.AbsolutePath == "/")
return null;

return new Uri(packUri.AbsolutePath, UriKind.Relative);
}

public static Uri GetRelationshipPartUri (Uri partUri)
Expand All @@ -143,8 +161,8 @@ public static Uri GetRelativeUri (Uri sourcePartUri, Uri targetPartUri)
Check.TargetPartUri (targetPartUri);

Uri uri = new Uri ("http://fake.com");
Uri a = new Uri (uri, sourcePartUri.AbsolutePath);
Uri b = new Uri (uri, targetPartUri.AbsolutePath);
Uri a = new Uri (uri, sourcePartUri.OriginalString);
Uri b = new Uri (uri, targetPartUri.OriginalString);

return a.MakeRelativeUri(b);
}
Expand Down
32 changes: 17 additions & 15 deletions mcs/class/WindowsBase/System.IO.Packaging/PackUriParser.cs
Expand Up @@ -64,35 +64,37 @@ protected override string GetComponents(Uri uri, UriComponents components, UriFo
builder.Length == 0)
start++;

builder.Append(s, start, end - start);
if (start > 0) builder.Append(s, start, end - start);
}

if ((components & UriComponents.Query) == UriComponents.Query)
{
int index = s.IndexOf('?');
if (index == -1)
return null;

if ((components & UriComponents.KeepDelimiter) != UriComponents.KeepDelimiter &&
builder.Length == 0)
index++;
if (index != -1)
{
if ((components & UriComponents.KeepDelimiter) != UriComponents.KeepDelimiter &&
builder.Length == 0)
index++;

int fragIndex = s.IndexOf('#');
int end = fragIndex == -1 ? s.Length : fragIndex;
builder.Append(s, index, end - index);
int fragIndex = s.IndexOf('#');
int end = fragIndex == -1 ? s.Length : fragIndex;
builder.Append(s, index, end - index);
}
}

if ((components & UriComponents.Fragment) == UriComponents.Fragment)
{
int index = s.IndexOf('#');
if (index == -1)
return null;

if ((components & UriComponents.KeepDelimiter) != UriComponents.KeepDelimiter &&
builder.Length == 0)
index++;
if (index != -1)
{
if ((components & UriComponents.KeepDelimiter) != UriComponents.KeepDelimiter &&
builder.Length == 0)
index++;

builder.Append(s, index, s.Length - index);
builder.Append(s, index, s.Length - index);
}
}

return builder.ToString();
Expand Down
2 changes: 1 addition & 1 deletion mcs/class/WindowsBase/System.IO.Packaging/PackagePart.cs
Expand Up @@ -165,7 +165,7 @@ void LoadRelationships (Dictionary<string, PackageRelationship> relationships, S
if (node.Attributes["TargetMode"] != null)
mode = (TargetMode) Enum.Parse (typeof(TargetMode), node.Attributes ["TargetMode"].Value);

CreateRelationship (new Uri ("/" + node.Attributes["Target"].Value.ToString(), UriKind.Relative),
CreateRelationship (new Uri (node.Attributes["Target"].Value.ToString(), UriKind.Relative),
mode,
node.Attributes["Type"].Value.ToString (),
node.Attributes["Id"].Value.ToString (),
Expand Down
Expand Up @@ -11,16 +11,13 @@
namespace System.IO.Packaging.Tests {

[TestFixture]
[Category ("NotWorking")]
[Ignore ("This depends on a fix to System.Uri to support the UriParser API")]
public class PackUriHelperTests {
static void Main (string [] args)
{
PackUriHelperTests t = new PackUriHelperTests ();
t.ResolvePartUri2 ();
}


Uri a;
Uri b;
Uri part1 = new Uri ("/file1", UriKind.Relative);
Expand All @@ -46,6 +43,7 @@ public void ComparePackUriTest ()
}

[Test]
[Category("NotWorking")]
[ExpectedException(typeof(UriFormatException))]
public void CompareInvalidTest ()
{
Expand All @@ -54,20 +52,23 @@ public void CompareInvalidTest ()
}

[Test]
[Category("NotWorking")]
[ExpectedException (typeof (ArgumentException))]
public void NonPackUriCompareTest ()
{
PackUriHelper.ComparePackUri (new Uri ("http://wtest.com"), a);
}

[Test]
[Category("NotWorking")]
[ExpectedException (typeof (ArgumentException))]
public void NonPackUriCompareRelativeTest ()
{
PackUriHelper.ComparePackUri (new Uri ("wtest.com", UriKind.Relative), a);
}

[Test]
[Category("NotWorking")]
[ExpectedException (typeof (ArgumentException))]
public void InvalidPartUriCompareTest ()
{
Expand Down Expand Up @@ -97,6 +98,13 @@ public void CreateTest ()
new Uri ("/main.html", UriKind.Relative), "#frag").ToString (), "#3");
}

[Test]
public void CreateTest2()
{
Uri uri = PackUriHelper.Create(new Uri("http://www.test.com/pack1.pkg"));
Assert.AreEqual("pack://pack:,,http:%2C%2Cwww.test.com%2Cpack1.pkg,/", PackUriHelper.Create(uri).ToString());
}

[Test]
[ExpectedException (typeof (ArgumentException))]
public void CreateInvalidTest ()
Expand Down Expand Up @@ -185,10 +193,16 @@ public void GetPackageUri3 ()
}

[Test]
[Category("NotWorking")]
public void GetPartUriTest ()
{
Assert.IsNull (PackUriHelper.GetPartUri (a), "#1");
Assert.AreEqual (main, PackUriHelper.GetPartUri (PackUriHelper.Create (a, main)), "#2");
var pack = PackUriHelper.Create(new Uri("http://www.test.com/pack1.pkg"));
var part = new Uri("/main.html", UriKind.Relative);
var pack_part = new Uri(@"pack://pack:,,http:%2C%2Cwww.test.com%2Cpack1.pkg,/main.html");

Assert.IsNull(PackUriHelper.GetPartUri(pack), "#1");
Assert.AreEqual(pack_part, PackUriHelper.Create(pack, part), "#2");
Assert.AreEqual(part, PackUriHelper.GetPartUri(PackUriHelper.Create(pack, part)), "#3");
}

[Test]
Expand Down Expand Up @@ -312,6 +326,34 @@ public void ResolvePartUri4 ()
Uri result = PackUriHelper.ResolvePartUri (src, dest);
Assert.IsFalse(result.IsAbsoluteUri, "#1");
Assert.AreEqual ("/word/document.xml", result.ToString(), "#2");

// See: http://msdn.microsoft.com/en-us/library/system.io.packaging.packurihelper.resolveparturi.aspx

src = new Uri ("/mydoc/markup/page.xml", UriKind.Relative);
dest = new Uri("picture.jpg", UriKind.Relative);
result = PackUriHelper.ResolvePartUri (src, dest);
Assert.AreEqual ("/mydoc/markup/picture.jpg", result.ToString(), "#3");

dest = new Uri("images/picture.jpg", UriKind.Relative);
result = PackUriHelper.ResolvePartUri (src, dest);
Assert.AreEqual ("/mydoc/markup/images/picture.jpg", result.ToString(), "#4");

dest = new Uri("./picture.jpg", UriKind.Relative);
result = PackUriHelper.ResolvePartUri (src, dest);
Assert.AreEqual ("/mydoc/markup/picture.jpg", result.ToString(), "#5");

dest = new Uri("../picture.jpg", UriKind.Relative);
result = PackUriHelper.ResolvePartUri (src, dest);
Assert.AreEqual ("/mydoc/picture.jpg", result.ToString(), "#6");

dest = new Uri("../images/picture.jpg", UriKind.Relative);
result = PackUriHelper.ResolvePartUri (src, dest);
Assert.AreEqual ("/mydoc/images/picture.jpg", result.ToString(), "#7");

src = new Uri ("/", UriKind.Relative);
dest = new Uri("images/picture.jpg", UriKind.Relative);
result = PackUriHelper.ResolvePartUri (src, dest);
Assert.AreEqual ("/images/picture.jpg", result.ToString(), "#8");
}
}
}

0 comments on commit 90bb2f1

Please sign in to comment.