Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert non-seekable PackagePart streams to seekable #1311

Merged
merged 6 commits into from
Jul 19, 2019

Conversation

rladuca
Copy link
Member

@rladuca rladuca commented Jul 18, 2019

Fixes #585

@rladuca rladuca added the Bug Product bug (most likely) label Jul 18, 2019
@rladuca rladuca added this to the 3.0 milestone Jul 18, 2019
@rladuca rladuca self-assigned this Jul 18, 2019
@ghost ghost requested review from vatsan-madhavan, ryalanms and stevenbrix July 18, 2019 22:20
@ghost ghost added the PR metadata: Label to tag PRs, to facilitate with triage label Jul 18, 2019
@ghost ghost requested a review from SamBent July 18, 2019 22:20
@rladuca rladuca force-pushed the dev/roladuca/wrappackagestreams branch from aa39f73 to 4ed3f7b Compare July 18, 2019 22:40
Copy link

@weltkante weltkante left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After seeing #1363 I realize this PR may not have considered the consequences of wrapping writable streams. If this is just wrapping in a MemoryStream then there needs to be someone who transfers the data to the original stream, otherwise the writes will never happen.

@@ -131,7 +131,7 @@ internal void SetCertificate(X509Certificate2 certificate)
Byte[] byteArray = _certificate.GetRawCertData();

// FileMode.Create will ensure that the stream will shrink if overwritten
using (Stream s = _part.GetStream(FileMode.Create, FileAccess.Write))
using (Stream s = _part.GetSeekableStream(FileMode.Create, FileAccess.Write))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

who writes back the writable stream?

@@ -937,7 +937,7 @@ private Stream GetRelationshipStream(PartManifestEntry partEntry)
private void UpdatePartFromSignature(Signature sig)
{
// write to stream
using (Stream s = SignaturePart.GetStream(FileMode.Create, FileAccess.Write))
using (Stream s = SignaturePart.GetSeekableStream(FileMode.Create, FileAccess.Write))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

who writes back the writable stream?

/// <param name="mode">The FileMode to open the PackagePart</param>
/// <param name="access">The FileAccess used to open the PackagePart</param>
/// <returns>A seekable stream representing the data in the PackagePart.</returns>
internal static Stream GetSeekableStream(this PackagePart packPart, FileMode mode, FileAccess access)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it even make sense to specify FileMode/FileAccess, shouldn't it always be open/read? When wrapping a writable stream into a MemoryStream who will be forwarding the writes to the original stream?

@rladuca
Copy link
Member Author

rladuca commented Jul 24, 2019

After seeing #1363 I realize this PR may not have considered the consequences of wrapping writable streams. If this is just wrapping in a MemoryStream then there needs to be someone who transfers the data to the original stream, otherwise the writes will never happen.

Look at the implementation of the extension method. A writeable stream is already seekable when it comes back from PackagePart.GetStream. We just forward those streams onto the caller and do not read them out. The only case where PackagePart.GetStream returns a non-seekable stream is in read-only scenarios. That is precisely why the workaround is to open your XPS or Package as write or read-write.

// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using MS.Internal.WindowsBase;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you move the other PackagePart extension method in WindowsBase\MS\Internal\IO\Packaging\PackagingExtensions.cs to this file?

public static ContentType ValidatedContentType(this PackagePart packagePart)
{
      return new ContentType(packagePart.ContentType);
}

@vatsan-madhavan vatsan-madhavan deleted the dev/roladuca/wrappackagestreams branch August 23, 2019 20:11
vatsan-madhavan pushed a commit that referenced this pull request Sep 6, 2019
Create extension methods for PackagePart that allow us to acquire a seekable stream in the case where the stream returned from PackagePart.GetStream is not already seekable.  Switch instances where we call PackagePart.GetStream to use this in order to work-around the fact that a read-only PackagePart stream will use DeflateStream, which is not seekable in .NET Core.
@ghost ghost locked as resolved and limited conversation to collaborators Apr 16, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug Product bug (most likely) PR metadata: Label to tag PRs, to facilitate with triage
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Behavior change regarding seekability of streams returned for ZipArchive
4 participants