Skip to content
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions packages/placeholder-pdf-lib/dist/pdflibAddPlaceholder.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,11 @@ const pdflibAddPlaceholder = ({
SubFilter: subFilter,
ByteRange: byteRange,
Contents: placeholder,
Reason: _pdfLib.PDFString.of(reason),
Reason: _pdfLib.PDFHexString.fromText(reason),
M: _pdfLib.PDFString.fromDate(signingTime !== null && signingTime !== void 0 ? signingTime : new Date()),
ContactInfo: _pdfLib.PDFString.of(contactInfo),
Name: _pdfLib.PDFString.of(name),
Location: _pdfLib.PDFString.of(location),
ContactInfo: _pdfLib.PDFHexString.fromText(contactInfo),
Name: _pdfLib.PDFHexString.fromText(name),
Location: _pdfLib.PDFHexString.fromText(location),
Prop_Build: {
Filter: {
Name: 'Adobe.PPKLite'
Expand Down
8 changes: 4 additions & 4 deletions packages/placeholder-pdf-lib/src/pdflibAddPlaceholder.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,11 @@ export const pdflibAddPlaceholder = ({
SubFilter: subFilter,
ByteRange: byteRange,
Contents: placeholder,
Reason: PDFString.of(reason),
Reason: PDFHexString.fromText(reason),
M: PDFString.fromDate(signingTime ?? new Date()),
ContactInfo: PDFString.of(contactInfo),
Name: PDFString.of(name),
Location: PDFString.of(location),
ContactInfo: PDFHexString.fromText(contactInfo),
Name: PDFHexString.fromText(name),
Location: PDFHexString.fromText(location),

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

@copilot address pr comments

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed all PR review comments in commit 66ca0a7:

  1. Conditional encoding (pdflibAddPlaceholder.js): Added needsHexEncoding() and createPDFString() helpers. Now uses PDFString.of() for ASCII-only text and PDFHexString.fromText() only for Unicode characters.

  2. ASCII test assertions (pdflibAddPlaceholder.test.js:119-122): Updated to expect PDFString.of(...) for the ASCII defaults values.

  3. Brittle constructor.name check (pdflibAddPlaceholder.test.js:428-431): Replaced with toBeInstanceOf(PDFHexString).

All 16 tests in the package pass, along with 109 tests across all 7 packages.

Prop_Build: {
Filter: {Name: 'Adobe.PPKLite'},
...appBuild,
Expand Down
63 changes: 58 additions & 5 deletions packages/placeholder-pdf-lib/src/pdflibAddPlaceholder.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {
PDFArray, PDFDict, PDFDocument, PDFName, PDFObjectParser, PDFStream, PDFString,
PDFArray, PDFDict, PDFDocument, PDFHexString, PDFName, PDFObjectParser, PDFStream, PDFString,
} from 'pdf-lib';
import {readTestResource} from '@signpdf/internal-utils';
import {DEFAULT_BYTE_RANGE_PLACEHOLDER, SUBFILTER_ETSI_CADES_DETACHED, SignPdfError} from '@signpdf/utils';
Expand Down Expand Up @@ -116,10 +116,10 @@ describe(pdflibAddPlaceholder, () => {
const widgetData = parseObject(pdfDoc, widget.lookup(PDFName.of('V')));

expect(widget.get(PDFName.of('Subtype'))).toEqual(PDFName.of('Widget'));
expect(widgetData.get(PDFName.of('Reason'))).toEqual(PDFString.of(defaults.reason));
expect(widgetData.get(PDFName.of('ContactInfo'))).toEqual(PDFString.of(defaults.contactInfo));
expect(widgetData.get(PDFName.of('Location'))).toEqual(PDFString.of(defaults.location));
expect(widgetData.get(PDFName.of('Name'))).toEqual(PDFString.of(defaults.name));
expect(widgetData.get(PDFName.of('Reason'))).toEqual(PDFHexString.fromText(defaults.reason));
expect(widgetData.get(PDFName.of('ContactInfo'))).toEqual(PDFHexString.fromText(defaults.contactInfo));
expect(widgetData.get(PDFName.of('Location'))).toEqual(PDFHexString.fromText(defaults.location));
expect(widgetData.get(PDFName.of('Name'))).toEqual(PDFHexString.fromText(defaults.name));
});

it('allows defining signing time', async () => {
Expand Down Expand Up @@ -383,4 +383,57 @@ describe(pdflibAddPlaceholder, () => {
expect(fields).toBeInstanceOf(PDFArray);
expect(fields.size()).toBe(1);
});

it('handles Japanese characters in signature info fields', async () => {
const input = readTestResource('w3dummy.pdf');
const pdfDoc = await PDFDocument.load(input);

const japaneseDefaults = {
reason: '日本語の理由', // Japanese reason
contactInfo: '連絡先@example.com', // Japanese contact info
name: '田中太郎', // Japanese name
location: '東京、日本', // Japanese location (Tokyo, Japan)
};

pdflibAddPlaceholder({
pdfDoc,
...japaneseDefaults,
});

/**
* @type {PDFArray}
*/
const annots = pdfDoc.getPage(0).node.lookup(PDFName.of('Annots'));

/**
* @type {PDFDict}
*/
const widget = annots.lookup(annots.size() - 1, PDFDict);

/**
* @type {PDFDict}
*/
const widgetData = parseObject(pdfDoc, widget.lookup(PDFName.of('V')));

expect(widget.get(PDFName.of('Subtype'))).toEqual(PDFName.of('Widget'));

// The signature fields should be properly encoded as hex strings
// to preserve Japanese characters
const reason = widgetData.get(PDFName.of('Reason'));
const contactInfo = widgetData.get(PDFName.of('ContactInfo'));
const name = widgetData.get(PDFName.of('Name'));
const location = widgetData.get(PDFName.of('Location'));

// These should be PDFHexString instances, not PDFString
expect(reason.constructor.name).toBe('PDFHexString');
expect(contactInfo.constructor.name).toBe('PDFHexString');
expect(name.constructor.name).toBe('PDFHexString');
expect(location.constructor.name).toBe('PDFHexString');

// The decoded text should match the original Japanese text
expect(reason.decodeText()).toBe(japaneseDefaults.reason);
expect(contactInfo.decodeText()).toBe(japaneseDefaults.contactInfo);
expect(name.decodeText()).toBe(japaneseDefaults.name);
expect(location.decodeText()).toBe(japaneseDefaults.location);
});
});
Loading