Split down into multiple functions
This commit is contained in:
@@ -13,6 +13,9 @@
|
|||||||
"extensions": ["golang.go"]
|
"extensions": ["golang.go"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"containerEnv": {
|
||||||
|
"TMPDIR": "/workspaces/pdfsign/tmp"
|
||||||
|
},
|
||||||
"forwardPorts": [],
|
"forwardPorts": [],
|
||||||
"postCreateCommand": "go mod download",
|
"postCreateCommand": "go mod download",
|
||||||
"remoteUser": "root"
|
"remoteUser": "root"
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -6,3 +6,4 @@ testfiles/*_signed.pdf
|
|||||||
testfiles/failed/*
|
testfiles/failed/*
|
||||||
pdfsign
|
pdfsign
|
||||||
certs/*
|
certs/*
|
||||||
|
tmp/
|
||||||
|
@@ -8,12 +8,127 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (context *SignContext) createAppearance(rect [4]float64) ([]byte, error) {
|
func (context *SignContext) createAppearance(rect [4]float64) ([]byte, error) {
|
||||||
if len(context.SignData.Signature.Info.Image) > 0 {
|
if len(context.SignData.Appearance.Image) > 0 {
|
||||||
return context.createImageAppearance(rect)
|
return context.createImageAppearance(rect)
|
||||||
}
|
}
|
||||||
return context.createTextAppearance(rect)
|
return context.createTextAppearance(rect)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper functions for PDF resource components
|
||||||
|
|
||||||
|
// writeAppearanceHeader writes the header for the appearance stream.
|
||||||
|
//
|
||||||
|
// Should be closed by writeFormTypeAndLength.
|
||||||
|
func writeAppearanceHeader(buffer *bytes.Buffer, rectWidth, rectHeight float64) {
|
||||||
|
buffer.WriteString("<<\n")
|
||||||
|
buffer.WriteString(" /Type /XObject\n")
|
||||||
|
buffer.WriteString(" /Subtype /Form\n")
|
||||||
|
buffer.WriteString(fmt.Sprintf(" /BBox [0 0 %f %f]\n", rectWidth, rectHeight))
|
||||||
|
buffer.WriteString(" /Matrix [1 0 0 1 0 0]\n") // No scaling or translation
|
||||||
|
}
|
||||||
|
|
||||||
|
func createFontResource(buffer *bytes.Buffer) {
|
||||||
|
buffer.WriteString(" /Font <<\n")
|
||||||
|
buffer.WriteString(" /F1 <<\n")
|
||||||
|
buffer.WriteString(" /Type /Font\n")
|
||||||
|
buffer.WriteString(" /Subtype /Type1\n")
|
||||||
|
buffer.WriteString(" /BaseFont /Times-Roman\n")
|
||||||
|
buffer.WriteString(" >>\n")
|
||||||
|
buffer.WriteString(" >>\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func createImageResource(buffer *bytes.Buffer, imageObjectId uint32) {
|
||||||
|
buffer.WriteString(" /XObject <<\n")
|
||||||
|
buffer.WriteString(fmt.Sprintf(" /Im1 %d 0 R\n", imageObjectId))
|
||||||
|
buffer.WriteString(" >>\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeFormTypeAndLength(buffer *bytes.Buffer, streamLength int) {
|
||||||
|
buffer.WriteString(" /FormType 1\n")
|
||||||
|
buffer.WriteString(fmt.Sprintf(" /Length %d\n", streamLength))
|
||||||
|
buffer.WriteString(">>\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeBufferStream(buffer *bytes.Buffer, stream []byte) {
|
||||||
|
buffer.WriteString("stream\n")
|
||||||
|
buffer.Write(stream)
|
||||||
|
buffer.WriteString("endstream\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (context *SignContext) createImageXObject() ([]byte, error) {
|
||||||
|
imageData := context.SignData.Appearance.Image
|
||||||
|
|
||||||
|
// Read image configuration to get original dimensions
|
||||||
|
img, _, err := image.DecodeConfig(bytes.NewReader(imageData))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to decode image configuration: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use original image dimensions
|
||||||
|
width := float64(img.Width)
|
||||||
|
height := float64(img.Height)
|
||||||
|
|
||||||
|
// Create basic PDF Image XObject
|
||||||
|
var imageObject bytes.Buffer
|
||||||
|
|
||||||
|
imageObject.WriteString("<<\n")
|
||||||
|
imageObject.WriteString(" /Type /XObject\n")
|
||||||
|
imageObject.WriteString(" /Subtype /Image\n")
|
||||||
|
imageObject.WriteString(fmt.Sprintf(" /Width %.0f\n", width))
|
||||||
|
imageObject.WriteString(fmt.Sprintf(" /Height %.0f\n", height))
|
||||||
|
imageObject.WriteString(" /ColorSpace /DeviceRGB\n")
|
||||||
|
imageObject.WriteString(" /BitsPerComponent 8\n")
|
||||||
|
imageObject.WriteString(" /Filter /DCTDecode\n")
|
||||||
|
imageObject.WriteString(fmt.Sprintf(" /Length %d\n", len(imageData)))
|
||||||
|
imageObject.WriteString(">>\n")
|
||||||
|
|
||||||
|
imageObject.WriteString("stream\n")
|
||||||
|
imageObject.Write(imageData)
|
||||||
|
imageObject.WriteString("\nendstream\n")
|
||||||
|
|
||||||
|
return imageObject.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func computeTextSizeAndPosition(text string, rectWidth, rectHeight float64) (float64, float64, float64) {
|
||||||
|
// Calculate font size
|
||||||
|
fontSize := rectHeight * 0.8 // Use most of the height for the font
|
||||||
|
textWidth := float64(len(text)) * fontSize * 0.5 // Approximate text width
|
||||||
|
if textWidth > rectWidth {
|
||||||
|
fontSize = rectWidth / (float64(len(text)) * 0.5) // Adjust font size to fit text within rect width
|
||||||
|
}
|
||||||
|
|
||||||
|
// Center text horizontally and vertically
|
||||||
|
textWidth = float64(len(text)) * fontSize * 0.5
|
||||||
|
textX := (rectWidth - textWidth) / 2
|
||||||
|
if textX < 0 {
|
||||||
|
textX = 0
|
||||||
|
}
|
||||||
|
textY := (rectHeight-fontSize)/2 + fontSize/3 // Approximate vertical centering
|
||||||
|
|
||||||
|
return fontSize, textX, textY
|
||||||
|
}
|
||||||
|
|
||||||
|
func drawText(buffer *bytes.Buffer, text string, fontSize float64, x, y float64) {
|
||||||
|
buffer.WriteString("q\n") // Save graphics state
|
||||||
|
buffer.WriteString("BT\n") // Begin text
|
||||||
|
buffer.WriteString(fmt.Sprintf("/F1 %.2f Tf\n", fontSize)) // Set font and size
|
||||||
|
buffer.WriteString(fmt.Sprintf("%.2f %.2f Td\n", x, y)) // Set text position
|
||||||
|
buffer.WriteString("0.2 0.2 0.6 rg\n") // Set font color to ballpoint-like color (RGB)
|
||||||
|
buffer.WriteString(fmt.Sprintf("%s Tj\n", pdfString(text))) // Show text
|
||||||
|
buffer.WriteString("ET\n") // End text
|
||||||
|
buffer.WriteString("Q\n") // Restore graphics state
|
||||||
|
}
|
||||||
|
|
||||||
|
func drawImage(buffer *bytes.Buffer, rectWidth, rectHeight float64) {
|
||||||
|
// We save state twice on purpose due to the cm operation
|
||||||
|
buffer.WriteString("q\n") // Save graphics state
|
||||||
|
buffer.WriteString("q\n") // Save before image transformation
|
||||||
|
buffer.WriteString(fmt.Sprintf("%.2f 0 0 %.2f 0 0 cm\n", rectWidth, rectHeight))
|
||||||
|
buffer.WriteString("/Im1 Do\n") // Draw image
|
||||||
|
buffer.WriteString("Q\n") // Restore after transformation
|
||||||
|
buffer.WriteString("Q\n") // Restore graphics state
|
||||||
|
}
|
||||||
|
|
||||||
func (context *SignContext) createTextAppearance(rect [4]float64) ([]byte, error) {
|
func (context *SignContext) createTextAppearance(rect [4]float64) ([]byte, error) {
|
||||||
rectWidth := rect[2] - rect[0]
|
rectWidth := rect[2] - rect[0]
|
||||||
rectHeight := rect[3] - rect[1]
|
rectHeight := rect[3] - rect[1]
|
||||||
@@ -22,61 +137,26 @@ func (context *SignContext) createTextAppearance(rect [4]float64) ([]byte, error
|
|||||||
return nil, fmt.Errorf("invalid rectangle dimensions: width %.2f and height %.2f must be greater than 0", rectWidth, rectHeight)
|
return nil, fmt.Errorf("invalid rectangle dimensions: width %.2f and height %.2f must be greater than 0", rectWidth, rectHeight)
|
||||||
}
|
}
|
||||||
|
|
||||||
var appearance_stream_buffer bytes.Buffer
|
|
||||||
|
|
||||||
text := context.SignData.Signature.Info.Name
|
text := context.SignData.Signature.Info.Name
|
||||||
|
|
||||||
// Calculate font size
|
fontSize, textX, textY := computeTextSizeAndPosition(text, rectWidth, rectHeight)
|
||||||
fontSize := rectHeight * 0.8 // Use most of the height for the font
|
|
||||||
textWidth := float64(len(text)) * fontSize * 0.5 // Approximate text width
|
|
||||||
if textWidth > rectWidth {
|
|
||||||
fontSize = rectWidth / (float64(len(text)) * 0.5) // Adjust font size to fit text within rect width
|
|
||||||
}
|
|
||||||
|
|
||||||
appearance_stream_buffer.WriteString("q\n") // Save graphics state
|
var appearance_stream_buffer bytes.Buffer
|
||||||
appearance_stream_buffer.WriteString("BT\n") // Begin text
|
|
||||||
appearance_stream_buffer.WriteString(fmt.Sprintf("/F1 %.2f Tf\n", fontSize)) // Font and size
|
|
||||||
|
|
||||||
// Center text horizontally and vertically
|
drawText(&appearance_stream_buffer, text, fontSize, textX, textY)
|
||||||
textWidth = float64(len(text)) * fontSize * 0.5
|
|
||||||
textX := (rectWidth - textWidth) / 2
|
|
||||||
if textX < 0 {
|
|
||||||
textX = 0
|
|
||||||
}
|
|
||||||
textY := (rectHeight-fontSize)/2 + fontSize/3 // Approximate vertical centering
|
|
||||||
|
|
||||||
appearance_stream_buffer.WriteString(fmt.Sprintf("%.2f %.2f Td\n", textX, textY)) // Position text
|
|
||||||
appearance_stream_buffer.WriteString("0.2 0.2 0.6 rg\n") // Set font color to ballpoint-like color (RGB)
|
|
||||||
appearance_stream_buffer.WriteString(fmt.Sprintf("%s Tj\n", pdfString(text))) // Show text
|
|
||||||
appearance_stream_buffer.WriteString("ET\n") // End text
|
|
||||||
appearance_stream_buffer.WriteString("Q\n") // Restore graphics state
|
|
||||||
|
|
||||||
// Create the appearance XObject
|
// Create the appearance XObject
|
||||||
var appearance_buffer bytes.Buffer
|
var appearance_buffer bytes.Buffer
|
||||||
appearance_buffer.WriteString("<<\n")
|
writeAppearanceHeader(&appearance_buffer, rectWidth, rectHeight)
|
||||||
appearance_buffer.WriteString(" /Type /XObject\n")
|
|
||||||
appearance_buffer.WriteString(" /Subtype /Form\n")
|
|
||||||
appearance_buffer.WriteString(fmt.Sprintf(" /BBox [0 0 %f %f]\n", rectWidth, rectHeight))
|
|
||||||
appearance_buffer.WriteString(" /Matrix [1 0 0 1 0 0]\n") // No scaling or translation
|
|
||||||
|
|
||||||
// Resources dictionary with font
|
// Resources dictionary with font
|
||||||
appearance_buffer.WriteString(" /Resources <<\n")
|
appearance_buffer.WriteString(" /Resources <<\n")
|
||||||
appearance_buffer.WriteString(" /Font <<\n")
|
createFontResource(&appearance_buffer)
|
||||||
appearance_buffer.WriteString(" /F1 <<\n")
|
|
||||||
appearance_buffer.WriteString(" /Type /Font\n")
|
|
||||||
appearance_buffer.WriteString(" /Subtype /Type1\n")
|
|
||||||
appearance_buffer.WriteString(" /BaseFont /Times-Roman\n")
|
|
||||||
appearance_buffer.WriteString(" >>\n")
|
|
||||||
appearance_buffer.WriteString(" >>\n")
|
|
||||||
appearance_buffer.WriteString(" >>\n")
|
appearance_buffer.WriteString(" >>\n")
|
||||||
|
|
||||||
appearance_buffer.WriteString(" /FormType 1\n")
|
writeFormTypeAndLength(&appearance_buffer, appearance_stream_buffer.Len())
|
||||||
appearance_buffer.WriteString(fmt.Sprintf(" /Length %d\n", appearance_stream_buffer.Len()))
|
|
||||||
appearance_buffer.WriteString(">>\n")
|
|
||||||
|
|
||||||
appearance_buffer.WriteString("stream\n")
|
writeBufferStream(&appearance_buffer, appearance_stream_buffer.Bytes())
|
||||||
appearance_buffer.Write(appearance_stream_buffer.Bytes())
|
|
||||||
appearance_buffer.WriteString("endstream\n")
|
|
||||||
|
|
||||||
return appearance_buffer.Bytes(), nil
|
return appearance_buffer.Bytes(), nil
|
||||||
}
|
}
|
||||||
@@ -102,71 +182,20 @@ func (context *SignContext) createImageAppearance(rect [4]float64) ([]byte, erro
|
|||||||
|
|
||||||
var appearance_stream_buffer bytes.Buffer
|
var appearance_stream_buffer bytes.Buffer
|
||||||
|
|
||||||
// We save state twice on purpose due to the cm operation
|
drawImage(&appearance_stream_buffer, rectWidth, rectHeight)
|
||||||
appearance_stream_buffer.WriteString("q\n") // Save graphics state
|
|
||||||
appearance_stream_buffer.WriteString("q\n") // Save before image transformation
|
|
||||||
appearance_stream_buffer.WriteString(fmt.Sprintf("%.2f 0 0 %.2f 0 0 cm\n", rectWidth, rectHeight))
|
|
||||||
appearance_stream_buffer.WriteString("/Im1 Do\n")
|
|
||||||
appearance_stream_buffer.WriteString("Q\n") // Restore after transformation
|
|
||||||
appearance_stream_buffer.WriteString("Q\n") // Restore graphics state
|
|
||||||
|
|
||||||
// Create the appearance XObject
|
// Create the appearance XObject
|
||||||
var appearance_buffer bytes.Buffer
|
var appearance_buffer bytes.Buffer
|
||||||
appearance_buffer.WriteString("<<\n")
|
writeAppearanceHeader(&appearance_buffer, rectWidth, rectHeight)
|
||||||
appearance_buffer.WriteString(" /Type /XObject\n")
|
|
||||||
|
|
||||||
appearance_buffer.WriteString(" /Subtype /Form\n")
|
|
||||||
appearance_buffer.WriteString(fmt.Sprintf(" /BBox [0 0 %f %f]\n", rectWidth, rectHeight))
|
|
||||||
|
|
||||||
// Resources dictionary with XObject
|
// Resources dictionary with XObject
|
||||||
appearance_buffer.WriteString(" /Resources <<\n")
|
appearance_buffer.WriteString(" /Resources <<\n")
|
||||||
|
createImageResource(&appearance_buffer, imageObjectId)
|
||||||
appearance_buffer.WriteString(" /XObject <<\n")
|
|
||||||
appearance_buffer.WriteString(fmt.Sprintf(" /Im1 %d 0 R\n", imageObjectId))
|
|
||||||
appearance_buffer.WriteString(" >>\n")
|
|
||||||
appearance_buffer.WriteString(" >>\n")
|
appearance_buffer.WriteString(" >>\n")
|
||||||
|
|
||||||
appearance_buffer.WriteString(" /FormType 1\n")
|
writeFormTypeAndLength(&appearance_buffer, appearance_stream_buffer.Len())
|
||||||
appearance_buffer.WriteString(fmt.Sprintf(" /Length %d\n", appearance_stream_buffer.Len()))
|
|
||||||
appearance_buffer.WriteString(">>\n")
|
|
||||||
|
|
||||||
appearance_buffer.WriteString("stream\n")
|
writeBufferStream(&appearance_buffer, appearance_stream_buffer.Bytes())
|
||||||
appearance_buffer.Write(appearance_stream_buffer.Bytes())
|
|
||||||
appearance_buffer.WriteString("endstream\n")
|
|
||||||
|
|
||||||
return appearance_buffer.Bytes(), nil
|
return appearance_buffer.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (context *SignContext) createImageXObject() ([]byte, error) {
|
|
||||||
imageData := context.SignData.Signature.Info.Image
|
|
||||||
|
|
||||||
// Read image configuration to get original dimensions
|
|
||||||
img, _, err := image.DecodeConfig(bytes.NewReader(imageData))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to decode image configuration: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use original image dimensions
|
|
||||||
width := float64(img.Width)
|
|
||||||
height := float64(img.Height)
|
|
||||||
|
|
||||||
// Create basic PDF Image XObject
|
|
||||||
var imageObject bytes.Buffer
|
|
||||||
|
|
||||||
imageObject.WriteString("<<\n")
|
|
||||||
imageObject.WriteString(" /Type /XObject\n")
|
|
||||||
imageObject.WriteString(" /Subtype /Image\n")
|
|
||||||
imageObject.WriteString(fmt.Sprintf(" /Width %.0f\n", width))
|
|
||||||
imageObject.WriteString(fmt.Sprintf(" /Height %.0f\n", height))
|
|
||||||
imageObject.WriteString(" /ColorSpace /DeviceRGB\n")
|
|
||||||
imageObject.WriteString(" /BitsPerComponent 8\n")
|
|
||||||
imageObject.WriteString(" /Filter /DCTDecode\n") // JPEG compression
|
|
||||||
imageObject.WriteString(fmt.Sprintf(" /Length %d\n", len(imageData)))
|
|
||||||
imageObject.WriteString(">>\n")
|
|
||||||
|
|
||||||
imageObject.WriteString("stream\n")
|
|
||||||
imageObject.Write(imageData)
|
|
||||||
imageObject.WriteString("\nendstream\n")
|
|
||||||
|
|
||||||
return imageObject.Bytes(), nil
|
|
||||||
}
|
|
||||||
|
@@ -7,7 +7,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -196,35 +195,3 @@ func isASCII(s string) bool {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// CopyFile copies a file from src to dst.
|
|
||||||
// It's a replacement for os.Rename that works across filesystems.
|
|
||||||
func CopyFile(src, dst string) error {
|
|
||||||
// Open the source file
|
|
||||||
srcFile, err := os.Open(src)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to open source file: %w", err)
|
|
||||||
}
|
|
||||||
defer srcFile.Close()
|
|
||||||
|
|
||||||
// Create the destination directory if it doesn't exist
|
|
||||||
dstDir := dst[:strings.LastIndex(dst, "/")]
|
|
||||||
if err := os.MkdirAll(dstDir, 0o755); err != nil {
|
|
||||||
return fmt.Errorf("failed to create destination directory: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the destination file
|
|
||||||
dstFile, err := os.Create(dst)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to create destination file: %w", err)
|
|
||||||
}
|
|
||||||
defer dstFile.Close()
|
|
||||||
|
|
||||||
// Copy the contents
|
|
||||||
_, err = io.Copy(dstFile, srcFile)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to copy file contents: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
@@ -45,12 +45,16 @@ type SignData struct {
|
|||||||
|
|
||||||
// Appearance represents the appearance of the signature
|
// Appearance represents the appearance of the signature
|
||||||
type Appearance struct {
|
type Appearance struct {
|
||||||
Visible bool
|
Visible bool
|
||||||
|
|
||||||
Page uint32
|
Page uint32
|
||||||
LowerLeftX float64
|
LowerLeftX float64
|
||||||
LowerLeftY float64
|
LowerLeftY float64
|
||||||
UpperRightX float64
|
UpperRightX float64
|
||||||
UpperRightY float64
|
UpperRightY float64
|
||||||
|
|
||||||
|
Image []byte // Image data to use as signature appearance
|
||||||
|
ImageAsWatermark bool // If true, the text will be drawn over the image
|
||||||
}
|
}
|
||||||
|
|
||||||
type VisualSignData struct {
|
type VisualSignData struct {
|
||||||
@@ -93,7 +97,6 @@ type SignDataSignatureInfo struct {
|
|||||||
Reason string
|
Reason string
|
||||||
ContactInfo string
|
ContactInfo string
|
||||||
Date time.Time
|
Date time.Time
|
||||||
Image []byte // Image data to use in signature appearance
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type SignContext struct {
|
type SignContext struct {
|
||||||
|
@@ -80,9 +80,9 @@ func verifySignedFile(t *testing.T, tmpfile *os.File, originalFileName string) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("%s: %s", tmpfile.Name(), err.Error())
|
t.Fatalf("%s: %s", tmpfile.Name(), err.Error())
|
||||||
|
|
||||||
destinationPath := "../testfiles/failed/" + originalFileName
|
err2 := os.Rename(tmpfile.Name(), "../testfiles/failed/"+originalFileName)
|
||||||
if copyErr := CopyFile(tmpfile.Name(), destinationPath); copyErr != nil {
|
if err2 != nil {
|
||||||
t.Errorf("Failed to copy failed test file: %s", copyErr)
|
t.Error(err2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -214,7 +214,8 @@ func TestSignPDFFileUTF8(t *testing.T) {
|
|||||||
info, err := verify.File(tmpfile)
|
info, err := verify.File(tmpfile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("%s: %s", tmpfile.Name(), err.Error())
|
t.Fatalf("%s: %s", tmpfile.Name(), err.Error())
|
||||||
if err := CopyFile(tmpfile.Name(), "../testfiles/failed/"+originalFileName); err != nil {
|
err := os.Rename(tmpfile.Name(), "../testfiles/failed/"+originalFileName)
|
||||||
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
} else if len(info.Signers) == 0 {
|
} else if len(info.Signers) == 0 {
|
||||||
@@ -271,7 +272,8 @@ func TestSignPDFVisible(t *testing.T) {
|
|||||||
_, err = verify.File(tmpfile)
|
_, err = verify.File(tmpfile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("%s: %s", tmpfile.Name(), err.Error())
|
t.Fatalf("%s: %s", tmpfile.Name(), err.Error())
|
||||||
if err := CopyFile(tmpfile.Name(), "../testfiles/failed/"+originalFileName); err != nil {
|
err := os.Rename(tmpfile.Name(), "../testfiles/failed/"+originalFileName)
|
||||||
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -504,7 +506,6 @@ func TestSignPDFWithImage(t *testing.T) {
|
|||||||
Reason: "Test with visible signature and image",
|
Reason: "Test with visible signature and image",
|
||||||
ContactInfo: "None",
|
ContactInfo: "None",
|
||||||
Date: time.Now().Local(),
|
Date: time.Now().Local(),
|
||||||
Image: signatureImage, // Use the signature image
|
|
||||||
},
|
},
|
||||||
CertType: ApprovalSignature,
|
CertType: ApprovalSignature,
|
||||||
DocMDPPerm: AllowFillingExistingFormFieldsAndSignaturesPerms,
|
DocMDPPerm: AllowFillingExistingFormFieldsAndSignaturesPerms,
|
||||||
@@ -515,6 +516,7 @@ func TestSignPDFWithImage(t *testing.T) {
|
|||||||
LowerLeftY: 50,
|
LowerLeftY: 50,
|
||||||
UpperRightX: 600,
|
UpperRightX: 600,
|
||||||
UpperRightY: 125,
|
UpperRightY: 125,
|
||||||
|
Image: signatureImage, // Use the signature image
|
||||||
},
|
},
|
||||||
DigestAlgorithm: crypto.SHA512,
|
DigestAlgorithm: crypto.SHA512,
|
||||||
Signer: pkey,
|
Signer: pkey,
|
||||||
@@ -555,7 +557,6 @@ func TestSignPDFWithTwoImages(t *testing.T) {
|
|||||||
Reason: "First signature with image",
|
Reason: "First signature with image",
|
||||||
ContactInfo: "None",
|
ContactInfo: "None",
|
||||||
Date: time.Now().Local(),
|
Date: time.Now().Local(),
|
||||||
Image: signatureImage,
|
|
||||||
},
|
},
|
||||||
CertType: ApprovalSignature,
|
CertType: ApprovalSignature,
|
||||||
DocMDPPerm: AllowFillingExistingFormFieldsAndSignaturesPerms,
|
DocMDPPerm: AllowFillingExistingFormFieldsAndSignaturesPerms,
|
||||||
@@ -566,6 +567,7 @@ func TestSignPDFWithTwoImages(t *testing.T) {
|
|||||||
LowerLeftY: 50,
|
LowerLeftY: 50,
|
||||||
UpperRightX: 250,
|
UpperRightX: 250,
|
||||||
UpperRightY: 125,
|
UpperRightY: 125,
|
||||||
|
Image: signatureImage,
|
||||||
},
|
},
|
||||||
DigestAlgorithm: crypto.SHA512,
|
DigestAlgorithm: crypto.SHA512,
|
||||||
Signer: pkey,
|
Signer: pkey,
|
||||||
@@ -594,7 +596,6 @@ func TestSignPDFWithTwoImages(t *testing.T) {
|
|||||||
Reason: "Second signature with image",
|
Reason: "Second signature with image",
|
||||||
ContactInfo: "None",
|
ContactInfo: "None",
|
||||||
Date: time.Now().Local(),
|
Date: time.Now().Local(),
|
||||||
Image: signatureImage,
|
|
||||||
},
|
},
|
||||||
CertType: ApprovalSignature,
|
CertType: ApprovalSignature,
|
||||||
DocMDPPerm: AllowFillingExistingFormFieldsAndSignaturesPerms,
|
DocMDPPerm: AllowFillingExistingFormFieldsAndSignaturesPerms,
|
||||||
@@ -605,6 +606,7 @@ func TestSignPDFWithTwoImages(t *testing.T) {
|
|||||||
LowerLeftY: 50,
|
LowerLeftY: 50,
|
||||||
UpperRightX: 500,
|
UpperRightX: 500,
|
||||||
UpperRightY: 125,
|
UpperRightY: 125,
|
||||||
|
Image: signatureImage,
|
||||||
},
|
},
|
||||||
DigestAlgorithm: crypto.SHA512,
|
DigestAlgorithm: crypto.SHA512,
|
||||||
Signer: pkey,
|
Signer: pkey,
|
||||||
|
Reference in New Issue
Block a user