//------------------------------------------------------ // // Private Methods // //------------------------------------------------------ #region Private Methods // IsRelationshipPartUri method returns a boolean indicating whether the // Uri given is a relationship part Uri or no. private bool IsRelationshipUri() { bool result = false; //exit early if the partUri does not end with the relationship extension if (!NormalizedPartUriString.EndsWith(s_relationshipPartUpperCaseExtension, StringComparison.Ordinal)) { return(false); } // if uri is /_rels/.rels then we return true if (PackUriHelper.ComparePartUri(s_containerRelationshipNormalizedPartUri, this) == 0) { return(true); } // Look for pattern that matches: "XXX/_rels/YYY.rels" where XXX is zero or more part name characters and // YYY is any legal part name characters. // We can assume that the string is a valid URI because it would have been rejected by the Uri parsing // code in the Uri constructor if it wasn't. // Uri's are case insensitive so we can compare them by upper-casing them // Essentially, we will just look for the existence of a "folder" called _rels and the trailing extension // of .rels. The folder must also be the last "folder". // Comparing using the normalized string to reduce the number of ToUpperInvariant operations // required for case-insensitive comparison string[] segments = NormalizedPartUriString.Split(s_forwardSlashCharArray); //new Uri(_defaultUri, this).Segments; //partUri.Segments cannot be called on a relative Uri; // String.Split, will always return an empty string as the // first member in the array as the string starts with a "/" Debug.Assert(segments.Length > 0 && segments[0] == string.Empty); //If the extension was not equal to .rels, we would have exited early. Debug.Assert(string.CompareOrdinal((Path.GetExtension(segments[segments.Length - 1])), s_relationshipPartUpperCaseExtension) == 0); // must be at least two segments and the last one must end with .RELs // and the length of the segment should be greater than just the extension. if ((segments.Length >= 3) && (segments[segments.Length - 1].Length > s_relationshipPartExtensionName.Length)) { // look for "_RELS" segment which must be second last segment result = (string.CompareOrdinal(segments[segments.Length - 2], s_relationshipPartUpperCaseSegmentName) == 0); } // In addition we need to make sure that the relationship is not created by taking another relationship // as the source of this uri. So XXX/_rels/_rels/YYY.rels.rels would be invalid. if (segments.Length > 3 && result == true) { if ((segments[segments.Length - 1]).EndsWith(s_relsrelsUpperCaseExtension, StringComparison.Ordinal)) { // look for "_rels" segment in the third last segment if (string.CompareOrdinal(segments[segments.Length - 3], s_relationshipPartUpperCaseSegmentName) == 0) { throw new ArgumentException(SR.NotAValidRelationshipPartUri); } } } return(result); }
/// <summary> /// Given a valid relationship Part Uri, this method returns the source Part Uri for /// this relationship Part Uri. /// If the relationship part name is for the Package Level relationships [/_rels/.rels], /// we return a relative Uri of the form "/" indicating that it has no part as the parent, /// but is at the package level /// Example Input - Relationship Uri - /files/_rels/document.xaml.rels /// Returns -Source Part Uri - /files/document.xaml /// </summary> /// <param name="relationshipPartUri">relationship part Uri</param> /// <returns>A uri that is a valid source part Uri for the relationship Uri provided</returns> /// <exception cref="ArgumentNullException">If relationshipPartUri parameter is null</exception> /// <exception cref="ArgumentException">If relationshipPartUri parameter is an absolute Uri</exception> /// <exception cref="ArgumentException">If relationshipPartUri parameter does not conform to the valid partUri Syntax</exception> /// <exception cref="ArgumentException">If the relationshipPartUri is not a relationship part Uri itself</exception> /// <exception cref="ArgumentException">If the resultant Uri obtained is a relationship part Uri</exception> public static Uri GetSourcePartUriFromRelationshipPartUri(Uri relationshipPartUri) { if (relationshipPartUri == null) { throw new ArgumentNullException(nameof(relationshipPartUri)); } // Verify - // 1. Validates that this part Uri is a valid part Uri relationshipPartUri = ValidatePartUri(relationshipPartUri); // 2. Checks that this part Uri is not a relationshipPart Uri if (!IsRelationshipPartUri(relationshipPartUri)) { throw new ArgumentException(SR.RelationshipPartUriExpected); } // _rels/.rels has no parent part if (PackUriHelper.ComparePartUri(PackageRelationship.ContainerRelationshipPartName, relationshipPartUri) == 0) { return(PackageRootUri); } else { //We should have a ValidatedPartUri by this time string path = ((ValidatedPartUri)relationshipPartUri).PartUriString; string partNameWithoutExtension = Path.GetFileNameWithoutExtension(path); Debug.Assert((path.Length - partNameWithoutExtension.Length - s_relationshipPartExtensionName.Length - 1) > 0, "The partname may not be well-formed"); //Get the part name without the last segment path = path.Substring(0, path.Length - partNameWithoutExtension.Length - s_relationshipPartExtensionName.Length - 1); Debug.Assert((path.Length - s_relationshipPartSegmentName.Length) > 0, "The partname may not be well-formed"); path = path.Substring(0, path.Length - s_relationshipPartSegmentName.Length); // Removing rels segment path = Path.Combine(path, partNameWithoutExtension); // Adding the last segment without ".rels" extension path = path.Replace(BackwardSlashChar, ForwardSlashChar); // convert to Uri - We could use PackUriHelper.Create, but since we know that this is a //valid Part Uri we can just call the Uri constructor. return(new ValidatedPartUri(path, isRelationshipUri: false)); } }