Comments (46)
I'm planning to make an example with pdf-lib soon. Just need the time for that. Would be nice if you can wait. I don't have a good snippet that I can paste at the moment and it's too much to explain.
from node-signpdf.
I recently mentioned this here: #37 (comment)
This issue #26 asks the same question.
I'm planning to give an example in the coming days on how this can be done with pdfkit. Not planning on the feature currently for the plain version. I'll get back to this (hopefully) this week.
from node-signpdf.
Thanks for the quick response @vbuch and apologies for raising a duplicate ticket.
However, the referenced issues (#26 and #37 ) does not clearly state how to add the visible widget to show the signature. As you have mentioned, may be this feature will be added in the pdfkit version, and not in the plain version.
Unfortunately we need the same in plain version only. Any clue how to do that?
from node-signpdf.
Hi @SnigBhaumik , have you been able to solve this issue? In the /helpers/plainAddPlaceholder/index.js
code, each one who signs a pdf uses the /helpers/pdfkitAddPlaceholder.js
file to capture a widget and the form and add it as an annotation to the pdf. However, I do not understand how a text should be sent so that it appears visible and a position in the pdf. Do you have any idea how to do it?
Thank you!
from node-signpdf.
I recently stumbled upon pdf-lib. Check it out. Seems promising. Allows editing pdfs.
from node-signpdf.
I am working with the dependency you mention, but when making a second signature with a visible mark, everything is damaged, the signatures disappear, the structure of the pdf must be damaging. That's why I better tried to add the widget since yesterday, but I still can't. The pdf-lib dependency is useful to me before signing, once I do it no longer allows me to edit and re-sign.
from node-signpdf.
If I am not mistaken, in the file src/helpers/plainAddPlaceholder/index.js
on line 34 a constant pdfKitMock
is generated where the widget should be added, the truth does not yet understand what form the widget should have and in what part of the constant, because then on line 85, the createBufferPageWithAnnotation
function is called which receives the widget by parameter and is added as an annotation to the PDF. You know what is the form in which it opens and in what part of the constant pdfKitMock
?
Thanks for your help.
from node-signpdf.
Of course, I have already made an example with pdf-lib
and if you want I can fork with a new test for signing with a note, for this I use the drawText
function like this: pages[0].drawText (textForPDF, drawOptions)
, where:
page[0]
: This is the first page of the PDF, this variable is chosen with thegetPages()
function.textForPDF
: The text to be inserted.drawOptions
: The text options you have to insert in object format.
But I fall into the problem that by signing a second time, after adding the text and signing; The pdf does not recognize the signatures, I think it somehow damages the pdf format.
from node-signpdf.
The best would be to talk with snippets, so, please create fork and include some test that breaks. You are combining two features: drawing on top of a pdf and incremental updates (for signing). Not really sure if pdf-lib supports incremental updates. Haven't had the chance to work with it.
from node-signpdf.
Ook, I am already working on this, what I have identified is that an error is jumping in your code, right in the file /src/helpers/plainAddPlaceholder/readRefTable.test
, well it's just an observation!
I hope to upload this test tomorrow.
from node-signpdf.
I have made a pull request where I tell you about the problem we were dealing with here. If you can check it please!
from node-signpdf.
I played with your code just a bit. I think you are making a fundamental mistake. You are trying to add the graphic/text with pdf-lib and then use plainAddPlaceholder
. If I was working with pdf-lib, I would've definetely find a way to add the placeholder with it instead of relying on the plain...
function. It would make my code cleaner. I will try to implement that as soon as I have the time for it. But if you already do, please give it a try. See what's being done in the pdfkit helper. What I will do is create the same thing with pdf-lib. Once you have the placeholder in place, the signing code will probably just work as it does not go through all the details.
from node-signpdf.
You're right, reviewing a little I found this, I hope to implement it, even though I still don't understand it very well, I'm going to try! If I finish it I upload it! Thanks for your help!
from node-signpdf.
Nice find! Commented there. Hopding/pdf-lib#39 (comment)
from node-signpdf.
I'm planning to make an example with pdf-lib soon. Just need the time for that. Would be nice if you can wait. I don't have a good snippet that I can paste at the moment and it's too much to explain.
Sure @vbuch , will eagerly wait for your example with pdf-lib
Meanwhile, trying our own. Seems pdf-lib might be a better choice than pdfkit, because the later does not support opening and editing existing pdfs.
from node-signpdf.
Nice find! Commented there. Hopding/pdf-lib#39 (comment)
2nd that @therpobinski, nice find. Will try to work on this in parallel. Please keep us posted on any progress!
from node-signpdf.
Excellent, so what they propose to me is to create a new file in the helpers
called pdflibAddPlaceholder
similar to the existing pdfAddPlaceholder
but with the pdf-lib
library and add the similar placeholder as did @Hopding .. I am in the right thing right?
from node-signpdf.
Excellent, so what they propose to me is to create a new file in the
helpers
calledpdflibAddPlaceholder
similar to the existingpdfAddPlaceholder
but with thepdf-lib
library and add the similar placeholder as did @Hopding .. I am in the right thing right?
Yes, agree with the approach @therpobinski. Am trying to do the same thing. Let us share each other's works and also wait for documentation/example code from @vbuch
from node-signpdf.
Ready, I made a breakthrough.
But I have 3 problems for which I have not been able to advance.
I have noticed that the example in this issue: How to obtain / configure Annot or Widget from pdf, is very old, most of the functions no longer exist, so I took care to investigate the pdf-lib
library for Find the functions similar to the previous ones. In the majority I have been able to solve them but in 3 observations no.
I would like you to help me with this so that I can add it to this great library.
The observations are the file src/helpers/pdflibAddPlaceholder.js
.
- The
PDFContentStream
class has aof
function that creates an object with the parameters:PDFDict
and an array ofPDFOperator
, but in the examples I see in the old and new version of the librarypdf-lib
It does not send anyPDFOperator
array, but several parameters withdrawRectangle
,drawText
, etc. - In the previous version of
pdf-lib
there is a classPDFDocument
with a functionregister
, this function no longer exists in the new version and when I looked in the library I found a similar one, which is inPDFContext
, but when called, the same problem occurs, that theregister
function does not exist. I don't know how to solve this, since it's the only one that doesn't work. - Near the end of the document, I am creating a
const widgetDict
, which gets aPDFDict
, has aP
parameter, which I have taken from the example that names first, but this one hasTypeScript
programming, and in that if I'm lost, I don't know how to complete that field.
I mean the previous version to the 0.6
version. Now the most current version is the 1.2.1-Master
, of pdf-lib
.
I think that with those 3 things to solve the pdflibPlaceHolder
would work.
In my last commit is what I have named. here
Can you help me solve this problem please?
from node-signpdf.
I will take a look at the code ASAP. Hopefully this weekend. Sorry to hear the snippetsbare outdated. Maybe the author of pdf-lib will help you if you asked their assistance...? Will get back to you as soon as I have a look.
from node-signpdf.
I'm sorry to bother you again.
I could not resolve these 3 observations, send an email to @Hopding, I have not yet received an answer.
Has anyone of you found any solution?
from node-signpdf.
Sorry for being unreliable and unavailable. I'll try to spend some time on it today.
from node-signpdf.
I found some of the documentation of the migration v1.x.x, I hope it helps, although I had already understood when I saw the code.
I have resolved the inconveniences, but when placing the placeholder, the mark does not appear anywhere.
I still think the mark is invisible
from node-signpdf.
Hi guys, I comment that I have resolved the conflicts we had, but I realize that it does not work in the same way, somehow it is not incorporating signatureDict
, this reference contains the ByteRange
, and when I try to sign it, it is not possible because it does not You can find the ByteRange
.
I feel that everything I've done doesn't work.
Has anyone been able to advance this?
If you wish, you can see my latest progress here.
from node-signpdf.
Ready, finished with all the observations, almost everything was wrong, I had to read the pdf-lib
programming carefully, now there are two observations:
-
When it is to be signed, an error appears that says:
Could not find ByteRange placeholder: /ByteRange [0 /********** /********** /**********]
.
This error occurs because you are specifically searching for a string/ByteRange [0 / ********** / ********** / **********]
, but if you have space, like:/ByteRange [ 0 / ********** / ********** / ********** ]
, It works , which I will implement a Regex for this problem. -
The big problem is that no visible widget has been embedded yet, which makes me think that the
PDFContentStrem
that I use does not work, somehow I have to solve this problem. Does anyone have any ideas to solve this?
With this we would finish everything, to be able to implement it, The last changes are in the last confirmation of the pull request.
from node-signpdf.
Hi, The new placeholder is almost ready, but at the time of signing I have a problem, there is a validation on line 161 of signpdf.js, I do not understand why the variable raw.length
is multiplied by 2.
I am printing the lengths of the variables, both the placeholder : 2581 and the raw.length
: 1592, I see that the placeholder is larger than the raw
, but multiplying it by 2, it happens the error . I think you can help me. @vbuch
Thank you!
from node-signpdf.
The comment above the line you are referring to says it:
// placeholderLength represents the length of the HEXified symbols but we're
// checking the actual lengths.
Since the 0 byte is represented by the 00 hex, you get different numbers in lengths and settings. So if your signature has a raw length of 1592, you would need to set the placeholderLength to 3184 which will match its hexadecimal represenation.
from node-signpdf.
Hi @therpobinski and others, I had also problem with corrupted PDF after signing, but I have used your code from pdflibAddPlaceholder
from PR41 and now first tests looks promising.
I have a fork of node-signpdf
rewritten into TypeScript, and with type-checking I have easily found few minor bugs in your code, maybe it helped. I will try to incorporate your PR into my fork.
from node-signpdf.
Since the 0 byte is represented by the 00 hex, you get different numbers in lengths and settings. So if your signature has a raw length of 1592, you would need to set the placeholderLength to 3184 which will match its hexadecimal represenation.
I understand that part, but I do not understand why when generating the placeholder with the library [pdfkitAddPlaceholder] (
)ContentLength
x2 does not multiply to complete with zeros so as not to have problems with the length of the RAW.But I must multiply x2 mi [ContentLength] ( ) to not have problems with the RAW.
Could you help me with this! Thank you. @vbuch
from node-signpdf.
Hi @therpobinski and others, I had also problem with corrupted PDF after signing, but I have used your code from
pdflibAddPlaceholder
from PR41 and now first tests looks promising.I have a fork of
node-signpdf
rewritten into TypeScript, and with type-checking I have easily found few minor bugs in your code, maybe it helped. I will try to incorporate your PR into my fork.
Excellent, do not forget to work since the last commit, because from one commit to another there are many changes.
Luck!
from node-signpdf.
Since the 0 byte is represented by the 00 hex, you get different numbers in lengths and settings. So if your signature has a raw length of 1592, you would need to set the placeholderLength to 3184 which will match its hexadecimal represenation.
I understand that part, but I do not understand why when generating the placeholder with the library [pdfkitAddPlaceholder] (
)
ContentLength
x2 does not multiply to complete with zeros so as not to have problems with the length of the RAW.
But I must multiply x2 mi [ContentLength] (
) to not have problems with the RAW.
Could you help me with this! Thank you. @vbuch
You may be right. It could me more consistent if the twonworked the same way. But actually mybthinking when writing this was that I need tonplace 100 zeros in there. When I first wrote it I didn't realize that this would then be replaced by 50 hexed bytes. So there are two ways of thinking:
- Adding the placeholder is a helper so it should respect the byte size
- (the one applied) The addplaceholder method works with string and not bytes. It sais placeholderLenght and not placeholder bytes.
But either way that should nlt be a problem for you once you understand it. For a next major version we could change that.
In addition: my approach on giving this setting a value is the following:
- I set the value to something big sso i can sign a pdf. 20000 for example.
- I generate a signed document
- I open the output document in a text editor and see the actual size of the signature. That is bytes x 2.
- Use this value instead of 20000 for next generations.
This easens the flow from the user perspective and adds a tiny bit of confusion in the source wwhich on the other hand is well documented.
from node-signpdf.
up, btw, is the new pdf-lib works now? please let me know. Thank you :)
from node-signpdf.
Hi @therpobinski
Thanks for the 'pdflibAddPlaceholder' implementation.
any update from your side?
i am still getting error "Could not find ByteRange placeholder: /ByteRange [ 0 / ********** / ********** / ********** ]" with the latest code from your repo, i guess you are still working on it.
when i analyzed the genated pdf file after calling function 'pdflibAddPlaceholder'
pdflibAddPlaceholder({
pdfBuffer,
infoSignature
})
it is not appending the /Sig or /Annot or /AcroForm objects.
I also checked the final file data directly in pdflibAddPlaceholder, result are same.
Not sure if i am missing anything.
from node-signpdf.
The error you say should no longer appear if you use the library that I haven't finished yet.
Are you sure you are using this latest version?
This is the version you should work with.
I couldn't finish, since I've been busy, I hope to finish it this week.
from node-signpdf.
I'm done, the last changes are in the develop branch, I have a doubt and I think that @vbuch can clarify us, when you open the PDF, in the signatures panel it doesn't show the signer's information.
This is file
from node-signpdf.
@therpobinski yes I was using the latest code from your branch(develop was default branch).
After i imported signer from your code (signpdf.js)(earlier i was importing from 'node-signpdf'), now 'plainAddPlaceholder' works with the PDF exported from pdf-lib (v 1.7), so that solved my issue.
maybe i messed my reference somewhere while I was copying codes from different sources. however i am good for now. when you complete your version I will try that and use it 👍
from node-signpdf.
hey @achieverprince , can you post your code in here, to share? Thanks if you can.
from node-signpdf.
Forgive me for my unstructured code, just a POC
var file = req.file; //A png file with signature received
const existingPdfBytes = fs.readFileSync(appRoot+'/sample_pdf/authorization_letter.pdf');
let signatureImage = fs.readFileSync(file.path);
var typedPdfByteArray = Uint8Array.from(existingPdfBytes);
const pdfDoc = PDFDocument.load(typedPdfByteArray,{ ignoreEncryption: true })
.then((pdfDoc) => {
const pages = pdfDoc.getPages()
// Embed the PNG image bytes
const pngImage = pdfDoc.embedPng(signatureImage).then((pdfImage)=>{
pages[0].drawImage(pdfImage, {
x: 370,
y: 100,
width: 150,
height: 75,
});
let pdfBuffer = pdfDoc.save({
useObjectStreams : false,
objectsPerTick: 150
}).then(value => {
const p12Buffer = fs.readFileSync(appRoot+'/certificate/certificate_test.p12');
fs.writeFileSync(appRoot+'/sample_pdf/tempSignatureFile.pdf',new Buffer.from(value));
// i could just use 'value' here, instead of reading the file again
//did this to debug the files generated
let pdfBuffer = fs.readFileSync(appRoot+'/sample_pdf/tempSignatureFile.pdf');
pdfBuffer = fs.readFileSync(appRoot+'/sample_pdf/tempSignatureFile.pdf');
pdfBuffer = plainAddPlaceholder({
pdfBuffer,
reason: 'I have reviewed it.',
signatureLength: p12Buffer.length,
});
console.log(pdfBuffer.toString('utf8'));
pdfBuffer = signer.sign(pdfBuffer, p12Buffer,{ passphrase : '123456'});
var savedFileName = 'output_signed_pdf_'+new Date().getTime()+'.pdf';
var savedFilePath = appRoot + '/sample_pdf/'+savedFileName;
fs.writeFileSync(savedFilePath, pdfBuffer);
res.send({fileName: savedFileName});
/* //Old code since pdflibAddPlaceholder wasnt working / plainAddPlaceholder started working with latest library code
const infoSignature = {
reason: 'SwiftDocuSign',
contactInfo: '[email protected]',
name: 'Jeba Prince',
location: 'SwiftDocuSign',
}
pdfBuffer = pdflibAddPlaceholder({
pdfBuffer,
infoSignature
}).then(bufferTemp => {
console.log(bufferTemp.toString('utf8'));
pdfBuffer = signer.sign(bufferTemp, p12Buffer,{ passphrase : 'WeLove9SA'});
fs.writeFileSync(appRoot + '/sample_pdf/demo.pdf', pdfBuffer);
res.send({success:true});
})*/
});
});
});
from node-signpdf.
@therpobinski yes I was using the latest code from your branch(develop was default branch).
After i imported signer from your code (signpdf.js)(earlier i was importing from 'node-signpdf'), now 'plainAddPlaceholder' works with the PDF exported from pdf-lib (v 1.7), so that solved my issue.
maybe i messed my reference somewhere while I was copying codes from different sources. however i am good for now. when you complete your version I will try that and use it +1
The idea is that if they can contribute to correcting the only problem we have, it would be a success.
I have finished the development, but when applying the placeholder
I do not understand why when opening the pdf, in the signatures panel, the signer's information does not appear.
Does anyone have any idea of the problem?
@vbuch Do you know why that happens?
from node-signpdf.
ready, finish the library, it works great! Now I wish I could make several signed ones, since this is not yet implemented. Anyone who can help me with that?
@vizicsaba89 I know you implemented this, could you give me a little guide on how to do it?
I understand that only one Acroform
should be modified in the same way / Type/Page/Parent
. Can you give me an idea about it?
from node-signpdf.
@therpobinski
So now your modification adds a visible signature placeholder in PDF, and you are still having issues signing this PDF am i correct?
If you can attach your output pdf it would help to debug
from node-signpdf.
Hi guys, I have progressed on this, I have a problem signing a second time.
Here I commented on the problem, I think that @vbuch can give me an idea of why this problem occurs.
I look forward to your help in culminating with this problem.
Thanks!
from node-signpdf.
If i remember correctly, in my version i had to add an Annotation Apparance object in order to show the signature. I dont have much time to rewrite the current code, but i can share the code snipped from my version, maybe this can help(this should be implemented in pdfkitAddPlaceHolder.js):
import { UserInformation } from '../model/user-information'
import { DEFAULT_BYTE_RANGE_PLACEHOLDER, DEFAULT_SIGNATURE_LENGTH } from './const'
import fs from 'fs'
import PDFKitReferenceMock from './pdf-kit-reference-mock'
import PNG from 'png-js'
import zlib from 'zlib';
const specialCharacters = ['á', 'Á', 'é', 'É', 'í', 'Í', 'ó', 'Ó', 'ö', 'Ö', 'ő', 'Ő', 'ú', 'Ú', 'ű', 'Ű']
const MARKERS = [
0xffc0,
0xffc1,
0xffc2,
0xffc3,
0xffc5,
0xffc6,
0xffc7,
0xffc8,
0xffc9,
0xffca,
0xffcb,
0xffcc,
0xffcd,
0xffce,
0xffcf
];
const COLOR_SPACE_MAP = {
1: 'DeviceGray',
3: 'DeviceRGB',
4: 'DeviceCMYK'
};
const pdfkitAddPlaceholder = ({
pdf,
pdfBuffer,
reason,
signatureLength = DEFAULT_SIGNATURE_LENGTH,
byteRangePlaceholder = DEFAULT_BYTE_RANGE_PLACEHOLDER,
userInformation,
}: {
pdf: any
pdfBuffer: Buffer
reason: string
userInformation: UserInformation
signatureLength?: number
byteRangePlaceholder?: string
}) => {
const acroFormPosition = pdfBuffer.lastIndexOf('/Type /AcroForm')
const isAcroFormExists = acroFormPosition !== -1
let acroFormId
let fieldIds: PDFKitReferenceMock[] = []
if (isAcroFormExists) {
const acroForm = getAcroForm(pdfBuffer, acroFormPosition)
acroFormId = getAcroFormId(acroForm)
fieldIds = getFieldIds(acroForm)
}
const FONT = getFont(pdf, 'Helvetica')
const ZAF = getFont(pdf, 'ZapfDingbats')
const APFONT = getFont(pdf, 'Helvetica')
const IMG = getImage(userInformation.imagePath, pdf)
const AP = getAnnotationApparance(pdf, IMG, APFONT, userInformation)
const SIGNATURE = getSignature(pdf, byteRangePlaceholder, signatureLength, reason, userInformation)
const WIDGET = getWidget(pdf, fieldIds, SIGNATURE, AP)
const ACROFORM = getAcroform(pdf, fieldIds, WIDGET, FONT, ZAF, acroFormId)
return {
signature: SIGNATURE,
form: ACROFORM,
widget: WIDGET,
}
}
const getImage = (imagePath: string, pdf) => {
let img
const data = fs.readFileSync(imagePath)
if (data[0] === 0xff && data[1] === 0xd8) {
img = getJpgImage(pdf, data)
} else if (data[0] === 0x89 && data.toString('ascii', 1, 4) === 'PNG') {
img = getPngImage(pdf, data)
} else {
throw new Error('Unknown image format.');
}
return img
}
const getAcroform = (pdf, fieldIds, WIDGET, FONT, ZAF, acroFormId) => {
return pdf.ref(
{
Type: 'AcroForm',
SigFlags: 3,
Fields: [...fieldIds, WIDGET],
DR: `<</Font\n<</Helvetica ${FONT.index} 0 R/ZapfDingbats ${ZAF.index} 0 R>>\n>>`,
},
acroFormId,
)
}
const getWidget = (pdf, fieldIds, signature, AP) => {
const signatureBaseName = 'Signature'
const signatureLeftOffset = fieldIds.length * 125
const signatureBottomOffset = 5
return pdf.ref({
Type: 'Annot',
Subtype: 'Widget',
FT: 'Sig',
Rect: [signatureLeftOffset, 0, signatureLeftOffset + 90, signatureBottomOffset + 60],
V: signature,
T: new String(signatureBaseName + (fieldIds.length + 1)), // eslint-disable-line no-new-wrappers
F: 4,
AP: `<</N ${AP.index} 0 R>>`,
P: pdf.page.dictionary, // eslint-disable-line no-underscore-dangle
DA: new String('/Helvetica 0 Tf 0 g'), // eslint-disable-line no-new-wrappers
})
}
const getAnnotationApparance = (pdf, IMG, APFONT, userInformation) => {
return pdf.ref({
CropBox: [0, 0, 197, 70],
Type: 'XObject',
FormType: 1,
BBox: [-10, 10, 197.0, 70.0],
Resources: `<</XObject <<\n/Img${IMG.index} ${IMG.index} 0 R\n>>\n/Font <<\n/f1 ${APFONT.index} 0 R\n>>\n>>`,
MediaBox: [0, 0, 197, 70],
Subtype: 'Form',
}, null, getStream(userInformation, IMG.index))
}
const getStream = (userInformation, imgIndex) => {
return getConvertedText(`
1.0 1.0 1.0 rg
0.0 0.0 0.0 RG
q
q
200 0 0 50 0 10 cm
/Img${imgIndex} Do
Q
0 0 0 rg
BT
0 Tr
/f1 10.0 Tf
1.4 0 0 1 20 45.97412 Tm
(Aláírta: ${userInformation.commonName}) Tj
ET
BT
0 Tr
/f1 10.0 Tf
1.4 0 0 1 20 33.56006 Tm
(${new Date().toISOString().slice(0,10)}) Tj
ET
Q`
)
}
const getJpgImage = (pdf: any, data: any) => {
if (data.readUInt16BE(0) !== 0xffd8) {
throw 'SOI not found in JPEG'
}
let pos = 2
let marker
while (pos < data.length) {
marker = data.readUInt16BE(pos);
pos += 2
if (MARKERS.includes(marker)) {
break
}
pos += data.readUInt16BE(pos)
}
if (!MARKERS.includes(marker)) {
throw 'Invalid JPEG.'
}
pos += 2
const bits = data[pos++]
const height = data.readUInt16BE(pos)
pos += 2
const width =data.readUInt16BE(pos)
pos += 2
const channels = data[pos++]
const colorSpace = COLOR_SPACE_MAP[channels]
const baseJpgData = {
Type: 'XObject',
Subtype: 'Image',
BitsPerComponent: bits,
Width: width,
Height: height,
ColorSpace: colorSpace,
Filter: 'DCTDecode',
}
if (colorSpace === 'DeviceCMYK') {
baseJpgData['Decode'] = [1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0]
}
const image = pdf.ref(baseJpgData, null, data);
return image
}
const getPngImage = (pdf: any, data: any) => {
const image = new PNG(data)
const hasAlphaChannel = image.hasAlphaChannel
const pngBaseData = {
Type: 'XObject',
Subtype: 'Image',
BitsPerComponent: hasAlphaChannel ? 8 : image.bits,
Width: image.width,
Height: image.height,
Filter: 'FlateDecode'
}
if (!hasAlphaChannel) {
const params = pdf.ref({
Predictor: 15,
Colors: image.colors,
BitsPerComponent: image.bits,
Columns: image.width
});
pngBaseData['DecodeParms'] = params
}
if (image.palette.length === 0) {
pngBaseData['ColorSpace'] = image.colorSpace
} else {
const palette = pdf.ref({
stream: new Buffer(image.palette)
})
pngBaseData['ColorSpace'] = ['Indexed', 'DeviceRGB', image.palette.length / 3 - 1, palette]
}
if (image.transparency.grayscale != null) {
const val = image.transparency.grayscale
pngBaseData['Mask'] = [val, val]
} else if (image.transparency.rgb) {
const { rgb } =image.transparency
const mask: any[] = []
for (let x of rgb) {
mask.push(x, x)
}
pngBaseData['Mask'] = mask
} else if (image.transparency.indexed) {
loadIndexedAlphaChannel(image)
} else if (hasAlphaChannel) {
splitAlphaChannel(pdf)
const sMask = getSmask(pdf, image)
pngBaseData['Mask'] = sMask
}
const pngImage = pdf.ref(pngBaseData, null, image.imgData)
return pngImage
}
const loadIndexedAlphaChannel = (image) => {
const transparency = image.transparency.indexed;
return image.decodePixels(pixels => {
const alphaChannel = new Buffer(image.width * image.height);
let i = 0;
for (let j = 0, end = pixels.length; j < end; j++) {
alphaChannel[i++] = transparency[pixels[j]];
}
image.alphaChannel = zlib.deflateSync(alphaChannel);
});
}
const splitAlphaChannel = (image) => {
image.decodePixels(pixels => {
let a, p
const colorCount = image.colors
const pixelCount = image.width * image.height
const imgData = new Buffer(pixelCount * colorCount)
const alphaChannel = new Buffer(pixelCount)
let i = (p = a = 0)
const len = pixels.length
const skipByteCount = image.bits === 16 ? 1 : 0
while (i < len) {
for (let colorIndex = 0; colorIndex < colorCount; colorIndex++) {
imgData[p++] = pixels[i++]
i += skipByteCount
}
alphaChannel[a++] = pixels[i++]
i += skipByteCount
}
image.imgData = zlib.deflateSync(imgData)
image.alphaChannel = zlib.deflateSync(alphaChannel)
})
}
const getSmask = (pdf, image) => {
let sMask
if (image.hasAlphaChannel) {
sMask = pdf.ref({
Type: 'XObject',
Subtype: 'Image',
Height: image.height,
Width: image.width,
BitsPerComponent: 8,
Filter: 'FlateDecode',
ColorSpace: 'DeviceGray',
Decode: [0, 1],
stream: image.alphaChannel
})
}
return sMask
}
const getFieldIds = acroForm => {
let fieldIds: PDFKitReferenceMock[] = []
const acroFormFields = acroForm.slice(acroForm.indexOf('/Fields [') + 9, acroForm.indexOf(']'))
fieldIds = acroFormFields
.split(' ')
.filter((_element, index) => index % 3 === 0)
.map(fieldId => new PDFKitReferenceMock(fieldId))
return fieldIds
}
const getAcroForm = (pdfBuffer, acroFormPosition) => {
const pdfSlice = pdfBuffer.slice(acroFormPosition - 12)
const acroForm = pdfSlice.slice(0, pdfSlice.indexOf('endobj')).toString()
return acroForm
}
const getAcroFormId = acroForm => {
const acroFormFirsRow = acroForm.split('\n')[0]
const acroFormId = parseInt(acroFormFirsRow.split(' ')[0])
return acroFormId
}
const getFont = (pdf, baseFont) => {
return pdf.ref({
Type: 'Font',
BaseFont: baseFont,
Encoding: 'WinAnsiEncoding',
Subtype: 'Type1',
})
}
const getSignature = (
pdf: any,
byteRangePlaceholder: string,
signatureLength: number,
reason: string,
userInformation: any
) => {
return pdf.ref({
Type: 'Sig',
Filter: 'Adobe.PPKLite',
SubFilter: 'adbe.pkcs7.detached',
ByteRange: [0, byteRangePlaceholder, byteRangePlaceholder, byteRangePlaceholder],
Contents: Buffer.from(String.fromCharCode(0).repeat(signatureLength)),
Reason: new String(reason),
M: new Date(),
ContactInfo: new String(`${userInformation.emailAddress}`),
Name: new String(`${userInformation.commonName}`),
Location: new String('Hungary, HU'),
})
}
const getConvertedText = (text: string) => {
return text.split('').map(character => {
return specialCharacters.includes(character) ? getOctalCodeFromCharacter(character) : character
}).join('')
}
const getOctalCodeFromCharacter = (character: string) => {
return '\\' + character.charCodeAt(0).toString(8)
}
export default pdfkitAddPlaceholder
In order to show some image to you have to move stream handling from pdfobject.js to index.js as the following snippet shows:
import { UserInformation } from '../model/user-information'
import { DEFAULT_SIGNATURE_LENGTH } from './const'
import createBufferPageWithAnnotation from './create-buffer-page-with-annotation'
import createBufferRootWithAcroform from './create-buffer-root-with-acrofrom'
import createBufferTrailer from './create-buffer-trailer'
import getIndexFromRef from './get-index-from-ref'
import getPageRef from './get-page-ref'
import pdfkitAddPlaceholder from './pdf-kit-add-placeholder'
import PDFKitReferenceMock from './pdf-kit-reference-mock'
import PDFObject from './pdfkit/pdfobject.js'
import readPdf from './read-pdf'
import removeTrailingNewLine from './remove-trailing-new-line'
const plainAddPlaceholder = (
pdfBuffer: Buffer,
userInformation: UserInformation,
{ reason, signatureLength = DEFAULT_SIGNATURE_LENGTH }: { reason: any; signatureLength: number },
) => {
let pdf = removeTrailingNewLine(pdfBuffer)
const info = readPdf(pdf)
const pageRef = getPageRef(pdf, info)
const pageIndex = getIndexFromRef(info.xref, pageRef)
const addedReferences = new Map()
const pdfKitMock = {
ref: (input: any, additionalIndex: number, stream: any) => {
info.xref.maxIndex += 1
const index = additionalIndex != null ? additionalIndex : info.xref.maxIndex
addedReferences.set(index, pdf.length + 1)
pdf = getAssembledPdf(pdf, index, input, stream)
return new PDFKitReferenceMock(info.xref.maxIndex)
},
page: {
dictionary: new PDFKitReferenceMock(pageIndex, {
data: {
Annots: [],
},
}),
},
_root: {
data: {},
},
}
const { form, widget } = pdfkitAddPlaceholder({
pdf: pdfKitMock,
pdfBuffer,
reason,
signatureLength,
userInformation,
})
if (!isContainBufferRootWithAcrofrom(pdfBuffer)) {
const rootIndex = getIndexFromRef(info.xref, info.rootRef)
addedReferences.set(rootIndex, pdf.length + 1)
pdf = Buffer.concat([pdf, Buffer.from('\n'), createBufferRootWithAcroform(info, form)])
}
addedReferences.set(pageIndex, pdf.length + 1)
pdf = Buffer.concat([pdf, Buffer.from('\n'), createBufferPageWithAnnotation(pdf, info, pageRef, widget)])
pdf = Buffer.concat([pdf, Buffer.from('\n'), createBufferTrailer(pdf, info, addedReferences)])
return pdf
}
const getAssembledPdf = (pdf: any, index: any, input: any, stream: any): Buffer => {
let finalPdf = pdf
finalPdf = Buffer.concat([
finalPdf,
Buffer.from('\n'),
Buffer.from(`${index} 0 obj\n`),
Buffer.from(PDFObject.convert(input)),
])
if (stream) {
finalPdf = Buffer.concat([
finalPdf,
Buffer.from('\nstream\n'),
Buffer.from(stream),
Buffer.from('\nendstream'),
]);
}
finalPdf = Buffer.concat([
finalPdf,
Buffer.from('\nendobj\n'),
]);
return finalPdf
}
const isContainBufferRootWithAcrofrom = (pdf: Buffer) => {
const bufferRootWithAcroformRefRegex = new RegExp('\\/AcroForm\\s+(\\d+\\s\\d+\\sR)', 'g')
const match = bufferRootWithAcroformRefRegex.exec(pdf.toString())
return match != null && match[1] != null && match[1] !== ''
}
export default plainAddPlaceholder
from node-signpdf.
Sorry guys but this issue is totally not readable. Tons of pasted code. Not sure what to help with and whom. From reading I get the impression that @therpobinski was close to proposing a PR. I saw a PR from his fork that fails CI. Is #41 related here?
from node-signpdf.
This issue has been automatically marked as stale because it has not had activity in the past 90 days. It will be closed if no further activity occurs. Thank you for your contributions.
from node-signpdf.
Hi guys, I'm sorry I haven't finished this yet. #41 .
I have not finished because first I have to finish a work presented with the current version. But I am having trouble signing some files and I don't know why. I have created a new issue to deal with the topic separately. Once finished, I will continue with the work I was doing with the "pdf-lib" library.
@vbuch , do you think you can help me with this problem, please? After solving this problem, I will continue with the RP that was left unfinished.
from node-signpdf.
Related Issues (20)
- Error when adding a second signature via adobe, if there is already 1 signature via pdf-signer. (the signature byte range is invalid) HOT 1
- Signature is not PAdES compliant and "The signature is not intact!" HOT 6
- Unparsed DER bytes remain after ASN.1 parsing. HOT 2
- Sample code for PAdES LTV? HOT 4
- Elastic HOT 1
- At leats one signature has problems
- How can I verify the signed pdf that is signed using node-signpdf? HOT 1
- Certification Level HOT 1
- plainAddPlaceholder breaks the PDF file with existing annotations HOT 4
- I need put text or image in my signature without change the file structure. If I change, all my oldest signatures will be invalid. It's possible?? HOT 8
- signer-p12 does not have a README HOT 1
- extractSignature is exported although it is an internal util
- Upgrade pdfkit version HOT 5
- Special Words cause issue in signature HOT 7
- '/Fields' is a PDFRef so it cannot be pushed to HOT 1
- Adding extra fields on placeholder HOT 2
- signpdf.sign's Signer and P12Signer type incompatibility
- Node requirement is set to 12. Needs an update
- Add a signature box to the signed pdf HOT 8
- Signer implementation expected using 3.2.3 HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from node-signpdf.