Replies: 3 comments
-
|
Hi, |
Beta Was this translation helpful? Give feedback.
-
|
We had the same requirement, and ended up forking the PdfSharp version to allow this. To ease things for users, would it be possible to either:
Regards, Arnaud |
Beta Was this translation helpful? Give feedback.
-
|
I'd like to also have this be supported. We would like to have the ability to use my own metadata entirely since we need to support PDF/UA which is not really posssible with PDFSharp right now. To be able to use our own metadata we have resorted to some byte manipulation but we would be happy to send a PR to address this if the team is open to it. In case someone is interested here is what we are doing. After saving the pdf to a /// <summary>
/// Handles XMP metadata injection for PDF/UA-1 compliance.
/// </summary>
public static class Metadata
{
public static byte[] ReplaceMetadataBytes(byte[] fileData, string title, string producer)
{
var template = LoadMetadataTemplate();
var targetXml = template
.Replace("$$TITLE$$", EncodeForXml(title))
.Replace("$$PRODUCER$$", EncodeForXml(producer));
byte[] startTag = Encoding.UTF8.GetBytes("<?xpacket begin=");
byte[] endTag = Encoding.UTF8.GetBytes("<?xpacket end=\"w\"?>");
// Locate the metadata block
int startIndex = FindBytes(fileData, startTag);
int endIndex = FindBytes(fileData, endTag);
if (startIndex != -1 && endIndex != -1)
{
// Determine total available space in the file
int originalBlockLength = (endIndex + endTag.Length) - startIndex;
byte[] newXmlBytes = Encoding.UTF8.GetBytes(targetXml);
// Ensure we fit
if (newXmlBytes.Length <= originalBlockLength)
{
// A. Overwrite with your XML
Array.Copy(newXmlBytes, 0, fileData, startIndex, newXmlBytes.Length);
// B. Fill the remaining space with blank spaces (Padding)
// This keeps the PDF valid by preserving the byte count.
int paddingStart = startIndex + newXmlBytes.Length;
int paddingLength = originalBlockLength - newXmlBytes.Length;
for (int i = 0; i < paddingLength; i++)
{
fileData[paddingStart + i] = (byte)' ';
}
}
}
return fileData;
}
/// <summary>
/// Encodes non-ASCII characters as XML numeric character references.
/// </summary>
private static string EncodeNonAscii(string text)
{
var sb = new StringBuilder();
foreach (var c in text)
{
if (c > 127)
{
sb.Append($"&#x{(int)c:X};");
}
else
{
sb.Append(c);
}
}
return sb.ToString();
}
/// <summary>
/// Encodes text for safe XML inclusion.
/// </summary>
private static string EncodeForXml(string text)
{
var result = text
.Replace("&", "&")
.Replace("<", "<")
.Replace(">", ">")
.Replace("\"", """)
.Replace("'", "'");
return EncodeNonAscii(result);
}
/// <summary>
/// Loads the XMP metadata template from embedded resources.
/// </summary>
private static string LoadMetadataTemplate()
{
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "metadata_template.xml";
using var stream = assembly.GetManifestResourceStream(resourceName);
if (stream == null)
{
throw new InvalidOperationException($"Embedded resource '{resourceName}' not found.");
}
using var reader = new StreamReader(stream);
return reader.ReadToEnd();
}
private static int FindBytes(byte[] haystack, byte[] needle)
{
for (int i = 0; i <= haystack.Length - needle.Length; i++)
{
bool match = true;
for (int j = 0; j < needle.Length; j++)
{
if (haystack[i + j] != needle[j])
{
match = false;
break;
}
}
if (match)
{
return i;
}
}
return -1;
}
} |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Hello,
I would like to remove or at least change the producer in PDF generation for security reasons.
Is there a possibility to do this? The property PdfDocumentRenderer.PdfDocument.Info.Producer is readonly.
Regards
Karl
Beta Was this translation helpful? Give feedback.
All reactions