protect-scr
Version:
Comprehensive client-side security protection for React applications against screenshots, printing, and unauthorized access
220 lines (218 loc) • 7.29 kB
JavaScript
export class PrintProtector {
constructor(config) {
this.isActive = false;
this.originalMethods = new Map();
this.config = config;
}
start() {
if (this.isActive)
return;
this.isActive = true;
if (this.config.preventPrinting) {
this.blockPrinting();
}
if (this.config.preventPDFGeneration) {
this.blockPDFGeneration();
}
this.setupMediaQueryDetection();
}
stop() {
if (!this.isActive)
return;
this.isActive = false;
this.restoreOriginalMethods();
}
blockPrinting() {
// Store original print method
this.originalPrint = window.print;
// Override window.print
window.print = () => {
if (this.config.showWarning) {
alert('Printing is disabled for security reasons.');
}
return;
};
// Block print media queries
this.addPrintBlockingCSS();
// Block beforeprint event
const beforePrintHandler = (e) => {
e.preventDefault();
e.stopPropagation();
if (this.config.showWarning) {
alert('Printing is disabled for security reasons.');
}
return false;
};
window.addEventListener('beforeprint', beforePrintHandler);
this.originalMethods.set('beforeprint', () => {
window.removeEventListener('beforeprint', beforePrintHandler);
});
}
blockPDFGeneration() {
// Block common PDF generation libraries
this.blockJsPDF();
this.blockPDFMake();
this.blockPuppeteer();
this.blockHtml2Canvas();
this.blockDomToPdf();
}
blockJsPDF() {
// Block jsPDF library
Object.defineProperty(window, 'jsPDF', {
get: () => {
throw new Error('PDF generation is blocked for security reasons');
},
set: () => {
throw new Error('PDF generation is blocked for security reasons');
},
configurable: false
});
// Block jspdf import
if (typeof window !== 'undefined') {
window.jsPDF = undefined;
}
}
blockPDFMake() {
// Block pdfMake library
Object.defineProperty(window, 'pdfMake', {
get: () => {
throw new Error('PDF generation is blocked for security reasons');
},
set: () => {
throw new Error('PDF generation is blocked for security reasons');
},
configurable: false
});
if (typeof window !== 'undefined') {
window.pdfMake = undefined;
}
}
blockPuppeteer() {
// Block puppeteer (mainly for server-side, but defensive)
if (typeof window !== 'undefined') {
window.puppeteer = undefined;
}
}
blockHtml2Canvas() {
// Block html2canvas library
Object.defineProperty(window, 'html2canvas', {
get: () => {
throw new Error('Canvas generation is blocked for security reasons');
},
set: () => {
throw new Error('Canvas generation is blocked for security reasons');
},
configurable: false
});
if (typeof window !== 'undefined') {
window.html2canvas = undefined;
}
}
blockDomToPdf() {
// Block dom-to-pdf and similar libraries
const blockedLibraries = [
'domToPdf',
'dom-to-pdf',
'htmlToPdf',
'html-to-pdf',
'pageToPdf',
'page-to-pdf'
];
blockedLibraries.forEach(lib => {
Object.defineProperty(window, lib, {
get: () => {
throw new Error('PDF generation is blocked for security reasons');
},
set: () => {
throw new Error('PDF generation is blocked for security reasons');
},
configurable: false
});
});
}
addPrintBlockingCSS() {
const styleId = 'secure-app-shield-print-block';
let styleElement = document.getElementById(styleId);
if (!styleElement) {
styleElement = document.createElement('style');
styleElement.id = styleId;
document.head.appendChild(styleElement);
}
styleElement.textContent = `
@media print {
* {
display: none !important;
visibility: hidden !important;
}
body::before {
content: "Printing is not allowed for security reasons" !important;
display: block !important;
visibility: visible !important;
position: fixed !important;
top: 50% !important;
left: 50% !important;
transform: translate(-50%, -50%) !important;
font-size: 24px !important;
font-weight: bold !important;
color: #000 !important;
background: #fff !important;
padding: 20px !important;
border: 2px solid #000 !important;
z-index: 9999999 !important;
}
}
@page {
margin: 0 !important;
size: A4 !important;
}
`;
this.originalMethods.set('printCSS', () => {
if (styleElement) {
styleElement.remove();
}
});
}
setupMediaQueryDetection() {
// Detect when print media query becomes active
const printMediaQuery = window.matchMedia('print');
const printHandler = (e) => {
var _a;
if (e.matches && this.config.preventPrinting) {
// Print mode detected
if (this.config.showWarning) {
alert('Printing is disabled for security reasons.');
}
// Try to cancel print dialog
(_a = window.stop) === null || _a === void 0 ? void 0 : _a.call(window);
}
};
if (printMediaQuery.addEventListener) {
printMediaQuery.addEventListener('change', printHandler);
this.originalMethods.set('mediaQuery', () => {
printMediaQuery.removeEventListener('change', printHandler);
});
}
else if (printMediaQuery.addListener) {
// Fallback for older browsers
printMediaQuery.addListener(printHandler);
this.originalMethods.set('mediaQuery', () => {
printMediaQuery.removeListener(printHandler);
});
}
}
restoreOriginalMethods() {
// Restore original print method
if (this.originalPrint) {
window.print = this.originalPrint;
this.originalPrint = undefined;
}
// Remove all event listeners and styles
this.originalMethods.forEach((cleanup) => {
if (typeof cleanup === 'function') {
cleanup();
}
});
this.originalMethods.clear();
}
}
//# sourceMappingURL=PrintProtector.js.map