* IU blocks without an egiz dict are not considered. *
* * @param pdf * @param blocks * @return Returns the List of signature holders. * @throws PresentableException */ protected List extractBinarySignaturesOnly(PdfDataSource pdf, List blocks) throws VerificationFilterException { SettingsReader settings; try { settings = SettingsReader.getInstance(); } catch (SettingsException e) { throw new VerificationFilterException(e); } String check_doc = settings.getSetting(CHECK_DOCUMENT, "false"); String binary_only = settings.getSetting(BINARY_ONLY, "false"); String assume_sigs_only = settings.getSetting(ASSUME_ONLY_SIGNATURE_BLOCKS, "false"); boolean supressException = "true".equalsIgnoreCase(settings.getSetting(SUPRESS_EXCEPTION_WHEN_LAST_UIBLOCK_IS_NO_SIGNATURE, "false")); try { // PERF: extract binary signatures needs byte array byte[] data = DataSourceHelper.convertDataSourceToByteArray(pdf); List binarySignatures = new ArrayList(blocks.size()); Iterator it = blocks.iterator(); int prev_end = 0; boolean sig_detected = false; while (it.hasNext()) { FooterParseResult fpr = (FooterParseResult) it.next(); assert fpr.next_index > prev_end; PdfASID kz = null; if (VerificationFilterBinaryHelper.containsEGIZDict(data, fpr) && (kz = VerificationFilterBinaryHelper.extractKZFromEGIZBlock(data, fpr)) != null) { // TODO dferbas hack baik test //kz = new PdfASID("urn:pdfsigfilter:bka.gv.at:binaer:v1.1.0"); Verificator verificator = VerificatorFactory.createBinaryVerificator(kz); List binary_holders = verificator.parseBlock(pdf, data, fpr, prev_end); binarySignatures.addAll(binary_holders); if(binary_holders.size() > 0) { sig_detected = true; } } else { // an Exception is thrown here if: // 1) check_document is activated // 2) assume_only_signature_blocks is false - otherwise we permit updates // 3) binary_only is true - otherwise updates are handled in method performFullConservative(). // when binary-only is true, we can be sure that a block that contains no egiz-dict is no textual // signature either but an illegal update, otherwise an Exception (doc contains textual sig) would have been thrown before // 4) a binary signature has been detected in a previous block if(check_doc.equalsIgnoreCase("true") && binary_only.equalsIgnoreCase("true") && assume_sigs_only.equalsIgnoreCase("false") && sig_detected) { if (!supressException) { throw new VerificationFilterException(ErrorCode.MODIFIED_AFTER_SIGNATION, "The document has been modified after being signed."); } else { log.debug("The document has been modified after being signed. According to the configuration, no exception is thrown."); } } } prev_end = fpr.next_index; } return binarySignatures; } catch (PresentableException e) { throw new VerificationFilterException(e); } } protected List extractSignatures(PdfDataSource pdf, int endOfDocument) throws VerificationFilterException { try { log.debug("Extracting text from 0 to " + endOfDocument + " (total document size = " + pdf.getLength() + "):"); String extractedText = extractText(pdf, endOfDocument); log.debug("Extracting text finished."); log.debug("extracted text: " + extractedText); log.debug("Extracting signatures:"); List extractedSignatures = extractNewSignaturesFromText(extractedText); log.debug("Extracting signatures finished."); log.debug("Number of found signatures: " + extractedSignatures.size()); if (extractedSignatures.size() > 0) { List cp1252SignaturesPositions = new ArrayList(); //boolean iscp1252Sig = false; for (int i = 0; i < extractedSignatures.size(); i++) { SignatureHolder sh = (SignatureHolder)extractedSignatures.get(i); PdfASID kzid = sh.getSignatureObject().getKZ(); if (kzid != null && kzid.isOldCp1252Version()) { log.debug("found cp1252 signature"); cp1252SignaturesPositions.add(new Integer(i)); //iscp1252Sig = true; //break; } } if (cp1252SignaturesPositions.size() > 0) { log.debug("redo text and signature extraction with cp1252 encoding"); extractedText = extractText(pdf, endOfDocument, "cp1252"); log.debug("Extracting text finished."); log.debug("Extracting signatures:"); List cp1252ExtractedSignatures = extractNewSignaturesFromText(extractedText); log.debug("Extracting signatures finished."); log.debug("Number of found signatures: " + extractedSignatures.size()); if (cp1252ExtractedSignatures.size() != extractedSignatures.size()) { log.error("Invalid cp1252 signatures found. Skipping cp1252 compatibility."); } // merge signature holders for (int i = 0; i < cp1252SignaturesPositions.size(); i++) { int replaceIndex = ((Integer)cp1252SignaturesPositions.get(i)).intValue(); extractedSignatures.remove(replaceIndex); extractedSignatures.add(replaceIndex, cp1252ExtractedSignatures.get(replaceIndex)); } } } if (log.isDebugEnabled()) { log.debug("extracted signatures:"); for (int i = 0; i < extractedSignatures.size(); i++) { SignatureHolder sh = (SignatureHolder)extractedSignatures.get(i); String dateStr = sh.getSignatureObject().getSignationDate(); EGIZDate ed = EGIZDate.parseFromString(dateStr); log.debug("#" + i + ": dateStr = " + dateStr + ", egizDate = " + ed.toString()); } } return extractedSignatures; } catch (PresentableException e) { throw new VerificationFilterException(e); } } protected String determineRestText(List newSignatures, String extractedText) { if (newSignatures.isEmpty()) { return extractedText; } // note that even if the oldest signature is a binary signature, // the rest text is the text of this binary signature, which was extracted // like a text signature. TextualSignatureHolder oldestSignature = (TextualSignatureHolder) newSignatures.get(0); return oldestSignature.getSignedText(); } protected List extractSignaturesFromPartition(PdfDataSource pdf, Partition partition) throws VerificationFilterException { assert partition.isTextPartition(); int endOfDocument = VerificationFilterHelper.getEndOfPartition(partition); List extractedSigs = extractSignatures(pdf, endOfDocument); TextualSignatureHolder.mulitSetUiBlockEndPos(extractedSigs, endOfDocument); return extractedSigs; } protected SignaturesAndOld extractSignaturesFromPartitionAndOld(PdfDataSource pdf, Partition partition) throws VerificationFilterException { assert partition.isTextPartition(); try { int endOfDocument = VerificationFilterHelper.getEndOfPartition(partition); // log.debug("Extracting text from 0 to " + endOfDocument + " (total document size = " + pdf.getLength() + "):"); String extractedText = extractText(pdf, endOfDocument); // log.debug("Extracting text finished."); // log.debug("extracted text: " + extractedText); SignaturesAndOld sao = extractSignaturesAndOld(extractedText); TextualSignatureHolder.trySetUiBlockEndPos(sao.oldSignature, endOfDocument); TextualSignatureHolder.mulitSetUiBlockEndPos(sao.newSignatures, endOfDocument); return sao; } catch (PresentableException e) { throw new VerificationFilterException(e); } } protected void checkBinaryOnly(PdfDataSource pdf, boolean considerOldSigs) throws VerificationFilterException { DelimitedPdfDataSource dds = new DelimitedPdfDataSource(pdf, pdf.getLength()); String text = null; try { text = PdfAS.extractNormalizedTextTextual(dds, "utf-8"); } catch (PresentableException e) { throw new VerificationFilterException(e); } List sigs = new ArrayList(); if(considerOldSigs) { SignaturesAndOld sao = extractSignaturesAndOld(text); if(sao != null) { if(sao.newSignatures != null) { sigs.addAll(sao.newSignatures); } if(sao.oldSignature != null) { sigs.add(sao.oldSignature); } } } else { List signatures = extractSignatures(pdf, pdf.getLength()); if(signatures != null) { sigs.addAll(signatures); } } Iterator it = sigs.iterator(); while(it.hasNext()) { SignatureHolder current = (SignatureHolder)it.next(); if((current != null)&&(!current.getSignatureObject().isBinary())) { throw new VerificationFilterException(ErrorCode.NON_BINARY_SIGNATURES_PRESENT, "The document contains non-binary signatures."); } } } protected static class SignaturesAndOld { public List newSignatures = null; public SignatureHolder oldSignature = null; } protected SignaturesAndOld extractSignaturesAndOld(String text) throws VerificationFilterException { try { log.debug("Extracting signatures:"); List extractedSignatures = extractNewSignaturesFromText(text); log.debug("Extracting signatures finished."); log.debug("Extracting old signatures:"); SignatureHolder oldSignature = extractOldSignature(text, extractedSignatures); log.debug("Extracting old signatures finished."); log.debug("oldSignature = null: " + (oldSignature==null)); SignaturesAndOld sao = new SignaturesAndOld(); sao.newSignatures = extractedSignatures; sao.oldSignature = oldSignature; return sao; } catch (PresentableException e) { throw new VerificationFilterException(e); } } /** * Extracts the old signature from the text, but only if it is older than the * oldest signature of the new signatueres. * * @param extractedText * @param newSignatures * @return * @throws PDFDocumentException * @throws SignatureException * @throws NormalizeException * @throws SignatureTypesException */ protected SignatureHolder extractOldSignature(String extractedText, List newSignatures) throws PDFDocumentException, SignatureException, NormalizeException, SignatureTypesException { SignatureHolder oldSignature = null; String restText = determineRestText(newSignatures, extractedText); List oldSignatures = PdfAS.extractSignatureHoldersTextual(restText, true); if (!oldSignatures.isEmpty()) { oldSignature = (SignatureHolder) oldSignatures.get(0); if (!newSignatures.isEmpty()) { SignatureHolder oldestNewSignature = (SignatureHolder) newSignatures.get(0); EGIZDate oldDate = EGIZDate.parseFromString(oldSignature.getSignatureObject().getSignationDate()); EGIZDate newDate = EGIZDate.parseFromString(oldestNewSignature.getSignatureObject().getSignationDate()); if (newDate.compareTo(oldDate) <= 0) { oldSignature = null; } } } return oldSignature; } }