NoPassSetMetadata.cs
//
// This code is part of Document Solutions for PDF demos.
// Copyright (c) MESCIUS inc. All rights reserved.
//
using System;
using System.IO;
using System.Drawing;
using GrapeCity.Documents.Pdf;
using GrapeCity.Documents.Pdf.Security;
using GrapeCity.Documents.Text;

namespace DsPdfWeb.Demos
{
    // This example shows how to load a password protected PDF and change its metadata.
    // Keep in mind that in some cases metadata in a PDF may also be encrypted, in which case
    // accessing it without the password is impossible.
    // For reference, the loaded PDF is protected with the owner password 'owner' and user password 'user'.
    public class NoPassSetMetadata
    {
        public int CreatePDF(Stream stream)
        {
            using var fs = File.OpenRead(Path.Combine("Resources", "PDFs", "Wetlands-password-user.pdf"));
            // Set up DecryptionOptions to allow loading password protected PDFs without password:
            var dopt = new DecryptionOptions() { ThrowExceptionIfInvalidPassword = false };
            var docSrc = new GcPdfDocument();
            docSrc.Load(fs, dopt);

            // All security handlers before StandardSecurityHandlerRev4 always encrypted metadata,
            // the StandardSecurityHandlerRev4 has EncryptMetadata property which we need to check:
            bool metadataIsEncrypted = true;
            if (docSrc.Security.EncryptHandler is StandardSecurityHandlerRev4 ssh)
                metadataIsEncrypted = ssh.EncryptMetadata;
            // In the PDf used by this demo the metadata is not encrypted:
            if (metadataIsEncrypted)
                throw new Exception("Set PDF Metadata demo: Unexpected error.");

            Metadata m = docSrc.Metadata;
            // Save original metadata so we can compare the results:
            var origTitle = m.Title;
            var origCreatorTool = m.CreatorTool;
            var origModifyDate = m.ModifyDate;
            // Change some metadata:
            m.Title = "Set PDF Metadata Demo";
            m.CreatorTool = "DsPdf Demo Browser";
            m.ModifyDate = Common.Util.TimeNow();

            // We save the modified password protected document to a temp file,
            // load it again (also without password), read the (modified) metadata
            // and display it in the resulting PDF:
            var fn = Path.GetTempFileName();
            {
                docSrc.Save(fn);

                using var fsTemp = File.OpenRead(fn);
                var docTemp = new GcPdfDocument();
                docTemp.Load(fsTemp, dopt);

                // The PDF to hold the results:
                var doc = new GcPdfDocument();
                var page = doc.NewPage();
                // Set up a TextLayout to format the results:
                var tl = page.Graphics.CreateTextLayout();
                tl.DefaultFormat.Font = StandardFonts.Courier;
                tl.DefaultFormat.FontSize = 14;
                tl.MaxWidth = doc.PageSize.Width;
                tl.MaxHeight = doc.PageSize.Height;
                tl.MarginAll = tl.Resolution;
                var captionFmt = new TextFormat(tl.DefaultFormat) { Font = StandardFonts.CourierBold, FontSize = tl.DefaultFormat.FontSize + 2 };

                if (docTemp.Security.EncryptHandler is StandardSecurityHandlerRev4 sshTemp)
                    metadataIsEncrypted = sshTemp.EncryptMetadata;
                if (metadataIsEncrypted)
                    throw new Exception("Set PDF Metadata demo: Unexpected error.");

                // Render the results:
                Metadata mTemp = docTemp.Metadata;
                tl.AppendLine("Modified metadata in a password protected PDF:", captionFmt);
                tl.AppendLine($"\nTitle", captionFmt);
                tl.AppendLine($"Was '{origTitle}', now '{mTemp.Title}'");
                tl.AppendLine($"\nCreatorTool", captionFmt);
                tl.AppendLine($"Was '{origCreatorTool}', now '{mTemp.CreatorTool}'");
                tl.AppendLine($"\nModifyDate", captionFmt);
                var origModifyDateStr = origModifyDate.HasValue ? origModifyDate.Value.ToString("R") : string.Empty;
                var newModifyDateStr = mTemp.ModifyDate.HasValue ? mTemp.ModifyDate.Value.ToString("R") : string.Empty;
                tl.AppendLine($"Was '{origModifyDateStr}', now '{newModifyDateStr}'");
                tl.PerformLayout(true);
                page.Graphics.DrawTextLayout(tl, PointF.Empty);
                doc.Save(stream);
            }
            File.Delete(fn);

            // Done:
            return 1;
        }
    }
}