@dbp-topics/signature
Version:
[GitLab Repository](https://gitlab.tugraz.at/dbp/esign/signature) | [npmjs package](https://www.npmjs.com/package/@dbp-topics/signature) | [Unpkg CDN](https://unpkg.com/browse/@dbp-topics/signature/) | [Esign Bundle](https://gitlab.tugraz.at/dbp/esign/dbp
300 lines (261 loc) • 8.6 kB
JavaScript
import {AnnotationFactory} from '@digital-blueprint/annotpdf/_bundles/pdfAnnotate.js';
import {html} from 'lit';
//import {humanFileSize} from "@dbp-toolkit/common/i18next";
/**
* Finds an object in a JSON result by identifier
*
* @param identifier
* @param results
* @param identifierAttribute
*/
export const findObjectInApiResults = (identifier, results, identifierAttribute = '@id') => {
const members = results['hydra:member'];
if (members === undefined) {
return;
}
for (const object of members) {
if (object[identifierAttribute] === identifier) {
return object;
}
}
};
export const getPDFFileBase64Content = (file) => {
return file.contentUrl.replace(/data:\s*application\/pdf;\s*base64,/, '');
};
export const convertDataURIToBinary = (dataURI) => {
const BASE64_MARKER = ';base64,';
const base64Index = dataURI.indexOf(BASE64_MARKER) + BASE64_MARKER.length;
const base64 = dataURI.substring(base64Index);
const raw = window.atob(base64);
const rawLength = raw.length;
let array = new Uint8Array(rawLength);
for (let i = 0; i < rawLength; i++) {
array[i] = raw.charCodeAt(i);
}
return array;
};
export const getDataURIContentType = (dataURI) => {
const BASE64_MARKER = ';base64,';
const base64Index = dataURI.indexOf(BASE64_MARKER);
return dataURI.substring(5, base64Index);
};
export const baseName = (str) => {
let base = String(str).substring(str.lastIndexOf('/') + 1);
if (base.lastIndexOf('.') !== -1) {
base = base.substring(0, base.lastIndexOf('.'));
}
return base;
};
export const fabricjs2pdfasPosition = (data) => {
let angle = -(data.angle - 360) % 360;
let bottom = data.bottom;
let left = data.left;
if (data.angle === 90) {
bottom += data.height;
left -= data.height;
} else if (data.angle === 180) {
bottom += data.height * 2;
} else if (data.angle === 270) {
bottom += data.height;
left += data.height;
}
return {
y: Math.round(bottom),
x: Math.round(left),
r: angle,
w: Math.round(data.width), // only width, no "height" allowed in PDF-AS
p: data.currentPage,
};
};
/**
* Returns the content of the file
*
* @param {File} file The file to read
* @returns {string} The content
*/
export const readBinaryFileContent = async (file) => {
return new Promise((resolve, reject) => {
let reader = new FileReader();
reader.onload = () => {
resolve(reader.result);
};
reader.onerror = () => {
reject(reader.error);
};
reader.readAsBinaryString(file);
});
};
/**
* Returns the content of the file as array buffer
*
* @param {File} file The file to read
* @returns {string} The content
*/
export const readArrayBufferFileContent = async (file) => {
return new Promise((resolve, reject) => {
let reader = new FileReader();
reader.onload = () => {
resolve(reader.result);
};
reader.onerror = () => {
reject(reader.error);
};
reader.readAsArrayBuffer(file);
});
};
/**
* Given a PDF file returns the amount of signatures found in it.
*
* Note that this uses an heuristic, so the result can be wrong
* (improvements welcome).
*
* @param {File} file The PDF file object
* @returns {number} The amount of signatures found
*/
export const getPDFSignatureCount = async (file) => {
const sigRegex = new RegExp(
'(/Type\\s*/Sig|/Filter\\s*/Adobe.PPKLite)[\\s\\S]*?/SubFilter\\s*(/ETSI\\.CAdES\\.detached|/adbe\\.pkcs7\\.detached)',
'g'
);
const content = await readBinaryFileContent(file);
let matches = 0;
while (sigRegex.exec(content) !== null) {
matches++;
}
return matches;
};
/**
* Returns a File from an AnnotationFactory
*
* @param annotationFactory
* @param file
* @returns {File} file given as parameter, but with annotations
*/
export const writeAnnotationFactoryToFile = (annotationFactory, file) => {
const blob = annotationFactory.write();
return new File([blob], file.name, {type: file.type});
};
/**
* Creates an AnnotationFactory from a File
*
* @param file
* @returns {AnnotationFactory} from given file
*/
export const getAnnotationFactoryFromFile = async (file) => {
const data = await readArrayBufferFileContent(file);
return new AnnotationFactory(data);
};
/**
* Adds a key/value annotation to a AnnotationFactory and returns the AnnotationFactory
*
* @param annotationFactory
* @param activityNameDE
* @param activityNameEN
* @param personName
* @param annotationType
* @param annotationTypeNameDE
* @param annotationTypeNameEN
* @param organizationNumber
* @param value
* @returns {AnnotationFactory} prepared to annotate
*/
export const addKeyValuePdfAnnotationsToAnnotationFactory = (
annotationFactory,
activityNameDE,
activityNameEN,
personName,
annotationType,
annotationTypeNameDE,
annotationTypeNameEN,
organizationNumber,
value
) => {
annotationType = annotationType.trim();
annotationTypeNameDE = annotationTypeNameDE.trim();
annotationTypeNameEN = annotationTypeNameEN.trim();
organizationNumber = organizationNumber.trim();
value = value.trim();
// don't annotate if key or value are empty
if (annotationType === '' || value === '') {
return annotationFactory;
}
// add human readable annotation
let author = personName + ' via "' + activityNameDE + ' / ' + activityNameEN + '"';
let content = annotationTypeNameDE + ': ' + value + '\n' + annotationTypeNameEN + ': ' + value;
annotationFactory = addPdfAnnotationToAnnotationFactory(annotationFactory, author, content);
// add machine readable annotation
const organizationNumberContent = organizationNumber !== '' ? '_' + organizationNumber : '';
author =
'Maschinell aufgebracht, bitte nicht entfernen / Applied automatically, please do not remove';
content = 'dbp_annotation_' + annotationType + organizationNumberContent + '=' + value;
annotationFactory = addPdfAnnotationToAnnotationFactory(annotationFactory, author, content);
return annotationFactory;
};
export const addPdfAnnotationToAnnotationFactory = (annotationFactory, author, content) => {
author = author.trim();
content = content.trim();
// don't annotate if author of content are empty
if (author === '' || content === '') {
return annotationFactory;
}
const page = 0;
const rect = [0, 0, 0, 0];
// annotationFactory.checkRect(4, rect);
// Create single free text annotation with print flag and 0 font size
let annotation = Object.assign(
annotationFactory.createBaseAnnotation(page, rect, content, author),
{
annotation_flag: 4, // enable print to be PDF/A conform
color: {r: 1, g: 1, b: 1}, // white to (maybe) hide it better
opacity: 0.001, // we can't set to 0 because of "if (opacity) {"
defaultAppearance: '/Invalid_font 0 Tf', // font size 0 to (maybe) hide it better
}
);
annotation.type = '/FreeText';
annotationFactory.annotations.push(annotation);
return annotationFactory;
};
/**
* Returns an object with all annotations types or only the values for one type
*
* @param key
* @returns {object} describing the annotation type named key
*/
export const getAnnotationTypes = (key = null) => {
const types = {
bbe3a371: {
name: {
de: 'Geschäftszahl',
en: 'Businessnumber',
},
hasOrganization: true,
},
'85a4eb4c': {
name: {
de: 'Verwendungszweck',
en: 'Intended use',
},
hasOrganization: false,
},
};
return key === null ? types : types[key] || {};
};
/**
* Returns the html for the annotation type select
*
* @param selectedKey
* @param lang
* @returns {*[]} Array of html templates
*/
export const getAnnotationTypeSelectOptionsHtml = (selectedKey, lang) => {
const annotationTypes = getAnnotationTypes();
const keys = Object.keys(annotationTypes);
let results = [];
keys.forEach((key) => {
const name = annotationTypes[key].name[lang];
results.push(html`
<option value="${key}" .selected=${selectedKey === key}>${name}</option>
`);
});
return results;
};